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

XYZ question

11 REPLIES 11
SOLVED
Reply
Message 1 of 12
MGO-Norsyn
2583 Views, 11 Replies

XYZ question

Hi all

 

I find the XYZ class very confusing because it can be a point or a vector.

 

Does any body knows any good guide on how to use them? Or some documentation.

 

Also, I have a specific question, how does one extract start and end points of a XYZ vector?

 

Thanks

11 REPLIES 11
Message 2 of 12

You're right, the XYZ class can represent a point or a vector, which are in fact quite similar.

If you have a XYZ object and run a angle method, you're in fact handling a vector information... but if you just get a coordinate, then a point.

Finally a vector don't have start or end point as they represent a direction, not a line. If you need a line, use the Curve/Line object.
Regards,



Augusto Goncalves
Twitter @augustomaia
Autodesk Developer Network
Message 3 of 12
BobbyC.Jones
in reply to: MGO-Norsyn

I suggest rolling your own Point and Vector wrappers around it. It will make your code much easier to maintain.
--
Bobby C. Jones
Message 4 of 12
MGO-Norsyn
in reply to: BobbyC.Jones

Thats very interesting. Could you provide a little example?
Message 5 of 12
BobbyC.Jones
in reply to: MGO-Norsyn

The XYZ class defines methods that are specific to the concept of points and vectors.  The biggest problem I had was in reviewing our code; it was difficult to know which concept it was dealing with at any given time.

 

Another benefit of providing your own point and vector wrappers is that you can limit their interface to only methods that make sense.  All of this code compiles, but none of it makes any sense.

 

 

public static void PointAndVectorExample(Line revitLine)
{
    var lineOrigin = revitLine.Origin;
    var whatIstheLengthOfaPoint = lineOrigin.GetLength();
    var howIsaPointaUnitLength = lineOrigin.IsUnitLength();

    var lineDirection = revitLine.Direction;
    var whatDoesThisRepresent = lineDirection.CrossProduct(lineOrigin);
    var thisDoesntMakeSense = lineDirection.DistanceTo(lineOrigin);
}

 

Here are some PARTIAL Point3D and Vector3D classes to give you the idea.  And some helper extensions to make using them easier to use.  You can take these and wrap the appropriate XYZ methods for each as well as define additional methods of your own.  And even implement additional interfaces, such as IEquatable.

 

 

public class Point3D
{
    public Point3D(XYZ revitXyz)
    {
        XYZ = revitXyz;
    }

    public Point3D() : this(XYZ.Zero)
    {}

    public Point3D(double x, double y, double z) : this(new XYZ(x, y, z))
    {}

    public XYZ XYZ { get; private set; }

    public double X => XYZ.X;
    public double Y => XYZ.Y;
    public double Z => XYZ.Z;

    public double DistanceTo(Point3D source)
    {
        return XYZ.DistanceTo(source.XYZ);
    }

    public Point3D Add(Vector3D source)
    {
        return new Point3D(XYZ.Add(source.XYZ));
    }

    public static Point3D operator +(Point3D point, Vector3D vector)
    {
        return point.Add(vector);
    }

    public override string ToString()
    {
        return XYZ.ToString();
    }

    public static Point3D Zero => new Point3D(XYZ.Zero);
}

 

 

 

public class Vector3D
{
    public Vector3D(XYZ revitXyz)
    {
        XYZ = revitXyz;
    }

    public Vector3D() : this(XYZ.Zero)
    {}

    public Vector3D(double x, double y, double z)  : this(new XYZ(x, y, z))
    {}

    public XYZ XYZ { get; private set; }

    public double X => XYZ.X;
    public double Y => XYZ.Y;
    public double Z => XYZ.Z;

    public Vector3D CrossProduct(Vector3D source)
    {
        return new Vector3D(XYZ.CrossProduct(source.XYZ));
    }
        
    public double GetLength()
    {
        return XYZ.GetLength();
    }

    public override string ToString()
    {
        return XYZ.ToString();
    }

