Пример #1
0
        static void generate_stacked_polygon(SingleMaterialFFFCompiler compiler,
                                             SingleMaterialFFFSettings settings)
        {
            int NLayers = 10;

            for (int layer_i = 0; layer_i < NLayers; ++layer_i)
            {
                // create data structures for organizing this layer
                ToolpathSetBuilder    layer_builder = new ToolpathSetBuilder();
                SequentialScheduler2d scheduler     = new SequentialScheduler2d(layer_builder, settings);
                if (layer_i == 0)
                {
                    scheduler.SpeedHint = SchedulerSpeedHint.Careful;
                }

                // initialize layer
                layer_builder.Initialize(compiler.NozzlePosition);

                // layer-up
                layer_builder.AppendZChange(settings.LayerHeightMM, settings.ZTravelSpeed);

                // schedule a circle
                FillPolygon2d circle_poly = new FillPolygon2d(Polygon2d.MakeCircle(25.0f, 64));
                circle_poly.TypeFlags = FillTypeFlags.OuterPerimeter;
                scheduler.AppendPolygon2d(circle_poly);

                // pass paths to compiler
                compiler.AppendPaths(layer_builder.Paths, settings);
            }
        }
Пример #2
0
 void update_polygon()
 {
     if (preview != null)
     {
         preview.Polygon = Polygon2d.MakeCircle(Radius, nSlices);
     }
 }
Пример #3
0
        /// <summary>
        /// Fallback to deal with very tiny polygons that disappear when insetting.
        /// This happens at Z-minima-tips, which can be a problem because it may leave
        /// gaps between layers. For tips we draw a tiny circle.
        /// For elongated shapes we...?? currently do something dumb.
        /// Probably should use robust thinning!
        /// </summary>
        public virtual void HandleTinyPolygon()
        {
            //(InsetFromInputPolygon) ?
            //ClipperUtil.ComputeOffsetPolygon(Polygon, -ToolWidth / 2, true) :
            AxisAlignedBox2d bounds = Polygon.Bounds;

            if (bounds.MaxDim < ToolWidth)
            {
                GeneralPolygon2d min_poly = new GeneralPolygon2d(Polygon2d.MakeCircle(ToolWidth / 4, 6));
                min_poly.Outer.Translate(bounds.Center);
                FillCurveSet2d paths = ShellPolysToPaths(new List <GeneralPolygon2d>()
                {
                    min_poly
                }, 0);
                Shells.Add(paths);
            }
            else
            {
                FillCurveSet2d paths = ShellPolysToPaths(new List <GeneralPolygon2d>()
                {
                    Polygon
                }, 0);
                Shells.Add(paths);
            }

            InnerPolygons = new List <GeneralPolygon2d>();
        }
Пример #4
0
        static DMesh3 GenerateTubeMeshesForGCode(string sPath, double pathWidth = 0.4)
        {
            GenericGCodeParser parser = new GenericGCodeParser();
            GCodeFile          gcode;

            using (FileStream fs = new FileStream(sPath, FileMode.Open, FileAccess.Read)) {
                using (TextReader reader = new StreamReader(fs)) {
                    gcode = parser.Parse(reader);
                }
            }
            GCodeToLayerTubeMeshes make_tubes = new GCodeToLayerTubeMeshes()
            {
                TubeProfile = Polygon2d.MakeCircle(pathWidth / 2, 12),
                InterpretZChangeAsLayerChange = false
            };

            make_tubes.WantTubeTypes.Add(ToolpathTypes.Travel);
            ThreeAxisCNCInterpreter interpreter = new ThreeAxisCNCInterpreter();

            interpreter.AddListener(make_tubes);
            interpreter.Interpret(gcode, new InterpretArgs());
            DMesh3 tubeMesh2 = make_tubes.GetCombinedMesh(1);

            return(tubeMesh2);
        }
Пример #5
0
        void enable_circle_indicator(bool enable)
        {
            if (enable == false && circle_indicator == null)
            {
                return;
            }
            if (enable && circle_indicator == null)
            {
                LineSet lines = new LineSet();
                lines.UseFixedNormal = true;
                lines.FixedNormal    = Vector3f.AxisY;
                DCurve3 curve = new DCurve3(Polygon2d.MakeCircle(gizmoInitialRadius, 64), 0, 2);
                lines.Curves.Add(curve);
                lines.Width     = 1.0f;
                lines.WidthType = LineWidthType.Pixel;
                lines.Segments.Add(
                    new Segment3d(Vector3d.Zero, gizmoInitialRadius * diagonals[nRotationAxis]));
                lines.Color      = Colorf.DimGrey;
                circle_indicator = new fLineSetGameObject(new GameObject(), lines, "circle");
                circle_indicator.SetLayer(FPlatform.WidgetOverlayLayer, true);

                circle_indicator.SetLocalRotation(Quaternionf.FromTo(Vector3f.AxisY, Frame3f.Identity.GetAxis(nRotationAxis)));
                RootGameObject.AddChild(circle_indicator, false);
            }
            circle_indicator.SetVisible(enable);
        }
Пример #6
0
        public static void test_svg()
        {
            Polygon2d  poly  = Polygon2d.MakeCircle(100.0f, 10);
            PolyLine2d pline = new PolyLine2d();

            pline.AppendVertex(Vector2d.Zero);
            pline.AppendVertex(200 * Vector2d.AxisX);
            pline.AppendVertex(200 * Vector2d.One);
            Circle2d  circ = new Circle2d(33 * Vector2d.One, 25);
            Segment2d seg  = new Segment2d(Vector2d.Zero, -50 * Vector2d.AxisY);

            SVGWriter writer = new SVGWriter();

            writer.AddPolygon(poly, SVGWriter.Style.Filled("lime", "black", 0.25f));
            writer.AddPolyline(pline, SVGWriter.Style.Outline("orange", 2.0f));
            writer.AddCircle(circ, SVGWriter.Style.Filled("yellow", "red", 5.0f));
            writer.AddLine(seg, SVGWriter.Style.Outline("blue", 10.0f));

            int      astep = 29;
            Vector2d c     = new Vector2d(-200, 100);

            for (int k = 1; k <= 12; ++k)
            {
                Arc2d arc = new Arc2d(c + k * 45 * Vector2d.AxisX, 20, 0, k * astep);
                writer.AddArc(arc);
                writer.AddBox(arc.Bounds, SVGWriter.Style.Outline("red", 0.5f));
            }
            c.y += 50;
            for (int k = 1; k <= 12; ++k)
            {
                Arc2d arc = new Arc2d(c + k * 45 * Vector2d.AxisX, 20, k * astep, (k + 5) * astep);
                writer.AddArc(arc);
                writer.AddBox(arc.Bounds, SVGWriter.Style.Outline("red", 0.5f));
            }
            c.y += 50;
            for (int k = 1; k <= 12; ++k)
            {
                Arc2d arc = new Arc2d(c + k * 45 * Vector2d.AxisX, 20, k * astep, (k + 10) * astep);
                writer.AddArc(arc);
                writer.AddBox(arc.Bounds, SVGWriter.Style.Outline("red", 0.5f));
            }
            c.y += 50;
            for (int k = 1; k <= 12; ++k)
            {
                Arc2d arc = new Arc2d(c + k * 45 * Vector2d.AxisX, 20, k * astep, (k + 10) * astep);
                arc.Reverse();
                writer.AddArc(arc);
                writer.AddBox(arc.Bounds, SVGWriter.Style.Outline("red", 0.5f));
            }

            writer.Write(TestUtil.GetTestOutputPath("test.svg"));
        }
