And here we are… 2021 finally! Freedom is on the horizon (if you squint really hard), although hard to see it amidst yet another national lock-down and Covid V2.0 running amok the streets of London.

So, with not much else to do other than hibernate over this Christmas holiday, regret having that third helping of Roast Turkey and vowing to get fit a week later, I thought I would actually start using some of the mathematics I’ve picked up over the past year or so while doing my degree, after all, there is no point learning applied mathematics unless you actually apply it, right?!

Well, if I’m honest, I had several bits I wanted to get done over xmas. One was continuing a silly game I made (Draftees vs Zombies – I’ll write about this at some point when it’s a little more fleshed out – pun intended). The other item on my list was to extend the Revit API’s Geometry methods. This has always been something that I found lacking and something that was sort of solved when Dynamo entered the scene. BUT, what about Devs that need the functionality of Dynamo but in a Plug-In. Well, there are a few options here… You can either use a third party .net geometry library and write an adapter between their respective Object Models (pretty good idea), wait for Autodesk to allow the Dynamo Engine to run within a plugin or integrate it yourself if you are savvy enough… or you can just write your own geometry methods. Can you guess which one I did?

The latter of course! I thought it would be a good opportunity to go deeper into 3D geometry and solidify my understanding of maths in the 3rd dimension (my degree hasn’t yet covered 3D and probably won’t until the much later). Since I program in 3D space a LOT as I’m also a Unity Dev, having a firm grasp in 3D space is fundamental.

Turns out 3D isn’t that hard after all – especially if you have a relatively solid understanding of vectors and matrices. I have bundled all the little utilities I made into a Library – this is an extension Library, so version of Revit doesn’t really matter as it only extends the classes that already exist in the Revit API. This project so far includes the following but is mostly focused on Planes…

  • Intersections
    • Plane/Plane/Plane
      • Given a Bundle of planes, calculates the intersection point if there is one. This could be useful for validating the location of an Element or could be used to place/correct the position of Elements in situations where it is difficult in 2D. See demo below.
    • Plane/Plane
      • Given a Sheaf of Planes, calculates the intersection line of these planes. Line is bound to the overall extents of the model – a BoundingBox that circumscribes all Elements, but could easily be modified to be Unbound. This could be useful for validating if say the location of a raking column is indeed in-plane for 2 planes. Or could be used to calculate the placement of a beam based on 2 faces and an offset in 3D. See demo below.
    • Plane/Line
      • The Intersection between a Line and a Plane. This allows for apparent intersection or only where plane intersects the Line Segment.
  • Line Utils
    • Vertical Plane
      • A plane that passes vertically through the given Line.
    • Horizontal Plane
      • A Plane that passes horizontally through the Line. This is with respect to the global BasisZ axis.
    • Plane perpendicular to Line
      • Creates a Plane at a particular Parameter on a Line Segment that is perpendicular to the Line. This is with respect to the global BasisZ Axis.
    • Point/Line Tests
      • PointWithinBounds
        • A test to determine if the given point lies upon the Line Segment.
      • IsPointOnLine
        • A test to determine if a Point is indeed on the Line. Optional argument for testing if within the bounds of the Line Segment.
    • Some other minor tests methods.
  • Conversion
    • Level.AsPlane
      • Converts a Level to a Plane.
    • Grid.AsPlane
      • Converts a Grid to a Plane.
    • ReferencePlane.AsPlane
      • Converts a Reference Plane to a Plane.
    • Face.AsPlane
      • Converts a Face to a Plane. If the Face is not a PlanarFace, then the Face will be evaluated at the given UV and a Plane constructed at that parameter.
    • Plane.ToReferencePlane
      • Creates a Reference Plane from the given Plane. This is useful for creating Reference Planes based on a face by 3 points in 3D. See demo below.
  • BoundingBox
    • Document.GetExtents
      • Document Extension Method to get a BoundingBox that circumscribes all Elements or all given Elements. This was liberated and tweaked from Jeremy Tammiks post. See demo below.
    • Profile.BoundingBox
      • Profile Extension Method that gets the BoundingBox that circumscribes all the curves in a Profile.
  • Structural Framing
    • Get Preset Positions
      • A utility to get one of the preset positions of a beam (say Top-Left, Middle-Right, Bottom-Centre etc). This is based on the actual geometry of the profile along the beam and not the LocationCurve of the beam. This means even if you have applied justification to your beam, it will still return the correct position. See demo below.

Here are some demo’s of some of these utilities in action…

Triple Plane Intersections
Plane/Plane Intersections
Create Reference Planes in 3D
Get Preset Positions of a Beam

Well, that’s about it. Like I said, mostly Plane methods as I find these the most useful. You can find the project here if you are interested and I hope to cover some of the maths (both python and C# examples) in later posts. However, if you are interested in the maths, there is a really good blog by Parametric Zoo (I found this after I had written half these utilities – but was a good read nevertheless), they are using Faces to get intersections which is really cool, especially if you are using geometry other than Lines/Planes.

I hope you find this useful and thanks for reading! 🙂