Example #1
0
static LWGEOM*
parse_geojson_multipolygon(json_object *geojson, bool *hasz,  int *root_srid)
{
	LWGEOM *geom = NULL;
	int i, j, k;
	json_object* poObjPolys = NULL;

	if (!*root_srid)
	{
		geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, *root_srid, 1, 0);
	}
	else
	{
		geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, -1, 1, 0);
	}

	poObjPolys = findMemberByName( geojson, "coordinates" );
	if ( ! poObjPolys )
		geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);

	if( json_type_array == json_object_get_type( poObjPolys ) )
	{
		const int nPolys = json_object_array_length( poObjPolys );

		for(i = 0; i < nPolys; ++i)
		{
			POINTARRAY **ppa;
			json_object* poObjPoly = NULL;
			poObjPoly = json_object_array_get_idx( poObjPolys, i );

			ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*));

			if( json_type_array == json_object_get_type( poObjPoly ) )
			{
				int nPoints;
				json_object* points = NULL;
				int ring = json_object_array_length( poObjPoly );
				ppa[0] = ptarray_construct_empty(1, 0, 1);

				points = json_object_array_get_idx( poObjPoly, 0 );
				nPoints = json_object_array_length( points );

				for (j=0; j < nPoints; j++ )
				{
					json_object* coords = NULL;
					coords = json_object_array_get_idx( points, j );
					parse_geojson_coord(coords, hasz, ppa[0]);
				}

				for(j = 1; j < ring; ++j)
				{
					int nPoints;
					ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa, sizeof(POINTARRAY*) * (j + 1));
					ppa[i] = ptarray_construct_empty(1, 0, 1);
					points = json_object_array_get_idx( poObjPoly, j );

					nPoints = json_object_array_length( points );
					for (k=0; k < nPoints; k++ )
					{
						json_object* coords = NULL;
						coords = json_object_array_get_idx( points, k );
						parse_geojson_coord(coords, hasz, ppa[i]);
					}
				}

				geom = (LWGEOM*)lwmpoly_add_lwpoly((LWMPOLY*)geom,
				                                   (LWPOLY*)lwpoly_construct(*root_srid, NULL, ring, ppa));
			}
		}
	}

	return geom;
}
Example #2
0
/* Return an LWGEOM from a Geometry */
LWGEOM *
GEOS2LWGEOM(const GEOSGeometry *geom, char want3d)
{
	int type = GEOSGeomTypeId(geom) ;
	int hasZ;
	int SRID = GEOSGetSRID(geom);

	/* GEOS's 0 is equivalent to our unknown as for SRID values */
	if ( SRID == 0 ) SRID = SRID_UNKNOWN;

	if ( want3d )
	{
		hasZ = GEOSHasZ(geom);
		if ( ! hasZ )
		{
			LWDEBUG(3, "Geometry has no Z, won't provide one");

			want3d = 0;
		}
	}

/*
	if ( GEOSisEmpty(geom) )
	{
		return (LWGEOM*)lwcollection_construct_empty(COLLECTIONTYPE, SRID, want3d, 0);
	}
*/

	switch (type)
	{
		const GEOSCoordSequence *cs;
		POINTARRAY *pa, **ppaa;
		const GEOSGeometry *g;
		LWGEOM **geoms;
		uint32_t i, ngeoms;

	case GEOS_POINT:
		LWDEBUG(4, "lwgeom_from_geometry: it's a Point");
		cs = GEOSGeom_getCoordSeq(geom);
		if ( GEOSisEmpty(geom) )
		  return (LWGEOM*)lwpoint_construct_empty(SRID, want3d, 0);
		pa = ptarray_from_GEOSCoordSeq(cs, want3d);
		return (LWGEOM *)lwpoint_construct(SRID, NULL, pa);

	case GEOS_LINESTRING:
	case GEOS_LINEARRING:
		LWDEBUG(4, "lwgeom_from_geometry: it's a LineString or LinearRing");
		if ( GEOSisEmpty(geom) )
		  return (LWGEOM*)lwline_construct_empty(SRID, want3d, 0);

		cs = GEOSGeom_getCoordSeq(geom);
		pa = ptarray_from_GEOSCoordSeq(cs, want3d);
		return (LWGEOM *)lwline_construct(SRID, NULL, pa);

	case GEOS_POLYGON:
		LWDEBUG(4, "lwgeom_from_geometry: it's a Polygon");
		if ( GEOSisEmpty(geom) )
		  return (LWGEOM*)lwpoly_construct_empty(SRID, want3d, 0);
		ngeoms = GEOSGetNumInteriorRings(geom);
		ppaa = lwalloc(sizeof(POINTARRAY *)*(ngeoms+1));
		g = GEOSGetExteriorRing(geom);
		cs = GEOSGeom_getCoordSeq(g);
		ppaa[0] = ptarray_from_GEOSCoordSeq(cs, want3d);
		for (i=0; i<ngeoms; i++)
		{
			g = GEOSGetInteriorRingN(geom, i);
			cs = GEOSGeom_getCoordSeq(g);
			ppaa[i+1] = ptarray_from_GEOSCoordSeq(cs,
			                                      want3d);
		}
		return (LWGEOM *)lwpoly_construct(SRID, NULL,
		                                  ngeoms+1, ppaa);

	case GEOS_MULTIPOINT:
	case GEOS_MULTILINESTRING:
	case GEOS_MULTIPOLYGON:
	case GEOS_GEOMETRYCOLLECTION:
		LWDEBUG(4, "lwgeom_from_geometry: it's a Collection or Multi");

		ngeoms = GEOSGetNumGeometries(geom);
		geoms = NULL;
		if ( ngeoms )
		{
			geoms = lwalloc(sizeof(LWGEOM *)*ngeoms);
			for (i=0; i<ngeoms; i++)
			{
				g = GEOSGetGeometryN(geom, i);
				geoms[i] = GEOS2LWGEOM(g, want3d);
			}
		}
		return (LWGEOM *)lwcollection_construct(type,
		                                        SRID, NULL, ngeoms, geoms);

	default:
		lwerror("GEOS2LWGEOM: unknown geometry type: %d", type);
		return NULL;

	}

}
Example #3
0
int *
lwgeom_cluster_2d_kmeans(const LWGEOM **geoms, int ngeoms, int k)
{
	int i;
	int num_centroids = 0;
	LWGEOM **centroids;
	POINT2D *centers_raw;
	const POINT2D *cp;
	POINT2D min = { DBL_MAX,   DBL_MAX };
	POINT2D max = { -DBL_MAX, -DBL_MAX };
	double dx, dy;
	kmeans_config config;
	kmeans_result result;
	int *seen;
	int sidx = 0;

	assert(k>0);
	assert(ngeoms>0);
	assert(geoms);

    /* Initialize our static structs */
    memset(&config, 0, sizeof(kmeans_config));
    memset(&result, 0, sizeof(kmeans_result));

	if (ngeoms<k)
	{
		lwerror("%s: number of geometries is less than the number of clusters requested", __func__);
	}

	/* We'll hold the temporary centroid objects here */
	centroids = lwalloc(sizeof(LWGEOM*) * ngeoms);
	memset(centroids, 0, sizeof(LWGEOM*) * ngeoms);

	/* The vector of cluster means. We have to allocate a */
	/* chunk of memory for these because we'll be mutating them */
	/* in the kmeans algorithm */
	centers_raw = lwalloc(sizeof(POINT2D) * k);
	memset(centers_raw, 0, sizeof(POINT2D) * k);

	/* K-means configuration setup */
	config.objs = lwalloc(sizeof(Pointer) * ngeoms);
	config.num_objs = ngeoms;
	config.clusters = lwalloc(sizeof(int) * ngeoms);
	config.centers = lwalloc(sizeof(Pointer) * k);
	config.k = k;
	config.max_iterations = 0;
	config.distance_method = lwkmeans_pt_distance;
	config.centroid_method = lwkmeans_pt_centroid;

	/* Clean the memory */
	memset(config.objs, 0, sizeof(Pointer) * ngeoms);
	memset(config.clusters, 0, sizeof(int) * ngeoms);
	memset(config.centers, 0, sizeof(Pointer) * k);

	/* Prepare the list of object pointers for K-means */
	for (i = 0; i < ngeoms; i++)
	{
		const LWGEOM *geom = geoms[i];
		LWPOINT *lwpoint;

		/* Null/empty geometries get a NULL pointer */
		if ((!geom) || lwgeom_is_empty(geom))
		{
			config.objs[i] = NULL;
			continue;
		}

		/* If the input is a point, use its coordinates */
		/* If its not a point, convert it to one via centroid */
		if (lwgeom_get_type(geom) != POINTTYPE)
		{
			LWGEOM *centroid = lwgeom_centroid(geom);
			if ((!centroid) || lwgeom_is_empty(centroid))
			{
				config.objs[i] = NULL;
				continue;
			}
			centroids[num_centroids++] = centroid;
			lwpoint = lwgeom_as_lwpoint(centroid);
		}
		else
		{
			lwpoint = lwgeom_as_lwpoint(geom);
		}

		/* Store a pointer to the POINT2D we are interested in */
		cp = getPoint2d_cp(lwpoint->point, 0);
		config.objs[i] = (Pointer)cp;

		/* Since we're already here, let's calculate the extrema of the set */
		if (cp->x < min.x) min.x = cp->x;
		if (cp->y < min.y) min.y = cp->y;
		if (cp->x > max.x) max.x = cp->x;
		if (cp->y > max.y) max.y = cp->y;
	}

	/*
	* We map a uniform assignment of points in the area covered by the set
	* onto actual points in the set
	*/
	dx = (max.x - min.x)/k;
	dy = (max.y - min.y)/k;
	seen = lwalloc(sizeof(int)*config.k);
	memset(seen, 0, sizeof(int)*config.k);
	for (i = 0; i < k; i++)
	{
		int closest;
		POINT2D p;
		int j;

		/* Calculate a point in the range */
		p.x = min.x + dx * (i + 0.5);
		p.y = min.y + dy * (i + 0.5);

		/* Find the data point closest to the calculated point */
		closest = lwkmeans_pt_closest(config.objs, config.num_objs, &p);

		/* If something is terrible wrong w/ data, cannot find a closest */
		if (closest < 0)
			lwerror("unable to calculate cluster seed points, too many NULLs or empties?");

		/* Ensure we aren't already using that point as a seed */
		j = 0;
		while(j < sidx)
		{
			if (seen[j] == closest)
			{
				closest = (closest + 1) % config.num_objs;
				j = 0;
			}
			else
			{
				j++;
			}
		}
		seen[sidx++] = closest;

		/* Copy the point coordinates into the initial centers array */
		/* This is ugly, but the centers array is an array of */
		/* pointers to points, not an array of points */
		centers_raw[i] = *((POINT2D*)config.objs[closest]);
		config.centers[i] = &(centers_raw[i]);
	}

	result = kmeans(&config);

	/* Before error handling, might as well clean up all the inputs */
	lwfree(config.objs);
	lwfree(config.centers);
	lwfree(centers_raw);
	lwfree(centroids);
	lwfree(seen);

	/* Good result */
	if (result == KMEANS_OK)
		return config.clusters;

	/* Bad result, not going to need the answer */
	lwfree(config.clusters);
	if (result == KMEANS_EXCEEDED_MAX_ITERATIONS)
	{
		lwerror("%s did not converge after %d iterations", __func__, config.max_iterations);
		return NULL;
	}

	/* Unknown error */
	return NULL;
}
Example #4
0
/* We supposed that the geometry is valid
   we could have wrong result if not */
