Beispiel #1
0
        public Brep buildHelical(Curve Sectioin, Circle C, double Deg, double H, bool Solid)
        {
            double       angle = (H / Math.Tan(toRadian(Deg))) / (C.Radius * 2 * Math.PI);
            List <Curve> gears = new List <Curve>();
            double       step  = 3;

            for (int i = 0; i < (int)step + 1; i++)
            {
                Curve     thisC  = Sectioin.DuplicateCurve();
                Transform rotate = Transform.Rotation(angle * (double)i / step, C.Normal, C.Center);
                Transform move   = Transform.Translation(C.Normal * H * (double)i / step);
                thisC.Transform(rotate);
                thisC.Transform(move);
                gears.Add(thisC);
            }
            Brep profile = Brep.CreateFromLoft(gears, Point3d.Unset, Point3d.Unset, LoftType.Normal, false)[0];

            if (Solid)
            {
                Brep        top    = Brep.CreatePlanarBreps(gears[0], 1)[0];
                Brep        buttom = Brep.CreatePlanarBreps(gears[(int)step], 1)[0];
                List <Brep> breps  = new List <Brep> {
                    buttom, profile, top
                };
                return(Brep.CreateSolid(breps, 1.0)[0]);
            }
            else
            {
                return(profile);
            }
        }
        public static Brep ToAllPlaneBrep(this Brep roomBrep, double tolerance = 0.0001)
        {
            var tol   = tolerance;
            var surfs = roomBrep.Faces;

            surfs.ShrinkFaces();
            var checkedSrfs = new List <Brep>();

            foreach (var srf in surfs)
            {
                var s = srf.UnderlyingSurface();
                if (s is PlaneSurface ps)
                {
                    checkedSrfs.Add(ps.ToBrep());
                }
                else if (srf.IsPlanar())
                {
                    var cv = srf.OuterLoop.To3dCurve();
                    var p  = Brep.CreatePlanarBreps(cv, tol).First();
                    checkedSrfs.Add(p);
                }
                else
                {
                    throw new ArgumentException("Non-planar surfaces are not accepted!");
                }
            }

            //Method 1
            var solid = Brep.CreateSolid(checkedSrfs, tol).OrderBy(_ => _.Faces.Count).LastOrDefault();

            if (solid.IsSolid)
            {
                return(solid);
            }

            //Method 2
            solid = new Brep();
            checkedSrfs.ToList().ForEach(_ => solid.Append(_));
            solid.JoinNakedEdges(tol);
            if (solid.IsSolid)
            {
                return(solid);
            }

            //Method 3
            var joined = Brep.JoinBreps(checkedSrfs, tol).OrderBy(_ => _.Faces.Count).ToList();

            if (!joined.LastOrDefault().IsSolid)
            {
                solid = joined.Select(_ => _.CapPlanarHoles(tol)).SkipWhile(_ => _ == null).FirstOrDefault();
            }
            return(solid);
        }
