Ejemplo n.º 1
0
        public static DGraph2 perturb_fill_2(DGraph2 graphIn, GeneralPolygon2d bounds, double waveWidth, double stepSize)
        {
            DGraph2Util.Curves curves = DGraph2Util.ExtractCurves(graphIn);
            Polygon2d          poly   = curves.Loops[0];

            GeneralPolygon2dBoxTree gpTree    = new GeneralPolygon2dBoxTree(bounds);
            Polygon2dBoxTree        outerTree = new Polygon2dBoxTree(bounds.Outer);
            Polygon2dBoxTree        innerTree = new Polygon2dBoxTree(bounds.Holes[0]);

            DGraph2 graph = new DGraph2();

            graph.EnableVertexColors(Vector3f.Zero);

            graph.AppendPolygon(poly);

            DGraph2Resampler resampler = new DGraph2Resampler(graph);

            resampler.CollapseToMinEdgeLength(waveWidth);
            if (graph.VertexCount % 2 != 0)
            {
                // TODO smallest edge
                Index2i ev = graph.GetEdgeV(graph.EdgeIndices().First());
                DGraph2.EdgeCollapseInfo cinfo;
                graph.CollapseEdge(ev.a, ev.b, out cinfo);
            }


            // move to borders
            int  startv = graph.VertexIndices().First();
            int  eid    = graph.VtxEdgesItr(startv).First();
            int  curv   = startv;
            bool outer  = true;

            do
            {
                Polygon2dBoxTree use_tree = (outer) ? outerTree : innerTree;
                outer = !outer;
                graph.SetVertex(curv, use_tree.NearestPoint(graph.GetVertex(curv)));

                Index2i next = DGraph2Util.NextEdgeAndVtx(eid, curv, graph);
                eid  = next.a;
                curv = next.b;
            } while (curv != startv);



            return(graph);
        }
Ejemplo n.º 2
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;
        }
Ejemplo n.º 3
0
        public static DGraph2 perturb_fill(DGraph2 graphIn, GeneralPolygon2d bounds, double waveWidth, double stepSize)
        {
            DGraph2Util.Curves curves = DGraph2Util.ExtractCurves(graphIn);
            Polygon2d          poly   = curves.Loops[0];

            GeneralPolygon2dBoxTree gpTree    = new GeneralPolygon2dBoxTree(bounds);
            Polygon2dBoxTree        outerTree = new Polygon2dBoxTree(bounds.Outer);
            Polygon2dBoxTree        innerTree = new Polygon2dBoxTree(bounds.Holes[0]);

            DGraph2 graph = new DGraph2();

            graph.EnableVertexColors(Vector3f.Zero);

            double len = poly.Perimeter;
            int    waves = (int)(len / waveWidth);
            double lenScale = len / (MathUtil.TwoPI * waves);
            double accum_len = 0;
            int    prev_vid = -1, start_vid = -1;
            int    N = poly.VertexCount;

            for (int k = 0; k < N; ++k)
            {
                double t = accum_len / lenScale;
                t = Math.Cos(t);
                //Vector2d normal = poly.GetNormal(k);
                Vector2d normal = poly[k].Normalized;
                int      vid    = graph.AppendVertex(poly[k], new Vector3f(t, normal.x, normal.y));
                if (prev_vid != -1)
                {
                    graph.AppendEdge(prev_vid, vid);
                    accum_len += graph.GetVertex(prev_vid).Distance(graph.GetVertex(vid));
                }
                else
                {
                    start_vid = vid;
                }
                prev_vid = vid;
            }
            graph.AppendEdge(prev_vid, start_vid);

            Vector2d[] newPos = new Vector2d[graph.MaxVertexID];

            for (int k = 0; k < 10; ++k)
            {
                smooth_pass(graph, 0.5f, newPos);
            }

            for (int k = 0; k < 20; ++k)
            {
                foreach (int vid in graph.VertexIndices())
                {
                    Vector2d v = graph.GetVertex(vid);
                    Vector3f c = graph.GetVertexColor(vid);

                    float    t = c.x;
                    Vector2d n = new Vector2d(c.y, c.z);

                    if (k == 0 || Math.Abs(t) > 0.9)
                    {
                        v += t * stepSize * n;
                        if (!bounds.Contains(v))
                        {
                            v = gpTree.NearestPoint(v);
                        }
                    }

                    newPos[vid] = v;
                }

                foreach (int vid in graph.VertexIndices())
                {
                    graph.SetVertex(vid, newPos[vid]);
                }

                for (int j = 0; j < 5; ++j)
                {
                    smooth_pass(graph, 0.1f, newPos);
                }
            }

            return(graph);
        }
