Beispiel #1
0
        /// <summary>
        /// Represents a simple polygon's edge
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        public Edge(TriPoint p1, TriPoint p2)
        {
            P = p1;
            Q = p2;

            if (p1.Y > p2.Y)
            {
                Q = p1;
                P = p2;
            }
            else if (p1.Y == p2.Y)
            {
                if (p1.X > p2.X)
                {
                    Q = p1;
                    P = p2;
                }
                else if (p1.X == p2.X)
                {
                    // Repeat points
                    throw new Exception("Edge::Edge: p1 == p2");
                }
            }

            Q.EdgeList = Q.EdgeList ?? new List <Edge>();
            Q.EdgeList.Add(this);
        }
Beispiel #2
0
 /// <summary>
 /// Legalize triagnle by rotating clockwise around oPoint
 /// </summary>
 /// <param name="opoint"></param>
 /// <param name="npoint"></param>
 public void Legalize(TriPoint opoint, TriPoint npoint)
 {
     if (opoint.Equals(Points[0]))
     {
         Points[1] = Points[0];
         Points[0] = Points[2];
         Points[2] = npoint;
     }
     else if (opoint.Equals(Points[1]))
     {
         Points[2] = Points[1];
         Points[1] = Points[0];
         Points[0] = npoint;
     }
     else if (opoint.Equals(Points[2]))
     {
         Points[0] = Points[2];
         Points[2] = Points[1];
         Points[1] = npoint;
     }
     else
     {
         Debug.Assert(false, "What happened here????");
     }
 }
Beispiel #3
0
 public Triangle(TriPoint a, TriPoint b, TriPoint c)
 {
     Points          = new TriPoint[] { a, b, c };
     ConstrainedEdge = new bool[3];
     DelaunayEdge    = new bool[3];
     _neighbours     = new Triangle[3];
 }
Beispiel #4
0
        public Node LocatePoint(TriPoint point)
        {
            double px   = point.X;
            Node   node = _search_node;
            double nx   = node.Point.X;

            if (px == nx)
            {
                if (point != node.Point)
                {
                    // We might have two nodes with same x value for a short time
                    if (point == node.Prev.Point)
                    {
                        node = node.Prev;
                    }
                    else if (point == node.Next.Point)
                    {
                        node = node.Next;
                    }
                    else
                    {
                        Debug.Assert(false, "What happened here????");
                    }
                }
            }
            else if (px < nx)
            {
                while ((node = node.Prev) != null)
                {
                    if (point == node.Point)
                    {
                        break;
                    }
                }
            }
            else
            {
                while ((node = node.Next) != null)
                {
                    if (point == node.Point)
                    {
                        break;
                    }
                }
            }
            if (node != null)
            {
                _search_node = node;
            }

            return(node);
        }
Beispiel #5
0
        private void FinalizationPolygon(SweepContext tcx)
        {
            // Get an Internal triangle to start with
            Triangle t = tcx.Front._head.Next.Triangle;
            TriPoint p = tcx.Front._head.Next.Point;

            while (!t.GetConstrainedEdgeCW(p))
            {
                t = t.NeighborCCW(p);
            }

            tcx.MeshClean(t);
        }
Beispiel #6
0
        public bool GetConstrainedEdgeCW(TriPoint p)
        {
            if (p.Equals(Points[0]))
            {
                return(ConstrainedEdge[1]);
            }
            else if (p.Equals(Points[1]))
            {
                return(ConstrainedEdge[2]);
            }

            return(ConstrainedEdge[0]);
        }
Beispiel #7
0
        public bool GetDelaunayEdgeCW(TriPoint p)
        {
            if (p.Equals(Points[0]))
            {
                return(DelaunayEdge[1]);
            }
            else if (p.Equals(Points[1]))
            {
                return(DelaunayEdge[2]);
            }

            return(DelaunayEdge[0]);
        }
Beispiel #8
0
        public Triangle NeighborCCW(TriPoint point)
        {
            if (point.Equals(Points[0]))
            {
                return(_neighbours[2]);
            }
            else if (point.Equals(Points[1]))
            {
                return(_neighbours[0]);
            }

            return(_neighbours[1]);
        }
Beispiel #9
0
        public Triangle NeighborAcross(TriPoint opoint)
        {
            if (opoint.Equals(Points[0]))
            {
                return(_neighbours[0]);
            }
            else if (opoint.Equals(Points[1]))
            {
                return(_neighbours[1]);
            }

            return(_neighbours[2]);
        }
