Box.Contains(Point) == true is not true

Ok, so I test for point inclusion in a Box. Result is valid as long as the box is aligned to world. When rotated it tries to trick me. Point’s outside the box is reported as inside the box. How can that be?

My code:

Inside = box.Contains(point, true);

Fig 1. My Point and my Box :face_with_monocle: :

bild

(Guess what? The point is not inside the box).

Perhaps nasty of me to rotate the Box, but in my opinion the documentation should warn against such abuse of the functions.

// Rolf

Could it be a tolerance issue maybe?

I don’t think so.

bild

Even at 4+ millimeter distance it still reports inside = true. Notice the world orientation in blue :
bild

It seems the function reports that the Point is inside the bounding box, and yes, it is, but it’s not inside the box.

// Rolf

Hmm, strange indeed. That said, tolerance definitely can be an issue:

Yes, if using meters… :slight_smile:

In my case I have this:

bild

// Rolf

Tolerance is not directly an issue of unit though, it’s entirely relative to the model. But I take your point :wink:

Hi Rolf

Just an idea …
Are you sure that your object is a Box and not a BoundingBox ?
They are different things in RhinoCommon

I’m pretty sure that GH represents the (rotated) box as a box (the box is greenish when clicking the Brep component). But the RhinoCommons command Box.Contains(Point) definitely thinks “BoundingBox” for the test.

(The blue line would be the edge of a BoundingBox, and as soon as I go “outside” of the blue line, the Included result goes “false” :

bild

// Rolf

Hmmm … weird …

In a (Rhino) script it does work as expected …

import Rhino
import math

def main():
  a = Rhino.Geometry.Point3d( -100, -100, -50 )
  b = Rhino.Geometry.Point3d( 100, 100, 50 )
  bb = Rhino.Geometry.BoundingBox( a, b )
  bx = Rhino.Geometry.Box( bb )
  xfo = Rhino.Geometry.Transform.Rotation( 
      math.radians( 45.0 ), Rhino.Geometry.Point3d.Origin )
  print( bx.Transform( xfo ) )
  print( bx.Contains( Rhino.Geometry.Point3d( 90, 90, 0 ) ) )
  print( bx.Contains( Rhino.Geometry.Point3d( 0, 90, 0 ) ) )

main()

I have no idea why manually rotated Boxes are so messed up…

But I desigend solution that actually works for any direction of the Box:

Fig 1. A GrassHopper component solution, and a C# solution that actually worx:

Update: This code can test point lists (see mesh vertices below):

private void RunScript(Brep box, List<Point3d> points, ref object Inside)
{
    Inside = false;
    if (box == null || (points == null || points.Count == 0))
        return;

    var inside = true;
    var centerPoint = box.GetBoundingBox(true).Center;
    var line = new Line(centerPoint, centerPoint);
    var hitList = new List<bool>();
    foreach (var pt in points)
    {
        inside = true;

        line.To = pt;
        var testCrv = line.ToNurbsCurve();
        foreach (var srf in box.Faces)
        {
            if (Rhino.Geometry.Intersect.Intersection.CurveSurface(testCrv, srf, 0.001, 0.001).Count > 0)
            {
                inside = false;
                break;
            }
        }
        hitList.Add(inside);
    }
    Inside = hitList;
}

Fig 2. Mesh vertices tested for inclusion in the Box using the code above:
bild

BTW, what does the “overlapTolerance” parameter mean in the CurveSurface command?

// Rolf

Not a guarantee. Your original geometry is a Brep shaped like a box, when you convert it into a Box you may well get the bounding box. You should output that value to be sure.

A very fast method that will work for any convex brep with planar faces is to create a list of Planes and for each plane test whether a point has positive or negative distance to it. You won’t need any expensive intersections and it’ll work for a wide variety of shapes.

However, if you know for a fact that your input is a Brep shaped like a box, then you should try and create the correct Box. There’s various ways to approach that, either look at the vertices, or the edges, or start with a single face and take it from there…

Box-Brep, Brep-Box

See? Breps destroy that information and it seems Box parameters aren’t smart enough to reverse engineer it.

Thank you David for these hints. And yes, in order to speed up things, intersections are costly. I’ll make good use of your hint, no doubt.

// Rolf