source: git/src/geom/GeometryFactory.cpp

main-relate-ng
Last change on this file was 4fc18f5, checked in by Daniel Baston <dbaston@…>, 5 months ago

Add tests for curved geometry types

  • Property mode set to 100644
File size: 26.0 KB
Line 
1/**********************************************************************
2 *
3 * GEOS - Geometry Engine Open Source
4 * http://geos.osgeo.org
5 *
6 * Copyright (C) 2011 Sandro Santilli <strk@kbt.io>
7 * Copyright (C) 2001-2002 Vivid Solutions Inc.
8 * Copyright (C) 2005 Refractions Research Inc.
9 *
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.
14 *
15 **********************************************************************
16 *
17 * Last port: geom/GeometryFactory.java r320 (JTS-1.12)
18 *
19 **********************************************************************/
20
21#include <geos/geom/Coordinate.h>
22#include <geos/geom/CoordinateSequence.h>
23#include <geos/geom/CircularString.h>
24#include <geos/geom/CurvePolygon.h>
25#include <geos/geom/CompoundCurve.h>
26#include <geos/geom/GeometryFactory.h>
27#include <geos/geom/Point.h>
28#include <geos/geom/LineString.h>
29#include <geos/geom/LinearRing.h>
30#include <geos/geom/Polygon.h>
31#include <geos/geom/MultiCurve.h>
32#include <geos/geom/MultiPoint.h>
33#include <geos/geom/MultiLineString.h>
34#include <geos/geom/MultiPolygon.h>
35#include <geos/geom/MultiSurface.h>
36#include <geos/geom/GeometryCollection.h>
37#include <geos/geom/PrecisionModel.h>
38#include <geos/geom/Envelope.h>
39#include <geos/geom/util/CoordinateOperation.h>
40#include <geos/geom/util/GeometryEditor.h>
41#include <geos/util/IllegalArgumentException.h>
42#include <geos/util.h>
43
44#include <cassert>
45#include <vector>
46#include <typeinfo>
47#include <cmath>
48
49#ifndef GEOS_DEBUG
50#define GEOS_DEBUG 0
51#endif
52
53#if GEOS_DEBUG
54#include <iostream>
55#endif
56
57namespace geos {
58namespace geom { // geos::geom
59
60namespace {
61
62class gfCoordinateOperation: public util::CoordinateOperation {
63 using CoordinateOperation::edit;
64public:
65 std::unique_ptr<CoordinateSequence>
66 edit(const CoordinateSequence* coordSeq,
67 const Geometry*) override
68 {
69 return detail::make_unique<CoordinateSequence>(*coordSeq);
70 }
71};
72
73} // anonymous namespace
74
75
76
77/*protected*/
78GeometryFactory::GeometryFactory()
79 :
80 SRID(0)
81 , _refCount(0), _autoDestroy(false)
82{
83#if GEOS_DEBUG
84 std::cerr << "GEOS_DEBUG: GeometryFactory[" << this << "]::GeometryFactory()" << std::endl;
85 std::cerr << "\tcreate PrecisionModel[" << &precisionModel << "]" << std::endl;
86#endif
87}
88
89/*public static*/
90GeometryFactory::Ptr
91GeometryFactory::create()
92{
93 return GeometryFactory::Ptr(new GeometryFactory());
94}
95
96/*protected*/
97GeometryFactory::GeometryFactory(const PrecisionModel* pm)
98 :
99 SRID(0)
100 , _refCount(0), _autoDestroy(false)
101{
102#if GEOS_DEBUG
103 std::cerr << "GEOS_DEBUG: GeometryFactory[" << this << "]::GeometryFactory(PrecisionModel[" << pm << "])" << std::endl;
104#endif
105 if(pm) {
106 precisionModel = *pm;
107 }
108}
109
110/*public static*/
111GeometryFactory::Ptr
112GeometryFactory::create(const PrecisionModel* pm)
113{
114 return GeometryFactory::Ptr(
115 new GeometryFactory(pm)
116 );
117}
118
119/*protected*/
120GeometryFactory::GeometryFactory(const PrecisionModel* pm, int newSRID)
121 : SRID(newSRID)
122 , _refCount(0)
123 , _autoDestroy(false)
124{
125#if GEOS_DEBUG
126 std::cerr << "GEOS_DEBUG: GeometryFactory[" << this << "]::GeometryFactory(PrecisionModel[" << pm << "], SRID)" <<
127 std::endl;
128#endif
129 if(pm) {
130 precisionModel = *pm;
131 }
132}
133
134/*public static*/
135GeometryFactory::Ptr
136GeometryFactory::create(const PrecisionModel* pm, int newSRID)
137{
138 return GeometryFactory::Ptr(
139 new GeometryFactory(pm, newSRID)
140 );
141}
142
143/*protected*/
144GeometryFactory::GeometryFactory(const GeometryFactory& gf)
145 : precisionModel(gf.precisionModel)
146 , SRID(gf.SRID)
147 , _refCount(0)
148 , _autoDestroy(false)
149{}
150
151/*public static*/
152GeometryFactory::Ptr
153GeometryFactory::create(const GeometryFactory& gf)
154{
155 return GeometryFactory::Ptr(
156 new GeometryFactory(gf)
157 );
158}
159
160/*public virtual*/
161GeometryFactory::~GeometryFactory()
162{
163#if GEOS_DEBUG
164 std::cerr << "GEOS_DEBUG: GeometryFactory[" << this << "]::~GeometryFactory()" << std::endl;
165#endif
166}
167
168/*public*/
169std::unique_ptr<Point>
170GeometryFactory::createPointFromInternalCoord(const Coordinate* coord,
171 const Geometry* exemplar)
172{
173 assert(coord);
174 Coordinate newcoord = *coord;
175 exemplar->getPrecisionModel()->makePrecise(&newcoord);
176 return exemplar->getFactory()->createPoint(newcoord);
177}
178
179
180/*public*/
181std::unique_ptr<Geometry>
182GeometryFactory::toGeometry(const Envelope* envelope) const
183{
184 CoordinateXY coord;
185
186 if(envelope->isNull()) {
187 return createPoint();
188 }
189 if(envelope->getMinX() == envelope->getMaxX() && envelope->getMinY() == envelope->getMaxY()) {
190 coord.x = envelope->getMinX();
191 coord.y = envelope->getMinY();
192 return std::unique_ptr<Geometry>(createPoint(coord));
193 }
194
195 auto cl = detail::make_unique<CoordinateSequence>(5u, false, false, false);
196
197 coord.x = envelope->getMinX();
198 coord.y = envelope->getMinY();
199 cl->setAt(coord, 0);
200
201 coord.x = envelope->getMaxX();
202 coord.y = envelope->getMinY();
203 cl->setAt(coord, 1);
204
205 coord.x = envelope->getMaxX();
206 coord.y = envelope->getMaxY();
207 cl->setAt(coord, 2);
208
209 coord.x = envelope->getMinX();
210 coord.y = envelope->getMaxY();
211 cl->setAt(coord, 3);
212
213 coord.x = envelope->getMinX();
214 coord.y = envelope->getMinY();
215 cl->setAt(coord, 4);
216
217 return createPolygon(createLinearRing(std::move(cl)));
218}
219
220/*public*/
221std::unique_ptr<Point>
222GeometryFactory::createPoint(std::size_t coordinateDimension) const
223{
224 CoordinateSequence seq(0u, coordinateDimension);
225 return std::unique_ptr<Point>(new Point(std::move(seq), this));
226}
227
228/*public*/
229std::unique_ptr<Point>
230GeometryFactory::createPoint(bool hasZ, bool hasM) const
231{
232 CoordinateSequence seq(0u, hasZ, hasM);
233 return std::unique_ptr<Point>(new Point(std::move(seq), this));
234}
235
236/*public*/
237std::unique_ptr<Point>
238GeometryFactory::createPoint(std::unique_ptr<CoordinateSequence>&& coords) const
239{
240 if (!coords) {
241 return createPoint();
242 }
243 return std::unique_ptr<Point>(new Point(std::move(*coords), this));
244}
245
246std::unique_ptr<Point>
247GeometryFactory::createPoint(const CoordinateXY& coordinate) const
248{
249 return std::unique_ptr<Point>(new Point(coordinate, this));
250}
251
252/*public*/
253std::unique_ptr<Point>
254GeometryFactory::createPoint(const Coordinate& coordinate) const
255{
256 return std::unique_ptr<Point>(new Point(coordinate, this));
257}
258
259std::unique_ptr<Point>
260GeometryFactory::createPoint(const CoordinateXYM& coordinate) const
261{
262 return std::unique_ptr<Point>(new Point(coordinate, this));
263}
264
265std::unique_ptr<Point>
266GeometryFactory::createPoint(const CoordinateXYZM& coordinate) const
267{
268 return std::unique_ptr<Point>(new Point(coordinate, this));
269}
270
271/*public*/
272std::unique_ptr<Point>
273GeometryFactory::createPoint(const CoordinateSequence& fromCoords) const
274{
275 CoordinateSequence newCoords(fromCoords);
276 return std::unique_ptr<Point>(new Point(std::move(newCoords), this));
277
278}
279
280/*public*/
281std::unique_ptr<MultiLineString>
282GeometryFactory::createMultiLineString() const
283{
284 return createMultiLineString(std::vector<std::unique_ptr<Geometry>>());
285}
286
287/*public*/
288std::unique_ptr<MultiLineString>
289GeometryFactory::createMultiLineString(const std::vector<const Geometry*>& fromLines)
290const
291{
292 std::vector<std::unique_ptr<Geometry>> newGeoms(fromLines.size());
293
294 for(std::size_t i = 0; i < fromLines.size(); i++) {
295 auto line = dynamic_cast<const LineString*>(fromLines[i]);
296
297 if(!line) {
298 throw geos::util::IllegalArgumentException("createMultiLineString called with a vector containing non-LineStrings");
299 }
300
301 newGeoms[i].reset(new LineString(*line));
302 }
303
304 return createMultiLineString(std::move(newGeoms));
305}
306
307std::unique_ptr<MultiLineString>
308GeometryFactory::createMultiLineString(std::vector<std::unique_ptr<LineString>> && fromLines) const {
309 // Can't use make_unique because constructor is protected
310 return std::unique_ptr<MultiLineString>(new MultiLineString(std::move(fromLines), *this));
311}
312
313std::unique_ptr<MultiLineString>
314GeometryFactory::createMultiLineString(std::vector<std::unique_ptr<Geometry>> && fromLines) const {
315 // Can't use make_unique because constructor is protected
316 return std::unique_ptr<MultiLineString>(new MultiLineString(std::move(fromLines), *this));
317}
318
319std::unique_ptr<MultiCurve>
320GeometryFactory::createMultiCurve() const {
321 return createMultiCurve(std::vector<std::unique_ptr<Curve>>());
322}
323
324std::unique_ptr<MultiCurve>
325GeometryFactory::createMultiCurve(std::vector<std::unique_ptr<Curve>> && fromCurves) const {
326 // Can't use make_unique because constructor is protected
327 return std::unique_ptr<MultiCurve>(new MultiCurve(std::move(fromCurves), *this));
328}
329
330std::unique_ptr<MultiCurve>
331GeometryFactory::createMultiCurve(std::vector<std::unique_ptr<Geometry>> && fromCurves) const {
332 // Can't use make_unique because constructor is protected
333 return std::unique_ptr<MultiCurve>(new MultiCurve(std::move(fromCurves), *this));
334}
335
336/*public*/
337std::unique_ptr<GeometryCollection>
338GeometryFactory::createGeometryCollection() const
339{
340 return createGeometryCollection(std::vector<std::unique_ptr<Geometry>>());
341}
342
343/*public*/
344std::unique_ptr<Geometry>
345GeometryFactory::createEmptyGeometry(GeometryTypeId type, bool hasZ, bool hasM) const
346{
347 switch (type) {
348 case GEOS_POINT: return createPoint(hasZ, hasM);
349 case GEOS_LINESTRING: return createLineString(hasZ, hasM);
350 case GEOS_LINEARRING: return createLinearRing(hasZ, hasM);
351 case GEOS_POLYGON: return createPolygon(hasZ, hasM);
352 case GEOS_MULTIPOINT: return createMultiPoint();
353 case GEOS_MULTILINESTRING: return createMultiLineString();
354 case GEOS_MULTIPOLYGON: return createMultiPolygon();
355 case GEOS_GEOMETRYCOLLECTION: return createGeometryCollection();
356 case GEOS_CIRCULARSTRING: return createCircularString(hasZ, hasM);
357 case GEOS_COMPOUNDCURVE: return createCompoundCurve();
358 case GEOS_CURVEPOLYGON: return createCurvePolygon(hasZ, hasM);
359 case GEOS_MULTICURVE: return createMultiCurve();
360 case GEOS_MULTISURFACE: return createMultiSurface();
361 default:
362 throw geos::util::IllegalArgumentException("Unexpected GeometryTypeId");
363
364 }
365}
366
367/*public*/
368std::unique_ptr<GeometryCollection>
369GeometryFactory::createGeometryCollection(const std::vector<const Geometry*>& fromGeoms) const
370{
371 std::vector<std::unique_ptr<Geometry>> newGeoms(fromGeoms.size());
372
373 for(std::size_t i = 0; i < fromGeoms.size(); i++) {
374 newGeoms[i] = fromGeoms[i]->clone();
375 }
376
377 return createGeometryCollection(std::move(newGeoms));
378}
379
380/*public*/
381std::unique_ptr<MultiPolygon>
382GeometryFactory::createMultiPolygon() const
383{
384 return createMultiPolygon(std::vector<std::unique_ptr<Polygon>>());
385}
386
387/*public*/
388std::unique_ptr<MultiPolygon>
389GeometryFactory::createMultiPolygon(std::vector<std::unique_ptr<Polygon>> && newPolys) const
390{
391 // Can't use make_unique because constructor is protected
392 return std::unique_ptr<MultiPolygon>(new MultiPolygon(std::move(newPolys), *this));
393}
394
395std::unique_ptr<MultiPolygon>
396GeometryFactory::createMultiPolygon(std::vector<std::unique_ptr<Geometry>> && newPolys) const
397{
398 // Can't use make_unique because constructor is protected
399 return std::unique_ptr<MultiPolygon>(new MultiPolygon(std::move(newPolys), *this));
400}
401
402/*public*/
403std::unique_ptr<MultiPolygon>
404GeometryFactory::createMultiPolygon(const std::vector<const Geometry*>& fromPolys) const
405{
406 std::vector<std::unique_ptr<Geometry>> newGeoms(fromPolys.size());
407
408 for(std::size_t i = 0; i < fromPolys.size(); i++) {
409 newGeoms[i] = fromPolys[i]->clone();
410 }
411
412 return createMultiPolygon(std::move(newGeoms));
413}
414
415std::unique_ptr<MultiSurface>
416GeometryFactory::createMultiSurface() const
417{
418 // Can't use make_unique because constructor is protected
419 return std::unique_ptr<MultiSurface>(new MultiSurface(std::vector<std::unique_ptr<Surface>>(), *this));
420}
421
422std::unique_ptr<MultiSurface>
423GeometryFactory::createMultiSurface(std::vector<std::unique_ptr<Geometry>> && newSurfaces) const
424{
425 // Can't use make_unique because constructor is protected
426 return std::unique_ptr<MultiSurface>(new MultiSurface(std::move(newSurfaces), *this));
427}
428
429std::unique_ptr<MultiSurface>
430GeometryFactory::createMultiSurface(std::vector<std::unique_ptr<Surface>> && newSurfaces) const
431{
432 // Can't use make_unique because constructor is protected
433 return std::unique_ptr<MultiSurface>(new MultiSurface(std::move(newSurfaces), *this));
434}
435
436/*public*/
437std::unique_ptr<LinearRing>
438GeometryFactory::createLinearRing(std::size_t coordinateDimension) const
439{
440 // Can't use make_unique with protected constructor
441 auto cs = detail::make_unique<CoordinateSequence>(0u, coordinateDimension);
442 return std::unique_ptr<LinearRing>(new LinearRing(std::move(cs), *this));
443}
444
445/*public*/
446std::unique_ptr<LinearRing>
447GeometryFactory::createLinearRing(bool hasZ, bool hasM) const
448{
449 // Can't use make_unique with protected constructor
450 auto cs = detail::make_unique<CoordinateSequence>(0u, hasZ, hasM);
451 return std::unique_ptr<LinearRing>(new LinearRing(std::move(cs), *this));
452}
453
454std::unique_ptr<LinearRing>
455GeometryFactory::createLinearRing(CoordinateSequence::Ptr && newCoords) const
456{
457 // Can't use make_unique with protected constructor
458 return std::unique_ptr<LinearRing>(new LinearRing(std::move(newCoords), *this));
459}
460
461/*public*/
462std::unique_ptr<LinearRing>
463GeometryFactory::createLinearRing(const CoordinateSequence& fromCoords) const
464{
465 return createLinearRing(fromCoords.clone());
466}
467
468/*public*/
469std::unique_ptr<MultiPoint>
470GeometryFactory::createMultiPoint(std::vector<std::unique_ptr<Point>> && newPoints) const
471{
472 return std::unique_ptr<MultiPoint>(new MultiPoint(std::move(newPoints), *this));
473}
474
475std::unique_ptr<MultiPoint>
476GeometryFactory::createMultiPoint(std::vector<std::unique_ptr<Geometry>> && newPoints) const
477{
478 return std::unique_ptr<MultiPoint>(new MultiPoint(std::move(newPoints), *this));
479}
480
481/*public*/
482std::unique_ptr<MultiPoint>
483GeometryFactory::createMultiPoint(const std::vector<const Geometry*>& fromPoints) const
484{
485 std::vector<std::unique_ptr<Geometry>> newGeoms(fromPoints.size());
486 for(std::size_t i = 0; i < fromPoints.size(); i++) {
487 newGeoms[i] = fromPoints[i]->clone();
488 }
489
490 return createMultiPoint(std::move(newGeoms));
491}
492
493/*public*/
494std::unique_ptr<MultiPoint>
495GeometryFactory::createMultiPoint() const
496{
497 return std::unique_ptr<MultiPoint>(new MultiPoint(std::vector<std::unique_ptr<Geometry>>(), *this));
498}
499
500/*public*/
501std::unique_ptr<MultiPoint>
502GeometryFactory::createMultiPoint(const CoordinateSequence& fromCoords) const
503{
504 std::size_t npts = fromCoords.getSize();
505 std::vector<std::unique_ptr<Geometry>> pts;
506 pts.reserve(npts);
507
508 fromCoords.forEach([&pts, this](const auto& coord) -> void {
509 pts.push_back(this->createPoint(coord));
510 });
511
512 return createMultiPoint(std::move(pts));
513}
514
515/*public*/
516std::unique_ptr<Polygon>
517GeometryFactory::createPolygon(std::size_t coordinateDimension) const
518{
519 auto cs = detail::make_unique<CoordinateSequence>(0u, coordinateDimension);
520 auto lr = createLinearRing(std::move(cs));
521 return createPolygon(std::move(lr));
522}
523
524/*public*/
525std::unique_ptr<Polygon>
526GeometryFactory::createPolygon(bool hasZ, bool hasM) const
527{
528 auto cs = detail::make_unique<CoordinateSequence>(0u, hasZ, hasM);
529 auto lr = createLinearRing(std::move(cs));
530 return createPolygon(std::move(lr));
531}
532
533std::unique_ptr<Polygon>
534GeometryFactory::createPolygon(std::unique_ptr<LinearRing> && shell)
535const
536{
537 // Can't use make_unique with protected constructor
538 return std::unique_ptr<Polygon>(new Polygon(std::move(shell), *this));
539}
540
541/*public*/
542std::unique_ptr<Polygon>
543GeometryFactory::createPolygon(CoordinateSequence && coords)
544const
545{
546 auto cs = detail::make_unique<CoordinateSequence>(std::move(coords));
547 std::unique_ptr<geom::LinearRing> lr = createLinearRing(std::move(cs));
548 std::unique_ptr<geom::Polygon> ply = createPolygon(std::move(lr));
549 return ply;
550}
551
552
553std::unique_ptr<Polygon>
554GeometryFactory::createPolygon(std::unique_ptr<LinearRing> && shell, std::vector<std::unique_ptr<LinearRing>> && holes)
555const
556{
557 // Can't use make_unique with protected constructor
558 return std::unique_ptr<Polygon>(new Polygon(std::move(shell), std::move(holes), *this));
559}
560
561/*public*/
562Polygon*
563GeometryFactory::createPolygon(const LinearRing& shell, const std::vector<LinearRing*>& holes)
564const
565{
566 std::unique_ptr<LinearRing> newRing(new LinearRing(shell));
567
568 std::vector<std::unique_ptr<LinearRing>> newHoles(holes.size());
569
570 for(std::size_t i = 0; i < holes.size(); i++) {
571 newHoles[i].reset(new LinearRing(*holes[i]));
572 }
573
574 return new Polygon(std::move(newRing), std::move(newHoles), *this);
575}
576
577/* public */
578std::unique_ptr<CurvePolygon>
579GeometryFactory::createCurvePolygon(bool hasZ, bool hasM)
580const
581{
582 // Can't use make_unique with protected constructor
583 return std::unique_ptr<CurvePolygon>(new CurvePolygon(createLinearRing(hasZ, hasM), *this));
584}
585
586/* public */
587std::unique_ptr<CurvePolygon>
588GeometryFactory::createCurvePolygon(std::unique_ptr<Curve> && shell)
589const
590{
591 // Can't use make_unique with protected constructor
592 return std::unique_ptr<CurvePolygon>(new CurvePolygon(std::move(shell), *this));
593}
594
595/* public */
596std::unique_ptr<CurvePolygon>
597GeometryFactory::createCurvePolygon(std::unique_ptr<Curve> && shell, std::vector<std::unique_ptr<Curve>> && holes)
598const
599{
600 // Can't use make_unique with protected constructor
601 return std::unique_ptr<CurvePolygon>(new CurvePolygon(std::move(shell), std::move(holes), *this));
602}
603
604/*public*/
605std::unique_ptr<LineString>
606GeometryFactory::createLineString(std::size_t coordinateDimension) const
607{
608 auto cs = detail::make_unique<CoordinateSequence>(0u, coordinateDimension);
609 return createLineString(std::move(cs));
610}
611
612/*public*/
613std::unique_ptr<LineString>
614GeometryFactory::createLineString(bool hasZ, bool hasM) const
615{
616 auto cs = detail::make_unique<CoordinateSequence>(0u, hasZ, hasM);
617 return createLineString(std::move(cs));
618}
619
620/*public*/
621std::unique_ptr<CircularString>
622GeometryFactory::createCircularString(bool hasZ, bool hasM) const
623{
624 auto cs = detail::make_unique<CoordinateSequence>(0u, hasZ, hasM);
625 return createCircularString(std::move(cs));
626}
627
628/*public*/
629std::unique_ptr<LineString>
630GeometryFactory::createLineString(const LineString& ls) const
631{
632 // Can't use make_unique with protected constructor
633 return std::unique_ptr<LineString>(new LineString(ls));
634}
635
636/*public*/
637std::unique_ptr<CircularString>
638GeometryFactory::createCircularString(const CircularString& ls) const
639{
640 // Can't use make_unique with protected constructor
641 return std::unique_ptr<CircularString>(new CircularString(ls));
642}
643
644/*public*/
645std::unique_ptr<LineString>
646GeometryFactory::createLineString(CoordinateSequence::Ptr && newCoords)
647const
648{
649 if (!newCoords)
650 return createLineString();
651 // Can't use make_unique with protected constructor
652 return std::unique_ptr<LineString>(new LineString(std::move(newCoords), *this));
653}
654
655/*public*/
656std::unique_ptr<CircularString>
657GeometryFactory::createCircularString(CoordinateSequence::Ptr && newCoords)
658const
659{
660 if (!newCoords)
661 return createCircularString(false, false);
662 // Can't use make_unique with protected constructor
663 return std::unique_ptr<CircularString>(new CircularString(std::move(newCoords), *this));
664}
665
666/*public*/
667std::unique_ptr<CompoundCurve>
668GeometryFactory::createCompoundCurve()
669const
670{
671 std::vector<std::unique_ptr<SimpleCurve>> curves;
672 return createCompoundCurve(std::move(curves));
673}
674
675/*public*/
676std::unique_ptr<CompoundCurve>
677GeometryFactory::createCompoundCurve(std::vector<std::unique_ptr<SimpleCurve>>&& curves)
678const
679{
680 return std::unique_ptr<CompoundCurve>(new CompoundCurve(std::move(curves), *this));
681}
682
683/*public*/
684std::unique_ptr<LineString>
685GeometryFactory::createLineString(const CoordinateSequence& fromCoords)
686const
687{
688 // Can't use make_unique with protected constructor
689 return std::unique_ptr<LineString>(new LineString(fromCoords.clone(), *this));
690}
691
692/*public*/
693std::unique_ptr<CircularString>
694GeometryFactory::createCircularString(const CoordinateSequence& fromCoords)
695const
696{
697 // Can't use make_unique with protected constructor
698 return std::unique_ptr<CircularString>(new CircularString(fromCoords.clone(), *this));
699}
700
701/*public*/
702std::unique_ptr<Geometry>
703GeometryFactory::createEmpty(int dimension) const
704{
705 switch (dimension) {
706 case -1: return createGeometryCollection();
707 case 0: return createPoint();
708 case 1: return createLineString();
709 case 2: return createPolygon();
710 default:
711 throw geos::util::IllegalArgumentException("Invalid dimension");
712 }
713}
714
715/*public*/
716std::unique_ptr<Geometry>
717GeometryFactory::createEmpty(GeometryTypeId typeId) const
718{
719 switch (typeId) {
720 case GEOS_POINT: return createPoint();
721 case GEOS_LINESTRING: return createLineString();
722 case GEOS_POLYGON: return createPolygon();
723 case GEOS_MULTIPOINT: return createMultiPoint();
724 case GEOS_MULTILINESTRING: return createMultiLineString();
725 case GEOS_MULTIPOLYGON: return createMultiPolygon();
726 case GEOS_GEOMETRYCOLLECTION: return createGeometryCollection();
727 default:
728 throw geos::util::IllegalArgumentException("Invalid GeometryTypeId");
729 }
730}
731
732/*public*/
733std::unique_ptr<Geometry>
734GeometryFactory::createMulti(std::unique_ptr<Geometry> && geom) const
735{
736 GeometryTypeId typeId = geom->getGeometryTypeId();
737
738 // Already a collection? Done!
739 if (geom->isCollection())
740 return std::move(geom);
741
742 if (geom->isEmpty()) {
743 return geom->getFactory()->createEmpty(Geometry::multiTypeId(typeId));
744 }
745
746 std::vector<std::unique_ptr<Geometry>> subgeoms;
747 const GeometryFactory* gf = geom->getFactory();
748 subgeoms.push_back(std::move(geom));
749 switch (typeId) {
750 case GEOS_POINT:
751 return gf->createMultiPoint(std::move(subgeoms));
752 case GEOS_LINESTRING:
753 return gf->createMultiLineString(std::move(subgeoms));
754 case GEOS_POLYGON:
755 return gf->createMultiPolygon(std::move(subgeoms));
756 default:
757 throw geos::util::IllegalArgumentException("Unsupported GeometryTypeId");
758 }
759}
760
761template<typename T>
762GeometryTypeId commonType(const T& geoms) {
763 if (geoms.empty()) {
764 return GEOS_GEOMETRYCOLLECTION;
765 }
766
767 if (geoms.size() == 1) {
768 return geoms[0]->getGeometryTypeId();
769 }
770
771 GeometryTypeId type = geoms[0]->getGeometryTypeId();
772 for (std::size_t i = 1; i < geoms.size(); i++) {
773 if (geoms[i]->getGeometryTypeId() != type) {
774 return GEOS_GEOMETRYCOLLECTION;
775 }
776 }
777
778 switch(geoms[0]->getGeometryTypeId()) {
779 case GEOS_POINT: return GEOS_MULTIPOINT;
780 case GEOS_LINEARRING:
781 case GEOS_LINESTRING: return GEOS_MULTILINESTRING;
782 case GEOS_POLYGON: return GEOS_MULTIPOLYGON;
783 default: return GEOS_GEOMETRYCOLLECTION;
784 }
785}
786
787std::unique_ptr<Geometry>
788GeometryFactory::buildGeometry(std::vector<std::unique_ptr<Geometry>> && geoms) const
789{
790 if (geoms.empty()) {
791 return createGeometryCollection();
792 }
793
794 if (geoms.size() == 1) {
795 return std::move(geoms[0]);
796 }
797
798 auto resultType = commonType(geoms);
799
800 switch(resultType) {
801 case GEOS_MULTIPOINT: return createMultiPoint(std::move(geoms));
802 case GEOS_MULTILINESTRING: return createMultiLineString(std::move(geoms));
803 case GEOS_MULTIPOLYGON: return createMultiPolygon(std::move(geoms));
804 default: return createGeometryCollection(std::move(geoms));
805 }
806}
807
808std::unique_ptr<Geometry>
809GeometryFactory::buildGeometry(std::vector<std::unique_ptr<Point>> && geoms) const
810{
811 if (geoms.empty()) {
812 return createGeometryCollection();
813 }
814
815 if (geoms.size() == 1) {
816 return std::move(geoms[0]);
817 }
818
819 return createMultiPoint(std::move(geoms));
820}
821
822std::unique_ptr<Geometry>
823GeometryFactory::buildGeometry(std::vector<std::unique_ptr<LineString>> && geoms) const
824{
825 if (geoms.empty()) {
826 return createGeometryCollection();
827 }
828
829 if (geoms.size() == 1) {
830 return std::move(geoms[0]);
831 }
832
833 return createMultiLineString(std::move(geoms));
834}
835
836std::unique_ptr<Geometry>
837GeometryFactory::buildGeometry(std::vector<std::unique_ptr<Polygon>> && geoms) const
838{
839 if (geoms.empty()) {
840 return createGeometryCollection();
841 }
842
843 if (geoms.size() == 1) {
844 return std::move(geoms[0]);
845 }
846
847 return createMultiPolygon(std::move(geoms));
848}
849
850/*public*/
851std::unique_ptr<Geometry>
852GeometryFactory::buildGeometry(const std::vector<const Geometry*>& fromGeoms) const
853{
854 if(fromGeoms.empty()) {
855 return createGeometryCollection();
856 }
857
858 if(fromGeoms.size() == 1) {
859 return fromGeoms[0]->clone();
860 }
861
862 auto resultType = commonType(fromGeoms);
863
864 switch(resultType) {
865 case GEOS_MULTIPOINT: return createMultiPoint(fromGeoms);
866 case GEOS_MULTILINESTRING: return createMultiLineString(fromGeoms);
867 case GEOS_MULTIPOLYGON: return createMultiPolygon(fromGeoms);
868 default: return createGeometryCollection(fromGeoms);
869 }
870}
871
872/*public*/
873std::unique_ptr<Geometry>
874GeometryFactory::createGeometry(const Geometry* g) const
875{
876 // could this be cached to make this more efficient? Or maybe it isn't enough overhead to bother
877 //return g->clone(); <-- a simple clone() wouldn't change the factory to `this`
878 util::GeometryEditor editor(this);
879 gfCoordinateOperation coordOp;
880 return editor.edit(g, &coordOp);
881}
882
883/*public*/
884void
885GeometryFactory::destroyGeometry(Geometry* g) const
886{
887 delete g;
888}
889
890/*public static*/
891const GeometryFactory*
892GeometryFactory::getDefaultInstance()
893{
894 static GeometryFactory defInstance;
895 return &defInstance;
896}
897
898/*private*/
899void
900GeometryFactory::addRef() const
901{
902 ++_refCount;
903}
904
905/*private*/
906void
907GeometryFactory::dropRef() const
908{
909 if(! --_refCount) {
910 if(_autoDestroy) {
911 delete this;
912 }
913 }
914}
915
916void
917GeometryFactory::destroy()
918{
919 assert(!_autoDestroy); // don't call me twice !
920 _autoDestroy = true;
921 if(! _refCount) {
922 delete this;
923 }
924}
925
926} // namespace geos::geom
927} // namespace geos
Note: See TracBrowser for help on using the repository browser.