Levels with python

Hi All,
@c.poupin
In my script below I want to create my levels and in the same time compute the remaining Height in each level…so what I’m doing wrong in my script to get each remaining Height (H_offset) repeated 12 times??

Check my script please:

import sys
import clr
import math
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference('RevitNodes')
import Revit
from Revit.Elements import *

H_Total = IN[0]
H_Shaft = IN[1]
n = math.ceil(H_Total / H_Shaft)

out = [i*H_Shaft for i in range(int(n))]
if math.ceil(H_Total % H_Shaft)  == 0:
    out = out     
else:
    out.append(H_Total)
lst = []
Lev = []

k = 0
H_offset = H_Total 
for i in out:
    k += 1
    Niv = Level.ByElevationAndName(i, 'Niveau ' + str(k))
    Lev.append(Niv)
    L = 0
    while L < int(n):
        L += 1
        H_offset = H_Total - i
        lst.append(H_offset)
        if math.ceil(H_offset) < H_Shaft:
            lst.append(H_offset)
            break
OUT = lst, Lev

Thanks.

You set L = 0 under your for loop which means it’s going to be reset on every iteration. I’m guessing you want to set the initial value before the loop, like you do with k. Otherwise it’s going to be causing some confusion in your looping process.

You can make this much simpler by not repeating your loops (once for creating out and once for iterating through it) and focusing only on building upwards until you hit your total height.

Python
H_Total = IN[0]
H_Shaft = IN[1]

lst = []
Lev = []

currentHeight = 0
i = 1

while currentHeight < H_Total:
    currentHeight += H_Shaft
    newLevel = "Level " + str(i) + " (" + str(currentHeight) +")" #create your level here
    Lev.append(newLevel)
    lst.append(H_Total - currentHeight)
    i += 1
    
OUT = lst,Lev

You can change the condition depending on whether you want to include a level over the total height or not.

2 Likes

@Nick_Boyts

My levels and offset distances should be as shown in the image below

In your exemple levels not start from 0 and the same thing for your distances not start from 45!! and they should stop at 1

I would like to keep the structure of my script because I need it for something else

I tried what you suggested but I get the same error

L = 0
    while L < int(n):
        H_offset = H_Total
        L += 1
        H_offset = H_Total - i
        lst.append(H_offset)
        if math.ceil(H_offset) < H_Shaft:
            lst.append(H_offset)
            break
OUT = lst, Lev

Thanks.

To include the initial value of 0 you just shift the current height to be updated at the end of the loop. You can then check the last value against the total height and create a top level if the loop doesn’t land exactly on the total height.

If that’s still not what you’re after then you’ll have to clarify (preferably with an example). Currently your while loop is running multiple times under the same i value. This is returning the same H_offset (since H_offset is calculated with i) over and over again.

2 Likes

Hello, valid only if integers in input the creation of altimetry copy should work all the same in response to the initial capture


python script:

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import math
H_Total=IN[0]
H_Shaft=IN[1]

new_list=[]

list_Altitude=[i for i in range(H_Total,0,-H_Shaft)]

for i in range(0,len(list_Altitude)):
    i=list_Altitude
    new_list.extend(i)
new_list.sort(reverse=True)

OUT = new_list
edit: with floats


Script:

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import math
H_Total=IN[0]
H_Shaft=IN[1]

new_list=[]

if H_Total%H_Shaft>0:
    list_Altitude=[H_Total-(i*H_Shaft+H_Shaft) for i in range(0,int(H_Total//H_Shaft))]
else:
    list_Altitude=[H_Total-(i*H_Shaft+H_Shaft) for i in range(0,int(H_Total//H_Shaft)-1)]
list_Altitude.insert(0,H_Total)

for i in range(0,len(list_Altitude)):
    i=list_Altitude
    new_list.extend(i)
new_list.sort(reverse=True)

OUT = list_Altitude,new_list

Cordially
christian.stan

1 Like

@Nick_Boyts @christian.stan @c.poupin

In reality this script is extract from another longer script that I can’t post for the moment
If you noticed the script I’ve set a parameter n which allow me to define the length of my levels list out from which I can iterate to compute the offset distances H_offset and the main purpose to be able to place my family instances in each level (I’ve two family instances, the height of the first is H_Shaft and should be placed from level 0 to level n-1 and the second which have the height =1 should be placed at level n)…the reason for which I should compute the offset distance H_offset and compare it to H_Shaft to be able to place the second instance in the last level if H_offset < H_Shaft

Thanks.

It should answer what you are looking for


Script:

import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import math
H_Total=IN[0]
H_Shaft=IN[1]

new_list=[]


if H_Total%H_Shaft>0:
    list_Altitude=[i*H_Shaft+H_Shaft for i in range(0,int(H_Total//H_Shaft))]
else:
    list_Altitude=[i*H_Shaft+H_Shaft for i in range(0,int(H_Total//H_Shaft)-1)]
list_Altitude.insert(len(list_Altitude),H_Total)
list_Altitude.insert(0,0)

level_list=['Niv_'+str(i+1)+'_Alt ' + "%.3f"%j for i,j in zip(range(0,len(list_Altitude)),list_Altitude)]

list_Altitude.sort(reverse=True)
for i in range(0,len(list_Altitude)):
    i=list_Altitude
    new_list.extend(i)
new_list.sort(reverse=True)

OUT = list_Altitude,level_list,new_list

Have a good evening
Cordially
christian.stan

1 Like

@christian.stan

Thank you Christian you’ve inspired me to find a solution how to place my family instances in their corresponding level using python function (zip)

here my principal script where I created my family instances…I still have some tweaking to do because I can’t land on the correct count of the family instance Fut1 (I always end up having 1 more extra if the remaining Height from the division H_2 = H_Total / H_Shaft is not equal to 0) since each instance is related to the level below it

  1. If H_2 = 0 I got an error in the script which tell me H_2 is not defined that its logic…so how to fix this error?

Please check my script and my dyn file below

import sys
import clr
import math
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
clr.AddReference('RevitNodes')
import Revit
from Revit.Elements import *

R_exter_Shaft = IN[0]
Thk_Shaft = IN[1]
R_inter_Shaft = R_exter_Shaft - Thk_Shaft 
H_Total = IN[2]
H_Shaft = IN[3]
Thk_Slab = IN[4]
H_1 = H_Shaft - Thk_Slab
Family_Cat = IN[5]
Family_Path = IN[6]
Material = IN[7]
Family1_name = 'Shaft1'
Family2_name = 'Shaft2'
Long_Trape = 0.8
angle_Trape = math.degrees(math.atan((Long_Trape/2) / R_inter_Shaft))

# Set Levels_List

if H_Total % H_Shaft > 0:
    H_Level = [ i * H_Shaft + H_Shaft for i in range(0, int(H_Total //H_Shaft))]
    
    #compute the remaining Height H_2 from the divison (H_Total / H_Shaft)
    H_2 = H_Total - H_Level[-1]
else:
    H_Level = [ i * H_Shaft + H_Shaft for i in range(0, int(H_Total //H_Shaft) - 1)]
#H_Level.insert(len(H_Level),H_Total)
H_Level.insert(0,0)

#Shaft1_Profil
lst1 = []
Pt1 = Point.ByCoordinates( R_exter_Shaft, 0, -Thk_Slab)
lst1.append(Pt1)
Pt2 = Point.ByCoordinates( R_exter_Shaft, 0, H_1)
lst1.append(Pt2)
Pt3 = Point.ByCoordinates( R_inter_Shaft , 0, H_1)
lst1.append(Pt3)
Pt4 = Point.ByCoordinates( R_inter_Shaft , 0, -Thk_Slab)
lst1.append(Pt4)
vector = Vector.ByCoordinates(0, 0, 1)
Center_pt = Point.ByCoordinates(0, 0, 0)
Shaft1_Profil = Polygon.ByPoints(lst1)
Shaft1 = Solid.ByRevolve(Shaft1_Profil, Center_pt, vector, 0, 360)

#Shaft2_Profil
lst2 = []
Pt_1 = Point.ByCoordinates( R_exter_Shaft, 0, -Thk_Slab)
lst2.append(Pt_1)
Pt_2 = Point.ByCoordinates( R_exter_Shaft, 0, H_2)
lst2.append(Pt_2)
Pt_3 = Point.ByCoordinates( R_inter_Shaft , 0, H_2)
lst2.append(Pt_3)
Pt_4 = Point.ByCoordinates( R_inter_Shaft , 0, -Thk_Slab)
lst2.append(Pt_4)
vector = Vector.ByCoordinates(0, 0, 1)
Center_pt = Point.ByCoordinates(0, 0, 0)
Shaft2_Profil = Polygon.ByPoints(lst2)
Shaft2 = Solid.ByRevolve(Shaft2_Profil, Center_pt, vector, 0, 360)

Slab_Profil = Surface.ByPatch(Circle.ByCenterPointRadius(Center_pt, R_inter_Shaft ))
Slab = Surface.Thicken(Slab_Profil, -Thk_Slab, bool(0))

# opening profil to be subtract from the slab
Trape_arc = Arc.ByCenterPointRadiusAngle(Center_pt, R_inter_Shaft, -angle_Trape, angle_Trape, vector )
Pt1 = Trape_arc.StartPoint
Pt2 = Trape_arc.EndPoint
Pt3 = Pt1.Translate(-Long_Trape)
Pt4 = Pt2.Translate(-Long_Trape)
Line1 = Line.ByStartPointEndPoint(Pt3, Pt4)
Line2 = Line.ByStartPointEndPoint(Pt3, Pt1)
Line3 = Line.ByStartPointEndPoint(Pt4, Pt2)

Profil_Trape = Surface.ByPatch(PolyCurve.ByJoinedCurves([Line1, Line2, Trape_arc, Line3]))
Trape = Surface.Thicken(Profil_Trape, Thk_Slab, bool(0))

Finale_Slab = Solid.Difference(Slab, Trape)

# Shaft1 geometry and Family Type
lst3 = [Shaft1, Finale_Slab]
Final_Shaft1 = Solid.ByUnion(lst3)
Final_Shaft1 = Geometry.Scale(Final_Shaft1, 0.3048)
Final_Shaft1 = FamilyType.ByGeometry(Final_Shaft1, Family1_name, Family_Cat, Family_Path, Material, 'a')

# Shaft2 geometry and Family Type
lst4 = [Shaft2, Finale_Slab]
Final_Shaft2 = Solid.ByUnion(lst4)
Final_Shaft2 = Geometry.Scale(Final_Shaft2, 0.3048)
Final_Shaft2 = FamilyType.ByGeometry(Final_Shaft2, Family2_name, Family_Cat, Family_Path, Material, 'a')

# create Revit Levels
k = 0
Niv = []
for i in H_Level:
    k += 1
    Lev = Level.ByElevationAndName(i, 'Niveau ' + str(k))
    Niv.append(Lev)
    print(Lev)

H_Level.sort(reverse=True)

#create and place family Instances Fut1 and Fut2 in their corresponding levels
Fut = []
for i, j in zip(Niv, H_Level):
    Fut1 = FamilyInstance.ByPointAndLevel(Final_Shaft1, Point.ByCoordinates(-R_exter_Shaft, -R_exter_Shaft, 0), i )
    H_offset = j
    print(Fut1)
    Fut.append(Fut1)
    if H_offset < H_Shaft:
        Fut2 = FamilyInstance.ByPointAndLevel(Final_Shaft2, Point.ByCoordinates(-R_exter_Shaft, -R_exter_Shaft, 0), i )
        print(Fut2)
        Fut.append(Fut2)

OUT = Fut

Shaft_python.dyn (23.5 KB)

Thanks.

1 Like

hello, You have to try as much as possible to avoid (subjects with evolving questions), for all the people who use the magnifying glass (it quickly becomes unusable), bounce on a thread already created it seems to me in this case. On this subject Mr. Nick, you brought a solution in his 2nd post with a while, and I have a hard time finding a solution with 2 for loops and list trituration (just to try another solution by for) I’ll take a look at it next weekend (I have overdue corrections)
Cordially
christian.stan

1 Like

I completely agree with @christian.stan. I’ll also add that while we may be happy to provide general solutions to your general problem (iteration of levels and heights), it’s often expected that you determine how it best fits the specifics of your exact scenario. We can’t keep updating a solution with every bit of information that you require, especially without seeing any major effort from your side.

If any of these responses have answered your initial question then please mark it as the solution. If you have follow-up questions concerning additional steps then you can create a new thread (referencing this one if you think that’s helpful).

1 Like

@Nick_Boyts

I’ve created a new thread How to place family Instances according to the levels below them in python and reference this one

Thanks