Пример #7
0
        public static void TestInflate()
        {
            Polygon2d poly = Polygon2d.MakeCircle(10.0f, 32);

            MeshInflater inflater = new MeshInflater(poly)
            {
                TargetEdgeLength = 1.0f
            };

            inflater.Compute();


            DebugUtil.WriteDebugMesh(inflater.ResultMesh, "c:\\scratch\\inflated.obj");
        }
Пример #8
0
        void CreateNewTube()
        {
            preview = new MeshTubePreview()
            {
                Polygon = Polygon2d.MakeCircle(Radius, nSlices)
            };
            preview.Create(scene.NewSOMaterial, scene.RootGameObject);

            smoother = new InPlaceIterativeCurveSmooth()
            {
                Curve = preview.Curve,
                Alpha = 0.2f
            };
        }
Пример #9
0
        DMesh3 compute_partial_hole(Vector3d start, Vector3d end, double tol)
        {
            DMesh3         origMesh    = MeshSource.GetDMeshUnsafe();
            DMeshAABBTree3 origSpatial = MeshSource.GetSpatial() as DMeshAABBTree3;

            DMesh3 cutMesh = new DMesh3(origMesh);

            Polygon2d polygon = Polygon2d.MakeCircle(hole_size / 2, hole_subdivisions);

            Vector3f axis = (Vector3f)(start - end).Normalized;

            int     start_tid   = origSpatial.FindNearestTriangle(start);
            Frame3f start_frame = origMesh.GetTriFrame(start_tid);

            start_frame.Origin = (Vector3f)start;
            start_frame.AlignAxis(2, axis);

            int end_tid = origSpatial.FindNearestTriangle(end);
            //Frame3f end_frame = origMesh.GetTriFrame(end_tid); end_frame.Origin = (Vector3f)end;
            Frame3f end_frame = start_frame; end_frame.Origin = (Vector3f)end;

            // [TODO] we don't need to Simplify here...is more robust?

            MeshInsertProjectedPolygon start_insert = new MeshInsertProjectedPolygon(cutMesh, polygon, start_frame, start_tid);
            bool start_ok = start_insert.Insert();

            if (start_ok == false)
            {
                throw new Exception("CutPolygonHoleOp.compute_partial_hole: start or end insertion failed!");
            }

            EdgeLoop outLoop = start_insert.InsertedLoop;

            MeshExtrudeLoop extrude = new MeshExtrudeLoop(cutMesh, outLoop);

            extrude.PositionF = (v, n, vid) => {
                cutMesh.GetVertex(vid);
                return(end_frame.ProjectToPlane((Vector3f)v, 2));
            };
            extrude.Extrude();

            SimpleHoleFiller filler = new SimpleHoleFiller(cutMesh, extrude.NewLoop);

            filler.Fill();

            return(cutMesh);
        }
Пример #10
0
        void validate_tube_meshes()
        {
            Polygon2d circle = Polygon2d.MakeCircle(Radius, Slices);

            for (int i = 0; i < CurveSet.Length; ++i)
            {
                TubeGenerator gen = new TubeGenerator(CurveSet[i].curve, circle)
                {
                    NoSharedVertices = false
                };
                gen.Generate();
                CurveSet[i].tubeMeshGO = GameObjectFactory.CreateMeshGO("tube_" + i.ToString(),
                                                                        gen.MakeUnityMesh(), false, true);
                CurveSet[i].tubeMeshGO.SetMaterial(curveMaterial, true);
                parentGO.AddChild(CurveSet[i].tubeMeshGO, false);
            }
        }
Пример #11
0
        static void generate_stacked_wavy_circle(SingleMaterialFFFCompiler compiler,
                                                 SingleMaterialFFFSettings settings)
        {
            double height    = 20.0;                                   // mm
            int    NLayers   = (int)(height / settings.LayerHeightMM); // 20mm
            int    NSteps    = 128;
            double radius    = 15.0;
            double frequency = 6;
            double scale     = 5.0;

            for (int layer_i = 0; layer_i < NLayers; ++layer_i)
            {
                // create data structures for organizing this layer
                ToolpathSetBuilder    layer_builder = new ToolpathSetBuilder();
                SequentialScheduler2d scheduler     = new SequentialScheduler2d(layer_builder, settings);
                if (layer_i == 0)
                {
                    scheduler.SpeedHint = SchedulerSpeedHint.Careful;
                }

                // initialize and layer-up
                layer_builder.Initialize(compiler.NozzlePosition);
                layer_builder.AppendZChange(settings.LayerHeightMM, settings.ZTravelSpeed);

                // start with circle
                FillPolygon2d circle_poly = new FillPolygon2d(Polygon2d.MakeCircle(radius, NSteps));

                // apply a wave deformation to circle, with wave height increasing with Z
                double layer_scale = MathUtil.Lerp(0, scale, (double)layer_i / (double)NLayers);
                for (int i = 0; i < NSteps; ++i)
                {
                    Vector2d v     = circle_poly[i];
                    double   angle = Math.Atan2(v.y, v.x);
                    double   r     = v.Length;
                    r += layer_scale * Math.Sin(frequency * angle);
                    circle_poly[i] = r * v.Normalized;
                }

                circle_poly.TypeFlags = FillTypeFlags.OuterPerimeter;
                scheduler.AppendPolygon2d(circle_poly);

                // pass paths to compiler
                compiler.AppendPaths(layer_builder.Paths, settings);
            }
        }
Пример #12
0
        public static void test_arrangement_stress()
        {
            Random r = new Random(31337);

            Arrangement2d builder = new Arrangement2d(new AxisAlignedBox2d(1024.0));

            Polygon2d circ = Polygon2d.MakeCircle(512, 33);

            builder.Insert(circ);

            // crazy stress-test
            for (int k = 0; k < 1000; ++k)
            {
                var pts = TestUtil.RandomPoints2(2, r, circ.Bounds.Center, 800);
                builder.Insert(new Segment2d(pts[0], pts[1]));
            }

            //TestUtil.WriteTestOutputGraph(builder.Graph, "graph_complex.svg");
        }
Пример #13
0
        public static void TestFill()
        {
            Window window = new Window("TestFill");

            window.SetDefaultSize(600, 600);
            window.SetPosition(WindowPosition.Center);

            DebugViewCanvas view = new DebugViewCanvas();

            GeneralPolygon2d poly = new GeneralPolygon2d(
                Polygon2d.MakeCircle(20, 32));

            Polygon2d hole = Polygon2d.MakeCircle(15, 32);

            hole.Reverse();
            hole.Translate(2 * Vector2d.AxisX);
            poly.AddHole(hole);

            view.AddPolygon(poly, Colorf.Black);

            double spacing = 0.5;

            double[] offsets = new double[] { 5 };

            foreach (double offset in offsets)
            {
                DGraph2            graph = TopoOffset2d.QuickCompute(poly, offset, spacing);
                DGraph2Util.Curves c     = DGraph2Util.ExtractCurves(graph);
                //view.AddGraph(graph, Colorf.Red);

                //DGraph2 perturbGraph = perturb_fill(graph, poly, 5.0f, spacing);
                DGraph2 perturbGraph = perturb_fill_2(graph, poly, 1.0f, spacing);
                //DGraph2Util.Curves c2 = DGraph2Util.ExtractCurves(perturbGraph);
                view.AddGraph(perturbGraph, Colorf.Orange);
            }

            window.Add(view);
            window.ShowAll();

            Active = view;
        }
