1 /**********************************************************************
3 * GEOS - Geometry Engine Open Source
4 * http://geos.osgeo.org
6 * Copyright (C) 2011 Sandro Santilli <strk@keybit.net>
7 * Copyright (C) 2001-2002 Vivid Solutions Inc.
8 * Copyright (C) 2005 Refractions Research Inc.
10 * This is free software; you can redistribute and/or modify it under
11 * the terms of the GNU Lesser General Public Licence as published
12 * by the Free Software Foundation.
13 * See the COPYING file for more information.
15 **********************************************************************
17 * Last port: geom/GeometryFactory.java r320 (JTS-1.12)
19 **********************************************************************/
21 #include <geos/geom/Coordinate.h>
22 #include <geos/geom/CoordinateArraySequenceFactory.h>
23 #include <geos/geom/CoordinateSequence.h>
24 #include <geos/geom/GeometryFactory.h>
25 #include <geos/geom/Point.h>
26 #include <geos/geom/LineString.h>
27 #include <geos/geom/LinearRing.h>
28 #include <geos/geom/Polygon.h>
29 #include <geos/geom/MultiPoint.h>
30 #include <geos/geom/MultiLineString.h>
31 #include <geos/geom/MultiPolygon.h>
32 #include <geos/geom/GeometryCollection.h>
33 #include <geos/geom/PrecisionModel.h>
34 #include <geos/geom/Envelope.h>
35 #include <geos/util/IllegalArgumentException.h>
51 # include <geos/geom/GeometryFactory.inl>
57 namespace geom
{ // geos::geom
60 // class gfCoordinateOperation: public CoordinateOperation {
61 // using CoordinateOperation::edit;
63 // virtual CoordinateSequence* edit(const CoordinateSequence *coordinates,
64 // const Geometry *geometry);
71 GeometryFactory::GeometryFactory()
73 precisionModel(new PrecisionModel()),
75 coordinateListFactory(CoordinateArraySequenceFactory::instance())
78 std::cerr
<< "GEOS_DEBUG: GeometryFactory["<<this<<"]::GeometryFactory()" << std::endl
;
79 std::cerr
<< "\tcreate PrecisionModel["<<precisionModel
<<"]" << std::endl
;
84 GeometryFactory::GeometryFactory(const PrecisionModel
* pm
, int newSRID
,
85 CoordinateSequenceFactory
* nCoordinateSequenceFactory
)
90 std::cerr
<< "GEOS_DEBUG: GeometryFactory["<<this<<"]::GeometryFactory(PrecisionModel["<<pm
<<"], SRID)" << std::endl
;
93 precisionModel
=new PrecisionModel();
95 precisionModel
=new PrecisionModel(*pm
);
98 if ( ! nCoordinateSequenceFactory
) {
99 coordinateListFactory
=CoordinateArraySequenceFactory::instance();
101 coordinateListFactory
=nCoordinateSequenceFactory
;
106 GeometryFactory::GeometryFactory(
107 CoordinateSequenceFactory
* nCoordinateSequenceFactory
)
109 precisionModel(new PrecisionModel()),
113 std::cerr
<< "GEOS_DEBUG: GeometryFactory["<<this<<"]::GeometryFactory(CoordinateSequenceFactory["<<nCoordinateSequenceFactory
<<"])" << std::endl
;
115 if ( ! nCoordinateSequenceFactory
) {
116 coordinateListFactory
=CoordinateArraySequenceFactory::instance();
118 coordinateListFactory
=nCoordinateSequenceFactory
;
123 GeometryFactory::GeometryFactory(const PrecisionModel
*pm
)
126 coordinateListFactory(CoordinateArraySequenceFactory::instance())
129 std::cerr
<< "GEOS_DEBUG: GeometryFactory["<<this<<"]::GeometryFactory(PrecisionModel["<<pm
<<"])" << std::endl
;
132 precisionModel
=new PrecisionModel();
134 precisionModel
=new PrecisionModel(*pm
);
139 GeometryFactory::GeometryFactory(const PrecisionModel
* pm
, int newSRID
)
142 coordinateListFactory(CoordinateArraySequenceFactory::instance())
145 std::cerr
<< "GEOS_DEBUG: GeometryFactory["<<this<<"]::GeometryFactory(PrecisionModel["<<pm
<<"], SRID)" << std::endl
;
148 precisionModel
=new PrecisionModel();
150 precisionModel
=new PrecisionModel(*pm
);
155 GeometryFactory::GeometryFactory(const GeometryFactory
&gf
)
157 assert(gf
.precisionModel
);
158 precisionModel
=new PrecisionModel(*(gf
.precisionModel
));
160 coordinateListFactory
=gf
.coordinateListFactory
;
164 GeometryFactory::~GeometryFactory(){
166 std::cerr
<< "GEOS_DEBUG: GeometryFactory["<<this<<"]::~GeometryFactory()" << std::endl
;
168 delete precisionModel
;
173 GeometryFactory::createPointFromInternalCoord(const Coordinate
* coord
,
174 const Geometry
*exemplar
) const
177 Coordinate newcoord
= *coord
;
178 exemplar
->getPrecisionModel()->makePrecise(&newcoord
);
179 return exemplar
->getFactory()->createPoint(newcoord
);
185 GeometryFactory::toGeometry(const Envelope
* envelope
) const
189 if (envelope
->isNull()) {
190 return createPoint();
192 if (envelope
->getMinX()==envelope
->getMaxX() && envelope
->getMinY()==envelope
->getMaxY()) {
193 coord
.x
= envelope
->getMinX();
194 coord
.y
= envelope
->getMinY();
195 return createPoint(coord
);
197 CoordinateSequence
*cl
=CoordinateArraySequenceFactory::instance()->
198 create((size_t) 0, 2);
199 coord
.x
= envelope
->getMinX();
200 coord
.y
= envelope
->getMinY();
202 coord
.x
= envelope
->getMaxX();
203 coord
.y
= envelope
->getMinY();
205 coord
.x
= envelope
->getMaxX();
206 coord
.y
= envelope
->getMaxY();
208 coord
.x
= envelope
->getMinX();
209 coord
.y
= envelope
->getMaxY();
211 coord
.x
= envelope
->getMinX();
212 coord
.y
= envelope
->getMinY();
215 Polygon
*p
= createPolygon(createLinearRing(cl
), NULL
);
220 const PrecisionModel
*
221 GeometryFactory::getPrecisionModel() const
223 return precisionModel
;
228 GeometryFactory::createPoint() const
230 return new Point(NULL
, this);
235 GeometryFactory::createPoint(const Coordinate
& coordinate
) const
237 if (coordinate
.isNull()) {
238 return createPoint();
240 std::size_t dim
= ISNAN(coordinate
.z
) ? 2 : 3;
241 CoordinateSequence
*cl
= coordinateListFactory
->create(new vector
<Coordinate
>(1, coordinate
), dim
);
242 //cl->setAt(coordinate, 0);
243 Point
*ret
= createPoint(cl
);
250 GeometryFactory::createPoint(CoordinateSequence
*newCoords
) const
252 return new Point(newCoords
,this);
257 GeometryFactory::createPoint(const CoordinateSequence
&fromCoords
) const
259 CoordinateSequence
*newCoords
= fromCoords
.clone();
262 g
= new Point(newCoords
,this);
273 GeometryFactory::createMultiLineString() const
275 return new MultiLineString(NULL
,this);
280 GeometryFactory::createMultiLineString(vector
<Geometry
*> *newLines
)
283 return new MultiLineString(newLines
,this);
288 GeometryFactory::createMultiLineString(const vector
<Geometry
*> &fromLines
)
291 vector
<Geometry
*>*newGeoms
= new vector
<Geometry
*>(fromLines
.size());
292 for (size_t i
=0; i
<fromLines
.size(); i
++)
294 const LineString
*line
= dynamic_cast<const LineString
*>(fromLines
[i
]);
295 if ( ! line
) throw geos::util::IllegalArgumentException("createMultiLineString called with a vector containing non-LineStrings");
296 (*newGeoms
)[i
] = new LineString(*line
);
298 MultiLineString
*g
= NULL
;
300 g
= new MultiLineString(newGeoms
,this);
302 for (size_t i
=0; i
<newGeoms
->size(); i
++) {
303 delete (*newGeoms
)[i
];
313 GeometryFactory::createGeometryCollection() const
315 return new GeometryCollection(NULL
,this);
320 GeometryFactory::createEmptyGeometry() const
322 return new GeometryCollection(NULL
,this);
327 GeometryFactory::createGeometryCollection(vector
<Geometry
*> *newGeoms
) const
329 return new GeometryCollection(newGeoms
,this);
334 GeometryFactory::createGeometryCollection(const vector
<Geometry
*> &fromGeoms
) const
336 vector
<Geometry
*> *newGeoms
= new vector
<Geometry
*>(fromGeoms
.size());
337 for (size_t i
=0; i
<fromGeoms
.size(); i
++) {
338 (*newGeoms
)[i
] = fromGeoms
[i
]->clone();
340 GeometryCollection
*g
= NULL
;
342 g
= new GeometryCollection(newGeoms
,this);
344 for (size_t i
=0; i
<newGeoms
->size(); i
++) {
345 delete (*newGeoms
)[i
];
355 GeometryFactory::createMultiPolygon() const
357 return new MultiPolygon(NULL
,this);
362 GeometryFactory::createMultiPolygon(vector
<Geometry
*> *newPolys
) const
364 return new MultiPolygon(newPolys
,this);
369 GeometryFactory::createMultiPolygon(const vector
<Geometry
*> &fromPolys
) const
371 vector
<Geometry
*>*newGeoms
= new vector
<Geometry
*>(fromPolys
.size());
372 for (size_t i
=0; i
<fromPolys
.size(); i
++)
374 (*newGeoms
)[i
] = fromPolys
[i
]->clone();
376 MultiPolygon
*g
= NULL
;
378 g
= new MultiPolygon(newGeoms
,this);
380 for (size_t i
=0; i
<newGeoms
->size(); i
++) {
381 delete (*newGeoms
)[i
];
391 GeometryFactory::createLinearRing() const
393 return new LinearRing(NULL
,this);
398 GeometryFactory::createLinearRing(CoordinateSequence
* newCoords
) const
400 return new LinearRing(newCoords
,this);
405 GeometryFactory::createLinearRing(CoordinateSequence::AutoPtr newCoords
) const
407 return Geometry::AutoPtr(new LinearRing(newCoords
, this));
412 GeometryFactory::createLinearRing(const CoordinateSequence
& fromCoords
) const
414 CoordinateSequence
*newCoords
= fromCoords
.clone();
415 LinearRing
*g
= NULL
;
416 // construction failure will delete newCoords
417 g
= new LinearRing(newCoords
, this);
423 GeometryFactory::createMultiPoint(vector
<Geometry
*> *newPoints
) const
425 return new MultiPoint(newPoints
,this);
430 GeometryFactory::createMultiPoint(const vector
<Geometry
*> &fromPoints
) const
432 vector
<Geometry
*>*newGeoms
= new vector
<Geometry
*>(fromPoints
.size());
433 for (size_t i
=0; i
<fromPoints
.size(); i
++)
435 (*newGeoms
)[i
] = fromPoints
[i
]->clone();
438 MultiPoint
*g
= NULL
;
440 g
= new MultiPoint(newGeoms
,this);
442 for (size_t i
=0; i
<newGeoms
->size(); i
++) {
443 delete (*newGeoms
)[i
];
453 GeometryFactory::createMultiPoint() const
455 return new MultiPoint(NULL
, this);
460 GeometryFactory::createMultiPoint(const CoordinateSequence
&fromCoords
) const
462 size_t npts
=fromCoords
.getSize();
463 vector
<Geometry
*> *pts
=new vector
<Geometry
*>;
465 for (size_t i
=0; i
<npts
; ++i
) {
466 Point
*pt
=createPoint(fromCoords
.getAt(i
));
469 MultiPoint
*mp
= NULL
;
471 mp
= createMultiPoint(pts
);
473 for (size_t i
=0; i
<npts
; ++i
) delete (*pts
)[i
];
482 GeometryFactory::createMultiPoint(const std::vector
<Coordinate
> &fromCoords
) const
484 size_t npts
=fromCoords
.size();
485 vector
<Geometry
*> *pts
=new vector
<Geometry
*>;
487 for (size_t i
=0; i
<npts
; ++i
) {
488 Point
*pt
=createPoint(fromCoords
[i
]);
491 MultiPoint
*mp
= NULL
;
493 mp
= createMultiPoint(pts
);
495 for (size_t i
=0; i
<npts
; ++i
) delete (*pts
)[i
];
504 GeometryFactory::createPolygon() const
506 return new Polygon(NULL
, NULL
, this);
511 GeometryFactory::createPolygon(LinearRing
*shell
, vector
<Geometry
*> *holes
)
514 return new Polygon(shell
, holes
, this);
519 GeometryFactory::createPolygon(const LinearRing
&shell
, const vector
<Geometry
*> &holes
)
522 LinearRing
*newRing
= dynamic_cast<LinearRing
*>(shell
.clone());
523 vector
<Geometry
*>*newHoles
= new vector
<Geometry
*>(holes
.size());
524 for (size_t i
=0; i
<holes
.size(); i
++)
526 (*newHoles
)[i
] = holes
[i
]->clone();
530 g
= new Polygon(newRing
, newHoles
, this);
533 for (size_t i
=0; i
<holes
.size(); i
++)
534 delete (*newHoles
)[i
];
543 GeometryFactory::createLineString() const
545 return new LineString(NULL
, this);
549 std::auto_ptr
<LineString
>
550 GeometryFactory::createLineString(const LineString
& ls
) const
552 return std::auto_ptr
<LineString
>(new LineString(ls
));
557 GeometryFactory::createLineString(CoordinateSequence
*newCoords
)
560 return new LineString(newCoords
, this);
565 GeometryFactory::createLineString(CoordinateSequence::AutoPtr newCoords
)
568 return Geometry::AutoPtr(new LineString(newCoords
, this));
573 GeometryFactory::createLineString(const CoordinateSequence
&fromCoords
)
576 CoordinateSequence
*newCoords
= fromCoords
.clone();
577 LineString
*g
= NULL
;
578 // construction failure will delete newCoords
579 g
= new LineString(newCoords
, this);
585 GeometryFactory::buildGeometry(vector
<Geometry
*> *newGeoms
) const
587 string
geomClass("NULL");
588 bool isHeterogeneous
=false;
589 bool hasGeometryCollection
=false;
591 for (size_t i
=0, n
=newGeoms
->size(); i
<n
; ++i
)
593 Geometry
* geom
= (*newGeoms
)[i
];
594 string
partClass(typeid(*geom
).name());
595 if (geomClass
=="NULL")
599 else if (geomClass
!=partClass
)
601 isHeterogeneous
= true;
603 if ( dynamic_cast<GeometryCollection
*>(geom
) )
605 hasGeometryCollection
=true;
609 // for the empty geometry, return an empty GeometryCollection
610 if (geomClass
=="NULL")
612 // we do not need the vector anymore
614 return createGeometryCollection();
616 if (isHeterogeneous
|| hasGeometryCollection
)
618 return createGeometryCollection(newGeoms
);
621 // At this point we know the collection is not hetereogenous.
622 // Determine the type of the result from the first Geometry in the
623 // list. This should always return a geometry, since otherwise
624 // an empty collection would have already been returned
625 Geometry
*geom0
=(*newGeoms
)[0];
626 bool isCollection
=newGeoms
->size()>1;
629 if (typeid(*geom0
)==typeid(Polygon
)) {
630 return createMultiPolygon(newGeoms
);
631 } else if (typeid(*geom0
)==typeid(LineString
)) {
632 return createMultiLineString(newGeoms
);
633 } else if (typeid(*geom0
)==typeid(LinearRing
)) {
634 return createMultiLineString(newGeoms
);
635 } else if (typeid(*geom0
)==typeid(Point
)) {
636 return createMultiPoint(newGeoms
);
638 return createGeometryCollection(newGeoms
);
642 // since this is not a collection we can delete vector
649 GeometryFactory::buildGeometry(const vector
<Geometry
*> &fromGeoms
) const
651 string
geomClass("NULL");
652 bool isHeterogeneous
=false;
653 bool isCollection
=fromGeoms
.size()>1;
656 for (i
=0; i
<fromGeoms
.size(); i
++) {
657 string
partClass(typeid(*fromGeoms
[i
]).name());
658 if (geomClass
=="NULL") {
660 } else if (geomClass
!=partClass
) {
661 isHeterogeneous
= true;
665 // for the empty geometry, return an empty GeometryCollection
666 if (geomClass
=="NULL") {
667 return createGeometryCollection();
669 if (isHeterogeneous
) {
670 return createGeometryCollection(fromGeoms
);
673 // At this point we know the collection is not hetereogenous.
674 // Determine the type of the result from the first Geometry in the
675 // list. This should always return a geometry, since otherwise
676 // an empty collection would have already been returned
677 Geometry
*geom0
=fromGeoms
[0];
679 if (typeid(*geom0
)==typeid(Polygon
)) {
680 return createMultiPolygon(fromGeoms
);
681 } else if (typeid(*geom0
)==typeid(LineString
)) {
682 return createMultiLineString(fromGeoms
);
683 } else if (typeid(*geom0
)==typeid(LinearRing
)) {
684 return createMultiLineString(fromGeoms
);
685 } else if (typeid(*geom0
)==typeid(Point
)) {
686 return createMultiPoint(fromGeoms
);
688 assert(0); // buildGeomtry encountered an unkwnon geometry type
691 return geom0
->clone();
696 GeometryFactory::createGeometry(const Geometry
*g
) const
698 // could this be cached to make this more efficient? Or maybe it isn't enough overhead to bother
700 //GeometryEditor *editor=new GeometryEditor(this);
701 //gfCoordinateOperation *coordOp = new gfCoordinateOperation();
702 //Geometry *ret=editor->edit(g, coordOp);
710 GeometryFactory::destroyGeometry(Geometry
*g
) const
716 const GeometryFactory
*
717 GeometryFactory::getDefaultInstance()
719 static GeometryFactory defInstance
;
723 } // namespace geos::geom
726 /**********************************************************************
728 * Revision 1.71 2006/07/08 00:33:54 strk
729 * * configure.in: incremented CAPI minor version, to avoid falling behind any future version from the 2.2. branch.
730 * * source/geom/Geometry.cpp, source/geom/GeometryFactory.cpp,
731 * source/geomgraph/EdgeRing.cpp,
732 * source/headers/geos/geom/Geometry.h,
733 * source/headers/geos/geom/GeometryFactory.h,
734 * source/headers/geos/geom/GeometryFactory.inl,
735 * source/headers/geos/geomgraph/EdgeRing.h:
736 * updated doxygen comments (sync with JTS head).
737 * * source/headers/geos/platform.h.in: include <inttypes.h>
738 * rather then <stdint.h>
740 * Revision 1.70 2006/06/19 21:17:23 strk
741 * port info and doxygen dox.
743 * Revision 1.69 2006/06/12 10:10:39 strk
744 * Fixed getGeometryN() to take size_t rather then int, changed unsigned int parameters to size_t.
746 * Revision 1.68 2006/04/28 11:56:52 strk
747 * * source/geom/GeometryFactory.cpp, source/headers/geos/geom/GeometryFactory.h: added LineString copy constructor.
748 * * source/geom/Polygon.cpp: fixed getBoundary method to always return a geometry composed by LineStrings (not LinearRings)
750 * Revision 1.67 2006/04/11 11:16:25 strk
751 * Added LineString and LinearRing constructors by auto_ptr
753 * Revision 1.66 2006/04/10 13:09:47 strk
754 * Added GeometryFactory::defaultInstance()
755 * Made Geometry::INTERNAL_GEOMETRY_FACTORY an alias for it
756 * removed last deletion from Unload::Release class
758 * Revision 1.65 2006/04/06 12:33:04 strk
759 * More debugging lines
761 * Revision 1.64 2006/03/31 17:51:24 strk
762 * A few assertion checking, comments cleanup, use of initialization lists
763 * in constructors, handled NULL parameters.
765 * Revision 1.63 2006/03/24 09:52:41 strk
766 * USE_INLINE => GEOS_INLINE
768 * Revision 1.62 2006/03/20 10:11:50 strk
769 * Bug #67 - Debugging helpers in GeometryFactory class
771 * Revision 1.61 2006/03/09 16:46:47 strk
772 * geos::geom namespace definition, first pass at headers split
774 * Revision 1.60 2006/03/06 19:40:46 strk
775 * geos::util namespace. New GeometryCollection::iterator interface, many cleanups.
777 * Revision 1.59 2006/03/03 10:46:21 strk
778 * Removed 'using namespace' from headers, added missing headers in .cpp files, removed useless includes in headers (bug#46)
780 * Revision 1.58 2006/03/01 18:37:08 strk
781 * Geometry::createPointFromInternalCoord dropped (it's a duplication of GeometryFactory::createPointFromInternalCoord).
782 * Fixed bugs in InteriorPoint* and getCentroid() inserted by previous commits.
784 * Revision 1.57 2006/02/23 23:17:52 strk
785 * - Coordinate::nullCoordinate made private
786 * - Simplified Coordinate inline definitions
787 * - LMGeometryComponentFilter definition moved to LineMerger.cpp file
790 * Revision 1.56 2006/02/09 15:52:47 strk
791 * GEOSException derived from std::exception; always thrown and cought by const ref.
793 **********************************************************************/