示例#1
0
VALUE rgeo_is_geos_line_string_closed(GEOSContextHandle_t context, const GEOSGeometry* geom)
{
  VALUE result;
  unsigned int n;
  double x1, x2, y1, y2, z1, z2;
  const GEOSCoordSequence* coord_seq;

  result = Qnil;
  n = GEOSGetNumCoordinates_r(context, geom);
  if (n > 0) {
    coord_seq = GEOSGeom_getCoordSeq_r(context, geom);
    if (GEOSCoordSeq_getX_r(context, coord_seq, 0, &x1)) {
      if (GEOSCoordSeq_getX_r(context, coord_seq, n-1, &x2)) {
        if (x1 == x2) {
          if (GEOSCoordSeq_getY_r(context, coord_seq, 0, &y1)) {
            if (GEOSCoordSeq_getY_r(context, coord_seq, n-1, &y2)) {
              result = y1 == y2 ? Qtrue : Qfalse;
            }
          }
        }
        else {
          result = Qfalse;
        }
      }
    }
  }
  return result;
}
示例#2
0
st_index_t rgeo_geos_coordseq_hash(GEOSContextHandle_t context, const GEOSGeometry* geom, st_index_t hash)
{
  const GEOSCoordSequence* cs;
  unsigned int len;
  unsigned int i;
  RGeo_Coordseq_Hash_Struct hash_struct;

  if (geom) {
    cs = GEOSGeom_getCoordSeq_r(context, geom);
    if (cs) {
      if (GEOSCoordSeq_getSize_r(context, cs, &len)) {
        for (i=0; i<len; ++i) {
          if (GEOSCoordSeq_getX_r(context, cs, i, &hash_struct.x)) {
            if (GEOSCoordSeq_getY_r(context, cs, i, &hash_struct.y)) {
              if (!GEOSCoordSeq_getY_r(context, cs, i, &hash_struct.z)) {
                hash_struct.z = 0;
              }
              hash_struct.seed_hash = hash;
              hash = rb_memhash(&hash_struct, sizeof(RGeo_Coordseq_Hash_Struct));
            }
          }
        }
      }
    }
  }
  return hash;
}
示例#3
0
static VALUE get_point_from_coordseq(VALUE self, const GEOSCoordSequence* coord_seq, unsigned int i, char has_z)
{
  VALUE result;
  RGeo_GeometryData* self_data;
  GEOSContextHandle_t self_context;
  double x, y, z;

  result = Qnil;
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
  self_context = self_data->geos_context;
  if (GEOSCoordSeq_getX_r(self_context, coord_seq, i, &x)) {
    if (GEOSCoordSeq_getY_r(self_context, coord_seq, i, &y)) {
      if (has_z) {
        if (!GEOSCoordSeq_getZ_r(self_context, coord_seq, i, &z)) {
          z = 0.0;
        }
      }
      else {
        z = 0.0;
      }
      result = rgeo_create_geos_point(self_data->factory, x, y, z);
    }
  }
  return result;
}
示例#4
0
文件: point.c 项目: WearyMonkey/rgeo
static VALUE method_point_x(VALUE self)
{
  VALUE result = Qnil;
  RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
  const GEOSGeometry* self_geom = self_data->geom;
  if (self_geom) {
    GEOSContextHandle_t self_context = self_data->geos_context;
    const GEOSCoordSequence* coord_seq = GEOSGeom_getCoordSeq_r(self_context, self_geom);
    if (coord_seq) {
      double val;
      if (GEOSCoordSeq_getX_r(self_context, coord_seq, 0, &val)) {
        result = rb_float_new(val);
      }
    }
  }
  return result;
}
示例#5
0
static void populate_geom_into_coord_seq(GEOSContextHandle_t context, const GEOSGeometry* geom, GEOSCoordSequence* coord_seq, unsigned int i, char has_z)
{
  const GEOSCoordSequence* cs = GEOSGeom_getCoordSeq_r(context, geom);
  double x = 0;
  if (cs) {
    GEOSCoordSeq_getX_r(context, cs, 0, &x);
  }
  GEOSCoordSeq_setX_r(context, coord_seq, i, x);
  x = 0;
  if (cs) {
    GEOSCoordSeq_getY_r(context, cs, 0, &x);
  }
  GEOSCoordSeq_setY_r(context, coord_seq, i, x);
  x = 0;
  if (has_z && cs) {
    GEOSCoordSeq_getZ_r(context, cs, 0, &x);
  }
  GEOSCoordSeq_setZ_r(context, coord_seq, i, x);
}
示例#6
0
VALUE rgeo_geos_coordseqs_eql(GEOSContextHandle_t context, const GEOSGeometry* geom1, const GEOSGeometry* geom2, char check_z)
{
  VALUE result;
  const GEOSCoordSequence* cs1;
  const GEOSCoordSequence* cs2;
  unsigned int len1;
  unsigned int len2;
  unsigned int i;
  double val1, val2;

  result = Qnil;
  if (geom1 && geom2) {
    cs1 = GEOSGeom_getCoordSeq_r(context, geom1);
    cs2 = GEOSGeom_getCoordSeq_r(context, geom2);
    if (cs1 && cs2) {
      len1 = 0;
      len2 = 0;
      if (GEOSCoordSeq_getSize_r(context, cs1, &len1) && GEOSCoordSeq_getSize_r(context, cs2, &len2)) {
        if (len1 == len2) {
          result = Qtrue;
          for (i=0; i<len1; ++i) {
            if (GEOSCoordSeq_getX_r(context, cs1, i, &val1) && GEOSCoordSeq_getX_r(context, cs2, i, &val2)) {
              if (val1 == val2) {
                if (GEOSCoordSeq_getY_r(context, cs1, i, &val1) && GEOSCoordSeq_getY_r(context, cs2, i, &val2)) {
                  if (val1 == val2) {
                    if (check_z) {
                      val1 = 0;
                      if (!GEOSCoordSeq_getZ_r(context, cs1, i, &val1)) {
                        result = Qnil;
                        break;
                      }
                      val2 = 0;
                      if (!GEOSCoordSeq_getZ_r(context, cs2, i, &val2)) {
                        result = Qnil;
                        break;
                      }
                      if (val1 != val2) {
                        result = Qfalse;
                        break;
                      }
                    }
                  }
                  else {  // Y coords are different
                    result = Qfalse;
                    break;
                  }
                }
                else {  // Failed to get Y coords
                  result = Qnil;
                  break;
                }
              }
              else {  // X coords are different
                result = Qfalse;
                break;
              }
            }
            else {  // Failed to get X coords
              result = Qnil;
              break;
            }
          }  // Iteration over coords
        }
        else {  // Lengths are different
          result = Qfalse;
        }
      }
    }
  }
  return result;
}
示例#7
0
void QgsGeometryValidator::run()
{
  mErrorCount = 0;
  QSettings settings;
  if ( settings.value( QStringLiteral( "/qgis/digitizing/validate_geometries" ), 1 ).toInt() == 2 )
  {
    char *r = nullptr;
    const GEOSGeometry *g0 = mG.asGeos();
    GEOSContextHandle_t handle = QgsGeometry::getGEOSHandler();
    if ( !g0 )
    {
      emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:could not produce geometry for GEOS (check log window)" ) ) );
    }
    else
    {
      GEOSGeometry *g1 = nullptr;
      if ( GEOSisValidDetail_r( handle, g0, GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE, &r, &g1 ) != 1 )
      {
        if ( g1 )
        {
          const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( handle, g1 );

          unsigned int n;
          if ( GEOSCoordSeq_getSize_r( handle, cs, &n ) && n == 1 )
          {
            double x, y;
            GEOSCoordSeq_getX_r( handle, cs, 0, &x );
            GEOSCoordSeq_getY_r( handle, cs, 0, &y );
            emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:%1" ).arg( r ), QgsPoint( x, y ) ) );
            mErrorCount++;
          }

          GEOSGeom_destroy_r( handle, g1 );
        }
        else
        {
          emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error:%1" ).arg( r ) ) );
          mErrorCount++;
        }

        GEOSFree_r( handle, r );
      }
    }

    return;
  }

  QgsDebugMsg( "validation thread started." );

  QgsWkbTypes::Type flatType = QgsWkbTypes::flatType( mG.wkbType() );
  //if ( flatType == QgsWkbTypes::Point || flatType == QgsWkbTypes::MultiPoint )
  //    break;
  if ( flatType == QgsWkbTypes::LineString )
  {
    validatePolyline( 0, mG.asPolyline() );
  }
  else if ( flatType == QgsWkbTypes::MultiLineString )
  {
    QgsMultiPolyline mp = mG.asMultiPolyline();
    for ( int i = 0; !mStop && i < mp.size(); i++ )
      validatePolyline( i, mp[i] );
  }
  else if ( flatType == QgsWkbTypes::Polygon )
  {
    validatePolygon( 0, mG.asPolygon() );
  }
  else if ( flatType == QgsWkbTypes::MultiPolygon )
  {
    QgsMultiPolygon mp = mG.asMultiPolygon();
    for ( int i = 0; !mStop && i < mp.size(); i++ )
    {
      validatePolygon( i, mp[i] );
    }

    for ( int i = 0; !mStop && i < mp.size(); i++ )
    {
      if ( mp[i].isEmpty() )
      {
        emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 has no rings" ).arg( i ) ) );
        mErrorCount++;
        continue;
      }

      for ( int j = i + 1;  !mStop && j < mp.size(); j++ )
      {
        if ( mp[j].isEmpty() )
          continue;

        if ( ringInRing( mp[i][0], mp[j][0] ) )
        {
          emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( i ).arg( j ) ) );
          mErrorCount++;
        }
        else if ( ringInRing( mp[j][0], mp[i][0] ) )
        {
          emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( j ).arg( i ) ) );
          mErrorCount++;
        }
        else
        {
          checkRingIntersections( i, 0, mp[i][0], j, 0, mp[j][0] );
        }
      }
    }
  }

  else if ( flatType == QgsWkbTypes::Unknown )
  {
    QgsDebugMsg( QObject::tr( "Unknown geometry type" ) );
    emit errorFound( QgsGeometry::Error( QObject::tr( "Unknown geometry type %1" ).arg( mG.wkbType() ) ) );
    mErrorCount++;
  }

  QgsDebugMsg( "validation finished." );

  if ( mStop )
  {
    emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry validation was aborted." ) ) );
  }
  else if ( mErrorCount > 0 )
  {
    emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry has %1 errors." ).arg( mErrorCount ) ) );
  }
