Exemplo n.º 1
0
        /// <summary>
        /// Compute the convex hull in 3-D space
        /// </summary>
        /// <returns>surfaces of the convex hull</returns>
        public List <TriangularFace> Compute()
        {
            NumFace = 0;
            if (NumVertex < 4)
            {
                return(null);
            }

            Prepare();

            for (int i = 4; i < NumVertex; i++)
            {
                for (int j = 0; j < NumFace; j++)
                {
                    if (HullFace[j].Valid && HullFace[j].VOutFace(Vertices[i]))
                    {
                        Horizon.Clear();
                        ComputeHorizon(HullFace[j], Vertices[i]);
                        SortHorizons();

                        TriangularFace first = null;
                        TriangularFace last  = null;
                        DualSite       v     = Vertices[i];
                        for (int ii = 0; ii < Horizon.Count; ii++)
                        {
                            Edge           e   = Horizon[ii];
                            TriangularFace f   = e.NeighborFace;
                            TriangularFace add = new TriangularFace(e.Vertex0, e.Vertex1, v);
                            HullFace.Add(add);
                            NumFace++;
                            f.SetNeighbor(add, e.Vertex0, e.Vertex1);
                            if (first == null)
                            {
                                first = add;
                            }
                            else
                            {
                                add.SetNeighbor(last, e.Vertex0, v);
                            }
                            last = add;
                        }

                        last.SetNeighbor(first, last.Edge0.Vertex1, Vertices[i]);
                        break;
                    }
                }
            }

            List <TriangularFace> result = new List <TriangularFace>();

            for (int i = 0; i < HullFace.Count; i++)
            {
                if (HullFace[i].Valid)
                {
                    result.Add(HullFace[i]);
                }
            }
            return(result);
        }
Exemplo n.º 2
0
        /// <summary>
        /// let the first three vertices noncollinear and the first four vertices noncoplanar
        /// </summary>
        private void Prepare()
        {
            Vector3D tmp_vector = new Vector3D();

            for (int i = 2; i < NumVertex; i++)
            {
                tmp_vector = Vector3D.CrossProduct(Vertices[1].Coordinate - Vertices[0].Coordinate, Vertices[i].Coordinate - Vertices[0].Coordinate);
                if (tmp_vector.LengthSquared > Eps)//三点不共线
                {
                    if (i != 2)
                    {
                        DualSite tmp = Vertices[i];
                        Vertices[i] = Vertices[2];
                        Vertices[2] = tmp;
                    }
                    break;
                }
            }

            for (int i = 3; i < NumVertex; i++)
            {
                if (Math.Abs(Vector3D.DotProduct(tmp_vector, Vertices[i].Coordinate - Vertices[0].Coordinate)) > Eps)//四点不共面
                {
                    if (i != 3)
                    {
                        DualSite tmp = Vertices[i];
                        Vertices[i] = Vertices[3];
                        Vertices[3] = tmp;
                    }
                    break;
                }
            }

            //为使面法向量方向指向凸包外
            TriangularFace tmp_face = new TriangularFace(Vertices[0], Vertices[1], Vertices[2]);

            if (tmp_face.VOutFace(Vertices[3]))
            {
                DualSite tmp = Vertices[2];
                Vertices[2] = Vertices[3];
                Vertices[3] = tmp;
            }
            HullFace.Add(new TriangularFace(Vertices[0], Vertices[1], Vertices[2]));
            HullFace.Add(new TriangularFace(Vertices[1], Vertices[3], Vertices[2]));
            HullFace.Add(new TriangularFace(Vertices[0], Vertices[2], Vertices[3]));
            HullFace.Add(new TriangularFace(Vertices[0], Vertices[3], Vertices[1]));

            HullFace[0].SetNeighbor(HullFace[1], Vertices[1], Vertices[2]);
            HullFace[0].SetNeighbor(HullFace[2], Vertices[0], Vertices[2]);
            HullFace[0].SetNeighbor(HullFace[3], Vertices[0], Vertices[1]);
            HullFace[1].SetNeighbor(HullFace[2], Vertices[2], Vertices[3]);
            HullFace[1].SetNeighbor(HullFace[3], Vertices[1], Vertices[3]);
            HullFace[2].SetNeighbor(HullFace[3], Vertices[0], Vertices[3]);

            NumFace = 4;
        }
