コード例 #1
0
char *msudf_convexHull(UDF_INIT *initid,UDF_ARGS *args, char *buf,
	unsigned long *length, char *is_null, char *error)
{
	char *result;
	GEOSGeom geom1,geom2;

	DEBUG("msudf_convexHull");

	geom1 = msudf_getGeometry((unsigned char *)args->args[0],args->lengths[0]);	
	if (geom1 == NULL) {
		strcpy(error,"Invalid geometry.");
		*is_null = 1;
		return NULL;
	}
	
	geom2 = GEOSConvexHull(geom1);

	if (geom2 != NULL) {
		GEOSSetSRID(geom2,GEOSGetSRID(geom1));
		result = msudf_returnGeometry(initid,length,geom2);
		GEOSGeom_destroy(geom1);
		GEOSGeom_destroy(geom2);
		return result;
	} else {
		GEOSGeom_destroy(geom1);
		*is_null = 1;
		return NULL;
	}
}
コード例 #2
0
char *msudf_lineSubstring(UDF_INIT *initid,UDF_ARGS *args, char *buf,
	unsigned long *length, char *is_null, char *error)
{
	char *result;
	GEOSGeom geom2;
	GEOSGeom geom1; 
	double start; 
	double end; 
	DEBUG("msudf_lineSubstring");

	geom1 = msudf_getGeometry((unsigned char *)args->args[0],args->lengths[0]);	
	if (geom1 == NULL) {
		strcpy(error,"Invalid geometry.");
		*is_null = 1;
		return NULL;
	}

	start = *(double*) args->args[1] ;
	end = *(double*) args->args[2] ;

	geom2 = gu_substringLineGeom(geom1,start,end);

	if (geom2 != NULL) {
		GEOSSetSRID(geom2,GEOSGetSRID(geom1));
		result = msudf_returnGeometry(initid,length,geom2);
		GEOSGeom_destroy(geom1);
		GEOSGeom_destroy(geom2);
		return result;
	} else {
		GEOSGeom_destroy(geom1);
		*is_null = 1;
		return NULL;
	}
}
コード例 #3
0
ファイル: lwgeom_geos.c プロジェクト: gravitystorm/postgis
LWGEOM*
lwgeom_sharedpaths(const LWGEOM* geom1, const LWGEOM* geom2)
{
#if POSTGIS_GEOS_VERSION < 33
	lwerror("The GEOS version this postgis binary "
	        "was compiled against (%d) doesn't support "
	        "'SharedPaths' function (3.3.0+ required)",
	        POSTGIS_GEOS_VERSION);
	return NULL;
#else /* POSTGIS_GEOS_VERSION >= 33 */
	GEOSGeometry *g1, *g2, *g3;
	LWGEOM *out;
	int is3d, srid;

	srid = geom1->srid;
	error_if_srid_mismatch(srid, (int)(geom2->srid));

	is3d = (FLAGS_GET_Z(geom1->flags) || FLAGS_GET_Z(geom2->flags)) ;

	initGEOS(lwnotice, lwgeom_geos_error);

	g1 = (GEOSGeometry *)LWGEOM2GEOS(geom1);
	if ( 0 == g1 )   /* exception thrown at construction */
	{
		lwerror("First argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	g2 = (GEOSGeometry *)LWGEOM2GEOS(geom2);
	if ( 0 == g2 )   /* exception thrown at construction */
	{
		lwerror("Second argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg);
		GEOSGeom_destroy(g1);
		return NULL;
	}

	g3 = GEOSSharedPaths(g1,g2);

	GEOSGeom_destroy(g1);
	GEOSGeom_destroy(g2);

	if (g3 == NULL)
	{
		lwerror("GEOSSharedPaths: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	GEOSSetSRID(g3, srid);
	out = GEOS2LWGEOM(g3, is3d);
	GEOSGeom_destroy(g3);

	if (out == NULL)
	{
		lwerror("GEOS2LWGEOM threw an error");
		return NULL;
	}

	return out;
#endif /* POSTGIS_GEOS_VERSION >= 33 */
}
コード例 #4
0
char *msudf_simplifyPreserveTopology(UDF_INIT *initid,UDF_ARGS *args, char *buf,
	unsigned long *length, char *is_null, char *error)
{
	char *result;
	GEOSGeom geom2;
	GEOSGeom geom1; 
	double tolerance; 
	DEBUG("msudf_simplifyPreserveTopology");

	geom1 = msudf_getGeometry((unsigned char *)args->args[0],args->lengths[0]);	
	if (geom1 == NULL) {
		strcpy(error,"Invalid geometry.");
		*is_null = 1;
		return NULL;
	}

	tolerance = *(double*) args->args[1] ;

	geom2 = GEOSTopologyPreserveSimplify(geom1,tolerance);

	if (geom2 != NULL) {
		GEOSSetSRID(geom2,GEOSGetSRID(geom1));
		result = msudf_returnGeometry(initid,length,geom2);
		GEOSGeom_destroy(geom1);
		GEOSGeom_destroy(geom2);
		return result;
	} else {
		GEOSGeom_destroy(geom1);
		*is_null = 1;
		return NULL;
	}
}
コード例 #5
0
ファイル: lwgeom_geos.c プロジェクト: gravitystorm/postgis
LWGEOM*
lwgeom_offsetcurve(const LWLINE *lwline, double size, int quadsegs, int joinStyle, double mitreLimit)
{
#if POSTGIS_GEOS_VERSION < 32
	lwerror("lwgeom_offsetcurve: GEOS 3.2 or higher required");
#else
	GEOSGeometry *g1, *g3;
	LWGEOM *lwgeom_result;
	LWGEOM *lwgeom_in = lwline_as_lwgeom(lwline);

	initGEOS(lwnotice, lwgeom_geos_error);

	g1 = (GEOSGeometry *)LWGEOM2GEOS(lwgeom_in);
	if ( ! g1 ) 
	{
		lwerror("lwgeom_offsetcurve: Geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg);
		return NULL;
	}

#if POSTGIS_GEOS_VERSION < 33
	/* Size is always positive for GEOSSingleSidedBuffer, and a flag determines left/right */
	g3 = GEOSSingleSidedBuffer(g1, size < 0 ? -size : size,
	                           quadsegs, joinStyle, mitreLimit,
	                           size < 0 ? 0 : 1);
#else
	g3 = GEOSOffsetCurve(g1, size, quadsegs, joinStyle, mitreLimit);
#endif
	/* Don't need input geometry anymore */
	GEOSGeom_destroy(g1);

	if (g3 == NULL)
	{
		GEOSGeom_destroy(g1);
		lwerror("GEOSOffsetCurve: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	LWDEBUGF(3, "result: %s", GEOSGeomToWKT(g3));

	GEOSSetSRID(g3, lwgeom_get_srid(lwgeom_in));
	lwgeom_result = GEOS2LWGEOM(g3, lwgeom_has_z(lwgeom_in));
	GEOSGeom_destroy(g3);

	if (lwgeom_result == NULL)
	{
		lwerror("lwgeom_offsetcurve: GEOS2LWGEOM returned null");
		return NULL;
	}

	return lwgeom_result;
	
#endif /* POSTGIS_GEOS_VERSION < 32 */
}
コード例 #6
0
GEOSGeom msudf_getGeometry(unsigned char *buf,unsigned int length)
{
	int srid;
	GEOSGeom geom;

	geom = GEOSGeomFromWKB_buf(buf + 4,length - 4);
	if (geom != NULL) {
		srid = msudf_getInt(buf);
		GEOSSetSRID(geom,srid);
	}
	return geom;
}
コード例 #7
0
char *msudf_buffer(UDF_INIT *initid,UDF_ARGS *args, char *buf,
	unsigned long *length, char *is_null, char *error)
{
	char *result;
	GEOSGeom geom1,geom2;
	double buffer;
	int quadsegs;

	DEBUG("msudf_buffer");

	geom1 = msudf_getGeometry((unsigned char *)args->args[0],args->lengths[0]);	
	if (geom1 == NULL) {
		strcpy(error,"Invalid geometry.");
		*is_null = 1;
		return NULL;
	}

	buffer = *((double*) args->args[1]);
	
	if (args->arg_count > 2 && args->arg_type[2] == INT_RESULT) {
		quadsegs = *((int *)args->args[2]);
	} else {
		quadsegs = 8;
	}

	geom2 = GEOSBuffer(geom1,buffer,quadsegs);

	if (geom2 != NULL) {
        GEOSSetSRID(geom2,GEOSGetSRID(geom1));
		result = msudf_returnGeometry(initid,length,geom2);
		GEOSGeom_destroy(geom1);
		GEOSGeom_destroy(geom2);
		return result;
	} else {
		GEOSGeom_destroy(geom1);
		*is_null = 1;
		return NULL;
	}
}
コード例 #8
0
ファイル: lwgeom_geos.c プロジェクト: abuhamid/bd_geonode
LWGEOM *
lwgeom_normalize(const LWGEOM *geom1)
{
	LWGEOM *result ;
	GEOSGeometry *g1;
	int is3d ;
	int srid ;

	srid = (int)(geom1->srid);
	is3d = FLAGS_GET_Z(geom1->flags);

	initGEOS(lwnotice, lwgeom_geos_error);

	g1 = LWGEOM2GEOS(geom1);
	if ( 0 == g1 )   /* exception thrown at construction */
	{
		lwerror("First argument geometry could not be converted to GEOS.");
		return NULL ;
	}

	if ( -1 == GEOSNormalize(g1) )
	{
	  lwerror("Error in GEOSNormalize: %s", lwgeom_geos_errmsg);
		return NULL; /* never get here */
	}

	GEOSSetSRID(g1, srid); /* needed ? */
	result = GEOS2LWGEOM(g1, is3d);
	GEOSGeom_destroy(g1);

	if (result == NULL)
	{
	  lwerror("Error performing intersection: GEOS2LWGEOM: %s",
	                lwgeom_geos_errmsg);
		return NULL ; /* never get here */
	}

	return result ;
}
コード例 #9
0
char *msudf_intersection(UDF_INIT *initid,UDF_ARGS *args, char *buf,
	unsigned long *length, char *is_null, char *error)
{
	char *result;
	GEOSGeom geomFirst,geomSecond,geomResult;

	DEBUG("msudf_intersection");
	
	geomFirst = msudf_getGeometry((unsigned char *)args->args[0],args->lengths[0]);
	if (geomFirst == NULL) {
		strcpy(error,"Invalid geometry.");
		*is_null = 1;
		return 0;
	}

	geomSecond = msudf_getGeometry((unsigned char *)args->args[1],args->lengths[1]);	
	if (geomSecond == NULL) {
		GEOSGeom_destroy(geomFirst);
		strcpy(error,"Invalid geometry.");
		*is_null = 1;
		return 0;
	}

	geomResult = GEOSIntersection(geomFirst,geomSecond);

	if (geomResult!= NULL) {
		GEOSSetSRID(geomResult,GEOSGetSRID(geomFirst));
		result = msudf_returnGeometry(initid,length,geomResult);
		GEOSGeom_destroy(geomFirst);
		GEOSGeom_destroy(geomSecond);
		GEOSGeom_destroy(geomResult);
		return result;
	} else {
		GEOSGeom_destroy(geomFirst);
		GEOSGeom_destroy(geomSecond);
		*is_null = 1;
		return NULL;
	}
}
コード例 #10
0
ファイル: lwgeom_geos.c プロジェクト: gravitystorm/postgis
LWGEOM*
lwgeom_snap(const LWGEOM* geom1, const LWGEOM* geom2, double tolerance)
{
#if POSTGIS_GEOS_VERSION < 33
	lwerror("The GEOS version this lwgeom library "
	        "was compiled against (%d) doesn't support "
	        "'Snap' function (3.3.0+ required)",
	        POSTGIS_GEOS_VERSION);
	return NULL;
#else /* POSTGIS_GEOS_VERSION >= 33 */

	int srid, is3d;
	GEOSGeometry *g1, *g2, *g3;
	LWGEOM* out;

	srid = geom1->srid;
	error_if_srid_mismatch(srid, (int)(geom2->srid));

	is3d = (FLAGS_GET_Z(geom1->flags) || FLAGS_GET_Z(geom2->flags)) ;

	initGEOS(lwnotice, lwgeom_geos_error);

	g1 = (GEOSGeometry *)LWGEOM2GEOS(geom1);
	if ( 0 == g1 )   /* exception thrown at construction */
	{
		lwerror("First argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	g2 = (GEOSGeometry *)LWGEOM2GEOS(geom2);
	if ( 0 == g2 )   /* exception thrown at construction */
	{
		lwerror("Second argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg);
		GEOSGeom_destroy(g1);
		return NULL;
	}

	g3 = GEOSSnap(g1, g2, tolerance);
	if (g3 == NULL)
	{
		GEOSGeom_destroy(g1);
		GEOSGeom_destroy(g2);
		lwerror("GEOSSnap: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	GEOSGeom_destroy(g1);
	GEOSGeom_destroy(g2);

	GEOSSetSRID(g3, srid);
	out = GEOS2LWGEOM(g3, is3d);
	if (out == NULL)
	{
		GEOSGeom_destroy(g3);
		lwerror("GEOSSnap() threw an error (result LWGEOM geometry formation)!");
		return NULL;
	}
	GEOSGeom_destroy(g3);

	return out;

#endif /* POSTGIS_GEOS_VERSION >= 33 */
}
コード例 #11
0
ファイル: gg_geoscvt.c プロジェクト: stefanklug/libspatialite
static GEOSGeometry *
toGeosGeometry (const gaiaGeomCollPtr gaia)
{
/* converting a GAIA Geometry into a GEOS Geometry */
    int pts = 0;
    int lns = 0;
    int pgs = 0;
    int type;
    int geos_type;
    unsigned int dims;
    int iv;
    int ib;
    int nItem;
    double x;
    double y;
    double z;
    double m;
    gaiaPointPtr pt;
    gaiaLinestringPtr ln;
    gaiaPolygonPtr pg;
    gaiaRingPtr rng;
    GEOSGeometry *geos;
    GEOSGeometry *geos_ext;
    GEOSGeometry *geos_int;
    GEOSGeometry *geos_item;
    GEOSGeometry **geos_holes;
    GEOSGeometry **geos_coll;
    GEOSCoordSequence *cs;
    if (!gaia)
	return NULL;
    pt = gaia->FirstPoint;
    while (pt)
      {
	  /* counting how many POINTs are there */
	  pts++;
	  pt = pt->Next;
      }
    ln = gaia->FirstLinestring;
    while (ln)
      {
	  /* counting how many LINESTRINGs are there */
	  lns++;
	  ln = ln->Next;
      }
    pg = gaia->FirstPolygon;
    while (pg)
      {
	  /* counting how many POLYGONs are there */
	  pgs++;
	  pg = pg->Next;
      }
    if (pts == 0 && lns == 0 && pgs == 0)
	type = GAIA_UNKNOWN;
    else if (pts == 1 && lns == 0 && pgs == 0)
      {
	  if (gaia->DeclaredType == GAIA_MULTIPOINT)
	      type = GAIA_MULTIPOINT;
	  else if (gaia->DeclaredType == GAIA_GEOMETRYCOLLECTION)
	      type = GAIA_GEOMETRYCOLLECTION;
	  else
	      type = GAIA_POINT;
      }
    else if (pts == 0 && lns == 1 && pgs == 0)
      {
	  if (gaia->DeclaredType == GAIA_MULTILINESTRING)
	      type = GAIA_MULTILINESTRING;
	  else if (gaia->DeclaredType == GAIA_GEOMETRYCOLLECTION)
	      type = GAIA_GEOMETRYCOLLECTION;
	  else
	      type = GAIA_LINESTRING;
      }
    else if (pts == 0 && lns == 0 && pgs == 1)
      {
	  if (gaia->DeclaredType == GAIA_MULTIPOLYGON)
	      type = GAIA_MULTIPOLYGON;
	  else if (gaia->DeclaredType == GAIA_GEOMETRYCOLLECTION)
	      type = GAIA_GEOMETRYCOLLECTION;
	  else
	      type = GAIA_POLYGON;
      }
    else if (pts > 1 && lns == 0 && pgs == 0)
      {
	  if (gaia->DeclaredType == GAIA_GEOMETRYCOLLECTION)
	      type = GAIA_GEOMETRYCOLLECTION;
	  else
	      type = GAIA_MULTIPOINT;
      }
    else if (pts == 0 && lns > 1 && pgs == 0)
      {
	  if (gaia->DeclaredType == GAIA_GEOMETRYCOLLECTION)
	      type = GAIA_GEOMETRYCOLLECTION;
	  else
	      type = GAIA_MULTILINESTRING;
      }
    else if (pts == 0 && lns == 0 && pgs > 1)
      {
	  if (gaia->DeclaredType == GAIA_GEOMETRYCOLLECTION)
	      type = GAIA_GEOMETRYCOLLECTION;
	  else
	      type = GAIA_MULTIPOLYGON;
      }
    else
	type = GAIA_GEOMETRYCOLLECTION;
    switch (gaia->DimensionModel)
      {
      case GAIA_XY_Z:
      case GAIA_XY_Z_M:
	  dims = 3;
	  break;
      default:
	  dims = 2;
	  break;
      };
    switch (type)
      {
      case GAIA_POINT:
	  pt = gaia->FirstPoint;
	  cs = GEOSCoordSeq_create (1, dims);
	  switch (gaia->DimensionModel)
	    {
	    case GAIA_XY_Z:
	    case GAIA_XY_Z_M:
		GEOSCoordSeq_setX (cs, 0, pt->X);
		GEOSCoordSeq_setY (cs, 0, pt->Y);
		GEOSCoordSeq_setZ (cs, 0, pt->Z);
		break;
	    default:
		GEOSCoordSeq_setX (cs, 0, pt->X);
		GEOSCoordSeq_setY (cs, 0, pt->Y);
		break;
	    };
	  geos = GEOSGeom_createPoint (cs);
	  break;
      case GAIA_LINESTRING:
	  ln = gaia->FirstLinestring;
	  cs = GEOSCoordSeq_create (ln->Points, dims);
	  for (iv = 0; iv < ln->Points; iv++)
	    {
		switch (ln->DimensionModel)
		  {
		  case GAIA_XY_Z:
		      gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z);
		      GEOSCoordSeq_setX (cs, iv, x);
		      GEOSCoordSeq_setY (cs, iv, y);
		      GEOSCoordSeq_setZ (cs, iv, z);
		      break;
		  case GAIA_XY_M:
		      gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
		      GEOSCoordSeq_setX (cs, iv, x);
		      GEOSCoordSeq_setY (cs, iv, y);
		      break;
		  case GAIA_XY_Z_M:
		      gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
		      GEOSCoordSeq_setX (cs, iv, x);
		      GEOSCoordSeq_setY (cs, iv, y);
		      GEOSCoordSeq_setZ (cs, iv, z);
		      break;
		  default:
		      gaiaGetPoint (ln->Coords, iv, &x, &y);
		      GEOSCoordSeq_setX (cs, iv, x);
		      GEOSCoordSeq_setY (cs, iv, y);
		      break;
		  };
	    }
	  geos = GEOSGeom_createLineString (cs);
	  break;
      case GAIA_POLYGON:
	  pg = gaia->FirstPolygon;
	  rng = pg->Exterior;
	  /* exterior ring */
	  cs = GEOSCoordSeq_create (rng->Points, dims);
	  for (iv = 0; iv < rng->Points; iv++)
	    {
		switch (rng->DimensionModel)
		  {
		  case GAIA_XY_Z:
		      gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
		      GEOSCoordSeq_setX (cs, iv, x);
		      GEOSCoordSeq_setY (cs, iv, y);
		      GEOSCoordSeq_setZ (cs, iv, z);
		      break;
		  case GAIA_XY_M:
		      gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
		      GEOSCoordSeq_setX (cs, iv, x);
		      GEOSCoordSeq_setY (cs, iv, y);
		      break;
		  case GAIA_XY_Z_M:
		      gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
		      GEOSCoordSeq_setX (cs, iv, x);
		      GEOSCoordSeq_setY (cs, iv, y);
		      GEOSCoordSeq_setZ (cs, iv, z);
		      break;
		  default:
		      gaiaGetPoint (rng->Coords, iv, &x, &y);
		      GEOSCoordSeq_setX (cs, iv, x);
		      GEOSCoordSeq_setY (cs, iv, y);
		      break;
		  };
	    }
	  geos_ext = GEOSGeom_createLinearRing (cs);
	  geos_holes = NULL;
	  if (pg->NumInteriors > 0)
	    {
		geos_holes =
		    malloc (sizeof (GEOSGeometry *) * pg->NumInteriors);
		for (ib = 0; ib < pg->NumInteriors; ib++)
		  {
		      /* interior ring */
		      rng = pg->Interiors + ib;
		      cs = GEOSCoordSeq_create (rng->Points, dims);
		      for (iv = 0; iv < rng->Points; iv++)
			{
			    switch (rng->DimensionModel)
			      {
			      case GAIA_XY_Z:
				  gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
				  GEOSCoordSeq_setX (cs, iv, x);
				  GEOSCoordSeq_setY (cs, iv, y);
				  GEOSCoordSeq_setZ (cs, iv, z);
				  break;
			      case GAIA_XY_M:
				  gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
				  GEOSCoordSeq_setX (cs, iv, x);
				  GEOSCoordSeq_setY (cs, iv, y);
				  break;
			      case GAIA_XY_Z_M:
				  gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z,
						    &m);
				  GEOSCoordSeq_setX (cs, iv, x);
				  GEOSCoordSeq_setY (cs, iv, y);
				  GEOSCoordSeq_setZ (cs, iv, z);
				  break;
			      default:
				  gaiaGetPoint (rng->Coords, iv, &x, &y);
				  GEOSCoordSeq_setX (cs, iv, x);
				  GEOSCoordSeq_setY (cs, iv, y);
				  break;
			      };
			}
		      geos_int = GEOSGeom_createLinearRing (cs);
		      *(geos_holes + ib) = geos_int;
		  }
	    }
	  geos =
	      GEOSGeom_createPolygon (geos_ext, geos_holes, pg->NumInteriors);
	  if (geos_holes)
	      free (geos_holes);
	  break;
      case GAIA_MULTIPOINT:
      case GAIA_MULTILINESTRING:
      case GAIA_MULTIPOLYGON:
      case GAIA_GEOMETRYCOLLECTION:
	  nItem = 0;
	  geos_coll = malloc (sizeof (GEOSGeometry *) * (pts + lns + pgs));
	  pt = gaia->FirstPoint;
	  while (pt)
	    {
		cs = GEOSCoordSeq_create (1, dims);
		switch (pt->DimensionModel)
		  {
		  case GAIA_XY_Z:
		  case GAIA_XY_Z_M:
		      GEOSCoordSeq_setX (cs, 0, pt->X);
		      GEOSCoordSeq_setY (cs, 0, pt->Y);
		      GEOSCoordSeq_setZ (cs, 0, pt->Z);
		      break;
		  default:
		      GEOSCoordSeq_setX (cs, 0, pt->X);
		      GEOSCoordSeq_setY (cs, 0, pt->Y);
		      break;
		  };
		geos_item = GEOSGeom_createPoint (cs);
		*(geos_coll + nItem++) = geos_item;
		pt = pt->Next;
	    }
	  ln = gaia->FirstLinestring;
	  while (ln)
	    {
		cs = GEOSCoordSeq_create (ln->Points, dims);
		for (iv = 0; iv < ln->Points; iv++)
		  {
		      switch (ln->DimensionModel)
			{
			case GAIA_XY_Z:
			    gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z);
			    GEOSCoordSeq_setX (cs, iv, x);
			    GEOSCoordSeq_setY (cs, iv, y);
			    GEOSCoordSeq_setZ (cs, iv, z);
			    break;
			case GAIA_XY_M:
			    gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m);
			    GEOSCoordSeq_setX (cs, iv, x);
			    GEOSCoordSeq_setY (cs, iv, y);
			    break;
			case GAIA_XY_Z_M:
			    gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m);
			    GEOSCoordSeq_setX (cs, iv, x);
			    GEOSCoordSeq_setY (cs, iv, y);
			    GEOSCoordSeq_setZ (cs, iv, z);
			    break;
			default:
			    gaiaGetPoint (ln->Coords, iv, &x, &y);
			    GEOSCoordSeq_setX (cs, iv, x);
			    GEOSCoordSeq_setY (cs, iv, y);
			    break;
			};
		  }
		geos_item = GEOSGeom_createLineString (cs);
		*(geos_coll + nItem++) = geos_item;
		ln = ln->Next;
	    }
	  pg = gaia->FirstPolygon;
	  while (pg)
	    {
		rng = pg->Exterior;
		/* exterior ring */
		cs = GEOSCoordSeq_create (rng->Points, dims);
		for (iv = 0; iv < rng->Points; iv++)
		  {
		      switch (rng->DimensionModel)
			{
			case GAIA_XY_Z:
			    gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z);
			    GEOSCoordSeq_setX (cs, iv, x);
			    GEOSCoordSeq_setY (cs, iv, y);
			    GEOSCoordSeq_setZ (cs, iv, z);
			    break;
			case GAIA_XY_M:
			    gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m);
			    GEOSCoordSeq_setX (cs, iv, x);
			    GEOSCoordSeq_setY (cs, iv, y);
			    break;
			case GAIA_XY_Z_M:
			    gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m);
			    GEOSCoordSeq_setX (cs, iv, x);
			    GEOSCoordSeq_setY (cs, iv, y);
			    GEOSCoordSeq_setZ (cs, iv, z);
			    break;
			default:
			    gaiaGetPoint (rng->Coords, iv, &x, &y);
			    GEOSCoordSeq_setX (cs, iv, x);
			    GEOSCoordSeq_setY (cs, iv, y);
			    break;
			};
		  }
		geos_ext = GEOSGeom_createLinearRing (cs);
		geos_holes = NULL;
		if (pg->NumInteriors > 0)
		  {
		      geos_holes =
			  malloc (sizeof (GEOSGeometry *) * pg->NumInteriors);
		      for (ib = 0; ib < pg->NumInteriors; ib++)
			{
			    /* interior ring */
			    rng = pg->Interiors + ib;
			    cs = GEOSCoordSeq_create (rng->Points, dims);
			    for (iv = 0; iv < rng->Points; iv++)
			      {
				  switch (rng->DimensionModel)
				    {
				    case GAIA_XY_Z:
					gaiaGetPointXYZ (rng->Coords, iv, &x,
							 &y, &z);
					GEOSCoordSeq_setX (cs, iv, x);
					GEOSCoordSeq_setY (cs, iv, y);
					GEOSCoordSeq_setZ (cs, iv, z);
					break;
				    case GAIA_XY_M:
					gaiaGetPointXYM (rng->Coords, iv, &x,
							 &y, &m);
					GEOSCoordSeq_setX (cs, iv, x);
					GEOSCoordSeq_setY (cs, iv, y);
					break;
				    case GAIA_XY_Z_M:
					gaiaGetPointXYZM (rng->Coords, iv, &x,
							  &y, &z, &m);
					GEOSCoordSeq_setX (cs, iv, x);
					GEOSCoordSeq_setY (cs, iv, y);
					GEOSCoordSeq_setZ (cs, iv, z);
					break;
				    default:
					gaiaGetPoint (rng->Coords, iv, &x, &y);
					GEOSCoordSeq_setX (cs, iv, x);
					GEOSCoordSeq_setY (cs, iv, y);
					break;
				    };
			      }
			    geos_int = GEOSGeom_createLinearRing (cs);
			    *(geos_holes + ib) = geos_int;
			}
		  }
		geos_item =
		    GEOSGeom_createPolygon (geos_ext, geos_holes,
					    pg->NumInteriors);
		if (geos_holes)
		    free (geos_holes);
		*(geos_coll + nItem++) = geos_item;
		pg = pg->Next;
	    }
	  geos_type = GEOS_GEOMETRYCOLLECTION;
	  if (type == GAIA_MULTIPOINT)
	      geos_type = GEOS_MULTIPOINT;
	  if (type == GAIA_MULTILINESTRING)
	      geos_type = GEOS_MULTILINESTRING;
	  if (type == GAIA_MULTIPOLYGON)
	      geos_type = GEOS_MULTIPOLYGON;
	  geos =
	      GEOSGeom_createCollection (geos_type, geos_coll, pts + lns + pgs);
	  if (geos_coll)
	      free (geos_coll);
	  break;
      default:
	  geos = NULL;
      };
    if (geos)
	GEOSSetSRID (geos, gaia->Srid);
    return geos;
}
コード例 #12
0
ファイル: lwgeom_geos.c プロジェクト: gravitystorm/postgis
LWGEOM*
lwgeom_union(const LWGEOM *geom1, const LWGEOM *geom2)
{
	int is3d;
	int srid;
	GEOSGeometry *g1, *g2, *g3;
	LWGEOM *result;

	LWDEBUG(2, "in geomunion");

	/* A.Union(empty) == A */
	if ( lwgeom_is_empty(geom1) )
		return lwgeom_clone(geom2);

	/* B.Union(empty) == B */
	if ( lwgeom_is_empty(geom2) )
		return lwgeom_clone(geom1);


	/* ensure srids are identical */
	srid = (int)(geom1->srid);
	error_if_srid_mismatch(srid, (int)(geom2->srid));

	is3d = (FLAGS_GET_Z(geom1->flags) || FLAGS_GET_Z(geom2->flags)) ;

	initGEOS(lwnotice, lwgeom_geos_error);

	g1 = LWGEOM2GEOS(geom1);

	if ( 0 == g1 )   /* exception thrown at construction */
	{
		lwerror("First argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	g2 = LWGEOM2GEOS(geom2);

	if ( 0 == g2 )   /* exception thrown at construction */
	{
		GEOSGeom_destroy(g1);
		lwerror("Second argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	LWDEBUGF(3, "g1=%s", GEOSGeomToWKT(g1));
	LWDEBUGF(3, "g2=%s", GEOSGeomToWKT(g2));

	g3 = GEOSUnion(g1,g2);

	LWDEBUGF(3, "g3=%s", GEOSGeomToWKT(g3));

	GEOSGeom_destroy(g1);
	GEOSGeom_destroy(g2);

	if (g3 == NULL)
	{
		lwerror("GEOSUnion: %s", lwgeom_geos_errmsg);
		return NULL; /* never get here */
	}


	GEOSSetSRID(g3, srid);

	result = GEOS2LWGEOM(g3, is3d);

	GEOSGeom_destroy(g3);

	if (result == NULL)
	{
	        lwerror("Error performing union: GEOS2LWGEOM: %s",
	                lwgeom_geos_errmsg);
		return NULL; /*never get here */
	}

	return result;
}
コード例 #13
0
ファイル: lwgeom_geos.c プロジェクト: gravitystorm/postgis
LWGEOM *
lwgeom_symdifference(const LWGEOM* geom1, const LWGEOM* geom2)
{
	GEOSGeometry *g1, *g2, *g3;
	LWGEOM *result;
	int is3d;
	int srid;

	/* A.SymDifference(Empty) == A */
	if ( lwgeom_is_empty(geom2) )
		return lwgeom_clone(geom1);

	/* Empty.DymDifference(B) == Empty */
	if ( lwgeom_is_empty(geom1) )
		return lwgeom_clone(geom1);

	/* ensure srids are identical */
	srid = (int)(geom1->srid);
	error_if_srid_mismatch(srid, (int)(geom2->srid));

	is3d = (FLAGS_GET_Z(geom1->flags) || FLAGS_GET_Z(geom2->flags)) ;

	initGEOS(lwnotice, lwgeom_geos_error);

	g1 = LWGEOM2GEOS(geom1);

	if ( 0 == g1 )   /* exception thrown at construction */
	{
		lwerror("First argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	g2 = LWGEOM2GEOS(geom2);

	if ( 0 == g2 )   /* exception thrown at construction */
	{
		lwerror("Second argument geometry could not be converted to GEOS: %s", lwgeom_geos_errmsg);
		GEOSGeom_destroy(g1);
		return NULL;
	}

	g3 = GEOSSymDifference(g1,g2);

	if (g3 == NULL)
	{
		GEOSGeom_destroy(g1);
		GEOSGeom_destroy(g2);
		lwerror("GEOSSymDifference: %s", lwgeom_geos_errmsg);
		return NULL; /*never get here */
	}

	LWDEBUGF(3, "result: %s", GEOSGeomToWKT(g3));

	GEOSSetSRID(g3, srid);

	result = GEOS2LWGEOM(g3, is3d);

	if (result == NULL)
	{
		GEOSGeom_destroy(g1);
		GEOSGeom_destroy(g2);
		GEOSGeom_destroy(g3);
		lwerror("GEOS symdifference() threw an error (result postgis geometry formation)!");
		return NULL ; /*never get here */
	}

	GEOSGeom_destroy(g1);
	GEOSGeom_destroy(g2);
	GEOSGeom_destroy(g3);

	return result;
}
コード例 #14
0
ファイル: lwgeom_geos.c プロジェクト: gravitystorm/postgis
LWGEOM *
lwgeom_intersection(const LWGEOM *geom1, const LWGEOM *geom2)
{
	LWGEOM *result ;
	GEOSGeometry *g1, *g2, *g3 ;
	int is3d ;
	int srid ;

	/* A.Intersection(Empty) == Empty */
	if ( lwgeom_is_empty(geom2) )
		return lwgeom_clone(geom2);

	/* Empty.Intersection(A) == Empty */
	if ( lwgeom_is_empty(geom1) )
		return lwgeom_clone(geom1);

	/* ensure srids are identical */
	srid = (int)(geom1->srid);
	error_if_srid_mismatch(srid, (int)(geom2->srid));

	is3d = (FLAGS_GET_Z(geom1->flags) || FLAGS_GET_Z(geom2->flags)) ;

	initGEOS(lwnotice, lwgeom_geos_error);

	LWDEBUG(3, "intersection() START");

	g1 = LWGEOM2GEOS(geom1);
	if ( 0 == g1 )   /* exception thrown at construction */
	{
		lwerror("First argument geometry could not be converted to GEOS.");
		return NULL ;
	}

	g2 = LWGEOM2GEOS(geom2);
	if ( 0 == g2 )   /* exception thrown at construction */
	{
		lwerror("Second argument geometry could not be converted to GEOS.");
		GEOSGeom_destroy(g1);
		return NULL ;
	}

	LWDEBUG(3, " constructed geometrys - calling geos");
	LWDEBUGF(3, " g1 = %s", GEOSGeomToWKT(g1));
	LWDEBUGF(3, " g2 = %s", GEOSGeomToWKT(g2));
	/*LWDEBUGF(3, "g2 is valid = %i",GEOSisvalid(g2)); */
	/*LWDEBUGF(3, "g1 is valid = %i",GEOSisvalid(g1)); */

	g3 = GEOSIntersection(g1,g2);

	LWDEBUG(3, " intersection finished");

	if (g3 == NULL)
	{
		GEOSGeom_destroy(g1);
		GEOSGeom_destroy(g2);
	        lwerror("Error performing intersection: %s",
	                lwgeom_geos_errmsg);
		return NULL; /* never get here */
	}

	LWDEBUGF(3, "result: %s", GEOSGeomToWKT(g3) ) ;

	GEOSSetSRID(g3, srid);

	result = GEOS2LWGEOM(g3, is3d);

	if (result == NULL)
	{
		GEOSGeom_destroy(g1);
		GEOSGeom_destroy(g2);
		GEOSGeom_destroy(g3);
	        lwerror("Error performing intersection: GEOS2LWGEOM: %s",
	                lwgeom_geos_errmsg);
		return NULL ; /* never get here */
	}

	GEOSGeom_destroy(g1);
	GEOSGeom_destroy(g2);
	GEOSGeom_destroy(g3);

	return result ;
}
コード例 #15
0
ファイル: lwgeom_geos.c プロジェクト: gravitystorm/postgis
GEOSGeometry *
LWGEOM2GEOS(const LWGEOM *lwgeom)
{
	GEOSCoordSeq sq;
	GEOSGeom g, shell;
	GEOSGeom *geoms = NULL;
	/*
	LWGEOM *tmp;
	*/
	uint32_t ngeoms, i;
	int geostype;
#if LWDEBUG_LEVEL >= 4
	char *wkt;
#endif

	LWDEBUGF(4, "LWGEOM2GEOS got a %s", lwtype_name(lwgeom->type));

	if (lwgeom_has_arc(lwgeom))
	{
		LWDEBUG(3, "LWGEOM2GEOS: arced geometry found.");

		lwerror("Exception in LWGEOM2GEOS: curved geometry not supported.");
		return NULL;
	}
	
	switch (lwgeom->type)
	{
		LWPOINT *lwp = NULL;
		LWPOLY *lwpoly = NULL;
		LWLINE *lwl = NULL;
		LWCOLLECTION *lwc = NULL;
#if POSTGIS_GEOS_VERSION < 33
		POINTARRAY *pa = NULL;
#endif
		
	case POINTTYPE:
		lwp = (LWPOINT *)lwgeom;
		
		if ( lwgeom_is_empty(lwgeom) )
		{
#if POSTGIS_GEOS_VERSION < 33
			pa = ptarray_construct_empty(lwgeom_has_z(lwgeom), lwgeom_has_m(lwgeom), 2);
			sq = ptarray_to_GEOSCoordSeq(pa);
			shell = GEOSGeom_createLinearRing(sq);
			g = GEOSGeom_createPolygon(shell, NULL, 0);
#else
			g = GEOSGeom_createEmptyPolygon();
#endif
		}
		else
		{
			sq = ptarray_to_GEOSCoordSeq(lwp->point);
			g = GEOSGeom_createPoint(sq);
		}
		if ( ! g )
		{
			/* lwnotice("Exception in LWGEOM2GEOS"); */
			return NULL;
		}
		break;
	case LINETYPE:
		lwl = (LWLINE *)lwgeom;
		if ( lwl->points->npoints == 1 ) {
			/* Duplicate point, to make geos-friendly */
			lwl->points = ptarray_addPoint(lwl->points,
		                           getPoint_internal(lwl->points, 0),
		                           FLAGS_NDIMS(lwl->points->flags),
		                           lwl->points->npoints);
		}
		sq = ptarray_to_GEOSCoordSeq(lwl->points);
		g = GEOSGeom_createLineString(sq);
		if ( ! g )
		{
			/* lwnotice("Exception in LWGEOM2GEOS"); */
			return NULL;
		}
		break;

	case POLYGONTYPE:
		lwpoly = (LWPOLY *)lwgeom;
		if ( lwgeom_is_empty(lwgeom) )
		{
#if POSTGIS_GEOS_VERSION < 33
			POINTARRAY *pa = ptarray_construct_empty(lwgeom_has_z(lwgeom), lwgeom_has_m(lwgeom), 2);
			sq = ptarray_to_GEOSCoordSeq(pa);
			shell = GEOSGeom_createLinearRing(sq);
			g = GEOSGeom_createPolygon(shell, NULL, 0);
#else
			g = GEOSGeom_createEmptyPolygon();
#endif
		}
		else
		{
			sq = ptarray_to_GEOSCoordSeq(lwpoly->rings[0]);
			/* TODO: check ring for being closed and fix if not */
			shell = GEOSGeom_createLinearRing(sq);
			if ( ! shell ) return NULL;
			/*lwerror("LWGEOM2GEOS: exception during polygon shell conversion"); */
			ngeoms = lwpoly->nrings-1;
			if ( ngeoms > 0 )
				geoms = malloc(sizeof(GEOSGeom)*ngeoms);

			for (i=1; i<lwpoly->nrings; ++i)
			{
				sq = ptarray_to_GEOSCoordSeq(lwpoly->rings[i]);
				geoms[i-1] = GEOSGeom_createLinearRing(sq);
				if ( ! geoms[i-1] )
				{
					--i;
					while (i) GEOSGeom_destroy(geoms[--i]);
					free(geoms);
					GEOSGeom_destroy(shell);
					return NULL;
				}
				/*lwerror("LWGEOM2GEOS: exception during polygon hole conversion"); */
			}
			g = GEOSGeom_createPolygon(shell, geoms, ngeoms);
			if (geoms) free(geoms);
		}
		if ( ! g ) return NULL;
		break;
	case MULTIPOINTTYPE:
	case MULTILINETYPE:
	case MULTIPOLYGONTYPE:
	case COLLECTIONTYPE:
		if ( lwgeom->type == MULTIPOINTTYPE )
			geostype = GEOS_MULTIPOINT;
		else if ( lwgeom->type == MULTILINETYPE )
			geostype = GEOS_MULTILINESTRING;
		else if ( lwgeom->type == MULTIPOLYGONTYPE )
			geostype = GEOS_MULTIPOLYGON;
		else
			geostype = GEOS_GEOMETRYCOLLECTION;

		lwc = (LWCOLLECTION *)lwgeom;

		ngeoms = lwc->ngeoms;
		if ( ngeoms > 0 )
			geoms = malloc(sizeof(GEOSGeom)*ngeoms);

		for (i=0; i<ngeoms; ++i)
		{
			GEOSGeometry* g = LWGEOM2GEOS(lwc->geoms[i]);
			if ( ! g )
			{
				while (i) GEOSGeom_destroy(geoms[--i]);
				free(geoms);
				return NULL;
			}
			geoms[i] = g;
		}
		g = GEOSGeom_createCollection(geostype, geoms, ngeoms);
		if ( geoms ) free(geoms);
		if ( ! g ) return NULL;
		break;

	default:
		lwerror("Unknown geometry type: %d - %s", lwgeom->type, lwtype_name(lwgeom->type));
		return NULL;
	}

	GEOSSetSRID(g, lwgeom->srid);

#if LWDEBUG_LEVEL >= 4
	wkt = GEOSGeomToWKT(g);
	LWDEBUGF(4, "LWGEOM2GEOS: GEOSGeom: %s", wkt);
	free(wkt);
#endif

	return g;
}
コード例 #16
0
ファイル: lwgeom_geos.c プロジェクト: abuhamid/bd_geonode
GEOSGeometry*
LWGEOM_GEOS_buildArea(const GEOSGeometry* geom_in)
{
  GEOSGeometry *tmp;
  GEOSGeometry *geos_result, *shp;
  GEOSGeometry const *vgeoms[1];
  uint32_t i, ngeoms;
  int srid = GEOSGetSRID(geom_in);
  Face ** geoms;

  vgeoms[0] = geom_in;
#ifdef LWGEOM_PROFILE_BUILDAREA
  lwnotice("Polygonizing");
#endif
  geos_result = GEOSPolygonize(vgeoms, 1);

  LWDEBUGF(3, "GEOSpolygonize returned @ %p", geos_result);

  /* Null return from GEOSpolygonize (an exception) */
  if ( ! geos_result ) return 0;

  /*
   * We should now have a collection
   */
#if PARANOIA_LEVEL > 0
  if ( GEOSGeometryTypeId(geos_result) != COLLECTIONTYPE )
  {
    GEOSGeom_destroy(geos_result);
    lwerror("Unexpected return from GEOSpolygonize");
    return 0;
  }
#endif

  ngeoms = GEOSGetNumGeometries(geos_result);
#ifdef LWGEOM_PROFILE_BUILDAREA
  lwnotice("Num geometries from polygonizer: %d", ngeoms);
#endif


  LWDEBUGF(3, "GEOSpolygonize: ngeoms in polygonize output: %d", ngeoms);
  LWDEBUGF(3, "GEOSpolygonize: polygonized:%s",
              lwgeom_to_ewkt(GEOS2LWGEOM(geos_result, 0)));

  /*
   * No geometries in collection, early out
   */
  if ( ngeoms == 0 )
  {
    GEOSSetSRID(geos_result, srid);
    return geos_result;
  }

  /*
   * Return first geometry if we only have one in collection,
   * to avoid the unnecessary Geometry clone below.
   */
  if ( ngeoms == 1 )
  {
    tmp = (GEOSGeometry *)GEOSGetGeometryN(geos_result, 0);
    if ( ! tmp )
    {
      GEOSGeom_destroy(geos_result);
      return 0; /* exception */
    }
    shp = GEOSGeom_clone(tmp);
    GEOSGeom_destroy(geos_result); /* only safe after the clone above */
    GEOSSetSRID(shp, srid);
    return shp;
  }

  LWDEBUGF(2, "Polygonize returned %d geoms", ngeoms);

  /*
   * Polygonizer returns a polygon for each face in the built topology.
   *
   * This means that for any face with holes we'll have other faces
   * representing each hole. We can imagine a parent-child relationship
   * between these faces.
   *
   * In order to maximize the number of visible rings in output we
   * only use those faces which have an even number of parents.
   *
   * Example:
   *
   *   +---------------+
   *   |     L0        |  L0 has no parents 
   *   |  +---------+  |
   *   |  |   L1    |  |  L1 is an hole of L0
   *   |  |  +---+  |  |
   *   |  |  |L2 |  |  |  L2 is an hole of L1 (which is an hole of L0)
   *   |  |  |   |  |  |
   *   |  |  +---+  |  |
   *   |  +---------+  |
   *   |               |
   *   +---------------+
   * 
   * See http://trac.osgeo.org/postgis/ticket/1806
   *
   */

#ifdef LWGEOM_PROFILE_BUILDAREA
  lwnotice("Preparing face structures");
#endif

  /* Prepare face structures for later analysis */
  geoms = lwalloc(sizeof(Face**)*ngeoms);
  for (i=0; i<ngeoms; ++i)
    geoms[i] = newFace(GEOSGetGeometryN(geos_result, i));

#ifdef LWGEOM_PROFILE_BUILDAREA
  lwnotice("Finding face holes");
#endif

  /* Find faces representing other faces holes */
  findFaceHoles(geoms, ngeoms);

#ifdef LWGEOM_PROFILE_BUILDAREA
  lwnotice("Colletting even ancestor faces");
#endif

  /* Build a MultiPolygon composed only by faces with an
   * even number of ancestors */
  tmp = collectFacesWithEvenAncestors(geoms, ngeoms);

#ifdef LWGEOM_PROFILE_BUILDAREA
  lwnotice("Cleaning up");
#endif

  /* Cleanup face structures */
  for (i=0; i<ngeoms; ++i) delFace(geoms[i]);
  lwfree(geoms);

  /* Faces referenced memory owned by geos_result.
   * It is safe to destroy geos_result after deleting them. */
  GEOSGeom_destroy(geos_result);

#ifdef LWGEOM_PROFILE_BUILDAREA
  lwnotice("Self-unioning");
#endif

  /* Run a single overlay operation to dissolve shared edges */
  shp = GEOSUnionCascaded(tmp);
  if ( ! shp )
  {
    GEOSGeom_destroy(tmp);
    return 0; /* exception */
  }

#ifdef LWGEOM_PROFILE_BUILDAREA
  lwnotice("Final cleanup");
#endif

  GEOSGeom_destroy(tmp);

  GEOSSetSRID(shp, srid);

  return shp;
}
コード例 #17
0
ファイル: lwgeom_geos.c プロジェクト: gravitystorm/postgis
GEOSGeometry*
LWGEOM_GEOS_buildArea(const GEOSGeometry* geom_in)
{
	GEOSGeometry *tmp;
	GEOSGeometry *geos_result, *shp;
	GEOSGeometry const *vgeoms[1];
	uint32_t i, ngeoms;
	int srid = GEOSGetSRID(geom_in);

	vgeoms[0] = geom_in;
	geos_result = GEOSPolygonize(vgeoms, 1);

	LWDEBUGF(3, "GEOSpolygonize returned @ %p", geos_result);

	/* Null return from GEOSpolygonize (an exception) */
	if ( ! geos_result ) return 0;

	/*
	 * We should now have a collection
	 */
#if PARANOIA_LEVEL > 0
	if ( GEOSGeometryTypeId(geos_result) != COLLECTIONTYPE )
	{
		GEOSGeom_destroy(geos_result);
		lwerror("Unexpected return from GEOSpolygonize");
		return 0;
	}
#endif

	ngeoms = GEOSGetNumGeometries(geos_result);

	LWDEBUGF(3, "GEOSpolygonize: ngeoms in polygonize output: %d", ngeoms);
	LWDEBUGF(3, "GEOSpolygonize: polygonized:%s",
	               lwgeom_to_ewkt(GEOS2LWGEOM(geos_result, 0)));

	/*
	 * No geometries in collection, early out
	 */
	if ( ngeoms == 0 )
	{
		GEOSSetSRID(geos_result, srid);
		return geos_result;
	}

	/*
	 * Return first geometry if we only have one in collection,
	 * to avoid the unnecessary Geometry clone below.
	 */
	if ( ngeoms == 1 )
	{
		tmp = (GEOSGeometry *)GEOSGetGeometryN(geos_result, 0);
		if ( ! tmp )
		{
			GEOSGeom_destroy(geos_result);
			return 0; /* exception */
		}
		shp = GEOSGeom_clone(tmp);
		GEOSGeom_destroy(geos_result); /* only safe after the clone above */
		GEOSSetSRID(shp, srid);
		return shp;
	}

	/*
	 * Iteratively invoke symdifference on outer rings
	 * as suggested by Carl Anderson:
	 * postgis-devel/2005-December/001805.html
	 */
	shp = NULL;
	for (i=0; i<ngeoms; ++i)
	{
		GEOSGeom extring;
		GEOSCoordSeq sq;

		/*
		 * Construct a Polygon from geometry i exterior ring
		 * We don't use GEOSGeom_clone on the ExteriorRing
		 * due to a bug in CAPI contained in GEOS 2.2 branch
		 * failing to properly return a LinearRing from
		 * a LinearRing clone.
		 */
		sq=GEOSCoordSeq_clone(GEOSGeom_getCoordSeq(
		                          GEOSGetExteriorRing(GEOSGetGeometryN( geos_result, i))
		                      ));
		extring = GEOSGeom_createPolygon(
		              GEOSGeom_createLinearRing(sq),
		              NULL, 0
		          );

		if ( extring == NULL ) /* exception */
		{
			lwerror("GEOSCreatePolygon threw an exception");
			return 0;
		}

		if ( shp == NULL )
		{
			shp = extring;
			LWDEBUGF(3, "GEOSpolygonize: shp:%s",
			               lwgeom_to_ewkt(GEOS2LWGEOM(shp, 0)));
		}
		else
		{
			tmp = GEOSSymDifference(shp, extring);
			LWDEBUGF(3, "GEOSpolygonize: SymDifference(%s, %s):%s",
			               lwgeom_to_ewkt(GEOS2LWGEOM(shp, 0)),
			               lwgeom_to_ewkt(GEOS2LWGEOM(extring, 0)),
			               lwgeom_to_ewkt(GEOS2LWGEOM(tmp, 0))
			              );
			GEOSGeom_destroy(shp);
			GEOSGeom_destroy(extring);
			shp = tmp;
		}
	}

	GEOSGeom_destroy(geos_result);

	GEOSSetSRID(shp, srid);

	return shp;
}
コード例 #18
0
ファイル: geometry.cpp プロジェクト: netconstructor/node-geos
void Geometry::SetSRID(Local<String> name, Local<Value> value, const AccessorInfo& info)
{
    Geometry *geom = ObjectWrap::Unwrap<Geometry>(info.Holder());
    GEOSSetSRID(geom->geos_geom_, value->Int32Value());
}