Ejemplo n.º 1
0
        /// <summary>
        /// Apply the transform to the ORIGINAL mesh that was created. Multiple
        /// calls are NOT cumulative.
        /// </summary>
        /// <param name="transform"></param>
        public override void ApplyTransform(Matrix4x4 transform)
        {
            {
                var list = new TriangleWithNormals[_OriginalTriangleVerticies.Count];

                list.Length
                .ParallelChunked((lower, upper) =>
                {
                    for (int i1 = lower; i1 < upper; i1++)
                    {
                        list[i1] = _OriginalTriangleVerticies[i1].ApplyTransform(transform);
                    }
                });

                TrianglesWithNormals = list;
            }
            {
                var list = new Edge3[_OriginalEdgeVertices.Count];

                list.Length
                .ParallelChunked((lower, upper) =>
                {
                    for (int i = lower; i < upper; i++)
                    {
                        list[i] = _OriginalEdgeVertices[i].ApplyTransform(transform);
                    }
                });

                Edges = list;
            }
            UpdateBoundingSphere();
        }
Ejemplo n.º 2
0
        public static void InitRaw2Sym()
        {
            Edge3 e = new Edge3();

            sbyte[] occ   = new sbyte[11880 / 8];
            int     count = 0;

            for (int i = 0; i < 11880; i++)
            {
                if ((occ[i >> 3] & (1 << (i & 7))) == 0) //>
                {
                    e.Set(i * factX[8]);
                    for (int j = 0; j < 8; j++)
                    {
                        int idx = e.Get(4);
                        if (idx == i)
                        {
                            symstate[count] |= (char)(1 << j);
                        }
                        occ[idx >> 3] |= (sbyte)(1 << (idx & 7));
                        raw2sym[idx]   = count << 3 | syminv[j];
                        e.Rot(0);
                        if (j % 2 == 1)
                        {
                            e.Rot(1);
                            e.Rot(2);
                        }
                    }
                    sym2raw[count++] = i;
                }
            }
            //assert count == 1538;
        }
Ejemplo n.º 3
0
        private static IEnumerable <Edge3> GetPolygonEdges(IEnumerable <Vector3> vectors)
        {
            var edges = new List <Edge3>();

            var vectorsEnumerator = vectors.GetEnumerator();

            vectorsEnumerator.MoveNext();
            var firstPoint = vectorsEnumerator.Current;
            var point1     = firstPoint;
            var point2     = firstPoint;

            while (vectorsEnumerator.MoveNext())
            {
                point1 = point2;
                point2 = vectorsEnumerator.Current;

                var edge = new Edge3(point1, point2);
                edges.Add(edge);
            }

            var lastEdge = new Edge3(point2, firstPoint);

            edges.Add(lastEdge);

            return(edges);
        }
        public void TrimLineShouldWork
            (float[] p0
            , float[] p1)
        {
            CreatePartDoc(modelDoc =>
            {
                var v0   = new Vector3(p0[0], p0[1], p0[2]);
                var v1   = new Vector3(p1[0], p1[1], p1[2]);
                var edge = new Edge3(v0, v1);

                var limitedLine = Modeler.CreateTrimmedLine(edge);

                var tol        = 1e-9f;
                var startPoint = limitedLine.StartPoint(0)[0];
                var endPoint   = limitedLine.EndPoint(0)[0];
                v0.X.Should().BeApproximately(startPoint.X, tol);
                v0.Y.Should().BeApproximately(startPoint.Y, tol);
                v0.Z.Should().BeApproximately(startPoint.Z, tol);
                v1.X.Should().BeApproximately(endPoint.X, tol);
                v1.Y.Should().BeApproximately(endPoint.Y, tol);
                v1.Z.Should().BeApproximately(endPoint.Z, tol);

                //######################################################
                var wbv = limitedLine.CreateWireBody();
                var d   = wbv.DisplayUndoable(modelDoc, Color.Blue);
                return(d);
            });
        }
