COMPUTER
AIDED
ARCHITECTURAL DESIGN
Workshop 18 Notes,
Week of November 30 , 2015
Array on Surface, Solar Shading Example With Vectors (DRAFT NOTES IN PROGRESS)
Within this set of workshop notes are several examples of
copying and translating an object onto a surface using vectors with a
surface's "uv" coordinates. A more complex example
illustrates the movement of a series of solar panels to the altitude
and azimuth position of the sun.
1. Array on Surface
1.1 Create "Rectangular Plane: corner to corner surface" from the
"Surface Creation" palette (second row, first icon), turn the control
points on, and with the Gumball tool translate the lower-left and
upper-right corner points upward so as to create a simple saddle shape.

1.2 Create a torus at the origin of the XYPlane from the
"Solid Creation" palette (third row, first icon) and also place a point
at the origin.

1.3 Open Grasshopper and from the "Params" tab create the following parameters:
From the parameters tab "startPt" (first row, first icon).
From
the parameters tab and below the geometry pull-down sub-tab, create
parameters for "Srf",(7th row, first icon ), and "Geo" (
8th row, second icon )
From the parameters tab and above "Input"
sub-tab create integer "int" sliders for "numRows" and "numCols"
with current value 3 and value range 1 to 40.

1.4 connect the paramters for geometry to the Rhino model:
Right-click on the "Geo" parameter and set it to the torus.
Rick-click on the "srf" parameter and set it to the simple saddle.
Rick-click on the "startPt" parameter and set it to the point at the origin.
1.5. Select a Python component from the "Math" tab, and crreate corresponding input ports for the parameters of 1.4.
"Geo" port with type hint "ghdoc Object when geometry (rhinoscriptsyntax)"
"surf" port with type hint "Surface"
"startPt" port with type hint "Point3d"
"numRows" port with type hint "int"
"nunCols" port with type hint "int"

1.6. Zoom up to the "Python" component and create an output port "b"

1.7 Within the Python component itself, create the following script as found in the Grasshopper file arrayObjOnSurf.gh:

Note that in the function "getSurfaceParamPt":
Line 10 creates a "pt" variable at some "u" value from 0 to 1 for "i/numRows", and a "v" value
0 to 1 for "ii/numCols", and "0".
The value range of these points address the two directions "u" and "v"
on the surface where the total value range is 0 to 1 in each direction.
Line 12 takes this "pt" variable and gets a parametric surface pt and assigns it to "surfPt".
Line 14 in turn takes "surfPt and and evaluates it to determine a
3D point in full Cartesian coordinate space and assigns it to "curPt".
Lines 15 and 16 return the total number of 3D points via the list "ptList"
Note that in the function "transObjectToSurface":
Line 21 gets each curPt from the list of of 3D points on the surface and
Line 22 creates a translation vector from the original "startPt" to the given surface curPt.
Line 23 uses the translation vector to translate a copy of the torus to the given point.
1.8 The resulting surface now is juxaposed the torus in a 4 x 4 array.

1.9 Reducing the scale of the torus and adding 7 rows and 7 columns yields the following result:

2.0 Adjust the torus rotation to the surface normal.
Note that in the figure above all the torus figures are juxposed with
the saddle surface in the same orientation as the original torus.
However, in the following figure, the torus has been rotated to be
normal (e.g., perpendicular) to where it located relative to the saddle
surface.

The script in the Grasshopper file arrayObjOnSurfaceNormal1.gh
has been modified from part 1 to incorporate a series of normalized
vectors for the saddle surface (see lines 19 through 21 below). These
surface normal vecturs are returned from procedure "getSurfaceParamPts
in line 23 below.

3.0 Creating a "Boolean" parameter.
3.1
From the "Params" tab and above the "input" area, add a "boolean"
parameter (1st row, second icon) to the Grasshopper canvas window.
3.2 Add a corresponding input port named "surfNormal" and give it the type hint "bool".

3.2 Connect the parameter to the input port.
3.3 In the script from part 2, comment out (or remove) line 57 as in the file arrayObjOnSurfaceNormal2.gh.

3.5 Note that togging the "boolean" symbol off reverts the torus copies to be normal to the x-y plane.

