From: Sandro Santilli Date: Tue, 13 Aug 2013 23:48:04 +0000 (+0000) Subject: Fix computation of number of quadrants per arc (#2420) X-Git-Tag: 2.2.0rc1~1403 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=711d56fe4e994641996223406191552b4836dc84;p=postgis Fix computation of number of quadrants per arc (#2420) Note: I had to change some tests that expected 3-quadrant curves to be accepted as curvey input to rely on round-trip instead git-svn-id: http://svn.osgeo.org/postgis/trunk@11794 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/liblwgeom/cunit/cu_ptarray.c b/liblwgeom/cunit/cu_ptarray.c index 933aa062e..6078f54d7 100644 --- a/liblwgeom/cunit/cu_ptarray.c +++ b/liblwgeom/cunit/cu_ptarray.c @@ -361,34 +361,50 @@ static void test_ptarray_desegmentize() lwfree(str); */ - in = lwgeom_from_text("LINESTRING(-1 0, 0 1, 1 0, 0 -1)"); + in = lwgeom_from_text("CIRCULARSTRING(-1 0,0 1,0 -1)"); + out = lwgeom_segmentize(in,8); + lwgeom_free(in); + in = out; out = lwgeom_desegmentize(in); str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL); - CU_ASSERT_STRING_EQUAL(str, "CIRCULARSTRING(-1 0,0 1,0 -1)"); + //printf("%s\n", str); + CU_ASSERT_STRING_EQUAL(str, "CIRCULARSTRING(-1 0,0.70710678 0.70710678,0 -1)"); lwgeom_free(in); lwgeom_free(out); lwfree(str); - in = lwgeom_from_text("LINESTRING(-1 0, 0 1, 1 0, 0 -1, -1 -1)"); + in = lwgeom_from_text("COMPOUNDCURVE(CIRCULARSTRING(-1 0,0 1,0 -1),(0 -1,-1 -1))"); + out = lwgeom_segmentize(in,8); + lwgeom_free(in); + in = out; out = lwgeom_desegmentize(in); str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL); - CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE(CIRCULARSTRING(-1 0,0 1,0 -1),(0 -1,-1 -1))"); + //printf("%s\n", str); + CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE(CIRCULARSTRING(-1 0,0.70710678 0.70710678,0 -1),(0 -1,-1 -1))"); lwgeom_free(in); lwgeom_free(out); lwfree(str); - in = lwgeom_from_text("LINESTRING(-3 -3,-1 0, 0 1, 1 0, 0 -1, 0 -1.5, 0 -2, -1 -3, 0 -4, 1 -3,5 5)"); + in = lwgeom_from_text("COMPOUNDCURVE((-3 -3,-1 0),CIRCULARSTRING(-1 0,0 1,0 -1),(0 -1,0 -1.5,0 -2),CIRCULARSTRING(0 -2,-1 -3,1 -3),(1 -3,5 5))"); + out = lwgeom_segmentize(in,8); + lwgeom_free(in); + in = out; out = lwgeom_desegmentize(in); str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL); - CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE((-3 -3,-1 0),CIRCULARSTRING(-1 0,0 1,0 -1),(0 -1,0 -1.5,0 -2),CIRCULARSTRING(0 -2,-1 -3,1 -3),(1 -3,5 5))"); + //printf("%s\n", str); + CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE((-3 -3,-1 0),CIRCULARSTRING(-1 0,0.70710678 0.70710678,0 -1),(0 -1,0 -1.5,0 -2),CIRCULARSTRING(0 -2,-0.70710678 -3.7071068,1 -3),(1 -3,5 5))"); lwgeom_free(in); lwgeom_free(out); lwfree(str); - in = lwgeom_from_text("LINESTRING(-1 0, 0 1, 1 0, 0 -1, -1 -2, 0 -3, 1 -2)"); + in = lwgeom_from_text("COMPOUNDCURVE(CIRCULARSTRING(-1 0,0 1,0 -1),CIRCULARSTRING(0 -1,-1 -2,1 -2))"); + out = lwgeom_segmentize(in,8); + lwgeom_free(in); + in = out; out = lwgeom_desegmentize(in); str = lwgeom_to_wkt(out, WKT_ISO, 8, NULL); - CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE(CIRCULARSTRING(-1 0,0 1,0 -1),CIRCULARSTRING(0 -1,-1 -2,1 -2))"); + //printf("%s\n", str); + CU_ASSERT_STRING_EQUAL(str, "COMPOUNDCURVE(CIRCULARSTRING(-1 0,0.70710678 0.70710678,0 -1),CIRCULARSTRING(0 -1,-0.70710678 -2.7071068,1 -2))"); lwgeom_free(in); lwgeom_free(out); lwfree(str); diff --git a/liblwgeom/lwsegmentize.c b/liblwgeom/lwsegmentize.c index 2fd5d063e..47966e67a 100644 --- a/liblwgeom/lwsegmentize.c +++ b/liblwgeom/lwsegmentize.c @@ -587,7 +587,7 @@ pta_desegmentize(POINTARRAY *points, int type, int srid) { int i = 0, j, k; POINT4D a1, a2, a3, b; - POINT4D first; + POINT4D first, center; char *edges_in_arcs; int found_arc = LW_FALSE; int current_arc = 1; @@ -623,7 +623,8 @@ pta_desegmentize(POINTARRAY *points, int type, int srid) while( i < num_edges-2 ) { unsigned int arc_edges; - unsigned int num_quadrants; + double num_quadrants; + double angle; found_arc = LW_FALSE; /* Make candidate arc */ @@ -665,15 +666,24 @@ pta_desegmentize(POINTARRAY *points, int type, int srid) * See http://trac.osgeo.org/postgis/ticket/2420 */ arc_edges = j - 1 - i; - num_quadrants = 1; /* silly guess, TODO: compute */ LWDEBUGF(4, "arc defined by %d edges found", arc_edges); if ( first.x == b.x && first.y == b.y ) { LWDEBUG(4, "arc is a circle"); num_quadrants = 4; } + else { + lw_arc_center((POINT2D*)&first, (POINT2D*)&b, (POINT2D*)&a1, (POINT2D*)¢er); + angle = lw_arc_angle((POINT2D*)&first, (POINT2D*)¢er, (POINT2D*)&b); + int p2_side = lw_segment_side((POINT2D*)&first, (POINT2D*)&a1, (POINT2D*)&b); + if ( p2_side != -1 ) angle = -angle; + + if ( angle < 0 ) angle = 2 * M_PI + angle; + num_quadrants = ( 4 * angle ) / ( 2 * M_PI ); + LWDEBUGF(4, "arc angle is %g, quandrants:%g", angle, num_quadrants); + } /* a1 is first point, b is last point */ if ( arc_edges < min_quad_edges * num_quadrants ) { - LWDEBUGF(4, "Not enough edges for a %d quadrants arc", num_quadrants); + LWDEBUGF(4, "Not enough edges for a %g quadrants arc, %g needed", num_quadrants, min_quad_edges * num_quadrants); for ( k = j-1; k >= i; k-- ) edges_in_arcs[k] = 0; } diff --git a/regress/tickets.sql b/regress/tickets.sql index 333b767bc..48bedd77d 100644 --- a/regress/tickets.sql +++ b/regress/tickets.sql @@ -831,7 +831,8 @@ SELECT '#2415.2', ST_AsText(ST_Multi( SELECT '#2412', ST_AsText(ST_LineToCurve('LINESTRING(0 0,10 0,20 0)')); -SELECT '#2420', ST_AsText(ST_LineToCurve('LINESTRING(0 0,10 0,10 10,0 10,0 0)')); +SELECT '#2420.1', ST_AsText(ST_LineToCurve('LINESTRING(0 0,10 0,10 10,0 10,0 0)')); +SELECT '#2420.2', ST_AsText(ST_LineToCurve('LINESTRING(0 0,10 0,10 10,0 10)')); SELECT '#2423', ST_AsText(ST_SnapToGrid(ST_CurveToLine(ST_LineToCurve( ST_Intersection(ST_Buffer(ST_Point(0,0),10),ST_MakeEnvelope(-10,0,10,10)) diff --git a/regress/tickets_expected b/regress/tickets_expected index 6dd393717..1e34dbdce 100644 --- a/regress/tickets_expected +++ b/regress/tickets_expected @@ -247,7 +247,8 @@ ERROR: invalid GML representation #2415.1|MULTICURVE(COMPOUNDCURVE((0 0,10 0),CIRCULARSTRING(10 0,15 1,20 10))) #2415.2|MULTISURFACE(CURVEPOLYGON(CIRCULARSTRING(10 0,15 1,20 0,18 5,20 10,10 10,10 0))) #2412|LINESTRING(0 0,10 0,20 0) -#2420|LINESTRING(0 0,10 0,10 10,0 10,0 0) +#2420.1|LINESTRING(0 0,10 0,10 10,0 10,0 0) +#2420.2|LINESTRING(0 0,10 0,10 10,0 10) #2423|POLYGON((-10 0,-9.2388 3.82683,-7.07107 7.07107,-3.82683 9.2388,0 10,3.82683 9.2388,7.07107 7.07107,9.2388 3.82683,10 0,-10 0)) #2424|MULTILINESTRING((0 0,10 0,24 3,30 10)) #2427|POINT(-1 0)