Ejemplo n.º 5
0
        public Model(Mesh source)
        {
            vertices       = new List <Vertex>();
            edges          = new List <Edge3>();
            this.triangles = new List <Triangle3>();

            Vector3[] points = source.vertices;
            for (int i = 0, n = points.Length; i < n; i++)
            {
                Vertex v = new Vertex(points[i], i);
                vertices.Add(v);
            }

            int[] triangles = source.triangles;
            for (int i = 0, n = triangles.Length; i < n; i += 3)
            {
                int    i0 = triangles[i], i1 = triangles[i + 1], i2 = triangles[i + 2];
                Vertex v0 = vertices[i0], v1 = vertices[i1], v2 = vertices[i2];

                Edge3     e0 = GetEdge(edges, v0, v1);
                Edge3     e1 = GetEdge(edges, v1, v2);
                Edge3     e2 = GetEdge(edges, v2, v0);
                Triangle3 f  = new Triangle3(v0, v1, v2, e0, e1, e2);

                this.triangles.Add(f);
                v0.AddTriangle(f); v1.AddTriangle(f); v2.AddTriangle(f);
                e0.AddTriangle(f); e1.AddTriangle(f); e2.AddTriangle(f);
            }
        }
        public static Gen <Triangle> Triangle(this Gen <double> floats)
        {
            return(floats
                   .Vector3()
                   .Triangle()
                   .Where
                       (v =>
            {
                var e0 = new Edge3(v.A, v.B);
                var e1 = new Edge3(v.A, v.C);
                var e2 = new Edge3(v.B, v.C);

                var minDist = 1e-2;
                var maxDist = 1;

                if (List(e0, e1, e2).Any(e => e.Length < minDist))
                {
                    return false;
                }

                if (List(e0, e1, e2).XPaired().Any(t => t.Map((a, b) => a.AngleBetween(b) < 5d / 180 * Math.PI)))
                {
                    return false;
                }

                return true;
            }));
        }
Ejemplo n.º 7
0
 public void Set(Edge3 e)
 {
     for (int i = 0; i < 12; i++)
     {
         edge[i]  = e.edge[i];
         edgeo[i] = e.edgeo[i];
     }
     isStd = e.isStd;
 }
        public void NonIntersectingLinesShouldReturnNone_v2(Vector3 position, Vector3 forward, Vector3 up)
        {
            var line  = new Edge3(new Vector3(-1, -2, -3) * 0.001, new Vector3(-1, -2, -3));
            var plane = new PointDirection3(Vector3.Zero, Vector3.UnitX);

            var transform = Matrix4x4.CreateWorld(position, forward, up);

            var tline  = line.ApplyTransform(transform);
            var tplane = plane.ApplyTransform(transform);

            tline.IntersectPlane(tplane).IsSome.Should().BeFalse();
        }
Ejemplo n.º 9
0
        private static Edge3[] TransformEdges(MeshData data, Matrix4x4 transform)
        {
            var list = new Edge3[data.Edges.Count];

            list.Length
            .ParallelChunked((lower, upper) =>
            {
                for (int i = lower; i < upper; i++)
                {
                    list[i] = data.Edges[i].ApplyTransform(transform);
                }
            });
            return(list);
        }
        public void IntersectingLineWithPlaneShouldReturnIntersectionPoint(Vector3 position, Vector3 forward, Vector3 up)
        {
            var line  = new Edge3(new Vector3(1, 2, 3), new Vector3(-1, -2, -3));
            var plane = new PointDirection3(Vector3.Zero, Vector3.UnitX);

            var transform = Matrix4x4.CreateWorld(position, forward, up);

            var tline  = line.ApplyTransform(transform);
            var tplane = plane.ApplyTransform(transform);

            var intersectPlane = tline.IntersectPlane(tplane).__Value__();
            var intersectPlaneExpectedValue = Vector3.Transform(Vector3.Zero, transform);

            intersectPlane.Should().BeApproximately(intersectPlaneExpectedValue, 1e-6);
        }
        public void ShouldGetTheShortestLine()
        {
            var edge0 = new Edge3(vector(0, -1, -1), vector(0, 1, -1));
            var edge1 = new Edge3(vector(-1, 0, 1), vector(1, 0, 1));

            var connect = edge0.ShortestEdgeJoining(edge1);

            connect.A.X.Should().BeApproximately(0, 1e-6f);
            connect.A.Y.Should().BeApproximately(0, 1e-6f);
            connect.A.Z.Should().BeApproximately(-1, 1e-6f);

            connect.B.X.Should().BeApproximately(0, 1e-6f);
            connect.B.Y.Should().BeApproximately(0, 1e-6f);
            connect.B.Z.Should().BeApproximately(1, 1e-6f);
        }
        /// <summary>
        /// Create a line from p0 to p1.
        /// </summary>
        /// <param name="modeler"></param>
        /// <param name="edge"></param>
        /// <returns></returns>
        public static ICurve CreateTrimmedLine(this IModeler modeler, Edge3 edge)
        {
            Debug.Assert(edge.Delta.Length() > double.Epsilon);
            var startPoint = new[] { (double)edge.A.X, (double)edge.A.Y, (double)edge.A.Z };
            var dir        = edge.Delta.Unit();
            var direction  = new[] { (double)dir.X, (double)dir.Y, (double)dir.Z };
            var line       = (ICurve)modeler.CreateLine(startPoint, direction);

            Debug.Assert(line != null, "line != null");
            var pp0 = line.GetClosestPointOn(edge.A.X, edge.A.Y, edge.A.Z).CastArray <double>();
            var pp1 = line.GetClosestPointOn(edge.B.X, edge.B.Y, edge.B.Z).CastArray <double>();
            //line = line.CreateTrimmedCurve2(pp0[0], pp0[1], pp0[2], pp1[0], pp1[1], pp1[2]);
            var trimmedLine = line.CreateTrimmedCurve(pp0[3], pp1[3]);

            Debug.Assert(trimmedLine != null, "line != null");
            return(trimmedLine);
        }
