Isis 3 Programmer Reference
GisGeometry.cpp
Go to the documentation of this file.
1 
24 #include "GisGeometry.h"
25 
26 // Qt library
27 #include <QDebug>
28 #include <QScopedPointer>
29 #include <QString>
30 
31 // geos library
32 #include <geos_c.h>
33 
34 // other ISIS
35 #include "Cube.h"
36 #include "IException.h"
37 #include "GisBlob.h"
38 #include "GisTopology.h"
39 #include "SpecialPixel.h"
40 
41 //#define DISABLE_PREPARED_GEOMETRY 1
42 
43 using namespace std;
44 
45 namespace Isis {
46 
50  GisGeometry::GisGeometry() : m_type(None), m_geom(0), m_preparedGeom(0) {
51  // Must ensure GEOS is initialized
53  }
54 
55 
67  GisGeometry::GisGeometry(const double xlongitude, const double ylatitude) :
68  m_type(GeosGis), m_geom(0), m_preparedGeom(0){
69 
71  m_geom = makePoint(xlongitude, ylatitude);
73  return;
74  }
75 
76 
85  GisGeometry::GisGeometry(Cube &cube) : m_type(IsisCube), m_geom(0), m_preparedGeom(0) {
86 
88  m_geom = fromCube(cube);
90  return;
91  }
92 
93 
102  GisGeometry::GisGeometry(const QString &gisSource, const GisGeometry::Type t) :
103  m_type(t), m_geom(0), m_preparedGeom(0) {
105  if (WKT == t) {
106  m_geom = gis->geomFromWKT(gisSource);
107  }
108  else if (WKB == t) {
109  m_geom = gis->geomFromWKB(gisSource);
110  }
111  else if (IsisCube == t) {
112  Cube cube;
113  cube.open(gisSource);
114  m_geom = fromCube(cube);
115  }
116  else {
118  QString("Unknown GIS type given [%1]").arg(typeToString(t)),
119  _FILEINFO_);
120  }
121 
122  // Get the prepared geometry
124  m_type = t;
125  return;
126  }
127 
128 
137  GisGeometry::GisGeometry(const GisGeometry &geom) : m_type(geom.m_type),
138  m_geom(0),
139  m_preparedGeom(0) {
140 
142  if ( geom.isDefined() ) {
143  m_geom = gis->clone(geom.m_geom);
145  }
146  }
147 
148 
157  GisGeometry::GisGeometry(GEOSGeometry *geom) : m_type(GeosGis), m_geom(geom),
158  m_preparedGeom(0) {
161  return;
162  }
163 
164 
169  destroy();
170  }
171 
172 
182  if ( this != &geom ) {
183  destroy();
184  m_type = geom.m_type;
185  if ( geom.isDefined() ) {
187  m_geom = gis->clone(geom.m_geom);
189  }
190  }
191  return (*this);
192  }
193 
194 
204  void GisGeometry::setGeometry(GEOSGeometry *geom) {
205  destroy();
206  m_geom = geom;
208  return;
209  }
210 
211 
217  bool GisGeometry::isDefined() const {
218  return (m_geom != 0);
219  }
220 
221 
230  bool GisGeometry::isValid() const {
231  if (!isDefined()) {
232  return (false);
233  }
234 
235  return (1 == GEOSisValid(this->m_geom));
236  }
237 
238 
244  QString GisGeometry::isValidReason() const {
245  QString result = "Not defined!";
246  if ( isDefined() ) {
248  char *reason = GEOSisValidReason(this->m_geom);
249  result = reason;
250  gis->destroy(reason);
251  }
252  return (result);
253  }
254 
255 
262  return (m_type);
263  }
264 
265 
273  GisGeometry::Type GisGeometry::type(const QString &gstrType) {
274  QString gtype = gstrType.toLower();
275  if ("wkt" == gtype) return (WKT);
276  if ("wkb" == gtype) return (WKB);
277  if ("cube" == gtype) return (IsisCube);
278  if ("isiscube" == gtype) return (IsisCube);
279  if ("geometry" == gtype) return (GeosGis);
280  if ("geosgis" == gtype) return (GeosGis);
281  if ("gis" == gtype) return (GeosGis);
282  if ("geos" == gtype) return (GeosGis);
283  return (None);
284  }
285 
286 
295  if (WKT == type) return "WKT";
296  if (WKB == type) return "WKB";
297  if (IsisCube == type) return "IsisCube";
298  if (GeosGis == type) return "GeosGis";
299  return "None";
300  }
301 
302 
308  const GEOSGeometry *GisGeometry::geometry() const {
309  return (m_geom);
310  }
311 
312 
322  const GEOSPreparedGeometry *GisGeometry::preparedGeometry() const {
323  return (m_preparedGeom);
324  }
325 
326 
336  if (!isDefined()) {
337  return (new GisGeometry());
338  }
339 
341  QScopedPointer<GisGeometry> geom(new GisGeometry());
342 
343  geom->m_type = m_type;
344  geom->m_geom = gis->clone(m_geom);
345  geom->m_preparedGeom = makePrepared(geom->m_geom);
346  return (geom.take());
347  }
348 
349 
355  bool GisGeometry::isEmpty() const {
356  if ( !isValid() ) {
357  return (true);
358  }
359  return (1 == GEOSisEmpty(this->m_geom));
360  }
361 
362 
376  double GisGeometry::area( ) const {
377  if ( !isValid() ) {
378  return (0.0);
379  }
380 
381  int result = 0;
382  double gisArea = 0.0;
383  result = GEOSArea(this->m_geom, &gisArea);
384  if (1 != result) {
385  gisArea = 0.0;
386  }
387  return (gisArea);
388  }
389 
390 
399  double GisGeometry::length( ) const {
400  if ( !isValid() ) {
401  return (0.0);
402  }
403 
404  int result = 0;
405  double gisLength = 0.0;
406  result = GEOSLength(this->m_geom, &gisLength);
407  if (1 != result) {
408  gisLength = 0.0;
409  }
410  return (gisLength);
411  }
412 
413 
423  double GisGeometry::distance(const GisGeometry &target) const {
424  if ( !isValid() ) {
425  return (false);
426  }
427  if ( !target.isValid() ) {
428  return (false);
429  }
430 
431  int result = 0;
432  double dist = Null;
433  result = GEOSDistance(this->m_geom, target.geometry(), &dist);
434  if ( 1 != result ) {
435  dist = Null;
436  }
437  return (dist);
438  }
439 
440 
446  int GisGeometry::points() const {
447  if (!isValid() ) { return (0); }
448 
449  int ngeoms = GEOSGetNumGeometries(m_geom);
450  int npoints = 0;
451  for (int i = 0 ; i < ngeoms ; i++) {
452  npoints += GEOSGetNumCoordinates(GEOSGetGeometryN(m_geom, i));
453  }
454 
455  return ( npoints );
456  }
457 
458 
468  bool GisGeometry::intersects(const GisGeometry &target) const {
469  if ( !isValid() ) {
470  return (false);
471  }
472  if ( !target.isValid() ) {
473  return (false);
474  }
475 
476  int result = 0;
477  if ( 0 != this->m_preparedGeom) {
478  result = GEOSPreparedIntersects(this->m_preparedGeom, target.geometry());
479  }
480  else {
481  result = GEOSIntersects(this->m_geom, target.geometry());
482  }
483 
484  return (1 == result);
485  }
486 
487 
495  bool GisGeometry::contains(const GisGeometry &target) const {
496  if ( !isValid() ) {
497  return (false);
498  }
499  if ( !target.isValid() ) {
500  return (false);
501  }
502 
503  int result = 0;
504  if ( 0 != this->m_preparedGeom) {
505  result = GEOSPreparedContains(this->m_preparedGeom, target.geometry());
506  }
507  else {
508  result = GEOSContains(this->m_geom, target.geometry());
509  }
510 
511  return (1 == result);
512  }
513 
514 
521  bool GisGeometry::disjoint(const GisGeometry &target) const {
522  if ( !isValid() ) {
523  return (false);
524  }
525  if ( !target.isValid() ) {
526  return (false);
527  }
528 
529  int result = 0;
530  if ( 0 != m_preparedGeom) {
531  result = GEOSPreparedDisjoint(m_preparedGeom, target.geometry());
532  }
533  else {
534  result = GEOSDisjoint(m_geom, target.geometry());
535  }
536 
537  return (1 == result);
538  }
539 
540 
548  bool GisGeometry::overlaps(const GisGeometry &target) const {
549  if ( !isValid() ) {
550  return (false);
551  }
552  if ( !target.isValid() ) {
553  return (false);
554  }
555 
556  int result = 0;
557  if ( 0 != m_preparedGeom) {
558  result = GEOSPreparedOverlaps(m_preparedGeom, target.geometry());
559  }
560  else {
561  result = GEOSOverlaps(m_geom, target.geometry());
562  }
563 
564  return (1 == result);
565  }
566 
567 
574  bool GisGeometry::equals(const GisGeometry &target) const {
575  if ( !isValid() ) {
576  return (false);
577  }
578 
579  if ( !target.isValid() ) {
580  return (false);
581  }
582 
583  int result = GEOSEquals(this->m_geom, target.geometry());
584  return ( 1 == result );
585  }
586 
587 
599  double GisGeometry::intersectRatio(const GisGeometry &target) const {
600  if ( !isValid() ) {
601  return (0.0);
602  }
603  if ( !target.isValid() ) {
604  return (0.0);
605  }
606 
607  // Check for any intersection at all
608  // if ( !intersects(target) ) {
609  // return (0.0);
610  // }
611 
612  // Prevent dividing by 0
613  if (this->area() == 0) {
614  return (0.0);
615  }
616 
617  QScopedPointer<GisGeometry> inCommon(intersection(target));
618  double ratio = inCommon->area() / this->area();
619  return (ratio);
620  }
621 
622 
637  if ( !isValid() ) {
638  return (new GisGeometry());
639  }
640 
641  GEOSGeometry *geom = GEOSEnvelope(m_geom);
642  return (new GisGeometry(geom));
643  }
644 
645 
654  if ( !isValid() ) {
655  return (new GisGeometry());
656  }
657 
658  GEOSGeometry *geom = GEOSConvexHull(m_geom);
659  return (new GisGeometry(geom));
660  }
661 
662 
676  GisGeometry *GisGeometry::simplify(const double &tolerance) const {
677  if ( !isValid() ) {
678  return (0);
679  }
680  GEOSGeometry *geom = GEOSTopologyPreserveSimplify(m_geom, tolerance);
681  if ( 0 == geom ) {
682  return (0);
683  }
684 
685  return (new GisGeometry(geom));
686  }
687 
688 
699  // Non-valid geometries return empty geometries
700  if ( !isValid() ) {
701  return (new GisGeometry());
702  }
703  if ( !target.isValid() ) {
704  return (new GisGeometry());
705  }
706 
707  GEOSGeometry *geom = GEOSIntersection(m_geom, target.geometry());
708  return (new GisGeometry(geom));
709  }
710 
711 
719  if ( !isValid() ) {
720  return (new GisGeometry());
721  }
722  if ( !target.isValid() ) {
723  return (new GisGeometry());
724  }
725 
726  GEOSGeometry *geom = GEOSUnion(m_geom, target.geometry());
727  return (new GisGeometry(geom));
728  }
729 
730 
740  bool GisGeometry::centroid(double &xlongitude, double &ylatitude) const {
741  xlongitude = ylatitude = Null;
742  if ( !isValid() ) {
743  return (false);
744  }
745 
746  GEOSGeometry *center = GEOSGetCentroid(m_geom);
747  if ( 0 != center ) {
748  GEOSGeomGetX(center, &xlongitude);
749  GEOSGeomGetY(center, &ylatitude);
750  GisTopology::instance()->destroy(center);
751  return (true);
752  }
753 
754  return (false);
755  }
756 
757 
764  if ( !isValid() ) {
765  return (new GisGeometry());
766  }
767 
768  GEOSGeometry *center = GEOSGetCentroid(m_geom);
769  return (new GisGeometry(center));
770  }
771 
772 
779  GEOSPreparedGeometry const *GisGeometry::makePrepared(const GEOSGeometry *geom)
780  const {
781  #if defined(DISABLE_PREPARED_GEOMETRY)
782  return (0);
783  #else
785  return (gis->preparedGeometry(geom));
786  #endif
787  }
788 
789 
796  GEOSGeometry *GisGeometry::makePoint(const double x, const double y) const {
797 
798  GEOSCoordSequence *point = GEOSCoordSeq_create(1, 2);
799  GEOSCoordSeq_setX(point, 0, x);
800  GEOSCoordSeq_setY(point, 0, y);
801 
802  return (GEOSGeom_createPoint(point));
803  }
804 
805 
812  GEOSGeometry *GisGeometry::fromCube(Cube &cube) const {
813  GisBlob myGis(cube);
815  return (gis->geomFromWKT(myGis.polygon()));
816  }
817 
818 
824  gis->destroy(m_geom);
825  gis->destroy(m_preparedGeom);
826  m_geom = 0;
827  m_preparedGeom = 0;
828  return;
829  }
830 
831 } //namespace Isis
GisGeometry * convexHull() const
Computes the convex hull of the geometry.
bool isDefined() const
Determines if the current geometry is valid.
GisGeometry * clone() const
Clones the contents of this geometry to a new instance.
GisGeometry * simplify(const double &tolerance) const
Simplify complex or overdetermined geoemtry.
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:110
bool equals(const GisGeometry &target) const
Test if target and this geometry are equal.
GEOSGeometry * geomFromWKB(const QString &wkb)
Reads in the geometry from the given well-known binary formatted string.
QString polygon() const
Accesses the well-known text string that defines the polygon.
Definition: GisBlob.cpp:66
GEOSPreparedGeometry const * m_preparedGeom
A prepared geometry from the GEOS library.
Definition: GisGeometry.h:137
bool contains(const GisGeometry &target) const
Test if the target geometry is contained within this geometry.
const GEOSPreparedGeometry * preparedGeometry() const
Returns special GEOS prepared geometry if it exists.
GEOSGeometry * makePoint(const double x, const double y) const
Create a point geometry.
No geometry. A geometry object cannot be created with this geometry type.
Definition: GisGeometry.h:74
GisGeometry * g_union(const GisGeometry &geom) const
Computes the union of two geometries.
The GEOS library WKB reader is used to create the geometry.
Definition: GisGeometry.h:76
GEOS GIS. A geometry object cannot be created with this geometry type.
Definition: GisGeometry.h:78
GEOSGeometry * geomFromWKT(const QString &wkt)
Reads in the geometry from the given well-known text formatted string.
double intersectRatio(const GisGeometry &geom) const
Computes intersect ratio between two geometries.
bool intersects(const GisGeometry &target) const
Computes a new geometry from the intersection of the two geomtries.
Namespace for the standard library.
GEOSGeometry * m_geom
Pointer to GEOS-C opaque structure.
Definition: GisGeometry.h:136
static QString typeToString(const Type &type)
Returns the type of the Geometry as a QString.
GEOSGeometry * fromCube(Cube &cube) const
Reads Polygon from ISIS Cube and returns geometry from contents.
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
bool disjoint(const GisGeometry &target) const
Tests for disjoint geometries.
An ISIS Cube is used to create the geometry.
Definition: GisGeometry.h:77
double length() const
Computes the length of a geometry.
virtual ~GisGeometry()
Destructor.
void destroy()
Destroys the GEOS elements of this geometry object
double distance(const GisGeometry &target) const
Computes the distance between two geometries.
bool isValid() const
Determines validity of the geometry contained in this object.
GisGeometry & operator=(GisGeometry const &geom)
Assignment operator for GISGeomtries.
Type
Source type of the geometry.
Definition: GisGeometry.h:73
GisGeometry * envelope() const
Computes the envelope or bounding box of this geometry.
bool overlaps(const GisGeometry &target) const
Test for overlapping geometries.
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
GisGeometry * centroid() const
Computes the centroid of the geometry and returns it as a new geometry.
double area() const
Computes the area of a geometry.
int points() const
Get number of points in geometry.
const GEOSPreparedGeometry * preparedGeometry(const GEOSGeometry *geom) const
Gets a GEOSPreparedGeometry from the given GEOSGeometry.
void open(const QString &cfile, QString access="r")
This method will open an isis cube for reading or reading/writing.
Definition: Cube.cpp:544
GisGeometry()
Fundamental constructor of an empty object.
Definition: GisGeometry.cpp:50
This class models GIS topology.
Definition: GisTopology.h:51
Type m_type
Geometry type of GIS source.
Definition: GisGeometry.h:135
QString isValidReason() const
Returns a string describing reason for invalid geometry.
GisGeometry * intersection(const GisGeometry &geom) const
Computes the intersection of two geometries.
Type type() const
Returns the type (origin) of the geometry.
Isis exception class.
Definition: IException.h:107
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
const GEOSGeometry * geometry() const
Returns the GEOSGeometry object to extend functionality.
bool isEmpty() const
Tests for a defined but empty geometry.
GEOSPreparedGeometry const * makePrepared(const GEOSGeometry *geom) const
Creates a prepared geometry of current geometry.
This class creates a polygon-type Isis Blob named "Footprint".
Definition: GisBlob.h:48
GEOSGeometry * clone(const GEOSGeometry *geom) const
Clones the given GEOSGeometry pointer.
void setGeometry(GEOSGeometry *geom)
Set the geometry directly taking ownership.
The GEOS library WKT reader is used to create the geometry.
Definition: GisGeometry.h:75
Encapsulation class provides support for GEOS-C API.
Definition: GisGeometry.h:67
void destroy(GEOSGeometry *geom) const
Destroys the given GEOS geometry.
static GisTopology * instance()
Gets the singleton instance of this class.
IO Handler for Isis Cubes.
Definition: Cube.h:170