Hi all,
I am trying to create a foundation slab according to existing room boundaries and I'm getting some wierd results.
If you look at the attached document I have included a macro for this:
Applying it to room 1 works fine
Applying to room 2 gets a funky shape
Applying to room 3 throws an error
I have included a commented out line that draws model lines and used it instead of creating slabs, it works fine for all rooms!
I don't know what am I doing wrong.
Here is my macro code:
public void floorByRoom() { Document doc = this.Document; Selection sel = this.Selection; List<ElementId> roomIdList = new List<ElementId>() ; //Checking if there is an existing selection if (sel.Elements.IsEmpty) // If no selection is present prompt for it { roomIdList.Clear(); RoomSelectionFilter gridSelFilter = new RoomSelectionFilter(doc); IList<Reference> roomRefList = sel.PickObjects(ObjectType.Element,gridSelFilter,"Select rooms"); foreach (Reference r in roomRefList){ roomIdList.Add(r.ElementId); } } else // If a selection is present filter the rooms out of it { FilteredElementCollector collector = new FilteredElementCollector(doc,sel.GetElementIds()); roomIdList=collector.OfCategory(BuiltInCategory.OST_Rooms).ToElementIds().ToList(); } // Get a floor type for floor creation FilteredElementCollector floorTypeCollector = new FilteredElementCollector(doc); floorTypeCollector.OfClass(typeof(FloorType)).OfCategory(BuiltInCategory.OST_StructuralFoundation); FloorType floorType = floorTypeCollector.FirstElement() as FloorType; Transaction t = new Transaction(doc,"Floor by rooms"); t.Start(); foreach (ElementId rmId in roomIdList) { Room rm = doc.GetElement(rmId) as Room; Parameter rmLvlParam = rm.get_Parameter("Level"); ElementId rmLvlId = rmLvlParam.AsElementId(); ElementId viewLvlId = doc.ActiveView.GenLevel.Id; if (rmLvlId==viewLvlId){ SpatialElementBoundaryOptions bo = new SpatialElementBoundaryOptions(); SketchPlane sp = doc.ActiveView.SketchPlane; CurveArray roomsCurves = new CurveArray(); // Array to hold curv data collected from room boundreis foreach (IList<Autodesk.Revit.DB.BoundarySegment> lstBs in rm.GetBoundarySegments(bo)) { foreach (Autodesk.Revit.DB.BoundarySegment bs in lstBs) { roomsCurves.Append(bs.Curve); } } // Uncomment the next line to model floor (doesnt work) //doc.Create.NewFoundationSlab(roomsCurves,floorType,doc.GetElement(viewLvlId) as Level,true,XYZ.BasisZ); foreach (Curve c in roomsCurves) doc.Create.NewModelCurve(c,sp); } } t.Commit(); } }
And after I solve this problem I want your advise on what is the appropreate method to apply an offset to the curves before creating the geometry, I have tried to use the Clipper library (http://www.angusj.com.......) and I have got some good results with rooms with straight boundary segments, but unfortunately this library does't seem to deal with arc segments.
Any suggestions are appreciated 🙂
Cheers,
Samer
Solved! Go to Solution.
Solved by jeremytammik. Go to Solution.
Dear Samer,
The problems are probably caused by the holes.
I believe you can initially only create a floor slab without holes, i.e. using a boundary loop without additional interior loops.
Here is an in-depth discussion of that:
Unfortunately, the only known current solution is to add the interior boundary loops after creating a slab with no holes, by adding openings later.
Regarding the offset question, you are in luck:
http://thebuildingcoder.typepad.com/blog/2014/04/whats-new-in-the-revit-2015-api.html#4.09
The new method:
creates a new curve that is offset from the original curve by a certain distance. The offset direction is determined by the normal of the curve at any given point.
I hope this helps.
Best regards,
Jeremy
Dear Jeremy,
Thanks for the swift answer, I actually found the info you referred to after I posted this, and it was a big disappointment for me to know that it was some sort of an API shortage, since I have been struggling with this for a few days trying not to do this task manually, and eventually the client is pissed off by the delay.
Anyways, I finally wrapped it up using the opening approach, abandoning the attempt to acquire Arcs and used Curve.Tessalate() instead, this also allowed me to make use of the Clipper library I mentioned earlier to apply an offset to the curves. Should do the job for now.
As for the 2015 API ... well... HALLELUJAH!!, but unfortunately, the project in hand is in Revit 2014 and I'm not allowed to convert it.. Shame!
Thanks again for your support,
Samer
Hi,
quick addition from experimenting with room to floor conversion:
it seems that revit has some "built-in" feature to "weld" room edges if they're not exactly closed..
however this caused some issues to me,
if you extract the room boundary curves and build a floor from them for example, then those tiny litlle patches will cause issues.
(because these curves can't be shorter than a certain threshold)
this issue is causing an area accuracy problem,
in other word: the room area will be different from the floor area (even if you trace it in user intercae -not programatically-)
Dear Ammwolma,
If you're using the curve.Tessellate() method to extract the curves you will get slightly different floor area and shape from rooms with curves boundary segments. Otherwise, I haven't yet encountered a notable difference between room area and the area of a floor sketched exactly to the room's boundary, unless the room calculation rules were set to wall center lines or any option other than wall finish face and the floor was sketched to wall finish face.
Cheers,
Samer
Using the IFCutils assembly included in Revit one can use the sort the curves method, and pass only the outer curves into a new curve array and avoid that error.