SlideShare a Scribd company logo
1 of 8
Download to read offline
By WOJCIECH KLEPACKI wklepa@gmail.com 
  It’s very common situation in real life scenario when we receive a structure model from the 
engineers and the structure columns don’t “cut” the room areas. It can be safely omitted when the 
column has a small section footprint, like double T or C. But when the footprint has a significant size 
it  might  cause  the  inaccuracy  in  room  areas  calculation.  Basically,  to  solve  this  issue,  one  must 
manually draw separation lines along the column perimeters. This is tedious, boring and human error 
vulnerable task. But it’s an ideal example how the automation can solve this almost seamlessly. 
 
  On  a  picture  below  I’m  presenting  exactly  what  I’m  looking  for.  Putting  manually  the 
separation lines is a simple operation for few columns. It can take more time for multi‐storey building 
especially when the section shape varies from the floor to floor.  
 
  Here is my solution based on the Dynamo. I want to share my idea in easy to follow way, 
hopefully. The basic understanding of the Dynamo and Design Scripting language is compulsory. 
  This is a snapshot with an overall look of the script. It’s divided into parts doing a series 
of connected tasks thereabouts. I prefer writing scripts in Dynamo using the Design Script Language. 
It’s based on the Code Blocks enriched with classic nodes in places when I either used the custom or 
By WOJCIECH KLEPACKI wklepa@gmail.com 
third‐party nodes or when I decided to leave them for code clarity. It’s a matter of a good practice to 
plug watch nodes to monitor the outcome in critical locations. 
 
  The whole idea of this script is to keep the user inputs on the very low level, almost “zero‐
touch‐code”. The first part shown below selects the plans from the model. Subsequently, it extracts 
the associated levels from the plans. It gives only one unique plan per level as an output. This data is 
necessary  to  draw  the  room  separation  lines  because  this  is  the  way  how  the 
RoomSeparator.FromCurve works. This node plays the crucial part in the workflow. 
 
  In the beginning, I must collect all the views in the model: 
 
  Then I’m cleaning the potential “nulls” in the view names. Subsequently, I’m splitting the view 
names to extract the real names. 
By WOJCIECH KLEPACKI wklepa@gmail.com 
 
  Now, I should consider only the views associated with the plans, filter the “empty” levels if 
any and group plans by the levels. I’m doing this because I want to use this information later to match 
with the levels associated with the structural columns. 
 
  This is the outcome I’m looking for: 
By WOJCIECH KLEPACKI wklepa@gmail.com 
 
  For the second logical part of the script I want to collect all the structural columns, find their 
locations, detect the intersection between the column geometry and the sketch plane related to every 
level and finally generate the room separation lines. 
  I’m  starting  from  collecting  all  the  elements  from  the  category  “Structural  Columns”.  If 
necessary, I can filter them by family type or another parameter later. Now, we are interested in 
gathering all the columns, hence the filtering is not required. 
 
  Next, let’s use a very well‐known chunk of the code to group the columns by levels: 
 
  Now, I’m using the instance parameter “Base Level” values to extract the information about 
the levels from the columns. I need to create a sketch plane; this step is compulsory because of the 
RoomSeparator.FromCurve utilises this data to create room separation lines. Finally, I’m bringing the 
columns geometry into Dynamo to intersect with a sketch plane. Because it performs better than the 
built‐in  Surface.PerimeterCurves  node,  I’m  using  the  Surfaces.DeconstructSurface  node  from 
LunchBox  package.  Please  pay  attention  that  it  gives  a  series  of  surfaces  as  a  resultant  of  the 
intersection.  
By WOJCIECH KLEPACKI wklepa@gmail.com 
 
  Subsequently. I’m matching the levels assigned to columns with the plans related to these 
same levels: 
 
  The next part is little tricky to follow if you haven’t seen it before. Pay attention, that inside 
the code, there are pieces of script related to extracting the information from the particular level of 
the nested lists. Instead of using List.Map node I’m using “@‐2<1>” syntax in Code Block. This is 
basically equal to “Use Levels” procedure in a classic node: 
 
Once you get familiar with this, it becomes very easy to follow. The “@‐3<1>” will apply a 
function on the third level of the nested list accordingly. 
 
  The code above performs the flatten of the nested list. This list is reversed on the sublevel 
