EVOLUTION-MANAGER
Edit File: GeometryFactory.cpp
/********************************************************************** * * GEOS - Geometry Engine Open Source * http://geos.osgeo.org * * Copyright (C) 2011 Sandro Santilli <strk@kbt.io> * Copyright (C) 2001-2002 Vivid Solutions Inc. * Copyright (C) 2005 Refractions Research Inc. * * This is free software; you can redistribute and/or modify it under * the terms of the GNU Lesser General Public Licence as published * by the Free Software Foundation. * See the COPYING file for more information. * ********************************************************************** * * Last port: geom/GeometryFactory.java r320 (JTS-1.12) * **********************************************************************/ #include <geos/geom/Coordinate.h> #include <geos/geom/CoordinateSequence.h> #include <geos/geom/DefaultCoordinateSequenceFactory.h> #include <geos/geom/GeometryFactory.h> #include <geos/geom/Point.h> #include <geos/geom/LineString.h> #include <geos/geom/LinearRing.h> #include <geos/geom/Polygon.h> #include <geos/geom/MultiPoint.h> #include <geos/geom/MultiLineString.h> #include <geos/geom/MultiPolygon.h> #include <geos/geom/GeometryCollection.h> #include <geos/geom/PrecisionModel.h> #include <geos/geom/Envelope.h> #include <geos/geom/util/CoordinateOperation.h> #include <geos/geom/util/GeometryEditor.h> #include <geos/util.h> #include <cassert> #include <vector> #include <typeinfo> #include <cmath> #ifndef GEOS_DEBUG #define GEOS_DEBUG 0 #endif #ifdef GEOS_DEBUG #include <iostream> #endif #ifndef GEOS_INLINE # include <geos/geom/GeometryFactory.inl> #endif using namespace std; namespace geos { namespace geom { // geos::geom namespace { class gfCoordinateOperation: public util::CoordinateOperation { using CoordinateOperation::edit; const CoordinateSequenceFactory* _gsf; public: gfCoordinateOperation(const CoordinateSequenceFactory* gsf) : _gsf(gsf) {} std::unique_ptr<CoordinateSequence> edit(const CoordinateSequence* coordSeq, const Geometry*) override { return _gsf->create(*coordSeq); } }; } // anonymous namespace /*protected*/ GeometryFactory::GeometryFactory() : SRID(0), coordinateListFactory(DefaultCoordinateSequenceFactory::instance()) , _refCount(0), _autoDestroy(false) { #if GEOS_DEBUG std::cerr << "GEOS_DEBUG: GeometryFactory[" << this << "]::GeometryFactory()" << std::endl; std::cerr << "\tcreate PrecisionModel[" << precisionModel << "]" << std::endl; #endif } /*public static*/ GeometryFactory::Ptr GeometryFactory::create() { return GeometryFactory::Ptr(new GeometryFactory()); } /*protected*/ GeometryFactory::GeometryFactory(const PrecisionModel* pm, int newSRID, CoordinateSequenceFactory* nCoordinateSequenceFactory) : SRID(newSRID) , _refCount(0), _autoDestroy(false) { #if GEOS_DEBUG std::cerr << "GEOS_DEBUG: GeometryFactory[" << this << "]::GeometryFactory(PrecisionModel[" << pm << "], SRID)" << std::endl; #endif if(pm) { precisionModel = *pm; } if(! nCoordinateSequenceFactory) { coordinateListFactory = DefaultCoordinateSequenceFactory::instance(); } else { coordinateListFactory = nCoordinateSequenceFactory; } } /*public static*/ GeometryFactory::Ptr GeometryFactory::create(const PrecisionModel* pm, int newSRID, CoordinateSequenceFactory* nCoordinateSequenceFactory) { return GeometryFactory::Ptr( new GeometryFactory(pm, newSRID, nCoordinateSequenceFactory) ); } /*protected*/ GeometryFactory::GeometryFactory( CoordinateSequenceFactory* nCoordinateSequenceFactory) : SRID(0) , _refCount(0), _autoDestroy(false) { #if GEOS_DEBUG std::cerr << "GEOS_DEBUG: GeometryFactory[" << this << "]::GeometryFactory(CoordinateSequenceFactory[" << nCoordinateSequenceFactory << "])" << std::endl; #endif if(! nCoordinateSequenceFactory) { coordinateListFactory = DefaultCoordinateSequenceFactory::instance(); } else { coordinateListFactory = nCoordinateSequenceFactory; } } /*public static*/ GeometryFactory::Ptr GeometryFactory::create( CoordinateSequenceFactory* nCoordinateSequenceFactory) { return GeometryFactory::Ptr( new GeometryFactory(nCoordinateSequenceFactory) ); } /*protected*/ GeometryFactory::GeometryFactory(const PrecisionModel* pm) : SRID(0), coordinateListFactory(DefaultCoordinateSequenceFactory::instance()) , _refCount(0), _autoDestroy(false) { #if GEOS_DEBUG std::cerr << "GEOS_DEBUG: GeometryFactory[" << this << "]::GeometryFactory(PrecisionModel[" << pm << "])" << std::endl; #endif if(pm) { precisionModel = *pm; } } /*public static*/ GeometryFactory::Ptr GeometryFactory::create(const PrecisionModel* pm) { return GeometryFactory::Ptr( new GeometryFactory(pm) ); } /*protected*/ GeometryFactory::GeometryFactory(const PrecisionModel* pm, int newSRID) : SRID(newSRID), coordinateListFactory(DefaultCoordinateSequenceFactory::instance()) , _refCount(0), _autoDestroy(false) { #if GEOS_DEBUG std::cerr << "GEOS_DEBUG: GeometryFactory[" << this << "]::GeometryFactory(PrecisionModel[" << pm << "], SRID)" << std::endl; #endif if(pm) { precisionModel = *pm; } } /*public static*/ GeometryFactory::Ptr GeometryFactory::create(const PrecisionModel* pm, int newSRID) { return GeometryFactory::Ptr( new GeometryFactory(pm, newSRID) ); } /*protected*/ GeometryFactory::GeometryFactory(const GeometryFactory& gf) : precisionModel(gf.precisionModel), SRID(gf.SRID), coordinateListFactory(gf.coordinateListFactory), _refCount(0), _autoDestroy(false) {} /*public static*/ GeometryFactory::Ptr GeometryFactory::create(const GeometryFactory& gf) { return GeometryFactory::Ptr( new GeometryFactory(gf) ); } /*public virtual*/ GeometryFactory::~GeometryFactory() { #if GEOS_DEBUG std::cerr << "GEOS_DEBUG: GeometryFactory[" << this << "]::~GeometryFactory()" << std::endl; #endif } /*public*/ Point* GeometryFactory::createPointFromInternalCoord(const Coordinate* coord, const Geometry* exemplar) const { assert(coord); Coordinate newcoord = *coord; exemplar->getPrecisionModel()->makePrecise(&newcoord); return exemplar->getFactory()->createPoint(newcoord); } /*public*/ std::unique_ptr<Geometry> GeometryFactory::toGeometry(const Envelope* envelope) const { Coordinate coord; if(envelope->isNull()) { return std::unique_ptr<Geometry>(createPoint()); } if(envelope->getMinX() == envelope->getMaxX() && envelope->getMinY() == envelope->getMaxY()) { coord.x = envelope->getMinX(); coord.y = envelope->getMinY(); return std::unique_ptr<Geometry>(createPoint(coord)); } auto cl = coordinateListFactory->create(5, 2); coord.x = envelope->getMinX(); coord.y = envelope->getMinY(); cl->setAt(coord, 0); coord.x = envelope->getMaxX(); coord.y = envelope->getMinY(); cl->setAt(coord, 1); coord.x = envelope->getMaxX(); coord.y = envelope->getMaxY(); cl->setAt(coord, 2); coord.x = envelope->getMinX(); coord.y = envelope->getMaxY(); cl->setAt(coord, 3); coord.x = envelope->getMinX(); coord.y = envelope->getMinY(); cl->setAt(coord, 4); return createPolygon(createLinearRing(std::move(cl))); } /*public*/ const PrecisionModel* GeometryFactory::getPrecisionModel() const { return &precisionModel; } /*public*/ std::unique_ptr<Point> GeometryFactory::createPoint() const { return std::unique_ptr<Point>(new Point(nullptr, this)); } /*public*/ Point* GeometryFactory::createPoint(const Coordinate& coordinate) const { if(coordinate.isNull()) { return createPoint().release(); } else { return new Point(coordinate, this); } } /*public*/ Point* GeometryFactory::createPoint(CoordinateSequence* newCoords) const { return new Point(newCoords, this); } /*public*/ Point* GeometryFactory::createPoint(const CoordinateSequence& fromCoords) const { auto newCoords = fromCoords.clone(); return new Point(newCoords.release(), this); } /*public*/ std::unique_ptr<MultiLineString> GeometryFactory::createMultiLineString() const { return std::unique_ptr<MultiLineString>(new MultiLineString(nullptr, this)); } /*public*/ MultiLineString* GeometryFactory::createMultiLineString(vector<Geometry*>* newLines) const { return new MultiLineString(newLines, this); } /*public*/ MultiLineString* GeometryFactory::createMultiLineString(const std::vector<const Geometry*>& fromLines) const { std::vector<std::unique_ptr<Geometry>> newGeoms(fromLines.size()); for(size_t i = 0; i < fromLines.size(); i++) { auto line = dynamic_cast<const LineString*>(fromLines[i]); if(!line) { throw geos::util::IllegalArgumentException("createMultiLineString called with a vector containing non-LineStrings"); } newGeoms[i].reset(new LineString(*line)); } return new MultiLineString(std::move(newGeoms), *this); } std::unique_ptr<MultiLineString> GeometryFactory::createMultiLineString(std::vector<std::unique_ptr<LineString>> && fromLines) const { // Can't use make_unique because constructor is protected return std::unique_ptr<MultiLineString>(new MultiLineString(std::move(fromLines), *this)); } std::unique_ptr<MultiLineString> GeometryFactory::createMultiLineString(std::vector<std::unique_ptr<Geometry>> && fromLines) const { // Can't use make_unique because constructor is protected return std::unique_ptr<MultiLineString>(new MultiLineString(std::move(fromLines), *this)); } /*public*/ std::unique_ptr<GeometryCollection> GeometryFactory::createGeometryCollection() const { return std::unique_ptr<GeometryCollection>(new GeometryCollection(nullptr, this)); } /*public*/ std::unique_ptr<Geometry> GeometryFactory::createEmptyGeometry() const { return createGeometryCollection(); } /*public*/ GeometryCollection* GeometryFactory::createGeometryCollection(vector<Geometry*>* newGeoms) const { return new GeometryCollection(newGeoms, this); } std::unique_ptr<GeometryCollection> GeometryFactory::createGeometryCollection(std::vector<std::unique_ptr<geos::geom::Geometry>> && newGeoms) const { // Can't use make_unique because constructor is protected return std::unique_ptr<GeometryCollection>(new GeometryCollection(std::move(newGeoms), *this)); } /*public*/ GeometryCollection* GeometryFactory::createGeometryCollection(const std::vector<const Geometry*>& fromGeoms) const { std::vector<std::unique_ptr<Geometry>> newGeoms(fromGeoms.size()); for(size_t i = 0; i < fromGeoms.size(); i++) { newGeoms[i] = fromGeoms[i]->clone(); } return new GeometryCollection(std::move(newGeoms), *this); } /*public*/ std::unique_ptr<MultiPolygon> GeometryFactory::createMultiPolygon() const { return std::unique_ptr<MultiPolygon>(new MultiPolygon(nullptr, this)); } /*public*/ MultiPolygon* GeometryFactory::createMultiPolygon(vector<Geometry*>* newPolys) const { return new MultiPolygon(newPolys, this); } std::unique_ptr<MultiPolygon> GeometryFactory::createMultiPolygon(std::vector<std::unique_ptr<Polygon>> && newPolys) const { // Can't use make_unique because constructor is protected return std::unique_ptr<MultiPolygon>(new MultiPolygon(std::move(newPolys), *this)); } std::unique_ptr<MultiPolygon> GeometryFactory::createMultiPolygon(std::vector<std::unique_ptr<Geometry>> && newPolys) const { // Can't use make_unique because constructor is protected return std::unique_ptr<MultiPolygon>(new MultiPolygon(std::move(newPolys), *this)); } /*public*/ MultiPolygon* GeometryFactory::createMultiPolygon(const std::vector<const Geometry*>& fromPolys) const { std::vector<std::unique_ptr<Geometry>> newGeoms(fromPolys.size()); for(size_t i = 0; i < fromPolys.size(); i++) { newGeoms[i] = fromPolys[i]->clone(); } return new MultiPolygon(std::move(newGeoms), *this); } /*public*/ std::unique_ptr<LinearRing> GeometryFactory::createLinearRing() const { return std::unique_ptr<LinearRing>(new LinearRing(nullptr, this)); } /*public*/ LinearRing* GeometryFactory::createLinearRing(CoordinateSequence* newCoords) const { return new LinearRing(newCoords, this); } std::unique_ptr<LinearRing> GeometryFactory::createLinearRing(CoordinateSequence::Ptr && newCoords) const { // Can't use make_unique with protected constructor return std::unique_ptr<LinearRing>(new LinearRing(std::move(newCoords), *this)); } /*public*/ LinearRing* GeometryFactory::createLinearRing(const CoordinateSequence& fromCoords) const { auto newCoords = fromCoords.clone(); LinearRing* g = nullptr; // construction failure will delete newCoords g = new LinearRing(newCoords.release(), this); return g; } /*public*/ MultiPoint* GeometryFactory::createMultiPoint(vector<Geometry*>* newPoints) const { return new MultiPoint(newPoints, this); } std::unique_ptr<MultiPoint> GeometryFactory::createMultiPoint(std::vector<std::unique_ptr<Point>> && newPoints) const { return std::unique_ptr<MultiPoint>(new MultiPoint(std::move(newPoints), *this)); } std::unique_ptr<MultiPoint> GeometryFactory::createMultiPoint(std::vector<std::unique_ptr<Geometry>> && newPoints) const { return std::unique_ptr<MultiPoint>(new MultiPoint(std::move(newPoints), *this)); } /*public*/ MultiPoint* GeometryFactory::createMultiPoint(const vector<const Geometry*>& fromPoints) const { std::vector<std::unique_ptr<Geometry>> newGeoms(fromPoints.size()); for(size_t i = 0; i < fromPoints.size(); i++) { newGeoms[i] = fromPoints[i]->clone(); } return new MultiPoint(std::move(newGeoms), *this); } /*public*/ std::unique_ptr<MultiPoint> GeometryFactory::createMultiPoint() const { return std::unique_ptr<MultiPoint>(new MultiPoint(nullptr, this)); } /*public*/ MultiPoint* GeometryFactory::createMultiPoint(const CoordinateSequence& fromCoords) const { size_t npts = fromCoords.getSize(); vector<std::unique_ptr<Geometry>> pts(npts); for(size_t i = 0; i < npts; ++i) { pts[i].reset(createPoint(fromCoords.getAt(i))); } return new MultiPoint(std::move(pts), *this); } /*public*/ MultiPoint* GeometryFactory::createMultiPoint(const std::vector<Coordinate>& fromCoords) const { size_t npts = fromCoords.size(); std::vector<std::unique_ptr<Geometry>> pts(npts); for(size_t i = 0; i < npts; ++i) { pts[i].reset(createPoint(fromCoords[i])); } return new MultiPoint(std::move(pts), *this); } /*public*/ std::unique_ptr<Polygon> GeometryFactory::createPolygon() const { return std::unique_ptr<Polygon>(new Polygon(nullptr, nullptr, this)); } /*public*/ Polygon* GeometryFactory::createPolygon(LinearRing* shell, vector<LinearRing*>* holes) const { return new Polygon(shell, holes, this); } std::unique_ptr<Polygon> GeometryFactory::createPolygon(std::unique_ptr<LinearRing> && shell) const { // Can't use make_unique with protected constructor return std::unique_ptr<Polygon>(new Polygon(std::move(shell), *this)); } std::unique_ptr<Polygon> GeometryFactory::createPolygon(std::unique_ptr<LinearRing> && shell, std::vector<std::unique_ptr<LinearRing>> && holes) const { // Can't use make_unique with protected constructor return std::unique_ptr<Polygon>(new Polygon(std::move(shell), std::move(holes), *this)); } /*public*/ Polygon* GeometryFactory::createPolygon(const LinearRing& shell, const std::vector<LinearRing*>& holes) const { std::unique_ptr<LinearRing> newRing(new LinearRing(shell)); std::vector<std::unique_ptr<LinearRing>> newHoles(holes.size()); for(size_t i = 0; i < holes.size(); i++) { newHoles[i].reset(new LinearRing(*holes[i])); } return new Polygon(std::move(newRing), std::move(newHoles), *this); } /*public*/ std::unique_ptr<LineString> GeometryFactory::createLineString() const { return std::unique_ptr<LineString>(new LineString(nullptr, this)); } /*public*/ std::unique_ptr<LineString> GeometryFactory::createLineString(const LineString& ls) const { // Can't use make_unique with protected constructor return std::unique_ptr<LineString>(new LineString(ls)); } /*public*/ LineString* GeometryFactory::createLineString(CoordinateSequence* newCoords) const { return new LineString(newCoords, this); } /*public*/ std::unique_ptr<LineString> GeometryFactory::createLineString(CoordinateSequence::Ptr && newCoords) const { // Can't use make_unique with protected constructor return std::unique_ptr<LineString>(new LineString(std::move(newCoords), *this)); } /*public*/ LineString* GeometryFactory::createLineString(const CoordinateSequence& fromCoords) const { auto newCoords = fromCoords.clone(); LineString* g = nullptr; // construction failure will delete newCoords g = new LineString(newCoords.release(), this); return g; } template<typename T> GeometryTypeId commonType(const T& geoms) { if (geoms.empty()) { return GEOS_GEOMETRYCOLLECTION; } if (geoms.size() == 1) { return geoms[0]->getGeometryTypeId(); } GeometryTypeId type = geoms[0]->getGeometryTypeId(); for (size_t i = 1; i < geoms.size(); i++) { if (geoms[i]->getGeometryTypeId() != type) { return GEOS_GEOMETRYCOLLECTION; } } switch(geoms[0]->getGeometryTypeId()) { case GEOS_POINT: return GEOS_MULTIPOINT; case GEOS_LINEARRING: case GEOS_LINESTRING: return GEOS_MULTILINESTRING; case GEOS_POLYGON: return GEOS_MULTIPOLYGON; default: return GEOS_GEOMETRYCOLLECTION; } } /*public*/ Geometry* GeometryFactory::buildGeometry(vector<Geometry*>* newGeoms) const { if(newGeoms->empty()) { // we do not need the vector anymore delete newGeoms; return createGeometryCollection().release(); } if (newGeoms->size() == 1) { Geometry* ret = (*newGeoms)[0]; delete newGeoms; return ret; } auto resultType = commonType(*newGeoms); switch(resultType) { case GEOS_MULTIPOINT: return createMultiPoint(newGeoms); case GEOS_MULTILINESTRING: return createMultiLineString(newGeoms); case GEOS_MULTIPOLYGON: return createMultiPolygon(newGeoms); default: return createGeometryCollection(newGeoms); } } std::unique_ptr<Geometry> GeometryFactory::buildGeometry(std::vector<std::unique_ptr<Geometry>> && geoms) const { if (geoms.empty()) { return createGeometryCollection(); } if (geoms.size() == 1) { return std::move(geoms[0]); } auto resultType = commonType(geoms); switch(resultType) { case GEOS_MULTIPOINT: return createMultiPoint(std::move(geoms)); case GEOS_MULTILINESTRING: return createMultiLineString(std::move(geoms)); case GEOS_MULTIPOLYGON: return createMultiPolygon(std::move(geoms)); default: return createGeometryCollection(std::move(geoms)); } } /*public*/ Geometry* GeometryFactory::buildGeometry(const vector<const Geometry*>& fromGeoms) const { if(fromGeoms.empty()) { return createGeometryCollection().release(); } if(fromGeoms.size() == 1) { return fromGeoms[0]->clone().release(); } auto resultType = commonType(fromGeoms); switch(resultType) { case GEOS_MULTIPOINT: return createMultiPoint(fromGeoms); case GEOS_MULTILINESTRING: return createMultiLineString(fromGeoms); case GEOS_MULTIPOLYGON: return createMultiPolygon(fromGeoms); default: return createGeometryCollection(fromGeoms); } } /*public*/ Geometry* GeometryFactory::createGeometry(const Geometry* g) const { // could this be cached to make this more efficient? Or maybe it isn't enough overhead to bother //return g->clone(); util::GeometryEditor editor(this); gfCoordinateOperation coordOp(coordinateListFactory); return editor.edit(g, &coordOp).release(); } /*public*/ void GeometryFactory::destroyGeometry(Geometry* g) const { delete g; } /*public static*/ const GeometryFactory* GeometryFactory::getDefaultInstance() { static GeometryFactory defInstance; return &defInstance; } /*private*/ void GeometryFactory::addRef() const { ++_refCount; } /*private*/ void GeometryFactory::dropRef() const { if(! --_refCount) { if(_autoDestroy) { delete this; } } } void GeometryFactory::destroy() { assert(!_autoDestroy); // don't call me twice ! _autoDestroy = true; if(! _refCount) { delete this; } } } // namespace geos::geom } // namespace geos