Creating a floor or foundation slab using room boundary segments

samernajjar
Contributor
Contributor

Creating a floor or foundation slab using room boundary segments

samernajjar
Contributor
Contributor

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

 

2014-09-01_10-27-45.jpg

 

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

0 Likes
Reply
Accepted solutions (1)
3,164 Views
5 Replies
Replies (5)

jeremytammik
Autodesk
Autodesk
Accepted 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:

 

http://thebuildingcoder.typepad.com/blog/2013/07/create-a-floor-with-an-opening-or-complex-boundary....

 

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

 

Geometry API additions

 

Curve

 

The new method:

 

  • Curve.CreateOffset()

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



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

samernajjar
Contributor
Contributor

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

0 Likes

Anonymous
Not applicable

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-)

 

 

0 Likes

samernajjar
Contributor
Contributor

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

 

 

0 Likes

luisPDAN6
Advocate
Advocate

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.

0 Likes