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"));
        }
Example #2
0
        /// <summary>
        /// shoot parallel set of 2D rays at input polygon, and find portions
        /// of rays that are inside the polygon (we call these "spans"). These
        /// are inserted into the polygon, resulting in a non-manifold 2D graph.
        /// </summary>
        protected DGraph2 ComputeSpanGraph(GeneralPolygon2d poly)
        {
            double   angleRad = AngleDeg * MathUtil.Deg2Rad;
            Vector2d dir      = new Vector2d(Math.Cos(angleRad), Math.Sin(angleRad));

            // compute projection span along axis
            Vector2d   axis         = dir.Perp;
            Interval1d axisInterval = Interval1d.Empty;
            Interval1d dirInterval  = Interval1d.Empty;

            foreach (Vector2d v in poly.Outer.Vertices)
            {
                dirInterval.Contain(v.Dot(dir));
                axisInterval.Contain(v.Dot(axis));
            }
            // [TODO] also check holes? or assume they are contained? should be
            //  classified as outside by winding check anyway...

            // construct interval we will step along to shoot parallel rays
            dirInterval.a -= 10 * ToolWidth;
            dirInterval.b += 10 * ToolWidth;
            double extent = dirInterval.Length;

            // nudge in a very tiny amount so that if poly is a rectangle, first
            // line is not directly on boundary
            axisInterval.a += ToolWidth * 0.01;
            axisInterval.b -= ToolWidth * 0.01;
            axisInterval.a -= PathShift;
            if (axisInterval.b < axisInterval.a)
            {
                return(null);     // [RMS] is this right? I guess so. interval is too small to fill?
            }
            // If we are doing a dense fill, we want to pack as tightly as possible.
            // But if we are doing a sparse fill, then we want layers to stack.
            // So in that case, snap the interval to increments of the spacing
            //  (does this work?)
            bool bIsSparse = (PathSpacing > ToolWidth * 2);

            if (bIsSparse)
            {
                // snap axisInterval.a to grid so that layers are aligned
                double snapped_a = Snapping.SnapToIncrement(axisInterval.a, PathSpacing);
                if (snapped_a > axisInterval.a)
                {
                    snapped_a -= PathSpacing;
                }
                axisInterval.a = snapped_a;
            }

            Vector2d startCorner = axisInterval.a * axis + dirInterval.a * dir;
            double   range       = axisInterval.Length;
            int      N           = (int)(range / PathSpacing) + 1;

            // nudge spacing so that we exactly fill the available space
            double use_spacing = PathSpacing;

            if (bIsSparse == false && AdjustSpacingToMaximizeFill)
            {
                int nn = (int)(range / use_spacing);
                use_spacing = range / (double)nn;
                N           = (int)(range / use_spacing) + 1;
            }

            DGraph2 graph = new DGraph2();

            graph.AppendPolygon(poly);
            GraphSplitter2d splitter = new GraphSplitter2d(graph);

            splitter.InsideTestF = poly.Contains;

            // insert sequential rays
            for (int ti = 0; ti <= N; ++ti)
            {
                Vector2d o   = startCorner + (double)ti * use_spacing * axis;
                Line2d   ray = new Line2d(o, dir);
                splitter.InsertLine(ray, ti);
            }

            return(graph);
        }
        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"));
        }