Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: The OGRCurvePolygon geometry class.
5 : * Author: Even Rouault <even dot rouault at spatialys dot com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2014, Even Rouault <even dot rouault at spatialys dot com>
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "cpl_port.h"
30 : #include "ogr_geometry.h"
31 :
32 : #include <cstddef>
33 :
34 : #include "cpl_error.h"
35 : #include "ogr_api.h"
36 : #include "ogr_core.h"
37 : #include "ogr_geos.h"
38 : #include "ogr_sfcgal.h"
39 : #include "ogr_p.h"
40 : #include "ogr_spatialref.h"
41 :
42 : /************************************************************************/
43 : /* OGRCurvePolygon() */
44 : /************************************************************************/
45 :
46 : /**
47 : * \brief Create an empty curve polygon.
48 : */
49 :
50 : OGRCurvePolygon::OGRCurvePolygon() = default;
51 :
52 : /************************************************************************/
53 : /* OGRCurvePolygon( const OGRCurvePolygon& ) */
54 : /************************************************************************/
55 :
56 : /**
57 : * \brief Copy constructor.
58 : *
59 : * Note: before GDAL 2.1, only the default implementation of the constructor
60 : * existed, which could be unsafe to use.
61 : *
62 : * @since GDAL 2.1
63 : */
64 :
65 : OGRCurvePolygon::OGRCurvePolygon(const OGRCurvePolygon &) = default;
66 :
67 : /************************************************************************/
68 : /* ~OGRCurvePolygon() */
69 : /************************************************************************/
70 :
71 : OGRCurvePolygon::~OGRCurvePolygon() = default;
72 :
73 : /************************************************************************/
74 : /* operator=( const OGRCurvePolygon&) */
75 : /************************************************************************/
76 :
77 : /**
78 : * \brief Assignment operator.
79 : *
80 : * Note: before GDAL 2.1, only the default implementation of the operator
81 : * existed, which could be unsafe to use.
82 : *
83 : * @since GDAL 2.1
84 : */
85 :
86 13 : OGRCurvePolygon &OGRCurvePolygon::operator=(const OGRCurvePolygon &other)
87 : {
88 13 : if (this != &other)
89 : {
90 12 : OGRSurface::operator=(other);
91 :
92 12 : oCC = other.oCC;
93 : }
94 13 : return *this;
95 : }
96 :
97 : /************************************************************************/
98 : /* clone() */
99 : /************************************************************************/
100 :
101 255 : OGRCurvePolygon *OGRCurvePolygon::clone() const
102 :
103 : {
104 255 : return new (std::nothrow) OGRCurvePolygon(*this);
105 : }
106 :
107 : /************************************************************************/
108 : /* empty() */
109 : /************************************************************************/
110 :
111 58396 : void OGRCurvePolygon::empty()
112 :
113 : {
114 58396 : oCC.empty(this);
115 58396 : }
116 :
117 : /************************************************************************/
118 : /* getGeometryType() */
119 : /************************************************************************/
120 :
121 1375 : OGRwkbGeometryType OGRCurvePolygon::getGeometryType() const
122 :
123 : {
124 1375 : if ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED))
125 180 : return wkbCurvePolygonZM;
126 1195 : else if (flags & OGR_G_MEASURED)
127 11 : return wkbCurvePolygonM;
128 1184 : else if (flags & OGR_G_3D)
129 106 : return wkbCurvePolygonZ;
130 : else
131 1078 : return wkbCurvePolygon;
132 : }
133 :
134 : /************************************************************************/
135 : /* getDimension() */
136 : /************************************************************************/
137 :
138 132 : int OGRCurvePolygon::getDimension() const
139 :
140 : {
141 132 : return 2;
142 : }
143 :
144 : /************************************************************************/
145 : /* flattenTo2D() */
146 : /************************************************************************/
147 :
148 753 : void OGRCurvePolygon::flattenTo2D()
149 :
150 : {
151 753 : oCC.flattenTo2D(this);
152 753 : }
153 :
154 : /************************************************************************/
155 : /* getGeometryName() */
156 : /************************************************************************/
157 :
158 675 : const char *OGRCurvePolygon::getGeometryName() const
159 :
160 : {
161 675 : return "CURVEPOLYGON";
162 : }
163 :
164 : /************************************************************************/
165 : /* getExteriorRingCurve() */
166 : /************************************************************************/
167 :
168 : /**
169 : * \brief Fetch reference to external polygon ring.
170 : *
171 : * Note that the returned ring pointer is to an internal data object of the
172 : * OGRCurvePolygon. It should not be modified or deleted by the application,
173 : * and the pointer is only valid till the polygon is next modified. Use the
174 : * OGRGeometry::clone() method to make a separate copy within the application.
175 : *
176 : * Relates to the Simple Features for COM (SFCOM) IPolygon::get_ExteriorRing()
177 : * method.
178 : * TODO(rouault): What does that mean?
179 : *
180 : * @return pointer to external ring. May be NULL if the OGRCurvePolygon is
181 : * empty.
182 : */
183 :
184 8333 : OGRCurve *OGRCurvePolygon::getExteriorRingCurve()
185 :
186 : {
187 8333 : return oCC.getCurve(0);
188 : }
189 :
190 : /**
191 : * \brief Fetch reference to external polygon ring.
192 : *
193 : * Note that the returned ring pointer is to an internal data object of the
194 : * OGRCurvePolygon. It should not be modified or deleted by the application,
195 : * and the pointer is only valid till the polygon is next modified. Use the
196 : * OGRGeometry::clone() method to make a separate copy within the application.
197 : *
198 : * Relates to the SFCOM IPolygon::get_ExteriorRing() method.
199 : *
200 : * @return pointer to external ring. May be NULL if the OGRCurvePolygon is
201 : * empty.
202 : */
203 7683 : const OGRCurve *OGRCurvePolygon::getExteriorRingCurve() const
204 :
205 : {
206 7683 : return oCC.getCurve(0);
207 : }
208 :
209 : /************************************************************************/
210 : /* getNumInteriorRings() */
211 : /************************************************************************/
212 :
213 : /**
214 : * \brief Fetch the number of internal rings.
215 : *
216 : * Relates to the SFCOM IPolygon::get_NumInteriorRings() method.
217 : *
218 : * @return count of internal rings, zero or more.
219 : */
220 :
221 162052 : int OGRCurvePolygon::getNumInteriorRings() const
222 :
223 : {
224 162052 : if (oCC.nCurveCount > 0)
225 162041 : return oCC.nCurveCount - 1;
226 : else
227 11 : return 0;
228 : }
229 :
230 : /************************************************************************/
231 : /* getInteriorRingCurve() */
232 : /************************************************************************/
233 :
234 : /**
235 : * \brief Fetch reference to indicated internal ring.
236 : *
237 : * Note that the returned ring pointer is to an internal data object of the
238 : * OGRCurvePolygon. It should not be modified or deleted by the application,
239 : * and the pointer is only valid till the polygon is next modified. Use the
240 : * OGRGeometry::clone() method to make a separate copy within the application.
241 : *
242 : * Relates to the SFCOM IPolygon::get_InternalRing() method.
243 : *
244 : * @param iRing internal ring index from 0 to getNumInteriorRings() - 1.
245 : *
246 : * @return pointer to interior ring. May be NULL.
247 : */
248 :
249 78 : OGRCurve *OGRCurvePolygon::getInteriorRingCurve(int iRing)
250 :
251 : {
252 78 : return oCC.getCurve(iRing + 1);
253 : }
254 :
255 : /**
256 : * \brief Fetch reference to indicated internal ring.
257 : *
258 : * Note that the returned ring pointer is to an internal data object of the
259 : * OGRCurvePolygon. It should not be modified or deleted by the application,
260 : * and the pointer is only valid till the polygon is next modified. Use the
261 : * OGRGeometry::clone() method to make a separate copy within the application.
262 : *
263 : * Relates to the SFCOM IPolygon::get_InternalRing() method.
264 : *
265 : * @param iRing internal ring index from 0 to getNumInteriorRings() - 1.
266 : *
267 : * @return pointer to interior ring. May be NULL.
268 : */
269 :
270 17 : const OGRCurve *OGRCurvePolygon::getInteriorRingCurve(int iRing) const
271 :
272 : {
273 17 : return oCC.getCurve(iRing + 1);
274 : }
275 :
276 : /************************************************************************/
277 : /* stealExteriorRingCurve() */
278 : /************************************************************************/
279 :
280 : /**
281 : * \brief "Steal" reference to external ring.
282 : *
283 : * After the call to that function, only call to stealInteriorRing() or
284 : * destruction of the OGRCurvePolygon is valid. Other operations may crash.
285 : *
286 : * @return pointer to external ring. May be NULL if the OGRCurvePolygon is
287 : * empty.
288 : */
289 :
290 858 : OGRCurve *OGRCurvePolygon::stealExteriorRingCurve()
291 : {
292 858 : if (oCC.nCurveCount == 0)
293 2 : return nullptr;
294 856 : OGRCurve *poRet = oCC.papoCurves[0];
295 856 : oCC.papoCurves[0] = nullptr;
296 856 : return poRet;
297 : }
298 :
299 : /************************************************************************/
300 : /* removeRing() */
301 : /************************************************************************/
302 :
303 : /**
304 : * \brief Remove a geometry from the container.
305 : *
306 : * Removing a geometry will cause the geometry count to drop by one, and all
307 : * "higher" geometries will shuffle down one in index.
308 : *
309 : * There is no SFCOM analog to this method.
310 : *
311 : * @param iIndex the index of the geometry to delete. A value of -1 is a
312 : * special flag meaning that all geometries should be removed.
313 : *
314 : * @param bDelete if true the geometry will be deallocated, otherwise it will
315 : * not. The default is true as the container is considered to own the
316 : * geometries in it.
317 : *
318 : * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is
319 : * out of range.
320 : */
321 :
322 16 : OGRErr OGRCurvePolygon::removeRing(int iIndex, bool bDelete)
323 : {
324 16 : return oCC.removeCurve(iIndex, bDelete);
325 : }
326 :
327 : /************************************************************************/
328 : /* addRing() */
329 : /************************************************************************/
330 :
331 : /**
332 : * \brief Add a ring to a polygon.
333 : *
334 : * If the polygon has no external ring (it is empty) this will be used as
335 : * the external ring, otherwise it is used as an internal ring. The passed
336 : * OGRCurve remains the responsibility of the caller (an internal copy
337 : * is made).
338 : *
339 : * This method has no SFCOM analog.
340 : *
341 : * @param poNewRing ring to be added to the polygon.
342 : * @return OGRERR_NONE in case of success
343 : */
344 :
345 49884 : OGRErr OGRCurvePolygon::addRing(OGRCurve *poNewRing)
346 :
347 : {
348 49884 : OGRCurve *poNewRingCloned = poNewRing->clone();
349 49883 : OGRErr eErr = addRingDirectly(poNewRingCloned);
350 49884 : if (eErr != OGRERR_NONE)
351 0 : delete poNewRingCloned;
352 49883 : return eErr;
353 : }
354 :
355 : /************************************************************************/
356 : /* checkRing() */
357 : /************************************************************************/
358 :
359 625 : int OGRCurvePolygon::checkRing(OGRCurve *poNewRing) const
360 : {
361 625 : if (!poNewRing->IsEmpty() && !poNewRing->get_IsClosed())
362 : {
363 : // This configuration option name must be the same as in
364 : // OGRPolygon::checkRing()
365 : const char *pszEnvVar =
366 7 : CPLGetConfigOption("OGR_GEOMETRY_ACCEPT_UNCLOSED_RING", nullptr);
367 7 : if (pszEnvVar != nullptr && !CPLTestBool(pszEnvVar))
368 : {
369 1 : CPLError(CE_Failure, CPLE_AppDefined, "Non closed ring detected.");
370 1 : return FALSE;
371 : }
372 : else
373 : {
374 6 : CPLError(CE_Warning, CPLE_AppDefined, "Non closed ring detected.%s",
375 : pszEnvVar == nullptr
376 : ? " To avoid accepting it, set the "
377 : "OGR_GEOMETRY_ACCEPT_UNCLOSED_RING configuration "
378 : "option to NO"
379 : : "");
380 : }
381 : }
382 :
383 624 : if (wkbFlatten(poNewRing->getGeometryType()) == wkbLineString)
384 : {
385 202 : if (poNewRing->getNumPoints() < 4)
386 : {
387 8 : return FALSE;
388 : }
389 :
390 194 : if (EQUAL(poNewRing->getGeometryName(), "LINEARRING"))
391 : {
392 0 : CPLError(CE_Failure, CPLE_AppDefined, "Linearring not allowed.");
393 0 : return FALSE;
394 : }
395 : }
396 :
397 616 : return TRUE;
398 : }
399 :
400 : /************************************************************************/
401 : /* addRingDirectly() */
402 : /************************************************************************/
403 :
404 : /**
405 : * \brief Add a ring to a polygon.
406 : *
407 : * If the polygon has no external ring (it is empty) this will be used as
408 : * the external ring, otherwise it is used as an internal ring. Ownership
409 : * of the passed ring is assumed by the OGRCurvePolygon, but otherwise this
410 : * method operates the same as OGRCurvePolygon::AddRing().
411 : *
412 : * This method has no SFCOM analog.
413 : *
414 : * @param poNewRing ring to be added to the polygon.
415 : * @return OGRERR_NONE in case of success
416 : */
417 :
418 109444 : OGRErr OGRCurvePolygon::addRingDirectly(OGRCurve *poNewRing)
419 : {
420 109444 : return addRingDirectlyInternal(poNewRing, TRUE);
421 : }
422 :
423 110353 : OGRErr OGRCurvePolygon::addRingDirectlyInternal(OGRCurve *poNewRing,
424 : int bNeedRealloc)
425 : {
426 110353 : if (!checkRing(poNewRing))
427 9 : return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
428 :
429 110343 : HomogenizeDimensionalityWith(poNewRing);
430 :
431 110343 : return oCC.addCurveDirectly(this, poNewRing, bNeedRealloc);
432 : }
433 :
434 : /************************************************************************/
435 : /* addRing() */
436 : /************************************************************************/
437 :
438 : /**
439 : * \brief Add a ring to a polygon.
440 : *
441 : * If the polygon has no external ring (it is empty) this will be used as
442 : * the external ring, otherwise it is used as an internal ring.
443 : *
444 : * This method has no SFCOM analog.
445 : *
446 : * @param poNewRing ring to be added to the polygon.
447 : * @return OGRERR_NONE in case of success
448 : */
449 873 : OGRErr OGRCurvePolygon::addRing(std::unique_ptr<OGRCurve> poNewRing)
450 : {
451 873 : OGRCurve *poNewRingPtr = poNewRing.release();
452 873 : OGRErr eErr = addRingDirectlyInternal(poNewRingPtr, TRUE);
453 873 : if (eErr != OGRERR_NONE)
454 0 : delete poNewRingPtr;
455 873 : return eErr;
456 : }
457 :
458 : /************************************************************************/
459 : /* WkbSize() */
460 : /* */
461 : /* Return the size of this object in well known binary */
462 : /* representation including the byte order, and type information. */
463 : /************************************************************************/
464 :
465 48 : size_t OGRCurvePolygon::WkbSize() const
466 :
467 : {
468 48 : return oCC.WkbSize();
469 : }
470 :
471 : /************************************************************************/
472 : /* addCurveDirectlyFromWkb() */
473 : /************************************************************************/
474 :
475 21 : OGRErr OGRCurvePolygon::addCurveDirectlyFromWkb(OGRGeometry *poSelf,
476 : OGRCurve *poCurve)
477 : {
478 21 : OGRCurvePolygon *poCP = poSelf->toCurvePolygon();
479 21 : return poCP->addRingDirectlyInternal(poCurve, FALSE);
480 : }
481 :
482 : /************************************************************************/
483 : /* importFromWkb() */
484 : /* */
485 : /* Initialize from serialized stream in well known binary */
486 : /* format. */
487 : /************************************************************************/
488 :
489 23 : OGRErr OGRCurvePolygon::importFromWkb(const unsigned char *pabyData,
490 : size_t nSize, OGRwkbVariant eWkbVariant,
491 : size_t &nBytesConsumedOut)
492 :
493 : {
494 23 : nBytesConsumedOut = 0;
495 : OGRwkbByteOrder eByteOrder;
496 23 : size_t nDataOffset = 0;
497 : // coverity[tainted_data]
498 23 : OGRErr eErr = oCC.importPreambleFromWkb(this, pabyData, nSize, nDataOffset,
499 : eByteOrder, 9, eWkbVariant);
500 23 : if (eErr != OGRERR_NONE)
501 0 : return eErr;
502 :
503 23 : eErr = oCC.importBodyFromWkb(this, pabyData + nDataOffset, nSize,
504 : true, // bAcceptCompoundCurve
505 : addCurveDirectlyFromWkb, eWkbVariant,
506 : nBytesConsumedOut);
507 23 : if (eErr == OGRERR_NONE)
508 23 : nBytesConsumedOut += nDataOffset;
509 23 : return eErr;
510 : }
511 :
512 : /************************************************************************/
513 : /* exportToWkb() */
514 : /* */
515 : /* Build a well known binary representation of this object. */
516 : /************************************************************************/
517 :
518 32 : OGRErr OGRCurvePolygon::exportToWkb(unsigned char *pabyData,
519 : const OGRwkbExportOptions *psOptions) const
520 : {
521 : OGRwkbExportOptions sOptions(psOptions ? *psOptions
522 32 : : OGRwkbExportOptions());
523 :
524 : // Does not make sense for new geometries, so patch it.
525 32 : if (sOptions.eWkbVariant == wkbVariantOldOgc)
526 14 : sOptions.eWkbVariant = wkbVariantIso;
527 64 : return oCC.exportToWkb(this, pabyData, &sOptions);
528 : }
529 :
530 : /************************************************************************/
531 : /* addCurveDirectlyFromWkt() */
532 : /************************************************************************/
533 :
534 341 : OGRErr OGRCurvePolygon::addCurveDirectlyFromWkt(OGRGeometry *poSelf,
535 : OGRCurve *poCurve)
536 : {
537 341 : OGRCurvePolygon *poCP = poSelf->toCurvePolygon();
538 341 : return poCP->addRingDirectly(poCurve);
539 : }
540 :
541 : /************************************************************************/
542 : /* importFromWkt() */
543 : /* */
544 : /* Instantiate from well known text format. */
545 : /************************************************************************/
546 :
547 319 : OGRErr OGRCurvePolygon::importFromWkt(const char **ppszInput)
548 :
549 : {
550 319 : return importCurveCollectionFromWkt(ppszInput,
551 : FALSE, // bAllowEmptyComponent
552 : TRUE, // bAllowLineString
553 : TRUE, // bAllowCurve
554 : TRUE, // bAllowCompoundCurve
555 319 : addCurveDirectlyFromWkt);
556 : }
557 :
558 : /************************************************************************/
559 : /* exportToWkt() */
560 : /************************************************************************/
561 :
562 112 : std::string OGRCurvePolygon::exportToWkt(const OGRWktOptions &opts,
563 : OGRErr *err) const
564 : {
565 112 : return oCC.exportToWkt(this, opts, err);
566 : }
567 :
568 : /************************************************************************/
569 : /* CurvePolyToPoly() */
570 : /************************************************************************/
571 :
572 : /**
573 : * \brief Return a polygon from a curve polygon.
574 : *
575 : * This method is the same as C function OGR_G_CurvePolyToPoly().
576 : *
577 : * The returned geometry is a new instance whose ownership belongs to
578 : * the caller.
579 : *
580 : * @param dfMaxAngleStepSizeDegrees the largest step in degrees along the
581 : * arc, zero to use the default setting.
582 : * @param papszOptions options as a null-terminated list of strings.
583 : * Unused for now. Must be set to NULL.
584 : *
585 : * @return a linestring
586 : *
587 : * @since OGR 2.0
588 : */
589 :
590 : OGRPolygon *
591 405 : OGRCurvePolygon::CurvePolyToPoly(double dfMaxAngleStepSizeDegrees,
592 : const char *const *papszOptions) const
593 : {
594 405 : OGRPolygon *poPoly = new OGRPolygon();
595 405 : poPoly->assignSpatialReference(getSpatialReference());
596 867 : for (int iRing = 0; iRing < oCC.nCurveCount; iRing++)
597 : {
598 924 : OGRLineString *poLS = oCC.papoCurves[iRing]->CurveToLine(
599 462 : dfMaxAngleStepSizeDegrees, papszOptions);
600 462 : OGRLinearRing *poRing = OGRCurve::CastToLinearRing(poLS);
601 462 : if (poRing == nullptr)
602 : {
603 0 : CPLError(CE_Failure, CPLE_IllegalArg,
604 : "OGRCurve::CastToLinearRing failed");
605 0 : break;
606 : }
607 462 : poPoly->addRingDirectly(poRing);
608 : }
609 405 : return poPoly;
610 : }
611 :
612 : /************************************************************************/
613 : /* hasCurveGeometry() */
614 : /************************************************************************/
615 :
616 593 : OGRBoolean OGRCurvePolygon::hasCurveGeometry(int bLookForNonLinear) const
617 : {
618 593 : if (bLookForNonLinear)
619 : {
620 57 : return oCC.hasCurveGeometry(bLookForNonLinear);
621 : }
622 :
623 536 : return TRUE;
624 : }
625 :
626 : /************************************************************************/
627 : /* getLinearGeometry() */
628 : /************************************************************************/
629 :
630 : OGRGeometry *
631 376 : OGRCurvePolygon::getLinearGeometry(double dfMaxAngleStepSizeDegrees,
632 : const char *const *papszOptions) const
633 : {
634 376 : return CurvePolyToPoly(dfMaxAngleStepSizeDegrees, papszOptions);
635 : }
636 :
637 : /************************************************************************/
638 : /* getEnvelope() */
639 : /************************************************************************/
640 :
641 187171 : void OGRCurvePolygon::getEnvelope(OGREnvelope *psEnvelope) const
642 :
643 : {
644 187171 : oCC.getEnvelope(psEnvelope);
645 187171 : }
646 :
647 : /************************************************************************/
648 : /* getEnvelope() */
649 : /************************************************************************/
650 :
651 7876 : void OGRCurvePolygon::getEnvelope(OGREnvelope3D *psEnvelope) const
652 :
653 : {
654 7876 : oCC.getEnvelope(psEnvelope);
655 7876 : }
656 :
657 : /************************************************************************/
658 : /* Equals() */
659 : /************************************************************************/
660 :
661 41363 : OGRBoolean OGRCurvePolygon::Equals(const OGRGeometry *poOther) const
662 :
663 : {
664 41363 : if (poOther == this)
665 1 : return TRUE;
666 :
667 41362 : if (poOther->getGeometryType() != getGeometryType())
668 1 : return FALSE;
669 :
670 41361 : if (IsEmpty() && poOther->IsEmpty())
671 6 : return TRUE;
672 :
673 41355 : return oCC.Equals(&(poOther->toCurvePolygon()->oCC));
674 : }
675 :
676 : /************************************************************************/
677 : /* transform() */
678 : /************************************************************************/
679 :
680 504 : OGRErr OGRCurvePolygon::transform(OGRCoordinateTransformation *poCT)
681 :
682 : {
683 504 : return oCC.transform(this, poCT);
684 : }
685 :
686 : /************************************************************************/
687 : /* get_Area() */
688 : /************************************************************************/
689 :
690 3726 : double OGRCurvePolygon::get_Area() const
691 :
692 : {
693 3726 : if (getExteriorRingCurve() == nullptr)
694 2 : return 0.0;
695 :
696 3724 : double dfArea = getExteriorRingCurve()->get_Area();
697 :
698 3736 : for (int iRing = 0; iRing < getNumInteriorRings(); iRing++)
699 : {
700 12 : dfArea -= getInteriorRingCurve(iRing)->get_Area();
701 : }
702 :
703 3724 : return dfArea;
704 : }
705 :
706 : /************************************************************************/
707 : /* get_GeodesicArea() */
708 : /************************************************************************/
709 :
710 17 : double OGRCurvePolygon::get_GeodesicArea(
711 : const OGRSpatialReference *poSRSOverride) const
712 :
713 : {
714 17 : if (getExteriorRingCurve() == nullptr)
715 1 : return 0.0;
716 :
717 16 : if (!poSRSOverride)
718 13 : poSRSOverride = getSpatialReference();
719 :
720 16 : double dfArea = getExteriorRingCurve()->get_GeodesicArea(poSRSOverride);
721 16 : if (dfArea > 0)
722 : {
723 15 : for (int iRing = 0; iRing < getNumInteriorRings(); iRing++)
724 : {
725 1 : dfArea -=
726 1 : getInteriorRingCurve(iRing)->get_GeodesicArea(poSRSOverride);
727 : }
728 : }
729 :
730 16 : return dfArea;
731 : }
732 :
733 : /************************************************************************/
734 : /* setCoordinateDimension() */
735 : /************************************************************************/
736 :
737 59252 : void OGRCurvePolygon::setCoordinateDimension(int nNewDimension)
738 :
739 : {
740 59252 : oCC.setCoordinateDimension(this, nNewDimension);
741 59252 : }
742 :
743 76783 : void OGRCurvePolygon::set3D(OGRBoolean bIs3D)
744 : {
745 76783 : oCC.set3D(this, bIs3D);
746 76783 : }
747 :
748 123963 : void OGRCurvePolygon::setMeasured(OGRBoolean bIsMeasured)
749 : {
750 123963 : oCC.setMeasured(this, bIsMeasured);
751 123962 : }
752 :
753 : /************************************************************************/
754 : /* assignSpatialReference() */
755 : /************************************************************************/
756 :
757 148923 : void OGRCurvePolygon::assignSpatialReference(const OGRSpatialReference *poSR)
758 : {
759 148923 : oCC.assignSpatialReference(this, poSR);
760 148923 : }
761 :
762 : /************************************************************************/
763 : /* IsEmpty() */
764 : /************************************************************************/
765 :
766 110031 : OGRBoolean OGRCurvePolygon::IsEmpty() const
767 : {
768 110031 : return oCC.IsEmpty();
769 : }
770 :
771 : /************************************************************************/
772 : /* segmentize() */
773 : /************************************************************************/
774 :
775 36 : void OGRCurvePolygon::segmentize(double dfMaxLength)
776 : {
777 36 : if (EQUAL(getGeometryName(), "TRIANGLE"))
778 : {
779 0 : CPLError(CE_Failure, CPLE_NotSupported,
780 : "segmentize() is not valid for Triangle");
781 0 : return;
782 : }
783 36 : oCC.segmentize(dfMaxLength);
784 : }
785 :
786 : /************************************************************************/
787 : /* swapXY() */
788 : /************************************************************************/
789 :
790 74 : void OGRCurvePolygon::swapXY()
791 : {
792 74 : oCC.swapXY();
793 74 : }
794 :
795 : /************************************************************************/
796 : /* ContainsPoint() */
797 : /************************************************************************/
798 :
799 15 : OGRBoolean OGRCurvePolygon::ContainsPoint(const OGRPoint *p) const
800 : {
801 15 : if (getExteriorRingCurve() != nullptr && getNumInteriorRings() == 0)
802 : {
803 15 : const int nRet = getExteriorRingCurve()->ContainsPoint(p);
804 15 : if (nRet >= 0)
805 5 : return nRet;
806 : }
807 :
808 10 : return OGRGeometry::Contains(p);
809 : }
810 :
811 : /************************************************************************/
812 : /* IntersectsPoint() */
813 : /************************************************************************/
814 :
815 3 : OGRBoolean OGRCurvePolygon::IntersectsPoint(const OGRPoint *p) const
816 : {
817 3 : if (getExteriorRingCurve() != nullptr && getNumInteriorRings() == 0)
818 : {
819 3 : const int nRet = getExteriorRingCurve()->IntersectsPoint(p);
820 3 : if (nRet >= 0)
821 2 : return nRet;
822 : }
823 :
824 1 : return OGRGeometry::Intersects(p);
825 : }
826 :
827 : /************************************************************************/
828 : /* Contains() */
829 : /************************************************************************/
830 :
831 29 : OGRBoolean OGRCurvePolygon::Contains(const OGRGeometry *poOtherGeom) const
832 :
833 : {
834 58 : if (!IsEmpty() && poOtherGeom != nullptr &&
835 29 : wkbFlatten(poOtherGeom->getGeometryType()) == wkbPoint)
836 : {
837 15 : return ContainsPoint(poOtherGeom->toPoint());
838 : }
839 :
840 14 : return OGRGeometry::Contains(poOtherGeom);
841 : }
842 :
843 : /************************************************************************/
844 : /* Intersects() */
845 : /************************************************************************/
846 :
847 10 : OGRBoolean OGRCurvePolygon::Intersects(const OGRGeometry *poOtherGeom) const
848 :
849 : {
850 20 : if (!IsEmpty() && poOtherGeom != nullptr &&
851 10 : wkbFlatten(poOtherGeom->getGeometryType()) == wkbPoint)
852 : {
853 3 : return IntersectsPoint(poOtherGeom->toPoint());
854 : }
855 :
856 7 : return OGRGeometry::Intersects(poOtherGeom);
857 : }
858 :
859 : /************************************************************************/
860 : /* CastToPolygon() */
861 : /************************************************************************/
862 :
863 : /**
864 : * \brief Convert to polygon.
865 : *
866 : * This method should only be called if the curve polygon actually only contains
867 : * instances of OGRLineString. This can be verified if hasCurveGeometry(TRUE)
868 : * returns FALSE. It is not intended to approximate curve polygons. For that
869 : * use getLinearGeometry().
870 : *
871 : * The passed in geometry is consumed and a new one returned (or NULL in case
872 : * of failure).
873 : *
874 : * @param poCP the input geometry - ownership is passed to the method.
875 : * @return new geometry.
876 : */
877 :
878 15 : OGRPolygon *OGRCurvePolygon::CastToPolygon(OGRCurvePolygon *poCP)
879 : {
880 29 : for (int i = 0; i < poCP->oCC.nCurveCount; i++)
881 : {
882 28 : poCP->oCC.papoCurves[i] =
883 14 : OGRCurve::CastToLinearRing(poCP->oCC.papoCurves[i]);
884 14 : if (poCP->oCC.papoCurves[i] == nullptr)
885 : {
886 0 : delete poCP;
887 0 : return nullptr;
888 : }
889 : }
890 15 : OGRPolygon *poPoly = new OGRPolygon();
891 15 : poPoly->setCoordinateDimension(poCP->getCoordinateDimension());
892 15 : poPoly->assignSpatialReference(poCP->getSpatialReference());
893 15 : poPoly->oCC.nCurveCount = poCP->oCC.nCurveCount;
894 15 : poPoly->oCC.papoCurves = poCP->oCC.papoCurves;
895 15 : poCP->oCC.nCurveCount = 0;
896 15 : poCP->oCC.papoCurves = nullptr;
897 15 : delete poCP;
898 15 : return poPoly;
899 : }
900 :
901 : //! @cond Doxygen_Suppress
902 : /************************************************************************/
903 : /* GetCasterToPolygon() */
904 : /************************************************************************/
905 :
906 15 : OGRPolygon *OGRCurvePolygon::CasterToPolygon(OGRSurface *poSurface)
907 : {
908 15 : OGRCurvePolygon *poCurvePoly = poSurface->toCurvePolygon();
909 15 : return OGRCurvePolygon::CastToPolygon(poCurvePoly);
910 : }
911 :
912 15 : OGRSurfaceCasterToPolygon OGRCurvePolygon::GetCasterToPolygon() const
913 : {
914 15 : return OGRCurvePolygon::CasterToPolygon;
915 : }
916 :
917 : /************************************************************************/
918 : /* GetCasterToCurvePolygon() */
919 : /************************************************************************/
920 :
921 0 : static OGRCurvePolygon *CasterToCurvePolygon(OGRSurface *poSurface)
922 : {
923 0 : return poSurface->toCurvePolygon();
924 : }
925 :
926 0 : OGRSurfaceCasterToCurvePolygon OGRCurvePolygon::GetCasterToCurvePolygon() const
927 : {
928 0 : return ::CasterToCurvePolygon;
929 : }
930 :
931 : //! @endcond
|