Tuesday, September 15, 2009

Ecotect

I had a meeting today with Thida about the Ecotect results. Here is what we concluded - mostly through trial and error:

Ecotect is good for Sunpath diagrams, Insolation calculations (under Solar Access menu), and Solar Exposure, all on individual surfaces. Insolation calculations on grid points are OK, but they are different from surfaces.
  • For a surface, the radiation can only hit it from one side. In addition, the angle of incidence makes a difference - radiation at right angles to the surface has a bigger effect that radiation coming in at an acute angle.
  • For a grid, the point is idealized like a small ball. The radiation can come from all directions - so the values can be much higher. Also, the angle of incidence makes no difference.

For Lighting Analysis - light levels (lux) and daylight factors (%), Ecotect is quite inaccurate. Therefore, it is better to use Ecotect together with Radiance. Radiance can be downloaded and installed for free . You can do either grids or images.
  • For Ecotect/Radiance grids: You set up the model and the grid in Ecotect, and then use Ecotect to run the Radiance calc, and then import the results back into Ecotect to display the results.
  • For Ecotect/Radiance images: You set up the model and the camera in Ecotect, and then use Ecotect to run the Radiance calc. The image will be displayed in a special Ecotect window, where you can do various things, like false colour images etc.
So, first you need to install Radiance. This is straightforward -
  • Download the software
    http://floyd.lbl.gov/misc/download20B.html
  • Unzip it to a temporary location
  • Run setup.exe
  • Click 'Next' until you get to 'Setup type', choose 'Radiance for Windows'
  • When you get to 'Choose Radiance for Windows Installation Location', the default location is fine. Or you may want to put it on D if you do not have permission for C. However, make sure your path has no spaces.
  • Then click 'Next' all the way to the end.
  • If you get an error about a folder icon, ignore it.
To run and Ecotect/Radiance analysis:
  • Set up your model in Ecotect
  • Set up the grid in Ecotect
  • In the menu, go to Calculate > Lighting Analysis
  • Select Export to Radiance, and click Next
Here are the steps to follow from here on if you want to do a grid analysis:
  1. Choose 'Daylight Factors' (for example)
  2. Choose 'Surface and/or point analysis'
  3. Choose 'Analysis Grid' - and if you want you can also choose the 3D option
  4. Choose 'Interior Views'
  5. De-select 'Current 3d Editor view' and make sure that nothing else is selected
  6. For accuracy, 'Medium' is fine
  7. For the output and installation, first click the Fix button and find the file Rad.exe (in ...Radiance\bin\) - which is teh RAdiance program; the n tell Ecotect where to save the ARdiance files - choose a path with no spaces.
  8. Accept the advanced rendering settings as they are - click next
  9. Finally, you are ready to run radiance - click OK
A black command window will pop up, and some calculations will start. When the calculations are complete, Ecotect will pop up a RadianceImport dialog box - which is asking you if you want to import the results. So click 'Import'. In the Analysis Grid panel, under Data & Scale, you will see RAD Daylight Factors. This will display the results from the Radiance calculation.

Tuesday, September 8, 2009

Ecotect video

There is agreat talk on Ectoect by the software developer Ander Marsh. It is a very good introduction to Ecotect. It is one and a half hours long!

