private ConvexPolygon2D(IReadOnlyList <CartesianPoint> vertices)
        {
            this.Vertices = vertices;

            var edges = new LineSegment2D[vertices.Count];

            for (int i = 0; i < vertices.Count; ++i)
            {
                edges[i] = new LineSegment2D(vertices[i], vertices[(i + 1) % vertices.Count]);
            }
            this.Edges = edges;
        }
        public PolygonPointPosition FindRelativePositionOfPoint(CartesianPoint point)
        {
            int edgesPassingThroughPoint = 0;

            for (int i = 0; i < Vertices.Count; ++i)
            {
                var edge = new LineSegment2D(Vertices[i], Vertices[(i + 1) % Vertices.Count]); //TODO: Perhaps I should use the DirectedSegment2D, which is faster for the use
                if (edge.FindRelativePositionOfPoint(point) == LineSegment2D.SegmentPointPosition.PointOnSegment)
                {
                    ++edgesPassingThroughPoint;
                }
            }
            if (edgesPassingThroughPoint == 1)
            {
                return(PolygonPointPosition.OnEdge);
            }
            else if (edgesPassingThroughPoint == 2)
            {
                return(PolygonPointPosition.OnVertex);
            }
            else if (IsPointInsidePolygon(point))
            {
                return(PolygonPointPosition.Inside);
            }
            else
            if (IsPointInsidePolygon(point))
            {
                return(PolygonPointPosition.Inside);
            }
            else
            {
                return(PolygonPointPosition.Outside);
            }

            //TODO: IsPointInsidePolygon(point) is undefined the point is on the boundary, so the following doesn't always work.
            //if (IsPointInsidePolygon(point)) return PolygonPointPosition.Inside;
            //{
            //    int edgesPassingThroughPoint = 0;
            //    for (int i = 0; i < Vertices.Count; ++i)
            //    {
            //        var edge = new LineSegment2D(Vertices[i], Vertices[(i + 1) % Vertices.Count]); //TODO: Perhaps I should use the DirectedSegment2D, which is faster for the use
            //        if (edge.FindRelativePositionOfPoint(point) == LineSegment2D.SegmentPointPosition.PointOnSegment)
            //        {
            //            ++edgesPassingThroughPoint;
            //        }
            //    }
            //    if (edgesPassingThroughPoint == 0) return PolygonPointPosition.Outside;
            //    else if (edgesPassingThroughPoint == 1) return PolygonPointPosition.OnEdge;
            //    else if (edgesPassingThroughPoint == 2) return PolygonPointPosition.OnVertex;
            //    else throw new Exception("This should not have happened.");
            //}
        }
Example #3
0
        /// <summary>
        /// See <see cref="http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect"/>
        /// </summary>
        /// <param name="segment"></param>
        /// <param name="intersectionPoint"></param>
        /// <returns></returns>
        public SegmentSegmentPosition IntersectionWith(LineSegment2D segment, out CartesianPoint intersectionPoint)
        {
            //TODO: optimize this:
            // a) Cache the vector representation of "this".Perhaps there could be a private vector representation class
            //b) Perhaps some cases can be ignored/lumped together.E.g. for colinear
            //c) Perhaps working with the double values instead of vector structs saves a lot of accesses.

            //TODO: handle extreme cases:
            // a) One segment's end lies on the other segment
            // b) One segment's end coincides with one of the other segment's ends, but otherwise they do not overlap
            // c) These cases probably need some tolerance checks.This requires attention since intersection points
            //      outside the element will create unwanted triangulations.

            //Create vectors p, r, q, s
            var p = Vector2.Create(this.Start.X, this.Start.Y);
            var r = Vector2.Create(this.End.X - this.Start.X, this.End.Y - this.Start.Y);
            var q = Vector2.Create(segment.Start.X, segment.Start.Y);
            var s = Vector2.Create(segment.End.X - segment.Start.X, segment.End.Y - segment.Start.Y);

            // Find the cross products r x s and (q-p)*r
            double rCrossS       = r.CrossProduct(s);
            var    qMinusP       = q - p;
            double qMinusPCrossR = qMinusP.CrossProduct(r);

            if (rCrossS == 0)           // TODO: use tolerance here
            {
                if (qMinusPCrossR == 0) // TODO: use tolerance here
                {
                    double        rDotR  = r * r;
                    double        t0     = (qMinusP * r) / rDotR;
                    double        t1     = t0 + (s * r) / rDotR;
                    LineSegment1D this1D = (new LineSegment1D(0.0, 1.0));
                    LineSegment1D.SegmentSegmentPosition intersection1D =
                        this1D.IntesectionWith(new LineSegment1D(t0, t1));
                    if (intersection1D == LineSegment1D.SegmentSegmentPosition.Disjoint)
                    {
                        intersectionPoint = null;
                        return(LineSegment2D.SegmentSegmentPosition.CollinearDisjoint);
                    }
                    else if (intersection1D == LineSegment1D.SegmentSegmentPosition.Overlapping)
                    {
                        intersectionPoint = null;
                        return(LineSegment2D.SegmentSegmentPosition.Overlapping);
                    }
                    else // TODO: handle this case
                    {
                        throw new NotImplementedException("The two segments are colinear and meet only at one point");
                    }
                }
                else
                {
                    intersectionPoint = null;
                    return(SegmentSegmentPosition.Parallel);
                }
            }
            else
            {
                double t = qMinusP.CrossProduct(s) / rCrossS;
                double u = qMinusPCrossR / rCrossS;
                if ((t >= 0.0) && (t <= 1.0) && (u >= 0.0) && (u <= 1.0))
                {
                    var solution = p + t * r;
                    intersectionPoint = new CartesianPoint(solution[0], solution[1]);
                    return(SegmentSegmentPosition.Intersecting);
                }
                else
                {
                    intersectionPoint = null;
                    return(SegmentSegmentPosition.Disjoint);
                }
            }
        }
Example #4
0
 //Perhaps I can override the intersects method and project the other segment onto the local system!
 public LineSegment2D.SegmentSegmentPosition IntersectionWith(LineSegment2D segment,
                                                              out CartesianPoint intersectionPoint)
 {
     return(segment.IntersectionWith(new LineSegment2D(Start, End), out intersectionPoint));
 }