int lwtin_is_closed(const LWTIN *tin)
{
	int i, j, k;
	int narcs, carc;
	int found;
	tin_arcs arcs;
	POINT4D pa, pb;
	LWTRIANGLE *patch;

	/* If surface is not 3D, it's can't be closed */
	if (!FLAGS_GET_Z(tin->flags)) return 0;

	/* Max theorical arcs number if no one is shared ... */
	narcs = 3 * tin->ngeoms;

	arcs = lwalloc(sizeof(struct struct_tin_arcs) * narcs);
	for (i=0, carc=0; i < tin->ngeoms ; i++)
	{

		patch = (LWTRIANGLE *) tin->geoms[i];
		for (j=0; j < 3 ; j++)
		{

			getPoint4d_p(patch->points, j,   &pa);
			getPoint4d_p(patch->points, j+1, &pb);

			/* Make sure to order the 'lower' point first */
			if ( (pa.x > pb.x) ||
			        (pa.x == pb.x && pa.y > pb.y) ||
			        (pa.x == pb.x && pa.y == pb.y && pa.z > pb.z) )
			{
				pa = pb;
				getPoint4d_p(patch->points, j, &pb);
			}

			for (found=0, k=0; k < carc ; k++)
			{

				if (  ( arcs[k].ax == pa.x && arcs[k].ay == pa.y &&
				        arcs[k].az == pa.z && arcs[k].bx == pb.x &&
				        arcs[k].by == pb.y && arcs[k].bz == pb.z &&
				        arcs[k].face != i) )
				{
					arcs[k].cnt++;
					found = 1;

					/* Look like an invalid TIN
					      anyway not a closed one */
					if (arcs[k].cnt > 2)
					{
						lwfree(arcs);
						return 0;
					}
				}
			}

			if (!found)
			{
				arcs[carc].cnt=1;
				arcs[carc].face=i;
				arcs[carc].ax = pa.x;
				arcs[carc].ay = pa.y;
				arcs[carc].az = pa.z;
				arcs[carc].bx = pb.x;
				arcs[carc].by = pb.y;
				arcs[carc].bz = pb.z;
				carc++;

				/* Look like an invalid TIN
				      anyway not a closed one */
				if (carc > narcs)
				{
					lwfree(arcs);
					return 0;
				}
			}
		}
	}

	/* A TIN is closed if each edge
	       is shared by exactly 2 faces */
	for (k=0; k < carc ; k++)
	{
		if (arcs[k].cnt != 2)
		{
			lwfree(arcs);
			return 0;
		}
	}
	lwfree(arcs);

	/* Invalid TIN case */
	if (carc < tin->ngeoms) return 0;

	return 1;
}
Example #5
0
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;
}
Example #6
0
/*
 * Add an edge to a face in a tgeom
 * Edge is describded as a starting and an ending point
 * Points are really copied
 * Return the new tgeom pointer
 */