In order to view this talk, you need to create an account at the Autodesk University wesbite (http://au.autodesk.com/) - it is free. Note that this is not the same as the Student Community website (http://students.autodesk.com/)

Log into the AU website, and then view the talk called Practical Sustainable Design Workflows with Ecotect and Revit

Interactive console

Ctrl+Alt+Enter (while in the Eclipse/Pydev editor) can be used to open a console if there's no open console. A dialog box will pop up - select "Console for currently active editor".

Monday, September 7, 2009

Vertical paths

Here is another version of the previous post, but in this case, we get a set of paths where the next point is always higher than the previous point. This uses the sort function.

import py2rhino as p2r
import random as rnd
#===============================================================================
# Parameters
#===============================================================================
num_points = 100
#===============================================================================
# Functions
#===============================================================================
def get_z(point):
return point[2]
#===============================================================================
# Main Script
#===============================================================================
#create some random points
points = []
for i in range(num_points):
x = rnd.randint(-25, 25)
y = rnd.randint(-25, 25)
z = rnd.randint(0,200)
points.append((x,y,z))
p2r.obj.Sphere.create((x,y,z), 0.5)

#sort the points, based on the x vale
points.sort()

#split the list into 4 sub lists
points1 = points[:num_points/4]
points2 = points[num_points/4:num_points/2]
points3 = points[num_points/2:100 - num_points/4]
points4 = points[100 - num_points/4:]

#sort all these lists, based on the z value
#in this case, the sort function is passed the get_z function
#this function returns the z vale (see above) of the point
points1.sort(key=get_z)
points2.sort(key=get_z)
points3.sort(key=get_z)
points4.sort(key=get_z)

#draw 4 vertical lines through these points
for pt_num in range((num_points/4) - 1):
p2r.obj.Line.create(points1[pt_num], points1[pt_num + 1])
p2r.obj.Line.create(points2[pt_num], points2[pt_num + 1])
p2r.obj.Line.create(points3[pt_num], points3[pt_num + 1])
p2r.obj.Line.create(points4[pt_num], points4[pt_num + 1])

print "done"

This script creates some random points and then draws lines to the next closest point. The result is a bit unexpected... the line zig zags all over the place.


import py2rhino as p2r
import random as rnd
#===============================================================================
# Parameters
#===============================================================================
num_points = 100
#===============================================================================
# Main Script
#===============================================================================
#create some random points
points = []
for i in range(num_points):
x = rnd.randint(-25, 25)
y = rnd.randint(-25, 25)
z = rnd.randint(0,200)
points.append((x,y,z))
p2r.obj.Sphere.create((x,y,z), 0.5)

#create a starting point
pt1= (0,0,0)

#draw a line from to the next closest point
for pt_num in range(num_points):
pt2_num = p2r.util.point.points_closest_point(points, pt1)
pt2 = points[pt2_num]
p2r.obj.Line.create(pt1, pt2)
points.remove(pt2)
pt1 = pt2

print "done"

The site...


Here is the site or the studio... It is marked by the red star. It is right next door to the tallest building in Singapore.. the Capital Tower.

Saturday, September 5, 2009

Roof structure

Here is a script that generates some randomly placed roof structure...
No geometry is required

import py2rhino as p2r
import random as rnd
#===============================================================================
# Parameters
#===============================================================================
num_roof_pnts = (8,8)
num_columns = 10
roof_size = (100,100)
roof_height = 50
#===============================================================================
# Main Script
#===============================================================================
points = ( (roof_size[0]/-2, roof_size[1]/-2, roof_height), #x,y,z
(roof_size[0]/2, roof_size[1]/-2, roof_height),
(roof_size[0]/2, roof_size[1]/2, roof_height),
(roof_size[0]/-2, roof_size[1]/2, roof_height) )

roof = p2r.obj.NurbsSurface.create_by_corner_pnts(points)
roof.modf.rebuild((5,5), num_roof_pnts)
roof_pnts = roof.prop.pnts(True)

column_upper_pnts = []
column_lower_pnts = []

#create columns in random positions
for col_num in range(num_columns):

#create the lower and upper points
x_size = 2 * roof_size[0]/5
y_size = 2 * roof_size[1]/5
x_pos = rnd.randint(-1*x_size, x_size)
y_pos = rnd.randint(-1*y_size, y_size)
col_lower_pnt = ( x_pos, y_pos, 0 )
col_upper_pnt = (col_lower_pnt[0], col_lower_pnt[1], roof_height/2)

#save the points
column_lower_pnts.append( col_lower_pnt )
column_upper_pnts.append( col_upper_pnt )

#create the column
base = p2r.obj.Circle.create(col_lower_pnt, 2)
top = p2r.obj.Circle.create(col_upper_pnt, 1)
p2r.obj.NurbsSurface.create_by_loft( (base, top) )

for roof_pnt in roof_pnts:

#for each point on the roof, find the closest column
closest = p2r.util.point.points_closest_point(column_upper_pnts, roof_pnt)
closest_column_upper_pnt = column_upper_pnts[closest]

#get the planes that are at right angles to the centre line of the branch
center_ln = p2r.obj.Line.create(closest_column_upper_pnt, roof_pnt)
domain = center_ln.prop.domain()
base_plane = center_ln.eval.perp_frame(domain[0]) #((x,y,z), (p,q,r), (p,q,r), (p,q,r))
top_plane = center_ln.eval.perp_frame(domain[1])

#create the branch
base = p2r.obj.Circle.create(base_plane, 1)
top = p2r.obj.Circle.create(top_plane, 0.5)
p2r.obj.NurbsSurface.create_by_loft( (base, top) )

#delete the centre line - it is no longer needed
center_ln.modf.delete()

print "done"

Friday, September 4, 2009

New version of PyDev

There is a new version of PyDev - version 1.5

http://pydev.org/download.html

This version includes PyDev Extensions, which was previously a commercial plugin seperate from PyDev. This plugin also kept poping up a window where you have to click OK.

So now with the new version, you will not get this any more. As far as I know, nothing else has changed. So - to install it, here is what you do:


  • Uninstall PyDevExtensions, and PyDev
  1. Start Eclipse (if it is not yet open)
  2. Close all your files that are open in Eclipse
  3. In the menu, go to Help > About Eclipse SDK
  4. Click on Installation Details
  5. Click PyDev Extensions
  6. Click Uninstall
  7. When asked to restart Eclipse, click cancel
  8. Click on Installation Details
  9. Click PyDev
  10. Click Uninstall
  11. This time, accept when asked to restart Eclipse
  • Install the new version of PyDev
  1. Start Eclipse (if it is not yet open)
  2. In the menu, go to Help > Install new software
  3. Click the Add button
  4. In the Add Site dialog box, enter:
    Name: PyDev
    Location: http://pydev.org/updates
  5. Then click install...

If you can see you Navigator pane - don't panic.... In the menu, go to Window > Show View > Navigator, and then dock it on the left side

Thursday, September 3, 2009

Wavy surface


import py2rhino as p2r
import random

points = ((0,0,0),(100,0,0), (100,100,0), (0,100,0))

srf = p2r.obj.NurbsSurface.create_by_corner_pnts(points)
srf.modf.rebuild((4,4), (20,20))
points = srf.prop.pnts(True)

print points
points_rand = []
for pt in points:
z = random.randint(0,10)
rand_point = (pt[0], pt[1], z)
points_rand.append(rand_point)

srf2 = p2r.obj.NurbsSurface.create_by_control_pnt_grid((20,20), points_rand, (4,4))

Saw Tooth Roof Deformed



import py2rhino as p2r
#===============================================================================
# Parameters
#===============================================================================

sec1 = p2r.obj.NurbsSurface("7f72bdb7-ef4f-4b09-a7ba-6b9e3458a0b5")
sec2 = p2r.obj.NurbsSurface("4c136d1d-dbee-4a58-90fb-1371a480269d")
sec3 = p2r.obj.NurbsSurface("9f5599dd-c9a0-49a0-be23-8857372ed973")
sec4 = p2r.obj.NurbsSurface("ab8125c7-4524-4716-8cc1-ffb03b62e1b6")
sec5 = p2r.obj.NurbsSurface("44002bb6-e116-402b-b193-893b8e5902c9")
sec6 = p2r.obj.NurbsSurface("4514f287-4322-426f-b2d7-faf5e7de6977")

lower = p2r.obj.NurbsSurface("21399d5b-427a-43db-84a3-7f76b23d4b16")
upper = p2r.obj.NurbsSurface("19ce0362-2971-4536-a943-1d3185ac1416")

#===============================================================================
# Functions
#===============================================================================
def draw_line_between_crv(crv):
start = crv.prop.start_pnt()
end = crv.prop.end_pnt()
line = p2r.obj.Line.create(start, end)
return line
#------------------------------------------------------------------------------
def loft_curve(crv):
line = draw_line_between_crv(crv)
srf = p2r.obj.NurbsSurface.create_by_loft( (line, crv) )
return srf
#------------------------------------------------------------------------------
def generate_roofs():
num_sections = len(lower_secs)
num_segments = num_sections - 1

roofs = []
for sec_num in range(num_segments):
roof = p2r.obj.NurbsSurface.create_by_loft( (lower_secs[sec_num], upper_secs[sec_num + 1]) )
roofs.append(roof)

return roofs
#------------------------------------------------------------------------------
def generate_shade(lower_roof, upper_roof, num_v):
points_shade_edge = []
points_shade_edge_projected = []

u_domain_lower = lower_roof.prop.domain(0) #(0, 12.2)
max_u_param_of_lower = u_domain_lower[1]

u_domain_upper = upper_roof.prop.domain(0) #(0, 12.2)
max_u_param_of_upper = u_domain_upper[1]

v_domain_lower = lower_roof.prop.domain(1)
v_domain_upper = upper_roof.prop.domain(1)

v_range_lower = v_domain_lower[1] - v_domain_lower[0]
v_range_upper = v_domain_upper[1] - v_domain_upper[0]

v_lower_step = v_range_lower / num_v
v_upper_step = v_range_upper / num_v

for point_num in range(num_v + 1):

param_lower = (max_u_param_of_lower, v_lower_step * point_num)
param_upper = (0, v_upper_step * point_num)
param_upper_2 = (max_u_param_of_upper, v_upper_step * point_num)

point_lower = lower_roof.eval.evaluate(param_lower)
point_upper = upper_roof.eval.evaluate(param_upper)
point_upper_2 = upper_roof.eval.evaluate(param_upper_2)

dist_vec = p2r.util.vector.create(point_lower, point_upper)
dist = p2r.util.vector.length(dist_vec)

dir_vec = p2r.util.vector.create(point_upper, point_upper_2)
dir_vec = p2r.util.vector.unitize(dir_vec)
dir_vec = p2r.util.vector.scale(dir_vec, dist)

point_projected = p2r.util.point.add(point_upper, dir_vec)

points_shade_edge.append(point_upper)
points_shade_edge_projected.append(point_projected)

pl1 = p2r.obj.Polyline.create(points_shade_edge)
pl2 = p2r.obj.Polyline.create(points_shade_edge_projected)
p2r.obj.NurbsSurface.create_by_loft( (pl1, pl2) )

#------------------------------------------------------------------------------
def generate_window(lower_roof, upper_roof, num_v):

points_lower = []
points_upper = []

u_domain_lower = lower_roof.prop.domain(0) #(0, 12.2)
u_param_of_lower = u_domain_lower[1]

v_domain_lower = lower_roof.prop.domain(1)
v_domain_upper = upper_roof.prop.domain(1)

v_range_lower = v_domain_lower[1] - v_domain_lower[0]
v_range_upper = v_domain_upper[1] - v_domain_upper[0]

v_lower_step = v_range_lower / num_v
v_upper_step = v_range_upper / num_v

for point_num in range(num_v + 1):

param_lower = (u_param_of_lower, v_lower_step * point_num)
param_upper = (0, v_upper_step * point_num)

point_lower = lower_roof.eval.evaluate(param_lower)
points_lower.append(point_lower)

point_upper = upper_roof.eval.evaluate(param_upper)
points_upper.append(point_upper)

pl1 = p2r.obj.Polyline.create(points_lower)
pl2 = p2r.obj.Polyline.create(points_upper)
p2r.obj.NurbsSurface.create_by_loft( (pl1, pl2) )

#------------------------------------------------------------------------------
def generate_windows(roofs, num_v):

windows = []
for roof_num in range(len(roofs) - 1):
lower_roof = roofs[roof_num]
upper_roof = roofs[roof_num + 1]
generate_window(lower_roof,upper_roof, num_v)
generate_shade(lower_roof,upper_roof, num_v)

start_window = loft_curve(lower_secs[0])
end_window = loft_curve(upper_secs[-1])

windows.append(start_window)
windows.append(end_window)

return windows
#------------------------------------------------------------------------------
def generate_panels(roof, num_u, num_v):

domain_u = roof.prop.domain(0)
u_range = domain_u[1] - domain_u[0]
u_step = u_range / num_u

domain_v = roof.prop.domain(1)
v_range = domain_v[1] - domain_v[0]
v_step = v_range / num_v

for v_panel_num in range(num_v):
v_param = v_panel_num * v_step

for u_panel_num in range(num_u):

u_param = u_panel_num * u_step

#parameters
param_1 = (u_param, v_param)
param_2 = (param_1[0]+u_step, param_1[1])
param_3 = (param_1[0]+u_step, param_1[1]+v_step)
param_4 = (param_1[0] , param_1[1]+v_step)

#points
p1 = roof.eval.evaluate(param_1)
p2 = roof.eval.evaluate(param_2)
p3 = roof.eval.evaluate(param_3)
p4 = roof.eval.evaluate(param_4)

#draw a panel
p2r.obj.NurbsSurface.create_by_corner_pnts( (p1, p2, p3, p4) )
#------------------------------------------------------------------------------
def generate_all_panels(roofs, num_u, num_v):
for roof in roofs:
generate_panels(roof, num_u, num_v)
roof.modf.delete()

#===============================================================================
# Main Script
#===============================================================================
sec_list = (sec1, sec2, sec3, sec4, sec5, sec6)

lower_secs = []
for sec in sec_list:
sec_crv = lower.func.intersect_2_srfs(sec, create=True)
lower_secs.append(sec_crv[0])

upper_secs = []
for sec in sec_list:
sec_crv = upper.func.intersect_2_srfs(sec, create=True)
upper_secs.append(sec_crv[0])

roofs = generate_roofs()
windows = generate_windows(roofs, 6)

generate_all_panels(roofs, 2, 6)


print "done"