예제 #1
0
        public PointFr?Intersection(LineSegmentFr that)
        {
            if (StartPoint.Equals(that.EndPoint))
            {
                return(StartPoint);
            }
            if (EndPoint.Equals(that.StartPoint))
            {
                return(EndPoint);
            }
            if (StartPoint.Equals(that.StartPoint))
            {
                return(Line.Slope.Equals(that.Line.Slope) ? (PointFr?)null : StartPoint);
            }
            if (EndPoint.Equals(that.EndPoint))
            {
                return(Line.Slope.Equals(that.Line.Slope) ? (PointFr?)null : EndPoint);
            }

            var p = Line.Intersection(that.Line);

            if (p == null || !Contains((PointFr)p) || !that.Contains((PointFr)p))
            {
                return(null);
            }
            return(p);
        }
        } // test bada współliniowość, a nie czy punkt jest zawarty w odcinku

        public static Fraction PointFrOrientationTest(PointFr point, LineSegmentFr segment)
        {
            var p0 = point;
            var p1 = segment.StartPoint;
            var p2 = segment.EndPoint;

            return((p1.X - p0.X) * (p2.Y - p0.Y) - (p1.Y - p0.Y) * (p2.X - p0.X));
        }
예제 #3
0
 public List <PointFr> Intersections(LineSegmentFr segment)
 {
     return
         (Edges(true)
          .Select(segment.Intersection)
          .Where(intersection => intersection != null)
          .Select(intersection => (PointFr)intersection).ToList());
 }
예제 #4
0
        public PointFr Center()
        {
            var segment = new LineSegmentFr(StartPoint, EndPoint, true);
            var dX      = segment.EndPoint.X - segment.StartPoint.X;
            var dY      = segment.EndPoint.Y - segment.StartPoint.Y;

            return(new PointFr(segment.StartPoint.X + dX / 2, segment.StartPoint.Y + dY / 2));
        }
        public static bool IsInsideConvexPolygon(PointFr point, PolygonFr polygon)
        {
            var vertices = polygon.Vertices.ToList(); // wierzchołki posortowane przeciwnie do wskazówek zegara względem wnętrza wielokąta
            var edges    = polygon.Edges().ToList();

            if (vertices.Count < 3)
            {
                throw new ArgumentException("Polygon can't have less than 3 vertices");
            }
            if (ConvexHullJarvis(vertices).Count != vertices.Count) // Powinno wystarczyć Count
            {
                throw new ArgumentException("Polygon must be convex");
            }

            if (vertices.Count == 3)
            {
                return(!edges.Any(point.IsRightOf));
            }

            var polyCenter = polygon.Center;

            if (polyCenter == null)
            {
                throw new Exception("Can't calculate center of the Polygon");
            }
            var mid = (PointFr)polyCenter;

            while (edges.Count > 1)
            {
                var testSegment = new LineSegmentFr(mid, edges[edges.Count / 2].StartPoint);
                if (point.IsRightOf(testSegment))
                {
                    edges = edges.Take(edges.Count / 2).ToList();
                }
                else if (point.IsLeftOf(testSegment))
                {
                    edges = edges.Skip(edges.Count / 2).ToList();
                }
                else if (testSegment.Contains(point))
                {
                    return(true);
                }
                else
                {
                    throw new Exception("Invalid calculations performed, it should never happen");
                }
            }

            return(!point.IsRightOf(edges.Single())); // czyli IsLeftOf + Contains, jeżeli jest we wierzchołku to będzie spełniony ostatni warunek z while'a
        }