Beispiel #3
0
        private static Brep IntersectWithMasses(Brep roomGeo, IEnumerable <Brep> adjacentRooms, double tolerance)
        {
            //return solo room directly.
            if (!adjacentRooms.Any())
            {
                return(roomGeo);
            }

            tolerance = Math.Max(tolerance, Rhino.RhinoMath.ZeroTolerance);

            //Check bounding boxes first
            var roomBBox = roomGeo.GetBoundingBox(false);

            var currentBrep = roomGeo;
            var allBreps    = adjacentRooms;


            //var currentBrepFaces = currentBrep.Faces;
            //var isRoomValid = allBreps.Select(_ => _.Surfaces.All(s => s.TryGetFaceEntity().IsValid));
            //var isThisRoomValid = currentBrep.Surfaces.All(s => s.TryGetFaceEntity().IsValid);
            //var faceAreasBeforeSplit = currentBrepFaces.Select(_ => AreaMassProperties.Compute(_).Area);
            foreach (Brep adjBrep in allBreps)
            {
                var isDup = adjBrep.IsDuplicate(roomGeo, tolerance);
                if (isDup)
                {
                    continue;
                }

                //Get matched faces, and its adjacent cutters.
                var matchAndCutters = currentBrep.GetAdjFaces(adjBrep, tolerance);
                //There is no overlapping area.
                if (!matchAndCutters.Any())
                {
                    continue;
                }


                //Split and Join
                var solidBrep      = currentBrep;
                var cuttedElements = new List <Brep>();
                foreach (var matchAndCutter in matchAndCutters)
                {
                    var currentRoomFace = matchAndCutter.roomFace;
                    var cutters         = matchAndCutter.matchedCutters.Select(_ => _.DuplicateFace(false)).ToList();
                    //Split the current brep by cutters
                    var newBreps = solidBrep.Split(cutters, tolerance).SkipWhile(_ => _ == null);

                    if (!newBreps.Any())
                    {
                        continue;
                    }


                    //var ent1 = currentRoomFace.UnderlyingSurface().TryGetFaceEntity();
                    ////var ent2 = currentBrep.Surfaces[currentRoomFace.SurfaceIndex].TryGetFaceEntity();
                    //////var ent3 = currentRoomFace.ToBrep().Surfaces[0].TryGetFaceEntity();
                    ////var ent = currentRoomFace.TryGetFaceEntity();

                    var faceEntID = currentRoomFace.UnderlyingSurface().GetUserString("HBDataID");
                    //assign new name ID to newly split faces.
                    //DO NOT use following Linq expression, because ToList() creates new object, instead of referencing the same one.
                    //newBreps.Where(_ => _.Faces.Count == 1).ToList().ForEach(_ => _.TryGetFaceEntity().UpdateID_CopyFrom(ent));
                    if (!string.IsNullOrEmpty(faceEntID))
                    {
                        foreach (var item in newBreps)
                        {
                            if (item.Faces.Count > 1)
                            {
                                continue;
                            }

                            item.Surfaces[0].SetUserString("HBDataID", faceEntID);
                            item.Surfaces[0].SetUserString("HBDataID_NewName", $"Face_{Guid.NewGuid().ToString()}");
                        }
                    }


                    //Join back to solid
                    //var roomEnts = newBreps.Select(_ => _.Surfaces.Select(s => s.TryGetFaceEntity()));
                    var newBrep = Brep.CreateSolid(newBreps, tolerance);
                    solidBrep = newBrep.First();
                    solidBrep.Faces.ShrinkFaces();
                }
                //just to make logically clear, but they are essentially the same.
                //solidBrep is only used in above foreach loop
                currentBrep = solidBrep;
            }
            //move over the roomEntity to new geometry.
            //all faceEntities in Brep.surface stays even after split.
            var roomEntID = roomGeo.GetUserString("HBDataID");

            if (!string.IsNullOrEmpty(roomEntID))
            {
                currentBrep.SetUserString("HBDataID", roomEntID);
            }

            //TODO: update subsurfaces geometry data
            //Probably there is no need to update this geometry data until export to simulation engine.
            //No one needs this data.

            return(currentBrep);
        }