#if 0
  else
  {
    emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry is valid." ) ) );
  }
#endif
}
示例#8
0
void Layer::chopFeaturesAtRepeatDistance()
{
    GEOSContextHandle_t geosctxt = geosContext();
    QLinkedList<FeaturePart*> * newFeatureParts = new QLinkedList<FeaturePart*>;
    while ( !featureParts->isEmpty() )
    {
        FeaturePart* fpart = featureParts->takeFirst();
        const GEOSGeometry* geom = fpart->geos();
        double chopInterval = fpart->getFeature()->repeatDistance();
        if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING )
        {

            double bmin[2], bmax[2];
            fpart->getBoundingBox( bmin, bmax );
            rtree->Remove( bmin, bmax, fpart );

            const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosctxt, geom );

            // get number of points
            unsigned int n;
            GEOSCoordSeq_getSize_r( geosctxt, cs, &n );

            // Read points
            std::vector<Point> points( n );
            for ( unsigned int i = 0; i < n; ++i )
            {
                GEOSCoordSeq_getX_r( geosctxt, cs, i, &points[i].x );
                GEOSCoordSeq_getY_r( geosctxt, cs, i, &points[i].y );
            }

            // Cumulative length vector
            std::vector<double> len( n, 0 );
            for ( unsigned int i = 1; i < n; ++i )
            {
                double dx = points[i].x - points[i - 1].x;
                double dy = points[i].y - points[i - 1].y;
                len[i] = len[i - 1] + std::sqrt( dx * dx + dy * dy );
            }

            // Walk along line
            unsigned int cur = 0;
            double lambda = 0;
            std::vector<Point> part;
            for ( ;; )
            {
                lambda += chopInterval;
                for ( ; cur < n && lambda > len[cur]; ++cur )
                {
                    part.push_back( points[cur] );
                }
                if ( cur >= n )
                {
                    break;
                }
                double c = ( lambda - len[cur - 1] ) / ( len[cur] - len[cur - 1] );
                Point p;
                p.x = points[cur - 1].x + c * ( points[cur].x - points[cur - 1].x );
                p.y = points[cur - 1].y + c * ( points[cur].y - points[cur - 1].y );
                part.push_back( p );
                GEOSCoordSequence* cooSeq = GEOSCoordSeq_create_r( geosctxt, part.size(), 2 );
                for ( std::size_t i = 0; i < part.size(); ++i )
                {
                    GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x );
                    GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y );
                }

                GEOSGeometry* newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
                FeaturePart* newfpart = new FeaturePart( fpart->getFeature(), newgeom );
                newFeatureParts->append( newfpart );
                newfpart->getBoundingBox( bmin, bmax );
                rtree->Insert( bmin, bmax, newfpart );
                part.clear();
                part.push_back( p );
            }
            // Create final part
            part.push_back( points[n - 1] );
            GEOSCoordSequence* cooSeq = GEOSCoordSeq_create_r( geosctxt, part.size(), 2 );
            for ( std::size_t i = 0; i < part.size(); ++i )
            {
                GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x );
                GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y );
            }

            GEOSGeometry* newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
            FeaturePart* newfpart = new FeaturePart( fpart->getFeature(), newgeom );
            newFeatureParts->append( newfpart );
            newfpart->getBoundingBox( bmin, bmax );
            rtree->Insert( bmin, bmax, newfpart );
        }
        else
        {
            newFeatureParts->append( fpart );
        }
    }

    delete featureParts;
    featureParts = newFeatureParts;
}
示例#9
0
文件: _trace.cpp 项目: Jeitan/cartopy
void _project_segment(GEOSContextHandle_t handle,
                      const GEOSCoordSequence *src_coords,
                      unsigned int src_idx_from, unsigned int src_idx_to,
                      Interpolator *interpolator,
                      const GEOSPreparedGeometry *gp_domain,
                      double threshold,
                      LineAccumulator &lines)
{
    Point p_current, p_min, p_max, p_end;
    double t_current, t_min, t_max;
    State state;

    GEOSCoordSeq_getX_r(handle, src_coords, src_idx_from, &p_current.x);
    GEOSCoordSeq_getY_r(handle, src_coords, src_idx_from, &p_current.y);
    GEOSCoordSeq_getX_r(handle, src_coords, src_idx_to, &p_end.x);
    GEOSCoordSeq_getY_r(handle, src_coords, src_idx_to, &p_end.y);
#ifdef DEBUG
    std::cerr << "Setting line:" << std::endl;
    std::cerr << "   " << p_current.x << ", " << p_current.y << std::endl;
    std::cerr << "   " << p_end.x << ", " << p_end.y << std::endl;
#endif
    interpolator->set_line(p_current, p_end);
    p_current = interpolator->project(p_current);
    p_end = interpolator->project(p_end);
#ifdef DEBUG
    std::cerr << "Projected as:" << std::endl;
    std::cerr << "   " << p_current.x << ", " << p_current.y << std::endl;
    std::cerr << "   " << p_end.x << ", " << p_end.y << std::endl;
#endif

    t_current = 0.0;
    state = get_state(p_current, gp_domain, handle);

    while(t_current < 1.0 && lines.size() < 500)
    {
        //std::cerr << "Bisecting" << std::endl;
#ifdef DEBUG
        std::cerr << "Working from: " << t_current << " (";
        if (state == POINT_IN)
            std::cerr << "IN";
        else if (state == POINT_OUT)
            std::cerr << "OUT";
        else
            std::cerr << "NAN";
        std::cerr << ")" << std::endl;
        std::cerr << "   " << p_current.x << ", " << p_current.y << std::endl;
        std::cerr << "   " << p_end.x << ", " << p_end.y << std::endl;
#endif
        bisect(t_current, p_current, p_end, handle, gp_domain, state,
               interpolator, threshold,
               t_min, p_min, t_max, p_max);
#ifdef DEBUG
        std::cerr << "   => " << t_min << " to " << t_max << std::endl;
        std::cerr << "   => (" << p_min.x << ", " << p_min.y << ") to (" << p_max.x << ", " << p_max.y << ")" << std::endl;
#endif
        if (state == POINT_IN)
        {
            lines.add_point_if_empty(p_current);
            if (t_min != t_current)
            {
                lines.add_point(p_min);
                t_current = t_min;
                p_current = p_min;
            }
            else
            {
                t_current = t_max;
                p_current = p_max;
                state = get_state(p_current, gp_domain, handle);
                if(state == POINT_IN)
                    lines.new_line();
            }
        }
        else if(state == POINT_OUT)
        {
            if (t_min != t_current)
            {
                t_current = t_min;
                p_current = p_min;
            }
            else
            {
                t_current = t_max;
                p_current = p_max;
                state = get_state(p_current, gp_domain, handle);
                if(state == POINT_IN)
                    lines.new_line();
            }
        }
        else
        {
            t_current = t_max;
            p_current = p_max;
            state = get_state(p_current, gp_domain, handle);
            if(state == POINT_IN)
                lines.new_line();
        }
    }
}
Q_NOWARN_UNREACHABLE_POP

