Math behinde: IsAlmostEqualTo

Math behinde: IsAlmostEqualTo

Anonymous
Not applicable
1,389 Views
8 Replies
Message 1 of 9

Math behinde: IsAlmostEqualTo

Anonymous
Not applicable

Please Autodesk enlighten us:

What is the special math that is so secrete behind the IsAlmostEqualTo function:

This routine uses an input tolerance to compare two vectors to see if they are almost equivalent. Because it is comparing two vectors the tolerance value is not in length units but instead represents the variation in direction between the vectors. For very small tolerance values it should also be possible to compare two points with this method. To compute the distance between two points for a comparison with a larger allowable difference, use DistanceTo(XYZ) .

This description is no good and returns true for the following example: Why?

 

 

Annotation 2020-08-18 145622.png

0 Likes
1,390 Views
8 Replies
Replies (8)
Message 2 of 9

jeremytammik
Autodesk
Autodesk

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

 



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

0 Likes
Message 3 of 9

Anonymous
Not applicable

I am doing something similar and yes it is nearly effortless to come up with these solutions, but since it is not the only issue I had to write a lot of bypasses for inbuilt functionality and there time builds up.

And we are talking about 305 $/month for a license you could expect some sort of clarity and reliable functionality in a software. If I would apply the same standards to the buildings we are designing with REVIT?

And I mean there are other CAD Softwares that can deliver... e.g. Rhino3d, not exactly the same use case as REVIT but you get your Value there!

I mean things like the questions which curve loops are outer / inner loops could be as easy to answer:
https://developer.rhino3d.com/api/RhinoCommon/html/T_Rhino_Geometry_BrepLoopType.htm

And he just to say it again it is actually very well implemented in REVIT you can figure out if a curve is an inner or an outer loop with the methode  isCounterclockwise using the face normal... and if you read through the forum it always ends in lengthy discussions with workarrounds...

0 Likes
Message 4 of 9

RPTHOMAS108
Mentor
Mentor

Regarding outer loops: .IsCounterClockwise will help you when your face has a pair of loops, more loops than this (like an onion) and you'll get multiple versions of each CW and CCW. Perimeter may also help you but sometimes you can have internal islands with a complex longer perimeter of edges. I think you are oversimplifying the problems we previous wanted to solve and spoke of.

0 Likes
Message 5 of 9

Anonymous
Not applicable

No sometimes it is as simple as that. Please read this discussion(it is for rhino3d) but it seams that The implementation of Revit is in-line: https://discourse.mcneel.com/t/consistent-winding-of-brep-faces/28385

I am sure that there is somewhere a standard definition of this.

 

0 Likes
Message 6 of 9

RPTHOMAS108
Mentor
Mentor

Are you following the subtlety of the problem we looked at? In the below image there is one top face and two outer loops but which one is the outermost of the two? From loop direction alone you can't tell because as stated there is one top face not two top faces.

 

You'll likely get an outer loop with your simplification but perhaps not the outermost (50/50 odds for this case). 

 

Capture200819.PNG

 

 

 

0 Likes
Message 7 of 9

jeremytammik
Autodesk
Autodesk

Ah yes, indeed. And then we have the issue that one single face may consist of separate disjunct regions...

 

https://thebuildingcoder.typepad.com/blog/2017/10/disjunct-outer-loops-from-planar-face-with-separat...

 



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

0 Likes
Message 8 of 9

Anonymous
Not applicable

Well that is actually also not a problem and can also be solved with curve orientation and some vector math (dot / cross product):

So to figure out if a point is within the curve (in respect to the face normal and the plane defined by this normal) we can simply compute the closest point onto the next curve. With the vector from the test point to the closest point on the curve we can compute the cross product and compute the dot product to the face normal. With this information and the information if a curve loop is part of an inner or an outer loop you can find out if a point is within the curve ore outside of the curve. or if it is within a hohle for example.

To now determine the most outer loop you simple have to finde the loop where all curveendpoints are outside of all other curve endpoints .... done

However I needed some time to figure this out (also I had known it from Rhino3d) I wasn't aware that this works in REVIT too simply because a lack of documentation (also I have to addmit I simply should have remempered it and tested instead of finding other funny solutions for the problem), which brings me back to the original question:

What is the secret math behinde IsAlmostEqualTo, the documentation provided gives no help to understand the tolerance that you can specify.

0 Likes
Message 9 of 9

jeremytammik
Autodesk
Autodesk

I asked the development team for you whether we can share the code behind Xyz.IsAlmostEqualTo. 

 



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

0 Likes