Beispiel #4
0
        public static IGH_GeometricGoo BldgPartToRoof(BuildingPart bldgPart)
        {
            IGH_GeometricGoo roof = bldgPart.PartGoo;
            PolylineCurve    pL   = bldgPart.PartFootprint; ///Already at min height

            bldgPart.PartOsmGeo.Tags.TryGetValue("roof:shape", out string roofShape);

            bldgPart.PartOsmGeo.Tags.TryGetValue("height", out string heightString);
            double height = GetHeightDimensioned(heightString);

            bldgPart.PartOsmGeo.Tags.TryGetValue("min_height", out string minHeightString);
            double min_height = GetHeightDimensioned(minHeightString);

            bldgPart.PartOsmGeo.Tags.TryGetValue("roof:height", out string roofHeightString);
            double roofHeight = GetHeightDimensioned(roofHeightString);

            double facadeHeight = height - roofHeight;

            ///Make sure there's a minium facade height for SF Transamerica Pyramid case
            if (facadeHeight <= 0)
            {
                facadeHeight = 2 * DocumentTolerance();
            }

            bldgPart.PartOsmGeo.Tags.TryGetValue("roof:orientation", out string roofOrientationString);

            bldgPart.PartOsmGeo.Tags.TryGetValue("roof:direction", out string roofDirectionString);
            double   roofDirection       = System.Convert.ToDouble(roofDirectionString);
            Vector3d roofDirectionVector = Plane.WorldXY.YAxis;

            roofDirectionVector.Rotate(RhinoMath.ToRadians(-roofDirection), Plane.WorldXY.ZAxis);

            Line[]  edges    = pL.ToPolyline().GetSegments();
            Point3d centroid = AreaMassProperties.Compute(pL).Centroid;

            switch (roofShape)
            {
            case "pyramidal":
                centroid.Z = height;
                pL.TryGetPolyline(out Polyline pLPolyline);
                Line[]      pLLines         = pLPolyline.GetSegments();
                List <Brep> pyramidBrepList = Brep.CreatePlanarBreps(pL, DocumentTolerance()).ToList();

                if (!string.IsNullOrEmpty(roofHeightString))
                {
                    Plane facadeHeightPlane = Plane.WorldXY;
                    facadeHeightPlane.Translate(new Vector3d(0, 0, facadeHeight));
                    pLPolyline.Transform(Transform.PlanarProjection(facadeHeightPlane));

                    ///Creating individual faces seems to work better/cleaner than lofting curves
                    for (int i = 0; i < pLLines.Count(); i++)
                    {
                        Line bottomEdge = pLLines[i];
                        Line topEdge    = bottomEdge;
                        topEdge.Transform(Transform.PlanarProjection(facadeHeightPlane));
                        pyramidBrepList.Add(Brep.CreateFromCornerPoints(bottomEdge.PointAt(0), bottomEdge.PointAt(1), topEdge.PointAt(1), topEdge.PointAt(0), DocumentTolerance()));
                    }
                }

                foreach (Line edge in pLPolyline.GetSegments())
                {
                    pyramidBrepList.Add(Brep.CreateFromCornerPoints(edge.PointAt(0), centroid, edge.PointAt(1), DocumentTolerance()));
                }

                Brep[] pyramidBrep = Brep.CreateSolid(pyramidBrepList, DocumentTolerance());
                if (pyramidBrep[0].IsSolid)
                {
                    roof = GH_Convert.ToGeometricGoo(pyramidBrep[0]);
                }
                break;

            case "skillion":
                Line   frontEdge     = new Line();
                Line   backEdge      = new Line();
                double frontAngleMin = RhinoMath.ToRadians(90);
                double backAngleMin  = RhinoMath.ToRadians(90);

                foreach (Line edge in edges)
                {
                    Point3d  closestPt       = edge.ClosestPoint(centroid, true);
                    Vector3d perpVector      = closestPt - centroid;
                    double   angleDifference = Vector3d.VectorAngle(roofDirectionVector, perpVector);
                    if (angleDifference < frontAngleMin)
                    {
                        frontEdge     = edge;
                        frontAngleMin = angleDifference;
                    }
                    if (angleDifference > backAngleMin)
                    {
                        backEdge     = edge;
                        backAngleMin = angleDifference;
                    }
                }

                Point3d backEdgeFrom = backEdge.From;
                backEdgeFrom.Z = height;
                Point3d backEdgeTo = backEdge.To;
                backEdgeTo.Z = height;
                Point3d frontEdgeFrom = frontEdge.From;
                frontEdgeFrom.Z = facadeHeight;
                Point3d frontEdgeTo = frontEdge.To;
                frontEdgeTo.Z = facadeHeight;

                List <Point3d> basePtList = new List <Point3d> {
                    backEdge.From, backEdge.To, frontEdge.From, frontEdge.To, backEdge.From
                };
                Polyline       basePolyline = new Polyline(basePtList);
                List <Point3d> topPtList    = new List <Point3d> {
                    backEdgeFrom, backEdgeTo, frontEdgeFrom, frontEdgeTo, backEdgeFrom
                };
                Polyline topPolyline = new Polyline(topPtList);

                ///Creating individual faces seems to work better/cleaner than lofting curves
                List <Brep> skillionBreps = new List <Brep>();
                Line[]      baseLines     = basePolyline.GetSegments();
                Line[]      topLines      = topPolyline.GetSegments();
                for (int i = 0; i < baseLines.Count(); i++)
                {
                    Line bottomEdge = baseLines[i];
                    Line topEdge    = topLines[i];
                    skillionBreps.Add(Brep.CreateFromCornerPoints(bottomEdge.PointAt(0), bottomEdge.PointAt(1), topEdge.PointAt(1), topEdge.PointAt(0), DocumentTolerance()));
                }
                Brep baseSkillion = Brep.CreateFromCornerPoints(backEdge.From, backEdge.To, frontEdge.From, frontEdge.To, DocumentTolerance());
                Brep topSkillion  = Brep.CreateFromCornerPoints(backEdgeFrom, backEdgeTo, frontEdgeFrom, frontEdgeTo, DocumentTolerance());

                skillionBreps.Add(baseSkillion);
                skillionBreps.Add(topSkillion);
                Brep[] skillion = Brep.CreateSolid(skillionBreps, DocumentTolerance());
                if (skillion.Count() > 0)
                {
                    roof = GH_Convert.ToGeometricGoo(skillion[0]);
                }

                break;

            case "gabled":
                ///TODO: Look into getting oriented bbox using front edge as orientation plane,
                ///extrude gable roof profile from face of bbox, trim roof geo from footprint,
                ///loft between footprint and trimmed roof edges and join everything.

                ///Need to simply polylines with colinear segments. Angle tolerance based on Notre-Dame de Paris case
                //pL.Simplify(CurveSimplifyOptions.All, 0, RhinoMath.ToRadians(2)).TryGetPolyline(out Polyline pLSimplified);
                Polyline pLSimplified = pL.ToPolyline();
                pLSimplified.MergeColinearSegments(DocumentAngleTolerance() * 5, true);

                Line[] edgesSimplified = pLSimplified.GetSegments();
                if (edgesSimplified.Count() != 4)
                {
                    break;
                }
                Line        ridge            = new Line();
                Line        eaveOne          = new Line();
                Line        eaveTwo          = new Line();
                Polyline    topGablePolyline = new Polyline();
                List <Brep> gableBreps       = new List <Brep>();

                if ((edgesSimplified[0].Length > edgesSimplified[1].Length && roofOrientationString != "across") || ((edgesSimplified[0].Length < edgesSimplified[1].Length && roofOrientationString == "across")))
                {
                    ridge         = new Line(edgesSimplified[3].PointAt(0.5), edgesSimplified[1].PointAt(0.5));
                    ridge.FromZ   = height;
                    ridge.ToZ     = height;
                    eaveOne       = edgesSimplified[0];
                    eaveOne.FromZ = facadeHeight;
                    eaveOne.ToZ   = facadeHeight;
                    eaveTwo       = edgesSimplified[2];
                    eaveTwo.Flip();
                    eaveTwo.FromZ    = facadeHeight;
                    eaveTwo.ToZ      = facadeHeight;
                    topGablePolyline = new Polyline {
                        eaveOne.From, eaveOne.To, ridge.To, eaveTwo.To, eaveTwo.From, ridge.From, eaveOne.From
                    };

                    Brep[] gableRoof = Brep.CreateFromLoft(new List <Curve> {
                        eaveOne.ToNurbsCurve(), ridge.ToNurbsCurve(), eaveTwo.ToNurbsCurve()
                    }, Point3d.Unset, Point3d.Unset, LoftType.Straight, false);
                    gableRoof[0].Faces.SplitKinkyFaces();
                    gableBreps.Add(gableRoof[0]);
                }

                if ((edgesSimplified[0].Length > edgesSimplified[1].Length && roofOrientationString == "across") || (edgesSimplified[0].Length < edgesSimplified[1].Length && roofOrientationString != "across"))
                {
                    ridge         = new Line(edgesSimplified[0].PointAt(0.5), edgesSimplified[2].PointAt(0.5));
                    ridge.FromZ   = height;
                    ridge.ToZ     = height;
                    eaveOne       = edgesSimplified[1];
                    eaveOne.FromZ = facadeHeight;
                    eaveOne.ToZ   = facadeHeight;
                    eaveTwo       = edgesSimplified[3];
                    eaveTwo.Flip();
                    eaveTwo.FromZ    = facadeHeight;
                    eaveTwo.ToZ      = facadeHeight;
                    topGablePolyline = new Polyline {
                        eaveTwo.From, ridge.From, eaveOne.From, eaveOne.To, ridge.To, eaveTwo.To, eaveTwo.From
                    };

                    Brep[] gableRoof = Brep.CreateFromLoft(new List <Curve> {
                        eaveOne.ToNurbsCurve(), ridge.ToNurbsCurve(), eaveTwo.ToNurbsCurve()
                    }, Point3d.Unset, Point3d.Unset, LoftType.Straight, false);
                    gableRoof[0].Faces.SplitKinkyFaces();
                    gableBreps.Add(gableRoof[0]);
                }

                Brep[] gablewalls = Brep.CreateFromLoft(new List <Curve> {
                    pLSimplified.ToPolylineCurve(), topGablePolyline.ToPolylineCurve()
                }, Point3d.Unset, Point3d.Unset, LoftType.Straight, false);
                gablewalls[0].Faces.SplitKinkyFaces();
                gablewalls[0].MergeCoplanarFaces(DocumentTolerance());
                gableBreps.Add(gablewalls[0]);

                Brep baseGable = Brep.CreateFromCornerPoints(edgesSimplified[0].From, edgesSimplified[0].To, edgesSimplified[2].From, edgesSimplified[2].To, DocumentTolerance());
                gableBreps.Add(baseGable);
                Brep[] gable = Brep.JoinBreps(gableBreps, DocumentTolerance());

                if (gable[0].IsValid)
                {
                    roof = GH_Convert.ToGeometricGoo(gable[0]);
                }
                break;

            default:
                break;
            }

            return(roof);
        }