Fix documentation typos.
[geos.git] / src / geom / GeometryFactory.cpp
blob0c8abfc74df58a6ba99e70067458746f32dfb841
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/geom/util/CoordinateOperation.h>
36 #include <geos/geom/util/GeometryEditor.h>
37 #include <geos/util/IllegalArgumentException.h>
39 #include <cassert>
40 #include <vector>
41 #include <typeinfo>
42 #include <cmath>
44 #ifndef GEOS_DEBUG
45 #define GEOS_DEBUG 0
46 #endif
48 #ifdef GEOS_DEBUG
49 #include <iostream>
50 #endif
52 #ifndef GEOS_INLINE
53 # include <geos/geom/GeometryFactory.inl>
54 #endif
56 using namespace std;
58 namespace geos {
59 namespace geom { // geos::geom
61 namespace {
63 class gfCoordinateOperation: public util::CoordinateOperation {
64 using CoordinateOperation::edit;
65 const CoordinateSequenceFactory* _gsf;
66 public:
67 gfCoordinateOperation(const CoordinateSequenceFactory* gsf)
68 : _gsf(gsf)
70 CoordinateSequence* edit( const CoordinateSequence *coordSeq,
71 const Geometry * )
73 return _gsf->create(*coordSeq);
77 } // anonymous namespace
81 /*protected*/
82 GeometryFactory::GeometryFactory()
84 precisionModel(new PrecisionModel()),
85 SRID(0),
86 coordinateListFactory(CoordinateArraySequenceFactory::instance())
87 ,_refCount(0),_autoDestroy(false)
89 #if GEOS_DEBUG
90 std::cerr << "GEOS_DEBUG: GeometryFactory["<<this<<"]::GeometryFactory()" << std::endl;
91 std::cerr << "\tcreate PrecisionModel["<<precisionModel<<"]" << std::endl;
92 #endif
95 /*public static*/
96 GeometryFactory::unique_ptr
97 GeometryFactory::create() { return GeometryFactory::unique_ptr(new GeometryFactory()); }
99 /*protected*/
100 GeometryFactory::GeometryFactory(const PrecisionModel* pm, int newSRID,
101 CoordinateSequenceFactory* nCoordinateSequenceFactory)
103 SRID(newSRID)
104 ,_refCount(0),_autoDestroy(false)
106 #if GEOS_DEBUG
107 std::cerr << "GEOS_DEBUG: GeometryFactory["<<this<<"]::GeometryFactory(PrecisionModel["<<pm<<"], SRID)" << std::endl;
108 #endif
109 if ( ! pm ) {
110 precisionModel=new PrecisionModel();
111 } else {
112 precisionModel=new PrecisionModel(*pm);
115 if ( ! nCoordinateSequenceFactory ) {
116 coordinateListFactory=CoordinateArraySequenceFactory::instance();
117 } else {
118 coordinateListFactory=nCoordinateSequenceFactory;
122 /*public static*/
123 GeometryFactory::unique_ptr
124 GeometryFactory::create(const PrecisionModel* pm, int newSRID,
125 CoordinateSequenceFactory* nCoordinateSequenceFactory)
127 return GeometryFactory::unique_ptr(
128 new GeometryFactory(pm, newSRID, nCoordinateSequenceFactory)
132 /*protected*/
133 GeometryFactory::GeometryFactory(
134 CoordinateSequenceFactory* nCoordinateSequenceFactory)
136 precisionModel(new PrecisionModel()),
137 SRID(0)
138 ,_refCount(0),_autoDestroy(false)
140 #if GEOS_DEBUG
141 std::cerr << "GEOS_DEBUG: GeometryFactory["<<this<<"]::GeometryFactory(CoordinateSequenceFactory["<<nCoordinateSequenceFactory<<"])" << std::endl;
142 #endif
143 if ( ! nCoordinateSequenceFactory ) {
144 coordinateListFactory=CoordinateArraySequenceFactory::instance();
145 } else {
146 coordinateListFactory=nCoordinateSequenceFactory;
150 /*public static*/
151 GeometryFactory::unique_ptr
152 GeometryFactory::create(
153 CoordinateSequenceFactory* nCoordinateSequenceFactory)
155 return GeometryFactory::unique_ptr(
156 new GeometryFactory(nCoordinateSequenceFactory)
160 /*protected*/
161 GeometryFactory::GeometryFactory(const PrecisionModel *pm)
163 SRID(0),
164 coordinateListFactory(CoordinateArraySequenceFactory::instance())
165 ,_refCount(0),_autoDestroy(false)
167 #if GEOS_DEBUG
168 std::cerr << "GEOS_DEBUG: GeometryFactory["<<this<<"]::GeometryFactory(PrecisionModel["<<pm<<"])" << std::endl;
169 #endif
170 if ( ! pm ) {
171 precisionModel=new PrecisionModel();
172 } else {
173 precisionModel=new PrecisionModel(*pm);
177 /*public static*/
178 GeometryFactory::unique_ptr
179 GeometryFactory::create(const PrecisionModel *pm)
181 return GeometryFactory::unique_ptr(
182 new GeometryFactory(pm)
186 /*protected*/
187 GeometryFactory::GeometryFactory(const PrecisionModel* pm, int newSRID)
189 SRID(newSRID),
190 coordinateListFactory(CoordinateArraySequenceFactory::instance())
191 ,_refCount(0),_autoDestroy(false)
193 #if GEOS_DEBUG
194 std::cerr << "GEOS_DEBUG: GeometryFactory["<<this<<"]::GeometryFactory(PrecisionModel["<<pm<<"], SRID)" << std::endl;
195 #endif
196 if ( ! pm ) {
197 precisionModel=new PrecisionModel();
198 } else {
199 precisionModel=new PrecisionModel(*pm);
203 /*public static*/
204 GeometryFactory::unique_ptr
205 GeometryFactory::create(const PrecisionModel* pm, int newSRID)
207 return GeometryFactory::unique_ptr(
208 new GeometryFactory(pm, newSRID)
212 /*protected*/
213 GeometryFactory::GeometryFactory(const GeometryFactory &gf)
215 assert(gf.precisionModel);
216 precisionModel=new PrecisionModel(*(gf.precisionModel));
217 SRID=gf.SRID;
218 coordinateListFactory=gf.coordinateListFactory;
219 _autoDestroy=false;
220 _refCount=0;
223 /*public static*/
224 GeometryFactory::unique_ptr
225 GeometryFactory::create(const GeometryFactory &gf)
227 return GeometryFactory::unique_ptr(
228 new GeometryFactory(gf)
232 /*public virtual*/
233 GeometryFactory::~GeometryFactory(){
234 #if GEOS_DEBUG
235 std::cerr << "GEOS_DEBUG: GeometryFactory["<<this<<"]::~GeometryFactory()" << std::endl;
236 #endif
237 delete precisionModel;
240 /*public*/
241 Point*
242 GeometryFactory::createPointFromInternalCoord(const Coordinate* coord,
243 const Geometry *exemplar) const
245 assert(coord);
246 Coordinate newcoord = *coord;
247 exemplar->getPrecisionModel()->makePrecise(&newcoord);
248 return exemplar->getFactory()->createPoint(newcoord);
252 /*public*/
253 Geometry*
254 GeometryFactory::toGeometry(const Envelope* envelope) const
256 Coordinate coord;
258 if (envelope->isNull()) {
259 return createPoint();
261 if (envelope->getMinX()==envelope->getMaxX() && envelope->getMinY()==envelope->getMaxY()) {
262 coord.x = envelope->getMinX();
263 coord.y = envelope->getMinY();
264 return createPoint(coord);
266 CoordinateSequence *cl=CoordinateArraySequenceFactory::instance()->
267 create((size_t) 0, 2);
268 coord.x = envelope->getMinX();
269 coord.y = envelope->getMinY();
270 cl->add(coord);
271 coord.x = envelope->getMaxX();
272 coord.y = envelope->getMinY();
273 cl->add(coord);
274 coord.x = envelope->getMaxX();
275 coord.y = envelope->getMaxY();
276 cl->add(coord);
277 coord.x = envelope->getMinX();
278 coord.y = envelope->getMaxY();
279 cl->add(coord);
280 coord.x = envelope->getMinX();
281 coord.y = envelope->getMinY();
282 cl->add(coord);
284 Polygon *p = createPolygon(createLinearRing(cl), NULL);
285 return p;
288 /*public*/
289 const PrecisionModel*
290 GeometryFactory::getPrecisionModel() const
292 return precisionModel;
295 /*public*/
296 Point*
297 GeometryFactory::createPoint() const
299 return new Point(NULL, this);
302 /*public*/
303 Point*
304 GeometryFactory::createPoint(const Coordinate& coordinate) const
306 if (coordinate.isNull()) {
307 return createPoint();
308 } else {
309 std::size_t dim = ISNAN(coordinate.z) ? 2 : 3;
310 CoordinateSequence *cl = coordinateListFactory->create(new vector<Coordinate>(1, coordinate), dim);
311 //cl->setAt(coordinate, 0);
312 Point *ret = createPoint(cl);
313 return ret;
317 /*public*/
318 Point*
319 GeometryFactory::createPoint(CoordinateSequence *newCoords) const
321 return new Point(newCoords,this);
324 /*public*/
325 Point*
326 GeometryFactory::createPoint(const CoordinateSequence &fromCoords) const
328 CoordinateSequence *newCoords = fromCoords.clone();
329 Point *g = NULL;
330 try {
331 g = new Point(newCoords,this);
332 } catch (...) {
333 delete newCoords;
334 throw;
336 return g;
340 /*public*/
341 MultiLineString*
342 GeometryFactory::createMultiLineString() const
344 return new MultiLineString(NULL,this);
347 /*public*/
348 MultiLineString*
349 GeometryFactory::createMultiLineString(vector<Geometry *> *newLines)
350 const
352 return new MultiLineString(newLines,this);
355 /*public*/
356 MultiLineString*
357 GeometryFactory::createMultiLineString(const vector<Geometry *> &fromLines)
358 const
360 vector<Geometry *>*newGeoms = new vector<Geometry *>(fromLines.size());
361 for (size_t i=0; i<fromLines.size(); i++)
363 const LineString *line = dynamic_cast<const LineString *>(fromLines[i]);
364 if ( ! line ) throw geos::util::IllegalArgumentException("createMultiLineString called with a vector containing non-LineStrings");
365 (*newGeoms)[i] = new LineString(*line);
367 MultiLineString *g = NULL;
368 try {
369 g = new MultiLineString(newGeoms,this);
370 } catch (...) {
371 for (size_t i=0; i<newGeoms->size(); i++) {
372 delete (*newGeoms)[i];
374 delete newGeoms;
375 throw;
377 return g;
380 /*public*/
381 GeometryCollection*
382 GeometryFactory::createGeometryCollection() const
384 return new GeometryCollection(NULL,this);
387 /*public*/
388 Geometry*
389 GeometryFactory::createEmptyGeometry() const
391 return new GeometryCollection(NULL,this);
394 /*public*/
395 GeometryCollection*
396 GeometryFactory::createGeometryCollection(vector<Geometry *> *newGeoms) const
398 return new GeometryCollection(newGeoms,this);
401 /*public*/
402 GeometryCollection*
403 GeometryFactory::createGeometryCollection(const vector<Geometry *> &fromGeoms) const
405 vector<Geometry *> *newGeoms = new vector<Geometry *>(fromGeoms.size());
406 for (size_t i=0; i<fromGeoms.size(); i++) {
407 (*newGeoms)[i] = fromGeoms[i]->clone();
409 GeometryCollection *g = NULL;
410 try {
411 g = new GeometryCollection(newGeoms,this);
412 } catch (...) {
413 for (size_t i=0; i<newGeoms->size(); i++) {
414 delete (*newGeoms)[i];
416 delete newGeoms;
417 throw;
419 return g;
422 /*public*/
423 MultiPolygon*
424 GeometryFactory::createMultiPolygon() const
426 return new MultiPolygon(NULL,this);
429 /*public*/
430 MultiPolygon*
431 GeometryFactory::createMultiPolygon(vector<Geometry *> *newPolys) const
433 return new MultiPolygon(newPolys,this);
436 /*public*/
437 MultiPolygon*
438 GeometryFactory::createMultiPolygon(const vector<Geometry *> &fromPolys) const
440 vector<Geometry *>*newGeoms = new vector<Geometry *>(fromPolys.size());
441 for (size_t i=0; i<fromPolys.size(); i++)
443 (*newGeoms)[i] = fromPolys[i]->clone();
445 MultiPolygon *g = NULL;
446 try {
447 g = new MultiPolygon(newGeoms,this);
448 } catch (...) {
449 for (size_t i=0; i<newGeoms->size(); i++) {
450 delete (*newGeoms)[i];
452 delete newGeoms;
453 throw;
455 return g;
458 /*public*/
459 LinearRing*
460 GeometryFactory::createLinearRing() const
462 return new LinearRing(NULL,this);
465 /*public*/
466 LinearRing*
467 GeometryFactory::createLinearRing(CoordinateSequence* newCoords) const
469 return new LinearRing(newCoords,this);
472 /*public*/
473 Geometry::AutoPtr
474 GeometryFactory::createLinearRing(CoordinateSequence::AutoPtr newCoords) const
476 return Geometry::AutoPtr(new LinearRing(newCoords, this));
479 /*public*/
480 LinearRing*
481 GeometryFactory::createLinearRing(const CoordinateSequence& fromCoords) const
483 CoordinateSequence *newCoords = fromCoords.clone();
484 LinearRing *g = NULL;
485 // construction failure will delete newCoords
486 g = new LinearRing(newCoords, this);
487 return g;
490 /*public*/
491 MultiPoint*
492 GeometryFactory::createMultiPoint(vector<Geometry *> *newPoints) const
494 return new MultiPoint(newPoints,this);
497 /*public*/
498 MultiPoint*
499 GeometryFactory::createMultiPoint(const vector<Geometry *> &fromPoints) const
501 vector<Geometry *>*newGeoms = new vector<Geometry *>(fromPoints.size());
502 for (size_t i=0; i<fromPoints.size(); i++)
504 (*newGeoms)[i] = fromPoints[i]->clone();
507 MultiPoint *g = NULL;
508 try {
509 g = new MultiPoint(newGeoms,this);
510 } catch (...) {
511 for (size_t i=0; i<newGeoms->size(); i++) {
512 delete (*newGeoms)[i];
514 delete newGeoms;
515 throw;
517 return g;
520 /*public*/
521 MultiPoint*
522 GeometryFactory::createMultiPoint() const
524 return new MultiPoint(NULL, this);
527 /*public*/
528 MultiPoint*
529 GeometryFactory::createMultiPoint(const CoordinateSequence &fromCoords) const
531 size_t npts=fromCoords.getSize();
532 vector<Geometry *> *pts=new vector<Geometry *>;
533 pts->reserve(npts);
534 for (size_t i=0; i<npts; ++i) {
535 Point *pt=createPoint(fromCoords.getAt(i));
536 pts->push_back(pt);
538 MultiPoint *mp = NULL;
539 try {
540 mp = createMultiPoint(pts);
541 } catch (...) {
542 for (size_t i=0; i<npts; ++i) delete (*pts)[i];
543 delete pts;
544 throw;
546 return mp;
549 /*public*/
550 MultiPoint*
551 GeometryFactory::createMultiPoint(const std::vector<Coordinate> &fromCoords) const
553 size_t npts=fromCoords.size();
554 vector<Geometry *> *pts=new vector<Geometry *>;
555 pts->reserve(npts);
556 for (size_t i=0; i<npts; ++i) {
557 Point *pt=createPoint(fromCoords[i]);
558 pts->push_back(pt);
560 MultiPoint *mp = NULL;
561 try {
562 mp = createMultiPoint(pts);
563 } catch (...) {
564 for (size_t i=0; i<npts; ++i) delete (*pts)[i];
565 delete pts;
566 throw;
568 return mp;
571 /*public*/
572 Polygon*
573 GeometryFactory::createPolygon() const
575 return new Polygon(NULL, NULL, this);
578 /*public*/
579 Polygon*
580 GeometryFactory::createPolygon(LinearRing *shell, vector<Geometry *> *holes)
581 const
583 return new Polygon(shell, holes, this);
586 /*public*/
587 Polygon*
588 GeometryFactory::createPolygon(const LinearRing &shell, const vector<Geometry *> &holes)
589 const
591 LinearRing *newRing = dynamic_cast<LinearRing *>(shell.clone());
592 vector<Geometry *>*newHoles = new vector<Geometry *>(holes.size());
593 for (size_t i=0; i<holes.size(); i++)
595 (*newHoles)[i] = holes[i]->clone();
597 Polygon *g = NULL;
598 try {
599 g = new Polygon(newRing, newHoles, this);
600 } catch (...) {
601 delete newRing;
602 for (size_t i=0; i<holes.size(); i++)
603 delete (*newHoles)[i];
604 delete newHoles;
605 throw;
607 return g;
610 /*public*/
611 LineString *
612 GeometryFactory::createLineString() const
614 return new LineString(NULL, this);
617 /*public*/
618 std::auto_ptr<LineString>
619 GeometryFactory::createLineString(const LineString& ls) const
621 return std::auto_ptr<LineString>(new LineString(ls));
624 /*public*/
625 LineString*
626 GeometryFactory::createLineString(CoordinateSequence *newCoords)
627 const
629 return new LineString(newCoords, this);
632 /*public*/
633 Geometry::AutoPtr
634 GeometryFactory::createLineString(CoordinateSequence::AutoPtr newCoords)
635 const
637 return Geometry::AutoPtr(new LineString(newCoords, this));
640 /*public*/
641 LineString*
642 GeometryFactory::createLineString(const CoordinateSequence &fromCoords)
643 const
645 CoordinateSequence *newCoords = fromCoords.clone();
646 LineString *g = NULL;
647 // construction failure will delete newCoords
648 g = new LineString(newCoords, this);
649 return g;
652 /*public*/
653 Geometry*
654 GeometryFactory::buildGeometry(vector<Geometry *> *newGeoms) const
656 string geomClass("NULL");
657 bool isHeterogeneous=false;
658 bool hasGeometryCollection=false;
660 for (size_t i=0, n=newGeoms->size(); i<n; ++i)
662 Geometry* geom = (*newGeoms)[i];
663 string partClass(typeid(*geom).name());
664 if (geomClass=="NULL")
666 geomClass=partClass;
668 else if (geomClass!=partClass)
670 isHeterogeneous = true;
672 if ( dynamic_cast<GeometryCollection*>(geom) )
674 hasGeometryCollection=true;
678 // for the empty geometry, return an empty GeometryCollection
679 if (geomClass=="NULL")
681 // we do not need the vector anymore
682 delete newGeoms;
683 return createGeometryCollection();
685 if (isHeterogeneous || hasGeometryCollection)
687 return createGeometryCollection(newGeoms);
690 // At this point we know the collection is not hetereogenous.
691 // Determine the type of the result from the first Geometry in the
692 // list. This should always return a geometry, since otherwise
693 // an empty collection would have already been returned
694 Geometry *geom0=(*newGeoms)[0];
695 bool isCollection=newGeoms->size()>1;
696 if (isCollection)
698 if (typeid(*geom0)==typeid(Polygon)) {
699 return createMultiPolygon(newGeoms);
700 } else if (typeid(*geom0)==typeid(LineString)) {
701 return createMultiLineString(newGeoms);
702 } else if (typeid(*geom0)==typeid(LinearRing)) {
703 return createMultiLineString(newGeoms);
704 } else if (typeid(*geom0)==typeid(Point)) {
705 return createMultiPoint(newGeoms);
706 } else {
707 return createGeometryCollection(newGeoms);
711 // since this is not a collection we can delete vector
712 delete newGeoms;
713 return geom0;
716 /*public*/
717 Geometry*
718 GeometryFactory::buildGeometry(const vector<Geometry *> &fromGeoms) const
720 string geomClass("NULL");
721 bool isHeterogeneous=false;
722 bool isCollection=fromGeoms.size()>1;
723 size_t i;
725 for (i=0; i<fromGeoms.size(); i++) {
726 string partClass(typeid(*fromGeoms[i]).name());
727 if (geomClass=="NULL") {
728 geomClass=partClass;
729 } else if (geomClass!=partClass) {
730 isHeterogeneous = true;
734 // for the empty geometry, return an empty GeometryCollection
735 if (geomClass=="NULL") {
736 return createGeometryCollection();
738 if (isHeterogeneous) {
739 return createGeometryCollection(fromGeoms);
742 // At this point we know the collection is not hetereogenous.
743 // Determine the type of the result from the first Geometry in the
744 // list. This should always return a geometry, since otherwise
745 // an empty collection would have already been returned
746 Geometry *geom0=fromGeoms[0];
747 if (isCollection) {
748 if (typeid(*geom0)==typeid(Polygon)) {
749 return createMultiPolygon(fromGeoms);
750 } else if (typeid(*geom0)==typeid(LineString)) {
751 return createMultiLineString(fromGeoms);
752 } else if (typeid(*geom0)==typeid(LinearRing)) {
753 return createMultiLineString(fromGeoms);
754 } else if (typeid(*geom0)==typeid(Point)) {
755 return createMultiPoint(fromGeoms);
757 assert(0); // buildGeomtry encountered an unkwnon geometry type
760 return geom0->clone();
763 /*public*/
764 Geometry*
765 GeometryFactory::createGeometry(const Geometry *g) const
767 // could this be cached to make this more efficient? Or maybe it isn't enough overhead to bother
768 //return g->clone();
769 util::GeometryEditor editor(this);
770 gfCoordinateOperation coordOp(coordinateListFactory);
771 Geometry *ret = editor.edit(g, &coordOp);
772 return ret;
775 /*public*/
776 void
777 GeometryFactory::destroyGeometry(Geometry *g) const
779 delete g;
782 /*public static*/
783 const GeometryFactory*
784 GeometryFactory::getDefaultInstance()
786 static GeometryFactory* defInstance = new GeometryFactory();
787 return defInstance;
790 /*private*/
791 void
792 GeometryFactory::addRef() const
794 ++_refCount;
797 /*private*/
798 void
799 GeometryFactory::dropRef() const
801 if ( ! --_refCount )
803 if ( _autoDestroy ) delete this;
807 void
808 GeometryFactory::destroy()
810 assert(!_autoDestroy); // don't call me twice !
811 _autoDestroy = true;
812 if ( ! _refCount ) delete this;
815 } // namespace geos::geom
816 } // namespace geos