Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Automatic Column Creation from Imported CAD Drawing

11 REPLIES 11
SOLVED
Reply
Message 1 of 12
kevin.anggrek
3046 Views, 11 Replies

Automatic Column Creation from Imported CAD Drawing

Hi all,

 

I have a CAD Drawing in DGN format that I have imported into a Revit Project. The drawing consists of columns, walls, beams, slabs, etc. My end goal is to create an API using C# to automatically create those elements in Revit from the CAD Drawing but i would like to start with columns. The following picture shows my Imported DGN drawing in Revit that I imported using the Insert > Import > Import CAD tools:

 

Untitled.png

 As with any other imported CAD drawing, all the geometrical objects in the imported CAD drawing is still joined together as one as shown below:

uvuv.png

 

After doing some study, I would like to do the following workflow in order to achieve my goal:

 

1. Filter for the columns by its specific Layer. 

After using the RevitLookup, I understand that the imported CAD drawing is of the ImportInstance Class and by going deeper, I can look at individual lines along with their GraphicStyleCategory which signify their Layer information. My question is: How to retrieve all of the geometrical objects (e.g. Line) from the imported CAD drawing and then filter based on the layer?

I saw an answer on an old thread: https://forums.autodesk.com/t5/revit-api-forum/how-to-create-beams-by-lines-from-dwg-linked-into-rev... but they were using PickObjects to pick individual elements in the imported CAD drawing. What I want to do is to retrieve all elements simultaneously.

I tried the following code to retrieve individual Line objects along with the layer name (GraphicStyleCategory.Name) but a Null reference was thrown stating that the GeometryElement is Null:

 

UIApplication uiapp = commandData.Application;
UIDocument uidoc = uiapp.ActiveUIDocument;
Document doc = uidoc.Document;
Options geoOptions = uiapp.Application.Create.NewGeometryOptions();

// Filter for all elements
FilteredElementCollector collector = new FilteredElementCollector(doc).WhereElementIsNotElementType();
StringBuilder sb = new StringBuilder();
foreach (Element elem in collector)
{
    GeometryElement geomElem = elem.get_Geometry(geoOptions);
    foreach (GeometryObject geomObj in geomElem)
    {
        if (geomObj is Line)
        {
            Line line = geomObj as Line;
            GraphicsStyle gStyle = doc.GetElement(line.GraphicsStyleId) as GraphicsStyle;
            sb.AppendLine(line.GraphicsStyleId.ToString() + "\t" + gStyle.GraphicsStyleCategory.Name+"\t"+line.Length.ToString());
        }
    }
}

 

Am I doing this correctly by using FilteredElementCollector to filter for all the elements from the imported CAD? Or is there other ways to do it?

 

2. Get the Column centroid/Location Point.

If I am able to filter for the column lines based on its layer, I would need the centroid of the column to create a new FamilyInstance for the column by using Document.Create.NewFamilyInstance Method (XYZ, FamilySymbol, Level, StructuralType). How to get the centroid information of each column in the imported DGN drawing? Should I get the Vertices of the column elements first? How can I achieve that?

 

3. Finally, Create the Columns by using Document.Create.NewFamilyInstance Method (XYZ, FamilySymbol, Level, StructuralType) Method.

 

 

That is all of what I can think for now. I would also like to receive some advice regarding this workflow because there might be another ways to create columns in Revit from imported CAD drawing that maybe I am not aware of. 

 

Thank you

Labels (1)
11 REPLIES 11
Message 2 of 12

after trying more by myself and trying to replicate what RevitLookup did, I can finally filter for the GeometryObjects in the imported CAD drawing by using the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using System.Windows.Forms;
using System.Drawing;

namespace DNGToRevitModeller
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    public class Command : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument uidoc = uiapp.ActiveUIDocument;
            Document doc = uidoc.Document;
            Autodesk.Revit.DB.View activeView = doc.ActiveView;
            Autodesk.Revit.DB.Options geomOption = uiapp.Application.Create.NewGeometryOptions();
            if (null != geomOption)
            {
                geomOption.ComputeReferences = true;
                geomOption.View = activeView;
            }

            FilteredElementCollector notElemTypeCtor = (new FilteredElementCollector(doc,activeView.Id)).WhereElementIsNotElementType().OfClass(typeof(ImportInstance));
           
            StringBuilder sb = new StringBuilder();

            foreach (Element elem in notElemTypeCtor)
            {
                GeometryElement geomElem = elem.get_Geometry(geomOption);
                foreach (GeometryObject geomObj in geomElem)
                {
                    GeometryInstance geomInst = geomObj as GeometryInstance;
                    GeometryElement symbolGeom = geomInst.GetSymbolGeometry();

                    foreach (GeometryObject gObj in symbolGeom)
                    {
                        if (gObj is Line || gObj is PolyLine)
                        {
                            GraphicsStyle gStyle = doc.GetElement(gObj.GraphicsStyleId) as GraphicsStyle;
                            sb.AppendLine(gObj.GraphicsStyleId.ToString() + "\t" + gStyle.GraphicsStyleCategory.Name);
                        }
                        
                    }

                    
                }
            }
            TaskDialog.Show("Revit", sb.ToString());
            return Result.Succeeded;
        }
    }
}

 