because I need to consider only the external outline if column “walls” has thickness. The tricky piece 
By WOJCIECH KLEPACKI wklepa@gmail.com 
performs the checking; if only one curve exists on a list take this curve (the column is solid and has the 
circular section)  if  four curves  are on a  list take them  as they are  (the column  is solid  and has  a 
polygonal section). In case of more than four curves are on the list take exactly half of them (the other 
half is responsible for the inner thickness lines). This assumption is a limitation I put on a script (please 
refer to the comment at the end of this article). In case of dealing with a column with 8 – sides polygon 
footprint, this portion of code must be changed. 
cntIdx=lstCnt==1? 0: lstCnt==4? 3: (lstCnt/2)‐1; 
defRng=0..cntIdx; 
  This bit of code counts the curves on the list. It’s necessary because I need to convert a circular 
footprint to the two arcs. The reason is the RoomSeparator.FromCurve accepts only lines and curves. 
Subsequently, I want to extract the centres of the columns and if columns have a circular footprint, 
the end point of the radiuses. Please, pay attention that these are not radiuses themselves, only the 
points on the perimeter of the circles. 
 
  Once I have this information extracted, I need to calculate the real radiuses. I’m using the 
length of vector function to solve this. This vector spans between the centre point of the circle and 
the point on its perimeter. To divide a circle into two arcs, I have to split it into four points first. I’m 
using the 4 – sides rectangular polygon to get the points. I’m extracting these points from the sublevel 
of the list using the described “@‐level<1>” method. The first arc has points with indexes 0,1,2 for the 
start, middle and the end. The second arc has 2,3,0 accordingly. Both of the arcs represent the circular 
column. I put some comments on the Code Block to make it clearer. Please take your time to analyse 
the code. 
 
 
 
By WOJCIECH KLEPACKI wklepa@gmail.com 
 
 
 
  The Dynamo itself lacks abilities to “sew” more complex lists together. The built‐in nodes like 
List.ReplaceItemAtIndex or ReplaceByCondition failed to solve the issue, I decided to write a custom 
ZIP Lists node in Python. The goal was to replace the single curves with two arcs to compose a full 
circle. The outcome is shown below: 
 
By WOJCIECH KLEPACKI wklepa@gmail.com 
  This is what the Python script is doing in a background. Initially, my intention was to write a 
script using plain “for in” loop but I was advised on the Stack Overflow forum, that using “for in zip” 
function performs better. 
 
  The last portion of the script utilises the RoomSeparator.FromCurve node from the Clockwork 
package. This node generates an error when the curve type is a circle. It must be replaced by the two 
arcs or polygon. Just one more thing must be done to make it work. Make sure that the Lacing is set 
to Longest. In case this node is fed with well‐prepared data it should give a positive outcome. 
 
  The script does the brilliant job for some general cases however, there is always a room for 
improvements. One can be interested in adding a chunk of code to detect the overlapping room 
separation line for instance. The other thing worth to mention is that the script will work only for the 
general and most common column footprints. It will generate separation lines for circles, tubes, and 
4  –  sides  rectangular  and  non‐rectangular  polygons.  It  may  fail  for  complex  shapes  composed  of 
multiple arc segments or ellipses. I decided to consider these specific cases separately mainly because 
they are not very common. 
  For the purpose of this  exercise,  I’m  detecting the structure columns  placed directly  in a 
model.  It’s  not  very  complicated  to  rearrange  the  script  to  collect  the  elements  from  the  linked 
models. I suggest using nodes from the outstanding BimorphNodes package for instance: 
 

More Related Content

Similar to Create room separations lines for the structure columns

What is 3 d modeling unit 66
What is 3 d modeling   unit 66What is 3 d modeling   unit 66
What is 3 d modeling unit 66
Richard Marshall
 
3D Final Work
3D Final Work3D Final Work
3D Final Work
conor0994
 
Jonathan Jones Mae377 Project03
Jonathan Jones Mae377 Project03Jonathan Jones Mae377 Project03
Jonathan Jones Mae377 Project03
spiffyjj115
 

Similar to Create room separations lines for the structure columns (20)

Datt2500 week5
Datt2500 week5Datt2500 week5
Datt2500 week5
 