// Return Nth vertex in GEOSGeometry as a POINT.
// May return NULL if the geometry has NO vertexex.
static GEOSGeometry *LWGEOM_GEOS_getPointN( const GEOSGeometry *g_in, uint32_t n )
{
  GEOSContextHandle_t handle = QgsGeos::getGEOSHandler();

  uint32_t dims;
  const GEOSCoordSequence *seq_in = nullptr;
  GEOSCoordSeq seq_out;
  double val;
  uint32_t sz;
  int gn;
  GEOSGeometry *ret = nullptr;

  switch ( GEOSGeomTypeId_r( handle, g_in ) )
  {
    case GEOS_MULTIPOINT:
    case GEOS_MULTILINESTRING:
    case GEOS_MULTIPOLYGON:
    case GEOS_GEOMETRYCOLLECTION:
    {
      for ( gn = 0; gn < GEOSGetNumGeometries_r( handle, g_in ); ++gn )
      {
        const GEOSGeometry *g = GEOSGetGeometryN_r( handle, g_in, gn );
        ret = LWGEOM_GEOS_getPointN( g, n );
        if ( ret ) return ret;
      }
      break;
    }

    case GEOS_POLYGON:
    {
      ret = LWGEOM_GEOS_getPointN( GEOSGetExteriorRing_r( handle, g_in ), n );
      if ( ret ) return ret;
      for ( gn = 0; gn < GEOSGetNumInteriorRings_r( handle, g_in ); ++gn )
      {
        const GEOSGeometry *g = GEOSGetInteriorRingN_r( handle, g_in, gn );
        ret = LWGEOM_GEOS_getPointN( g, n );
        if ( ret ) return ret;
      }
      break;
    }

    case GEOS_POINT:
    case GEOS_LINESTRING:
    case GEOS_LINEARRING:
      break;

  }

  seq_in = GEOSGeom_getCoordSeq_r( handle, g_in );
  if ( ! seq_in ) return nullptr;
  if ( ! GEOSCoordSeq_getSize_r( handle, seq_in, &sz ) ) return nullptr;
  if ( ! sz ) return nullptr;

  if ( ! GEOSCoordSeq_getDimensions_r( handle, seq_in, &dims ) ) return nullptr;

  seq_out = GEOSCoordSeq_create_r( handle, 1, dims );
  if ( ! seq_out ) return nullptr;

  if ( ! GEOSCoordSeq_getX_r( handle, seq_in, n, &val ) ) return nullptr;
  if ( ! GEOSCoordSeq_setX_r( handle, seq_out, n, val ) ) return nullptr;
  if ( ! GEOSCoordSeq_getY_r( handle, seq_in, n, &val ) ) return nullptr;
  if ( ! GEOSCoordSeq_setY_r( handle, seq_out, n, val ) ) return nullptr;
  if ( dims > 2 )
  {
    if ( ! GEOSCoordSeq_getZ_r( handle, seq_in, n, &val ) ) return nullptr;
    if ( ! GEOSCoordSeq_setZ_r( handle, seq_out, n, val ) ) return nullptr;
  }

  return GEOSGeom_createPoint_r( handle, seq_out );
}
示例#11
0
static GEOSCoordSequence* coord_seq_from_array(VALUE factory, VALUE array, char close)
{
  Check_Type(array, T_ARRAY);
  RGeo_FactoryData* factory_data = RGEO_FACTORY_DATA_PTR(factory);
  VALUE point_type = factory_data->globals->feature_point;
  unsigned int len = (unsigned int)RARRAY_LEN(array);
  char has_z = (char)(RGEO_FACTORY_DATA_PTR(factory)->flags & RGEO_FACTORYFLAGS_SUPPORTS_Z_OR_M);
  unsigned int dims = has_z ? 3 : 2;
  double* coords = ALLOC_N(double, len == 0 ? 1 : len * dims);
  if (!coords) {
    return NULL;
  }
  GEOSContextHandle_t context = factory_data->geos_context;
  unsigned int i;
  for (i=0; i<len; ++i) {
    char good = 0;
    const GEOSGeometry* entry_geom = rgeo_convert_to_geos_geometry(factory, rb_ary_entry(array, i), point_type);
    if (entry_geom) {
      const GEOSCoordSequence* entry_cs = GEOSGeom_getCoordSeq_r(context, entry_geom);
      if (entry_cs) {
        double x;
        if (GEOSCoordSeq_getX_r(context, entry_cs, 0, &x)) {
          coords[i*dims] = x;
          if (GEOSCoordSeq_getY_r(context, entry_cs, 0, &x)) {
            coords[i*dims+1] = x;
            good = 1;
            if (has_z) {
              if (GEOSCoordSeq_getZ_r(context, entry_cs, 0, &x)) {
                coords[i*dims+2] = x;
              }
              else {
                good = 0;
              }
            }
          }
        }
      }
    }
    if (!good) {
      free(coords);
      return NULL;
    }
  }
  if (len > 0 && close) {
    if (coords[0] == coords[(len-1)*dims] && coords[1] == coords[(len-1)*dims+1]) {
      close = 0;
    }
  }
  else {
    close = 0;
  }
  GEOSCoordSequence* coord_seq = GEOSCoordSeq_create_r(context, len + close, 3);
  if (coord_seq) {
    for (i=0; i<len; ++i) {
      GEOSCoordSeq_setX_r(context, coord_seq, i, coords[i*dims]);
      GEOSCoordSeq_setY_r(context, coord_seq, i, coords[i*dims+1]);
      GEOSCoordSeq_setZ_r(context, coord_seq, i, has_z ? coords[i*dims+2] : 0);
    }
    if (close) {
      GEOSCoordSeq_setX_r(context, coord_seq, len, coords[0]);
      GEOSCoordSeq_setY_r(context, coord_seq, len, coords[1]);
      GEOSCoordSeq_setZ_r(context, coord_seq, len, has_z ? coords[2] : 0);
    }
  }
  free(coords);
  return coord_seq;
}
示例#12
0
void coordseq_to_terms(GEOSCommand *command) {

	GEOSContextHandle_t handle = command->driver_data->handle;
	GEOSCoordSequence *coordSeq;
	unsigned int dims = 2;

	ERL_READ_PTR_GEOSCOORDSEQUENCE(command, coordSeq);
	//ERL_READ_INT(command, dims);
	
	unsigned int size;
	if(GEOSCoordSeq_getSize_r(handle, coordSeq, &size)==0) {
		erl_send_error(command, "invalidcs");
		return;
	}
	//if(GEOSCoordSeq_getDimensions_r(handle, coordSeq,&dims)==0) {
	//	erl_send_error(command, "invalidcs");
	//	return;
	//} always return 3
	
	int allocSize = 7 + (size * (dims * 2 + 2));
	//int allocSize = 6 + (dims*2 + 2) * size + 1;


	double *digits = driver_alloc(sizeof(double) * dims * size);

	memset(digits, 0, sizeof(double) * dims * size);

	ErlDrvTermData *terms = driver_alloc(sizeof(ErlDrvTermData) * (allocSize));

	terms[0] = ERL_DRV_ATOM;
	terms[1] = driver_mk_atom("ok");

	int pos = 2;
	int i,d = 0;

	for(i = 0; i < size; i++) {

		GEOSCoordSeq_getX_r(handle,coordSeq,i, &digits[d]);

		terms[pos++] = ERL_DRV_FLOAT;
		terms[pos++] = (ErlDrvTermData) &digits[d];
		d++;

		if(dims >= 2) {
			GEOSCoordSeq_getY_r(handle,coordSeq,i, &digits[d]);
			terms[pos++] = ERL_DRV_FLOAT;
			terms[pos++] = (ErlDrvTermData) &digits[d];
			d++;
		}
		if(dims >= 3) {
			GEOSCoordSeq_getZ_r(handle,coordSeq,i, &digits[d]);
			terms[pos++] = ERL_DRV_FLOAT;
			terms[pos++] = (ErlDrvTermData) &digits[d];
			d++;
		}
		terms[pos++] = ERL_DRV_TUPLE;
		terms[pos++] = dims;
	
	}

	terms[pos++] = ERL_DRV_NIL;
	terms[pos++] = ERL_DRV_LIST;
	terms[pos++] = size+1;

	terms[pos++] = ERL_DRV_TUPLE;
	terms[pos] = 2;

  	driver_output_term(command->driver_data->port, terms, pos+1);

	driver_free(digits);
	driver_free(terms);
}
示例#13
0
void QgsGeometryValidator::run()
{
  mErrorCount = 0;
  switch ( mMethod )
  {
    case QgsGeometry::ValidatorGeos:
    {
      char *r = nullptr;
      geos::unique_ptr g0( mGeometry.exportToGeos() );
      GEOSContextHandle_t handle = QgsGeometry::getGEOSHandler();
      if ( !g0 )
      {
        emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error: could not produce geometry for GEOS (check log window)" ) ) );
      }
      else
      {
        GEOSGeometry *g1 = nullptr;
        char res = GEOSisValidDetail_r( handle, g0.get(), GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE, &r, &g1 );
        if ( res != 1 )
        {
          if ( g1 )
          {
            const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( handle, g1 );

            unsigned int n;
            if ( GEOSCoordSeq_getSize_r( handle, cs, &n ) && n == 1 )
            {
              double x, y;
              GEOSCoordSeq_getX_r( handle, cs, 0, &x );
              GEOSCoordSeq_getY_r( handle, cs, 0, &y );
              emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error: %1" ).arg( r ), QgsPointXY( x, y ) ) );
              mErrorCount++;
            }

            GEOSGeom_destroy_r( handle, g1 );
          }
          else
          {
            emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error: %1" ).arg( r ) ) );
            mErrorCount++;
          }

          GEOSFree_r( handle, r );
        }
      }

      break;
    }

    case QgsGeometry::ValidatorQgisInternal:
    {
      QgsWkbTypes::Type flatType = QgsWkbTypes::flatType( mGeometry.wkbType() );
      //if ( flatType == QgsWkbTypes::Point || flatType == QgsWkbTypes::MultiPoint )
      //    break;
      if ( flatType == QgsWkbTypes::LineString )
      {
        validatePolyline( 0, mGeometry.asPolyline() );
      }
      else if ( flatType == QgsWkbTypes::MultiLineString )
      {
        QgsMultiPolylineXY mp = mGeometry.asMultiPolyline();
        for ( int i = 0; !mStop && i < mp.size(); i++ )
          validatePolyline( i, mp[i] );
      }
      else if ( flatType == QgsWkbTypes::Polygon )
      {
        validatePolygon( 0, mGeometry.asPolygon() );
      }
      else if ( flatType == QgsWkbTypes::MultiPolygon )
      {
        QgsMultiPolygonXY mp = mGeometry.asMultiPolygon();
        for ( int i = 0; !mStop && i < mp.size(); i++ )
        {
          validatePolygon( i, mp[i] );
        }

        for ( int i = 0; !mStop && i < mp.size(); i++ )
        {
          if ( mp[i].isEmpty() )
          {
            emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 has no rings" ).arg( i ) ) );
            mErrorCount++;
            continue;
          }

          for ( int j = i + 1;  !mStop && j < mp.size(); j++ )
          {
            if ( mp[j].isEmpty() )
              continue;

            if ( ringInRing( mp[i][0], mp[j][0] ) )
            {
              emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( i ).arg( j ) ) );
              mErrorCount++;
            }
            else if ( ringInRing( mp[j][0], mp[i][0] ) )
            {
              emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( j ).arg( i ) ) );
              mErrorCount++;
            }
            else
            {
              checkRingIntersections( i, 0, mp[i][0], j, 0, mp[j][0] );
            }
          }
        }
      }

      else if ( flatType == QgsWkbTypes::Unknown )
      {
        QgsDebugMsg( QObject::tr( "Unknown geometry type" ) );
        emit errorFound( QgsGeometry::Error( QObject::tr( "Unknown geometry type %1" ).arg( mGeometry.wkbType() ) ) );
        mErrorCount++;
      }

      if ( mStop )
      {
        emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry validation was aborted." ) ) );
      }
      else if ( mErrorCount > 0 )
      {
        emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry has %1 errors." ).arg( mErrorCount ) ) );
      }
#if 0
      else
      {
        emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry is valid." ) ) );
      }
#endif
      break;
    }
  }
}