コード例 #1
0
ファイル: Segment.cs プロジェクト: naszta/MeshGenerator
 /// <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;
 }
コード例 #2
0
ファイル: Front.cs プロジェクト: naszta/MeshGenerator
 /// <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();
 }
コード例 #3
0
ファイル: Front.cs プロジェクト: naszta/MeshGenerator
 /// <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;
 }
コード例 #4
0
ファイル: Segment.cs プロジェクト: naszta/MeshGenerator
 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;
 }
コード例 #5
0
ファイル: Front.cs プロジェクト: naszta/MeshGenerator
        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);
        }
コード例 #6
0
ファイル: Segment.cs プロジェクト: naszta/MeshGenerator
 /// <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;
 }
コード例 #7
0
        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;
        }
コード例 #8
0
        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);
            }
        }
コード例 #9
0
        /// <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;
        }
コード例 #10
0
ファイル: Segment.cs プロジェクト: naszta/MeshGenerator
        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;
        }
コード例 #11
0
ファイル: Front.cs プロジェクト: naszta/MeshGenerator
        /// <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);
        }
コード例 #12
0
ファイル: Front.cs プロジェクト: naszta/MeshGenerator
 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;
 }