Пример #14
0
        public static void test_winding()
        {
            Random r    = new Random(31337);
            int    NPTS = 1000;

            double    radius = 1;
            Polygon2d poly   = Polygon2d.MakeCircle(radius, 777);

            Vector2d[] testPts = TestUtil.RandomPoints2(NPTS, r, Vector2d.Zero, radius);
            foreach (Vector2d v in testPts)
            {
                bool   really_inside  = (v.Length < radius);
                bool   inside         = poly.Contains(v);
                double winding0       = poly.WindingIntegral(v);
                bool   inside_winding = !(Math.Abs(winding0) < MathUtil.Epsilonf);
                if (really_inside != inside || really_inside != inside_winding)
                {
                    System.Console.WriteLine("Failed! truth {0}  inside {1}   winding0 {2}",
                                             really_inside, inside, winding0);
                }
            }

            // test random polygons
            int NPOLYS = 100;

            for (int k = 0; k < NPOLYS; ++k)
            {
                poly    = new Polygon2d(TestUtil.RandomPoints2(30, r, Vector2d.Zero, radius));
                testPts = TestUtil.RandomPoints2(NPTS, r, Vector2d.Zero, radius);
                foreach (Vector2d v in testPts)
                {
                    bool   inside         = poly.Contains(v);
                    double winding0       = poly.WindingIntegral(v);
                    bool   inside_winding = !(Math.Abs(winding0) < MathUtil.Epsilonf);
                    if (inside != inside_winding)
                    {
                        System.Console.WriteLine("Failed! inside {0}   winding0 {1}", inside, winding0);
                    }
                }
            }
        }
Пример #15
0
        DMesh3 compute_through_hole(Vector3d start, Vector3d end, double tol)
        {
            DMesh3         origMesh    = MeshSource.GetDMeshUnsafe();
            DMeshAABBTree3 origSpatial = MeshSource.GetSpatial() as DMeshAABBTree3;

            DMesh3 cutMesh = new DMesh3(origMesh);

            Polygon2d polygon = Polygon2d.MakeCircle(hole_size / 2, hole_subdivisions);

            Vector3f axis = (Vector3f)(start - end).Normalized;

            int     start_tid   = origSpatial.FindNearestTriangle(start);
            Frame3f start_frame = origMesh.GetTriFrame(start_tid);

            start_frame.Origin = (Vector3f)start;
            start_frame.AlignAxis(2, axis);

            int end_tid = origSpatial.FindNearestTriangle(end);
            //Frame3f end_frame = origMesh.GetTriFrame(end_tid); end_frame.Origin = (Vector3f)end;
            Frame3f end_frame = start_frame; end_frame.Origin = (Vector3f)end;

            MeshInsertProjectedPolygon start_insert = new MeshInsertProjectedPolygon(cutMesh, polygon, start_frame, start_tid);
            bool start_ok = start_insert.Insert();

            MeshInsertProjectedPolygon end_insert = new MeshInsertProjectedPolygon(cutMesh, polygon, end_frame, end_tid);
            bool end_ok = end_insert.Insert();

            if (start_ok == false || end_ok == false)
            {
                throw new Exception("CutPolygonHoleOp.compute_through_hole: start or end insertion failed!");
            }

            MeshEditor editor = new MeshEditor(cutMesh);
            EdgeLoop   l0     = start_insert.InsertedLoop;
            EdgeLoop   l1     = end_insert.InsertedLoop;

            l1.Reverse();
            editor.StitchLoop(l0.Vertices, l1.Vertices);

            return(cutMesh);
        }
Пример #16
0
        override protected void Create_internal(fMaterial useMaterial)
        {
            if (polygon == null)
            {
                polygon = Polygon2d.MakeCircle(0.3f, 8);
            }

            // generate mesh tube
            TubeGenerator meshGen = new TubeGenerator()
            {
                Vertices = new List <Vector3d>(curve.Vertices), Capped = true,
                Polygon  = polygon,
                Frame    = new Frame3f(Vector3f.Zero, Vector3f.AxisY)
            };

            meshGen.Generate();
            Mesh m = meshGen.MakeUnityMesh(false);

            meshGO = UnityUtil.CreateMeshGO("tube_mesh", m, useMaterial, true);
            AppendNewGO(meshGO, RootGameObject, false);
        }
Пример #17
0
        static DMesh3 GenerateTubeMeshesForGCode(string sPath)
        {
            GenericGCodeParser parser = new GenericGCodeParser();
            GCodeFile          gcode;

            using (FileStream fs = new FileStream(sPath, FileMode.Open, FileAccess.Read)) {
                using (TextReader reader = new StreamReader(fs)) {
                    gcode = parser.Parse(reader);
                }
            }
            GCodeToLayerTubeMeshes make_tubes = new GCodeToLayerTubeMeshes()
            {
                TubeProfile = Polygon2d.MakeCircle(0.2f, 12)
            };
            MakerbotInterpreter interpreter = new MakerbotInterpreter();

            interpreter.AddListener(make_tubes);
            interpreter.Interpret(gcode, new InterpretArgs());
            DMesh3 tubeMesh2 = make_tubes.GetCombinedMesh(1);

            return(tubeMesh2);
        }
Пример #18
0
        public DMesh3 Make3DTubes(Interval1i layer_range, double merge_tol, double tube_radius)
        {
            Polygon2d tube_profile = Polygon2d.MakeCircle(tube_radius, 8);
            Frame3f   frame        = Frame3f.Identity;

            DMesh3 full_mesh = new DMesh3();

            foreach (int layer_i in layer_range)
            {
                PlanarSlice slice = Slices[layer_i];
                frame.Origin = new Vector3f(0, 0, slice.Z);
                foreach (GeneralPolygon2d gpoly in slice.Solids)
                {
                    List <Polygon2d> polys = new List <Polygon2d>()
                    {
                        gpoly.Outer
                    }; polys.AddRange(gpoly.Holes);
                    foreach (Polygon2d poly in polys)
                    {
                        Polygon2d simpPoly = new Polygon2d(poly);
                        simpPoly.Simplify(merge_tol, 0.01, true);
                        if (simpPoly.VertexCount < 3)
                        {
                            Util.gBreakToDebugger();
                        }
                        TubeGenerator tubegen = new TubeGenerator(simpPoly, frame, tube_profile)
                        {
                            NoSharedVertices = true
                        };
                        DMesh3 tubeMesh = tubegen.Generate().MakeDMesh();
                        MeshEditor.Append(full_mesh, tubeMesh);
                    }
                }
            }

            return(full_mesh);
        }