static TGEOM*
tgeom_add_face_edge(TGEOM *tgeom, int face_id, POINT4D *s, POINT4D *e)
{
	int nedges, edge_id;

	assert(tgeom);
	assert(s);
	assert(e);

	edge_id = tgeom_is_edge(tgeom, s, e);

	if (edge_id)
	{
		tgeom->edges[abs(edge_id)]->count++;
		LWDEBUGF(3, "face [%i] Founded Edge: %i\n",
		         face_id, edge_id);
	}
	else
	{
		if ((tgeom->nedges + 1) == INT_MAX)
			lwerror("tgeom_add_face_edge: Unable to alloc more than %i edges", INT_MAX);

		/* alloc edges array */
		if (tgeom->maxedges == 0)
		{
			tgeom->edges = (TEDGE**) lwalloc(sizeof(TEDGE*) * 4);
			tgeom->maxedges = 4;
		}
		if (tgeom->maxedges >= (tgeom->nedges + 1))
		{
			tgeom->edges = (TEDGE **) lwrealloc(tgeom->edges,
			                         sizeof(TEDGE*) * tgeom->maxedges * 2);
			tgeom->maxedges *= 2;
		}

		edge_id = ++tgeom->nedges; /* edge_id is 1 based */
		tgeom->edges[edge_id] = (TEDGE*) lwalloc(sizeof(TEDGE));
		tgeom->edges[edge_id]->s = lwalloc(sizeof(POINT4D));
		tgeom->edges[edge_id]->e = lwalloc(sizeof(POINT4D));
		memcpy(tgeom->edges[edge_id]->s, s, sizeof(POINT4D));
		memcpy(tgeom->edges[edge_id]->e, e, sizeof(POINT4D));
		tgeom->edges[edge_id]->count = 1;

		LWDEBUGF(3, "face [%i] adding edge [%i] (%lf, %lf, %lf, %lf) -> (%lf, %lf, %lf, %lf)\n",
		         face_id, edge_id, s->x, s->y, s->z, s->m, e->x, e->y, e->z, e->m);
	}

	nedges = tgeom->faces[face_id]->nedges;
	if (tgeom->faces[face_id]->maxedges == 0)
	{
		tgeom->faces[face_id]->edges = (int *) lwalloc(sizeof(int) * 4);
		tgeom->faces[face_id]->maxedges = 4;
	}
	if (tgeom->faces[face_id]->maxedges == nedges)
	{
		tgeom->faces[face_id]->edges = (int *) lwrealloc(tgeom->faces[face_id]->edges,
		                               sizeof(int) * tgeom->faces[face_id]->maxedges * 2);
		tgeom->faces[face_id]->maxedges *= 2;
	}

	LWDEBUGF(3, "face [%i] add %i in edge array in %i pos\n",
	         face_id, edge_id, tgeom->faces[face_id]->nedges);

	tgeom->faces[face_id]->edges[nedges]= edge_id;
	tgeom->faces[face_id]->nedges++;

	return tgeom;
}
Example #7
0
/* We supposed that the geometry is valid
   we could have wrong result if not */
