72 double side = ( (q->
x - p1->
x) * (p2->
y - p1->
y) - (p2->
x - p1->
x) * (q->
y - p1->
y) );
82 return sqrt((A1->
x-A2->
x)*(A1->
x-A2->
x)+(A1->
y-A2->
y)*(A1->
y-A2->
y));
103 return ((A1->
x <= P->
x && P->
x < A2->
x) || (A1->
x >= P->
x && P->
x > A2->
x)) ||
104 ((A1->
y <= P->
y && P->
y < A2->
y) || (A1->
y >= P->
y && P->
y > A2->
y));
113 if ( A1->
x == A2->
x && A2->
x == A3->
x &&
114 A1->
y == A2->
y && A2->
y == A3->
y )
127 double radius_A, circumference_A;
128 int a2_side, clockwise;
140 double dx = A1->
x - A3->
x;
141 double dy = A1->
y - A3->
y;
142 return sqrt(dx*dx + dy*dy);
146 circumference_A = M_PI * 2 * radius_A;
148 return circumference_A;
161 a1 = atan2(A1->
y - C.
y, A1->
x - C.
x);
162 a3 = atan2(A3->
y - C.
y, A3->
x - C.
x);
170 angle = 2*M_PI + a1 - a3;
177 angle = 2*M_PI + a3 - a1;
181 return circumference_A * (angle / (2*M_PI));
188 double side_Q, side_A2;
202 if ( d == radius_A && side_Q == side_A2 )
217 if ( d < radius_A && side_Q == side_A2 )
238 double dx21, dy21, dx31, dy31, h21, h31, d;
242 LWDEBUGF(2,
"lw_arc_center called (%.16f,%.16f), (%.16f,%.16f), (%.16f,%.16f).", p1->
x, p1->
y, p2->
x, p2->
y, p3->
x, p3->
y);
248 cx = p1->
x + (p2->
x - p1->
x) / 2.0;
249 cy = p1->
y + (p2->
y - p1->
y) / 2.0;
253 cr = sqrt(pow(cx - p1->
x, 2.0) + pow(cy - p1->
y, 2.0));
258 dx21 = p2->
x - p1->
x;
259 dy21 = p2->
y - p1->
y;
260 dx31 = p3->
x - p1->
x;
261 dy31 = p3->
y - p1->
y;
263 h21 = pow(dx21, 2.0) + pow(dy21, 2.0);
264 h31 = pow(dx31, 2.0) + pow(dy31, 2.0);
267 d = 2 * (dx21 * dy31 - dx31 * dy21);
274 cx = p1->
x + (h21 * dy31 - h31 * dy21) / d;
275 cy = p1->
y - (h21 * dx31 - h31 * dx21) / d;
279 cr = sqrt(pow(cx - p1->
x, 2) + pow(cy - p1->
y, 2));
296 if ( memcmp(first, last,
sizeof(
POINT2D)) )
298 lwerror(
"pt_in_ring_2d: V[n] != V[0] (%g %g != %g %g)",
299 first->
x, first->
y, last->
x, last->
y);
304 LWDEBUGF(2,
"pt_in_ring_2d called with point: %g %g", p->
x, p->
y);
309 for (i=0; i<ring->
npoints-1; i++)
318 ((v1->
y <= p->
y) && (v2->
y > p->
y))
320 || ((v1->
y > p->
y) && (v2->
y <= p->
y))
324 vt = (double)(p->
y - v1->
y) / (v2->
y - v1->
y);
327 if (p->
x < v1->
x + vt * (v2->
x - v1->
x))
336 LWDEBUGF(3,
"pt_in_ring_2d returning %d", cn&1);
381 int pq1, pq2, qp1, qp2;
392 if ((pq1>0 && pq2>0) || (pq1<0 && pq2<0))
400 if ( (qp1 > 0.0 && qp2 > 0.0) || (qp1 < 0.0 && qp2 < 0.0) )
406 if ( pq1 == 0.0 && pq2 == 0.0 && qp1 == 0.0 && qp2 == 0.0 )
416 LWDEBUGF(4,
"pq1=%d pq2=%d", pq1, pq2);
417 LWDEBUGF(4,
"qp1=%d qp2=%d", qp1, qp2);
420 if ( pq2 == 0 || qp2 == 0 )
469 uint32_t i = 0, j = 0;
470 const POINT2D *p1, *p2, *q1, *q2;
476 #if POSTGIS_DEBUG_LEVEL >= 4
484 if ( pa1->
npoints < 2 || pa2->npoints < 2 )
492 #if POSTGIS_DEBUG_LEVEL >= 4
504 for ( i = 1; i < pa2->npoints; i++ )
513 for ( j = 1; j < pa1->
npoints; j++ )
521 LWDEBUGF(4,
"i=%d, j=%d (%.8g %.8g, %.8g %.8g)", i, j, p1->
x, p1->
y, p2->
x, p2->
y);
525 LWDEBUG(4,
"this_cross == SEG_CROSS_LEFT");
533 LWDEBUG(4,
"this_cross == SEG_CROSS_RIGHT");
546 LWDEBUG(4,
"this_cross == SEG_COLINEAR");
552 LWDEBUG(4,
"this_cross == SEG_NO_INTERSECTION");
564 LWDEBUGF(4,
"first_cross=%d, cross_left=%d, cross_right=%d", first_cross, cross_left, cross_right);
566 if ( !cross_left && !cross_right )
569 if ( !cross_left && cross_right == 1 )
572 if ( !cross_right && cross_left == 1 )
575 if ( cross_left - cross_right == 1 )
578 if ( cross_left - cross_right == -1 )
581 if ( cross_left - cross_right == 0 && first_cross ==
SEG_CROSS_LEFT )
595 static char *
base32 =
"0123456789bcdefghjkmnpqrstuvwxyz";
606 double lat[2], lon[2], mid;
607 char bits[] = {16,8,4,2,1};
611 char *geohash = v->
data;
622 mid = (lon[0] + lon[1]) / 2;
623 if (longitude >= mid)
635 mid = (lat[0] + lat[1]) / 2;
654 geohash[i++] =
base32[ch];
672 double lat[2], lon[2], mid;
676 double longitude = pt->
x;
677 double latitude = pt->
y;
688 mid = (lon[0] + lon[1]) / 2;
691 ch |= 0x0001u << bit;
701 mid = (lat[0] + lat[1]) / 2;
735 size_t hashlen = strlen(geohash);
743 char c = tolower(geohash[i]);
746 char *base32_pos = strchr(
base32, c);
749 lwerror(
"%s: Invalid character '%c'", __func__, geohash[i]);
752 char cd = base32_pos -
base32;
754 for (
size_t j = 0; j < 5; j++)
756 const char bits[] = {16, 8, 4, 2, 1};
760 lon[!(cd & mask)] = (lon[0] + lon[1]) / 2;
764 lat[!(cd & mask)] = (lat[0] + lat[1]) / 2;
773 double minx, miny, maxx, maxy;
774 double latmax, latmin, lonmax, lonmin;
775 double lonwidth, latwidth;
776 double latmaxadjust, lonmaxadjust, latminadjust, lonminadjust;
785 if ( minx == maxx && miny == maxy )
801 lonwidth = lonmax - lonmin;
802 latwidth = latmax - latmin;
803 latmaxadjust = lonmaxadjust = latminadjust = lonminadjust = 0.0;
805 if ( minx > lonmin + lonwidth / 2.0 )
807 lonminadjust = lonwidth / 2.0;
809 else if ( maxx < lonmax - lonwidth / 2.0 )
811 lonmaxadjust = -1 * lonwidth / 2.0;
813 if ( lonminadjust || lonmaxadjust )
815 lonmin += lonminadjust;
816 lonmax += lonmaxadjust;
826 if ( miny > latmin + latwidth / 2.0 )
828 latminadjust = latwidth / 2.0;
830 else if (maxy < latmax - latwidth / 2.0 )
832 latmaxadjust = -1 * latwidth / 2.0;
835 if ( latminadjust || latmaxadjust )
837 latmin += latminadjust;
838 latmax += latmaxadjust;
850 bounds->
xmin = lonmin;
851 bounds->
xmax = lonmax;
852 bounds->
ymin = latmin;
853 bounds->
ymax = latmax;
871 GBOX gbox_bounds = {0};
882 if ( gbox.
xmin < -180 || gbox.
ymin < -90 || gbox.
xmax > 180 || gbox.
ymax > 90 )
884 lwerror(
"Geohash requires inputs in decimal degrees, got (%g %g, %g %g).",
char result[OUT_DOUBLE_BUFFER_SIZE]
int lwgeom_calculate_gbox_cartesian(const LWGEOM *lwgeom, GBOX *gbox)
Calculate the 2-4D bounding box of a geometry.
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an allocated string.
@ LINE_MULTICROSS_END_RIGHT
@ LINE_MULTICROSS_END_SAME_FIRST_LEFT
@ LINE_MULTICROSS_END_LEFT
@ LINE_MULTICROSS_END_SAME_FIRST_RIGHT
#define LWSIZE_SET(varsize, len)
void * lwalloc(size_t size)
#define LW_TRUE
Return types for functions with status returns.
#define EPSILON_SQLMM
Tolerance used to determine equality.
#define SIGNUM(n)
Macro that returns: -1 if n < 0, 1 if n > 0, 0 if n == 0.
int lwgeom_geohash_precision(GBOX bbox, GBOX *bounds)
int p4d_same(const POINT4D *p1, const POINT4D *p2)
int p3d_same(const POINT3D *p1, const POINT3D *p2)
double lw_arc_length(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
Returns the length of a circular arc segment.
lwvarlena_t * lwgeom_geohash(const LWGEOM *lwgeom, int precision)
Calculate the GeoHash (http://geohash.org) string for a geometry.
lwvarlena_t * geohash_point(double longitude, double latitude, int precision)
unsigned int geohash_point_as_int(POINT2D *pt)
int lwline_crossing_direction(const LWLINE *l1, const LWLINE *l2)
lwline_crossing_direction: returns the kind of CG_LINE_CROSS_TYPE behavior of 2 linestrings
int lw_segment_intersects(const POINT2D *p1, const POINT2D *p2, const POINT2D *q1, const POINT2D *q2)
returns the kind of CG_SEGMENT_INTERSECTION_TYPE behavior of lineseg 1 (constructed from p1 and p2) a...
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 pt_in_ring_2d(const POINT2D *p, const POINTARRAY *ring)
int lw_arc_side(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3, const POINT2D *Q)
double lw_seg_length(const POINT2D *A1, const POINT2D *A2)
Returns the length of a linear segment.
int p3dz_same(const POINT3DZ *p1, const POINT3DZ *p2)
static int lw_seg_interact(const POINT2D *p1, const POINT2D *p2, const POINT2D *q1, const POINT2D *q2)
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) .
void decode_geohash_bbox(char *geohash, double *lat, double *lon, int precision)
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)
#define LWDEBUG(level, msg)
#define LWDEBUGF(level, msg,...)
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.