Ejemplo n.º 4
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();
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Convert the input polygons to a set of paths.
        /// If FilterSelfOverlaps=true, then the paths will be clipped against
        /// themselves, in an attempt to avoid over-printing.
        /// </summary>
        public virtual FillCurveSet2d ShellPolysToPaths(List <GeneralPolygon2d> shell_polys, int nShell)
        {
            FillCurveSet2d paths = new FillCurveSet2d();

            FillTypeFlags flags = FillTypeFlags.PerimeterShell;

            if (nShell == 0 && ShellType == ShellTypes.ExternalPerimeters)
            {
                flags = FillTypeFlags.OutermostShell;
            }
            else if (ShellType == ShellTypes.InternalShell)
            {
                flags = FillTypeFlags.InteriorShell;
            }
            else if (ShellType == ShellTypes.BridgeShell)
            {
                flags = FillTypeFlags.BridgeSupport;
            }

            if (FilterSelfOverlaps == false)
            {
                foreach (GeneralPolygon2d shell in shell_polys)
                {
                    paths.Append(shell, flags);
                }
                return(paths);
            }

            int outer_shell_edgegroup = 100;

            foreach (GeneralPolygon2d shell in shell_polys)
            {
                PathOverlapRepair repair = new PathOverlapRepair();
                repair.OverlapRadius = SelfOverlapTolerance;
                repair.Add(shell, outer_shell_edgegroup);

                // Ideally want to presreve outermost shell of external perimeters.
                // However in many cases internal holes are 'too close' to outer border.
                // So we will still apply to those, but use edge filter to preserve outermost loop.
                // [TODO] could we be smarter about this somehow?
                if (PreserveOuterShells && nShell == 0 && ShellType == ShellTypes.ExternalPerimeters)
                {
                    repair.PreserveEdgeFilterF = (eid) => { return(repair.Graph.GetEdgeGroup(eid) == outer_shell_edgegroup); }
                }
                ;

                repair.Compute();

                DGraph2Util.Curves c = DGraph2Util.ExtractCurves(repair.GetResultGraph());

                foreach (var polygon in c.Loops)
                {
                    paths.Append(polygon, flags);
                }
                foreach (var polyline in c.Paths)
                {
                    if (polyline.ArcLength < DiscardTinyPerimterLengthMM)
                    {
                        continue;
                    }
                    if (polyline.Bounds.MaxDim < DiscardTinyPerimterLengthMM)
                    {
                        continue;
                    }
                    paths.Append(new FillPolyline2d(polyline)
                    {
                        TypeFlags = flags
                    });
                }
            }
            return(paths);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Convert the input polygons to a set of paths.
        /// If FilterSelfOverlaps=true, then the paths will be clipped against
        /// themselves, in an attempt to avoid over-printing.
        /// </summary>
        public virtual FillCurveSet2d ShellPolysToPaths(List <GeneralPolygon2d> shell_polys, int nShell)
        {
            FillCurveSet2d paths = new FillCurveSet2d();

            IFillType currentFillType = nShell == 0 ? firstShellFillType ?? fillType : fillType;

            if (FilterSelfOverlaps == false)
            {
                foreach (var shell in shell_polys)
                {
                    paths.Append(new FillLoop <FillSegment>(shell.Outer.Vertices)
                    {
                        FillType = currentFillType, PerimeterOrder = nShell
                    });
                    foreach (var hole in shell.Holes)
                    {
                        paths.Append(new FillLoop <FillSegment>(hole.Vertices)
                        {
                            FillType = currentFillType, PerimeterOrder = nShell, IsHoleShell = true
                        });;
                    }
                }
                return(paths);
            }

            int outer_shell_edgegroup = 100;

            foreach (GeneralPolygon2d shell in shell_polys)
            {
                PathOverlapRepair repair = new PathOverlapRepair();
                repair.OverlapRadius = SelfOverlapTolerance;
                repair.Add(shell, outer_shell_edgegroup);

                // Ideally want to presreve outermost shell of external perimeters.
                // However in many cases internal holes are 'too close' to outer border.
                // So we will still apply to those, but use edge filter to preserve outermost loop.
                // [TODO] could we be smarter about this somehow?
                if (PreserveOuterShells && nShell == 0)
                {
                    repair.PreserveEdgeFilterF = (eid) => { return(repair.Graph.GetEdgeGroup(eid) == outer_shell_edgegroup); }
                }
                ;

                repair.Compute();

                DGraph2Util.Curves c = DGraph2Util.ExtractCurves(repair.GetResultGraph());

                #region Borrow nesting calculations from PlanarSlice to enforce winding direction

                PlanarComplex complex = new PlanarComplex();
                foreach (Polygon2d poly in c.Loops)
                {
                    complex.Add(poly);
                }

                PlanarComplex.FindSolidsOptions options
                    = PlanarComplex.FindSolidsOptions.Default;
                options.WantCurveSolids            = false;
                options.SimplifyDeviationTolerance = 0.001;
                options.TrustOrientations          = false;
                options.AllowOverlappingHoles      = false;

                PlanarComplex.SolidRegionInfo solids = complex.FindSolidRegions(options);
                foreach (var polygon in solids.Polygons)
                {
                    polygon.EnforceCounterClockwise();
                    paths.Append(new FillLoop <FillSegment>(polygon.Outer.Vertices)
                    {
                        FillType       = currentFillType,
                        PerimeterOrder = nShell
                    });
                    foreach (var hole in polygon.Holes)
                    {
                        paths.Append(new FillLoop <FillSegment>(hole.Vertices)
                        {
                            FillType       = currentFillType,
                            PerimeterOrder = nShell,
                            IsHoleShell    = true,
                        });
                    }
                }

                #endregion Borrow nesting calculations from PlanarSlice to enforce winding direction

                foreach (var polyline in c.Paths)
                {
                    if (polyline.ArcLength < DiscardTinyPerimeterLengthMM)
                    {
                        continue;
                    }
                    if (polyline.Bounds.MaxDim < DiscardTinyPerimeterLengthMM)
                    {
                        continue;
                    }
                    paths.Append(new FillCurve <FillSegment>(polyline)
                    {
                        FillType = currentFillType, PerimeterOrder = nShell
                    });
                }
            }
            return(paths);
        }