Room get_Geometry, But Not Area get_Geometry?

I am trying to get the geometry from Areas (not Area Boundaries). You can get Rooms from the Element.Geometry node, no problem, but not Areas. Revit Lookup clearly shows that both have the Geometry there, but I can’t figure out how to access it. Preferably, I want Lines as opposed to solids. Any help is appreciated. Here are a few screen shots for context:





@lorhal ,

when realy want an area from tags you have to use boundingbox

or you want areas from room(solids/surfaces)?

KR
Andreas

Hi @Draxl_Andreas, I am looking for Area geometry (that have been tagged) not the tag itself (or Rooms). I can’t use bounding boxes because the shapes are not all rectangles/squares. Sorry for the confusion!

Hi @lorhal …you could try something,

1 Like

Hi @sovitek , sorry, I am looking for Area Geometry, not Boundaries.
The problem with Boundaries is the lines often overshoot when Areas are contiguous, so they are not truly representative of the shape and actual dimensions (and often do not form a closed loop). That is the main reason why I am looking for the Geometry property. I want to be able to region fill/mask Areas according to certain parameters. Boundaries won’t give me closed loops consistently. I’ve tried splitting up the lines at intersections, but then you lose track of which line belongs to which Area.

If there is a Python solution, that would be great too. Maybe there is an Option() flag along the lines of @c.poupin’s post? Frankly, I have to wonder if there is a quirk in the Revit API (no surprise there), because Rooms and Areas have different creation methods. But, they are both Elements, so the Geometry property should be available, right? BTW, I am using Revit 2021.1.7 if that makes a difference.

Not sure an area can be open,so far i know spaces and rooms have volume, area have no volume only boundery i think,

Yes, I think you are correct that Areas don’t have volume, but they do have a Planar Face, which breaks down to Edges, Lines and XYZ:

It’s all there in Revit Lookup. One thing I may not quite understand is that there are two “View = Document.ActiveView” entries, one “including Geometry”. That entry has most of the goodies, and I’m thinking this is the…Non-Visible Geometry? How do you get that?

1 Like

I do not thing there will be a direct conversion, as if memory serves the Dynamo node utilizes visible geometry, which areas don’t ever have.

The planar face (surface) should be equal to what is recreated from the boundaries by creating a patch. You may need to group curves and trim with edge loops to account for donut objects. Are you seeing different?

That now makes sense I’m getting empty lists. Is there a node that calls the IncludeNonVisibleObjects option?

I will also revisit my Python script, which will post later once I debug. If I can get *anything *that represents the true geometry (not Area Boundary lines) I can take it from there.

Not that I know of.

Why are you after that surface in particular?

1 Like

It is part of an automation to mask specific Areas depending on certain shared parameter values. We need to redact certain Areas for security while keeping others visible.
This is part of that SDM/Revit workflow I have mentioned in other posts.
Using Area Boundaries to create the masked regions doesn’t work, as stated previously. Also, we have to use Areas (not Rooms or Spaces) due to their unique functionality.

I’ve seen a few get_Geometry() Python examples with the Options() arg, so I’ll try to make that work.

Something like:

areaGeo = []
for area in areas:
    opt = Options()
    opt.IncludeNonVisibleObjects
    geo = area.get_Geometry(opt)
    areaGeo.append(geo)

The Geometry property is in Area Class, so surely there is a way.

1 Like

Rhythm has a node which pulls the curves of the surface which may be of use - Area.Boundaries.

This pulls the curves which you’re after to define the filled region.

1 Like

Hi @lorhal …sounds good…but dont understand why your area bounderies doesnt work…as they should always be closed and if so its probably sort the order…does it work if you take the area modelcurve directly instead of use area bounderies node…

1 Like

@jacob.small , @sovitek
Sorry to be a stickler on this but, boundaries don’t work for my purposes. Because they don’t work, the Rhythm node, Area.Boundaries, (and any others of the same function) also will not work:


 /// This node will retrieve the area's boundaries. The first list is typically the outermost boundaries.
        /// </summary>
        /// <param name="area">The area to extract curves from.</param>
        /// <returns name="boundaries">The boundaries.</returns>
        /// <search>
        /// Area.Boundaries
        /// </search>
        [NodeCategory("Query")]
        public static List<List<Autodesk.DesignScript.Geometry.Curve>> Boundaries(global::Revit.Elements.Element area)
        {
            Autodesk.Revit.DB.Area internalArea = (Autodesk.Revit.DB.Area)area.InternalElement;

            var boundaries = new List<List<Autodesk.DesignScript.Geometry.Curve>>();
            foreach (var segments in internalArea.GetBoundarySegments(new SpatialElementBoundaryOptions()))
            {
                var boundary = new List<Autodesk.DesignScript.Geometry.Curve>();

                foreach (Autodesk.Revit.DB.BoundarySegment segment in segments)
                {
                    boundary.Add(segment.GetCurve().ToProtoType());
                }

                boundaries.Add(boundary);
            }

            return boundaries;
        }

