Hello,

Alex is correct in that the intersection operation you are attempting
to perform will only work in 2D. When you constructed bsp1 and bsp2
from the faces, what you ended up with was 2 half spaces of infinite
size.

        List<ConvexPolygon3D> list1 = new ArrayList<>();
        list1.add(face1);
        RegionBSPTree3D bsp1 = RegionBSPTree3D.from(list1); // this is
an infinite half space

        List<ConvexPolygon3D> list2 = new ArrayList<>();
        list2.add(face2);
        RegionBSPTree3D bsp2 = RegionBSPTree3D.from(list2); // this is
also an infinite half-space and is actually identical to the first one

(The reason for this has to do with the way BSP trees represent
regions. I suggest taking a look at the BSP tree tutorial on the
commons-geometry site [1].)

The intersection of those two infinite half-spaces is itself an
infinite half-space. Regions of infinite size do not have a defined
centroid, which is why the centroid in your example is null.

In order to compute the intersection of the two polygons in your
example, we have to use 2D space. We can either do the entire thing in
2D (as Alex demonstrated), or we can start in 3D and pop down to 2D
when needed. This is the approach that I will show here. We'll start
with the same 3D convex polygons that you had:

        List<Vector3D> pts1 = Arrays.asList(
                Vector3D.of(0, 10, 0),
                Vector3D.of(30, 10, 0),
                Vector3D.of(30, 20, 0),
                Vector3D.of(0, 20, 0));
        ConvexPolygon3D face1 = Planes.convexPolygonFromVertices(pts1,
precision);

        List<Vector3D> pts2 = Arrays.asList(
                Vector3D.of(10, 0, 0),
                Vector3D.of(20, 0, 0),
                Vector3D.of(20, 30, 0),
                Vector3D.of(10, 30, 0));
        ConvexPolygon3D face2 = Planes.convexPolygonFromVertices(pts2,
precision);

Now, in order to perform the 2D intersection, we will first access the
2D geometries that are embedded in the 3D planes of the
ConvexPolygon3D instances. You can picture a ConvexPolygon3D (and any
other PlaneSubset subclass) as a 2D sticker stuck to a pane of glass
(the infinite 3D plane). In the lines below, we are extracting the 2D
"sticker" in order to work with it directly.

        ConvexArea area1 = face1.getEmbedded().getSubspaceRegion();
        ConvexArea area2 = face2.getEmbedded().getSubspaceRegion();

We can now compute the intersection in 2D:

        RegionBSPTree2D areaBsp = RegionBSPTree2D.empty();
        areaBsp.intersection(area1.toTree(), area2.toTree());

This gives us a finite 2D region with the expected centroid:

        Vector2D centroid2d = areaBsp.getCentroid();
        System.out.println(centroid2d); // prints (15.000000000000002,
-15.000000000000002)

If we wish to take this 2D centroid back up to 3D, we can again use
the subspace embedding information from the faces. In this case, we
only need to use one of the faces:

        Vector3D centroid3d = face1.getEmbedded().toSpace(centroid2d);
        System.out.println(centroid3d); // prints (15.000000000000002,
15.000000000000002, 0.0)

I hope this helps. Thank you for your interest in this project and
feel free to reach out if you have any more questions.

Regards,
Matt J

[1] https://commons.apache.org/proper/commons-geometry/tutorials/bsp-tree.html

