def _get_plane_aligned_to_surface(_surface): """Finds an Aligned Plane for Surface input Note, will try and correct to make sure the aligned plane's Y-Axis aligns to the surface and goes 'up' (world Z) if it can. Arguments: _surface: The Rhino surface to align with Returns: srfcPlane: A single Plane object, aligned to the surface """ # Get the UV info for the surface srfcPlane = rs.SurfaceFrame(_surface, [0.5, 0.5]) centroid = ghc.Area(_surface).centroid uVector = srfcPlane.XAxis vVector = srfcPlane.YAxis # Create a Plane aligned to the UV of the srfc lineU = ghc.LineSDL(centroid, uVector, 1) lineV = ghc.LineSDL(centroid, vVector, 1) srfcPlane = ghc.Line_Line(lineU, lineV) # Try and make sure its pointing the right directions if abs(round(srfcPlane.XAxis.Z, 2)) != 0: srfcPlane = ghc.RotatePlane(srfcPlane, ghc.Radians(90)) if round(srfcPlane.YAxis.Z, 2) < 0: srfcPlane = ghc.RotatePlane(srfcPlane, ghc.Radians(180)) return srfcPlane
def nextPt(pt, surface, DistanceFactor): boolean, u, v = Surface.ClosestPoint(pt) norm = Surface.NormalAt(u, v) unitNormLine = gh.LineSDL(pt, norm, DistanceFactor) ptToProject = gh.EndPoints(unitNormLine) ProjectedPt = gh.ProjectPoint(ptToProject, -gh.UnitZ(), Surface)[0] return ProjectedPt
def rhino_vector2d_from_angle(_angle=0): """ Get a Rhino Vector2d from a numeric angle Arguments: _angle (float): Angle in degrees. Note, this should be a positive value representing the degree of rotation (about the Z axis) from Y. North 0=0 West=90, South=180, East=270 """ if not _angle: return None # Use the Grasshopper rotate to create the new vector # according to the numeric angle origin = Rhino.Geometry.Point3d(0, 0, 0) north_axis = Rhino.Geometry.Vector3d(0, 1, 0) angle = ghc.Radians(_angle) rotation_axis_vec = Rhino.Geometry.Vector3d(0, 0, 1) rotation_axis_line = ghc.LineSDL(origin, rotation_axis_vec, 1) north_vec = ghc.RotateAxis(north_axis, angle, rotation_axis_line).geometry return north_vec
def find_reveal_shading(_phpp_window_obj, _shadingGeom, _extents=99): WinCenter = ghc.Area(_phpp_window_obj.glazing_surface).centroid edges = _phpp_window_obj._get_edges_in_order( _phpp_window_obj.glazing_surface ) surface_normal = _phpp_window_obj.surface_normal #Create the Intersection Surface for each side Side1_OriginPt = ghc.CurveMiddle( from_linesegment3d(edges.Left) ) Side1_NormalLine = ghc.LineSDL(Side1_OriginPt, surface_normal, _extents) Side1_Direction = ghc.Vector2Pt(WinCenter, Side1_OriginPt, False).vector Side1_HorizLine = ghc.LineSDL(Side1_OriginPt, Side1_Direction, _extents) Side1_IntersectionSurface = ghc.SumSurface(Side1_NormalLine, Side1_HorizLine) #Side2_OriginPt = SideMidPoints[1] #ghc.CurveMiddle(self.Edge_Left) Side2_OriginPt = ghc.CurveMiddle( from_linesegment3d(edges.Right) ) Side2_NormalLine = ghc.LineSDL(Side2_OriginPt, surface_normal, _extents) Side2_Direction = ghc.Vector2Pt(WinCenter, Side2_OriginPt, False).vector Side2_HorizLine = ghc.LineSDL(Side2_OriginPt, Side2_Direction, _extents) Side2_IntersectionSurface = ghc.SumSurface(Side2_NormalLine, Side2_HorizLine) #Find any Shader Objects and put them all into a list Side1_RevealShaderObjs = [] testStartPt = ghc.Move(WinCenter, ghc.Amplitude(surface_normal, 0.1)).geometry #Offsets the test line just a bit Side1_TesterLine = ghc.LineSDL(testStartPt, Side1_Direction, _extents) #extend a line off to side 1 for i in range(len(_shadingGeom)): if ghc.BrepXCurve(_shadingGeom[i],Side1_TesterLine).points != None: Side1_RevealShaderObjs.append(_shadingGeom[i]) Side2_RevealShaderObjs = [] Side2_TesterLine = ghc.LineSDL(testStartPt, Side2_Direction, _extents) #extend a line off to side 2 for i in range(len(_shadingGeom)): if ghc.BrepXCurve(_shadingGeom[i],Side2_TesterLine).points != None: Side2_RevealShaderObjs.append(_shadingGeom[i]) #--------------------------------------------------------------------------- # Calc Shading reveal dims NumShadedSides = 0 if len(Side1_RevealShaderObjs) != 0: Side1_o_reveal = CalcRevealDims(_phpp_window_obj, Side1_RevealShaderObjs, Side1_IntersectionSurface, Side1_OriginPt, Side1_Direction)[0] Side1_d_reveal = CalcRevealDims(_phpp_window_obj, Side1_RevealShaderObjs, Side1_IntersectionSurface, Side1_OriginPt, Side1_Direction)[1] Side1_CheckLine = CalcRevealDims(_phpp_window_obj, Side1_RevealShaderObjs, Side1_IntersectionSurface, Side1_OriginPt, Side1_Direction)[2] NumShadedSides = NumShadedSides + 1 else: Side1_o_reveal = None Side1_d_reveal = None Side1_CheckLine = Side1_HorizLine if len(Side2_RevealShaderObjs) != 0: Side2_o_reveal = CalcRevealDims(_phpp_window_obj, Side2_RevealShaderObjs, Side2_IntersectionSurface, Side2_OriginPt, Side2_Direction)[0] Side2_d_reveal = CalcRevealDims(_phpp_window_obj, Side2_RevealShaderObjs, Side2_IntersectionSurface, Side2_OriginPt, Side2_Direction)[1] Side2_CheckLine = CalcRevealDims(_phpp_window_obj, Side2_RevealShaderObjs, Side2_IntersectionSurface, Side2_OriginPt, Side2_Direction)[2] NumShadedSides = NumShadedSides + 1 else: Side2_o_reveal = None Side2_d_reveal = None Side2_CheckLine = Side2_HorizLine # # # # TODO: how to handel asymetrical reveals???? o_reveal = Side1_o_reveal#(Side1_o_reveal + Side2_o_reveal )/ max(1,NumShadedSides) d_reveal = Side1_d_reveal#(Side1_d_reveal + Side2_d_reveal )/ max(1,NumShadedSides) # # # # # return o_reveal, d_reveal, Side1_CheckLine, Side2_CheckLine
def find_overhang_shading(_phpp_window_obj, _shadingGeom, _extents=99): # Figure out the glass surface (inset a bit) and then # find the origin point for all the subsequent shading calcs (top, middle) glzgCenter = ghc.Area(_phpp_window_obj.glazing_surface).centroid glazingEdges = _phpp_window_obj._get_edges_in_order( _phpp_window_obj.glazing_surface ) glazingTopEdge = from_linesegment3d(glazingEdges.Top) ShadingOrigin = ghc.CurveMiddle(glazingTopEdge) # In order to also work for windows which are not vertical, find the # 'direction' from the glazing origin and the top/middle ege point UpVector = ghc.Vector2Pt(glzgCenter, ShadingOrigin, True).vector #----------------------------------------------------------------------- # First, need to filter the scene to find the objects that are 'above' # the window. Create a 'test plane' that is _extents (99m) tall and 0.5m past the wall surface, test if # any objects intersect that plane. If so, add them to the set of things # test in the next step depth = float(_phpp_window_obj.install_depth) + 0.5 edge1 = ghc.LineSDL(ShadingOrigin, UpVector, _extents) edge2 = ghc.LineSDL(ShadingOrigin, _phpp_window_obj.surface_normal, depth) intersectionTestPlane = ghc.SumSurface(edge1, edge2) OverhangShadingObjs = (x for x in _shadingGeom if ghc.BrepXBrep(intersectionTestPlane, x).curves != None) #----------------------------------------------------------------------- # Using the filtered set of shading objects, find the 'edges' of shading # geom and then decide where the maximums shading point is # Create a new 'test' plane coming off the origin (99m in both directions this time). # Test to find any intersection shading objs and all their crvs/points with this plane HorizontalLine = ghc.LineSDL(ShadingOrigin, _phpp_window_obj.surface_normal, _extents) VerticalLine = ghc.LineSDL(ShadingOrigin, UpVector, _extents) IntersectionSurface = ghc.SumSurface(HorizontalLine, VerticalLine) IntersectionCurves = (ghc.BrepXBrep(obj, IntersectionSurface).curves for obj in OverhangShadingObjs if ghc.BrepXBrep(obj, IntersectionSurface).curves != None) IntersectionPointsList = (ghc.ControlPoints(crv).points for crv in IntersectionCurves) IntersectionPoints = (pt for list_of_pts in IntersectionPointsList for pt in list_of_pts) #----------------------------------------------------------------------- # If there are any intersection Points found, choose the right one to use to calc shading.... # Find the top/closets point for each of the objects that could possibly shade smallest_angle_found = 2 * math.pi key_point = None for pt in IntersectionPoints: if pt == None: continue # Protect against Zero-Length error ray = ghc.Vector2Pt(ShadingOrigin, pt, False).vector if ray.Length < 0.001: continue this_ray_angle = ghc.Angle(_phpp_window_obj.surface_normal , ray).angle if this_ray_angle < 0.001: continue if this_ray_angle <= smallest_angle_found: smallest_angle_found = this_ray_angle key_point = pt #----------------------------------------------------------------------- # Use the 'key point' found to deliver the Height and Distance for the PHPP Shading Calculator if not key_point: d_over = None o_over = None CheckLine = VerticalLine else: d_over = key_point.Z - ShadingOrigin.Z # Vertical distance Hypot = ghc.Length(ghc.Line(ShadingOrigin, key_point)) # Hypot o_over = math.sqrt(Hypot**2 - d_over**2) # Horizontal distance CheckLine = ghc.Line(ShadingOrigin, key_point) return d_over, o_over, CheckLine
def find_horizon_shading(_phpp_window_obj, _shadingGeom, _extents=99): """ Arguments: _phpp_winddow_obj: The PHPP_Window object to calcualte the values for _shadingGeom: (list) A list of possible shading objects to test against _extents: (float) A number (m) to limit the shading search to. Default = 99m Returns: h_hori: Distance (m) out from the glazing surface of any horizontal shading objects found d_hori: Distance (m) up from the base of the window to the top of any horizontal shading objects found """ surface_normal = _phpp_window_obj.surface_normal #----------------------------------------------------------------------- # Find Starting Point glazingEdges = _phpp_window_obj._get_edges_in_order( _phpp_window_obj.glazing_surface ) glazingBottomEdge = glazingEdges.Bottom ShadingOrigin = ghc.CurveMiddle( from_linesegment3d(glazingBottomEdge) ) UpVector = ghc.VectorXYZ(0,0,1).vector #----------------------------------------------------------------------- # Find if there are any shading objects and if so put them in a list HorizonShading = [] HorizontalLine = ghc.LineSDL(ShadingOrigin, surface_normal, _extents) VerticalLine = ghc.LineSDL(ShadingOrigin, UpVector, _extents) for shadingObj in _shadingGeom: if ghc.BrepXCurve(shadingObj, HorizontalLine).points != None: HorizonShading.append( shadingObj ) #----------------------------------------------------------------------- # Find any intersection Curves with the shading objects IntersectionSurface = ghc.SumSurface(HorizontalLine, VerticalLine) IntersectionCurve = [] IntersectionPoints = [] for shadingObj in HorizonShading: if ghc.BrepXBrep(shadingObj, IntersectionSurface).curves != None: IntersectionCurve.append(ghc.BrepXBrep(shadingObj, IntersectionSurface)) for pnt in IntersectionCurve: IntersectionPoints.append(ghc.ControlPoints(pnt).points) #----------------------------------------------------------------------- # Run the "Top-Corner-Finder" if there are any intersecting objects... if len(IntersectionPoints) != 0: # Find the top/closets point for each of the objects that could possibly shade KeyPoints = [] for pnt in IntersectionPoints: Rays = [] Angles = [] if pnt: for k in range(len(pnt)): Rays.append(ghc.Vector2Pt(ShadingOrigin,pnt[k], False).vector) Angles.append(ghc.Angle(surface_normal , Rays[k]).angle) KeyPoints.append(pnt[Angles.index(max(Angles))]) # Find the relevant highest / closest point Rays = [] Angles = [] for i in range(len(KeyPoints)): Rays.append(ghc.Vector2Pt(surface_normal, KeyPoints[i], False).vector) Angles.append(ghc.Angle(surface_normal, Rays[i]).angle) KeyPoint = KeyPoints[Angles.index(max(Angles))] # Use the point it finds to deliver the Height and Distance for the PHPP Shading Calculator h_hori = KeyPoint.Z - ShadingOrigin.Z #Vertical distance Hypot = ghc.Length(ghc.Line(ShadingOrigin, KeyPoint)) d_hori = math.sqrt(Hypot**2 - h_hori**2) CheckLine = ghc.Line(ShadingOrigin, KeyPoint) else: h_hori = None d_hori = None CheckLine = HorizontalLine return h_hori, d_hori, CheckLine