Beispiel #10
0
 /// <summary>
 /// Mark edge as constrained
 /// </summary>
 /// <param name="p"></param>
 /// <param name="q"></param>
 public void MarkConstrainedEdge(TriPoint p, TriPoint q)
 {
     if ((q.Equals(Points[0]) && p.Equals(Points[1])) || (q.Equals(Points[1]) && p.Equals(Points[0])))
     {
         ConstrainedEdge[2] = true;
     }
     else if ((q.Equals(Points[0]) && p.Equals(Points[2])) || (q.Equals(Points[2]) && p.Equals(Points[0])))
     {
         ConstrainedEdge[1] = true;
     }
     else if ((q.Equals(Points[1]) && p.Equals(Points[2])) || (q.Equals(Points[2]) && p.Equals(Points[1])))
     {
         ConstrainedEdge[0] = true;
     }
 }
Beispiel #11
0
 public void SetConstrainedEdgeCW(TriPoint p, bool ce)
 {
     if (p.Equals(Points[0]))
     {
         ConstrainedEdge[1] = ce;
     }
     else if (p.Equals(Points[1]))
     {
         ConstrainedEdge[2] = ce;
     }
     else
     {
         ConstrainedEdge[0] = ce;
     }
 }
Beispiel #12
0
 public void SetDelunayEdgeCW(TriPoint p, bool e)
 {
     if (p.Equals(Points[0]))
     {
         DelaunayEdge[1] = e;
     }
     else if (p.Equals(Points[1]))
     {
         DelaunayEdge[2] = e;
     }
     else
     {
         DelaunayEdge[0] = e;
     }
 }
Beispiel #13
0
        private void SweepPoints(SweepContext tcx)
        {
            for (int i = 1; i < tcx.PointCount(); i++)
            {
                TriPoint point = tcx.GetPoint(i);
                Node     node  = PointEvent(tcx, point);

                if (point.EdgeList != null)
                {
                    for (int j = 0; j < point.EdgeList.Count; j++)
                    {
                        EdgeEvent(tcx, point.EdgeList[j], node);
                    }
                }
            }
        }
Beispiel #14
0
        public static Winding Orient2d(TriPoint pa, TriPoint pb, TriPoint pc)
        {
            double detleft  = (pa.X - pc.X) * (pb.Y - pc.Y);
            double detright = (pa.Y - pc.Y) * (pb.X - pc.X);
            double val      = detleft - detright;

            if (val > -EPSILON && val < EPSILON)
            {
                return(Winding.Collinear);
            }
            else if (val > 0)
            {
                return(Winding.CCW);
            }

            return(Winding.CW);
        }
Beispiel #15
0
        private TriPoint NextFlipPoint(TriPoint ep, TriPoint eq, Triangle ot, TriPoint op)
        {
            Winding o2d = TriUtil.Orient2d(eq, op, ep);

            if (o2d == Winding.CW)
            {
                // Right
                return(ot.PointCCW(op));
            }
            else if (o2d == Winding.CCW)
            {
                // Left
                return(ot.PointCW(op));
            }

            throw new NotSupportedException("[Unsupported] Opposing point on constrained edge");
        }
Beispiel #16
0
        private Node PointEvent(SweepContext tcx, TriPoint point)
        {
            Node node     = tcx.LocateNode(point);
            Node new_node = NewFrontTriangle(tcx, point, node);

            // Only need to check +epsilon since point never have smaller
            // x value than node due to how we fetch nodes from the front
            if (point.X <= node.Point.X + TriUtil.EPSILON)
            {
                Fill(tcx, node);
            }

            //tcx.AddNode(new_node);

            FillAdvancingFront(tcx, new_node);
            return(new_node);
        }
Beispiel #17
0
        /// <summary>
        /// The point counter-clockwise to given point
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        public TriPoint PointCCW(TriPoint point)
        {
            if (point.Equals(Points[0]))
            {
                return(Points[1]);
            }
            else if (point.Equals(Points[1]))
            {
                return(Points[2]);
            }
            else if (point.Equals(Points[2]))
            {
                return(Points[0]);
            }

            Debug.Assert(false, "What happened here????");
            return(TriPoint.Empty);
        }
Beispiel #18
0
        private bool IsEdgeSideOfTriangle(Triangle triangle, TriPoint ep, TriPoint eq)
        {
            int index = triangle.EdgeIndex(ep, eq);

            if (index != -1)
            {
                triangle.MarkConstrainedEdge(index);
                Triangle t = triangle.GetNeighbor(index);
                if (t != null)
                {
                    t.MarkConstrainedEdge(ep, eq);
                }

                return(true);
            }

            return(false);
        }
Beispiel #19
0
        public int Index(TriPoint p)
        {
            if (p.Equals(Points[0]))
            {
                return(0);
            }
            else if (p.Equals(Points[1]))
            {
                return(1);
            }
            else if (p.Equals(Points[2]))
            {
                return(2);
            }

            Debug.Assert(false, "What happened here????");
            return(-1);
        }
