Repository: commons-math Updated Branches: refs/heads/MATH_3_X b4d2c75d3 -> 5c07e5487
Added dump/parse utilities for BSP trees. These utilities are for test and debug purposes only. Project: http://git-wip-us.apache.org/repos/asf/commons-math/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-math/commit/9744a812 Tree: http://git-wip-us.apache.org/repos/asf/commons-math/tree/9744a812 Diff: http://git-wip-us.apache.org/repos/asf/commons-math/diff/9744a812 Branch: refs/heads/MATH_3_X Commit: 9744a812bdca34cdfc3663e4fbcd40df73def460 Parents: b4d2c75 Author: Luc Maisonobe <l...@apache.org> Authored: Thu Apr 9 22:13:45 2015 +0200 Committer: Luc Maisonobe <l...@apache.org> Committed: Thu Apr 9 22:19:06 2015 +0200 ---------------------------------------------------------------------- .../euclidean/threed/PolyhedronsSetTest.java | 57 ++++ .../geometry/partitioning/RegionDumper.java | 244 +++++++++++++++ .../geometry/partitioning/RegionParser.java | 303 +++++++++++++++++++ 3 files changed, 604 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-math/blob/9744a812/src/test/java/org/apache/commons/math3/geometry/euclidean/threed/PolyhedronsSetTest.java ---------------------------------------------------------------------- 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 b23fc5d..ce7c49d 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,7 +16,11 @@ */ package org.apache.commons.math3.geometry.euclidean.threed; +import java.io.IOException; +import java.text.ParseException; import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; import org.apache.commons.math3.exception.MathArithmeticException; import org.apache.commons.math3.exception.MathIllegalArgumentException; @@ -29,7 +33,9 @@ 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.RegionDumper; import org.apache.commons.math3.geometry.partitioning.RegionFactory; +import org.apache.commons.math3.geometry.partitioning.RegionParser; import org.apache.commons.math3.geometry.partitioning.SubHyperplane; import org.apache.commons.math3.util.FastMath; import org.junit.Assert; @@ -307,6 +313,57 @@ public class PolyhedronsSetTest { } } + @Test + public void testDumpParse() throws IOException, ParseException { + double tol=1e-8; + + Vector3D[] verts=new Vector3D[8]; + double xmin=-1,xmax=1; + double ymin=-1,ymax=1; + double zmin=-1,zmax=1; + verts[0]=new Vector3D(xmin,ymin,zmin); + verts[1]=new Vector3D(xmax,ymin,zmin); + verts[2]=new Vector3D(xmax,ymax,zmin); + verts[3]=new Vector3D(xmin,ymax,zmin); + verts[4]=new Vector3D(xmin,ymin,zmax); + verts[5]=new Vector3D(xmax,ymin,zmax); + verts[6]=new Vector3D(xmax,ymax,zmax); + verts[7]=new Vector3D(xmin,ymax,zmax); + // + int[][] faces=new int[12][]; + faces[0]=new int[]{3,1,0}; // bottom (-z) + faces[1]=new int[]{1,3,2}; // bottom (-z) + faces[2]=new int[]{5,7,4}; // top (+z) + faces[3]=new int[]{7,5,6}; // top (+z) + faces[4]=new int[]{2,5,1}; // right (+x) + faces[5]=new int[]{5,2,6}; // right (+x) + faces[6]=new int[]{4,3,0}; // left (-x) + faces[7]=new int[]{3,4,7}; // left (-x) + faces[8]=new int[]{4,1,5}; // front (-y) + faces[9]=new int[]{1,4,0}; // front (-y) + faces[10]=new int[]{3,6,2}; // back (+y) + faces[11]=new int[]{6,3,7}; // back (+y) + // + Set<SubHyperplane<Euclidean3D>> pset=new HashSet<>(); + for (int f=0; f<faces.length; f++) { + int[] vidx=faces[f]; + Plane p=new Plane(verts[vidx[0]],verts[vidx[1]],verts[vidx[2]],tol); + Vector2D p0=p.toSubSpace(verts[vidx[0]]); + Vector2D p1=p.toSubSpace(verts[vidx[1]]); + Vector2D p2=p.toSubSpace(verts[vidx[2]]); + PolygonsSet lset=new PolygonsSet(tol,p0,p1,p2); + pset.add(new SubPlane(p,lset)); + } + PolyhedronsSet polyset=new PolyhedronsSet(pset,tol); + Assert.assertEquals(8.0, polyset.getSize(), 1.0e-10); + Assert.assertEquals(24.0, polyset.getBoundarySize(), 1.0e-10); + String dump = RegionDumper.dump(polyset); + PolyhedronsSet parsed = RegionParser.parsePolyhedronsSet(dump); + Assert.assertEquals(8.0, parsed.getSize(), 1.0e-10); + Assert.assertEquals(24.0, parsed.getBoundarySize(), 1.0e-10); + Assert.assertTrue(new RegionFactory<Euclidean3D>().difference(polyset, parsed).isEmpty()); + } + 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])); http://git-wip-us.apache.org/repos/asf/commons-math/blob/9744a812/src/test/java/org/apache/commons/math3/geometry/partitioning/RegionDumper.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math3/geometry/partitioning/RegionDumper.java b/src/test/java/org/apache/commons/math3/geometry/partitioning/RegionDumper.java new file mode 100644 index 0000000..33be9d7 --- /dev/null +++ b/src/test/java/org/apache/commons/math3/geometry/partitioning/RegionDumper.java @@ -0,0 +1,244 @@ +/* + * 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.math3.geometry.partitioning; + +import java.util.Formatter; +import java.util.Locale; + +import org.apache.commons.math3.geometry.Space; +import org.apache.commons.math3.geometry.euclidean.oned.Euclidean1D; +import org.apache.commons.math3.geometry.euclidean.oned.IntervalsSet; +import org.apache.commons.math3.geometry.euclidean.oned.OrientedPoint; +import org.apache.commons.math3.geometry.euclidean.oned.Vector1D; +import org.apache.commons.math3.geometry.euclidean.threed.Euclidean3D; +import org.apache.commons.math3.geometry.euclidean.threed.Plane; +import org.apache.commons.math3.geometry.euclidean.threed.PolyhedronsSet; +import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; +import org.apache.commons.math3.geometry.euclidean.twod.Euclidean2D; +import org.apache.commons.math3.geometry.euclidean.twod.Line; +import org.apache.commons.math3.geometry.euclidean.twod.PolygonsSet; +import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; +import org.apache.commons.math3.geometry.spherical.oned.ArcsSet; +import org.apache.commons.math3.geometry.spherical.oned.LimitAngle; +import org.apache.commons.math3.geometry.spherical.oned.Sphere1D; +import org.apache.commons.math3.geometry.spherical.twod.Circle; +import org.apache.commons.math3.geometry.spherical.twod.Sphere2D; +import org.apache.commons.math3.geometry.spherical.twod.SphericalPolygonsSet; + +/** Class dumping a string representation of an {@link AbstractRegion}. + * <p> + * This class is intended for tests and debug purposes only. + * </p> + * @see RegionParser + * @since 3.5 + */ +public class RegionDumper { + + /** Private constructor for a utility class + */ + private RegionDumper() { + } + + /** Get a string representation of an {@link ArcsSet}. + * @param arcsSet region to dump + * @return string representation of the region + */ + public static String dump(final ArcsSet arcsSet) { + final TreeDumper<Sphere1D> visitor = new TreeDumper<Sphere1D>("ArcsSet", arcsSet.getTolerance()) { + + /** {@inheritDoc} */ + @Override + protected void formatHyperplane(final Hyperplane<Sphere1D> hyperplane) { + final LimitAngle h = (LimitAngle) hyperplane; + getFormatter().format("%22.15e %b %22.15e", + h.getLocation().getAlpha(), h.isDirect(), h.getTolerance()); + } + + }; + arcsSet.getTree(false).visit(visitor); + return visitor.getDump(); + } + + /** Get a string representation of a {@link SphericalPolygonsSet}. + * @param sphericalPolygonsSet region to dump + * @return string representation of the region + */ + public static String dump(final SphericalPolygonsSet sphericalPolygonsSet) { + final TreeDumper<Sphere2D> visitor = new TreeDumper<Sphere2D>("SphericalPolygonsSet", sphericalPolygonsSet.getTolerance()) { + + /** {@inheritDoc} */ + @Override + protected void formatHyperplane(final Hyperplane<Sphere2D> hyperplane) { + final Circle h = (Circle) hyperplane; + getFormatter().format("%22.15e %22.15e %22.15e %22.15e", + h.getPole().getX(), h.getPole().getY(), h.getPole().getZ(), + h.getTolerance()); + } + + }; + sphericalPolygonsSet.getTree(false).visit(visitor); + return visitor.getDump(); + } + + /** Get a string representation of an {@link IntervalsSet}. + * @param intervalsSet region to dump + * @return string representation of the region + */ + public static String dump(final IntervalsSet intervalsSet) { + final TreeDumper<Euclidean1D> visitor = new TreeDumper<Euclidean1D>("IntervalsSet", intervalsSet.getTolerance()) { + + /** {@inheritDoc} */ + @Override + protected void formatHyperplane(final Hyperplane<Euclidean1D> hyperplane) { + final OrientedPoint h = (OrientedPoint) hyperplane; + getFormatter().format("%22.15e %b %22.15e", + h.getLocation().getX(), h.isDirect(), h.getTolerance()); + } + + }; + intervalsSet.getTree(false).visit(visitor); + return visitor.getDump(); + } + + /** Get a string representation of a {@link PolygonsSet}. + * @param polygonsSet region to dump + * @return string representation of the region + */ + public static String dump(final PolygonsSet polygonsSet) { + final TreeDumper<Euclidean2D> visitor = new TreeDumper<Euclidean2D>("PolygonsSet", polygonsSet.getTolerance()) { + + /** {@inheritDoc} */ + @Override + protected void formatHyperplane(final Hyperplane<Euclidean2D> hyperplane) { + final Line h = (Line) hyperplane; + final Vector2D p = h.toSpace(Vector1D.ZERO); + getFormatter().format("%22.15e %22.15e %22.15e %22.15e", + p.getX(), p.getY(), h.getAngle(), h.getTolerance()); + } + + }; + polygonsSet.getTree(false).visit(visitor); + return visitor.getDump(); + } + + /** Get a string representation of a {@link PolyhedronsSet}. + * @param polyhedronsSet region to dump + * @return string representation of the region + */ + public static String dump(final PolyhedronsSet polyhedronsSet) { + final TreeDumper<Euclidean3D> visitor = new TreeDumper<Euclidean3D>("PolyhedronsSet", polyhedronsSet.getTolerance()) { + + /** {@inheritDoc} */ + @Override + protected void formatHyperplane(final Hyperplane<Euclidean3D> hyperplane) { + final Plane h = (Plane) hyperplane; + final Vector3D p = h.toSpace(Vector2D.ZERO); + getFormatter().format("%22.15e %22.15e %22.15e %22.15e %22.15e %22.15e %22.15e", + p.getX(), p.getY(), p.getZ(), + h.getNormal().getX(), h.getNormal().getY(), h.getNormal().getZ(), + h.getTolerance()); + } + + }; + polyhedronsSet.getTree(false).visit(visitor); + return visitor.getDump(); + } + + /** Dumping visitor. + * @param <S> Type of the space. + */ + private abstract static class TreeDumper<S extends Space> implements BSPTreeVisitor<S> { + + /** Builder for the string representation of the dumped tree. */ + private final StringBuilder dump; + + /** Formatter for strings. */ + private final Formatter formatter; + + /** Current indentation prefix. */ + private String prefix; + + /** Simple constructor. + * @param type type of the region to dump + * @param tolerance tolerance of the region + */ + public TreeDumper(final String type, final double tolerance) { + this.dump = new StringBuilder(); + this.formatter = new Formatter(dump, Locale.US); + this.prefix = ""; + formatter.format("%s%n", type); + formatter.format("tolerance %22.15e%n", tolerance); + } + + /** Get the string representation of the tree. + * @return string representation of the tree. + */ + public String getDump() { + return dump.toString(); + } + + /** Get the formatter to use. + * @return formatter to use + */ + protected Formatter getFormatter() { + return formatter; + } + + /** Format a string representation of the hyperplane underlying a cut sub-hyperplane. + * @param hyperplane hyperplane to format + */ + protected abstract void formatHyperplane(Hyperplane<S> hyperplane); + + /** {@inheritDoc} */ + @Override + public Order visitOrder(final BSPTree<S> node) { + return Order.SUB_MINUS_PLUS; + } + + /** {@inheritDoc} */ + @Override + public void visitInternalNode(final BSPTree<S> node) { + formatter.format("%s %s internal ", prefix, type(node)); + formatHyperplane(node.getCut().getHyperplane()); + formatter.format("%n"); + prefix = prefix + " "; + } + + /** {@inheritDoc} */ + @Override + public void visitLeafNode(final BSPTree<S> node) { + formatter.format("%s %s leaf %s%n", + prefix, type(node), node.getAttribute()); + for (BSPTree<S> n = node; + n.getParent() != null && n == n.getParent().getPlus(); + n = n.getParent()) { + prefix = prefix.substring(0, prefix.length() - 2); + } + } + + /** Get the type of the node. + * @param node node to check + * @return "plus " or "minus" depending on the node being the plus or minus + * child of its parent ("plus " is arbitrarily returned for the root node) + */ + private String type(final BSPTree<S> node) { + return (node.getParent() != null && node == node.getParent().getMinus()) ? "minus" : "plus "; + } + + } + +} http://git-wip-us.apache.org/repos/asf/commons-math/blob/9744a812/src/test/java/org/apache/commons/math3/geometry/partitioning/RegionParser.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/math3/geometry/partitioning/RegionParser.java b/src/test/java/org/apache/commons/math3/geometry/partitioning/RegionParser.java new file mode 100644 index 0000000..8fc1e6e --- /dev/null +++ b/src/test/java/org/apache/commons/math3/geometry/partitioning/RegionParser.java @@ -0,0 +1,303 @@ +/* + * 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.math3.geometry.partitioning; + +import java.io.IOException; +import java.text.ParseException; +import java.util.StringTokenizer; + +import org.apache.commons.math3.geometry.Space; +import org.apache.commons.math3.geometry.euclidean.oned.Euclidean1D; +import org.apache.commons.math3.geometry.euclidean.oned.IntervalsSet; +import org.apache.commons.math3.geometry.euclidean.oned.OrientedPoint; +import org.apache.commons.math3.geometry.euclidean.oned.Vector1D; +import org.apache.commons.math3.geometry.euclidean.threed.Euclidean3D; +import org.apache.commons.math3.geometry.euclidean.threed.Plane; +import org.apache.commons.math3.geometry.euclidean.threed.PolyhedronsSet; +import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; +import org.apache.commons.math3.geometry.euclidean.twod.Euclidean2D; +import org.apache.commons.math3.geometry.euclidean.twod.Line; +import org.apache.commons.math3.geometry.euclidean.twod.PolygonsSet; +import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; +import org.apache.commons.math3.geometry.spherical.oned.ArcsSet; +import org.apache.commons.math3.geometry.spherical.oned.LimitAngle; +import org.apache.commons.math3.geometry.spherical.oned.S1Point; +import org.apache.commons.math3.geometry.spherical.oned.Sphere1D; +import org.apache.commons.math3.geometry.spherical.twod.Circle; +import org.apache.commons.math3.geometry.spherical.twod.Sphere2D; +import org.apache.commons.math3.geometry.spherical.twod.SphericalPolygonsSet; + +/** Class parsing a string representation of an {@link AbstractRegion}. + * <p> + * This class is intended for tests and debug purposes only. + * </p> + * @see RegionDumper + * @since 3.5 + */ +public class RegionParser { + + /** Private constructor for a utility class + */ + private RegionParser() { + } + + /** Parse a string representation of an {@link ArcsSet}. + * @param s string to parse + * @return parsed region + * @exception IOException if the string cannot be read + * @exception ParseException if the string cannot be parsed + */ + public static ArcsSet parseArcsSet(final String s) + throws IOException, ParseException { + final TreeBuilder<Sphere1D> builder = new TreeBuilder<Sphere1D>("ArcsSet", s) { + + /** {@inheritDoc} */ + @Override + protected LimitAngle parseHyperplane() + throws IOException, ParseException { + return new LimitAngle(new S1Point(getNumber()), getBoolean(), getNumber()); + } + + }; + return new ArcsSet(builder.getTree(), builder.getTolerance()); + } + + /** Parse a string representation of a {@link SphericalPolygonsSet}. + * @param s string to parse + * @return parsed region + * @exception IOException if the string cannot be read + * @exception ParseException if the string cannot be parsed + */ + public static SphericalPolygonsSet parseSphericalPolygonsSet(final String s) + throws IOException, ParseException { + final TreeBuilder<Sphere2D> builder = new TreeBuilder<Sphere2D>("SphericalPolygonsSet", s) { + + /** {@inheritDoc} */ + @Override + public Circle parseHyperplane() + throws IOException, ParseException { + return new Circle(new Vector3D(getNumber(), getNumber(), getNumber()), getNumber()); + } + + }; + return new SphericalPolygonsSet(builder.getTree(), builder.getTolerance()); + } + + /** Parse a string representation of an {@link IntervalsSet}. + * @param s string to parse + * @return parsed region + * @exception IOException if the string cannot be read + * @exception ParseException if the string cannot be parsed + */ + public static IntervalsSet parseIntervalsSet(final String s) + throws IOException, ParseException { + final TreeBuilder<Euclidean1D> builder = new TreeBuilder<Euclidean1D>("IntervalsSet", s) { + + /** {@inheritDoc} */ + @Override + public OrientedPoint parseHyperplane() + throws IOException, ParseException { + return new OrientedPoint(new Vector1D(getNumber()), getBoolean(), getNumber()); + } + + }; + return new IntervalsSet(builder.getTree(), builder.getTolerance()); + } + + /** Parse a string representation of a {@link PolygonsSet}. + * @param s string to parse + * @return parsed region + * @exception IOException if the string cannot be read + * @exception ParseException if the string cannot be parsed + */ + public static PolygonsSet parsePolygonsSet(final String s) + throws IOException, ParseException { + final TreeBuilder<Euclidean2D> builder = new TreeBuilder<Euclidean2D>("PolygonsSet", s) { + + /** {@inheritDoc} */ + @Override + public Line parseHyperplane() + throws IOException, ParseException { + return new Line(new Vector2D(getNumber(), getNumber()), getNumber(), getNumber()); + } + + }; + return new PolygonsSet(builder.getTree(), builder.getTolerance()); + } + + /** Parse a string representation of a {@link PolyhedronsSet}. + * @param s string to parse + * @return parsed region + * @exception IOException if the string cannot be read + * @exception ParseException if the string cannot be parsed + */ + public static PolyhedronsSet parsePolyhedronsSet(final String s) + throws IOException, ParseException { + final TreeBuilder<Euclidean3D> builder = new TreeBuilder<Euclidean3D>("PolyhedronsSet", s) { + + /** {@inheritDoc} */ + @Override + public Plane parseHyperplane() + throws IOException, ParseException { + return new Plane(new Vector3D(getNumber(), getNumber(), getNumber()), + new Vector3D(getNumber(), getNumber(), getNumber()), + getNumber()); + } + + }; + return new PolyhedronsSet(builder.getTree(), builder.getTolerance()); + } + + /** Local class for building an {@link AbstractRegion} tree. + * @param <S> Type of the space. + */ + private abstract static class TreeBuilder<S extends Space> { + + /** Keyword for tolerance. */ + private static final String TOLERANCE = "tolerance"; + + /** Keyword for internal nodes. */ + private static final String INTERNAL = "internal"; + + /** Keyword for leaf nodes. */ + private static final String LEAF = "leaf"; + + /** Keyword for plus children trees. */ + private static final String PLUS = "plus"; + + /** Keyword for minus children trees. */ + private static final String MINUS = "minus"; + + /** Keyword for true flags. */ + private static final String TRUE = "true"; + + /** Keyword for false flags. */ + private static final String FALSE = "false"; + + /** Tree root. */ + private BSPTree<S> root; + + /** Tolerance. */ + private final double tolerance; + + /** Tokenizer parsing string representation. */ + private final StringTokenizer tokenizer; + + /** Simple constructor. + * @param type type of the expected representation + * @param reader reader for the string representation + * @exception IOException if the string cannot be read + * @exception ParseException if the string cannot be parsed + */ + public TreeBuilder(final String type, final String s) + throws IOException, ParseException { + root = null; + tokenizer = new StringTokenizer(s); + getWord(type); + getWord(TOLERANCE); + tolerance = getNumber(); + getWord(PLUS); + root = new BSPTree<S>(); + parseTree(root); + if (tokenizer.hasMoreTokens()) { + throw new ParseException("unexpected " + tokenizer.nextToken(), 0); + } + } + + /** Parse a tree. + * @param node start node + * @exception IOException if the string cannot be read + * @exception ParseException if the string cannot be parsed + */ + private void parseTree(final BSPTree<S> node) + throws IOException, ParseException { + if (INTERNAL.equals(getWord(INTERNAL, LEAF))) { + // this is an internal node, it has a cut sub-hyperplane (stored as a whole hyperplane) + // then a minus tree, then a plus tree + node.insertCut(parseHyperplane()); + getWord(MINUS); + parseTree(node.getMinus()); + getWord(PLUS); + parseTree(node.getPlus()); + } else { + // this is a leaf node, it has only an inside/outside flag + node.setAttribute(getBoolean()); + } + } + + /** Get next word. + * @param allowed allowed values + * @return parsed word + * @exception IOException if the string cannot be read + * @exception ParseException if the string cannot be parsed + */ + protected String getWord(final String ... allowed) + throws IOException, ParseException { + final String token = tokenizer.nextToken(); + for (final String a : allowed) { + if (a.equals(token)) { + return token; + } + } + throw new ParseException(token + " != " + allowed[0], 0); + } + + /** Get next number. + * @return parsed number + * @exception IOException if the string cannot be read + * @exception NumberFormatException if the string cannot be parsed + */ + protected double getNumber() + throws IOException, NumberFormatException { + return Double.parseDouble(tokenizer.nextToken()); + } + + /** Get next boolean. + * @return parsed boolean + * @exception IOException if the string cannot be read + * @exception ParseException if the string cannot be parsed + */ + protected boolean getBoolean() + throws IOException, ParseException { + return getWord(TRUE, FALSE).equals(TRUE); + } + + /** Get the built tree. + * @return built tree + */ + public BSPTree<S> getTree() { + return root; + } + + /** Get the tolerance. + * @return tolerance + */ + public double getTolerance() { + return tolerance; + } + + /** Parse an hyperplane. + * @return next hyperplane from the stream + * @exception IOException if the string cannot be read + * @exception ParseException if the string cannot be parsed + */ + protected abstract Hyperplane<S> parseHyperplane() + throws IOException, ParseException; + + } + +}