Esempio n. 1
0
void
GeometryGroup::Draw (cairo_t *cr)
{
	Transform *transform = GetTransform ();
	cairo_matrix_t saved;
	cairo_get_matrix (cr, &saved);

	if (transform) {
		cairo_matrix_t matrix;
		transform->GetTransform (&matrix);
		cairo_transform (cr, &matrix);
	}
	
	GeometryCollection *children = GetChildren ();
	Geometry *geometry;

	// GeometryGroup is used for Clip (as a Geometry) so Fill (normally setting the fill rule) is never called
	cairo_set_fill_rule (cr, convert_fill_rule (GetFillRule ()));
	
	int children_count = children->GetCount ();
	for (int i = 0; i < children_count; i++) {
		geometry = children->GetValueAt (i)->AsGeometry ();
		
		geometry->Draw (cr);
	}
	
	cairo_set_matrix (cr, &saved);
}
Esempio n. 2
0
	std::auto_ptr<Geometry> collect( const Geometry& ga, const Geometry& gb )
	{
		if ( ga.geometryTypeId() == gb.geometryTypeId() ) {
			if ( ga.geometryTypeId() == TYPE_POINT ) {
				MultiPoint *mp = new MultiPoint;
				mp->addGeometry( ga );
				mp->addGeometry( gb );
				return std::auto_ptr<Geometry>(mp);
			}
			else if ( ga.geometryTypeId() == TYPE_LINESTRING ) {
				MultiLineString *mls = new MultiLineString();
				mls->addGeometry(ga);
				mls->addGeometry(gb);
				return std::auto_ptr<Geometry>( mls );
			}
			else if ( ga.geometryTypeId() == TYPE_POLYGON ) {
				MultiPolygon *mp = new MultiPolygon();
				mp->addGeometry(ga);
				mp->addGeometry(gb);
				return std::auto_ptr<Geometry>( mp );
			}
			else if ( ga.geometryTypeId() == TYPE_SOLID ) {
				MultiSolid *mp = new MultiSolid();
				mp->addGeometry(ga);
				mp->addGeometry(gb);
				return std::auto_ptr<Geometry>( mp );
			}
		}

		// else
		GeometryCollection* coll = new GeometryCollection();
		coll->addGeometry(ga);
		coll->addGeometry(gb);
		return std::auto_ptr<Geometry>( coll );
	}
optional<GeometryCollection> offsetLine(const GeometryCollection& rings, const double offset) {
    if (offset == 0) return {};

    GeometryCollection newRings;
    Point<double> zero(0, 0);
    for (const auto& ring : rings) {
        newRings.emplace_back();
        auto& newRing = newRings.back();

        for (auto i = ring.begin(); i != ring.end(); i++) {
            auto& p = *i;

            Point<double> aToB = i == ring.begin() ?
                zero :
                util::perp(util::unit(convertPoint<double>(p - *(i - 1))));
            Point<double> bToC = i + 1 == ring.end() ?
                zero :
                util::perp(util::unit(convertPoint<double>(*(i + 1) - p)));
            Point<double> extrude = util::unit(aToB + bToC);

            const double cosHalfAngle = extrude.x * bToC.x + extrude.y * bToC.y;
            extrude *= (1.0 / cosHalfAngle);

            newRing.push_back(convertPoint<int16_t>(extrude * offset) + p);
        }
    }

    return newRings;
}
/**
 * Tiles the geometry up until all the cells have less than given number of points.
 */
