Hi Matt,
I've written a CGA rule that allows the user to control the splitting of a block into a series of shapes. Once the final subblock units have been set I've used a python script to convert them to static parcels. One problem I'm having is saving the area of each of these areas as an object attribute in the newly created shapes (for subsequent FAR calculations). Once they are static shapes I need to manually remove some excess shapes (there are extra subblock areas created for each rectangle in the block, including the block itself). Finally, I've tried writing an Export (Reporting) Python module that creates a new object attribute for each subblock unit and assigns the area to that attribute.
Any advice you can provide is greatly appreciated!
Brendan
_______________________________________________________________________________________
CGA rule for controlled subdivision of a block:
/**
* File: subblock.cga
* Created: 20 Jul 2017 18:58:27 GMT
* Author: bcbd
*/
version "2017.0"
import Zoning : "Zoning.cga"
@hidden
attr myZoning = ""
attr zoningResidentialArea = 0
attr zoningCommercialArea = 0
attr zoningInstitutitonalArea = 0
attr zoningMixed_UseArea = 0
attr zoningIndustrialArea = 0
@Group("Initial Block: First Split", 1)
attr A_B_Split = false
attr rotate_AB = false
@Range(0,200)
attr A_Depth = 20
@Range("Residential", "Commercial", "Institutional", "Mixed_Use", "Industrial")
attr zoningA = "Residential"
@Range("Residential", "Commercial", "Institutional", "Mixed_Use", "Industrial")
attr zoningB = "Residential"
@Group("A: Second Split", 3)
attr A1_A2_Split = false
attr rotate_ZoneA = false
@Range(0,100)
attr A2_Width = 20
attr A3_Split = false
@Range(0,100)
attr A3_Width = 20
@Range("Residential", "Commercial", "Institutional", "Mixed_Use", "Industrial")
attr zoningA1 = "Residential"
@Range("Residential", "Commercial", "Institutional", "Mixed_Use", "Industrial")
attr zoningA2 = "Residential"
@Range("Residential", "Commercial", "Institutional", "Mixed_Use", "Industrial")
attr zoningA3 = "Residential"
@Group("B: Second Split", 4)
attr B1_B2_Split = false
attr rotate_ZoneB = false
@Range(0,100)
attr B2_Width = 20
attr B3_Split = false
@Range(0,100)
attr B3_Width = 20
@Range("Residential", "Commercial", "Institutional", "Mixed_Use", "Industrial")
attr zoningB1 = "Residential"
@Range("Residential", "Commercial", "Institutional", "Mixed_Use", "Industrial")
attr zoningB2 = "Residential"
@Range("Residential", "Commercial", "Institutional", "Mixed_Use", "Industrial")
attr zoningB3 = "Residential"
////////////////////////// BEGINNING OF SPLIT
@StartRule
block -->
case A_B_Split == true :
case rotate_AB == false :
split(x) {A_Depth : zoneA | ~1 : zoneB}
Reporting
NIL ///////////////////
else :
split(z) {A_Depth : zoneA | ~1 : zoneB}
Reporting ///////////////////
NIL
else :
colorPicker(zoningA)
Reporting ///////////////////
NIL
zoneA -->
case A1_A2_Split == true && A3_Split == false :
case rotate_ZoneA == false :
split(x) {A2_Width : zoneA1 | ~1 : zoneA2}
Reporting ///////////////////
NIL
else :
split(z) {A2_Width : zoneA1 | ~1 : zoneA2}
Reporting ///////////////////
NIL
case A1_A2_Split == true && A3_Split == true :
case rotate_ZoneA == false :
split(x) {A2_Width : zoneA1 | ~1 : zoneA2 | A3_Width : zoneA3}
Reporting ///////////////////
NIL
else :
split(z) {A2_Width : zoneA1 | ~1 : zoneA2 | A3_Width : zoneA3}
Reporting ///////////////////
NIL
else :
colorPicker(zoningA)
Reporting ///////////////////
NIL
zoneB -->
case B1_B2_Split == true && B3_Split == false :
case rotate_ZoneB == false :
split(x) {B2_Width : zoneB1 | ~1 : zoneB2}
Reporting ///////////////////
NIL
else :
split(z) {B2_Width : zoneB1 | ~1 : zoneB2}
Reporting ///////////////////
NIL
case B1_B2_Split == true && B3_Split == true :
case rotate_ZoneB == false :
split(x) {B2_Width : zoneB1 | ~1 : zoneB2 | B3_Width : zoneB3}
Reporting ///////////////////
NIL
else :
split(z) {B2_Width : zoneB1 | ~1 : zoneB2 | B3_Width : zoneB3}
Reporting ///////////////////
NIL
else :
colorPicker(zoningB)
Reporting ///////////////////
NIL
#ZONE A
zoneA1 -->
colorPicker(zoningA1)
zoneA2 -->
colorPicker(zoningA2)
zoneA3 -->
colorPicker(zoningA3)
#ZONE B
zoneB1 -->
colorPicker(zoningB1)
zoneB2 -->
colorPicker(zoningB2)
zoneB3 -->
colorPicker(zoningB3)
colorPicker(zoningType)-->
case zoningType == "Residential" :
Zoning.Residential
label("Residential")
set(myZoning, "Residential")
//set(zoningResidentialArea, geometry.area)
print(myZoning + " Area: " + geometry.area)
case zoningType == "Commercial" :
Zoning.Commercial
set(myZoning, "Commercial")
label("Commercial")
//set(zoningCommercialArea, geometry.area)
print(myZoning + " Area: " + geometry.area)
case zoningType == "Institutional" :
Zoning.Institutional
label("Institutional")
set(myZoning, "Institutional")
//set(zoningInstitutitonalArea, geometry.area)
print(myZoning + " Area: " + geometry.area)
case zoningType == "Mixed_Use" :
Zoning.Mixed_Use
label("Mixed_Use")
set(myZoning, "Mixed_Use")
//set(zoningMixed_UseArea, geometry.area)
print(myZoning + " Area: " + geometry.area)
case zoningType == "Industrial" :
Zoning.Industrial
label("Industrial")
set(myZoning, "Industrial")
//set(zoningIndustrialArea, geometry.area)
print(myZoning + " Area: " + geometry.area)
else : NIL
Reporting -->
report("Area_Residential", zoningResidentialArea)
report("Area_Commercial", zoningCommercialArea)
report("Area_Institutional", zoningInstitutitonalArea)
report("Area.Mixed_Use", zoningMixed_UseArea)
report("Area.Industrial", zoningIndustrialArea)
_______________________________________________________________________________________
Script to convert selected block into static subblock fragments:
'''
Created on 2017-07-26
@author: bcbd
'''
from scripting import *
# get a CityEngine instance
ce = CE()
def convertModelsToShapes():
models = ce.selection()
shapes = ce.convertModelsToShapes(models)
newShapes = ce.separateFaces(shapes)
#cleanupSettings = CleanupShapesSettings()
#LIST ALL CLEANUP SETTINGS TO BE APPLIED
#cleanupSettings.setRemoveCoplanarEdges(True) #DOES THIS EVEN WORK?
#cleanedShapes = ce.cleanupShapes(newShapes,cleanupSettings)
#print "new shape converted from model: "+ce.getName(newShapes[0])
def subblockSelection():
shapes = ce.getObjectsFrom(ce.scene, ce.isShape)
if __name__ == '__main__':
convertModelsToShapes()
pass
_______________________________________________________________________________________
Once excess subblock units are removed (currently manual):
Script to calculate parcel area:
attr parcelArea_Calc = geometry.area
Lot -->
set(parcelArea_Calc, geometry.area)
report("Parcel_Area", parcelArea_Calc)
print("Parcel Area: " + parcelArea_Calc)
color(0.2,0.2,0.2) #color orange if CGA rule is complete
_______________________________________________________________________________________
Script to generate new object attributes (parcel area) for each subblock unit. Not yet complete.
'''
Created on 2017-07-27
@author: bcbd
'''
from scripting import *
# Get a CityEngine instance
ce = CE()
REPORT = ""
def initExport(exportContextOID):
global REPORT
REPORT = "Name,parcelArea\n"
parcelArea()
# Called for each shape after generation.
def finishModel(exportContextOID, shapeOID, modelOID):
shape = Shape(shapeOID)
model = Model(modelOID)
global REPORT
i = 0
totalArea = 0.0
reports = model.getReports()
if 'Parcel_Area' in reports.keys():
for area in reports['Parcel_Area']:
#totalArea +=area
i+=1
REPORT += "%s,%d\n" % (ce.getName(shape), area)
#ce.addAttributeLayer(model, 'parcelArea', area)
else :
REPORT += "%s,%d\n" % (model, 0)
def finishExport(exportContextOID):
filename = ce.toFSPath("models/"+"/reportdata.txt")
FILE = open(filename, "w")
FILE.write(REPORT)
FILE.close()
'''
if(model.getReports().has_key('Parcel_Area')):
l = len(model.getReports()['Parcel_Area'])
for i in range(0,l):
parcelArea = model.getReports()['Parcel_Area']
l = ce.addAttributeLayer('Parcel_Area')
ce.setAttribute(shape, "/ce/rule/Parcel_Area", parcelArea)
# Called after all shapes are generated.
def finishExport(exportContextOID):
ctx = ScriptExportModelSettings(exportContextOID)
parcelArea()
'''
def parcelArea():
objects = ce.getObjectsFrom(ce.selection, ce.isShape)
for o in objects:
ce.setRuleFile(ce.selection(), 'calculateParcelArea.cga') # assign CGA rule calcParcelArea
ce.setStartRule(ce.selection(), 'Lot')
ce.generateModels(ce.selection())