void Cleanup()
        {
            for (int i = 0; i < edges.Count; ++i)
            {
                ConvexHullEdge edge = edges[i];
                if (edge.remove)
                {
                    Vector3D point1 = edge.pointA;
                    Vector3D point2 = edge.pointB;

                    int keyToEvict = Key2Edge(point1, point2);
                    edgeMap.Remove(keyToEvict);
                    edges.RemoveAt(i--);
                }
            }

            for (int i = 0; i < faces.Count; ++i)
            {
                ConvexHullFace face = faces[i];

                if (face.visible)
                {
                    faces.RemoveAt(i--);
                }
            }
        }
        private void CreateEdge(Vector3D pointA, Vector3D pointB, ConvexHullFace face)
        {
            int key = Key2Edge(pointA, pointB);

            if (!edgeMap.ContainsKey(key))
            {
                ConvexHullEdge edge = new ConvexHullEdge(pointA, pointB);
                edges.Add(edge);
                edgeMap.Add(key, edge);
            }

            edgeMap[key].LinkAdjFace(face);
        }
        Vector3D FindInnerPoint(ConvexHullFace f, ConvexHullEdge e)
        {
            if (!f.pointA.Equals(e.pointA) && !f.pointA.Equals(e.pointB))
            {
                return(f.pointA);
            }
            if (!f.pointB.Equals(e.pointA) && !f.pointB.Equals(e.pointB))
            {
                return(f.pointB);
            }
            if (!f.pointC.Equals(e.pointA) && !f.pointC.Equals(e.pointB))
            {
                return(f.pointC);
            }

            return(null);
        }
        void IncrementHull(Vector3D pt)
        {
            bool vis = false;

            foreach (ConvexHullFace face in faces)
            {
                if (VolumeSign(face, pt) < 0)
                {
                    face.visible = vis = true;
                }
            }
            if (!vis)
            {
                return;
            }

            for (int i = 0; i < edges.Count; ++i)
            {
                ConvexHullEdge edge  = edges[i];
                ConvexHullFace face1 = edge.adjface1;
                ConvexHullFace face2 = edge.adjface2;

                if (face1 == null || face2 == null)
                {
                    continue;
                }
                else if (face1.visible && face2.visible)
                {
                    edge.remove = true;
                }
                else if (face1.visible || face2.visible)
                {
                    if (face1.visible)
                    {
                        ConvexHullFace faceT = face2;
                        face2 = face1;
                        face1 = faceT;
                    }

                    Vector3D innerPoint = FindInnerPoint(face2, edge);
                    edge.Erase(face2);
                    AddOneFace(edge.pointA, edge.pointB, pt, innerPoint);
                }
            }
        }