]> granicus.if.org Git - postgis/commitdiff
Fix azimuth computation for 2.5D edge ends
authorSandro Santilli <strk@kbt.io>
Sat, 11 Mar 2017 16:21:18 +0000 (16:21 +0000)
committerSandro Santilli <strk@kbt.io>
Sat, 11 Mar 2017 16:21:18 +0000 (16:21 +0000)
The change disreguard vertical movemements of the edge and computes
azimuth of the first segment getting away from the node.

Includes automated testcase

See #3711

git-svn-id: http://svn.osgeo.org/postgis/trunk@15330 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/lwgeom_topo.c
topology/test/regress/topogeo_addlinestring.sql
topology/test/regress/topogeo_addlinestring_expected_newsnap
topology/test/regress/topogeo_addlinestring_expected_oldsnap

index 9602238be9f5e2863600c00cf7801fa071c99218..17535cfacbc211b8b511d2731c71e05ebf6d5de6 100644 (file)
@@ -1401,7 +1401,7 @@ typedef struct edgeend_t {
  * Get first distinct vertex from endpoint
  * @param pa the pointarray to seek points in
  * @param ref the point we want to search a distinct one
- * @param from vertex index to start from
+ * @param from vertex index to start from (will really start from "from"+dir)
  * @param dir  1 to go forward
  *            -1 to go backward
  * @return 0 if edge is collapsed (no distinct points)
@@ -1570,7 +1570,12 @@ _lwt_FindAdjacentEdges( LWT_TOPOLOGY* topo, LWT_ELEMID node, edgeend *data,
 
     if ( edge->start_node == node ) {
       getPoint2d_p(pa, 0, &p1);
-      getPoint2d_p(pa, 1, &p2);
+      if ( ! _lwt_FirstDistinctVertex2D(pa, &p1, 0, 1, &p2) )
+      {
+        lwerror("Edge %d has no distinct vertices: [%.15g %.15g,%.15g %.15g]: ",
+                edge->edge_id, p1.x, p1.y, p2.x, p2.y);
+        return -1;
+      }
       LWDEBUGF(1, "edge %" LWTFMT_ELEMID
                   " starts on node %" LWTFMT_ELEMID
                   ", edgeend is %g,%g-%g,%g",
@@ -1627,7 +1632,12 @@ _lwt_FindAdjacentEdges( LWT_TOPOLOGY* topo, LWT_ELEMID node, edgeend *data,
 
     if ( edge->end_node == node ) {
       getPoint2d_p(pa, pa->npoints-1, &p1);
-      getPoint2d_p(pa, pa->npoints-2, &p2);
+      if ( ! _lwt_FirstDistinctVertex2D(pa, &p1, pa->npoints-1, -1, &p2) )
+      {
+        lwerror("Edge %d has no distinct vertices: [%.15g %.15g,%.15g %.15g]: ",
+                edge->edge_id, p1.x, p1.y, p2.x, p2.y);
+        return -1;
+      }
       LWDEBUGF(1, "edge %" LWTFMT_ELEMID " ends on node %" LWTFMT_ELEMID
                   ", edgeend is %g,%g-%g,%g",
                   edge->edge_id, node, p1.x, p1.y, p2.x, p2.y);
@@ -2362,6 +2372,7 @@ _lwt_AddEdge( LWT_TOPOLOGY* topo,
   newedge.geom = geom;
   newedge.face_left = -1;
   newedge.face_right = -1;
+  /* TODO: should do the repeated points removal in 2D space */
   cleangeom = lwgeom_remove_repeated_points( lwline_as_lwgeom(geom), 0 );
 
   pa = lwgeom_as_lwline(cleangeom)->points;
@@ -2375,18 +2386,17 @@ _lwt_AddEdge( LWT_TOPOLOGY* topo,
   span.cwFace = span.ccwFace =
   epan.cwFace = epan.ccwFace = -1;
 
-  /* Compute azimut of first edge end on start node */
+  /* Compute azimuth of first edge end on start node */
   getPoint2d_p(pa, 0, &p1);
-  getPoint2d_p(pa, 1, &pn);
-  if ( p2d_same(&p1, &pn) ) {
+  if ( ! _lwt_FirstDistinctVertex2D(pa, &p1, 0, 1, &pn) )
+  {
     lwgeom_free(cleangeom);
-    /* Can still happen, for 2-point lines */
     lwerror("Invalid edge (no two distinct vertices exist)");
     return -1;
   }
   if ( ! azimuth_pt_pt(&p1, &pn, &span.myaz) ) {
     lwgeom_free(cleangeom);
-    lwerror("error computing azimuth of first edgeend [%g,%g-%g,%g]",
+    lwerror("error computing azimuth of first edgeend [%.15g %.15g,%.15g %.15g]",
             p1.x, p1.y, pn.x, pn.y);
     return -1;
   }
@@ -2394,10 +2404,16 @@ _lwt_AddEdge( LWT_TOPOLOGY* topo,
 
   /* Compute azimuth of last edge end on end node */
   getPoint2d_p(pa, pa->npoints-1, &p2);
-  getPoint2d_p(pa, pa->npoints-2, &pn);
+  if ( ! _lwt_FirstDistinctVertex2D(pa, &p2, pa->npoints-1, -1, &pn) )
+  {
+    lwgeom_free(cleangeom);
+    /* This should never happen as we checked the edge while computing first edgend */
+    lwerror("Invalid clean edge (no two distinct vertices exist) - should not happen");
+    return -1;
+  }
   lwgeom_free(cleangeom);
   if ( ! azimuth_pt_pt(&p2, &pn, &epan.myaz) ) {
-    lwerror("error computing azimuth of last edgeend [%g,%g-%g,%g]",
+    lwerror("error computing azimuth of last edgeend [%.15g %.15g,%.15g %.15g]",
             p2.x, p2.y, pn.x, pn.y);
     return -1;
   }
index 283ef7048b08da4bb360dda76a5791d46da3f250..83397d0543d107afd00f928aad9c3d1efb5cb408 100644 (file)
@@ -322,3 +322,13 @@ SELECT 't3412.L2', TopoGeo_AddLinestring('bug3412',
 '0102000000020000003AB42BBFEE4C22410010C5A997A6524167BB5DBDEE4C224117FE3DA85FA75241'
 ::geometry, 0);
 SELECT 't3412.end', DropTopology('bug3412');
+
+-- See http://trac.osgeo.org/postgis/ticket/3711
+SELECT 't3371.start', topology.CreateTopology('bug3711', 0, 0, true) > 1;
+SELECT 't3371.L1', topology.TopoGeo_AddLineString('bug3711',
+'LINESTRING (618369 4833784 0.88, 618370 4833784 1.93, 618370 4833780 1.90)'
+::geometry, 0);
+SELECT 't3371.L2', topology.TopoGeo_AddLineString( 'bug3711',
+'LINESTRING (618370 4833780 1.92, 618370 4833784 1.90, 618371 4833780 1.93)'
+::geometry, 0);
+SELECT 't3371.end', topology.DropTopology('bug3711');
index 0c564763c3aae3a214479bfc4bdc182443eb2e27..475bb75982d06a5fe1abbecdc15c249644829e33 100644 (file)
@@ -201,3 +201,8 @@ t3412.L2|3
 t3412.L2|5
 t3412.L2|4
 t3412.end|Topology 'bug3412' dropped
+t3371.start|t
+t3371.L1|1
+t3371.L2|3
+t3371.L2|2
+t3371.end|Topology 'bug3711' dropped
index dec535d4b379e95bc8604b750549ea298144ccb4..f3e29c3c84848593e6273134651a551e951c23f2 100644 (file)
@@ -198,3 +198,8 @@ t3412.L2|3
 t3412.L2|5
 t3412.L2|4
 t3412.end|Topology 'bug3412' dropped
+t3371.start|t
+t3371.L1|1
+t3371.L2|3
+t3371.L2|2
+t3371.end|Topology 'bug3711' dropped