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); }
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); }
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); }