On Fri, Sep 16, 2022 at 6:10 AM Alex Herbert <alex.d.herb...@gmail.com> wrote:
>
> This may be related to the fact that you are using the 3D API with 2D
> areas. Since the shapes have no volume the intersection may not be defined.
>
> This does work as expected in 2D:
>
>         Precision.DoubleEquivalence precision =
> Precision.doubleEquivalenceOfEpsilon(1e-6);
>
>         List<Vector2D> pts1 = new ArrayList<>();
>         pts1.add(Vector2D.of(0, 10));
>         pts1.add(Vector2D.of(30, 10));
>         pts1.add(Vector2D.of(30, 20));
>         pts1.add(Vector2D.of(0, 20));
>         ConvexArea face1 = ConvexArea.convexPolygonFromVertices(pts1,
> precision);
>
>         List<Vector2D> pts2 = new ArrayList<>();
>         pts2.add(Vector2D.of(10, 0));
>         pts2.add(Vector2D.of(20, 0));
>         pts2.add(Vector2D.of(20, 30));
>         pts2.add(Vector2D.of(10, 30));
>         ConvexArea face2 = ConvexArea.convexPolygonFromVertices(pts2,
> precision);
>
>         RegionBSPTree2D bsp1 = RegionBSPTree2D.from(face1.getBoundaries());
>
>         RegionBSPTree2D bsp2 = RegionBSPTree2D.from(face2.getBoundaries());
>
>         RegionBSPTree2D result = RegionBSPTree2D.empty();
>         result.intersection(bsp1, bsp2);
>
>         System.out.println("Hello, Geometry! Centroid: " +
> result.getCentroid());
>
> Result:
>
>         Hello, Geometry! Centroid: (15.000000000000002, 15.000000000000002)
>
> There may be a setting for the 3D equivalent to allow intersections on the
> plane to be returned. I could not find anything obvious in the API.
>
> Regards,
>
> Alex
>
>
>
> On Fri, 16 Sept 2022 at 10:03, Bai Song <baisongm...@163.com> wrote:
>
> > Hi, Geometry Team
> >
> > I'm learning this interesting project and facing some difficulties when i
> > did a little experiment.
> >
> > I created two ConvexPolygon3D instances (2 white rectangles in below
> > image) on the same plane, and try to get the overlaping area(blue part) by
> > RegionBSPTree3D intersection operation.
> >
> >
> > But i got null when getting the centroid of the intersection. It looks
> > that this test of intersection failed.
> > Could you tell me how can i fix this?
> >
> > Thanks for your contribution to this project!
> >
> > //---------my test codes----------
> > public class TestIntersection
> > {
> >     public static void main(String args[])
> >     {
> >         Precision.DoubleEquivalence precision =
> > Precision.doubleEquivalenceOfEpsilon(1e-6);
> >
> >         List<Vector3D> pts1 = new ArrayList<>();
> >         pts1.add(Vector3D.of(0, 10, 0));
> >         pts1.add(Vector3D.of(30, 10, 0));
> >         pts1.add(Vector3D.of(30, 20, 0));
> >         pts1.add(Vector3D.of(0, 20, 0));
> >         ConvexPolygon3D face1=Planes.convexPolygonFromVertices(pts1,
> > precision);
> >
> >         List<Vector3D> pts2 = new ArrayList<>();
> >         pts2.add(Vector3D.of(10, 0, 0));
> >         pts2.add(Vector3D.of(20, 0, 0));
> >         pts2.add(Vector3D.of(20, 30, 0));
> >         pts2.add(Vector3D.of(10, 30, 0));
> >         ConvexPolygon3D face2 = Planes.convexPolygonFromVertices(pts2,
> > precision);
> >
> >         List<ConvexPolygon3D> list1 = new ArrayList<>();
> >         list1.add(face1);
> >         RegionBSPTree3D bsp1 = RegionBSPTree3D.from(list1);
> >
> >         List<ConvexPolygon3D> list2 = new ArrayList<>();
> >         list2.add(face2);
> >         RegionBSPTree3D bsp2 = RegionBSPTree3D.from(list2);
> >
> >         RegionBSPTree3D result = RegionBSPTree3D.empty();
> >         result.intersection(bsp1, bsp2);
> >
> >         System.out.println("Hello, Geometry! Centroid:
> > "+result.getCentroid()); //expect (15,15,0), but got null actually
> >     }
> > }
> >
> >

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscr...@commons.apache.org
For additional commands, e-mail: user-h...@commons.apache.org

Reply via email to