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
}
Esempio n. 3
0
 inline GeometryCollectionBaseType::const_iterator range_begin(const GeometryCollection& gc) {return gc.begin();}