Beispiel #20
0
        public static bool InScanArea(TriPoint pa, TriPoint pb, TriPoint pc, TriPoint pd)
        {
            double oadb = (pa.X - pb.X) * (pd.Y - pb.Y) - (pd.X - pb.X) * (pa.Y - pb.Y);

            if (oadb >= -EPSILON)
            {
                return(false);
            }


            double oadc = (pa.X - pc.X) * (pd.Y - pc.Y) - (pd.X - pc.X) * (pa.Y - pc.Y);

            if (oadc <= EPSILON)
            {
                return(false);
            }

            return(true);
        }
Beispiel #21
0
 /// <summary>
 /// Update neighbor pointers
 /// </summary>
 /// <param name="p1"></param>
 /// <param name="p2"></param>
 /// <param name="t"></param>
 public void MarkNeighbor(TriPoint p1, TriPoint p2, Triangle t)
 {
     if ((p1.Equals(Points[2]) && p2.Equals(Points[1])) || (p1.Equals(Points[1]) && p2.Equals(Points[2])))
     {
         _neighbours[0] = t;
     }
     else if ((p1.Equals(Points[0]) && p2.Equals(Points[2])) || (p1.Equals(Points[2]) && p2.Equals(Points[0])))
     {
         _neighbours[1] = t;
     }
     else if ((p1.Equals(Points[0]) && p2.Equals(Points[1])) || (p1.Equals(Points[1]) && p2.Equals(Points[0])))
     {
         _neighbours[2] = t;
     }
     else
     {
         Debug.Assert(false, "Specified trianlge is not a neighbor");
     }
 }
Beispiel #22
0
        private double Angle(TriPoint origin, TriPoint pa, TriPoint pb)
        {
            /* Complex plane
             * ab = cosA +i*sinA
             * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
             * atan2(y,x) computes the principal value of the argument function
             * applied to the complex number x+iy
             * Where x = ax*bx + ay*by
             *       y = ax*by - ay*bx
             */
            double px = origin.X;
            double py = origin.Y;
            double ax = pa.X - px;
            double ay = pa.Y - py;
            double bx = pb.X - px;
            double by = pb.Y - py;
            double x  = ax * by - ay * bx;
            double y  = ax * bx + ay * by;

            return(System.Math.Atan2(x, y));
        }
Beispiel #23
0
        private void FlipEdgeEvent(SweepContext tcx, TriPoint ep, TriPoint eq, Triangle t, TriPoint p)
        {
            Triangle ot = t.NeighborAcross(p);
            TriPoint op = ot.OppositePoint(t, p);

            if (TriUtil.InScanArea(p, t.PointCCW(p), t.PointCW(p), op))
            {
                // Lets rotate shared edge one vertex CW
                RotateTrianglePair(t, p, ot, op);
                tcx.MapTriangleToNodes(t);
                tcx.MapTriangleToNodes(ot);

                if (p == eq && op == ep)
                {
                    if (eq == tcx.EdgeEvent.ConstrainedEdge.Q && ep == tcx.EdgeEvent.ConstrainedEdge.P)
                    {
                        t.MarkConstrainedEdge(ep, eq);
                        ot.MarkConstrainedEdge(ep, eq);
                        Legalize(tcx, t);
                        Legalize(tcx, ot);
                    }
                    else
                    {
                        // XXX: I think one of the triangles should be legalized here?
                    }
                }
                else
                {
                    Winding o = TriUtil.Orient2d(eq, op, ep);
                    t = NextFlipTriangle(tcx, o, t, ot, p, op);
                    FlipEdgeEvent(tcx, ep, eq, t, p);
                }
            }
            else
            {
                TriPoint newP = NextFlipPoint(ep, eq, ot, op);
                FlipScanEdgeEvent(tcx, ep, eq, t, ot, newP);
                EdgeEvent(tcx, ep, eq, t, p);
            }
        }
