Пример #1
0
        protected void createInitialSimplex()
        {
            double max  = 0;
            int    imax = 0;

            for (int i = 0; i < 3; i++)
            {
                double diff = maxVtxs[i].pnt.get(i) - minVtxs[i].pnt.get(i);
                if (diff > max)
                {
                    max  = diff;
                    imax = i;
                }
            }

            if (max <= tolerance)
            {
                throw new Exception("Input points appear to be coincident");
            }
            Vertex[] vtx = new Vertex[4];
            // set first two vertices to be those with the greatest
            // one dimensional separation

            vtx[0] = maxVtxs[imax];
            vtx[1] = minVtxs[imax];
            // set third vertex to be the vertex farthest from
            // the line between vtx0 and vtx1
            Vector3d u01    = new Vector3d();
            Vector3d diff02 = new Vector3d();
            Vector3d nrml   = new Vector3d();
            Vector3d xprod  = new Vector3d();
            double   maxSqr = 0;

            u01.sub(vtx[1].pnt, vtx[0].pnt);
            u01.normalize();
            for (int i = 0; i < numPoints; i++)
            {
                diff02.sub(pointBuffer[i].pnt, vtx[0].pnt);
                xprod.cross(u01, diff02);
                double lenSqr = xprod.normSquared();
                if (lenSqr > maxSqr &&
                    pointBuffer[i] != vtx[0] && // paranoid
                    pointBuffer[i] != vtx[1])
                {
                    maxSqr = lenSqr;
                    vtx[2] = pointBuffer[i];
                    nrml.set(xprod);
                }
            }
            if (Math.Sqrt(maxSqr) <= 100 * tolerance)
            {
                throw new Exception("Input points appear to be colinear");
            }
            nrml.normalize();


            double maxDist = 0;
            double d0      = vtx[2].pnt.dot(nrml);

            for (int i = 0; i < numPoints; i++)
            {
                double dist = Math.Abs(pointBuffer[i].pnt.dot(nrml) - d0);
                if (dist > maxDist &&
                    pointBuffer[i] != vtx[0] && // paranoid
                    pointBuffer[i] != vtx[1] &&
                    pointBuffer[i] != vtx[2])
                {
                    maxDist = dist;
                    vtx[3]  = pointBuffer[i];
                }
            }
            if (Math.Abs(maxDist) <= 100 * tolerance)
            {
                throw new Exception("Input points appear to be coplanar");
            }

            Face[] tris = new Face[4];

            if (vtx[3].pnt.dot(nrml) - d0 < 0)
            {
                tris[0] = Face.createTriangle(vtx[0], vtx[1], vtx[2]);
                tris[1] = Face.createTriangle(vtx[3], vtx[1], vtx[0]);
                tris[2] = Face.createTriangle(vtx[3], vtx[2], vtx[1]);
                tris[3] = Face.createTriangle(vtx[3], vtx[0], vtx[2]);

                for (int i = 0; i < 3; i++)
                {
                    int k = (i + 1) % 3;
                    tris[i + 1].getEdge(1).setOpposite(tris[k + 1].getEdge(0));
                    tris[i + 1].getEdge(2).setOpposite(tris[0].getEdge(k));
                }
            }
            else
            {
                tris[0] = Face.createTriangle(vtx[0], vtx[2], vtx[1]);
                tris[1] = Face.createTriangle(vtx[3], vtx[0], vtx[1]);
                tris[2] = Face.createTriangle(vtx[3], vtx[1], vtx[2]);
                tris[3] = Face.createTriangle(vtx[3], vtx[2], vtx[0]);

                for (int i = 0; i < 3; i++)
                {
                    int k = (i + 1) % 3;
                    tris[i + 1].getEdge(0).setOpposite(tris[k + 1].getEdge(1));
                    tris[i + 1].getEdge(2).setOpposite(tris[0].getEdge((3 - i) % 3));
                }
            }
            for (int i = 0; i < 4; i++)
            {
                faces.Add(tris[i]);
            }

            for (int i = 0; i < numPoints; i++)
            {
                Vertex v = pointBuffer[i];

                if (v == vtx[0] || v == vtx[1] || v == vtx[2] || v == vtx[3])
                {
                    continue;
                }

                maxDist = tolerance;
                Face maxFace = null;
                for (int k = 0; k < 4; k++)
                {
                    double dist = tris[k].distanceToPlane(v.pnt);
                    if (dist > maxDist)
                    {
                        maxFace = tris[k];
                        maxDist = dist;
                    }
                }
                if (maxFace != null)
                {
                    addPointToFace(v, maxFace);
                }
            }
        }
Пример #2
0
        private bool doAdjacentMerge(Face face, int mergeType)
        {
            HalfEdge hedge = face.he0;

            bool convex = true;

            do
            {
                Face   oppFace = hedge.oppositeFace();
                bool   merge = false;
                double dist1, dist2;

                if (mergeType == NONCONVEX)
                { // then merge faces if they are definitively non-convex
                    if (oppFaceDistance(hedge) > -tolerance ||
                        oppFaceDistance(hedge.opposite) > -tolerance)
                    {
                        merge = true;
                    }
                }
                else // mergeType == NONCONVEX_WRT_LARGER_FACE
                { // merge faces if they are parallel or non-convex
                    // wrt to the larger face; otherwise, just mark
                    // the face non-convex for the second pass.
                    if (face.area > oppFace.area)
                    {
                        if ((dist1 = oppFaceDistance(hedge)) > -tolerance)
                        {
                            merge = true;
                        }
                        else if (oppFaceDistance(hedge.opposite) > -tolerance)
                        {
                            convex = false;
                        }
                    }
                    else
                    {
                        if (oppFaceDistance(hedge.opposite) > -tolerance)
                        {
                            merge = true;
                        }
                        else if (oppFaceDistance(hedge) > -tolerance)
                        {
                            convex = false;
                        }
                    }
                }

                if (merge)
                {
                    if (debug)
                    {
                        Console.WriteLine(
                            "  merging " + face.getVertexString() + "  and  " +
                            oppFace.getVertexString());
                    }

                    int numd = face.mergeAdjacentFace(hedge, discardedFaces);
                    for (int i = 0; i < numd; i++)
                    {
                        deleteFacePoints(discardedFaces[i], face);
                    }
                    if (debug)
                    {
                        Console.WriteLine(
                            "  result: " + face.getVertexString());
                    }
                    return(true);
                }
                hedge = hedge.next;
            }while (hedge != face.he0);
            if (!convex)
            {
                face.mark = Face.NON_CONVEX;
            }
            return(false);
        }
Пример #3
0
 /**
  * Constructs a HalfEdge with head vertex <code>v</code> and
  * left-hand triangular face <code>f</code>.
  *
  * @param v head vertex
  * @param f left-hand triangular face
  */
 public HalfEdge(Vertex v, Face f)
 {
     vertex = v;
     face   = f;
 }