예제 #1
0
        public void ConvexHullFrom3DCloudAndNormal()
        {
            Name = nameof(ConvexHullFrom3DCloudAndNormal);
            var L = Polygon.L(2, 4, 1).TransformedPolygon(new Transform().Moved(3, 4));
            var jitteredVertices = L.Vertices.ToList();

            jitteredVertices[0] = new Transform().Moved(0, 0, 0.1).OfPoint(jitteredVertices[0]);
            jitteredVertices[1] = new Transform().Moved(0, 0, -0.1).OfPoint(jitteredVertices[1]);

            var flatHull = ConvexHull.FromPoints(L.Vertices);

            var jitteredHull = ConvexHull.FromPointsInPlane(jitteredVertices, Vector3.ZAxis);

            Assert.True(jitteredHull.IsAlmostEqualTo(flatHull), "Jittered flat hull doesn't match original hull.");

            // Simple transform allows simple polygon comparison for Assert.
            var simpleTransform = new Transform(Vector3.Origin, new Vector3(1, 0, 0).Unitized(), 0);
            var liftedPoints    = jitteredVertices.Select(p => simpleTransform.OfPoint(p));
            var liftedHull      = ConvexHull.FromPointsInPlane(liftedPoints, Vector3.XAxis);

            Assert.True(liftedHull.IsAlmostEqualTo(flatHull.TransformedPolygon(simpleTransform)), "The lifted hull doesn't match the transformed flat hull.");

            // Complex transform can be used for visual inspection of the resulting frame.
            var complexTransform    = new Transform(Vector3.Origin, new Vector3(1, 2, 0).Unitized(), 0);
            var complexLiftedPoints = jitteredVertices.Select(p => complexTransform.OfPoint(p));
            var complexLiftedHull   = ConvexHull.FromPointsInPlane(complexLiftedPoints, Vector3.XAxis);
            var complexliftedHull2  = ConvexHull.FromPointsInPlane(complexLiftedPoints, new Vector3(1, 1, 0));;

            this.Model.AddElement(L);
            this.Model.AddElement(new ModelCurve(flatHull, new Material("aqua", Colors.Aqua)));
            this.Model.AddElement(new ModelCurve(jitteredHull, new Material("cobalt", Colors.Cobalt)));
            this.Model.AddElements(CylinderAtPoints(complexLiftedPoints));
            this.Model.AddElement(new ModelCurve(complexLiftedHull, new Material("cobalt", Colors.Cobalt)));
            this.Model.AddElement(new ModelCurve(complexliftedHull2, new Material("crimson", Colors.Crimson)));
        }
예제 #2
0
        /// <summary>
        /// Extract polygons from a collection of elements.
        /// </summary>
        /// <param name="elements">The elements to get polygons from.</param>
        /// <param name="getDefaultPolygon">A function for extracting the default relevant polygon from an envelope.
        /// If this returns null, we'll use the 2D convex hull of the geometry of the element's representation </param>
        private static List <Polygon> ExtractPolygonsFromElements <T>(IEnumerable <T> elements, Func <T, Polygon> getDefaultPolygon) where T : GeometricElement
        {
            var polygons = new List <Polygon>();

            foreach (var element in elements)
            {
                var polygon = getDefaultPolygon(element) ?? ConvexHull.FromPoints(element.Representation.SolidOperations.SelectMany(o => o.Solid.Vertices.Select(v => new Vector3(v.Value.Point.X, v.Value.Point.Y))));
                polygons.Add(polygon);
            }
            return(polygons);
        }
예제 #3
0
        public void ConvexHullOrthogonalWithDuplicateVertices()
        {
            var points = new List <Vector3>()
            {
                new Vector3(51.8160, 6.0960, 45.7200),
                new Vector3(0.0000, 6.0960, 45.7200),
                new Vector3(0.0000, 24.3840, 45.7200),
                new Vector3(51.8160, 24.3840, 45.7200),
                new Vector3(51.8160, 24.3840, 45.7200),
                new Vector3(51.8160, 6.0960, 45.7200)
            };
            var hull = ConvexHull.FromPoints(points);

            Assert.Equal(4, hull.Segments().Length);
        }
