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 finalSurfStuff(cullPts, delaunayHeight, offsetFactor, shadeSurface): worldPlane = rc.Geometry.Plane.WorldXY if shadeSurface == None: # In case no shading surface was provided #$print 'None' planeFromPoints = rc.Geometry.Plane.FitPlaneToPoints(cullPts) else: # In case shading surface was provided #$print 'WITH' points_surface = ghc.SurfacePoints(shadeSurface).points planeFromPoints = rc.Geometry.Plane.FitPlaneToPoints( points_surface) ## #planeFromPoints = rc.Geometry.Plane.FitPlaneToPoints(points_surface)[1]## if planeFromPoints: wp = worldPlane.Normal if shadeSurface == None: # In case no shading surface was provided myPlane = planeFromPoints[1] # extract plane from FitPlaneToPoints else: # In case shading surface was provided myPlane = planeFromPoints[ 1] # extract plane from FitPlaneToPoints###########################################???????????????????????? ##myPlane = planeFromPoints # extract plane from FitPlaneToPoints #print type(myPlane), planeFromPoints pfp = rc.Geometry.Plane.Normal.GetValue(myPlane) vectorAngle = rc.Geometry.Vector3d.VectorAngle(pfp, wp) tolAngle = 70 # Tolerance angle. Right now I set it to 70 but this should be followed up if ((vectorAngle >= tolAngle) and (vectorAngle <= 90)) or (vectorAngle >= tolAngle and (vectorAngle < (90 + (90 - tolAngle)))): flag = 0 #0 is for VERTICAL shading surface elif (vectorAngle < tolAngle) or (vectorAngle > (90 + (90 - tolAngle))): flag = 1 #1 is for NON VERTICAL shading surface if flag == 0: worldZXPlane = rc.Geometry.Plane.WorldZX worldYZPlane = rc.Geometry.Plane.WorldYZ wp_ZX = worldZXPlane.Normal * -(1) wp_YZ = worldYZPlane.Normal * -(1) vectorAngle_ZX = rc.Geometry.Vector3d.VectorAngle(pfp, wp_ZX) vectorAngle_YZ = rc.Geometry.Vector3d.VectorAngle(pfp, wp_YZ) if vectorAngle_ZX <= 45 or vectorAngle_ZX >= 135 and worldYZPlane <= 225: basePlane = worldZXPlane convexHullPlane = cutPlane = rc.Geometry.Plane.WorldZX convexHullPlane = rc.Geometry.Plane.Translate( convexHullPlane, worldZXPlane.Normal * -delaunayHeight) convex_Trim_Plane = convexHullPlane cutPlane = rc.Geometry.Plane.Translate( cutPlane, worldZXPlane.Normal * -(delaunayHeight - .01)) directionPlane = cutPlane else: basePlane = worldYZPlane G, X = ghc.MoveToPlane(cullPts, convexHullPlane, True, True) delaunayPoints1 = G flatPts = [rc.Geometry.Point3d(p) for p in delaunayPoints1] elif flag == 1: convex_Trim_Plane = rc.Geometry.Plane.WorldXY # Connect to ConvexHull and MeshPlaneSec convexHullPlane = convex_Trim_Plane p1 = rc.Geometry.Point3d(0, 0, delaunayHeight - 0.01) v1 = rc.Geometry.Vector3d(1, 0, 0) v2 = rc.Geometry.Vector3d(0, 1, 0) directionPlane = rc.Geometry.Plane( p1, v1, v2) # Connect to Direction input of Project direction = rc.Geometry.Vector3d.Add(rc.Geometry.Vector3d( 0, 0, 0), rc.Geometry.Vector3d( 0, 0, delaunayHeight)) # Connect to Direction input of Project #Using RS the direction is 0,0,5. Using RC direction is 0,0,-5. Be aware of this, maybe we need to multiply by (-1) flatPts = [rc.Geometry.Point3d(p) for p in cullPts] for i in range( len(cullPts) ): # Flat Z axis point to some height for the DelaunayMesh action flatPts[i][2] = delaunayHeight trimPlanePoint = rc.Geometry.Point3d(0, 0, delaunayHeight - 0.01) ################### spans = 20 flexibility = 1 points_CULL = [rc.Geometry.Point(pt) for pt in cullPts] patch = ghc.Patch(None, cullPts, spans, flexibility, True) if flag == 0: H, Hz, I = ghc.ConvexHull( cullPts, rc.Geometry.Plane.WorldZX ) # CHECK THIS LATER FOR OTHER CASES or UNIFY WITH FLAG 1 elif flag == 1: H, Hz, I = ghc.ConvexHull(cullPts, convexHullPlane) points_PV = [] count = H.PointCount for i in range(count): points_PV.append(H.Point(i)) H_alt = rc.Geometry.PolylineCurve(points_PV) areaH = rc.Geometry.AreaMassProperties.Compute(H).Area centH_alt = rc.Geometry.AreaMassProperties.Compute(H).Centroid scaleH = rc.Geometry.Transform.Scale(centH_alt, offsetFactor) dupH_alt = rc.Geometry.PolylineCurve.Duplicate(H_alt) dupH_alt.Transform(scaleH) offsetCrv = [dupH_alt] areaHalt = rc.Geometry.AreaMassProperties.Compute(H_alt).Area areaoffsetCrv = rc.Geometry.AreaMassProperties.Compute(offsetCrv[0]).Area if (areaHalt > areaoffsetCrv): print "Case BAD offset" scaleH = rc.Geometry.Transform.Scale(centH_alt, offsetFactor * (-1)) dupH_alt = rc.Geometry.PolylineCurve.Duplicate(H_alt) dupH_alt.Transform(scaleH) offsetCrv = [dupH_alt] delaunayPoints = [] for i in range( len(cullPts) ): # Flat Z axis point to some height for the DelaunayMesh action delaunayPoints.append(flatPts[i]) res = 40 divCrv = offsetCrv[0].DivideByCount(res, True) for p in divCrv: delaunayPoints.append(offsetCrv[0].PointAt(p)) delaunayMesh = ghc.DelaunayMesh(delaunayPoints, convex_Trim_Plane) M = delaunayMesh trimCurve = ghc.MeshXPlane(delaunayMesh, directionPlane) projectedCrv = ghc.Project(trimCurve, patch, directionPlane) splitSrf = ghc.SurfaceSplit(patch, projectedCrv) H1, Hz1, I1 = ghc.ConvexHull(cullPts, myPlane) #planeFromPoints cen = rc.Geometry.AreaMassProperties.Compute(H1).Centroid centerH = rc.Geometry.Point3d(cen) #print centerH distances = [] for srf in splitSrf: cent = rc.Geometry.AreaMassProperties.Compute(srf).Centroid distance = centerH.DistanceTo(cent) distances.append(distance) #print ' Min distance for split surface ', min(distances), distances finalSrf = splitSrf[distances.index(min(distances))] """ # Below the original way to solve the issue ## if shadeSurface: H1, Hz1, I1 = ghc.ConvexHull(cullPts, planeFromPoints) cen = rc.Geometry.AreaMassProperties.Compute(H1).Centroid centerH = rc.Geometry.Point3d(cen) #print centerH uv = rc.Geometry.Surface.ClosestPoint(shadeSurface, centerH) point = rc.Geometry.Surface.Evaluate(shadeSurface, uv[0], uv[1], 10) s0 = splitSrf[0] s1 = splitSrf[1] swapFinalSrf = False if swapFinalSrf ==False: finalSrf = splitSrf[1] else: finalSrf = splitSrf[0] """ return finalSrf