int lwpsurface_is_closed(const LWPSURFACE *psurface)
{
	int i, j, k;
	int narcs, carc;
	int found;
	psurface_arcs arcs;
	POINT4D pa, pb;
	LWPOLY *patch;

	/* If surface is not 3D, it's can't be closed */
	if (!FLAGS_GET_Z(psurface->flags)) return 0;

	/* If surface is less than 4 faces hard to be closed too */
	if (psurface->ngeoms < 4) return 0;

	/* Max theorical arcs number if no one is shared ... */
	for (i=0, narcs=0 ; i < psurface->ngeoms ; i++)
	{
		patch = (LWPOLY *) psurface->geoms[i];
		narcs += patch->rings[0]->npoints - 1;
	}

	arcs = lwalloc(sizeof(struct struct_psurface_arcs) * narcs);
	for (i=0, carc=0; i < psurface->ngeoms ; i++)
	{

		patch = (LWPOLY *) psurface->geoms[i];
		for (j=0; j < patch->rings[0]->npoints - 1; j++)
		{

			getPoint4d_p(patch->rings[0], j,   &pa);
			getPoint4d_p(patch->rings[0], j+1, &pb);

			/* remove redundant points if any */
			if (pa.x == pb.x && pa.y == pb.y && pa.z == pb.z) continue;

			/* Make sure to order the 'lower' point first */
			if ( (pa.x > pb.x) ||
			        (pa.x == pb.x && pa.y > pb.y) ||
			        (pa.x == pb.x && pa.y == pb.y && pa.z > pb.z) )
			{
				pa = pb;
				getPoint4d_p(patch->rings[0], j, &pb);
			}

			for (found=0, k=0; k < carc ; k++)
			{

				if (  ( arcs[k].ax == pa.x && arcs[k].ay == pa.y &&
				        arcs[k].az == pa.z && arcs[k].bx == pb.x &&
				        arcs[k].by == pb.y && arcs[k].bz == pb.z &&
				        arcs[k].face != i) )
				{
					arcs[k].cnt++;
					found = 1;

					/* Look like an invalid PolyhedralSurface
					      anyway not a closed one */
					if (arcs[k].cnt > 2)
					{
						lwfree(arcs);
						return 0;
					}
				}
			}

			if (!found)
			{
				arcs[carc].cnt=1;
				arcs[carc].face=i;
				arcs[carc].ax = pa.x;
				arcs[carc].ay = pa.y;
				arcs[carc].az = pa.z;
				arcs[carc].bx = pb.x;
				arcs[carc].by = pb.y;
				arcs[carc].bz = pb.z;
				carc++;

				/* Look like an invalid PolyhedralSurface
				      anyway not a closed one */
				if (carc > narcs)
				{
					lwfree(arcs);
					return 0;
				}
			}
		}
	}

	/* A polyhedron is closed if each edge
	       is shared by exactly 2 faces */
	for (k=0; k < carc ; k++)
	{
		if (arcs[k].cnt != 2)
		{
			lwfree(arcs);
			return 0;
		}
	}
	lwfree(arcs);

	/* Invalid Polyhedral case */
	if (carc < psurface->ngeoms) return 0;

	return 1;
}
Example #8
0
Datum BOX2D_to_LWGEOM(PG_FUNCTION_ARGS)
{
	GBOX *box = (GBOX *)PG_GETARG_POINTER(0);
	POINTARRAY *pa = ptarray_construct_empty(0, 0, 5);
	POINT4D pt;
	GSERIALIZED *result;


	/*
	 * Alter BOX2D cast so that a valid geometry is always
	 * returned depending upon the size of the BOX2D. The
	 * code makes the following assumptions:
	 *     - If the BOX2D is a single point then return a
	 *     POINT geometry
	 *     - If the BOX2D represents either a horizontal or
	 *     vertical line, return a LINESTRING geometry
	 *     - Otherwise return a POLYGON
	 */

	if ( (box->xmin == box->xmax) && (box->ymin == box->ymax) )
	{
		/* Construct and serialize point */
		LWPOINT *point = lwpoint_make2d(SRID_UNKNOWN, box->xmin, box->ymin);
		result = geometry_serialize(lwpoint_as_lwgeom(point));
		lwpoint_free(point);
	}
	else if ( (box->xmin == box->xmax) || (box->ymin == box->ymax) )
	{
		LWLINE *line;

		/* Assign coordinates to point array */
		pt.x = box->xmin;
		pt.y = box->ymin;
		ptarray_append_point(pa, &pt, LW_TRUE);
		pt.x = box->xmax;
		pt.y = box->ymax;
		ptarray_append_point(pa, &pt, LW_TRUE);

		/* Construct and serialize linestring */
		line = lwline_construct(SRID_UNKNOWN, NULL, pa);
		result = geometry_serialize(lwline_as_lwgeom(line));
		lwline_free(line);
	}
	else
	{
		LWPOLY *poly;
		POINTARRAY **ppa = lwalloc(sizeof(POINTARRAY*));

		/* Assign coordinates to point array */
		pt.x = box->xmin;
		pt.y = box->ymin;
		ptarray_append_point(pa, &pt, LW_TRUE);
		pt.x = box->xmin;
		pt.y = box->ymax;
		ptarray_append_point(pa, &pt, LW_TRUE);
		pt.x = box->xmax;
		pt.y = box->ymax;
		ptarray_append_point(pa, &pt, LW_TRUE);
		pt.x = box->xmax;
		pt.y = box->ymin;
		ptarray_append_point(pa, &pt, LW_TRUE);
		pt.x = box->xmin;
		pt.y = box->ymin;
		ptarray_append_point(pa, &pt, LW_TRUE);

		/* Construct polygon */
		ppa[0] = pa;
		poly = lwpoly_construct(SRID_UNKNOWN, NULL, 1, ppa);
		result = geometry_serialize(lwpoly_as_lwgeom(poly));
		lwpoly_free(poly);
	}

	PG_RETURN_POINTER(result);
}
Example #9
0
GBOX* gbox_clone(const GBOX *gbox)
{
	GBOX *g = lwalloc(sizeof(GBOX));
	memcpy(g, gbox, sizeof(GBOX));
	return g;
}
Example #10
0
LWGEOM*
pta_unstroke(const POINTARRAY *points, int type, int srid)
{
	int i = 0, j, k;
	POINT4D a1, a2, a3, b;
	POINT4D first, center;
	char *edges_in_arcs;
	int found_arc = LW_FALSE;
	int current_arc = 1;
	int num_edges;
	int edge_type; /* non-zero if edge is part of an arc */
	int start, end;
	LWCOLLECTION *outcol;
	/* Minimum number of edges, per quadrant, required to define an arc */
	const unsigned int min_quad_edges = 2;

	/* Die on null input */
	if ( ! points )
		lwerror("pta_unstroke called with null pointarray");

	/* Null on empty input? */
	if ( points->npoints == 0 )
		return NULL;

	/* We can't desegmentize anything shorter than four points */
	if ( points->npoints < 4 )
	{
		/* Return a linestring here*/
		lwerror("pta_unstroke needs implementation for npoints < 4");
	}

	/* Allocate our result array of vertices that are part of arcs */
	num_edges = points->npoints - 1;
	edges_in_arcs = lwalloc(num_edges + 1);
	memset(edges_in_arcs, 0, num_edges + 1);

	/* We make a candidate arc of the first two edges, */
	/* And then see if the next edge follows it */
	while( i < num_edges-2 )
	{
		unsigned int arc_edges;
		double num_quadrants;
		double angle;

		found_arc = LW_FALSE;
		/* Make candidate arc */
		getPoint4d_p(points, i  , &a1);
		getPoint4d_p(points, i+1, &a2);
		getPoint4d_p(points, i+2, &a3);
		memcpy(&first, &a1, sizeof(POINT4D));

		for( j = i+3; j < num_edges+1; j++ )
		{
			LWDEBUGF(4, "i=%d, j=%d", i, j);
			getPoint4d_p(points, j, &b);
			/* Does this point fall on our candidate arc? */
			if ( pt_continues_arc(&a1, &a2, &a3, &b) )
			{
				/* Yes. Mark this edge and the two preceding it as arc components */
				LWDEBUGF(4, "pt_continues_arc #%d", current_arc);
				found_arc = LW_TRUE;
				for ( k = j-1; k > j-4; k-- )
					edges_in_arcs[k] = current_arc;
			}
			else
			{
				/* No. So we're done with this candidate arc */
				LWDEBUG(4, "pt_continues_arc = false");
				current_arc++;
				break;
			}

			memcpy(&a1, &a2, sizeof(POINT4D));
			memcpy(&a2, &a3, sizeof(POINT4D));
			memcpy(&a3,  &b, sizeof(POINT4D));
		}
		/* Jump past all the edges that were added to the arc */
		if ( found_arc )
		{
			/* Check if an arc was composed by enough edges to be
			 * really considered an arc
			 * See http://trac.osgeo.org/postgis/ticket/2420
			 */
			arc_edges = j - 1 - i;
			LWDEBUGF(4, "arc defined by %d edges found", arc_edges);
			if ( first.x == b.x && first.y == b.y ) {
				LWDEBUG(4, "arc is a circle");
				num_quadrants = 4;
			}
			else {
				lw_arc_center((POINT2D*)&first, (POINT2D*)&b, (POINT2D*)&a1, (POINT2D*)&center);
				angle = lw_arc_angle((POINT2D*)&first, (POINT2D*)&center, (POINT2D*)&b);
        int p2_side = lw_segment_side((POINT2D*)&first, (POINT2D*)&a1, (POINT2D*)&b);
        if ( p2_side >= 0 ) angle = -angle;

				if ( angle < 0 ) angle = 2 * M_PI + angle;
				num_quadrants = ( 4 * angle ) / ( 2 * M_PI );
				LWDEBUGF(4, "arc angle (%g %g, %g %g, %g %g) is %g (side is %d), quandrants:%g", first.x, first.y, center.x, center.y, b.x, b.y, angle, p2_side, num_quadrants);
			}
			/* a1 is first point, b is last point */
			if ( arc_edges < min_quad_edges * num_quadrants ) {
				LWDEBUGF(4, "Not enough edges for a %g quadrants arc, %g needed", num_quadrants, min_quad_edges * num_quadrants);
				for ( k = j-1; k >= i; k-- )
					edges_in_arcs[k] = 0;
			}

			i = j-1;
		}
		else
		{
			/* Mark this edge as a linear edge */
			edges_in_arcs[i] = 0;
			i = i+1;
		}
	}

#if POSTGIS_DEBUG_LEVEL > 3
	{
		char *edgestr = lwalloc(num_edges+1);
		for ( i = 0; i < num_edges; i++ )
		{
			if ( edges_in_arcs[i] )
				edgestr[i] = 48 + edges_in_arcs[i];
			else
				edgestr[i] = '.';
		}
		edgestr[num_edges] = 0;
		LWDEBUGF(3, "edge pattern %s", edgestr);
		lwfree(edgestr);
	}
#endif

	start = 0;
	edge_type = edges_in_arcs[0];
	outcol = lwcollection_construct_empty(COMPOUNDTYPE, srid, ptarray_has_z(points), ptarray_has_m(points));
	for( i = 1; i < num_edges; i++ )
	{
		if( edge_type != edges_in_arcs[i] )
		{
			end = i - 1;
			lwcollection_add_lwgeom(outcol, geom_from_pa(points, srid, edge_type, start, end));
			start = i;
			edge_type = edges_in_arcs[i];
		}
	}
	lwfree(edges_in_arcs); /* not needed anymore */

	/* Roll out last item */
	end = num_edges - 1;
	lwcollection_add_lwgeom(outcol, geom_from_pa(points, srid, edge_type, start, end));

	/* Strip down to singleton if only one entry */
	if ( outcol->ngeoms == 1 )
	{
		LWGEOM *outgeom = outcol->geoms[0];
		outcol->ngeoms = 0; lwcollection_free(outcol);
		return outgeom;
	}
	return lwcollection_as_lwgeom(outcol);
}
Datum LWGEOM_line_substring(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
	double from = PG_GETARG_FLOAT8(1);
	double to = PG_GETARG_FLOAT8(2);
	LWGEOM *olwgeom;
	POINTARRAY *ipa, *opa;
	GSERIALIZED *ret;
	int type = gserialized_get_type(geom);

	if ( from < 0 || from > 1 )
	{
		elog(ERROR,"line_interpolate_point: 2nd arg isn't within [0,1]");
		PG_RETURN_NULL();
	}

	if ( to < 0 || to > 1 )
	{
		elog(ERROR,"line_interpolate_point: 3rd arg isn't within [0,1]");
		PG_RETURN_NULL();
	}

	if ( from > to )
	{
		elog(ERROR, "2nd arg must be smaller then 3rd arg");
		PG_RETURN_NULL();
	}

	if ( type == LINETYPE )
	{
		LWLINE *iline = lwgeom_as_lwline(lwgeom_from_gserialized(geom));

		if ( lwgeom_is_empty((LWGEOM*)iline) )
		{
			/* TODO return empty line */
			lwline_release(iline);
			PG_FREE_IF_COPY(geom, 0);
			PG_RETURN_NULL();
		}

		ipa = iline->points;

		opa = ptarray_substring(ipa, from, to, 0);

		if ( opa->npoints == 1 ) /* Point returned */
			olwgeom = (LWGEOM *)lwpoint_construct(iline->srid, NULL, opa);
		else
			olwgeom = (LWGEOM *)lwline_construct(iline->srid, NULL, opa);

	}
	else if ( type == MULTILINETYPE )
	{
		LWMLINE *iline;
		int i = 0, g = 0;
		int homogeneous = LW_TRUE;
		LWGEOM **geoms = NULL;
		double length = 0.0, sublength = 0.0, minprop = 0.0, maxprop = 0.0;

		iline = lwgeom_as_lwmline(lwgeom_from_gserialized(geom));

		if ( lwgeom_is_empty((LWGEOM*)iline) )
		{
			/* TODO return empty collection */
			lwmline_release(iline);
			PG_FREE_IF_COPY(geom, 0);
			PG_RETURN_NULL();
		}

		/* Calculate the total length of the mline */
		for ( i = 0; i < iline->ngeoms; i++ )
		{
			LWLINE *subline = (LWLINE*)iline->geoms[i];
			if ( subline->points && subline->points->npoints > 1 )
				length += ptarray_length_2d(subline->points);
		}

		geoms = lwalloc(sizeof(LWGEOM*) * iline->ngeoms);

		/* Slice each sub-geometry of the multiline */
		for ( i = 0; i < iline->ngeoms; i++ )
		{
			LWLINE *subline = (LWLINE*)iline->geoms[i];
			double subfrom = 0.0, subto = 0.0;

			if ( subline->points && subline->points->npoints > 1 )
				sublength += ptarray_length_2d(subline->points);

			/* Calculate proportions for this subline */
			minprop = maxprop;
			maxprop = sublength / length;

			/* This subline doesn't reach the lowest proportion requested
			   or is beyond the highest proporton */
			if ( from > maxprop || to < minprop )
				continue;

			if ( from <= minprop )
				subfrom = 0.0;
			if ( to >= maxprop )
				subto = 1.0;

			if ( from > minprop && from <= maxprop )
				subfrom = (from - minprop) / (maxprop - minprop);

			if ( to < maxprop && to >= minprop )
				subto = (to - minprop) / (maxprop - minprop);


			opa = ptarray_substring(subline->points, subfrom, subto, 0);
			if ( opa && opa->npoints > 0 )
			{
				if ( opa->npoints == 1 ) /* Point returned */
				{
					geoms[g] = (LWGEOM *)lwpoint_construct(SRID_UNKNOWN, NULL, opa);
					homogeneous = LW_FALSE;
				}
				else
				{
					geoms[g] = (LWGEOM *)lwline_construct(SRID_UNKNOWN, NULL, opa);
				}
				g++;
			}



		}
		/* If we got any points, we need to return a GEOMETRYCOLLECTION */
		if ( ! homogeneous )
			type = COLLECTIONTYPE;

		olwgeom = (LWGEOM*)lwcollection_construct(type, iline->srid, NULL, g, geoms);
	}
	else
	{
		elog(ERROR,"line_substring: 1st arg isn't a line");
		PG_RETURN_NULL();
	}

	ret = geometry_serialize(olwgeom);
	lwgeom_free(olwgeom);
	PG_FREE_IF_COPY(geom, 0);
	PG_RETURN_POINTER(ret);

}
Example #12
0
/*
 * Deserialize a TSERIALIZED struct and
 * return a TGEOM pointer
 */
