We value your input! Please participate in Archicad 28 Home Screen and Tooltips/Quick Tutorials survey
2022-10-11 09:41 AM
Hello Everybody,
I want to give a custom number for every Zone in my Project.
The result should be construct with the Storyname and the zone Number.
XXXX-XXX
Storeyname-Zone Number
How could we customize the Python-Script to insert the Storey name in front of the Zone numbering?
from Archicad import ACConnection
from typing import List, Tuple, Iterable
from itertools import cycle
conn = ACConnection.connect()
assert conn
acc = conn.commands
act = conn.types
acu = conn.utilities
################################ CONFIGURATION #################################
propertyId = acu.GetBuiltInPropertyId('Zone_ZoneNumber')
propertyValueStringPrefix = ''
elements = acc.GetElementsByType('Zone')
ROW_GROUPING_LIMIT = 0.25
STORY_GROUPING_LIMIT = 1
def GeneratePropertyValueString(storyIndex: int, elemIndex: int) -> str:
return f"{propertyValueStringPrefix}{storyIndex:1d}{elemIndex:02d}"
################################################################################
def generatePropertyValue(storyIndex: int, elemIndex: int) -> act.NormalStringPropertyValue:
return act.NormalStringPropertyValue(GeneratePropertyValueString(storyIndex, elemIndex))
def createClusters(positions: Iterable[float], limit: float) -> List[Tuple[float, float]]:
positions = sorted(positions)
if len(positions) == 0:
return []
clusters = []
posIter = iter(positions)
firstPos = lastPos = next(posIter)
for pos in posIter:
if pos - lastPos <= limit:
lastPos = pos
else:
clusters.append((firstPos, lastPos))
firstPos = lastPos = pos
clusters.append((firstPos, lastPos))
return clusters
boundingBoxes = acc.Get3DBoundingBoxes(elements)
elementBoundingBoxes = list(zip(elements, boundingBoxes))
zClusters = createClusters((bb.boundingBox3D.zMin for bb in boundingBoxes), STORY_GROUPING_LIMIT)
storyIndex = 0
elemPropertyValues = []
for (zMin, zMax) in zClusters:
elemIndex = 1
elemsOnStory = [e for e in elementBoundingBoxes if zMin <= e[1].boundingBox3D.zMin <= zMax]
yClusters = createClusters((e[1].boundingBox3D.yMin for e in elemsOnStory), ROW_GROUPING_LIMIT)
for ((yMin, yMax), reverseOrder) in zip(yClusters, cycle([False, True])):
elemsInRow = [e for e in elemsOnStory
if yMin <= e[1].boundingBox3D.yMin <= yMax]
for (elem, bb) in sorted(elemsInRow, key=lambda e: e[1].boundingBox3D.xMin, reverse=reverseOrder):
elemPropertyValues.append(act.ElementPropertyValue(
elem.elementId, propertyId, generatePropertyValue(storyIndex, elemIndex)))
elemIndex += 1
storyIndex += 1
acc.SetPropertyValuesOfElements(elemPropertyValues)
# Print the result
newValues = acc.GetPropertyValuesOfElements(elements, [propertyId])
elemAndValuePairs = [(elements[i].elementId.guid, v.propertyValue.value) for i in range(len(newValues)) for v in newValues[i].propertyValues]
for elemAndValuePair in sorted(elemAndValuePairs, key=lambda p: p[1]):
print(elemAndValuePair)
Thank in Advance for your Support
Solved! Go to Solution.
2022-10-12 05:17 PM
Hy,
With Python I don't know… but in GDL it's very easy.
Make a copy of the zone mark object and add these few lines at the beginning of the master script
n = REQUEST ("Home_story", "", index, story_name)
num_eta = STR ("%.0m", index)
ROOM_NUMBER = story_name + "."+ ROOM_NUMBER
2022-10-12 05:17 PM
Hy,
With Python I don't know… but in GDL it's very easy.
Make a copy of the zone mark object and add these few lines at the beginning of the master script
n = REQUEST ("Home_story", "", index, story_name)
num_eta = STR ("%.0m", index)
ROOM_NUMBER = story_name + "."+ ROOM_NUMBER
2022-10-13 12:01 PM
Hy Yves,
Thank you for your solution. It's work very well!!!
After the changing the GDL code, you can run the Python script and print the ROOM NUMBER
----
Gwenael Tripodi, Architect | BIM Manager
AC 8.1-26
MacOS Big Sur | 3,8 GHz i7 8Core | 24GB | AMD 5500 XT
2022-10-13 05:21 PM
Hey Yves,
I just spoked with the User from the Model...
He needs to "Print" the the complete Information in Room number.
With GDL, you can show the Information on the floor plan as a "prefix".
Maybe there are some possibility to made it with Python....
We could create a User Property for the the Story name and print this User Property with a Built-in Property (Roomnummer) Together.
But I have no idea what the Python code should look like....
Does anyone have any ideas?
---
Gwenael Tripodi, Architect | BIM Manager
AC 8.1-26
MacOS Big Sur | 3,8 GHz i7 8Core | 24GB | AMD 5500 XT
2022-10-18 12:01 AM
I believe that the GDL script might be the simpler approach if you could live with the above. But if you wanted to use Python? you would first have to create two custom properties, classified to zones( spaces).
1. An expression returning the Story Name for the zone
2. A custom property to receive the room name.
3. Then configure the zone label to display the custom property -- room name
The Python code would be as follows:
from Archicad import ACConnection
import Archicad
conn = ACConnection.connect()
assert conn
acc = conn.commands
act = conn.types
acu = conn.utilities
zoneNumberId = acu.GetBuiltInPropertyId('Zone_ZoneNumber')
roomNameId = acu.GetUserDefinedPropertyId('Zone_Names','RoomName')
storyNameId = acu.GetUserDefinedPropertyId('Zone_Names','Story_Name')
zones = acc.GetElementsByType('Zone')
names =[]
for element in zones:
number = acc.GetPropertyValuesOfElements([element],[zoneNumberId,storyNameId])
name = (number[0].propertyValues[0].propertyValue.value,
number[0].propertyValues[1].propertyValue.value)
name = name[1]+'-'+name[0]
names.append(name)
EPVArray = []
for index,obj in enumerate(names):
normalname = act.NormalStringPropertyValue(obj, type='string', status='normal')
EPV = act.ElementPropertyValue(zones[index].elementId, storyNameId, normalname)
EPVArray.append(EPV)
result = acc.SetPropertyValuesOfElements(EPVArray)
print(result)
2022-10-24 06:19 PM
Hi Gerry,
Could you maybe help, how would the script look like, if i simply want to replace the zone number with a custom property?
I have a concat expression to automatize the room numbering from different parameters, i just need this actually as the zone number.
2023-01-02 10:43 PM
Hey @Daniel Pataki
The following will provide you with the necessary:
from Archicad import ACConnection
conn = ACConnection.connect()
assert conn
acc = conn.commands
act = conn.types
acu = conn.utilities
# get all zones (returns GUIDs)
elem_all_zones = acc.GetElementsByType('Zone')
# returns GUIDs of prop (Built-ins are non-localized)
prop_znumber = acu.GetBuiltInPropertyId('Zone_ZoneNumber')
# user properties are localized: 'Group', 'Prop Name'
# CHANGE THIS:
prop_pnumber = acu.GetUserDefinedPropertyId('Allgemeine Werte', 'Raumnummer')
propvallist_pnumber = [val.propertyValues[0].propertyValue.value for val in acc.GetPropertyValuesOfElements(elem_all_zones, [prop_pnumber])]
for i, elem in enumerate(elem_all_zones):
new_zonenumber = act.ElementPropertyValue(
elem.elementId, prop_znumber, act.NormalStringPropertyValue(propvallist_pnumber[i]))
# write number back
acc.SetPropertyValuesOfElements([new_zonenumber])