Creating A Roof Using Revit APIs

Creating A Roof Using Revit APIs

aniket_pachore
Enthusiast Enthusiast
1,683 Views
20 Replies
Message 1 of 21

Creating A Roof Using Revit APIs

aniket_pachore
Enthusiast
Enthusiast

I am facing an issue while creating a roof using C# Revit APIs.
              I am automating the conversion of 2D AutoCAD drawings to Revit 3D models. The process involves reading data from AutoCAD drawings. I store the polylines (on which I want to create the roof) in a list, specifically List<PolyLine> roofPolyLineList, and pass it to my function. First, I convert the polyline into a CurveArray, CurveArray topFloorCurveArray = application.Create.NewCurveArray(), and pass it to the API. I am not getting any errors, but the roof is not created in Revit.
I have attached my code below.
Please help me to solve the issue.

private void CreateRoof(Document doc, List<Level> floorlevels, List<PolyLine> roofPolyLineList)
        {
            Application application = doc.Application;
            CurveArray topFloorCurveArray = application.Create.NewCurveArray();

            RoofType roofType= new FilteredElementCollector(doc).OfClass(typeof(RoofType)).FirstOrDefault<Element>() as RoofType;

            Transaction trans = new Transaction(doc, "Create Roof");
            trans.Start();
            {
                for (int i = 0; i < roofPolyLineList.Count; ++i)
                {
                    var points = roofPolyLineList[i].GetCoordinates();

                    for (int j = 0; j < points.Count - 1; j++)
                    {
                        var start = points[j];
                        var end = points[j + 1];
                        var line = Line.CreateBound(new XYZ(start.X, start.Y, start.Z), new XYZ(end.X, end.Y, end.Z));
                        topFloorCurveArray.Append(line);
                    }
                }

                for (int i = 0; i < floorlevels.Count; i++)
                {
                    int count = floorlevels.Count;
                    string name = "Floor " + (count - 1);
                    Level level = floorlevels[i];

                    if (level.Name == name)
                    {
                        ModelCurveArray footPrintToModelCurveMapping = new ModelCurveArray();
                        FootPrintRoof footprintRoof = doc.Create.NewFootPrintRoof(topFloorCurveArray, level, roofType, out footPrintToModelCurveMapping);

                        ModelCurveArrayIterator iterator = footPrintToModelCurveMapping.ForwardIterator();
                        iterator.Reset();
                        while (iterator.MoveNext())
                        {
                            ModelCurve modelCurve = iterator.Current as ModelCurve;
                            footprintRoof.set_DefinesSlope(modelCurve, true);
                            footprintRoof.set_SlopeAngle(modelCurve, 0.5);
                        }
                    }
                }
                doc.Regenerate();
                trans.Commit();
            }
        }

 

0 Likes
1,684 Views
20 Replies
Replies (20)
Message 2 of 21

Moustafa_K
Collaborator
Collaborator

I see your code is fine. Are you sure the level name matches your specifics, specifically at this part of the code

string name = "Floor " + (count - 1);
Level level = floorlevels[i];

