예제 #1
0
        public void HalfEdgeGraphFromLinesBothWays()
        {
            Name = nameof(HalfEdgeGraphFromLinesBothWays);
            // not in order and inconsistently wound
            var lines = new List <Line> {
                new Line((0, 0), (10, 0)),
                new Line((10, 10), (5, 15)),
                new Line((10, 0), (10, 10)),
                new Line((0, 0), (0, 10)),
                new Line((0, 10), (5, 15)),
            };
            var heg      = HalfEdgeGraph2d.Construct(lines, true);
            var polygons = heg.Polygonize();

            Assert.Equal(2, polygons.Count);
            Assert.Single(polygons.Where(p => p.Normal().Dot(Vector3.ZAxis) > 0));
        }
예제 #2
0
        public void HalfEdgeGraphFromLines()
        {
            Name = nameof(HalfEdgeGraphFromLines);
            // not in order, but clockwise-wound
            var lines = new List <Line> {
                new Line((0, 0), (10, 0)),
                new Line((10, 10), (5, 15)),
                new Line((10, 0), (10, 10)),
                new Line((0, 10), (0, 0)),
                new Line((5, 15), (0, 10)),
            };
            var heg      = HalfEdgeGraph2d.Construct(lines);
            var polygons = heg.Polygonize();

            Assert.Single(polygons);
            Model.AddElement(polygons[0]);
        }
예제 #3
0
        public void PolygonCleanupIssue()
        {
            Name = nameof(PolygonCleanupIssue);
            var rect      = Polygon.Rectangle(10, 10);
            var splitters = Polygon.Rectangle(4, 15).Segments().Select(s => s.ToPolyline(1));

            Model.AddElements(rect);

            var heg      = HalfEdgeGraph2d.Construct(new[] { rect }, splitters);
            var polygons = heg.Polygonize();

            Assert.Equal(3, polygons.Count);
            Assert.True(polygons.All(p => p.Segments().Count() == 4), "All polygons should be simple rectangles");
            var rand = new Random();

            foreach (var s in polygons)
            {
                Model.AddElement(new ModelCurve(s, rand.NextMaterial(), new Transform(0, 0, rand.NextDouble())));
            }
        }
예제 #4
0
        /// <summary>
        /// Intersect this solid with the provided plane.
        /// </summary>
        /// <param name="p">The plane of intersection.</param>
        /// <param name="result">A collection of polygons resulting
        /// from the intersection or null if there was no intersection.</param>
        /// <returns>True if an intersection occurred, otherwise false.</returns>
        public bool Intersects(Plane p, out List <Polygon> result)
        {
            var graphVertices = new List <Vector3>();
            var graphEdges    = new List <List <(int from, int to, int?tag)> >();

            foreach (var f in this.Faces)
            {
                var facePlane = f.Value.Plane();

                // If the face is coplanar, skip it. The edges of
                // the face also belong to adjacent faces and will
                // be included in their results.
                if (facePlane.IsCoplanar(p))
                {
                    continue;
                }

                var edgeResults = new List <Vector3>();

                edgeResults.AddRange(IntersectLoop(f.Value.Outer, p));

                if (f.Value.Inner != null)
                {
                    foreach (var inner in f.Value.Inner)
                    {
                        edgeResults.AddRange(IntersectLoop(inner, p));
                    }
                }

                var d = facePlane.Normal.Cross(p.Normal).Unitized();
                edgeResults.Sort(new DirectionComparer(d));

                // Draw segments through the results and add to the
                // half edge graph.
                for (var j = 0; j < edgeResults.Count - 1; j += 2)
                {
                    // Don't create zero-length edges.
                    if (edgeResults[j].IsAlmostEqualTo(edgeResults[j + 1]))
                    {
                        continue;
                    }

                    var a  = FindOrCreateGraphVertex(edgeResults[j], graphVertices, graphEdges);
                    var b  = FindOrCreateGraphVertex(edgeResults[j + 1], graphVertices, graphEdges);
                    var e1 = (a, b, 0);
                    var e2 = (b, a, 0);
                    if (graphEdges[a].Contains(e1) || graphEdges[b].Contains(e2))
                    {
                        continue;
                    }
                    else
                    {
                        graphEdges[a].Add(e1);
                    }
                }
            }

            var heg = new HalfEdgeGraph2d()
            {
                Vertices       = graphVertices,
                EdgesPerVertex = graphEdges
            };

            try
            {
                var polys = heg.Polygonize();
                if (polys == null || polys.Count == 0)
                {
                    result = null;
                    return(false);
                }
                result = polys;
                return(true);
            }
            catch (Exception ex)
            {
                // TODO: We could test for known failure modes, but the
                // iteration over the edge graph before attempting to
                // graph to identify these modes, is as expensive as
                // the graph attempt.
                // Known cases there the half edge graph will throw an
                // exception:
                // - Co-linear edges.
                // - Disconnected graphs.
                // - Graphs with one vertex.
                Console.WriteLine(ex.Message);

                result = null;
                return(false);
            }
        }