Ejemplo n.º 13
0
        Edge3 GetEdge(List <Edge3> edges, Vertex v0, Vertex v1)
        {
            Edge3 match = v0.edges.Find(e => {
                return(e.Has(v1));
            });

            if (match != null)
            {
                return(match);
            }

            Edge3 ne = new Edge3(v0, v1);

            v0.AddEdge(ne);
            v1.AddEdge(ne);
            edges.Add(ne);
            return(ne);
        }
Ejemplo n.º 14
0
        public static int Getprun(int edge)
        {
            Edge3 e     = new Edge3();
            int   depth = 0;
            int   depm3 = GetPruning(eprun, edge);

            if (depm3 == 0x3)
            {
                return(MAX_DEPTH);
            }
            while (edge != 0)
            {
                if (depm3 == 0)
                {
                    depm3 = 2;
                }
                else
                {
                    depm3--;
                }

                int symcord1 = edge / N_RAW;
                int cord1    = sym2raw[symcord1];
                int cord2    = edge % N_RAW;
                e.Set(cord1 * N_RAW + cord2);

                for (int m = 0; m < 17; m++)
                {
                    int cord1x    = Getmvrot(e.edge, m << 3, 4);
                    int symcord1x = raw2sym[cord1x];
                    int symx      = symcord1x & 0x7;
                    symcord1x >>= 3;
                    int cord2x = Getmvrot(e.edge, m << 3 | symx, 10) % N_RAW;
                    int idx    = symcord1x * N_RAW + cord2x;
                    if (GetPruning(eprun, idx) == depm3)
                    {
                        depth++;
                        edge = idx;
                        break;
                    }
                }
            }
            return(depth);
        }
Ejemplo n.º 15
0
        Edge3 GetEdge(Vertex v0, Vertex v1)
        {
            Edge3 match = v0.edges.Find(e =>
            {
                return(e.a == v1 || e.b == v1);
            });

            if (match != null)
            {
                return(match);
            }

            Edge3 ne = new Edge3(v0, v1);

            edges.Add(ne);
            v0.AddEdge(ne);
            v1.AddEdge(ne);
            return(ne);
        }
