Isis 3 Programmer Reference
GisGeometry.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "GisGeometry.h"
8
9// Qt library
10#include <QDebug>
11#include <QScopedPointer>
12#include <QString>
13
14// geos library
15#include <geos_c.h>
16
17// other ISIS
18#include "Cube.h"
19#include "IException.h"
20#include "ImagePolygon.h"
21#include "GisTopology.h"
22#include "SpecialPixel.h"
23
24//#define DISABLE_PREPARED_GEOMETRY 1
25
26using namespace std;
27
28namespace Isis {
29
33 GisGeometry::GisGeometry() : m_type(None), m_geom(0), m_preparedGeom(0) {
34 // Must ensure GEOS is initialized
36 }
37
38
50 GisGeometry::GisGeometry(const double xlongitude, const double ylatitude) :
51 m_type(GeosGis), m_geom(0), m_preparedGeom(0){
52
54 m_geom = makePoint(xlongitude, ylatitude);
56 return;
57 }
58
59
68 GisGeometry::GisGeometry(Cube &cube) : m_type(IsisCube), m_geom(0), m_preparedGeom(0) {
69
71 m_geom = fromCube(cube);
73 return;
74 }
75
76
85 GisGeometry::GisGeometry(const QString &gisSource, const GisGeometry::Type t) :
86 m_type(t), m_geom(0), m_preparedGeom(0) {
88 if (WKT == t) {
89 m_geom = gis->geomFromWKT(gisSource);
90 }
91 else if (WKB == t) {
92 m_geom = gis->geomFromWKB(gisSource);
93 }
94 else if (IsisCube == t) {
95 Cube cube;
96 cube.open(gisSource);
97 m_geom = fromCube(cube);
98 }
99 else {
101 QString("Unknown GIS type given [%1]").arg(typeToString(t)),
102 _FILEINFO_);
103 }
104
105 // Get the prepared geometry
107 m_type = t;
108 return;
109 }
110
111
120 GisGeometry::GisGeometry(const GisGeometry &geom) : m_type(geom.m_type),
121 m_geom(0),
122 m_preparedGeom(0) {
123
125 if ( geom.isDefined() ) {
126 m_geom = gis->clone(geom.m_geom);
128 }
129 }
130
131
140 GisGeometry::GisGeometry(GEOSGeometry *geom) : m_type(GeosGis), m_geom(geom),
141 m_preparedGeom(0) {
144 return;
145 }
146
147
154
155
165 if ( this != &geom ) {
166 destroy();
167 m_type = geom.m_type;
168 if ( geom.isDefined() ) {
170 m_geom = gis->clone(geom.m_geom);
172 }
173 }
174 return (*this);
175 }
176
177
187 void GisGeometry::setGeometry(GEOSGeometry *geom) {
188 destroy();
189 m_geom = geom;
191 return;
192 }
193
194
201 return (m_geom != 0);
202 }
203
204
213 bool GisGeometry::isValid() const {
214 if (!isDefined()) {
215 return (false);
216 }
217
218 return (1 == GEOSisValid(this->m_geom));
219 }
220
221
228 QString result = "Not defined!";
229 if ( isDefined() ) {
231 char *reason = GEOSisValidReason(this->m_geom);
232 result = reason;
233 gis->destroy(reason);
234 }
235 return (result);
236 }
237
238
245 return (m_type);
246 }
247
248
256 GisGeometry::Type GisGeometry::type(const QString &gstrType) {
257 QString gtype = gstrType.toLower();
258 if ("wkt" == gtype) return (WKT);
259 if ("wkb" == gtype) return (WKB);
260 if ("cube" == gtype) return (IsisCube);
261 if ("isiscube" == gtype) return (IsisCube);
262 if ("geometry" == gtype) return (GeosGis);
263 if ("geosgis" == gtype) return (GeosGis);
264 if ("gis" == gtype) return (GeosGis);
265 if ("geos" == gtype) return (GeosGis);
266 return (None);
267 }
268
269
278 if (WKT == type) return "WKT";
279 if (WKB == type) return "WKB";
280 if (IsisCube == type) return "IsisCube";
281 if (GeosGis == type) return "GeosGis";
282 return "None";
283 }
284
285
291 const GEOSGeometry *GisGeometry::geometry() const {
292 return (m_geom);
293 }
294
295
305 const GEOSPreparedGeometry *GisGeometry::preparedGeometry() const {
306 return (m_preparedGeom);
307 }
308
309
319 if (!isDefined()) {
320 return (new GisGeometry());
321 }
322
324 QScopedPointer<GisGeometry> geom(new GisGeometry());
325
326 geom->m_type = m_type;
327 geom->m_geom = gis->clone(m_geom);
328 geom->m_preparedGeom = makePrepared(geom->m_geom);
329 return (geom.take());
330 }
331
332
338 bool GisGeometry::isEmpty() const {
339 if ( !isValid() ) {
340 return (true);
341 }
342 return (1 == GEOSisEmpty(this->m_geom));
343 }
344
345
359 double GisGeometry::area( ) const {
360 if ( !isValid() ) {
361 return (0.0);
362 }
363
364 int result = 0;
365 double gisArea = 0.0;
366 result = GEOSArea(this->m_geom, &gisArea);
367 if (1 != result) {
368 gisArea = 0.0;
369 }
370 return (gisArea);
371 }
372
373
382 double GisGeometry::length( ) const {
383 if ( !isValid() ) {
384 return (0.0);
385 }
386
387 int result = 0;
388 double gisLength = 0.0;
389 result = GEOSLength(this->m_geom, &gisLength);
390 if (1 != result) {
391 gisLength = 0.0;
392 }
393 return (gisLength);
394 }
395
396
406 double GisGeometry::distance(const GisGeometry &target) const {
407 if ( !isValid() ) {
408 return (false);
409 }
410 if ( !target.isValid() ) {
411 return (false);
412 }
413
414 int result = 0;
415 double dist = Null;
416 result = GEOSDistance(this->m_geom, target.geometry(), &dist);
417 if ( 1 != result ) {
418 dist = Null;
419 }
420 return (dist);
421 }
422
423
430 if (!isValid() ) { return (0); }
431
432 int ngeoms = GEOSGetNumGeometries(m_geom);
433 int npoints = 0;
434 for (int i = 0 ; i < ngeoms ; i++) {
435 npoints += GEOSGetNumCoordinates(GEOSGetGeometryN(m_geom, i));
436 }
437
438 return ( npoints );
439 }
440
441
451 bool GisGeometry::intersects(const GisGeometry &target) const {
452 if ( !isValid() ) {
453 return (false);
454 }
455 if ( !target.isValid() ) {
456 return (false);
457 }
458
459 int result = 0;
460 if ( 0 != this->m_preparedGeom) {
461 result = GEOSPreparedIntersects(this->m_preparedGeom, target.geometry());
462 }
463 else {
464 result = GEOSIntersects(this->m_geom, target.geometry());
465 }
466
467 return (1 == result);
468 }
469
470
478 bool GisGeometry::contains(const GisGeometry &target) const {
479 if ( !isValid() ) {
480 return (false);
481 }
482 if ( !target.isValid() ) {
483 return (false);
484 }
485
486 int result = 0;
487 if ( 0 != this->m_preparedGeom) {
488 result = GEOSPreparedContains(this->m_preparedGeom, target.geometry());
489 }
490 else {
491 result = GEOSContains(this->m_geom, target.geometry());
492 }
493
494 return (1 == result);
495 }
496
497
504 bool GisGeometry::disjoint(const GisGeometry &target) const {
505 if ( !isValid() ) {
506 return (false);
507 }
508 if ( !target.isValid() ) {
509 return (false);
510 }
511
512 int result = 0;
513 if ( 0 != m_preparedGeom) {
514 result = GEOSPreparedDisjoint(m_preparedGeom, target.geometry());
515 }
516 else {
517 result = GEOSDisjoint(m_geom, target.geometry());
518 }
519
520 return (1 == result);
521 }
522
523
531 bool GisGeometry::overlaps(const GisGeometry &target) const {
532 if ( !isValid() ) {
533 return (false);
534 }
535 if ( !target.isValid() ) {
536 return (false);
537 }
538
539 int result = 0;
540 if ( 0 != m_preparedGeom) {
541 result = GEOSPreparedOverlaps(m_preparedGeom, target.geometry());
542 }
543 else {
544 result = GEOSOverlaps(m_geom, target.geometry());
545 }
546
547 return (1 == result);
548 }
549
550
557 bool GisGeometry::equals(const GisGeometry &target) const {
558 if ( !isValid() ) {
559 return (false);
560 }
561
562 if ( !target.isValid() ) {
563 return (false);
564 }
565
566 int result = GEOSEquals(this->m_geom, target.geometry());
567 return ( 1 == result );
568 }
569
570
582 double GisGeometry::intersectRatio(const GisGeometry &target) const {
583 if ( !isValid() ) {
584 return (0.0);
585 }
586 if ( !target.isValid() ) {
587 return (0.0);
588 }
589
590 // Check for any intersection at all
591 // if ( !intersects(target) ) {
592 // return (0.0);
593 // }
594
595 // Prevent dividing by 0
596 if (this->area() == 0) {
597 return (0.0);
598 }
599
600 QScopedPointer<GisGeometry> inCommon(intersection(target));
601 double ratio = inCommon->area() / this->area();
602 return (ratio);
603 }
604
605
620 if ( !isValid() ) {
621 return (new GisGeometry());
622 }
623
624 GEOSGeometry *geom = GEOSEnvelope(m_geom);
625 return (new GisGeometry(geom));
626 }
627
628
637 if ( !isValid() ) {
638 return (new GisGeometry());
639 }
640
641 GEOSGeometry *geom = GEOSConvexHull(m_geom);
642 return (new GisGeometry(geom));
643 }
644
645
659 GisGeometry *GisGeometry::simplify(const double &tolerance) const {
660 if ( !isValid() ) {
661 return (0);
662 }
663 GEOSGeometry *geom = GEOSTopologyPreserveSimplify(m_geom, tolerance);
664 if ( 0 == geom ) {
665 return (0);
666 }
667
668 return (new GisGeometry(geom));
669 }
670
671
682 // Non-valid geometries return empty geometries
683 if ( !isValid() ) {
684 return (new GisGeometry());
685 }
686 if ( !target.isValid() ) {
687 return (new GisGeometry());
688 }
689
690 GEOSGeometry *geom = GEOSIntersection(m_geom, target.geometry());
691 return (new GisGeometry(geom));
692 }
693
694
702 if ( !isValid() ) {
703 return (new GisGeometry());
704 }
705 if ( !target.isValid() ) {
706 return (new GisGeometry());
707 }
708
709 GEOSGeometry *geom = GEOSUnion(m_geom, target.geometry());
710 return (new GisGeometry(geom));
711 }
712
713
723 bool GisGeometry::centroid(double &xlongitude, double &ylatitude) const {
724 xlongitude = ylatitude = Null;
725 if ( !isValid() ) {
726 return (false);
727 }
728
729 GEOSGeometry *center = GEOSGetCentroid(m_geom);
730 if ( 0 != center ) {
731 GEOSGeomGetX(center, &xlongitude);
732 GEOSGeomGetY(center, &ylatitude);
733 GisTopology::instance()->destroy(center);
734 return (true);
735 }
736
737 return (false);
738 }
739
740
747 if ( !isValid() ) {
748 return (new GisGeometry());
749 }
750
751 GEOSGeometry *center = GEOSGetCentroid(m_geom);
752 return (new GisGeometry(center));
753 }
754
755
762 GEOSPreparedGeometry const *GisGeometry::makePrepared(const GEOSGeometry *geom)
763 const {
764 #if defined(DISABLE_PREPARED_GEOMETRY)
765 return (0);
766 #else
768 return (gis->preparedGeometry(geom));
769 #endif
770 }
771
772
779 GEOSGeometry *GisGeometry::makePoint(const double x, const double y) const {
780
781 GEOSCoordSequence *point = GEOSCoordSeq_create(1, 2);
782 GEOSCoordSeq_setX(point, 0, x);
783 GEOSCoordSeq_setY(point, 0, y);
784
785 return (GEOSGeom_createPoint(point));
786 }
787
788
795 GEOSGeometry *GisGeometry::fromCube(Cube &cube) const {
796 ImagePolygon myGis = cube.readFootprint();
798 QString polyStr = QString::fromStdString(myGis.polyStr());
799 return (gis->geomFromWKT(polyStr));
800 }
801
802
808 gis->destroy(m_geom);
809 gis->destroy(m_preparedGeom);
810 m_geom = 0;
811 m_preparedGeom = 0;
812 return;
813 }
814
815} //namespace Isis
IO Handler for Isis Cubes.
Definition Cube.h:168
ImagePolygon readFootprint() const
Read the footprint polygon for the Cube.
Definition Cube.cpp:872
void open(const QString &cfile, QString access="r")
This method will open an existing isis cube for reading or reading/writing.
Definition Cube.cpp:622
Encapsulation class provides support for GEOS-C API.
Definition GisGeometry.h:50
GEOSPreparedGeometry const * makePrepared(const GEOSGeometry *geom) const
Creates a prepared geometry of current geometry.
static QString typeToString(const Type &type)
Returns the type of the Geometry as a QString.
virtual ~GisGeometry()
Destructor.
double intersectRatio(const GisGeometry &geom) const
Computes intersect ratio between two geometries.
bool overlaps(const GisGeometry &target) const
Test for overlapping geometries.
GisGeometry * centroid() const
Computes the centroid of the geometry and returns it as a new geometry.
GEOSGeometry * fromCube(Cube &cube) const
Reads Polygon from ISIS Cube and returns geometry from contents.
bool contains(const GisGeometry &target) const
Test if the target geometry is contained within this geometry.
double area() const
Computes the area of a geometry.
Type type() const
Returns the type (origin) of the geometry.
bool equals(const GisGeometry &target) const
Test if target and this geometry are equal.
bool disjoint(const GisGeometry &target) const
Tests for disjoint geometries.
bool intersects(const GisGeometry &target) const
Computes a new geometry from the intersection of the two geomtries.
GisGeometry * convexHull() const
Computes the convex hull of the geometry.
void destroy()
Destroys the GEOS elements of this geometry object.
GisGeometry * g_union(const GisGeometry &geom) const
Computes the union of two geometries.
Type
Source type of the geometry.
Definition GisGeometry.h:56
@ IsisCube
An ISIS Cube is used to create the geometry.
Definition GisGeometry.h:60
@ GeosGis
GEOS GIS. A geometry object cannot be created with this geometry type.
Definition GisGeometry.h:61
@ None
No geometry. A geometry object cannot be created with this geometry type.
Definition GisGeometry.h:57
@ WKB
The GEOS library WKB reader is used to create the geometry.
Definition GisGeometry.h:59
@ WKT
The GEOS library WKT reader is used to create the geometry.
Definition GisGeometry.h:58
GisGeometry * clone() const
Clones the contents of this geometry to a new instance.
const GEOSGeometry * geometry() const
Returns the GEOSGeometry object to extend functionality.
GisGeometry & operator=(GisGeometry const &geom)
Assignment operator for GISGeomtries.
double distance(const GisGeometry &target) const
Computes the distance between two geometries.
double length() const
Computes the length of a geometry.
GEOSGeometry * m_geom
Pointer to GEOS-C opaque structure.
bool isValid() const
Determines validity of the geometry contained in this object.
const GEOSPreparedGeometry * preparedGeometry() const
Returns special GEOS prepared geometry if it exists.
void setGeometry(GEOSGeometry *geom)
Set the geometry directly taking ownership.
GisGeometry * envelope() const
Computes the envelope or bounding box of this geometry.
GEOSPreparedGeometry const * m_preparedGeom
A prepared geometry from the GEOS library.
int points() const
Get number of points in geometry.
GisGeometry * simplify(const double &tolerance) const
Simplify complex or overdetermined geoemtry.
bool isDefined() const
Determines if the current geometry is valid.
bool isEmpty() const
Tests for a defined but empty geometry.
Type m_type
Geometry type of GIS source.
GisGeometry * intersection(const GisGeometry &geom) const
Computes the intersection of two geometries.
QString isValidReason() const
Returns a string describing reason for invalid geometry.
GEOSGeometry * makePoint(const double x, const double y) const
Create a point geometry.
GisGeometry()
Fundamental constructor of an empty object.
This class models GIS topology.
Definition GisTopology.h:34
static GisTopology * instance()
Gets the singleton instance of this class.
Isis exception class.
Definition IException.h:91
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
Create cube polygons, read/write polygons to blobs.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
const double Null
Value for an Isis Null pixel.
Namespace for the standard library.