Detect if two PlanarFace lie on each other

Detect if two PlanarFace lie on each other

l.virone
Enthusiast Enthusiast
1,548 Views
5 Replies
Message 1 of 6

Detect if two PlanarFace lie on each other

l.virone
Enthusiast
Enthusiast

Hi everyone,

 

I try to detect if two walls (or two floors) are on each other (if they have a common face).

I think we should start by comparing the normals and they must be opposite, but after this I don't know what to do.

I've tried to use a FaceIntersectionFaceResult but i don't think it'll work with two faces on each other.

/// <summary>
/// Return True if the faces lies against each other, otherwise return False
/// </summary>
            static public bool FaceOnFace(PlanarFace f1, PlanarFace f2)
            {
                if(f1.FaceNormal != -f2.FaceNormal) return false;

                //FaceIntersectionFaceResult result = f1.Intersect(f2);
                //if (result == FaceIntersectionFaceResult.Intersecting) return true;

                return false;
            }

 

 If anyone have an idea, it would be awesome !

 

Tks,

Virone Lorenzo

0 Likes
Accepted solutions (2)
1,549 Views
5 Replies
Replies (5)
Message 2 of 6

RPTHOMAS108
Mentor
Mentor
Accepted solution

The starting point in terms of discovering if two things are equal is always to determine what defines them as unique.

 

A plane has an origin and a normal

A PlanarFace is made up of edges/curves bound on a plane.

 

For me I would probably attack it as follows:

Start with the low level comparisons:

Are the areas the same

When you average the triangulated points of each edge into a single point are they the same (by a tolerance)*

 

Then move on to more intensive checks.

Identify if the origin of one plane lies on the other also

Establish a transform to align space to one of the planes

Check the transformed Z values of the curves from the other plane (are they coplanar or not)

Look at the outer curves transformed into that space, I should find there is no curve of one that isn't matched by a similar curve on the other; in terms of type of curve and key points of curve etc.

i.e. you know a line is defined by two points whilst an arc by three. The arc could be reversed but it would still contain those three points (with the middle being the same). There are more exotic curves to consider the identity of such as ellipses and splines.

 

It is all about breaking down things into what uniquely identifies them and grouping identities together for a composite identity.

*As always when considering doubles you need to decide how to deal with rounding of those for comparison.

 

What is the motivation for this exercise?

 

 

0 Likes
Message 3 of 6

jeremy_tammik
Alumni
Alumni
Accepted solution

Just as Richard suggests (thank you, Richard!):

 

  • Compare the two infinite planes, e.g., by implementing an equality operator
  • Compare the 2D Boolean intersection of the two face boundaries projected from 3D into the 2D plane that they both reside on

 

Here is the implementation of a plane comparison operator from The Building Coder samples Util.cs:

  

https://github.com/jeremytammik/the_building_coder_samples

 

  /// <summary>
  ///   Predicate to determine whether the given
  ///   real number should be considered equal to
  ///   zero, adding fuzz according to the specified
  ///   tolerance
  /// </summary>
  public static bool IsZero(
    double a,
    double tolerance = _eps)
  {
    return tolerance > Math.Abs(a);
  }

  /// <summary>
  ///   Predicate to determine whether the two given
  ///   real numbers should be considered equal, adding
  ///   fuzz according to the specified tolerance
  /// </summary>
  public static bool IsEqual(
    double a,
    double b,
    double tolerance = _eps)
  {
    return IsZero(b - a, tolerance);
  }
  
  /// <summary>
  ///   Comparison method for two real numbers
  ///   returning 0 if they are to be considered equal,
  ///   -1 if the first is smaller and +1 otherwise
  /// </summary>
  public static int Compare(
    double a,
    double b,
    double tolerance = _eps)
  {
    return IsEqual(a, b, tolerance)
      ? 0
      : a < b
        ? -1
        : 1;
  }

  /// <summary>
  ///   Comparison method for two XYZ objects
  ///   returning 0 if they are to be considered equal,
  ///   -1 if the first is smaller and +1 otherwise
  /// </summary>
  public static int Compare(
    XYZ p,
    XYZ q,
    double tolerance = _eps)
  {
    var 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;
  }
  
  public static int Compare(Plane a, Plane b)
  {
    var d = Compare(a.Normal, b.Normal);

    if (0 == d)
    {
      d = Compare(a.SignedDistanceTo(XYZ.Zero),
        b.SignedDistanceTo(XYZ.Zero));

      if (0 == d)
        d = Compare(a.XVec.AngleOnPlaneTo(
          b.XVec, b.Normal), 0);
    }
    return d;
  }

 

For the 2D Boolean operation, I can recommend Clipper, discussed elsewqhere here in the forum and by The Building Coder:

 

https://thebuildingcoder.typepad.com/blog/about-the-author.html#5.2

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 4 of 6

l.virone
Enthusiast
Enthusiast

Hi@RPTHOMAS108  and @jeremy_tammik ,

 

Huge thank for you two !

 

The motivation is to create automatically dimensions inside a building depending on options. I know revit have a method to create a dimension for an entire wall but it only work like we want for the exterior of a building, inside it's not like we exactly want because it takes every references (It can be usefull, but not for every plan we produce).

 

I don't know for others countries but in my side of the Belgium, we like to separate the structure of the finish, so we have 2 or 3 walls to represent a single wall (same logic with floors and roofs). Sometimes we need to reference each wall faces, but sometimes we want the value of the entire complex as if it was a single wall, so I need to detect "face to face" and ignore them.

 

My logic to create the dimension is to ask the user to create a line, after this I detect the rooms (to identify doors and windows) and walls (or floors in section) which intersect the view and the line, then I have to sort the references perpendicular to the line. In the future, I will try to deduce algorithmically, using rooms and surfaces, where to place the lines (in order to remove this task to the user).

 

 

So thank you very much for this, it was my last big problem !

0 Likes
Message 5 of 6

l.virone
Enthusiast
Enthusiast

Hi @jeremy_tammik  and @RPTHOMAS108 

 

I've a result which seems to work, I'm not 100% sure it will work for all cases but I've tested a few cases and it works.

/// <summary>
/// Return True if the faces lies against each other, otherwise return False
/// </summary>
static public bool FaceOnFace(PlanarFace f1, PlanarFace f2)
{
    //If their loop intersect
    CurveLoop cl1 = f1.GetEdgesAsCurveLoops().First();
    CurveLoop cl2 = f2.GetEdgesAsCurveLoops().First();
    if(Personal.curveLoop.Intersect(cl1, cl2)) return true; //Personal.curveLoop.Intersect use SetComparisonResult.Overlap on each curve

    //But maybe the loop do not intersect, so the plane does
    Plane p1 = Plane.CreateByNormalAndOrigin(f1.FaceNormal, f1.Origin);
    Plane p2 = Plane.CreateByNormalAndOrigin(f1.FaceNormal, f2.Origin); //Must have same normal
    int v = Extern.Util.Compare(p1, p2); //Return 0 if the same plane

    if(v == 0) return true;
    else return false;
}

 

 Tks again for the tips !

0 Likes
Message 6 of 6

BKSpurgeon
Collaborator
Collaborator

Here is the direct link to the method for anyone who's interested:

 

https://github.com/jeremytammik/the_building_coder_samples/blob/b5c5addb3808560a7cdf0688a28996e58671...

 

 

0 Likes