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: 

Floor Profile slightly off axis after creating floors from room boundaries where walls off axis. How can i amend?

Message 1 of 3
265 Views, 2 Replies

Floor Profile slightly off axis after creating floors from room boundaries where walls off axis. How can i amend?

I am trying to fix off axis lines by modification of the curves taken from a room boundary, at the finish edges.

The following below runs to completion however it does nothing, its within a loop that is within a transaction so i am assuming i dont need another transaction and just i havent ported this correctly from rotating grids to rotating curves. To test i have created a room with some of its walls rotated by .005 and .00000001, The last is picked up as off axis internally be revit and the method below is returning an angle that is different from an orthogonal room.


Also perhaps i should post-process the curves from the floor profile and align them after the floor is created? 



private static Curve AlignOffAxisCurve(Curve curve)
XYZ direction = curve

double distance2hor = direction.DotProduct(XYZ.BasisY);
double distance2vert = direction.DotProduct(XYZ.BasisX);
double angle = 0;

double max_distance = 0.0001;

if (Math.Abs(distance2hor) < max_distance)
XYZ vector = direction.X < 0
? direction.Negate()
: direction;

angle = Math.Asin(-vector.Y);

if (Math.Abs(distance2vert) < max_distance)
XYZ vector = direction.Y < 0
? direction.Negate()
: direction;

angle = Math.Asin(vector.X);

TaskDialog.Show("Angle", "Angle: "+ angle.ToString());

Curve newCurve;
if (angle.CompareTo(0) != 0)
XYZ pt1 = curve.GetEndPoint(0);
XYZ pt2 = curve.GetEndPoint(1);

Transform rotate = Transform.CreateRotationAtPoint(pt1.Add(XYZ.BasisZ), angle, pt1);

XYZ pt1New = rotate.OfPoint(pt1);
XYZ pt2New = rotate.OfPoint(pt2);
Line newLine = Line.CreateBound(pt1New, pt2New);

newCurve = newLine;
newCurve = curve;

return newCurve;

Message 2 of 3

Thank you for raising this interesting question.


I see you also posted a comment to discuss it on The Building Coder:



I prefer to continue the discussion here instead, since the Revit API forum is more frequented than The Building Coder comments.


I think the goal is a very valid one. 


I can imagine that simpler solutions are possible. 


Personally, the only solution I have developed and used myself in the past to clean up geometry goes as follows:


Clean up all the vertices to exact millimetre based integer coordinates.


Given some input geometry A, I wish to generate a very similar output geometry B, but cleaned up in some way, e.g., to align all edges with the principal axes, as you describe. To do so, I iterate over all the XYZ vertices of A. For each vertex P encountered, I calculate an integer-based vertex Q that lies very close to P. I have a dictionary using the integer-based points as keys. Being integers, exact comparison of vertices is possible. I eliminate all floating point errors and requirements for fuzz and tolerance in comparison operators.


Each vertex of A is mapped to an integer-based point close by, more or less within a cubic millimetre of the original.


If that kind of precision (or imprecision) is enough to clean up your off-axis room boundaries, it would probably be a lot easier to implement and a lot more performant than the kinds of calculations that you are currently performing.


Depending of the requirements of your model, you could also increase the grid size from one mm to two, or three, or five, ten or even more. I would not go below one millimetre, though, because that corresponds pretty well with the minimal line length length allowed in a Revit model.


The Building Coder samples includes a class IntPoint3d, and the external command CmdListAllRooms makes use of it.



For an example of creating a dictionary using these points as keys, though, you will have to look elsewhere in The Building Coder:



To apply this to your room boundary situation, note that you do not even need 3D coordinates, just 2D onese, since your room boundaries have a constant Z elevation:


  • Define a dictionary D mapping IntPoint2d to anything you like. The value is irrelevant, I often just use a count of how often the vertex was used.
  • Iterate over the room boundaries. Apparently, your boundaries are all just straight line segments. That makes it all very simple.
  • Map each start and end point to the closest IntPoint2d. Very short segments may be eliminated.
  • Generate new XYZ vertices and new room boundary lines using the keys of D.


Jeremy Tammik, Developer Advocacy and Support, The Building Coder, Autodesk Developer Network, ADN Open
Message 3 of 3

They did away with (hid) the short curve tolerance failure (SCT) for some things.


When you move an element by a small amount likely the failure still happens internally but is masked. I know in the past making such minor movements threw the SCT exception in the API.


You had to instead exaggerate the movement by moving away by a distance (say 2xSCT) and then move it back to final position. 

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

Post to forums  

Autodesk Customer Advisory Groups

Rail Community