Esempio n. 1
0
        /// <summary>
        /// Construct a group of 4 edges {e[0], e[1], e[2], e[3]} where e[0] represent the canonical
        /// representative to which edge e belongs. This allows to represent and edge
        /// by dividing it into 4 edges.
        /// For more See 2.2 Duality (Definition 2.1.) and 5.BASIC TOPOLOGICAL OPERATORS in the article.
        /// </summary>
        public static QuadEdge <T> MakeEdge(Vec3 origin, Vec3 destination)
        {
            // Primal
            QuadEdge <T> qE0 = new QuadEdge <T>(null, null, origin);
            // Dual
            QuadEdge <T> qE1 = new QuadEdge <T>(null, null, null);
            // Primal
            QuadEdge <T> qE2 = new QuadEdge <T>(null, null, destination);
            // Dual
            QuadEdge <T> qE3 = new QuadEdge <T>(null, null, null);

            // Onext ring of the primal (delaunay)
            // See Fig.5 (c)
            qE0._oNext = qE0;
            qE2._oNext = qE2;

            // Onext ring of the Dual (Voronoi)
            // See Fig.5 (c)
            qE1._oNext = qE3;
            qE3._oNext = qE1;

            // Create connection between subdivision (allow to access Primal and Dual)
            // Implicitly set qE0.Destination = qE2.Origin (Destination == Rot.Rot.Origin)
            qE0._rot = qE1;
            qE1._rot = qE2;
            qE2._rot = qE3;
            qE3._rot = qE0;

            // Return the canonical representative.
            return(qE0);
        }
Esempio n. 2
0
        /// <summary>
        /// Construct a face abstraction based on a <paramref name="primal"/> edge.
        /// </summary>
        /// <param name="primal">Delaunay edge with Origin as face center.</param>
        /// <param name="onBounds">Mark face as a face on the faces bounds.</param>
        /// <param name="reconstructed">Must be true if face has a site at infinity.</param>
        public Face(QuadEdge <TEdge> primal, bool onBounds, bool reconstructed)
        {
            this._primal        = primal;
            this._onBounds      = onBounds;
            this._reconstructed = reconstructed;

            this._id = nextID++;
        }
Esempio n. 3
0
        /// <summary>
        /// This operation affects the two edge rings a.Origin and b.Origin and, independently,
        /// the two edge rings a.Left and b.Left. In each case,
        ///   - (a) if the two rings are distinct, Splice will combine them into one
        ///   - (b) if the two are exactly the same ring, Splice will break it in two separate pieces
        ///   - (c) if the two are the same ring taken with opposite orientations, Splice will Flip (and reverse the order)
        ///         of a segment of that ring
        /// </summary>
        /// <remarks>
        /// Splice is its own inverse and calling twice in a row revert it back to origin.
        /// Splice does not affect Rot neither Origin and Destination that have no topological meaning.
        /// </remarks>
        /// <param name="a">First QuadEdge<T></param>
        /// <param name="b">Second QuadEdge<T></param>
        public static void Splice(QuadEdge <T> a, QuadEdge <T> b)
        {
            QuadEdge <T> alpha = a._oNext._rot;
            QuadEdge <T> beta  = b._oNext._rot;

            // Swap them all !
            Helper.Swap <QuadEdge <T> >(ref a._oNext, ref b._oNext);
            Helper.Swap <QuadEdge <T> >(ref alpha._oNext, ref beta._oNext);
        }
Esempio n. 4
0
        /// <summary>
        /// Construct an edge.
        /// </summary>
        public QuadEdge(QuadEdge <T> oNext, QuadEdge <T> rot, Vec3 origin)
        {
            this._oNext  = oNext;
            this._rot    = rot;
            this._origin = origin;

            this.Tag = false;

            _id = QuadEdge <T> .nextID++;
        }
Esempio n. 5
0
        /// <summary>
        /// Iterate over every edge destination sharing the same origin (default to CW order)
        /// </summary>
        /// <param name="CCW">Select in which order vertices should be returned.</param>
        public IEnumerable <Vec3> DestinationsFrom(bool CCW = false)
        {
            QuadEdge <T> current = this;

            do
            {
                yield return(current.Destination);

                current = CCW ? current.Onext : current.Oprev;
            } while (current != this);
        }