Пример #19
0
        public static void test_chamfer()
        {
            //Polygon2d poly = Polygon2d.MakeRectangle(Vector2d.Zero, 200, 200);
            //if (poly.IsClockwise)
            //    poly.Reverse();

            Polygon2d poly       = Polygon2d.MakeCircle(100, 64);
            double    max_offset = 50;

            for (int k = 0; k < poly.VertexCount; k++)
            {
                double t      = (double)k / (double)poly.VertexCount;
                double offset = (k % 2 == 0) ? -t * max_offset : t * max_offset;
                poly[k] = poly[k] + offset * poly[k].Normalized;
            }

            poly.Chamfer(60, 30, 30);

            SVGWriter writer = new SVGWriter();

            writer.AddPolygon(poly, SVGWriter.Style.Filled("lime", "black", 0.25f));

            writer.Write(TestUtil.GetTestOutputPath("test.svg"));
        }
Пример #20
0
        static void generate_vertical_wave(SingleMaterialFFFCompiler compiler,
                                           SingleMaterialFFFSettings settings)
        {
            ToolpathSetBuilder builder = new ToolpathSetBuilder();

            builder.Initialize(compiler.NozzlePosition);

            // layer-up
            builder.AppendZChange(settings.LayerHeightMM, settings.ZTravelSpeed);

            int       N      = 24;
            Polygon2d circle = Polygon2d.MakeCircle(15.0f, N, -MathUtil.HalfPI);

            int REPEAT = 5;

            for (int ri = 0; ri < REPEAT; ++ri)
            {
                builder.AppendTravel(circle[0], settings.RapidTravelSpeed);
                for (int k = 1; k <= N; k++)
                {
                    builder.AppendExtrude(circle[k % N], settings.CarefulExtrudeSpeed / 4);
                }
                builder.AppendZChange(settings.LayerHeightMM, settings.ZTravelSpeed);

                builder.AppendTravel(circle[0], settings.RapidTravelSpeed);
                for (int k = 1; k <= N; k++)
                {
                    builder.AppendExtrude(circle[k % N], settings.CarefulExtrudeSpeed / 4);
                }
                builder.AppendZChange(settings.LayerHeightMM, settings.ZTravelSpeed);

                if (ri == REPEAT - 1)
                {
                    break;
                }

                // make on the move up we should also move 'back' a bit,
                // to counteract forward pull force?

                double height  = 1.0f;
                double h_fudge = 0.0f;
                double z_stick = -0.05f;
                double z_layer = builder.Position.z;
                double top_z   = z_layer + height + h_fudge;
                for (int k = 0; k < N - 1; k++)
                {
                    Vector2d pcur = circle[k % N], pnext = circle[(k + 1) % N];
                    Vector3d pUp = new Vector3d(pcur.x, pcur.y, top_z);
                    builder.AppendExtrude(pUp, settings.CarefulExtrudeSpeed / 8);
                    builder.AppendDwell(500, false);
                    Vector3d pDown = new Vector3d(pnext.x, pnext.y, z_layer + z_stick);
                    builder.AppendExtrude(pDown, settings.CarefulExtrudeSpeed / 8);
                }

                // move up to z_high
                Vector3d vpos = new Vector3d(circle[0].x, circle[0].y, z_layer + height);
                builder.AppendExtrude(vpos, settings.CarefulExtrudeSpeed / 8);
            }

            compiler.AppendPaths(builder.Paths, settings);
        }
Пример #21
0
        /// <summary>
        /// Cut a "partial" hole, ie we cut the mesh with the polygon once, and then
        /// extrude downwards to a planar version of the cut boundary.
        ///
        /// Currently only supports extruding downwards from topmost intersection.
        ///
        /// </summary>
        protected bool CutPartialHole(DMesh3 mesh, HoleInfo hi, Vector3d translate, bool bUpwards)
        {
            if (hi.IsVertical == false)
            {
                throw new Exception("unsupported!");
            }

            Vector3d basePoint = CombinedBounds.Center - CombinedBounds.Extents.y * Vector3d.AxisY + translate;

            // do we need to compute spatial DS for each hole? not super efficient...
            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true);

            Vector3d direction = (bUpwards) ? Vector3d.AxisY : -Vector3d.AxisY;
            Vector3d center    = basePoint + new Vector3d(hi.XZOffset.x, 0, hi.XZOffset.y) - 10000 * direction;


            Ray3d ray     = new Ray3d(center, direction);
            int   hit_tid = spatial.FindNearestHitTriangle(ray);

            if (hit_tid == DMesh3.InvalidID)
            {
                return(false);
            }

            IntrRay3Triangle3 intersection = MeshQueries.TriangleIntersection(mesh, hit_tid, ray);
            Vector3d          inter_pos    = ray.PointAt(intersection.RayParameter);

            Frame3f projectFrame = new Frame3f(ray.Origin, ray.Direction);

            int nVerts = 32;

            if (hi.Vertices != 0)
            {
                nVerts = hi.Vertices;
            }
            double    angleShiftRad = hi.AxisAngleD * MathUtil.Deg2Rad;
            Polygon2d circle        = Polygon2d.MakeCircle(hi.Radius, nVerts, angleShiftRad);

            try {
                EdgeLoop loop = null;

                MeshInsertProjectedPolygon insert = new MeshInsertProjectedPolygon(mesh, circle, projectFrame, hit_tid)
                {
                    SimplifyInsertion = false
                };
                if (insert.Insert())
                {
                    loop = insert.InsertedLoop;

                    // [RMS] do we need to simplify for this one?
                    //if (loop.VertexCount > circle.VertexCount)
                    //    loop = simplify_loop(mesh, loop, circle.VertexCount);

                    MeshEditor editor = new MeshEditor(mesh);

                    Vector3d base_pos = inter_pos;
                    base_pos.y = basePoint.y + hi.PartialHoleBaseHeight;

                    int   N       = loop.VertexCount;
                    int[] newLoop = new int[N];
                    for (int k = 0; k < N; ++k)
                    {
                        newLoop[k] = mesh.AppendVertex(mesh, loop.Vertices[k]);
                        Vector3d cur_v = mesh.GetVertex(newLoop[k]);
                        cur_v.y = base_pos.y;
                        mesh.SetVertex(newLoop[k], cur_v);
                    }
                    int   base_vid = mesh.AppendVertex(base_pos);
                    int[] fan_tris = editor.AddTriangleFan_OrderedVertexLoop(base_vid, newLoop);
                    FaceGroupUtil.SetGroupID(mesh, fan_tris, hi.PartialHoleGroupID);
                    int[] stitch_tris = editor.StitchLoop(loop.Vertices, newLoop);

                    // need to remesh fan region because otherwise we get pathological cases
                    RegionRemesher remesh = new RegionRemesher(mesh, fan_tris);
                    remesh.SetTargetEdgeLength(2.0);
                    remesh.SmoothSpeedT       = 1.0;
                    remesh.PreventNormalFlips = true;
                    for (int k = 0; k < 25; ++k)
                    {
                        remesh.BasicRemeshPass();
                    }
                    //remesh.EnableCollapses = remesh.EnableFlips = remesh.EnableSplits = false;
                    //for (int k = 0; k < 20; ++k)
                    //    remesh.BasicRemeshPass();
                    remesh.BackPropropagate();

                    return(true);
                }
                else
                {
                    return(false);
                }
            } catch (Exception e) {
                f3.DebugUtil.Log("partial hole {0} failed!! {1}", hi.nHole, e.Message);
                return(false);
            }
        }
