[mapguide-commits] r9525 - sandbox/jng/mvt/Common/Renderers
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Fri May 31 06:06:39 PDT 2019
Author: jng
Date: 2019-05-31 06:06:39 -0700 (Fri, 31 May 2019)
New Revision: 9525
Modified:
sandbox/jng/mvt/Common/Renderers/MVTRenderer.cpp
sandbox/jng/mvt/Common/Renderers/MVTRenderer.h
Log:
Initial implementation of MVT geometry encoding
Modified: sandbox/jng/mvt/Common/Renderers/MVTRenderer.cpp
===================================================================
--- sandbox/jng/mvt/Common/Renderers/MVTRenderer.cpp 2019-05-29 17:37:02 UTC (rev 9524)
+++ sandbox/jng/mvt/Common/Renderers/MVTRenderer.cpp 2019-05-31 13:06:39 UTC (rev 9525)
@@ -16,9 +16,42 @@
//
#include "MVTRenderer.h"
+#include "RS_FeatureReader.h"
+#include "UnicodeString.h"
+// =========================== MVTRenderer overview =============================== //
+//
+// MVTRenderer is really just an adapter to connect our Stylizer to the vtzero library
+// that does all the actual hard work
+//
+// So the responsibility of MVTRenderer is simply to:
+//
+// - Create a new vtzero::layer_builder instance on every StartLayer(). Push any
+// current instance to the internal list for cleanup
+// - Clear and fill the internal property map on every StartFeature() call
+// - For every ProcessXXX() call
+// - Create a vtzero::feature_builder instance
+// - Write the line buffer coordinates to this builder
+// - Write the active property map (via add_property() calls)
+// - Commit the builder
+//
+// Some notes about coordinates:
+//
+// MVT coordinates are not geographic coordinates. They are tile-relative coordinates
+// on a virtual "screen" of 4096x4096 "pixels"
+//
+// ================================================================================ //
+
+const int MVT_SIZE = 4096;
+
MVTRenderer::MVTRenderer()
- : m_activeLayer(nullptr), m_mapInfo(nullptr), m_layerInfo(nullptr), m_fcInfo(nullptr)
+ : m_tileBuilder(new vtzero::tile_builder())
+ , m_activeLayerBuilder(nullptr)
+ , m_mapInfo(nullptr)
+ , m_layerInfo(nullptr)
+ , m_fcInfo(nullptr)
+ , m_width(MVT_SIZE)
+ , m_height(MVT_SIZE)
{
}
@@ -25,71 +58,205 @@
MVTRenderer::~MVTRenderer()
{
- for (auto layer : m_prevLayers)
+ for (auto lb : m_prevLayerBuilder)
{
- delete layer;
+ delete lb;
}
- m_prevLayers.clear();
+ m_prevLayerBuilder.clear();
+ delete m_tileBuilder;
}
+//Called by the stylizer when rendering is about to begin on the map
void MVTRenderer::StartMap(RS_MapUIInfo * mapInfo, RS_Bounds & extents, double mapScale, double dpi, double metersPerUnit, CSysTransformer * xformToLL)
{
- return void();
+ m_mapScale = mapScale;
+ m_dpi = dpi;
+ m_metersPerUnit = metersPerUnit;
+ m_extents = extents;
+
+ // find scale used to convert to pixel coordinates
+ // need to take aspect ratios into account
+ double arDisplay = (double)m_width / (double)m_height;
+ double arMap = m_extents.width() / m_extents.height();
+
+ double scale;
+ if (arDisplay > arMap)
+ scale = (double)m_height / m_extents.height();
+ else
+ scale = (double)m_width / m_extents.width();
+
+ m_xform.x0 = scale;
+ m_xform.x1 = 0.0;
+ m_xform.x2 = -scale * m_extents.minx;
+ m_xform.y0 = 0.0;
+ m_xform.y1 = scale;
+ m_xform.y2 = -scale * m_extents.miny;
+
+ m_ixform.x0 = 1.0 / scale;
+ m_ixform.x1 = 0.0;
+ m_ixform.x2 = m_extents.minx;
+ m_ixform.y0 = 0.0;
+ m_ixform.y1 = m_ixform.x0;
+ m_ixform.y2 = m_extents.miny;
+
+ double metersPerPixel = METERS_PER_INCH / m_dpi;
+
+ // compute drawing scale
+ // drawing scale is map scale converted to [mapping units] / [pixels]
+ m_drawingScale = m_mapScale * metersPerPixel / m_metersPerUnit;
}
+//Called by the stylizer when rendering is about to begin on the map
void MVTRenderer::EndMap()
{
-
+ // clear the map info
+ m_mapInfo = nullptr;
}
+//Called by the stylizer when rendering is about to begin on the map for the given layer
void MVTRenderer::StartLayer(RS_LayerUIInfo * layerInfo, RS_FeatureClassInfo * classInfo)
{
-
+ m_layerInfo = layerInfo;
+ m_fcInfo = classInfo;
+
+ std::string name;
+ UnicodeString::WideCharToMultiByte(m_layerInfo->name().c_str(), name);
+
+ m_activeLayerBuilder = new vtzero::layer_builder(*m_tileBuilder, name);
}
+//Called by the stylizer when rendering is about to begin on the map for the layer indicated by StartLayer()
void MVTRenderer::EndLayer()
{
-
+ // clear the layer/feature info
+ m_layerInfo = nullptr;
+ m_fcInfo = nullptr;
+
+ m_prevLayerBuilder.push_back(m_activeLayerBuilder);
+ m_activeLayerBuilder = nullptr;
}
+//Called by the stylizer when rendering is about to begin on the map for the given feature
void MVTRenderer::StartFeature(RS_FeatureReader * feature, bool initialPass, const RS_String * tooltip, const RS_String * url, const RS_String * theme, double zOffset, double zExtrusion, RS_ElevationType zOffsetType)
{
-
+ m_activeFeature = feature;
}
+//Entry point for polygon rendering. Perform any pre-rendering operations.
void MVTRenderer::ProcessPolygon(LineBuffer * lb, RS_FillStyle & fill)
{
+ vtzero::polygon_feature_builder builder(*m_activeLayerBuilder);
+ if (lb->cntr_count() == 1)
+ {
+ auto numPoints = lb->point_count();
+ builder.add_ring(numPoints);
+ for (auto i = 0; i < numPoints; i++)
+ {
+ auto x = lb->x_coord(i);
+ auto y = lb->y_coord(i);
+
+ double tx;
+ double ty;
+ WorldToScreenPoint(x, y, tx, ty);
+
+ builder.set_point(static_cast<int>(tx), static_cast<int>(ty));
+ }
+ }
+ else //MultiPolygon
+ {
+
+ }
+
+ AddActiveFeatureProperties(&builder);
+ builder.commit();
}
+//Entry point for polyline rendering. Perform any pre-rendering operations.
void MVTRenderer::ProcessPolyline(LineBuffer * lb, RS_LineStroke & lsym)
{
+ vtzero::linestring_feature_builder builder(*m_activeLayerBuilder);
+ if (lb->cntr_count() == 1)
+ {
+ auto numPoints = lb->cntr_size(0);
+ auto pointOffset = lb->contour_start_point(0);
+ for (auto i = 0; i < numPoints; i++)
+ {
+ auto x = lb->x_coord(i + pointOffset);
+ auto y = lb->y_coord(i + pointOffset);
+
+ double tx;
+ double ty;
+ WorldToScreenPoint(x, y, tx, ty);
+
+ builder.set_point(static_cast<int>(tx), static_cast<int>(ty));
+ }
+ }
+ else //MultiLineString
+ {
+
+ }
+
+ AddActiveFeatureProperties(&builder);
+ builder.commit();
}
+//Entry point for raster/image rendering. Perform any pre-rendering operations.
void MVTRenderer::ProcessRaster(unsigned char * data, int length, RS_ImageFormat format, int width, int height, RS_Bounds & extents, TransformMesh * xformMesh)
{
- //Not applicable for MVT
+ //This will generally result in a call to DrawScreenRaster() after processing.
+ //
+ //If your renderer only concerns vector data, this method can be left blank
}
+//Entry point for marker rendering. Perform any pre-rendering operations.
void MVTRenderer::ProcessMarker(LineBuffer * lb, RS_MarkerDef & mdef, bool allowOverpost, RS_Bounds * bounds)
{
-
+ vtzero::point_feature_builder builder(*m_activeLayerBuilder);
+
+ if (lb->point_count() == 1)
+ {
+ auto x = lb->x_coord(0);
+ auto y = lb->y_coord(0);
+
+ double tx;
+ double ty;
+ WorldToScreenPoint(x, y, tx, ty);
+
+ builder.set_point(static_cast<int>(tx), static_cast<int>(ty));
+ }
+ else //MultiPoint
+ {
+
+ }
+
+ AddActiveFeatureProperties(&builder);
+ builder.commit();
}
+//Entry point for label group rendering.
void MVTRenderer::ProcessLabelGroup(RS_LabelInfo * labels, int nlabels, const RS_String & text, RS_OverpostType type, bool exclude, LineBuffer * path, double scaleLimit)
{
- //Not applicable for MVT
+ //Most implementations will carry a LabelRenderer member and forward this method call
+ //to it.
+ //
+ //If your renderer does not render labels, this method can be left blank
}
+// Inserts the contents of a given DWF input stream into the current
+// output W2D. The given coord sys transformation is applied and geometry
+// will be clipped to the RS_Bounds context of the DWFRenderer.
void MVTRenderer::AddDWFContent(RS_InputStream * in, CSysTransformer * xformer, const RS_String & section, const RS_String & passwd, const RS_String & w2dfilter)
{
- //Not applicable for MVT
+ // This is data from a DWF drawing layer. If your renderer is not intended to support DWF
+ // drawing layers/sources, this method can be left blank.
}
+//Sets the legacy symbol manager which will be used when fetching (DWF) symbol data
void MVTRenderer::SetSymbolManager(RS_SymbolManager * manager)
{
- //Not applicable for MVT
+ //If your renderer does not render DWF-based image symbols, this method can be left blank
}
RS_MapUIInfo * MVTRenderer::GetMapInfo()
@@ -142,34 +309,40 @@
return false;
}
+//Return true if this renderer can handle 3D geometries
bool MVTRenderer::SupportsZ()
{
return false;
}
+//Render out the given polyline using the provided fill style
void MVTRenderer::DrawScreenPolyline(LineBuffer * polyline, const SE_Matrix * xform, const SE_LineStroke & lineStroke)
{
}
+//Render out the given polygon using the provided fill style
void MVTRenderer::DrawScreenPolygon(LineBuffer * polygon, const SE_Matrix * xform, unsigned int fill)
{
}
+//Render out the given raster data.
void MVTRenderer::DrawScreenRaster(unsigned char * data, int length, RS_ImageFormat format, int native_width, int native_height, double x, double y, double w, double h, double angleDeg)
{
- //Not applicable for MVT
+ //If your renderer only concerns vector data, this method can be left blank
}
+//Render out the given raster data.
void MVTRenderer::DrawScreenRaster(unsigned char * data, int length, RS_ImageFormat format, int native_width, int native_height, double x, double y, double w, double h, double angleDeg, double alpha)
{
- //Not applicable for MVT
+ //If your renderer only concerns vector data, this method can be left blank
}
+//Render out the given text.
void MVTRenderer::DrawScreenText(const RS_TextMetrics & tm, RS_TextDef & tdef, double insx, double insy, RS_F_Point * path, int npts, double param_position)
{
- //Not applicable for MVT
+ //If your renderer does not render labels, this method can be left blank
}
bool MVTRenderer::YPointsUp()
@@ -212,12 +385,83 @@
return NULL;
}
+//Entry point for label rendering.
void MVTRenderer::ProcessSELabelGroup(SE_LabelInfo * labels, int nlabels, RS_OverpostType type, bool exclude, LineBuffer * path)
{
- //Not applicable for MVT
+ //Most implementations will carry a LabelRenderer member and forward this method call
+ //to it.
+ //
+ //If this render does not render labels, this method can be left blank.
}
+//If this renderer can render labels, add and track the given exclusion region.
+//An exclusion region is a region that should not factor into desired label/symbol placement.
void MVTRenderer::AddExclusionRegion(RS_F_Point * fpts, int npts)
{
- //Not applicable for MVT
+ //Most implementations will carry a LabelRenderer member and forward this method call
+ //to it.
+ //
+ //If this renderer does not render labels. This method can be left blank.
}
+
+void MVTRenderer::GetMVTContent(std::string& buffer)
+{
+ m_tileBuilder->serialize(buffer);
+}
+
+void MVTRenderer::AddActiveFeatureProperties(vtzero::feature_builder* builder)
+{
+ int count;
+ auto propNames = m_activeFeature->GetPropNames(count);
+ for (int i = 0; i < count; i++)
+ {
+ auto name = propNames[i];
+ std::string mbName;
+ UnicodeString::WideCharToMultiByte(name, mbName);
+ auto propType = m_activeFeature->GetPropertyType(name);
+ switch (propType)
+ {
+ case FdoDataType_Boolean:
+ builder->add_property(mbName, vtzero::bool_value_type(m_activeFeature->GetBoolean(name)));
+ break;
+ case FdoDataType_Byte:
+ builder->add_property(mbName, vtzero::int_value_type(m_activeFeature->GetByte(name)));
+ break;
+ case FdoDataType_DateTime:
+ {
+ auto dt = m_activeFeature->GetAsString(name);
+ std::string sDt;
+ UnicodeString::WideCharToMultiByte(dt, sDt);
+ builder->add_property(mbName, vtzero::string_value_type(sDt));
+ break;
+ }
+ case FdoDataType_Decimal:
+ case FdoDataType_Double:
+ builder->add_property(mbName, vtzero::double_value_type(m_activeFeature->GetDouble(name)));
+ break;
+ case FdoDataType_Int16:
+ builder->add_property(mbName, vtzero::int_value_type(m_activeFeature->GetInt16(name)));
+ break;
+ case FdoDataType_Int32:
+ builder->add_property(mbName, vtzero::int_value_type(m_activeFeature->GetInt32(name)));
+ break;
+ case FdoDataType_Int64:
+ builder->add_property(mbName, vtzero::int_value_type(m_activeFeature->GetInt64(name)));
+ break;
+ case FdoDataType_Single:
+ builder->add_property(mbName, vtzero::float_value_type(m_activeFeature->GetSingle(name)));
+ break;
+ case FdoDataType_String:
+ {
+ auto s = m_activeFeature->GetString(name);
+ std::string sVal;
+ UnicodeString::WideCharToMultiByte(s, sVal);
+ builder->add_property(mbName, vtzero::string_value_type(sVal));
+ break;
+ }
+ case FdoDataType_BLOB: //Not handled
+ case FdoDataType_CLOB:
+ break;
+ }
+ }
+}
\ No newline at end of file
Modified: sandbox/jng/mvt/Common/Renderers/MVTRenderer.h
===================================================================
--- sandbox/jng/mvt/Common/Renderers/MVTRenderer.h 2019-05-29 17:37:02 UTC (rev 9524)
+++ sandbox/jng/mvt/Common/Renderers/MVTRenderer.h 2019-05-31 13:06:39 UTC (rev 9525)
@@ -70,11 +70,17 @@
RENDERERS_API virtual void ProcessSELabelGroup(SE_LabelInfo * labels, int nlabels, RS_OverpostType type, bool exclude, LineBuffer * path = NULL);
RENDERERS_API virtual void AddExclusionRegion(RS_F_Point * fpts, int npts);
+ //MVT-specific
+ RENDERERS_API void GetMVTContent(std::string& buffer);
+
private:
- vtzero::tile_builder m_tile;
- vtzero::layer_builder* m_activeLayer;
- std::vector<vtzero::layer_builder*> m_prevLayers;
+ void AddActiveFeatureProperties(vtzero::feature_builder* builder);
+ RS_FeatureReader* m_activeFeature;
+ vtzero::tile_builder* m_tileBuilder;
+ vtzero::layer_builder* m_activeLayerBuilder;
+ std::vector<vtzero::layer_builder*> m_prevLayerBuilder;
+
// map/layer/feature info
RS_MapUIInfo* m_mapInfo;
RS_LayerUIInfo* m_layerInfo;
@@ -82,6 +88,8 @@
SE_Matrix m_xform;
SE_Matrix m_ixform;
+ int m_width;
+ int m_height;
RS_Bounds m_extents;
double m_drawingScale;
More information about the mapguide-commits
mailing list