TGEOM *
tgeom_deserialize(TSERIALIZED *serialized_form)
{
	uint8_t type, flags;
	TGEOM *result;
	uint8_t *loc, *data;
	int i, j;

	assert(serialized_form);
	assert(serialized_form->data);

	data = serialized_form->data;

	/* type and flags */
	type  = data[0];
	flags = data[1];
	result = tgeom_new(type, FLAGS_GET_Z(flags), FLAGS_GET_M(flags));
	loc = data + 2;

	/* srid */
	result->srid = lw_get_int32_t(loc);
	loc += 4;

	/* bbox */
	if (FLAGS_GET_BBOX(flags))
	{
		result->bbox = lwalloc(sizeof(BOX3D));
		memcpy(result->bbox, loc, sizeof(BOX3D));
		loc += sizeof(BOX3D);
	}
	else result->bbox = NULL;

	/* edges number (0=> EMPTY) */
	result->nedges = lw_get_int32_t(loc);
	loc  += 4;

	/* edges */
	result->edges = lwalloc(sizeof(TEDGE*) * (result->nedges + 1));
	for (i=1 ; i <= result->nedges ; i++)
	{
		result->edges[i] = lwalloc(sizeof(TEDGE));
		result->edges[i]->s = lwalloc(sizeof(POINT4D));
		result->edges[i]->e = lwalloc(sizeof(POINT4D));

		/* 3DM specific handle */
		if (!FLAGS_GET_Z(result->flags) && FLAGS_GET_M(result->flags))
		{
			memcpy(result->edges[i]->s, loc, sizeof(double) * 2);
			loc  += sizeof(double) * 2;
			memcpy(&(result->edges[i]->s->m), loc, sizeof(double));
			loc  += sizeof(double);

			memcpy(result->edges[i]->e, loc, sizeof(double) * 2);
			loc  += sizeof(double) * 2;
			memcpy(&(result->edges[i]->e->m), loc, sizeof(double));
			loc  += sizeof(double);
		}
		else /* 2D,3DZ && 4D */
		{
			memcpy(result->edges[i]->s, loc,
			       sizeof(double) * FLAGS_NDIMS(flags));
			loc  += sizeof(double) * FLAGS_NDIMS(flags);

			result->edges[i]->e = lwalloc(sizeof(POINT4D));
			memcpy(result->edges[i]->e, loc,
			       sizeof(double) * FLAGS_NDIMS(flags));
			loc  += sizeof(double) * FLAGS_NDIMS(flags);
		}

		result->edges[i]->count = lw_get_int32_t(loc);
		loc  += 4;
	}

	/* faces number */
	result->nfaces = lw_get_int32_t(loc);
	loc  += 4;

	/* faces */
	result->faces = lwalloc(sizeof(TFACE*) * result->nfaces);
	for (i=0 ; i < result->nfaces ; i++)
	{
		result->faces[i] = lwalloc(sizeof(TFACE));

		/* number of edges */
		result->faces[i]->nedges = lw_get_int32_t(loc);
		loc  += 4;

		/* edges array */
		result->faces[i]->edges = lwalloc(sizeof(TEDGE*)
		                                  * result->faces[i]->nedges);
		memcpy(result->faces[i]->edges, loc, sizeof(TEDGE*)
		       * result->faces[i]->nedges);
		loc  += 4 * result->faces[i]->nedges;

		/* number of rings */
		result->faces[i]->nrings = lw_get_int32_t(loc);
		loc  += 4;

		if (result->faces[i]->nrings)
			result->faces[i]->rings = lwalloc(sizeof(POINTARRAY*)
			                                  * result->faces[i]->nrings);

		for (j=0 ; j < result->faces[i]->nrings ; j++)
		{
			int npoints;

			/* number of points */
			npoints = lw_get_int32_t(loc);
			loc  += 4;

			/* pointarray */
			result->faces[i]->rings[j] = ptarray_construct_reference_data(FLAGS_GET_Z(flags), FLAGS_GET_M(flags), npoints, loc);
			
			loc += sizeof(double)* FLAGS_NDIMS(flags) * npoints;
		}
	}

	return result;
}
Example #13
0
/*
 * Return a LWGEOM pointer from an TGEOM struct
 * Geometries are NOT copied
 */