Пример #22
0
        /// <summary>
        /// Cut through-hole either vertically or horizontally.
        ///
        /// One current failure mode is if we get more than two ray-hits, which
        /// can happen due pathological cases or unexpected mesh shape. Currently
        /// trying to handle the pathological cases (ie ray hits adjacent triangles cases)
        /// via sorting, not sure if this works spectacularly well.
        ///
        /// </summary>
        protected bool CutThroughHole(DMesh3 mesh, HoleInfo hi, Vector3d translate)
        {
            Vector3d basePoint = CombinedBounds.Center - CombinedBounds.Extents.y * Vector3d.AxisY + translate;

            // do we need to compute spatial DS for each hole? not super efficient...
            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true);

            Vector3d origin    = Vector3d.Zero;
            Vector3d direction = Vector3d.One;

            if (hi.IsVertical)
            {
                direction = Vector3d.AxisY;
                origin    = basePoint + new Vector3d(hi.XZOffset.x, 0, hi.XZOffset.y) - 100 * direction;
            }
            else
            {
                origin    = basePoint + hi.Height * Vector3d.AxisY;
                direction = Quaterniond.AxisAngleD(Vector3d.AxisY, hi.AroundAngle) * Vector3d.AxisX;
            }

            // Find upper and lower triangles that contain center-points of
            // holes we want to cut. This is the most error-prone part
            // because we depend on ray-hits, which is not very reliable...

            Ray3d ray1 = new Ray3d(origin, direction);
            Ray3d ray2 = new Ray3d(origin + 10000 * direction, -direction);

            if (hi.GroupIDFilters.a > 0)
            {
                spatial.TriangleFilterF = (tid) => {
                    return(mesh.GetTriangleGroup(tid) == hi.GroupIDFilters.a);
                };
            }
            int hit_1 = spatial.FindNearestHitTriangle(ray1);

            spatial.TriangleFilterF = null;

            if (hi.GroupIDFilters.b > 0)
            {
                spatial.TriangleFilterF = (tid) => {
                    return(mesh.GetTriangleGroup(tid) == hi.GroupIDFilters.b);
                };
            }
            int hit_2 = spatial.FindNearestHitTriangle(ray2);

            spatial.TriangleFilterF = null;

            if (hit_1 == DMesh3.InvalidID || hit_2 == DMesh3.InvalidID)
            {
                return(false);
            }
            if (hit_1 == hit_2)
            {
                return(false);
            }

            List <int> hitTris = new List <int>()
            {
                hit_1, hit_2
            };


            Frame3f projectFrame = new Frame3f(ray1.Origin, ray1.Direction);

            int nVerts = 32;

            if (hi.Vertices != 0)
            {
                nVerts = hi.Vertices;
            }
            double    angleShiftRad = hi.AxisAngleD * MathUtil.Deg2Rad;
            Polygon2d circle        = Polygon2d.MakeCircle(hi.Radius, nVerts, angleShiftRad);


            List <EdgeLoop> edgeLoops = new List <EdgeLoop>();

            foreach (int hit_tid in hitTris)
            {
                try {
                    MeshInsertProjectedPolygon insert = new MeshInsertProjectedPolygon(mesh, circle, projectFrame, hit_tid)
                    {
                        SimplifyInsertion = true
                    };
                    if (insert.Insert())
                    {
                        // if we have extra edges just randomly collapse
                        EdgeLoop loop = insert.InsertedLoop;

                        if (loop.VertexCount > circle.VertexCount)
                        {
                            loop = simplify_loop(mesh, loop, circle.VertexCount);
                        }

                        edgeLoops.Add(loop);
                    }
                    else
                    {
                        f3.DebugUtil.Log("insert.Insert() failed!!");
                        return(false);
                    }
                } catch (Exception e) {
                    // ignore this loop but we might already be in trouble...
                    f3.DebugUtil.Log("insert.Insert() threw exception for hole {0}!!", hi.nHole);
                    f3.DebugUtil.Log(e.Message);
                }
            }
            if (edgeLoops.Count != 2)
            {
                return(false);
            }

            try {
                MeshEditor editor = new MeshEditor(mesh);
                EdgeLoop   l0     = edgeLoops[0];
                EdgeLoop   l1     = edgeLoops[1];
                l1.Reverse();
                editor.StitchVertexLoops_NearestV(l0.Vertices, l1.Vertices);

                // split edges around the holes we cut. This is helpful
                // if we are going to do additional operations in these areas,
                // as it gives us extra rings to work with
                //MeshEdgeSelection edges = new MeshEdgeSelection(mesh);
                //edges.SelectVertexEdges(l0.Vertices);
                //edges.SelectVertexEdges(l1.Vertices);
                //DMesh3.EdgeSplitInfo splitInfo;
                //foreach ( int eid in edges )
                //    mesh.SplitEdge(eid, out splitInfo);

                return(true);
            } catch {
                f3.DebugUtil.Log("stitch threw exception!");
                return(false);
            }
        }
Пример #23
0
        public static void testInsertPolygon_PlanarProj()
        {
            double dscale = 1.0;
            DMesh3 mesh   = TestUtil.LoadTestInputMesh("bunny_solid.obj");  dscale = 0.3;
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("cylinder.obj");
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("cube.obj");
            double   size = mesh.CachedBounds.MaxDim;
            Vector3d c    = mesh.CachedBounds.Center;
            Vector3d fw   = c + mesh.CachedBounds.DiagonalLength * 2 * Vector3d.AxisZ;
            Ray3d    ray  = new Ray3d(fw, (c - fw).Normalized);

            // projection frame and polygon that lives in this frame
            Frame3f   projectFrame = new Frame3f(ray.Origin, ray.Direction);
            Polygon2d circle       = Polygon2d.MakeCircle(dscale * size * 0.1, 6);


            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true);
            List <int>     hitTris = new List <int>();

            spatial.FindAllHitTriangles(ray, hitTris);
            while (hitTris.Count != 2)
            {
                ray.Origin += 100 * MathUtil.Epsilon * Vector3d.One;
                hitTris.Clear();
                spatial.FindAllHitTriangles(ray, hitTris);
            }

            // insert polygons but don't simplify the result

            DMesh3          noTrimMesh      = new DMesh3(mesh);
            List <int[]>    noTrimPolyVerts = new List <int[]>();
            List <EdgeLoop> noTrimLoops     = new List <EdgeLoop>();

            foreach (int hit_tid in hitTris)
            {
                MeshInsertProjectedPolygon insert = new MeshInsertProjectedPolygon(noTrimMesh, circle, projectFrame, hit_tid);
                insert.SimplifyInsertion = false;
                if (insert.Insert())
                {
                    noTrimPolyVerts.Add(insert.InsertedPolygonVerts);
                    noTrimLoops.Add(insert.InsertedLoop);
                }
                else
                {
                    System.Console.WriteLine("testInsertPolygon_PlanarProj: no-trim Insert() failed");
                }
            }
            TestUtil.WriteTestOutputMesh(noTrimMesh, "insert_polygon_notrim.obj");

            // do different-vtx-count stitch
            if (noTrimLoops.Count == 2)
            {
                noTrimLoops[1].Reverse();
                MeshStitchLoops stitcher = new MeshStitchLoops(noTrimMesh, noTrimLoops[0], noTrimLoops[1]);
                stitcher.TrustLoopOrientations = false;
                stitcher.AddKnownCorrespondences(noTrimPolyVerts[0], noTrimPolyVerts[1]);
                stitcher.Stitch();
            }
            TestUtil.WriteTestOutputMesh(noTrimMesh, "insert_polygon_notrim_joined.obj");


            // now do simplified version, which we can trivially stitch

            List <EdgeLoop> edgeLoops = new List <EdgeLoop>();

            foreach (int hit_tid in hitTris)
            {
                MeshInsertProjectedPolygon insert = new MeshInsertProjectedPolygon(mesh, circle, projectFrame, hit_tid);
                if (insert.Insert())
                {
                    edgeLoops.Add(insert.InsertedLoop);
                }
                else
                {
                    System.Console.WriteLine("testInsertPolygon_PlanarProj: Insert() failed");
                }
            }

            //TestUtil.WriteTestOutputMesh(mesh, "insert_polygon_before_stitch.obj");

            // do stitch
            if (edgeLoops.Count == 2)
            {
                MeshEditor editor = new MeshEditor(mesh);
                EdgeLoop   l0     = edgeLoops[0];
                EdgeLoop   l1     = edgeLoops[1];
                l1.Reverse();
                editor.StitchLoop(l0.Vertices, l1.Vertices);
            }

            TestUtil.WriteTestOutputMesh(mesh, "insert_polygon_joined.obj");
        }
