void limitHoles(GeometryCollection& polygon, uint32_t maxHoles) { if (polygon.size() > 1 + maxHoles) { std::nth_element(polygon.begin() + 1, polygon.begin() + 1 + maxHoles, polygon.end(), [] (const auto& a, const auto& b) { return signedArea(a) > signedArea(b); }); polygon.resize(1 + maxHoles); } }
/** * Prepares a geometry into a grid if it is too big geospatially to have a sensible local tangent plane * We will also tile the geometry if it just has too many points to speed up the tesselator. */ void prepareForTesselation(Geometry* geometry, const SpatialReference* featureSRS, double targetTileSizeDeg, unsigned int maxPointsPerTile, GeometryCollection& out) { // Clear the output list. GeometryCollection tiles; unsigned int count = geometry->size(); unsigned int tx = 1; unsigned int ty = 1; // Tile the geometry if it's geospatial size is too large to have a sensible local tangent plane. GeoExtent featureExtentDeg = GeoExtent(featureSRS, geometry->getBounds()).transform(SpatialReference::create("wgs84")); // Tile based on the extent if ( featureExtentDeg.width() > targetTileSizeDeg || featureExtentDeg.height() > targetTileSizeDeg) { // Determine the tile size based on the extent. tx = ceil( featureExtentDeg.width() / targetTileSizeDeg ); ty = ceil (featureExtentDeg.height() / targetTileSizeDeg ); } else if (count > maxPointsPerTile) { // Determine the size based on the number of points. unsigned numTiles = ((double)count / (double)maxPointsPerTile) + 1u; tx = ceil(sqrt((double)numTiles)); ty = tx; } if (tx == 1 && ty == 1) { // The geometry doesn't need modified so just add it to the list. tiles.push_back( geometry ); } else { tileGeometry( geometry, featureSRS, tx, ty, tiles ); } out.clear(); #if 1 // Just copy the output tiles to the output. std::copy(tiles.begin(), tiles.end(), std::back_inserter(out)); #else // Calling this code will recursively subdivide the cells based on the number of points they have. // This works but it will produces a non-regular grid which doesn't render well in geocentric // due to the curvature of the earth so we disable it for now. // // Reduce the size of the tiles if needed. for (unsigned int i = 0; i < tiles.size(); i++) { if (tiles[i]->size() > maxPointsPerTile) { GeometryCollection tmp; downsizeGeometry(tiles[i].get(), featureSRS, maxPointsPerTile, tmp); std::copy(tmp.begin(), tmp.end(), std::back_inserter(out)); } else { out.push_back( tiles[i].get() ); } } #endif }
inline GeometryCollectionBaseType::const_iterator range_begin(const GeometryCollection& gc) {return gc.begin();}