if (level.Name == name)
{

 

Moustafa Khalil
Cropped-Sharp-Bim-500x125-Autodesk-1
Message 3 of 21

admaecc211151
Advocate
Advocate

A simple way is to show Messages or write log into a log file

to check where your code is running to there or not.

......

I thought you can replace

 

for (int i = 0; i < floorlevels.Count; i++)
{
    int count = floorlevels.Count;
    string name = "Floor " + (count - 1);
    Level level = floorlevels[i];
    if (level.Name == name)
    {
        ...;
    }
}
 
into
 
floorlevels = floorlevels.OrderBy(i => i.Elevation).ToList();
Level level = floorlevels[floorlevels.Count -1];
{
    ...;
}
 
Since you only want to create the roof in top level.
//or maybe not send a list, just a level into this function is better.
Message 4 of 21

aniket_pachore
Enthusiast
Enthusiast

Yes, the condition is fine; my pointer goes into the 'if' condition. The 'Level Name' matches the 'Expected Level Name'. The code in the 'if' condition also gets executed, but the roof doesn't get created.

 

DebugCode.JPG


My Question : Whether the API works for only wall selection, or it also takes the CurveArray (Closed Loop PolyLines) ?
Please help @admaecc211151@Moustafa_K 

0 Likes
Message 5 of 21

Moustafa_K
Collaborator
Collaborator

Surely it has to be closed loop. Try testing your method by supplying rectangle points. It should be 5 points to close the loop.

 

Moustafa Khalil
Cropped-Sharp-Bim-500x125-Autodesk-1
Message 6 of 21

aniket_pachore
Enthusiast
Enthusiast

Ok Sure, I will try and get back to you. Thank you.

0 Likes
Message 7 of 21

aniket_pachore
Enthusiast
Enthusiast

Hello @Moustafa_K,

I tried using a simple rectangle, but it still isn't working. I also checked that the lines I am adding to the CurveArray 'topFloorCurveArray' are appended in order and form a closed loop. Yes, they are in order and forms a closed loop.
@Moustafa_K 
DebugCode1.JPG

0 Likes
Message 8 of 21

jeremy_tammik
Alumni
Alumni

Have you looked at the Revit SDK NewRoof sample? It includes a call to set_DefinesSlope. Maybe that will give you some hints.

   

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 9 of 21

scgq425
Advocate
Advocate

hi @aniket_pachore : i saw u code is fine , in u rvt template the pashe is archite or all , may be u create it but the target view hidden it . u can open u filter to set this .

LanHui Xu 徐兰辉
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

Blog
LinkedIn
Revit/CAD Development | Steel Product Manager

EESignature

0 Likes
Message 10 of 21

aniket_pachore
Enthusiast
Enthusiast

Hi @scgq425 , 

                        I didn't get what you want to suggest me, you mean I have to open the project in "Architectural Template". yes I tried in "Architectural Template" also but it still not reflecting. 

0 Likes
Message 11 of 21

Charles.Piro
Advisor
Advisor

Hi @aniket_pachore,

in my view, your problem is in inside this loop :

 

for (int j = 0; j < points.Count - 1; j++)
{
   var start = points[j];
   var end = points[j + 1];
   var line = Line.CreateBound(new XYZ(start.X, start.Y, start.Z), new XYZ(end.X, end.Y, end.Z));
   topFloorCurveArray.Append(line);
}

 

At the end, the last Curve is missed.
With this loop, your code is functional :

for (int j = 0; j < points.Count; j++)
{
   var start = points[j];
   var end = new XYZ();
   if (j + 1 == points.Count)
   {
      end = points[0];
   }
   else
   {
      end = points[j + 1];
   }
   var line = Line.CreateBound(new XYZ(start.X, start.Y, start.Z), new XYZ(end.X, end.Y, end.Z));
   topFloorCurveArray.Append(line);
}

 

😉



PIRO Charles
Developer

PIRO CIE
Linkedin


Message 12 of 21

aniket_pachore
Enthusiast
Enthusiast

Hi @Charles.Piro ,

                                As I am trying for a simple rectangle input, I get total 5 point to close my loop. The loop was also closing using my previous code. I also tried using your code. You can see I get total 5 points from my Polyline, And it is creating four curves as I see while debugging. Still same problem I am Facing.

I have made small change in your code .
Previous for Loop,

for (int j = 0; j < points.Count; j++)

Changed for Loop,

for (int j = 0; j < points.Count - 1; j++)

Because of 5 Points.

DebugCode2.JPG

 

0 Likes
Message 13 of 21

Moustafa_K
Collaborator
Collaborator

Just a simple 5 points, no need for for loop, I just tested your code and seems fine with the five points. it looks like your inputs are not correct, could be a level or polyline

 

CreateRoof(Doc, aLevel.Id, new List<PolyLine>
{
     PolyLine.Create([XYZ.Zero,new XYZ(10,0,0), new XYZ(10,5,0 ),new  XYZ(0,5,0),XYZ.Zero])
});

 

Moustafa Khalil
Cropped-Sharp-Bim-500x125-Autodesk-1
Message 14 of 21

Charles.Piro
Advisor
Advisor

I have tried it with your data and it works fine for me.

I just removed the level name test.

 

😉



PIRO Charles
Developer

PIRO CIE
Linkedin


Message 15 of 21

aniket_pachore
Enthusiast
Enthusiast

Hi @Charles.Piro 

Everything looks fine to me: the level, the closed loop curve, etc.

I have a question: Is there a chance that elements are hidden by default?

                                  If so, how can I unhide them using programming?

Because from your side, you can see the roof, but from my side, I can't.

I am new to Revit, so your answer would be very helpful for me.

 

0 Likes
Message 16 of 21

aniket_pachore
Enthusiast
Enthusiast

Hi @Moustafa_K ,

                              I didn't get it, How could I directly Pass the polyline. 

0 Likes
Message 17 of 21

admaecc211151
Advocate
Advocate

I would check and fix every point in the polyline.

Check that the end of line n-1 is same to the start of line n.

Or just replace all the start of line n to the same point as end of line n-1.

Sometimes the points work good in Revit and Cad (the distance is 0.00(several zeros)001).

But too large for C# API.

 

 

Message 18 of 21

aniket_pachore
Enthusiast
Enthusiast

@admaecc211151 
Ok Sure, I will try and let you know. Thank you

0 Likes
Message 19 of 21

aniket_pachore
Enthusiast
Enthusiast

Hi @admaecc211151 ,

Yes, I did it what you suggested. I replaced the endPoint of previous curve with startPoint of current Curve, but still not working. 
I didn't get any type of error, and I cant see the roof. 

0 Likes
Message 20 of 21

aniket_pachore
Enthusiast
Enthusiast

Thanks a lot, @Moustafa_K, @Charles.Piro, @scgq425, @admaecc211151.

I was making a silly mistake. The problem was that I was using the default roof type, which was transparent, so I couldn't see it. I just chose another type, and the job is done.

 

aniket_pachore_0-1718901672920.png