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

Not all curtain walls behaving equally

Message 1 of 4
345 Views, 3 Replies

Not all curtain walls behaving equally

I've made an addin to dimension curtain walls, and in my test projects it was working fairly well. That's to say, tagging worked 100% (easy win), but elevation tags and dimensioning didn't always work (let's say 70% or 80% worked for me, but for some users and some projects 100% produced the same failure).


The problem is that I'm not getting the total widths of these windows, in rare cases the total hights, or the bottom reference for spot elevations. I'm getting the references based on physical mullion faces with a certain normal, for mulions that work in a certain direction (this works very well, generally, if I need all unfiltered references). It's probably where I filter out the exterior faces that I make a mistake.


Example of how I do my filtering:


 foreach (Face fa in faces)

 Mullion m = doc.GetElement(fa.Reference) as Mullion;
LocationPoint lp = m.Location as LocationPoint;
Reference r = fa.Reference;

if (direction == Direction.horizontal) { if (lp.Point.Z == bb.Min.Z && !minAdded && fa.ComputeNormal(new UV(0, 0)).X > 0) { totaalMaten.Append(r); minAdded = true; } if (lp.Point.Z == bb.Max.Z && !maxAdded && fa.ComputeNormal(new UV(0, 0)).X > 0) { totaalMaten.Append(r); maxAdded = true; } } else if (direction == Direction.vertical) { if (lp.Point.X == bb.Min.X && !leftAdded && fa.ComputeNormal(new UV(0, 0)).X > 0) { totaalMaten.Append(r); leftAdded = true; } if (lp.Point.X == bb.Max.X && !rightAdded && fa.ComputeNormal(new UV(0, 0)).X > 0) { totaalMaten.Append(r); rightAdded = true; } }

The Normal is always relative to the mullion interior coordinates; in short this is filtering the faces that are looking out. But apparently, this is not an adequate method in all situations.


Does anyone know whether there can be a difference between curtain walls that makes them behave differently? Sidenote: is there a more reliable way to get the exterior references (say, by bounding box)? Thanks in advance.



Message 2 of 4
in reply to: bweinreder

And I found my own answer.

What's vexing me is that these references don't have GlobalPoints, or I would've stumbled upon this quicker.


The error is in this part of the filtering:

if (lp.Point.Z == bb.Min.Z */.../*)


I'm not sure whether it's due to the conversion between imperial and metric, but I forgot the fundamental rule that you can't always directly compare two XYZ values.


I replaced the condition with this:


if (Math.Abs(lp.Point.Z - bb.Min.Z) < 0.005 */.../*)

which translates to a tolerance of about 1.5mm. Could've probably added three more zeroes there but this is precise enough for our case.


Message 3 of 4
in reply to: bweinreder

Thank you Bram for raising this issue and sharing the solution!


Preserved for posterity by The Building Coder:






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

Message 4 of 4
in reply to: jeremytammik


When it comes to curtain walls, there's precious little documentation to find. But I now figured out what's the best way to evaluate mullions (however, the panels might be a different story).

Summarized: filtering mullions by orientation can be done best based on its curve, and probably the endpoints. This can be extracted from the mullions LocationCurve. These are project-based coordinates.


If you want to get front- and back faces, compare against the wall's Orientation. Faces can be extracted by converting the mullion to a GeometryElement, iterate trough its GeometryInstances, get the GeometryElement from it again, iterate through its GeometryObjects and convert that to a Solid which will have a FaceArray. This IMO is quite a tedious process to figure out.

The Face will have a Normal which can be computed given a UV.

From a face you can compute relative (Face.ComputeNormal(new UV(0.5, 0.5))) and absolute (GeometryInstance.Transform.OfVector(Face.ComputeNormal(new UV(0, 0)))) normals. A relative Normal with a positive X is always looking out, not sure where Y and Z are pointing, but I'm guessing +Y/-Y are the front- and back faces, and +Z/-Z are the start- and end planes.


If you have several mullion panels in horizontal or vertical direction, then the mullions will be segmented. In my case I wanted to only reference one mullion segment. This is how I did it:


            ReferenceArray mullionReferences = new ReferenceArray();
            List<double> mullionPositions= new List<double>();

            foreach (Face fa in faces)
                Mullion m = doc.GetElement(fa.Reference) as Mullion;
                LocationPoint lp = m.Location as LocationPoint;
                double refPt = direction == Direction.horizontal ? lp.Point.Z : lp.Point.X;

                if (mullionPositions.Where(p => p - refPt < 0.005 && p - refPt > -0.005).Count() < 2)
                    mullionReferences .Append(fa.Reference);

I add a product of its position to a list (based on the mulion's direction), and if that position (or one close to it) is already in a list twice then that mullion segment gets ignored. Otherwise the face reference is added to a ReferenceArray. Since I'm iterating through mullions to extract the faces, this is a reliable solution.


I'm sure this can be explained a lot clearer, and it would probably help many people if this was documented somewhere.

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

Post to forums  

Autodesk Customer Advisory Groups

Rail Community