예제 #1
0
        private 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];
            vtx[0] = maxVtxs[imax];
            vtx[1] = minVtxs[imax];
            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");
            }

            if (debug)
            {
                Print("initial vertices:");
                Print(vtx[0].index + ": " + vtx[0].pnt);
                Print(vtx[1].index + ": " + vtx[1].pnt);
                Print(vtx[2].index + ": " + vtx[2].pnt);
                Print(vtx[3].index + ": " + vtx[3].pnt);
            }

            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 void computeMaxAndMin()
        {
            vector3d max = new vector3d();
            vector3d min = new vector3d();

            for (int i = 0; i < 3; i++)
            {
                maxVtxs[i] = minVtxs[i] = pointBuffer[0];
            }
            max.set(pointBuffer[0].pnt);
            min.set(pointBuffer[0].pnt);

            for (int i = 1; i < numPoints; i++)
            {
                point3d pnt = pointBuffer[i].pnt;
                if (pnt.x > max.x)
                {
                    max.x      = pnt.x;
                    maxVtxs[0] = pointBuffer[i];
                }
                else if (pnt.x < min.x)
                {
                    min.x      = pnt.x;
                    minVtxs[0] = pointBuffer[i];
                }
                if (pnt.y > max.y)
                {
                    max.y      = pnt.y;
                    maxVtxs[1] = pointBuffer[i];
                }
                else if (pnt.y < min.y)
                {
                    min.y      = pnt.y;
                    minVtxs[1] = pointBuffer[i];
                }
                if (pnt.z > max.z)
                {
                    max.z      = pnt.z;
                    maxVtxs[2] = pointBuffer[i];
                }
                else if (pnt.z < min.z)
                {
                    min.z      = pnt.z;
                    minVtxs[2] = pointBuffer[i];
                }
            }

            // this epsilon formula comes from QuickHull, and I'm
            // not about to quibble.
            charLength = Math.Max(max.x - min.x, max.y - min.y);
            charLength = Math.Max(max.z - min.z, charLength);
            if (explicitTolerance == AUTOMATIC_TOLERANCE)
            {
                tolerance =
                    3 * DOUBLE_PREC * (Math.Max(Math.Abs(max.x), Math.Abs(min.x)) +
                                       Math.Max(Math.Abs(max.y), Math.Abs(min.y)) +
                                       Math.Max(Math.Abs(max.z), Math.Abs(min.z)));
            }
            else
            {
                tolerance = explicitTolerance;
            }
        }