예제 #4
0
        public void ConvexHullAndBoundingRect()
        {
            Name = "Convex Hull";
            var rand = new Random();

            // fuzz test
            for (int test = 0; test < 50; test++)
            {
                var basePt = new Vector3((test % 5) * 12, (test - (test % 5)) / 5 * 12);
                var pts    = new List <Vector3>();
                for (int i = 0; i < 20; i++)
                {
                    pts.Add(basePt + new Vector3(rand.NextDouble() * 10, rand.NextDouble() * 10));
                }
                var modelPts     = pts.Select(p => new ModelCurve(new Circle(p, 0.2)));
                var hull         = ConvexHull.FromPoints(pts);
                var boundingRect = Polygon.FromAlignedBoundingBox2d(pts);
                Model.AddElements(modelPts);
                Model.AddElements(boundingRect);
                Model.AddElement(hull);
            }

            // handle collinear pts test
            var coPts = new List <Vector3> {
                new Vector3(0, 0),
                new Vector3(1, 0),
                new Vector3(2, 0),
                new Vector3(4, 0),
                new Vector3(10, 0),
                new Vector3(10, 5),
                new Vector3(10, 10)
            };
            var coHull = ConvexHull.FromPoints(coPts);

            Assert.Equal(50, coHull.Area());
        }
        public static List <Envelope> SliceAtHeight(Envelope envelope, double cutHeight, Boolean showDebugGeometry)
        {
            var debugMaterial = new Material("DebugSolid", new Color(1, 0, 0, 1));

            var plane = new Plane(new Vector3(0, 0, cutHeight), Vector3.ZAxis);
            var top   = envelope.Elevation + envelope.Height;
            var envelopesForBlockage = new List <Envelope>();
            var newUpperSolids       = new List <Elements.Geometry.Solids.SolidOperation>();

            Polygon slice = null;

            foreach (var solidOp in envelope.Representation.SolidOperations)
            {
                var intersections = new List <Vector3>();
                var newUpperSolid = new Elements.Geometry.Solids.Solid();

                foreach (var face in solidOp.Solid.Faces)
                {
                    var polygon = face.Value.Outer.ToPolygon();
                    if (solidOp.LocalTransform != null)
                    {
                        polygon = (Polygon)polygon.Transformed(solidOp.LocalTransform);
                    }
                    if (envelope.Transform != null)
                    {
                        polygon = (Polygon)polygon.Transformed(envelope.Transform);
                    }

                    var faceIntersections = new List <Vector3>();

                    foreach (var segment in polygon.Segments())
                    {
                        if (segment.Intersects(plane, out var intersection))
                        {
                            intersections.Add(intersection);
                            faceIntersections.Add(intersection);
                        }
                    }

                    if (faceIntersections.Count == 0)
                    {
                        if (polygon.Centroid().Z > cutHeight)
                        {
                            newUpperSolid.AddFace(polygon);
                        }
                    }
                    else if (faceIntersections.Count > 1)
                    {
                        faceIntersections = faceIntersections.OrderBy(p => p.X).ThenBy(p => p.Y).ToList();
                        var splitLine = new Polyline(faceIntersections);
                        var splits    = polygon.Split(splitLine);
                        foreach (var split in splits)
                        {
                            if (split.Centroid().Z > cutHeight)
                            {
                                newUpperSolid.AddFace(split);
                            }
                        }
                    }
                }

                if (intersections.Count >= 3)
                {
                    slice = ConvexHull.FromPoints(intersections);
                    slice = slice.Project(new Plane(new Vector3(), Vector3.ZAxis));
                }
                else if (intersections.Count > 0)
                {
                    Console.WriteLine($"Failed to intersect polygon for East Midtown: Found {intersections.Count} point");
                }

                newUpperSolids.Add(new Elements.Geometry.Solids.ConstructedSolid(newUpperSolid));
            }

            if (slice != null)
            {
                var extrude1 = new Elements.Geometry.Solids.Extrude(slice, cutHeight, Vector3.ZAxis, false);
                var rep1     = new Representation(new List <Elements.Geometry.Solids.SolidOperation>()
                {
                    extrude1
                });
                var env1 = new Envelope(slice, 0, cutHeight, Vector3.ZAxis, 0, new Transform(), _debugMaterial, rep1, false, Guid.NewGuid(), "");
                envelopesForBlockage.Add(env1);

                var rep2 = new Representation(newUpperSolids);
                var env2 = new Envelope(slice, 0, cutHeight, Vector3.ZAxis, 0, new Transform(), _debugMaterial, rep2, false, Guid.NewGuid(), "");
                envelopesForBlockage.Add(env2);

                if (showDebugGeometry)
                {
                    Model.AddElement(env1);
                    Model.AddElement(env2);
                }
            }

            return(envelopesForBlockage);
        }