/// <summary> /// Checks if a segments end is another segments start. /// </summary> public bool Connected(Segment other) { if (/*this.Start.Equals(other.Start) || */this.Start.Equals(other.End) || this.End.Equals(other.Start)/* || this.End.Equals(other.End)*/) { return true; } return false; }
/// <summary> /// Adds a segment to the front. /// </summary> public void AddSegment(Segment segment) { double len = segment.GetLength(); if (!this.Segments.ContainsKey(len)) { this.Segments.Add(len, new List<Segment>()); } this.Segments[len].Add(segment); segment.ConnectEndpoints(); }
/// <summary> /// Checks if the front contains a segment. /// </summary> public bool Contains(Segment s, int cellDistance) { HashSet<Segment> segments = s.GetNearbySegments(this, cellDistance);//GetSegmentsUnordered(); foreach (Segment segment in segments) { if (segment.Equals(s)) { return true; } } return false; }
public bool Equals(Segment other) { // start == start && end == end if (this.Start.Equals(other.Start)) { if (this.End.Equals(other.End)) return true; } // start == end && end == start (reverse dir) if (this.Start.Equals(other.End)) { if (this.End.Equals(other.Start)) return true; } return false; }
public Front(List<Point> pts) { this.InitialPoints = pts; this.Points = new Quadtree(this.InitialPoints); this.Segments = new SortedList<double, List<Segment>>(); if (this.InitialPoints.Count == 0) return; // Create segments between points. for (int i = 0; i < this.InitialPoints.Count - 1; i++) { Segment seg = new Segment(this.InitialPoints[i], this.InitialPoints[i + 1]); AddSegment(seg); } Segment s = new Segment(this.InitialPoints[this.InitialPoints.Count - 1], this.InitialPoints[0]); AddSegment(s); }
/// <summary> /// Calculates the angle of two connected segments in degrees. /// </summary> public static double Angle(Segment s1, Segment s2) { Vector3D v1, v2; if (s1.End.Equals(s2.Start)) { v1 = s1.ToVector3D(); v2 = s2.ToVector3D(); } else if (s2.End.Equals(s1.Start)) { v1 = s2.ToVector3D(); v2 = s1.ToVector3D(); } else { throw new ApplicationException("Invalid segment order"); } double temp = Math.Acos(Vector3D.DotProduct(v1, v2) / (v1.Length * v2.Length)); double angle = temp * (180 / Math.PI); return Vector3D.CrossProduct(v1, v2).Z >= 0 ? 180 - angle : 180 + angle; }
private bool TryFormTriangle(Segment shortestSegment, Point p, bool existingPoint) { Segment newSegment1 = new Segment(shortestSegment.Start, p); Segment newSegment2 = new Segment(p, shortestSegment.End); List<Segment> SegmentsToAdd = new List<Segment>(); List<Segment> SegmentsToRemove = new List<Segment>(); // Check if triangle can be formed if (this.Front.Contains(newSegment1, cellDistance)) { SegmentsToRemove.Add(newSegment1); } else { // Test if triangle candidate intersects with existing elements if (IsIntersecting(newSegment1)) return false; // Test if segment is outside of the front if (!this.Front.IsPointInside(newSegment1.GetPoint(0.5))) return false; SegmentsToAdd.Add(newSegment1); } if (this.Front.Contains(newSegment2, cellDistance)) { SegmentsToRemove.Add(newSegment2); } else { // Test if triangle candidate intersects with existing elements if (IsIntersecting(newSegment2)) return false; // Test if segment is outside of the front if (!this.Front.IsPointInside(newSegment2.GetPoint(0.5))) return false; SegmentsToAdd.Add(newSegment2); } // update front and form triangle // Remove current segment from the front. this.Front.RemoveSegment(shortestSegment); // Update front with new segments. if (!existingPoint) { this.Points.Add(p); this.Front.Points.Add(p); } foreach (Segment s in SegmentsToAdd) { this.Front.AddSegment(s); } foreach (Segment s in SegmentsToRemove) { this.Front.RemoveSegment(s); } AddTriangle(shortestSegment.Start, shortestSegment.End, p); return true; }
private void TryContractVertices(Segment s1, Segment s2) { Point p1, p2, common; if (s1.End.Equals(s2.Start)) { common = s1.End; p1 = s1.Start; p2 = s2.End; } else if (s1.Start.Equals(s2.End)) { common = s1.Start; p2 = s1.End; p1 = s2.Start; } else { throw new ApplicationException("Invalid segment order"); } if (p1.IsEdgePoint && p2.IsEdgePoint) { AddTriangle(p1, p2, common); this.Front.AddSegment(new Segment(p1, p2)); } else { Point midPoint; if (p1.IsEdgePoint) midPoint = p1; else if (p2.IsEdgePoint) midPoint = p2; else { midPoint = new Point((p1.X + p2.X) / 2, (p1.Y + p2.Y) / 2, 0); } ReplacePoints(p1, p2, midPoint); } }
/// <summary> /// Checks if the segment is intersecting with nearby front and mesh elements. /// </summary> private bool IsIntersecting(Segment s) { bool intersecting = false; // Get nearby triangles HashSet<Triangle> triangles = s.GetNearbyTriangles(this, cellDistance); // Check intersection with nearby triangles foreach (Triangle triangle in triangles) { Point p1 = s.Intersection(new Segment(triangle.Points[0], triangle.Points[1])); Point p2 = s.Intersection(new Segment(triangle.Points[1], triangle.Points[2])); Point p3 = s.Intersection(new Segment(triangle.Points[2], triangle.Points[0])); if (p1 != null || p2 != null || p3 != null) return true; } //Parallel.ForEach(triangles, (triangle, state) => //{ // Point p1 = s.Intersection(new Segment(triangle.Points[0], triangle.Points[1])); // Point p2 = s.Intersection(new Segment(triangle.Points[1], triangle.Points[2])); // Point p3 = s.Intersection(new Segment(triangle.Points[2], triangle.Points[0])); // if (p1 != null || p2 != null || p3 != null) // { // intersecting = true; // state.Stop(); // } //}); // Get nearby segments of the front HashSet<Segment> segments = s.GetNearbySegments(this.Front, cellDistance); // Check intersecion with nearby segments foreach (Segment other in segments) { Point p = s.Intersection(other); if (p != null) return true; } //Parallel.ForEach(segments, (other, state) => //{ // Point p = s.Intersection(other); // if (p != null) // { // intersecting = true; // state.Stop(); // } //}); return false; //return intersecting; }
public Point Intersection(Segment other) { // Algo from stackoverflow Vector3D p = this.Start.ToVector3D(); Vector3D q = other.Start.ToVector3D(); Vector3D s = other.End.ToVector3D() - q; Vector3D r = this.End.ToVector3D() - p; Vector3D qmp = q - p; Vector3D rxs = new Vector3D(0, 0, s.X * r.Y - r.X * s.Y);//Vector3D.CrossProduct(r, s); Vector3D qmpxr = new Vector3D(0, 0, r.X * qmp.Y - qmp.X * r.Y);//Vector3D.CrossProduct(qmp, r); Vector3D qmpxs = new Vector3D(0, 0, s.X * qmp.Y - qmp.X * s.Y);//Vector3D.CrossProduct(qmp, s); if (/*rxs.Z == 0 && qmpxr.Z == 0.0*/ Math.Abs(rxs.Z) < Geometry.Epsilon && Math.Abs(qmpxr.Z) < Geometry.Epsilon && qmp.Length > Geometry.Epsilon) { // Collinear //p p+r q q+s if (p.X > Math.Min(q.X, (q + s).X) && p.X < Math.Max(q.X, (q + s).X) && p.Y > Math.Min(q.Y, (q + s).Y) && p.Y < Math.Max(q.Y, (q + s).Y)) return new Point(p.X, p.Y, 0.0); if ((p + r).X > Math.Min(q.X, (q + s).X) && (p + r).X < Math.Max(q.X, (q + s).X) && (p + r).Y > Math.Min(q.Y, (q + s).Y) && (p + r).Y < Math.Max(q.Y, (q + s).Y)) return new Point((p + r).X, (p + r).Y, 0.0); if (q.X > Math.Min(p.X, (p + r).X) && q.X < Math.Max(p.X, (p + r).X) && q.Y > Math.Min(p.Y, (p + r).Y) && q.Y < Math.Max(p.Y, (p + r).Y)) return new Point(q.X, q.Y, 0.0); if ((q + s).X > Math.Min(p.X, (p + r).X) && (q + s).X < Math.Max(p.X, (p + r).X) && (q + s).Y > Math.Min(p.Y, (p + r).Y) && (q + s).Y < Math.Max(p.Y, (p + r).Y)) return new Point((q + s).X, (q + s).Y, 0.0); return null; } if (Math.Abs(rxs.Z) < Geometry.Epsilon) { // Parallel. return null; } double t = qmpxs.Z / rxs.Z; double u = qmpxr.Z / rxs.Z; if ((t > 0.0 + Geometry.Epsilon) && (t < 1.0 - Geometry.Epsilon) && (u > 0.0 + Geometry.Epsilon) && (u < 1.0 - Geometry.Epsilon)) { return this.GetPoint(t); } return null; }
/// <summary> /// Removes the points from the front that are not part of any /// segment of the front. /// </summary> private void RemoveUnconnectedEndpoints(Segment s) { bool endRemains = false; bool startRemains = false; foreach (Segment segment in this.GetSegmentsUnordered()) { if (s.End.Equals(segment.End) || s.End.Equals(segment.Start)) { endRemains = true; } } foreach (Segment segment in this.GetSegmentsUnordered()) { if (s.Start.Equals(segment.End) || s.Start.Equals(segment.Start)) { startRemains = true; } } if (!endRemains) this.Points.Remove(s.End); if (!startRemains) this.Points.Remove(s.Start); }
public bool RemoveSegment(Segment s) { bool removed = false; double? toRemove = null; foreach (var item in this.Segments) { Segment sToRemove = null; foreach (Segment segment in item.Value) { if (s.Equals(segment)) { sToRemove = segment; //if (item.Value.Count == 0) //{ // Segments.Remove(item.Key); //} } } if (sToRemove != null) { item.Value.RemoveAll(seg => seg.Equals(sToRemove)); removed = true; } if (item.Value.Count == 0) { toRemove = item.Key; } } if (toRemove != null) { this.Segments.Remove((double)toRemove); } RemoveUnconnectedEndpoints(s); s.DisconnectEndpoints(); return removed; }