From dd6cefb0ccb596d0597e2a9991766e109153ab25 Mon Sep 17 00:00:00 2001 From: Luc Maisonobe Date: Sun, 13 May 2012 15:51:56 +0000 Subject: [PATCH] Fixed a wrong assumption on BSP tree attributes. The assumption was that the attribute was always a boolean when boundary was empty. This assumption was false when emptiness resulted from a collapsed boundary. Boolean attributes occur only at leaf nodes, so it is the cut sub-hyperplane that needed to be checked. JIRA: MATH-780 git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1337929 13f79535-47bb-0310-9956-ffa450edef68 --- src/changes/changes.xml | 4 ++ .../geometry/euclidean/twod/PolygonsSet.java | 4 +- .../euclidean/threed/PolyhedronsSetTest.java | 54 +++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 5fb43778a..a3c40fe96 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -52,6 +52,10 @@ If the output is not quite correct, check for invisible trailing spaces! + + Fixed a wrong assumption on BSP tree attributes when boundary collapses to a too + small polygon at a non-leaf node. + Put serialization back for PointValuePair and PointVectorValuePair. diff --git a/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSet.java b/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSet.java index 6ba72be94..add24acea 100644 --- a/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSet.java +++ b/src/main/java/org/apache/commons/math3/geometry/euclidean/twod/PolygonsSet.java @@ -132,7 +132,9 @@ public class PolygonsSet extends AbstractRegion { final Vector2D[][] v = getVertices(); if (v.length == 0) { - if ((Boolean) getTree(false).getAttribute()) { + final BSPTree tree = getTree(false); + if (tree.getCut() == null && (Boolean) tree.getAttribute()) { + // the instance covers the whole space setSize(Double.POSITIVE_INFINITY); setBarycenter(Vector2D.NaN); } else { diff --git a/src/test/java/org/apache/commons/math3/geometry/euclidean/threed/PolyhedronsSetTest.java b/src/test/java/org/apache/commons/math3/geometry/euclidean/threed/PolyhedronsSetTest.java index 6c776711f..a55f017f1 100644 --- a/src/test/java/org/apache/commons/math3/geometry/euclidean/threed/PolyhedronsSetTest.java +++ b/src/test/java/org/apache/commons/math3/geometry/euclidean/threed/PolyhedronsSetTest.java @@ -16,13 +16,18 @@ */ package org.apache.commons.math3.geometry.euclidean.threed; +import java.util.ArrayList; + +import org.apache.commons.math3.geometry.euclidean.twod.Euclidean2D; import org.apache.commons.math3.geometry.euclidean.twod.PolygonsSet; +import org.apache.commons.math3.geometry.euclidean.twod.SubLine; import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; import org.apache.commons.math3.geometry.partitioning.BSPTree; import org.apache.commons.math3.geometry.partitioning.BSPTreeVisitor; import org.apache.commons.math3.geometry.partitioning.BoundaryAttribute; import org.apache.commons.math3.geometry.partitioning.Region; import org.apache.commons.math3.geometry.partitioning.RegionFactory; +import org.apache.commons.math3.geometry.partitioning.SubHyperplane; import org.apache.commons.math3.util.FastMath; import org.junit.Assert; import org.junit.Test; @@ -228,6 +233,55 @@ public class PolyhedronsSetTest { } + @Test + public void testIssue780() { + float[] coords = { + 1.000000f, -1.000000f, -1.000000f, + 1.000000f, -1.000000f, 1.000000f, + -1.000000f, -1.000000f, 1.000000f, + -1.000000f, -1.000000f, -1.000000f, + 1.000000f, 1.000000f, -1f, + 0.999999f, 1.000000f, 1.000000f, // 1.000000f, 1.000000f, 1.000000f, + -1.000000f, 1.000000f, 1.000000f, + -1.000000f, 1.000000f, -1.000000f}; + int[] indices = { + 0, 1, 2, 0, 2, 3, + 4, 7, 6, 4, 6, 5, + 0, 4, 5, 0, 5, 1, + 1, 5, 6, 1, 6, 2, + 2, 6, 7, 2, 7, 3, + 4, 0, 3, 4, 3, 7}; + ArrayList> subHyperplaneList = new ArrayList>(); + for (int idx = 0; idx < indices.length; idx += 3) { + int idxA = indices[idx] * 3; + int idxB = indices[idx + 1] * 3; + int idxC = indices[idx + 2] * 3; + Vector3D v_1 = new Vector3D(coords[idxA], coords[idxA + 1], coords[idxA + 2]); + Vector3D v_2 = new Vector3D(coords[idxB], coords[idxB + 1], coords[idxB + 2]); + Vector3D v_3 = new Vector3D(coords[idxC], coords[idxC + 1], coords[idxC + 2]); + Vector3D[] vertices = {v_1, v_2, v_3}; + Plane polyPlane = new Plane(v_1, v_2, v_3); + ArrayList> lines = new ArrayList>(); + + Vector2D[] projPts = new Vector2D[vertices.length]; + for (int ptIdx = 0; ptIdx < projPts.length; ptIdx++) { + projPts[ptIdx] = polyPlane.toSubSpace(vertices[ptIdx]); + } + + SubLine lineInPlane = null; + for (int ptIdx = 0; ptIdx < projPts.length; ptIdx++) { + lineInPlane = new SubLine(projPts[ptIdx], projPts[(ptIdx + 1) % projPts.length]); + lines.add(lineInPlane); + } + Region polyRegion = new PolygonsSet(lines); + SubPlane polygon = new SubPlane(polyPlane, polyRegion); + subHyperplaneList.add(polygon); + } + PolyhedronsSet polyhedronsSet = new PolyhedronsSet(subHyperplaneList); + Assert.assertEquals( 8.0, polyhedronsSet.getSize(), 3.0e-6); + Assert.assertEquals(24.0, polyhedronsSet.getBoundarySize(), 5.0e-6); + } + private void checkPoints(Region.Location expected, PolyhedronsSet tree, Vector3D[] points) { for (int i = 0; i < points.length; ++i) { Assert.assertEquals(expected, tree.checkPoint(points[i]));