[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