[mapguide-commits] r9618 - in sandbox/jng/mvt_alt: Common/Renderers Server/src/Services/Rendering Server/src/UnitTesting

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Mon Sep 23 14:09:00 PDT 2019


Author: jng
Date: 2019-09-23 14:09:00 -0700 (Mon, 23 Sep 2019)
New Revision: 9618

Modified:
   sandbox/jng/mvt_alt/Common/Renderers/MVTRenderer.cpp
   sandbox/jng/mvt_alt/Server/src/Services/Rendering/ServerRenderingService.cpp
   sandbox/jng/mvt_alt/Server/src/Services/Rendering/ServerRenderingService.h
   sandbox/jng/mvt_alt/Server/src/UnitTesting/TestRenderingService.cpp
Log:
With better understanding of how LineBuffer instances are structured (thanks unit tests!), implement the remainder of the MVT renderer

Modified: sandbox/jng/mvt_alt/Common/Renderers/MVTRenderer.cpp
===================================================================
--- sandbox/jng/mvt_alt/Common/Renderers/MVTRenderer.cpp	2019-09-22 01:35:43 UTC (rev 9617)
+++ sandbox/jng/mvt_alt/Common/Renderers/MVTRenderer.cpp	2019-09-23 21:09:00 UTC (rev 9618)
@@ -32,12 +32,16 @@
 //  - Stash the RS_FeatureReader pointer on every StartFeature() call (we need this for writing properties)
 //  - For every ProcessXXX() call
 //    - Create a MVTTileLayerFeature instance
-//    - Write the line buffer coordinates to this builder
 //    - Write the active property map
-//    - Commit the builder
+//    - Encode the geometry coordinates
+//    - Add the MVTTileLayerFeature if encoding succeeds
 //
 // ================================================================================ //
 
