[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