void downsizeGeometry(Geometry* geometry, const SpatialReference* featureSRS, unsigned int maxPoints, GeometryCollection& out)
{
    // If the geometyr is greater than the maximum number of points, we need to tile it up further.
    if (geometry->size() > maxPoints)
    {
        OE_NOTICE << "Downsizing geometry of size " << geometry->size() << std::endl;
        // Tile the geometry.
        GeometryCollection tmp;
        tileGeometry(geometry, featureSRS, 2, 2, tmp );
        
        for (unsigned int i = 0; i < tmp.size(); i++)
        {
            Geometry* g = tmp[i].get();

            // If the generated geometry still has too many points, continue to downsample it recursively.
            if (g->size() > maxPoints)
            {
                // We pass "out" as the destination here since downsizeGeometry will only append tiles that are less than the max size.
                downsizeGeometry( g, featureSRS, maxPoints, out );
            }
            else
            {
                // Append the geometry to the output list.
                out.push_back( g );
            }
        }
    }
    else
    {
        // The geometry is valid, so add it to the output list.
        out.push_back( geometry );
    }
}
Esempio n. 5
0
GeometryCollection*
GeometryEditor::editGeometryCollection(const GeometryCollection *collection, GeometryEditorOperation *operation)
{
	GeometryCollection *newCollection = (GeometryCollection*) operation->edit(collection,factory);
	vector<Geometry*> *geometries = new vector<Geometry*>();
	for (int i = 0; i < newCollection->getNumGeometries(); i++) {
		Geometry *geometry = edit(newCollection->getGeometryN(i),
			operation);
		if (geometry->isEmpty()) {
			delete geometry;
			continue;
		}
		geometries->push_back(geometry);
	}

	if (typeid(*newCollection)==typeid(MultiPoint)) {
		delete newCollection;
		return factory->createMultiPoint(geometries);
	}
	else if (typeid(*newCollection)==typeid(MultiLineString)) {
		delete newCollection;
		return factory->createMultiLineString(geometries);
	}
	else if (typeid(*newCollection)==typeid(MultiPolygon)) {
		delete newCollection;
		return factory->createMultiPolygon(geometries);
	}
	else {
		delete newCollection;
		return factory->createGeometryCollection(geometries);
	}
}
optional<GeometryCollection> FeatureIndex::translateQueryGeometry(
        const GeometryCollection& queryGeometry,
        const std::array<float, 2>& translate,
        const TranslateAnchorType anchorType,
        const float bearing,
        const float pixelsToTileUnits) {

    if (translate[0] == 0 && translate[1] == 0) return {};

    GeometryCoordinate translateVec(translate[0] * pixelsToTileUnits, translate[1] * pixelsToTileUnits);

    if (anchorType == TranslateAnchorType::Viewport) {
        translateVec = util::rotate(translateVec, -bearing);
    }

    GeometryCollection translated;
    for (auto& ring : queryGeometry) {
        translated.emplace_back();
        auto& translatedRing = translated.back();
        for (auto& p : ring) {
            translatedRing.push_back(p - translateVec);
        }
    }
    return translated;
}
Esempio n. 7
0
void ForceValidityVisitor::visit( GeometryCollection& g )
{
    g.forceValidityFlag( valid_ );
    for ( size_t i = 0; i < g.numGeometries(); i++ ) {
        g.geometryN( i ).accept( *this );
    }
}
Esempio n. 8
0
void triangulatePolygon3D(
    const GeometryCollection& g,
    TriangulatedSurface& triangulatedSurface
)
{
    for ( size_t i = 0; i < g.numGeometries(); i++ ) {
        triangulatePolygon3D( g.geometryN( i ), triangulatedSurface );
    }
}
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);
    }
}
 GeometryCollection operator()(const mapbox::geometry::multi_line_string<int16_t>& geom) const {
     GeometryCollection collection;
     collection.reserve(geom.size());
     for (const auto& ring : geom) {
         GeometryCoordinates coordinates;
         coordinates.reserve(ring.size());
         for (const auto& point : ring) {
             coordinates.emplace_back(point);
         }
         collection.push_back(std::move(coordinates));
     }
     return collection;
 }
 GeometryCollection operator()(const mapbox::geometry::multi_polygon<int16_t>& geom) const {
     GeometryCollection collection;
     for (auto& polygon : geom) {
         for (auto& ring : polygon) {
             GeometryCoordinates coordinates;
             coordinates.reserve(ring.size());
             for (auto& point : ring) {
                 coordinates.emplace_back(point);
             }
             collection.push_back(std::move(coordinates));
         }
     }
     return collection;
 }
