31 #include "../postgis_config.h"
90 LWDEBUGF(5,
"pa = %p; p = %p; where = %d", pa, p, where);
95 lwerror(
"ptarray_insert_point: called on read-only point array");
102 lwerror(
"ptarray_insert_point: offset out of range (%d)", where);
129 if( where < pa->npoints )
131 size_t copy_size = point_size * (pa->
npoints - where);
133 LWDEBUGF(5,
"copying %zu bytes to start vertex %d from start vertex %d", copy_size, where+1, where);
141 LWDEBUGF(5,
"copying new point to start vertex %zu", point_size);
152 lwerror(
"ptarray_append_point: null input");
161 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);
164 if ( (pt->
x == tmp.
x) && (pt->
y == tmp.
y) &&
179 unsigned int poff = 0;
180 unsigned int npoints;
187 lwerror(
"%s: null input", __func__);
197 lwerror(
"%s: target pointarray is read-only", __func__);
203 lwerror(
"%s: appending mixed dimensionality is not allowed", __func__);
221 else if ((gap_tolerance == 0) ||
224 lwerror(
"Second line start point too far from first line end point");
264 lwerror(
"ptarray_remove_point: null input");
271 lwerror(
"ptarray_remove_point: offset out of range (%d)", where);
276 if (where < pa->npoints - 1)
294 LWDEBUGF(5,
"hasz = %d, hasm = %d, npoints = %d, ptlist = %p", hasz, hasm, npoints, ptlist);
344 uint32_t last = pa->
npoints - 1;
345 uint32_t mid = pa->
npoints / 2;
350 for (i = 0; i < mid; i++)
352 for (j = 0; j < ndims; j++)
356 d[i*ndims+j] = d[(last-i)*ndims+j];
357 d[(last-i)*ndims+j] = buf;
374 for (i=0 ; i < pa->
npoints ; i++)
390 double d, *dp1, *dp2;
393 dp1 = ((
double*)&p)+(unsigned)o1;
394 dp2 = ((
double*)&p)+(unsigned)o2;
395 for (i=0 ; i < pa->
npoints ; i++)
423 pbuf.
x = pbuf.
y = pbuf.
z = pbuf.
m = 0;
433 for (i = 1; i < ipa->
npoints; i++)
444 POINT4D *p1ptr=&p1, *p2ptr=&p2;
451 segments = ceil(segdist / dist);
456 lwnotice(
"%s:%d - %s: Too many segments required (%e)",
457 __FILE__, __LINE__,__func__, segments);
463 for (j = 1; j < nseg; j++)
465 pbuf.
x = p1.
x + (p2.
x - p1.
x) * j / nseg;
466 pbuf.
y = p1.
y + (p2.
y - p1.
y) * j / nseg;
468 pbuf.
z = p1.
z + (p2.
z - p1.
z) * j / nseg;
470 pbuf.
m = p1.
m + (p2.
m - p1.
m) * j / nseg;
490 LWDEBUG(5,
"dimensions are the same");
493 LWDEBUG(5,
"npoints are the same");
496 LWDEBUGF(5,
"ptsize = %zu", ptsize);
502 LWDEBUGF(5,
"point #%d is the same",i);
514 LWDEBUG(5,
"dimensions are the same");
517 LWDEBUG(5,
"npoints are the same");
523 LWDEBUGF(5,
"point #%d is the same",i);
536 LWDEBUGF(3,
"pa %p p %p size %zu where %u",
537 pa, p, pdims, where);
539 if ( pdims < 2 || pdims > 4 )
541 lwerror(
"ptarray_addPoint: point dimension out of range (%zu)",
548 lwerror(
"ptarray_addPoint: offset out of range (%d)",
553 LWDEBUG(3,
"called with a point");
555 pbuf.
x = pbuf.
y = pbuf.
z = pbuf.
m = 0.0;
556 memcpy((uint8_t *)&pbuf, p, pdims*
sizeof(
double));
558 LWDEBUG(3,
"initialized point buffer");
587 LWDEBUGF(3,
"pa %p which %u", pa, which);
589 assert(which <= pa->npoints-1);
602 if ( which < pa->npoints-1 )
618 lwerror(
"ptarray_cat: Mixed dimension");
647 LWDEBUG(3,
"ptarray_clone_deep called.");
678 LWDEBUG(3,
"ptarray_clone called.");
700 lwerror(
"ptarray_is_closed: called with null point array");
714 lwerror(
"ptarray_is_closed_2d: called with null point array");
727 lwerror(
"ptarray_is_closed_3d: called with null point array");
763 lwerror(
"ptarray_contains_point called on unclosed ring");
765 for (uint32_t i = 1; i < pa->
npoints; i++)
767 double side, ymin, ymax;
782 if (pt->
y > ymax || pt->
y < ymin)
804 if ((side < 0) && (seg1->
y <= pt->
y) && (pt->
y < seg2->
y))
814 else if ( (side > 0) && (seg2->
y <= pt->
y) && (pt->
y < seg1->
y) )
831 lwerror(
"%s called on invalid linestring", __func__);
833 int intersections = 0;
838 for (uint32_t i = 0; i < pa->
npoints-1; ++i)
862 if (((p1->
y <= py) && (py < p2->
y)) || ((p2->
y <= py) && (py < p1->
y)))
868 double x_intersection = p1->
x + (py - p1->
y) * (p2->
x - p1->
x) / (p2->
y - p1->
y);
874 if (x_intersection > px)
881 return intersections;
906 double dy = ray - center->
y;
909 if (fabs(dy) > radius)
915 double dx_squared = radius * radius - dy * dy;
929 double dx = sqrt(dx_squared);
932 i0->
x = center->
x - dx;
936 i1->
x = center->
x + dx;
946 int intersections = 0;
954 lwerror(
"%s called on invalid circularstring", __func__);
957 lwerror(
"%s called with even number of points", __func__);
960 for (uint32_t i = 1; i < pa->
npoints-1; i +=2)
994 if ((gbox.
ymin <= py) && (py < gbox.
ymax))
1022 return intersections;
1041 if ( check_closed && !
p2d_same(seg1, seg2) )
1042 lwerror(
"ptarray_contains_point called on unclosed ring");
1044 for ( i=1; i < pa->
npoints; i++ )
1049 if ( seg1->
x == seg2->
x && seg1->
y == seg2->
y )
1059 if ( pt->
y > ymax || pt->
y < ymin )
1081 if ( (side < 0) && (seg1->
y <= pt->
y) && (pt->
y < seg2->
y) )
1091 else if ( (side > 0) && (seg2->
y <= pt->
y) && (pt->
y < seg1->
y) )
1100 if ( winding_number )
1101 *winding_number = wn;
1128 lwerror(
"%s called on unclosed ring", __func__);
1149 double x0,
x, y1, y2;
1158 for ( i = 2; i < pa->
npoints; i++ )
1197 for( i = 0; i < pa->
npoints; i++ )
1200 if( hasz && ! in_hasz )
1202 if( hasm && ! in_hasm )
1219 double length, slength, tlength;
1232 LWDEBUGF(3,
"Total length: %g", length);
1240 LWDEBUGF(3,
"From/To: %g/%g", from, to);
1246 for ( i = 0; i < nsegs; i++ )
1253 LWDEBUGF(3 ,
"Segment %d: (%g,%g,%g,%g)-(%g,%g,%g,%g)",
1254 i, p1.
x, p1.
y, p1.
z, p1.
m, p2.
x, p2.
y, p2.
z, p2.
m);
1268 if ( fabs ( from - ( tlength + slength ) ) <= tolerance )
1271 LWDEBUG(3,
" Second point is our start");
1281 else if ( fabs(from - tlength) <= tolerance )
1284 LWDEBUG(3,
" First point is our start");
1302 else if ( from > tlength + slength )
goto END;
1307 LWDEBUG(3,
" Seg contains first point");
1313 dseg = (from - tlength) / slength;
1335 if ( fabs(to - ( tlength + slength ) ) <= tolerance )
1338 LWDEBUG(3,
" Second point is our end");
1348 else if ( fabs(to - tlength) <= tolerance )
1351 LWDEBUG(3,
" First point is our end");
1362 else if ( to > tlength + slength )
1372 else if ( to < tlength + slength )
1375 LWDEBUG(3,
" Seg contains our end");
1377 dseg = (to - tlength) / slength;
1395 memcpy(&p1, &p2,
sizeof(
POINT4D));
1432 r = ( (p->
x-A->
x) * (B->
x-A->
x) + (p->
y-A->
y) * (B->
y-A->
y) )/( (B->
x-A->
x)*(B->
x-A->
x) +(B->
y-A->
y)*(B->
y-A->
y) );
1445 ret->
x = A->
x + ( (B->
x - A->
x) *
r );
1446 ret->
y = A->
y + ( (B->
y - A->
y) *
r );
1447 ret->
z = A->
z + ( (B->
z - A->
z) *
r );
1448 ret->
m = A->
m + ( (B->
m - A->
m) *
r );
1456 double mindist=DBL_MAX;
1465 if (dist_sqr < mindist)
1471 LWDEBUG(3,
"Breaking on mindist=0");
1479 if ( dist ) *dist = sqrt(mindist);
1489 double mindist = DBL_MAX;
1498 if (dist_sqr < mindist)
1504 LWDEBUG(3,
"Breaking on mindist=0");
1509 if ( dist ) *dist = sqrt(mindist);
1520 double mindist=DBL_MAX;
1523 POINT4D start4d, end4d, projtmp;
1525 const POINT2D *start = NULL, *end = NULL;
1531 if ( ! proj4d ) proj4d = &projtmp;
1553 if (dist_sqr < mindist)
1559 LWDEBUG(3,
"Breaking on mindist=0");
1566 mindist = sqrt(mindist);
1568 if ( mindistout ) *mindistout = mindist;
1570 LWDEBUGF(3,
"Closest segment: %d", seg);
1571 LWDEBUGF(3,
"mindist: %g", mindist);
1593 LWDEBUGF(3,
"Closest point on segment: %g,%g", proj.
x, proj.
y);
1601 if ( tlen == 0 )
return 0;
1605 for (t=0; t<seg; t++, start=end)
1610 LWDEBUGF(4,
"Segment %d made plen %g", t, plen);
1615 LWDEBUGF(3,
"plen %g, tlen %g", plen, tlen);
1618 double result = plen / tlen;
1621 }
else if (
result > 1.0 ) {
1645 if (
x < 0 )
x+= 360;
1646 else if (
x > 180 )
x -= 360;
1677 double tolsq = tolerance * tolerance;
1680 uint32_t n_points = pa->
npoints;
1681 uint32_t n_points_out = 1;
1684 double dsq = FLT_MAX;
1687 if ( n_points <= min_points )
return;
1690 void *p_to = ((
char *)last) + pt_size;
1691 for (i = 1; i < n_points; i++)
1693 int last_point = (i == n_points - 1);
1699 if (n_points + n_points_out > min_points + i)
1701 if (tolerance > 0.0)
1706 if (!last_point && dsq <= tolsq)
1714 if (memcmp((
char*)pt, (
char*)last, pt_size) == 0)
1722 if (last_point && n_points_out > 1 && tolerance > 0.0 && dsq <= tolsq)
1725 p_to = (
char*)p_to - pt_size;
1730 memcpy(p_to, pt, pt_size);
1732 p_to = (
char*)p_to + pt_size;
1747 uint32_t split = it_first;
1748 if ((it_first - it_last) < 2)
1757 for (uint32_t itk = it_first + 1; itk < it_last; itk++)
1761 if (distance_sqr > max_distance_sqr)
1764 max_distance_sqr = distance_sqr;
1771 double ba_x = (B->
x - A->
x);
1772 double ba_y = (B->
y - A->
y);
1773 double ab_length_sqr = (ba_x * ba_x + ba_y * ba_y);
1776 max_distance_sqr *= ab_length_sqr;
1777 for (uint32_t itk = it_first + 1; itk < it_last; itk++)
1780 double distance_sqr;
1781 double ca_x = (C->
x - A->
x);
1782 double ca_y = (C->
y - A->
y);
1783 double dot_ac_ab = (ca_x * ba_x + ca_y * ba_y);
1785 if (dot_ac_ab <= 0.0)
1789 else if (dot_ac_ab >= ab_length_sqr)
1795 double s_numerator = ca_x * ba_y - ca_y * ba_x;
1796 distance_sqr = s_numerator * s_numerator;
1799 if (distance_sqr > max_distance_sqr)
1802 max_distance_sqr = distance_sqr;
1812 uint32_t kept_it = 0;
1813 uint32_t last_it = pa->
npoints - 1;
1817 for (uint32_t i = 1; i < last_it; i++)
1822 double ba_x = next_pt->
x - kept_pt->
x;
1823 double ba_y = next_pt->
y - kept_pt->
y;
1824 double ab_length_sqr = ba_x * ba_x + ba_y * ba_y;
1826 double ca_x = curr_pt->
x - kept_pt->
x;
1827 double ca_y = curr_pt->
y - kept_pt->
y;
1828 double dot_ac_ab = ca_x * ba_x + ca_y * ba_y;
1829 double s_numerator = ca_x * ba_y - ca_y * ba_x;
1833 dot_ac_ab > ab_length_sqr ||
1848 if (kept_it != last_it)
1862 if (tolerance == 0 && minpts <= 2)
1880 uint32_t *iterator_stack =
lwalloc(
sizeof(uint32_t) * pa->
npoints);
1881 iterator_stack[0] = 0;
1882 uint32_t iterator_stack_size = 1;
1884 uint32_t it_first = 0;
1885 uint32_t it_last = pa->
npoints - 1;
1887 const double tolerance_sqr = tolerance * tolerance;
1889 double it_tol = keptn >= minpts ? tolerance_sqr : -1.0;
1891 while (iterator_stack_size)
1894 if (split == it_first)
1897 it_last = iterator_stack[--iterator_stack_size];
1904 iterator_stack[iterator_stack_size++] = it_last;
1906 it_tol = keptn >= minpts ? tolerance_sqr : -1.0;
1921 else if (pa->
npoints != keptn)
1923 for (uint32_t i = 1; i < pa->
npoints; i++)
1957 lwerror(
"arc point array with even number of points");
1961 for ( i=2; i < pts->
npoints; i += 2 )
1982 if ( pts->
npoints < 2 )
return 0.0;
1986 for ( i=1; i < pts->
npoints; i++ )
1990 dist += sqrt( ((frm->
x - to->
x)*(frm->
x - to->
x)) +
1991 ((frm->
y - to->
y)*(frm->
y - to->
y)) );
2010 if ( pts->
npoints < 2 )
return 0.0;
2016 for ( i=1; i < pts->
npoints; i++ )
2019 dist += sqrt( ((frm.
x - to.
x)*(frm.
x - to.
x)) +
2020 ((frm.
y - to.
y)*(frm.
y - to.
y)) +
2021 ((frm.
z - to.
z)*(frm.
z - to.
z)) );
2037 for (uint32_t i = 0; i < pa->
npoints; i++)
2050 for (uint32_t i = 0; i < pa->
npoints; i++)
2066 static int gluInvertMatrix(
const double *m,
double *invOut)
2068 double inv[16],
det;
2071 inv[0] = m[5] * m[10] * m[15] -
2072 m[5] * m[11] * m[14] -
2073 m[9] * m[6] * m[15] +
2074 m[9] * m[7] * m[14] +
2075 m[13] * m[6] * m[11] -
2076 m[13] * m[7] * m[10];
2078 inv[4] = -m[4] * m[10] * m[15] +
2079 m[4] * m[11] * m[14] +
2080 m[8] * m[6] * m[15] -
2081 m[8] * m[7] * m[14] -
2082 m[12] * m[6] * m[11] +
2083 m[12] * m[7] * m[10];
2085 inv[8] = m[4] * m[9] * m[15] -
2086 m[4] * m[11] * m[13] -
2087 m[8] * m[5] * m[15] +
2088 m[8] * m[7] * m[13] +
2089 m[12] * m[5] * m[11] -
2090 m[12] * m[7] * m[9];
2092 inv[12] = -m[4] * m[9] * m[14] +
2093 m[4] * m[10] * m[13] +
2094 m[8] * m[5] * m[14] -
2095 m[8] * m[6] * m[13] -
2096 m[12] * m[5] * m[10] +
2097 m[12] * m[6] * m[9];
2099 inv[1] = -m[1] * m[10] * m[15] +
2100 m[1] * m[11] * m[14] +
2101 m[9] * m[2] * m[15] -
2102 m[9] * m[3] * m[14] -
2103 m[13] * m[2] * m[11] +
2104 m[13] * m[3] * m[10];
2106 inv[5] = m[0] * m[10] * m[15] -
2107 m[0] * m[11] * m[14] -
2108 m[8] * m[2] * m[15] +
2109 m[8] * m[3] * m[14] +
2110 m[12] * m[2] * m[11] -
2111 m[12] * m[3] * m[10];
2113 inv[9] = -m[0] * m[9] * m[15] +
2114 m[0] * m[11] * m[13] +
2115 m[8] * m[1] * m[15] -
2116 m[8] * m[3] * m[13] -
2117 m[12] * m[1] * m[11] +
2118 m[12] * m[3] * m[9];
2120 inv[13] = m[0] * m[9] * m[14] -
2121 m[0] * m[10] * m[13] -
2122 m[8] * m[1] * m[14] +
2123 m[8] * m[2] * m[13] +
2124 m[12] * m[1] * m[10] -
2125 m[12] * m[2] * m[9];
2127 inv[2] = m[1] * m[6] * m[15] -
2128 m[1] * m[7] * m[14] -
2129 m[5] * m[2] * m[15] +
2130 m[5] * m[3] * m[14] +
2131 m[13] * m[2] * m[7] -
2132 m[13] * m[3] * m[6];
2134 inv[6] = -m[0] * m[6] * m[15] +
2135 m[0] * m[7] * m[14] +
2136 m[4] * m[2] * m[15] -
2137 m[4] * m[3] * m[14] -
2138 m[12] * m[2] * m[7] +
2139 m[12] * m[3] * m[6];
2141 inv[10] = m[0] * m[5] * m[15] -
2142 m[0] * m[7] * m[13] -
2143 m[4] * m[1] * m[15] +
2144 m[4] * m[3] * m[13] +
2145 m[12] * m[1] * m[7] -
2146 m[12] * m[3] * m[5];
2148 inv[14] = -m[0] * m[5] * m[14] +
2149 m[0] * m[6] * m[13] +
2150 m[4] * m[1] * m[14] -
2151 m[4] * m[2] * m[13] -
2152 m[12] * m[1] * m[6] +
2153 m[12] * m[2] * m[5];
2155 inv[3] = -m[1] * m[6] * m[11] +
2156 m[1] * m[7] * m[10] +
2157 m[5] * m[2] * m[11] -
2158 m[5] * m[3] * m[10] -
2159 m[9] * m[2] * m[7] +
2162 inv[7] = m[0] * m[6] * m[11] -
2163 m[0] * m[7] * m[10] -
2164 m[4] * m[2] * m[11] +
2165 m[4] * m[3] * m[10] +
2166 m[8] * m[2] * m[7] -
2169 inv[11] = -m[0] * m[5] * m[11] +
2170 m[0] * m[7] * m[9] +
2171 m[4] * m[1] * m[11] -
2172 m[4] * m[3] * m[9] -
2173 m[8] * m[1] * m[7] +
2176 inv[15] = m[0] * m[5] * m[10] -
2177 m[0] * m[6] * m[9] -
2178 m[4] * m[1] * m[10] +
2179 m[4] * m[2] * m[9] +
2180 m[8] * m[1] * m[6] -
2183 det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
2190 for (i = 0; i < 16; i++)
2191 invOut[i] = inv[i] *
det;
2205 LWDEBUG(3,
"ptarray_scale start");
2215 LWDEBUG(3,
"ptarray_scale end");
2238 double x,
y, z = 0, m = 0;
2243 for (uint32_t i = 0; i < pa->
npoints; i++)
2259 if (grid->
xsize > 0) {
2260 if (grid->
xsize < 1)
2266 if (grid->
ysize > 0) {
2267 if (grid->
ysize < 1)
2275 if (has_z && grid->
zsize > 0)
2279 if (has_m && grid->
msize > 0)
2292 (ndims > 2 ? p_out->
z == z : 1) &&
2293 (ndims > 3 ? p_out->
m == m : 1))
2319 for ( i = 0; i < pa->
npoints; i++ )
2346 lwerror(
"ptarray_scroll_in_place: input POINTARRAY is not closed");
2354 for ( it = 0; it < pa->
npoints; ++it )
2365 lwerror(
"ptarray_scroll_in_place: input POINTARRAY does not contain the given point");
2383 (
size_t)ptsize * ( pa->
npoints - it )
2391 (
size_t)ptsize * ( it )
2398 (
size_t)ptsize * ( pa->
npoints )
char result[OUT_DOUBLE_BUFFER_SIZE]
int gbox_contains_point2d(const GBOX *g, const POINT2D *p)
int lw_arc_calculate_gbox_cartesian_2d(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, GBOX *gbox)
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
void interpolate_point4d(const POINT4D *A, const POINT4D *B, POINT4D *I, double F)
Find interpolation point I between point A and point B so that the len(AI) == len(AB)*F and I falls o...
#define FLAGS_GET_READONLY(flags)
#define FLAGS_GET_Z(flags)
int getPoint3dz_p(const POINTARRAY *pa, uint32_t n, POINT3DZ *point)
void * lwrealloc(void *mem, size_t size)
#define FLAGS_NDIMS(flags)
#define FLAGS_GET_M(flags)
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
double distance2d_sqr_pt_seg(const POINT2D *p, const POINT2D *A, const POINT2D *B)
#define FLAGS_GET_ZM(flags)
void * lwalloc(size_t size)
#define FLAGS_SET_READONLY(flags, value)
lwflags_t lwflags(int hasz, int hasm, int geodetic)
Construct a new flags bitmask.
#define LW_TRUE
Return types for functions with status returns.
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
enum LWORD_T LWORD
Ordinate names.
#define LW_CLOCKWISE
Constants for orientation checking and forcing.
#define LW_INSIDE
Constants for point-in-polygon return values.
#define LW_COUNTERCLOCKWISE
double lw_arc_length(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
Returns the length of a circular arc segment.
#define LW_ON_INTERRUPT(x)
int lw_pt_on_segment(const POINT2D *p1, const POINT2D *p2, const POINT2D *p)
double lw_arc_center(const POINT2D *p1, const POINT2D *p2, const POINT2D *p3, POINT2D *result)
Determines the center of the circle defined by the three given points.
int lw_pt_in_seg(const POINT2D *P, const POINT2D *A1, const POINT2D *A2)
Returns true if P is between A1/A2.
int lw_segment_side(const POINT2D *p1, const POINT2D *p2, const POINT2D *q)
lw_segment_side()
int lw_arc_is_pt(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
Returns true if arc A is actually a point (all vertices are the same) .
int lw_pt_in_arc(const POINT2D *P, const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
Returns true if P is on the same side of the plane partition defined by A1/A3 as A2 is.
int p2d_same(const POINT2D *p1, const POINT2D *p2)
static double det(double m00, double m01, double m10, double m11)
#define LWDEBUG(level, msg)
#define LWDEBUGF(level, msg,...)
void lwnotice(const char *fmt,...) __attribute__((format(printf
Write a notice out to the notice handler.
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
static double distance2d_sqr_pt_pt(const POINT2D *p1, const POINT2D *p2)
static size_t ptarray_point_size(const POINTARRAY *pa)
static uint8_t * getPoint_internal(const POINTARRAY *pa, uint32_t n)
int ptarray_contains_point_partial(const POINTARRAY *pa, const POINT2D *pt, int check_closed, int *winding_number)
POINTARRAY * ptarray_force_dims(const POINTARRAY *pa, int hasz, int hasm, double zval, double mval)
static uint32_t ptarray_dp_findsplit_in_place(const POINTARRAY *pts, uint32_t it_first, uint32_t it_last, double max_distance_sqr)
POINTARRAY * ptarray_construct_reference_data(char hasz, char hasm, uint32_t npoints, uint8_t *ptlist)
Build a new POINTARRAY, but on top of someone else's ordinate array.
int ptarray_remove_point(POINTARRAY *pa, uint32_t where)
Remove a point from an existing POINTARRAY.
void ptarray_longitude_shift(POINTARRAY *pa)
Longitude shift for a pointarray.
POINTARRAY * ptarray_construct_copy_data(char hasz, char hasm, uint32_t npoints, const uint8_t *ptlist)
Construct a new POINTARRAY, copying in the data from ptlist.
int ptarray_closest_segment_2d(const POINTARRAY *pa, const POINT2D *qp, double *dist)
POINTARRAY * ptarray_clone(const POINTARRAY *in)
Clone a POINTARRAY object.
int ptarray_append_ptarray(POINTARRAY *pa1, POINTARRAY *pa2, double gap_tolerance)
Append a POINTARRAY, pa2 to the end of an existing POINTARRAY, pa1.
void ptarray_reverse_in_place(POINTARRAY *pa)
int ptarray_closest_vertex_2d(const POINTARRAY *pa, const POINT2D *qp, double *dist)
int ptarrayarc_contains_point(const POINTARRAY *pa, const POINT2D *pt)
For POINTARRAYs representing CIRCULARSTRINGS.
int ptarray_is_closed_2d(const POINTARRAY *in)
int ptarray_is_closed_z(const POINTARRAY *in)
int ptarray_raycast_intersections(const POINTARRAY *pa, const POINT2D *p, int *on_boundary)
double ptarray_length(const POINTARRAY *pts)
Find the 3d/2d length of the given POINTARRAY (depending on its dimensionality)
double ptarray_signed_area(const POINTARRAY *pa)
Returns the area in cartesian units.
POINTARRAY * ptarray_addPoint(const POINTARRAY *pa, uint8_t *p, size_t pdims, uint32_t where)
Add a point in a pointarray.
void closest_point_on_segment(const POINT4D *p, const POINT4D *A, const POINT4D *B, POINT4D *ret)
int ptarray_startpoint(const POINTARRAY *pa, POINT4D *pt)
int ptarray_is_closed(const POINTARRAY *in)
Check for ring closure using whatever dimensionality is declared on the pointarray.
POINTARRAY * ptarray_clone_deep(const POINTARRAY *in)
Deep clone a pointarray (also clones serialized pointlist)
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
char ptarray_same(const POINTARRAY *pa1, const POINTARRAY *pa2)
int ptarray_is_closed_3d(const POINTARRAY *in)
void ptarray_remove_repeated_points_in_place(POINTARRAY *pa, double tolerance, uint32_t min_points)
int ptarrayarc_raycast_intersections(const POINTARRAY *pa, const POINT2D *p, int *on_boundary)
POINTARRAY * ptarray_removePoint(POINTARRAY *pa, uint32_t which)
Remove a point from a pointarray.
int ptarray_scroll_in_place(POINTARRAY *pa, const POINT4D *pt)
void ptarray_simplify_in_place(POINTARRAY *pa, double tolerance, uint32_t minpts)
int ptarray_insert_point(POINTARRAY *pa, const POINT4D *p, uint32_t where)
Insert a point into an existing POINTARRAY.
void ptarray_grid_in_place(POINTARRAY *pa, gridspec *grid)
Snap to grid.
double ptarray_arc_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY, using circular arc interpolation between each coordinate ...
POINTARRAY * ptarray_remove_repeated_points(const POINTARRAY *in, double tolerance)
static int circle_raycast_intersections(const POINT2D *center, double radius, double ray, POINT2D *i0, POINT2D *i1)
Calculates the intersection points of a circle and a horizontal line.
void ptarray_affine(POINTARRAY *pa, const AFFINE *a)
Affine transform a pointarray.
int ptarray_contains_point(const POINTARRAY *pa, const POINT2D *pt)
The following is based on the "Fast Winding Number Inclusion of a Point in a Polygon" algorithm by Da...
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
int ptarray_has_orientation(const POINTARRAY *pa, int orientation)
void ptarray_free(POINTARRAY *pa)
static void ptarray_simplify_in_place_tolerance0(POINTARRAY *pa)
int ptarray_isccw(const POINTARRAY *pa)
int ptarray_has_z(const POINTARRAY *pa)
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int repeated_points)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE,...
void ptarray_scale(POINTARRAY *pa, const POINT4D *fact)
WARNING, make sure you send in only 16-member double arrays or obviously things will go pear-shaped f...
static POINTARRAY * ptarray_remove_repeated_points_minpoints(const POINTARRAY *in, double tolerance, int minpoints)
void ptarray_swap_ordinates(POINTARRAY *pa, LWORD o1, LWORD o2)
Swap ordinate values o1 and o2 on a given POINTARRAY.
int ptarray_npoints_in_rect(const POINTARRAY *pa, const GBOX *gbox)
char ptarray_same2d(const POINTARRAY *pa1, const POINTARRAY *pa2)
POINTARRAY * ptarray_substring(POINTARRAY *ipa, double from, double to, double tolerance)
@d1 start location (distance from start / total distance) @d2 end location (distance from start / tot...
POINTARRAY * ptarray_merge(POINTARRAY *pa1, POINTARRAY *pa2)
Merge two given POINTARRAY and returns a pointer on the new aggregate one.
POINTARRAY * ptarray_flip_coordinates(POINTARRAY *pa)
Reverse X and Y axis on a given POINTARRAY.
int ptarray_has_m(const POINTARRAY *pa)
POINTARRAY * ptarray_segmentize2d(const POINTARRAY *ipa, double dist)
Returns a modified POINTARRAY so that no segment is longer than the given distance (computed using 2d...
double ptarray_locate_point(const POINTARRAY *pa, const POINT4D *p4d, double *mindistout, POINT4D *proj4d)
uint8_t * serialized_pointlist