Esempio n. 6
0
        /// <summary>
        /// Iterate over every edges sharing the same origin (default to CW order)
        /// </summary>
        /// <param name="CCW">Select in which order edges should be returned.</param>
        public IEnumerable <QuadEdge <T> > EdgesFrom(bool CCW = false)
        {
            QuadEdge <T> current = this;

            do
            {
                yield return(current);

                current = CCW ? current.Onext : current.Oprev;
            } while (current != this);
        }
Esempio n. 7
0
        /// <summary>
        /// Iterate over edges with same LEFT face (default to CW order)
        /// starting from this and return their origin.
        /// </summary>
        /// <param name="CCW">Select in which order vertices should be returned.</param>
        public IEnumerable <Vec3> LeftVertices(bool CCW = false)
        {
            QuadEdge <T> current = this;

            do
            {
                yield return(current.Origin);

                current = CCW ? current.Lnext : current.Lprev;
            } while (current != this);
        }
Esempio n. 8
0
        // Helpers enumerables used to abstract structure complexity

        /// <summary>
        /// Iterate over edges with same RIGHT face (default to CW order)
        /// starting from this.
        /// </summary>
        /// <param name="CCW">Select in which order vertices should be returned.</param>
        public IEnumerable <QuadEdge <T> > RightEdges(bool CCW = false)
        {
            QuadEdge <T> current = this;

            do
            {
                yield return(current);

                current = CCW ? current.Rnext : current.Rprev;
            } while (current != this);
        }
Esempio n. 9
0
        /// <summary>
        /// Connect two edges together leading to a.Destination --> b.Origin
        /// </summary>
        public static QuadEdge <T> Connect(QuadEdge <T> a, QuadEdge <T> b)
        {
            // Connect a to b
            QuadEdge <T> edge = MakeEdge(a.Destination, b.Origin);

            // See 6. TOPOLOGICAL OPERATORS FOR DELAUNAY DIAGRAMS
            Splice(edge, a.Lnext);
            Splice(edge.Sym, b);

            return(edge);
        }
Esempio n. 10
0
        /// <summary>
        /// Iterate over every vertices forming a face around this edge origin
        /// (default to CW order) assuming each edge face share the same left face.
        /// Edge between two sites at infinity does not exists (occurs for a face
        /// on the convex hull) and then a site will be missing.
        /// </summary>
        /// <remarks>
        /// In case of CCW == false missing edge Origin can be found by first taking
        /// left most edge (in primal graph) and then its Destination.
        /// </remarks>
        /// <param name="CCW">Select in which order vertices should be returned.</param>
        public IEnumerable <Vec3> FaceLeftVertices(bool CCW = false)
        {
            QuadEdge <T> current = this.Rot;
            var          first   = current;

            do
            {
                yield return(current.Origin);

                current = CCW ? current.Lnext : current.Lprev;
            } while (current != first);
        }
Esempio n. 11
0
        /// <summary>
        /// Swap common segment between two triangles. Can be used to transform
        /// a two non delaunay triangles to a pair of triangle respecting this constraint.
        /// </summary>
        /// <remarks>
        ///
        ///    /|\              / \
        ///   / | \            /   \
        ///  /  |  \          /     \
        ///  \  |  /   --->   \-----/
        ///   \ | /            \   /
        ///    \|/              \ /
        ///
        ///
        /// </remarks>
        public static void Swap(QuadEdge <T> edge)
        {
            QuadEdge <T> a = edge.Oprev;
            QuadEdge <T> b = edge.Sym.Oprev;

            // Disconnect edge
            Splice(edge, a);
            Splice(edge.Sym, b);

            // Reconnect edge
            Splice(edge, a.Lnext);
            Splice(edge.Sym, b.Lnext);

            // Update pointers
            edge._origin     = a.Destination;
            edge.Destination = b.Destination;
        }
Esempio n. 12
0
 /// <summary>
 /// Disconnect edge from the structure. Opposite operation of Connect.
 /// </summary>
 public static void Delete(QuadEdge <T> edge)
 {
     Splice(edge, edge.Oprev);
     Splice(edge.Sym, edge.Sym.Oprev);
 }