예제 #1
0
        internal double ComputeFacePerimeter(int faceId, bool[] flags)
        {
            var perim = 0.0;
            var face  = Face(faceId);

            for (var i = 0; i < 3; i++)
            {
                if (flags != null)
                {
                    if (!flags[i])
                    {
                        continue;
                    }
                }

                var vi   = Vertex(face[i]);
                var vj   = Vertex(face[(i + 1) % 3]);
                var diff = new double[3];

                MxVectorOps.Sub3(ref diff, vi.Pos, vj.Pos);
                perim += MxVectorOps.Length3(diff);
            }

            return(perim);
        }
예제 #2
0
        internal void ComputeContraction(int vertId1, int vertId2, MxPairContraction conx, double[] newVert)
        {
            conx.VertId1 = vertId1;
            conx.VertId2 = vertId2;

            if (newVert != null)
            {
                MxVectorOps.Sub3(ref conx.DeltaV1, newVert, Vertex(vertId1).Pos);
                MxVectorOps.Sub3(ref conx.DeltaV2, newVert, Vertex(vertId2).Pos);
            }
            else
            {
                conx.DeltaV1 = new[] { 0.0, 0.0, 0.0 };
                conx.DeltaV2 = new[] { 0.0, 0.0, 0.0 };
            }

            conx.DeltaFaces.Clear();
            conx.DeadFaces.Clear();

            MarkNeighborhood(vertId2, 0x0);
            MarkNeighborhood(vertId1, 0x1);
            MarkNeighborhoodDelta(vertId2, 0x1);

            PartitionMarkedNeighbors(vertId1, 0x2, conx.DeltaFaces, conx.DeadFaces);
            conx.DeltaPivot = conx.DeltaFaces.Count;
            PartitionMarkedNeighbors(vertId2, 0x2, conx.DeltaFaces, conx.DeadFaces);
        }
예제 #3
0
        internal double ComputeFaceArea(int faceId)
        {
            var normal = new double[3];

            ComputeFaceNormal(faceId, ref normal, false);
            return(0.5 * MxVectorOps.Length3(normal));
        }
예제 #4
0
 internal void Contract(int vertId1, int vertId2, double[] newVert, MxPairContraction conx)
 {
     ComputeContraction(vertId1, vertId2, conx, null);
     MxVectorOps.Sub3(ref conx.DeltaV1, newVert, Vertex(vertId1).Pos);
     MxVectorOps.Sub3(ref conx.DeltaV2, newVert, Vertex(vertId2).Pos);
     ApplyContraction(conx);
 }
예제 #5
0
        internal void ApplyExpansion(MxPairContraction conx)
        {
            var vertId1 = conx.VertId1;
            var vertId2 = conx.VertId2;

            var newPos1 = new double[3];

            MxVectorOps.Sub3(ref newPos1, Vertex(vertId1).Pos, conx.DeltaV2);
            Vertex(vertId2).Pos = newPos1;

            var newPos2 = Vertex(vertId2).Pos;

            MxVectorOps.SubFrom3(ref newPos2, conx.DeltaV1);
            Vertex(vertId2).Pos = newPos2;

            foreach (var faceId in conx.DeadFaces)
            {
                FaceMarkValid(faceId);

                var face = Face(faceId);
                faceLinks[face[0]].Add(faceId);
                faceLinks[face[1]].Add(faceId);
                faceLinks[face[2]].Add(faceId);
            }

            for (var i = conx.DeltaPivot; i < conx.DeltaFaces.Count; i++)
            {
                var faceId = conx.DeltaFaces[i];
                var face   = Face(faceId);
                face.RemapVertex(vertId1, vertId2);
                faceLinks[vertId2].Add(faceId);
                faceLinks[vertId1].Remove(faceId);
            }

            if (NormalBinding == MxBinding.PerFace)
            {
                var nml = new double[3];
                foreach (var faceId in conx.DeltaFaces)
                {
                    ComputeFaceNormal(faceId, ref nml);
                    Normal(faceId, new MxNormal(nml));
                }

                foreach (var faceId in conx.DeadFaces)
                {
                    ComputeFaceNormal(faceId, ref nml);
                    Normal(faceId, new MxNormal(nml));
                }
            }

            VertexMarkValid(vertId2);
        }