    public static Vector3D BasisX => new Vector3D(XYZ.BasisX);
    public static Vector3D BasisY => new Vector3D(XYZ.BasisY);
    public static Vector3D BasisZ => new Vector3D(XYZ.BasisZ);
}

 

 

 

public static class XYZExtensions
{
    public static Point3D ToPoint3D(this XYZ revitXyz)
    {
        return new Point3D(revitXyz);
    }

    public static Vector3D ToVector3D(this XYZ revitXyz)
    {
        return new Vector3D(revitXyz);
    }
}

 

 

public static class LineExtensions
{
    public static Vector3D Direction(this Line revitLine)
    {
        return new Vector3D(revitLine.Direction);
    }

    public static Point3D Origin(this Line revitLine)
    {
        return new Point3D(revitLine.Origin);
    }
}

 

 

 

--
Bobby C. Jones
Message 6 of 12
MGO-Norsyn
in reply to: BobbyC.Jones

Thank you. There's some stuff I'll have to learn. 🙂
Message 7 of 12
BobbyC.Jones
in reply to: MGO-Norsyn

Ha!  Don't we all have much to learn; I certainly do!  You're very welcome and I hope this helped get you started.  And don't hesitate to ask if you have any more questions.

--
Bobby C. Jones
Message 8 of 12
jeremytammik
in reply to: MGO-Norsyn

Edited and summarised for posterity:

 

http://thebuildingcoder.typepad.com/blog/2017/08/birthday-post-on-the-xyz-class.html

 

Cheers,

 

Jeremy



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

Message 9 of 12
BobbyC.Jones
in reply to: jeremytammik

Hi Jeremy,

Very cool!  In looking over that code I noticed a call to an extension method that I did not supply.  For completeness sake:

 

 

public static class DoubleExtensions
{
private const double Tolerance = 1.0e-10;
public static bool IsAlmostEqualTo(this double double1, double double2) {
var isAlmostEqual = Math.Abs(double1 - double2) <= Tolerance;

return isAlmostEqual; }
}

 

--
Bobby C. Jones
Message 10 of 12
jeremytammik
in reply to: BobbyC.Jones

Thank you!

 

Added to the post.

 

Cheers,

 

Jeremy



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

Message 11 of 12
MGO-Norsyn
in reply to: jeremytammik

Thank you very much for help on this topic. I've finally come around to implement the ConnectorXYZComparer in my codez and, while developing a new utility which at one point seeks to find distinct pipe connectors based on location in space by comparing Connector.Origin which is a XYZ, I have discovered that some connectors can have a much larger tolerance than the 1.0e-9 which is used in the BuildingCoder samples and utils.

 

In my test set, which is around 800 connectors, I got 32 false negatives. The largest delta is at 0.0004... ft. See the attached text file for my test results. So the HashString method from the ConnectorXYZComparer, which writes the coordinates to 9th decimal place returns slightly different hashstrings for connectors at the same location, but with large deltas. Also the Equals method operating with 1.0e-9 tolerance is returning false negatives.

 

So anybody using the Comparer provided by Jeremy is going to have some false negatives and wrong results when working with XYZs from MEP connectors.

 

To fix this I had to up the tolerance on the Equals method to 0.00328 ft -> roughly 1 mm, which is okay, because I will never have two distinct groups of connectors at distances lower than 1 mm, and I could probably have set it even higher safely.

 

Second part is that the hash string has to have only two decimals or else I was getting with four decimals:

(13.6971,19.1862,11.0728)
(13.6971,19.1866,11.0728)

And with three decimals:

(13.697,19.186,11.073)
(13.697,19.187,11.073)

I *HOPE* that two decimals is enough to cover the wildest imaginable tolerance for Revit piping Connectors...

Message 12 of 12
jeremytammik
in reply to: MGO-Norsyn

Dear Mgo,

 

Thank you for your update, research and results.

 

I agree that 1 mm is a sensible threshold to use.

 

In fact, I often an integer-based coordinate system by rounding every single coordinate value to the closest millimetre when processing Revit models:

 

 

Best regards,

 

Jeremy

 



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

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

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community