Example #1
0
        private TriangleNet.Mesh createMesh()
        {
            TriangleNet.Geometry.Polygon          polygon = createPolygon();
            TriangleNet.Meshing.ConstraintOptions options = new TriangleNet.Meshing.ConstraintOptions()
            {
                ConformingDelaunay = true
            };
            TriangleNet.Meshing.GenericMesher mesher = new TriangleNet.Meshing.GenericMesher();

            TriangleNet.Mesh mesh = (TriangleNet.Mesh)mesher.Triangulate(polygon, options);

            TriangleNet.Smoothing.SimpleSmoother smoother = new TriangleNet.Smoothing.SimpleSmoother();
            smoother.Smooth(mesh, smoothingIterations);

            return(mesh);
        }
Example #2
0
        public void Build(QuadTreeNode Mask, double compensateangle = 0.0)
        {
            //  M = new Mesh();

            Lines.Clear();
            Mask.NodeWalker(GetAllCorners, true, true);
            var GM = new TriangleNet.Meshing.GenericMesher();

            if (IG.Count < 3)
            {
                M = null;
                return;
            }
            else
            {
                M = GM.Triangulate(IG);
            }
            //M.Triangulate(IG);
            //M.Smooth();
            //M.Refine();
            //M.Refine();

            double S = Math.Sin(compensateangle);
            double C = Math.Cos(compensateangle);

            foreach (var a in M.Triangles)
            {
                var V1 = M.Vertices.ElementAt(a.GetVertexID(0));
                var V2 = M.Vertices.ElementAt(a.GetVertexID(1));
                var V3 = M.Vertices.ElementAt(a.GetVertexID(2));

                QuadTreeNode N = Mask.GetNode((V1.X + V2.X + V3.X) / 3.0, (V1.Y + V2.Y + V3.Y) / 3.0);

                if (N != null && N.Items.Count == 0)
                {
                    var D1  = MathHelpers.Difference(new PointF((float)V1.X, (float)V1.Y), new PointF((float)V2.X, (float)V2.Y));
                    var D2  = MathHelpers.Difference(new PointF((float)V2.X, (float)V2.Y), new PointF((float)V3.X, (float)V3.Y));
                    var D3  = MathHelpers.Difference(new PointF((float)V3.X, (float)V3.Y), new PointF((float)V1.X, (float)V1.Y));
                    var D1L = MathHelpers.Length(D1);
                    var D2L = MathHelpers.Length(D2);
                    var D3L = MathHelpers.Length(D3);
                    if (D1L < D2L && D1L < D3L)
                    {
                        //   Lines.Add(new Tuple<PointF, PointF>(new PointF((float)V2.X, (float)V2.Y), new PointF((float)V3.X, (float)V3.Y)));
                        //   Lines.Add(new Tuple<PointF, PointF>(new PointF((float)V3.X, (float)V3.Y), new PointF((float)V1.X, (float)V1.Y)));

                        Lines.Add(new Tuple <PointF, PointF>(new PointF((float)V1.X, (float)V1.Y), new PointF((float)V2.X, (float)V2.Y)));
                    }

                    if (D2L < D1L && D2L < D3L)
                    {
                        Lines.Add(new Tuple <PointF, PointF>(new PointF((float)V2.X, (float)V2.Y), new PointF((float)V3.X, (float)V3.Y)));
                        //                        Lines.Add(new Tuple<PointF, PointF>(new PointF((float)V1.X, (float)V1.Y), new PointF((float)V2.X, (float)V2.Y)));
                        //                      Lines.Add(new Tuple<PointF, PointF>(new PointF((float)V3.X, (float)V3.Y), new PointF((float)V1.X, (float)V1.Y)));
                    }

                    if (D3L < D2L && D3L < D1L)
                    {
                        Lines.Add(new Tuple <PointF, PointF>(new PointF((float)V3.X, (float)V3.Y), new PointF((float)V1.X, (float)V1.Y)));
                        //                    Lines.Add(new Tuple<PointF, PointF>(new PointF((float)V1.X, (float)V1.Y), new PointF((float)V2.X, (float)V2.Y)));
                        //                  Lines.Add(new Tuple<PointF, PointF>(new PointF((float)V2.X, (float)V2.Y), new PointF((float)V3.X, (float)V3.Y)));
                    }
                }
            }
            Matrix mM = new Matrix();

            mM.Rotate((float)compensateangle);
            List <Tuple <PointF, PointF> > l2 = new List <Tuple <PointF, PointF> >();

            foreach (var a in Lines)
            {
                PointF[] A = new PointF[2] {
                    a.Item1, a.Item2
                };
                mM.TransformPoints(A);

                l2.Add(new Tuple <PointF, PointF>(A[0], A[1]));
            }
            Lines = l2;
        }
