예제 #1
0
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