Beispiel #1
0
 /// <summary>
 /// Returns 0 if no intersections occur, 1 if an intersection point is found,
 /// and 2 if the segments are colinear and overlap.
 /// </summary>
 /// <param name="other"></param>
 /// <returns></returns>
 public int IntersectionCount(Segment other)
 {
     double x1 = P1.X;
     double y1 = P1.Y;
     double x2 = P2.X;
     double y2 = P2.Y;
     double x3 = other.P1.X;
     double y3 = other.P1.Y;
     double x4 = other.P2.X;
     double y4 = other.P2.Y;
     double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
    
     // if denom is 0, then the two lines are parallel
     double na = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
     double nb = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3);
     // if denom is 0 AND na and nb are 0, then the lines are coincident and DO intersect
     if (Math.Abs(denom) < Epsilon && Math.Abs(na) < Epsilon && Math.Abs(nb) < Epsilon) return 2;
     // If denom is 0, but na or nb are not 0, then the lines are parallel and not coincident
     if (denom == 0) return 0;
     double ua = na / denom;
     double ub = nb / denom;
     if (ua < 0 || ua > 1) return 0; // not intersecting with segment a
     if (ub < 0 || ub > 1) return 0; // not intersecting with segment b
     // If we get here, then one intersection exists and it is found on both line segments
     return 1;
 }
Beispiel #2
0
 /// <summary>
 /// Uses the intersection count to detect if there is an intersection
 /// </summary>
 /// <param name="other"></param>
 /// <returns></returns>
 public bool Intersects(Segment other)
 {
     return (IntersectionCount(other) > 0);
 }
        /// <summary>
        /// For each coordinate in the other part, if it falls in the extent of this polygon, a 
        /// ray crossing test is used for point in polygon testing.  If it is not in the extent,
        /// it is skipped.
        /// </summary>
        /// <param name="polygonShape">The part of the polygon to analyze polygon</param>
        /// <param name="otherPart">The other part</param>
        /// polygonshape and the shape extent is the same as the part extent.</param>
        /// <returns>Boolean, true if any coordinate falls inside the polygon</returns>
        private static bool ContainsVertex(ShapeRange polygonShape, PartRange otherPart)
        {
            // Create an extent for faster checking in most cases
            Extent ext = polygonShape.Extent;

            foreach (Vertex point in otherPart)
            {
                // This extent check shortcut should help speed things up for large polygon parts
                if (!ext.Intersects(point)) continue;
                
                // Imagine a ray on the horizontal starting from point.X -> infinity.  (In practice this can be ext.XMax)
                // Count the intersections of segments with that line.  If the resulting count is odd, the point is inside.
                double x1 = point.X;
                double y1 = point.Y;
                double x2 = ext.XMax;
                Segment ray = new Segment(point.X, point.Y, ext.XMax, point.Y);
                int[] numCrosses = new int[polygonShape.NumParts]; // A cross is a complete cross.  Coincident doesn't count because it is either 0 or 2 crosses.
                int totalCrosses = 0;
                int iPart = 0;
                foreach (PartRange ring in polygonShape.Parts)
                {
                   
                    foreach (Segment segment in ring.Segments)
                    {
                        if(segment.IntersectionCount(ray) != 1) continue;
                        numCrosses[iPart]++;
                        totalCrosses++;
                    }
                    iPart++;
                }

                // If we didn't actually have any polygons we cant intersect with anything
                if (polygonShape.NumParts < 1) return false;

                // For shapes with only one part, we don't need to test part-containment.
                if(polygonShape.NumParts == 1 && totalCrosses % 2 == 1) return true;

                // Regardless of number of parts or holiness, 1 crossing can only be inside.
                if(totalCrosses == 1) return true;

                
                totalCrosses = 0;
                for (iPart = 0; iPart < numCrosses.Length; iPart++)
                {
                    int count = numCrosses[iPart];
                    // If this part does not contain the point, don't bother trying to figure out if the part is a hole or not.
                    if (count % 2 == 0) continue;
                    
                    // If this particular part is a hole, subtract the total crosses by 1,  otherwise add one.
                    // This takes time, so we want to do this as few times as possible.
                    if(polygonShape.Parts[iPart].IsHole())
                    {
                        totalCrosses--;
                    }
                    else
                    {
                        totalCrosses++;
                    }
                }
                return totalCrosses > 0;

            }
            return false;
        }