Monday, August 24, 2009

Ecotect + Rhino

Here is an example of scripting between rhino and Ecotect.


import py2rhino as p2r
import py2ecotect as p2e
print p2r._version
import math

#===============================================================================
# Parameters
#===============================================================================
crv_centre = p2r.obj.NurbsCurve("54cd3b4b-40d0-4602-8774-75412d2e1c20")
crv_radius = p2r.obj.NurbsCurve("a822cc3e-67fb-4df3-b7bc-3c40080302a9")
floor_height = 5
facade_inset = 5
wall_panels = 5
#===============================================================================
# Functions
#===============================================================================
def mid_point(point_1, point_2):
vector = p2r.util.vector.create(point_2, point_1)
half_vector = p2r.util.vector.divide(vector, 2.0)
return p2r.util.vector.add(point_1, half_vector)


#===============================================================================
# Main script
#===============================================================================
#get the start and end point of the centre curve
crv_s = crv_centre.prop.start_pnt()
crv_e = crv_centre.prop.end_pnt()

#sub divide the curves
points_centre = crv_centre.func.contour_pnts((0,0,crv_s[2]), (0,0,crv_e[2]), floor_height)
points_radius = crv_radius.func.contour_pnts((0,0,crv_s[2]), (0,0,crv_e[2]), floor_height)

#draw circles and save them in the list
circles = []
for point_counter in range(len(points_centre)):

#get the points out of the list
centre_pnt = points_centre[point_counter]
radius_pnt = points_radius[point_counter]

#create the circle
cir = p2r.obj.Circle.create((centre_pnt), radius_pnt[0])
circles.append(cir)

#draw a surface for each floor
centre_points = []
panels = []
corners = []
for cir_num in range(len(circles) - 1):

#get this circle and the next circle
cir1 = circles[cir_num]
cir2 = circles[cir_num + 1]

#add the center point to the data list
centre_points.append( ( cir1.prop.center_pnt(), cir2.prop.center_pnt() ) )

#split the circles into points
points1 = list(cir1.func.divide_crv(wall_panels))
points2 = list(cir2.func.divide_crv(wall_panels))

#add one more to the end
points1.append(points1[0])
points2.append(points2[0])

#my lists for storing data
panel_data = []
corner_data = []

for wall_panel_counter in range(wall_panels):

#create the points of the vertical facade lines
line1_pt1 = points1[wall_panel_counter]
line1_pt2 = points2[wall_panel_counter]
line2_pt1 = points1[wall_panel_counter + 1]
line2_pt2 = points2[wall_panel_counter + 1]

#draw in ecotect
points = (line1_pt1, line1_pt2, line2_pt2, line2_pt1)
panel = p2e.obj.Wall.create(points)

#add panels to the data list
panel_data.append(panel)

#add corner points to the data list
corner_data.append( (line1_pt1, line1_pt2, line2_pt2, line2_pt1) )

#deal with the circular problem
panel_data.append(panel_data[0])
corner_data.append(corner_data[0])

panels.append(panel_data)
corners.append(corner_data)

"""
for i in corners:
print "next"
for j in i:
print "\t", j"""

raw_input("Continue:")


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# DO THE SIMULATION
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


#get the maximum and minimum insolation value
max_insolation = panels[0][0].prop.attr_1
min_insolation = panels[0][0].prop.attr_1
for floor in panels:
for panel in floor:
insolation = panel.prop.attr_1
if insolation > max_insolation:
max_insolation = insolation
if insolation < min_insolation:
min_insolation = insolation
insolation_range = max_insolation - min_insolation

#now create the rhino geometry
num_floors = len(centre_points)
for floor_num in range(num_floors):

#get centre points
cir1_center_pnt = centre_points[floor_num][0]
cir2_center_pnt = centre_points[floor_num][1]
center_pnt = mid_point(cir1_center_pnt, cir2_center_pnt)

p2r.obj.Sphere.create(center_pnt, 0.2)

facade_sections = []

#for each panel
for panel_num in range(wall_panels):

this_panel = panels[floor_num][panel_num]
next_panel = panels[floor_num][panel_num + 1]
this_corners = corners[floor_num][panel_num]

#get the two points between these panels
pnt2 = this_corners[2]
pnt1 = this_corners[3]
mid_pnt = mid_point(pnt1, pnt2)

#get the vector to move points
vec = p2r.util.vector.create(center_pnt, mid_pnt)
vec = p2r.util.vector.unitize(vec)

#get the vector scale factor based on insolation levels
insolation_1 = this_panel.prop.attr_1
insolation_2 = next_panel.prop.attr_1
av_insolation = (insolation_1 + insolation_2) /2.0
scale_factor = ((av_insolation - min_insolation) / insolation_range) * facade_inset

#scale the vector
vec = p2r.util.vector.scale(vec, scale_factor)

#move the mid point
moved_pnt = p2r.util.vector.add(mid_pnt, vec)

#create a section through the facade
pline= p2r.obj.Polyline.create((pnt1, moved_pnt, pnt2))
facade_sections.append(pline)

#join up all the facade sections with a loft
p2r.obj.NurbsSurface.create_by_loft(facade_sections, closed = True)

print "done"

No comments:

Post a Comment