Exemplo n.º 3
0
        private void MainLoop()
        {
            int count = 0;

            while (faceQueue.Count > 0)
            {
                count++;
                HullFace face = faceQueue.Dequeue();

                if (face.active == false)
                {
                    continue;
                }

                if (face.furthestIndex != -1)
                {
                    int p0 = face.furthestIndex;

                    this.hullVertices.Add(p0);

                    // collect visible faces, boundary edges and assoicated vertices
                    List <HullFace>      holeFace         = new List <HullFace>();
                    HashSet <EdgeRecord> holeBoundary     = new HashSet <EdgeRecord>();
                    HashSet <int>        assoicatedVertex = new HashSet <int>();
                    foreach (HullFace f in this.surfaceSet)
                    {
                        Vector3d v = this.p[p0] - this.p[f.p1];
                        if (v.Dot(f.normal) > 0)
                        {
                            holeFace.Add(f);

                            int        p1 = f.p1;
                            int        p2 = f.p2;
                            int        p3 = f.p3;
                            EdgeRecord r1 = new EdgeRecord(p1, p2);
                            EdgeRecord r2 = new EdgeRecord(p2, p3);
                            EdgeRecord r3 = new EdgeRecord(p3, p1);
                            if (holeBoundary.Contains(r1))
                            {
                                holeBoundary.Remove(r1);
                            }
                            else
                            {
                                holeBoundary.Add(r1);
                            }
                            if (holeBoundary.Contains(r2))
                            {
                                holeBoundary.Remove(r2);
                            }
                            else
                            {
                                holeBoundary.Add(r2);
                            }
                            if (holeBoundary.Contains(r3))
                            {
                                holeBoundary.Remove(r3);
                            }
                            else
                            {
                                holeBoundary.Add(r3);
                            }

                            foreach (int index in f.associatedPoints)
                            {
                                assoicatedVertex.Add(index);
                            }
                        }
                    }
                    if (holeFace.Count == 0)
                    {
                        throw new Exception();
                    }

                    // remove add visible faces
                    foreach (HullFace f in holeFace)
                    {
                        this.surfaceSet.Remove(f);
                        f.active = false;
                    }

                    // add new faces
                    foreach (EdgeRecord edge in holeBoundary)
                    {
                        HullFace newFace = new HullFace(p0, edge.p1, edge.p2);
                        newFace.normal = ((p[edge.p1] - p[p0]).Cross(p[edge.p2] - p[p0])).normalize();
                        this.surfaceSet.Add(newFace);
                        this.faceQueue.Enqueue(newFace);

                        // add assoicated vertices
                        foreach (int index in assoicatedVertex)
                        {
                            if (index == p0)
                            {
                                continue;
                            }

                            double dis = (p[index] - p[p0]).Dot(newFace.normal);
                            if (dis > 0)
                            {
                                newFace.AddPoint(index, dis);
                            }
                        }
                    }
                }
            }
            computeCenter();
        }
Exemplo n.º 4
0
        private void InitHullFaces()
        {
            // get init points
            int[] initPts = FindInitPoints();
            this.initIndex = initPts;
            int    p0  = initPts[0];
            int    p1  = initPts[1];
            int    p2  = initPts[2];
            int    p3  = initPts[3];
            double vol = (p[p1] - p[p0]).Dot((p[p2] - p[p0]).Cross(p[p3] - p[p0]));

            if (vol > 0)
            {
                int t = p0; p0 = p1; p1 = t;
            }
            this.hullVertices.Add(p0);
            this.hullVertices.Add(p1);
            this.hullVertices.Add(p2);
            this.hullVertices.Add(p3);

            // create hull faces
            HullFace f1 = new HullFace(p0, p1, p2); this.faceQueue.Enqueue(f1);
            HullFace f2 = new HullFace(p3, p1, p0); this.faceQueue.Enqueue(f2);
            HullFace f3 = new HullFace(p3, p2, p1); this.faceQueue.Enqueue(f3);
            HullFace f4 = new HullFace(p3, p0, p2); this.faceQueue.Enqueue(f4);

            f1.normal = ((p[p1] - p[p0]).Cross(p[p2] - p[p0])).normalize();
            f2.normal = ((p[p1] - p[p3]).Cross(p[p0] - p[p3])).normalize();
            f3.normal = ((p[p2] - p[p3]).Cross(p[p1] - p[p3])).normalize();
            f4.normal = ((p[p0] - p[p3]).Cross(p[p2] - p[p3])).normalize();
            this.surfaceSet.Add(f1);
            this.surfaceSet.Add(f2);
            this.surfaceSet.Add(f3);
            this.surfaceSet.Add(f4);
            // assoicate vertices outside current hull
            foreach (int i in this.pointIndex)
            {
                if (i == p0 || i == p1 || i == p2 || i == p3)
                {
                    continue;
                }
                double d1 = (p[i] - p[p0]).Dot(f1.normal);
                double d2 = (p[i] - p[p3]).Dot(f2.normal);
                double d3 = (p[i] - p[p3]).Dot(f3.normal);
                double d4 = (p[i] - p[p3]).Dot(f4.normal);
                if (d1 < 0 && d2 < 0 && d3 < 0 && d4 < 0)
                {
                    continue;
                }
                if (d1 > 0)
                {
                    f1.AddPoint(i, d1);
                }
                if (d2 > 0)
                {
                    f2.AddPoint(i, d2);
                }
                if (d3 > 0)
                {
                    f3.AddPoint(i, d3);
                }
                if (d4 > 0)
                {
                    f4.AddPoint(i, d4);
                }
            }
        }
Exemplo n.º 5
0
            public List<HullEdge> GetSharedEdges(HullFace other)
            {
                List<HullEdge> result = new List<HullEdge>();

                if (ab.IsContainedIn(other))
                    result.Add(ab);
                if (ca.IsContainedIn(other))
                    result.Add(ca);
                if (bc.IsContainedIn(other))
                    result.Add(bc);

                return result;
            }
Exemplo n.º 6
0
 public bool IsContainedIn(HullFace other)
 {
     return Equivalent(other.ab) || Equivalent(other.ca) || Equivalent(other.bc);
 }