def _inset_floor_surfaces( _floor_surface, _inset_dist, _ghenv ): '''Shrinks/Insets the surface by the specified amount ''' try: rh_srfc = from_face3d(_floor_surface.geometry) except Exception as e: msg = 'Error. Can not convert floor surface: "{}" to Rhino geometry?'.format( _floor_surface ) _ghenv.Component.AddRuntimeMessage(ghK.GH_RuntimeMessageLevel.Remark, msg) return None if _inset_dist < 0.001: return rh_srfc #----------------------------------------------------------------------- srfcPerim = ghc.JoinCurves( ghc.BrepEdges(rh_srfc)[0], preserve=False ) # Get the inset Curve srfcCentroid = Rhino.Geometry.AreaMassProperties.Compute(rh_srfc).Centroid plane = ghc.XYPlane(srfcCentroid) srfcPerim_Inset_Pos = ghc.OffsetCurve(srfcPerim, _inset_dist, plane, 1) srfcPerim_Inset_Neg = ghc.OffsetCurve(srfcPerim, _inset_dist*-1, srfcCentroid, 1) # Choose the right Offset Curve. The one with the smaller area srfcInset_Pos = ghc.BoundarySurfaces( srfcPerim_Inset_Pos ) srfcInset_Neg = ghc.BoundarySurfaces( srfcPerim_Inset_Neg ) area_Pos = ghc.Area(srfcInset_Pos).area area_neg = ghc.Area(srfcInset_Neg).area if area_Pos < area_neg: return srfcInset_Pos else: return srfcInset_Neg
def buildZoneBrep(_zoneObjs, _opaqueSurfaces): # Takes in the IDF Surfaces and builds Zone Breps from them # Sets the ZoneObj as an attr using the new Brep zoneBreps = [] for zone in _zoneObjs: zoneSurfaces = [] for srfc in _opaqueSurfaces: if srfc.HostZoneName == zone.ZoneName: zoneSurfaces.append(ghc.BoundarySurfaces(srfc.Boundary)) zoneBrep = ghc.BrepJoin(zoneSurfaces).breps zoneBreps.append(zoneBrep) setattr(zone, 'ZoneBrep', zoneBrep) return zoneBreps
def getWindowBasics(_in): with idf2ph_rhDoc(): # Get the Window Geometry geom = rs.coercegeometry(_in) windowSurface = ghc.BoundarySurfaces(geom) # Inset the window just slightly. If any windows touch one another or the zone edges # will failt to create a proper closed Brep. So shink them ever so slightly. Hopefully # not enough to affect the results. windowPerim = ghc.JoinCurves(ghc.DeconstructBrep(windowSurface).edges, preserve=False) try: windowPerim = ghc.OffsetonSrf( windowPerim, 0.004, windowSurface) # 0.4mm so hopefully rounds down except: windowPerim = ghc.OffsetonSrf(windowPerim, -0.004, windowSurface) windowSurface = ghc.BoundarySurfaces(windowPerim) # Pull in the Object Name from Rhino Scene windowName = None try: windowName = rs.ObjectName(_in) except: warning = "Can't get the Window name from Rhino for some reason?\n"\ "If you are passing in Rhino Geometry, double check you have named all the surfaces?\n"\ "If you are passing in Grasshopper geometry though, ignore this message." ghenv.Component.AddRuntimeMessage( ghK.GH_RuntimeMessageLevel.Remark, warning) windowName = windowName if windowName != None else 'Unnamed_Window' windowName = cleanUpName(windowName) # Double check that the surface Normal didn't get flipped c1 = ghc.Area(geom).centroid n1 = rs.SurfaceNormal(geom, c1) c2 = ghc.Area(windowSurface).centroid n2 = rs.SurfaceNormal(windowSurface, c2) normAngleDifference = ghc.Degrees(ghc.Angle(n1, n2).angle) if round(normAngleDifference, 0) != 0: # Flip the surface if it doesn't match the source windowSurface = ghc.Flip(windowSurface).surface return windowName, windowSurface
def get_footprint(_surfaces): # Finds the 'footprint' of the building for 'Primary Energy Renewable' reference # 1) Re-build the Opaque Surfaces # 2) Join all the surface Breps into a single brep # 3) Find the 'box' for the single joined brep # 4) Find the lowest Z points on the box, offset another 10 units 'down' # 5) Make a new Plane at this new location # 6) Projects the brep edges onto the new Plane # 7) Split a surface using the edges, combine back into a single surface Footprint = namedtuple('Footprint', ['Footprint_surface', 'Footprint_area']) #----- Build brep surfaces = (from_face3d(surface.Srfc) for surface in _surfaces) bldg_mass = ghc.BrepJoin(surfaces).breps bldg_mass = ghc.BoundaryVolume(bldg_mass) if not bldg_mass: return Footprint(None, None) #------- Find Corners, Find 'bottom' (lowest Z) bldg_mass_corners = [v for v in ghc.BoxCorners(bldg_mass)] bldg_mass_corners.sort(reverse=False, key=lambda point3D: point3D.Z) rect_pts = bldg_mass_corners[0:3] #------- Projection Plane projection_plane1 = ghc.Plane3Pt(rect_pts[0], rect_pts[1], rect_pts[2]) projection_plane2 = ghc.Move(projection_plane1, ghc.UnitZ(-10)).geometry matrix = rs.XformPlanarProjection(projection_plane2) #------- Project Edges onto Projection Plane projected_edges = [] for edge in ghc.DeconstructBrep(bldg_mass).edges: projected_edges.append(ghc.Transform(edge, matrix)) #------- Split the projection surface using the curves l1 = ghc.Line(rect_pts[0], rect_pts[1]) l2 = ghc.Line(rect_pts[0], rect_pts[2]) max_length = max(ghc.Length(l1), ghc.Length(l2)) projection_surface = ghc.Polygon(projection_plane2, max_length * 100, 4, 0).polygon projected_surfaces = ghc.SurfaceSplit(projection_surface, projected_edges) #------- Remove the biggest surface from the set(the background srfc) projected_surfaces.sort(key=lambda x: x.GetArea()) projected_surfaces.pop(-1) #------- Join the new srfcs back together into a single one unioned_NURB = ghc.RegionUnion(projected_surfaces) unioned_surface = ghc.BoundarySurfaces(unioned_NURB) return Footprint(unioned_surface, unioned_surface.GetArea())
def calcFootprint(_zoneObjs, _opaqueSurfaces): # Finds the 'footprint' of the building for 'Primary Energy Renewable' reference # 1) Re-build the zone Breps # 2) Join all the zone Breps into a single brep # 3) Find the 'box' for the single joined brep # 4) Find the lowest Z points on the box, offset another 10 units 'down' # 5) Make a new Plane at this new location # 6) Projects the brep onto the new Plane #----- zoneBreps = [] for zone in _zoneObjs: zoneSurfaces = [] for srfc in _opaqueSurfaces: if srfc.HostZoneName == zone.ZoneName: zoneSurfaces.append(ghc.BoundarySurfaces(srfc.Boundary)) zoneBrep = ghc.BrepJoin(zoneSurfaces).breps zoneBreps.append(zoneBrep) bldg_mass = ghc.SolidUnion(zoneBreps) if bldg_mass == None: return None #------- Find Corners, Find 'bottom' (lowest Z) bldg_mass_corners = [v for v in ghc.BoxCorners(bldg_mass)] bldg_mass_corners.sort(reverse=False, key=lambda point3D: point3D.Z) rect_pts = bldg_mass_corners[0:3] #------- Project Brep to Footprint projection_plane1 = ghc.Plane3Pt(rect_pts[0], rect_pts[1], rect_pts[2]) projection_plane2 = ghc.Move(projection_plane1, ghc.UnitZ(-10)).geometry matrix = rs.XformPlanarProjection(projection_plane2) footprint_srfc = rs.TransformObjects(bldg_mass, matrix, copy=True) footprint_area = rs.Area(footprint_srfc) #------- Output Footprint = namedtuple('Footprint', ['Footprint_surface', 'Footprint_area']) fp = Footprint(footprint_srfc, footprint_area) return fp
def inset_rhino_surface(_srfc, _inset_dist=0.001, _srfc_name=""): """ Insets/shrinks a Rhino Brep some dimension Arg: _srfc: A Rhino Brep _inset_dist: float: Default=0.001m _srfc_name: str: The name of the surface, used for error messages Returns: new_srfc: A new Rhino surface, shrunk/inset by the specified amount """ #----------------------------------------------------------------------- # Get all the surface params needed srfc_Center = ghc.Area(_srfc).centroid srfc_normal_vector = brep_avg_surface_normal(_srfc) srfc_edges = ghc.DeconstructBrep(_srfc).edges srfc_perimeter = ghc.JoinCurves(srfc_edges, False) #----------------------------------------------------------------------- # Try to inset the perimeter Curve inset_curve = rs.OffsetCurve(srfc_perimeter, srfc_Center, _inset_dist, srfc_normal_vector, 0) #----------------------------------------------------------------------- # In case the new curve goes 'out' and the offset fails # Or is too small and results in multiple offset Curves if len(inset_curve)>1: warning = 'Error. The surface: "{}" is too small. The offset of {} m"\ "can not be done. Check the offset size?'.format(_srfc_name, _inset_dist) print(warning) inset_curve = rs.OffsetCurve(srfc_perimeter, srfc_Center, 0.001, srfc_normal_vector, 0) inset_curve = rs.coercecurve( inset_curve[0] ) else: inset_curve = rs.coercecurve( inset_curve[0] ) new_srfc = ghc.BoundarySurfaces(inset_curve) return new_srfc
for xx in range(1, int(nsquaresA) + 2): noise = perlin_noise([(xx / (speed / (2 * octave))), (yy / (speed / (2 * octave)))]) indx = int(((yy - 1) * (nsquaresA + 1)) + xx - 1) zvals[indx] += noise * (amplitude / (2 * octave)) pointsMoved = [ rg.Point3d(pnt.X, pnt.Y, pnt.Z + noise) for pnt, noise in zip(pointGrid, zvals) ] bottom = rg.PolylineCurve( rg.Point3d( outline.Point(indx).X, outline.Point(indx).Y, crvMinHeight - minThickness - abs(min(zvals))) for indx in range(0, outline.PointCount)) bottomSurface = ghc.BoundarySurfaces(bottom) bottomExtruded = ghc.Extrude( bottomSurface, rg.Vector3d(0, 0, minThickness + (abs(max(zvals)) + abs(min(zvals))) * 2)) #*2 just to be safe top = ghc.SurfaceFromPoints(pointsMoved, nsquaresA + 1, True) _terrain = ghc.SolidIntersection(top, bottomExtruded) terrain = ghc.Mirror(_terrain, rg.Plane.WorldYZ)[0] #to mimic AC and RVT orientation topography = rg.Brep.CreateContourCurves( terrain, rg.Point3d(0, 0, crvMinHeight - abs(min(zvals))), rg.Point3d(0, 0, crvMinHeight + abs(max(zvals))), topographyInterval)
for pt in crvPts: x = ghc.RemapNumbers(pt.X, domainX, domain)[0] y = ghc.RemapNumbers(pt.Y, domainY, domain)[0] surfPts.Add(Surface.PointAt(x, y), path) # 4) Creating the panels surcCrvs = DataTree[rg.Curve]() survPanels = DataTree[rg.Brep]() for i in range(surfPts.BranchCount): path = GH_Path(i) branch = surfPts.Branch(i) flatCrv = [] if branch.Count > 3: # let the GH do the work for us plane = ghc.PlaneFit(branch)[0] for i in range(0, branch.Count): pt = plane.ClosestPoint(branch[i]) flatCrv.append(pt) else: flatCrv = branch closedCrv = ghc.PolyLine(flatCrv, True) surcCrvs.Add(closedCrv, path) Panel = ghc.BoundarySurfaces(closedCrv) survPanels.Add(Panel, path) # ----------------------------------------------------------- # Output _ptsOnSrf = surfPts _polyCrv = surcCrvs _panels = survPanels
def fractal(depth, x1, y1, z1, x2, y2, z2, length, anglerec, angle, lvariation, aran, lran, anglerech, angleh, branches, verticality, gchance, depthstart, radtolen, radchng, mngon, polygon, branch_cluster): #test if depth>0 if depth: #defining random angle variation and length variation arn = random.uniform(-angle / 100 * aran, angle / 100 * aran) lrn = random.uniform(-length / 100 * lran, length / 100 * lran) if hrandom == True: #defining horizontal rotation angles ahor = random.sample(range(0, 360), branches) #removing numbers within tolerance ahr = rs.CullDuplicateNumbers(ahor, angleh) #in a 360 fashion if ahr[0] + 360 - angleh < ahr[-1]: del ahr[0] else: #generating evenly distributed angles ahr = range(0, 360 + 1, 360 // branches)[:-1] #previous branch vector vecst = rg.Point3d(x1, y1, z1) vecend = rg.Point3d(x2, y2, z2) movevec = ghc.Vector2Pt(vecst, vecend, True)[0] #returns vector and it's length #perpendicular vector rotplane3 = ghc.PlaneNormal( vecend, movevec) #creates plane perpendicular to vector plns = ghc.DeconstructPlane(rotplane3) #origin, x, y, z rotplane = ghc.ConstructPlane( plns[2], plns[1], plns[3] ) #constructing new plane switching x and y planes to make perpendicular #generating perpendicular vector vecperp = ghc.Rotate(movevec, radians(90), rotplane)[0] #generating vector amplitudes leny = (length + lrn) * sin( radians((anglerec + arn) * (1 - (verticality**depth)))) lenz = (length + lrn) * cos(radians(anglerec + arn)) ampy = ghc.Amplitude(vecperp, leny) ampz = ghc.Amplitude(movevec, lenz) #changing branch length dependant on branch depth length = length * lvariation #building points endpoint1 = ghc.Move( vecend, ampz)[0] #returns moved object and transformation data endpoint = ghc.Move( endpoint1, ampy)[0] #returns moved object and transformation data #rotating point in a cone fashion rotpoint = ghc.Rotate3D( endpoint, radians(anglerech), vecend, movevec)[0] #returns rotated geometry and transformation data #building line between points linegeo = rg.Line(vecend, rotpoint) #defining recursion depth key = depthstart + 1 - depth #building geometry pln = ghc.PlaneNormal(rotpoint, linegeo) #returns a plane perp to a vector radius = length * (radchng**(key)) / radtolen #reduce details with each branch, but not less than 3 splits = 3 if mngon - key + 1 <= 3 else mngon - key + 1 polygonend = ghc.Polygon(pln, radius, splits, 0)[0] #returns a polygon and its perimeter #aligning curves for loft creation crvst = ghc.EndPoints(polygon)[0] pntcld = ghc.Discontinuity(polygonend, 1) #returns points and point parameters #finind seam point closest_point = ghc.ClosestPoint( crvst, pntcld[0] ) #returns closest point, closest point index, distance between closest points seampnt = pntcld[1][closest_point[1]] polygonend = ghc.Seam(polygonend, seampnt) lcurves = [polygon, polygonend] #building geometry geo = ghc.ExtrudePoint( polygon, rotpoint ) if depth == 1 and splits == 3 else rg.Brep.CreateFromLoft( lcurves, rg.Point3d.Unset, rg.Point3d.Unset, rg.LoftType.Normal, False)[0] #if last branch than make a pyramid #make solid geocapped = ghc.CapHoles(geo) #building a dict of geo with depth as key, and geo as values pgons.update( {branch_cluster: [geocapped]}) if branch_cluster not in pgons.keys( ) else pgons[branch_cluster].append(geocapped) branchesout.append(geocapped) #setting coords for next branch x1 = x2 y1 = y2 z1 = z2 #getting xyz from rotated point x2 = rg.Point3d(rotpoint)[0] y2 = rg.Point3d(rotpoint)[1] z2 = rg.Point3d(rotpoint)[2] #setting base polygon for next branch polygon = polygonend #filling dict with branch clusters cluster.append(cluster[-1] + 1) branch_cluster = cluster[-1] #calling function with different angle parameter for branch splitting, calling as many branches as spread within tolerance if depth != 1: for aa in ahr: if ( (random.randint(40, 99) / 100)**depth ) < gchance or depth == depthstart + 1: #or added to prevent blank trees fractal(depth - 1, x1, y1, z1, x2, y2, z2, length, angle, angle, lvariation, aran, lran, aa, angleh, branches, verticality, gchance, depthstart, radtolen, radchng, mngon, polygon, branch_cluster) #leaf logic if depth <= leavesdepth and leavesperbranch > 0 and maxleaves > 0: #vector for leaf growth spread leafpntvec = ghc.Vector2Pt(vecend, rotpoint, True)[0] #setting leaf growth position on last barnch, leafpnt list lastbranchlength = ghc.Length(linegeo) leaves_list = [lastbranchlength] [ leaves_list.append(lengthparam) for lengthparam in random.sample( range(0, int(lastbranchlength)), leavesperbranch - 1) ] if leavesperbranch > 1 else None for leafpnt in leaves_list: leafamp = ghc.Amplitude(leafpntvec, leafpnt) leafpoint = ghc.Move(vecend, leafamp)[0] #plane for leaf generation linetocenter = ghc.Line(stpntbase, leafpoint) planetocenter = ghc.PlaneNormal(leafpoint, linetocenter) #create an imaginary circle with leaflen radius and populate it with points for random leaf generation leafgenerationcircle = ghc.CircleCNR(leafpoint, linetocenter, leaflen) circlesurf = ghc.BoundarySurfaces(leafgenerationcircle) leafcnt = random.randint(0, maxleaves) if leafcnt > 0: leafendpnts = ghc.PopulateGeometry(circlesurf, leafcnt, random.randint(1, 500)) def leafgenerator(point): #random z move zmove = rg.Vector3d(0, 0, 1) moveamp = random.uniform(-leaflen / 3, leaflen / 5) ampzmove = ghc.Amplitude(zmove, moveamp) llendpnt = ghc.Move(point, ampzmove)[0] #setting a leaf centerline vector leafvector = ghc.Vector2Pt(leafpoint, llendpnt, True)[0] #defining leaf center point as avarage of st and end pnts midpnt = ghc.Average([leafpoint, llendpnt]) #generating perpendicular vector vecperpleaf = ghc.Rotate(leafvector, radians(90), planetocenter)[0] leafperpamp = ghc.Amplitude( vecperpleaf, random.uniform((leafwidth / 2) / 5 * 4, (leafwidth / 2) / 5 * 6)) #moving mid point to both sides midpnt1 = ghc.Move(midpnt, leafperpamp)[0] midpnt2 = ghc.Move(midpnt, -leafperpamp)[0] #leaf geo leafgeo = rg.NurbsSurface.CreateFromCorners( leafpoint, midpnt1, llendpnt, midpnt2) leaves.append(leafgeo) #iterate over random number of generated points if list, else generate for one point [leafgenerator(pp) for pp in leafendpnts] if isinstance( leafendpnts, list) else leafgenerator(leafendpnts)