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)); }
public List <PointFr> Intersections(LineSegmentFr segment) { return (Edges(true) .Select(segment.Intersection) .Where(intersection => intersection != null) .Select(intersection => (PointFr)intersection).ToList()); }
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 }
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); }
public bool Intersects(LineSegmentFr segment) { return(Intersections(segment).Any()); }
public bool IsLeftOf(LineSegmentFr segment) { return(PointFrOrientationTest(this, segment) > 0); }
public bool IsRightOf(LineSegmentFr segment) { return(PointFrOrientationTest(this, segment) < 0); }
public bool isShorterThan(LineSegmentFr that) { return(LengthSquared() < that.LengthSquared()); }
public bool IsLongerThan(LineSegmentFr that) { return(LengthSquared() > that.LengthSquared()); }
public bool IsEqualLength(LineSegmentFr that) { return(LengthSquared().Equals(that.LengthSquared())); }
public bool Intersects(LineSegmentFr that) { return(Intersection(that) != null); }
public bool Intersects(LineSegmentFr that) { return(that.Intersects(this)); }
public PointFr?Intersection(LineSegmentFr segment) { return(segment.Intersection(this)); }