This is an automated email from the ASF dual-hosted git repository. mattjuntunen pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-geometry.git
The following commit(s) were added to refs/heads/master by this push: new 29b20e9 GEOMETRY-108: adding BoundaryList classes 29b20e9 is described below commit 29b20e9cb6e0577c2c5754dc7089b1cafe578200 Author: Matt Juntunen <mattjuntu...@apache.org> AuthorDate: Mon Dec 14 21:20:28 2020 -0500 GEOMETRY-108: adding BoundaryList classes --- .../AbstractConvexHyperplaneBoundedRegion.java | 3 +- .../geometry/core/partitioning/BoundaryList.java | 82 ++++++++++++++++++++ .../AbstractConvexHyperplaneBoundedRegionTest.java | 3 +- .../core/partitioning/BoundaryListTest.java | 87 ++++++++++++++++++++++ .../geometry/euclidean/threed/BoundaryList3D.java | 47 ++++++++++++ .../euclidean/threed/BoundarySource3D.java | 11 +++ .../geometry/euclidean/twod/BoundaryList2D.java | 47 ++++++++++++ .../geometry/euclidean/twod/BoundarySource2D.java | 11 +++ .../euclidean/threed/BoundaryList3DTest.java | 50 +++++++------ .../euclidean/threed/BoundarySource3DTest.java | 27 +++++++ .../euclidean/threed/ConvexVolumeTest.java | 33 ++++++++ .../euclidean/threed/RegionBSPTree3DTest.java | 21 ++++++ .../euclidean/twod/BoundaryList2DTest.java | 50 +++++++------ .../euclidean/twod/BoundarySource2DTest.java | 27 +++++++ .../geometry/euclidean/twod/ConvexAreaTest.java | 27 +++++++ .../euclidean/twod/RegionBSPTree2DTest.java | 20 +++++ .../geometry/spherical/twod/BoundaryList2S.java | 47 ++++++++++++ .../geometry/spherical/twod/BoundarySource2S.java | 32 ++++++++ ...rySource2STest.java => BoundaryList2STest.java} | 48 +++++++----- .../spherical/twod/BoundarySource2STest.java | 36 ++++++++- .../geometry/spherical/twod/ConvexArea2STest.java | 29 ++++++++ .../spherical/twod/RegionBSPTree2STest.java | 21 ++++++ 22 files changed, 690 insertions(+), 69 deletions(-) diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/AbstractConvexHyperplaneBoundedRegion.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/AbstractConvexHyperplaneBoundedRegion.java index 20e7f7b..e449955 100644 --- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/AbstractConvexHyperplaneBoundedRegion.java +++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/AbstractConvexHyperplaneBoundedRegion.java @@ -144,7 +144,8 @@ public abstract class AbstractConvexHyperplaneBoundedRegion<P extends Point<P>, final StringBuilder sb = new StringBuilder(); sb.append(this.getClass().getSimpleName()) .append("[boundaries= ") - .append(boundaries); + .append(boundaries) + .append(']'); return sb.toString(); } diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryList.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryList.java new file mode 100644 index 0000000..edf839f --- /dev/null +++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/partitioning/BoundaryList.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.geometry.core.partitioning; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Stream; + +import org.apache.commons.geometry.core.Point; + +/** Simple implementation of {@link BoundarySource} containing boundaries stored in a list. + * Lists given during construction are used directly; no copies are made. Thread safety and + * immutability therefore depend on the underlying list and its usage outside of this class. + * The boundary list cannot be modified through this class. + * @param <P> Point implementation type + * @param <S> Hyperplane convex subset implementation type + */ +public class BoundaryList<P extends Point<P>, S extends HyperplaneConvexSubset<P>> + implements BoundarySource<S> { + + /** List of boundaries. */ + private final List<S> boundaries; + + /** Construct a new instance containing the given boundaries. The input list is + * used directly; no copy is made. + * @param boundaries boundary list + */ + public BoundaryList(final List<? extends S> boundaries) { + this.boundaries = Collections.unmodifiableList(boundaries); + } + + /** Get the boundaries for the instance. The returned list cannot be modified. + * @return boundaries for the instance + */ + public List<S> getBoundaries() { + return boundaries; + } + + /** Get the number of boundaries in the instance. This is exactly + * equivalent to {@code boundaryList.getBoundaries().size()} but the + * word "size" is avoided here to prevent confusion with geometric + * size. + * @return number of boundaries in the instance + */ + public int count() { + return boundaries.size(); + } + + /** {@inheritDoc} */ + @Override + public Stream<S> boundaryStream() { + return boundaries.stream(); + } + + /** {@inheritDoc} */ + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append(this.getClass().getSimpleName()) + // only display the count and not the actual boundaries + // since the list could be huge + .append("[count= ") + .append(count()) + .append(']'); + + return sb.toString(); + } +} diff --git a/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/AbstractConvexHyperplaneBoundedRegionTest.java b/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/AbstractConvexHyperplaneBoundedRegionTest.java index b018d21..73961d6 100644 --- a/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/AbstractConvexHyperplaneBoundedRegionTest.java +++ b/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/AbstractConvexHyperplaneBoundedRegionTest.java @@ -646,8 +646,7 @@ public class AbstractConvexHyperplaneBoundedRegionTest { final String str = region.toString(); // assert - Assertions.assertTrue(str.contains("StubRegion")); - Assertions.assertTrue(str.contains("boundaries= ")); + Assertions.assertEquals("StubRegion[boundaries= []]", str); } private static void checkClassify(final Region<TestPoint2D> region, final RegionLocation loc, final TestPoint2D... pts) { diff --git a/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/BoundaryListTest.java b/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/BoundaryListTest.java new file mode 100644 index 0000000..62827a5 --- /dev/null +++ b/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/partitioning/BoundaryListTest.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.geometry.core.partitioning; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.geometry.core.partitioning.test.TestLineSegment; +import org.apache.commons.geometry.core.partitioning.test.TestPoint2D; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class BoundaryListTest { + + @Test + public void testBoundaries() { + // arrange + final List<TestLineSegment> boundaries = new ArrayList<>(); + boundaries.add(new TestLineSegment(0, 0, 1, 1)); + boundaries.add(new TestLineSegment(1, 1, 0, 2)); + + // act + final BoundaryList<TestPoint2D, TestLineSegment> list = new BoundaryList<>(boundaries); + + // assert + Assertions.assertNotSame(boundaries, list.getBoundaries()); + Assertions.assertEquals(boundaries, list.getBoundaries()); + Assertions.assertEquals(boundaries, list.boundaryStream().collect(Collectors.toList())); + } + + @Test + public void testGetBoundaries_listCannotBeModified() { + // arrange + final List<TestLineSegment> boundaries = new ArrayList<>(); + boundaries.add(new TestLineSegment(0, 0, 1, 1)); + + final BoundaryList<TestPoint2D, TestLineSegment> list = new BoundaryList<>(boundaries); + + // act/assert + Assertions.assertThrows(UnsupportedOperationException.class, () -> { + list.getBoundaries().add(new TestLineSegment(1, 1, 0, 2)); + }); + } + + @Test + public void testCount() { + // act/assert + Assertions.assertEquals(0, new BoundaryList<>(Collections.emptyList()).count()); + Assertions.assertEquals(1, new BoundaryList<>(Arrays.asList( + new TestLineSegment(0, 0, 1, 1) + )).count()); + Assertions.assertEquals(2, new BoundaryList<>(Arrays.asList( + new TestLineSegment(0, 0, 1, 1), + new TestLineSegment(1, 1, 0, 2) + )).count()); + } + + @Test + public void testToString() { + // arrange + final BoundaryList<TestPoint2D, TestLineSegment> empty = new BoundaryList<>(Collections.emptyList()); + final BoundaryList<TestPoint2D, TestLineSegment> single = new BoundaryList<>(Arrays.asList( + new TestLineSegment(0, 0, 1, 1) + )); + + // act + Assertions.assertEquals("BoundaryList[count= 0]", empty.toString()); + Assertions.assertEquals("BoundaryList[count= 1]", single.toString()); + } +} diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/BoundaryList3D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/BoundaryList3D.java new file mode 100644 index 0000000..645643c --- /dev/null +++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/BoundaryList3D.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.geometry.euclidean.threed; + +import java.util.List; + +import org.apache.commons.geometry.core.partitioning.BoundaryList; + +/** {@link BoundarySource3D} implementation that uses boundaries stored in + * a list. Lists given during construction are used directly; no copies are made. + * Thread safety and immutability therefore depend on the underlying list and its + * usage outside of this class. The boundary list cannot be modified through this + * class. + */ +public class BoundaryList3D extends BoundaryList<Vector3D, PlaneConvexSubset> + implements BoundarySource3D { + + /** Construct a new instance with the given list of boundaries. The + * argument is used directly; no copy is made. + * @param boundaries list of boundaries for the instance + */ + public BoundaryList3D(final List<? extends PlaneConvexSubset> boundaries) { + super(boundaries); + } + + /** Return this instance. + * @return this instance + */ + @Override + public BoundaryList3D toList() { + return this; + } +} diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/BoundarySource3D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/BoundarySource3D.java index f7e7cf0..7188f2d 100644 --- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/BoundarySource3D.java +++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/BoundarySource3D.java @@ -19,6 +19,7 @@ package org.apache.commons.geometry.euclidean.threed; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.geometry.core.partitioning.BoundarySource; @@ -33,6 +34,16 @@ import org.apache.commons.geometry.euclidean.threed.mesh.TriangleMesh; */ public interface BoundarySource3D extends BoundarySource<PlaneConvexSubset>, Linecastable3D { + /** Return a {@link BoundaryList3D} containing the boundaries in this instance. + * @return a {@link BoundaryList3D} containing the boundaries in this instance + */ + default BoundaryList3D toList() { + final List<PlaneConvexSubset> boundaries = boundaryStream() + .collect(Collectors.toList()); + + return new BoundaryList3D(boundaries); + } + /** Return a BSP tree constructed from the boundaries contained in this instance. This is * a convenience method for quickly constructing BSP trees and may produce unbalanced trees * with unacceptable performance characteristics when used with large numbers of boundaries. diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/BoundaryList2D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/BoundaryList2D.java new file mode 100644 index 0000000..42062ea --- /dev/null +++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/BoundaryList2D.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.geometry.euclidean.twod; + +import java.util.List; + +import org.apache.commons.geometry.core.partitioning.BoundaryList; + +/** {@link BoundarySource2D} implementation that uses boundaries stored in + * a list. Lists given during construction are used directly; no copies are made. + * Thread safety and immutability therefore depend on the underlying list and its + * usage outside of this class. The boundary list cannot be modified through this + * class. + */ +public class BoundaryList2D extends BoundaryList<Vector2D, LineConvexSubset> + implements BoundarySource2D { + + /** Construct a new instance with the given list of boundaries. The + * argument is used directly; no copy is made. + * @param boundaries list of boundaries for the instance + */ + public BoundaryList2D(final List<? extends LineConvexSubset> boundaries) { + super(boundaries); + } + + /** Return this instance. + * @return this instance + */ + @Override + public BoundaryList2D toList() { + return this; + } +} diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/BoundarySource2D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/BoundarySource2D.java index 12cd0de..cd7f6fc 100644 --- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/BoundarySource2D.java +++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/BoundarySource2D.java @@ -19,6 +19,7 @@ package org.apache.commons.geometry.euclidean.twod; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; import org.apache.commons.geometry.core.partitioning.BoundarySource; @@ -26,6 +27,16 @@ import org.apache.commons.geometry.core.partitioning.BoundarySource; */ public interface BoundarySource2D extends BoundarySource<LineConvexSubset>, Linecastable2D { + /** Return a {@link BoundaryList2D} containing the boundaries in this instance. + * @return a {@link BoundaryList2D} containing the boundaries in this instance + */ + default BoundaryList2D toList() { + final List<LineConvexSubset> boundaries = boundaryStream() + .collect(Collectors.toList()); + + return new BoundaryList2D(boundaries); + } + /** Return a BSP tree constructed from the boundaries contained in this instance. This is * a convenience method for quickly constructing BSP trees and may produce unbalanced trees * with unacceptable performance characteristics when used with large numbers of boundaries. diff --git a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundarySource2STest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/BoundaryList3DTest.java similarity index 52% copy from commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundarySource2STest.java copy to commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/BoundaryList3DTest.java index 03a741a..723dae6 100644 --- a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundarySource2STest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/BoundaryList3DTest.java @@ -14,47 +14,55 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.geometry.spherical.twod; +package org.apache.commons.geometry.euclidean.threed; -import java.util.stream.Stream; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.apache.commons.geometry.core.precision.DoublePrecisionContext; import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class BoundarySource2STest { +public class BoundaryList3DTest { private static final double TEST_EPS = 1e-10; - private static final DoublePrecisionContext TEST_PRECISION = new EpsilonDoublePrecisionContext(TEST_EPS); + private static final DoublePrecisionContext TEST_PRECISION = + new EpsilonDoublePrecisionContext(TEST_EPS); @Test - public void testToTree() { - // act - final BoundarySource2S src = () -> Stream.of( - GreatCircles.arcFromPoints(Point2S.PLUS_I, Point2S.PLUS_J, TEST_PRECISION)); + public void testCtor() { + // arrange + final List<PlaneConvexSubset> boundaries = Arrays.asList( + Planes.fromNormal(Vector3D.Unit.PLUS_X, TEST_PRECISION).span() + ); // act - final RegionBSPTree2S tree = src.toTree(); + final BoundaryList3D list = new BoundaryList3D(boundaries); // assert - Assertions.assertEquals(3, tree.count()); - Assertions.assertFalse(tree.isFull()); - Assertions.assertFalse(tree.isEmpty()); + Assertions.assertNotSame(boundaries, list.getBoundaries()); + Assertions.assertEquals(boundaries, list.getBoundaries()); + Assertions.assertEquals(1, list.count()); } @Test - public void testToTree_noBoundaries() { - // act - final BoundarySource2S src = Stream::empty; + public void testToList() { + // arrange + final BoundaryList3D list = new BoundaryList3D(Collections.emptyList()); - // act - final RegionBSPTree2S tree = src.toTree(); + // act/assert + Assertions.assertSame(list, list.toList()); + } - // assert - Assertions.assertEquals(1, tree.count()); - Assertions.assertFalse(tree.isFull()); - Assertions.assertTrue(tree.isEmpty()); + @Test + public void testToString() { + // arrange + final BoundaryList3D list = new BoundaryList3D(Collections.emptyList()); + + // act + Assertions.assertEquals("BoundaryList3D[count= 0]", list.toString()); } } diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/BoundarySource3DTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/BoundarySource3DTest.java index 16bd1d9..f2767a8 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/BoundarySource3DTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/BoundarySource3DTest.java @@ -34,6 +34,33 @@ public class BoundarySource3DTest { new EpsilonDoublePrecisionContext(TEST_EPS); @Test + public void testToList() { + // act + final BoundarySource3D src = BoundarySource3D.from( + Planes.convexPolygonFromVertices( + Arrays.asList(Vector3D.ZERO, Vector3D.Unit.PLUS_X, Vector3D.Unit.PLUS_Y), TEST_PRECISION) + ); + + // act + final BoundaryList3D list = src.toList(); + + // assert + Assertions.assertEquals(1, list.count()); + } + + @Test + public void testToList_noBoundaries() { + // act + final BoundarySource3D src = BoundarySource3D.from(); + + // act + final BoundaryList3D list = src.toList(); + + // assert + Assertions.assertEquals(0, list.count()); + } + + @Test public void testToTree() { // act final PlaneConvexSubset a = Planes.convexPolygonFromVertices( diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/ConvexVolumeTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/ConvexVolumeTest.java index c81e19c..80f6e8c 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/ConvexVolumeTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/ConvexVolumeTest.java @@ -179,6 +179,39 @@ public class ConvexVolumeTest { } @Test + public void testToList_full() { + // arrange + final ConvexVolume volume = ConvexVolume.full(); + + // act + final BoundaryList3D list = volume.toList(); + + // assert + Assertions.assertEquals(0, list.count()); + } + + @Test + public void testToList() { + // arrange + final ConvexVolume volume = ConvexVolume.fromBounds( + Planes.fromPointAndNormal(Vector3D.ZERO, Vector3D.Unit.MINUS_X, TEST_PRECISION), + Planes.fromPointAndNormal(Vector3D.ZERO, Vector3D.Unit.MINUS_Y, TEST_PRECISION), + Planes.fromPointAndNormal(Vector3D.ZERO, Vector3D.Unit.MINUS_Z, TEST_PRECISION), + + Planes.fromPointAndNormal(Vector3D.of(1, 1, 1), Vector3D.Unit.PLUS_X, TEST_PRECISION), + Planes.fromPointAndNormal(Vector3D.of(1, 1, 1), Vector3D.Unit.PLUS_Y, TEST_PRECISION), + Planes.fromPointAndNormal(Vector3D.of(1, 1, 1), Vector3D.Unit.PLUS_Z, TEST_PRECISION) + ); + + // act + final BoundaryList3D list = volume.toList(); + + // assert + Assertions.assertEquals(6, list.count()); + Assertions.assertEquals(1, list.toTree().getSize(), TEST_EPS); + } + + @Test public void testToTree_full() { // arrange final ConvexVolume volume = ConvexVolume.full(); diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/RegionBSPTree3DTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/RegionBSPTree3DTest.java index 12519b6..1c9ccb6 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/RegionBSPTree3DTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/RegionBSPTree3DTest.java @@ -460,6 +460,27 @@ public class RegionBSPTree3DTest { } @Test + public void testToList() { + // arrange + final RegionBSPTree3D tree = Parallelepiped.axisAligned( + Vector3D.ZERO, Vector3D.of(1, 3, 3), TEST_PRECISION).toTree(); + + // act + final BoundaryList3D list = tree.toList(); + + // assert + Assertions.assertEquals(6, list.count()); + Assertions.assertEquals(9, list.toTree().getSize()); + } + + @Test + public void testToList_fullAndEmpty() { + // act/assert + Assertions.assertEquals(0, RegionBSPTree3D.full().toList().count()); + Assertions.assertEquals(0, RegionBSPTree3D.empty().toList().count()); + } + + @Test public void testToTree_returnsSameInstance() { // arrange final RegionBSPTree3D tree = createRect(Vector3D.ZERO, Vector3D.of(1, 2, 1)); diff --git a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundarySource2STest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/BoundaryList2DTest.java similarity index 52% copy from commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundarySource2STest.java copy to commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/BoundaryList2DTest.java index 03a741a..816af97 100644 --- a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundarySource2STest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/BoundaryList2DTest.java @@ -14,47 +14,55 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.geometry.spherical.twod; +package org.apache.commons.geometry.euclidean.twod; -import java.util.stream.Stream; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.apache.commons.geometry.core.precision.DoublePrecisionContext; import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class BoundarySource2STest { +public class BoundaryList2DTest { private static final double TEST_EPS = 1e-10; - private static final DoublePrecisionContext TEST_PRECISION = new EpsilonDoublePrecisionContext(TEST_EPS); + private static final DoublePrecisionContext TEST_PRECISION = + new EpsilonDoublePrecisionContext(TEST_EPS); @Test - public void testToTree() { - // act - final BoundarySource2S src = () -> Stream.of( - GreatCircles.arcFromPoints(Point2S.PLUS_I, Point2S.PLUS_J, TEST_PRECISION)); + public void testCtor() { + // arrange + final List<LineConvexSubset> boundaries = Arrays.asList( + Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION) + ); // act - final RegionBSPTree2S tree = src.toTree(); + final BoundaryList2D list = new BoundaryList2D(boundaries); // assert - Assertions.assertEquals(3, tree.count()); - Assertions.assertFalse(tree.isFull()); - Assertions.assertFalse(tree.isEmpty()); + Assertions.assertNotSame(boundaries, list.getBoundaries()); + Assertions.assertEquals(boundaries, list.getBoundaries()); + Assertions.assertEquals(1, list.count()); } @Test - public void testToTree_noBoundaries() { - // act - final BoundarySource2S src = Stream::empty; + public void testToList() { + // arrange + final BoundaryList2D list = new BoundaryList2D(Collections.emptyList()); - // act - final RegionBSPTree2S tree = src.toTree(); + // act/assert + Assertions.assertSame(list, list.toList()); + } - // assert - Assertions.assertEquals(1, tree.count()); - Assertions.assertFalse(tree.isFull()); - Assertions.assertTrue(tree.isEmpty()); + @Test + public void testToString() { + // arrange + final BoundaryList2D list = new BoundaryList2D(Collections.emptyList()); + + // act + Assertions.assertEquals("BoundaryList2D[count= 0]", list.toString()); } } diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/BoundarySource2DTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/BoundarySource2DTest.java index 1236add..ae736cb 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/BoundarySource2DTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/BoundarySource2DTest.java @@ -33,6 +33,33 @@ public class BoundarySource2DTest { new EpsilonDoublePrecisionContext(TEST_EPS); @Test + public void testToList() { + // act + final BoundarySource2D src = BoundarySource2D.from( + Lines.segmentFromPoints(Vector2D.ZERO, Vector2D.of(1, 0), TEST_PRECISION), + Lines.segmentFromPoints(Vector2D.of(1, 0), Vector2D.of(1, 1), TEST_PRECISION) + ); + + // act + final BoundaryList2D list = src.toList(); + + // assert + Assertions.assertEquals(2, list.count()); + } + + @Test + public void testToList_noBoundaries() { + // act + final BoundarySource2D src = BoundarySource2D.from(); + + // act + final BoundaryList2D list = src.toList(); + + // assert + Assertions.assertEquals(0, list.count()); + } + + @Test public void testToTree() { // act final BoundarySource2D src = BoundarySource2D.from( diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/ConvexAreaTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/ConvexAreaTest.java index 113795c..8c85262 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/ConvexAreaTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/ConvexAreaTest.java @@ -87,6 +87,33 @@ public class ConvexAreaTest { } @Test + public void testToList() { + // arrange + final ConvexArea area = ConvexArea.convexPolygonFromVertices(Arrays.asList( + Vector2D.ZERO, Vector2D.of(1, 0), Vector2D.of(0, 1) + ), TEST_PRECISION); + + // act + final BoundaryList2D list = area.toList(); + + // assert + Assertions.assertEquals(3, list.count()); + Assertions.assertEquals(area.getBoundaries(), list.getBoundaries()); + } + + @Test + public void testToList_full() { + // arrange + final ConvexArea area = ConvexArea.full(); + + // act + final BoundaryList2D list = area.toList(); + + // assert + Assertions.assertEquals(0, list.count()); + } + + @Test public void testToTree() { // arrange final ConvexArea area = ConvexArea.fromBounds( diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/RegionBSPTree2DTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/RegionBSPTree2DTest.java index 93a11be..908dab8 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/RegionBSPTree2DTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/RegionBSPTree2DTest.java @@ -1081,6 +1081,26 @@ public class RegionBSPTree2DTest { } @Test + public void testToList() { + // arrange + final RegionBSPTree2D tree = Parallelogram.axisAligned(Vector2D.ZERO, Vector2D.of(1, 1), TEST_PRECISION).toTree(); + + // act + final BoundaryList2D list = tree.toList(); + + // assert + Assertions.assertEquals(4, list.toList().count()); + Assertions.assertEquals(1, list.toTree().getSize(), TEST_EPS); + } + + @Test + public void testToList_fullAndEmpty() { + // act/assert + Assertions.assertEquals(0, RegionBSPTree2D.full().toList().count()); + Assertions.assertEquals(0, RegionBSPTree2D.empty().toList().count()); + } + + @Test public void testToTree_returnsSameInstance() { // arrange final RegionBSPTree2D tree = Parallelogram.axisAligned(Vector2D.ZERO, Vector2D.of(1, 2), TEST_PRECISION).toTree(); diff --git a/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/BoundaryList2S.java b/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/BoundaryList2S.java new file mode 100644 index 0000000..d0b12ae --- /dev/null +++ b/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/BoundaryList2S.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.geometry.spherical.twod; + +import java.util.List; + +import org.apache.commons.geometry.core.partitioning.BoundaryList; + +/** {@link BoundarySource2S} implementation that uses boundaries stored in + * a list. Lists given during construction are used directly; no copies are made. + * Thread safety and immutability therefore depend on the underlying list and its + * usage outside of this class. The boundary list cannot be modified through this + * class. + */ +public class BoundaryList2S extends BoundaryList<Point2S, GreatArc> + implements BoundarySource2S { + + /** Construct a new instance with the given list of boundaries. The + * argument is used directly; no copy is made. + * @param boundaries list of boundaries for the instance + */ + public BoundaryList2S(final List<? extends GreatArc> boundaries) { + super(boundaries); + } + + /** Return this instance. + * @return this instance + */ + @Override + public BoundaryList2S toList() { + return this; + } +} diff --git a/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/BoundarySource2S.java b/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/BoundarySource2S.java index 190e53b..749904d 100644 --- a/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/BoundarySource2S.java +++ b/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/BoundarySource2S.java @@ -16,6 +16,11 @@ */ package org.apache.commons.geometry.spherical.twod; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + import org.apache.commons.geometry.core.partitioning.BoundarySource; /** Extension of the {@link BoundarySource} interface for spherical 2D @@ -23,6 +28,16 @@ import org.apache.commons.geometry.core.partitioning.BoundarySource; */ public interface BoundarySource2S extends BoundarySource<GreatArc> { + /** Return a {@link BoundaryList2S} containing the boundaries in this instance. + * @return a {@link BoundaryList2S} containing the boundaries in this instance + */ + default BoundaryList2S toList() { + final List<GreatArc> boundaries = boundaryStream() + .collect(Collectors.toList()); + + return new BoundaryList2S(boundaries); + } + /** Return a BSP tree constructed from the boundaries contained in this * instance. The default implementation creates a new, empty tree * and inserts the boundaries from this instance. @@ -34,4 +49,21 @@ public interface BoundarySource2S extends BoundarySource<GreatArc> { return tree; } + + /** Return a {@link BoundarySource2S} instance containing the given boundaries. + * @param boundaries boundaries to include in the boundary source + * @return a boundary source containing the given boundaries + */ + static BoundarySource2S from(final GreatArc... boundaries) { + return from(Arrays.asList(boundaries)); + } + + /** Return a {@link BoundarySource2S} instance containing the given boundaries. The given + * collection is used directly as the source of the line subsets; no copy is made. + * @param boundaries boundaries to include in the boundary source + * @return a boundary source containing the given boundaries + */ + static BoundarySource2S from(final Collection<GreatArc> boundaries) { + return boundaries::stream; + } } diff --git a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundarySource2STest.java b/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundaryList2STest.java similarity index 54% copy from commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundarySource2STest.java copy to commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundaryList2STest.java index 03a741a..c36c850 100644 --- a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundarySource2STest.java +++ b/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundaryList2STest.java @@ -16,45 +16,53 @@ */ package org.apache.commons.geometry.spherical.twod; -import java.util.stream.Stream; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.apache.commons.geometry.core.precision.DoublePrecisionContext; import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -public class BoundarySource2STest { +public class BoundaryList2STest { private static final double TEST_EPS = 1e-10; - private static final DoublePrecisionContext TEST_PRECISION = new EpsilonDoublePrecisionContext(TEST_EPS); + private static final DoublePrecisionContext TEST_PRECISION = + new EpsilonDoublePrecisionContext(TEST_EPS); @Test - public void testToTree() { - // act - final BoundarySource2S src = () -> Stream.of( - GreatCircles.arcFromPoints(Point2S.PLUS_I, Point2S.PLUS_J, TEST_PRECISION)); + public void testCtor() { + // arrange + final List<GreatArc> boundaries = Arrays.asList( + GreatCircles.arcFromPoints(Point2S.PLUS_I, Point2S.PLUS_J, TEST_PRECISION) + ); // act - final RegionBSPTree2S tree = src.toTree(); + final BoundaryList2S list = new BoundaryList2S(boundaries); // assert - Assertions.assertEquals(3, tree.count()); - Assertions.assertFalse(tree.isFull()); - Assertions.assertFalse(tree.isEmpty()); + Assertions.assertNotSame(boundaries, list.getBoundaries()); + Assertions.assertEquals(boundaries, list.getBoundaries()); + Assertions.assertEquals(1, list.count()); } @Test - public void testToTree_noBoundaries() { - // act - final BoundarySource2S src = Stream::empty; + public void testToList() { + // arrange + final BoundaryList2S list = new BoundaryList2S(Collections.emptyList()); - // act - final RegionBSPTree2S tree = src.toTree(); + // act/assert + Assertions.assertSame(list, list.toList()); + } - // assert - Assertions.assertEquals(1, tree.count()); - Assertions.assertFalse(tree.isFull()); - Assertions.assertTrue(tree.isEmpty()); + @Test + public void testToString() { + // arrange + final BoundaryList2S list = new BoundaryList2S(Collections.emptyList()); + + // act + Assertions.assertEquals("BoundaryList2S[count= 0]", list.toString()); } } diff --git a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundarySource2STest.java b/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundarySource2STest.java index 03a741a..0ed9362 100644 --- a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundarySource2STest.java +++ b/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/BoundarySource2STest.java @@ -16,7 +16,7 @@ */ package org.apache.commons.geometry.spherical.twod; -import java.util.stream.Stream; +import java.util.Collections; import org.apache.commons.geometry.core.precision.DoublePrecisionContext; import org.apache.commons.geometry.core.precision.EpsilonDoublePrecisionContext; @@ -27,12 +27,40 @@ public class BoundarySource2STest { private static final double TEST_EPS = 1e-10; - private static final DoublePrecisionContext TEST_PRECISION = new EpsilonDoublePrecisionContext(TEST_EPS); + private static final DoublePrecisionContext TEST_PRECISION = + new EpsilonDoublePrecisionContext(TEST_EPS); + + @Test + public void testToList() { + // act + final BoundarySource2S src = BoundarySource2S.from( + GreatCircles.arcFromPoints(Point2S.PLUS_I, Point2S.PLUS_J, TEST_PRECISION), + GreatCircles.arcFromPoints(Point2S.PLUS_J, Point2S.PLUS_K, TEST_PRECISION) + ); + + // act + final BoundaryList2S list = src.toList(); + + // assert + Assertions.assertEquals(2, list.count()); + } + + @Test + public void testToList_noBoundaries() { + // act + final BoundarySource2S src = BoundarySource2S.from(); + + // act + final BoundaryList2S list = src.toList(); + + // assert + Assertions.assertEquals(0, list.count()); + } @Test public void testToTree() { // act - final BoundarySource2S src = () -> Stream.of( + final BoundarySource2S src = BoundarySource2S.from( GreatCircles.arcFromPoints(Point2S.PLUS_I, Point2S.PLUS_J, TEST_PRECISION)); // act @@ -47,7 +75,7 @@ public class BoundarySource2STest { @Test public void testToTree_noBoundaries() { // act - final BoundarySource2S src = Stream::empty; + final BoundarySource2S src = BoundarySource2S.from(Collections.emptyList()); // act final RegionBSPTree2S tree = src.toTree(); diff --git a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/ConvexArea2STest.java b/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/ConvexArea2STest.java index 78c38a1..d2bbc81 100644 --- a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/ConvexArea2STest.java +++ b/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/ConvexArea2STest.java @@ -791,6 +791,35 @@ public class ConvexArea2STest { } @Test + public void testToList_full() { + // arrange + final ConvexArea2S area = ConvexArea2S.full(); + + // act + final BoundaryList2S list = area.toList(); + + // assert + Assertions.assertEquals(0, list.count()); + } + + @Test + public void testToList() { + // arrange + final ConvexArea2S area = ConvexArea2S.fromVertexLoop(Arrays.asList( + Point2S.of(0.1, 0.1), Point2S.of(-0.4, 1), + Point2S.of(0.15, 1.5), Point2S.of(0.3, 1.2), + Point2S.of(0.1, 0.1) + ), TEST_PRECISION); + + // act + final BoundaryList2S list = area.toList(); + + // assert + Assertions.assertEquals(4, list.count()); + Assertions.assertEquals(area.getSize(), list.toTree().getSize(), TEST_EPS); + } + + @Test public void testToTree_full() { // arrange final ConvexArea2S area = ConvexArea2S.full(); diff --git a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java b/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java index 867d4d8..16259ad 100644 --- a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java +++ b/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/RegionBSPTree2STest.java @@ -226,6 +226,27 @@ public class RegionBSPTree2STest { } @Test + public void testToList_fullAndEmpty() { + // act/assert + Assertions.assertEquals(0, RegionBSPTree2S.full().toList().count()); + Assertions.assertEquals(0, RegionBSPTree2S.empty().toList().count()); + } + + @Test + public void testToList() { + // arrange + final RegionBSPTree2S tree = RegionBSPTree2S.empty(); + insertPositiveQuadrant(tree); + + // act + final BoundaryList2S list = tree.toList(); + + // assert + Assertions.assertEquals(3, list.count()); + Assertions.assertEquals(0.5 * Math.PI, list.toTree().getSize(), TEST_EPS); + } + + @Test public void testToTree_returnsSameInstance() { // arrange final RegionBSPTree2S tree = RegionBSPTree2S.empty();