3.6 Togging the "boolean" symbol to on returns the torus copies to be normal to the surface.

4.0 Solar Shading Array.
In this illustration, the Grasshopper file pthonSunVectorShaderArray.gh
detemines an array of panels is rotated to match the Sun position such
that they either 1) admits indirect daylight but not direct
sunling to penetrate the panels if the "shade" is on, or 2)
permits direct sunlight to penetrate the panels if the "shade" is off.
It draws upon an internal Rhino function that calculates a
vector representing the sun, translates the vector into "Altitude",
"Azimuth" and "Effective Angle" (see below) calculcations, and adjusts
the shader panels accordingly.
If a boolean variable for "shadeOn"
is set to "true" for spring soltice (March 20, 2016, then the panels
are pendendicular to the direction of the sun:.

If
the boolean variable for "shadeOn" is set to false for spring solstice,
then the panels are parallel to the direction of the sun:

If the sun angle is below the horizon, then the shader panels close so as to minimize any light penetration:

4.1. The script is initiated with the following input parameters and types
numRows = number of rows of the shader along the Y axis in the figure above (int, 1 to 200)
numCols = number of columns of the shader along the X axis in the figure above (int, 1 to 200)
width = the width of any given panel, (float, 0.1 to 100.0)
depth = the depth of any given panel (float, 0.1 to 100.0)
spacing = row-to-row and column-to-column spacing(float, 0.1 to 100.0)
latitude = latitude for Sun calculation (int, -180 to 180)
longitude = longitude for Sun calculation (int, -90 to 90)
year = year for Sun calculation (int, 0 to 3000)
month = month for Sun calculation (int, 1 to 12)
day = day for Sun calculation (int, 1 to 31)
hour =hour for Sun calculation (int, 0 to 23)
minute =minute for Sun calculation (int, 0 to 59)
second =second for Sun calculation (int, 0 to 59)
GMT-Offset = Greenwich Meant Time Offset (int, -24 to 24)
Shade toggle = determines if shaders are "on" or "off" (Boolean, "true" or "false")
Correspondingly, input ports are created on a Python script component within Grasshopper:

Note
that the Python script determines the "Altitude" and "Azimuth" as
is typical of sun calculations. It also calculates a somewhat
unconventional "Effectve Altitude" of the sun relative to the ground
with respect to the southern elevation of the shader array. That is,
relative to alocation in the Northern Hemisphere, the Sun moves from east to south to west. The "Effective Altitude" of the sun relative to the southern elevation of a a building may be relatively at a
higher angle in mid-morning then it is at mid-day, even if the
"Altitude" is higher at mid-day than it is at mid-morning relative to
the ground surface overall. (Note: the "Effective Altitude" is not
typically used, but created here just for illustrative purposes. It is
determined by creating a vector from "Y and Z" components of a vector from the
ground to the sun and measuring its angle with the vector 0, -1,
0.
The Python script is detailed below. It consists of a number of defined functions
(e.g., "def copyObject", etc.) on lines 9 thorugh 101. The "#main" part of the script on lines 104 through 128 calls the
defined functions and activates the script. The functions within the script
on lines 9 through 70 address the calculation the sun position. The remaining two functions
are "makeShadeUnit" and "makeShadeArray" on lines 72 through 101. The function "makeShadeUnit"determines the size and angle of the
individual shading unit relative to the sun. The function "makeShadeArray" copies the shade unit into an array. The details of this script as a whole are
beyond the scope of these workshop notes. However, the comment lines
and variable names should help to explain how the script works.

4.2 Note that the script can be modified, as in the file pythonSunVectorShaderArray2.gh,
such that the Shader array is vertical rather than horizontal by
changing lines 96 and 97 above of the "def makeShadeArray"
function as follows:

Thus, if the boolean variable for "shadeOn" is set to "false", then the resulting shaders appear as follows:

Conversely, if the boolean variable for "shadeOn" is set to "true", the resulting shaders appear as follows:

In addition, adding
lines 88 and 89 to the function "def makeShadeUnit" has the impact of
causing the shaders to form a vertical plane if the sun angle is less
than 0 degrees or greater than 90 degrees (the sun is below the horizon):