Пример #24
0
        public static void test_tube_generator()
        {
            Polygon2d  circle_path = Polygon2d.MakeCircle(50, 64);
            PolyLine2d arc_path    = new PolyLine2d(circle_path.Vertices.Take(circle_path.VertexCount / 2));
            Polygon2d  irreg_path  = new Polygon2d();

            for (int k = 0; k < circle_path.VertexCount; ++k)
            {
                irreg_path.AppendVertex(circle_path[k]);
                k += k / 2;
            }
            PolyLine2d irreg_arc_path = new PolyLine2d(irreg_path.Vertices.Take(circle_path.VertexCount - 1));

            Polygon2d square_profile = Polygon2d.MakeCircle(7, 32);

            square_profile.Translate(4 * Vector2d.One);
            //square_profile[0] = 20 * square_profile[0].Normalized;

            bool no_shared = true;

            WriteGeneratedMesh(
                new TubeGenerator(circle_path, Frame3f.Identity, square_profile)
            {
                WantUVs = true, NoSharedVertices = no_shared
            },
                "tubegen_loop_standarduv.obj");

            WriteGeneratedMesh(
                new TubeGenerator(irreg_path, Frame3f.Identity, square_profile)
            {
                WantUVs = true, NoSharedVertices = no_shared
            },
                "tubegen_irregloop_standarduv.obj");

            WriteGeneratedMesh(
                new TubeGenerator(arc_path, Frame3f.Identity, square_profile)
            {
                WantUVs = true, NoSharedVertices = no_shared
            },
                "tubegen_arc_standarduv.obj");

            WriteGeneratedMesh(
                new TubeGenerator(irreg_arc_path, Frame3f.Identity, square_profile)
            {
                WantUVs = true, NoSharedVertices = no_shared
            },
                "tubegen_irregarc_standarduv.obj");



            // append tube border around each hole of input mesh
            DMesh3            inMesh   = TestUtil.LoadTestInputMesh("n_holed_bunny.obj");
            Polygon2d         bdrycirc = Polygon2d.MakeCircle(0.25, 6);
            MeshBoundaryLoops loops    = new MeshBoundaryLoops(inMesh);

            foreach (EdgeLoop loop in loops)
            {
                DCurve3       curve = loop.ToCurve().ResampleSharpTurns();
                TubeGenerator gen   = new TubeGenerator(curve, bdrycirc)
                {
                    NoSharedVertices = false
                };
                MeshEditor.Append(inMesh, gen.Generate().MakeDMesh());
            }
            TestUtil.WriteTestOutputMesh(inMesh, "boundary_tubes.obj");
        }
Пример #25
0
        public static void test_basic_generators()
        {
            TrivialDiscGenerator disc_gen = new TrivialDiscGenerator();

            WriteGeneratedMesh(disc_gen, "meshgen_Disc.obj");

            TrivialRectGenerator rect_gen = new TrivialRectGenerator();

            WriteGeneratedMesh(rect_gen, "meshgen_Rect.obj");

            GriddedRectGenerator gridrect_gen = new GriddedRectGenerator();

            WriteGeneratedMesh(gridrect_gen, "meshgen_GriddedRect.obj");

            PuncturedDiscGenerator punc_disc_gen = new PuncturedDiscGenerator();

            WriteGeneratedMesh(punc_disc_gen, "meshgen_PuncturedDisc.obj");

            TrivialBox3Generator box_gen = new TrivialBox3Generator();
            Frame3f f = Frame3f.Identity;

            f.Rotate(Quaternionf.AxisAngleD(Vector3f.AxisY, 45.0f));
            f.Rotate(Quaternionf.AxisAngleD(Vector3f.AxisZ, 45.0f));
            box_gen.Box = new Box3d(f.Origin, f.X, f.Y, f.Z, new Vector3d(3, 2, 1));
            WriteGeneratedMesh(box_gen, "meshgen_TrivialBox_shared.obj");
            box_gen.NoSharedVertices = true;
            WriteGeneratedMesh(box_gen, "meshgen_TrivialBox_noshared.obj");


            RoundRectGenerator roundrect_gen = new RoundRectGenerator();

            roundrect_gen.Width = 2;
            WriteGeneratedMesh(roundrect_gen, "meshgen_RoundRect.obj");


            GridBox3Generator gridbox_gen = new GridBox3Generator();

            WriteGeneratedMesh(gridbox_gen, "meshgen_GridBox_shared.obj");
            gridbox_gen.NoSharedVertices = true;
            WriteGeneratedMesh(gridbox_gen, "meshgen_GridBox_noshared.obj");

            Sphere3Generator_NormalizedCube normcube_gen = new Sphere3Generator_NormalizedCube();

            WriteGeneratedMesh(normcube_gen, "meshgen_Sphere_NormalizedCube_shared.obj");
            normcube_gen.NoSharedVertices = true;
            normcube_gen.Box = new Box3d(new Frame3f(Vector3f.One, Vector3f.One), Vector3d.One * 1.3);
            WriteGeneratedMesh(normcube_gen, "meshgen_Sphere_NormalizedCube_noshared.obj");


            TubeGenerator tube_gen = new TubeGenerator()
            {
                Vertices = new List <Vector3d>()
                {
                    Vector3d.Zero, Vector3d.AxisX, 2 * Vector3d.AxisX, 3 * Vector3d.AxisX
                },
                Polygon = Polygon2d.MakeCircle(1, 16)
            };

            WriteGeneratedMesh(tube_gen, "meshgen_TubeGenerator.obj");

            tube_gen.Polygon.Translate(Vector2d.One);
            tube_gen.CapCenter = Vector2d.One;
            WriteGeneratedMesh(tube_gen, "meshgen_TubeGenerator_shifted.obj");
        }