Ejemplo n.º 16
0
        public void DrawPolygonFilled(ITransformation transformation, IEnumerable <Vector3> vectors, ushort?colorOverride = null, byte?pixelOverride = null)
        {
            var transformedVectors = vectors
                                     .Select(transformation.Transform)
                                     .ToList();
            var yMax  = (int)System.Math.Ceiling(transformedVectors.Max(vector => vector.Y));
            var yMin  = (int)System.Math.Floor(transformedVectors.Min(vector => vector.Y));
            var edges = GetPolygonEdges(transformedVectors);

            for (var scanlineY = yMin; scanlineY <= yMax; scanlineY++)
            {
                var yEdgeIntersections = edges
                                         .Where(edge => edge.IsYValueOnEdge(scanlineY))
                                         .Select(edge => edge.GetPointFromY(scanlineY))
                                         .ToList();
                var xSortedIntersections = yEdgeIntersections.OrderBy(vector => vector.X).ToList();
                var index1 = 0;
                var index2 = 1;
                while (index2 < xSortedIntersections.Count)
                {
                    var point1 = xSortedIntersections[index1];
                    var point2 = xSortedIntersections[index2];
                    var line   = new Edge3(point1, point2);
                    var startX = point1.X;
                    var endX   = point2.X;
                    for (var x = startX; x <= endX; x++)
                    {
                        // Z ALGO IS BUGGY
                        var point = new Vector3(x, scanlineY, line.GetPointFromX(x).Z);
                        //var point = new Vector2(x, scanlineY);
                        DrawPoint(Transformation.None, point, colorOverride, pixelOverride);
                    }

                    index1 += 2;
                    index2 += 2;
                }
            }
        }
Ejemplo n.º 17
0
        public static void InitMvrot()
        {
            Edge3 e = new Edge3();

            for (int m = 0; m < 20; m++)
            {
                for (int r = 0; r < 8; r++)
                {
                    e.Set(0);
                    e.Move(m);
                    e.Rotate(r);
                    for (int i = 0; i < 12; i++)
                    {
                        mvrot[m << 3 | r, i] = e.edge[i];
                    }
                    e.Std();
                    for (int i = 0; i < 12; i++)
                    {
                        mvroto[m << 3 | r, i] = e.temp[i];
                    }
                }
            }
        }
        public void LinspaceForVector3ShouldWork()
        {
            CreatePartDoc(modelDoc =>
            {
                var v0 = new Vector3(0, 0, 0);
                var v1 = new Vector3(1, 0, 0);

                var intV = Sequences.LinSpace(v0, v1, 5).ToList();

                var interpolated = intV
                                   .Buffer(2, 1)
                                   .Where(p => p.Count == 2)
                                   .Select(ps =>
                {
                    var edge        = new Edge3(ps[0], ps[1]);
                    var limitedLine = Modeler.CreateTrimmedLine(edge);
                    var wB          = limitedLine.CreateWireBody();
                    return(wB.DisplayUndoable(modelDoc, Color.Blue));
                })
                                   .ToCompositeDisposable();

                return(new CompositeDisposable(interpolated));
            });
        }
Ejemplo n.º 19
0
        public Vertex GetEdgePoint(Edge3 e)
        {
            if (e.ept != null)
            {
                return(e.ept);
            }

            if (e.faces.Count != 2)
            {
                // boundary case for edge
                Vector3 m = (e.a.p + e.b.p) * 0.5f;
                e.ept = new Vertex(m, e.a.index);
            }
            else
            {
                const float alpha = 3f / 8f;
                const float beta  = 1f / 8f;
                var         left  = e.faces[0].GetOtherVertex(e);
                var         right = e.faces[1].GetOtherVertex(e);
                e.ept = new Vertex((e.a.p + e.b.p) * alpha + (left.p + right.p) * beta, e.a.index);
            }

            return(e.ept);
        }
Ejemplo n.º 20
0
        public void AddTriangle(Vertex v0, Vertex v1, Vertex v2)
        {
            if (!vertices.Contains(v0))
            {
                vertices.Add(v0);
            }
            if (!vertices.Contains(v1))
            {
                vertices.Add(v1);
            }
            if (!vertices.Contains(v2))
            {
                vertices.Add(v2);
            }

            Edge3     e0 = GetEdge(v0, v1);
            Edge3     e1 = GetEdge(v1, v2);
            Edge3     e2 = GetEdge(v2, v0);
            Triangle3 f  = new Triangle3(v0, v1, v2, e0, e1, e2);

            this.triangles.Add(f);
            v0.AddTriangle(f); v1.AddTriangle(f); v2.AddTriangle(f);
            e0.AddTriangle(f); e1.AddTriangle(f); e2.AddTriangle(f);
        }
