Archicad Python API
About automating tasks in Archicad using the Python API.
SOLVED!

Customization Python Script - ZONE NUMBERING

Anarchiteckt
Contributor

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

 

image.pngimage.png

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

 

 

Gwenael Tripodi, Architect | BIM Manager
AC 8.1-26
MacOS Big Sur | 3,8 GHz i7 8Core | 24GB | AMD 5500 XT
1 ACCEPTED SOLUTION

Accepted Solutions
Solution
Yves
Advocate

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
Yves Houssier
Belgium
Archicad 19 -> 24
iMac - Mac Os 10,13

View solution in original post

6 REPLIES 6
Solution
Yves
Advocate

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
Yves Houssier
Belgium
Archicad 19 -> 24
iMac - Mac Os 10,13

Hy Yves,

Thank you for your solution. It's work very well!!!

Capture d’écran 2022-10-13 à 11.47.33.png

 

 

 

 

 

 

 

 

 

 

 

After the changing the GDL code, you can run the Python script and print the ROOM NUMBER 

 

Capture d’écran 2022-10-13 à 11.57.42.png







----
Gwenael Tripodi, Architect | BIM Manager
AC 8.1-26
MacOS Big Sur | 3,8 GHz i7 8Core | 24GB | AMD 5500 XT

Gwenael Tripodi, Architect | BIM Manager
AC 8.1-26
MacOS Big Sur | 3,8 GHz i7 8Core | 24GB | AMD 5500 XT
Anarchiteckt
Contributor

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".

Capture d’écran 2022-10-13 à 17.06.38.png
 
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

Gwenael Tripodi, Architect | BIM Manager
AC 8.1-26
MacOS Big Sur | 3,8 GHz i7 8Core | 24GB | AMD 5500 XT
poco2013
Mentor

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)
Gerry

Windows 11 - Visual Studio 2022; ArchiCAD 27

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.

Archicad BIM-Expert
https://www.a-null.com/

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])
Lucas Becker | AC 27 on Mac | Author of Runxel's Archicad Wiki | Editor at SelfGDL | Developer of the GDL plugin for Sublime Text |
«Furthermore, I consider that Carth... yearly releases must be destroyed»