static int lwcircstring_calculate_gbox(LWCIRCSTRING *curve, GBOX *gbox) { uchar flags = gflags(TYPE_HASZ(curve->type), TYPE_HASM(curve->type), 0); GBOX tmp; POINT4D p1, p2, p3; int i; if ( ! curve ) return G_FAILURE; if ( curve->points->npoints < 3 ) return G_FAILURE; tmp.flags = flags; /* Initialize */ gbox->xmin = gbox->ymin = gbox->zmin = gbox->mmin = MAXFLOAT; gbox->xmax = gbox->ymax = gbox->zmax = gbox->mmax = -1 * MAXFLOAT; for ( i = 2; i < curve->points->npoints; i += 2 ) { getPoint4d_p(curve->points, i-2, &p1); getPoint4d_p(curve->points, i-1, &p2); getPoint4d_p(curve->points, i, &p3); if (lwcircle_calculate_gbox(p1, p2, p3, &tmp) == G_FAILURE) continue; gbox_merge(&tmp, gbox); } return G_SUCCESS; }
static POINTARRAY* ptarray_locate_along(const POINTARRAY *pa, double m, double offset) { int i; POINT4D p1, p2, pn; POINTARRAY *dpa = NULL; /* Can't do anything with degenerate point arrays */ if ( ! pa || pa->npoints < 2 ) return NULL; /* Walk through each segment in the point array */ for ( i = 1; i < pa->npoints; i++ ) { getPoint4d_p(pa, i-1, &p1); getPoint4d_p(pa, i, &p2); /* No derived point? Move to next segment. */ if ( segment_locate_along(&p1, &p2, m, offset, &pn) == LW_FALSE ) continue; /* No pointarray, make a fresh one */ if ( dpa == NULL ) dpa = ptarray_construct_empty(ptarray_has_z(pa), ptarray_has_m(pa), 8); /* Add our new point to the array */ ptarray_append_point(dpa, &pn, 0); } return dpa; }
int lwcompound_add_lwgeom(LWCOMPOUND *comp, LWGEOM *geom) { LWCOLLECTION *col = (LWCOLLECTION*)comp; /* Empty things can't continuously join up with other things */ if ( lwgeom_is_empty(geom) ) { LWDEBUG(4, "Got an empty component for a compound curve!"); return LW_FAILURE; } if( col->ngeoms > 0 ) { POINT4D last, first; /* First point of the component we are adding */ LWLINE *newline = (LWLINE*)geom; /* Last point of the previous component */ LWLINE *prevline = (LWLINE*)(col->geoms[col->ngeoms-1]); getPoint4d_p(newline->points, 0, &first); getPoint4d_p(prevline->points, prevline->points->npoints-1, &last); if ( !(FP_EQUALS(first.x,last.x) && FP_EQUALS(first.y,last.y)) ) { LWDEBUG(4, "Components don't join up end-to-end!"); LWDEBUGF(4, "first pt (%g %g %g %g) last pt (%g %g %g %g)", first.x, first.y, first.z, first.m, last.x, last.y, last.z, last.m); return LW_FAILURE; } } col = lwcollection_add_lwgeom(col, geom); return LW_SUCCESS; }
static int lwcircstring_calculate_gbox_cartesian(LWCIRCSTRING *curve, GBOX *gbox) { uint8_t flags = gflags(FLAGS_GET_Z(curve->flags), FLAGS_GET_M(curve->flags), 0); GBOX tmp; POINT4D p1, p2, p3; int i; if ( ! curve ) return LW_FAILURE; if ( curve->points->npoints < 3 ) return LW_FAILURE; tmp.flags = flags; /* Initialize */ gbox->xmin = gbox->ymin = gbox->zmin = gbox->mmin = MAXFLOAT; gbox->xmax = gbox->ymax = gbox->zmax = gbox->mmax = -1 * MAXFLOAT; for ( i = 2; i < curve->points->npoints; i += 2 ) { getPoint4d_p(curve->points, i-2, &p1); getPoint4d_p(curve->points, i-1, &p2); getPoint4d_p(curve->points, i, &p3); if (lw_arc_calculate_gbox_cartesian(&p1, &p2, &p3, &tmp) == LW_FAILURE) continue; gbox_merge(&tmp, gbox); } return LW_SUCCESS; }
/* * Add a LWTRIANGLE inside a tgeom * Copy geometries from LWTRIANGLE */ static TGEOM* tgeom_add_triangle(TGEOM *tgeom, LWTRIANGLE *triangle) { int i; assert(tgeom); assert(triangle); if ((tgeom->nfaces + 1) == INT_MAX) lwerror("tgeom_add_triangle: Unable to alloc more than %i faces", INT_MAX); /* Integrity checks on subgeom, dims and srid */ if (tgeom->type != TINTYPE) lwerror("tgeom_add_triangle: Unable to handle %s - %s type", tgeom->type, lwtype_name(tgeom->type)); if (FLAGS_NDIMS(tgeom->flags) != FLAGS_NDIMS(triangle->flags)) lwerror("tgeom_add_triangle: Mixed dimension"); if (tgeom->srid != triangle->srid && (tgeom->srid != 0 && triangle->srid != SRID_UNKNOWN)) lwerror("tgeom_add_triangle: Mixed srid. Tgeom: %i / Triangle: %i", tgeom->srid, triangle->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 triangle */ for (i=1 ; i < triangle->points->npoints ; i++) { POINT4D p1, p2; getPoint4d_p(triangle->points, i-1, &p1); getPoint4d_p(triangle->points, i, &p2); tgeom_add_face_edge(tgeom, tgeom->nfaces, &p1, &p2); } tgeom->nfaces++; return tgeom; }
POINTARRAY * ptarray_simplify(POINTARRAY *inpts, double epsilon, unsigned int minpts) { int *stack; /* recursion stack */ int sp=-1; /* recursion stack pointer */ int p1, split; double dist; POINTARRAY *outpts; POINT4D pt; double eps_sqr = epsilon * epsilon; /* Allocate recursion stack */ stack = lwalloc(sizeof(int)*inpts->npoints); p1 = 0; stack[++sp] = inpts->npoints-1; LWDEBUGF(2, "Input has %d pts and %d dims", inpts->npoints, FLAGS_NDIMS(inpts->flags)); /* Allocate output POINTARRAY, and add first point. */ outpts = ptarray_construct_empty(FLAGS_GET_Z(inpts->flags), FLAGS_GET_M(inpts->flags), inpts->npoints); getPoint4d_p(inpts, 0, &pt); ptarray_append_point(outpts, &pt, LW_FALSE); LWDEBUG(3, "Added P0 to simplified point array (size 1)"); do { ptarray_dp_findsplit(inpts, p1, stack[sp], &split, &dist); LWDEBUGF(3, "Farthest point from P%d-P%d is P%d (dist. %g)", p1, stack[sp], split, dist); if (dist > eps_sqr || ( outpts->npoints+sp+1 < minpts && dist >= 0 ) ) { LWDEBUGF(4, "Added P%d to stack (outpts:%d)", split, sp); stack[++sp] = split; } else { getPoint4d_p(inpts, stack[sp], &pt); LWDEBUGF(4, "npoints , minpoints %d %d", outpts->npoints, minpts); ptarray_append_point(outpts, &pt, LW_FALSE); LWDEBUGF(4, "Added P%d to simplified point array (size: %d)", stack[sp], outpts->npoints); p1 = stack[sp--]; } LWDEBUGF(4, "stack pointer = %d", sp); } while (! (sp<0) ); lwfree(stack); return outpts; }
/* * @param icurve input curve * @param tol tolerance, semantic driven by tolerance_type * @param tolerance_type see LW_LINEARIZE_TOLERANCE_TYPE * @param flags see flags in lwarc_linearize * * @return a newly allocated LWLINE */ static LWLINE * lwcircstring_linearize(const LWCIRCSTRING *icurve, double tol, LW_LINEARIZE_TOLERANCE_TYPE tolerance_type, int flags) { LWLINE *oline; POINTARRAY *ptarray; uint32_t i, j; POINT4D p1, p2, p3, p4; int ret; LWDEBUGF(2, "lwcircstring_linearize called., dim = %d", icurve->points->flags); ptarray = ptarray_construct_empty(FLAGS_GET_Z(icurve->points->flags), FLAGS_GET_M(icurve->points->flags), 64); for (i = 2; i < icurve->points->npoints; i+=2) { LWDEBUGF(3, "lwcircstring_linearize: arc ending at point %d", i); getPoint4d_p(icurve->points, i - 2, &p1); getPoint4d_p(icurve->points, i - 1, &p2); getPoint4d_p(icurve->points, i, &p3); ret = lwarc_linearize(ptarray, &p1, &p2, &p3, tol, tolerance_type, flags); if ( ret > 0 ) { LWDEBUGF(3, "lwcircstring_linearize: generated %d points", ptarray->npoints); } else if ( ret == 0 ) { LWDEBUG(3, "lwcircstring_linearize: points are colinear, returning curve points as line"); for (j = i - 2 ; j < i ; j++) { getPoint4d_p(icurve->points, j, &p4); ptarray_append_point(ptarray, &p4, LW_TRUE); } } else { /* An error occurred, lwerror should have been called by now */ ptarray_free(ptarray); return NULL; } } getPoint4d_p(icurve->points, icurve->points->npoints-1, &p1); ptarray_append_point(ptarray, &p1, LW_TRUE); oline = lwline_construct(icurve->srid, NULL, ptarray); return oline; }
static LWGEOM* circstring_from_pa(const POINTARRAY *pa, int srid, int start, int end) { POINT4D p0, p1, p2; POINTARRAY *pao = ptarray_construct(ptarray_has_z(pa), ptarray_has_m(pa), 3); LWDEBUGF(4, "srid=%d, start=%d, end=%d", srid, start, end); getPoint4d_p(pa, start, &p0); ptarray_set_point4d(pao, 0, &p0); getPoint4d_p(pa, (start+end)/2, &p1); ptarray_set_point4d(pao, 1, &p1); getPoint4d_p(pa, end+1, &p2); ptarray_set_point4d(pao, 2, &p2); return lwcircstring_as_lwgeom(lwcircstring_construct(srid, NULL, pao)); }
/* * @param icompound input compound curve * @param tol tolerance, semantic driven by tolerance_type * @param tolerance_type see LW_LINEARIZE_TOLERANCE_TYPE * @param flags see flags in lwarc_linearize * * @return a newly allocated LWLINE */ static LWLINE * lwcompound_linearize(const LWCOMPOUND *icompound, double tol, LW_LINEARIZE_TOLERANCE_TYPE tolerance_type, int flags) { LWGEOM *geom; POINTARRAY *ptarray = NULL, *ptarray_out = NULL; LWLINE *tmp = NULL; uint32_t i, j; POINT4D p; LWDEBUG(2, "lwcompound_stroke called."); ptarray = ptarray_construct_empty(FLAGS_GET_Z(icompound->flags), FLAGS_GET_M(icompound->flags), 64); for (i = 0; i < icompound->ngeoms; i++) { geom = icompound->geoms[i]; if (geom->type == CIRCSTRINGTYPE) { tmp = lwcircstring_linearize((LWCIRCSTRING *)geom, tol, tolerance_type, flags); for (j = 0; j < tmp->points->npoints; j++) { getPoint4d_p(tmp->points, j, &p); ptarray_append_point(ptarray, &p, LW_TRUE); } lwline_free(tmp); } else if (geom->type == LINETYPE) { tmp = (LWLINE *)geom; for (j = 0; j < tmp->points->npoints; j++) { getPoint4d_p(tmp->points, j, &p); ptarray_append_point(ptarray, &p, LW_TRUE); } } else { lwerror("Unsupported geometry type %d found.", geom->type, lwtype_name(geom->type)); return NULL; } } ptarray_out = ptarray_remove_repeated_points(ptarray, 0.0); ptarray_free(ptarray); return lwline_construct(icompound->srid, NULL, ptarray_out); }
static int ptarray_to_kml2_sb(const POINTARRAY *pa, int precision, stringbuffer_t *sb) { int i, j; int dims = FLAGS_GET_Z(pa->flags) ? 3 : 2; POINT4D pt; double *d; for ( i = 0; i < pa->npoints; i++ ) { getPoint4d_p(pa, i, &pt); d = (double*)(&pt); if ( i ) stringbuffer_append(sb," "); for (j = 0; j < dims; j++) { if ( j ) stringbuffer_append(sb,","); if( fabs(d[j]) < OUT_MAX_DOUBLE ) { if ( stringbuffer_aprintf(sb, "%.*f", precision, d[j]) < 0 ) return LW_FAILURE; } else { if ( stringbuffer_aprintf(sb, "%g", d[j]) < 0 ) return LW_FAILURE; } stringbuffer_trim_trailing_zeroes(sb); } } return LW_SUCCESS; }
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int repeated_points) { /* Check for pathology */ if( ! pa || ! pt ) { lwerror("ptarray_append_point: null input"); return LW_FAILURE; } /* Check for duplicate end point */ if ( repeated_points == LW_FALSE && pa->npoints > 0 ) { POINT4D tmp; getPoint4d_p(pa, pa->npoints-1, &tmp); LWDEBUGF(4,"checking for duplicate end point (pt = POINT(%g %g) pa->npoints-q = POINT(%g %g))",pt->x,pt->y,tmp.x,tmp.y); /* Return LW_SUCCESS and do nothing else if previous point in list is equal to this one */ if ( (pt->x == tmp.x) && (pt->y == tmp.y) && (FLAGS_GET_Z(pa->flags) ? pt->z == tmp.z : 1) && (FLAGS_GET_M(pa->flags) ? pt->m == tmp.m : 1) ) { return LW_SUCCESS; } } /* Append is just a special case of insert */ return ptarray_insert_point(pa, pt, pa->npoints); }
/** * Affine transform a pointarray. */ void ptarray_affine(POINTARRAY *pa, const AFFINE *a) { int i; double x,y,z; POINT4D p4d; LWDEBUG(2, "lwgeom_affine_ptarray start"); if ( FLAGS_GET_Z(pa->flags) ) { LWDEBUG(3, " has z"); for (i=0; i<pa->npoints; i++) { getPoint4d_p(pa, i, &p4d); x = p4d.x; y = p4d.y; z = p4d.z; p4d.x = a->afac * x + a->bfac * y + a->cfac * z + a->xoff; p4d.y = a->dfac * x + a->efac * y + a->ffac * z + a->yoff; p4d.z = a->gfac * x + a->hfac * y + a->ifac * z + a->zoff; ptarray_set_point4d(pa, i, &p4d); LWDEBUGF(3, " POINT %g %g %g => %g %g %g", x, y, x, p4d.x, p4d.y, p4d.z); } } else { LWDEBUG(3, " doesn't have z"); for (i=0; i<pa->npoints; i++) { getPoint4d_p(pa, i, &p4d); x = p4d.x; y = p4d.y; p4d.x = a->afac * x + a->bfac * y + a->xoff; p4d.y = a->dfac * x + a->efac * y + a->yoff; ptarray_set_point4d(pa, i, &p4d); LWDEBUGF(3, " POINT %g %g %g => %g %g %g", x, y, x, p4d.x, p4d.y, p4d.z); } } LWDEBUG(3, "lwgeom_affine_ptarray end"); }
/** * POLYGON */ static LWPOLY* lwpoly_from_twkb_state(twkb_parse_state *s) { uint32_t nrings; int i; LWPOLY *poly; LWDEBUG(2,"Entering lwpoly_from_twkb_state"); if ( s->is_empty ) return lwpoly_construct_empty(SRID_UNKNOWN, s->has_z, s->has_m); /* Read number of rings */ nrings = twkb_parse_state_uvarint(s); /* Start w/ empty polygon */ poly = lwpoly_construct_empty(SRID_UNKNOWN, s->has_z, s->has_m); LWDEBUGF(4,"Polygon has %d rings", nrings); /* Empty polygon? */ if( nrings == 0 ) return poly; for( i = 0; i < nrings; i++ ) { /* Ret number of points */ uint32_t npoints = twkb_parse_state_uvarint(s); POINTARRAY *pa = ptarray_from_twkb_state(s, npoints); /* Skip empty rings */ if( pa == NULL ) continue; /* Force first and last points to be the same. */ if( ! ptarray_is_closed_2d(pa) ) { POINT4D pt; getPoint4d_p(pa, 0, &pt); ptarray_append_point(pa, &pt, LW_FALSE); } /* Check for at least four points. */ if( s->check & LW_PARSER_CHECK_MINPOINTS && pa->npoints < 4 ) { LWDEBUGF(2, "%s must have at least four points in each ring", lwtype_name(s->lwtype)); lwerror("%s must have at least four points in each ring", lwtype_name(s->lwtype)); return NULL; } /* Add ring to polygon */ if ( lwpoly_add_ring(poly, pa) == LW_FAILURE ) { LWDEBUG(2, "Unable to add ring to polygon"); lwerror("Unable to add ring to polygon"); } } return poly; }
double lwpoint_get_y(const LWPOINT *point) { POINT4D pt; if ( lwpoint_is_empty(point) ) lwerror("lwpoint_get_y called with empty geometry"); getPoint4d_p(point->point, 0, &pt); return pt.y; }
int ptarray_calculate_gbox_cartesian(const POINTARRAY *pa, GBOX *gbox ) { int i; POINT4D p; int has_z, has_m; if ( ! pa ) return LW_FAILURE; if ( ! gbox ) return LW_FAILURE; if ( pa->npoints < 1 ) return LW_FAILURE; has_z = FLAGS_GET_Z(pa->flags); has_m = FLAGS_GET_M(pa->flags); gbox->flags = gflags(has_z, has_m, 0); LWDEBUGF(4, "ptarray_calculate_gbox Z: %d M: %d", has_z, has_m); getPoint4d_p(pa, 0, &p); gbox->xmin = gbox->xmax = p.x; gbox->ymin = gbox->ymax = p.y; if ( has_z ) gbox->zmin = gbox->zmax = p.z; if ( has_m ) gbox->mmin = gbox->mmax = p.m; for ( i = 1 ; i < pa->npoints; i++ ) { getPoint4d_p(pa, i, &p); gbox->xmin = FP_MIN(gbox->xmin, p.x); gbox->xmax = FP_MAX(gbox->xmax, p.x); gbox->ymin = FP_MIN(gbox->ymin, p.y); gbox->ymax = FP_MAX(gbox->ymax, p.y); if ( has_z ) { gbox->zmin = FP_MIN(gbox->zmin, p.z); gbox->zmax = FP_MAX(gbox->zmax, p.z); } if ( has_m ) { gbox->mmin = FP_MIN(gbox->mmin, p.m); gbox->mmax = FP_MAX(gbox->mmax, p.m); } } return LW_SUCCESS; }
double lwpoint_get_m(const LWPOINT *point) { POINT4D pt; if ( lwpoint_is_empty(point) ) lwerror("lwpoint_get_m called with empty geometry"); if ( ! FLAGS_GET_M(point->flags) ) lwerror("lwpoint_get_m called without m dimension"); getPoint4d_p(point->point, 0, &pt); return pt.m; }
/* * Find bounding box (standard one) * zmin=zmax=NO_Z_VALUE if 2d * TODO: This ignores curvature, which should be taken into account. */ BOX3D * lwcircstring_compute_box3d(LWCIRCSTRING *curve) { BOX3D *box, *tmp; int i; POINT4D *p1 = lwalloc(sizeof(POINT4D)); POINT4D *p2 = lwalloc(sizeof(POINT4D)); POINT4D *p3 = lwalloc(sizeof(POINT4D)); LWDEBUG(2, "lwcircstring_compute_box3d called."); /* initialize box values */ box = lwalloc(sizeof(BOX3D)); box->xmin = MAXFLOAT; box->xmax = -1 * MAXFLOAT; box->ymin = MAXFLOAT; box->ymax = -1 * MAXFLOAT; box->zmin = MAXFLOAT; box->zmax = -1 * MAXFLOAT; for (i = 2; i < curve->points->npoints; i+=2) { getPoint4d_p(curve->points, i-2, p1); getPoint4d_p(curve->points, i-1, p2); getPoint4d_p(curve->points, i, p3); tmp = lwcircle_compute_box3d(p1, p2, p3); if (tmp == NULL) continue; box->xmin = (box->xmin < tmp->xmin) ? box->xmin : tmp->xmin; box->xmax = (box->xmax > tmp->xmax) ? box->xmax : tmp->xmax; box->ymin = (box->ymin < tmp->ymin) ? box->ymin : tmp->ymin; box->ymax = (box->ymax > tmp->ymax) ? box->ymax : tmp->ymax; box->zmin = (box->zmin < tmp->zmin) ? box->zmin : tmp->zmin; box->zmax = (box->zmax > tmp->zmax) ? box->zmax : tmp->zmax; LWDEBUGF(4, "circularstring %d x=(%.16f,%.16f) y=(%.16f,%.16f) z=(%.16f,%.16f)", i/2, box->xmin, box->xmax, box->ymin, box->ymax, box->zmin, box->zmax); } return box; }
int ptarray_calculate_gbox(const POINTARRAY *pa, GBOX *gbox ) { int i; POINT4D p; int has_z = FLAGS_GET_Z(gbox->flags); int has_m = FLAGS_GET_M(gbox->flags); if ( ! pa ) return G_FAILURE; if ( pa->npoints < 1 ) return G_FAILURE; getPoint4d_p(pa, 0, &p); gbox->xmin = gbox->xmax = p.x; gbox->ymin = gbox->ymax = p.y; if ( has_z ) gbox->zmin = gbox->zmax = p.z; if ( has_m ) gbox->mmin = gbox->mmax = p.m; for ( i = 1 ; i < pa->npoints; i++ ) { getPoint4d_p(pa, i, &p); gbox->xmin = FP_MIN(gbox->xmin, p.x); gbox->xmax = FP_MAX(gbox->xmax, p.x); gbox->ymin = FP_MIN(gbox->ymin, p.y); gbox->ymax = FP_MAX(gbox->ymax, p.y); if ( has_z ) { gbox->zmin = FP_MIN(gbox->zmin, p.z); gbox->zmax = FP_MAX(gbox->zmax, p.z); } if ( has_m ) { gbox->mmin = FP_MIN(gbox->mmin, p.m); gbox->mmax = FP_MAX(gbox->mmax, p.m); } } return G_SUCCESS; }
static LWGEOM* linestring_from_pa(const POINTARRAY *pa, int srid, int start, int end) { int i = 0, j = 0; POINT4D p; POINTARRAY *pao = ptarray_construct(ptarray_has_z(pa), ptarray_has_m(pa), end-start+2); LWDEBUGF(4, "srid=%d, start=%d, end=%d", srid, start, end); for( i = start; i < end + 2; i++ ) { getPoint4d_p(pa, i, &p); ptarray_set_point4d(pao, j++, &p); } return lwline_as_lwgeom(lwline_construct(srid, NULL, pao)); }
/** * Transform given POINTARRAY * from inpj projection to outpj projection */ int ptarray_transform(POINTARRAY *pa, projPJ inpj, projPJ outpj) { int i; POINT4D p; for ( i = 0; i < pa->npoints; i++ ) { getPoint4d_p(pa, i, &p); if ( ! point4d_transform(&p, inpj, outpj) ) return LW_FAILURE; ptarray_set_point4d(pa, i, &p); } return LW_SUCCESS; }
/** * Reverse X and Y axis on a given POINTARRAY */ POINTARRAY* ptarray_flip_coordinates(POINTARRAY *pa) { int i; double d; POINT4D p; for (i=0 ; i < pa->npoints ; i++) { getPoint4d_p(pa, i, &p); d = p.y; p.y = p.x; p.x = d; ptarray_set_point4d(pa, i, &p); } return pa; }
LWLINE * lwcircstring_segmentize(const LWCIRCSTRING *icurve, uint32_t perQuad) { LWLINE *oline; POINTARRAY *ptarray; POINTARRAY *tmp; uint32_t i, j; POINT4D p1, p2, p3, p4; LWDEBUGF(2, "lwcircstring_segmentize called., dim = %d", icurve->points->flags); ptarray = ptarray_construct_empty(FLAGS_GET_Z(icurve->points->flags), FLAGS_GET_M(icurve->points->flags), 64); for (i = 2; i < icurve->points->npoints; i+=2) { LWDEBUGF(3, "lwcircstring_segmentize: arc ending at point %d", i); getPoint4d_p(icurve->points, i - 2, &p1); getPoint4d_p(icurve->points, i - 1, &p2); getPoint4d_p(icurve->points, i, &p3); tmp = lwcircle_segmentize(&p1, &p2, &p3, perQuad); if (tmp) { LWDEBUGF(3, "lwcircstring_segmentize: generated %d points", tmp->npoints); for (j = 0; j < tmp->npoints; j++) { getPoint4d_p(tmp, j, &p4); ptarray_append_point(ptarray, &p4, LW_TRUE); } ptarray_free(tmp); } else { LWDEBUG(3, "lwcircstring_segmentize: points are colinear, returning curve points as line"); for (j = i - 1 ; j <= i ; j++) { getPoint4d_p(icurve->points, j, &p4); ptarray_append_point(ptarray, &p4, LW_TRUE); } } } getPoint4d_p(icurve->points, icurve->points->npoints-1, &p1); ptarray_append_point(ptarray, &p1, LW_TRUE); oline = lwline_construct(icurve->srid, NULL, ptarray); return oline; }
LWMPOINT * lwmpoint_construct(int srid, const POINTARRAY *pa) { int i; int hasz = ptarray_has_z(pa); int hasm = ptarray_has_m(pa); LWMPOINT *ret = (LWMPOINT*)lwcollection_construct_empty(MULTIPOINTTYPE, srid, hasz, hasm); for ( i = 0; i < pa->npoints; i++ ) { LWPOINT *lwp; POINT4D p; getPoint4d_p(pa, i, &p); lwp = lwpoint_make(srid, hasz, hasm, &p); lwmpoint_add_lwpoint(ret, lwp); } return ret; }
/** * Scale a pointarray. */ void ptarray_scale(POINTARRAY *pa, const POINT4D *fact) { int i; POINT4D p4d; LWDEBUG(3, "ptarray_scale start"); for (i=0; i<pa->npoints; ++i) { getPoint4d_p(pa, i, &p4d); p4d.x *= fact->x; p4d.y *= fact->y; p4d.z *= fact->z; p4d.m *= fact->m; ptarray_set_point4d(pa, i, &p4d); } LWDEBUG(3, "ptarray_scale end"); }
POINTARRAY* ptarray_force_dims(const POINTARRAY *pa, int hasz, int hasm) { /* TODO handle zero-length point arrays */ int i; int in_hasz = FLAGS_GET_Z(pa->flags); int in_hasm = FLAGS_GET_M(pa->flags); POINT4D pt; POINTARRAY *pa_out = ptarray_construct_empty(hasz, hasm, pa->npoints); for( i = 0; i < pa->npoints; i++ ) { getPoint4d_p(pa, i, &pt); if( hasz && ! in_hasz ) pt.z = 0.0; if( hasm && ! in_hasm ) pt.m = 0.0; ptarray_append_point(pa_out, &pt, LW_TRUE); } return pa_out; }
/* * Stick an array of points to the given gridspec. * Return "gridded" points in *outpts and their number in *outptsn. * * Two consecutive points falling on the same grid cell are collapsed * into one single point. * */ POINTARRAY * ptarray_grid(const POINTARRAY *pa, const gridspec *grid) { POINT4D pt; int ipn; /* input point numbers */ POINTARRAY *dpa; LWDEBUGF(2, "ptarray_grid called on %p", pa); dpa = ptarray_construct_empty(FLAGS_GET_Z(pa->flags),FLAGS_GET_M(pa->flags), pa->npoints); for (ipn=0; ipn<pa->npoints; ++ipn) { getPoint4d_p(pa, ipn, &pt); if ( grid->xsize ) pt.x = rint((pt.x - grid->ipx)/grid->xsize) * grid->xsize + grid->ipx; if ( grid->ysize ) pt.y = rint((pt.y - grid->ipy)/grid->ysize) * grid->ysize + grid->ipy; if ( FLAGS_GET_Z(pa->flags) && grid->zsize ) pt.z = rint((pt.z - grid->ipz)/grid->zsize) * grid->zsize + grid->ipz; if ( FLAGS_GET_M(pa->flags) && grid->msize ) pt.m = rint((pt.m - grid->ipm)/grid->msize) * grid->msize + grid->ipm; ptarray_append_point(dpa, &pt, LW_FALSE); } return dpa; }
/* * Stick an array of points to the given gridspec. * Return "gridded" points in *outpts and their number in *outptsn. * * Two consecutive points falling on the same grid cell are collapsed * into one single point. * */ POINTARRAY * ptarray_grid(POINTARRAY *pa, gridspec *grid) { POINT4D pbuf; int ipn, opn; /* point numbers (input/output) */ POINTARRAY *dpa; POSTGIS_DEBUGF(2, "ptarray_grid called on %p", pa); dpa = ptarray_construct_empty(FLAGS_GET_Z(pa->flags),FLAGS_GET_M(pa->flags), pa->npoints); for (ipn=0, opn=0; ipn<pa->npoints; ++ipn) { getPoint4d_p(pa, ipn, &pbuf); if ( grid->xsize ) pbuf.x = rint((pbuf.x - grid->ipx)/grid->xsize) * grid->xsize + grid->ipx; if ( grid->ysize ) pbuf.y = rint((pbuf.y - grid->ipy)/grid->ysize) * grid->ysize + grid->ipy; if ( FLAGS_GET_Z(pa->flags) && grid->zsize ) pbuf.z = rint((pbuf.z - grid->ipz)/grid->zsize) * grid->zsize + grid->ipz; if ( FLAGS_GET_M(pa->flags) && grid->msize ) pbuf.m = rint((pbuf.m - grid->ipm)/grid->msize) * grid->msize + grid->ipm; ptarray_append_point(dpa, &pbuf, LW_FALSE); } return dpa; }
void ptarray_swap_ordinates(POINTARRAY *pa, LWORD o1, LWORD o2) { int i; double d, *dp1, *dp2; POINT4D p; #if PARANOIA_LEVEL > 0 assert(o1 < 4); assert(o2 < 4); #endif dp1 = ((double*)&p)+(unsigned)o1; dp2 = ((double*)&p)+(unsigned)o2; for (i=0 ; i < pa->npoints ; i++) { getPoint4d_p(pa, i, &p); d = *dp2; *dp2 = *dp1; *dp1 = d; ptarray_set_point4d(pa, i, &p); } }
int lwline_split_by_point_to(const LWLINE* lwline_in, const LWPOINT* blade_in, LWMLINE* v) { double mindist = -1; POINT4D pt, pt_projected; POINT4D p1, p2; POINTARRAY *ipa = lwline_in->points; POINTARRAY* pa1; POINTARRAY* pa2; int i, nsegs, seg = -1; /* Possible outcomes: * * 1. The point is not on the line or on the boundary * -> Leave collection untouched, return 0 * 2. The point is on the boundary * -> Leave collection untouched, return 1 * 3. The point is in the line * -> Push 2 elements on the collection: * o start_point - cut_point * o cut_point - last_point * -> Return 2 */ getPoint4d_p(blade_in->point, 0, &pt); /* Find closest segment */ getPoint4d_p(ipa, 0, &p1); nsegs = ipa->npoints - 1; for ( i = 0; i < nsegs; i++ ) { getPoint4d_p(ipa, i+1, &p2); double dist; dist = distance2d_pt_seg((POINT2D*)&pt, (POINT2D*)&p1, (POINT2D*)&p2); LWDEBUGF(4, " Distance of point %g %g to segment %g %g, %g %g: %g", pt.x, pt.y, p1.x, p1.y, p2.x, p2.y, dist); if (i==0 || dist < mindist ) { mindist = dist; seg=i; if ( mindist == 0.0 ) break; /* can't be closer than ON line */ } p1 = p2; } LWDEBUGF(3, "Closest segment: %d", seg); LWDEBUGF(3, "mindist: %g", mindist); /* No intersection */ if ( mindist > 0 ) return 0; /* empty or single-point line, intersection on boundary */ if ( seg < 0 ) return 1; /* * We need to project the * point on the closest segment, * to interpolate Z and M if needed */ getPoint4d_p(ipa, seg, &p1); getPoint4d_p(ipa, seg+1, &p2); closest_point_on_segment(&pt, &p1, &p2, &pt_projected); /* But X and Y we want the ones of the input point, * as on some architectures the interpolation math moves the * coordinates (see #3422) */ pt_projected.x = pt.x; pt_projected.y = pt.y; LWDEBUGF(3, "Projected point:(%g %g), seg:%d, p1:(%g %g), p2:(%g %g)", pt_projected.x, pt_projected.y, seg, p1.x, p1.y, p2.x, p2.y); /* When closest point == an endpoint, this is a boundary intersection */ if ( ( (seg == nsegs-1) && p4d_same(&pt_projected, &p2) ) || ( (seg == 0) && p4d_same(&pt_projected, &p1) ) ) { return 1; } /* This is an internal intersection, let's build the two new pointarrays */ pa1 = ptarray_construct_empty(FLAGS_GET_Z(ipa->flags), FLAGS_GET_M(ipa->flags), seg+2); /* TODO: replace with a memcpy ? */ for (i=0; i<=seg; ++i) { getPoint4d_p(ipa, i, &p1); ptarray_append_point(pa1, &p1, LW_FALSE); } ptarray_append_point(pa1, &pt_projected, LW_FALSE); pa2 = ptarray_construct_empty(FLAGS_GET_Z(ipa->flags), FLAGS_GET_M(ipa->flags), ipa->npoints-seg); ptarray_append_point(pa2, &pt_projected, LW_FALSE); /* TODO: replace with a memcpy (if so need to check for duplicated point) ? */ for (i=seg+1; i<ipa->npoints; ++i) { getPoint4d_p(ipa, i, &p1); ptarray_append_point(pa2, &p1, LW_FALSE); } /* NOTE: I've seen empty pointarrays with loc != 0 and loc != 1 */ if ( pa1->npoints == 0 || pa2->npoints == 0 ) { ptarray_free(pa1); ptarray_free(pa2); /* Intersection is on the boundary */ return 1; } lwmline_add_lwline(v, lwline_construct(SRID_UNKNOWN, NULL, pa1)); lwmline_add_lwline(v, lwline_construct(SRID_UNKNOWN, NULL, pa2)); return 2; }
int lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out) { return getPoint4d_p(point->point,0,out); }