]> granicus.if.org Git - postgis/commitdiff
#2463, st_length on curve is on linearized geom
authorPaul Ramsey <pramsey@cleverelephant.ca>
Fri, 18 Oct 2013 21:00:07 +0000 (21:00 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Fri, 18 Oct 2013 21:00:07 +0000 (21:00 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@12045 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/liblwgeom.h.in
liblwgeom/lwalgorithm.c
liblwgeom/lwcircstring.c
liblwgeom/ptarray.c
regress/tickets_expected

index 6772080c1d9f0c3bf6bfd2bbaff5d59d155f1055..4eaa4919571848f05e18d27c803559c1539a44fa 100644 (file)
@@ -1103,6 +1103,7 @@ extern LWPOINT* lwcircstring_get_lwpoint(LWCIRCSTRING *circ, int where);
 
 extern double ptarray_length_2d(const POINTARRAY *pts);
 extern double ptarray_length(const POINTARRAY *pts);
+extern double ptarray_arc_length_2d(const POINTARRAY *pts);
 
 
 extern int pt_in_ring_2d(const POINT2D *p, const POINTARRAY *ring);
index 861e6daf90dc8d96c51565ef01b47e8ed676c96e..d91f3a349fef75becc3f5f20dd9c0cc3581ed9d8 100644 (file)
@@ -132,7 +132,9 @@ lw_arc_length(const POINT2D *A1, const POINT2D *A2, const POINT2D *A3)
        /* Co-linear! Return linear distance! */
        if ( radius_A < 0 ) 
        {
-               return sqrt((A1->x-A3->x)*(A1->x-A3->x) + (A1->y-A3->y)*(A1->y-A3->y));
+        double dx = A1->x - A3->x;
+        double dy = A1->y - A3->y;
+               return sqrt(dx*dx + dy*dy);
        }
        
        /* Closed circle! Return the circumference! */
index 247439b396a8d35f0b55416075a57697d8b60254..f381b3eb28a70d86d2cc790f5ee1a32a3ce4fedd 100644 (file)
@@ -269,26 +269,16 @@ int lwcircstring_is_empty(const LWCIRCSTRING *circ)
 
 double lwcircstring_length(const LWCIRCSTRING *circ)
 {
-       double length = 0.0;
-       LWLINE *line;
-       if ( lwcircstring_is_empty(circ) )
-               return 0.0;
-       line = lwcircstring_segmentize(circ, 32);
-       length = lwline_length(line);
-       lwline_free(line);
-       return length;
+       return lwcircstring_length_2d(circ);
 }
 
 double lwcircstring_length_2d(const LWCIRCSTRING *circ)
 {
        double length = 0.0;
-       LWLINE *line;
        if ( lwcircstring_is_empty(circ) )
                return 0.0;
-       line = lwcircstring_segmentize(circ, 32);
-       length = lwline_length_2d(line);
-       lwline_free(line);
-       return length;
+       
+    return ptarray_arc_length_2d(circ->points);
 }
 
 /*
index 6baad62df24cf19d773ab3fad114bfdd722fa043..4a33ecc958eed50db9d459d3b449250d5326da2c 100644 (file)
@@ -1532,6 +1532,34 @@ ptarray_simplify(POINTARRAY *inpts, double epsilon, unsigned int minpts)
        return outpts;
 }
 
+/**
+* Find the 2d length of the given #POINTARRAY, using circular
+* arc interpolation between each coordinate triple.
+* Length(A1, A2, A3, A4, A5) = Length(A1, A2, A3)+Length(A3, A4, A5)
+*/
+double
+ptarray_arc_length_2d(const POINTARRAY *pts)
+{
+       double dist = 0.0;
+       int i;
+       const POINT2D *a1;
+       const POINT2D *a2;
+       const POINT2D *a3;
+
+       if ( pts->npoints % 2 != 1 )
+        lwerror("arc point array with even number of points");
+        
+       a1 = getPoint2d_cp(pts, 0);
+       
+       for ( i=2; i < pts->npoints; i += 2 )
+       {
+       a2 = getPoint2d_cp(pts, i-1);
+               a3 = getPoint2d_cp(pts, i);
+               dist += lw_arc_length(a1, a2, a3);
+               a1 = a3;
+       }
+       return dist;
+}
 
 /**
 * Find the 2d length of the given #POINTARRAY (even if it's 3d)
index 10842ff76af55d6e96c2ba1443c2b9f9753228f2..cee55ef1f39cc0a6c178da442b9f0950a7acd48b 100644 (file)
@@ -226,7 +226,7 @@ NOTICE:  SRID value -1 converted to the officially unknown SRID value 0
 ERROR:  ST_Segmentize: invalid max_distance 0 (must be >= 0)
 ERROR:  invalid GML representation
 #1957|1
-#1978|3.1413
+#1978|3.1416
 #1996|{"type":"Point","coordinates":[]}
 #2001|POLYGON((0 0,0 1,1 1,0 0))
 #2028|TIN(((0 0,0 1,1 1,0 0)))