Unverified Commit 2e617f62 authored by Kelvin Rodriguez's avatar Kelvin Rodriguez Committed by GitHub
Browse files

added polytools syntax sugar for geos c-api (#3846)

parent 4e0ace32
Loading
Loading
Loading
Loading
+217 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <cmath>

#include <QDebug>

#include "geos/geom/BinaryOp.h"
#include "geos/geom/CoordinateArraySequence.h"
#include "geos/geom/CoordinateSequence.h"
@@ -2209,5 +2210,221 @@ namespace Isis {
      throw IException(IException::Unknown, msg, _FILEINFO_);
    }
  }

 
  /** 
   * A static method for handling geos errors. 
   * required for initing geos c-api and converts geos  
   * errors to ISIS exceptions
   *  
   * @param fmt
   *  
   * @throw IException::Programmer
   */  
  void PolygonTools::geosNotice(const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    char buffer[1024];
    vsprintf(buffer, fmt, ap);
    va_end(ap);
    throw IException(IException::Programmer, buffer, _FILEINFO_);
  }


  /** 
   * A static method for handling geos errors. 
   * required for initing geos c-api and converts geos  
   * errors to ISIS exceptions
   *
   * @param fmt
   *  
   * @throw IException::Programmer
   */  
  void PolygonTools::geosError(const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    char buffer[1024];
    vsprintf(buffer, fmt, ap);
    va_end(ap);
    throw IException(IException::Programmer, buffer, _FILEINFO_);
  }

  /** 
   * inits geos 
   *
   */
  void PolygonTools::geosInit() {
    initGEOS(geosNotice, geosError);
  }
  
  /** 
   * Get size of GEOS coordseq object 
   * 
   * @param seq pointer to GEOS coordseq object to get the size of  
   *
   */
  unsigned int PolygonTools::getCoordSeqSize(const GEOSCoordSequence* seq) {
    unsigned int size; 
    int code = GEOSCoordSeq_getSize(seq, &size);
    
    if (code == 0) {
      std::string msg = "Unable to get X value from GEOS Coord Sequence due to ";
      msg += "unknown exception";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }

    return size; 
  }

  /** 
   * Get the x value of some coord at some index for a geos coordinate sequence 
   * 
   * @param seq pointer to GEOS coordseq object to get the value of 
   * @param idx index of coordinate 
   *
   * @return double value of x coordinate 
   */
  double PolygonTools::getCoordSeqX(const GEOSCoordSequence* seq, unsigned int idx) {
    // c-api doesn't check sizes
    if (idx > getCoordSeqSize(seq)) {
       std::string msg = "Unable to get X value from GEOS Coord Sequence due to ";
      msg += "index being greater than sequence size";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }
    
    double x; 
    int code = GEOSCoordSeq_getX(seq, idx, &x);
    
    if (code == 0) {
      std::string msg = "Unable to get X value from GEOS Coord Sequence due to ";
      msg += "unknown exception";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }

    return x; 
  }

  /** 
   * Get the y value of some coord at some index for a geos coordinate sequence 
   * 
   * @param seq pointer to GEOS coordseq object to get the value of 
   * @param idx index of coordinate 
   *
   * @return double value of y coordinate 
   */
  double PolygonTools::getCoordSeqY(const GEOSCoordSequence* seq, unsigned int idx) {
    // c-api doesn't check sizes
    if (idx > getCoordSeqSize(seq)) {
       std::string msg = "Unable to get Y value from GEOS Coord Sequence due to ";
      msg += "index being greater than sequence size";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }

    double y;
    
    int code = GEOSCoordSeq_getY(seq, idx, &y);

    if (code == 0) {
      std::string msg = "Unable to get Y value from GEOS Coord Sequence due to ";
      msg += "unknown exception";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }
 
    return y;  
  }

  /** 
   * Get the xy value of some coord at some index for a geos coordinate sequence 
   * 
   * @param seq pointer to GEOS coordseq object to get the value of 
   * @param idx index of coordinate 
   *
   * @return QPoint point object containing coordinate values  
   */
  QPoint PolygonTools::getCoordSeqXY(const GEOSCoordSequence* seq, unsigned int idx) {
    double x = getCoordSeqX(seq, idx); 
    double y = getCoordSeqY(seq, idx);
    return QPoint(x,y);
  }

  /** 
   * Set the x value of some coord at some index for a geos coordinate sequence  
   * 
   * @param seq pointer to GEOS coordseq object to get the value of 
   * @param idx index of coordinate 
   * @param x value to set 
   */
  void PolygonTools::setCoordSeqX(GEOSCoordSequence* seq, unsigned int idx, double x) {
    // c-api doesn't check sizes
    if (idx > getCoordSeqSize(seq)) {
       std::string msg = "Unable to set X value from GEOS Coord Sequence due to ";
      msg += "index being greater than sequence size";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }

    int code = GEOSCoordSeq_setX(seq, idx, x);
    
    if (code == 0) {
      std::string msg = "Unable to set X value from GEOS Coord Sequence due to ";
      msg += "unknown exception";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    } 
  }

  /** 
   * Set the y value of some coord at some index for a geos coordinate sequence  
   * 
   * @param seq pointer to GEOS coordseq object to get the value of 
   * @param idx index of coordinate 
   * @param y value to set 
   */
  void PolygonTools::setCoordSeqY(GEOSCoordSequence* seq, unsigned int idx, double y) {
    // c-api doesn't check sizes
    if (idx > getCoordSeqSize(seq)) {
       std::string msg = "Unable to set Y value from GEOS Coord Sequence due to ";
      msg += "index being greater than sequence size";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }
    
    int code = GEOSCoordSeq_setY(seq, idx, y);
    
    if (code == 0) {
      std::string msg = "Unable to set Y value from GEOS Coord Sequence due to ";
      msg += "unknown exception";
      throw IException(IException::Programmer, msg, _FILEINFO_);
    }
  }

  /** 
   * Set the xy value of some coord at some index for a geos coordinate sequence  
   * 
   * @param seq pointer to GEOS coordseq object to get the value of 
   * @param idx index of coordinate 
   * @param x x-value to set
   * @param y y-value to set
   */
  void PolygonTools::setCoordSeqXY(GEOSCoordSequence* seq, unsigned int idx, double x, double y) {
    setCoordSeqX(seq, idx, x);  
    setCoordSeqY(seq, idx, y);
  }

  /** 
   * syntax sugar to covert a Vector of points to a GEOS coordinate sequence. 
   *
   * @param vec QVector of QPoints to convert to GEOS coordinate sequence 
   *
   * @return GEOSCoordSequence* pointer to GEOS coord sequence 
   */
  GEOSCoordSequence *PolygonTools::coordSequenceFromVector(QVector<QPoint> vec) {
    GEOSCoordSequence *seq = GEOSCoordSeq_create(vec.size(), 2);
    
    for(int i = 0; i < vec.size(); i++) {
      setCoordSeqXY(seq, i, vec[i].x(), vec[i].y()); 
    }

    return seq; 
  }
    

} // end namespace isis
+18 −0
Original line number Diff line number Diff line
@@ -26,7 +26,13 @@
#include <geos/geom/MultiPolygon.h>
#include <geos/geom/CoordinateSequence.h>

