This is an automated email from the ASF dual-hosted git repository. erans pushed a commit to branch GEOMETRY-3__TBR in repository https://gitbox.apache.org/repos/asf/commons-geometry.git
commit 2331c8a18296ae25e1b4b85b98bc7b7dbb718d05 Author: Matt Juntunen <[email protected]> AuthorDate: Sat Jun 30 00:53:10 2018 -0400 GEOMETRY-3: simplifying parse and format functionality; renaming Coordinates.Factory?D interfaces to be more generic RealFunction interfaces --- .../core/util/AbstractCoordinateParser.java | 257 ------------ .../commons/geometry/core/util/Coordinates.java | 68 ---- .../commons/geometry/core/util/RealFunction.java | 31 ++ .../commons/geometry/core/util/RealFunction2N.java | 32 ++ .../commons/geometry/core/util/RealFunction3N.java | 33 ++ .../geometry/core/util/SimpleCoordinateFormat.java | 202 ---------- .../core/util/internal/SimpleTupleFormat.java | 430 +++++++++++++++++++++ .../geometry/core/util/internal/package-info.java | 24 ++ .../SimpleTupleFormatTest.java} | 88 ++--- .../geometry/euclidean/oned/Cartesian1D.java | 7 + .../commons/geometry/euclidean/oned/Point1D.java | 20 +- .../commons/geometry/euclidean/oned/Vector1D.java | 20 +- .../geometry/euclidean/threed/Cartesian3D.java | 7 + .../commons/geometry/euclidean/threed/Point3D.java | 20 +- .../geometry/euclidean/threed/Vector3D.java | 20 +- .../geometry/euclidean/twod/Cartesian2D.java | 7 + .../commons/geometry/euclidean/twod/Point2D.java | 20 +- .../commons/geometry/euclidean/twod/Vector2D.java | 20 +- .../geometry/euclidean/oned/Cartesian1DTest.java | 16 + .../geometry/euclidean/oned/Point1DTest.java | 8 +- .../geometry/euclidean/oned/Vector1DTest.java | 20 +- .../geometry/euclidean/threed/Cartesian3DTest.java | 16 + .../geometry/euclidean/threed/Point3DTest.java | 8 +- .../geometry/euclidean/threed/Vector3DTest.java | 18 +- .../geometry/euclidean/twod/Cartesian2DTest.java | 16 + .../geometry/euclidean/twod/Point2DTest.java | 8 +- .../geometry/euclidean/twod/Vector2DTest.java | 18 +- .../commons/geometry/spherical/oned/S1Point.java | 16 +- .../commons/geometry/spherical/twod/S2Point.java | 16 +- .../geometry/spherical/oned/S1PointTest.java | 10 +- .../geometry/spherical/twod/S2PointTest.java | 8 +- 31 files changed, 765 insertions(+), 719 deletions(-) diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/AbstractCoordinateParser.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/AbstractCoordinateParser.java deleted file mode 100644 index ceb8527..0000000 --- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/AbstractCoordinateParser.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * 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.util; - -import java.text.ParsePosition; - -/** Abstract class providing basic parsing functionality for reading coordinate tuples - * from strings. - */ -public abstract class AbstractCoordinateParser { - - /** String separating coordinate values */ - private final String separator; - - /** String used to signal the start of a coordinate tuple; may be null */ - private final String prefix; - - /** String used to signal the end of a coordinate tuple; may be null */ - private final String suffix; - - /** Simple constructor - * @param separator String used to separate coordinate values; must not be null. - * @param prefix String used to signal the start of a coordinate tuple; if null, no - * string is expected at the start of the tuple - * @param suffix String used to signal the end of a coordinate tuple; if null, no - * string is expected at the end of the tuple - */ - protected AbstractCoordinateParser(String separator, String prefix, String suffix) { - this.separator = separator; - this.prefix = prefix; - this.suffix = suffix; - } - - /** Returns the string used to separate coordinate values. - * @return the coordinate value separator string - */ - public String getSeparator() { - return separator; - } - - /** Returns the string used to signal the start of a coordinate tuple. This value may be null. - * @return the string used to begin each coordinate tuple or null - */ - public String getPrefix() { - return prefix; - } - - /** Returns the string used to signal the end of a coordinate tuple. This value may be null. - * @return the string used to end each coordinate tuple or null - */ - public String getSuffix() { - return suffix; - } - - /** Reads the configured prefix from the current position in the given string, ignoring any preceding - * whitespace, and advances the parsing position past the prefix sequence. An exception is thrown if the - * prefix is not found. Does nothing if the prefix is null. - * @param str the string being parsed - * @param pos the current parsing position - * @throws IllegalArgumentException if the configured prefix is not null and is not found at the current - * parsing position, ignoring preceding whitespace - */ - protected void readPrefix(String str, ParsePosition pos) throws IllegalArgumentException { - if (prefix != null) { - consumeWhitespace(str, pos); - readSequence(str, prefix, pos); - } - } - - /** Reads and returns a coordinate value from the current position in the given string. An exception is thrown if a - * valid number is not found. The parsing position is advanced past the parsed number and any trailing separator. - * @param str the string being parsed - * @param pos the current parsing position - * @return the coordinate value - * @throws IllegalArgumentException if the configured prefix is not null and is not found at the current - * parsing position, ignoring preceding whitespace - */ - protected double readCoordinateValue(String str, ParsePosition pos) throws IllegalArgumentException { - final int startIdx = pos.getIndex(); - - int endIdx = str.indexOf(separator, startIdx); - if (endIdx < 0) { - if (suffix != null) { - endIdx = str.indexOf(suffix, startIdx); - } - - if (endIdx < 0) { - endIdx = str.length(); - } - } - - String substr = str.substring(startIdx, endIdx); - try { - double value = Double.parseDouble(substr); - - // advance the position and move past any terminating separator - pos.setIndex(endIdx); - matchSequence(str, separator, pos); - - return value; - } - catch (NumberFormatException exc) { - fail(String.format("unable to parse number from string \"%s\"", substr), str, pos, exc); - return 0.0; // for the compiler - } - } - - /** Reads the configured suffix from the current position in the given string, ignoring any preceding - * whitespace, and advances the parsing position past the suffix sequence. An exception is thrown if the - * suffix is not found. Does nothing if the suffix is null. - * @param str the string being parsed - * @param pos the current parsing position - * @throws IllegalArgumentException if the configured suffix is not null and is not found at the current - * parsing position, ignoring preceding whitespace - */ - protected void readSuffix(String str, ParsePosition pos) throws IllegalArgumentException { - if (suffix != null) { - consumeWhitespace(str, pos); - readSequence(str, suffix, pos); - } - } - - /** Ends a parse operation by ensuring that all non-whitespace characters in the string have been parsed. An - * exception is thrown if extra content is found. - * @param str the string being parsed - * @param pos the current parsing position - * @throws IllegalArgumentException if extra non-whitespace content is found past the current parsing position - */ - protected void endParse(String str, ParsePosition pos) throws IllegalArgumentException { - consumeWhitespace(str, pos); - if (pos.getIndex() != str.length()) { - fail("unexpected content", str, pos); - } - } - - /** Advances {@code pos} past any whitespace characters in {@code str}, - * starting at the current parse position index. - * @param str the input string - * @param pos the current parse position - */ - protected void consumeWhitespace(String str, ParsePosition pos) { - int idx = pos.getIndex(); - final int len = str.length(); - - for (; idx<len; ++idx) { - if (!Character.isWhitespace(str.codePointAt(idx))) { - break; - } - } - - pos.setIndex(idx); - } - - /** Returns a boolean indicating whether or not the input string {@code str} - * contains the string {@code seq} at the given parse index. If the match succeeds, - * the index of {@code pos} is moved to the first character after the match. If - * the match does not succeed, the parse position is left unchanged. - * @param str the string to match against - * @param seq the sequence to look for in {@code str} - * @param pos the parse position indicating the index in {@code str} - * to attempt the match - * @return true if {@code str} contains exactly the same characters as {@code seq} - * at {@code pos}; otherwise, false - */ - protected boolean matchSequence(String str, String seq, ParsePosition pos) { - final int idx = pos.getIndex(); - final int inputLength = str.length(); - final int seqLength = seq.length(); - - int i = idx; - int s = 0; - for (; i<inputLength && s<seqLength; ++i, ++s) { - if (str.codePointAt(i) != seq.codePointAt(s)) { - break; - } - } - - if (i <= inputLength && s == seqLength) { - pos.setIndex(idx + seqLength); - return true; - } - return false; - } - - /** Reads the string given by {@code seq} from the given position in {@code str}. - * Throws an IllegalArgumentException if the sequence is not found at that position. - * @param str the string to match against - * @param seq the sequence to look for in {@code str} - * @param pos the parse position indicating the index in {@code str} - * to attempt the match - * @throws IllegalArgumentException if {@code str} does not contain the characters from - * {@code seq} at position {@code pos} - */ - protected void readSequence(String str, String seq, ParsePosition pos) throws IllegalArgumentException { - if (!matchSequence(str, seq, pos)) { - final int idx = pos.getIndex(); - final String actualSeq = str.substring(idx, Math.min(str.length(), idx + seq.length())); - - fail(String.format("expected \"%s\" but found \"%s\"", seq, actualSeq), str, pos); - } - } - - /** Aborts the current parsing operation by throwing an {@link IllegalArgumentException} with an informative - * error message. - * @param msg the error message - * @param str the string being parsed - * @param pos the current parse position - * @throws IllegalArgumentException the exception signaling a parse failure - */ - protected void fail(String msg, String str, ParsePosition pos) throws IllegalArgumentException { - fail(msg, str, pos, null); - } - - /** Aborts the current parsing operation by throwing an {@link IllegalArgumentException} with an informative - * error message. - * @param msg the error message - * @param str the string being parsed - * @param pos the current parse position - * @param cause the original cause of the error - * @throws IllegalArgumentException the exception signaling a parse failure - */ - protected void fail(String msg, String str, ParsePosition pos, Throwable cause) throws IllegalArgumentException { - String fullMsg = String.format("Failed to parse string \"%s\" at index %d: %s", str, pos.getIndex(), msg); - - throw new CoordinateParseException(fullMsg, cause); - } - - /** Exception class for errors occurring during coordinate parsing. - */ - private static class CoordinateParseException extends IllegalArgumentException { - - /** Serializable version identifier */ - private static final long serialVersionUID = 1494716029613981959L; - - /** Simple constructor. - * @param msg the exception message - * @param cause the exception root cause - */ - CoordinateParseException(String msg, Throwable cause) { - super(msg, cause); - } - } -} diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/Coordinates.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/Coordinates.java deleted file mode 100644 index c9c5fbc..0000000 --- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/Coordinates.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.util; - -/** Utility class for working with coordinate tuples. - */ -public class Coordinates { - - /** Interface for classes that create objects from a single coordinate value. - * @param <T> The type created by this factory. - */ - @FunctionalInterface - public interface Factory1D<T> { - - /** Creates a new instance of type T from the given coordinate value. - * @param a the coordinate value - * @return a new instance of type T - */ - T create(double a); - } - - /** Interface for classes that create objects from two coordinate values. - * @param <T> The type created by this factory. - */ - @FunctionalInterface - public interface Factory2D<T> { - - /** Creates a new instance of type T from the given coordinate values. - * @param a1 the first coordinate value - * @param a2 the second coordinate value - * @return a new instance of type T - */ - T create(double a1, double a2); - } - - /** Interface for classes that create objects from three coordinate values. - * @param <T> The type created by this factory. - */ - @FunctionalInterface - public interface Factory3D<T> { - - /** Creates a new instance of type T from the given coordinate values. - * @param a1 the first coordinate value - * @param a2 the second coordinate value - * @param a3 the third coordinate value - * @return a new instance of type T - */ - T create(double a1, double a2, double a3); - } - - /** Private constructor. */ - private Coordinates() { - } -} diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/RealFunction.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/RealFunction.java new file mode 100644 index 0000000..1b9acb6 --- /dev/null +++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/RealFunction.java @@ -0,0 +1,31 @@ +/* + * 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.util; + +/** Represents a function that accepts a single real number and returns + * a result. + * @param <T> The function return type. + */ +@FunctionalInterface +public interface RealFunction<T> { + + /** Apply the function and return the result. + * @param n the function argument + * @return the function result + */ + T apply(double n); +} diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/RealFunction2N.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/RealFunction2N.java new file mode 100644 index 0000000..20df7c7 --- /dev/null +++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/RealFunction2N.java @@ -0,0 +1,32 @@ +/* + * 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.util; + +/** Represents a function that accepts two real numbers and returns + * a result. + * @param <T> The function return type. + */ +@FunctionalInterface +public interface RealFunction2N<T> { + + /** Apply the function and return the result. + * @param n1 first function argument + * @param n2 second function argument + * @return the function result + */ + T apply(double n1, double n2); +} diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/RealFunction3N.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/RealFunction3N.java new file mode 100644 index 0000000..08e22e2 --- /dev/null +++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/RealFunction3N.java @@ -0,0 +1,33 @@ +/* + * 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.util; + +/** Represents a function that accepts three real numbers and returns + * a result. + * @param <T> The function return type. + */ +@FunctionalInterface +public interface RealFunction3N<T> { + + /** Apply the function and return the result. + * @param n1 first function argument + * @param n2 second function argument + * @param n3 third function argument + * @return the function result + */ + T apply(double n1, double n2, double n3); +} diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/SimpleCoordinateFormat.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/SimpleCoordinateFormat.java deleted file mode 100644 index 6a4eb09..0000000 --- a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/SimpleCoordinateFormat.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * 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.util; - -import java.text.ParsePosition; - -/** Class for performing simple formatting and parsing of coordinate tuples in common dimensions. - */ -public class SimpleCoordinateFormat extends AbstractCoordinateParser { - - /** Default coordinate separator value */ - private static final String DEFAULT_SEPARATOR = ","; - - /** Space character */ - private static final String SPACE = " "; - - /** Static instance configured with default values for working with points. */ - private static final SimpleCoordinateFormat DEFAULT_POINT_FORMAT = - new SimpleCoordinateFormat(DEFAULT_SEPARATOR, "(", ")"); - - /** Static instance configured with default values for working with vectors. */ - private static final SimpleCoordinateFormat DEFAULT_VECTOR_FORMAT = - new SimpleCoordinateFormat(DEFAULT_SEPARATOR, "{", "}"); - - /** Creates a new format instance with the default separator value and the given - * tuple prefix and suffix. - * @param prefix coordinate tuple prefix; may be null - * @param suffix coordinate tuple suffix; may be null - */ - public SimpleCoordinateFormat(String prefix, String suffix) { - this(DEFAULT_SEPARATOR, prefix, suffix); - } - - /** Creates a new format instance with the given separator, prefix, and suffix. - * @param separator string separating coordinate values - * @param prefix coordinate tuple prefix; may be null - * @param suffix coordinate tuple suffix; may be null - */ - public SimpleCoordinateFormat(String separator, String prefix, String suffix) { - super(separator, prefix, suffix); - } - - /** Returns a 1D coordinate tuple string with the given value. - * @param a coordinate value - * @return 1D coordinate tuple string - */ - public String format(double a) { - StringBuilder sb = new StringBuilder(); - - if (getPrefix() != null) { - sb.append(getPrefix()); - } - - sb.append(a); - - if (getSuffix() != null) { - sb.append(getSuffix()); - } - - return sb.toString(); - } - - /** Returns a 2D coordinate tuple string with the given values. - * @param a1 first coordinate value - * @param a2 second coordinate value - * @return 2D coordinate tuple string - */ - public String format(double a1, double a2) { - StringBuilder sb = new StringBuilder(); - - if (getPrefix() != null) { - sb.append(getPrefix()); - } - - sb.append(a1); - sb.append(getSeparator()); - sb.append(SPACE); - sb.append(a2); - - if (getSuffix() != null) { - sb.append(getSuffix()); - } - - return sb.toString(); - } - - /** Returns a 3D coordinate tuple string with the given values. - * @param a1 first coordinate value - * @param a2 second coordinate value - * @param a3 third coordinate value - * @return 3D coordinate tuple string - */ - public String format(double a1, double a2, double a3) { - StringBuilder sb = new StringBuilder(); - - if (getPrefix() != null) { - sb.append(getPrefix()); - } - - sb.append(a1); - sb.append(getSeparator()); - sb.append(SPACE); - sb.append(a2); - sb.append(getSeparator()); - sb.append(SPACE); - sb.append(a3); - - if (getSuffix() != null) { - sb.append(getSuffix()); - } - - return sb.toString(); - } - - /** Parses the given string as a 1D coordinate tuple and passes the coordinate value to the - * given factory. The object created by the factory is returned. - * @param <T> The type created by {@code factory} - * @param str the string to be parsed - * @param factory object that will be passed the parsed coordinate value - * @return object created by {@code factory} - * @throws IllegalArgumentException if the input string format is invalid - */ - public <T> T parse(String str, Coordinates.Factory1D<T> factory) throws IllegalArgumentException { - final ParsePosition pos = new ParsePosition(0); - - readPrefix(str, pos); - final double v = readCoordinateValue(str, pos); - readSuffix(str, pos); - endParse(str, pos); - - return factory.create(v); - } - - /** Parses the given string as a 2D coordinate tuple and passes the coordinate values to the - * given factory. The object created by the factory is returned. - * @param <T> The type created by {@code factory} - * @param str the string to be parsed - * @param factory object that will be passed the parsed coordinate values - * @return object created by {@code factory} - * @throws IllegalArgumentException if the input string format is invalid - */ - public <T> T parse(String str, Coordinates.Factory2D<T> factory) throws IllegalArgumentException { - final ParsePosition pos = new ParsePosition(0); - - readPrefix(str, pos); - final double v1 = readCoordinateValue(str, pos); - final double v2 = readCoordinateValue(str, pos); - readSuffix(str, pos); - endParse(str, pos); - - return factory.create(v1, v2); - } - - /** Parses the given string as a 3D coordinate tuple and passes the coordinate values to the - * given factory. The object created by the factory is returned. - * @param <T> The type created by {@code factory} - * @param str the string to be parsed - * @param factory object that will be passed the parsed coordinate values - * @return object created by {@code factory} - * @throws IllegalArgumentException if the input string format is invalid - */ - public <T> T parse(String str, Coordinates.Factory3D<T> factory) throws IllegalArgumentException { - ParsePosition pos = new ParsePosition(0); - - readPrefix(str, pos); - final double v1 = readCoordinateValue(str, pos); - final double v2 = readCoordinateValue(str, pos); - final double v3 = readCoordinateValue(str, pos); - readSuffix(str, pos); - endParse(str, pos); - - return factory.create(v1, v2, v3); - } - - /** Returns a default instance for working with points. - * @return instance configured with default values for points - */ - public static SimpleCoordinateFormat getPointFormat() { - return DEFAULT_POINT_FORMAT; - } - - /** Returns a default instance for working with vectors. - * @return instance configured with default values for vectors. - */ - public static SimpleCoordinateFormat getVectorFormat() { - return DEFAULT_VECTOR_FORMAT; - } -} diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/internal/SimpleTupleFormat.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/internal/SimpleTupleFormat.java new file mode 100644 index 0000000..84641cb --- /dev/null +++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/internal/SimpleTupleFormat.java @@ -0,0 +1,430 @@ +/* + * 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.util.internal; + +import java.text.ParsePosition; + +import org.apache.commons.geometry.core.util.RealFunction; +import org.apache.commons.geometry.core.util.RealFunction2N; +import org.apache.commons.geometry.core.util.RealFunction3N; + +/** Class for performing simple formatting and parsing of real number tuples. + */ +public class SimpleTupleFormat { + + /** Default value separator string. */ + private static final String DEFAULT_SEPARATOR = ","; + + /** Space character */ + private static final String SPACE = " "; + + /** Static instance configured with default values. Tuples in this format + * are enclosed by parentheses and separated by commas. + */ + private static final SimpleTupleFormat DEFAULT_INSTANCE = + new SimpleTupleFormat(",", "(", ")"); + + /** String separating tuple values */ + private final String separator; + + /** String used to signal the start of a tuple; may be null */ + private final String prefix; + + /** String used to signal the end of a tuple; may be null */ + private final String suffix; + + /** Constructs a new instance with the default string separator (a comma) + * and the given prefix and suffix. + * @param prefix String used to signal the start of a tuple; if null, no + * string is expected at the start of the tuple + * @param suffix String used to signal the end of a tuple; if null, no + * string is expected at the end of the tuple + */ + public SimpleTupleFormat(String prefix, String suffix) { + this(DEFAULT_SEPARATOR, prefix, suffix); + } + + /** Simple constructor. + * @param separator String used to separate tuple values; must not be null. + * @param prefix String used to signal the start of a tuple; if null, no + * string is expected at the start of the tuple + * @param suffix String used to signal the end of a tuple; if null, no + * string is expected at the end of the tuple + */ + protected SimpleTupleFormat(String separator, String prefix, String suffix) { + this.separator = separator; + this.prefix = prefix; + this.suffix = suffix; + } + + /** Return the string used to separate tuple values. + * @return the value separator string + */ + public String getSeparator() { + return separator; + } + + /** Return the string used to signal the start of a tuple. This value may be null. + * @return the string used to begin each tuple or null + */ + public String getPrefix() { + return prefix; + } + + /** Returns the string used to signal the end of a tuple. This value may be null. + * @return the string used to end each tuple or null + */ + public String getSuffix() { + return suffix; + } + + /** Return a tuple string with the given value. + * @param a value + * @return 1-tuple string + */ + public String format(double a) { + StringBuilder sb = new StringBuilder(); + + if (prefix != null) { + sb.append(prefix); + } + + sb.append(a); + + if (suffix != null) { + sb.append(suffix); + } + + return sb.toString(); + } + + /** Return a tuple string with the given values. + * @param a1 first value + * @param a2 second value + * @return 2-tuple string + */ + public String format(double a1, double a2) { + StringBuilder sb = new StringBuilder(); + + if (prefix != null) { + sb.append(prefix); + } + + sb.append(a1); + sb.append(separator); + sb.append(SPACE); + sb.append(a2); + + if (suffix != null) { + sb.append(suffix); + } + + return sb.toString(); + } + + /** Return a tuple string with the given values. + * @param a1 first value + * @param a2 second value + * @param a3 third value + * @return 3-tuple string + */ + public String format(double a1, double a2, double a3) { + StringBuilder sb = new StringBuilder(); + + if (prefix != null) { + sb.append(prefix); + } + + sb.append(a1); + sb.append(separator); + sb.append(SPACE); + sb.append(a2); + sb.append(separator); + sb.append(SPACE); + sb.append(a3); + + if (suffix != null) { + sb.append(suffix); + } + + return sb.toString(); + } + + /** Parse the given string as a 1-tuple and passes the tuple values to the + * given function. The function output is returned. + * @param <T> function return type + * @param str the string to be parsed + * @param fn function that will be passed the parsed tuple values + * @return object returned by {@code fn} + * @throws IllegalArgumentException if the input string format is invalid + */ + public <T> T parse(String str, RealFunction<T> factory) throws IllegalArgumentException { + final ParsePosition pos = new ParsePosition(0); + + readPrefix(str, pos); + final double v = readTupleValue(str, pos); + readSuffix(str, pos); + endParse(str, pos); + + return factory.apply(v); + } + + /** Parse the given string as a 2-tuple and passes the tuple values to the + * given function. The function output is returned. + * @param <T> function return type + * @param str the string to be parsed + * @param fn function that will be passed the parsed tuple values + * @return object returned by {@code fn} + * @throws IllegalArgumentException if the input string format is invalid + */ + public <T> T parse(String str, RealFunction2N<T> factory) throws IllegalArgumentException { + final ParsePosition pos = new ParsePosition(0); + + readPrefix(str, pos); + final double v1 = readTupleValue(str, pos); + final double v2 = readTupleValue(str, pos); + readSuffix(str, pos); + endParse(str, pos); + + return factory.apply(v1, v2); + } + + /** Parse the given string as a 3-tuple and passes the parsed values to the + * given function. The function output is returned. + * @param <T> function return type + * @param str the string to be parsed + * @param fn function that will be passed the parsed tuple values + * @return object returned by {@code fn} + * @throws IllegalArgumentException if the input string format is invalid + */ + public <T> T parse(String str, RealFunction3N<T> fn) throws IllegalArgumentException { + ParsePosition pos = new ParsePosition(0); + + readPrefix(str, pos); + final double v1 = readTupleValue(str, pos); + final double v2 = readTupleValue(str, pos); + final double v3 = readTupleValue(str, pos); + readSuffix(str, pos); + endParse(str, pos); + + return fn.apply(v1, v2, v3); + } + + /** Read the configured prefix from the current position in the given string, ignoring any preceding + * whitespace, and advance the parsing position past the prefix sequence. An exception is thrown if the + * prefix is not found. Does nothing if the prefix is null. + * @param str the string being parsed + * @param pos the current parsing position + * @throws IllegalArgumentException if the configured prefix is not null and is not found at the current + * parsing position, ignoring preceding whitespace + */ + private void readPrefix(String str, ParsePosition pos) throws IllegalArgumentException { + if (prefix != null) { + consumeWhitespace(str, pos); + readSequence(str, prefix, pos); + } + } + + /** Read and return a tuple value from the current position in the given string. An exception is thrown if a + * valid number is not found. The parsing position is advanced past the parsed number and any trailing separator. + * @param str the string being parsed + * @param pos the current parsing position + * @return the tuple value + * @throws IllegalArgumentException if the configured prefix is not null and is not found at the current + * parsing position, ignoring preceding whitespace + */ + private double readTupleValue(String str, ParsePosition pos) throws IllegalArgumentException { + final int startIdx = pos.getIndex(); + + int endIdx = str.indexOf(separator, startIdx); + if (endIdx < 0) { + if (suffix != null) { + endIdx = str.indexOf(suffix, startIdx); + } + + if (endIdx < 0) { + endIdx = str.length(); + } + } + + String substr = str.substring(startIdx, endIdx); + try { + double value = Double.parseDouble(substr); + + // advance the position and move past any terminating separator + pos.setIndex(endIdx); + matchSequence(str, separator, pos); + + return value; + } + catch (NumberFormatException exc) { + fail(String.format("unable to parse number from string \"%s\"", substr), str, pos, exc); + return 0.0; // for the compiler + } + } + + /** Read the configured suffix from the current position in the given string, ignoring any preceding + * whitespace, and advance the parsing position past the suffix sequence. An exception is thrown if the + * suffix is not found. Does nothing if the suffix is null. + * @param str the string being parsed + * @param pos the current parsing position + * @throws IllegalArgumentException if the configured suffix is not null and is not found at the current + * parsing position, ignoring preceding whitespace + */ + private void readSuffix(String str, ParsePosition pos) throws IllegalArgumentException { + if (suffix != null) { + consumeWhitespace(str, pos); + readSequence(str, suffix, pos); + } + } + + /** End a parse operation by ensuring that all non-whitespace characters in the string have been parsed. An + * exception is thrown if extra content is found. + * @param str the string being parsed + * @param pos the current parsing position + * @throws IllegalArgumentException if extra non-whitespace content is found past the current parsing position + */ + private void endParse(String str, ParsePosition pos) throws IllegalArgumentException { + consumeWhitespace(str, pos); + if (pos.getIndex() != str.length()) { + fail("unexpected content", str, pos); + } + } + + /** Advance {@code pos} past any whitespace characters in {@code str}, + * starting at the current parse position index. + * @param str the input string + * @param pos the current parse position + */ + private void consumeWhitespace(final String str, final ParsePosition pos) { + int idx = pos.getIndex(); + final int len = str.length(); + + for (; idx<len; ++idx) { + if (!Character.isWhitespace(str.codePointAt(idx))) { + break; + } + } + + pos.setIndex(idx); + } + + /** Return a boolean indicating whether or not the input string {@code str} + * contains the string {@code seq} at the given parse index. If the match succeeds, + * the index of {@code pos} is moved to the first character after the match. If + * the match does not succeed, the parse position is left unchanged. + * @param str the string to match against + * @param seq the sequence to look for in {@code str} + * @param pos the parse position indicating the index in {@code str} + * to attempt the match + * @return true if {@code str} contains exactly the same characters as {@code seq} + * at {@code pos}; otherwise, false + */ + private boolean matchSequence(final String str, final String seq, final ParsePosition pos) { + final int idx = pos.getIndex(); + final int inputLength = str.length(); + final int seqLength = seq.length(); + + int i = idx; + int s = 0; + for (; i<inputLength && s<seqLength; ++i, ++s) { + if (str.codePointAt(i) != seq.codePointAt(s)) { + break; + } + } + + if (i <= inputLength && s == seqLength) { + pos.setIndex(idx + seqLength); + return true; + } + return false; + } + + /** Read the string given by {@code seq} from the given position in {@code str}. + * Throws an IllegalArgumentException if the sequence is not found at that position. + * @param str the string to match against + * @param seq the sequence to look for in {@code str} + * @param pos the parse position indicating the index in {@code str} + * to attempt the match + * @throws IllegalArgumentException if {@code str} does not contain the characters from + * {@code seq} at position {@code pos} + */ + private void readSequence(String str, String seq, ParsePosition pos) throws IllegalArgumentException { + if (!matchSequence(str, seq, pos)) { + final int idx = pos.getIndex(); + final String actualSeq = str.substring(idx, Math.min(str.length(), idx + seq.length())); + + fail(String.format("expected \"%s\" but found \"%s\"", seq, actualSeq), str, pos); + } + } + + /** Abort the current parsing operation by throwing an {@link IllegalArgumentException} with an informative + * error message. + * @param msg the error message + * @param str the string being parsed + * @param pos the current parse position + * @throws IllegalArgumentException the exception signaling a parse failure + */ + private void fail(String msg, String str, ParsePosition pos) throws IllegalArgumentException { + fail(msg, str, pos, null); + } + + /** Abort the current parsing operation by throwing an {@link IllegalArgumentException} with an informative + * error message. + * @param msg the error message + * @param str the string being parsed + * @param pos the current parse position + * @param cause the original cause of the error + * @throws IllegalArgumentException the exception signaling a parse failure + */ + private void fail(String msg, String str, ParsePosition pos, Throwable cause) throws IllegalArgumentException { + String fullMsg = String.format("Failed to parse string \"%s\" at index %d: %s", str, pos.getIndex(), msg); + + throw new TupleParseException(fullMsg, cause); + } + + /** Return an instance configured with default values. Tuples in this format + * are enclosed by parentheses and separated by commas. + * + * Ex: + * <pre> + * "(1.0)" + * "(1.0, 2.0)" + * "(1.0, 2.0, 3.0)" + * </pre> + * @return instance configured with default values + */ + public static SimpleTupleFormat getDefault() { + return DEFAULT_INSTANCE; + } + + /** Exception class for errors occurring during tuple parsing. + */ + private static class TupleParseException extends IllegalArgumentException { + + /** Serializable version identifier */ + private static final long serialVersionUID = 20180629; + + /** Simple constructor. + * @param msg the exception message + * @param cause the exception root cause + */ + TupleParseException(String msg, Throwable cause) { + super(msg, cause); + } + } +} diff --git a/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/internal/package-info.java b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/internal/package-info.java new file mode 100644 index 0000000..547fc6b --- /dev/null +++ b/commons-geometry-core/src/main/java/org/apache/commons/geometry/core/util/internal/package-info.java @@ -0,0 +1,24 @@ +/* + * 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. + */ +/** + * + * <p> + * This package contains geometry utilities intended for internal use only. + * No guarantees are made for the stability of the contained APIs. + * </p> + */ +package org.apache.commons.geometry.core.util.internal; diff --git a/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/util/SimpleCoordinateFormatTest.java b/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/util/internal/SimpleTupleFormatTest.java similarity index 80% rename from commons-geometry-core/src/test/java/org/apache/commons/geometry/core/util/SimpleCoordinateFormatTest.java rename to commons-geometry-core/src/test/java/org/apache/commons/geometry/core/util/internal/SimpleTupleFormatTest.java index 23202d7..a3e554b 100644 --- a/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/util/SimpleCoordinateFormatTest.java +++ b/commons-geometry-core/src/test/java/org/apache/commons/geometry/core/util/internal/SimpleTupleFormatTest.java @@ -14,22 +14,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.commons.geometry.core.util; +package org.apache.commons.geometry.core.util.internal; +import org.apache.commons.geometry.core.util.RealFunction; +import org.apache.commons.geometry.core.util.RealFunction2N; +import org.apache.commons.geometry.core.util.RealFunction3N; import org.junit.Assert; import org.junit.Test; -public class SimpleCoordinateFormatTest { +public class SimpleTupleFormatTest { private static final double EPS = 1e-10; private static final String OPEN_PAREN = "("; private static final String CLOSE_PAREN = ")"; - private static Coordinates.Factory1D<Stub1D> FACTORY_1D = new Coordinates.Factory1D<Stub1D>() { + private static RealFunction<Stub1D> FACTORY_1D = new RealFunction<Stub1D>() { @Override - public Stub1D create(double v) { + public Stub1D apply(double v) { Stub1D result = new Stub1D(); result.v = v; @@ -37,10 +40,10 @@ public class SimpleCoordinateFormatTest { } }; - private static Coordinates.Factory2D<Stub2D> FACTORY_2D = new Coordinates.Factory2D<Stub2D>() { + private static RealFunction2N<Stub2D> FACTORY_2D = new RealFunction2N<Stub2D>() { @Override - public Stub2D create(double v1, double v2) { + public Stub2D apply(double v1, double v2) { Stub2D result = new Stub2D(); result.v1 = v1; result.v2 = v2; @@ -49,10 +52,10 @@ public class SimpleCoordinateFormatTest { } }; - private static Coordinates.Factory3D<Stub3D> FACTORY_3D = new Coordinates.Factory3D<Stub3D>() { + private static RealFunction3N<Stub3D> FACTORY_3D = new RealFunction3N<Stub3D>() { @Override - public Stub3D create(double v1, double v2, double v3) { + public Stub3D apply(double v1, double v2, double v3) { Stub3D result = new Stub3D(); result.v1 = v1; result.v2 = v2; @@ -65,7 +68,7 @@ public class SimpleCoordinateFormatTest { @Test public void testConstructor() { // act - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat("|", "{", "}"); + SimpleTupleFormat formatter = new SimpleTupleFormat("|", "{", "}"); // assert Assert.assertEquals("|", formatter.getSeparator()); @@ -76,7 +79,7 @@ public class SimpleCoordinateFormatTest { @Test public void testConstructor_defaultSeparator() { // act - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat("{", "}"); + SimpleTupleFormat formatter = new SimpleTupleFormat("{", "}"); // assert Assert.assertEquals(",", formatter.getSeparator()); @@ -87,7 +90,7 @@ public class SimpleCoordinateFormatTest { @Test public void testFormat1D() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(OPEN_PAREN, CLOSE_PAREN); + SimpleTupleFormat formatter = new SimpleTupleFormat(OPEN_PAREN, CLOSE_PAREN); // act/assert Assert.assertEquals("(1.0)", formatter.format(1.0)); @@ -100,7 +103,7 @@ public class SimpleCoordinateFormatTest { @Test public void testFormat1D_noPrefixSuffix() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(null, null); + SimpleTupleFormat formatter = new SimpleTupleFormat(null, null); // act/assert Assert.assertEquals("1.0", formatter.format(1.0)); @@ -113,7 +116,7 @@ public class SimpleCoordinateFormatTest { @Test public void testFormat2D() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(OPEN_PAREN, CLOSE_PAREN); + SimpleTupleFormat formatter = new SimpleTupleFormat(OPEN_PAREN, CLOSE_PAREN); // act/assert Assert.assertEquals("(1.0, -1.0)", formatter.format(1.0, -1.0)); @@ -125,7 +128,7 @@ public class SimpleCoordinateFormatTest { @Test public void testFormat2D_noPrefixSuffix() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(null, null); + SimpleTupleFormat formatter = new SimpleTupleFormat(null, null); // act/assert Assert.assertEquals("1.0, -1.0", formatter.format(1.0, -1.0)); @@ -137,7 +140,7 @@ public class SimpleCoordinateFormatTest { @Test public void testFormat3D() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(OPEN_PAREN, CLOSE_PAREN); + SimpleTupleFormat formatter = new SimpleTupleFormat(OPEN_PAREN, CLOSE_PAREN); // act/assert Assert.assertEquals("(1.0, 0.0, -1.0)", formatter.format(1.0, 0.0, -1.0)); @@ -148,7 +151,7 @@ public class SimpleCoordinateFormatTest { @Test public void testFormat3D_noPrefixSuffix() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(null, null); + SimpleTupleFormat formatter = new SimpleTupleFormat(null, null); // act/assert Assert.assertEquals("1.0, 0.0, -1.0", formatter.format(1.0, 0.0, -1.0)); @@ -159,7 +162,7 @@ public class SimpleCoordinateFormatTest { @Test public void testFormat_longTokens() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat("||", "<<", ">>"); + SimpleTupleFormat formatter = new SimpleTupleFormat("||", "<<", ">>"); // act/assert Assert.assertEquals("<<1.0>>", formatter.format(1.0)); @@ -170,7 +173,7 @@ public class SimpleCoordinateFormatTest { @Test public void testParse1D() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(OPEN_PAREN, CLOSE_PAREN); + SimpleTupleFormat formatter = new SimpleTupleFormat(OPEN_PAREN, CLOSE_PAREN); // act/assert checkParse1D(formatter, "(1)", 1.0); @@ -196,7 +199,7 @@ public class SimpleCoordinateFormatTest { @Test public void testParse1D_noPrefixSuffix() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(null, null); + SimpleTupleFormat formatter = new SimpleTupleFormat(null, null); // act/assert checkParse1D(formatter, "1", 1.0); @@ -222,7 +225,7 @@ public class SimpleCoordinateFormatTest { @Test public void testParse1D_failure() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(OPEN_PAREN, CLOSE_PAREN); + SimpleTupleFormat formatter = new SimpleTupleFormat(OPEN_PAREN, CLOSE_PAREN); // act/assert checkParse1DFailure(formatter, "", "index 0: expected \"(\" but found \"\""); @@ -236,7 +239,7 @@ public class SimpleCoordinateFormatTest { @Test public void testParse2D() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(OPEN_PAREN, CLOSE_PAREN); + SimpleTupleFormat formatter = new SimpleTupleFormat(OPEN_PAREN, CLOSE_PAREN); // act/assert checkParse2D(formatter, "(1,-2)", 1.0, -2.0); @@ -260,7 +263,7 @@ public class SimpleCoordinateFormatTest { @Test public void testParse2D_noPrefixSuffix() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(null, null); + SimpleTupleFormat formatter = new SimpleTupleFormat(null, null); // act/assert checkParse2D(formatter, "1,-2", 1.0, -2.0); @@ -284,7 +287,7 @@ public class SimpleCoordinateFormatTest { @Test public void testParse2D_failure() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(OPEN_PAREN, CLOSE_PAREN); + SimpleTupleFormat formatter = new SimpleTupleFormat(OPEN_PAREN, CLOSE_PAREN); // act/assert checkParse2DFailure(formatter, "", "index 0: expected \"(\" but found \"\""); @@ -298,7 +301,7 @@ public class SimpleCoordinateFormatTest { @Test public void testParse3D() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(OPEN_PAREN, CLOSE_PAREN); + SimpleTupleFormat formatter = new SimpleTupleFormat(OPEN_PAREN, CLOSE_PAREN); // act/assert checkParse3D(formatter, "(1,-2,3)", 1.0, -2.0, 3.0); @@ -321,7 +324,7 @@ public class SimpleCoordinateFormatTest { @Test public void testParse3D_noPrefixSuffix() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(null, null); + SimpleTupleFormat formatter = new SimpleTupleFormat(null, null); // act/assert checkParse3D(formatter, "1,-2,3", 1.0, -2.0, 3.0); @@ -344,7 +347,7 @@ public class SimpleCoordinateFormatTest { @Test public void testParse3D_failure() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat(OPEN_PAREN, CLOSE_PAREN); + SimpleTupleFormat formatter = new SimpleTupleFormat(OPEN_PAREN, CLOSE_PAREN); // act/assert checkParse3DFailure(formatter, "", "index 0: expected \"(\" but found \"\""); @@ -358,7 +361,7 @@ public class SimpleCoordinateFormatTest { @Test public void testParse_longTokens() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat("||", "<<", ">>"); + SimpleTupleFormat formatter = new SimpleTupleFormat("||", "<<", ">>"); // act/assert checkParse1D(formatter, "<<1.0>>", 1.0); @@ -369,7 +372,7 @@ public class SimpleCoordinateFormatTest { @Test public void testParse_longTokens_failure() { // arrange - SimpleCoordinateFormat formatter = new SimpleCoordinateFormat("||", "<<", ">>"); + SimpleTupleFormat formatter = new SimpleTupleFormat("||", "<<", ">>"); // act/assert checkParse1DFailure(formatter, "<", "index 0: expected \"<<\" but found \"<\""); @@ -379,9 +382,9 @@ public class SimpleCoordinateFormatTest { } @Test - public void testDefaultPointFormat() { + public void testDefaultInstance() { // act - SimpleCoordinateFormat formatter = SimpleCoordinateFormat.getPointFormat(); + SimpleTupleFormat formatter = SimpleTupleFormat.getDefault(); // assert Assert.assertEquals(",", formatter.getSeparator()); @@ -391,26 +394,13 @@ public class SimpleCoordinateFormatTest { Assert.assertEquals("(1.0, 2.0)", formatter.format(1, 2)); } - @Test - public void testDefaultVectorFormat() { - // act - SimpleCoordinateFormat formatter = SimpleCoordinateFormat.getVectorFormat(); - - // assert - Assert.assertEquals(",", formatter.getSeparator()); - Assert.assertEquals("{", formatter.getPrefix()); - Assert.assertEquals("}", formatter.getSuffix()); - - Assert.assertEquals("{1.0, 2.0}", formatter.format(1, 2)); - } - - private void checkParse1D(SimpleCoordinateFormat formatter, String str, double v) { + private void checkParse1D(SimpleTupleFormat formatter, String str, double v) { Stub1D result = formatter.parse(str, FACTORY_1D); Assert.assertEquals(v, result.v, EPS); } - private void checkParse1DFailure(SimpleCoordinateFormat formatter, String str, String msgSubstr) { + private void checkParse1DFailure(SimpleTupleFormat formatter, String str, String msgSubstr) { try { formatter.parse(str, FACTORY_1D); Assert.fail("Operation should have failed"); @@ -422,14 +412,14 @@ public class SimpleCoordinateFormatTest { } } - private void checkParse2D(SimpleCoordinateFormat formatter, String str, double v1, double v2) { + private void checkParse2D(SimpleTupleFormat formatter, String str, double v1, double v2) { Stub2D result = formatter.parse(str, FACTORY_2D); Assert.assertEquals(v1, result.v1, EPS); Assert.assertEquals(v2, result.v2, EPS); } - private void checkParse2DFailure(SimpleCoordinateFormat formatter, String str, String msgSubstr) { + private void checkParse2DFailure(SimpleTupleFormat formatter, String str, String msgSubstr) { try { formatter.parse(str, FACTORY_2D); Assert.fail("Operation should have failed"); @@ -441,7 +431,7 @@ public class SimpleCoordinateFormatTest { } } - private void checkParse3D(SimpleCoordinateFormat formatter, String str, double v1, double v2, double v3) { + private void checkParse3D(SimpleTupleFormat formatter, String str, double v1, double v2, double v3) { Stub3D result = formatter.parse(str, FACTORY_3D); Assert.assertEquals(v1, result.v1, EPS); @@ -449,7 +439,7 @@ public class SimpleCoordinateFormatTest { Assert.assertEquals(v3, result.v3, EPS); } - private void checkParse3DFailure(SimpleCoordinateFormat formatter, String str, String msgSubstr) { + private void checkParse3DFailure(SimpleTupleFormat formatter, String str, String msgSubstr) { try { formatter.parse(str, FACTORY_3D); Assert.fail("Operation should have failed"); diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Cartesian1D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Cartesian1D.java index 8d9b800..19ea67f 100644 --- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Cartesian1D.java +++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Cartesian1D.java @@ -19,6 +19,7 @@ package org.apache.commons.geometry.euclidean.oned; import java.io.Serializable; import org.apache.commons.geometry.core.Spatial; +import org.apache.commons.geometry.core.util.internal.SimpleTupleFormat; /** This class represents a Cartesian coordinate value in * one-dimensional Euclidean space. @@ -64,4 +65,10 @@ public abstract class Cartesian1D implements Spatial, Serializable { public boolean isInfinite() { return !isNaN() && Double.isInfinite(x); } + + /** {@inheritDoc} */ + @Override + public String toString() { + return SimpleTupleFormat.getDefault().format(getX()); + } } diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Point1D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Point1D.java index 3715c69..870ac6e 100644 --- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Point1D.java +++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Point1D.java @@ -16,8 +16,8 @@ */ package org.apache.commons.geometry.euclidean.oned; -import org.apache.commons.geometry.core.util.Coordinates; -import org.apache.commons.geometry.core.util.SimpleCoordinateFormat; +import org.apache.commons.geometry.core.util.RealFunction; +import org.apache.commons.geometry.core.util.internal.SimpleTupleFormat; import org.apache.commons.geometry.euclidean.EuclideanPoint; import org.apache.commons.numbers.arrays.LinearCombination; @@ -49,12 +49,12 @@ public final class Point1D extends Cartesian1D implements EuclideanPoint<Point1D private static final long serialVersionUID = 7556674948671647925L; /** Factory for delegating instance creation. */ - private static Coordinates.Factory1D<Point1D> FACTORY = new Coordinates.Factory1D<Point1D>() { + private static RealFunction<Point1D> FACTORY = new RealFunction<Point1D>() { /** {@inheritDoc} */ @Override - public Point1D create(double a) { - return new Point1D(a); + public Point1D apply(double n) { + return new Point1D(n); } }; @@ -145,12 +145,6 @@ public final class Point1D extends Cartesian1D implements EuclideanPoint<Point1D return false; } - /** {@inheritDoc} */ - @Override - public String toString() { - return SimpleCoordinateFormat.getPointFormat().format(getX()); - } - /** Returns a point with the given coordinate value. * @param x point coordinate * @return point instance @@ -174,13 +168,13 @@ public final class Point1D extends Cartesian1D implements EuclideanPoint<Point1D * @throws IllegalArgumentException if the given string has an invalid format */ public static Point1D parse(String str) throws IllegalArgumentException { - return SimpleCoordinateFormat.getPointFormat().parse(str, FACTORY); + return SimpleTupleFormat.getDefault().parse(str, FACTORY); } /** Returns a factory object that can be used to created new point instances. * @return point factory instance */ - public static Coordinates.Factory1D<Point1D> getFactory() { + public static RealFunction<Point1D> getFactory() { return FACTORY; } diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java index 0aab089..d9fd0c2 100644 --- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java +++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/oned/Vector1D.java @@ -16,8 +16,8 @@ */ package org.apache.commons.geometry.euclidean.oned; -import org.apache.commons.geometry.core.util.Coordinates; -import org.apache.commons.geometry.core.util.SimpleCoordinateFormat; +import org.apache.commons.geometry.core.util.RealFunction; +import org.apache.commons.geometry.core.util.internal.SimpleTupleFormat; import org.apache.commons.geometry.euclidean.EuclideanVector; import org.apache.commons.numbers.arrays.LinearCombination; @@ -49,12 +49,12 @@ public final class Vector1D extends Cartesian1D implements EuclideanVector<Point private static final long serialVersionUID = 1582116020164328846L; /** Factory for delegating instance creation. */ - private static Coordinates.Factory1D<Vector1D> FACTORY = new Coordinates.Factory1D<Vector1D>() { + private static RealFunction<Vector1D> FACTORY = new RealFunction<Vector1D>() { /** {@inheritDoc} */ @Override - public Vector1D create(double a) { - return new Vector1D(a); + public Vector1D apply(double n) { + return new Vector1D(n); } }; @@ -229,12 +229,6 @@ public final class Vector1D extends Cartesian1D implements EuclideanVector<Point return false; } - /** {@inheritDoc} */ - @Override - public String toString() { - return SimpleCoordinateFormat.getVectorFormat().format(getX()); - } - /** Returns a vector with the given coordinate value. * @param x vector coordinate * @return vector instance @@ -258,13 +252,13 @@ public final class Vector1D extends Cartesian1D implements EuclideanVector<Point * @throws IllegalArgumentException if the given string has an invalid format */ public static Vector1D parse(String str) throws IllegalArgumentException { - return SimpleCoordinateFormat.getVectorFormat().parse(str, FACTORY); + return SimpleTupleFormat.getDefault().parse(str, FACTORY); } /** Returns a factory object that can be used to created new vector instances. * @return vector factory instance */ - public static Coordinates.Factory1D<Vector1D> getFactory() { + public static RealFunction<Vector1D> getFactory() { return FACTORY; } diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Cartesian3D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Cartesian3D.java index 6b619ac..8d680e9 100644 --- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Cartesian3D.java +++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Cartesian3D.java @@ -20,6 +20,7 @@ package org.apache.commons.geometry.euclidean.threed; import java.io.Serializable; import org.apache.commons.geometry.core.Spatial; +import org.apache.commons.geometry.core.util.internal.SimpleTupleFormat; /** This class represents a Cartesian coordinate value in * three-dimensional Euclidean space. @@ -95,6 +96,12 @@ public abstract class Cartesian3D implements Spatial, Serializable { return !isNaN() && (Double.isInfinite(x) || Double.isInfinite(y) || Double.isInfinite(z)); } + /** {@inheritDoc} */ + @Override + public String toString() { + return SimpleTupleFormat.getDefault().format(getX(), getY(), getZ()); + } + /** Returns the Euclidean distance from this set of coordinates to the given coordinates. * @param other coordinates to compute the distance to. * @return Euclidean distance value diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Point3D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Point3D.java index f257425..c9841ac 100644 --- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Point3D.java +++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Point3D.java @@ -17,8 +17,8 @@ package org.apache.commons.geometry.euclidean.threed; -import org.apache.commons.geometry.core.util.Coordinates; -import org.apache.commons.geometry.core.util.SimpleCoordinateFormat; +import org.apache.commons.geometry.core.util.RealFunction3N; +import org.apache.commons.geometry.core.util.internal.SimpleTupleFormat; import org.apache.commons.geometry.euclidean.EuclideanPoint; import org.apache.commons.numbers.arrays.LinearCombination; @@ -47,12 +47,12 @@ public final class Point3D extends Cartesian3D implements EuclideanPoint<Point3D private static final long serialVersionUID = 1313493323784566947L; /** Factory for delegating instance creation. */ - private static Coordinates.Factory3D<Point3D> FACTORY = new Coordinates.Factory3D<Point3D>() { + private static RealFunction3N<Point3D> FACTORY = new RealFunction3N<Point3D>() { /** {@inheritDoc} */ @Override - public Point3D create(double a1, double a2, double a3) { - return new Point3D(a1, a2, a3); + public Point3D apply(double n1, double n2, double n3) { + return new Point3D(n1, n2, n3); } }; @@ -154,12 +154,6 @@ public final class Point3D extends Cartesian3D implements EuclideanPoint<Point3D return false; } - /** {@inheritDoc} */ - @Override - public String toString() { - return SimpleCoordinateFormat.getPointFormat().format(getX(), getY(), getZ()); - } - /** Returns a point with the given coordinate values * @param x abscissa (first coordinate value) * @param y ordinate (second coordinate value) @@ -197,13 +191,13 @@ public final class Point3D extends Cartesian3D implements EuclideanPoint<Point3D * @throws IllegalArgumentException if the given string has an invalid format */ public static Point3D parse(String str) throws IllegalArgumentException { - return SimpleCoordinateFormat.getPointFormat().parse(str, FACTORY); + return SimpleTupleFormat.getDefault().parse(str, FACTORY); } /** Returns a factory object that can be used to created new point instances. * @return point factory instance */ - public static Coordinates.Factory3D<Point3D> getFactory() { + public static RealFunction3N<Point3D> getFactory() { return FACTORY; } diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java index 9d1f258..5e9d952 100644 --- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java +++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/threed/Vector3D.java @@ -16,8 +16,8 @@ */ package org.apache.commons.geometry.euclidean.threed; -import org.apache.commons.geometry.core.util.Coordinates; -import org.apache.commons.geometry.core.util.SimpleCoordinateFormat; +import org.apache.commons.geometry.core.util.RealFunction3N; +import org.apache.commons.geometry.core.util.internal.SimpleTupleFormat; import org.apache.commons.geometry.euclidean.EuclideanVector; import org.apache.commons.numbers.arrays.LinearCombination; @@ -67,12 +67,12 @@ public final class Vector3D extends Cartesian3D implements EuclideanVector<Point private static final String ZERO_NORM_MSG = "Norm is zero"; /** Factory for delegating instance creation. */ - private static Coordinates.Factory3D<Vector3D> FACTORY = new Coordinates.Factory3D<Vector3D>() { + private static RealFunction3N<Vector3D> FACTORY = new RealFunction3N<Vector3D>() { /** {@inheritDoc} */ @Override - public Vector3D create(double a1, double a2, double a3) { - return new Vector3D(a1, a2, a3); + public Vector3D apply(double n1, double n2, double n3) { + return new Vector3D(n1, n2, n3); } }; @@ -382,12 +382,6 @@ public final class Vector3D extends Cartesian3D implements EuclideanVector<Point return false; } - /** {@inheritDoc} */ - @Override - public String toString() { - return SimpleCoordinateFormat.getVectorFormat().format(getX(), getY(), getZ()); - } - /** Computes the dot product between to vectors. This method simply * calls {@code v1.dotProduct(v2)}. * @param v1 first vector @@ -477,13 +471,13 @@ public final class Vector3D extends Cartesian3D implements EuclideanVector<Point * @throws IllegalArgumentException if the given string has an invalid format */ public static Vector3D parse(String str) throws IllegalArgumentException { - return SimpleCoordinateFormat.getVectorFormat().parse(str, FACTORY); + return SimpleTupleFormat.getDefault().parse(str, FACTORY); } /** Returns a factory object that can be used to created new vector instances. * @return vector factory instance */ - public static Coordinates.Factory3D<Vector3D> getFactory() { + public static RealFunction3N<Vector3D> getFactory() { return FACTORY; } diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Cartesian2D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Cartesian2D.java index d4c69b6..8ddb6a0 100644 --- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Cartesian2D.java +++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Cartesian2D.java @@ -20,6 +20,7 @@ package org.apache.commons.geometry.euclidean.twod; import java.io.Serializable; import org.apache.commons.geometry.core.Spatial; +import org.apache.commons.geometry.core.util.internal.SimpleTupleFormat; /** This class represents a set of Cartesian coordinates in * two-dimensional Euclidean space. @@ -84,6 +85,12 @@ public abstract class Cartesian2D implements Spatial, Serializable { return !isNaN() && (Double.isInfinite(x) || Double.isInfinite(y)); } + /** {@inheritDoc} */ + @Override + public String toString() { + return SimpleTupleFormat.getDefault().format(getX(), getY()); + } + /** Returns the Euclidean distance from this value to the given value. * @param other the set of coordinates to compute the distance to * @return Euclidean distance diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Point2D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Point2D.java index c32777a..0d2af49 100644 --- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Point2D.java +++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Point2D.java @@ -16,8 +16,8 @@ */ package org.apache.commons.geometry.euclidean.twod; -import org.apache.commons.geometry.core.util.Coordinates; -import org.apache.commons.geometry.core.util.SimpleCoordinateFormat; +import org.apache.commons.geometry.core.util.RealFunction2N; +import org.apache.commons.geometry.core.util.internal.SimpleTupleFormat; import org.apache.commons.geometry.euclidean.EuclideanPoint; import org.apache.commons.numbers.arrays.LinearCombination; @@ -46,12 +46,12 @@ public final class Point2D extends Cartesian2D implements EuclideanPoint<Point2D private static final long serialVersionUID = 266938651998679754L; /** Factory for delegating instance creation. */ - private static Coordinates.Factory2D<Point2D> FACTORY = new Coordinates.Factory2D<Point2D>() { + private static RealFunction2N<Point2D> FACTORY = new RealFunction2N<Point2D>() { /** {@inheritDoc} */ @Override - public Point2D create(double a1, double a2) { - return new Point2D(a1, a2); + public Point2D apply(double n1, double n2) { + return new Point2D(n1, n2); } }; @@ -143,12 +143,6 @@ public final class Point2D extends Cartesian2D implements EuclideanPoint<Point2D return false; } - /** {@inheritDoc} */ - @Override - public String toString() { - return SimpleCoordinateFormat.getPointFormat().format(getX(), getY()); - } - /** Returns a point with the given coordinate values * @param x abscissa (first coordinate value) * @param y ordinate (second coordinate value) @@ -185,13 +179,13 @@ public final class Point2D extends Cartesian2D implements EuclideanPoint<Point2D * @throws IllegalArgumentException if the given string has an invalid format */ public static Point2D parse(String str) throws IllegalArgumentException { - return SimpleCoordinateFormat.getPointFormat().parse(str, FACTORY); + return SimpleTupleFormat.getDefault().parse(str, FACTORY); } /** Returns a factory object that can be used to created new point instances. * @return point factory instance */ - public static Coordinates.Factory2D<Point2D> getFactory() { + public static RealFunction2N<Point2D> getFactory() { return FACTORY; } diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java index ac8e380..42dc10d 100644 --- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java +++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/Vector2D.java @@ -16,8 +16,8 @@ */ package org.apache.commons.geometry.euclidean.twod; -import org.apache.commons.geometry.core.util.Coordinates; -import org.apache.commons.geometry.core.util.SimpleCoordinateFormat; +import org.apache.commons.geometry.core.util.RealFunction2N; +import org.apache.commons.geometry.core.util.internal.SimpleTupleFormat; import org.apache.commons.geometry.euclidean.EuclideanVector; import org.apache.commons.numbers.arrays.LinearCombination; @@ -61,12 +61,12 @@ public final class Vector2D extends Cartesian2D implements EuclideanVector<Point private static final String ZERO_NORM_MSG = "Norm is zero"; /** Factory for delegating instance creation. */ - private static Coordinates.Factory2D<Vector2D> FACTORY = new Coordinates.Factory2D<Vector2D>() { + private static RealFunction2N<Vector2D> FACTORY = new RealFunction2N<Vector2D>() { /** {@inheritDoc} */ @Override - public Vector2D create(double a1, double a2) { - return new Vector2D(a1, a2); + public Vector2D apply(double n1, double n2) { + return new Vector2D(n1, n2); } }; @@ -320,12 +320,6 @@ public final class Vector2D extends Cartesian2D implements EuclideanVector<Point return false; } - /** {@inheritDoc} */ - @Override - public String toString() { - return SimpleCoordinateFormat.getVectorFormat().format(getX(), getY()); - } - /** Computes the dot product between to vectors. This method simply * calls {@code v1.dotProduct(v2)}. * @param v1 first vector @@ -384,13 +378,13 @@ public final class Vector2D extends Cartesian2D implements EuclideanVector<Point * @throws IllegalArgumentException if the given string has an invalid format */ public static Vector2D parse(String str) throws IllegalArgumentException { - return SimpleCoordinateFormat.getVectorFormat().parse(str, FACTORY); + return SimpleTupleFormat.getDefault().parse(str, FACTORY); } /** Returns a factory object that can be used to created new vector instances. * @return vector factory instance */ - public static Coordinates.Factory2D<Vector2D> getFactory() { + public static RealFunction2N<Vector2D> getFactory() { return FACTORY; } diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Cartesian1DTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Cartesian1DTest.java index 835a368..afd6ca8 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Cartesian1DTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Cartesian1DTest.java @@ -16,6 +16,8 @@ */ package org.apache.commons.geometry.euclidean.oned; +import java.util.regex.Pattern; + import org.apache.commons.geometry.euclidean.EuclideanTestUtils; import org.junit.Assert; import org.junit.Test; @@ -64,6 +66,20 @@ public class Cartesian1DTest { Assert.assertFalse(new StubCartesian1D(Double.NaN).isInfinite()); } + @Test + public void testToString() { + // arrange + StubCartesian1D c = new StubCartesian1D(1); + Pattern pattern = Pattern.compile("\\(1.{0,2}\\)"); + + // act + String str = c.toString(); + + // assert + Assert.assertTrue("Expected string " + str + " to match regex " + pattern, + pattern.matcher(str).matches()); + } + private static class StubCartesian1D extends Cartesian1D { private static final long serialVersionUID = 1L; diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Point1DTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Point1DTest.java index bcde081..2ac7379 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Point1DTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Point1DTest.java @@ -19,7 +19,7 @@ package org.apache.commons.geometry.euclidean.oned; import java.util.regex.Pattern; -import org.apache.commons.geometry.core.util.Coordinates; +import org.apache.commons.geometry.core.util.RealFunction; import org.apache.commons.numbers.core.Precision; import org.junit.Assert; import org.junit.Test; @@ -231,11 +231,11 @@ public class Point1DTest { @Test public void testGetFactory() { // act - Coordinates.Factory1D<Point1D> factory = Point1D.getFactory(); + RealFunction<Point1D> factory = Point1D.getFactory(); // assert - checkPoint(factory.create(1), 1); - checkPoint(factory.create(-1), -1); + checkPoint(factory.apply(1), 1); + checkPoint(factory.apply(-1), -1); } @Test diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Vector1DTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Vector1DTest.java index 7184476..9e81737 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Vector1DTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/oned/Vector1DTest.java @@ -2,7 +2,7 @@ package org.apache.commons.geometry.euclidean.oned; import java.util.regex.Pattern; -import org.apache.commons.geometry.core.util.Coordinates; +import org.apache.commons.geometry.core.util.RealFunction; import org.apache.commons.numbers.core.Precision; import org.junit.Assert; import org.junit.Test; @@ -281,7 +281,7 @@ public class Vector1DTest { public void testToString() { // arrange Vector1D v = Vector1D.of(3); - Pattern pattern = Pattern.compile("\\{3.{0,2}\\}"); + Pattern pattern = Pattern.compile("\\(3.{0,2}\\)"); // act String str = v.toString(); @@ -294,13 +294,13 @@ public class Vector1DTest { @Test public void testParse() { // act/assert - checkVector(Vector1D.parse("{1}"), 1); - checkVector(Vector1D.parse("{-1}"), -1); + checkVector(Vector1D.parse("(1)"), 1); + checkVector(Vector1D.parse("(-1)"), -1); - checkVector(Vector1D.parse("{0.01}"), 1e-2); - checkVector(Vector1D.parse("{-1e-3}"), -1e-3); + checkVector(Vector1D.parse("(0.01)"), 1e-2); + checkVector(Vector1D.parse("(-1e-3)"), -1e-3); - checkVector(Vector1D.parse("{NaN}"), Double.NaN); + checkVector(Vector1D.parse("(NaN)"), Double.NaN); checkVector(Vector1D.parse(Vector1D.ZERO.toString()), 0); checkVector(Vector1D.parse(Vector1D.ONE.toString()), 1); @@ -339,11 +339,11 @@ public class Vector1DTest { @Test public void testGetFactory() { // act - Coordinates.Factory1D<Vector1D> factory = Vector1D.getFactory(); + RealFunction<Vector1D> factory = Vector1D.getFactory(); // assert - checkVector(factory.create(1), 1); - checkVector(factory.create(-1), -1); + checkVector(factory.apply(1), 1); + checkVector(factory.apply(-1), -1); } @Test diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Cartesian3DTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Cartesian3DTest.java index 4e6205d..aadfe73 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Cartesian3DTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Cartesian3DTest.java @@ -1,5 +1,7 @@ package org.apache.commons.geometry.euclidean.threed; +import java.util.regex.Pattern; + import org.junit.Assert; import org.junit.Test; @@ -73,6 +75,20 @@ public class Cartesian3DTest { Assert.assertFalse(new StubCartesian3D(0, Double.NaN, Double.POSITIVE_INFINITY).isInfinite()); } + @Test + public void testToString() { + // arrange + StubCartesian3D c = new StubCartesian3D(1, 2, 3); + Pattern pattern = Pattern.compile("\\(1.{0,2}, 2.{0,2}, 3.{0,2}\\)"); + + // act + String str = c.toString(); + + // assert + Assert.assertTrue("Expected string " + str + " to match regex " + pattern, + pattern.matcher(str).matches()); + } + private static class StubCartesian3D extends Cartesian3D { private static final long serialVersionUID = 1L; diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Point3DTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Point3DTest.java index d20d918..d2959dc 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Point3DTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Point3DTest.java @@ -18,7 +18,7 @@ package org.apache.commons.geometry.euclidean.threed; import java.util.regex.Pattern; -import org.apache.commons.geometry.core.util.Coordinates; +import org.apache.commons.geometry.core.util.RealFunction3N; import org.apache.commons.numbers.core.Precision; import org.junit.Assert; import org.junit.Test; @@ -245,11 +245,11 @@ public class Point3DTest { @Test public void testGetFactory() { // act - Coordinates.Factory3D<Point3D> factory = Point3D.getFactory(); + RealFunction3N<Point3D> factory = Point3D.getFactory(); // assert - checkPoint(factory.create(1, 2, 3), 1, 2, 3); - checkPoint(factory.create(-1, -2, -3), -1, -2, -3); + checkPoint(factory.apply(1, 2, 3), 1, 2, 3); + checkPoint(factory.apply(-1, -2, -3), -1, -2, -3); } @Test diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Vector3DTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Vector3DTest.java index c9b3cf9..17e6a36 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Vector3DTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/threed/Vector3DTest.java @@ -20,7 +20,7 @@ package org.apache.commons.geometry.euclidean.threed; import java.util.regex.Pattern; import org.apache.commons.geometry.core.Geometry; -import org.apache.commons.geometry.core.util.Coordinates; +import org.apache.commons.geometry.core.util.RealFunction3N; import org.apache.commons.numbers.core.Precision; import org.apache.commons.rng.UniformRandomProvider; import org.apache.commons.rng.simple.RandomSource; @@ -619,7 +619,7 @@ public class Vector3DTest { public void testToString() { // arrange Vector3D v = Vector3D.of(1, 2, 3); - Pattern pattern = Pattern.compile("\\{1.{0,2}, 2.{0,2}, 3.{0,2}\\}"); + Pattern pattern = Pattern.compile("\\(1.{0,2}, 2.{0,2}, 3.{0,2}\\)"); // act String str = v.toString(); @@ -632,12 +632,12 @@ public class Vector3DTest { @Test public void testParse() { // act/assert - checkVector(Vector3D.parse("{1, 2, 3}"), 1, 2, 3); - checkVector(Vector3D.parse("{-1, -2, -3}"), -1, -2, -3); + checkVector(Vector3D.parse("(1, 2, 3)"), 1, 2, 3); + checkVector(Vector3D.parse("(-1, -2, -3)"), -1, -2, -3); - checkVector(Vector3D.parse("{0.01, -1e-3, 0}"), 1e-2, -1e-3, 0); + checkVector(Vector3D.parse("(0.01, -1e-3, 0)"), 1e-2, -1e-3, 0); - checkVector(Vector3D.parse("{NaN, -Infinity, Infinity}"), Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); + checkVector(Vector3D.parse("(NaN, -Infinity, Infinity)"), Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY); checkVector(Vector3D.parse(Vector3D.ZERO.toString()), 0, 0, 0); checkVector(Vector3D.parse(Vector3D.MINUS_X.toString()), -1, 0, 0); @@ -691,11 +691,11 @@ public class Vector3DTest { @Test public void testGetFactory() { // act - Coordinates.Factory3D<Vector3D> factory = Vector3D.getFactory(); + RealFunction3N<Vector3D> factory = Vector3D.getFactory(); // assert - checkVector(factory.create(1, 2, 3), 1, 2, 3); - checkVector(factory.create(-1, -2, -3), -1, -2, -3); + checkVector(factory.apply(1, 2, 3), 1, 2, 3); + checkVector(factory.apply(-1, -2, -3), -1, -2, -3); } @Test diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Cartesian2DTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Cartesian2DTest.java index b8c7238..e3d5127 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Cartesian2DTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Cartesian2DTest.java @@ -1,5 +1,7 @@ package org.apache.commons.geometry.euclidean.twod; +import java.util.regex.Pattern; + import org.junit.Assert; import org.junit.Test; @@ -68,6 +70,20 @@ public class Cartesian2DTest { Assert.assertFalse(new StubCartesian2D(Double.NaN, Double.POSITIVE_INFINITY).isInfinite()); } + @Test + public void testToString() { + // arrange + StubCartesian2D c = new StubCartesian2D(1, 2); + Pattern pattern = Pattern.compile("\\(1.{0,2}, 2.{0,2}\\)"); + + // act + String str = c.toString(); + + // assert + Assert.assertTrue("Expected string " + str + " to match regex " + pattern, + pattern.matcher(str).matches()); + } + private static class StubCartesian2D extends Cartesian2D { private static final long serialVersionUID = 1L; diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Point2DTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Point2DTest.java index 20d95ad..d26f002 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Point2DTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Point2DTest.java @@ -18,7 +18,7 @@ package org.apache.commons.geometry.euclidean.twod; import java.util.regex.Pattern; -import org.apache.commons.geometry.core.util.Coordinates; +import org.apache.commons.geometry.core.util.RealFunction2N; import org.apache.commons.numbers.core.Precision; import org.junit.Assert; import org.junit.Test; @@ -222,11 +222,11 @@ public class Point2DTest { @Test public void testGetFactory() { // act - Coordinates.Factory2D<Point2D> factory = Point2D.getFactory(); + RealFunction2N<Point2D> factory = Point2D.getFactory(); // assert - checkPoint(factory.create(1, 2), 1, 2); - checkPoint(factory.create(-1, -2), -1, -2); + checkPoint(factory.apply(1, 2), 1, 2); + checkPoint(factory.apply(-1, -2), -1, -2); } @Test diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Vector2DTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Vector2DTest.java index 13208c0..fa130e8 100644 --- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Vector2DTest.java +++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/Vector2DTest.java @@ -3,7 +3,7 @@ package org.apache.commons.geometry.euclidean.twod; import java.util.regex.Pattern; import org.apache.commons.geometry.core.Geometry; -import org.apache.commons.geometry.core.util.Coordinates; +import org.apache.commons.geometry.core.util.RealFunction2N; import org.apache.commons.numbers.core.Precision; import org.junit.Assert; import org.junit.Test; @@ -421,7 +421,7 @@ public class Vector2DTest { public void testToString() { // arrange Vector2D v = Vector2D.of(1, 2); - Pattern pattern = Pattern.compile("\\{1.{0,2}, 2.{0,2}\\}"); + Pattern pattern = Pattern.compile("\\(1.{0,2}, 2.{0,2}\\)"); // act String str = v.toString(); @@ -434,12 +434,12 @@ public class Vector2DTest { @Test public void testParse() { // act/assert - checkVector(Vector2D.parse("{1, 2}"), 1, 2); - checkVector(Vector2D.parse("{-1, -2}"), -1, -2); + checkVector(Vector2D.parse("(1, 2)"), 1, 2); + checkVector(Vector2D.parse("(-1, -2)"), -1, -2); - checkVector(Vector2D.parse("{0.01, -1e-3}"), 1e-2, -1e-3); + checkVector(Vector2D.parse("(0.01, -1e-3)"), 1e-2, -1e-3); - checkVector(Vector2D.parse("{NaN, -Infinity}"), Double.NaN, Double.NEGATIVE_INFINITY); + checkVector(Vector2D.parse("(NaN, -Infinity)"), Double.NaN, Double.NEGATIVE_INFINITY); checkVector(Vector2D.parse(Vector2D.ZERO.toString()), 0, 0); checkVector(Vector2D.parse(Vector2D.MINUS_X.toString()), -1, 0); @@ -487,11 +487,11 @@ public class Vector2DTest { @Test public void testGetFactory() { // act - Coordinates.Factory2D<Vector2D> factory = Vector2D.getFactory(); + RealFunction2N<Vector2D> factory = Vector2D.getFactory(); // assert - checkVector(factory.create(1, 2), 1, 2); - checkVector(factory.create(-1, -2), -1, -2); + checkVector(factory.apply(1, 2), 1, 2); + checkVector(factory.apply(-1, -2), -1, -2); } @Test diff --git a/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/oned/S1Point.java b/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/oned/S1Point.java index 7cced20..9dd2d32 100644 --- a/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/oned/S1Point.java +++ b/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/oned/S1Point.java @@ -19,8 +19,8 @@ package org.apache.commons.geometry.spherical.oned; import java.io.Serializable; import org.apache.commons.geometry.core.Point; -import org.apache.commons.geometry.core.util.Coordinates; -import org.apache.commons.geometry.core.util.SimpleCoordinateFormat; +import org.apache.commons.geometry.core.util.RealFunction; +import org.apache.commons.geometry.core.util.internal.SimpleTupleFormat; import org.apache.commons.geometry.euclidean.twod.Vector2D; import org.apache.commons.numbers.angle.PlaneAngleRadians; @@ -38,12 +38,12 @@ public final class S1Point implements Point<S1Point>, Serializable { private static final long serialVersionUID = 20131218L; /** Factory for delegating instance creation. */ - private static Coordinates.Factory1D<S1Point> FACTORY = new Coordinates.Factory1D<S1Point>() { + private static RealFunction<S1Point> FACTORY = new RealFunction<S1Point>() { /** {@inheritDoc} */ @Override - public S1Point create(double a) { - return S1Point.of(a); + public S1Point apply(double n) { + return S1Point.of(n); } }; @@ -167,7 +167,7 @@ public final class S1Point implements Point<S1Point>, Serializable { /** {@inheritDoc} */ @Override public String toString() { - return SimpleCoordinateFormat.getPointFormat().format(getAlpha()); + return SimpleTupleFormat.getDefault().format(getAlpha()); } /** Creates a new point instance from the given azimuthal coordinate value. @@ -189,13 +189,13 @@ public final class S1Point implements Point<S1Point>, Serializable { * @throws IllegalArgumentException if the given string has an invalid format */ public static S1Point parse(String str) throws IllegalArgumentException { - return SimpleCoordinateFormat.getPointFormat().parse(str, FACTORY); + return SimpleTupleFormat.getDefault().parse(str, FACTORY); } /** Returns a factory object that can be used to created new point instances. * @return point factory instance */ - public static Coordinates.Factory1D<S1Point> getFactory() { + public static RealFunction<S1Point> getFactory() { return FACTORY; } } diff --git a/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/S2Point.java b/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/S2Point.java index f8d3f4e..e5b2fbb 100644 --- a/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/S2Point.java +++ b/commons-geometry-spherical/src/main/java/org/apache/commons/geometry/spherical/twod/S2Point.java @@ -19,8 +19,8 @@ package org.apache.commons.geometry.spherical.twod; import java.io.Serializable; import org.apache.commons.geometry.core.Point; -import org.apache.commons.geometry.core.util.Coordinates; -import org.apache.commons.geometry.core.util.SimpleCoordinateFormat; +import org.apache.commons.geometry.core.util.RealFunction2N; +import org.apache.commons.geometry.core.util.internal.SimpleTupleFormat; import org.apache.commons.geometry.euclidean.threed.Vector3D; /** This class represents a point on the 2-sphere. @@ -62,12 +62,12 @@ public final class S2Point implements Point<S2Point>, Serializable { private static final long serialVersionUID = 20131218L; /** Factory for delegating instance creation. */ - private static Coordinates.Factory2D<S2Point> FACTORY = new Coordinates.Factory2D<S2Point>() { + private static RealFunction2N<S2Point> FACTORY = new RealFunction2N<S2Point>() { /** {@inheritDoc} */ @Override - public S2Point create(double a1, double a2) { - return S2Point.of(a1, a2); + public S2Point apply(double n1, double n2) { + return S2Point.of(n1, n2); } }; @@ -209,7 +209,7 @@ public final class S2Point implements Point<S2Point>, Serializable { /** {@inheritDoc} */ @Override public String toString() { - return SimpleCoordinateFormat.getPointFormat().format(getTheta(), getPhi()); + return SimpleTupleFormat.getDefault().format(getTheta(), getPhi()); } /** Build a vector from its spherical coordinates @@ -263,13 +263,13 @@ public final class S2Point implements Point<S2Point>, Serializable { * @throws IllegalArgumentException if the given string has an invalid format */ public static S2Point parse(String str) throws IllegalArgumentException { - return SimpleCoordinateFormat.getPointFormat().parse(str, FACTORY); + return SimpleTupleFormat.getDefault().parse(str, FACTORY); } /** Returns a factory object that can be used to created new point instances. * @return point factory instance */ - public static Coordinates.Factory2D<S2Point> getFactory() { + public static RealFunction2N<S2Point> getFactory() { return FACTORY; } } diff --git a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/oned/S1PointTest.java b/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/oned/S1PointTest.java index eac954d..e4f8b08 100644 --- a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/oned/S1PointTest.java +++ b/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/oned/S1PointTest.java @@ -17,7 +17,7 @@ package org.apache.commons.geometry.spherical.oned; import org.apache.commons.geometry.core.Geometry; -import org.apache.commons.geometry.core.util.Coordinates; +import org.apache.commons.geometry.core.util.RealFunction; import org.junit.Assert; import org.junit.Test; @@ -83,12 +83,12 @@ public class S1PointTest { @Test public void testGetFactory() { // act - Coordinates.Factory1D<S1Point> factory = S1Point.getFactory(); + RealFunction<S1Point> factory = S1Point.getFactory(); // assert - checkPoint(factory.create(0), 0); - checkPoint(factory.create(1), 1); - checkPoint(factory.create(Geometry.TWO_PI), 0); + checkPoint(factory.apply(0), 0); + checkPoint(factory.apply(1), 1); + checkPoint(factory.apply(Geometry.TWO_PI), 0); } private void checkPoint(S1Point p, double alpha) { diff --git a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/S2PointTest.java b/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/S2PointTest.java index 1661921..1a04010 100644 --- a/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/S2PointTest.java +++ b/commons-geometry-spherical/src/test/java/org/apache/commons/geometry/spherical/twod/S2PointTest.java @@ -18,7 +18,7 @@ package org.apache.commons.geometry.spherical.twod; import org.apache.commons.geometry.core.Geometry; -import org.apache.commons.geometry.core.util.Coordinates; +import org.apache.commons.geometry.core.util.RealFunction2N; import org.junit.Assert; import org.junit.Test; @@ -100,11 +100,11 @@ public class S2PointTest { @Test public void testGetFactory() { // act - Coordinates.Factory2D<S2Point> factory = S2Point.getFactory(); + RealFunction2N<S2Point> factory = S2Point.getFactory(); // assert - checkPoint(factory.create(0, 0), 0, 0); - checkPoint(factory.create(1, 2), 1, 2); + checkPoint(factory.apply(0, 0), 0, 0); + checkPoint(factory.apply(1, 2), 1, 2); } private void checkPoint(S2Point p, double theta, double phi) {
