Original User: Daniel.OShaughnessy1) Yes, each block is 1 OBJ file2) Not from Rhino (they always get triangulated). You can avoid the triangulation by using 3d Max instead, but a quick test of that reveals the same problem[ATTACH=CONFIG]15876[/ATTACH]3) OK4) Here is the code (sorry it's kind of long). The model import is in the InsertModel rule, while the splitting occurs between Mass and Floors@Group("Model",0) @Order(1)
attr Model_file = "my.obj"
@Group("Model",0) @Order(2) @Range("Scale to Parcel Size","Scale to Parcel and Set Height","Set Height","Do not scale (model in realworld dimensions)")
attr Model_Size = "Scale to Parcel and Set Height"
@Group("Model",0) @Order(3)
attr Model_Height = 50
@Group("Model",0) @Order(4) @Range("0","90","180","270")
attr Model_Rotation = 0
@Group("Lot Attributes",1)
attr distanceStreet = 0 // Lot setback
@Hidden
attr Block_Area = 0
Block -->
set(Block_Area,geometry.area) //PM: We have to store this value to calculate the FAR below
report("Block Area",Block_Area) //PM: Plus we write it out for the report
offset(distanceStreet)
comp(f) {inside: alignScopeToAxes InsertModel | border: O}
InsertModel -->
// examples of different insert 'modes'
case Model_Size == "Scale to Parcel Size":
i(Model_file) // the insert operation fits in the model automatically and scales the height accordingly
r(scopeCenter, 0, Model_Rotation, 0)
Mass
case Model_Size == "Scale to Parcel and Set Height":
s('1,Model_Height,'1)
i(Model_file)
r(scopeCenter, 0, Model_Rotation, 0)
Mass
case Model_Size == "Set Target Height":
s(0,Model_Height,0) center(xz) // in case only height is set..
i(Model_file) // ..the insert operation scales the width and depth according to the given height
r(scopeCenter, 0, Model_Rotation, 0)
Mass
else:
s(0,0,0) center(xyz) // in case size is 0..
r(scopeCenter, 0, Model_Rotation, 0)
i(Model_file) // ..the insert operation uses the realworld dimensions
Mass
##############################################
# REST IS THE SAME AS IN THE PREVIOUS CGA FILE
#
@Group("Land Use Control",5) @Order(1) @Range("Residential","Commercial","Mixed-Use","Industrial", "Retail","Government","Cultural","Education","Hotel") //PM: @Range annotation creates drop-down
attr Land_Use = 10%: "Residential" 50%: "Commercial" 30%: "Mixed-Use" else: "Industrial" //PM: These attribute is usually controlled by image map
@Group("Building Attributes") @Order(2)
attr retailheight = 5
@Group("Building Attributes") @Order(1)
attr floorheight = 4
@Group("Visualization") @Range("Mass_white","Mass_color","Floors","MassAndFloors")
attr vizMode = "MassAndFloors"
@Group("Land Use Control") @Order(5) @Description("% of commercial floors in a mixed-use residential building")
attr mixedUsePercentage = 0.4 //PM: New attribute
@Group("Building Attributes")
attr getNumberOfRetailFloors =
case Land_Use == "Residential" : 0
case Land_Use == "Industrial" : 0
case Land_Use == "Education" : 0
case Land_Use == "Cultural" : 0
case Land_Use == "Commercial" : 1
case Land_Use == "Mixed-Use" : 1
else : floor(rand(1))
getColor(myLandUse) =
case myLandUse == "Commercial" : "#DD7300"
case myLandUse == "Retail" : "#D63200"
case myLandUse == "Residential" : "#FFD255"
case myLandUse == "Industrial" : "#720000"
case myLandUse == "Government" : "#1887B2"
case myLandUse == "Cultural" : "#46B8E6"
case myLandUse == "Education" : "#8D7CC1"
case myLandUse == "Hotel" : "#D8ABC8"
else : "#888888"
calcNumberOfFloors =
rint(scope.sy/floorheight)
//PM: handles mixed use and adds retail floors
Mass -->
case Land_Use == "Mixed-Use":
split(y){ retailheight * getNumberOfRetailFloors: Floors("Retail")
| floorheight * mixedUsePercentage*calcNumberOfFloors : Floors("Commercial")
| ~1: Floors("Residential") }
MassViz(Land_Use)
else:
split(y){ retailheight * getNumberOfRetailFloors: Floors("Retail")
| ~1: Floors(Land_Use) }
MassViz(Land_Use)
// PM: sets the color according the landuse-parameter and splits them in single floors using a repeat split
Floors(myLandUse) -->
color(getColor(myLandUse))
split(y){ ~floorheight: comp(f){ bottom: FloorArea(myLandUse) } }*
FloorArea(myLandUse) -->
reverseNormals
report("GFA."+myLandUse,geometry.area) //PM: the default staticts show the sum, so we just have to call it for each floor
report("FAR",geometry.area/Block_Area) //PM: same here (we just do the division for each floor instead for the whole sum at the end)
FloorViz(myLandUse)
O -->
color("#A7BC2B")
##############################################
# Visualization
#
MassViz(myLandUse) --> //DOS: the idea is to have viz modes similar to those in the reporting tutorial
case vizMode == "Mass_white" : Mass. //DOS: solid white mass
case vizMode == "Mass_color" : //DOS: mass colored by land use
color(getColor(myLandUse)) Mass.
case vizMode == "MassAndFloors" : //DOS: transparent mass with floors
set(material.color.a, 0.2) Mass.
else: NIL //DOS: if set to "Floors" there should be no mass shown at all, only floors
FloorViz(myLandUse) -->
case vizMode == "Mass_white" || vizMode == "Mass_color" : NIL
else:
color(getColor(myLandUse)) Floors.