Пример #1
0
    private static bool PreconditionLegalCollapse(Halfedge he, Vector3D pos)
    {
        if (he.IsDestroyed())
        {
            return(false);
        }
        if (he.CollapsePrecondition(pos, Halfedge.CollapsePreconditionReason.NormalFlipped) != Halfedge.CollapsePreconditionReason.Ok)
        {
            return(false);
        }
        HMesh           hmesh              = he.hmesh;
        HashSet <int>   uniqueLabels       = new HashSet <int>();
        List <Vector3D> vertexPositions    = new List <Vector3D>();
        int             index              = 0;
        int             indexOfHe          = 0;
        var             prevVertCirculated = he.prev.vert.Circulate();


        // Check that all normals (of same label) are facing the same way
        var      prev        = he.prev;
        int      thisLabel   = he.face.label;
        Vector3D normal      = he.face.GetNormal();
        Vector3D otherNormal = Vector3D.zero;

        foreach (var vHe in prev.vert.Circulate())
        {
            uniqueLabels.Add(vHe.face.label);
            if (vHe.face.label != thisLabel)
            {
                otherNormal = vHe.face.GetNormal();
            }
        }
        if (uniqueLabels.Count > 2)
        {
            // currently not simplified
            return(false);
        }
        // 2. all face normals of the same label must be equal when having the same label
        foreach (var vHe in prev.vert.Circulate())
        {
            var circulateFaceNormal = vHe.face.GetNormal();
            if (vHe.face.label == thisLabel)
            {
                if (!hmesh.AreNormalsEqual(circulateFaceNormal, normal))
                {
                    return(false);
                }
            }
            else
            {
                if (!hmesh.AreNormalsEqual(circulateFaceNormal, otherNormal))
                {
                    return(false);
                }
            }
        }

        // if more labels, make sure that the collapse does not change any boundary between labels
        if (uniqueLabels.Count == 2)
        {
            if (he.opp != null && he.face.label == he.opp.face.label)
            {
                return(false);
            }

            foreach (var otherHe in prevVertCirculated)
            {
                bool compareToSelf = otherHe.id == he.id;
                if (compareToSelf)
                {
                    continue;
                }
                bool isLabelBoundary = otherHe.opp != null && otherHe.opp.face.label != otherHe.face.label;
                if (isLabelBoundary)
                {
                    var  dir1        = he.GetDirection();
                    var  dir2        = otherHe.GetDirection();
                    bool oppositeDir = Vector3D.Dot(dir1, dir2) > 0;
                    // if boundary between labels then they must be parallel in same direction
                    if (Vector3D.IsParallelDist(dir1, dir2, hmesh.zeroMagnitudeTresholdSqr) == false || oppositeDir)
                    {
                        return(false);
                    }
                }
            }
        }

        return(true);
    }