Ejemplo n.º 21
0
        private static IEnumerable<Edge3> GetPolygonEdges(IEnumerable<Vector3> vectors)
        {
            var edges = new List<Edge3>();

            var vectorsEnumerator = vectors.GetEnumerator();

            vectorsEnumerator.MoveNext();
            var firstPoint = vectorsEnumerator.Current;
            var point1 = firstPoint;
            var point2 = firstPoint;

            while (vectorsEnumerator.MoveNext())
            {
                point1 = point2;
                point2 = vectorsEnumerator.Current;

                var edge = new Edge3(point1, point2);
                edges.Add(edge);
            }

            var lastEdge = new Edge3(point2, firstPoint);
            edges.Add(lastEdge);

            return edges;
        }
Ejemplo n.º 22
0
        public void DrawPolygonFilled(ITransformation transformation, IEnumerable<Vector3> vectors, ushort? colorOverride = null, byte? pixelOverride = null)
        {
            var transformedVectors = vectors
                .Select(transformation.Transform)
                .ToList();
            var yMax = (int) System.Math.Ceiling(transformedVectors.Max(vector => vector.Y));
            var yMin = (int) System.Math.Floor(transformedVectors.Min(vector => vector.Y));
            var edges = GetPolygonEdges(transformedVectors);
            for (var scanlineY = yMin; scanlineY <= yMax; scanlineY++)
            {
                var yEdgeIntersections = edges
                    .Where(edge => edge.IsYValueOnEdge(scanlineY))
                    .Select(edge => edge.GetPointFromY(scanlineY))
                    .ToList();
                var xSortedIntersections = yEdgeIntersections.OrderBy(vector => vector.X).ToList();
                var index1 = 0;
                var index2 = 1;
                while (index2 < xSortedIntersections.Count)
                {
                    var point1 = xSortedIntersections[index1];
                    var point2 = xSortedIntersections[index2];
                    var line = new Edge3(point1, point2);
                    var startX = point1.X;
                    var endX = point2.X;
                    for (var x = startX; x <= endX; x++)
                    {
                        // Z ALGO IS BUGGY
                        var point = new Vector3(x, scanlineY, line.GetPointFromX(x).Z);
                        //var point = new Vector2(x, scanlineY);
                        DrawPoint(Transformation.None, point, colorOverride, pixelOverride);
                    }

                    index1 += 2;
                    index2 += 2;
                }
            }
        }
 public EdgeDistance(Edge3 edge, double distance)
 {
     Edge = edge;
     Distance = distance;
 }
 public EdgeDistance(Edge3 edge, double distance)
 {
     this.Edge     = edge;
     this.Distance = distance;
 }
Ejemplo n.º 25
0
 public override double GetInitializationStatus() => Edge3.InitStatus();
