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