private void GetVisiblePoints(int holeIndex, List <Polygon> polygons, out ConnectionEdge M, out ConnectionEdge P) { M = FindLargest(polygons[holeIndex]); var direction = (polygons[holeIndex].Start.Next.Origin - polygons[holeIndex].Start.Origin).Cross(Normal); var I = FindPointI(M, polygons, holeIndex, direction); Vector3m res; if (polygons[I.PolyIndex].Contains(I.I, out res)) { var incidentEdges = (List <ConnectionEdge>)res.DynamicProperties.GetValue(PropertyConstants.IncidentEdges); foreach (var connectionEdge in incidentEdges) { if (Misc.IsBetween(connectionEdge.Origin, connectionEdge.Next.Origin, connectionEdge.Prev.Origin, M.Origin, Normal) == 1) { P = connectionEdge; return; } } throw new Exception(); } else { P = FindVisiblePoint(I, polygons, M, direction); } }
private ConnectionEdge FindLargest(Polygon testHole) { Rational maximum = 0; ConnectionEdge maxEdge = null; Vector3m v0 = testHole.Start.Origin; Vector3m v1 = testHole.Start.Next.Origin; foreach (var connectionEdge in testHole.GetPolygonCirculator()) { // we take the first two points as a reference line if (Misc.GetOrientation(v0, v1, connectionEdge.Origin, Normal) < 0) { var r = Misc.PointLineDistance(v0, v1, connectionEdge.Origin); if (r > maximum) { maximum = r; maxEdge = connectionEdge; } } } if (maxEdge == null) { return(testHole.Start); } return(maxEdge); }
private void InsertNewEdges(ConnectionEdge insertionEdge, ConnectionEdge m) { insertionEdge.Polygon.PointCount += m.Polygon.PointCount; var cur = m; var forwardEdge = new ConnectionEdge(insertionEdge.Origin, insertionEdge.Polygon); forwardEdge.Prev = insertionEdge.Prev; forwardEdge.Prev.Next = forwardEdge; forwardEdge.Next = m; forwardEdge.Next.Prev = forwardEdge; var end = insertionEdge; ConnectionEdge prev = null; do { cur.Polygon = insertionEdge.Polygon; prev = cur; cur = cur.Next; } while (m != cur); var backEdge = new ConnectionEdge(cur.Origin, insertionEdge.Polygon); cur = prev; cur.Next = backEdge; backEdge.Prev = cur; backEdge.Next = end; end.Prev = backEdge; }
internal void Remove(ConnectionEdge cur) { cur.Prev.Next = cur.Next; cur.Next.Prev = cur.Prev; var incidentEdges = (List <ConnectionEdge>)cur.Origin.DynamicProperties.GetValue(PropertyConstants.IncidentEdges); int index = incidentEdges.FindIndex(x => x.Equals(cur)); Debug.Assert(index >= 0); incidentEdges.RemoveAt(index); if (incidentEdges.Count == 0) { PointCount--; } if (cur == Start) { Start = cur.Prev; } }
private ConnectionEdge FindVisiblePoint(Candidate I, List <Polygon> polygons, ConnectionEdge M, Vector3m direction) { ConnectionEdge P = null; if (I.Origin.Origin.X > I.Origin.Next.Origin.X) { P = I.Origin; } else { P = I.Origin.Next; } List <ConnectionEdge> nonConvexPoints = FindNonConvexPoints(polygons[I.PolyIndex]); nonConvexPoints.Remove(P); var m = M.Origin; var i = I.I; var p = P.Origin; List <ConnectionEdge> candidates = new List <ConnectionEdge>(); // invert i and p if triangle is oriented CW if (Misc.GetOrientation(m, i, p, Normal) == -1) { var tmp = i; i = p; p = tmp; } foreach (var nonConvexPoint in nonConvexPoints) { if (Misc.PointInOrOnTriangle(m, i, p, nonConvexPoint.Origin, Normal)) { candidates.Add(nonConvexPoint); } } if (candidates.Count == 0) { return(P); } return(FindMinimumAngle(candidates, m, direction)); }
private ConnectionEdge FindMinimumAngle(List <ConnectionEdge> candidates, Vector3m M, Vector3m direction) { Rational angle = -double.MaxValue; ConnectionEdge result = null; foreach (var R in candidates) { var a = direction; var b = R.Origin - M; var num = a.Dot(b) * a.Dot(b); var denom = b.Dot(b); var res = num / denom; if (res > angle) { result = R; angle = res; } } return(result); }
private Candidate FindPointI(ConnectionEdge M, List <Polygon> polygons, int holeIndex, Vector3m direction) { Candidate candidate = new Candidate(); for (int i = 0; i < polygons.Count; i++) { if (i == holeIndex) // Don't test the hole with itself { continue; } foreach (var connectionEdge in polygons[i].GetPolygonCirculator()) { Rational rayDistanceSquared; Vector3m intersectionPoint; if (RaySegmentIntersection(out intersectionPoint, out rayDistanceSquared, M.Origin, direction, connectionEdge.Origin, connectionEdge.Next.Origin, direction)) { if (rayDistanceSquared == candidate.currentDistance) // if this is an M/I edge, then both edge and his twin have the same distance; we take the edge where the point is on the left side { if (Misc.GetOrientation(connectionEdge.Origin, connectionEdge.Next.Origin, M.Origin, Normal) == 1) { candidate.currentDistance = rayDistanceSquared; candidate.Origin = connectionEdge; candidate.PolyIndex = i; candidate.I = intersectionPoint; } } else if (rayDistanceSquared < candidate.currentDistance) { candidate.currentDistance = rayDistanceSquared; candidate.Origin = connectionEdge; candidate.PolyIndex = i; candidate.I = intersectionPoint; } } } } return(candidate); }
private void LinkAndAddToList(Polygon polygon, List <Vector3m> points) { ConnectionEdge prev = null, first = null; Dictionary <Vector3m, Vector3m> pointsHashSet = new Dictionary <Vector3m, Vector3m>(); int pointCount = 0; for (int i = 0; i < points.Count; i++) { // we don't wanna have duplicates Vector3m p0; if (pointsHashSet.ContainsKey(points[i])) { p0 = pointsHashSet[points[i]]; } else { p0 = points[i]; pointsHashSet.Add(p0, p0); List <ConnectionEdge> list = new List <ConnectionEdge>(); p0.DynamicProperties.AddProperty(PropertyConstants.IncidentEdges, list); pointCount++; } ConnectionEdge current = new ConnectionEdge(p0, polygon); first = (i == 0) ? current : first; // remember first if (prev != null) { prev.Next = current; } current.Prev = prev; prev = current; } first.Prev = prev; prev.Next = first; polygon.Start = first; polygon.PointCount = pointCount; }
internal void AddIncidentEdge(ConnectionEdge next) { var list = (List <ConnectionEdge>)Origin.DynamicProperties.GetValue(PropertyConstants.IncidentEdges); list.Add(next); }
protected bool Equals(ConnectionEdge other) { return(Next.Origin.Equals(other.Next.Origin) && Origin.Equals(other.Origin)); }
private bool IsConvex(ConnectionEdge curPoint) { int orientation = Misc.GetOrientation(curPoint.Prev.Origin, curPoint.Origin, curPoint.Next.Origin, Normal); return(orientation == 1); }