Dear Richard,
Personally, I have no idea why, and I don't really care all that much.
In my humble opinion, both DistanceTo and IsAlmostEualTo leave something to be desired.
Therefore, I don't use them except in trivial situations where I don't care too much about the exact result.
If I care about the result, I prefer to use my own methods that I can control and understand, e.g.:
#region Geometrical Comparison
public const double _eps = 1.0e-9;
public static double Eps
{
get
{
return _eps;
}
}
public static double MinLineLength
{
get
{
return _eps;
}
}
public static double TolPointOnPlane
{
get
{
return _eps;
}
}
public static bool IsZero(
double a,
double tolerance = _eps )
{
return tolerance > Math.Abs( a );
}
public static bool IsEqual(
double a,
double b,
double tolerance = _eps )
{
return IsZero( b - a, tolerance );
}
public static int Compare(
double a,
double b,
double tolerance = _eps )
{
return IsEqual( a, b, tolerance )
? 0
: (a < b ? -1 : 1);
}
public static int Compare(
XYZ p,
XYZ q,
double tolerance = _eps )
{
int d = Compare( p.X, q.X, tolerance );
if( 0 == d )
{
d = Compare( p.Y, q.Y, tolerance );
if( 0 == d )
{
d = Compare( p.Z, q.Z, tolerance );
}
}
return d;
}
/// <summary>
/// Predicate to test whewther two points or
/// vectors can be considered equal with the
/// given tolerance.
/// </summary>
public static bool IsEqual(
XYZ p,
XYZ q,
double tolerance = _eps )
{
return 0 == Compare( p, q, tolerance );
}
public static bool IsParallel( XYZ p, XYZ q )
{
return p.CrossProduct( q ).IsZeroLength();
}
public static bool IsCollinear( Line a, Line b )
{
XYZ v = a.Direction;
XYZ w = b.Origin - a.Origin;
return IsParallel( v, b.Direction )
&& IsParallel( v, w );
}
public static bool IsHorizontal( XYZ v )
{
return IsZero( v.Z );
}
public static bool IsVertical( XYZ v )
{
return IsZero( v.X ) && IsZero( v.Y );
}
public static bool IsVertical( XYZ v, double tolerance )
{
return IsZero( v.X, tolerance )
&& IsZero( v.Y, tolerance );
}
...
From:
https://github.com/jeremytammik/the_building_coder_samples/blob/master/BuildingCoder/BuildingCoder/U...
As you can see, they are all pretty trivial to implement.
In general, you will require different tolerances in different contexts and to handle different situations.
So, for any complex task, you will certainly fare better implementing your own comparison operators.
I find that more useful than asking why.
I hope this helps.
'Ours is not to wonder why / ours is but to do or die.'
Best regards,
Jeremy