Esempio n. 12
0
void WktWriter::write( const GeometryCollection & g )
{
	_s << "GEOMETRYCOLLECTION" ;
	if ( g.isEmpty() ){
		_s << " EMPTY" ;
		return ;
	}

	_s << "(" ;
	for ( size_t i = 0 ; i < g.numGeometries(); i++ ){
		if ( i != 0 )
			_s << ",";
		write( g.geometryN(i) );
	}
	_s << ")" ;
}
Esempio n. 13
0
Rect
GeometryGroup::ComputePathBounds ()
{
	GeometryCollection *children = GetChildren ();
	Rect bounds = Rect (0.0, 0.0, 0.0, 0.0);
	Geometry *geometry;
	int children_count = children->GetCount ();

	for (int i = 0; i < children_count; i++) {
		geometry = children->GetValueAt (i)->AsGeometry ();
		
		bounds = bounds.Union (geometry->GetBounds (), true);
	}
	
	//g_warning ("GeometryGroup::ComputeBounds - x %g y %g w %g h %g", bounds.x, bounds.y, bounds.w, bounds.h);
	return bounds;
}
static void processPolynodeBranch(ClipperLib::PolyNode* polynode, GeometryCollection& rings) {
    // Exterior ring.
    rings.push_back(fromClipperPath(polynode->Contour));
    assert(signedArea(rings.back()) > 0);

    // Interior rings.
    for (auto * ring : polynode->Childs) {
        rings.push_back(fromClipperPath(ring->Contour));
        assert(signedArea(rings.back()) < 0);
    }

    // PolyNodes may be nested in the case of a polygon inside a hole.
    for (auto * ring : polynode->Childs) {
        for (auto * subRing : ring->Childs) {
            processPolynodeBranch(subRing, rings);
        }
    }
}
GeometryCollection clipLines(const GeometryCollection &lines,
        const int16_t x1, const int16_t y1, const int16_t x2, const int16_t y2) {

    GeometryCollection clippedLines;

    for (auto& line : lines) {

        if (line.empty())
            continue;

        auto end = line.end() - 1;
        for (auto it = line.begin(); it != end; it++) {
            GeometryCoordinate p0 = *(it);
            GeometryCoordinate p1 = *(it + 1);

            if (p0.x < x1 && p1.x < x1) {
                continue;
            } else if (p0.x < x1) {
                p0 = { x1, static_cast<int16_t>(::round(p0.y + (p1.y - p0.y) * ((float)(x1 - p0.x) / (p1.x - p0.x)))) };
            } else if (p1.x < x1) {
                p1 = { x1, static_cast<int16_t>(::round(p0.y + (p1.y - p0.y) * ((float)(x1 - p0.x) / (p1.x - p0.x)))) };
            }

            if (p0.y < y1 && p1.y < y1) {
                continue;
            } else if (p0.y < y1) {
                p0 = { static_cast<int16_t>(::round(p0.x + (p1.x - p0.x) * ((float)(y1 - p0.y) / (p1.y - p0.y)))), y1 };
            } else if (p1.y < y1) {
                p1 = { static_cast<int16_t>(::round(p0.x + (p1.x - p0.x) * ((float)(y1 - p0.y) / (p1.y - p0.y)))), y1 };
            }

            if (p0.x >= x2 && p1.x >= x2) {
                continue;
            } else if (p0.x >= x2) {
                p0 = { x2, static_cast<int16_t>(::round(p0.y + (p1.y - p0.y) * ((float)(x2 - p0.x) / (p1.x - p0.x)))) };
            } else if (p1.x >= x2) {
                p1 = { x2, static_cast<int16_t>(::round(p0.y + (p1.y - p0.y) * ((float)(x2 - p0.x) / (p1.x - p0.x)))) };
            }

            if (p0.y >= y2 && p1.y >= y2) {
                continue;
            } else if (p0.y >= y2) {
                p0 = { static_cast<int16_t>(::round(p0.x + (p1.x - p0.x) * ((float)(y2 - p0.y) / (p1.y - p0.y)))), y2 };
            } else if (p1.y >= y2) {
                p1 = { static_cast<int16_t>(::round(p0.x + (p1.x - p0.x) * ((float)(y2 - p0.y) / (p1.y - p0.y)))), y2 };
            }

            if (clippedLines.empty() || (!clippedLines.back().empty() && !(p0 == clippedLines.back().back()))) {
                clippedLines.emplace_back();
                clippedLines.back().push_back(p0);
            }

            clippedLines.back().push_back(p1);
        }
    }

    return clippedLines;
}
/**
 * Tiles the Geometry into the given number of columns and rows
 */