LWGEOM*
lwgeom_from_tgeom(TGEOM *tgeom)
{
	int i, j, k;
	LWGEOM *geom;
	POINTARRAY *dpa;
	POINTARRAY **ppa;
	int hasz, hasm, edge_id;
	int dims=0;

	assert(tgeom);

	hasz=FLAGS_GET_Z(tgeom->flags);
	hasm=FLAGS_GET_M(tgeom->flags);

	geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, tgeom->srid, hasz, hasm);

	switch (tgeom->type)
	{
	case TINTYPE:
		geom->type = TINTYPE;
		for (i=0 ; i < tgeom->nfaces ; i++)
		{
			FLAGS_SET_Z(dims, hasz?1:0);
			FLAGS_SET_M(dims, hasm?1:0);
			dpa = ptarray_construct_empty(hasz, hasm, 4);

			for (j=0 ; j < tgeom->faces[i]->nedges ; j++)
			{
				edge_id = tgeom->faces[i]->edges[j];
				LWDEBUGF(3, "TIN edge_id: %i\n", edge_id);

				assert(edge_id);
				if (edge_id > 0)
					ptarray_append_point(dpa, tgeom->edges[edge_id]->s, LW_TRUE);
				else
					ptarray_append_point(dpa, tgeom->edges[-edge_id]->e, LW_TRUE);
			}

			edge_id = tgeom->faces[i]->edges[0];
			LWDEBUGF(3, "TIN edge_id: %i\n", edge_id);
			if (edge_id > 0)
				ptarray_append_point(dpa, tgeom->edges[edge_id]->s, LW_TRUE); 
			else
				ptarray_append_point(dpa, tgeom->edges[-edge_id]->e, LW_TRUE); 

			geom = (LWGEOM *) lwtin_add_lwtriangle((LWTIN *) geom,
			                                       lwtriangle_construct(tgeom->srid, NULL, dpa));
		}
		break;

	case POLYHEDRALSURFACETYPE:
		geom->type = POLYHEDRALSURFACETYPE;
		for (i=0 ; i < tgeom->nfaces ; i++)
		{
			FLAGS_SET_Z(dims, hasz?1:0);
			FLAGS_SET_M(dims, hasm?1:0);;
			dpa = ptarray_construct_empty(hasz, hasm, 4);

			for (j=0 ; j < tgeom->faces[i]->nedges ; j++)
			{
				edge_id = tgeom->faces[i]->edges[j];
				assert(edge_id);
				LWDEBUGF(3, "POLYHEDRALSURFACE edge_id: %i\n", edge_id);
				if (edge_id > 0)
					ptarray_append_point(dpa, tgeom->edges[edge_id]->s, LW_TRUE);
				else
					ptarray_append_point(dpa, tgeom->edges[-edge_id]->e, LW_TRUE);
			}

			edge_id = tgeom->faces[i]->edges[0];
			LWDEBUGF(3, "POLYHEDRALSURFACE edge_id: %i\n", edge_id);
			if (edge_id > 0)
				ptarray_append_point(dpa, tgeom->edges[edge_id]->s, LW_TRUE);
			else
				ptarray_append_point(dpa, tgeom->edges[-edge_id]->e, LW_TRUE);

			ppa = lwalloc(sizeof(POINTARRAY*)
			              * (tgeom->faces[i]->nrings + 1));
			ppa[0] = dpa;
			for (k=0; k < tgeom->faces[i]->nrings ; k++)
				ppa[k+1] = tgeom->faces[i]->rings[k];

			geom = (LWGEOM *) lwpsurface_add_lwpoly((LWPSURFACE *) geom,
			                                        lwpoly_construct(tgeom->srid, NULL, k + 1, ppa));
		}
		break;

	default:
		lwerror("lwgeom_from_tgeom: Unkwnown type %i - %s\n",
		        tgeom->type, lwtype_name(tgeom->type));
	}

	if (geom->srid == 0) geom->srid = SRID_UNKNOWN;

	return geom;
}
Example #14
0
/*
 * Add a LWPOLY inside a tgeom
 * Copy geometries from LWPOLY
 */