+// WebMercator related constants
+constexpr double kmSPHERICAL_RADIUS = 6378137.0;
+constexpr double kmMAX_GM = kmSPHERICAL_RADIUS * M_PI;  // 20037508.342789244
+
 static unsigned GetCmdCountCombined(unsigned int nCmdId,
     unsigned int nCmdCount)
 {
@@ -52,9 +56,10 @@
         , m_tileX(x)
         , m_tileY(y)
         , m_tileZ(z)
-        , m_dfTopX(0.0)
-        , m_dfTopY(0.0)
-        , m_dfTileDim0(0.0)
+        //InitWebMercatorTilingScheme
+        , m_dfTopX(-kmMAX_GM)
+        , m_dfTopY(kmMAX_GM)
+        , m_dfTileDim0(2 * kmMAX_GM)
         , m_parent(parent)
     { }
 
@@ -65,14 +70,14 @@
 
     void SetActiveLayerBuilder(const std::string& name)
     {
-        m_activeLayer = new MVTTileLayer();
+        m_activeLayer = std::make_shared<MVTTileLayer>();
         m_activeLayer->setName(name);
+        m_tile.addLayer(m_activeLayer);
     }
 
     void ClearActiveLayerBuilder()
     {
-        m_prevLayers.push_back(m_activeLayer);
-        m_activeLayer = nullptr;
+        m_activeLayer.reset();
     }
 
     void ConvertToTileCoords(double dfX,
@@ -186,7 +191,7 @@
 
     bool EncodePolygonGeometry(MVTTileLayerFeature* poGPBFeature,
                                LineBuffer* lb,
-                               int polyIdx,
+                               int cStart, int cEnd,
                                double dfTopX,
                                double dfTopY,
                                double dfTileDim,
@@ -194,7 +199,30 @@
                                int& nLastX,
                                int& nLastY) const
     {
-        return false;
+        for (int i = cStart; i <= cEnd; i++)
+        {
+            const bool bWriteLastPoint = false;
+            const bool bReverseOrder = (i > 0);
+            const GUInt32 nMinLineTo = 2;
+            const GUInt32 nInitialSize = poGPBFeature->getGeometryCount();
+            const int nLastXOri = nLastX;
+            const int nLastYOri = nLastY;
+
+            bool bSuccess =
+                EncodeLineStringGeometry(poGPBFeature, lb, i,
+                    bWriteLastPoint, bReverseOrder,
+                    nMinLineTo,
+                    dfTopX, dfTopY, dfTileDim, nLastX, nLastY);
+            
+            if (!bSuccess)
+            {
+                if (i == 0)
+                    return false;
+                continue;
+            }
+            poGPBFeature->addGeometry(GetCmdCountCombined(knCMD_CLOSEPATH, 1));
+        }
+        return true;
     }
 
     bool EncodePolygon(MVTTileLayerFeature* feature, LineBuffer* lb)
@@ -206,24 +234,20 @@
         int nLastY = 0;
         bool bGeomOK = false;
 
-        //TODO: Can probably fold everything into the MultiPolygon code path here
-        if (lb->cntr_count() == 1)
+        int cStart = 0;
+        int geom_count = lb->geom_count();
+        for (int i = 0; i < geom_count; i++)
         {
-            bGeomOK = EncodePolygonGeometry(feature, lb, 0,
+            int cSize = lb->geom_size(i);
+
+            bGeomOK |= EncodePolygonGeometry(feature, lb,
+                cStart, cSize - 1,
                 dfTopX, dfTopY, dfTileDim,
                 true,
                 nLastX, nLastY);
+
+            cStart += cSize;
         }
-        else //MultiPolygon
-        {
-            for (int i = 0; i < lb->cntr_count(); i++)
-            {
-                bGeomOK |= EncodePolygonGeometry(feature, lb, i,
-                    dfTopX, dfTopY, dfTileDim,
-                    true,
-                    nLastX, nLastY);
-            }
-        }
 
         return bGeomOK;
     }
@@ -232,9 +256,9 @@
     {
         auto feature = std::make_shared<MVTTileLayerFeature>();
         feature->setType(MVTTileLayerFeature::GeomType::POLYGON);
-        AddActiveFeatureProperties(activeFeature, m_activeLayer, feature.get());
-        EncodePolygon(feature.get(), lb);
-        m_activeLayer->addFeature(feature);
+        AddActiveFeatureProperties(activeFeature, m_activeLayer.get(), feature.get());
+        if (EncodePolygon(feature.get(), lb))
+            m_activeLayer->addFeature(feature);
     }
 
     bool EncodeLineStringGeometry(MVTTileLayerFeature* poGPBFeature,
@@ -371,9 +395,9 @@
     {
         auto feature = std::make_shared<MVTTileLayerFeature>();
         feature->setType(MVTTileLayerFeature::GeomType::LINESTRING);
-        AddActiveFeatureProperties(activeFeature, m_activeLayer, feature.get());
-        EncodePolyine(feature.get(), lb);
-        m_activeLayer->addFeature(feature);
+        AddActiveFeatureProperties(activeFeature, m_activeLayer.get(), feature.get());
+        if (EncodePolyine(feature.get(), lb))
+            m_activeLayer->addFeature(feature);
     }
 
     bool EncodePoint(MVTTileLayerFeature* feature, LineBuffer* lb)
@@ -431,9 +455,9 @@
     {
         auto feature = std::make_shared<MVTTileLayerFeature>();
         feature->setType(MVTTileLayerFeature::GeomType::POINT);
-        AddActiveFeatureProperties(activeFeature, m_activeLayer, feature.get());
-        EncodePoint(feature.get(), lb);
-        m_activeLayer->addFeature(feature);
+        AddActiveFeatureProperties(activeFeature, m_activeLayer.get(), feature.get());
+        if (EncodePoint(feature.get(), lb))
+            m_activeLayer->addFeature(feature);
     }
 
     unsigned char* GetMVTContent(size_t& size)
@@ -458,8 +482,7 @@
 
 private:
     MVTTile m_tile;
-    MVTTileLayer* m_activeLayer;
-    std::vector<MVTTileLayer*> m_prevLayers;
+    std::shared_ptr<MVTTileLayer> m_activeLayer;
     MVTRenderer* m_parent;
 
     int m_tileX;

Modified: sandbox/jng/mvt_alt/Server/src/Services/Rendering/ServerRenderingService.cpp
===================================================================
--- sandbox/jng/mvt_alt/Server/src/Services/Rendering/ServerRenderingService.cpp	2019-09-22 01:35:43 UTC (rev 9617)
+++ sandbox/jng/mvt_alt/Server/src/Services/Rendering/ServerRenderingService.cpp	2019-09-23 21:09:00 UTC (rev 9618)
@@ -208,7 +208,7 @@
     return ret.Detach();
 }
 
-void MgServerRenderingService::ComputeXYZTileExtents(MgMap* map, INT32 x, INT32 y, INT32 z, RS_Bounds& extent)
+void MgServerRenderingService::ComputeXYZTileExtents(MgCoordinateSystem* mapCs, INT32 x, INT32 y, INT32 z, RS_Bounds& extent)
 {
     //XYZ to lat/lon math. From this we can convert to the bounds in the map's CS
     //
@@ -225,11 +225,9 @@
     double mcsMaxX = std::max(lonMin, lonMax);
     double mcsMaxY = std::max(latMin, latMax);
 
-    STRING mapCsWkt = map->GetMapSRS();
-    Ptr<MgCoordinateSystemFactory> csFactory = new MgCoordinateSystemFactory();
-    Ptr<MgCoordinateSystem> mapCs = csFactory->Create(mapCsWkt);
     if (mapCs->GetCsCode() != L"LL84")
     {
+        Ptr<MgCoordinateSystemFactory> csFactory = new MgCoordinateSystemFactory();
         //Set up LL to map transform and transform the bounds into map space
         Ptr<MgCoordinateSystem> llCs = csFactory->CreateFromCode(L"LL84");
         Ptr<MgCoordinateSystemTransform> trans = csFactory->GetTransform(llCs, mapCs);
@@ -250,6 +248,14 @@
     extent.maxy = mcsMaxY;
 }
 
+void MgServerRenderingService::ComputeXYZTileExtents(STRING mapCsWkt, INT32 x, INT32 y, INT32 z, RS_Bounds& extent)
+{
+    Ptr<MgCoordinateSystemFactory> csFactory = new MgCoordinateSystemFactory();
+    Ptr<MgCoordinateSystem> mapCs = csFactory->Create(mapCsWkt);
+    
+    ComputeXYZTileExtents(mapCs, x, y, z, extent);
+}
+
 MgByteReader* MgServerRenderingService::RenderTileXYZ(MgMap* map,
                                                       CREFSTRING baseMapLayerGroupName,
                                                       INT32 x,
@@ -317,7 +323,7 @@
 
     // get map extent that corresponds to tile extent
     RS_Bounds extent;
-    ComputeXYZTileExtents(map, x, y, z, extent);
+    ComputeXYZTileExtents(map->GetMapSRS(), x, y, z, extent);
 
     // use the map's background color, but always make it fully transparent
     RS_Color bgColor;
@@ -465,24 +471,25 @@
     int width = MVT_TILE_WIDTH;
     int height = MVT_TILE_HEIGHT;
 
+    // MVT tiles are always written in web mercator
+    STRING srs = m_pCSFactory->ConvertCoordinateSystemCodeToWkt(L"WGS84.PseudoMercator");
+    Ptr<MgCoordinateSystem> dstCs = m_pCSFactory->Create(srs);
+    double metersPerUnit = dstCs->ConvertCoordinateSystemUnitsToMeters(1.0);
+
     // Inlining same logic from RenderTile() overload below as we want the same logic, but we want to pass scale
     // instead of scale index
 
     // get map extent that corresponds to tile extent
     RS_Bounds extent;
-    ComputeXYZTileExtents(map, x, y, z, extent);
+    ComputeXYZTileExtents(dstCs, x, y, z, extent);
 
     INT32 drawWidth = width;
     INT32 drawHeight = height;
     double scale = 0.0;
-    ComputeScaledDimensions(extent, width, height, dpi, map->GetMetersPerUnit(), drawWidth, drawHeight, scale);
+    ComputeScaledDimensions(extent, width, height, dpi, metersPerUnit, drawWidth, drawHeight, scale);
 
     //printf("XYZ(%d, %d, %d) -> [%f, %f] [%f, %f] at %f -- (w: %d, h: %d, mpu: %f)\n", x, y, z, mcsMinX, mcsMinY, mcsMaxX, mcsMaxY, scale, width, height, map->GetMetersPerUnit());
 
-    // sanity check - number of image pixels cannot exceed MAX_PIXELS
-    if (drawWidth * drawHeight > MAX_PIXELS)
-        throw new MgOutOfRangeException(L"MgServerRenderingService.RenderTileMVT", __LINE__, __WFILE__, NULL, L"MgInvalidImageSizeTooBig", NULL);
-
     // create a temporary collection containing all the layers for the base group
     Ptr<MgLayerCollection> layers = map->GetLayers();
     Ptr<MgReadOnlyLayerCollection> roLayers = new MgReadOnlyLayerCollection();
@@ -506,23 +513,6 @@
     // set the map scale to the requested scale
     map->SetViewScale(scale);
 
-    // convert the map coordinate system from srs wkt to a mentor cs structure
-    STRING srs = map->GetMapSRS();
-    Ptr<MgCoordinateSystem> dstCs;
-    if (!srs.empty())
-    {
-        // let's not fail here if coord sys conversion fails for the map's
-        // coordinate system. Instead we will fail per layer at a later stage
-        try
-        {
-            dstCs = m_pCSFactory->Create(srs);
-        }
-        catch (MgInvalidCoordinateSystemException* e)
-        {
-            e->Release();
-        }
-    }
-
     RS_String units = dstCs.p ? dstCs->GetUnits() : L"";
 
     // get the session ID
@@ -549,7 +539,7 @@
     dr.StartMap(&mapInfo, extent, scale, map->GetDisplayDpi(), map->GetMetersPerUnit(), NULL);
 
     // We can't use RenderMapInternal, but we can use RenderLayers, which is all we really need
-    RenderLayers(map, roLayers, &ds, &dr, dstCs, true, scale, L"UTFGRID", NULL);
+    RenderLayers(map, roLayers, &ds, &dr, dstCs, true, scale, L"MVT", NULL);
 
     dr.EndMap();
 
@@ -2549,7 +2539,8 @@
     // Inlining same logic from RenderTile() overload below as we want the same logic, but we want to pass scale
     // instead of scale index
     RS_Bounds extent;
-    ComputeXYZTileExtents(map, x, y, z, extent);
+    STRING mapSrs = map->GetMapSRS();
+    ComputeXYZTileExtents(mapSrs, x, y, z, extent);
 
     // If meta-tiling, request bounds for:
     //   (x, y, z) -> (x + (tm - 1), y + (tm - 1), z)
@@ -2559,7 +2550,7 @@
         RS_Bounds extent2;
         INT32 endX = x + (metaTilingFactor - 1);
         INT32 endY = y + (metaTilingFactor - 1);
-        ComputeXYZTileExtents(map, endX, endY, z, extent2);
+        ComputeXYZTileExtents(mapSrs, endX, endY, z, extent2);
 
         extent.add_bounds(extent2);
     }

Modified: sandbox/jng/mvt_alt/Server/src/Services/Rendering/ServerRenderingService.h
===================================================================
--- sandbox/jng/mvt_alt/Server/src/Services/Rendering/ServerRenderingService.h	2019-09-22 01:35:43 UTC (rev 9617)
+++ sandbox/jng/mvt_alt/Server/src/Services/Rendering/ServerRenderingService.h	2019-09-23 21:09:00 UTC (rev 9618)
@@ -311,7 +311,8 @@
     static void ComputeScaledDimensions(RS_Bounds& extent, INT32 width, INT32 height, INT32 dpi,
                                         double metersPerUnit, INT32& drawWidth, INT32& drawHeight, double& scale);
 
-    static void ComputeXYZTileExtents(MgMap* map, INT32 x, INT32 y, INT32 z, RS_Bounds& extent);
+    static void ComputeXYZTileExtents(MgCoordinateSystem* mapCs, INT32 x, INT32 y, INT32 z, RS_Bounds& extent);
+    static void ComputeXYZTileExtents(STRING mapCsWkt, INT32 x, INT32 y, INT32 z, RS_Bounds& extent);
     // used for tile generation
     MgByteReader* RenderTileInternal(MgMap* map,
                                      MgLayerGroup* baseGroup,

Modified: sandbox/jng/mvt_alt/Server/src/UnitTesting/TestRenderingService.cpp
===================================================================
--- sandbox/jng/mvt_alt/Server/src/UnitTesting/TestRenderingService.cpp	2019-09-22 01:35:43 UTC (rev 9617)
+++ sandbox/jng/mvt_alt/Server/src/UnitTesting/TestRenderingService.cpp	2019-09-23 21:09:00 UTC (rev 9618)
@@ -1920,7 +1920,7 @@
         imgBL->ToFile(L"../UnitTestFiles/RenderTileMVT_BL_ImageBaseline.png");
         imgBR->ToFile(L"../UnitTestFiles/RenderTileMVT_BR_ImageBaseline.png");
 
-        //Now render the utf grids at the same place
+        //Now render the MVT tiles at the same place
         Ptr<MgByteReader> mvtTL = m_svcRendering->RenderTileMVT(map, L"BaseLayers", 16797, 23893, 16, 96);
         Ptr<MgByteReader> mvtTR = m_svcRendering->RenderTileMVT(map, L"BaseLayers", 16798, 23893, 16, 96);
         Ptr<MgByteReader> mvtBL = m_svcRendering->RenderTileMVT(map, L"BaseLayers", 16797, 23894, 16, 96);



More information about the mapguide-commits mailing list