Example #3
0
        // TODO Generalize Slice to be more than just a plane (Maybe a parametric surface or NURB?)
        // Implement with Binary Space Partitioning
        private Triangle[] PatchSlice(Plane Slice)    // this function triangulates the slicing plane so that the split parts are watertight
        {
            var PlanePts   = new HashSet <double3>(); // these are the points in the plane
            var PlaneTris  = new List <Triangle>();   // these will be holes or required triangles depending on the unit normal
            var PlaneLines = new HashSet <Line>();    // these are required edges in the surface triangulation

            for (int i = 0; i < Triangles.Length; i++)
            {
                var Tri  = Triangles[i];
                var LocA = Slice.AboveOrBelow(Tri.A);
                var LocB = Slice.AboveOrBelow(Tri.B);
                var LocC = Slice.AboveOrBelow(Tri.C);

                Tri.A = ToDouble3(ToFloat3(Tri.A));
                Tri.B = ToDouble3(ToFloat3(Tri.B));
                Tri.C = ToDouble3(ToFloat3(Tri.C));

                if (LocA == Location.On)
                {
                    PlanePts.Add(Tri.A);
                }


                if (LocB == Location.On)
                {
                    PlanePts.Add(Tri.B);
                }

                if (LocC == Location.On)
                {
                    PlanePts.Add(Tri.C);
                }

                if (LocA == Location.On && LocB == Location.On && LocC == Location.On)
                {
                    PlaneTris.Add(Tri);
                }
                else if (LocA == Location.On && LocB == Location.On)
                {
                    PlaneLines.Add(new Line(Tri.A, Tri.B));
                }
                else if (LocB == Location.On && LocC == Location.On)
                {
                    PlaneLines.Add(new Line(Tri.B, Tri.C));
                }
                else if (LocA == Location.On && LocB == Location.On)
                {
                    PlaneLines.Add(new Line(Tri.A, Tri.C));
                }
            }

            var Pts3D = PlanePts.ToArray();

            var Lines = PlaneLines.ToArray();

            var x_new = Pts3D[1] - Pts3D[0];

            x_new.Normalize(); // define the new x-axis as the vector between the  first two
            // coplanar points
            var z_new = Slice.UnitNormal;

            var Poly = new Polygon();

            double ZOffset = Slice.Transform(Pts3D[0], x_new).z;

            for (int i = 0; i < Pts3D.Length; i++)
            {
                var Pt_new     = Slice.Transform(Pts3D[i], x_new);
                var Vertex_new = new Vertex(Pt_new.x, Pt_new.y);
                Poly.Add(Vertex_new);
            }

            var EdgeSet = new HashSet <Edge>();

            for (int i = 0; i < Lines.Length; i++)
            {
                var PtA = Lines[i].A;
                var PtB = Lines[i].B;
                PtA = Slice.Transform(PtA, x_new);
                PtB = Slice.Transform(PtB, x_new);
                var P1 = new Vertex(PtA.x, PtA.y);
                var P2 = new Vertex(PtB.x, PtB.y);
                int I1 = Poly.Points.IndexOf(P1);
                int I2 = Poly.Points.IndexOf(P2);
                if (I1 == -1 || I2 == -1)
                {
                    Console.WriteLine("Bad Segment Found!");
                }

                var Edge = new Edge(Math.Min(I1, I2), Math.Max(I1, I2));
                EdgeSet.Add(Edge);
            }
            var PolyEdges = EdgeSet.ToArray();

            foreach (var item in PolyEdges)
            {
                Poly.Add(item);
            }
            //Poly = RemoveRedundantSegments(Poly.Segments, Poly.Points);

            bool Status = CheckWaterTightness(Poly.Segments, Poly.Points);

            TriangleNet.IO.TriangleWriter.WritePoly(Poly, "PolyTest.poly");

            if (Status == false)
            {
                Console.WriteLine("Warning, Inconsistent cross section detected!");
                //throw new Exception("STL File is not watertight!");
            }

            var qualityOptions = new TriangleNet.Meshing.QualityOptions();

            qualityOptions.MinimumAngle = 20;
            qualityOptions.MaximumAngle = 140;

            var myMesher = new TriangleNet.Meshing.GenericMesher();
            var myMesh   = (TriangleNet.Mesh)myMesher.Triangulate(Poly, qualityOptions); // Poly needs to be broken up into self contained singular regions

            // TODO:
            // How does this fair when the cross section is multiple separate regions adhering to Jordan Curve Theorem
            // Each region/ closed curve is a linked list.


            // FIXME: Write algorithm to break up seperate regions along the plane

            // Also account for holes being punched in the mesh (One side gets a hole, the mirror doesnt) when the cutting plane is along an interior surface

            // TODO Add back in unit normals to patch

            var Ans = new Triangle[myMesh.Triangles.Count];

            if (Ans.Length == 0)
            {
                throw new Exception("Patch Meshing Failure Detected!");
            }
            TriangleNet.IO.TriangleWriter.Write(myMesh, "MeshTest.ele");
            for (int i = 0; i < Ans.Length; i++)
            {
                var myTri = myMesh.Triangles.ElementAt(i);
                var P0    = myMesh.Vertices.ElementAt(myTri.P0);
                var P1    = myMesh.Vertices.ElementAt(myTri.P1);
                var P2    = myMesh.Vertices.ElementAt(myTri.P2);
                var PtA   = new double3(P0.X, P0.Y, ZOffset);
                var PtB   = new double3(P1.X, P1.Y, ZOffset);
                var PtC   = new double3(P2.X, P2.Y, ZOffset);
                PtA    = Slice.UnTransform(PtA, x_new); // map back to 3d
                PtB    = Slice.UnTransform(PtB, x_new);
                PtC    = Slice.UnTransform(PtC, x_new);
                Ans[i] = new Triangle(PtA, PtB, PtC);
            }
            return(Ans);
        }