[mapguide-commits] r4322 - trunk/MgDev/Common/Geometry/Spatial

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Tue Oct 27 15:04:41 EDT 2009


Author: NormOlsen
Date: 2009-10-27 15:04:39 -0400 (Tue, 27 Oct 2009)
New Revision: 4322

Modified:
   trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp
   trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.h
Log:
Correction for Trac Ticket # 1130: Missing and reversed grid labels.  This is the result of testing of the overall RFC 76 submission.

Actually, there were no missing labels.  There were labels showing up on the wrong side of the dividing line of the regions which was to be labeled. Thus, the wrongly positioned label overwrote the label which then appeared to be missing.

The wrong position was caused by a defect in the clipping algorithm which would change the direction of the clipped result to be the opposite of the original line which was being clipped.  This occurred when a single line segment of the line string being clipped would transverse the entire viewport boundary region.  Since boundaries are always counterclockwise, clipping a line which (for example) proceeds from north to south would often produce a dingle line segment which would proceed from south to north.  This caused the labels to be placed on the wrong side of the line.


Modified: trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp
===================================================================
--- trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp	2009-10-26 22:25:40 UTC (rev 4321)
+++ trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.cpp	2009-10-27 19:04:39 UTC (rev 4322)
@@ -667,6 +667,7 @@
                                                                                              MgCoordinate* segTo)
 {
     int status;
+    INT32 insertIndex;                      // for test and debug;
     Ptr<MgCoordinateCollection> coordinateCollection;
     Ptr<MgCoordinate> intersection;
     Ptr<MgCoordinate> polyFrom;
@@ -700,17 +701,71 @@
             // point which will still be on the heap when we are done, so we
             // definitely do not want to add the intersection point.
             Ptr<MgCoordinate> newPoint = new MgCoordinateXY (intersection->GetX(),intersection->GetY());
-            coordinateCollection->Add(newPoint);
+            insertIndex = AddToCoordinateCollection (coordinateCollection,newPoint,segFrom);
+            if (insertIndex != 0)
+            {
+                insertIndex = 0;
+            }
 
-            // The line segment can, and often does, have more than one
-            // intersection point with the polygon.  SO we keep trucking.
+            // The line segment can have more than one intersection point with
+            // the polygon.  So we keep trucking.
         }
     }
-    
+
     // We return the generated collection, which will often be empty.
     return coordinateCollection.Detach ();
 }
 
+// In the event that the PolySegIntersection function discovers two or more
+// intersection points for a single line segment, it is important that they
+// get added to the coordinate collection in the proper order.  This is a
+// brute force technique, but this situation is rather rare.
+INT32 MgSpatialUtility::AddToCoordinateCollection (MgCoordinateCollection* collection,MgCoordinate* newPoint,MgCoordinate* basePoint)
+{
+    INT32 index = 0;
+    double deltaX, deltaY;
+    double newDistance, indexDistance;
+
+    INT32 segCount = collection->GetCount ();
+    if (segCount == 0)
+    {
+        // This case happens so often that its worth having extra code to
+        // deal with this case very efficiently.
+        collection->Add (newPoint);
+    }
+    else
+    {
+        // This happens rather in frequently, but it can happen.  Need to
+        // insert the value into the collection such that when we are
+        // done, the points represent the same disrection as the original
+        // line segment.
+        
+        // Compute the distance from the basePoint to the newPoint.  To
+        // keep performance up we'll use the square of the distance
+        // rather than the distance itself;
+        deltaX = newPoint->GetX () - basePoint->GetX ();
+        deltaY = newPoint->GetY () - basePoint->GetY ();
+        newDistance = /*sqrt*/ (deltaX * deltaX + deltaY * deltaY);
+        
+        // Loop through all points in the collection and determine the index
+        // value of the first point whose distance from the base point is
+        // greater than the distance for the newPoint.
+        for (index = 0;index < segCount;index += 1)
+        {
+            Ptr<MgCoordinate> indexPoint = collection->GetItem (index);
+            deltaX = indexPoint->GetX () - basePoint->GetX ();
+            deltaY = indexPoint->GetY () - basePoint->GetY ();
+            indexDistance = /*sqrt*/ (deltaX * deltaX + deltaY * deltaY);
+            if (indexDistance > newDistance)
+            {
+                break;
+            }
+        }
+        collection->Insert (index,newPoint);
+    }
+    return index;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 /// <summary>
 /// Returns true if the provided query point is inside of, or on, the closed

Modified: trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.h
===================================================================
--- trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.h	2009-10-26 22:25:40 UTC (rev 4321)
+++ trunk/MgDev/Common/Geometry/Spatial/SpatialUtility.h	2009-10-27 19:04:39 UTC (rev 4322)
@@ -192,8 +192,41 @@
                                                         MgCoordinate* segFrom,
                                                         MgCoordinate* segTo);
 
+
     ///////////////////////////////////////////////////////////////////////////////
     /// <summary>
+    /// Adds a coordinate to a coordinate collection such that the resulting
+    /// collection represents a collection of points in sequence from the
+    /// [rpvoded base point.
+    /// </summary>
+    /// <param name="collection">
+    /// The coordinate collection to which the <c>newPoint</c> is to be added.
+    /// </param>
+    /// <param name="newPoint">
+    /// The point to be added to the provided collection.
+    /// </param>
+    /// <param name="basePoint">
+    /// The base point which is used to order the collection.
+    /// </param>
+    /// <returns>
+    /// the index at which the insertion occurred.
+    /// </returns>
+    /// <remarks>
+    /// This is a 2D function only, Z and M coordinates are ignored; the provided
+    /// point collection is expected to be a collection of <c>MgCoordinateXY</c> objects.<para>
+    /// The purpose of this function is serve as a helper for the PolySegIntersection
+    /// function.  It enables PolySegIntersection to return a point collection such
+    /// that the points in the collection present an orderly sequence of points from
+    /// the provided base point.  Thus, if the original line segment provided to
+    /// PolySegIntersection proceeded in the south to north direction, the point
+    /// collection returned would also be returned in that order; regardless of the
+    /// shape of the polygon or the direction in which it proceeds.
+    /// </remarks>
+    static INT32 AddToCoordinateCollection (MgCoordinateCollection* collection,MgCoordinate* newPoint,
+                                                                        MgCoordinate* basePoint);
+
+    ///////////////////////////////////////////////////////////////////////////////
+    /// <summary>
     /// Determines if the provided point is inside (or actually on) the closed
     /// ring provided bythe polyItr argument.
     /// </summary>



More information about the mapguide-commits mailing list