// geos library
#include <geos_c.h>

#include <QString>
#include <QVector>
#include <QPoint>


namespace Isis {

@@ -151,6 +157,7 @@ namespace Isis {
      // Return a deep copy of a multpolygon
      static geos::geom::MultiPolygon *CopyMultiPolygon(const geos::geom::MultiPolygon *mpolygon);
      static geos::geom::MultiPolygon *CopyMultiPolygon(const geos::geom::MultiPolygon &mpolygon);
      static GEOSGeometry *CopyMultiPolygon(const GEOSGeometry &mpolygon);

      static geos::geom::MultiPolygon *Despike(const geos::geom::Geometry *geom);
      static geos::geom::MultiPolygon *Despike(const geos::geom::MultiPolygon *multiPoly);
@@ -207,6 +214,17 @@ namespace Isis {
                                                      UniversalGroundMap *ugm);
      static geos::geom::MultiPolygon *SplitPolygonOn360(const geos::geom::Polygon *inPoly);

      static void geosNotice(const char* fmt, ...);
      static void geosError(const char*fmt, ...); 
      static void geosInit(); 
      static unsigned int getCoordSeqSize(const GEOSCoordSequence* seq);
      static double getCoordSeqX(const GEOSCoordSequence* seq, unsigned int idx);
      static double getCoordSeqY(const GEOSCoordSequence* seq, unsigned int idx);
      static QPoint getCoordSeqXY(const GEOSCoordSequence* seq, unsigned int idx); 
      static void setCoordSeqX(GEOSCoordSequence *seq, unsigned int idx, double x); 
      static void setCoordSeqY(GEOSCoordSequence *seq, unsigned int idx, double y); 
      static void setCoordSeqXY(GEOSCoordSequence *seq, unsigned int idx, double x, double y);
      static GEOSCoordSequence *coordSequenceFromVector(QVector<QPoint> vec);

    private:
      //! Returns true if the middle point is spiked
+34 −0
Original line number Diff line number Diff line
@@ -25,6 +25,40 @@ int main() {
  try {
    cout << "Unit test for PolygonTools" << endl << endl;

    // test Geos C-API functions 
    PolygonTools::geosInit(); 
    QVector<QPoint> pointVector(5);
    pointVector[0] = QPoint(0,0);
    pointVector[1] = QPoint(0,1);
    pointVector[2] = QPoint(1,1);
    pointVector[3] = QPoint(1,0);
    pointVector[4] = QPoint(0,0);
    
    GEOSCoordSequence *cseq = PolygonTools::coordSequenceFromVector(pointVector); 
    QPoint qp = PolygonTools::getCoordSeqXY(cseq, 0); 
    std::cout << "point 0: " << qp.x() << ", " << qp.y() << std::endl;
    qp = PolygonTools::getCoordSeqXY(cseq, 1);
    std::cout << "point 1: " << qp.x() << ", " << qp.y() << std::endl;
    qp = PolygonTools::getCoordSeqXY(cseq, 2);
    std::cout << "point 2: " << qp.x() << ", " << qp.y() << std::endl;
    qp = PolygonTools::getCoordSeqXY(cseq, 3);
    std::cout << "point 3: " << qp.x() << ", " << qp.y() << std::endl;
    qp = PolygonTools::getCoordSeqXY(cseq, 4);
    std::cout << "point 4: " << qp.x() << ", " << qp.y() << std::endl << std::endl;

    // force error 
    try {
      qp = PolygonTools::getCoordSeqXY(cseq, 6);
    } catch (IException &e) {
      std::cout << e.what() << std::endl << std::endl;
    }
    
    GEOSGeometry * cring = GEOSGeom_createLinearRing(cseq);
    std::cout << "As LinearRing WKT: " << GEOSGeomToWKT(cring) << std::endl;  
    GEOSGeometry * cpoly = GEOSGeom_createPolygon(cring, nullptr, 0);
    std::cout << "As Polygon WKT: " << GEOSGeomToWKT(cpoly) << std::endl;  
    

    // Create coordinate sequence for the first of two polygons
    geos::geom::CoordinateSequence *pts = new geos::geom::CoordinateArraySequence();
    pts->add(geos::geom::Coordinate(0.0, 0.0));