I’m a big fan of @john_pierson, maybe he can chime in?

I thought I made it clear previously why this is the case, but here is another attempt:

Area Boundaries, although they fully enclose the Area…

  • Don’t necessarily represent the actual geometry of the Area.

*** You can have one boundary line that borders multiple areas.**

  • Because of this, my script won’t work as intended, as it hinges on selecting and masking Areas that match certain shared parameters.

Believe it or not, the Revit models where I will be using this script contain almost no building objects. They are automatically generated from a spreadsheet that was created by an FME Workspace which queries an Oracle Spatial database. @jacob.small , we have chatted about this.
These models, of which there will be ~1,000, represent actual buildings managed by my organization. They consist of levels, boundaries, Areas, Rooms, gross area extrusions, linked CAD floor plans and various data specific to occupancy. The only actual objects are antennas, parking spaces and floors, which represent the interior gross boundary. So, imagine a floor plan that has boundary lines and Areas superimposed on a linked CAD file. It looks almost exactly like a regular Revit floor plan.

Yes, this is unorthodox, but it works! The added bonus is they are very light and usually between 10-50MB in size. This whole thing is now part of a national program which ties into a larger real estate system.

I’m in the mountains right now, but will post a pic soon that may help to explain better.

But at this point, it’s a matter of principle:

  • An Area is an Element in Revit API.

  • It says right in the docs that Geometry is one of it’s Properties.

  • There is a method to get this geometry: get_Geometry(Options())

  • @jeremytammik posted an exhaustive explanation of how it works in …2010

So, in my view, there is no reason why the (non-visible) Geometry of an Area cannot be obtained. If there is, I have yet to see it.

Hello,
here, an example analyzing geometry

import clr
import sys
import System
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS

clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

def find_area_view_by_area(area):
	"""
	Finds the view associated with a given area.

	:param area: The area element to find the view for.
	:type area: DB.Area

	:returns: The view associated with the given area.
	:rtype: DB.View
	"""
	filterFunc = System.Predicate[System.Object](lambda v : v.ViewType == ViewType.AreaPlan)
	areaViews = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Views).WhereElementIsNotElementType().ToElements().FindAll(lambda x :filterFunc(x) )
	for v in areaViews:
		idRule = ParameterFilterRuleFactory.CreateEqualsRule(ElementId(BuiltInParameter.ID_PARAM), area.Id )
		idFilter = ElementParameterFilter(idRule)
		elemIdInView = FilteredElementCollector(doc, v.Id).WherePasses(idFilter).ToElementIds()
		if area.Id in elemIdInView:
			return v

def get_lines_GeometryArea(area):
	"""
	Gets the geometry lines for a given area.

	:param area: The area element to get the geometry lines for.
	:type area: DB.Area

	:returns: The geometry lines for the given area.
	:rtype: List[DS.Line]
	"""
	lines = []
	opt = Options()
	opt.IncludeNonVisibleObjects = True
	opt.View = find_area_view_by_area(area)
	geoSet = area.get_Geometry(opt)
	for g in geoSet:
		if isinstance(g, Solid):
			for f in g.Faces:
				for curvloop in f.GetEdgesAsCurveLoops():
					for line in curvloop:
						lines.append(line.ToProtoType())
	opt.Dispose()
	return lines
	
OUT = get_lines_GeometryArea(UnwrapElement(IN[0]))

I can’t reproduce this in any circumstances for areas, as they require placing the lines themselves unlike rooms which have some fudge factor built in. Can you post a reproducible case, just for educational and testing purposes?

Hi @jacob.small,
Here is a Dynamo script that I think will be helpful.
AgencyThematic_WithMasking.dyn (63.6 KB)

Many thanks to @c.poupin who, once again, got me out of a jam!

The Revit files are too big to upload, but my screen shots should illustrate the issue.

Looking at the Dynamo script again, I found the Area.Boundaries node will give you Area boundaries regardless of any overshoot, except in certain conditions.

Here, we see a large Area selected with both the Area.Boundaries and @c.poupin 's Python script in action. This is the “Unfixed” Revit file:

What I found was that another Area adjacent to this one had a zero-length line that affected the larger one:
BndryVsGeom_Unfixed

There were no warnings that indicated anything wrong. This is where the overshoot theory originated. I guess my hunch was technically correct, in that it had to do with boundary line problems. Once the line was fixed, the Area boundary came through:

Something I didn’t realize, Area geometries are offset +5 feet on Z. That should not be an issue for me, but it is good to know if you expect them to be at the same elevation as an Area.Boundaries node output .

Although ideally these problem boundaries should be fixed prior to running Dynamo, if there are no warnings how can you? The get_Geometry Python script acts as an error handler, it only cares that there is a valid Area.

If you unfreeze the rest of the Dynamo script, it will prompt you to select an ABCode parameter value (I imagine you would change it to a parameter you have), and then generate a filled region over any Areas not the selected value.


Thanks, everybody, for their input. I learned a few things!

2 Likes