/* ----------------------------------------------------------
move the rest of the list down to eliminate the duplicate.
The replacement entry will become the new, requested stz
-
+
if there are, for instance, n stz pointers active, stz_list_size
will be n. So the ordinal n-1 is the last active stz. In this
function, after the first instruction, n will point to the last
/* -- Increase the list size only if it isn't full. If it is full, take
the score of the last on the list (which we're going to knock off the
list) as the new cutoff -- */
-
+
if (__stz_info__->stz_list_size != MAX_STZ)
{
__stz_info__->stz_list_size++ ;
}
-
+
/* -- Get the pointer of the last on the list if the list is full (to be
knocked off, or one beyond the previous last item (with undefined
content) if the list isn't full. -- */
=======================================================================*/
static void save_current_composition(STAND_PARAM *__stand_param__,SEG *__segments__, int depth, SYMB *__best_output__ , DEF **__best_defs__)
{
-
+
int lex_pos ;
SEG *__seg__ ;
int *__sym_sel__ = __stand_param__->cur_sym_sel ;
-
+
/*-- <remarks> Get the definitions selected from save_defs - needed for outputing
the lexemes. Different definitions may give a different
standardization for the same input - the letter W may be standardized
as W if a SINGLE or WEST if a DIRECT </remarks> --*/
-
+
/* -- use the whole target -- */
for ( lex_pos = FIRST_LEX_POS ; lex_pos < __stand_param__->LexNum ; lex_pos++ )
{
__best_defs__[lex_pos] = __stand_param__->def_array[lex_pos][__sym_sel__[lex_pos]] ;
}
__best_defs__[lex_pos] = NULL ;
-
+
/*-- <remarks> Segments go backwards (right to left) , but the content for
each segment goes left to right </remarks> --*/
-
+
for ( __seg__ = __segments__ + depth, lex_pos = FIRST_LEX_POS ; __seg__ >= __segments__ ; __seg__-- )
{
SYMB *__sym_ptr__ ;
{
int lex_pos ;
int *__orig_pos__ = __stand_param__->orig_str_pos ;
-
+
/*-- <remarks> <code>orig_pos</code> has the (multiple) LEXEME positions to which the
(single) output symbol corresponds - so we add that symbol to each of
the positions </remarks> --*/
-
+
int next_target_pos = __orig_pos__[beg] + 1 ;
for ( lex_pos = beg ; __orig_pos__[lex_pos] < next_target_pos ; lex_pos ++ )
{
char *err_dest ) {
ERR_REC *err_mem ;
-
+
if ( err_p == NULL ) {
return FALSE ;
}
{
LWDEBUG(2,"Entered bytebuffer_destroy");
LWDEBUGF(4,"The buffer has used %d bytes",bytebuffer_getlength(s));
-
+
if ( s->buf_start )
{
LWDEBUGF(4,"let's free buf_start %p",s->buf_start);
}
if ( s )
{
- lwfree(s);
+ lwfree(s);
LWDEBUG(4,"bytebuffer_t is freed");
}
return;
*/
void
bytebuffer_append_byte(bytebuffer_t *s, const uint8_t val)
-{
- LWDEBUGF(2,"Entered bytebuffer_append_byte with value %d", val);
+{
+ LWDEBUGF(2,"Entered bytebuffer_append_byte with value %d", val);
bytebuffer_makeroom(s, 1);
*(s->writecursor)=val;
s->writecursor += 1;
*/
void
bytebuffer_append_bulk(bytebuffer_t *s, void * start, size_t size)
-{
- LWDEBUGF(2,"bytebuffer_append_bulk with size %d",size);
+{
+ LWDEBUGF(2,"bytebuffer_append_bulk with size %d",size);
bytebuffer_makeroom(s, size);
memcpy(s->writecursor, start, size);
s->writecursor += size;
*/
void
bytebuffer_append_bytebuffer(bytebuffer_t *write_to,bytebuffer_t *write_from )
-{
- LWDEBUG(2,"bytebuffer_append_bytebuffer");
+{
+ LWDEBUG(2,"bytebuffer_append_bytebuffer");
size_t size = bytebuffer_getlength(write_from);
bytebuffer_makeroom(write_to, size);
memcpy(write_to->writecursor, write_from->buf_start, size);
*/
void
bytebuffer_append_varint(bytebuffer_t *b, const int64_t val)
-{
+{
size_t size;
bytebuffer_makeroom(b, 8);
size = varint_s64_encode_buf(val, b->writecursor);
*/
void
bytebuffer_append_uvarint(bytebuffer_t *b, const uint64_t val)
-{
+{
size_t size;
bytebuffer_makeroom(b, 8);
size = varint_u64_encode_buf(val, b->writecursor);
void
bytebuffer_append_int(bytebuffer_t *buf, const int val, int swap)
{
- LWDEBUGF(2,"Entered bytebuffer_append_int with value %d, swap = %d", val, swap);
-
+ LWDEBUGF(2,"Entered bytebuffer_append_int with value %d, swap = %d", val, swap);
+
LWDEBUGF(4,"buf_start = %p and write_cursor=%p", buf->buf_start,buf->writecursor);
char *iptr = (char*)(&val);
int i = 0;
{
lwerror("Machine int size is not %d bytes!", WKB_INT_SIZE);
}
-
+
bytebuffer_makeroom(buf, WKB_INT_SIZE);
/* Machine/request arch mismatch, so flip byte order */
if ( swap)
{
- LWDEBUG(4,"Ok, let's do the swaping thing");
+ LWDEBUG(4,"Ok, let's do the swaping thing");
for ( i = 0; i < WKB_INT_SIZE; i++ )
{
*(buf->writecursor) = iptr[WKB_INT_SIZE - 1 - i];
/* If machine arch and requested arch match, don't flip byte order */
else
{
- LWDEBUG(4,"Ok, let's do the memcopying thing");
+ LWDEBUG(4,"Ok, let's do the memcopying thing");
memcpy(buf->writecursor, iptr, WKB_INT_SIZE);
buf->writecursor += WKB_INT_SIZE;
}
-
+
LWDEBUGF(4,"buf_start = %p and write_cursor=%p", buf->buf_start,buf->writecursor);
return;
void
bytebuffer_append_double(bytebuffer_t *buf, const double val, int swap)
{
- LWDEBUGF(2,"Entered bytebuffer_append_double with value %lf swap = %d", val, swap);
-
+ LWDEBUGF(2,"Entered bytebuffer_append_double with value %lf swap = %d", val, swap);
+
LWDEBUGF(4,"buf_start = %p and write_cursor=%p", buf->buf_start,buf->writecursor);
char *dptr = (char*)(&val);
int i = 0;
}
bytebuffer_makeroom(buf, WKB_DOUBLE_SIZE);
-
+
/* Machine/request arch mismatch, so flip byte order */
if ( swap )
{
- LWDEBUG(4,"Ok, let's do the swapping thing");
+ LWDEBUG(4,"Ok, let's do the swapping thing");
for ( i = 0; i < WKB_DOUBLE_SIZE; i++ )
{
*(buf->writecursor) = dptr[WKB_DOUBLE_SIZE - 1 - i];
/* If machine arch and requested arch match, don't flip byte order */
else
{
- LWDEBUG(4,"Ok, let's do the memcopying thing");
+ LWDEBUG(4,"Ok, let's do the memcopying thing");
memcpy(buf->writecursor, dptr, WKB_DOUBLE_SIZE);
buf->writecursor += WKB_DOUBLE_SIZE;
}
-
- LWDEBUG(4,"Return from bytebuffer_append_double");
+
+ LWDEBUG(4,"Return from bytebuffer_append_double");
return;
}
*/
uint64_t
bytebuffer_read_uvarint(bytebuffer_t *b)
-{
+{
size_t size;
uint64_t val = varint_u64_decode(b->readcursor, b->buf_start + b->capacity, &size);
b->readcursor += size;
{
total_size += bytebuffer_getlength(buff_array[i]);
}
-
+
bytebuffer_t *res = bytebuffer_create_with_size(total_size);
for ( i = 0; i < nbuffers; i++)
{
CU_ASSERT_DOUBLE_EQUAL(d1, 0.0046097720751, 0.0001);
CU_ASSERT_DOUBLE_EQUAL(c1.x, 2047538.599, 0.001);
CU_ASSERT_DOUBLE_EQUAL(c1.y, 7268770.4395, 0.001);
-
+
// printf("lw_arc_center: (%12.12g, %12.12g) %12.12g\n", c1.x, c1.y, d1);
}
unsigned int gh;
POINT2D p;
unsigned long long rs;
-
+
p.x = 50; p.y = 35;
gh = geohash_point_as_int(&p);
rs = 3440103613;
CU_ASSERT_EQUAL(l, NULL);
lwgeom_free(g);
lwgeom_free(l);
-
+
/* Not simplifiable */
g = lwgeom_from_wkt("LINESTRING(0 0, 50 1.00001, 100 0)", LW_PARSER_CHECK_NONE);
l = lwgeom_simplify(g, 1.0, LW_FALSE);
LWPOINT* result = lwgeom_median(g, FP_TOLERANCE / 10.0, 1000, LW_TRUE);
int passed = LW_TRUE;
-
+
lwpoint_getPoint3dz_p(result, &actual_pt);
lwpoint_getPoint3dz_p(expected_result, &expected_pt);
bytebuffer_t *bb1;
int64_t res;
bb1 = bytebuffer_create_with_size(2);
-
+
bytebuffer_append_varint(bb1,(int64_t) -12345);
-
+
bytebuffer_reset_reading(bb1);
-
+
res= bytebuffer_read_varint(bb1);
CU_ASSERT_EQUAL(res, -12345);
CU_ASSERT(1); \
} \
} while (0)
-
+
static void test_lwgeom_make_valid(void)
{
LWGEOM *gin, *gout, *gexp;
{
int i;
- EFFECTIVE_AREAS *ea;
-
- ea=initiate_effectivearea(pa);
+ EFFECTIVE_AREAS *ea;
+
+ ea=initiate_effectivearea(pa);
ptarray_calc_areas(ea,avoid_collaps,1,0);
for (i=0;i<pa->npoints;i++)
}
destroy_effectivearea(ea);
-
-
+
+
}
static void do_test_lwgeom_effectivearea_lines(void)
{
LWPOLY *the_geom;
int avoid_collaps=4;
-
+
/*POLYGON 1*/
the_geom = (LWPOLY*)lwgeom_from_wkt("POLYGON((10 10,12 8, 15 7, 18 7, 20 20, 15 21, 18 22, 10 30,1 99, 0 100, 10 10))", LW_PARSER_CHECK_NONE);
double the_areas1[]={FLT_MAX,5,1.5,55,100,4,4,FLT_MAX,30,FLT_MAX,FLT_MAX};
POLYGONTYPE);
do_type_test("CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (0 0 2 5,1 1 2 6,1 0 2 5), (1 0 2 3,0 1 2 2), (0 1 2 2,30 1 2 2), CIRCULARSTRING (30 1 2 2,12 1 2 6,1 10 2 5, 1 10 3 5, 0 0 2 5)))",
- POLYGONTYPE);
+ POLYGONTYPE);
do_type_test("MULTISURFACE (CURVEPOLYGON (CIRCULARSTRING (-2 0, -1 -1, 0 0, 1 -1, 2 0, 0 2, -2 0), (-1 0, 0 0.5, 1 0, 0 1, -1 0)), ((7 8, 10 10, 6 14, 4 11, 7 8)))",
MULTIPOLYGONTYPE);
/* GeodSolve -i -E -p 16 -e 1 0 --input-string "0 0 1 0" */
CU_ASSERT_DOUBLE_EQUAL(dir, 0.0, 1e-14);
CU_ASSERT_DOUBLE_EQUAL(dist, 0.0174532925199433, 1e-14);
-
+
}
static void test_sphere_project(void)
dir1 = M_PI_2;
dist1 = 0.1;
-
+
geographic_point_init(0, 0, &s);
sphere_project(&s, dist1, dir1, &e);
CU_ASSERT_DOUBLE_EQUAL(e.lon, 0.1, 1e-14);
CU_ASSERT_DOUBLE_EQUAL(e.lat, 0.0, 1e-14);
-
+
/* Direct and inverse solutions agree */
dist2 = sphere_distance(&s, &e);
dir2 = sphere_direction(&s, &e, dist1);
CU_ASSERT_DOUBLE_EQUAL(dist1, dist2, 1e-14);
CU_ASSERT_DOUBLE_EQUAL(dir1, dir2, 1e-14);
-
+
dist1 = sphere_distance(&e, &s);
dir1 = sphere_direction(&e, &s, dist1);
sphere_project(&e, dist1, dir1, &s);
/* GeodSolve -i -E -p 16 -e 1 0 --input-string "1 0 2 0" */
CU_ASSERT_DOUBLE_EQUAL(dir2, 0.0, 1e-14);
CU_ASSERT_DOUBLE_EQUAL(dist2, 0.0174532925199433, 1e-14);
-
+
geographic_point_init(1, 1, &e);
dist2 = sphere_distance(&s, &e);
dir2 = sphere_direction(&s, &e, dist2);
p1.y = 45.0;
p2.x = 10.0;
p2.y = 50.0;
-
+
geographic_point_init(p1.x, p1.y, &g1);
ll2cart(&p1, &A1);
{
geographic_point_init(p2.x, p2.y, &g2);
ll2cart(&p2, &A2);
-
+
/* Skea */
robust_cross_product(&g1, &g2, &Nr);
normalize(&Nr);
-
+
/* Ramsey */
unit_normal(&A1, &A2, &Nc);
printf("Ramsey Diff: %.24g,%.24g,%.24g\n", Oc.x-Nc.x, Oc.y-Nc.y, Oc.z-Nc.z);
printf("Diff: %.24g,%.24g,%.24g\n", Nr.x-Nc.x, Nr.y-Nc.y, Nr.z-Nc.z);
}
-
+
Or = Nr;
Oc = Nc;
-
+
p2.y += (p1.y - p2.y)/2.0;
}
}
ll[3] = -5.25;
pa = ptarray_construct_reference_data(0, 0, 2, (uint8_t*)ll);
-
+
lwline = lwline_as_lwgeom(lwline_construct(SRID_UNKNOWN, 0, pa));
FLAGS_SET_GEODETIC(lwline->flags, 1);
line2pts("LINESTRING(45.0 10.0, 50.0 20.0)", &A1, &A2);
line2pts("LINESTRING(45.0 10.0, 50.0 20.0)", &B1, &B2);
rv = edge_intersects(&A1, &A2, &B1, &B2);
- CU_ASSERT(rv & PIR_INTERSECTS);
-
+ CU_ASSERT(rv & PIR_INTERSECTS);
+
/* Parallel edges (same great circle, different end points) return true */
line2pts("LINESTRING(40.0 0.0, 70.0 0.0)", &A1, &A2);
line2pts("LINESTRING(60.0 0.0, 50.0 0.0)", &B1, &B2);
line2pts("LINESTRING(90.0 80.0, -90.0 90.0)", &B1, &B2);
rv = edge_intersects(&A1, &A2, &B1, &B2);
CU_ASSERT(rv == (PIR_INTERSECTS|PIR_B_TOUCH_LEFT) );
-
+
/* End touches end at north pole */
line2pts("LINESTRING(-180.0 80.0, 0.0 90.0)", &A1, &A2);
line2pts("LINESTRING(90.0 80.0, -90.0 90.0)", &B1, &B2);
line2pts("LINESTRING(65 0, -105 0)", &B1, &B2);
rv = edge_intersects(&A1, &A2, &B1, &B2);
CU_ASSERT(rv == 0);
-
+
line2pts("LINESTRING(175 -85, 175 85)", &A1, &A2);
line2pts("LINESTRING(45 0, -125 0)", &B1, &B2);
rv = edge_intersects(&A1, &A2, &B1, &B2);
CU_ASSERT(rv == 0);
-
+
}
static void test_edge_distance_to_point(void)
// printf("CLOSE POINT(%g %g)\n", closest.lon, closest.lat);
// printf(" ORIG POINT(%g %g)\n", g.lon, g.lat);
CU_ASSERT_DOUBLE_EQUAL(g.lat, closest.lat, 0.00001);
- CU_ASSERT_DOUBLE_EQUAL(g.lon, closest.lon, 0.00001);
+ CU_ASSERT_DOUBLE_EQUAL(g.lon, closest.lon, 0.00001);
}
static void test_edge_distance_to_edge(void)
result = ptarray_contains_point_sphere(poly->rings[0], &pt_outside, &pt_to_test);
CU_ASSERT_EQUAL(result, LW_FALSE);
lwgeom_free(lwg);
-
+
/* Point on ring between vertexes case */
lwg = lwgeom_from_wkt("POLYGON((1.0 1.0, 1.0 1.1, 1.1 1.1, 1.1 1.0, 1.0 1.0))", LW_PARSER_CHECK_NONE);
poly = (LWPOLY*)lwg;
result = ptarray_contains_point_sphere(poly->rings[0], &pt_outside, &pt_to_test);
CU_ASSERT_EQUAL(result, LW_TRUE);
lwgeom_free(lwg);
-
+
/* Simple containment case */
lwg = lwgeom_from_wkt("POLYGON((1.0 1.0, 1.0 1.1, 1.1 1.1, 1.1 1.0, 1.0 1.0))", LW_PARSER_CHECK_NONE);
poly = (LWPOLY*)lwg;
result = lwpoly_covers_point2d(poly, &pt_to_test);
CU_ASSERT_EQUAL(result, LW_TRUE);
lwgeom_free(lwg);
-
+
}
static void test_ptarray_contains_point_sphere_iowa(void)
pt_to_test.y = 42.899999999999999;
pt_outside.x = -96.381873780830645;
pt_outside.y = 40.185394449416371;
-
+
rv = ptarray_contains_point_sphere(pa, &pt_outside, &pt_to_test);
CU_ASSERT_EQUAL(rv, LW_TRUE);
spheroid_init(&s, WGS84_MAJOR_AXIS, WGS84_MINOR_AXIS);
gbox.flags = gflags(0, 0, 1);
-
+
/* One-degree square by equator */
lwg = lwgeom_from_wkt("POLYGON((1 20,1 21,2 21,2 20,1 20))", LW_PARSER_CHECK_NONE);
lwgeom_calculate_gbox_geodetic(lwg, &gbox);
CU_ASSERT_DOUBLE_EQUAL(a1, 0.0174613, 0.0000001);
CU_ASSERT_DOUBLE_EQUAL(a2, 0.0174553, 0.0000001);
lwgeom_free(lwg);
-
+
/* One-degree square *across* antimeridian */
lwg = lwgeom_from_wkt("POLYGON((178.5 2,178.5 1,-179.5 1,-179.5 2,178.5 2))", LW_PARSER_CHECK_NONE);
lwgeom_calculate_gbox_geodetic(lwg, &gbox);
CU_ASSERT_DOUBLE_EQUAL(pt.x, 179.5, 0.0001);
CU_ASSERT_DOUBLE_EQUAL(pt.y, 1.50024, 0.0001);
lwgeom_free(lwg);
-
+
}
static void test_vector_angle(void)
{
POINT3D p1, p2;
double angle;
-
+
memset(&p1, 0, sizeof(POINT3D));
memset(&p2, 0, sizeof(POINT3D));
-
+
p1.x = 1.0;
p2.y = 1.0;
angle = vector_angle(&p1, &p2);
p2.x = p2.y = p2.z = 1.0;
normalize(&p2);
angle = vector_angle(&p1, &p2);
- CU_ASSERT_DOUBLE_EQUAL(angle, 0.955317, 0.00001);
+ CU_ASSERT_DOUBLE_EQUAL(angle, 0.955317, 0.00001);
//printf ("angle = %g\n\n", angle);
}
{
POINT3D p1, p2, n;
double angle;
-
+
memset(&p1, 0, sizeof(POINT3D));
memset(&p2, 0, sizeof(POINT3D));
memset(&n, 0, sizeof(POINT3D));
-
+
p1.x = 1.0;
p2.y = 1.0;
angle = M_PI_4;
vector_rotate(&p1, &p2, angle, &n);
//printf("%g %g %g\n\n", n.x, n.y, n.z);
- CU_ASSERT_DOUBLE_EQUAL(n.x, 0.707107, 0.00001);
+ CU_ASSERT_DOUBLE_EQUAL(n.x, 0.707107, 0.00001);
angle = 2*M_PI/400000000;
vector_rotate(&p1, &p2, angle, &n);
//printf("%.21g %.21g %.21g\n\n", n.x, n.y, n.z);
- CU_ASSERT_DOUBLE_EQUAL(n.x, 0.999999999999999888978, 0.0000000000000001);
- CU_ASSERT_DOUBLE_EQUAL(n.y, 1.57079632679489654446e-08, 0.0000000000000001);
+ CU_ASSERT_DOUBLE_EQUAL(n.x, 0.999999999999999888978, 0.0000000000000001);
+ CU_ASSERT_DOUBLE_EQUAL(n.y, 1.57079632679489654446e-08, 0.0000000000000001);
angle = 0;
vector_rotate(&p1, &p2, angle, &n);
//printf("%.16g %.16g %.16g\n\n", n.x, n.y, n.z);
- CU_ASSERT_DOUBLE_EQUAL(n.x, 1.0, 0.00000001);
+ CU_ASSERT_DOUBLE_EQUAL(n.x, 1.0, 0.00000001);
}
static void test_lwgeom_segmentize_sphere(void)
lwgeom_free(lwg1);
lwgeom_free(lwg2);
//lwfree(wkt);
-
+
return;
}
/* Simple case */
lwg = lwgeom_from_wkt("POLYGON((1 1, 1 2, 2 2, 2 1, 1 1))", LW_PARSER_CHECK_NONE);
area = lwgeom_area_sphere(lwg, &s);
-
+
CU_ASSERT_DOUBLE_EQUAL(area, 12360265021.3561, 1.0);
lwgeom_free(lwg);
char *out_ewkt;
LWGEOM *geom1 = lwgeom_from_wkt(ewkt, LW_PARSER_CHECK_NONE);
LWGEOM *geom2 = lwgeom_segmentize2d(geom1, 1.0);
-
+
LWCOLLECTION *geom3 = lwgeom_subdivide(geom2, 80);
out_ewkt = lwgeom_to_ewkt((LWGEOM*)geom3);
// printf("\n--------\n%s\n--------\n", out_ewkt);
{
struct dbscan_test_info test;
char* wkt_inputs[] = { "POLYGONM((-71.1319 42.2503 1,-71.132 42.2502 3,-71.1323 42.2504 -2,-71.1322 42.2505 1,-71.1319 42.2503 0))",
- "POLYGONM((-71.1319 42.2512 0,-71.1318 42.2511 20,-71.1317 42.2511 -20,-71.1317 42.251 5,-71.1317 42.2509 4,-71.132 42.2511 6,-71.1319 42.2512 30))" };
+ "POLYGONM((-71.1319 42.2512 0,-71.1318 42.2511 20,-71.1317 42.2511 -20,-71.1317 42.251 5,-71.1317 42.2509 4,-71.132 42.2511 6,-71.1319 42.2512 30))" };
test.eps = 20.1;
test.min_points = 5;
uint32_t expected_ids[] = { rand(), rand() };
printf("POSITION: %d\n", pr.errlocation);
exit(0);
}
-
+
/* Get the geom */
g_a = pr.geom;
uint8_t *wkb_a, *wkb_b;
size_t wkb_size_a, wkb_size_b;
/* int i; char *hex; */
-
+
if ( hex_a ) free(hex_a);
if ( hex_b ) free(hex_b);
/* Get the geom */
g_a = pr.geom;
-
+
/* Turn geom into WKB */
wkb_a = lwgeom_to_wkb(g_a, WKB_NDR | WKB_EXTENDED, &wkb_size_a);
cu_wkb_in("SRID=4;POINTM(1 1 1)");
CU_ASSERT_STRING_EQUAL(hex_a, hex_b);
-
+
cu_wkb_in("POINT EMPTY");
CU_ASSERT_STRING_EQUAL(hex_a, hex_b);
lwgeom_calculate_gbox_cartesian(g, &b);
CU_ASSERT_DOUBLE_EQUAL(b.xmin, 0.0, 0.0000001);
lwgeom_free(g);
-
+
/* Inf = 0x7FF0000000000000 */
/* POINT(0 0) = 00 00000001 0000000000000000 0000000000000000 */
/* POINT(0 Inf) = 00 00000001 0000000000000000 7FF0000000000000 */
CU_ASSERT_DOUBLE_EQUAL(b.xmin, 0.0, 0.0000001);
CU_ASSERT(isinf(b.ymax));
lwgeom_free(g);
-
+
/* Geometry with NaN 0101000020E8640000000000000000F8FF000000000000F8FF */
/* NaN should show up in bbox for "SRID=4326;POINT(0 NaN)" */
g = lwgeom_from_hexwkb("0101000020E86400000000000000000000000000000000F8FF", LW_PARSER_CHECK_NONE);
lwgeom_calculate_gbox_cartesian(g, &b);
CU_ASSERT(isnan(b.ymax));
- lwgeom_free(g);
-
+ lwgeom_free(g);
+
}
static void test_gbox_serialized_size(void)
const char* wkt;
int isempty;
};
-
+
struct gserialized_empty_cases cases[] = {
{ "POINT EMPTY", 1 },
{ "POINT(1 1)", 0 },
{ "GEOMETRYCOLLECTION(POLYGON EMPTY,GEOMETRYCOLLECTION(POINT EMPTY),MULTILINESTRING(EMPTY,EMPTY),POINT EMPTY)", 1 },
{ NULL, 0 }
};
-
+
while( cases[i].wkt )
{
// i = 11;
i++;
}
}
-
+
static void test_geometry_type_from_string(void)
{
xmax = g->bbox->xmax;
ymax = g->bbox->ymax;
}
-
+
g = lwgeom_flip_coordinates(g);
-
+
if ( testbox )
{
CU_ASSERT_DOUBLE_EQUAL(g->bbox->xmax, ymax, 0.00001);
double d = 1000000.123456789123456789;
float f;
double e;
-
+
f = next_float_down(d);
- d = next_float_down(f);
+ d = next_float_down(f);
CU_ASSERT_DOUBLE_EQUAL(f,d, 0.0000001);
-
+
e = (double)f;
CU_ASSERT_DOUBLE_EQUAL(f,e, 0.0000001);
-
+
f = next_float_down(d);
d = next_float_down(f);
CU_ASSERT_DOUBLE_EQUAL(f,d, 0.0000001);
geom = lwgeom_from_hexwkb(in_ewkt, LW_PARSER_CHECK_NONE);
geom2 = lwgeom_from_hexwkb(in_ewkt, LW_PARSER_CHECK_NONE);
lwgeom_force_clockwise(geom2);
-
+
/** use same check instead of strcmp to account
for difference in endianness **/
CU_ASSERT( lwgeom_same(geom, geom2) );
line = lwline_from_lwmpoint(SRID_DEFAULT, mpoint);
CU_ASSERT_EQUAL(line->points->npoints, mpoint->ngeoms);
CU_ASSERT_DOUBLE_EQUAL(lwline_length_2d(line), 4.0, 0.000001);
-
+
lwline_free(line);
lwmpoint_free(mpoint);
}
LWGEOM *out = NULL;
double measure = 105.0;
char *str;
-
+
/* ST_Locatealong(ST_GeomFromText('MULTILINESTRING M ((1 2 3, 5 4 5), (50 50 1, 60 60 200))'), 105) */
geom = lwgeom_from_wkt("MULTILINESTRING M ((1 2 3, 5 4 5), (50 50 1, 60 60 200))", LW_PARSER_CHECK_NONE);
out = lwgeom_locate_along(geom, measure, 0.0);
lwgeom_free(out);
CU_ASSERT_STRING_EQUAL("MULTIPOINT M (55.226131 55.226131 105)", str);
lwfree(str);
-
+
/* ST_Locatealong(ST_GeomFromText('MULTILINESTRING M ((1 2 3, 5 4 5), (50 50 1, 60 60 200))'), 105) */
geom = lwgeom_from_wkt("MULTILINESTRING M ((1 2 3, 3 4 2, 9 4 3), (1 2 3, 5 4 5), (50 50 1, 60 60 200))", LW_PARSER_CHECK_NONE);
out = lwgeom_locate_along(geom, measure, 0.0);
POINT2D P, A1, A2, A3;
int rv;
-
+
/* Point within unit semicircle, 0.5 units from arc */
A1.x = -1; A1.y = 0;
A2.x = 0 ; A2.y = 1;
A3.x = 1 ; A3.y = 0;
- P.x = 0 ; P.y = 0.5;
+ P.x = 0 ; P.y = 0.5;
lw_dist2d_distpts_init(&dl, DIST_MIN);
rv = lw_dist2d_pt_arc(&P, &A1, &A2, &A3, &dl);
CU_ASSERT_DOUBLE_EQUAL(dl.distance, 0.5, 0.000001);
/* Point outside unit semicircle, 0.5 units from arc */
- P.x = 0 ; P.y = 1.5;
+ P.x = 0 ; P.y = 1.5;
lw_dist2d_distpts_init(&dl, DIST_MIN);
rv = lw_dist2d_pt_arc(&P, &A1, &A2, &A3, &dl);
CU_ASSERT_EQUAL( rv, LW_SUCCESS );
CU_ASSERT_DOUBLE_EQUAL(dl.distance, 0.5, 0.000001);
/* Point outside unit semicircle, sqrt(2) units from arc end point*/
- P.x = 0 ; P.y = -1;
+ P.x = 0 ; P.y = -1;
lw_dist2d_distpts_init(&dl, DIST_MIN);
rv = lw_dist2d_pt_arc(&P, &A1, &A2, &A3, &dl);
CU_ASSERT_EQUAL( rv, LW_SUCCESS );
CU_ASSERT_DOUBLE_EQUAL(dl.distance, sqrt(2.0), 0.000001);
/* Point outside unit semicircle, sqrt(2)-1 units from arc end point*/
- P.x = 1 ; P.y = 1;
+ P.x = 1 ; P.y = 1;
lw_dist2d_distpts_init(&dl, DIST_MIN);
rv = lw_dist2d_pt_arc(&P, &A1, &A2, &A3, &dl);
CU_ASSERT_EQUAL( rv, LW_SUCCESS );
CU_ASSERT_DOUBLE_EQUAL(dl.distance, sqrt(2.0)-1, 0.000001);
/* Point on unit semicircle midpoint */
- P.x = 0 ; P.y = 1;
+ P.x = 0 ; P.y = 1;
lw_dist2d_distpts_init(&dl, DIST_MIN);
rv = lw_dist2d_pt_arc(&P, &A1, &A2, &A3, &dl);
CU_ASSERT_EQUAL( rv, LW_SUCCESS );
CU_ASSERT_DOUBLE_EQUAL(dl.distance, 0, 0.000001);
/* Point on unit semicircle endpoint */
- P.x = 1 ; P.y = 0;
+ P.x = 1 ; P.y = 0;
lw_dist2d_distpts_init(&dl, DIST_MIN);
rv = lw_dist2d_pt_arc(&P, &A1, &A2, &A3, &dl);
CU_ASSERT_EQUAL( rv, LW_SUCCESS );
rv = lw_dist2d_pt_arc(&P, &A1, &A2, &A3, &dl);
//printf("distance %g\n", dl.distance);
CU_ASSERT_EQUAL( rv, LW_SUCCESS );
- CU_ASSERT_DOUBLE_EQUAL(dl.distance, 0.5, 0.000001);
+ CU_ASSERT_DOUBLE_EQUAL(dl.distance, 0.5, 0.000001);
}
static void
DISTPTS dl;
POINT2D A1, A2, B1, B2, B3;
int rv;
-
+
/* Unit semicircle */
B1.x = -1; B1.y = 0;
B2.x = 0 ; B2.y = 1;
DISTPTS dl;
POINT2D A1, A2, A3, B1, B2, B3;
int rv;
-
+
/* Unit semicircle at 0,0 */
B1.x = -1; B1.y = 0;
B2.x = 0 ; B2.y = 1;
POINT2D A1, A2, A3;
double d;
-
+
/* Unit semicircle at 0,0 */
A1.x = -1; A1.y = 0;
A2.x = 0 ; A2.y = 1;
/* Unit semi-circle above X axis */
lwline = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-1 0, 0 1, 1 0)"));
-
+
/* Point at origin */
P.x = P.y = 0;
lw_dist2d_distpts_init(&dl, DIST_MIN);
/* Unit semi-circle above X axis */
lwline1 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-1 0, 0 1, 1 0)"));
-
+
/* Line above top of semi-circle */
lwline2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-2 2, -1 2, 1 2, 2 2)"));
lw_dist2d_distpts_init(&dl, DIST_MIN);
CU_ASSERT_STRING_EQUAL("lw_dist2d_ptarray_ptarrayarc called with non-arc input", cu_error_msg);
lwline_free(lwline2);
-
+
/* Line along side of semi-circle */
lwline2 = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-2 -3, -2 -2, -2 2, -2 3)"));
lw_dist2d_distpts_init(&dl, DIST_MIN);
LWBOUNDINGCIRCLE* result = lwgeom_calculate_mbc(input);
CU_ASSERT_TRUE(result == NULL);
-
+
lwgeom_free(input);
}
geom = lwgeom_from_wkt("CURVEPOLYGON((0 0,1 0,0 1,0 0),CIRCULARSTRING(0 0,1 0,1 1,1 0,0 0))", LW_PARSER_CHECK_NONE);
count = lwgeom_count_vertices(geom);
CU_ASSERT_EQUAL(count,9);
- lwgeom_free(geom);
+ lwgeom_free(geom);
}
static void test_misc_area(void)
geom = lwgeom_from_wkt("LINESTRING EMPTY", LW_PARSER_CHECK_ALL);
area = lwgeom_area(geom);
- CU_ASSERT_DOUBLE_EQUAL(area, 0.0, 0.0001);
+ CU_ASSERT_DOUBLE_EQUAL(area, 0.0, 0.0001);
lwgeom_free(geom);
}
CU_ASSERT_STRING_EQUAL(str, "CURVEPOLYGON(CIRCULARSTRING(-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0 0.5,1 0,0 1,-1 0))");
lwfree(str);
lwgeom_free(geom);
-
+
}
LWGEOM *geom = lwgeom_from_wkt(wkt, LW_PARSER_CHECK_ALL);
LWGEOM *geomgrid;
char *str;
-
+
grid.ipx = grid.ipy = 0;
grid.xsize = grid.ysize = 20;
CU_ASSERT_STRING_EQUAL(str, "MULTIPOLYGON EMPTY");
lwfree(str);
lwgeom_free(geom);
- lwgeom_free(geomgrid);
+ lwgeom_free(geomgrid);
}
static void test_clone(void)
static char *wkt = "GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0))),POINT(1 1),LINESTRING(2 3,4 5))";
LWGEOM *geom1 = lwgeom_from_wkt(wkt, LW_PARSER_CHECK_ALL);
LWGEOM *geom2;
-
+
/* Free in "backwards" order */
geom2 = lwgeom_clone(geom1);
lwgeom_free(geom1);
cu_twkb_idlist("MULTIPOINT(1 1, 0 0)",idlist, 0, 0, 0, 0);
// printf("TWKB: %s\n",s);
// printf("WKT: %s\n",w);
- CU_ASSERT_STRING_EQUAL(s,"040402040802020101");
- CU_ASSERT_STRING_EQUAL(w,"MULTIPOINT(1 1,0 0)");
+ CU_ASSERT_STRING_EQUAL(s,"040402040802020101");
+ CU_ASSERT_STRING_EQUAL(w,"MULTIPOINT(1 1,0 0)");
/*
04 06 multipoint, size/idlist
cu_twkb_idlist("MULTIPOINT(1 1, 0 0)",idlist, 0, 0, 0, TWKB_SIZE);
// printf("TWKB: %s\n",s);
// printf("WKT: %s\n",w);
- CU_ASSERT_STRING_EQUAL(s,"04060702040802020101");
- CU_ASSERT_STRING_EQUAL(w,"MULTIPOINT(1 1,0 0)");
+ CU_ASSERT_STRING_EQUAL(s,"04060702040802020101");
+ CU_ASSERT_STRING_EQUAL(w,"MULTIPOINT(1 1,0 0)");
/*
04 07 multipoint, bbox/size/idlist
cu_twkb_idlist("MULTIPOINT(1 1, 0 0)",idlist, 0, 0, 0, TWKB_SIZE | TWKB_BBOX);
// printf("TWKB: %s\n",s);
// printf("WKT: %s\n",w);
- CU_ASSERT_STRING_EQUAL(s,"04070B0002000202040802020101");
- CU_ASSERT_STRING_EQUAL(w,"MULTIPOINT(1 1,0 0)");
+ CU_ASSERT_STRING_EQUAL(s,"04070B0002000202040802020101");
+ CU_ASSERT_STRING_EQUAL(w,"MULTIPOINT(1 1,0 0)");
/*
0704 geometrycollection, idlist
0408 idlist (2,4)
01000202 first point (type, meta, x, y)
01000000 second point (type, meta, x, y)
- */
+ */
idlist[0] = 2;
idlist[1] = 4;
cu_twkb_idlist("GEOMETRYCOLLECTION(POINT(1 1),POINT(0 0))",idlist, 0, 0, 0, 0);
// printf("TWKB: %s\n",s);
CU_ASSERT_STRING_EQUAL(s,"07040204080100020201000000");
- CU_ASSERT_STRING_EQUAL(w,"GEOMETRYCOLLECTION(POINT(1 1),POINT(0 0))");
+ CU_ASSERT_STRING_EQUAL(w,"GEOMETRYCOLLECTION(POINT(1 1),POINT(0 0))");
/*
0706 geometrycollection, size/idlist
cu_twkb_idlist("GEOMETRYCOLLECTION(POINT(1 1),POINT(0 0))",idlist, 0, 0, 0, TWKB_SIZE);
// printf("TWKB: %s\n",s);
CU_ASSERT_STRING_EQUAL(s,"07060D02040801020202020102020000");
- CU_ASSERT_STRING_EQUAL(w,"GEOMETRYCOLLECTION(POINT(1 1),POINT(0 0))");
+ CU_ASSERT_STRING_EQUAL(w,"GEOMETRYCOLLECTION(POINT(1 1),POINT(0 0))");
}
CU_ASSERT(g != NULL);
CU_ASSERT(lwgeom_is_empty(g));
CU_ASSERT(g->type == POINTTYPE);
- lwgeom_free(g);
+ lwgeom_free(g);
}
static void test_wkb_out_point(void)
cu_wkb("SRID=4;POINTM(1 1 1)");
CU_ASSERT_STRING_EQUAL(s,"0060000001000000043FF00000000000003FF00000000000003FF0000000000000");
-
+
cu_wkb("POINT EMPTY");
cu_wkb_empty_point_check(s);
-
+
cu_wkb("SRID=4326;POINT EMPTY");
cu_wkb_empty_point_check(s);
static void test_wkb_out_polyhedralsurface(void)
{
// cu_wkb("POLYHEDRALSURFACE(((0 0 0 0,0 0 1 0,0 1 0 2,0 0 0 0)),((0 0 0 0,0 1 0 0,1 0 0 4,0 0 0 0)),((0 0 0 0,1 0 0 0,0 0 1 6,0 0 0 0)),((1 0 0 0,0 1 0 0,0 0 1 0,1 0 0 0)))");
-// CU_ASSERT_STRING_EQUAL(s, t);
+// CU_ASSERT_STRING_EQUAL(s, t);
// printf("\nnew: %s\nold: %s\n",s,t);
}
"MULTIPOINT(0 1,2 3,4 5)",
"<Polypoint2D point='0 1 2 3 4 5 ' />",
NULL, 0, 0);
-
+
/* 3D MultiPoint */
do_x3d3_test(
"MULTIPOINT Z(0 1 1,2 3 4,4 5 5)",
"MULTIPOLYGON(((0 1 1,2 3 1,4 5 1,0 1 1)),((6 7 1,8 9 1,10 11 1,6 7 1)))",
"<IndexedFaceSet convex='false' coordIndex='0 1 2 -1 3 4 5'><Coordinate point='0 1 1 2 3 1 4 5 1 6 7 1 8 9 1 10 11 1 ' /></IndexedFaceSet>",
NULL, 0, 0);
-
+
/* PolyhedralSurface */
do_x3d3_test(
"POLYHEDRALSURFACE( ((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)), ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)), ((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)), ((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)), ((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)) )",
"POINT(3.1111111111111 1.1111111111111 2.11111111111111)",
"1 3 2",
NULL, 0, 1);
-
+
/* geocoordinate long,lat*/
do_x3d3_test(
"SRID=4326;POLYGON((15 10 3,13.536 6.464 3,10 5 3,6.464 6.464 3,5 10 3,6.464 13.536 3,10 15 3,13.536 13.536 3,15 10 3))",
"<IndexedFaceSet convex='false' coordIndex='0 1 2 3 4 5 6 7'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"longitude_first\"' point='15 10 3 13.536 6.464 3 10 5 3 6.464 6.464 3 5 10 3 6.464 13.536 3 10 15 3 13.536 13.536 3 ' /></IndexedFaceSet>",
NULL, 3, 2);
-
+
/* geocoordinate lat long*/
do_x3d3_test(
"SRID=4326;POLYGON((15 10 3,13.536 6.464 3,10 5 3,6.464 6.464 3,5 10 3,6.464 13.536 3,10 15 3,13.536 13.536 3,15 10 3))",
CU_ASSERT_STRING_EQUAL("POLYHEDRALSURFACE(((0 1,2 3,4 5,0 1)))", tmp);
lwfree(tmp);
lwgeom_free(geom);
-
+
/* 3DM */
geom = lwgeom_from_wkt("POLYHEDRALSURFACEM(((0 1 2,3 4 5,6 7 8,0 1 2)))", LW_PARSER_CHECK_NONE);
CU_ASSERT_EQUAL(strlen(cu_error_msg), 0);
{
CU_ASSERT(c->num_nodes == ( 4 % CIRC_NODE_SIZE ? 1 : 0 ) + 4 / CIRC_NODE_SIZE);
}
-
+
circ_tree_free(c);
lwline_free(g);
}
CIRC_NODE *c;
POINT2D pt, pt_outside;
int rv, on_boundary;
-
+
pt.x = 0.0;
pt.y = 0.0;
pt_outside.x = -2.0;
pt_outside.y = 0.0;
-
+
/* Point in square */
g = lwgeom_as_lwline(lwgeom_from_wkt("LINESTRING(-1 -1,1 -1,1 1,-1 1,-1 -1)", LW_PARSER_CHECK_NONE));
c = circ_tree_new(g->points);
CU_ASSERT_EQUAL(rv_tree, rv_classic);
circ_tree_free(c);
lwgeom_free(g);
-
+
g = lwgeom_from_hexwkb("0103000020E6100000010000004700000000000000621119C000000040C70C4B40000000E0CC6C18C0000000A026FF4A4000000040438519C000000000E8F44A40000000000F5318C00000004024C84A4000000060F9E518C0000000A027AD4A40000000805E0D18C0000000C0F5784A4000000040539718C000000080815E4A40000000C026FE19C0000000C0502D4A4000000060127019C000000040EA164A40000000003BFD1BC0000000609E234A4000000080D9011CC000000060B9114A4000000040C8501EC0000000C0D50C4A40000000C05F2C20C000000040C9E749400000006008D820C000000080D6F0494000000080139F20C000000060F3DE4940000000A0B16421C0000000C059C94940000000808FA223C0000000C007B949400000000041E722C000000080C3DC4940000000808F4224C0000000405DCE494000000060752923C000000040A9EF4940000000005CAD24C0000000C036E4494000000040F88624C00000008078FE494000000060558523C00000006025134A40000000403AED24C00000000011174A40000000A05E7D23C0000000E0A41F4A4000000040F0AD23C0000000809A304A4000000040A64E23C000000040C9474A40000000C0FCA221C0000000C030554A40000000805EDD23C0000000E010474A4000000040BFF822C00000008078664A4000000080C98F22C000000040E2914A40000000C036E021C00000002024924A4000000080D9E121C000000000D0A14A4000000040533723C000000040B99D4A40000000204B1E23C0000000C0CCB04A4000000000625A24C0000000A071B44A40000000004A5F24C0000000806FC64A40000000E0DD6523C00000006088CC4A400000004012D023C0000000001AE14A40000000806E1F23C0000000400BEE4A40000000E0A2E123C0000000C017EF4A4000000060449423C00000004003F94A40000000C0DC0624C0000000A0ED1B4B40000000A0803F24C0000000005D0C4B4000000040753924C000000080701D4B400000002021F320C00000000001234B4000000000C65221C000000080792D4B40000000406D6020C0000000001A514B4000000040BF9821C0000000A00E594B400000000031B520C0000000C0726B4B400000002019EA20C000000020977F4B400000000002ED1FC0000000E0B49B4B400000000084CC1EC0000000602D8C4B4000000020BB2A1FC000000060239B4B4000000040AE871EC0000000A0FDA14B400000008077771EC0000000C0E5864B40000000C0AABA1EC000000000B7794B40000000C03EC91DC0000000E020874B4000000000A4301EC0000000C0C49B4B4000000000B5811DC0000000A0A3B04B400000004095BD1BC000000020869E4B400000004091021DC00000004009894B40000000409D361EC000000080A2614B40000000809FB41FC0000000A0AB594B40000000C046021FC0000000C0164C4B40000000C0EC5020C0000000E05A384B4000000040DF3C1EC0000000803F104B4000000000B4221DC0000000C0CD0F4B40000000C0261E1CC00000006067354B4000000080E17A1AC000000080C3044B4000000000621119C000000040C70C4B40", LW_PARSER_CHECK_NONE);
p = lwgeom_as_lwpoly(g);
lwpt = (LWPOINT*)lwgeom_from_hexwkb("0101000020E610000057B89C28FEB320C09C8102CB3B2B4A40", LW_PARSER_CHECK_NONE);
SPHEROID s;
double d1, d2, d3, d4;
double threshold = 0.0;
-
+
spheroid_init(&s, 1.0, 1.0);
/* Ticket #1958 */
lwgeom_free(lwg1);
lwgeom_free(lwg2);
CU_ASSERT_DOUBLE_EQUAL(d1, d2, 0.0000001);
-
+
/* Ticket #1951 */
lwg1 = lwgeom_from_wkt("LINESTRING(0 0, 0 0)", LW_PARSER_CHECK_NONE);
lwg2 = lwgeom_from_wkt("POINT(0.1 0.1)", LW_PARSER_CHECK_NONE);
lwgeom_free(lwg1);
lwgeom_free(lwg2);
CU_ASSERT_DOUBLE_EQUAL(d1, d2, 0.0000001);
-
+
/* Ticket #2634 */
lwg1 = lwgeom_from_wkt("MULTIPOINT (-10 40,-10 65,10 40,10 65,30 40,30 65,50 40,50 65)", LW_PARSER_CHECK_NONE);
lwg2 = lwgeom_from_wkt("POLYGON((-9.1111111 40,-9.14954053919354 39.6098193559677,-9.26335203497743 39.2346331352698,-9.44817187539491 38.8888595339608,-9.6968975376269 38.5857864376269,-9.99997063396079 38.3370607753949,-10.3457442352698 38.1522409349774,-10.7209304559677 38.0384294391935,-11.1111111 38,-11.5012917440323 38.0384294391935,-11.8764779647302 38.1522409349774,-12.2222515660392 38.3370607753949,-12.5253246623731 38.5857864376269,-12.7740503246051 38.8888595339608,-12.9588701650226 39.2346331352698,-13.0726816608065 39.6098193559677,-13.1111111 40,-13.0726816608065 40.3901806440322,-12.9588701650226 40.7653668647302,-12.7740503246051 41.1111404660392,-12.5253246623731 41.4142135623731,-12.2222515660392 41.6629392246051,-11.8764779647302 41.8477590650226,-11.5012917440323 41.9615705608065,-11.1111111 42,-10.7209304559678 41.9615705608065,-10.3457442352698 41.8477590650226,-9.9999706339608 41.6629392246051,-9.69689753762691 41.4142135623731,-9.44817187539491 41.1111404660392,-9.26335203497743 40.7653668647302,-9.14954053919354 40.3901806440323,-9.1111111 40))", LW_PARSER_CHECK_NONE);
// printf("\n");
// circ_tree_print(c1, 0);
// printf("\n");
-// circ_tree_print(c2, 0);
+// circ_tree_print(c2, 0);
// printf("\n");
d1 = lwgeom_distance_spheroid(lwg1, lwg2, &s, threshold);
d2 = circ_tree_distance_tree(c1, c2, &s, threshold);
SPHEROID s;
int i, j;
int step = 10;
-
+
const char *txt_poly1 = "0103000020E6100000010000000B0000000AA2F068F47651C0F7893DEB70B8454007ABD4C6D57651C000FB650799B84540C21AA2645A7651C011C24BA84AB8454089A9A325E87751C03314EB5453B74540AF9ED96BF57751C0BF9818F889B74540E936A498B47751C0690C87D1C5B74540F5386204DC7751C02FCA658F1AB8454077B65F7B657751C012C586EE37B845408C1862C5977751C00F17E41674B84540D4012F57357751C0AD3BC67E99B845400AA2F068F47651C0F7893DEB70B84540";
const char *txt_poly2 = "0103000020E610000003000000B5000000E0D13F40187451C01A09009164BB4540771C07D8FA7351C04DBBEDB634BB45400D27D627A47351C070625C9386BB4540D691981FAD7351C02F382CCDFABA4540AA38FA85B97351C03AD3A8271CBB4540D211F0CBBE7351C027F11A8FD9BA4540839AE427EB7351C0BF97C6BBA3BA4540748967A4D47351C00C0037C970BA45408F182A0CF07351C0C050808070BA45405063F06DD27351C0681018D037BA4540E509D5C2EE7351C0B9429E0231BA4540EA39B20CCC7351C018FBB70F22BA454072DD47C8ED7351C04C992D5E0BBA4540934BDE09CE7351C04B17895ACFB94540F7AA9F1EF77351C04DE737D4DCB945400D217458DF7351C022324164B0B945408A2F53C4087451C0A7EC0972B1B9454091A02DF3FC7351C0077F0D388AB94540D9EA0152187451C02316A57280B9454023E37795F07351C09314E67D36B945408DD1866BFC7351C06A0A537214B945405F77D635DE7351C01C7B3C251EB945404785C336F27351C07D767383F1B8454043664E41C77351C0F499D9F3C2B84540DA5CD86FDC7351C0ECA943B295B845403A60B1A2AF7351C063B81C61AFB8454041469468AA7351C0B0727EE16AB845405ADF4611937351C0AA5D2634A3B84540D1BB958D917351C0086C6F1450B845408BBECFF4787351C008F3F4958EB845407F025FE0737351C0506C9F8057B845405A49EDDE5E7351C0AB88DA1B84B845402AAE2CB6767351C07ECC7AEB33B845406C3BCEFF557351C0D93C09506DB8454032C3D6B8577351C0CF4410B115B84540C47F5B30337351C08DCEBB6F7DB845400DC58DB4127351C0D68016845EB845409E0DC353E17251C05E161FDE94B84540D94A5CCDF87251C0D4A79022C3B745404B789041A97151C0D366245447B64540E229E50C7A7151C04864DEC059B645403CF020E75F7151C0C2341E664FB745404F6388C1807151C0BE100BDA2FB7454099DB3D97877151C0853918DE6CB74540080D2824137151C017385A8090B74540A380F14EE97051C0A517F62259B74540C9B0B8E1F47051C019014EF43DB7454075AB809D997051C023033EFC28B745401FCC6CFD3C7051C01778CC51B1B74540A5AFFD2A5E7051C08B7644232EB8454075947311FD7051C0EB4B7B9F09B8454007A084455D7151C065E676C6A7B845401CB4DA891A7151C096D19999D0B84540F9D410BC3E7151C08C3797C11CB945400CA63027017151C0640A96032BBA4540B07FB7D8897151C0B632805859BA454078D01A1FDD7151C0202711EE70B945405F3A6E8E627251C0932D32FE34BA4540B532341D277251C0DFA18E0392BA4540CD8E813B147251C0FEBBA2346EBA4540421F7F16F87151C0DEB93B76A3BA45403B2350A3D37151C0330AF75F99BA454077512147AC7151C0A628D5F117BB454011C9CE77507151C04CC4E1E705BB4540E6889885EE7051C0C45D89CDA8BA4540575D1B37B07051C0F883C0A0D7BA45408A0FB14B977051C01D328086A9BA454033A7D2839B7051C0EEC463DD22BA4540AFDC6C64DC7051C013983A6CE3B94540CC1E39AEE17051C076E753DD7BB94540F6E0B3BECA7051C070E459395BB94540E636719D447051C0CB5C78F2F8B845402D3B6C3AC76F51C08AFD07346AB945404080D345386F51C02EFB7C9465B94540B5BB47ED506F51C0B5742F4FC3B84540F4DAAD32326F51C03AE0604DCEB8454079D03A00286F51C0BFE416D692B84540E7EEF142456F51C026483D9219B84540556E7F645D6F51C06BA1A86620B845406BD12F44536F51C0F976E08663B84540D7BFD8077B6F51C0C500FD8E63B8454004DD9EC4816F51C0441D30FBDBB745403EE733710C6F51C05E6524F44EB74540BEEA42C14A6E51C0367C93EEDEB54540C84C8F841D6E51C0F035740AD0B54540F0B3122E316E51C09158039618B44540F5E629F8706E51C02FD3E2F726B44540533862949E6E51C015FA5534BBB34540C649D8EDEF6E51C02B5E6D6F80B345405D7B912E616F51C0DF4BA76B0EB2454072578CCFB76F51C0A22CCF6690B1454015A5C130647051C0F4EFF7540FB14540F1ACD1FA9D7051C0329CCCA94CB14540374504840E7151C04726DFC9B5B04540C4B031D7D97151C0FC7C331392B04540DC234455E77151C00A9F4A04B9B04540D1505DECCD7151C0D9351517EAB04540CDD86B5EF87151C004CB649085B1454099BE7DDB797151C037D42330B4B245400EA292D32C7151C0820E1DD8B4B24540ACE77E61257151C0EE15BF9BEBB245407AA945D2867151C0666E8B0F01B345404EE1C915D37151C04B6DD883B3B24540C58BDF35247251C0D3FB74C050B445403C06C143697251C0603A1C0D59B44540D2F9E6E6B07251C0BC16F1CCC7B44540E47B911C8D7251C0A95F88542AB5454047BC0FA6237251C031E8A2FB38B54540CAB1FB9FF87151C03B2BF41EF7B445404EBF18E8017251C09C164886A8B4454050CD38EBC67151C014E9B12709B54540B4C7E42DD37151C0FB5B1E864CB54540BECC9D27167251C0B37B1B12AEB545400643207D967251C048C2DBC1ACB5454039070923977251C0E6D50A2602B64540DDD41A1C2E7351C06156AFD91EB645402FAEBC26AD7251C06DB4F5FA28B64540E6498EEFD87251C06214C5327CB645400C5E024B2E7351C0CABD9E93B9B6454001F550AB447351C0FBAFC57D96B645405AE881CF3D7351C01917460EC7B64540695D4AA6607351C00D689CE284B64540C6299985517351C076C84855D3B645406625BA34747351C0E739BF479CB64540386A02DD607351C0D6534476E1B645400B69DB9F997351C0B8AC5ACD90B645400E3CF2EEAC7351C05979D2F9A1B645400FD99F71887351C03916C9ACFAB64540CA154DF19B7351C0CC4ECC370AB745403B8F39FFC07351C0311B27F4ACB6454008ED94DBD07351C069128CC9B9B64540BDEC1CCDAA7351C0FA1AAC0617B74540A99C51C1C07351C07759CE3A2AB7454073FCF177E67351C04A84EAA2CDB6454055CDCB6ED17351C0CB6C7B6438B74540DDD31435F87351C0D4D993891FB74540811059D30D7451C077753AD162B74540F18AF9E46B7451C0FD21E09762B74540F253FA4F547451C067E3343FACB74540F0BCC760697451C0E0AE673BDBB74540FA1616AB497451C0D50836ABF0B74540F41845176E7451C0950B89B7FCB74540A16098ED3D7451C0D4E3E2D80BB84540B9AFBD7B727451C019895C361DB84540163C14EB717451C013C465C245B845402645A98E427451C049F426523FB84540C47E7169707451C0958552ED5DB84540652934E8467451C0D6A4B9DC6EB84540762DC58E717451C0F00F358EA7B8454052BD47144E7451C0CE25A2A9B7B84540FE28AFF55E7451C0EC20702D0BB94540DC47DC52777451C0DB556D5401B945407C974EEE617451C0DF8FB3BF25B94540F486D9A77E7451C0C20621B41AB94540432A3030707451C08AB2EDBC39B945409B0D7D28167551C0BB2B0598F9B84540E9C3E5D1067551C0617DD7107BB94540ADD4816DC57451C052E51C9E7FB9454083A85A09D37451C04AA52729AAB94540E8B74A52A57451C0054656858DB94540C1F58C11C07451C073982E6DC8B945406639F493967451C09D31BA6A90B9454023779107AB7451C026DD7171DFB945404CC088A46D7451C00324607A78B94540B4263081827451C0AF743013AAB94540A1FEA7A25A7451C030846A958DB945403B797701697451C00240A15CE1B945405EBCC1C4497451C0AF0092E9BCB945408A96E72B6A7451C0A85FF698F9B9454048855507427451C06852C7B9F0B94540CFBB01EA5C7451C0DC68FBB715BA4540D42EA3CF3C7451C0D2A6746A0BBA4540510413EB577451C0EE883A7D2CBA4540DC8C76E73B7451C0808E628128BA4540904E729D4F7451C09335C2C358BA4540A9018BEC347451C0017C60D031BA4540508873A32E7451C03F4C9200BDBA45400FEFB0B0567451C00274F969CCBA45402E2B3AC7317451C09C029279CBBA4540C6748AB7417451C060364B9C0EBB4540E0D13F40187451C01A09009164BB4540080000006DABE362BF6F51C03B3EAB0286B84540F2EBCFEEAC6F51C008D8984EA3B84540FF2B5394BB6F51C0B2F08C42CBB84540FDF9E71CFC6F51C07C7C0453C8B845403ABCCFEBCF6F51C0D477C34AC2B845402D81685DC76F51C071D8F5EE94B84540FB229C95E86F51C0BD8E7FF7AEB845406DABE362BF6F51C03B3EAB0286B8454008000000DB185B503E7051C066B728BCD3B245400AC83B92357051C04BA0208DA3B34540D7FCFFA31D7051C0CF7C254CD6B345400E29CDB9907051C012EB7D78CCB34540806300429F7051C0B0D493C19CB34540786CA34E6C7051C093B0BB4060B345407D77C1F9657051C0497CC614C3B24540DB185B503E7051C066B728BCD3B24540";
const char *polys[2];
static int npolys = 2;
-
+
polys[0] = txt_poly1;
polys[1] = txt_poly2;
{
LWGEOM *lwg1 = lwgeom_from_hexwkb(polys[j], LW_PARSER_CHECK_NONE);
LWGEOM *lwg2 = lwgeom_from_wkt("POINT(-69.83262 43.43636)", LW_PARSER_CHECK_NONE);
-
+
CIRC_NODE *c1 = lwgeom_calculate_circ_tree(lwg1);
CIRC_NODE *c2 = lwgeom_calculate_circ_tree(lwg2);
lwgeom_free(lwg1);
lwgeom_free(lwg2);
}
-
+
}
/*
static void test_unionfind_collapse_cluster_ids(void)
{
UNIONFIND* uf = UF_create(10);
-
+
uf->clusters[0] = 8;
uf->clusters[1] = 5;
uf->clusters[2] = 5;
collapsed_ids = UF_get_collapsed_cluster_ids(uf, is_in_cluster);
int i;
for (i = 0; i < uf->N; i++)
- {
+ {
if (is_in_cluster[i])
ASSERT_INT_EQUAL(expected_collapsed_ids2[i], collapsed_ids[i]);
}
int size;
char *hex;
uint8_t buf[16];
-
+
size = varint_u32_encode_buf(nr, buf);
if ( size != expected_size )
printf("Expected: %d\nObtained: %d\n", expected_size, size);
CU_ASSERT_EQUAL(size, expected_size);
-
+
hex = hexbytes_from_bytes(buf, size);
- ASSERT_STRING_EQUAL(hex, expected_res);
+ ASSERT_STRING_EQUAL(hex, expected_res);
lwfree(hex);
}
uint8_t buf[16];
int size;
char *hex;
-
+
size = varint_s32_encode_buf(nr, buf);
if ( size != expected_size )
{
CU_ASSERT_EQUAL(size,expected_size);
hex = hexbytes_from_bytes(buf, size);
- ASSERT_STRING_EQUAL(hex, expected_res);
+ ASSERT_STRING_EQUAL(hex, expected_res);
lwfree(hex);
}
uint8_t buf[16];
int size;
char *hex;
-
+
size = varint_u64_encode_buf(nr, buf);
if ( size != expected_size )
{
uint8_t buf[16];
int size;
char *hex;
-
+
size = varint_s64_encode_buf(nr, buf);
if ( size != expected_size )
{
printf("Expected: %d\nObtained: %d\n", expected_size, size);
}
CU_ASSERT_EQUAL(size,expected_size);
-
+
hex = hexbytes_from_bytes(buf,size);
- ASSERT_STRING_EQUAL(hex, expected_res);
+ ASSERT_STRING_EQUAL(hex, expected_res);
lwfree(hex);
}
a = b = i;
CU_ASSERT_EQUAL(a, unzigzag64(zigzag64(a)));
CU_ASSERT_EQUAL(b, unzigzag32(zigzag64(b)));
-
+
a = b = -1 * i;
CU_ASSERT_EQUAL(a, unzigzag64(zigzag64(a)));
CU_ASSERT_EQUAL(b, unzigzag32(zigzag64(b)));
ea->initial_arealist = lwalloc(inpts->npoints*sizeof(areanode));
ea->res_arealist = lwalloc(inpts->npoints*sizeof(double));
ea->inpts=inpts;
- return ea;
+ return ea;
}
{
LWDEBUG(2, "Entered triarea3d");
double ax,bx,ay,by,az,bz,cx,cy,cz, area;
-
+
ax=P1[0]-P2[0];
bx=P3[0]-P2[0];
ay=P1[1]-P2[1];
by=P3[1]-P2[1];
az=P1[2]-P2[2];
- bz=P3[2]-P2[2];
-
+ bz=P3[2]-P2[2];
+
cx = ay*bz - az*by;
cy = az*bx - ax*bz;
cz = ax*by - ay*bx;
- area = fabs(0.5*(sqrt(cx*cx+cy*cy+cz*cz)));
+ area = fabs(0.5*(sqrt(cx*cx+cy*cy+cz*cz)));
return area;
}
int swap=parent;
double leftarea=0;
double rightarea=0;
-
+
double parentarea=((areanode*) treearray[parent])->area;
-
+
if(left<tree->usedSize)
- {
+ {
leftarea=((areanode*) treearray[left])->area;
if(parentarea>leftarea)
swap=left;
}
if(right<tree->usedSize)
{
- rightarea=((areanode*) treearray[right])->area;
+ rightarea=((areanode*) treearray[right])->area;
if(rightarea<parentarea&&rightarea<leftarea)
swap=right;
- }
+ }
if(swap>parent)
{
/*ok, we have to swap something*/
((areanode*) treearray[parent])->treeindex=parent;
treearray[swap]=tmp;
/*Update reference*/
- ((areanode*) treearray[swap])->treeindex=swap;
+ ((areanode*) treearray[swap])->treeindex=swap;
if(swap<tree->usedSize)
down(tree,arealist,swap);
}
void *tmp;
areanode **treearray=tree->key_array;
-
+
int parent=floor((c-1)/2);
-
+
while(((areanode*) treearray[c])->area<((areanode*) treearray[parent])->area)
{
/*ok, we have to swap*/
treearray[parent]=treearray[c];
/*Update reference*/
((areanode*) treearray[parent])->treeindex=parent;
- treearray[c]=tmp;
+ treearray[c]=tmp;
/*Update reference*/
((areanode*) treearray[c])->treeindex=c;
- c=parent;
+ c=parent;
parent=floor((c-1)/2);
}
return;
{
LWDEBUG(2, "Entered minheap_pop");
areanode *res = tree->key_array[0];
-
+
/*put last value first*/
tree->key_array[0]=tree->key_array[(tree->usedSize)-1];
- ((areanode*) tree->key_array[0])->treeindex=0;
-
- tree->usedSize--;
+ ((areanode*) tree->key_array[0])->treeindex=0;
+
+ tree->usedSize--;
down(tree,arealist,0);
return res;
}
double area;
int go_on=1;
double check_order_min_area = 0;
-
+
int npoints=ea->inpts->npoints;
int i;
int current, before_current, after_current;
-
+
MINHEAP tree = initiate_minheap(npoints);
-
+
int is3d = FLAGS_GET_Z(ea->inpts->flags);
-
-
+
+
/*Add all keys (index in initial_arealist) into minheap array*/
for (i=0;i<npoints;i++)
{
LWDEBUGF(2, "add nr %d, with area %lf, and %lf",i,ea->initial_arealist[i].area, tree.key_array[i]->area );
}
tree.usedSize=npoints;
-
- /*order the keys by area, small to big*/
+
+ /*order the keys by area, small to big*/
qsort(tree.key_array, npoints, sizeof(void*), cmpfunc);
-
+
/*We have to put references to our tree in our point-list*/
for (i=0;i<npoints;i++)
{
LWDEBUGF(4,"Check ordering qsort gives, area=%lf and belong to point %d",((areanode*) tree.key_array[i])->area, tree.key_array[i]-ea->initial_arealist);
}
/*Ok, now we have a minHeap, just need to keep it*/
-
+
/*for (i=0;i<npoints-1;i++)*/
i=0;
while (go_on)
- {
+ {
/*Get a reference to the point with the currently smallest effective area*/
current=minheap_pop(&tree, ea->initial_arealist)-ea->initial_arealist;
-
+
/*We have found the smallest area. That is the resulting effective area for the "current" point*/
if (i<npoints-avoid_collaps)
ea->res_arealist[current]=ea->initial_arealist[current].area;
else
- ea->res_arealist[current]=FLT_MAX;
-
+ ea->res_arealist[current]=FLT_MAX;
+
if(ea->res_arealist[current]<check_order_min_area)
lwerror("Oh no, this is a bug. For some reason the minHeap returned our points in the wrong order. Please file a ticket in PostGIS ticket system, or send a mial at the mailing list.Returned area = %lf, and last area = %lf",ea->res_arealist[current],check_order_min_area);
-
- check_order_min_area=ea->res_arealist[current];
-
+
+ check_order_min_area=ea->res_arealist[current];
+
/*The found smallest area point is now regarded as elimnated and we have to recalculate the area the adjacent (ignoring earlier elimnated points) points gives*/
-
+
/*FInd point before and after*/
before_current=ea->initial_arealist[current].prev;
after_current=ea->initial_arealist[current].next;
-
+
P2= (double*)getPoint_internal(ea->inpts, before_current);
P3= (double*)getPoint_internal(ea->inpts, after_current);
-
+
/*Check if point before current point is the first in the point array. */
if(before_current>0)
- {
-
+ {
+
P1= (double*)getPoint_internal(ea->inpts, ea->initial_arealist[before_current].prev);
if(is3d)
area=triarea3d(P1, P2, P3);
else
- area=triarea2d(P1, P2, P3);
-
+ area=triarea2d(P1, P2, P3);
+
ea->initial_arealist[before_current].area = FP_MAX(area,ea->res_arealist[current]);
minheap_update(&tree, ea->initial_arealist, ea->initial_arealist[before_current].treeindex);
}
if(after_current<npoints-1)/*Check if point after current point is the last in the point array. */
{
P1=P2;
- P2=P3;
-
+ P2=P3;
+
P3= (double*)getPoint_internal(ea->inpts, ea->initial_arealist[after_current].next);
-
+
if(is3d)
area=triarea3d(P1, P2, P3);
else
- area=triarea2d(P1, P2, P3);
-
-
+ area=triarea2d(P1, P2, P3);
+
+
ea->initial_arealist[after_current].area = FP_MAX(area,ea->res_arealist[current]);
minheap_update(&tree, ea->initial_arealist, ea->initial_arealist[after_current].treeindex);
}
-
+
/*rearrange the nodes so the eliminated point will be ingored on the next run*/
ea->initial_arealist[before_current].next = ea->initial_arealist[current].next;
ea->initial_arealist[after_current].prev = ea->initial_arealist[current].prev;
-
+
/*Check if we are finnished*/
if((!set_area && ea->res_arealist[current]>trshld) || (ea->initial_arealist[0].next==(npoints-1)))
go_on=0;
-
+
i++;
};
destroy_minheap(tree);
- return;
+ return;
}
int npoints=ea->inpts->npoints;
int is3d = FLAGS_GET_Z(ea->inpts->flags);
double area;
-
+
const double *P1;
const double *P2;
- const double *P3;
-
+ const double *P3;
+
P1 = (double*)getPoint_internal(ea->inpts, 0);
P2 = (double*)getPoint_internal(ea->inpts, 1);
-
+
/*The first and last point shall always have the maximum effective area. We use float max to not make trouble for bbox*/
ea->initial_arealist[0].area=ea->initial_arealist[npoints-1].area=FLT_MAX;
ea->res_arealist[0]=ea->res_arealist[npoints-1]=FLT_MAX;
-
+
ea->initial_arealist[0].next=1;
ea->initial_arealist[0].prev=0;
-
+
for (i=1;i<(npoints)-1;i++)
{
ea->initial_arealist[i].next=i+1;
area=triarea3d(P1, P2, P3);
else
area=triarea2d(P1, P2, P3);
-
+
LWDEBUGF(4,"Write area %lf to point %d on address %p",area,i,&(ea->initial_arealist[i].area));
ea->initial_arealist[i].area=area;
P1=P2;
P2=P3;
-
- }
+
+ }
ea->initial_arealist[npoints-1].next=npoints-1;
ea->initial_arealist[npoints-1].prev=npoints-2;
-
+
for (i=1;i<(npoints)-1;i++)
{
ea->res_arealist[i]=FLT_MAX;
}
-
+
tune_areas(ea,avoid_collaps,set_area, trshld);
return ;
}
opts = ptarray_construct_empty(FLAGS_GET_Z(inpts->flags), set_m, inpts->npoints);
- ptarray_calc_areas(ea,avoid_collaps,set_area,trshld);
-
+ ptarray_calc_areas(ea,avoid_collaps,set_area,trshld);
+
if(set_area)
{
/*Only return points with an effective area above the threashold*/
}
}
else
- {
+ {
/*Only return points with an effective area above the threashold*/
for (p=0;p<ea->inpts->npoints;p++)
{
pt=getPoint4d(ea->inpts, p);
ptarray_append_point(opts, &pt, LW_TRUE);
}
- }
+ }
}
destroy_effectivearea(ea);
-
+
return opts;
-
+
}
static LWLINE* lwline_set_effective_area(const LWLINE *iline,int set_area, double trshld)
{
LWDEBUG(2, "Entered lwline_set_effective_area");
-
+
/* Skip empty case or too small to simplify */
if( lwline_is_empty(iline) || iline->points->npoints<3)
return lwline_clone(iline);
-
+
int set_m;
if(set_area)
set_m=1;
else
set_m=FLAGS_GET_M(iline->flags);
-
+
LWLINE *oline = lwline_construct_empty(iline->srid, FLAGS_GET_Z(iline->flags), set_m);
-
+
oline = lwline_construct(iline->srid, NULL, ptarray_set_effective_area(iline->points,2,set_area,trshld));
-
+
oline->type = iline->type;
return oline;
-
+
}
opoly->type = ipoly->type;
if( lwpoly_is_empty(opoly) )
- return NULL;
+ return NULL;
return opoly;
-
+
}
static LWCOLLECTION* lwcollection_set_effective_area(const LWCOLLECTION *igeom,int set_area, double trshld)
{
- LWDEBUG(2, "Entered lwcollection_set_effective_area");
+ LWDEBUG(2, "Entered lwcollection_set_effective_area");
int i;
int set_m;
if(set_area)
{
BOX3D *b;
assert(gbox);
-
+
b = lwalloc(sizeof(BOX3D));
b->xmin = gbox->xmin;
}
b->srid = SRID_UNKNOWN;
- return b;
+ return b;
}
/* TODO to be removed */
{
GBOX *b;
assert(b3d);
-
+
b = lwalloc(sizeof(GBOX));
b->xmin = b3d->xmin;
memcpy(gout, g1, sizeof(GBOX));
return LW_TRUE;
}
-
+
gout->flags = g1->flags;
gout->xmin = FP_MIN(g1->xmin, g2->xmin);
gout->ymin = FP_MIN(g1->ymin, g2->ymin);
gout->ymax = FP_MAX(g1->ymax, g2->ymax);
-
+
gout->zmin = FP_MIN(g1->zmin, g2->zmin);
gout->zmax = FP_MAX(g1->zmax, g2->zmax);
if ( ! isfinite(gbox->xmin) || isnan(gbox->xmin) ||
! isfinite(gbox->xmax) || isnan(gbox->xmax) )
return LW_FALSE;
-
+
/* Y */
if ( ! isfinite(gbox->ymin) || isnan(gbox->ymin) ||
! isfinite(gbox->ymax) || isnan(gbox->ymax) )
return LW_FALSE;
-
+
/* Z */
if ( FLAGS_GET_GEODETIC(gbox->flags) || FLAGS_GET_Z(gbox->flags) )
{
! isfinite(gbox->mmax) || isnan(gbox->mmax) )
return LW_FALSE;
}
-
- return LW_TRUE;
+
+ return LW_TRUE;
}
int gbox_merge_point3d(const POINT3D *p, GBOX *gbox)
if ( g1->zmax < g2->zmin || g1->zmin > g2->zmax )
return LW_FALSE;
else
- return LW_TRUE;
+ return LW_TRUE;
}
-
+
/* If both geodetic or both have Z, check Z */
if ( FLAGS_GET_Z(g1->flags) && FLAGS_GET_Z(g2->flags) )
{
if ( g1->zmax < g2->zmin || g1->zmin > g2->zmax )
return LW_FALSE;
}
-
+
/* If both have M, check M */
if ( FLAGS_GET_M(g1->flags) && FLAGS_GET_M(g2->flags) )
{
if ( g1->mmax < g2->mmin || g1->mmin > g2->mmax )
return LW_FALSE;
}
-
+
return LW_TRUE;
}
if ( g1->xmax < g2->xmin || g1->ymax < g2->ymin ||
g1->xmin > g2->xmax || g1->ymin > g2->ymax )
return LW_FALSE;
-
+
return LW_TRUE;
}
{
uint32_t sz = 8; /* varsize (4) + srid(3) + flags (1) */
- if (gserialized_has_bbox(gser))
+ if (gserialized_has_bbox(gser))
sz += gbox_serialized_size(gser->flags);
return sz;
/* Only the first 21 bits are set. Slide up and back to pull
the negative bits down, if we need them. */
srid = (srid<<11)>>11;
-
+
/* 0 is our internal unknown value. We'll map back and forth here for now */
if ( srid == 0 )
return SRID_UNKNOWN;
* We'll map back and forth here for now */
if ( srid == SRID_UNKNOWN )
srid = 0;
-
+
s->srid[0] = (srid & 0x001F0000) >> 16;
s->srid[1] = (srid & 0x0000FF00) >> 8;
s->srid[2] = (srid & 0x000000FF);
memcpy(&type, p, 4);
memcpy(&num, p+4, 4);
-
+
if ( lwtype_is_collection(type) )
{
size_t lz = 8;
}
/* Unfortunately including advanced instructions is something that
-only helps a small sliver of users who can build their own
+only helps a small sliver of users who can build their own
knowing the target system they will be running on. Packagers
-have to aim for the lowest common demoninator. So this is
+have to aim for the lowest common demoninator. So this is
dead code for the forseeable future. */
#define HAVE_PDEP 0
#if HAVE_PDEP
uint64_t y = u2;
int i;
- static uint64_t B[5] =
- {
- 0x5555555555555555,
- 0x3333333333333333,
- 0x0F0F0F0F0F0F0F0F,
- 0x00FF00FF00FF00FF,
- 0x0000FFFF0000FFFF
+ static uint64_t B[5] =
+ {
+ 0x5555555555555555,
+ 0x3333333333333333,
+ 0x0F0F0F0F0F0F0F0F,
+ 0x00FF00FF00FF00FF,
+ 0x0000FFFF0000FFFF
};
static uint64_t S[5] = { 1, 2, 4, 8, 16 };
uint32_t ux, uy;
float fx, fy;
- /*
+ /*
* Since in theory the bitwise representation of an IEEE
* float is sortable (exponents come before mantissa, etc)
* we just copy the bits directly into an int and then
size_t bsz1 = sz1 - hsz1;
size_t bsz2 = sz2 - hsz2;
size_t bsz = bsz1 < bsz2 ? bsz1 : bsz2;
-
+
uint64_t hash1, hash2;
int32_t srid1 = gserialized_get_srid(g1);
int32_t srid2 = gserialized_get_srid(g2);
-
+
g1_is_empty = (gserialized_get_gbox_p(g1, &box1) == LW_FAILURE);
g2_is_empty = (gserialized_get_gbox_p(g2, &box2) == LW_FAILURE);
-
+
/* Empty == Empty */
if (g1_is_empty && g2_is_empty)
{
uint32_t t2 = gserialized_get_type(g2);
return t1 == t2 ? 0 : (t1 < t2 ? -1 : 1);
}
-
+
/* Empty < Non-empty */
if (g1_is_empty)
return -1;
-
+
/* Non-empty > Empty */
if (g2_is_empty)
return 1;
cmp = memcmp(b1, b2, bsz);
if ( bsz1 == bsz2 && srid1 == srid2 && cmp == 0 )
return 0;
-
+
/* Using the centroids, calculate somewhat sortable */
/* hash key. The key doesn't provide good locality over */
/* the +/- boundary, but otherwise is pretty OK */
if ( hash1 > hash2 )
return 1;
- else if ( hash1 < hash2 )
+ else if ( hash1 < hash2 )
return -1;
-
+
/* What, the hashes are equal? OK... sort on the */
/* box minima */
if (box1.xmin < box2.xmin)
return -1;
else if (hsz1 > hsz2)
return 1;
-
+
/* OK fine, we'll sort on the memcmp just to be done with this */
return cmp == 0 ? 0 : (cmp > 0 ? 1 : -1);
}
{
return LW_FAILURE;
}
-
+
/* Boxes of points are easy peasy */
if ( type == POINTTYPE )
{
double *dptr = (double*)(g->data);
int *iptr = (int*)(g->data);
int npoints = iptr[1]; /* Read the npoints */
-
+
/* This only works with 2-point lines */
if ( npoints != 2 )
return LW_FAILURE;
-
+
/* Advance to X */
/* Past <linetype><npoints> */
i++;
gbox->xmin = FP_MIN(dptr[i], dptr[i+ndims]);
gbox->xmax = FP_MAX(dptr[i], dptr[i+ndims]);
-
+
/* Advance to Y */
i++;
gbox->ymin = FP_MIN(dptr[i], dptr[i+ndims]);
gbox->ymax = FP_MAX(dptr[i], dptr[i+ndims]);
-
+
gbox->flags = g->flags;
if ( FLAGS_GET_Z(g->flags) )
{
i += 2;
gbox->xmin = FP_MIN(dptr[i], dptr[i+ndims]);
gbox->xmax = FP_MAX(dptr[i], dptr[i+ndims]);
-
+
/* Advance to Y */
i++;
gbox->ymin = FP_MIN(dptr[i], dptr[i+ndims]);
gbox->ymax = FP_MAX(dptr[i], dptr[i+ndims]);
-
+
gbox->flags = g->flags;
if ( FLAGS_GET_Z(g->flags) )
{
gbox_float_round(gbox);
return LW_SUCCESS;
}
-
+
return LW_FAILURE;
}
{
size_t size = 8; /* Header overhead. */
assert(geom);
-
+
if ( geom->bbox )
- size += gbox_serialized_size(geom->flags);
-
+ size += gbox_serialized_size(geom->flags);
+
size += gserialized_from_any_size(geom);
LWDEBUGF(3, "g_serialize size = %d", size);
-
+
return size;
}
{
lwgeom_add_bbox(geom);
}
-
+
/*
** Harmonize the flags to the state of the lwgeom
*/
if ( npoints > 0 )
line->points = ptarray_construct_reference_data(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), npoints, data_ptr);
-
+
else
line->points = ptarray_construct(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), 0); /* Empty linestring */
/* Make a point array for the ring, and move the ordinate pointer past the ring ordinates. */
poly->rings[i] = ptarray_construct_reference_data(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), npoints, ordinate_ptr);
-
+
ordinate_ptr += sizeof(double) * FLAGS_NDIMS(g_flags) * npoints;
}
data_ptr += 4; /* Skip past the npoints. */
if ( npoints > 0 )
- triangle->points = ptarray_construct_reference_data(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), npoints, data_ptr);
+ triangle->points = ptarray_construct_reference_data(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), npoints, data_ptr);
else
triangle->points = ptarray_construct(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), 0); /* Empty triangle */
data_ptr += 4; /* Skip past the npoints. */
if ( npoints > 0 )
- circstring->points = ptarray_construct_reference_data(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), npoints, data_ptr);
+ circstring->points = ptarray_construct_reference_data(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), npoints, data_ptr);
else
circstring->points = ptarray_construct(FLAGS_GET_Z(g_flags), FLAGS_GET_M(g_flags), 0); /* Empty circularstring */
int a2_side, clockwise;
double a1, a3;
double angle;
-
+
if ( lw_arc_is_pt(A1, A2, A3) )
return 0.0;
-
+
radius_A = lw_arc_center(A1, A2, A3, &C);
/* Co-linear! Return linear distance! */
double dy = A1->y - A3->y;
return sqrt(dx*dx + dy*dy);
}
-
+
/* Closed circle! Return the circumference! */
circumference_A = M_PI * 2 * radius_A;
if ( p2d_same(A1, A3) )
return circumference_A;
-
+
/* Determine the orientation of the arc */
a2_side = lw_segment_side(A1, A3, A2);
clockwise = LW_TRUE;
else
clockwise = LW_FALSE;
-
+
/* Angles of each point that defines the arc section */
a1 = atan2(A1->y - C.y, A1->x - C.x);
a3 = atan2(A3->y - C.y, A3->x - C.x);
if ( a3 > a1 )
angle = a3 - a1;
else
- angle = 2*M_PI + a3 - a1;
+ angle = 2*M_PI + a3 - a1;
}
/* Length as proportion of circumference */
double radius_A;
double side_Q, side_A2;
double d;
-
+
side_Q = lw_segment_side(A1, A3, Q);
radius_A = lw_arc_center(A1, A2, A3, &C);
side_A2 = lw_segment_side(A1, A3, A2);
-
+
/* Linear case */
if ( radius_A < 0 )
return side_Q;
-
+
d = distance2d_pt_pt(Q, &C);
-
+
/* Q is on the arc boundary */
if ( d == radius_A && side_Q == side_A2 )
- {
+ {
return 0;
}
-
+
/* Q on A1-A3 line, so its on opposite side to A2 */
if ( side_Q == 0 )
{
return -1 * side_A2;
}
-
+
/*
* Q is inside the arc boundary, so it's not on the side we
* might think from examining only the end points
{
side_Q *= -1;
}
-
+
return side_Q;
}
* point is coincident with either end point, they are taken as colinear.
*/
double
-lw_arc_center(const POINT2D *p1, const POINT2D *p2, const POINT2D *p3, POINT2D *result)
+lw_arc_center(const POINT2D *p1, const POINT2D *p2, const POINT2D *p3, POINT2D *result)
{
POINT2D c;
double cx, cy, cr;
{
break;
}
-
+
if ( miny > latmin + latwidth / 2.0 )
{
latminadjust = latwidth / 2.0;
gbox_init(&gbox);
gbox_init(&gbox_bounds);
- result = lwgeom_calculate_gbox_cartesian(lwgeom, &gbox);
+ result = lwgeom_calculate_gbox_cartesian(lwgeom, &gbox);
if ( result == LW_FAILURE ) return NULL;
/* Return error if we are being fed something outside our working bounds */
{
int i;
if ( ! col ) return;
-
+
if ( col->bbox )
{
lwfree(col->bbox);
/**
* Takes a potentially heterogeneous collection and returns a homogeneous
* collection consisting only of the specified type.
-* WARNING: the output will contain references to geometries in the input,
+* WARNING: the output will contain references to geometries in the input,
* so the result must be carefully released, not freed.
*/
LWCOLLECTION* lwcollection_extract(LWCOLLECTION *col, int type)
lwcollection_force_dims(const LWCOLLECTION *col, int hasz, int hasm)
{
LWCOLLECTION *colout;
-
+
/* Return 2D empty */
if( lwcollection_is_empty(col) )
{
{
if ( col->ngeoms < 1 )
return LW_FAILURE;
-
+
return lwgeom_startpoint(col->geoms[0], pt);
}
{
uint32_t i;
LWCOLLECTION *newcoll;
-
+
newcoll = lwcollection_construct_empty(coll->type, coll->srid, lwgeom_has_z((LWGEOM*)coll), lwgeom_has_m((LWGEOM*)coll));
for (i=0; i<coll->ngeoms; i++)
int lwcurvepoly_add_ring(LWCURVEPOLY *poly, LWGEOM *ring)
{
int i;
-
+
/* Can't do anything with NULLs */
if( ! poly || ! ring )
{
return LW_FAILURE;
}
-
+
/* In case this is a truly empty, make some initial space */
if ( poly->rings == NULL )
{
/* Add the ring and increment the ring count */
poly->rings[poly->nrings] = (LWGEOM*)ring;
poly->nrings++;
- return LW_SUCCESS;
+ return LW_SUCCESS;
}
/**
if ( lon < -1.0 * M_PI )
lon = 2.0 * M_PI + lon;
-
+
if ( lon == -2.0 * M_PI )
lon *= -1.0;
double zmin = FLT_MAX;
double zmax = -1 * FLT_MAX;
POINT3D pt;
-
+
/* Take a copy of the box corners so we can treat them as a list */
/* Elements are xmin, xmax, ymin, ymax, zmin, zmax */
memcpy(d, &(gbox->xmin), 6*sizeof(double));
-
+
/* Generate all 8 corner vectors of the box */
for ( i = 0; i < 8; i++ )
{
{
double angle, dotprod;
POINT3D pt_n;
-
+
pt_n.x = d[i / 2];
pt_n.y = d[2 + (i % 2)];
magnitude = sqrt(pt_n.x*pt_n.x + pt_n.y*pt_n.y);
}
}
}
-
+
/* Return the distance between the two furthest vectors */
return maxangle;
}
/* Take a copy of the box corners so we can treat them as a list */
/* Elements are xmin, xmax, ymin, ymax, zmin, zmax */
memcpy(d, &(gbox->xmin), 6*sizeof(double));
-
+
/* Zero out our return vector */
pt.x = pt.y = pt.z = 0.0;
for ( i = 0; i < 8; i++ )
{
POINT3D pt_n;
-
+
pt_n.x = d[i / 4];
pt_n.y = d[2 + ((i % 4) / 2)];
pt_n.z = d[4 + (i % 2)];
normalize(&pt_n);
-
+
pt.x += pt_n.x;
pt.y += pt_n.y;
- pt.z += pt_n.z;
+ pt.z += pt_n.z;
}
-
+
pt.x /= 8.0;
pt.y /= 8.0;
pt.z /= 8.0;
cart2geog(&pt, &g);
out->x = longitude_degrees_normalize(rad2deg(g.lon));
out->y = latitude_degrees_normalize(rad2deg(g.lat));
-
+
return LW_SUCCESS;
}
cross_product(v1, v2, &normal);
normalize(&normal);
cross_product(&normal, v1, &v3);
-
+
x = dot_product(v1, v2);
y = dot_product(v2, &v3);
-
+
angle = atan2(y, x);
return angle;
}
{
double p_dot = dot_product(P1, P2);
POINT3D P3;
-
+
/* If edge is really large, calculate a narrower equivalent angle A1/A3. */
if ( p_dot < 0 )
{
{
P3 = *P2;
}
-
+
/* Normals to the A-plane and B-plane */
cross_product(P1, &P3, normal);
normalize(normal);
double uxuy, uyuz, uxuz;
double ux2, uy2, uz2;
double rxx, rxy, rxz, ryx, ryy, ryz, rzx, rzy, rzz;
-
+
/* Need a unit vector normal to rotate around */
unit_normal(v1, v2, &u);
-
+
uxuy = u.x * u.y;
uxuz = u.x * u.z;
uyuz = u.y * u.z;
-
+
ux2 = u.x * u.x;
uy2 = u.y * u.y;
uz2 = u.z * u.z;
-
+
rxx = cos_a + ux2 * (1 - cos_a);
rxy = uxuy * (1 - cos_a) - u.z * sin_a;
rxz = uxuz * (1 - cos_a) + u.y * sin_a;
-
+
ryx = uxuy * (1 - cos_a) + u.z * sin_a;
ryy = cos_a + uy2 * (1 - cos_a);
ryz = uyuz * (1 - cos_a) - u.x * sin_a;
-
+
rzx = uxuz * (1 - cos_a) - u.y * sin_a;
rzy = uyuz * (1 - cos_a) + u.x * sin_a;
rzz = cos_a + uz2 * (1 - cos_a);
LWDEBUG(4, "point is on plane (dot product is zero)");
return 0;
}
-
+
if ( w < 0 )
return -1;
else
robust_cross_product(b, c, &normal2);
normalize(&normal1);
normalize(&normal2);
- return sphere_distance_cartesian(&normal1, &normal2);
+ return sphere_distance_cartesian(&normal1, &normal2);
}
/**
double area_radians = 0.0;
int side;
GEOGRAPHIC_EDGE e;
-
+
angle_a = sphere_angle(b,a,c);
angle_b = sphere_angle(a,b,c);
angle_c = sphere_angle(b,c,a);
-
+
area_radians = angle_a + angle_b + angle_c - M_PI;
/* What's the direction of the B/C edge? */
e.start = *a;
e.end = *b;
side = edge_point_side(&e, c);
-
+
/* Co-linear points implies no area */
if ( side == 0 )
return 0.0;
int side = edge_point_side(e, p);
if ( side == 0 )
return LW_TRUE;
-
+
return LW_FALSE;
}
{
double heading = 0.0;
double f;
-
+
/* Starting from the poles? Special case. */
if ( FP_IS_ZERO(cos(s->lat)) )
return (s->lat > 0.0) ? M_PI : 0.0;
{
lon2 = lon1 + atan2(sin(azimuth)*sin(d)*cos(lat1), cos(d)-sin(lat1)*sin(lat2));
}
-
+
if ( isnan(lat2) || isnan(lon2) )
return LW_FAILURE;
/* Initialize the box with the edge end points */
gbox_init_point3d(A1, gbox);
gbox_merge_point3d(A2, gbox);
-
+
/* Zero length edge, just return! */
if ( p3d_same(A1, A2) )
return LW_SUCCESS;
-
+
/* Error out on antipodal edge */
if ( FP_EQUALS(A1->x, -1*A2->x) && FP_EQUALS(A1->y, -1*A2->y) && FP_EQUALS(A1->z, -1*A2->z) )
{
lwerror("Antipodal (180 degrees long) edge detected!");
return LW_FAILURE;
}
-
+
/* Create A3, a vector in the plane of A1/A2, orthogonal to A1 */
unit_normal(A1, A2, &AN);
unit_normal(&AN, A1, &A3);
memset(X, 0, sizeof(POINT3D) * 6);
X[0].x = X[2].y = X[4].z = 1.0;
X[1].x = X[3].y = X[5].z = -1.0;
-
+
/* Initialize a 2-space origin point. */
O.x = O.y = 0.0;
/* What side of the line joining R1/R2 is O? */
o_side = lw_segment_side(&R1, &R2, &O);
-
+
/* Add any extrema! */
for ( i = 0; i < 6; i++ )
{
RX.x = dot_product(&(X[i]), A1);
RX.y = dot_product(&(X[i]), &A3);
normalize2d(&RX);
-
+
/* Any axis end on the side of R1/R2 opposite the origin */
/* is an extreme point in the arc, so we add the 3-space */
/* version of the point on R1/R2 to the gbox */
Xn.x = RX.x * A1->x + RX.y * A3.x;
Xn.y = RX.x * A1->y + RX.y * A3.y;
Xn.z = RX.x * A1->z + RX.y * A3.z;
-
+
gbox_merge_point3d(&Xn, gbox);
}
}
}
void lwpoly_pt_outside(const LWPOLY *poly, POINT2D *pt_outside)
-{
+{
/* Make sure we have boxes */
if ( poly->bbox )
{
POINT4D p1, p2, p;
GEOGRAPHIC_POINT g1, g2, g;
double d;
-
+
/* Just crap out on crazy input */
if ( ! pa_in )
lwerror("ptarray_segmentize_sphere: null input pointarray");
- if ( max_seg_length <= 0.0 )
+ if ( max_seg_length <= 0.0 )
lwerror("ptarray_segmentize_sphere: maximum segment length must be positive");
/* Empty starting array */
ptarray_append_point(pa_out, &p1, LW_FALSE);
geographic_point_init(p1.x, p1.y, &g1);
pa_in_offset++;
-
+
while ( pa_in_offset < pa_in->npoints )
{
getPoint4d_p(pa_in, pa_in_offset, &p2);
geographic_point_init(p2.x, p2.y, &g2);
-
+
/* Skip duplicate points (except in case of 2-point lines!) */
if ( (pa_in->npoints > 2) && p4d_same(&p1, &p2) )
{
/* How long is this edge? */
d = sphere_distance(&g1, &g2);
-
+
/* We need to segmentize this edge */
if ( d > max_seg_length )
{
/* The independent Z/M values on the ptarray */
if ( hasz ) dzz = (p2.z - p1.z) / nsegs;
if ( hasm ) dmm = (p2.m - p1.m) / nsegs;
-
+
g = g1;
p = p1;
for ( i = 0; i < nsegs - 1; i++ )
p.m += dmm;
ptarray_append_point(pa_out, &p, LW_FALSE);
}
-
+
ptarray_append_point(pa_out, &p2, LW_FALSE);
}
/* This edge is already short enough */
g1 = g2;
pa_in_offset++;
}
-
- return pa_out;
+
+ return pa_out;
}
/**
LWPOLY *lwpoly_in, *lwpoly_out;
LWCOLLECTION *lwcol_in, *lwcol_out;
int i;
-
+
/* Reflect NULL */
if ( ! lwg_in )
return NULL;
-
+
/* Clone empty */
if ( lwgeom_is_empty(lwg_in) )
return lwgeom_clone(lwg_in);
-
+
switch (lwg_in->type)
{
case MULTIPOINTTYPE:
lwg_in->type, lwtype_name(lwg_in->type));
break;
}
-
+
lwerror("lwgeom_segmentize_sphere got to the end of the function, should not happen");
return NULL;
}
const POINT2D *p;
GEOGRAPHIC_POINT a, b, c;
double area = 0.0;
-
+
/* Return zero on nonsensical inputs */
if ( ! pa || pa->npoints < 4 )
return 0.0;
-
+
p = getPoint2d_cp(pa, 0);
geographic_point_init(p->x, p->y, &a);
p = getPoint2d_cp(pa, 1);
geographic_point_init(p->x, p->y, &b);
-
+
for ( i = 2; i < pa->npoints-1; i++ )
{
p = getPoint2d_cp(pa, i);
area += sphere_signed_area(&a, &b, &c);
b = c;
}
-
+
return fabs(area);
}
double x, y;
POINTARRAY *pa;
LWPOINT *lwp;
-
+
/* Normalize distance to be positive*/
if ( distance < 0.0 ) {
distance = -distance;
azimuth += M_PI;
}
-
+
/* Normalize azimuth */
azimuth -= 2.0 * M_PI * floor(azimuth / (2.0 * M_PI));
lwerror("Distance must not be greater than %g", M_PI * spheroid->radius);
return NULL;
}
-
+
/* Convert to ta geodetic point */
x = lwpoint_get_x(r);
y = lwpoint_get_y(r);
geographic_point_init(x, y, &geo_source);
-
+
/* Try the projection */
if( spheroid_project(&geo_source, spheroid, distance, azimuth, &geo_dest) == LW_FAILURE )
{
lwerror("Unable to project from (%g %g) with azimuth %g and distance %g", x, y, azimuth, distance);
return NULL;
}
-
+
/* Build the output LWPOINT */
pa = ptarray_construct(0, 0, 1);
pt_dest.x = rad2deg(longitude_radians_normalize(geo_dest.lon));
x2 = lwpoint_get_x(s);
y2 = lwpoint_get_y(s);
geographic_point_init(x2, y2, &g2);
-
+
/* Same point, return NaN */
if ( FP_EQUALS(x1, x2) && FP_EQUALS(y1, y2) )
{
return NAN;
}
-
+
/* Do the direction calculation */
return spheroid_direction(&g1, &g2, spheroid);
}
gbox_init(&gbox1);
gbox_init(&gbox2);
-
+
assert(lwgeom1);
assert(lwgeom2);
-
+
LWDEBUGF(4, "entered function, tolerance %.8g", tolerance);
/* What's the distance to an empty geometry? We don't know.
{
return 0.0;
}
-
+
/* Not inside, so what's the actual distance? */
for ( i = 0; i < lwpoly->nrings; i++ )
{
p = getPoint2d_cp(pa, 0);
ll2cart(p, &A1);
-
+
for ( i = 1; i < pa->npoints; i++ )
{
-
+
p = getPoint2d_cp(pa, i);
ll2cart(p, &A2);
-
+
edge_calculate_gbox(&A1, &A2, &edge_gbox);
/* Initialize the box */
{
gbox_merge(&edge_gbox, gbox);
}
-
+
A1 = A2;
}
{
if ( lwgeom_is_empty(geom) )
return LW_TRUE;
-
+
switch (geom->type)
{
case POINTTYPE:
/* Add in the vertical displacement if we're in 3D */
if ( hasz )
seglength = sqrt( (zb-za)*(zb-za) + seglength*seglength );
-
+
/* Add this segment length to the total */
length += seglength;
{
POINT3D AC; /* Center point of A1/A2 */
double min_similarity, similarity;
-
+
/* The normalized sum bisects the angle between start and end. */
vector_sum(A1, A2, &AC);
normalize(&AC);
-
+
/* The projection of start onto the center defines the minimum similarity */
min_similarity = dot_product(A1, &AC);
if ( FP_IS_ZERO(dp) )
return 0;
-
+
return dp < 0.0 ? -1 : 1;
}
double ab_dot;
int a1_side, a2_side, b1_side, b2_side;
int rv = PIR_NO_INTERACT;
-
+
/* Normals to the A-plane and B-plane */
unit_normal(A1, A2, &AN);
unit_normal(B1, B2, &BN);
-
+
/* Are A-plane and B-plane basically the same? */
ab_dot = dot_product(&AN, &BN);
if ( FP_EQUALS(fabs(ab_dot), 1.0) )
}
return rv;
}
-
+
/* What side of plane-A and plane-B do the end points */
/* of A and B fall? */
a1_side = dot_product_side(&BN, A1);
{
return PIR_INTERSECTS;
}
-
+
return PIR_NO_INTERACT;
}
/* Touches at B2, B1 is on what side? */
rv |= (b1_side < 0 ? PIR_B_TOUCH_RIGHT : PIR_B_TOUCH_LEFT);
}
-
+
return rv;
}
{
continue;
}
-
+
/* Our test point is on an edge end! Point is "in ring" by our definition */
if ( point3d_equals(&S1, &E1) )
{
return LW_TRUE;
}
-
+
/* Calculate relationship between stab line and edge */
inter = edge_intersects(&S1, &S2, &E1, &E2);
-
+
/* We have some kind of interaction... */
if ( inter & PIR_INTERSECTS )
{
{
return LW_TRUE;
}
-
+
/* It's a touching interaction, disregard all the left-side ones. */
/* It's a co-linear intersection, ignore those. */
if ( inter & PIR_B_TOUCH_RIGHT || inter & PIR_COLINEAR )
{
LWDEBUGF(4," edge (%d) did not cross", i);
}
-
+
/* Increment to next edge */
E1 = E2;
}
{
int i;
if ( ! node ) return;
-
+
for ( i = 0; i < node->num_nodes; i++ )
circ_tree_free(node->nodes[i]);
geographic_point_init(p2->x, p2->y, &g2);
LWDEBUGF(3,"edge #%d (%g %g, %g %g)", i, p1->x, p1->y, p2->x, p2->y);
-
+
diameter = sphere_distance(&g1, &g2);
/* Zero length edge, doesn't get a node */
node = lwalloc(sizeof(CIRC_NODE));
node->p1 = p1;
node->p2 = p2;
-
+
/* Convert ends to X/Y/Z, sum, and normalize to get mid-point */
geog2cart(&g1, &q1);
geog2cart(&g2, &q2);
node->pt_outside.x = 0.0;
node->pt_outside.y = 0.0;
node->geom_type = 0;
-
+
return node;
}
/* Catch sphere_direction when it barfs */
if ( isnan(dir) )
return LW_FAILURE;
-
+
/* Center of new circle is projection from start point, using offset distance*/
return sphere_project(c1, offset, dir, center);
}
POINT3D p1, p2;
POINT3D p1p2, pc;
double proportion = offset/distance;
-
+
LWDEBUG(4,"calculating cartesian center");
-
+
geog2cart(c1, &p1);
geog2cart(c2, &p2);
-
+
/* Difference between p2 and p1 */
p1p2.x = p2.x - p1.x;
p1p2.y = p2.y - p1.y;
p1p2.x *= proportion;
p1p2.y *= proportion;
p1p2.z *= proportion;
-
+
/* Add difference to p1 to get approximate center point */
pc.x = p1.x + p1p2.x;
pc.y = p1.y + p1p2.y;
pc.z = p1.z + p1p2.z;
normalize(&pc);
-
+
/* Convert center point to geographics */
cart2geog(&pc, center);
-
+
return LW_SUCCESS;
}
/* 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;
new_geom_type = c[0]->geom_type;
-
+
/* 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;
}
else
{
- new_geom_type = lwtype_get_collectiontype(new_geom_type);
+ new_geom_type = lwtype_get_collectiontype(new_geom_type);
}
}
/* If we can't add next feature to this collection cleanly, promote again to anonymous collection */
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");
}
}
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 */
new_radius *= 1.1;
}
}
- LWDEBUGF(3, " new center is (%g %g) new radius is %g", new_center.lon, new_center.lat, new_radius);
+ 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;
/* Can't do anything with no points */
if ( pa->npoints < 1 )
return NULL;
-
+
/* Special handling for a single point */
if ( pa->npoints == 1 )
return circ_node_leaf_point_new(pa);
-
+
/* First create a flat list of nodes, one per edge. */
num_edges = pa->npoints - 1;
nodes = lwalloc(sizeof(CIRC_NODE*) * pa->npoints);
if ( node ) /* Not zero length? */
nodes[j++] = node;
}
-
+
/* Special case: only zero-length edges. Make a point node. */
if ( j == 0 ) {
lwfree(nodes);
inodes = lwalloc(sizeof(CIRC_NODE*)*CIRC_NODE_SIZE);
inodes[inode_num] = nodes[j];
-
+
if ( inode_num == CIRC_NODE_SIZE-1 )
nodes[num_parents++] = circ_node_internal_new(inodes, CIRC_NODE_SIZE);
}
-
+
/* Clean up any remaining nodes... */
if ( inode_num == 0 )
{
/* Merge spare nodes */
nodes[num_parents++] = circ_node_internal_new(inodes, inode_num+1);
}
-
- num_children = num_parents;
+
+ num_children = num_parents;
num_parents = 0;
}
-
+
/* Return a reference to the head of the tree */
return nodes[0];
}
POINT3D S1, S2, E1, E2;
double d;
int i, c;
-
+
/* Construct a stabline edge from our "inside" to our known outside point */
geographic_point_init(pt->x, pt->y, &(stab_edge.start));
geographic_point_init(pt_outside->x, pt_outside->y, &(stab_edge.end));
geog2cart(&(stab_edge.start), &S1);
geog2cart(&(stab_edge.end), &S2);
-
+
LWDEBUG(3, "entered");
-
+
/*
* If the stabline doesn't cross within the radius of a node, there's no
* way it can cross.
*/
-
+
LWDEBUGF(3, "working on node %p, edge_num %d, radius %g, center POINT(%g %g)", node, node->edge_num, node->radius, rad2deg(node->center.lon), rad2deg(node->center.lat));
d = edge_distance_to_point(&stab_edge, &(node->center), &closest);
LWDEBUGF(3, "edge_distance_to_point=%g, node_radius=%g", d, node->radius);
if ( FP_LTEQ(d, node->radius) )
{
LWDEBUGF(3,"entering this branch (%p)", node);
-
+
/* Return the crossing number of this leaf */
if ( circ_node_is_leaf(node) )
{
geographic_point_init(node->p2->x, node->p2->y, &(edge.end));
geog2cart(&(edge.start), &E1);
geog2cart(&(edge.end), &E2);
-
+
inter = edge_intersects(&S1, &S2, &E1, &E2);
-
+
if ( inter & PIR_INTERSECTS )
{
LWDEBUG(3," got stab line edge_intersection with this edge!");
{
LWDEBUGF(3,"skipping this branch (%p)", node);
}
-
+
return 0;
}
double d = sphere_distance(&(n1->center), &(n2->center));
double r1 = n1->radius;
double r2 = n2->radius;
-
+
if ( d < r1 + r2 )
return 0.0;
-
+
return d - r1 - r2;
}
/* the actual spheroid distance is larger than the sphere distance */
/* causing the return value to be larger than the threshold value */
double threshold_radians = 0.95 * threshold / spheroid->radius;
-
+
circ_tree_distance_tree_internal(n1, n2, threshold_radians, &min_dist, &max_dist, &closest1, &closest2);
/* Spherical case */
}
else
{
- return spheroid_distance(&closest1, &closest2, spheroid);
+ return spheroid_distance(&closest1, &closest2, spheroid);
}
}
static double
circ_tree_distance_tree_internal(const CIRC_NODE* n1, const CIRC_NODE* n2, double threshold, double* min_dist, double* max_dist, GEOGRAPHIC_POINT* closest1, GEOGRAPHIC_POINT* closest2)
-{
+{
double max;
double d, d_min;
int i;
-
+
LWDEBUGF(4, "entered, min_dist=%.8g max_dist=%.8g, type1=%d, type2=%d", *min_dist, *max_dist, n1->geom_type, n2->geom_type);
/*
circ_tree_print(n1, 0);
circ_tree_print(n2, 0);
*/
-
+
/* Short circuit if we've already hit the minimum */
if( *min_dist < threshold || *min_dist == 0.0 )
return *min_dist;
-
+
/* If your minimum is greater than anyone's maximum, you can't hold the winner */
if( circ_node_min_distance(n1, n2) > *max_dist )
{
- LWDEBUGF(4, "pruning pair %p, %p", n1, n2);
+ LWDEBUGF(4, "pruning pair %p, %p", n1, n2);
return FLT_MAX;
}
-
+
/* If your maximum is a new low, we'll use that as our new global tolerance */
max = circ_node_max_distance(n1, n2);
LWDEBUGF(5, "max %.8g", max);
geographic_point_init(pt.x, pt.y, closest1);
geographic_point_init(pt.x, pt.y, closest2);
return *min_dist;
- }
+ }
}
/* Polygon on one side, primitive type on the other. Check for point-in-polygon */
/* short circuit. */
geographic_point_init(pt.x, pt.y, closest2);
*min_dist = 0.0;
return *min_dist;
- }
+ }
}
-
+
/* Both leaf nodes, do a real distance calculation */
if( circ_node_is_leaf(n1) && circ_node_is_leaf(n2) )
{
double d;
GEOGRAPHIC_POINT close1, close2;
- LWDEBUGF(4, "testing leaf pair [%d], [%d]", n1->edge_num, n2->edge_num);
+ LWDEBUGF(4, "testing leaf pair [%d], [%d]", n1->edge_num, n2->edge_num);
/* One of the nodes is a point */
if ( n1->p1 == n1->p2 || n2->p1 == n2->p2 )
{
geographic_point_init(n2->p1->x, n2->p1->y, &gp2);
close1 = gp1; close2 = gp2;
d = sphere_distance(&gp1, &gp2);
- }
+ }
/* Node 1 is a point */
else if ( n1->p1 == n1->p2 )
{
close1 = gp1;
d = edge_distance_to_point(&e, &gp1, &close2);
}
- LWDEBUGF(4, " got distance %g", d);
+ LWDEBUGF(4, " got distance %g", d);
}
/* Both nodes are edges */
else
{
d = edge_distance_to_edge(&e1, &e2, &close1, &close2);
}
- LWDEBUGF(4, "edge_distance_to_edge returned %g", d);
+ LWDEBUGF(4, "edge_distance_to_edge returned %g", d);
}
if ( d < *min_dist )
{
return d;
}
else
- {
+ {
d_min = FLT_MAX;
/* Drive the recursion into the COLLECTION types first so we end up with */
/* pairings of primitive geometries that can be forced into the point-in-polygon */
{
/* Never get here */
}
-
+
return d_min;
}
}
if ( node->geom_type )
{
printf(" %s", lwtype_name(node->geom_type));
- }
+ }
if ( node->geom_type == POLYGONTYPE )
{
printf(" O(%.5g %.5g)", node->pt_outside.x, node->pt_outside.y);
- }
+ }
printf("\n");
-
- }
+
+ }
else
{
printf("%*s C(%.5g %.5g) R(%.5g)",
if ( node->geom_type == POLYGONTYPE )
{
printf(" O(%.5g %.5g)", node->pt_outside.x, node->pt_outside.y);
- }
+ }
printf("\n");
}
for ( i = 0; i < node->num_nodes; i++ )
/* One ring? Handle it like a line. */
if ( lwpoly->nrings == 1 )
{
- node = circ_tree_new(lwpoly->rings[0]);
+ node = circ_tree_new(lwpoly->rings[0]);
}
else
{
/* selectively when doing distance calculations */
node->geom_type = lwgeom_get_type((LWGEOM*)lwpoly);
lwpoly_pt_outside(lwpoly, &(node->pt_outside));
-
+
return node;
}
/* One geometry? Done! */
if ( lwcol->ngeoms == 1 )
- return lwgeom_calculate_circ_tree(lwcol->geoms[0]);
-
+ return lwgeom_calculate_circ_tree(lwcol->geoms[0]);
+
/* Calculate a tree for each sub-geometry*/
nodes = lwalloc(lwcol->ngeoms * sizeof(CIRC_NODE*));
for ( i = 0; i < lwcol->ngeoms; i++ )
{
if ( lwgeom_is_empty(lwgeom) )
return NULL;
-
+
switch ( lwgeom->type )
{
case POINTTYPE:
lwerror("Unable to calculate spherical index tree for type %s", lwtype_name(lwgeom->type));
return NULL;
}
-
+
}
}
}
-/** Make a GEOSSTRtree that stores a pointer to a variable containing
+/** Make a GEOSSTRtree that stores a pointer to a variable containing
* the array index of the input geoms */
static struct STRTree
make_strtree(void** geoms, uint32_t num_geoms, char is_lwgeom)
lwcollection_build_buffer(const LWCOLLECTION *col, HomogenizeBuffer *buffer)
{
int i;
-
+
if ( ! col ) return;
if ( lwgeom_is_empty(lwcollection_as_lwgeom(col)) ) return;
for ( i = 0; i < col->ngeoms; i++ )
int ntypes = 0;
int type = 0;
LWGEOM *outgeom = NULL;
-
+
HomogenizeBuffer buffer;
/* Sort all the parts into a buffer */
init_homogenizebuffer(&buffer);
lwcollection_build_buffer(col, &buffer);
-
+
/* Check for homogeneity */
for ( i = 0; i < NUMTYPES; i++ )
{
type = i;
}
}
-
+
/* No types? Huh. Return empty. */
if ( ntypes == 0 )
{
{
return lwcollection_as_lwgeom(lwcollection_construct_empty(geom->type, geom->srid, lwgeom_has_z(geom), lwgeom_has_m(geom)));
}
-
+
return lwgeom_clone(geom);
}
/* Return proper multigeometry untouched */
return lwgeom_clone(geom);
}
-
+
/* Work on anonymous collections separately */
case COLLECTIONTYPE:
return lwcollection_homogenize((LWCOLLECTION *) geom);
geojson_lwerror("Too few ordinates in GeoJSON", 4);
return LW_FAILURE;
}
-
+
/* Read X coordinate */
poObjCoord = json_object_array_get_idx( poObj, 0 );
pt.x = json_object_get_double( poObjCoord );
geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
return NULL;
}
-
+
pa = ptarray_construct_empty(1, 0, 1);
parse_geojson_coord(coords, hasz, pa);
{
return (LWGEOM *)lwpoly_construct_empty(root_srid, 0, 0);
}
-
+
for ( i = 0; i < nRings; i++ )
{
points = json_object_array_get_idx(rings, i);
return NULL;
}
nPoints = json_object_array_length(points);
-
+
/* Skip empty rings */
if ( nPoints == 0 ) continue;
-
+
if ( ! ppa )
ppa = (POINTARRAY**)lwalloc(sizeof(POINTARRAY*) * nRings);
-
+
ppa[i] = ptarray_construct_empty(1, 0, 1);
for ( j = 0; j < nPoints; j++ )
{
coords = json_object_array_get_idx( points, j );
parse_geojson_coord(coords, hasz, ppa[i]);
}
- }
-
+ }
+
/* All the rings were empty! */
if ( ! ppa )
return (LWGEOM *)lwpoly_construct_empty(root_srid, 0, 0);
-
+
return (LWGEOM *) lwpoly_construct(root_srid, NULL, nRings, ppa);
}
const int nPolys = json_object_array_length( poObjPolys );
for(i = 0; i < nPolys; ++i)
- {
+ {
json_object* poObjPoly = json_object_array_get_idx( poObjPolys, i );
if( json_type_array == json_object_get_type( poObjPoly ) )
{
LWPOLY *lwpoly = lwpoly_construct_empty(geom->srid, lwgeom_has_z(geom), lwgeom_has_m(geom));
int nRings = json_object_array_length( poObjPoly );
-
+
for(j = 0; j < nRings; ++j)
{
json_object* points = json_object_array_get_idx( poObjPoly, j );
-
+
if( json_type_array == json_object_get_type( points ) )
{
json_object* coords = json_object_array_get_idx( points, k );
parse_geojson_coord(coords, hasz, pa);
}
-
+
lwpoly_add_ring(lwpoly, pa);
}
}
uint8_t *buf = NULL;
register uint8_t h1, h2;
int i;
-
+
if( hexsize % 2 )
lwerror("Invalid hex string, length (%d) has to be a multiple of two!", hexsize);
buf = lwalloc(hexsize/2);
-
+
if( ! buf )
lwerror("Unable to allocate memory buffer.");
-
+
for( i = 0; i < hexsize/2; i++ )
{
h1 = hex2char[(int)hexbuf[2*i]];
static void lwtype_from_wkb_state(wkb_parse_state *s, uint32_t wkb_type)
{
uint32_t wkb_simple_type;
-
+
LWDEBUG(4, "Entered function");
-
+
s->has_z = LW_FALSE;
s->has_m = LW_FALSE;
s->has_srid = LW_FALSE;
if( wkb_type & WKBSRIDFLAG ) s->has_srid = LW_TRUE;
LWDEBUGF(4, "Extended type: has_z=%d has_m=%d has_srid=%d", s->has_z, s->has_m, s->has_srid);
}
-
+
/* Mask off the flags */
wkb_type = wkb_type & 0x0FFFFFFF;
/* Strip out just the type number (1-12) from the ISO number (eg 3001-3012) */
wkb_simple_type = wkb_type % 1000;
-
+
/* Extract the Z/M information from ISO style numbers */
if( wkb_type >= 3000 && wkb_type < 4000 )
{
case WKB_TRIANGLE_TYPE:
s->lwtype = TRIANGLETYPE;
break;
-
+
/* PostGIS 1.5 emits 13, 14 for CurvePolygon, MultiCurve */
/* These numbers aren't SQL/MM (numbers currently only */
/* go up to 12. We can handle the old data here (for now??) */
case WKB_SURFACE_TYPE:
s->lwtype = MULTICURVETYPE;
break;
-
+
default: /* Error! */
lwerror("Unknown WKB type (%d)! Full WKB type number was (%d).", wkb_simple_type, wkb_type);
- break;
+ break;
}
LWDEBUGF(4,"Got lwtype %s (%u)", lwtype_name(s->lwtype), s->lwtype);
wkb_parse_state_check(s, WKB_BYTE_SIZE);
LWDEBUG(4, "Passed state check");
-
+
char_value = s->pos[0];
LWDEBUGF(4, "Read byte value: %x", char_value);
s->pos += WKB_BYTE_SIZE;
-
+
return char_value;
}
uint32_t i = 0;
wkb_parse_state_check(s, WKB_INT_SIZE);
-
+
memcpy(&i, s->pos, WKB_INT_SIZE);
-
+
/* Swap? Copy into a stack-allocated integer. */
if( s->swap_bytes )
{
int j = 0;
uint8_t tmp;
-
+
for( j = 0; j < WKB_INT_SIZE/2; j++ )
{
tmp = ((uint8_t*)(&i))[j];
{
int i = 0;
uint8_t tmp;
-
+
for( i = 0; i < WKB_DOUBLE_SIZE/2; i++ )
{
tmp = ((uint8_t*)(&d))[i];
/* Does the data we want to read exist? */
wkb_parse_state_check(s, pa_size);
-
+
/* If we're in a native endianness, we can just copy the data directly! */
if( ! s->swap_bytes )
{
dlist[i] = double_from_wkb_state(s);
}
}
-
+
/* Check for POINT(NaN NaN) ==> POINT EMPTY */
pt = getPoint2d_cp(pa, 0);
if ( isnan(pt->x) && isnan(pt->y) )
return NULL;
}
- return lwcircstring_construct(s->srid, NULL, pa);
+ return lwcircstring_construct(s->srid, NULL, pa);
}
/**
LWPOLY *poly = lwpoly_construct_empty(s->srid, s->has_z, s->has_m);
LWDEBUGF(4,"Polygon has %d rings", nrings);
-
+
/* Empty polygon? */
if( nrings == 0 )
return poly;
lwerror("%s must have closed rings", lwtype_name(s->lwtype));
return NULL;
}
-
+
/* Add ring to polygon */
if ( lwpoly_add_ring(poly, pa) == LW_FAILURE )
{
if ( nrings != 1 )
lwerror("Triangle has wrong number of rings: %d", nrings);
- /* There's only one ring, we hope? */
+ /* There's only one ring, we hope? */
pa = ptarray_from_wkb_state(s);
/* If there's no points, return an empty triangle. */
/* Empty TRIANGLE starts w/ empty POINTARRAY, free it first */
if (tri->points)
ptarray_free(tri->points);
-
- tri->points = pa;
+
+ tri->points = pa;
return tri;
}
LWCURVEPOLY *cp = lwcurvepoly_construct_empty(s->srid, s->has_z, s->has_m);
LWGEOM *geom = NULL;
int i;
-
+
/* Empty collection? */
if ( ngeoms == 0 )
return cp;
if ( lwcurvepoly_add_ring(cp, geom) == LW_FAILURE )
lwerror("Unable to add geometry (%p) to curvepoly (%p)", geom, cp);
}
-
+
return cp;
}
int i;
LWDEBUGF(4,"Collection has %d components", ngeoms);
-
+
/* Empty collection? */
if ( ngeoms == 0 )
return col;
return NULL;
}
}
-
+
return col;
}
{
char wkb_little_endian;
uint32_t wkb_type;
-
+
LWDEBUG(4,"Entered function");
-
+
/* Fail when handed incorrect starting byte */
wkb_little_endian = byte_from_wkb_state(s);
if( wkb_little_endian != 1 && wkb_little_endian != 0 )
wkb_type = integer_from_wkb_state(s);
LWDEBUGF(4,"Got WKB type number: 0x%X", wkb_type);
lwtype_from_wkb_state(s, wkb_type);
-
+
/* Read the SRID, if necessary */
if( s->has_srid )
{
/* TODO: warn on explicit UNKNOWN srid ? */
LWDEBUGF(4,"Got SRID: %u", s->srid);
}
-
+
/* Do the right thing */
switch( s->lwtype )
{
/* Return value to keep compiler happy. */
return NULL;
-
+
}
/* TODO add check for SRID consistency */
LWGEOM* lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
{
wkb_parse_state s;
-
+
/* Initialize the state appropriately */
s.wkb = wkb;
s.wkb_size = wkb_size;
s.has_m = LW_FALSE;
s.has_srid = LW_FALSE;
s.pos = wkb;
-
+
/* Hand the check catch-all values */
if ( check & LW_PARSER_CHECK_NONE )
s.check = 0;
int hexwkb_len;
uint8_t *wkb;
LWGEOM *lwgeom;
-
- if ( ! hexwkb )
+
+ if ( ! hexwkb )
{
lwerror("lwgeom_from_hexwkb: null input");
return NULL;
}
-
+
hexwkb_len = strlen(hexwkb);
wkb = bytes_from_hexbytes(hexwkb, hexwkb_len);
lwgeom = lwgeom_from_wkb(wkb, hexwkb_len/2, check);
lwfree(wkb);
- return lwgeom;
+ return lwgeom;
}
global_parser_result.errcode = (errno); \
global_parser_result.errlocation = wkt_yylloc.last_column; \
}
-
+
/**
* Read the SRID number from an SRID=<> string
*/
{
int i = 0;
uint8_t flags = 0;
-
+
if( ! dimensionality )
return flags;
-
+
/* If there's an explicit dimensionality, we use that */
for( i = 0; i < strlen(dimensionality); i++ )
{
int hasz = FLAGS_GET_Z(flags);
int hasm = FLAGS_GET_M(flags);
int i = 0;
-
+
/* Error on junk */
if( ! geom )
return LW_FAILURE;
FLAGS_SET_Z(geom->flags, hasz);
FLAGS_SET_M(geom->flags, hasm);
-
+
switch( geom->type )
{
case POINTTYPE:
{
LWCOLLECTION *col = (LWCOLLECTION*)geom;
for ( i = 0; i < col->ngeoms; i++ )
- wkt_parser_set_dims(col->geoms[i], flags);
+ wkt_parser_set_dims(col->geoms[i], flags);
return LW_SUCCESS;
}
else
}
}
- return LW_SUCCESS;
+ return LW_SUCCESS;
}
/**
* match, ensure the pointarray is using the right "Z" or "M".
*/
static int wkt_pointarray_dimensionality(POINTARRAY *pa, uint8_t flags)
-{
+{
int hasz = FLAGS_GET_Z(flags);
int hasm = FLAGS_GET_M(flags);
int ndims = 2 + hasz + hasm;
/* No dimensionality or array means we go with what we have */
if( ! (flags && pa) )
return LW_TRUE;
-
+
LWDEBUGF(5,"dimensionality ndims == %d", ndims);
LWDEBUGF(5,"FLAGS_NDIMS(pa->flags) == %d", FLAGS_NDIMS(pa->flags));
-
+
/*
* ndims > 2 implies that the flags have something useful to add,
* that there is a 'Z' or an 'M' or both.
{
POINT4D pt;
LWDEBUG(4,"entered");
-
+
/* Error on trouble */
if( ! pa )
{
SET_PARSER_ERROR(PARSER_ERROR_OTHER);
- return NULL;
+ return NULL;
}
-
+
/* Check that the coordinate has the same dimesionality as the array */
if( FLAGS_NDIMS(p.flags) != FLAGS_NDIMS(pa->flags) )
{
SET_PARSER_ERROR(PARSER_ERROR_MIXDIMS);
return NULL;
}
-
+
/* While parsing the point arrays, XYM and XMZ points are both treated as XYZ */
pt.x = p.x;
pt.y = p.y;
/* If the destination is XYM, we'll write the third coordinate to m */
if( FLAGS_GET_M(pa->flags) && ! FLAGS_GET_Z(pa->flags) )
pt.m = p.z;
-
+
ptarray_append_point(pa, &pt, LW_TRUE); /* Allow duplicate points in array */
return pa;
}
{
uint8_t flags = wkt_dimensionality(dimensionality);
LWDEBUG(4,"entered");
-
+
/* No pointarray means it is empty */
if( ! pa )
return lwpoint_as_lwgeom(lwpoint_construct_empty(SRID_UNKNOWN, FLAGS_GET_Z(flags), FLAGS_GET_M(flags)));
return NULL;
}
- /* Only one point allowed in our point array! */
+ /* Only one point allowed in our point array! */
if( pa->npoints != 1 )
{
ptarray_free(pa);
SET_PARSER_ERROR(PARSER_ERROR_LESSPOINTS);
return NULL;
- }
+ }
return lwpoint_as_lwgeom(lwpoint_construct(SRID_UNKNOWN, NULL, pa));
}
SET_PARSER_ERROR(PARSER_ERROR_MIXDIMS);
return NULL;
}
-
- /* Apply check for not enough points, if requested. */
+
+ /* Apply check for not enough points, if requested. */
if( (global_parser_result.parser_check_flags & LW_PARSER_CHECK_MINPOINTS) && (pa->npoints < 2) )
{
ptarray_free(pa);
SET_PARSER_ERROR(PARSER_ERROR_MIXDIMS);
return NULL;
}
-
- /* Apply check for not enough points, if requested. */
+
+ /* Apply check for not enough points, if requested. */
if( (global_parser_result.parser_check_flags & LW_PARSER_CHECK_MINPOINTS) && (pa->npoints < 3) )
{
ptarray_free(pa);
SET_PARSER_ERROR(PARSER_ERROR_MOREPOINTS);
return NULL;
- }
+ }
- /* Apply check for odd number of points, if requested. */
+ /* Apply check for odd number of points, if requested. */
if( (global_parser_result.parser_check_flags & LW_PARSER_CHECK_ODD) && ((pa->npoints % 2) == 0) )
{
ptarray_free(pa);
SET_PARSER_ERROR(PARSER_ERROR_ODDPOINTS);
return NULL;
}
-
- return lwcircstring_as_lwgeom(lwcircstring_construct(SRID_UNKNOWN, NULL, pa));
+
+ return lwcircstring_as_lwgeom(lwcircstring_construct(SRID_UNKNOWN, NULL, pa));
}
LWGEOM* wkt_parser_triangle_new(POINTARRAY *pa, char *dimensionality)
return NULL;
}
- /* Triangles need four points. */
+ /* Triangles need four points. */
if( (pa->npoints != 4) )
{
ptarray_free(pa);
SET_PARSER_ERROR(PARSER_ERROR_TRIANGLEPOINTS);
return NULL;
- }
-
- /* Triangles need closure. */
+ }
+
+ /* Triangles need closure. */
if( ! ptarray_is_closed(pa) )
{
ptarray_free(pa);
SET_PARSER_ERROR(PARSER_ERROR_UNCLOSED);
return NULL;
- }
+ }
return lwtriangle_as_lwgeom(lwtriangle_construct(SRID_UNKNOWN, NULL, pa));
}
{
LWPOLY *poly = NULL;
LWDEBUG(4,"entered");
-
+
/* No pointarray is a problem */
if( ! pa )
{
SET_PARSER_ERROR(PARSER_ERROR_OTHER);
- return NULL;
+ return NULL;
}
poly = lwpoly_construct_empty(SRID_UNKNOWN, FLAGS_GET_Z(pa->flags), FLAGS_GET_M(pa->flags));
-
+
/* Error out if we can't build this polygon. */
if( ! poly )
{
SET_PARSER_ERROR(PARSER_ERROR_OTHER);
return NULL;
}
-
- wkt_parser_polygon_add_ring(lwpoly_as_lwgeom(poly), pa, dimcheck);
+
+ wkt_parser_polygon_add_ring(lwpoly_as_lwgeom(poly), pa, dimcheck);
return lwpoly_as_lwgeom(poly);
}
if( ! (pa && poly) )
{
SET_PARSER_ERROR(PARSER_ERROR_OTHER);
- return NULL;
+ return NULL;
}
/* Rings must agree on dimensionality */
return NULL;
}
- /* Apply check for minimum number of points, if requested. */
+ /* Apply check for minimum number of points, if requested. */
if( (global_parser_result.parser_check_flags & LW_PARSER_CHECK_MINPOINTS) && (pa->npoints < 4) )
{
ptarray_free(pa);
SET_PARSER_ERROR(PARSER_ERROR_MOREPOINTS);
return NULL;
}
-
- /* Apply check for not closed rings, if requested. */
+
+ /* Apply check for not closed rings, if requested. */
if( (global_parser_result.parser_check_flags & LW_PARSER_CHECK_CLOSURE) &&
! (dimcheck == 'Z' ? ptarray_is_closed_z(pa) : ptarray_is_closed_2d(pa)) )
{
ptarray_free(pa);
lwgeom_free(poly);
SET_PARSER_ERROR(PARSER_ERROR_OTHER);
- return NULL;
+ return NULL;
}
return poly;
}
uint8_t flags = wkt_dimensionality(dimensionality);
int flagdims = FLAGS_NDIMS(flags);
LWDEBUG(4,"entered");
-
+
/* Null input implies empty return */
if( ! poly )
return lwpoly_as_lwgeom(lwpoly_construct_empty(SRID_UNKNOWN, FLAGS_GET_Z(flags), FLAGS_GET_M(flags)));
SET_PARSER_ERROR(PARSER_ERROR_MIXDIMS);
return NULL;
}
-
+
/* Harmonize the flags in the sub-components with the wkt flags */
if( LW_FAILURE == wkt_parser_set_dims(poly, flags) )
{
return NULL;
}
}
-
+
return poly;
}
LWGEOM* wkt_parser_curvepolygon_new(LWGEOM *ring)
{
- LWGEOM *poly;
+ LWGEOM *poly;
LWDEBUG(4,"entered");
/* Toss error on null geometry input */
SET_PARSER_ERROR(PARSER_ERROR_OTHER);
return NULL;
}
-
+
/* Construct poly and add the ring. */
poly = lwcurvepoly_as_lwgeom(lwcurvepoly_construct_empty(SRID_UNKNOWN, FLAGS_GET_Z(ring->flags), FLAGS_GET_M(ring->flags)));
/* Return the result. */
LWDEBUG(4,"inputs are null");
return NULL;
}
-
+
/* All the elements must agree on dimensionality */
if( FLAGS_NDIMS(poly->flags) != FLAGS_NDIMS(ring->flags) )
{
SET_PARSER_ERROR(PARSER_ERROR_MIXDIMS);
return NULL;
}
-
- /* Apply check for minimum number of points, if requested. */
+
+ /* Apply check for minimum number of points, if requested. */
if( (global_parser_result.parser_check_flags & LW_PARSER_CHECK_MINPOINTS) )
{
int vertices_needed = 3;
if ( ring->type == LINETYPE )
vertices_needed = 4;
-
+
if (lwgeom_count_vertices(ring) < vertices_needed)
{
LWDEBUG(4,"number of points is incorrect");
lwgeom_free(poly);
SET_PARSER_ERROR(PARSER_ERROR_MOREPOINTS);
return NULL;
- }
+ }
}
-
- /* Apply check for not closed rings, if requested. */
+
+ /* Apply check for not closed rings, if requested. */
if( (global_parser_result.parser_check_flags & LW_PARSER_CHECK_CLOSURE) )
{
int is_closed = 1;
case LINETYPE:
is_closed = lwline_is_closed(lwgeom_as_lwline(ring));
break;
-
+
case CIRCSTRINGTYPE:
is_closed = lwcircstring_is_closed(lwgeom_as_lwcircstring(ring));
break;
-
+
case COMPOUNDTYPE:
is_closed = lwcompound_is_closed(lwgeom_as_lwcompound(ring));
break;
return NULL;
}
}
-
+
if( LW_FAILURE == lwcurvepoly_add_ring(lwgeom_as_lwcurvepoly(poly), ring) )
{
LWDEBUG(4,"failed to add ring");
SET_PARSER_ERROR(PARSER_ERROR_OTHER);
return NULL;
}
-
+
return poly;
}
uint8_t flags = wkt_dimensionality(dimensionality);
int flagdims = FLAGS_NDIMS(flags);
LWDEBUG(4,"entered");
-
+
/* Null input implies empty return */
if( ! poly )
return lwcurvepoly_as_lwgeom(lwcurvepoly_construct_empty(SRID_UNKNOWN, FLAGS_GET_Z(flags), FLAGS_GET_M(flags)));
return NULL;
}
}
-
+
return poly;
}
LWGEOM **geoms;
static int ngeoms = 1;
LWDEBUG(4,"entered");
-
+
/* Toss error on null geometry input */
if( ! geom )
{
SET_PARSER_ERROR(PARSER_ERROR_OTHER);
return NULL;
}
-
+
/* Create our geometry array */
geoms = lwalloc(sizeof(LWGEOM*) * ngeoms);
geoms[0] = geom;
-
+
/* Make a new collection */
col = lwcollection_construct(COLLECTIONTYPE, SRID_UNKNOWN, NULL, ngeoms, geoms);
LWGEOM **geoms;
static int ngeoms = 1;
LWDEBUG(4,"entered");
-
+
/* Toss error on null geometry input */
if( ! geom )
{
SET_PARSER_ERROR(PARSER_ERROR_OTHER);
return NULL;
}
-
+
/* Elements of a compoundcurve cannot be empty, because */
/* empty things can't join up and form a ring */
if ( lwgeom_is_empty(geom) )
{
lwgeom_free(geom);
SET_PARSER_ERROR(PARSER_ERROR_INCONTINUOUS);
- return NULL;
+ return NULL;
}
-
+
/* Create our geometry array */
geoms = lwalloc(sizeof(LWGEOM*) * ngeoms);
geoms[0] = geom;
-
+
/* Make a new collection */
col = lwcollection_construct(COLLECTIONTYPE, SRID_UNKNOWN, NULL, ngeoms, geoms);
SET_PARSER_ERROR(PARSER_ERROR_MIXDIMS);
return NULL;
}
-
+
if( LW_FAILURE == lwcompound_add_lwgeom((LWCOMPOUND*)col, geom) )
{
lwgeom_free(col);
SET_PARSER_ERROR(PARSER_ERROR_INCONTINUOUS);
return NULL;
}
-
+
return col;
}
SET_PARSER_ERROR(PARSER_ERROR_OTHER);
return NULL;
}
-
+
return lwcollection_as_lwgeom(lwcollection_add_lwgeom(lwgeom_as_lwcollection(col), geom));
}
{
uint8_t flags = wkt_dimensionality(dimensionality);
int flagdims = FLAGS_NDIMS(flags);
-
+
/* No geometry means it is empty */
if( ! geom )
{
{
LWCOLLECTION *col = lwgeom_as_lwcollection(geom);
int i;
-
+
for ( i = 0 ; i < col->ngeoms; i++ )
{
LWGEOM *subgeom = col->geoms[i];
SET_PARSER_ERROR(PARSER_ERROR_MIXDIMS);
return NULL;
}
-
+
if ( lwtype == COLLECTIONTYPE &&
( (FLAGS_GET_Z(flags) != FLAGS_GET_Z(subgeom->flags)) ||
(FLAGS_GET_M(flags) != FLAGS_GET_M(subgeom->flags)) ) &&
return NULL;
}
}
-
+
/* Harmonize the collection dimensionality */
if( LW_FAILURE == wkt_parser_set_dims(geom, flags) )
{
return NULL;
}
}
-
+
/* Set the collection type */
geom->type = lwtype;
-
+
return geom;
}
lwerror("Parsed geometry is null!");
return;
}
-
+
if ( srid != SRID_UNKNOWN && srid < SRID_MAXIMUM )
lwgeom_set_srid(geom, srid);
else
lwgeom_set_srid(geom, SRID_UNKNOWN);
-
+
global_parser_result.geom = geom;
}
lwerror(r.message);
return NULL;
}
-
- return r.geom;
+
+ return r.geom;
}
);
if ( ! (yy_buffer_stack) )
YY_FATAL_ERROR( "out of dynamic memory in wkt_yyensure_buffer_stack()" );
-
+
memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-
+
(yy_buffer_stack_max) = num_to_alloc;
(yy_buffer_stack_top) = 0;
return;
/* Set the input text string, and parse checks. */
global_parser_result.wkinput = wktstr;
global_parser_result.parser_check_flags = parser_check_flags;
-
+
wkt_lexer_init(wktstr); /* Lexer ready */
parse_rv = wkt_yyparse(); /* Run the parse */
LWDEBUGF(4,"wkt_yyparse returned %d", parse_rv);
wkt_lexer_close(); /* Clean up lexer */
-
+
/* A non-zero parser return is an error. */
if ( parse_rv != 0 )
{
global_parser_result.errlocation,
global_parser_result.errcode,
global_parser_result.message);
-
+
/* Copy the global values into the return pointer */
*parser_result = global_parser_result;
wkt_yylex_destroy();
return LW_FAILURE;
}
-
+
/* Copy the global value into the return pointer */
*parser_result = global_parser_result;
wkt_yylex_destroy();
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__);
/* 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?");
LWDEBUG(2, "lwline_construct called.");
result->type = LINETYPE;
-
+
result->flags = points->flags;
FLAGS_SET_BBOX(result->flags, bbox?1:0);
void lwline_free (LWLINE *line)
{
if ( ! line ) return;
-
+
if ( line->bbox )
lwfree(line->bbox);
if ( line->points )
* ngeoms should be a guess about how many points we have in input.
* It's an underestimate for lines and multipoints */
pa = ptarray_construct_empty(hasz, hasm, ngeoms);
-
+
for ( i=0; i < ngeoms; i++ )
{
LWGEOM *g = geoms[i];
ptarray_free(pa);
line = lwline_construct_empty(srid, hasz, hasm);
}
-
+
return line;
}
}
pa = ptarray_construct_empty(hasz, hasm, npoints);
-
+
for ( i=0; i < npoints; i++ )
{
if ( ! lwpoint_is_empty(points[i]) )
line = lwline_construct(srid, NULL, pa);
else
line = lwline_construct_empty(srid, hasz, hasm);
-
+
return line;
}
getPoint4d_p(mpoint->geoms[i]->point, 0, &pt);
ptarray_set_point4d(pa, i, &pt);
}
-
+
LWDEBUGF(3, "lwline_from_lwmpoint: constructed pointarray for %d points", mpoint->ngeoms);
return lwline_construct(srid, NULL, pa);
int
lwline_add_lwpoint(LWLINE *line, LWPOINT *point, int where)
{
- POINT4D pt;
+ POINT4D pt;
getPoint4d_p(point->point, 0, &pt);
if ( ptarray_insert_point(line->points, &pt, where) != LW_SUCCESS )
lwgeom_drop_bbox(lwline_as_lwgeom(line));
lwgeom_add_bbox(lwline_as_lwgeom(line));
}
-
+
return LW_SUCCESS;
}
{
POINTARRAY *pdims = NULL;
LWLINE *lineout;
-
+
/* Return 2D empty */
if( lwline_is_empty(line) )
{
lineout = lwline_construct_empty(line->srid, hasz, hasm);
}
else
- {
+ {
pdims = ptarray_force_dims(line->points, hasz, hasm);
lineout = lwline_construct(line->srid, NULL, pdims);
}
if ( preserve_collapsed )
{
POINT4D pt;
- getPoint4d_p(pa, 0, &pt);
+ getPoint4d_p(pa, 0, &pt);
ptarray_append_point(pa, &pt, LW_TRUE);
}
/* Return null for collapse */
{
int i;
if ( ! mline ) return;
-
+
if ( mline->bbox )
lwfree(mline->bbox);
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);
+ getPoint4d_p(pa, i, &p);
lwp = lwpoint_make(srid, hasz, hasm, &p);
lwmpoint_add_lwpoint(ret, lwp);
}
-
+
return ret;
}
int i;
if ( ! mpt ) return;
-
+
if ( mpt->bbox )
lwfree(mpt->bbox);
uint32_t i, j;
LWGEOM **newgeoms;
LWGEOM *lwpt1, *lwpt2;
-
+
newgeoms = lwalloc(sizeof(LWGEOM *)*mpoint->ngeoms);
nnewgeoms = 0;
for (i=0; i<mpoint->ngeoms; ++i)
}
return (LWGEOM*)lwcollection_construct(mpoint->type,
- mpoint->srid,
+ mpoint->srid,
mpoint->bbox ? gbox_copy(mpoint->bbox) : NULL,
nnewgeoms, newgeoms);
the GeoJSON expects a cartesian bounding box */
lwgeom_calculate_gbox_cartesian(geom, &tmp);
bbox = &tmp;
- }
+ }
switch (type)
{
sb = stringbuffer_create();
rv = lwgeom_to_kml2_sb(geom, precision, prefix, sb);
-
+
if ( rv == LW_FAILURE )
{
stringbuffer_destroy(sb);
return NULL;
}
-
+
kml = stringbuffer_getstringcopy(sb);
stringbuffer_destroy(sb);
-
+
return kml;
}
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);
if ( ptarray_to_kml2_sb(line->points, precision, sb) == LW_FAILURE ) return LW_FAILURE;
/* Close linestring */
if ( stringbuffer_aprintf(sb, "</%scoordinates></%sLineString>", prefix, prefix) < 0 ) return LW_FAILURE;
-
+
return LW_SUCCESS;
}
lwpoly_to_kml2_sb(const LWPOLY *poly, int precision, const char *prefix, stringbuffer_t *sb)
{
int i, rv;
-
+
/* Open polygon */
if ( stringbuffer_aprintf(sb, "<%sPolygon>", prefix) < 0 ) return LW_FAILURE;
for ( i = 0; i < poly->nrings; i++ )
if( i )
rv = stringbuffer_aprintf(sb, "<%sinnerBoundaryIs><%sLinearRing><%scoordinates>", prefix, prefix, prefix);
else
- rv = stringbuffer_aprintf(sb, "<%souterBoundaryIs><%sLinearRing><%scoordinates>", prefix, prefix, prefix);
+ rv = stringbuffer_aprintf(sb, "<%souterBoundaryIs><%sLinearRing><%scoordinates>", prefix, prefix, prefix);
if ( rv < 0 ) return LW_FAILURE;
-
+
/* Coordinate array */
if ( ptarray_to_kml2_sb(poly->rings[i], precision, sb) == LW_FAILURE ) return LW_FAILURE;
-
+
/* Inner or outer ring closing tags */
if( i )
rv = stringbuffer_aprintf(sb, "</%scoordinates></%sLinearRing></%sinnerBoundaryIs>", prefix, prefix, prefix);
else
- rv = stringbuffer_aprintf(sb, "</%scoordinates></%sLinearRing></%souterBoundaryIs>", prefix, prefix, prefix);
+ rv = stringbuffer_aprintf(sb, "</%scoordinates></%sLinearRing></%souterBoundaryIs>", prefix, prefix, prefix);
if ( rv < 0 ) return LW_FAILURE;
}
/* Close polygon */
lwcollection_to_kml2_sb(const LWCOLLECTION *col, int precision, const char *prefix, stringbuffer_t *sb)
{
int i, rv;
-
+
/* Open geometry */
if ( stringbuffer_aprintf(sb, "<%sMultiGeometry>", prefix) < 0 ) return LW_FAILURE;
for ( i = 0; i < col->ngeoms; i++ )
{
rv = lwgeom_to_kml2_sb(col->geoms[i], precision, prefix, sb);
- if ( rv == LW_FAILURE ) return LW_FAILURE;
+ if ( rv == LW_FAILURE ) return LW_FAILURE;
}
/* Close geometry */
if ( stringbuffer_aprintf(sb, "</%sMultiGeometry>", prefix) < 0 ) return LW_FAILURE;
ret[0] = '\0';
return ret;
}
-
+
switch (type)
{
case POINTTYPE:
trim_trailing_zeros(sy);
ptr += sprintf(ptr,"%s %s l", sx, sy);
-
+
/* accum */
accum_x = x;
accum_y = y;
// lpt = pt;
pt = getPoint2d_cp(pa, i);
-
+
x = round(pt->x*f)/f;
y = round(pt->y*f)/f;
dx = x - accum_x;
dy = y - accum_y;
-
+
if (fabs(dx) < OUT_MAX_DOUBLE)
sprintf(sx, "%.*f", precision, dx);
else
sprintf(sy, "%g",
fabs(dy) ? dy * -1: dy);
trim_trailing_zeros(sy);
-
+
accum_x += dx;
accum_y += dy;
LWDEBUGF(2, "Entered %s", __func__);
/* Dispense with the empty case right away */
- if ( pa->npoints == 0 && register_npoints )
- {
+ if ( pa->npoints == 0 && register_npoints )
+ {
LWDEBUGF(4, "Register npoints:%d", pa->npoints);
bytebuffer_append_uvarint(ts->geom_buf, pa->npoints);
return 0;
{
/* We give an alias to our ordinary buffer */
b_p = ts->geom_buf;
- if ( register_npoints )
- {
+ if ( register_npoints )
+ {
/* We do not store a pointer to the place where we want the npoints value */
/* Instead we store how far from the beginning of the buffer we want the value */
- /* That is because we otherwise will get in trouble if the buffer is reallocated */
+ /* That is because we otherwise will get in trouble if the buffer is reallocated */
npoints_offset = b_p->writecursor - b_p->buf_start;
-
+
/* We just move the cursor 1 step to make room for npoints byte */
/* We use the function append_byte even if we have no value yet, */
/* since that gives us the check for big enough buffer and moves the cursor */
bytebuffer_append_byte(b_p, 0);
}
}
-
+
for ( i = 0; i < pa->npoints; i++ )
{
double *dbl_ptr = (double*)getPoint_internal(pa, i);
LWDEBUGF(4, "deltavalue: %d, ", nextdelta[j]);
diff += llabs(nextdelta[j]);
}
-
+
/* Skipping the first point is not allowed */
/* If the sum(abs()) of all the deltas was zero, */
/* then this was a duplicate point, so we can ignore it */
if ( i > minpoints && diff == 0 )
continue;
-
+
/* We really added a point, so... */
npoints++;
-
+
/* Write this vertex to the temporary buffer as varints */
for ( j = 0; j < ndims; j++ )
{
}
}
- }
+ }
if ( pa->npoints > 127 )
- {
+ {
/* Now write the temporary results into the main buffer */
/* First the npoints */
- if ( register_npoints )
+ if ( register_npoints )
bytebuffer_append_uvarint(ts->geom_buf, npoints);
/* Now the coordinates */
bytebuffer_append_bytebuffer(ts->geom_buf, b_p);
-
+
/* Clear our temporary buffer */
lwfree(b.buf_start);
}
{
/* If we didn't use a temp buffer, we just write that npoints value */
/* to where it belongs*/
- if ( register_npoints )
+ if ( register_npoints )
varint_u64_encode_buf(npoints, b_p->buf_start + npoints_offset);
}
-
+
return 0;
}
/* Skip empty points in multipoints, we can't represent them */
if ( col->type == MULTIPOINTTYPE && lwgeom_is_empty(col->geoms[i]) )
continue;
-
+
bytebuffer_append_varint(ts->geom_buf, ts->idlist[i]);
}
-
+
/* Empty it out to nobody else uses it now */
ts->idlist = NULL;
}
{
for ( i = 0; i < col->ngeoms; i++ )
bytebuffer_append_varint(ts->geom_buf, ts->idlist[i]);
-
+
/* Empty it out to nobody else uses it now */
ts->idlist = NULL;
}
/* TYPE/PRECISION BYTE */
if ( abs(globals->prec_xy) > 7 )
lwerror("%s: X/Z precision cannot be greater than 7 or less than -7", __func__);
-
+
/* Read the TWKB type number from the geometry */
TYPE_PREC_SET_TYPE(type_prec, lwgeom_twkb_type(geom));
/* Zig-zag the precision value before encoding it since it is a signed value */
parent_state->bbox_max[i] = child_state.bbox_max[i];
}
}
-
+
/* Did we have a box? If so, how big? */
bbox_size = 0;
if( globals->variant & TWKB_BBOX )
memset(&ts, 0, sizeof(TWKB_STATE));
memset(&tg, 0, sizeof(TWKB_GLOBALS));
-
+
tg.variant = variant;
tg.prec_xy = precision_xy;
tg.prec_z = precision_z;
lwerror("Cannot convert NULL into TWKB");
return NULL;
}
-
+
ts.idlist = idlist;
ts.header_buf = NULL;
ts.geom_buf = bytebuffer_create();
We force that behavior with the WKB_NO_SRID flag */
if ( variant & WKB_NO_SRID )
return LW_FALSE;
-
+
/* We can only add an SRID if the geometry has one, and the
- WKB form is extended */
+ WKB form is extended */
if ( (variant & WKB_EXTENDED) && lwgeom_has_srid(geom) )
return LW_TRUE;
-
+
/* Everything else doesn't get an SRID */
return LW_FALSE;
}
if ( geom->type == POINTTYPE )
{
const LWPOINT *pt = (LWPOINT*)geom;
- size += WKB_DOUBLE_SIZE * FLAGS_NDIMS(pt->point->flags);
+ size += WKB_DOUBLE_SIZE * FLAGS_NDIMS(pt->point->flags);
}
/* num-elements */
else
/* Set nrings/npoints/ngeoms to zero */
buf = integer_to_wkb_buf(0, buf, variant);
}
-
+
return buf;
}
/* Set the endian flag */
buf = endian_to_wkb_buf(buf, variant);
-
+
/* Set the geometry type */
buf = integer_to_wkb_buf(lwgeom_wkb_type((LWGEOM*)tri, variant), buf, variant);
-
+
/* Set the optional SRID for extended variant */
if ( lwgeom_wkb_needs_srid((LWGEOM*)tri, variant) )
buf = integer_to_wkb_buf(tri->srid, buf, variant);
/* Set the number of rings (only one, it's a triangle, buddy) */
buf = integer_to_wkb_buf(1, buf, variant);
-
+
/* Write that ring */
buf = ptarray_to_wkb_buf(tri->points, buf, variant);
/* endian flag + type number + number of rings */
size_t size = WKB_BYTE_SIZE + WKB_INT_SIZE + WKB_INT_SIZE;
int i = 0;
-
+
/* Only process empty at this level in the EXTENDED case */
if ( (variant & WKB_EXTENDED) && lwgeom_is_empty((LWGEOM*)poly) )
return empty_to_wkb_size((LWGEOM*)poly, variant);
/* We don't want type strings on our subgeoms */
lwpoly_to_wkt_sb(psurf->geoms[i], sb, precision, variant | WKT_NO_TYPE );
}
- stringbuffer_append(sb, ")");
+ stringbuffer_append(sb, ")");
}
{
if( ! poly || ! pa )
return LW_FAILURE;
-
+
/* We have used up our storage, add some more. */
if( poly->nrings >= poly->maxrings )
{
poly->rings = lwrealloc(poly->rings, new_maxrings * sizeof(POINTARRAY*));
poly->maxrings = new_maxrings;
}
-
+
/* Add the new ring entry. */
poly->rings[poly->nrings] = pa;
poly->nrings++;
-
+
return LW_SUCCESS;
}
lwpoly_force_dims(const LWPOLY *poly, int hasz, int hasm)
{
LWPOLY *polyout;
-
+
/* Return 2D empty */
if( lwpoly_is_empty(poly) )
{
/* and this is a shell, we ensure it is kept */
if ( preserve_collapsed && i == 0 )
minvertices = 4;
-
+
opts = ptarray_simplify(ipoly->rings[i], dist, minvertices);
LWDEBUGF(3, "ring%d simplified from %d to %d points", i, ipoly->rings[i]->npoints, opts->npoints);
{
double poly_area = 0.0;
int i;
-
+
if ( ! poly )
lwerror("lwpoly_area called with null polygon pointer!");
/* Empty or messed-up ring. */
if ( ring->npoints < 3 )
continue;
-
+
ringarea = fabs(ptarray_signed_area(ring));
if ( i == 0 ) /* Outer ring, positive area! */
poly_area += ringarea;
lwpoly_is_closed(const LWPOLY *poly)
{
int i = 0;
-
+
if ( poly->nrings == 0 )
return LW_TRUE;
-
+
for ( i = 0; i < poly->nrings; i++ )
{
if (FLAGS_GET_Z(poly->flags))
return LW_FALSE;
}
else
- {
+ {
if ( ! ptarray_is_closed_2d(poly->rings[i]) )
return LW_FALSE;
}
}
-
+
return LW_TRUE;
}
lwpoly_contains_point(const LWPOLY *poly, const POINT2D *pt)
{
int i;
-
+
if ( lwpoly_is_empty(poly) )
return LW_FALSE;
-
+
if ( ptarray_contains_point(poly->rings[0], pt) == LW_OUTSIDE )
return LW_FALSE;
-
+
for ( i = 1; i < poly->nrings; i++ )
{
if ( ptarray_contains_point(poly->rings[i], pt) == LW_INSIDE )
if ( ri ) continue;
else break; /* this is the external ring, no need to work on holes */
}
-
+
if ( ! lwpoly_add_ring(opoly, newring) )
{
lwerror("lwpoly_grid, memory error");
result->flags = points->flags;
FLAGS_SET_BBOX(result->flags, bbox?1:0);
-
+
result->srid = srid;
result->points = points;
result->bbox = bbox;
void lwtriangle_free(LWTRIANGLE *triangle)
{
if ( ! triangle ) return;
-
+
if (triangle->bbox)
lwfree(triangle->bbox);
-
+
if (triangle->points)
ptarray_free(triangle->points);
-
+
lwfree(triangle);
}
}
}
-static void
+static void
default_errorreporter(const char *fmt, va_list ap)
{
char msg[LW_MSG_MAXLEN+1];
v->x=p2->x-p1->x;
v->y=p2->y-p1->y;
v->z=p2->z-p1->z;
-
+
return LW_TRUE;
}
static
LWGEOM* create_v_line(const LWGEOM *lwgeom,double x, double y, int srid)
{
-
+
LWPOINT *lwpoints[2];
GBOX gbox;
int rv = lwgeom_calculate_gbox(lwgeom, &gbox);
-
+
if ( rv == LW_FAILURE )
return NULL;
-
+
lwpoints[0] = lwpoint_make3dz(srid, x, y, gbox.zmin);
lwpoints[1] = lwpoint_make3dz(srid, x, y, gbox.zmax);
-
- return (LWGEOM *)lwline_from_ptarray(srid, 2, lwpoints);
+
+ return (LWGEOM *)lwline_from_ptarray(srid, 2, lwpoints);
}
LWGEOM *
/*as an infinite z-value at one or two of the geometries*/
if(!lwgeom_has_z(lw1) || !lwgeom_has_z(lw2))
{
-
+
lwnotice("One or both of the geometries is missing z-value. The unknown z-value will be regarded as \"any value\"");
-
+
if(!lwgeom_has_z(lw1) && !lwgeom_has_z(lw2))
- return lw_dist2d_distanceline(lw1, lw2, srid, mode);
-
+ return lw_dist2d_distanceline(lw1, lw2, srid, mode);
+
DISTPTS thedl2d;
thedl2d.mode = mode;
thedl2d.distance = initdistance;
lwfree(vertical_line);
lwerror("Some unspecified error.");
result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0);
- }
- lwfree(vertical_line);
- }
+ }
+ lwfree(vertical_line);
+ }
if(!lwgeom_has_z(lw2))
{
x=thedl2d.p2.x;
- y=thedl2d.p2.y;
-
+ y=thedl2d.p2.y;
+
vertical_line = create_v_line(lw1,x,y,srid);
if (!lw_dist3d_recursive(lw1, vertical_line, &thedl))
{
lwfree(vertical_line);
lwerror("Some unspecified error.");
return (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0);
- }
- lwfree(vertical_line);
- }
-
+ }
+ lwfree(vertical_line);
+ }
+
}
else
- {
+ {
if (!lw_dist3d_recursive(lw1, lw2, &thedl))
{
/*should never get here. all cases ought to be error handled earlier*/
LWGEOM *
lw_dist3d_distancepoint(const LWGEOM *lw1, const LWGEOM *lw2, int srid, int mode)
{
-
+
double x,y,z;
DISTPTS3D thedl;
double initdistance = FLT_MAX;
thedl.tolerance = 0;
LWDEBUG(2, "lw_dist3d_distancepoint is called");
-
+
/*Check if we really have 3D geoemtries*/
/*If not, send it to 2D-calculations which will give the same result*/
/*as an infinite z-value at one or two of the geometries*/
if(!lwgeom_has_z(lw1) || !lwgeom_has_z(lw2))
- {
+ {
lwnotice("One or both of the geometries is missing z-value. The unknown z-value will be regarded as \"any value\"");
-
+
if(!lwgeom_has_z(lw1) && !lwgeom_has_z(lw2))
return lw_dist2d_distancepoint(lw1, lw2, srid, mode);
-
-
+
+
DISTPTS thedl2d;
thedl2d.mode = mode;
thedl2d.distance = initdistance;
lwerror("Some unspecified error.");
return (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0);
}
-
+
LWGEOM *vertical_line;
if(!lwgeom_has_z(lw1))
{
x=thedl2d.p1.x;
y=thedl2d.p1.y;
-
- vertical_line = create_v_line(lw2,x,y,srid);
+
+ vertical_line = create_v_line(lw2,x,y,srid);
if (!lw_dist3d_recursive(vertical_line, lw2, &thedl))
{
/*should never get here. all cases ought to be error handled earlier*/
- lwfree(vertical_line);
+ lwfree(vertical_line);
lwerror("Some unspecified error.");
return (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0);
- }
- lwfree(vertical_line);
- }
-
+ }
+ lwfree(vertical_line);
+ }
+
if(!lwgeom_has_z(lw2))
{
x=thedl2d.p2.x;
if (!lw_dist3d_recursive(lw1, vertical_line, &thedl))
{
/*should never get here. all cases ought to be error handled earlier*/
- lwfree(vertical_line);
+ lwfree(vertical_line);
lwerror("Some unspecified error.");
result = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, srid, 0, 0);
- }
- lwfree(vertical_line);
- }
-
+ }
+ lwfree(vertical_line);
+ }
+
}
else
{
if(!lwgeom_has_z(lw1) || !lwgeom_has_z(lw2))
{
lwnotice("One or both of the geometries is missing z-value. The unknown z-value will be regarded as \"any value\"");
- return lwgeom_maxdistance2d_tolerance(lw1, lw2, tolerance);
+ return lwgeom_maxdistance2d_tolerance(lw1, lw2, tolerance);
}
/*double thedist;*/
DISTPTS3D thedl;
if(!lwgeom_has_z(lw1) || !lwgeom_has_z(lw2))
{
lwnotice("One or both of the geometries is missing z-value. The unknown z-value will be regarded as \"any value\"");
-
- return lwgeom_mindistance2d_tolerance(lw1, lw2, tolerance);
+
+ return lwgeom_mindistance2d_tolerance(lw1, lw2, tolerance);
}
DISTPTS3D thedl;
LWDEBUG(2, "lwgeom_mindistance3d_tolerance is called");
PLANE3D plane;
LWDEBUG(2, "lw_dist3d_point_poly is called");
getPoint3dz_p(point->point, 0, &p);
-
+
/*If we are lookig for max distance, longestline or dfullywithin*/
if (dl->mode == DIST_MAX)
{
LWDEBUG(3, "looking for maxdistance");
return lw_dist3d_pt_ptarray(&p, poly->rings[0], dl);
}
-
+
/*Find the plane of the polygon, the "holes" have to be on the same plane. so we only care about the boudary*/
if(!define_plane(poly->rings[0], &plane))
return LW_FALSE;
-
+
/*get our point projected on the plane of the polygon*/
project_point_on_plane(&p, &plane, &projp);
-
+
return lw_dist3d_pt_poly(&p, poly,&plane, &projp, dl);
}
*/
int lw_dist3d_line_poly(LWLINE *line, LWPOLY *poly, DISTPTS3D *dl)
{
- PLANE3D plane;
- LWDEBUG(2, "lw_dist3d_line_poly is called");
-
+ PLANE3D plane;
+ LWDEBUG(2, "lw_dist3d_line_poly is called");
+
if (dl->mode == DIST_MAX)
{
return lw_dist3d_ptarray_ptarray(line->points, poly->rings[0], dl);
}
-
+
if(!define_plane(poly->rings[0], &plane))
return LW_FALSE;
-
+
return lw_dist3d_ptarray_poly(line->points, poly,&plane, dl);
}
polygon to polygon calculation
*/
int lw_dist3d_poly_poly(LWPOLY *poly1, LWPOLY *poly2, DISTPTS3D *dl)
-{
- PLANE3D plane;
+{
+ PLANE3D plane;
LWDEBUG(2, "lw_dist3d_poly_poly is called");
if (dl->mode == DIST_MAX)
{
return lw_dist3d_ptarray_ptarray(poly1->rings[0], poly2->rings[0], dl);
}
-
+
if(!define_plane(poly2->rings[0], &plane))
return LW_FALSE;
-
+
/*What we do here is to compare the bondary of one polygon with the other polygon
and then take the second boudary comparing with the first polygon*/
dl->twisted=1;
return LW_FALSE;
if(dl->distance==0.0) /*Just check if the answer already is given*/
return LW_TRUE;
-
+
if(!define_plane(poly1->rings[0], &plane))
return LW_FALSE;
dl->twisted=-1; /*because we swithc the order of geometries we swithch "twisted" to -1 which will give the right order of points in shortest line.*/
double s1k, s2k; /*two variables representing where on Line 1 (s1k) and where on Line 2 (s2k) a connecting line between the two lines is perpendicular to both lines*/
POINT3DZ p1, p2;
double a, b, c, d, e, D;
-
+
/*s1p1 and s1p2 are the same point */
if ( ( s1p1->x == s1p2->x) && (s1p1->y == s1p2->y) && (s1p1->z == s1p2->z) )
{
dl->twisted= ((dl->twisted) * (-1));
return lw_dist3d_pt_seg(s2p1,s1p1,s1p2,dl);
}
-
+
/*
Here we use algorithm from softsurfer.com
that can be found here
http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm
*/
-
+
if (!get_3dvector_from_points(s1p1, s1p2, &v1))
- return LW_FALSE;
+ return LW_FALSE;
if (!get_3dvector_from_points(s2p1, s2p2, &v2))
- return LW_FALSE;
+ return LW_FALSE;
if (!get_3dvector_from_points(s2p1, s1p1, &vl))
- return LW_FALSE;
+ return LW_FALSE;
a = DOT(v1,v1);
b = DOT(v1,v2);
*/
int
lw_dist3d_pt_poly(POINT3DZ *p, LWPOLY *poly, PLANE3D *plane,POINT3DZ *projp, DISTPTS3D *dl)
-{
+{
int i;
-
+
LWDEBUG(2, "lw_dist3d_point_poly called");
-
+
if(pt_in_ring_3d(projp, poly->rings[0], plane))
{
for (i=1; i<poly->nrings; i++)
LWDEBUG(3, " inside an hole");
return lw_dist3d_pt_ptarray(p, poly->rings[i], dl);
}
- }
-
+ }
+
return lw_dist3d_pt_pt(p,projp,dl);/* If the projected point is inside the polygon the shortest distance is between that point and the inputed point*/
}
else
{
return lw_dist3d_pt_ptarray(p, poly->rings[0], dl); /*If the projected point is outside the polygon we search for the closest distance against the boundarry instead*/
- }
-
+ }
+
return LW_TRUE;
-
+
}
/**
*/
int lw_dist3d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly,PLANE3D *plane, DISTPTS3D *dl)
{
-
+
int i,j,k;
double f, s1, s2;
VECTOR3D projp1_projp2;
POINT3DZ p1, p2,projp1, projp2, intersectionp;
-
+
getPoint3dz_p(pa, 0, &p1);
-
+
s1=project_point_on_plane(&p1, plane, &projp1); /*the sign of s1 tells us on which side of the plane the point is. */
- lw_dist3d_pt_poly(&p1, poly, plane,&projp1, dl);
-
+ lw_dist3d_pt_poly(&p1, poly, plane,&projp1, dl);
+
for (i=1;i<pa->npoints;i++)
- {
+ {
int intersects;
getPoint3dz_p(pa, i, &p2);
- s2=project_point_on_plane(&p2, plane, &projp2);
+ s2=project_point_on_plane(&p2, plane, &projp2);
lw_dist3d_pt_poly(&p2, poly, plane,&projp2, dl);
-
+
/*If s1and s2 has different signs that means they are on different sides of the plane of the polygon.
That means that the edge between the points crosses the plane and might intersect with the polygon*/
if((s1*s2)<=0)
{
f=fabs(s1)/(fabs(s1)+fabs(s2)); /*The size of s1 and s2 is the distance from the point to the plane.*/
get_3dvector_from_points(&projp1, &projp2,&projp1_projp2);
-
+
/*get the point where the line segment crosses the plane*/
intersectionp.x=projp1.x+f*projp1_projp2.x;
intersectionp.y=projp1.y+f*projp1_projp2.y;
intersectionp.z=projp1.z+f*projp1_projp2.z;
-
+
intersects = LW_TRUE; /*We set intersects to true until the opposite is proved*/
-
+
if(pt_in_ring_3d(&intersectionp, poly->rings[0], plane)) /*Inside outer ring*/
{
for (k=1;k<poly->nrings; k++)
intersects=LW_FALSE;
break;
}
- }
+ }
if(intersects)
{
dl->distance=0.0;
dl->p1.x=intersectionp.x;
dl->p1.y=intersectionp.y;
dl->p1.z=intersectionp.z;
-
+
dl->p2.x=intersectionp.x;
dl->p2.y=intersectionp.y;
dl->p2.z=intersectionp.z;
return LW_TRUE;
-
- }
- }
+
+ }
+ }
}
-
+
projp1=projp2;
s1=s2;
p1=p2;
- }
-
+ }
+
/*check or pointarray against boundary and inner boundaries of the polygon*/
for (j=0;j<poly->nrings;j++)
{
lw_dist3d_ptarray_ptarray(pa, poly->rings[j], dl);
}
-
+
return LW_TRUE;
-}
+}
/**
double vl; /*vector length*/
VECTOR3D v1, v2, v;
-
+
if((pa->npoints-1)==3) /*Triangle is special case*/
{
- pointsinslice=1;
+ pointsinslice=1;
}
else
{
pointsinslice=(int) floor((pa->npoints-1)/4); /*divide the pointarray into 4 slices*/
}
-
+
/*find the avg point*/
for (i=0;i<(pa->npoints-1);i++)
{
getPoint3dz_p(pa, i, &p);
sumx+=p.x;
sumy+=p.y;
- sumz+=p.z;
- }
+ sumz+=p.z;
+ }
pl->pop.x=(sumx/(pa->npoints-1));
pl->pop.y=(sumy/(pa->npoints-1));
pl->pop.z=(sumz/(pa->npoints-1));
-
+
sumx=0;
sumy=0;
sumz=0;
numberofvectors= floor((pa->npoints-1)/pointsinslice); /*the number of vectors we try can be 3, 4 or 5*/
-
+
getPoint3dz_p(pa, 0, &p1);
for (j=pointsinslice;j<pa->npoints;j+=pointsinslice)
{
- getPoint3dz_p(pa, j, &p2);
-
+ getPoint3dz_p(pa, j, &p2);
+
if (!get_3dvector_from_points(&(pl->pop), &p1, &v1) || !get_3dvector_from_points(&(pl->pop), &p2, &v2))
- return LW_FALSE;
+ return LW_FALSE;
/*perpendicular vector is cross product of v1 and v2*/
if (!get_3dcross_product(&v1,&v2, &v))
- return LW_FALSE;
+ return LW_FALSE;
vl=VECTORLENGTH(v);
sumx+=(v.x/vl);
sumy+=(v.y/vl);
- sumz+=(v.z/vl);
+ sumz+=(v.z/vl);
p1=p2;
}
pl->pv.x=(sumx/numberofvectors);
pl->pv.y=(sumy/numberofvectors);
pl->pv.z=(sumz/numberofvectors);
-
+
return 1;
}
VECTOR3D v1;
double f;
-
+
if (!get_3dvector_from_points(&(pl->pop), p, &v1))
- return LW_FALSE;
-
+ return LW_FALSE;
+
f=-(DOT(pl->pv,v1)/DOT(pl->pv,pl->pv));
-
+
p0->x=p->x+pl->pv.x*f;
p0->y=p->y+pl->pv.y*f;
p0->z=p->z+pl->pv.z*f;
-
- return f;
+
+ return f;
}
int
pt_in_ring_3d(const POINT3DZ *p, const POINTARRAY *ring,PLANE3D *plane)
{
-
+
int cn = 0; /* the crossing number counter */
int i;
POINT3DZ v1, v2;
/* loop through all edges of the polygon */
getPoint3dz_p(ring, 0, &v1);
-
-
+
+
if(fabs(plane->pv.z)>=fabs(plane->pv.x)&&fabs(plane->pv.z)>=fabs(plane->pv.y)) /*If the z vector of the normal vector to the plane is larger than x and y vector we project the ring to the xy-plane*/
{
for (i=0; i<ring->npoints-1; i++)
{
if( s->str_end == s->str_start )
return 0;
-
+
return *(s->str_end - 1);
}
{
char *ptr = s->str_end;
int dist = 0;
-
+
/* Roll backwards until we hit a non-space. */
while( ptr > s->str_start )
- {
+ {
ptr--;
if( (*ptr == ' ') || (*ptr == '\t') )
{
return dist;
}
}
- return dist;
+ return dist;
}
/**
char *ptr = s->str_end;
char *decimal_ptr = NULL;
int dist;
-
+
if ( s->str_end - s->str_start < 2)
return 0;
/* Roll backwards to find the decimal for this number */
while( ptr > s->str_start )
- {
+ {
ptr--;
if ( *ptr == '.' )
{
/* No decimal? Nothing to trim! */
if ( ! decimal_ptr )
return 0;
-
+
ptr = s->str_end;
-
+
/* Roll backwards again, with the decimal as stop point, trimming contiguous zeroes */
while( ptr >= decimal_ptr )
{
else
break;
}
-
+
/* Huh, we get anywhere. Must not have trimmed anything. */
if ( ptr == s->str_end )
return 0;
static size_t
_varint_u64_encode_buf(uint64_t val, uint8_t *buf)
{
- uint8_t grp;
+ uint8_t grp;
uint64_t q = val;
uint8_t *ptr = buf;
while (1)
/* We rightshift our input value 7 bits */
/* which means that the 7 next least significant bits */
/* becomes the 7 least significant */
- q = q >> 7;
+ q = q >> 7;
/* Check if, after our rightshifting, we still have */
/* anything to read in our input value. */
if ( q > 0 )
/* Read from signed 64bit varint */
int64_t
varint_s64_decode(const uint8_t *the_start, const uint8_t *the_end, size_t *size)
-{
+{
return unzigzag64(varint_u64_decode(the_start, the_end, size));
}
{
return (val << 1) ^ (val >> 31);
}
-
+
uint8_t zigzag8(int8_t val)
{
return (val << 1) ^ (val >> 7);
}
-
+
int64_t unzigzag64(uint64_t val)
{
if ( val & 0x01 )
else
return (int64_t)(val >> 1);
}
-
+
int32_t unzigzag32(uint32_t val)
{
if ( val & 0x01 )
else
return (int32_t)(val >> 1);
}
-
+
int8_t unzigzag8(uint8_t val)
{
if ( val & 0x01 )
else
return (int8_t)(val >> 1);
}
-
+
{
char gboxmem[GIDX_MAX_SIZE];
GIDX *gidx = (GIDX*)gboxmem;
-
+
if( LW_FAILURE == gserialized_datum_get_gidx_p(gsdatum, gidx) )
return LW_FAILURE;
-
+
gbox->flags = gserialized_datum_get_flags(gsdatum);
gbox_from_gidx(gidx, gbox, gbox->flags);
-
+
return LW_SUCCESS;
}
memset(cache, 0, sizeof(GenericCacheCollection));
fcinfo->flinfo->fn_extra = cache;
}
- return cache;
+ return cache;
}
-
+
/**
* Get the Proj4 entry from the generic cache if one exists.
{
GenericCacheCollection* generic_cache = GetGenericCacheCollection(fcinfo);
PROJ4PortalCache* cache = (PROJ4PortalCache*)(generic_cache->entry[PROJ_CACHE_ENTRY]);
-
+
if ( ! cache )
{
/* Allocate in the upper context */
const GSERIALIZED *geom;
GenericCacheCollection* generic_cache = GetGenericCacheCollection(fcinfo);
int entry_number = cache_methods->entry_number;
-
+
Assert(entry_number >= 0);
Assert(entry_number < NUM_CACHE_ENTRIES);
-
+
cache = (GeomCache*)(generic_cache->entry[entry_number]);
-
+
if ( ! cache )
{
old_context = MemoryContextSwitchTo(FIContext(fcinfo));
/* Store the pointer in GenericCache */
cache->type = entry_number;
generic_cache->entry[entry_number] = (GenericCache*)cache;
- }
+ }
/* Cache hit on the first argument */
if ( g1 &&
{
text *output;
size_t sz;
-
+
/* Guard against null input */
if( !cstring )
return NULL;
-
+
sz = strlen(cstring);
output = palloc(sz + VARHDRSZ);
if ( ! output )
if ( level >= 0 && level <= 5 )
ereport(pglevel[level], (errmsg_internal("%s", errmsg)));
else
- ereport(DEBUG5, (errmsg_internal("%s", errmsg)));
+ ereport(DEBUG5, (errmsg_internal("%s", errmsg)));
}
void
GetNumConfigOptions(),
sizeof(struct config_generic *),
postgis_guc_var_compare);
-
+
/* Found nothing? Good */
if ( ! res ) return 0;
-
+
/* Hm, you found something, but maybe it's just a placeholder? */
/* We'll consider a placehold a "not found" */
if ( (*res)->flags & GUC_CUSTOM_PLACEHOLDER )
return 0;
-
+
return 1;
}
int yzone = zone / 20;
double lat_0 = 30.0 * (yzone - 3) + 15.0;
double lon_0 = 0.0;
-
+
/* The number of xzones is variable depending on yzone */
if ( yzone == 2 || yzone == 3 )
lon_0 = 30.0 * (xzone - 6) + 15.0;
lon_0 = 90.0 * (xzone - 2) + 45.0;
else
lwerror("Unknown yzone encountered!");
-
+
snprintf(proj_str, maxproj4len, "+proj=laea +ellps=WGS84 +datum=WGS84 +lat_0=%g +lon_0=%g +units=m +no_defs", lat_0, lon_0);
}
/* Lambert Azimuthal Equal Area South Pole */
char *pj_errstr = pj_strerrno(*pj_get_errno_ref());
if ( ! pj_errstr )
pj_errstr = "";
-
+
elog(ERROR,
"AddToPROJ4SRSCache: could not parse proj4 string '%s' %s",
proj_str, pj_errstr);
projPJ pj2;
srs_precision sp;
-
+
sp.precision_xy = precision;
sp.precision_z = precision;
sp.precision_m = precision;
-
+
if ( srid == SRID_UNKNOWN )
return sp;
sp.precision_xy += 5;
return sp;
}
-
+
return sp;
}
}
void test_ShpDumperCreate(void)
-{
+{
dumper_config = (SHPDUMPERCONFIG*)calloc(1, sizeof(SHPDUMPERCONFIG));
set_dumper_config_defaults(dumper_config);
dumper_state = ShpDumperCreate(dumper_config);
}
void test_ShpLoaderCreate(void)
-{
+{
loader_config = (SHPLOADERCONFIG*)calloc(1, sizeof(SHPLOADERCONFIG));
set_loader_config_defaults(loader_config);
loader_state = ShpLoaderCreate(loader_config);
"Record count in .shp header is %d, which seems\n"
"unreasonable. Assuming header is corrupt.",
psSHP->nRecords );
- psSHP->sHooks.Error( szError );
+ psSHP->sHooks.Error( szError );
psSHP->sHooks.FClose( psSHP->fpSHP );
psSHP->sHooks.FClose( psSHP->fpSHX );
free( psSHP );
int SHPAPI_CALL
SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
-
+
{
unsigned int nRecordOffset, nRecordSize=0;
int i;
if( bBigEndian ) SwapWord( 4, &nPoints );
ByteCopy( &nPoints, pabyRec + 44, 4 );
-
+
for( i = 0; i < psObject->nVertices; i++ )
{
ByteCopy( psObject->padfX + i, pabyRec + 48 + i*16, 8 );
if (cmp < 0)
PG_RETURN_BOOL(TRUE);
else
- PG_RETURN_BOOL(FALSE);
+ PG_RETURN_BOOL(FALSE);
}
/*
if (cmp <= 0)
PG_RETURN_BOOL(TRUE);
else
- PG_RETURN_BOOL(FALSE);
+ PG_RETURN_BOOL(FALSE);
}
/*
if (cmp > 0)
PG_RETURN_BOOL(TRUE);
else
- PG_RETURN_BOOL(FALSE);
+ PG_RETURN_BOOL(FALSE);
}
/*
if (cmp >= 0)
PG_RETURN_BOOL(TRUE);
else
- PG_RETURN_BOOL(FALSE);
+ PG_RETURN_BOOL(FALSE);
}
/*
if (cmp == 0)
PG_RETURN_BOOL(TRUE);
else
- PG_RETURN_BOOL(FALSE);
+ PG_RETURN_BOOL(FALSE);
}
/*
/* Error on any SRID != default */
srid_is_latlong(fcinfo, lwgeom->srid);
-
+
/* Convert to gserialized */
g_ser = gserialized_geography_from_lwgeom(lwgeom, geog_typmod);
}
svg = lwgeom_to_svg(lwgeom, precision, relative);
-
+
lwgeom_free(lwgeom);
PG_FREE_IF_COPY(g, 0);
LWGEOM_PARSER_RESULT lwg_parser_result;
GSERIALIZED *g_ser = NULL;
text *wkt_text = PG_GETARG_TEXT_P(0);
-
+
/* Extract the cstring from the varlena */
char *wkt = text2cstring(wkt_text);
- /* Pass the cstring to the input parser, and magic occurs! */
+ /* Pass the cstring to the input parser, and magic occurs! */
if ( lwgeom_parse_wkt(&lwg_parser_result, wkt, LW_PARSER_CHECK_ALL) == LW_FAILURE )
PG_PARSER_ERROR(lwg_parser_result);
size_t wkb_size = VARSIZE(wkb_bytea);
uint8_t *wkb = (uint8_t*)VARDATA(wkb_bytea);
LWGEOM *lwgeom = lwgeom_from_wkb(wkb, wkb_size, LW_PARSER_CHECK_NONE);
-
+
if ( ! lwgeom )
lwpgerror("Unable to parse WKB");
/* Error on any SRID != default */
srid_is_latlong(fcinfo, lwgeom->srid);
-
+
gser = gserialized_geography_from_lwgeom(lwgeom, -1);
lwgeom_free(lwgeom);
PG_RETURN_POINTER(gser);
/* force recalculate of box by dropping */
lwgeom_drop_bbox(lwgeom);
- lwgeom_set_geodetic(lwgeom, true);
- /* We are trusting geography_serialize will add a box if needed */
+ lwgeom_set_geodetic(lwgeom, true);
+ /* We are trusting geography_serialize will add a box if needed */
g_ser = geography_serialize(lwgeom);
lwgeom = lwgeom_from_gserialized(g_ser);
/* Recalculate the boxes after re-setting the geodetic bit */
- lwgeom_set_geodetic(lwgeom, false);
+ lwgeom_set_geodetic(lwgeom, false);
lwgeom_drop_bbox(lwgeom);
lwgeom_add_bbox(lwgeom);
spheroid_init_from_srid(fcinfo, gserialized_get_srid(g1), &s);
error_if_srid_mismatch(gserialized_get_srid(g1), gserialized_get_srid(g2));
-
+
/* Set to sphere if requested */
if ( ! use_spheroid )
s.a = s.b = s.radius;
/* Make sure we have boxes attached */
lwgeom_add_bbox_deep(lwgeom1, NULL);
lwgeom_add_bbox_deep(lwgeom2, NULL);
-
+
distance = lwgeom_distance_spheroid(lwgeom1, lwgeom2, &s, tolerance);
POSTGIS_DEBUGF(2, "[GIST] '%s' got distance %g", __func__, distance);
/* Initialize spheroid */
spheroid_init_from_srid(fcinfo, gserialized_get_srid(g1), &s);
-
+
/* Set to sphere if requested */
if ( ! use_spheroid )
s.a = s.b = s.radius;
/* Make sure we have boxes attached */
lwgeom_add_bbox_deep(lwgeom1, NULL);
lwgeom_add_bbox_deep(lwgeom2, NULL);
-
+
distance = lwgeom_distance_spheroid(lwgeom1, lwgeom2, &s, tolerance);
POSTGIS_DEBUGF(2, "[GIST] '%s' got distance %g", __func__, distance);
use_spheroid = PG_GETARG_BOOL(3);
error_if_srid_mismatch(gserialized_get_srid(g1), gserialized_get_srid(g2));
-
+
/* Initialize spheroid */
spheroid_init_from_srid(fcinfo, gserialized_get_srid(g1), &s);
-
+
/* Set to sphere if requested */
if ( ! use_spheroid )
s.a = s.b = s.radius;
PG_FREE_IF_COPY(g2, 1);
PG_RETURN_NULL();
}
-
+
/* Do the brute force calculation if the cached calculation doesn't tick over */
if ( LW_FAILURE == geography_distance_cache(fcinfo, g1, g2, &s, &distance) )
{
use_spheroid = PG_GETARG_BOOL(3);
error_if_srid_mismatch(gserialized_get_srid(g1), gserialized_get_srid(g2));
-
+
/* Initialize spheroid */
spheroid_init_from_srid(fcinfo, gserialized_get_srid(g1), &s);
elog(ERROR, "geography_distance_tree failed!");
PG_RETURN_NULL();
}
-
+
PG_RETURN_FLOAT8(distance);
}
{
PG_RETURN_POINTER(g);
}
-
+
if ( g_out != g )
{
pfree(g);
lwgeom_free(lwgeom);
PG_RETURN_FLOAT8(0.0);
}
-
+
if ( lwgeom->bbox )
gbox = *(lwgeom->bbox);
else
/* Get our geometry object loaded into memory. */
g = PG_GETARG_GSERIALIZED_P(0);
-
+
/* Only return for area features. */
type = gserialized_get_type(g);
if ( ! (type == POLYGONTYPE || type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE) )
{
PG_RETURN_FLOAT8(0.0);
}
-
+
lwgeom = lwgeom_from_gserialized(g);
/* EMPTY things have no perimeter */
/* Get our geometry object loaded into memory. */
g = PG_GETARG_GSERIALIZED_P(0);
-
+
/* We need the bounding box to get an outside point for area algorithm */
if ( gserialized_get_gbox_p(g, &gbox) == LW_FAILURE )
{
/* Calculate a geocentric bounds for the objects */
if ( ! empty1 && gserialized_get_gbox_p(g1, &gbox1) == LW_FAILURE )
elog(ERROR, "Error in geography_bestsrid calling gserialized_get_gbox_p(g1, &gbox1)");
-
+
POSTGIS_DEBUGF(4, "calculated gbox = %s", gbox_to_string(&gbox1));
/* If we have a unique second argument, fill in all the necessary variables. */
if ( xwidth < 6.0 )
{
int zone = floor((center.x + 180.0) / 6.0);
-
+
if ( zone > 59 ) zone = 59;
/* Are these data below the equator? UTM South. */
{
int xzone = -1;
int yzone = 3 + floor(center.y / 30.0); /* (range of 0-5) */
-
+
/* Equatorial band, 12 zones, 30 degrees wide */
if ( (yzone == 2 || yzone == 3) && xwidth < 30.0 )
{
{
xzone = 2 + floor(center.x / 90.0);
}
-
+
/* Did we fit into an appropriate xzone? */
if ( xzone != -1 )
{
/* Return NULL on NULL distance or geography */
if ( PG_NARGS() < 2 || PG_ARGISNULL(0) || PG_ARGISNULL(1) )
PG_RETURN_NULL();
-
+
/* Get our geometry object loaded into memory. */
g = PG_GETARG_GSERIALIZED_P(0);
-
+
/* Only return for points. */
type = gserialized_get_type(g);
if ( type != POINTTYPE )
elog(ERROR, "ST_Project(geography) cannot project from an empty start point");
PG_RETURN_NULL();
}
-
+
if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
azimuth = PG_GETARG_FLOAT8(2); /* Azimuth in Radians */
/* Get our geometry object loaded into memory. */
g1 = PG_GETARG_GSERIALIZED_P(0);
g2 = PG_GETARG_GSERIALIZED_P(1);
-
+
/* Only return for points. */
type1 = gserialized_get_type(g1);
type2 = gserialized_get_type(g2);
elog(ERROR, "ST_Azimuth(geography, geography) is only valid for point inputs");
PG_RETURN_NULL();
}
-
+
lwgeom1 = lwgeom_from_gserialized(g1);
lwgeom2 = lwgeom_from_gserialized(g2);
elog(ERROR, "ST_Azimuth(geography, geography) cannot work with empty points");
PG_RETURN_NULL();
}
-
+
/* Initialize spheroid */
spheroid_init_from_srid(fcinfo, gserialized_get_srid(g1), &s);
/* Return NULL for unknown (same point) azimuth */
if( isnan(azimuth) )
{
- PG_RETURN_NULL();
+ PG_RETURN_NULL();
}
PG_RETURN_FLOAT8(azimuth);
GSERIALIZED *g2 = NULL;
double max_seg_length;
uint32_t type1;
-
+
/* Get our geometry object loaded into memory. */
g1 = PG_GETARG_GSERIALIZED_P(0);
type1 = gserialized_get_type(g1);
-
+
/* Convert max_seg_length from metric units to radians */
max_seg_length = PG_GETARG_FLOAT8(1) / WGS84_RADIUS;
-
+
/* We can't densify points or points, reflect them back */
if ( type1 == POINTTYPE || type1 == MULTIPOINTTYPE || gserialized_is_empty(g1) )
PG_RETURN_POINTER(g1);
-
+
/* Deserialize */
lwgeom1 = lwgeom_from_gserialized(g1);
-
+
/* Calculate the densified geometry */
lwgeom2 = lwgeom_segmentize_sphere(lwgeom1, max_seg_length);
-
+
/*
** Set the geodetic flag so subsequent
** functions do the right thing.
*/
lwgeom_set_geodetic(lwgeom2, true);
-
+
/* Recalculate the boxes after re-setting the geodetic bit */
lwgeom_drop_bbox(lwgeom2);
-
- /* We are trusting geography_serialize will add a box if needed */
+
+ /* We are trusting geography_serialize will add a box if needed */
g2 = geography_serialize(lwgeom2);
-
+
/* Clean up */
lwgeom_free(lwgeom1);
lwgeom_free(lwgeom2);
PG_FREE_IF_COPY(g1, 0);
-
+
PG_RETURN_POINTER(g2);
}
}
if ( ! tree )
return LW_FAILURE;
-
+
circ_cache->index = tree;
return LW_SUCCESS;
}
lwgeom_calculate_gbox_geodetic(lwgeom1, &gbox1);
lwgeom_free(lwgeom1);
}
-
+
/* Flip the candidate point into geographics */
geographic_point_init(in_point->x, in_point->y, &in_gpoint);
geog2cart(&in_gpoint, &in_point3d);
-
+
/* If the candidate isn't in the tree box, it's not in the tree area */
if ( ! gbox_contains_point3d(&gbox1, &in_point3d) )
{
{
POSTGIS_DEBUG(3, "tree1 not polygonal, so CircTreePIP returning FALSE");
return LW_FALSE;
- }
+ }
}
int type1 = gserialized_get_type(g1);
int type2 = gserialized_get_type(g2);
-
+
Assert(distance);
-
+
/* Two points? Get outa here... */
if ( type1 == POINTTYPE && type2 == POINTTYPE )
return LW_FAILURE;
/* Fetch/build our cache, if appropriate, etc... */
tree_cache = GetCircTreeGeomCache(fcinfo, g1, g2);
-
+
/* OK, we have an index at the ready! Use it for the one tree argument and */
/* fill in the other tree argument */
if ( tree_cache && tree_cache->argnum && tree_cache->index )
int geomtype_cached;
int geomtype;
POINT4D p4d;
-
+
/* We need to dynamically build a tree for the uncached side of the function call */
if ( tree_cache->argnum == 1 )
{
lwpgerror("geography_distance_cache this cannot happen!");
return LW_FAILURE;
}
-
+
lwgeom = lwgeom_from_gserialized(g);
if ( geomtype_cached == POLYGONTYPE || geomtype_cached == MULTIPOLYGONTYPE )
{
return LW_SUCCESS;
}
}
-
+
circtree = lwgeom_calculate_circ_tree(lwgeom);
if ( geomtype == POLYGONTYPE || geomtype == MULTIPOLYGONTYPE )
{
*distance = circ_tree_distance_tree(circtree_cached, circtree, s, tolerance);
circ_tree_free(circtree);
- lwgeom_free(lwgeom);
+ lwgeom_free(lwgeom);
return LW_SUCCESS;
}
else
}
return LW_FAILURE;
}
-
+
int
geography_tree_distance(const GSERIALIZED* g1, const GSERIALIZED* g2, const SPHEROID* s, double tolerance, double* distance)
{
LWGEOM* lwgeom1 = NULL;
LWGEOM* lwgeom2 = NULL;
POINT4D pt1, pt2;
-
+
lwgeom1 = lwgeom_from_gserialized(g1);
lwgeom2 = lwgeom_from_gserialized(g2);
circ_tree1 = lwgeom_calculate_circ_tree(lwgeom1);
circ_tree2 = lwgeom_calculate_circ_tree(lwgeom2);
lwgeom_startpoint(lwgeom1, &pt1);
lwgeom_startpoint(lwgeom2, &pt2);
-
+
if ( CircTreePIP(circ_tree1, g1, &pt2) || CircTreePIP(circ_tree2, g2, &pt1) )
{
*distance = 0.0;
/* Calculate tree/tree distance */
*distance = circ_tree_distance_tree(circ_tree1, circ_tree2, s, tolerance);
}
-
+
circ_tree_free(circ_tree1);
circ_tree_free(circ_tree2);
lwgeom_free(lwgeom1);
if ( PG_ARGISNULL(0) )
PG_RETURN_NULL();
-
+
point = PG_GETARG_POINT_P(0);
-
+
if ( ! point )
PG_RETURN_NULL();
-
+
lwpoint = lwpoint_make2d(SRID_UNKNOWN, point->x, point->y);
geom = geometry_serialize(lwpoint_as_lwgeom(lwpoint));
lwpoint_free(lwpoint);
-
+
PG_RETURN_POINTER(geom);
}
if ( PG_ARGISNULL(0) )
PG_RETURN_NULL();
-
+
geom = PG_GETARG_GSERIALIZED_P(0);
-
+
if ( gserialized_get_type(geom) != POINTTYPE )
elog(ERROR, "geometry_to_point only accepts Points");
-
+
lwgeom = lwgeom_from_gserialized(geom);
-
+
if ( lwgeom_is_empty(lwgeom) )
PG_RETURN_NULL();
-
+
lwpoint = lwgeom_as_lwpoint(lwgeom);
-
+
point = (Point*)palloc(sizeof(Point));
point->x = lwpoint_get_x(lwpoint);
point->y = lwpoint_get_y(lwpoint);
-
+
lwpoint_free(lwpoint);
PG_FREE_IF_COPY(geom,0);
-
+
PG_RETURN_POINT_P(point);
}
if ( PG_ARGISNULL(0) )
PG_RETURN_NULL();
-
+
geom = PG_GETARG_GSERIALIZED_P(0);
-
+
if ( gserialized_get_type(geom) != LINETYPE )
elog(ERROR, "geometry_to_path only accepts LineStrings");
-
+
lwgeom = lwgeom_from_gserialized(geom);
if ( lwgeom_is_empty(lwgeom) )
- PG_RETURN_NULL();
+ PG_RETURN_NULL();
lwline = lwgeom_as_lwline(lwgeom);
-
+
pa = lwline->points;
size = offsetof(PATH, p[0]) + sizeof(path->p[0]) * pa->npoints;
path = (PATH*)palloc(size);
(path->p[i]).x = pt->x;
(path->p[i]).y = pt->y;
}
-
+
lwgeom_free(lwgeom);
PG_FREE_IF_COPY(geom,0);
-
+
PG_RETURN_PATH_P(path);
}
if ( PG_ARGISNULL(0) )
PG_RETURN_NULL();
-
+
path = PG_GETARG_PATH_P(0);
if ( ! path )
PG_RETURN_NULL();
-
+
pa = ptarray_construct_empty(0, 0, path->npts);
for ( i = 0; i < path->npts; i++ )
{
lwline = lwline_construct(SRID_UNKNOWN, NULL, pa);
geom = geometry_serialize(lwline_as_lwgeom(lwline));
lwline_free(lwline);
-
+
PG_RETURN_POINTER(geom);
}
if ( PG_ARGISNULL(0) )
PG_RETURN_NULL();
-
+
geom = PG_GETARG_GSERIALIZED_P(0);
-
+
if ( gserialized_get_type(geom) != POLYGONTYPE )
elog(ERROR, "geometry_to_polygon only accepts Polygons");
-
+
lwgeom = lwgeom_from_gserialized(geom);
if ( lwgeom_is_empty(lwgeom) )
- PG_RETURN_NULL();
+ PG_RETURN_NULL();
lwpoly = lwgeom_as_lwpoly(lwgeom);
-
+
pa = lwpoly->rings[0];
size = offsetof(POLYGON, p[0]) + sizeof(polygon->p[0]) * pa->npoints;
polygon = (POLYGON*)palloc0(size); /* zero any holes */
SET_VARSIZE(polygon, size);
- polygon->npts = pa->npoints;
+ polygon->npts = pa->npoints;
lwgeom_calculate_gbox(lwgeom, &gbox);
polygon->boundbox.low.x = gbox.xmin;
polygon->boundbox.low.y = gbox.ymin;
polygon->boundbox.high.x = gbox.xmax;
polygon->boundbox.high.y = gbox.ymax;
-
+
for ( i = 0; i < pa->npoints; i++ )
{
const POINT2D *pt = getPoint2d_cp(pa, i);
lwgeom_free(lwgeom);
PG_FREE_IF_COPY(geom,0);
-
+
PG_RETURN_POLYGON_P(polygon);
}
if ( PG_ARGISNULL(0) )
PG_RETURN_NULL();
-
+
polygon = PG_GETARG_POLYGON_P(0);
if ( ! polygon )
{
unclosed = 1;
}
-
+
pa = ptarray_construct_empty(0, 0, polygon->npts + unclosed);
-
+
for ( i = 0; i < (polygon->npts+unclosed); i++ )
{
POINT4D pt;
pt.y = p.y;
ptarray_append_point(pa, &pt, LW_FALSE);
}
-
+
ppa = palloc(sizeof(POINTARRAY*));
ppa[0] = pa;
- lwpoly = lwpoly_construct(SRID_UNKNOWN, NULL, 1, ppa);
+ lwpoly = lwpoly_construct(SRID_UNKNOWN, NULL, 1, ppa);
geom = geometry_serialize(lwpoly_as_lwgeom(lwpoly));
lwpoly_free(lwpoly);
-
+
PG_RETURN_POINTER(geom);
}
/**
* More modest fallback selectivity factor
*/
-#define FALLBACK_ND_SEL 0.2
-#define FALLBACK_ND_JOINSEL 0.3
+#define FALLBACK_ND_SEL 0.2
+#define FALLBACK_ND_JOINSEL 0.3
/**
* N-dimensional box type for calculations, to avoid doing
{
/* Dimensionality of the histogram. */
float4 ndims;
-
+
/* Size of n-d histogram in each dimension. */
float4 size[ND_DIMS];
/* How many rows in the table itself? */
float4 table_features;
-
+
/* How many rows were in the sample that built this histogram? */
float4 sample_features;
-
+
/* How many not-Null/Empty features were in the sample? */
float4 not_null_features;
/* How many cells in histogram? (sizex*sizey*sizez*sizem) */
float4 histogram_cells;
-
+
/* How many cells did those histogram features cover? */
/* Since we are pro-rating coverage, this number should */
/* now always equal histogram_features */
float4 cells_covered;
-
+
/* Variable length # of floats for histogram */
float4 value[1];
} ND_STATS;
int i;
double sigma2 = 0;
double mean = avg(vals, nvals);
-
+
/* Calculate sigma2 */
for ( i = 0; i < nvals; i++ )
{
{
int d;
int accum = 1, vdx = 0;
-
+
/* Calculate the index into the 1-d values array that the (i,j,k,l) */
/* n-d histogram coordinate implies. */
/* index = x + y * sizex + z * sizex * sizey + m * sizex * sizey * sizez */
char *rv;
int i;
stringbuffer_t *sb = stringbuffer_create();
-
+
stringbuffer_append(sb, "{\"min\":[");
for ( i = 0; i < ndims; i++ )
{
rv = stringbuffer_getstringcopy(sb);
stringbuffer_destroy(sb);
- return rv;
+ return rv;
}
int d;
stringbuffer_t *sb = stringbuffer_create();
int ndims = (int)roundf(nd_stats->ndims);
-
+
stringbuffer_append(sb, "{");
stringbuffer_aprintf(sb, "\"ndims\":%d,", ndims);
-
+
/* Size */
stringbuffer_append(sb, "\"size\":[");
for ( d = 0; d < ndims; d++ )
json_extent = nd_box_to_json(&(nd_stats->extent), ndims);
stringbuffer_aprintf(sb, "\"extent\":%s,", json_extent);
pfree(json_extent);
-
+
stringbuffer_aprintf(sb, "\"table_features\":%d,", (int)roundf(nd_stats->table_features));
stringbuffer_aprintf(sb, "\"sample_features\":%d,", (int)roundf(nd_stats->sample_features));
stringbuffer_aprintf(sb, "\"not_null_features\":%d,", (int)roundf(nd_stats->not_null_features));
str = stringbuffer_getstringcopy(sb);
stringbuffer_destroy(sb);
return str;
-}
+}
/**
{
int d = 0;
POSTGIS_DEBUGF(3, " %s", gbox_to_string(gbox));
-
+
nd_box_init(nd_box);
nd_box->min[d] = gbox->xmin;
nd_box->max[d] = gbox->xmax;
nd_box_overlap(const ND_STATS *nd_stats, const ND_BOX *nd_box, ND_IBOX *nd_ibox)
{
int d;
-
+
POSTGIS_DEBUGF(4, " nd_box: %s", nd_box_to_json(nd_box, nd_stats->ndims));
-
+
/* Initialize ibox */
memset(nd_ibox, 0, sizeof(ND_IBOX));
-
+
/* In each dimension... */
for ( d = 0; d < nd_stats->ndims; d++ )
{
double smax = nd_stats->extent.max[d];
double width = smax - smin;
int size = roundf(nd_stats->size[d]);
-
+
/* ... find cells the box overlaps with in this dimension */
nd_ibox->min[d] = floor(size * (nd_box->min[d] - smin) / width);
nd_ibox->max[d] = floor(size * (nd_box->max[d] - smin) / width);
POSTGIS_DEBUGF(5, " stats: dim %d: min %g: max %g: width %g", d, smin, smax, width);
POSTGIS_DEBUGF(5, " overlap: dim %d: (%d, %d)", d, nd_ibox->min[d], nd_ibox->max[d]);
-
+
/* Push any out-of range values into range */
nd_ibox->min[d] = Max(nd_ibox->min[d], 0);
nd_ibox->max[d] = Min(nd_ibox->max[d], size-1);
double ivol = 1.0;
double vol2 = 1.0;
double vol1 = 1.0;
-
+
for ( d = 0 ; d < ndims; d++ )
{
if ( b1->max[d] <= b2->min[d] || b1->min[d] >= b2->max[d] )
return 0.0; /* Disjoint */
-
+
if ( b1->min[d] > b2->min[d] || b1->max[d] < b2->max[d] )
covered = FALSE;
}
-
+
if ( covered )
return 1.0;
double width1 = b1->max[d] - b1->min[d];
double width2 = b2->max[d] - b2->min[d];
double imin, imax, iwidth;
-
+
vol1 *= width1;
vol2 *= width2;
-
+
imin = Max(b1->min[d], b2->min[d]);
imax = Min(b1->max[d], b2->max[d]);
iwidth = imax - imin;
iwidth = Max(0.0, iwidth);
-
+
ivol *= iwidth;
}
-
+
if ( vol2 == 0.0 )
return vol2;
-
+
return ivol / vol2;
}
#endif
int bmin, bmax; /* Bin min, bin max */
const ND_BOX *ndb;
-
- /* For each dimension... */
+
+ /* For each dimension... */
for ( d = 0; d < ndims; d++ )
{
/* Initialize counts for this dimension */
memset(counts, 0, sizeof(int)*num_bins);
-
+
smin = extent->min[d];
smax = extent->max[d];
swidth = smax - smin;
-
+
/* Don't try and calculate distribution of overly narrow dimensions */
if ( swidth < MIN_DIMENSION_WIDTH )
{
for ( i = 0; i < num_boxes; i++ )
{
double minoffset, maxoffset;
-
+
/* Skip null entries */
- ndb = nd_boxes[i];
+ ndb = nd_boxes[i];
if ( ! ndb ) continue;
-
+
/* Where does box fall relative to the working range */
minoffset = ndb->min[d] - smin;
- maxoffset = ndb->max[d] - smin;
+ maxoffset = ndb->max[d] - smin;
/* Skip boxes that our outside our working range */
if ( minoffset < 0 || minoffset > swidth ||
{
continue;
}
-
+
/* What bins does this range correspond to? */
bmin = num_bins * (minoffset) / swidth;
bmax = num_bins * (maxoffset) / swidth;
-
+
POSTGIS_DEBUGF(4, " dimension %d, feature %d: bin %d to bin %d", d, i, bmin, bmax);
-
+
/* Increment the counts in all the bins this feature overlaps */
for ( k = bmin; k <= bmax; k++ )
{
counts[k] += 1;
}
-
+
}
/* How dispersed is the distribution of features across bins? */
POSTGIS_DEBUGF(3, " dimension %d: stddev = %.6g", d, sdev);
POSTGIS_DEBUGF(3, " dimension %d: stddev_ratio = %.6g", d, sdev_ratio);
#endif
-
+
distribution[d] = range;
}
-
+
return TRUE;
}
if ( mode == 2 ) stats_kind = STATISTIC_KIND_2D;
/* Then read the geom status histogram from that */
-
+
#if POSTGIS_PGSQL_VERSION < 100
float4 *floatptr;
int nvalues;
-
+
rv = get_attstatsslot(stats_tuple, 0, 0, stats_kind, InvalidOid,
NULL, NULL, NULL, &floatptr, &nvalues);
-
+
if ( ! rv ) {
POSTGIS_DEBUGF(2,
"no slot of kind %d in stats tuple", stats_kind);
return NULL;
}
-
+
/* Clone the stats here so we can release the attstatsslot immediately */
nd_stats = palloc(sizeof(float) * nvalues);
memcpy(nd_stats, floatptr, sizeof(float) * nvalues);
-
+
/* Clean up */
free_attstatsslot(0, NULL, 0, floatptr, nvalues);
#else /* PostgreSQL 10 or higher */
"no slot of kind %d in stats tuple", stats_kind);
return NULL;
}
-
+
/* Clone the stats here so we can release the attstatsslot immediately */
nd_stats = palloc(sizeof(float4) * sslot.nnumbers);
memcpy(nd_stats, sslot.numbers, sizeof(float4) * sslot.nnumbers);
-
+
free_attstatsslot(&sslot);
#endif
"histogram for attribute %d of table \"%s\" does not exist?",
att_num, get_rel_name(table_oid));
}
-
+
return nd_stats;
}
elog(ERROR, "attribute name is null");
return NULL;
}
-
+
return pg_get_nd_stats(table_oid, att_num, mode, only_parent);
}
int ndims1, ndims2, ndims;
double ntuples_max;
double ntuples_not_null1, ntuples_not_null2;
-
+
ND_BOX extent1, extent2;
ND_IBOX ibox1, ibox2;
int at1[ND_DIMS];
s1 = s2;
s2 = stats_tmp;
}
-
+
POSTGIS_DEBUGF(3, "s1: %s", nd_stats_to_json(s1));
POSTGIS_DEBUGF(3, "s2: %s", nd_stats_to_json(s2));
-
+
/* Re-read that info after the swap */
ncells1 = (int)roundf(s1->histogram_cells);
ncells2 = (int)roundf(s2->histogram_cells);
ndims1 = (int)roundf(s1->ndims);
ndims2 = (int)roundf(s2->ndims);
ndims = Max(ndims1, ndims2);
-
+
/* Get the extents */
extent1 = s1->extent;
extent2 = s2->extent;
POSTGIS_DEBUG(3, "relation stats do not intersect, returning 0");
PG_RETURN_FLOAT8(0.0);
}
-
+
/*
* First find the index range of the part of the smaller
* histogram that overlaps the larger one.
if ( ! nd_box_overlap(s1, &extent2, &ibox1) )
{
POSTGIS_DEBUG(3, "could not calculate overlap of relations");
- PG_RETURN_FLOAT8(FALLBACK_ND_JOINSEL);
+ PG_RETURN_FLOAT8(FALLBACK_ND_JOINSEL);
}
-
+
/* Initialize counters / constants on s1 */
for ( d = 0; d < ndims1; d++ )
{
nd_cell1.min[d] = min1[d] + (at1[d]+0) * cellsize1[d];
nd_cell1.max[d] = min1[d] + (at1[d]+1) * cellsize1[d];
}
-
+
/* Find the cells of s2 that cell1 overlaps.. */
nd_box_overlap(s2, &nd_cell1, &ibox2);
-
+
/* Initialize counter */
for ( d = 0; d < ndims2; d++ )
{
at2[d] = ibox2.min[d];
}
-
+
POSTGIS_DEBUGF(3, "at1 %d,%d %s", at1[0], at1[1], nd_box_to_json(&nd_cell1, ndims1));
-
+
/* Get the value at this cell */
val1 = s1->value[nd_stats_value_index(s1, at1)];
-
+
/* For each overlapped cell of s2... */
do
{
double ratio2;
double val2;
-
+
/* Construct the bounds of this cell */
ND_BOX nd_cell2;
nd_box_init(&nd_cell2);
}
POSTGIS_DEBUGF(3, " at2 %d,%d %s", at2[0], at2[1], nd_box_to_json(&nd_cell2, ndims2));
-
+
/* Calculate overlap ratio of the cells */
ratio2 = nd_box_ratio(&nd_cell1, &nd_cell2, Max(ndims1, ndims2));
-
+
/* Multiply the cell counts, scaled by overlap ratio */
val2 = s2->value[nd_stats_value_index(s2, at2)];
POSTGIS_DEBUGF(3, " val1 %.6g val2 %.6g ratio %.6g", val1, val2, ratio2);
val += val1 * (val2 * ratio2);
}
while ( nd_increment(&ibox2, ndims2, at2) );
-
+
}
while( nd_increment(&ibox1, ndims1, at1) );
-
+
POSTGIS_DEBUGF(3, "val of histogram = %g", val);
-
+
/*
* In order to compare our total cell count "val" to the
* ntuples_max, we need to scale val up to reflect a full
val *= (s2->table_features / s2->sample_features);
POSTGIS_DEBUGF(3, "val scaled to full table size = %g", val);
-
+
/*
* Because the cell counts are over-determined due to
* double counting of features that overlap multiple cells
{
selectivity = 1.0;
}
-
+
return selectivity;
}
Node *arg1, *arg2;
Var *var1, *var2;
Oid relid1, relid2;
-
+
ND_STATS *stats1, *stats2;
float8 selectivity;
selectivity = estimate_join_selectivity(stats1, stats2);
POSTGIS_DEBUGF(2, "got selectivity %g", selectivity);
-
+
pfree(stats1);
pfree(stats2);
PG_RETURN_FLOAT8(selectivity);
ND_STATS *nd_stats; /* Our histogram */
size_t nd_stats_size; /* Size to allocate */
-
+
double total_width = 0; /* # of bytes used by sample */
double total_sample_volume = 0; /* Area/volume coverage of the sample */
double total_cell_count = 0; /* # of cells in histogram affected by sample */
ND_BOX sum; /* Sum of extents of sample boxes */
ND_BOX avg; /* Avg of extents of sample boxes */
ND_BOX stddev; /* StdDev of extents of sample boxes */
-
+
const ND_BOX **sample_boxes; /* ND_BOXes for each of the sample features */
ND_BOX sample_extent; /* Extent of the raw sample */
int histo_size[ND_DIMS]; /* histogram nrows, ncols, etc */
int histo_cells_target; /* Number of cells we will shoot for, given the stats target */
int histo_cells; /* Number of cells in the histogram */
int histo_cells_new = 1; /* Temporary variable */
-
+
int ndims = 2; /* Dimensionality of the sample */
int histo_ndims = 0; /* Dimensionality of the histogram */
double sample_distribution[ND_DIMS]; /* How homogeneous is distribution of sample in each axis? */
null_cnt++;
continue;
}
-
+
/* Read the bounds from the gserialized. */
geom = (GSERIALIZED *)PG_DETOAST_DATUM(datum);
is_copy = VARATT_IS_EXTENDED(datum);
POSTGIS_DEBUGF(3, " skipped empty geometry %d", i);
continue;
}
-
+
/* If we're in 2D mode, zero out the higher dimensions for "safety" */
if ( mode == 2 )
gbox.zmin = gbox.zmax = gbox.mmin = gbox.mmax = 0.0;
-
+
/* Check bounds for validity (finite and not NaN) */
if ( ! gbox_is_valid(&gbox) )
{
*/
if ( mode != 2 )
ndims = Max(gbox_ndims(&gbox), ndims);
-
- /* Convert gbox to n-d box */
+
+ /* Convert gbox to n-d box */
nd_box = palloc(sizeof(ND_BOX));
nd_box_from_gbox(&gbox, nd_box);
-
+
/* Cache n-d bounding box */
sample_boxes[notnull_cnt] = nd_box;
/* Initialize sample extent before merging first entry */
if ( ! notnull_cnt )
nd_box_init_bounds(&sample_extent);
-
+
/* Add current sample to overall sample extent */
nd_box_merge(nd_box, &sample_extent);
-
+
/* How many bytes does this sample use? */
total_width += VARSIZE(geom);
-
+
/* Add bounds coordinates to sums for stddev calculation */
for ( d = 0; d < ndims; d++ )
{
/* Increment our "good feature" count */
notnull_cnt++;
-
+
/* Free up memory if our sample geometry was copied */
if ( is_copy )
pfree(geom);
/*
* Second scan:
* o compute standard deviation
- */
+ */
for ( d = 0; d < ndims; d++ )
{
/* Calculate average bounds values */
avg.min[d] = sum.min[d] / notnull_cnt;
avg.max[d] = sum.max[d] / notnull_cnt;
-
+
/* Calculate standard deviation for this dimension bounds */
for ( i = 0; i < notnull_cnt; i++ )
{
}
stddev.min[d] = sqrt(stddev.min[d] / notnull_cnt);
stddev.max[d] = sqrt(stddev.max[d] / notnull_cnt);
-
+
/* Histogram bounds for this dimension bounds is avg +/- SDFACTOR * stdev */
histo_extent.min[d] = Max(avg.min[d] - SDFACTOR * stddev.min[d], sample_extent.min[d]);
histo_extent.max[d] = Min(avg.max[d] + SDFACTOR * stddev.max[d], sample_extent.max[d]);
POSTGIS_DEBUGF(4, " feature %d is a hard deviant, skipped", i);
sample_boxes[i] = NULL;
continue;
- }
+ }
/* Expand our new box to fit all the other features. */
nd_box_merge(ndb, &histo_extent_new);
}
*/
nd_box_expand(&histo_extent_new, 0.01);
histo_extent = histo_extent_new;
-
+
/*
* How should we allocate our histogram cells to the
* different dimensions? We can't do it by raw dimensional width,
* At this point, histo_cells_target is the approximate target number
* of cells.
*/
-
+
/*
* Some dimensions have basically a uniform distribution, we want
* to allocate no cells to those dimensions, only to dimensions
if ( sample_distribution[d] > 0 )
histo_ndims++;
}
-
+
if ( histo_ndims == 0 )
{
/* Special case: all our dimensions had low variability! */
}
POSTGIS_DEBUGF(3, " histo_cells_new: %d", histo_cells_new);
}
-
+
/* Update histo_cells to the actual number of cells we need to allocate */
histo_cells = histo_cells_new;
POSTGIS_DEBUGF(3, " histo_cells: %d", histo_cells);
-
+
/*
* Create the histogram (ND_STATS) in the stats memory context
*/
/* Give backend a chance of interrupting us */
vacuum_delay_point();
-
+
/* Find the cells that overlap with this box and put them into the ND_IBOX */
nd_box_overlap(nd_stats, nd_box, &nd_ibox);
memset(at, 0, sizeof(int)*ND_DIMS);
-
+
POSTGIS_DEBUGF(3, " feature %d: ibox (%d, %d, %d, %d) (%d, %d, %d, %d)", i,
nd_ibox.min[0], nd_ibox.min[1], nd_ibox.min[2], nd_ibox.min[3],
nd_ibox.max[0], nd_ibox.max[1], nd_ibox.max[2], nd_ibox.max[3]);
min[d] = nd_stats->extent.min[d];
max[d] = nd_stats->extent.max[d];
cellsize[d] = (max[d] - min[d])/(nd_stats->size[d]);
-
+
/* What's the volume (area) of this feature's box? */
tmp_volume *= (nd_box->max[d] - nd_box->min[d]);
}
POSTGIS_DEBUGF(3, " at (%d, %d, %d, %d)", at[0], at[1], at[2], at[3]);
}
while ( nd_increment(&nd_ibox, nd_stats->ndims, at) );
-
+
/* Keep track of overall number of overlaps counted */
total_cell_count += num_cells;
/* How many features have we added to this histogram? */
stats->stats_valid = false;
return;
}
-
+
nd_stats->histogram_features = histogram_features;
nd_stats->histogram_cells = histo_cells;
nd_stats->cells_covered = total_cell_count;
stats_slot = STATISTIC_SLOT_ND;
stats_kind = STATISTIC_KIND_ND;
}
-
+
/* Write the statistics data */
stats->stakind[stats_slot] = stats_kind;
stats->staop[stats_slot] = InvalidOid;
/* 2D Mode */
compute_gserialized_stats_mode(stats, fetchfunc, sample_rows, total_rows, 2);
/* ND Mode */
- compute_gserialized_stats_mode(stats, fetchfunc, sample_rows, total_rows, 0);
+ compute_gserialized_stats_mode(stats, fetchfunc, sample_rows, total_rows, 0);
}
static float8
estimate_selectivity(const GBOX *box, const ND_STATS *nd_stats, int mode)
{
- int d; /* counter */
+ int d; /* counter */
float8 selectivity;
ND_BOX nd_box;
ND_IBOX nd_ibox;
double min[ND_DIMS];
double max[ND_DIMS];
double total_count = 0.0;
- int ndims_max = Max(nd_stats->ndims, gbox_ndims(box));
-// int ndims_min = Min(nd_stats->ndims, gbox_ndims(box));
+ int ndims_max = Max(nd_stats->ndims, gbox_ndims(box));
+// int ndims_min = Min(nd_stats->ndims, gbox_ndims(box));
/* Calculate the overlap of the box on the histogram */
if ( ! nd_stats )
POSTGIS_DEBUG(3, " in 2d mode, stripping the computation down to 2d");
ndims_max = 2;
}
-
+
POSTGIS_DEBUGF(3, " nd_stats->extent: %s", nd_box_to_json(&(nd_stats->extent), nd_stats->ndims));
POSTGIS_DEBUGF(3, " nd_box: %s", nd_box_to_json(&(nd_box), gbox_ndims(box)));
max[d] = nd_stats->extent.max[d];
cell_size[d] = (max[d] - min[d]) / nd_stats->size[d];
POSTGIS_DEBUGF(3, " cell_size[%d] : %.9g", d, cell_size[d]);
-
+
/* Initialize the counter */
at[d] = nd_ibox.min[d];
}
{
float cell_count, ratio;
ND_BOX nd_cell;
-
+
/* We have to pro-rate partially overlapped cells. */
for ( d = 0; d < nd_stats->ndims; d++ )
{
ratio = nd_box_ratio(&nd_box, &nd_cell, nd_stats->ndims);
cell_count = nd_stats->value[nd_stats_value_index(nd_stats, at)];
-
+
/* Add the pro-rated count for this cell to the overall total */
- total_count += cell_count * ratio;
- POSTGIS_DEBUGF(4, " cell (%d,%d), cell value %.6f, ratio %.6f", at[0], at[1], cell_count, ratio);
+ total_count += cell_count * ratio;
+ POSTGIS_DEBUGF(4, " cell (%d,%d), cell value %.6f, ratio %.6f", at[0], at[1], cell_count, ratio);
}
while ( nd_increment(&nd_ibox, nd_stats->ndims, at) );
nd_stats = pg_get_nd_stats_by_name(table_oid, att_text, mode, only_parent);
if ( ! nd_stats )
elog(ERROR, "stats for \"%s.%s\" do not exist", get_rel_name(table_oid), text2cstring(att_text));
-
+
/* Convert to JSON */
str = nd_stats_to_json(nd_stats);
json = cstring2text(str);
/* Retrieve the stats object */
nd_stats = pg_get_nd_stats_by_name(table_oid, att_text, mode, FALSE);
-
+
if ( ! nd_stats )
elog(ERROR, "stats for \"%s.%s\" do not exist", get_rel_name(table_oid), text2cstring(att_text));
elog(ERROR, "unable to calculate bounding box from geometry");
POSTGIS_DEBUGF(3, " %s", gbox_to_string(&gbox));
-
+
/* Do the estimation */
selectivity = estimate_selectivity(&gbox, nd_stats, mode);
-
+
pfree(nd_stats);
PG_RETURN_FLOAT8(selectivity);
}
text *modetxt = PG_GETARG_TEXT_P(4);
char *modestr = text2cstring(modetxt);
if ( modestr[0] == 'N' )
- mode = 0;
+ mode = 0;
}
/* Do the estimation */
selectivity = estimate_join_selectivity(nd_stats1, nd_stats2);
-
+
pfree(nd_stats1);
pfree(nd_stats2);
PG_RETURN_FLOAT8(selectivity);
List *args = (List *) PG_GETARG_POINTER(2);
/* int varRelid = PG_GETARG_INT32(3); */
int mode = PG_GETARG_INT32(4);
-
+
VariableStatData vardata;
ND_STATS *nd_stats = NULL;
Var *self;
GBOX search_box;
float8 selectivity = 0;
-
+
POSTGIS_DEBUG(2, "gserialized_gist_sel called");
/*
* calculation should take account of the incoming operator
* type and do the right thing.
*/
-
+
/* Fail if not a binary opclause (probably shouldn't happen) */
if (list_length(args) != 2)
{
/* Estimated extent only returns 2D bounds, so use mode 2 */
nd_stats = pg_get_nd_stats_by_name(tbl_oid, col, 2, only_parent);
-
+
/* Error out on no stats */
if ( ! nd_stats ) {
elog(WARNING, "stats for \"%s.%s\" do not exist", tbl, text2cstring(col));
if( a == NULL || b == NULL || n == NULL )
return FALSE;
-
+
n->xmax = Min(a->xmax, b->xmax);
n->ymax = Min(a->ymax, b->ymax);
n->xmin = Max(a->xmin, b->xmin);
if ( a == NULL )
return (float)0.0;
-
+
if ( (a->xmax <= a->xmin) || (a->ymax <= a->ymin) )
{
result = (float) 0.0;
elog(ERROR, "box2df_union_size received two null arguments");
return 0.0;
}
-
+
if ( a == NULL )
return box2df_size(b);
elog(ERROR, "box2df_union_edge received two null arguments");
return 0.0;
}
-
+
if ( a == NULL )
return box2df_edge(b);
BOX2DF b1, b2;
Datum gs1 = PG_GETARG_DATUM(0);
Datum gs2 = PG_GETARG_DATUM(1);
-
+
POSTGIS_DEBUG(3, "entered function");
/* Must be able to build box for each argument (ie, not empty geometry). */
if ( (gserialized_datum_get_box2df_p(gs1, &b1) == LW_SUCCESS) &&
(gserialized_datum_get_box2df_p(gs2, &b2) == LW_SUCCESS) )
- {
+ {
double distance = box2df_distance_leaf_centroid(&b1, &b2);
POSTGIS_DEBUGF(3, "got boxes %s and %s", box2df_to_string(&b1), box2df_to_string(&b2));
PG_RETURN_FLOAT8(distance);
BOX2DF b1, b2;
Datum gs1 = PG_GETARG_DATUM(0);
Datum gs2 = PG_GETARG_DATUM(1);
-
+
POSTGIS_DEBUG(3, "entered function");
/* Must be able to build box for each argument (ie, not empty geometry). */
if ( (gserialized_datum_get_box2df_p(gs1, &b1) == LW_SUCCESS) &&
(gserialized_datum_get_box2df_p(gs2, &b2) == LW_SUCCESS) )
- {
+ {
double distance = box2df_distance(&b1, &b2);
POSTGIS_DEBUGF(3, "got boxes %s and %s", box2df_to_string(&b1), box2df_to_string(&b2));
PG_RETURN_FLOAT8(distance);
case RTOldContainedByStrategyNumber:
retval = (bool) box2df_contains(query, key);
break;
-
+
/* To one side */
case RTAboveStrategyNumber:
retval = (bool) box2df_above(key, query);
break;
case RTOverLeftStrategyNumber:
retval = (bool) box2df_overleft(key, query);
- break;
-
+ break;
+
default:
retval = FALSE;
}
switch (strategy)
{
-
+
/* Basic overlaps */
case RTOverlapStrategyNumber:
retval = (bool) box2df_overlaps(key, query);
case RTOldContainedByStrategyNumber:
retval = (bool) box2df_overlaps(key, query);
break;
-
+
/* To one side */
case RTAboveStrategyNumber:
retval = (bool)(!box2df_overbelow(key, query));
case RTOverLeftStrategyNumber:
retval = (bool)(!box2df_right(key, query));
break;
-
+
default:
retval = FALSE;
}
POSTGIS_DEBUG(4, "[GIST] null query_gbox_index!");
PG_RETURN_FLOAT8(FLT_MAX);
}
-
+
/* Get the entry box */
entry_box = (BOX2DF*)DatumGetPointer(entry->key);
-
+
#if POSTGIS_PGSQL_VERSION >= 95
-
+
/* Box-style distance test */
if ( strategy == 14 ) /* operator <#> */
{
/* Calculate distance for internal nodes */
distance = (double)box2df_distance_node_centroid(entry_box, &query_box);
}
-#endif
-
+#endif
+
PG_RETURN_FLOAT8(distance);
}
size_union = box2df_union_size(gbox_index_orig, gbox_index_new);
size_orig = box2df_size(gbox_index_orig);
*result = size_union - size_orig;
-
+
/* REALM 0: No extension is required, volume is zero, return edge */
/* REALM 1: No extension is required, return nonzero area */
/* REALM 2: Area extension is zero, return nonzero edge extension */
/* REALM 3: Area extension is nonzero, return it */
-
+
if( *result == 0 )
{
- if (size_orig > 0)
+ if (size_orig > 0)
{
- *result = pack_float(size_orig, 1); /* REALM 1 */
+ *result = pack_float(size_orig, 1); /* REALM 1 */
}
- else
+ else
{
edge_union = box2df_union_edge(gbox_index_orig, gbox_index_new);
edge_orig = box2df_edge(gbox_index_orig);
POSTGIS_DEBUGF(5, "consider split: dimNum = %d, rightLower = %f, "
"minLeftCount = %d, leftUpper = %f, maxLeftCount = %d ",
dimNum, rightLower, minLeftCount, leftUpper, maxLeftCount);
-
+
/*
* Calculate entries distribution ratio assuming most uniform distribution
* of common entries.
*intervalsUpper;
CommonEntry *commonEntries;
int nentries;
-
+
POSTGIS_DEBUG(3, "[GIST] 'picksplit' entered");
memset(&context, 0, sizeof(ConsiderSplitContext));
else
adjustBox(&context.boundingBox, box);
}
-
+
POSTGIS_DEBUGF(4, "boundingBox is %s", box2df_to_string(
&context.boundingBox));
*/
POSTGIS_DEBUGF(4, "split direction: %d", context.dim);
-
+
/* Allocate vectors for results */
v->spl_left = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
v->spl_right = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
PLACE_RIGHT(box, i);
}
}
-
+
POSTGIS_DEBUGF(4, "leftBox is %s", box2df_to_string(leftBox));
POSTGIS_DEBUGF(4, "rightBox is %s", box2df_to_string(rightBox));
}
v->spl_ldatum = PointerGetDatum(leftBox);
v->spl_rdatum = PointerGetDatum(rightBox);
-
+
POSTGIS_DEBUG(4, "[GIST] 'picksplit' completed");
-
+
PG_RETURN_POINTER(v);
}
{
float sizeLR, sizeBT;
BOX2DF interLR, interBT;
-
+
if ( box2df_intersection(unionL, unionR, &interLR) == FALSE )
sizeLR = 0.0;
else
sizeBT = 0.0;
else
sizeBT = box2df_size(&interBT);
-
+
if (sizeLR < sizeBT)
direction = 'x';
else
v->spl_ldatum = PointerGetDatum(unionB);
v->spl_rdatum = PointerGetDatum(unionT);
}
-
+
POSTGIS_DEBUG(4, "[GIST] 'picksplit' completed");
-
+
PG_RETURN_POINTER(v);
}
/* Can't merge an unknown into any thing */
if( gidx_is_unknown(b_new) )
return;
-
+
/* Merge of unknown and known is known */
if( gidx_is_unknown(*b_union) )
{
/* Ensure the first argument has the higher dimensionality. */
static void gidx_dimensionality_check(GIDX **a, GIDX **b)
-{
+{
if ( GIDX_NDIMS(*a) < GIDX_NDIMS(*b) )
{
GIDX *tmp = *b;
{
return 0.0;
}
-
+
/* Ensure 'a' has the most dimensions. */
gidx_dimensionality_check(&a, &b);
int i;
int ndims_b;
POSTGIS_DEBUG(5, "entered function");
-
+
if ( (a == NULL) || (b == NULL) ) return FALSE;
if ( gidx_is_unknown(a) || gidx_is_unknown(b) )
assert( bmin > amax );
d = bmin - amax;
}
-
+
return d;
}
#endif /* POSTGIS_PGSQL_VERSION >= 96 */
{
return g;
}
-
+
gidx_expand(gidx, fdistance);
return gserialized_set_gidx(g, gidx);
{
double m1, m2;
int usebox = false;
-
+
if ( lwgeom_get_type(lw1) == POINTTYPE )
{
POINT4D p;
{
usebox = true;
}
-
+
if ( lwgeom_get_type(lw2) == POINTTYPE )
{
POINT4D p;
GIDX *bbox_out = (GIDX*)gidxmem;
int result = LW_SUCCESS;
int i;
-
+
POSTGIS_DEBUG(4, "[GIST] 'compress' function called");
/*
break;
default:
retval = FALSE;
- }
+ }
return (retval);
}
/* REALM 1: No extension is required, return nonzero area */
/* REALM 2: Area extension is zero, return nonzero edge extension */
/* REALM 3: Area extension is nonzero, return it */
-
+
if( *result == 0 )
{
- if (size_orig > 0)
+ if (size_orig > 0)
{
- *result = pack_float(size_orig, 1); /* REALM 1 */
+ *result = pack_float(size_orig, 1); /* REALM 1 */
}
- else
+ else
{
edge_union = gidx_union_edge(gbox_index_orig, gbox_index_new);
edge_orig = gidx_edge(gbox_index_orig);
{
*result = pack_float(*result, 3); /* REALM 3 */
}
-
+
POSTGIS_DEBUGF(4, "[GIST] union size (%.12f), original size (%.12f), penalty (%.12f)", size_union, size_orig, *result);
PG_RETURN_POINTER(result);
*recheck = true;
}
#endif
-
+
/* Get the entry box */
entry_box = (GIDX*)DatumGetPointer(entry->key);
#if POSTGIS_PGSQL_VERSION >= 95
bool *recheck = (bool *) PG_GETARG_POINTER(4);
#endif
-
+
double distance;
POSTGIS_DEBUG(4, "[GIST] 'distance' function called");
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("Geometry has M dimension but column does not" )));
}
-
+
return gser;
-
+
}
int srid = TYPMOD_GET_SRID(typmod);
/* Check the SRID is legal (geographic coordinates) */
srid_is_latlong(fcinfo, srid);
-
+
PG_RETURN_INT32(typmod);
}
/* can skip GUC definition in this case, so we just return. */
static const char *guc_name = "postgis.backend";
// const char *guc_installed = GetConfigOption(guc_name, TRUE, FALSE);
-
+
/* Uh oh, this GUC name already exists. Ordinarily we could just go on */
/* our way, but the way the postgis.backend works is by using the "assign" */
/* callback to change which backend is in use by flipping a global variable */
LWGEOM *lwgeom2 = lwgeom_from_gserialized(geom2);
error_if_srid_mismatch(lwgeom1->srid, lwgeom2->srid);
-
+
mindist = lwgeom_mindistance3d_tolerance(lwgeom1,lwgeom2,0.0);
PG_FREE_IF_COPY(geom1, 0);
double tmp;
GBOX box;
int i;
-
+
gbox_init(&box);
for(i = 0; str[i]; i++) {
str[i] = tolower(str[i]);
}
-
+
nitems = sscanf(str,"box(%lf %lf,%lf %lf)", &box.xmin, &box.ymin, &box.xmax, &box.ymax);
if (nitems != 4)
{
/* Cannot calculate box? */
if ( lwgeom_calculate_gbox(lwgeom, &gbox) == LW_FAILURE )
PG_RETURN_NULL();
-
+
/* Strip out higher dimensions */
FLAGS_SET_Z(gbox.flags, 0);
FLAGS_SET_M(gbox.flags, 0);
if ( rv == LW_FAILURE )
PG_RETURN_NULL();
-
+
result = box3d_from_gbox(&gbox);
result->srid = lwgeom->srid;
if (!box1 && !box0)
PG_RETURN_NULL();
-
+
result = palloc(sizeof(BOX3D));
result->xmax = Max(box0->xmax, box1->xmax);
result->ymax = Max(box0->ymax, box1->ymax);
result->ymin = Min(box0->ymin, box1->ymin);
result->zmin = Min(box0->zmin, box1->zmin);
result->srid = box0->srid;
-
+
PG_RETURN_POINTER(result);
}
if (cmp < 0)
PG_RETURN_BOOL(TRUE);
else
- PG_RETURN_BOOL(FALSE);
+ PG_RETURN_BOOL(FALSE);
}
PG_FUNCTION_INFO_V1(lwgeom_le);
if (cmp == 0)
PG_RETURN_BOOL(TRUE);
else
- PG_RETURN_BOOL(FALSE);
+ PG_RETURN_BOOL(FALSE);
}
PG_FUNCTION_INFO_V1(lwgeom_eq);
if (cmp == 0)
PG_RETURN_BOOL(TRUE);
else
- PG_RETURN_BOOL(FALSE);
+ PG_RETURN_BOOL(FALSE);
}
PG_FUNCTION_INFO_V1(lwgeom_ge);
if (cmp >= 0)
PG_RETURN_BOOL(TRUE);
else
- PG_RETURN_BOOL(FALSE);
+ PG_RETURN_BOOL(FALSE);
}
PG_FUNCTION_INFO_V1(lwgeom_gt);
if (cmp > 0)
PG_RETURN_BOOL(TRUE);
else
- PG_RETURN_BOOL(FALSE);
+ PG_RETURN_BOOL(FALSE);
}
PG_FUNCTION_INFO_V1(lwgeom_cmp);
*/
gser = PG_GETARG_GSERIALIZED_P(0);
geom = lwgeom_from_gserialized(gser);
-
+
/*
* Get the max vertices value
*/
if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
maxvertices = PG_GETARG_INT32(1);
-
+
/*
* Compute the subdivision of the geometry
*/
col = lwgeom_subdivide(geom, maxvertices);
-
+
if ( ! col )
SRF_RETURN_DONE(funcctx);
/* do when there is no more left */
SRF_RETURN_DONE(funcctx);
}
-
+
#endif /* POSTGIS_GEOS_VERSION >= 35 */
}
state->path[state->pathlen] = Int32GetDatum(state->pt);
pathpt[0] = PointerGetDatum(construct_array(state->path, state->pathlen+1,
INT4OID, state->typlen, state->byval, state->align));
-
+
pathpt[1] = PointerGetDatum(gserialized_from_lwgeom((LWGEOM*)lwpoint,0));
-
+
tuple = heap_form_tuple(funcctx->tuple_desc, pathpt, isnull);
result = HeapTupleGetDatum(tuple);
SRF_RETURN_NEXT(funcctx, result);
size_t len;
char *gml_id_buf, *prefix_buf;
text *prefix_text, *gml_id_text;
-
+
/* Get the version */
version = PG_GETARG_INT32(0);
kml = lwgeom_to_kml2(lwgeom, precision, prefix);
lwgeom_free(lwgeom);
PG_FREE_IF_COPY(geom, 1);
-
+
if( ! kml )
- PG_RETURN_NULL();
+ PG_RETURN_NULL();
result = cstring2text(kml);
lwfree(kml);
/* Get the geometry */
if ( PG_ARGISNULL(0) )
PG_RETURN_NULL();
-
+
geom = PG_GETARG_GSERIALIZED_P(0);
/* Retrieve precision if any (default is max) */
{
if ( option & 2 )
srs = getSRSbySRID(srid, true);
-
+
if ( option & 4 )
srs = getSRSbySRID(srid, false);
-
+
if ( !srs )
{
elog(ERROR,
/* retrieve option */
if (PG_NARGS() >3 && !PG_ARGISNULL(3))
option = PG_GETARG_INT32(3);
-
-
+
+
/* retrieve defid */
if (PG_NARGS() >4 && !PG_ARGISNULL(4))
if (srid == SRID_UNKNOWN) srs = NULL;
else if (option & 1) srs = getSRSbySRID(srid, false);
else srs = getSRSbySRID(srid, true);
-
+
if (option & LW_X3D_USE_GEOCOORDS) {
if (srid != 4326) {
PG_FREE_IF_COPY(geom, 0);
PG_RETURN_NULL();
}
}
-
+
x3d = lwgeom_to_x3d3(lwgeom, srs, precision,option, defid);
}
lwgeom = lwgeom_from_gserialized(geom);
PG_FREE_IF_COPY(geom, 0);
-
+
if (PG_NARGS() > 1 && !PG_ARGISNULL(1))
{
precision = PG_GETARG_INT32(1);
/* Can't simplify points! */
if ( type == POINTTYPE || type == MULTIPOINTTYPE )
PG_RETURN_POINTER(geom);
-
+
in = lwgeom_from_gserialized(geom);
out = lwgeom_simplify(in, dist, preserve_collapsed);
PG_RETURN_POINTER(result);
}
-
+
/***********************************************************************
* --strk@kbt.io;
***********************************************************************/
opa = ptarray_construct(lwgeom_has_z(geom), lwgeom_has_m(geom), 1);
ptarray_set_point4d(opa, 0, &pt);
-
+
point = lwpoint_construct(line->srid, NULL, opa);
PG_RETURN_POINTER(geometry_serialize(lwpoint_as_lwgeom(point)));
}
{
PG_RETURN_POINTER(in_geom);
}
-
+
/* Return input geometry if input grid is meaningless */
if ( grid.xsize==0 && grid.ysize==0 && grid.zsize==0 && grid.msize==0 )
{
#if POSTGIS_DEBUG_LEVEL >= 4
grid_print(&grid);
#endif
-
+
/* Return input geometry if input grid is meaningless */
if ( grid.xsize==0 && grid.ysize==0 && grid.zsize==0 && grid.msize==0 )
{
}
result = geometry_serialize(lwpoint_as_lwgeom(lwresult));
-
+
PG_RETURN_POINTER(result);
}
}
line_in = lwgeom_from_gserialized(geom_in);
- geom_out = lwgeom_clip_to_ordinate_range(line_in, ordinate, from, to, offset);
+ geom_out = lwgeom_clip_to_ordinate_range(line_in, ordinate, from, to, offset);
lwgeom_free(line_in);
PG_FREE_IF_COPY(geom_in, 0);
}
line_in = lwgeom_from_gserialized(geom_in);
- geom_out = lwgeom_clip_to_ordinate_range(line_in, ordinate, from, to, offset);
+ geom_out = lwgeom_clip_to_ordinate_range(line_in, ordinate, from, to, offset);
lwgeom_free(line_in);
PG_FREE_IF_COPY(geom_in, 0);
elog(ERROR,"ST_InterpolatePoint only accepts geometries that have an M dimension");
PG_RETURN_NULL();
}
-
+
lwpoint = lwgeom_as_lwpoint(lwgeom_from_gserialized(gser_point));
lwline = lwgeom_from_gserialized(gser_line);
-
+
PG_RETURN_FLOAT8(lwgeom_interpolate_point(lwline, lwpoint));
}
lwpgerror("locate_between_m: 2nd arg must be bigger then 1st arg");
PG_RETURN_NULL();
}
-
+
/*
* Return error if input doesn't have a measure
*/
* 'LINESTRING (0 0, 50 200, 100 0, 150 200, 200 0)'::geometry,
* 'LINESTRING (0 200, 200 150, 0 100, 200 50, 0 0)'::geometry, 0.5);
*/
-
+
PG_FUNCTION_INFO_V1(ST_FrechetDistance);
Datum ST_FrechetDistance(PG_FUNCTION_ARGS)
{
double densifyFrac;
double result;
int retcode;
-
+
geom1 = PG_GETARG_GSERIALIZED_P(0);
geom2 = PG_GETARG_GSERIALIZED_P(1);
densifyFrac = PG_GETARG_FLOAT8(2);
-
+
if ( gserialized_is_empty(geom1) || gserialized_is_empty(geom2) )
PG_RETURN_NULL();
-
+
initGEOS(lwpgnotice, lwgeom_geos_error);
-
+
g1 = (GEOSGeometry *)POSTGIS2GEOS(geom1);
if ( 0 == g1 ) /* exception thrown at construction */
{
HANDLE_GEOS_ERROR("First argument geometry could not be converted to GEOS");
PG_RETURN_NULL();
}
-
+
g2 = (GEOSGeometry *)POSTGIS2GEOS(geom2);
if ( 0 == g2 ) /* exception thrown at construction */
{
GEOSGeom_destroy(g1);
GEOSGeom_destroy(g2);
-
+
if (retcode == 0)
{
HANDLE_GEOS_ERROR("GEOSFrechetDistance");
PG_RETURN_NULL(); /*never get here */
}
-
+
PG_FREE_IF_COPY(geom1, 0);
PG_FREE_IF_COPY(geom2, 1);
-
+
PG_RETURN_FLOAT8(result);
#endif /* POSTGIS_GEOS_VERSION >= 37 */
array = PG_GETARG_ARRAYTYPE_P(0);
nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array));
-
+
/* Empty array? Null return */
if ( nelems == 0 ) PG_RETURN_NULL();
/* Quick scan for nulls */
-#if POSTGIS_PGSQL_VERSION >= 95
+#if POSTGIS_PGSQL_VERSION >= 95
iterator = array_create_iterator(array, 0, NULL);
#else
iterator = array_create_iterator(array, 0);
/* Skip null array items */
if ( isnull )
continue;
-
+
count++;
}
array_free_iterator(iterator);
-
-
+
+
/* All-nulls? Return null */
if ( count == 0 )
PG_RETURN_NULL();
-
+
/* One geom, good geom? Return it */
if ( count == 1 && nelems == 1 )
PG_RETURN_POINTER((GSERIALIZED *)(ARR_DATA_PTR(array)));
-
+
/* Ok, we really need GEOS now ;) */
initGEOS(lwpgnotice, lwgeom_geos_error);
** We need to convert the array of GSERIALIZED into a GEOS collection.
** First make an array of GEOS geometries.
*/
-#if POSTGIS_PGSQL_VERSION >= 95
+#if POSTGIS_PGSQL_VERSION >= 95
iterator = array_create_iterator(array, 0, NULL);
#else
iterator = array_create_iterator(array, 0);
/* Skip null array items */
if ( isnull )
continue;
-
+
gser_in = (GSERIALIZED *)DatumGetPointer(value);
/* Check for SRID mismatch in array elements */
gser_input = PG_GETARG_GSERIALIZED_P(0);
npoints = DatumGetInt32(DirectFunctionCall1(numeric_int4, PG_GETARG_DATUM(1)));
-
+
/* Smartasses get nothing back */
if (npoints < 0)
PG_RETURN_NULL();
-
+
/* Types get checked in the code, we'll keep things small out there */
lwgeom_input = lwgeom_from_gserialized(gser_input);
lwgeom_result = (LWGEOM*)lwgeom_to_points(lwgeom_input, npoints);
lwgeom_free(lwgeom_input);
PG_FREE_IF_COPY(gser_input, 0);
-
+
/* Return null as null */
if (!lwgeom_result)
PG_RETURN_NULL();
lwgeom_input = lwgeom_from_gserialized(gser_input);
if ( ! lwgeom_input )
lwpgerror("ST_OffsetCurve: lwgeom_from_gserialized returned NULL");
-
+
/* For empty inputs, just echo them back */
if ( lwgeom_is_empty(lwgeom_input) )
PG_RETURN_POINTER(gser_input);
lwpoint_free(lwp);
PG_RETURN_POINTER(result);
}
-
+
type = gserialized_get_type(geom) ;
/* Converting curve geometry to linestring if necessary*/
if(type == CIRCSTRINGTYPE || type == COMPOUNDTYPE )
lwgeom_free(igeom);
if (linear_geom == NULL)
PG_RETURN_NULL();
-
+
geom = geometry_serialize(linear_geom);
lwgeom_free(linear_geom);
}
result = geometry_serialize(lwresult) ;
lwgeom_free(lwresult) ;
PG_RETURN_POINTER(result);
-
+
#endif /* POSTGIS_GEOS_VERSION >= 35 */
}
GSERIALIZED* gpoint = is_point(geom1) ? geom1 : geom2;
RTREE_POLY_CACHE* cache = GetRtreeCache(fcinfo, gpoly);
int retval;
-
+
POSTGIS_DEBUG(3, "Point in Polygon test requested...short-circuiting.");
if (gserialized_get_type(gpoint) == POINTTYPE)
{
}
else if (gserialized_get_type(gpoint) == MULTIPOINTTYPE)
{
- LWMPOINT* mpoint = lwgeom_as_lwmpoint(lwgeom_from_gserialized(gpoint));
+ LWMPOINT* mpoint = lwgeom_as_lwmpoint(lwgeom_from_gserialized(gpoint));
uint32_t i;
int found_completely_inside = LW_FALSE;
}
else if (gserialized_get_type(gpoint) == MULTIPOINTTYPE)
{
- LWMPOINT* mpoint = lwgeom_as_lwmpoint(lwgeom_from_gserialized(gpoint));
+ LWMPOINT* mpoint = lwgeom_as_lwmpoint(lwgeom_from_gserialized(gpoint));
uint32_t i;
retval = LW_TRUE;
}
else if (gserialized_get_type(gpoint) == MULTIPOINTTYPE)
{
- LWMPOINT* mpoint = lwgeom_as_lwmpoint(lwgeom_from_gserialized(gpoint));
+ LWMPOINT* mpoint = lwgeom_as_lwmpoint(lwgeom_from_gserialized(gpoint));
uint32_t i;
retval = LW_FALSE;
bool isnull;
uint32_t nelems_not_null = 0;
-#if POSTGIS_PGSQL_VERSION >= 95
+#if POSTGIS_PGSQL_VERSION >= 95
iterator = array_create_iterator(array, 0, NULL);
#else
iterator = array_create_iterator(array, 0);
}
return NULL;
}
-
+
i++;
}
#else /* POSTGIS_GEOS_VERSION >= 35 */
GSERIALIZED* input;
GSERIALIZED* clip;
- GSERIALIZED* result;
+ GSERIALIZED* result;
LWGEOM* lwgeom_input;
LWGEOM* lwgeom_result;
double tolerance;
PG_RETURN_NULL();
}
return_polygons = PG_GETARG_BOOL(3);
-
+
/* Read our clipping envelope, if applicable. */
custom_clip_envelope = !PG_ARGISNULL(1);
if (custom_clip_envelope) {
{
PrepGeomCache* prepcache = (PrepGeomCache*)cache;
PrepGeomHashEntry* pghe;
-
+
/*
* First time through? allocate the global hash.
*/
pghe.context = prepcache->context_callback;
pghe.geom = 0;
pghe.prepared_geom = 0;
- AddPrepGeomHashEntry( pghe );
+ AddPrepGeomHashEntry( pghe );
}
-
+
/*
* Hum, we shouldn't be asked to build a new cache on top of
* an existing one. Error.
*/
if (lwgeom_get_type(lwgeom) == POINTTYPE || lwgeom_get_type(lwgeom) == MULTIPOINTTYPE)
return LW_FAILURE;
-
+
prepcache->geom = LWGEOM2GEOS( lwgeom , 0);
if ( ! prepcache->geom ) return LW_FAILURE;
prepcache->prepared_geom = GEOSPrepare( prepcache->geom );
if ( ! prepcache->prepared_geom ) return LW_FAILURE;
prepcache->argnum = cache->argnum;
-
+
/*
* In order to find the objects we need to destroy, we keep
* extra references in a global hash object.
lwpgerror("PrepGeomCacheBuilder failed to find hash entry for context %p", prepcache->context_callback);
return LW_FAILURE;
}
-
+
pghe->geom = prepcache->geom;
pghe->prepared_geom = prepcache->prepared_geom;
prepcache->argnum = 0;
prepcache->prepared_geom = 0;
prepcache->geom = 0;
-
+
return LW_SUCCESS;
}
/* Get the geojson stream */
if (PG_ARGISNULL(0))
PG_RETURN_NULL();
-
+
geojson_input = PG_GETARG_TEXT_P(0);
geojson = text2cstring(geojson_input);
/* HasZ?, !HasM, 1 Point */
dpa = ptarray_construct_empty(1, 0, 1);
-
+
x = y = z = false;
for (xyz = xnode->children ; xyz != NULL ; xyz = xyz->next)
{
if (xnode->children == NULL)
return lwline_as_lwgeom(lwline_construct_empty(*root_srid, 0, 0));
-
+
pa = parse_gml_data(xnode->children, hasz, root_srid);
if (pa->npoints < 2) gml_lwpgerror("invalid GML representation", 36);
if (srs.reverse_axis)
ppa[0] = ptarray_flip_coordinates(ppa[0]);
-
+
if (srs.srid != *root_srid && *root_srid != SRID_UNKNOWN)
gml_reproject_pa(ppa[0], srs.srid, *root_srid);
-
+
geom = (LWGEOM *) lwpoly_construct(*root_srid, NULL, 1, ppa);
return geom;
/* Found an <exterior> or <outerBoundaryIs> but no rings?!? We're outa here! */
if ( ! ppa )
- gml_lwpgerror("invalid GML representation", 43);
+ gml_lwpgerror("invalid GML representation", 43);
for (ring=1, xa = xnode->children ; xa != NULL ; xa = xa->next)
{
outer_rings++;
}
}
-
+
if (outer_rings != 1)
lwpgerror("invalid KML representation");
-
+
for (ring=1, xa = xnode->children ; xa != NULL ; xa = xa->next)
{
char *tmp = str;
while ( tmp && *tmp != ';' )
tmp++;
-
+
/* Check next character to see if we have WKB */
if ( tmp && *(tmp+1) == '0' )
{
srid = atoi(tmp);
}
}
-
+
/* WKB? Let's find out. */
if ( str[0] == '0' )
{
}
lwgeom = lwg_parser_result.geom;
if ( lwgeom_needs_bbox(lwgeom) )
- lwgeom_add_bbox(lwgeom);
+ lwgeom_add_bbox(lwgeom);
ret = geometry_serialize(lwgeom);
lwgeom_parser_result_free(&lwg_parser_result);
}
/* Don't free the parser result (and hence lwgeom) until we have done */
/* the typemod check with lwgeom */
-
+
PG_RETURN_POINTER(ret);
}
lwgeom = lwgeom_from_gserialized(geom);
hexwkb = lwgeom_to_hexwkb(lwgeom, WKB_EXTENDED, &hexwkb_size);
lwgeom_free(lwgeom);
-
+
PG_RETURN_CSTRING(hexwkb);
}
lwgeom = lwgeom_from_gserialized(geom);
hexwkb = lwgeom_to_hexwkb(lwgeom, variant | WKB_EXTENDED, &hexwkb_size);
lwgeom_free(lwgeom);
-
+
/* Prepare the PgSQL text return type */
text_size = hexwkb_size - 1 + VARHDRSZ;
result = palloc(text_size);
memcpy(VARDATA(result), hexwkb, hexwkb_size - 1);
SET_VARSIZE(result, text_size);
-
+
/* Clean up and return */
pfree(hexwkb);
PG_FREE_IF_COPY(geom, 0);
lwgeom = lwgeom_from_gserialized(geom);
hexwkb = lwgeom_to_hexwkb(lwgeom, WKB_EXTENDED, &hexwkb_size);
lwgeom_free(lwgeom);
-
+
/* Copy into text obect */
result = cstring2text(hexwkb);
pfree(hexwkb);
-
+
/* Clean up and return */
PG_FREE_IF_COPY(geom, 0);
PG_RETURN_TEXT_P(result);
GSERIALIZED *geom;
LWGEOM *lwgeom;
uint8_t *wkb = (uint8_t*)VARDATA(bytea_wkb);
-
+
lwgeom = lwgeom_from_wkb(wkb, VARSIZE(bytea_wkb)-VARHDRSZ, LW_PARSER_CHECK_ALL);
-
+
if ( ( PG_NARGS()>1) && ( ! PG_ARGISNULL(1) ))
{
srid = PG_GETARG_INT32(1);
GSERIALIZED *geom;
LWGEOM *lwgeom;
uint8_t *twkb = (uint8_t*)VARDATA(bytea_twkb);
-
+
lwgeom = lwgeom_from_twkb(twkb, VARSIZE(bytea_twkb)-VARHDRSZ, LW_PARSER_CHECK_ALL);
if ( lwgeom_needs_bbox(lwgeom) )
wkb = lwgeom_to_wkb(lwgeom, variant | WKB_EXTENDED , &wkb_size);
lwgeom_free(lwgeom);
-
+
/* Prepare the PgSQL text return type */
result = palloc(wkb_size + VARHDRSZ);
memcpy(VARDATA(result), wkb, wkb_size);
SET_VARSIZE(result, wkb_size+VARHDRSZ);
-
+
/* Clean up and return */
pfree(wkb);
PG_FREE_IF_COPY(geom, 0);
uint8_t variant = 0;
bytea *result;
srs_precision sp;
-
+
/*check for null input since we cannot have the sql-function as strict.
- That is because we use null as default for optional ID*/
+ That is because we use null as default for optional ID*/
if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
-
+
geom = PG_GETARG_GSERIALIZED_P(0);
/* Read sensible precision defaults (about one meter) given the srs */
sp = srid_axis_precision(fcinfo, gserialized_get_srid(geom), TWKB_DEFAULT_PRECISION);
-
+
/* If user specified XY precision, use it */
if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
sp.precision_xy = PG_GETARG_INT32(1);
/* If user wants registered twkb sizes */
if ( PG_NARGS() > 4 && ! PG_ARGISNULL(4) && PG_GETARG_BOOL(4) )
variant |= TWKB_SIZE;
-
+
/* If user wants bounding boxes */
if ( PG_NARGS() > 5 && ! PG_ARGISNULL(5) && PG_GETARG_BOOL(5) )
variant |= TWKB_BBOX;
lwgeom = lwgeom_from_gserialized(geom);
twkb = lwgeom_to_twkb(lwgeom, variant, sp.precision_xy, sp.precision_z, sp.precision_m, &twkb_size);
lwgeom_free(lwgeom);
-
+
/* Prepare the PgSQL text return type */
result = palloc(twkb_size + VARHDRSZ);
memcpy(VARDATA(result), twkb, twkb_size);
SET_VARSIZE(result, twkb_size + VARHDRSZ);
-
+
pfree(twkb);
PG_FREE_IF_COPY(geom, 0);
PG_RETURN_BYTEA_P(result);
num_geoms = ArrayGetNItems(ARR_NDIM(arr_geoms), ARR_DIMS(arr_geoms));
num_ids = ArrayGetNItems(ARR_NDIM(arr_ids), ARR_DIMS(arr_ids));
-
+
if ( num_geoms != num_ids )
{
elog(ERROR, "size of geometry[] and integer[] arrays must match");
/* Loop through array and build a collection of geometry and */
/* a simple array of ids. If either side is NULL, skip it */
-#if POSTGIS_PGSQL_VERSION >= 95
+#if POSTGIS_PGSQL_VERSION >= 95
iter_geoms = array_create_iterator(arr_geoms, 0, NULL);
iter_ids = array_create_iterator(arr_ids, 0, NULL);
#else
geom = lwgeom_from_gserialized((GSERIALIZED*)DatumGetPointer(val_geom));
uid = DatumGetInt64(val_id);
-
+
/* Construct collection/idlist first time through */
if ( ! col )
{
if ( ! idlist )
idlist = palloc0(num_geoms * sizeof(int64_t));
-
+
/*Check if there is differences in dimmenstionality*/
if( lwgeom_has_z(geom)!=has_z || lwgeom_has_m(geom)!=has_m)
{
elog(ERROR, "Geometries have differenct dimensionality");
PG_FREE_IF_COPY(arr_geoms, 0);
PG_FREE_IF_COPY(arr_ids, 1);
- PG_RETURN_NULL();
+ PG_RETURN_NULL();
}
/* Store the values */
lwcollection_add_lwgeom(col, geom);
idlist[i++] = uid;
-
+
/* Grab the geometry type and note if all geometries share it */
/* If so, we can make this a homogeneous collection and save some space */
if ( lwgeom_get_type(geom) != subtype && subtype )
}
array_free_iterator(iter_geoms);
array_free_iterator(iter_ids);
-
+
if(i==0)
{
elog(NOTICE, "No valid geometry - id pairs found");
PG_FREE_IF_COPY(arr_geoms, 0);
PG_FREE_IF_COPY(arr_ids, 1);
- PG_RETURN_NULL();
+ PG_RETURN_NULL();
}
if ( is_homogeneous )
{
/* Read sensible precision defaults (about one meter) given the srs */
sp = srid_axis_precision(fcinfo, lwgeom_get_srid(lwcollection_as_lwgeom(col)), TWKB_DEFAULT_PRECISION);
-
+
/* If user specified XY precision, use it */
if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
sp.precision_xy = PG_GETARG_INT32(2);
/* We are building an ID'ed output */
variant = TWKB_ID;
-
+
/* If user wants registered twkb sizes */
if ( PG_NARGS() > 5 && ! PG_ARGISNULL(5) && PG_GETARG_BOOL(5) )
variant |= TWKB_SIZE;
-
+
/* If user wants bounding boxes */
if ( PG_NARGS() > 6 && ! PG_ARGISNULL(6) && PG_GETARG_BOOL(6) )
variant |= TWKB_BBOX;
idlist, variant,
sp.precision_xy, sp.precision_z, sp.precision_m,
&twkb_size);
-
+
/* Convert to a bytea return type */
result = palloc(twkb_size + VARHDRSZ);
memcpy(VARDATA(result), twkb, twkb_size);
SET_VARSIZE(result, twkb_size + VARHDRSZ);
-
+
/* Clean up */
pfree(twkb);
pfree(idlist);
lwcollection_free(col);
PG_FREE_IF_COPY(arr_geoms, 0);
PG_FREE_IF_COPY(arr_ids, 1);
-
+
PG_RETURN_BYTEA_P(result);
}
lwgeom = lwgeom_from_gserialized(geom);
lwgeom_add_bbox(lwgeom);
result = geometry_serialize(lwgeom);
-
+
PG_FREE_IF_COPY(geom, 0);
PG_RETURN_POINTER(result);
}
/* No box? we're done already! */
if ( ! gserialized_has_bbox(geom) )
PG_RETURN_POINTER(geom);
-
+
PG_RETURN_POINTER(gserialized_drop_gidx(geom));
}
/* Unwrap the PgSQL text type into a cstring */
wkt = text2cstring(wkt_text);
-
+
/* Now we call over to the geometry_in function */
result = DirectFunctionCall1(LWGEOM_in, CStringGetDatum(wkt));
if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) ) {
geom_typmod = PG_GETARG_INT32(2);
}
-
+
lwgeom = lwgeom_from_wkb((uint8_t*)buf->data, buf->len, LW_PARSER_CHECK_ALL);
if ( lwgeom_needs_bbox(lwgeom) )
POSTGIS_DEBUG(3, "typmod was -1");
}
-
+
PG_RETURN_POINTER(geom);
}
/* Build up the output string */
strncat(type_str, "ST_", type_str_len);
strncat(type_str, lwtype_name(gserialized_get_type(gser)), type_str_len - 3);
-
+
/* Build a text type to store things in */
type_text = cstring2text(type_str);
LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
int count = -1;
int type = lwgeom->type;
-
+
if ( type == LINETYPE || type == CIRCSTRINGTYPE || type == COMPOUNDTYPE )
count = lwgeom_count_vertices(lwgeom);
dimension = lwgeom_dimension(lwgeom);
lwgeom_free(lwgeom);
PG_FREE_IF_COPY(geom, 0);
-
+
if ( dimension < 0 )
{
elog(NOTICE, "Could not compute geometry dimensions");
elog(ERROR, "ExteriorRing: geom is not a polygon");
PG_RETURN_NULL();
}
-
+
lwgeom = lwgeom_from_gserialized(geom);
-
+
if( lwgeom_is_empty(lwgeom) )
{
line = lwline_construct_empty(lwgeom->srid,
result = curvepoly->nrings - 1;
}
}
-
+
lwgeom_free(lwgeom);
PG_FREE_IF_COPY(geom, 0);
-
+
if ( result < 0 )
PG_RETURN_NULL();
PG_FREE_IF_COPY(geom, 0);
PG_RETURN_NULL();
}
-
+
lwgeom = lwgeom_from_gserialized(geom);
if( lwgeom_is_empty(lwgeom) )
{
PG_FREE_IF_COPY(geom, 0);
PG_RETURN_NULL();
}
-
+
if ( type == POLYGONTYPE)
{
poly = lwgeom_as_lwpoly(lwgeom_from_gserialized(geom));
if (where < 1)
PG_RETURN_NULL();
}
-
+
if ( type == LINETYPE || type == CIRCSTRINGTYPE )
{
/* OGC index starts at one, so we substract first. */
else if ( type == COMPOUNDTYPE )
{
lwpoint = lwcompound_get_lwpoint((LWCOMPOUND*)lwgeom, where - 1);
- }
+ }
lwgeom_free(lwgeom);
PG_FREE_IF_COPY(geom, 0);
lwgeom = lwgeom_from_gserialized(geom);
point = lwgeom_as_lwpoint(lwgeom);
-
+
if ( lwgeom_is_empty(lwgeom) )
PG_RETURN_NULL();
lwgeom = lwgeom_from_gserialized(geom);
point = lwgeom_as_lwpoint(lwgeom);
-
+
if ( lwgeom_is_empty(lwgeom) )
PG_RETURN_NULL();
lwgeom = lwgeom_from_gserialized(geom);
point = lwgeom_as_lwpoint(lwgeom);
-
+
if ( lwgeom_is_empty(lwgeom) )
PG_RETURN_NULL();
lwgeom = lwgeom_from_gserialized(geom);
point = lwgeom_as_lwpoint(lwgeom);
-
+
if ( lwgeom_is_empty(lwgeom) )
PG_RETURN_NULL();
GSERIALIZED *geom;
LWGEOM *lwgeom;
uint8_t *wkb = (uint8_t*)VARDATA(bytea_wkb);
-
+
lwgeom = lwgeom_from_wkb(wkb, VARSIZE(bytea_wkb)-VARHDRSZ, LW_PARSER_CHECK_ALL);
-
+
if ( lwgeom_needs_bbox(lwgeom) )
lwgeom_add_bbox(lwgeom);
-
+
geom = geometry_serialize(lwgeom);
lwgeom_free(lwgeom);
PG_FREE_IF_COPY(bytea_wkb, 0);
-
+
if ( gserialized_get_srid(geom) != SRID_UNKNOWN )
{
elog(WARNING, "OGC WKB expected, EWKB provided - use GeometryFromEWKB() for this");
}
-
+
if ( PG_NARGS() > 1 )
{
srid = PG_GETARG_INT32(1);
variant = variant | WKB_NDR;
}
}
-
+
/* Write to WKB and free the geometry */
wkb = lwgeom_to_wkb(lwgeom, variant, &wkb_size);
lwgeom_free(lwgeom);
GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
LWGEOM *lwgeom = lwgeom_from_gserialized(geom);
int closed = lwgeom_is_closed(lwgeom);
-
+
lwgeom_free(lwgeom);
PG_FREE_IF_COPY(geom, 0);
PG_RETURN_BOOL(closed);
-}
+}
getPoint4d_p(pa, startPoint, &tmp);
value1 = tmp.y;
ptarray_append_point(npa,&tmp,LW_TRUE);
-
+
getPoint4d_p(pa, startPoint+1, &tmp);
value2 = tmp.y;
ptarray_append_point(npa,&tmp,LW_TRUE);
line = lwline_construct(SRID_UNKNOWN, NULL, npa);
-
+
parent = lwalloc(sizeof(RTREE_NODE));
parent->interval = RTreeCreateInterval(value1, value2);
parent->segment = line;
int nrings;
RTreeGeomCache* rtree_cache = (RTreeGeomCache*)cache;
RTREE_POLY_CACHE* currentCache;
-
+
if ( ! cache )
return LW_FAILURE;
lwpgerror("RTreeBuilder asked to build index where one already exists.");
return LW_FAILURE;
}
-
+
if (lwgeom->type == MULTIPOLYGONTYPE)
{
POSTGIS_DEBUG(2, "RTreeBuilder MULTIPOLYGON");
lwpgerror("RTreeBuilder got asked to build index on non-polygon");
return LW_FAILURE;
}
- return LW_SUCCESS;
+ return LW_SUCCESS;
}
/**
RTreeFreer(GeomCache* cache)
{
RTreeGeomCache* rtree_cache = (RTreeGeomCache*)cache;
-
+
if ( ! cache )
return LW_FAILURE;
-
+
if ( rtree_cache->index )
{
RTreeCacheClear(rtree_cache->index);
}
-PG_FUNCTION_INFO_V1(sfcgal_tesselate);
+PG_FUNCTION_INFO_V1(sfcgal_tesselate);
Datum sfcgal_tesselate(PG_FUNCTION_ARGS)
{
GSERIALIZED *input, *output;
}
-PG_FUNCTION_INFO_V1(sfcgal_triangulate);
+PG_FUNCTION_INFO_V1(sfcgal_triangulate);
Datum sfcgal_triangulate(PG_FUNCTION_ARGS)
{
GSERIALIZED *input, *output;
}
-PG_FUNCTION_INFO_V1(sfcgal_force_lhr);
+PG_FUNCTION_INFO_V1(sfcgal_force_lhr);
Datum sfcgal_force_lhr(PG_FUNCTION_ARGS)
{
GSERIALIZED *input, *output;
}
-PG_FUNCTION_INFO_V1(sfcgal_straight_skeleton);
+PG_FUNCTION_INFO_V1(sfcgal_straight_skeleton);
Datum sfcgal_straight_skeleton(PG_FUNCTION_ARGS)
{
GSERIALIZED *input, *output;
}
-PG_FUNCTION_INFO_V1(sfcgal_intersection);
+PG_FUNCTION_INFO_V1(sfcgal_intersection);
Datum sfcgal_intersection(PG_FUNCTION_ARGS)
{
GSERIALIZED *input0, *input1, *output;
}
-PG_FUNCTION_INFO_V1(sfcgal_intersection3D);
+PG_FUNCTION_INFO_V1(sfcgal_intersection3D);
Datum sfcgal_intersection3D(PG_FUNCTION_ARGS)
{
GSERIALIZED *input0, *input1, *output;
PG_RETURN_POINTER(output);
}
-PG_FUNCTION_INFO_V1(sfcgal_difference);
+PG_FUNCTION_INFO_V1(sfcgal_difference);
Datum sfcgal_difference(PG_FUNCTION_ARGS)
{
GSERIALIZED *input0, *input1, *output;
}
-PG_FUNCTION_INFO_V1(sfcgal_difference3D);
+PG_FUNCTION_INFO_V1(sfcgal_difference3D);
Datum sfcgal_difference3D(PG_FUNCTION_ARGS)
{
GSERIALIZED *input0, *input1, *output;
PG_RETURN_POINTER(output);
}
-PG_FUNCTION_INFO_V1(sfcgal_union);
+PG_FUNCTION_INFO_V1(sfcgal_union);
Datum sfcgal_union(PG_FUNCTION_ARGS)
{
GSERIALIZED *input0, *input1, *output;
}
-PG_FUNCTION_INFO_V1(sfcgal_union3D);
+PG_FUNCTION_INFO_V1(sfcgal_union3D);
Datum sfcgal_union3D(PG_FUNCTION_ARGS)
{
GSERIALIZED *input0, *input1, *output;
PG_RETURN_FLOAT8(result);
}
-PG_FUNCTION_INFO_V1(sfcgal_minkowski_sum);
+PG_FUNCTION_INFO_V1(sfcgal_minkowski_sum);
Datum sfcgal_minkowski_sum(PG_FUNCTION_ARGS)
{
GSERIALIZED *input0, *input1, *output;
PG_RETURN_POINTER(result);
}
-PG_FUNCTION_INFO_V1(sfcgal_is_solid);
+PG_FUNCTION_INFO_V1(sfcgal_is_solid);
Datum sfcgal_is_solid(PG_FUNCTION_ARGS)
{
int result;
PG_RETURN_BOOL(result);
}
-PG_FUNCTION_INFO_V1(sfcgal_make_solid);
+PG_FUNCTION_INFO_V1(sfcgal_make_solid);
Datum sfcgal_make_solid(PG_FUNCTION_ARGS)
{
GSERIALIZED *output;
/* Get #LWGEOM structures */
lwgeom1 = lwgeom_from_gserialized(geom1);
lwgeom2 = lwgeom_from_gserialized(geom2);
-
+
/* We are going to be calculating geodetic distances */
lwgeom_set_geodetic(lwgeom1, LW_TRUE);
lwgeom_set_geodetic(lwgeom2, LW_TRUE);
elog(ERROR,"Failure reading projections from spatial_ref_sys.");
PG_RETURN_NULL();
}
-
+
/* now we have a geometry, and input/output PJ structs. */
lwgeom = lwgeom_from_gserialized(geom);
lwgeom_transform(lwgeom, input_pj, output_pj);
/* pfree(input_proj4); */
pfree(output_proj4);
pfree(geom);
-
+
elog(ERROR,
"transform_geom: could not parse proj4 string '%s' %s",
input_proj4, pj_errstr);
{
WindowObject win_obj = PG_WINDOW_OBJECT();
uint32_t row = WinGetCurrentPosition(win_obj);
- uint32_t ngeoms = WinGetPartitionRowCount(win_obj);
+ uint32_t ngeoms = WinGetPartitionRowCount(win_obj);
dbscan_context* context = WinGetPartitionLocalMemory(win_obj, sizeof(dbscan_context) + ngeoms * sizeof(dbscan_cluster_result));
if (row == 0) /* beginning of the partition; do all of the work now */
width = rt_band_get_width(band);
height = rt_band_get_height(band);
-
+
/* top */
for (y = 0; y < height; y++) {
for (offset = 0; offset < 3; offset++) {
}
else
nband = -1;
-
+
RASTER_DEBUGF(3, "rt_raster_get_perimeter: nband, numband = %d, %d", nband, numband);
_nband = rtalloc(sizeof(uint16_t) * numband);
OGR_Fld_Destroy(hFldDfn);
OGR_DS_DeleteLayer(memdatasource, 0);
OGRReleaseDataSource(memdatasource);
-
+
return NULL;
}
}
case ET_LAST:
if (i < 0) i = itrcount - 1;
-
+
/* input raster is null, return NULL */
if (_param->raster[i] == NULL) {
RASTER_DEBUGF(3, "returning NULL as %s raster is NULL and extent type is ET_%s",
_rti_iterator_arg_destroy(_param);
rt_raster_destroy(rtnrast);
-
+
return ES_ERROR;
}
_param->band.isnodata[i]
) {
RASTER_DEBUG(4, "empty raster, band does not exist or band is NODATA. using empty values and NODATA");
-
+
x = _x;
y = _y;
return ES_ERROR;
}
}
-
+
/* callback */
RASTER_DEBUG(4, "calling callback function");
value = 0;
rterror("rt_pixel_set_array: mask dimensions %d x %d do not match given dims %d x %d", mask->dimx, mask->dimy, dim[0], dim[1]);
return ES_ERROR;
}
-
+
if (mask->values == NULL || mask->nodata == NULL) {
rterror("rt_pixel_set_array: Invalid mask");
return ES_ERROR;
rtdealloc(values);
rtdealloc(nodatas);
-
+
return ES_ERROR;
}
rt_raster_get_geotransform_matrix(raster, _gt);
else
memcpy(_gt, gt, sizeof(double) * 6);
-
+
if (!GDALInvGeoTransform(_gt, igt)) {
rterror("rt_raster_get_inverse_geotransform_matrix: Could not compute inverse geotransform matrix");
return ES_ERROR;
raster->width--;
else
raster->height--;
-
+
/* construct sgeom from raster */
if ((rt_raster_get_convex_hull(raster, &geom) != ES_NONE) || geom == NULL) {
rterror("rt_raster_compute_skewed_raster: Could not build skewed extent's geometry for minimizing dimensions");
}
pts = rings[0];
-
+
/* Upper-left corner (first and last points) */
p4d.x = env.MinX;
p4d.y = env.MaxY;
elog(ERROR, "RASTER_fromGDALRaster: Could not open bytea with GDAL. Check that the bytea is of a GDAL supported format");
PG_RETURN_NULL();
}
-
+
#if POSTGIS_DEBUG_LEVEL > 3
{
GDALDriverH hdrv = GDALGetDatasetDriver(hdsSrc);
formattext = PG_GETARG_TEXT_P(1);
format = text_to_cstring(formattext);
}
-
+
POSTGIS_RT_DEBUGF(3, "RASTER_asGDALRaster: Arg 1 (format) is %s", format);
/* process options */
bandindex = -1;
else
bandindex = PG_GETARG_INT32(1);
-
+
if (bandindex < 1) {
elog(NOTICE, "Invalid band index (must use 1-based). Value not set. Returning original raster");
skipset = TRUE;
/* error */
if (count < 0) {
elog(NOTICE, "Could not get the pixel's neighborhood for band at index %d", bandindex);
-
+
rt_band_destroy(band);
rt_raster_destroy(raster);
PG_FREE_IF_COPY(pgraster, 0);
CU_ASSERT_EQUAL(nvals, maxX);
CU_ASSERT_EQUAL(((int8_t *) vals)[3], 3);
rtdealloc(vals);
-
+
err = rt_band_get_pixel_line(band, 4, 4, maxX, &vals, &nvals);
CU_ASSERT_EQUAL(err, ES_NONE);
CU_ASSERT_EQUAL(nvals, 1);
CU_ASSERT_DOUBLE_EQUAL(val,1,.01);
/* set up mask */
-
+
mask = (rt_mask) rtalloc(sizeof(struct rt_mask_t) );
CU_ASSERT(mask != NULL);
mask->values = rtalloc(sizeof(double*)*maskY);
mask->nodata = rtalloc(sizeof(int*)*maskY);
-
+
for( i = 0; i < maskY; i++) {
mask->values[i] = rtalloc(sizeof(double) *maskX);
mask->nodata[i] = rtalloc(sizeof(int) *maskX);
&nodata,
&dimx, &dimy
);
-
+
rtdealloc(npixels);
CU_ASSERT_EQUAL(rtn, ES_NONE);
rtdealloc(nodata);
rtdealloc(value);
-
+
/* set mask to 1 */
for(y = 0; y < maskY; y++) {
&nodata,
&dimx, &dimy
);
-
+
rtdealloc(npixels);
CU_ASSERT_EQUAL(rtn, ES_NONE);
&nodata,
&dimx, &dimy
);
-
+
rtdealloc(npixels);
CU_ASSERT_EQUAL(rtn, ES_NONE);
rtdealloc(mask->values);
rtdealloc(mask->nodata);
rtdealloc(mask);
-
+
if (rtn)
rtdealloc(npixels);
-
+
cu_free_raster(rast);
}
/* Third test: NODATA value = 2.8 */
#ifdef GDALFPOLYGONIZE
rt = fillRasterToPolygonize(1, 2.8);
-#else
+#else
rt = fillRasterToPolygonize(1, 3.0);
#endif
nPols = 0;
gv = rt_raster_gdal_polygonize(rt, 0, TRUE, &nPols);
-
+
/*
for (i = 0; i < nPols; i++) {
wkt = lwgeom_to_text((const LWGEOM *) gv[i].geom);