예제 #6
0
        public bool IntersectsStrict(LineSegmentFr that) // nie uwzględnia stykających się wierzchołków
        {
            if (!Intersects(that))
            {
                return(false);
            }
            return(!Contains(that.StartPoint) && !Contains(that.EndPoint) &&
                   !that.Contains(StartPoint) && !that.Contains(EndPoint));

            //var pn = Line.Intersection(that.Line);
            //if (pn == null) return false;
            //var p = (PointFr) pn;
            //return
            //    Line.Contains(p)
            //        && (MinX == MaxX ? p.X >= MinX : p.X > MinX)
            //        && (MinX == MaxX ? p.X <= MaxX : p.X < MaxX)
            //        && (MinY == MaxY ? p.Y >= MinY : p.Y > MinY)
            //        && (MinY == MaxY ? p.Y <= MaxY : p.Y < MaxY)
            //    && that.Line.Contains(p)
            //        && (that.MinX == that.MaxX ? p.X >= that.MinX : p.X > that.MinX)
            //        && (that.MinX == that.MaxX ? p.X <= that.MaxX : p.X < that.MaxX)
            //        && (that.MinY == that.MaxY ? p.Y >= that.MinY : p.Y > that.MinY)
            //        && (that.MinY == that.MaxY ? p.Y <= that.MaxY : p.Y < that.MaxY);
        }
        private static List <LineSegmentFr> MergeTriangulationDnQ(List <LineSegmentFr> leftTri, List <LineSegmentFr> rightTri)
        {
            var leftPoints    = leftTri.SelectMany(p => p.EndPoints()).OrderBy(p => p.Y).ThenByDescending(p => p.X).Distinct().ToList();
            var rightPoints   = rightTri.SelectMany(p => p.EndPoints()).OrderBy(p => p.Y).ThenBy(p => p.X).Distinct().ToList();
            var triangulation = leftTri.Concat(rightTri).ToList();
            var baseLREdge    = new LineSegmentFr(leftPoints.First(), rightPoints.First(), true);

            var allPoints = leftPoints.Concat(rightPoints).ToList();

            while (allPoints.Any(p => p.IsRightOf(baseLREdge)))
            {
                var newBaseLREdgeC1 = new LineSegmentFr(baseLREdge.StartPoint, allPoints.First(p => p.IsRightOf(baseLREdge)), true);

                var newBaseLREdgeC2 = new LineSegmentFr(baseLREdge.EndPoint, allPoints.First(p => p.IsRightOf(baseLREdge)), true);
                if (baseLREdge.StartPoint.Y < baseLREdge.EndPoint.Y)
                {
                    baseLREdge = triangulation.Contains(newBaseLREdgeC1) ? newBaseLREdgeC2 : newBaseLREdgeC1;
                }
                else
                {
                    baseLREdge = triangulation.Contains(newBaseLREdgeC2) ? newBaseLREdgeC1 : newBaseLREdgeC2;
                }
            }

            triangulation.Add(baseLREdge);

            PointFr?rightCandidate;
            PointFr?leftCandidate;

            do
            {
                rightCandidate = null;
                leftCandidate  = null;
                var rightCandidates = AngularSortDescending(rightPoints, baseLREdge.EndPoint, false, baseLREdge.StartPoint);
                for (var i = 0; i < rightCandidates.Count; i++)
                {
                    var rc = rightCandidates[i];
                    if (rc.IsRightOf(baseLREdge))
                    {
                        break;
                    }

                    if (i + 1 >= rightCandidates.Count ||
                        !new TriangleFr(baseLREdge.StartPoint, baseLREdge.EndPoint, rc).ContainsInCircumcircle(
                            rightCandidates[i + 1]))
                    {
                        if (rightTri.Any(s => s.IntersectsStrict(new LineSegmentFr(baseLREdge.StartPoint, rc, true))))
                        {
                            continue;
                        }
                        rightCandidate = rc;
                        break;
                    }

                    rightTri.RemoveAll(s => s == new LineSegmentFr(baseLREdge.EndPoint, rc, true));
                    triangulation.RemoveAll(s => s == new LineSegmentFr(baseLREdge.EndPoint, rc, true));
                }

                var leftCandidates = AngularSort(leftPoints, baseLREdge.StartPoint, false, baseLREdge.EndPoint);
                for (var i = 0; i < leftCandidates.Count; i++)
                {
                    var lc = leftCandidates[i];
                    if (lc.IsRightOf(baseLREdge))
                    {
                        break;
                    }

                    if (i + 1 >= leftCandidates.Count ||
                        !new TriangleFr(baseLREdge.StartPoint, baseLREdge.EndPoint, lc).ContainsInCircumcircle(
                            leftCandidates[i + 1]))
                    {
                        if (leftTri.Any(s => s.IntersectsStrict(new LineSegmentFr(baseLREdge.EndPoint, lc, true))))
                        {
                            continue;
                        }
                        leftCandidate = lc;
                        break;
                    }

                    leftTri.RemoveAll(s => s == new LineSegmentFr(baseLREdge.StartPoint, lc, true));
                    triangulation.RemoveAll(s => s == new LineSegmentFr(baseLREdge.StartPoint, lc, true));
                }

                if (leftCandidate != null && rightCandidate != null)
                {
                    if (new TriangleFr(baseLREdge.StartPoint, baseLREdge.EndPoint, (PointFr)rightCandidate)
                        .ContainsInCircumcircle((PointFr)leftCandidate))
                    {
                        triangulation.Add(new LineSegmentFr(baseLREdge.EndPoint, (PointFr)leftCandidate, true));
                    }
                    else if (
                        new TriangleFr(baseLREdge.StartPoint, baseLREdge.EndPoint, (PointFr)leftCandidate)
                        .ContainsInCircumcircle((PointFr)rightCandidate))
                    {
                        triangulation.Add(new LineSegmentFr(baseLREdge.StartPoint, (PointFr)rightCandidate, true));
                    }
                    else // cztery punkty leżą na jednym okręgu
                    {
                        triangulation.Add(new LineSegmentFr(baseLREdge.EndPoint, (PointFr)leftCandidate, true));
                    }
                }
                else if (leftCandidate != null)
                {
                    triangulation.Add(new LineSegmentFr(baseLREdge.EndPoint, (PointFr)leftCandidate, true));
                }
                else if (rightCandidate != null)
                {
                    triangulation.Add(new LineSegmentFr(baseLREdge.StartPoint, (PointFr)rightCandidate, true));
                }

                baseLREdge = triangulation.Last();
            }while (leftCandidate != null || rightCandidate != null);

            return(triangulation);
        }
예제 #8
0
 public bool Intersects(LineSegmentFr segment)
 {
     return(Intersections(segment).Any());
 }
예제 #9
0
 public bool IsLeftOf(LineSegmentFr segment)
 {
     return(PointFrOrientationTest(this, segment) > 0);
 }
예제 #10
0
 public bool IsRightOf(LineSegmentFr segment)
 {
     return(PointFrOrientationTest(this, segment) < 0);
 }
예제 #11
0
 public bool isShorterThan(LineSegmentFr that)
 {
     return(LengthSquared() < that.LengthSquared());
 }
예제 #12
0
 public bool IsLongerThan(LineSegmentFr that)
 {
     return(LengthSquared() > that.LengthSquared());
 }
예제 #13
0
 public bool IsEqualLength(LineSegmentFr that)
 {
     return(LengthSquared().Equals(that.LengthSquared()));
 }
예제 #14
0
 public bool Intersects(LineSegmentFr that)
 {
     return(Intersection(that) != null);
 }
예제 #15
0
 public bool Intersects(LineSegmentFr that)
 {
     return(that.Intersects(this));
 }
예제 #16
0
 public PointFr?Intersection(LineSegmentFr segment)
 {
     return(segment.Intersection(this));
 }