Beispiel #1
0
    public SplitType SplitWithPlane(Plane3D plane, out Polygon3D front, out Polygon3D back,
                                    bool veryPrecise)
    {
        Vector3D intersection;

        front = null;
        back  = null;

        double dist    = 0;
        double maxDist = 0;
        double minDist = 0;
        double prevDist;
        double threshold;
        VType  status;
        VType  prevStatus = VType.Either;

        // double scale
        if (veryPrecise)
        {
            threshold = 0.01;
        }
        else
        {
            threshold = 0.25;
        }

        for (int i = 0; i < vertices.Count; i++)
        {
            dist = plane.GetDistanceToPoint(vertices[i]);
            if (i == 0 || dist > maxDist)
            {
                maxDist = dist;
            }
            if (i == 0 || dist < minDist)
            {
                minDist = dist;
            }
            if (dist > +threshold)
            {
                prevStatus = VType.Front;
            }
            else if (dist < -threshold)
            {
                prevStatus = VType.Back;
            }
        }
        if (maxDist < threshold && minDist > -threshold)
        {
            return(SplitType.SP_Coplanar);
        }
        else if (maxDist < threshold)
        {
            return(SplitType.SP_Back);
        }
        else if (minDist > -threshold)
        {
            return(SplitType.SP_Front);
        }
        else
        {
            front = Clone();
            front.vertices.Clear();

            back = Clone();
            back.vertices.Clear();

            int j = vertices.Count - 1;

            for (int i = 0; i < vertices.Count; i++)
            {
                prevDist = dist;
                dist     = plane.GetDistanceToPoint(vertices[i]);

                if (dist > +threshold)
                {
                    status = VType.Front;
                }
                else if (dist < -threshold)
                {
                    status = VType.Back;
                }
                else
                {
                    status = prevStatus;
                }

                if (status != prevStatus)
                {
                    // Crossing.  Either Front-to-Back or Back-To-Front.
                    // Intersection point is naturally on both front and back polys.
                    if ((dist >= -threshold) && (dist < +threshold))
                    {
                        // This point lies on plane.
                        if (prevStatus == VType.Front)
                        {
                            front.vertices.Add(vertices[i]);
                            back.vertices.Add(vertices[i]);
                        }
                        else
                        {
                            back.vertices.Add(vertices[i]);
                            front.vertices.Add(vertices[i]);
                        }
                    }
                    else if ((prevDist >= -threshold) && (prevDist < +threshold))
                    {
                        // Previous point lies on plane.
                        if (status == VType.Front)
                        {
                            front.vertices.Add(vertices[j]);
                            front.vertices.Add(vertices[i]);
                        }
                        else
                        {
                            back.vertices.Add(vertices[j]);
                            back.vertices.Add(vertices[i]);
                        }
                    }
                    else
                    {
                        // Intersection point is in between.
                        intersection = plane.LineIntersection(vertices[j], vertices[i]);

                        if (prevStatus == VType.Front)
                        {
                            front.vertices.Add(intersection);
                            back.vertices.Add(intersection);
                            back.vertices.Add(vertices[i]);
                        }
                        else
                        {
                            back.vertices.Add(intersection);
                            front.vertices.Add(intersection);
                            front.vertices.Add(vertices[i]);
                        }
                    }
                }
                else
                {
                    if (status == VType.Front)
                    {
                        front.vertices.Add(vertices[i]);
                    }
                    else
                    {
                        back.vertices.Add(vertices[i]);
                    }
                }
                j          = i;
                prevStatus = status;
            }

            // Handle possibility of sliver polys due to precision errors.
            if (front.Fix() < 3)
            {
                return(SplitType.SP_Back);
            }
            else if (back.Fix() < 3)
            {
                return(SplitType.SP_Front);
            }
            else
            {
                return(SplitType.SP_Split);
            }
        }
    }