Beispiel #24
0
        /**
         * <b>Requirement</b>:<br>
         * 1. a,b and c form a triangle.<br>
         * 2. a and d is know to be on opposite side of bc<br>
         * <pre>
         *                a
         *                +
         *               / \
         *              /   \
         *            b/     \c
         *            +-------+
         *           /    d    \
         *          /           \
         * </pre>
         * <b>Fact</b>: d has to be in area B to have a chance to be inside the circle formed by
         *  a,b and c<br>
         *  d is outside B if TriUtil.Orient2d(a,b,d) or TriUtil.Orient2d(c,a,d) is CW<br>
         *  This preknowledge gives us a way to optimize the incircle test
         * @param a - triangle point, opposite d
         * @param b - triangle point
         * @param c - triangle point
         * @param d - point opposite a
         * @return true if d is inside circle, false if on circle edge
         */
        private bool Incircle(TriPoint pa, TriPoint pb, TriPoint pc, TriPoint pd)
        {
            double adx = pa.X - pd.X;
            double ady = pa.Y - pd.Y;
            double bdx = pb.X - pd.X;
            double bdy = pb.Y - pd.Y;

            double adxbdy = adx * bdy;
            double bdxady = bdx * ady;
            double oabd   = adxbdy - bdxady;

            if (oabd <= 0)
            {
                return(false);
            }

            double cdx = pc.X - pd.X;
            double cdy = pc.Y - pd.Y;

            double cdxady = cdx * ady;
            double adxcdy = adx * cdy;
            double ocad   = cdxady - adxcdy;

            if (ocad <= 0)
            {
                return(false);
            }

            double bdxcdy = bdx * cdy;
            double cdxbdy = cdx * bdy;

            double alift = adx * adx + ady * ady;
            double blift = bdx * bdx + bdy * bdy;
            double clift = cdx * cdx + cdy * cdy;

            double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;

            return(det > 0);
        }
Beispiel #25
0
        public void InitTriangulation()
        {
            float xmax = _points[0].X;
            float xmin = _points[0].X;
            float ymax = _points[0].Y;
            float ymin = _points[0].Y;

            // Calculate bounds
            for (int i = 0; i < _points.Count; i++)
            {
                TriPoint p = _points[i];
                if (p.X > xmax)
                {
                    xmax = p.X;
                }
                if (p.X < xmin)
                {
                    xmin = p.X;
                }
                if (p.Y > ymax)
                {
                    ymax = p.Y;
                }
                if (p.Y < ymin)
                {
                    ymin = p.Y;
                }
            }

            float dx = K_ALPHA * (xmax - xmin);
            float dy = K_ALPHA * (ymax - ymin);

            _head = new TriPoint(xmax + dx, ymin - dy);
            _tail = new TriPoint(xmin - dx, ymin - dy);

            // Sort points along y-axis
            _points.Sort(_cmp);
        }
Beispiel #26
0
        public int EdgeIndex(TriPoint p1, TriPoint p2)
        {
            if (Points[0].Equals(p1))
            {
                if (Points[1].Equals(p2))
                {
                    return(2);
                }
                else if (Points[2].Equals(p2))
                {
                    return(1);
                }
            }
            else if (Points[1].Equals(p1))
            {
                if (Points[2].Equals(p2))
                {
                    return(0);
                }
                else if (Points[0].Equals(p2))
                {
                    return(2);
                }
            }
            else if (Points[2].Equals(p1))
            {
                if (Points[0].Equals(p2))
                {
                    return(1);
                }
                else if (Points[1].Equals(p2))
                {
                    return(0);
                }
            }

            return(-1);
        }
Beispiel #27
0
        private Node NewFrontTriangle(SweepContext tcx, TriPoint point, Node node)
        {
            Triangle triangle = new Triangle(point, node.Point, node.Next.Point);

            triangle.MarkNeighbor(node.Triangle);
            tcx.AddToMap(triangle);

            Node new_node = new Node(point);

            _nodes.Add(new_node);

            new_node.Next  = node.Next;
            new_node.Prev  = node;
            node.Next.Prev = new_node;
            node.Next      = new_node;

            if (!Legalize(tcx, triangle))
            {
                tcx.MapTriangleToNodes(triangle);
            }

            return(new_node);
        }
Beispiel #28
0
        private void FlipScanEdgeEvent(SweepContext tcx, TriPoint ep, TriPoint eq, Triangle flip_triangle, Triangle t, TriPoint p)
        {
            Triangle ot = t.NeighborAcross(p);
            TriPoint op = ot.OppositePoint(t, p);

            if (TriUtil.InScanArea(eq, flip_triangle.PointCCW(eq), flip_triangle.PointCW(eq), op))
            {
                // flip with new edge op->eq
                FlipEdgeEvent(tcx, eq, op, ot, op);
                // TODO: Actually I just figured out that it should be possible to
                //       improve this by getting the next ot and op before the the above
                //       flip and continue the flipScanEdgeEvent here
                // set new ot and op here and loop back to inScanArea test
                // also need to set a new flip_triangle first
                // Turns out at first glance that this is somewhat complicated
                // so it will have to wait.
            }
            else
            {
                TriPoint newP = NextFlipPoint(ep, eq, ot, op);
                FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP);
            }
        }
Beispiel #29
0
 public void AddPoint(TriPoint point)
 {
     _points.Add(point);
 }
Beispiel #30
0
 public void SetHead(TriPoint p1)
 {
     _head = p1;
 }