static TGEOM*
tgeom_add_polygon(TGEOM *tgeom, LWPOLY *poly)
{
	int i;

	assert(tgeom);
	assert(poly);

	if ((tgeom->nfaces + 1) == INT_MAX)
		lwerror("tgeom_add_polygon: Unable to alloc more than %i faces", INT_MAX);

	/* Integrity checks on subgeom, dims and srid */
	if (tgeom->type != POLYHEDRALSURFACETYPE)
		lwerror("tgeom_add_polygon: Unable to handle %s - %s type",
		        tgeom->type, lwtype_name(tgeom->type));

	if (FLAGS_NDIMS(tgeom->flags) != FLAGS_NDIMS(poly->flags))
		lwerror("tgeom_add_polygon: Mixed dimension");

	if (tgeom->srid != poly->srid && (tgeom->srid != 0 && poly->srid != SRID_UNKNOWN))
		lwerror("tgeom_add_polygon: Mixed srid. Tgeom: %i / Polygon: %i",
		        tgeom->srid, poly->srid);

	/* handle face array allocation */
	if (tgeom->maxfaces == 0)
	{
		tgeom->faces = lwalloc(sizeof(TFACE*) * 2);
		tgeom->maxfaces = 2;
	}
	if ((tgeom->maxfaces - 1) == tgeom->nfaces)
	{
		tgeom->faces = lwrealloc(tgeom->faces,
		                         sizeof(TFACE*) * tgeom->maxfaces * 2);
		tgeom->maxfaces *= 2;
	}

	/* add an empty face */
	tgeom->faces[tgeom->nfaces] = lwalloc(sizeof(TFACE));
	tgeom->faces[tgeom->nfaces]->rings = NULL;
	tgeom->faces[tgeom->nfaces]->nrings = 0;
	tgeom->faces[tgeom->nfaces]->nedges = 0;
	tgeom->faces[tgeom->nfaces]->maxedges = 0;

	/* Compute edge on poly external ring */
	for (i=1 ; i < poly->rings[0]->npoints ; i++)
	{
		POINT4D p1, p2;

		getPoint4d_p(poly->rings[0], i-1, &p1);
		getPoint4d_p(poly->rings[0], i,   &p2);
		tgeom_add_face_edge(tgeom, tgeom->nfaces, &p1, &p2);
	}

	/* External ring is already handled by edges */
	tgeom->faces[tgeom->nfaces]->nrings = poly->nrings - 1;

	/* handle rings array allocation */
	if (tgeom->faces[tgeom->nfaces]->nrings >= 1)
		tgeom->faces[tgeom->nfaces]->rings = lwalloc(sizeof(POINTARRAY*)
		                                     * tgeom->faces[tgeom->nfaces]->nrings);

	/* clone internal rings */
	for (i=0 ; i < tgeom->faces[tgeom->nfaces]->nrings ; i++)
		tgeom->faces[tgeom->nfaces]->rings[i]
		= ptarray_clone_deep(poly->rings[i+1]);

	tgeom->nfaces++;

	return tgeom;
}
Example #15
0
Datum LWGEOM_interiorringn_polygon(PG_FUNCTION_ARGS)
{
	GSERIALIZED *geom;
	int32 wanted_index;
	LWCURVEPOLY *curvepoly = NULL;
	LWPOLY *poly = NULL;
	POINTARRAY *ring;
	LWLINE *line;
	LWGEOM *lwgeom;
	GSERIALIZED *result;
	GBOX *bbox = NULL;
	int type;

	POSTGIS_DEBUG(2, "LWGEOM_interierringn_polygon called.");

	wanted_index = PG_GETARG_INT32(1);
	if ( wanted_index < 1 )
	{
		/* elog(ERROR, "InteriorRingN: ring number is 1-based"); */
		PG_RETURN_NULL(); /* index out of range */
	}

	geom = PG_GETARG_GSERIALIZED_P(0);
	type = gserialized_get_type(geom);

	if ( (type != POLYGONTYPE) && (type != CURVEPOLYTYPE) )
	{
		elog(ERROR, "InteriorRingN: geom is not a polygon");
		PG_FREE_IF_COPY(geom, 0);
		PG_RETURN_NULL();
	}
	
	lwgeom = lwgeom_from_gserialized(geom);
	if( lwgeom_is_empty(lwgeom) )
	{
		lwpoly_free(poly);
		PG_FREE_IF_COPY(geom, 0);
		PG_RETURN_NULL();
	}
	
	if ( type == POLYGONTYPE)
	{
		poly = lwgeom_as_lwpoly(lwgeom_from_gserialized(geom));

		/* Ok, now we have a polygon. Let's see if it has enough holes */
		if ( wanted_index >= poly->nrings )
		{
			lwpoly_free(poly);
			PG_FREE_IF_COPY(geom, 0);
			PG_RETURN_NULL();
		}

		ring = poly->rings[wanted_index];

		/* COMPUTE_BBOX==TAINTING */
		if ( poly->bbox ) 
		{
			bbox = lwalloc(sizeof(GBOX));
			ptarray_calculate_gbox_cartesian(ring, bbox);
		}

		/* This is a LWLINE constructed by interior ring POINTARRAY */
		line = lwline_construct(poly->srid, bbox, ring);


		result = geometry_serialize((LWGEOM *)line);
		lwline_release(line);
		lwpoly_free(poly);
	}
	else
	{
		curvepoly = lwgeom_as_lwcurvepoly(lwgeom_from_gserialized(geom));

		if (wanted_index >= curvepoly->nrings)
		{
			PG_FREE_IF_COPY(geom, 0);
			lwgeom_release((LWGEOM *)curvepoly);
			PG_RETURN_NULL();
		}

		result = geometry_serialize(curvepoly->rings[wanted_index]);
		lwgeom_free((LWGEOM*)curvepoly);
	}

	PG_FREE_IF_COPY(geom, 0);
	PG_RETURN_POINTER(result);
}
Example #16
0
/**
* Create a new internal node, calculating the new measure range for the node,
* and storing pointers to the child nodes.
*/
static CIRC_NODE* 
circ_node_internal_new(CIRC_NODE** c, int num_nodes)
{
	CIRC_NODE *node = NULL;
	GEOGRAPHIC_POINT new_center, c1;
	double new_radius;
	double offset1, dist, D, r1, ri;
	int i;

	LWDEBUGF(3, "called with %d nodes --", num_nodes);

	/* Can't do anything w/ empty input */
	if ( num_nodes < 1 )
		return node;
	
	/* Initialize calculation with values of the first circle */
	new_center = c[0]->center;
	new_radius = c[0]->radius;
	
	/* Merge each remaining circle into the new circle */
	for ( i = 1; i < num_nodes; i++ )
	{
		c1 = new_center; 
		r1 = new_radius;
		
		dist = sphere_distance(&c1, &(c[i]->center));
		ri = c[i]->radius;

		LWDEBUGF(3, "distance between new (%g %g) and %i (%g %g) is %g", c1.lon, c1.lat, i, c[i]->center.lon, c[i]->center.lat, dist);
		
		if ( FP_EQUALS(dist, 0) )
		{
			LWDEBUG(3, "  distance between centers is zero");
			new_radius = r1 + 2*dist;
			new_center = c1;
		}
		else if ( dist < fabs(r1 - ri) )
		{
			/* new contains next */
			if ( r1 > ri )
			{
				LWDEBUG(3, "  c1 contains ci");
				new_center = c1;
				new_radius = r1;
			}
			/* next contains new */
			else
			{
				LWDEBUG(3, "  ci contains c1");
				new_center = c[i]->center;
				new_radius = ri;
			}
		}
		else
		{	
			LWDEBUG(3, "  calculating new center");
			/* New circle diameter */
			D = dist + r1 + ri;
			LWDEBUGF(3,"    D is %g", D);
			
			/* New radius */
			new_radius = D / 2.0;
			
			/* Distance from cn1 center to the new center */
			offset1 = ri + (D - (2.0*r1 + 2.0*ri)) / 2.0;
			LWDEBUGF(3,"    offset1 is %g", offset1);
			
			/* Sometimes the sphere_direction function fails... this causes the center calculation */
			/* to fail too. In that case, we're going to fall back ot a cartesian calculation, which */
			/* is less exact, so we also have to pad the radius by (hack alert) an arbitrary amount */
			/* which is hopefully always big enough to contain the input edges */
			if ( circ_center_spherical(&c1, &(c[i]->center), dist, offset1, &new_center) == LW_FAILURE )
			{
				circ_center_cartesian(&c1, &(c[i]->center), dist, offset1, &new_center);
				new_radius *= 1.1;
			}
		}
		LWDEBUGF(3, " new center is (%g %g) new radius is %g", new_center.lon, new_center.lat, new_radius);	
	}
	
	node = lwalloc(sizeof(CIRC_NODE));
	node->p1 = NULL;
	node->p2 = NULL;
	node->center = new_center;
	node->radius = new_radius;
	node->num_nodes = num_nodes;
	node->nodes = c;
	node->edge_num = -1;
	return node;
}
Example #17
0
GBOX* gbox_copy(const GBOX *box)
{
	GBOX *copy = (GBOX*)lwalloc(sizeof(GBOX));
	memcpy(copy, box, sizeof(GBOX));
	return copy;
}
Example #18
0
/**

The new faster calculation comparing pointarray to another pointarray
the arrays can come from both polygons and linestrings.
The naming is not good but comes from that it compares a
chosen selection of the points not all of them
*/
int
lw_dist2d_fast_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2,DISTPTS *dl, GBOX *box1, GBOX *box2)
{
	/*here we define two lists to hold our calculated "z"-values and the order number in the geometry*/

	double k, thevalue;
	float	deltaX, deltaY, c1m, c2m;
	POINT2D	theP,c1, c2;
	float min1X, max1X, max1Y, min1Y,min2X, max2X, max2Y, min2Y;
	int t;
	int n1 = l1->npoints;
	int n2 = l2->npoints;
	
	LISTSTRUCT *list1, *list2;
	list1 = (LISTSTRUCT*)lwalloc(sizeof(LISTSTRUCT)*n1); 
	list2 = (LISTSTRUCT*)lwalloc(sizeof(LISTSTRUCT)*n2);
	
	LWDEBUG(2, "lw_dist2d_fast_ptarray_ptarray is called");

	max1X = box1->xmax;
	min1X = box1->xmin;
	max1Y = box1->ymax;
	min1Y = box1->ymin;
	max2X = box2->xmax;
	min2X = box2->xmin;
	max2Y = box2->ymax;
	min2Y = box2->ymin;
	/*we want the center of the bboxes, and calculate the slope between the centerpoints*/
	c1.x = min1X + (max1X-min1X)/2;
	c1.y = min1Y + (max1Y-min1Y)/2;
	c2.x = min2X + (max2X-min2X)/2;
	c2.y = min2Y + (max2Y-min2Y)/2;

	deltaX=(c2.x-c1.x);
	deltaY=(c2.y-c1.y);


	/*Here we calculate where the line perpendicular to the center-center line crosses the axes for each vertex
	if the center-center line is vertical the perpendicular line will be horizontal and we find it's crossing the Y-axes with z = y-kx */
	if ((deltaX*deltaX)<(deltaY*deltaY))        /*North or South*/
	{
		k = -deltaX/deltaY;
		for (t=0; t<n1; t++) /*for each segment in L1 */
		{
			getPoint2d_p(l1, t, &theP);
			thevalue = theP.y-(k*theP.x);
			list1[t].themeasure=thevalue;
			list1[t].pnr=t;

		}
		for (t=0; t<n2; t++) /*for each segment in L2*/
		{
			getPoint2d_p(l2, t, &theP);
			thevalue = theP.y-(k*theP.x);
			list2[t].themeasure=thevalue;
			list2[t].pnr=t;

		}
		c1m = c1.y-(k*c1.x);
		c2m = c2.y-(k*c2.x);
	}


	/*if the center-center line is horizontal the perpendicular line will be vertical. To eliminate problems with deviding by zero we are here mirroring the coordinate-system
	 and we find it's crossing the X-axes with z = x-(1/k)y */
	else        /*West or East*/
	{
		k = -deltaY/deltaX;
		for (t=0; t<n1; t++) /*for each segment in L1 */
		{
			getPoint2d_p(l1, t, &theP);
			thevalue = theP.x-(k*theP.y);
			list1[t].themeasure=thevalue;
			list1[t].pnr=t;
			/* lwnotice("l1 %d, measure=%f",t,thevalue ); */
		}
		for (t=0; t<n2; t++) /*for each segment in L2*/
		{
			getPoint2d_p(l2, t, &theP);

			thevalue = theP.x-(k*theP.y);
			list2[t].themeasure=thevalue;
			list2[t].pnr=t;
			/* lwnotice("l2 %d, measure=%f",t,thevalue ); */
		}
		c1m = c1.x-(k*c1.y);
		c2m = c2.x-(k*c2.y);
	}

	/*we sort our lists by the calculated values*/
	qsort(list1, n1, sizeof(LISTSTRUCT), struct_cmp_by_measure);
	qsort(list2, n2, sizeof(LISTSTRUCT), struct_cmp_by_measure);

	if (c1m < c2m)
	{
		if (!lw_dist2d_pre_seg_seg(l1,l2,list1,list2,k,dl)) 
		{
			lwfree(list1);
			lwfree(list2);
			return LW_FALSE;
		}
	}
	else
	{
		dl->twisted= ((dl->twisted) * (-1));
		if (!lw_dist2d_pre_seg_seg(l2,l1,list2,list1,k,dl)) 
		{
			lwfree(list1);
			lwfree(list2);
			return LW_FALSE;
		}
	}
	lwfree(list1);
	lwfree(list2);	
	return LW_TRUE;
}