Пример #26
0
        public static void TestDGraph2()
        {
            Window window = new Window("TestDGraph2");

            window.SetDefaultSize(600, 600);
            window.SetPosition(WindowPosition.Center);

            DebugViewCanvas view = new DebugViewCanvas();

            GeneralPolygon2d poly = new GeneralPolygon2d(
                Polygon2d.MakeCircle(10, 32));

            //Polygon2d hole = Polygon2d.MakeCircle(9, 32);
            //hole.Reverse();
            //poly.AddHole(hole);

            Polygon2d hole = Polygon2d.MakeCircle(5, 32);

            hole.Translate(new Vector2d(2, 0));
            hole.Reverse();
            poly.AddHole(hole);

            Polygon2d hole2 = Polygon2d.MakeCircle(1, 32);

            hole2.Translate(-6 * Vector2d.AxisX);
            hole2.Reverse();
            poly.AddHole(hole2);

            Polygon2d hole3 = Polygon2d.MakeCircle(1, 32);

            hole3.Translate(-6 * Vector2d.One);
            hole3.Reverse();
            poly.AddHole(hole3);

            Polygon2d hole4 = Polygon2d.MakeCircle(1, 32);

            hole4.Translate(7 * Vector2d.AxisY);
            hole4.Reverse();
            poly.AddHole(hole4);

            view.AddPolygon(poly, Colorf.Black);

            double spacing = 0.2;

            //double[] offsets = new double[] { 0.5, 1, 1.5, 2, 2.5 };
            double[] offsets = new double[] { 0.2, 0.6 };

            TopoOffset2d o = new TopoOffset2d(poly)
            {
                PointSpacing = spacing
            };

            foreach (double offset in offsets)
            {
                o.Offset = offset;
                DGraph2            graph = o.Compute();
                DGraph2Util.Curves c     = DGraph2Util.ExtractCurves(graph);
                view.AddGraph(graph, Colorf.Red);
            }



            window.Add(view);
            window.ShowAll();
        }
Пример #27
0
        public static void quick_test()
        {
            DMesh3         mesh    = StandardMeshReader.ReadMesh("c:\\scratch\\block.obj");
            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true);

            Vector3d rayCenter = new Vector3d(0, 0, 1);
            Frame3f  rayFrame  = new Frame3f(rayCenter, Vector3d.AxisZ);

            List <Frame3f> frames = new List <Frame3f>();

            // how far into surface we will inset
            float SurfaceOffset = 0.01f;

            double step = 2.5f;

            for (double angle = 0; angle < 360; angle += step)
            {
                double dx    = Math.Cos(angle * MathUtil.Deg2Rad),
                       dy    = Math.Sin(angle * MathUtil.Deg2Rad);
                Vector3d dir = dx * (Vector3d)rayFrame.X + dy * (Vector3d)rayFrame.Y;
                Ray3d    ray = new Ray3d(rayFrame.Origin, dir.Normalized);

                Frame3f hitFrame;
                if (MeshQueries.RayHitPointFrame(mesh, spatial, ray, out hitFrame))
                {
                    frames.Add(hitFrame);
                }
            }

            int N = frames.Count;

            for (int k = 0; k < N; ++k)
            {
                Frame3f f    = frames[k];
                int     prev = (k == 0) ? N - 1 : k - 1;
                int     next = (k + 1) % N;
                //Vector3f dv = frames[(k + 1) % frames.Count].Origin - f.Origin;
                Vector3f dv = frames[next].Origin - frames[prev].Origin;
                dv.Normalize();
                f.ConstrainedAlignAxis(0, dv, f.Z);

                f.Origin = f.Origin + SurfaceOffset * f.Z;

                frames[k] = f;
            }

            //Frame3f f = frames[0];
            //Vector3f dv = (frames[1].Origin - frames[0].Origin).Normalized;
            //f.ConstrainedAlignAxis(1, dv, f.Z);
            //for (int k = 1; k < frames.Count; ++k) {
            //    f.Origin = frames[k].Origin;
            //    f.AlignAxis(2, frames[k].Z);
            //    frames[k] = f;
            //}


            List <Vector3d> vertices = frames.ConvertAll((ff) => { return((Vector3d)ff.Origin); });

            TubeGenerator tubegen = new TubeGenerator()
            {
                Vertices         = vertices,
                Polygon          = Polygon2d.MakeCircle(0.05, 16),
                NoSharedVertices = false
            };
            DMesh3 tubeMesh = tubegen.Generate().MakeDMesh();

            TestUtil.WriteTestOutputMeshes(new List <IMesh>()
            {
                mesh, tubeMesh
            }, "curve_tube.obj");


            SimpleQuadMesh stripMeshY = new SimpleQuadMesh();
            double         w = 0.1;
            int            preva = -1, prevb = -1;

            for (int k = 0; k < N; ++k)
            {
                Vector3d pa = frames[k].Origin + w * (Vector3d)frames[k].Y;
                Vector3d pb = frames[k].Origin - w * (Vector3d)frames[k].Y;
                int      a  = stripMeshY.AppendVertex(pa);
                int      b  = stripMeshY.AppendVertex(pb);
                if (preva != -1)
                {
                    stripMeshY.AppendQuad(preva, prevb, b, a);
                }
                preva = a; prevb = b;
            }
            stripMeshY.AppendQuad(preva, prevb, 1, 0);
            SimpleQuadMesh.WriteOBJ(stripMeshY, TEST_OUTPUT_PATH + "quadstripy.obj", WriteOptions.Defaults);



            SimpleQuadMesh stripMeshZ = new SimpleQuadMesh();

            preva = -1; prevb = -1;
            double wz = 0.1;

            for (int k = 0; k < N; ++k)
            {
                Vector3d pa = frames[k].Origin + wz * (Vector3d)frames[k].Z;
                Vector3d pb = frames[k].Origin - wz * (Vector3d)frames[k].Z;
                int      a  = stripMeshZ.AppendVertex(pa);
                int      b  = stripMeshZ.AppendVertex(pb);
                if (preva != -1)
                {
                    stripMeshZ.AppendQuad(preva, prevb, b, a);
                }
                preva = a; prevb = b;
            }
            stripMeshZ.AppendQuad(preva, prevb, 1, 0);
            SimpleQuadMesh.WriteOBJ(stripMeshZ, TEST_OUTPUT_PATH + "quadstripz.obj", WriteOptions.Defaults);
        }