I think I can filter for the GeometryObjects for now and will later be able to filter the columns.

The problem in the second part of my workflow still persists. Even after getting the GeometryObjects of the Columns, How can I find the centroid of the columns to create a NewFamilyInstance for the column which requires the XYZ of the column centroid/Location point as input argument? Is there any workaround to this i.e. creating columns without its XYZ Location Point?

 

Thank you

Message 3 of 12
lukaskohout
in reply to: kevin.anggrek

If you have the outline curve of the column from the CAD, you should be able to get the vertices and then determine the centre of the column.

 

If the columns are rectangular (it seems that way to me from your pictures), it should be fairly simple.


Hitting Accepted Answer is a Community Contribution from me as well as from you.
======================================================================
Message 4 of 12
kevin.anggrek
in reply to: lukaskohout

Dear @lukaskohout,

 

Yes sir, after filtering for the specific Column Layer, I found out that the columns lines in the imported DGN are in the form of the PolyLine Class. Thus, I implemented the getCoordinates() Method of the PolyLine Class to get the Column Vertices and thus solve the problem!

 

Now I have successfully created columns automatically:

 

col.png

 

Thank you sir for taking an interest to the thread

Message 5 of 12

Hello man,

I was following the same logic that you followed to achieve the same goal and now I have a list of polylines that represents the column layer and a list of points that represents the middle points of these polylines.. so how can I reach familySymbol from the list of polylines and do I have to use foreach loop to pass the list of points ?! what is next ?

Message 6 of 12

Hi, sorry for the late reply

After obtaining the middle points of the columns, everything is basically set in stone.
In order to get the FamilySymbol of the Column, you can use the FilteredElementCollector to obtain the appropriate FamilySymbol.

In order to create the columns, you can loop for each middle point/column centroid and then in each iteration you will need to call the Document.Create.NewFamilyInstance() Method, passing the input arguments (the middle point, the FamilySymbol, the Level where the column is placed, and the StructuralType of the Family Instance).

I hope this answered your question, if you have further issues, please do not hesitate to ask

Message 7 of 12

Ok now I managed to create column types by extracting the unique values of width and height and put these types in a list of familySymbols and I already have a list of XYZ represents the center points of columns and also I have to lists of doubles one for widths and another one for heights .. How can I use the FilteredElementCollector to obtain the appropriate FamilySymbol from the list of familySymbols I created as you suggested? 

Message 8 of 12

IList<FamilySymbol> columnFamilyCtor = new FilteredElementCollector(M_doc)
                                                            .OfCategory(BuiltInCategory.OST_StructuralColumns)
                                                            .OfClass(typeof(FamilySymbol))
                                                            .Cast<FamilySymbol>()
                                                            .ToList();

 

Try this and see if it solve your problems

Message 9 of 12

I already have this list but I don't know how to use it yo loop for all center points and detect the suitable column type for this point from this list. 

maybe I'm terrible in illustration so excuse me.


@kevin.anggrek wrote:

 

IList<FamilySymbol> columnFamilyCtor = new FilteredElementCollector(M_doc)
                                                            .OfCategory(BuiltInCategory.OST_StructuralColumns)
                                                            .OfClass(typeof(FamilySymbol))
                                                            .Cast<FamilySymbol>()
                                                            .ToList();

 

 

Try this and see if it solve your problems



@kevin.anggrek wrote:

 

IList<FamilySymbol> columnFamilyCtor = new FilteredElementCollector(M_doc)
                                                            .OfCategory(BuiltInCategory.OST_StructuralColumns)
                                                            .OfClass(typeof(FamilySymbol))
                                                            .Cast<FamilySymbol>()
                                                            .ToList();

 

 

Try this and see if it solve your problems


 

Message 10 of 12

Sorry for the late reply, I was busy in the last 2 weeks.

 

Let me clarify your question again.

Right now, you have the list of Column Family, and the list of the center coordinate of the column. But you are wondering on how to create the column with the correct family for each center coordinate? Am I right?

 

In this case, what I did was use the Text Objects in CAD to convey the information on the column family (usually in a CAD file, drafters put the legend/text next to a column that indicate the column type/size). I loop through each center coordinate of the column, pair the center coordinate with the nearest Text object coordinate, find the suitable Revit column family based on the content of the text object, and then proceed to create a new column based on these input arguments.

Message 11 of 12

yes Sir, I used another technique by measuring the distances between points, and actually, It worked well but as you see the problem now is the direction of columns. I tried to rearrange points that I got from getCoordinates function after removing the fifth point of each polyLine but the result was much worse.ColumnsRotation.PNG

Message 12 of 12

You can share method create center point of polyline. Sorry I'm new learn revit API. Thanh kou sir.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community