예제 #6
0
        internal void ComputeFaceNormal(int faceId, ref double[] nml, bool willUnitize = true)
        {
            var v0 = Vertex(Face(faceId)[0]);
            var v1 = Vertex(Face(faceId)[1]);
            var v2 = Vertex(Face(faceId)[2]);

            var a = new[] { v1[0] - v0[0], v1[1] - v0[1], v1[2] - v0[2] };
            var b = new[] { v2[0] - v0[0], v2[1] - v0[1], v2[2] - v0[2] };

            MxVectorOps.Cross3(ref nml, a, b);
            if (willUnitize)
            {
                MxVectorOps.Unitize3(ref nml);
            }
        }
예제 #7
0
        internal double ComputeCornerAngle(int faceId, int corner)
        {
            var cornerPrev = (corner == 0) ? 2 : (corner - 1);
            var cornerNext = (corner == 2) ? 0 : (corner + 1);

            var ePrev = new double[3];

            MxVectorOps.Sub3(ref ePrev, Corner(faceId, cornerPrev).Pos, Corner(faceId, corner).Pos);
            MxVectorOps.Unitize3(ref ePrev);

            var eNext = new double[3];

            MxVectorOps.Sub3(ref eNext, Corner(faceId, cornerNext).Pos, Corner(faceId, corner).Pos);
            MxVectorOps.Unitize3(ref eNext);

            return(Math.Acos(MxVectorOps.Dot3(ePrev, eNext)));
        }
예제 #8
0
        internal int CheckLocalValidity(int vertId, double[] vNew)
        {
            var n1      = model.Neighbors(vertId);
            var nFailed = 0;

            foreach (var faceId in n1)
            {
                if (!model.FaceIsValid(faceId))
                {
                    continue;
                }

                var face = model.Face(faceId);
                var k    = face.FindVertex(vertId);
                var x    = face[(k + 1) % 3];
                var y    = face[(k + 2) % 3];
                var vPos = model.Vertex(vertId).Pos;
                var xPos = model.Vertex(x).Pos;
                var yPos = model.Vertex(y).Pos;

                var dYX = new double[3];
                MxVectorOps.Sub3(ref dYX, xPos, yPos);

                var dVX = new double[3];
                MxVectorOps.Sub3(ref dVX, vPos, xPos);

                var dVNew = new double[3];
                MxVectorOps.Sub3(ref dVNew, vNew, xPos);

                var fN = new double[3];
                MxVectorOps.Cross3(ref fN, dYX, dVX);

                var nml = new double[3];
                MxVectorOps.Cross3(ref nml, dYX, dVX);
                MxVectorOps.Unitize3(ref nml);

                if (MxVectorOps.Dot3(dVNew, nml) < LocalValidityThreshold * MxVectorOps.Dot3(dVX, nml))
                {
                    nFailed++;
                }
            }

            return(nFailed);
        }
예제 #9
0
        internal void ComputeVertexNormal(int vertId, ref double[] nml)
        {
            for (var i = 0; i < 3; i++)
            {
                nml[i] = 0.0;
            }
            var star = faceLinks[vertId];

            foreach (var faceId in star)
            {
                var faceNml = new double[3];

                ComputeFaceNormal(faceId, ref faceNml, false);
                MxVectorOps.AddInto3(ref nml, faceNml);
            }

            if (star.Count > 1)
            {
                MxVectorOps.Unitize3(ref nml);
            }
        }
예제 #10
0
        internal void ApplyContraction(MxPairContraction conx)
        {
            var vertId1 = conx.VertId1;
            var vertId2 = conx.VertId2;

            // Move vert1 to new position
            var pos = Vertex(vertId1).Pos;

            MxVectorOps.AddInto3(ref pos, conx.DeltaV1);
            Vertex(vertId1).Pos = pos;

            // Remove dead faces
            foreach (var faceId in conx.DeadFaces)
            {
                UnLinkFace(faceId);
            }

            // Modify changed faces
            for (var i = conx.DeltaPivot; i < conx.DeltaFaces.Count; i++)
            {
                var faceId = conx.DeltaFaces[i];
                var face   = Face(faceId);
                face.RemapVertex(vertId2, vertId1);
                faceLinks[vertId1].Add(faceId);
            }

            if (NormalBinding == MxBinding.PerFace)
            {
                var nml = new double[3];
                foreach (var faceId in conx.DeltaFaces)
                {
                    ComputeFaceNormal(faceId, ref nml);
                    Normal(faceId, new MxNormal(nml));
                }
            }

            // Remove v2
            VertexMarkInvalid(vertId2);
            faceLinks[vertId2].Clear();
        }
예제 #11
0
 internal void ComputeFacePlane(int faceId, ref double[] plane, bool willUnitize = true)
 {
     ComputeFaceNormal(faceId, ref plane, willUnitize);
     plane[3] = -MxVectorOps.Dot3(plane, Corner(faceId, 0).Pos);
 }