Ejemplo n.º 26
0
        public static void CreatePrun()
        {
            Edge3 e = new Edge3();
            Edge3 f = new Edge3();
            Edge3 g = new Edge3();

            for (int i = 0; i < eprun.Length; i++)
            {
                eprun[i] = -1;
            }
            int depth = 0;

            done = 1;
            SetPruning(eprun, 0, 0);

            while (done != N_EPRUN)
            {
                bool inv    = depth > 9;
                int  depm3  = depth % 3;
                int  dep1m3 = (depth + 1) % 3;
                int  find   = inv ? 0x3 : depm3;
                int  chk    = inv ? depm3 : 0x3;

                if (depth >= MAX_DEPTH - 1)
                {
                    break;
                }

                for (int i_ = 0; i_ < N_EPRUN; i_ += 16)
                {
                    int val = eprun[i_ >> 4];
                    if (!inv && val == -1)
                    {
                        continue;
                    }
                    for (int i = i_, end = i_ + 16; i < end; i++, val >>= 2)
                    {
                        if ((val & 0x3) != find)
                        {
                            continue;
                        }
                        int symcord1 = i / N_RAW;
                        int cord1    = sym2raw[symcord1];
                        int cord2    = i % N_RAW;
                        e.Set(cord1 * N_RAW + cord2);

                        for (int m = 0; m < 17; m++)
                        {
                            int cord1x    = Getmvrot(e.edge, m << 3, 4);
                            int symcord1x = raw2sym[cord1x];
                            int symx      = symcord1x & 0x7;
                            symcord1x >>= 3;
                            int cord2x = Getmvrot(e.edge, m << 3 | symx, 10) % N_RAW;
                            int idx    = symcord1x * N_RAW + cord2x;
                            if (GetPruning(eprun, idx) != chk)
                            {
                                continue;
                            }
                            SetPruning(eprun, inv ? i : idx, dep1m3);
                            done++;
                            // if ((done & 0x3ffff) == 0) {
                            //  System.out.print(string.format("%d\r", done));
                            // }
                            if (inv)
                            {
                                break;
                            }
                            char symState = symstate[symcord1x];
                            if (symState == 1)
                            {
                                continue;
                            }
                            f.Set(e);
                            f.Move(m);
                            f.Rotate(symx);
                            for (int j = 1; (symState >>= 1) != 0; j++)
                            {
                                if ((symState & 1) != 1)
                                {
                                    continue;
                                }
                                g.Set(f);
                                g.Rotate(j);
                                int idxx = symcord1x * N_RAW + g.Get(10) % N_RAW;
                                if (GetPruning(eprun, idxx) == chk)
                                {
                                    SetPruning(eprun, idxx, dep1m3);
                                    done++;
                                    // if ((done & 0x3ffff) == 0) {
                                    //  System.out.print(string.format("%d\r", done));
                                    // }
                                }
                            }
                        }
                    }
                }
                depth++;
                //System.out.println(depth + "\t" + done);
            }
        }
    private IEnumerator QEMLoop(HalfEdgeData3 halfEdgeMeshData, Heap <QEM_Edge> sorted_QEM_edges, Dictionary <MyVector3, Matrix4x4> qMatrices, Dictionary <HalfEdge3, QEM_Edge> halfEdge_QEM_Lookup, int maxEdgesToContract, float maxError, bool normalizeTriangles = false)
    {
        //PAUSE FOR VISUALIZATION
        //Display what we have so far
        controller.DisplayMeshMain(halfEdgeMeshData.faces);

        controller.displayStuffUI.text = "Triangles: " + halfEdgeMeshData.faces.Count.ToString();

        yield return(new WaitForSeconds(5f));


        //
        // Start contracting edges
        //

        //For each edge we want to remove
        for (int i = 0; i < maxEdgesToContract; i++)
        {
            //Check that we can simplify the mesh
            //The smallest mesh we can have is a tetrahedron with 4 faces, itherwise we get a flat triangle
            if (halfEdgeMeshData.faces.Count <= 4)
            {
                Debug.Log($"Cant contract more than {i} edges");

                break;
            }


            //
            // Remove the pair (v1,v2) of the least cost and contract the pair
            //

            //timer.Start();

            QEM_Edge smallestErrorEdge = sorted_QEM_edges.RemoveFirst();

            //This means an edge in this face has already been contracted
            //We are never removing edges from the heap after contracting and edges,
            //so we do it this way for now, which is maybe better?
            if (smallestErrorEdge.halfEdge.face == null)
            {
                //This edge wasn't contracted so don't add it to iteration
                i -= 1;

                continue;
            }

            if (smallestErrorEdge.qem > maxError)
            {
                Debug.Log($"Cant contract more than {i} edges because reached max error");

                break;
            }

            //timer.Stop();


            //timer.Start();

            //Get the half-edge we want to contract
            HalfEdge3 edgeToContract = smallestErrorEdge.halfEdge;

            //Need to save the endpoints so we can remove the old Q matrices from the pos-matrix lookup table
            Edge3 contractedEdgeEndpoints = new Edge3(edgeToContract.prevEdge.v.position, edgeToContract.v.position);

            //Contract edge
            HashSet <HalfEdge3> edgesPointingToNewVertex = halfEdgeMeshData.ContractTriangleHalfEdge(edgeToContract, smallestErrorEdge.mergePosition);

            //timer.Stop();



            //
            // Remove all QEM_edges that belonged to the faces we contracted
            //

            //This is not needed if we check if an edge in the triangle has already been contracted

            /*
             * //timer.Start();
             *
             * //This edge doesnt exist anymore, so remove it from the lookup
             * halfEdge_QEM_Lookup.Remove(edgeToContract);
             *
             * //Remove the two edges that were a part of the triangle of the edge we contracted
             * RemoveHalfEdgeFromQEMEdges(edgeToContract.nextEdge, QEM_edges, halfEdge_QEM_Lookup);
             * RemoveHalfEdgeFromQEMEdges(edgeToContract.nextEdge.nextEdge, QEM_edges, halfEdge_QEM_Lookup);
             *
             * //Remove the three edges belonging to the triangle on the opposite side of the edge we contracted
             * //If there was an opposite side...
             * if (edgeToContract.oppositeEdge != null)
             * {
             *  HalfEdge3 oppositeEdge = edgeToContract.oppositeEdge;
             *
             *  RemoveHalfEdgeFromQEMEdges(oppositeEdge, QEM_edges, halfEdge_QEM_Lookup);
             *  RemoveHalfEdgeFromQEMEdges(oppositeEdge.nextEdge, QEM_edges, halfEdge_QEM_Lookup);
             *  RemoveHalfEdgeFromQEMEdges(oppositeEdge.nextEdge.nextEdge, QEM_edges, halfEdge_QEM_Lookup);
             * }
             * //timer.Stop();
             */

            //Remove the edges start and end vertices from the pos-matrix lookup table
            qMatrices.Remove(contractedEdgeEndpoints.p1);
            qMatrices.Remove(contractedEdgeEndpoints.p2);
            //timer.Stop();



            //
            // Update all QEM_edges that is now connected with the new contracted vertex because their errors have changed
            //

            //The contracted position has a new Q matrix
            Matrix4x4 QNew = MeshSimplification_QEM.CalculateQMatrix(edgesPointingToNewVertex, normalizeTriangles);

            //Add the Q matrix to the pos-matrix lookup table
            qMatrices.Add(smallestErrorEdge.mergePosition, QNew);


            //Update the error of the QEM_edges of the edges that pointed to and from one of the two old Q matrices
            //Those edges are the same edges that points to the new vertex and goes from the new vertex
            //timer.Start();
            foreach (HalfEdge3 edgeToV in edgesPointingToNewVertex)
            {
                //The edge going from the new vertex is the next edge of the edge going to the vertex
                HalfEdge3 edgeFromV = edgeToV.nextEdge;


                //To
                QEM_Edge QEM_edgeToV = halfEdge_QEM_Lookup[edgeToV];

                Edge3 edgeToV_endPoints = QEM_edgeToV.GetEdgeEndPoints();

                Matrix4x4 Q1_edgeToV = qMatrices[edgeToV_endPoints.p1];
                Matrix4x4 Q2_edgeToV = QNew;

                QEM_edgeToV.UpdateEdge(edgeToV, Q1_edgeToV, Q2_edgeToV);

                sorted_QEM_edges.UpdateItem(QEM_edgeToV);


                //From
                QEM_Edge QEM_edgeFromV = halfEdge_QEM_Lookup[edgeFromV];

                Edge3 edgeFromV_endPoints = QEM_edgeFromV.GetEdgeEndPoints();

                Matrix4x4 Q1_edgeFromV = QNew;
                Matrix4x4 Q2_edgeFromV = qMatrices[edgeFromV_endPoints.p2];

                QEM_edgeFromV.UpdateEdge(edgeFromV, Q1_edgeFromV, Q2_edgeFromV);

                sorted_QEM_edges.UpdateItem(QEM_edgeFromV);
            }
            //timer.Stop();



            //PAUSE FOR VISUALIZATION
            //Display what we have so far
            controller.DisplayMeshMain(halfEdgeMeshData.faces);

            controller.displayStuffUI.text = "Triangles: " + halfEdgeMeshData.faces.Count.ToString();

            yield return(new WaitForSeconds(0.02f));
        }
    }
 public static Matrix4x4 CreateFromEdgeAngleOrigin(Edge3 p, float angle)
 {
     return(CreateFromAxisAngleOrigin(new PointDirection3(p.A, p.Delta), angle));
 }
 public EdgeDistance(Edge3 edge, double distance)
 {
     Edge     = edge;
     Distance = distance;
 }
 public override double GetInitializationStatus()
 {
     return(Edge3.InitStatus());
 }