Пример #28
0
        public static void test_cells()
        {
            Polygon2d        outer = Polygon2d.MakeCircle(1000, 17);
            Polygon2d        hole  = Polygon2d.MakeCircle(100, 32); hole.Reverse();
            GeneralPolygon2d gpoly = new GeneralPolygon2d(outer);

            gpoly.AddHole(hole);

            DGraph2 graph = new DGraph2();

            graph.AppendPolygon(gpoly);

            GraphSplitter2d splitter = new GraphSplitter2d(graph);

            splitter.InsideTestF = gpoly.Contains;
            for (int k = 0; k < outer.VertexCount; ++k)
            {
                Line2d line = new Line2d(outer[k], Vector2d.AxisY);
                splitter.InsertLine(line);
            }
            for (int k = 0; k < outer.VertexCount; ++k)
            {
                Line2d line = new Line2d(outer[k], Vector2d.AxisX);
                splitter.InsertLine(line);
            }
            for (int k = 0; k < outer.VertexCount; ++k)
            {
                Line2d line = new Line2d(outer[k], Vector2d.One.Normalized);
                splitter.InsertLine(line);
            }
            for (int k = 0; k < outer.VertexCount; ++k)
            {
                Line2d line = new Line2d(outer[k], new Vector2d(1, -1).Normalized);
                splitter.InsertLine(line);
            }

            GraphCells2d cells = new GraphCells2d(graph);

            cells.FindCells();

            List <Polygon2d> polys = cells.ContainedCells(gpoly);

            for (int k = 0; k < polys.Count; ++k)
            {
                double offset = polys[k].IsClockwise ? 4 : 20;
                polys[k].PolyOffset(offset);
            }


            PlanarComplex cp = new PlanarComplex();

            for (int k = 0; k < polys.Count; ++k)
            {
                cp.Add(polys[k]);
            }

            // convert back to solids
            var options = PlanarComplex.FindSolidsOptions.Default;

            options.WantCurveSolids            = false;
            options.SimplifyDeviationTolerance = 0;
            var solids = cp.FindSolidRegions(options);

            SVGWriter svg = new SVGWriter();

            svg.AddGraph(graph, SVGWriter.Style.Outline("red", 5));
            for (int k = 0; k < polys.Count; ++k)
            {
                svg.AddPolygon(polys[k], SVGWriter.Style.Outline("black", 1));
            }

            svg.Write(TestUtil.GetTestOutputPath("cells_graph.svg"));
        }
Пример #29
0
        public static void test_splitter()
        {
            Polygon2d        poly  = Polygon2d.MakeCircle(1000, 16);
            Polygon2d        hole  = Polygon2d.MakeCircle(500, 32); hole.Reverse();
            GeneralPolygon2d gpoly = new GeneralPolygon2d(poly);

            gpoly.AddHole(hole);
            //Polygon2d poly = Polygon2d.MakeRectangle(Vector2d.Zero, 1000, 1000);

            DGraph2 graph = new DGraph2();

            graph.AppendPolygon(gpoly);

            System.Console.WriteLine("Stats before: verts {0} edges {1} ", graph.VertexCount, graph.EdgeCount);

            GraphSplitter2d splitter = new GraphSplitter2d(graph);

            splitter.InsideTestF = gpoly.Contains;

            for (int k = 0; k < poly.VertexCount; ++k)
            {
                Line2d line = new Line2d(poly[k], Vector2d.AxisY);
                splitter.InsertLine(line);
            }
            System.Console.WriteLine("Stats after 1: verts {0} edges {1} ", graph.VertexCount, graph.EdgeCount);
            for (int k = 0; k < poly.VertexCount; ++k)
            {
                Line2d line = new Line2d(poly[k], Vector2d.AxisX);
                splitter.InsertLine(line);
            }
            for (int k = 0; k < poly.VertexCount; ++k)
            {
                Line2d line = new Line2d(poly[k], Vector2d.One.Normalized);
                splitter.InsertLine(line);
            }
            for (int k = 0; k < poly.VertexCount; ++k)
            {
                Line2d line = new Line2d(poly[k], new Vector2d(1, -1).Normalized);
                splitter.InsertLine(line);
            }

            System.Console.WriteLine("Stats after: verts {0} edges {1} ", graph.VertexCount, graph.EdgeCount);


            Random r = new Random(31337);

            foreach (int vid in graph.VertexIndices())
            {
                Vector2d v = graph.GetVertex(vid);
                v += TestUtil.RandomPoints2(1, r, v, 25)[0];
                graph.SetVertex(vid, v);
            }



            SVGWriter svg = new SVGWriter();

            svg.AddGraph(graph);

            var vtx_style = SVGWriter.Style.Outline("red", 1.0f);

            foreach (int vid in graph.VertexIndices())
            {
                Vector2d v = graph.GetVertex(vid);
                svg.AddCircle(new Circle2d(v, 10), vtx_style);
            }

            svg.Write(TestUtil.GetTestOutputPath("split_graph.svg"));
        }
Пример #30
0
        static void generate_vertical(SingleMaterialFFFCompiler compiler,
                                      SingleMaterialFFFSettings settings)
        {
            ToolpathSetBuilder builder = new ToolpathSetBuilder();

            builder.Initialize(compiler.NozzlePosition);

            // layer-up
            builder.AppendZChange(settings.LayerHeightMM, settings.ZTravelSpeed);

            // draw circle
            int       N      = 32;
            Polygon2d circle = Polygon2d.MakeCircle(25.0f, N, -MathUtil.HalfPI);

            builder.AppendTravel(circle[0], settings.RapidTravelSpeed);
            for (int k = 1; k <= N; k++)
            {
                builder.AppendExtrude(circle[k % N], settings.CarefulExtrudeSpeed);
            }

            // layer-up
            builder.AppendZChange(settings.LayerHeightMM, settings.ZTravelSpeed);

            double height  = 5.0f;
            double z_layer = builder.Position.z;
            double z_high  = z_layer + height;

            for (int k = 1; k <= N; k++)
            {
                Vector2d p2 = circle[k % N];
                double   z  = (k % 2 == 1) ? z_high : z_layer;
                Vector3d p3 = new Vector3d(p2.x, p2.y, z);
                builder.AppendExtrude(p3, settings.CarefulExtrudeSpeed / 4);

                // dwell at tops
                if (z == z_high)
                {
                    AssemblerCommandsToolpath dwell_path = new AssemblerCommandsToolpath()
                    {
                        AssemblerF = make_tip
                    };
                    builder.AppendPath(dwell_path);
                }
            }

            // move up to z_high
            builder.AppendZChange(height, settings.ZTravelSpeed);

            // draw circle again
            builder.AppendTravel(circle[0], settings.RapidTravelSpeed);
            for (int k = 1; k <= N; k++)
            {
                builder.AppendExtrude(circle[k % N], settings.RapidExtrudeSpeed);
            }


            // draw teeth again

            z_layer = builder.Position.z;
            z_high  = z_layer + height;
            for (int k = 1; k <= N; k++)
            {
                Vector2d p2 = circle[k % N];
                double   z  = (k % 2 == 1) ? z_high : z_layer;
                Vector3d p3 = new Vector3d(p2.x, p2.y, z);
                builder.AppendExtrude(p3, settings.CarefulExtrudeSpeed / 4);

                // dwell at tops
                if (z == z_high)
                {
                    AssemblerCommandsToolpath dwell_path = new AssemblerCommandsToolpath()
                    {
                        AssemblerF = make_tip
                    };
                    builder.AppendPath(dwell_path);
                }
            }


            // move up to z_high
            builder.AppendZChange(height, settings.ZTravelSpeed);

            // draw circle again
            builder.AppendTravel(circle[0], settings.RapidTravelSpeed);
            for (int k = 1; k <= N; k++)
            {
                builder.AppendExtrude(circle[k % N], settings.RapidExtrudeSpeed);
            }


            compiler.AppendPaths(builder.Paths, settings);
        }