How to draw mechanical parts correctly
How to draw mechanical parts correctly How to draw mechanical parts correctly
How to draw mechanical parts correctly
 
Software Engineering: Models
Software Engineering: ModelsSoftware Engineering: Models
Software Engineering: Models
 
What is 3 d modeling unit 66
What is 3 d modeling   unit 66What is 3 d modeling   unit 66
What is 3 d modeling unit 66
 
3D Final Work
3D Final Work3D Final Work
3D Final Work
 
Why you should consider a microframework for your next web project
Why you should consider a microframework for your next web projectWhy you should consider a microframework for your next web project
Why you should consider a microframework for your next web project
 
Create a camera view by room
Create a camera view by roomCreate a camera view by room
Create a camera view by room
 
Sbwire 531031
Sbwire 531031Sbwire 531031
Sbwire 531031
 
How architectures fail, and what to do about it
How architectures fail, and what to do about itHow architectures fail, and what to do about it
How architectures fail, and what to do about it
 
CAD/CAM ppt
CAD/CAM pptCAD/CAM ppt
CAD/CAM ppt
 
what is CAD
what is CADwhat is CAD
what is CAD
 
Responsive Design: Out of the Box and Down the Rabbit Hole
Responsive Design: Out of the Box and Down the Rabbit HoleResponsive Design: Out of the Box and Down the Rabbit Hole
Responsive Design: Out of the Box and Down the Rabbit Hole
 
3 d modelling
3 d modelling3 d modelling
3 d modelling
 
Solid-Surface Hybrid Modeling: Future Trends of 3D CAD Modeling
Solid-Surface Hybrid Modeling: Future Trends of 3D CAD ModelingSolid-Surface Hybrid Modeling: Future Trends of 3D CAD Modeling
Solid-Surface Hybrid Modeling: Future Trends of 3D CAD Modeling
 
Datt2500 week3
Datt2500 week3Datt2500 week3
Datt2500 week3
 
DevOne - How to not fail with Azure
DevOne - How to not fail with AzureDevOne - How to not fail with Azure
DevOne - How to not fail with Azure
 
Jonathan Jones Mae377 Project03
Jonathan Jones Mae377 Project03Jonathan Jones Mae377 Project03
Jonathan Jones Mae377 Project03
 
Software Architecture Stories
Software Architecture StoriesSoftware Architecture Stories
Software Architecture Stories
 
Architecting for Change: An Agile Approach
Architecting for Change: An Agile ApproachArchitecting for Change: An Agile Approach
Architecting for Change: An Agile Approach
 
Intro to AutoCAD
Intro to AutoCADIntro to AutoCAD
Intro to AutoCAD
 

More from Wojciech Klepacki (9)

Format any sequence of numbers
Format any sequence of numbersFormat any sequence of numbers
Format any sequence of numbers
 
Controlling the visibility in a Revit family
Controlling the visibility in a Revit familyControlling the visibility in a Revit family
Controlling the visibility in a Revit family
 
Bialystok
BialystokBialystok
Bialystok
 
Sopot
SopotSopot
Sopot
 
Detal rynny
Detal rynnyDetal rynny
Detal rynny
 
BRAWO_portfolio
BRAWO_portfolioBRAWO_portfolio
BRAWO_portfolio
 
ZDZ_portfolio
ZDZ_portfolioZDZ_portfolio
ZDZ_portfolio
 
MROZA_portfolio
MROZA_portfolioMROZA_portfolio
MROZA_portfolio
 
DAMIR_portfolio
DAMIR_portfolioDAMIR_portfolio
DAMIR_portfolio
 

Recently uploaded