void tileGeometry(Geometry* geometry, const SpatialReference* featureSRS, unsigned int numCols, unsigned int numRows, GeometryCollection& out)
{
    // Clear the output list.
    out.clear();

    Bounds b = geometry->getBounds();
    double tw = b.width() / (double)numCols;
    double th = b.height() / (double)numRows;

    // Get the average Z, since GEOS will set teh Z of new verts to that of the cropping polygon,
    // which is stupid but that's how it is.
    double z = 0.0;
    for(unsigned i=0; i<geometry->size(); ++i)
        z += geometry->at(i).z();
    z /= geometry->size();

    osg::ref_ptr<Polygon> poly = new Polygon;
    poly->resize( 4 );        

    for(int x=0; x<(int)numCols; ++x)
    {
        for(int y=0; y<(int)numRows; ++y)
        {
            (*poly)[0].set( b.xMin() + tw*(double)x,     b.yMin() + th*(double)y,     z );
            (*poly)[1].set( b.xMin() + tw*(double)(x+1), b.yMin() + th*(double)y,     z );
            (*poly)[2].set( b.xMin() + tw*(double)(x+1), b.yMin() + th*(double)(y+1), z );
            (*poly)[3].set( b.xMin() + tw*(double)x,     b.yMin() + th*(double)(y+1), z );

            osg::ref_ptr<Geometry> ringTile;
            if ( geometry->crop(poly.get(), ringTile) )
            {
                // Use an iterator since crop could return a multi-polygon
                GeometryIterator gi( ringTile.get(), false );
                while( gi.hasMore() )
                {
                    Geometry* geom = gi.next();
                    out.push_back( geom );                                                
                }
            }
        }
    }
}
Esempio n. 17
0
GeometryCollection VectorTileFeature::getGeometries() const {
    uint8_t cmd = 1;
    uint32_t length = 0;
    int32_t x = 0;
    int32_t y = 0;
    const float scale = float(util::EXTENT) / layer.extent;

    GeometryCollection lines;

    lines.emplace_back();
    GeometryCoordinates* line = &lines.back();

    auto g_itr = geometry_iter.begin();
    while (g_itr != geometry_iter.end()) {
        if (length == 0) {
            uint32_t cmd_length = static_cast<uint32_t>(*g_itr++);
            cmd = cmd_length & 0x7;
            length = cmd_length >> 3;
        }

        --length;

        if (cmd == 1 || cmd == 2) {
            x += protozero::decode_zigzag32(static_cast<uint32_t>(*g_itr++));
            y += protozero::decode_zigzag32(static_cast<uint32_t>(*g_itr++));

            if (cmd == 1 && !line->empty()) { // moveTo
                lines.emplace_back();
                line = &lines.back();
            }

            line->emplace_back(::round(x * scale), ::round(y * scale));

        } else if (cmd == 7) { // closePolygon
            if (!line->empty()) {
                line->push_back((*line)[0]);
            }

        } else {
            throw std::runtime_error("unknown command");
        }
    }
Esempio n. 18
0
GeometryCollection VectorTileFeature::getGeometries() const {
    pbf data(geometry_pbf);
    uint8_t cmd = 1;
    uint32_t length = 0;
    int32_t x = 0;
    int32_t y = 0;

    GeometryCollection lines;

    lines.emplace_back();
    GeometryCoordinates* line = &lines.back();

    while (data.data < data.end) {
        if (length == 0) {
            uint32_t cmd_length = data.varint();
            cmd = cmd_length & 0x7;
            length = cmd_length >> 3;
        }

        --length;

        if (cmd == 1 || cmd == 2) {
            x += data.svarint();
            y += data.svarint();

            if (cmd == 1 && !line->empty()) { // moveTo
                lines.emplace_back();
                line = &lines.back();
            }

            line->emplace_back(x, y);

        } else if (cmd == 7) { // closePolygon
            if (!line->empty()) {
                line->push_back((*line)[0]);
            }

        } else {
            throw std::runtime_error("unknown command");
        }
    }
Esempio n. 19
0
void
WKBWriter::writeGeometryCollection(const GeometryCollection &g,
	int wkbtype) 
{
	writeByteOrder();
	
	writeGeometryType(wkbtype, g.getSRID());
	writeSRID(g.getSRID());
	
	int ngeoms = g.getNumGeometries();
	writeInt(ngeoms);

	assert(outStream);
	for (int i=0; i<ngeoms; i++)
	{
		const Geometry* elem = g.getGeometryN(i);
		assert(elem);

		write(*elem, *outStream);
	}
}
std::vector<GeometryCollection> classifyRings(const GeometryCollection& rings) {
    std::vector<GeometryCollection> polygons;

    std::size_t len = rings.size();

    if (len <= 1) {
        polygons.push_back(rings);
        return polygons;
    }

    GeometryCollection polygon;
    int8_t ccw = 0;

    for (std::size_t i = 0; i < len; i++) {
        double area = signedArea(rings[i]);

        if (area == 0)
            continue;

        if (ccw == 0)
            ccw = (area < 0 ? -1 : 1);

        if (ccw == (area < 0 ? -1 : 1) && !polygon.empty()) {
            polygons.push_back(polygon);
            polygon.clear();
        }

        polygon.push_back(rings[i]);
    }

    if (!polygon.empty())
        polygons.push_back(polygon);

    return polygons;
}
Esempio n. 21
0
void
WKBWriter::writeGeometryCollection(const GeometryCollection& g,
                                   int wkbtype)
{
    writeByteOrder();

    writeGeometryType(wkbtype, g.getSRID());
    writeSRID(g.getSRID());

    auto ngeoms = g.getNumGeometries();
    writeInt(static_cast<int>(ngeoms));
    auto orig_includeSRID = includeSRID;
    includeSRID = false;

    assert(outStream);
    for(std::size_t i = 0; i < ngeoms; i++) {
        const Geometry* elem = g.getGeometryN(i);
        assert(elem);

        write(*elem, *outStream);
    }
    includeSRID = orig_includeSRID;
}
Esempio n. 22
0
void GetPointsVisitor::visit( const GeometryCollection& g )
{
    for ( size_t i = 0; i < g.numGeometries(); i++ ) {
        g.geometryN( i ).accept( *this );
    }
}
void
BuildGeometryFilter::tileAndBuildPolygon(Geometry*               ring,
                                         const SpatialReference* featureSRS,
                                         const SpatialReference* mapSRS,
                                         bool                    makeECEF,
                                         bool                    tessellate,
                                         osg::Geometry*          osgGeom,
                                         const osg::Matrixd      &world2local)
{
#define MAX_POINTS_PER_CROP_TILE 1024
#define TARGET_TILE_SIZE_EXTENT_DEGREES 5.0

    // Tile the incoming polygon if necessary
    GeometryCollection tiles;
    prepareForTesselation( ring, featureSRS, TARGET_TILE_SIZE_EXTENT_DEGREES, MAX_POINTS_PER_CROP_TILE, tiles);    

    osg::ref_ptr<osg::Geode> geode = new osg::Geode;

    // Process each ring independently
    for (int ringIndex = 0; ringIndex < tiles.size(); ringIndex++)
    {
        Ring* geom = dynamic_cast< Ring*>(tiles[ringIndex].get());
        if (geom)
        {            
            // temporary target geometry for this cell:
            osg::ref_ptr<osg::Geometry> temp = new osg::Geometry();
            temp->setVertexArray( new osg::Vec3Array() );

            // establish a local plane for this cell based on its centroid:
            GeoPoint cellCenter(featureSRS, geom->getBounds().center());
            cellCenter.transform(mapSRS, cellCenter);                        
            osg::Matrix world2cell;
            cellCenter.createWorldToLocal( world2cell );

            // build the localized polygon:
            buildPolygon(geom, featureSRS, mapSRS, makeECEF, tessellate, temp.get(), world2cell);

            // if successful, transform the verts back into our master LTP:
            if ( temp->getNumPrimitiveSets() > 0 )
            {
                // Tesselate the polygon while the coordinates are still in the LTP
                if (tesselateGeometry( temp.get() ))
                {
                    osg::Vec3Array* verts = static_cast<osg::Vec3Array*>(temp->getVertexArray());
                    if ( verts->getNumElements() > 0 )
                    {
                        // Convert the coordinates back to the master LTP.
                        // This is ok, but you will probably run into precision errors if the tile size is very large.
                        osg::Matrix cell2world;
                        cell2world.invert( world2cell );
                        osg::Matrix cell2local = cell2world * world2local; // pre-multiply to avoid precision loss

                        for(int i=0; i<verts->size(); ++i)
                        {
                            (*verts)[i] = (*verts)[i] * cell2local;
                        }
                        geode->addDrawable(temp.get());
                    }
                }
            }
        }
    }

    // The geode is going to contain all of our polygons now, so merge them into one.
    osgUtil::Optimizer optimizer;
    osgUtil::Optimizer::MergeGeometryVisitor mgv;
    // We only want one Geometry, so don't limit the number of vertices.
    mgv.setTargetMaximumNumberOfVertices(UINT_MAX);
    mgv.apply( *geode.get() );

    // and copy them into the output geometry.
    if ( geode->getNumDrawables() > 0 )
    {
        // If we have more than one drawable after the MergeGeometryVisitor ran, we have a problem so
        // dump out some info to help debug.
        if (geode->getNumDrawables() != 1)
        {
            OE_WARN << LC << "MergeGeometryVisitor failed to merge geometries into a single one.  Num drawables " << geode->getNumDrawables() << std::endl;            
            for (unsigned int i = 0; i < geode->getNumDrawables(); i++)
            {
                osg::Geometry* g = geode->getDrawable(i)->asGeometry();
                if (g)
                {
                    osg::Vec3Array* verts = dynamic_cast<osg::Vec3Array*>(g->getVertexArray());
                    OE_WARN << "Geometry " << i << " has " << verts->size() << " verts" << std::endl;
                    OE_WARN << "Geometry " << i << " has " << g->getNumPrimitiveSets() << " primitive sets" << std::endl;
                    for (unsigned int j = 0; j < g->getNumPrimitiveSets(); j++)
                    {
                        osg::PrimitiveSet* ps = g->getPrimitiveSet(j);
                        OE_WARN << "PrimitiveSet " << j << ps->className() << std::endl;
                    }
                }
            }
        }
        osgGeom->setVertexArray( geode->getDrawable(0)->asGeometry()->getVertexArray() );
        osgGeom->setPrimitiveSetList( geode->getDrawable(0)->asGeometry()->getPrimitiveSetList() );
    }

    osgUtil::SmoothingVisitor::smooth( *osgGeom );
}
/**
 * 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. 25
0
int parse_wkt(const char * wkt, struct osmNode *** xnodes, int ** xcount, int * polygon) {
    GeometryFactory		gf;
    WKTReader		reader(&gf);
    std::string		wkt_string(wkt);
    Geometry *		geometry;
    const Geometry *	subgeometry;
    GeometryCollection *	gc;
    CoordinateSequence *	coords;
    size_t			num_geometries;
    size_t			i;
	
    *polygon = 0;
    try {
        geometry = reader.read(wkt_string);
        switch (geometry->getGeometryTypeId()) {
            // Single geometries
            case GEOS_POLYGON:
                // Drop through
            case GEOS_LINEARRING:
                *polygon = 1;
                // Drop through
            case GEOS_POINT:
                // Drop through
            case GEOS_LINESTRING:
                *xnodes = (struct osmNode **) malloc(2 * sizeof(struct osmNode *));
                *xcount = (int *) malloc(sizeof(int));
                coords = geometry->getCoordinates();
                (*xcount)[0] = coords2nodes(coords, &((*xnodes)[0]));
                (*xnodes)[1] = NULL;
                delete coords;
                break;
            // Geometry collections
            case GEOS_MULTIPOLYGON:
                *polygon = 1;
                // Drop through
            case GEOS_MULTIPOINT:
                // Drop through
            case GEOS_MULTILINESTRING:
                gc = dynamic_cast<GeometryCollection *>(geometry);;
                num_geometries = gc->getNumGeometries();
                *xnodes = (struct osmNode **) malloc((num_geometries + 1) * sizeof(struct osmNode *));
                *xcount = (int *) malloc(num_geometries * sizeof(int));
                for (i = 0; i < num_geometries; i++) {
                    subgeometry = gc->getGeometryN(i);
                    coords = subgeometry->getCoordinates();
                    (*xcount)[i] = coords2nodes(coords, &((*xnodes)[i]));
                    delete coords;
                }
                (*xnodes)[i] = NULL;
                break;
            default:
                std::cerr << std::endl << "unexpected object type while processing PostGIS data" << std::endl;
                delete geometry;
                return -1;
        }
        delete geometry;
    } catch (...) {
        std::cerr << std::endl << "Exception caught parsing PostGIS data" << std::endl;
        return -1;
    }
    return 0;
}
void ShapeAnnotationImpl::updateTile(const TileID& tileID, AnnotationTile& tile) {
    static const double baseTolerance = 4;

    if (!shapeTiler) {
        const uint64_t maxAmountOfTiles = 1 << maxZoom;
        const double tolerance = baseTolerance / (maxAmountOfTiles * GeometryTileFeature::defaultExtent);

        geojsonvt::ProjectedRings rings;
        std::vector<geojsonvt::LonLat> points;

        for (size_t i = 0; i < shape.segments[0].size(); ++i) { // first segment for now (no holes)
            const double constrainedLatitude = util::clamp(shape.segments[0][i].latitude, -util::LATITUDE_MAX, util::LATITUDE_MAX);
            points.push_back(geojsonvt::LonLat(shape.segments[0][i].longitude, constrainedLatitude));
        }

        if (type == geojsonvt::ProjectedFeatureType::Polygon &&
                (points.front().lon != points.back().lon || points.front().lat != points.back().lat)) {
            points.push_back(geojsonvt::LonLat(points.front().lon, points.front().lat));
        }

        auto ring = geojsonvt::Convert::projectRing(points, tolerance);
        rings.push_back(ring);

        std::vector<geojsonvt::ProjectedFeature> features;
        features.push_back(geojsonvt::Convert::create(geojsonvt::Tags(), type, rings));

        mapbox::geojsonvt::Options options;
        options.maxZoom = maxZoom;
        options.buffer = 255u;
        options.extent = util::EXTENT;
        options.tolerance = baseTolerance;
        shapeTiler = std::make_unique<mapbox::geojsonvt::GeoJSONVT>(features, options);
    }

    const auto& shapeTile = shapeTiler->getTile(tileID.sourceZ, tileID.x, tileID.y);
    if (!shapeTile)
        return;

    AnnotationTileLayer& layer = *tile.layers.emplace(layerID,
                                 std::make_unique<AnnotationTileLayer>()).first->second;

    for (auto& shapeFeature : shapeTile.features) {
        FeatureType featureType = FeatureType::Unknown;

        if (shapeFeature.type == geojsonvt::TileFeatureType::LineString) {
            featureType = FeatureType::LineString;
        } else if (shapeFeature.type == geojsonvt::TileFeatureType::Polygon) {
            featureType = FeatureType::Polygon;
        }

        assert(featureType != FeatureType::Unknown);

        GeometryCollection renderGeometry;
        for (auto& shapeRing : shapeFeature.tileGeometry.get<geojsonvt::TileRings>()) {
            GeometryCoordinates renderLine;

            for (auto& shapePoint : shapeRing) {
                renderLine.emplace_back(shapePoint.x, shapePoint.y);
            }

            renderGeometry.push_back(renderLine);
        }

        layer.features.emplace_back(
            std::make_shared<AnnotationTileFeature>(featureType, renderGeometry));
    }
}
Esempio n. 27
0
 inline GeometryCollectionBaseType::const_iterator range_end(const GeometryCollection& gc) {return gc.end();}
void ShapeAnnotationImpl::updateTile(const TileID& tileID, AnnotationTile& tile) {
    static const double baseTolerance = 3;
    static const uint16_t extent = 4096;

    if (!shapeTiler) {
        const uint64_t maxAmountOfTiles = 1 << maxZoom;
        const double tolerance = baseTolerance / (maxAmountOfTiles * extent);

        ProjectedGeometryContainer rings;
        std::vector<LonLat> points;

        for (size_t i = 0; i < shape.segments[0].size(); ++i) { // first segment for now (no holes)
            const double constraintedLatitude = ::fmin(::fmax(shape.segments[0][i].latitude, -util::LATITUDE_MAX), util::LATITUDE_MAX);
            points.push_back(LonLat(shape.segments[0][i].longitude, constraintedLatitude));
        }

        if (type == ProjectedFeatureType::Polygon &&
                (points.front().lon != points.back().lon || points.front().lat != points.back().lat)) {
            points.push_back(LonLat(points.front().lon, points.front().lat));
        }

        ProjectedGeometryContainer ring = Convert::project(points, tolerance);
        rings.members.push_back(ring);

        std::vector<ProjectedFeature> features;
        features.push_back(Convert::create(Tags(), type, rings));

        shapeTiler = std::make_unique<mapbox::util::geojsonvt::GeoJSONVT>(features, maxZoom, 4, 100, 10);
    }

    const auto& shapeTile = shapeTiler->getTile(tileID.z, tileID.x, tileID.y);
    if (!shapeTile)
        return;

    AnnotationTileLayer& layer = *tile.layers.emplace(layerID,
        std::make_unique<AnnotationTileLayer>()).first->second;

    for (auto& shapeFeature : shapeTile.features) {
        FeatureType featureType = FeatureType::Unknown;

        if (shapeFeature.type == TileFeatureType::LineString) {
            featureType = FeatureType::LineString;
        } else if (shapeFeature.type == TileFeatureType::Polygon) {
            featureType = FeatureType::Polygon;
        }

        assert(featureType != FeatureType::Unknown);

        GeometryCollection renderGeometry;
        for (auto& shapeGeometry : shapeFeature.tileGeometry) {
            std::vector<Coordinate> renderLine;
            auto& shapeRing = shapeGeometry.get<TileRing>();

            for (auto& shapePoint : shapeRing.points) {
                renderLine.emplace_back(shapePoint.x, shapePoint.y);
            }

            renderGeometry.push_back(renderLine);
        }

        layer.features.emplace_back(
            std::make_shared<AnnotationTileFeature>(featureType, renderGeometry));
    }
}
Esempio n. 29
0
void BoundaryVisitor::visit( const GeometryCollection& g )
{
    BOOST_THROW_EXCEPTION( Exception(
                               ( boost::format( "unsupported type %1% in boundary operation" ) % g.geometryType() ).str()
                           ) );
}
Esempio n. 30
0
 inline GeometryCollectionBaseType::const_iterator range_begin(const GeometryCollection& gc) {return gc.begin();}