Team Transformation Tactics for Holistic Testing and Quality (NewCrafts Paris...
Team Transformation Tactics for Holistic Testing and Quality (NewCrafts Paris...Team Transformation Tactics for Holistic Testing and Quality (NewCrafts Paris...
Team Transformation Tactics for Holistic Testing and Quality (NewCrafts Paris...
Lisi Hocke
 

Recently uploaded (20)

Abortion Clinic Pretoria ](+27832195400*)[ Abortion Clinic Near Me ● Abortion...
Abortion Clinic Pretoria ](+27832195400*)[ Abortion Clinic Near Me ● Abortion...Abortion Clinic Pretoria ](+27832195400*)[ Abortion Clinic Near Me ● Abortion...
Abortion Clinic Pretoria ](+27832195400*)[ Abortion Clinic Near Me ● Abortion...
 
Modern binary build systems - PyCon 2024
Modern binary build systems - PyCon 2024Modern binary build systems - PyCon 2024
Modern binary build systems - PyCon 2024
 
Evolving Data Governance for the Real-time Streaming and AI Era
Evolving Data Governance for the Real-time Streaming and AI EraEvolving Data Governance for the Real-time Streaming and AI Era
Evolving Data Governance for the Real-time Streaming and AI Era
 
Prompt Engineering - an Art, a Science, or your next Job Title?
Prompt Engineering - an Art, a Science, or your next Job Title?Prompt Engineering - an Art, a Science, or your next Job Title?
Prompt Engineering - an Art, a Science, or your next Job Title?
 
Community is Just as Important as Code by Andrea Goulet
Community is Just as Important as Code by Andrea GouletCommunity is Just as Important as Code by Andrea Goulet
Community is Just as Important as Code by Andrea Goulet
 
Team Transformation Tactics for Holistic Testing and Quality (NewCrafts Paris...
Team Transformation Tactics for Holistic Testing and Quality (NewCrafts Paris...Team Transformation Tactics for Holistic Testing and Quality (NewCrafts Paris...
Team Transformation Tactics for Holistic Testing and Quality (NewCrafts Paris...
 
Rapidoform for Modern Form Building and Insights
Rapidoform for Modern Form Building and InsightsRapidoform for Modern Form Building and Insights
Rapidoform for Modern Form Building and Insights
 
Software Engineering - Introduction + Process Models + Requirements Engineering
Software Engineering - Introduction + Process Models + Requirements EngineeringSoftware Engineering - Introduction + Process Models + Requirements Engineering
Software Engineering - Introduction + Process Models + Requirements Engineering
 
Auto Affiliate AI Earns First Commission in 3 Hours..pdf
Auto Affiliate  AI Earns First Commission in 3 Hours..pdfAuto Affiliate  AI Earns First Commission in 3 Hours..pdf
Auto Affiliate AI Earns First Commission in 3 Hours..pdf
 
Wired_2.0_CREATE YOUR ULTIMATE LEARNING ENVIRONMENT_JCON_16052024
Wired_2.0_CREATE YOUR ULTIMATE LEARNING ENVIRONMENT_JCON_16052024Wired_2.0_CREATE YOUR ULTIMATE LEARNING ENVIRONMENT_JCON_16052024
Wired_2.0_CREATE YOUR ULTIMATE LEARNING ENVIRONMENT_JCON_16052024
 
Abortion Clinic In Pretoria ](+27832195400*)[ 🏥 Safe Abortion Pills in Pretor...
Abortion Clinic In Pretoria ](+27832195400*)[ 🏥 Safe Abortion Pills in Pretor...Abortion Clinic In Pretoria ](+27832195400*)[ 🏥 Safe Abortion Pills in Pretor...
Abortion Clinic In Pretoria ](+27832195400*)[ 🏥 Safe Abortion Pills in Pretor...
 
Abortion Clinic In Stanger ](+27832195400*)[ 🏥 Safe Abortion Pills In Stanger...
Abortion Clinic In Stanger ](+27832195400*)[ 🏥 Safe Abortion Pills In Stanger...Abortion Clinic In Stanger ](+27832195400*)[ 🏥 Safe Abortion Pills In Stanger...
Abortion Clinic In Stanger ](+27832195400*)[ 🏥 Safe Abortion Pills In Stanger...
 
AzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdf
AzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdfAzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdf
AzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdf
 
Your Ultimate Web Studio for Streaming Anywhere | Evmux
Your Ultimate Web Studio for Streaming Anywhere | EvmuxYour Ultimate Web Studio for Streaming Anywhere | Evmux
Your Ultimate Web Studio for Streaming Anywhere | Evmux
 
GraphSummit Milan - Visione e roadmap del prodotto Neo4j
GraphSummit Milan - Visione e roadmap del prodotto Neo4jGraphSummit Milan - Visione e roadmap del prodotto Neo4j
GraphSummit Milan - Visione e roadmap del prodotto Neo4j
 
Anypoint Code Builder - Munich MuleSoft Meetup - 16th May 2024
Anypoint Code Builder - Munich MuleSoft Meetup - 16th May 2024Anypoint Code Builder - Munich MuleSoft Meetup - 16th May 2024
Anypoint Code Builder - Munich MuleSoft Meetup - 16th May 2024
 
Food Delivery Business App Development Guide 2024
Food Delivery Business App Development Guide 2024Food Delivery Business App Development Guide 2024
Food Delivery Business App Development Guide 2024
 
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...Navigation in flutter – how to add stack, tab, and drawer navigators to your ...
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...
 
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit Milan
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit MilanWorkshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit Milan
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit Milan
 
A Deep Dive into Secure Product Development Frameworks.pdf
A Deep Dive into Secure Product Development Frameworks.pdfA Deep Dive into Secure Product Development Frameworks.pdf
A Deep Dive into Secure Product Development Frameworks.pdf
 

Create room separations lines for the structure columns

  • 1. By WOJCIECH KLEPACKI wklepa@gmail.com    It’s very common situation in real life scenario when we receive a structure model from the  engineers and the structure columns don’t “cut” the room areas. It can be safely omitted when the  column has a small section footprint, like double T or C. But when the footprint has a significant size  it  might  cause  the  inaccuracy  in  room  areas  calculation.  Basically,  to  solve  this  issue,  one  must  manually draw separation lines along the column perimeters. This is tedious, boring and human error  vulnerable task. But it’s an ideal example how the automation can solve this almost seamlessly.      On  a  picture  below  I’m  presenting  exactly  what  I’m  looking  for.  Putting  manually  the  separation lines is a simple operation for few columns. It can take more time for multi‐storey building  especially when the section shape varies from the floor to floor.       Here is my solution based on the Dynamo. I want to share my idea in easy to follow way,  hopefully. The basic understanding of the Dynamo and Design Scripting language is compulsory.    This is a snapshot with an overall look of the script. It’s divided into parts doing a series  of connected tasks thereabouts. I prefer writing scripts in Dynamo using the Design Script Language.  It’s based on the Code Blocks enriched with classic nodes in places when I either used the custom or 
  • 2. By WOJCIECH KLEPACKI wklepa@gmail.com  third‐party nodes or when I decided to leave them for code clarity. It’s a matter of a good practice to  plug watch nodes to monitor the outcome in critical locations.      The whole idea of this script is to keep the user inputs on the very low level, almost “zero‐ touch‐code”. The first part shown below selects the plans from the model. Subsequently, it extracts  the associated levels from the plans. It gives only one unique plan per level as an output. This data is  necessary  to  draw  the  room  separation  lines  because  this  is  the  way  how  the  RoomSeparator.FromCurve works. This node plays the crucial part in the workflow.      In the beginning, I must collect all the views in the model:      Then I’m cleaning the potential “nulls” in the view names. Subsequently, I’m splitting the view  names to extract the real names. 
  • 3. By WOJCIECH KLEPACKI wklepa@gmail.com      Now, I should consider only the views associated with the plans, filter the “empty” levels if  any and group plans by the levels. I’m doing this because I want to use this information later to match  with the levels associated with the structural columns.      This is the outcome I’m looking for: 
  • 4. By WOJCIECH KLEPACKI wklepa@gmail.com      For the second logical part of the script I want to collect all the structural columns, find their  locations, detect the intersection between the column geometry and the sketch plane related to every  level and finally generate the room separation lines.    I’m  starting  from  collecting  all  the  elements  from  the  category  “Structural  Columns”.  If  necessary, I can filter them by family type or another parameter later. Now, we are interested in  gathering all the columns, hence the filtering is not required.      Next, let’s use a very well‐known chunk of the code to group the columns by levels:      Now, I’m using the instance parameter “Base Level” values to extract the information about  the levels from the columns. I need to create a sketch plane; this step is compulsory because of the  RoomSeparator.FromCurve utilises this data to create room separation lines. Finally, I’m bringing the  columns geometry into Dynamo to intersect with a sketch plane. Because it performs better than the  built‐in  Surface.PerimeterCurves  node,  I’m  using  the  Surfaces.DeconstructSurface  node  from  LunchBox  package.  Please  pay  attention  that  it  gives  a  series  of  surfaces  as  a  resultant  of  the  intersection.  
  • 5. By WOJCIECH KLEPACKI wklepa@gmail.com      Subsequently. I’m matching the levels assigned to columns with the plans related to these  same levels:      The next part is little tricky to follow if you haven’t seen it before. Pay attention, that inside  the code, there are pieces of script related to extracting the information from the particular level of  the nested lists. Instead of using List.Map node I’m using “@‐2<1>” syntax in Code Block. This is  basically equal to “Use Levels” procedure in a classic node:    Once you get familiar with this, it becomes very easy to follow. The “@‐3<1>” will apply a  function on the third level of the nested list accordingly.      The code above performs the flatten of the nested list. This list is reversed on the sublevel  because I need to consider only the external outline if column “walls” has thickness. The tricky piece 
  • 6. By WOJCIECH KLEPACKI wklepa@gmail.com  performs the checking; if only one curve exists on a list take this curve (the column is solid and has the  circular section)  if  four curves  are on a  list take them  as they are  (the column  is solid  and has  a  polygonal section). In case of more than four curves are on the list take exactly half of them (the other  half is responsible for the inner thickness lines). This assumption is a limitation I put on a script (please  refer to the comment at the end of this article). In case of dealing with a column with 8 – sides polygon  footprint, this portion of code must be changed.  cntIdx=lstCnt==1? 0: lstCnt==4? 3: (lstCnt/2)‐1;  defRng=0..cntIdx;    This bit of code counts the curves on the list. It’s necessary because I need to convert a circular  footprint to the two arcs. The reason is the RoomSeparator.FromCurve accepts only lines and curves.  Subsequently, I want to extract the centres of the columns and if columns have a circular footprint,  the end point of the radiuses. Please, pay attention that these are not radiuses themselves, only the  points on the perimeter of the circles.      Once I have this information extracted, I need to calculate the real radiuses. I’m using the  length of vector function to solve this. This vector spans between the centre point of the circle and  the point on its perimeter. To divide a circle into two arcs, I have to split it into four points first. I’m  using the 4 – sides rectangular polygon to get the points. I’m extracting these points from the sublevel  of the list using the described “@‐level<1>” method. The first arc has points with indexes 0,1,2 for the  start, middle and the end. The second arc has 2,3,0 accordingly. Both of the arcs represent the circular  column. I put some comments on the Code Block to make it clearer. Please take your time to analyse  the code.       
  • 7. By WOJCIECH KLEPACKI wklepa@gmail.com          The Dynamo itself lacks abilities to “sew” more complex lists together. The built‐in nodes like  List.ReplaceItemAtIndex or ReplaceByCondition failed to solve the issue, I decided to write a custom  ZIP Lists node in Python. The goal was to replace the single curves with two arcs to compose a full  circle. The outcome is shown below:   
  • 8. By WOJCIECH KLEPACKI wklepa@gmail.com    This is what the Python script is doing in a background. Initially, my intention was to write a  script using plain “for in” loop but I was advised on the Stack Overflow forum, that using “for in zip”  function performs better.      The last portion of the script utilises the RoomSeparator.FromCurve node from the Clockwork  package. This node generates an error when the curve type is a circle. It must be replaced by the two  arcs or polygon. Just one more thing must be done to make it work. Make sure that the Lacing is set  to Longest. In case this node is fed with well‐prepared data it should give a positive outcome.      The script does the brilliant job for some general cases however, there is always a room for  improvements. One can be interested in adding a chunk of code to detect the overlapping room  separation line for instance. The other thing worth to mention is that the script will work only for the  general and most common column footprints. It will generate separation lines for circles, tubes, and  4  –  sides  rectangular  and  non‐rectangular  polygons.  It  may  fail  for  complex  shapes  composed  of  multiple arc segments or ellipses. I decided to consider these specific cases separately mainly because  they are not very common.    For the purpose of this  exercise,  I’m  detecting the structure columns  placed directly  in a  model.  It’s  not  very  complicated  to  rearrange  the  script  to  collect  the  elements  from  the  linked  models. I suggest using nodes from the outstanding BimorphNodes package for instance: