You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2014/01/01 18:24:38 UTC

svn commit: r1554648 - in /commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical: ./ oned/ twod/

Author: luc
Date: Wed Jan  1 17:24:37 2014
New Revision: 1554648

URL: http://svn.apache.org/r1554648
Log:
Starting work on BSP trees for spheres.

Added:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Arc.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Chord.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/S1Point.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Sphere1D.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubChord.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/package-info.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Circle.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/S2Point.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Sphere2D.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/SubCircle.java   (with props)
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/package-info.java   (with props)

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Arc.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Arc.java?rev=1554648&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Arc.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Arc.java Wed Jan  1 17:24:37 2014
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.geometry.spherical.oned;
+
+import org.apache.commons.math3.geometry.partitioning.Region.Location;
+import org.apache.commons.math3.util.FastMath;
+import org.apache.commons.math3.util.MathUtils;
+import org.apache.commons.math3.util.Precision;
+
+
+/** This class represents an arc on a circle.
+ * @see ArcsSet
+ * @version $Id$
+ * @since 3.3
+ */
+public class Arc {
+
+    /** The lower angular bound of the arc. */
+    private final double lower;
+
+    /** The upper angular bound of the arc. */
+    private final double upper;
+
+    /** Middle point of the arc. */
+    private final double middle;
+
+    /** Simple constructor.
+     * <p>
+     * As the circle is a closed curve, {@code lower} is
+     * allowed to be greater than {@code upper}, and will
+     * be automatically canonicalized so the arc wraps
+     * around \( 2\pi \), but without exceeding a total
+     * length of \( 2\pi \). If {@code lower} is equals
+     * to {@code upper}, the arc is considered to be the full
+     * circle.
+     * </p>
+     * @param lower lower angular bound of the arc
+     * @param upper upper angular bound of the arc
+     */
+    public Arc(final double lower, final double upper) {
+        this.lower = lower;
+        if (Precision.equals(lower, upper, 0)) {
+            this.upper = 2 * FastMath.PI + lower;
+        } else {
+            this.upper = MathUtils.normalizeAngle(upper, lower + FastMath.PI);
+        }
+        this.middle = 0.5 * (this.lower + this.upper);
+    }
+
+    /** Get the lower angular bound of the arc.
+     * @return lower angular bound of the arc
+     */
+    public double getInf() {
+        return lower;
+    }
+
+    /** Get the upper angular bound of the arc.
+     * @return upper angular bound of the arc
+     */
+    public double getSup() {
+        return upper;
+    }
+
+    /** Get the angular size of the arc.
+     * @return angular size of the arc
+     */
+    public double getSize() {
+        return upper - lower;
+    }
+
+    /** Get the barycenter of the arc.
+     * @return barycenter of the arc
+     */
+    public double getBarycenter() {
+        return middle;
+    }
+
+    /** Check a point with respect to the arc.
+     * @param point point to check
+     * @param tolerance tolerance below which points are considered to
+     * belong to the boundary
+     * @return a code representing the point status: either {@link
+     * Location#INSIDE}, {@link Location#OUTSIDE} or {@link Location#BOUNDARY}
+     */
+    public Location checkPoint(final double point, final double tolerance) {
+        final double normalizedPoint = MathUtils.normalizeAngle(point, middle);
+        if (normalizedPoint < lower - tolerance || normalizedPoint > upper + tolerance) {
+            return Location.OUTSIDE;
+        } else if (normalizedPoint > lower + tolerance && normalizedPoint < upper - tolerance) {
+            return Location.INSIDE;
+        } else {
+            return Location.BOUNDARY;
+        }
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Arc.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Arc.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java?rev=1554648&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java Wed Jan  1 17:24:37 2014
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.geometry.spherical.oned;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.commons.math3.geometry.partitioning.AbstractRegion;
+import org.apache.commons.math3.geometry.partitioning.BSPTree;
+import org.apache.commons.math3.geometry.partitioning.SubHyperplane;
+import org.apache.commons.math3.util.FastMath;
+import org.apache.commons.math3.util.MathUtils;
+import org.apache.commons.math3.util.Precision;
+
+/** This class represents a region of a circle: a set of arcs.
+ * @version $Id$
+ * @since 3.3
+ */
+public class ArcsSet extends AbstractRegion<Sphere1D, Sphere1D> {
+
+    /** Build an arcs set representing the whole circle.
+     */
+    public ArcsSet() {
+        super();
+    }
+
+    /** Build an arcs set corresponding to a single arc.
+     * <p>
+     * As the circle is a closed curve, {@code lower} is
+     * allowed to be greater than {@code upper}, and will
+     * be automatically canonicalized so the arc wraps
+     * around \( 2\pi \), but without exceeding a total
+     * length of \( 2\pi \). If {@code lower} is equals
+     * to {@code upper}, the arc is considered to be the full
+     * circle.
+     * </p>
+     * @param lower lower bound of the arc
+     * @param upper upper bound of the arc
+     */
+    public ArcsSet(final double lower, final double upper) {
+        super(buildTree(lower, upper));
+    }
+
+    /** Build an arcs set from an inside/outside BSP tree.
+     * <p>The leaf nodes of the BSP tree <em>must</em> have a
+     * {@code Boolean} attribute representing the inside status of
+     * the corresponding cell (true for inside cells, false for outside
+     * cells). In order to avoid building too many small objects, it is
+     * recommended to use the predefined constants
+     * {@code Boolean.TRUE} and {@code Boolean.FALSE}</p>
+     * @param tree inside/outside BSP tree representing the arcs set
+     */
+    public ArcsSet(final BSPTree<Sphere1D> tree) {
+        super(tree);
+    }
+
+    /** Build an arcs set from a Boundary REPresentation (B-rep).
+     * <p>The boundary is provided as a collection of {@link
+     * SubHyperplane sub-hyperplanes}. Each sub-hyperplane has the
+     * interior part of the region on its minus side and the exterior on
+     * its plus side.</p>
+     * <p>The boundary elements can be in any order, and can form
+     * several non-connected sets (like for example polygons with holes
+     * or a set of disjoints polyhedrons considered as a whole). In
+     * fact, the elements do not even need to be connected together
+     * (their topological connections are not used here). However, if the
+     * boundary does not really separate an inside open from an outside
+     * open (open having here its topological meaning), then subsequent
+     * calls to the {@link
+     * org.apache.commons.math3.geometry.partitioning.Region#checkPoint(org.apache.commons.math3.geometry.Vector)
+     * checkPoint} method will not be meaningful anymore.</p>
+     * <p>If the boundary is empty, the region will represent the whole
+     * space.</p>
+     * @param boundary collection of boundary elements
+     */
+    public ArcsSet(final Collection<SubHyperplane<Sphere1D>> boundary) {
+        super(boundary);
+    }
+
+    /** Build an inside/outside tree representing a single arc.
+     * <p>
+     * As the circle is a closed curve, {@code lower} is
+     * allowed to be greater than {@code upper}, and will
+     * be automatically canonicalized so the arc wraps
+     * around \( 2\pi \), but without exceeding a total
+     * length of \( 2\pi \). If {@code lower} is equals
+     * to {@code upper}, the arc is considered to be the full
+     * circle.
+     * </p>
+     * @param lower lower angular bound of the arc
+     * @param upper upper angular bound of the arc
+     * @return the built tree
+     */
+    private static BSPTree<Sphere1D> buildTree(final double lower, final double upper) {
+
+        if (Precision.equals(lower, upper, 0)) {
+            // the tree must cover the whole real line
+            return new BSPTree<Sphere1D>(Boolean.TRUE);
+        }
+
+        // the two boundary angles define only one cutting chord
+        final double normalizedUpper = MathUtils.normalizeAngle(upper, lower + FastMath.PI);
+        return new BSPTree<Sphere1D>(new Chord(lower, normalizedUpper).wholeHyperplane(),
+                                     new BSPTree<Sphere1D>(Boolean.FALSE),
+                                     new BSPTree<Sphere1D>(Boolean.TRUE),
+                                     null);
+
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public ArcsSet buildNew(final BSPTree<Sphere1D> tree) {
+        return new ArcsSet(tree);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void computeGeometricalProperties() {
+        if (getTree(false).getCut() == null) {
+            setBarycenter(S1Point.NaN);
+            setSize(((Boolean) getTree(false).getAttribute()) ? 2 * FastMath.PI : 0);
+        } else {
+            double size = 0.0;
+            double sum  = 0.0;
+            for (final Arc arc : asList()) {
+                size += arc.getSize();
+                sum  += arc.getSize() * arc.getBarycenter();
+            }
+            setSize(size);
+            if (Precision.equals(size, 2 * FastMath.PI, 0)) {
+                setBarycenter(S1Point.NaN);
+            } else if (size >= Precision.SAFE_MIN) {
+                setBarycenter(new S1Point(sum / size));
+            } else {
+                final Chord chord = (Chord) getTree(false).getCut().getHyperplane();
+                setBarycenter(new S1Point(0.5 * (chord.getStart() + chord.getEnd())));
+            }
+        }
+    }
+
+    /** Build an ordered list of arcs representing the instance.
+     * <p>This method builds this arcs set as an ordered list of
+     * {@link Arc Arc} elements. An empty tree will build an empty list
+     * while a tree representing the whole real line will build a one
+     * element list with bounds set to \( 0 and \pi \).</p>
+     * @return a new ordered list containing {@link Arc Arc} elements
+     */
+    public List<Arc> asList() {
+        final List<Arc> list = new ArrayList<Arc>();
+        recurseList(getTree(false), list, 0, 2 * FastMath.PI);
+        return list;
+    }
+
+    /** Update an arcs list.
+     * @param node current node
+     * @param list list to update
+     * @param lower lower bound of the current convex cell
+     * @param upper upper bound of the current convex cell
+     */
+    private void recurseList(final BSPTree<Sphere1D> node, final List<Arc> list,
+                             final double lower, final double upper) {
+
+        if (node.getCut() == null) {
+            if ((Boolean) node.getAttribute()) {
+                // this leaf cell is an inside cell: an arc
+                list.add(new Arc(lower, upper));
+            }
+        } else {
+            final Chord   chord = (Chord) node.getCut().getHyperplane();
+            final S1Point loc   = chord.getMiddle();
+            double        alpha = loc.getAlpha();
+
+            // make sure we explore the tree in increasing order
+            final BSPTree<Sphere1D> low  = chord.isDirect() ? node.getMinus() : node.getPlus();
+            final BSPTree<Sphere1D> high = chord.isDirect() ? node.getPlus()  : node.getMinus();
+
+            recurseList(low, list, lower, alpha);
+            if ((checkPoint(low,  loc) == Location.INSIDE) &&
+                (checkPoint(high, loc) == Location.INSIDE)) {
+                // merge the last arc added and the first one of the high sub-tree
+                alpha = list.remove(list.size() - 1).getInf();
+            }
+            recurseList(high, list, alpha, upper);
+
+        }
+
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Chord.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Chord.java?rev=1554648&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Chord.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Chord.java Wed Jan  1 17:24:37 2014
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.geometry.spherical.oned;
+
+import org.apache.commons.math3.geometry.Point;
+import org.apache.commons.math3.geometry.partitioning.Hyperplane;
+import org.apache.commons.math3.util.FastMath;
+
+/** This class represents a 1D oriented hyperplane on the circle.
+ * <p>An hyperplane on the 1-sphere is a chord that splits
+ * the circle in two parts.</p>
+ * <p>Instances of this class are guaranteed to be immutable.</p>
+ * @version $Id$
+ * @since 3.3
+ */
+public class Chord implements Hyperplane<Sphere1D> {
+
+    /** Start angle of the chord. */
+    private final double start;
+
+    /** End angle of the chord. */
+    private final double end;
+
+    /** Cosine of the half aperture. */
+    private final double cos;
+
+    /** Middle point of the chord. */
+    private final S1Point middle;
+
+    /** Simple constructor.
+     * @param start start angle of the chord
+     * @param end end angle of the chord
+     */
+    public Chord(final double start, final double end) {
+        this.start  = start;
+        this.end    = end;
+        this.middle = new S1Point(0.5 * (start + end));
+        this.cos    = FastMath.cos(0.5 * (end - start));
+    }
+
+    /** Copy the instance.
+     * <p>Since instances are immutable, this method directly returns
+     * the instance.</p>
+     * @return the instance itself
+     */
+    public Chord copySelf() {
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    public double getOffset(final Point<Sphere1D> point) {
+        return cos - middle.getVector().dotProduct(((S1Point) point).getVector());
+    }
+
+    /** Build a region covering the whole hyperplane.
+     * <p>Since this class represent zero dimension spaces which does
+     * not have lower dimension sub-spaces, this method returns a dummy
+     * implementation of a {@link
+     * org.apache.commons.math3.geometry.partitioning.SubHyperplane SubHyperplane}.
+     * This implementation is only used to allow the {@link
+     * org.apache.commons.math3.geometry.partitioning.SubHyperplane
+     * SubHyperplane} class implementation to work properly, it should
+     * <em>not</em> be used otherwise.</p>
+     * @return a dummy sub hyperplane
+     */
+    public SubChord wholeHyperplane() {
+        return new SubChord(this);
+    }
+
+    /** Build a region covering the whole space.
+     * @return a region containing the instance (really an {@link
+     * ArcsSet IntervalsSet} instance)
+     */
+    public ArcsSet wholeSpace() {
+        return new ArcsSet();
+    }
+
+    /** {@inheritDoc} */
+    public boolean sameOrientationAs(final Hyperplane<Sphere1D> other) {
+        return middle.getVector().dotProduct(((Chord) other).middle.getVector()) >= 0.0;
+    }
+
+    /** Get the start angle of the chord.
+     * @return start angle of the chord.
+     */
+    public double getStart() {
+        return start;
+    }
+
+    /** Get the end angle of the chord.
+     * @return end angle of the chord.
+     */
+    public double getEnd() {
+        return end;
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Chord.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Chord.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/S1Point.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/S1Point.java?rev=1554648&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/S1Point.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/S1Point.java Wed Jan  1 17:24:37 2014
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.geometry.spherical.oned;
+
+import org.apache.commons.math3.geometry.Point;
+import org.apache.commons.math3.geometry.Space;
+import org.apache.commons.math3.geometry.euclidean.twod.Vector2D;
+import org.apache.commons.math3.util.FastMath;
+import org.apache.commons.math3.util.MathUtils;
+
+/** This class represents a point on the 1-sphere.
+ * <p>Instances of this class are guaranteed to be immutable.</p>
+ * @version $Id$
+ * @since 3.3
+ */
+public class S1Point implements Point<Sphere1D> {
+
+   // CHECKSTYLE: stop ConstantName
+    /** A vector with all coordinates set to NaN. */
+    public static final S1Point NaN = new S1Point(Double.NaN, Vector2D.NaN);
+    // CHECKSTYLE: resume ConstantName
+
+    /** Serializable UID. */
+    private static final long serialVersionUID = 20131218L;
+
+    /** Azimuthal angle \( \alpha \). */
+    private final double alpha;
+
+    /** Corresponding 2D normalized vector. */
+    private final Vector2D vector;
+
+    /** Simple constructor.
+     * Build a vector from its coordinates
+     * @param alpha azimuthal angle \( \alpha \)
+     * @see #getAlpha()
+     */
+    public S1Point(final double alpha) {
+        this(alpha, new Vector2D(FastMath.cos(alpha), FastMath.sin(alpha)));
+    }
+
+    /** Build a point from its internal components.
+     * @param alpha azimuthal angle \( \alpha \)
+     * @param vector corresponding vector
+     */
+    private S1Point(final double alpha, final Vector2D vector) {
+        this.alpha  = alpha;
+        this.vector = vector;
+    }
+
+    /** Get the azimuthal angle \( \alpha \).
+     * @return azimuthal angle \( \alpha \)
+     * @see #S1Point(double)
+     */
+    public double getAlpha() {
+        return alpha;
+    }
+
+    /** Get the corresponding normalized vector in the 2D euclidean space.
+     * @return normalized vector
+     */
+    public Vector2D getVector() {
+        return vector;
+    }
+
+    /** {@inheritDoc} */
+    public Space getSpace() {
+        return Sphere1D.getInstance();
+    }
+
+    /** {@inheritDoc} */
+    public boolean isNaN() {
+        return Double.isNaN(alpha);
+    }
+
+    /** Compute the distance (angular separation) between two points.
+     * @param p1 first vector
+     * @param p2 second vector
+     * @return the angular separation between p1 and p2
+     */
+    public static double distance(S1Point p1, S1Point p2) {
+        return Vector2D.angle(p1.vector, p2.vector);
+    }
+
+    /**
+     * Test for the equality of two points on the 2-sphere.
+     * <p>
+     * If all coordinates of two points are exactly the same, and none are
+     * <code>Double.NaN</code>, the two points are considered to be equal.
+     * </p>
+     * <p>
+     * <code>NaN</code> coordinates are considered to affect globally the vector
+     * and be equals to each other - i.e, if either (or all) coordinates of the
+     * 2D vector are equal to <code>Double.NaN</code>, the 2D vector is equal to
+     * {@link #NaN}.
+     * </p>
+     *
+     * @param other Object to test for equality to this
+     * @return true if two points on the 2-sphere objects are equal, false if
+     *         object is null, not an instance of S2Point, or
+     *         not equal to this S2Point instance
+     *
+     */
+    @Override
+    public boolean equals(Object other) {
+
+        if (this == other) {
+            return true;
+        }
+
+        if (other instanceof S1Point) {
+            final S1Point rhs = (S1Point) other;
+            if (rhs.isNaN()) {
+                return this.isNaN();
+            }
+
+            return alpha == rhs.alpha;
+        }
+
+        return false;
+
+    }
+
+    /**
+     * Get a hashCode for the 2D vector.
+     * <p>
+     * All NaN values have the same hash code.</p>
+     *
+     * @return a hash code value for this object
+     */
+    @Override
+    public int hashCode() {
+        if (isNaN()) {
+            return 542;
+        }
+        return 1759 * MathUtils.hash(alpha);
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/S1Point.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/S1Point.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Sphere1D.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Sphere1D.java?rev=1554648&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Sphere1D.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Sphere1D.java Wed Jan  1 17:24:37 2014
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math3.geometry.spherical.oned;
+
+import java.io.Serializable;
+
+import org.apache.commons.math3.exception.MathUnsupportedOperationException;
+import org.apache.commons.math3.exception.util.LocalizedFormats;
+import org.apache.commons.math3.geometry.Space;
+import org.apache.commons.math3.geometry.spherical.oned.Sphere1D;
+
+/**
+ * This class implements a one-dimensional sphere (i.e. a circle).
+ * <p>
+ * We use here the topologists definition of the 1-sphere (see
+ * <a href="http://mathworld.wolfram.com/Sphere.html">Sphere</a> on
+ * MathWorld), i.e. the 1-sphere is the one-dimensional closed curve
+ * defined in 2D as x<sup>2</sup>+y<sup>2</sup>=1.
+ * </p>
+ * @version $Id$
+ * @since 3.3
+ */
+public class Sphere1D implements Serializable, Space {
+
+    /** Serializable version identifier. */
+    private static final long serialVersionUID = 20131218L;
+
+    /** Private constructor for the singleton.
+     */
+    private Sphere1D() {
+    }
+
+    /** Get the unique instance.
+     * @return the unique instance
+     */
+    public static Sphere1D getInstance() {
+        return LazyHolder.INSTANCE;
+    }
+
+    /** {@inheritDoc} */
+    public int getDimension() {
+        return 1;
+    }
+
+    /** {@inheritDoc}
+     * <p>
+     * As the 1-dimension sphere does not have proper sub-spaces,
+     * this method always throws a {@link MathUnsupportedOperationException}
+     * </p>
+     * @return nothing
+     * @throws MathUnsupportedOperationException in all cases
+     */
+    public Space getSubSpace() throws MathUnsupportedOperationException {
+        throw new MathUnsupportedOperationException(LocalizedFormats.NOT_SUPPORTED_IN_DIMENSION_N, 1);
+    }
+
+    // CHECKSTYLE: stop HideUtilityClassConstructor
+    /** Holder for the instance.
+     * <p>We use here the Initialization On Demand Holder Idiom.</p>
+     */
+    private static class LazyHolder {
+        /** Cached field instance. */
+        private static final Sphere1D INSTANCE = new Sphere1D();
+    }
+    // CHECKSTYLE: resume HideUtilityClassConstructor
+
+    /** Handle deserialization of the singleton.
+     * @return the singleton instance
+     */
+    private Object readResolve() {
+        // return the singleton instance
+        return LazyHolder.INSTANCE;
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Sphere1D.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Sphere1D.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubChord.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubChord.java?rev=1554648&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubChord.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubChord.java Wed Jan  1 17:24:37 2014
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.geometry.spherical.oned;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.math3.geometry.partitioning.Hyperplane;
+import org.apache.commons.math3.geometry.partitioning.Side;
+import org.apache.commons.math3.geometry.partitioning.SubHyperplane;
+import org.apache.commons.math3.util.Precision;
+
+/** This class represents sub-hyperplane for {@link Chord}.
+ * <p>Instances of this class are guaranteed to be immutable.</p>
+ * @version $Id$
+ * @since 3.3
+ */
+public class SubChord implements SubHyperplane<Sphere1D> {
+
+    /** Underlying hyperplane. */
+    private final Chord chord;
+
+    /** Boundary angles. */
+    private final List<Double> limits;
+
+    /** Simple constructor.
+     * @param chord underlying hyperplane
+     */
+    public SubChord(final Chord chord) {
+        this.chord = chord;
+        this.limits = new ArrayList<Double>();
+        limits.add(chord.getStart());
+        limits.add(chord.getEnd());
+    }
+
+    /** Simple constructor.
+     * @param chord underlying hyperplane
+     * @param limits limit angles
+     */
+    private SubChord(final Chord chord, final List<Double> limits) {
+        this.chord = chord;
+        this.limits = new ArrayList<Double>(limits);
+    }
+
+    /** {@inheritDoc} */
+    public double getSize() {
+        double sum = 0;
+        for (int i = 0; i < limits.size(); i += 2) {
+            sum += limits.get(i + 1) - limits.get(i);
+        }
+        return sum;
+    }
+
+    /** {@inheritDoc} */
+    public Side side(final Hyperplane<Sphere1D> hyperplane) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    public SplitSubHyperplane<Sphere1D> split(final Hyperplane<Sphere1D> hyperplane) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    public SubHyperplane<Sphere1D> copySelf() {
+        return new SubChord(chord, limits);
+    }
+
+    /** {@inheritDoc} */
+    public Hyperplane<Sphere1D> getHyperplane() {
+        return chord;
+    }
+
+    /** {@inheritDoc} */
+    public boolean isEmpty() {
+        return getSize() <= Precision.SAFE_MIN;
+    }
+
+    /** {@inheritDoc} */
+    public SubHyperplane<Sphere1D> reunite(SubHyperplane<Sphere1D> other) {
+        final List<Double> otherLimits = ((SubChord) other).limits;
+        final List<Double> merged = new ArrayList<Double>(limits.size() + otherLimits.size());
+
+        int i = 0;
+        int j = 0;
+        boolean inside = false;
+        while (i < limits.size() || j < otherLimits.size()) {
+            // TODO: implement merging loop
+        }
+
+        return new SubChord(chord, merged);
+
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubChord.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubChord.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/package-info.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/package-info.java?rev=1554648&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/package-info.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/package-info.java Wed Jan  1 17:24:37 2014
@@ -0,0 +1,30 @@
+/*
+ * 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 provides basic geometry components on the 1-sphere.
+ * </p>
+ * <p>
+ * We use here the topologists definition of the 1-sphere (see
+ * <a href="http://mathworld.wolfram.com/Sphere.html">Sphere</a> on
+ * MathWorld), i.e. the 1-sphere is the one-dimensional closed curve
+ * defined in 2D as x<sup>2</sup>+y<sup>2</sup>=1.
+ * </p>
+ *
+ */
+package org.apache.commons.math3.geometry.spherical.oned;

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/package-info.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Circle.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Circle.java?rev=1554648&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Circle.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Circle.java Wed Jan  1 17:24:37 2014
@@ -0,0 +1,341 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.geometry.spherical.twod;
+
+import org.apache.commons.math3.geometry.Point;
+import org.apache.commons.math3.geometry.euclidean.threed.Rotation;
+import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
+import org.apache.commons.math3.geometry.partitioning.Embedding;
+import org.apache.commons.math3.geometry.partitioning.Hyperplane;
+import org.apache.commons.math3.geometry.partitioning.SubHyperplane;
+import org.apache.commons.math3.geometry.partitioning.Transform;
+import org.apache.commons.math3.geometry.spherical.oned.Chord;
+import org.apache.commons.math3.geometry.spherical.oned.ArcsSet;
+import org.apache.commons.math3.geometry.spherical.oned.S1Point;
+import org.apache.commons.math3.geometry.spherical.oned.Sphere1D;
+import org.apache.commons.math3.util.FastMath;
+
+/** This class represents an oriented circle on the 2-sphere.
+
+ * <p>An oriented circle can be defined by a center point and an
+ * angular radius. The circle is the the set of points that are exactly
+ * at the specified angular radius from the center (which does not
+ * belong to the circle it defines except if angular radius is 0).</p>
+
+ * <p>Since it is oriented the two spherical caps at its two sides are
+ * unambiguously identified as a left cap and a right cap. This can be
+ * used to identify the interior and the exterior in a simple way by
+ * local properties only when part of a line is used to define part of
+ * a spherical polygon boundary.</p>
+
+ * @version $Id$
+ * @since 3.3
+ */
+public class Circle implements Hyperplane<Sphere2D>, Embedding<Sphere2D, Sphere1D> {
+
+    /** Pole or circle center. */
+    private Vector3D pole;
+
+    /** First axis in the equator plane, origin of the phase angles. */
+    private Vector3D x;
+
+    /** Second axis in the equator plane, in quadrature with respect to x. */
+    private Vector3D y;
+
+    /** Angular radius. */
+    private double radius;
+
+    /** Cosine of the radius. */
+    private double cos;
+
+    /** Sine of the radius. */
+    private double sin;
+
+    /** Build a circle from a center and a radius.
+     * <p>The circle is oriented in the trigonometric direction around center.</p>
+     * @param center circle enter
+     * @param radius cirle radius
+     */
+    public Circle(final Vector3D center, final double radius) {
+        reset(center, radius);
+    }
+
+    /** Build a great circle from a center only, radius being forced to \( \pi/2 \).
+     * <p>This constructor is recommended to build great circles as it does
+     * ensure the exact values of \( \cos(\pi/2) = 0 and \sin(\pi) = 1 \) are used.</p>
+     * <p>The circle is oriented in the trigonometric direction around center.</p>
+     * @param center circle enter
+     */
+    public Circle(final Vector3D center) {
+        reset(center);
+    }
+
+    /** Build a circle from its internal components.
+     * <p>The circle is oriented in the trigonometric direction around center.</p>
+     * @param pole circle pole
+     * @param x first axis in the equator plane
+     * @param y second axis in the equator plane
+     * @param radius cirle radius
+     * @param cos cosine of the radius
+     * @param sin sine of the radius
+     */
+    private Circle(final Vector3D pole, final Vector3D x, final Vector3D y,
+                   final double radius, final double cos, final double sin) {
+        this.pole   = pole;
+        this.x      = x;
+        this.y      = y;
+        this.radius = radius;
+        this.cos    = cos;
+        this.sin    = sin;
+    }
+
+    /** Copy constructor.
+     * <p>The created instance is completely independent from the
+     * original instance, it is a deep copy.</p>
+     * @param circle circle to copy
+     */
+    public Circle(final Circle circle) {
+        this(circle.pole, circle.x, circle.y, circle.radius, circle.cos, circle.sin);
+    }
+
+    /** {@inheritDoc} */
+    public Circle copySelf() {
+        return new Circle(this);
+    }
+
+    /** Reset the instance as if built from a center and a radius.
+     * <p>The circle is oriented in the trigonometric direction around center.</p>
+     * @param newCenter circle enter
+     * @param newRadius cirle radius
+     */
+    public void reset(final Vector3D newCenter, final double newRadius) {
+        reset(newCenter, newRadius, FastMath.cos(radius), FastMath.sin(radius));
+    }
+
+    /** Reset the instance as if built from a center, radius being forced to \( \pi/2 \).
+     * <p>This constructor is recommended to build great circles as it does
+     * ensure the exact values of \( \cos(\pi/2) = 0 and \sin(\pi) = 1 \) are used.</p>
+     * <p>The circle is oriented in the trigonometric direction around center.</p>
+     * @param newCenter circle enter
+     */
+    public void reset(final Vector3D newCenter) {
+        reset(newCenter, 0.5 * FastMath.PI, 0.0, 1.0);
+    }
+
+    /** Reset the instance.
+     * @param newCenter circle enter
+     * @param newRadius cirle radius
+     * @param newCos cosine of the radius
+     * @param newSin sine of the radius
+     */
+    private void reset(final Vector3D newCenter, final double newRadius,
+                       final double newCos, final double newSin) {
+        this.pole   = newCenter.normalize();
+        this.x      = newCenter.orthogonal();
+        this.y      = Vector3D.crossProduct(newCenter, x).normalize();
+        this.radius = newRadius;
+        this.cos    = newCos;
+        this.sin    = newSin;
+    }
+
+    /** Revert the instance.
+     */
+    public void revertSelf() {
+        // x remains the same
+        y      = y.negate();
+        pole   = pole.negate();
+        radius = FastMath.PI - radius;
+        cos    = -cos;
+    }
+
+    /** Get the reverse of the instance.
+     * <p>Get a circle with reversed orientation with respect to the
+     * instance. A new object is built, the instance is untouched.</p>
+     * @return a new circle, with orientation opposite to the instance orientation
+     */
+    public Circle getReverse() {
+        return new Circle(pole.negate(), x, y.negate(), FastMath.PI - radius, -cos, sin);
+    }
+
+    /** {@inheritDoc}
+     * @see #getPhase(Vector3D)
+     */
+    public S1Point toSubSpace(final Point<Sphere2D> point) {
+        return new S1Point(getPhase(((S2Point) point).getVector()));
+    }
+
+    /** Get the phase angle of a direction.
+     * <p>
+     * The direction may not belong to the circle as the
+     * phase is computed for the meridian plane between the circle
+     * pole and the direction.
+     * </p>
+     * @param direction direction for which phase is requested
+     * @return phase angle of the direction around the circle
+     * @see #toSubSpace(Point)
+     */
+    public double getPhase(final Vector3D direction) {
+        return FastMath.PI + FastMath.atan2(-direction.dotProduct(y), -direction.dotProduct(x));
+    }
+
+    /** {@inheritDoc}
+     * @see #getPointAt(double)
+     */
+    public S2Point toSpace(final Point<Sphere1D> point) {
+        return new S2Point(getPointAt(((S1Point) point).getAlpha()));
+    }
+
+    /** Get a circle point from its phase around the circle.
+     * @param alpha phase around the circle
+     * @return circle point on the sphere
+     * @see #toSpace(Point)
+     */
+    public Vector3D getPointAt(final double alpha) {
+        final double cosAlpha = FastMath.cos(alpha);
+        final double sinAlpha = FastMath.sin(alpha);
+        return new Vector3D(cosAlpha * sin, x, sinAlpha * sin, y, cos, pole);
+    }
+
+    /** Get the intersection points of the instance and another circle.
+     * @param other other circle
+     * @return intersection points of the instance and the other circle
+     * or null if there are no intersection points
+     */
+    public S2Point[] intersection(final Circle other) {
+
+        // we look for a vector as v = a pole + b other.pole +/- c pole ^ other.pole
+        // and such that v angular separation with both centers is consistent
+        // with each circle radius, and v is also on the 2-sphere
+
+        final double dot = Vector3D.dotProduct(pole, other.pole);
+        final double f = 1.0 / (1.0 - dot * dot);
+        final double a = f * (cos - dot * other.cos);
+        final double b = f * (other.cos - dot * cos);
+        final Vector3D inPlane = new Vector3D(a, pole, b, other.pole);
+        final double omN2 = 1.0 - inPlane.getNormSq();
+        if (omN2 <= 0) {
+            // no intersections (we include the just tangent case too)
+            return null;
+        }
+
+        final double c = FastMath.sqrt(f * omN2);
+        final Vector3D outOfPlane = new Vector3D(c, Vector3D.crossProduct(pole, other.pole));
+
+        return new S2Point[] {
+            new S2Point(inPlane.add(outOfPlane)),
+            new S2Point(inPlane.subtract(outOfPlane))
+        };
+
+    }
+
+    /** {@inheritDoc} */
+    public SubCircle wholeHyperplane() {
+        return new SubCircle(this, new ArcsSet());
+    }
+
+    /** Build a region covering the whole space.
+     * @return a region containing the instance (really a {@link
+     * SphericalPolygonsSet SphericalPolygonsSet} instance)
+     */
+    public SphericalPolygonsSet wholeSpace() {
+        return new SphericalPolygonsSet();
+    }
+
+    /** {@inheritDoc}
+     * @see #getOffset(Vector3D)
+     */
+    public double getOffset(final Point<Sphere2D> point) {
+        return getOffset(((S2Point) point).getVector());
+    }
+
+    /** Get the offset (oriented distance) of a direction.
+     * <p>The offset is defined as the angular distance between the
+     * circle center and the direction minus the circle radius. It
+     * is therefore 0 on the circle, positive for directions outside of
+     * the cone delimited by the circle, and negative inside the cone.</p>
+     * @param direction direction to check
+     * @return offset of the direction
+     * @see #getOffset(Point)
+     */
+    public double getOffset(final Vector3D direction) {
+        return Vector3D.angle(pole, direction) - radius;
+    }
+
+    /** {@inheritDoc} */
+    public boolean sameOrientationAs(final Hyperplane<Sphere2D> other) {
+        final Circle otherC = (Circle) other;
+        return Vector3D.dotProduct(pole, otherC.pole) >= 0.0;
+    }
+
+    /** Check if the circle contains a point.
+     * @param p point to check
+     * @return true if p belongs to the circle
+     */
+    public boolean contains(final Point<Sphere2D> p) {
+        return FastMath.abs(getOffset(p)) < 1.0e-10;
+    }
+
+    /** Get a {@link org.apache.commons.math3.geometry.partitioning.Transform
+     * Transform} embedding a 3D rotation.
+     * @param rotation rotation to use
+     * @return a new transform that can be applied to either {@link
+     * Point<Sphere2D> Point<Sphere2D>}, {@link Circle Line} or {@link
+     * org.apache.commons.math3.geometry.partitioning.SubHyperplane
+     * SubHyperplane} instances
+     */
+    public static Transform<Sphere2D, Sphere1D> getTransform(final Rotation rotation) {
+        return new CircleTransform(rotation);
+    }
+
+    /** Class embedding a 3D rotation. */
+    private static class CircleTransform implements Transform<Sphere2D, Sphere1D> {
+
+        /** Underlying rotation. */
+        private final Rotation rotation;
+
+        /** Build a transform from a {@code Rotation}.
+         * @param rotation rotation to use
+         */
+        public CircleTransform(final Rotation rotation) {
+            this.rotation = rotation;
+        }
+
+        /** {@inheritDoc} */
+        public S2Point apply(final Point<Sphere2D> point) {
+            return new S2Point(rotation.applyTo(((S2Point) point).getVector()));
+        }
+
+        /** {@inheritDoc} */
+        public Circle apply(final Hyperplane<Sphere2D> hyperplane) {
+            final Circle circle = (Circle) hyperplane;
+            return new Circle(rotation.applyTo(circle.pole),
+                              rotation.applyTo(circle.x),
+                              rotation.applyTo(circle.y),
+                              circle.radius, circle.cos, circle.sin);
+        }
+
+        /** {@inheritDoc} */
+        public SubHyperplane<Sphere1D> apply(final SubHyperplane<Sphere1D> sub,
+                                             final Hyperplane<Sphere2D> original,
+                                             final Hyperplane<Sphere2D> transformed) {
+            // as the circle is rotated, the chords are rotated too
+            return sub;
+        }
+
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Circle.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Circle.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/S2Point.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/S2Point.java?rev=1554648&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/S2Point.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/S2Point.java Wed Jan  1 17:24:37 2014
@@ -0,0 +1,226 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.geometry.spherical.twod;
+
+import org.apache.commons.math3.exception.MathArithmeticException;
+import org.apache.commons.math3.exception.OutOfRangeException;
+import org.apache.commons.math3.geometry.Point;
+import org.apache.commons.math3.geometry.Space;
+import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
+import org.apache.commons.math3.util.FastMath;
+import org.apache.commons.math3.util.MathUtils;
+
+/** This class represents a point on the 2-sphere.
+ * <p>
+ * We use the mathematical convention to use the azimuthal angle \( \theta \)
+ * in the x-y plane as the first coordinate, and the polar angle \( \varphi \)
+ * as the second coordinate (see <a
+ * href="http://mathworld.wolfram.com/SphericalCoordinates.html">Spherical
+ * Coordinates</a> in MathWorld).
+ * </p>
+ * <p>Instances of this class are guaranteed to be immutable.</p>
+ * @version $Id$
+ * @since 3.3
+ */
+public class S2Point implements Point<Sphere2D> {
+
+    /** +I (coordinates: \( \theta = 0, \varphi = \pi/2 \)). */
+    public static final S2Point PLUS_I = new S2Point(0, 0.5 * FastMath.PI, Vector3D.PLUS_I);
+
+    /** +J (coordinates: \( \theta = \pi/2, \varphi = \pi/2 \))). */
+    public static final S2Point PLUS_J = new S2Point(0.5 * FastMath.PI, 0.5 * FastMath.PI, Vector3D.PLUS_J);
+
+    /** +K (coordinates: \( \theta = any angle, \varphi = 0 \)). */
+    public static final S2Point PLUS_K = new S2Point(0, 0, Vector3D.PLUS_K);
+
+    /** -I (coordinates: \( \theta = \pi, \varphi = \pi/2 \)). */
+    public static final S2Point MINUS_I = new S2Point(FastMath.PI, 0.5 * FastMath.PI, Vector3D.MINUS_I);
+
+    /** -J (coordinates: \( \theta = 3\pi/2, \varphi = \pi/2 \)). */
+    public static final S2Point MINUS_J = new S2Point(1.5 * FastMath.PI, 0.5 * FastMath.PI, Vector3D.MINUS_J);
+
+    /** -K (coordinates: \( \theta = any angle, \varphi = \pi \)). */
+    public static final S2Point MINUS_K = new S2Point(0, FastMath.PI, Vector3D.MINUS_K);
+
+    // CHECKSTYLE: stop ConstantName
+    /** A vector with all coordinates set to NaN. */
+    public static final S2Point NaN = new S2Point(Double.NaN, Double.NaN, Vector3D.NaN);
+    // CHECKSTYLE: resume ConstantName
+
+    /** Serializable UID. */
+    private static final long serialVersionUID = 20131218L;
+
+    /** Azimuthal angle \( \theta \) in the x-y plane. */
+    private final double theta;
+
+    /** Polar angle \( \varphi \). */
+    private final double phi;
+
+    /** Corresponding 3D normalized vector. */
+    private final Vector3D vector;
+
+    /** Simple constructor.
+     * Build a vector from its spherical coordinates
+     * @param theta azimuthal angle \( \theta \) in the x-y plane
+     * @param phi polar angle \( \varphi \)
+     * @see #getTheta()
+     * @see #getPhi()
+     * @exception OutOfRangeException if \( \varphi \) is not in the [\( 0; \pi \)] range
+     */
+    public S2Point(final double theta, final double phi)
+        throws OutOfRangeException {
+        this(theta, phi, vector(theta, phi));
+    }
+
+    /** Simple constructor.
+     * Build a vector from its underlying 3D vector
+     * @param vector 3D vector
+     * @exception MathArithmeticException if vector norm is zero
+     */
+    public S2Point(final Vector3D vector) throws MathArithmeticException {
+        this(FastMath.atan2(vector.getY(), vector.getX()), Vector3D.angle(Vector3D.PLUS_K, vector),
+             vector.normalize());
+    }
+
+    /** Build a point from its internal components.
+     * @param theta azimuthal angle \( \theta \) in the x-y plane
+     * @param phi polar angle \( \varphi \)
+     * @param vector corresponding vector
+     */
+    private S2Point(final double theta, final double phi, final Vector3D vector) {
+        this.theta  = theta;
+        this.phi    = phi;
+        this.vector = vector;
+    }
+
+    /** Build the normalized vector corresponding to spherical coordinates.
+     * @param theta azimuthal angle \( \theta \) in the x-y plane
+     * @param phi polar angle \( \varphi \)
+     * @return normalized vector
+     * @exception OutOfRangeException if \( \varphi \) is not in the [\( 0; \pi \)] range
+     */
+    private static Vector3D vector(final double theta, final double phi)
+       throws OutOfRangeException {
+
+        if (phi < 0 || phi > FastMath.PI) {
+            throw new OutOfRangeException(phi, 0, FastMath.PI);
+        }
+
+        final double cosTheta = FastMath.cos(theta);
+        final double sinTheta = FastMath.sin(theta);
+        final double cosPhi   = FastMath.cos(phi);
+        final double sinPhi   = FastMath.sin(phi);
+
+        return new Vector3D(cosTheta * sinPhi, sinTheta * sinPhi, cosPhi);
+
+    }
+
+    /** Get the azimuthal angle \( \theta \) in the x-y plane.
+     * @return azimuthal angle \( \theta \) in the x-y plane
+     * @see #S2Point(double, double)
+     */
+    public double getTheta() {
+        return theta;
+    }
+
+    /** Get the polar angle \( \varphi \).
+     * @return polar angle \( \varphi \)
+     * @see #S2Point(double, double)
+     */
+    public double getPhi() {
+        return phi;
+    }
+
+    /** Get the corresponding normalized vector in the 3D euclidean space.
+     * @return normalized vector
+     */
+    public Vector3D getVector() {
+        return vector;
+    }
+
+    /** {@inheritDoc} */
+    public Space getSpace() {
+        return Sphere2D.getInstance();
+    }
+
+    /** {@inheritDoc} */
+    public boolean isNaN() {
+        return Double.isNaN(theta) || Double.isNaN(phi);
+    }
+
+    /** Compute the distance (angular separation) between two points.
+     * @param p1 first vector
+     * @param p2 second vector
+     * @return the angular separation between p1 and p2
+     */
+    public static double distance(S2Point p1, S2Point p2) {
+        return Vector3D.angle(p1.vector, p2.vector);
+    }
+
+    /**
+     * Test for the equality of two points on the 2-sphere.
+     * <p>
+     * If all coordinates of two points are exactly the same, and none are
+     * <code>Double.NaN</code>, the two points are considered to be equal.
+     * </p>
+     * <p>
+     * <code>NaN</code> coordinates are considered to affect globally the vector
+     * and be equals to each other - i.e, if either (or all) coordinates of the
+     * 2D vector are equal to <code>Double.NaN</code>, the 2D vector is equal to
+     * {@link #NaN}.
+     * </p>
+     *
+     * @param other Object to test for equality to this
+     * @return true if two points on the 2-sphere objects are equal, false if
+     *         object is null, not an instance of S2Point, or
+     *         not equal to this S2Point instance
+     *
+     */
+    @Override
+    public boolean equals(Object other) {
+
+        if (this == other) {
+            return true;
+        }
+
+        if (other instanceof S2Point) {
+            final S2Point rhs = (S2Point) other;
+            if (rhs.isNaN()) {
+                return this.isNaN();
+            }
+
+            return (theta == rhs.theta) && (phi == rhs.phi);
+        }
+        return false;
+    }
+
+    /**
+     * Get a hashCode for the 2D vector.
+     * <p>
+     * All NaN values have the same hash code.</p>
+     *
+     * @return a hash code value for this object
+     */
+    @Override
+    public int hashCode() {
+        if (isNaN()) {
+            return 542;
+        }
+        return 134 * (37 * MathUtils.hash(theta) +  MathUtils.hash(phi));
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/S2Point.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/S2Point.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Sphere2D.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Sphere2D.java?rev=1554648&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Sphere2D.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Sphere2D.java Wed Jan  1 17:24:37 2014
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math3.geometry.spherical.twod;
+
+import java.io.Serializable;
+
+import org.apache.commons.math3.geometry.Space;
+import org.apache.commons.math3.geometry.spherical.oned.Sphere1D;
+
+/**
+ * This class implements a two-dimensional sphere (i.e. the regular sphere).
+ * <p>
+ * We use here the topologists definition of the 2-sphere (see
+ * <a href="http://mathworld.wolfram.com/Sphere.html">Sphere</a> on
+ * MathWorld), i.e. the 2-sphere is the two-dimensional surface
+ * defined in 3D as x<sup>2</sup>+y<sup>2</sup>+z<sup>2</sup>=1.
+ * </p>
+ * @version $Id$
+ * @since 3.3
+ */
+public class Sphere2D implements Serializable, Space {
+
+    /** Serializable version identifier. */
+    private static final long serialVersionUID = 20131218L;
+
+    /** Private constructor for the singleton.
+     */
+    private Sphere2D() {
+    }
+
+    /** Get the unique instance.
+     * @return the unique instance
+     */
+    public static Sphere2D getInstance() {
+        return LazyHolder.INSTANCE;
+    }
+
+    /** {@inheritDoc} */
+    public int getDimension() {
+        return 2;
+    }
+
+    /** {@inheritDoc} */
+    public Sphere1D getSubSpace() {
+        return Sphere1D.getInstance();
+    }
+
+    // CHECKSTYLE: stop HideUtilityClassConstructor
+    /** Holder for the instance.
+     * <p>We use here the Initialization On Demand Holder Idiom.</p>
+     */
+    private static class LazyHolder {
+        /** Cached field instance. */
+        private static final Sphere2D INSTANCE = new Sphere2D();
+    }
+    // CHECKSTYLE: resume HideUtilityClassConstructor
+
+    /** Handle deserialization of the singleton.
+     * @return the singleton instance
+     */
+    private Object readResolve() {
+        // return the singleton instance
+        return LazyHolder.INSTANCE;
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Sphere2D.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Sphere2D.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/SubCircle.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/SubCircle.java?rev=1554648&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/SubCircle.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/SubCircle.java Wed Jan  1 17:24:37 2014
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.math3.geometry.spherical.twod;
+
+import org.apache.commons.math3.geometry.partitioning.AbstractSubHyperplane;
+import org.apache.commons.math3.geometry.partitioning.BSPTree;
+import org.apache.commons.math3.geometry.partitioning.Hyperplane;
+import org.apache.commons.math3.geometry.partitioning.Region;
+import org.apache.commons.math3.geometry.partitioning.Side;
+import org.apache.commons.math3.geometry.partitioning.SubHyperplane;
+import org.apache.commons.math3.geometry.spherical.oned.Chord;
+import org.apache.commons.math3.geometry.spherical.oned.ArcsSet;
+import org.apache.commons.math3.geometry.spherical.oned.S1Point;
+import org.apache.commons.math3.geometry.spherical.oned.Sphere1D;
+import org.apache.commons.math3.util.FastMath;
+
+/** This class represents a sub-hyperplane for {@link Circle}.
+ * @version $Id$
+ * @since 3.3
+ */
+public class SubCircle extends AbstractSubHyperplane<Sphere2D, Sphere1D> {
+
+    /** Simple constructor.
+     * @param hyperplane underlying hyperplane
+     * @param remainingRegion remaining region of the hyperplane
+     */
+    public SubCircle(final Hyperplane<Sphere2D> hyperplane,
+                     final Region<Sphere1D> remainingRegion) {
+        super(hyperplane, remainingRegion);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected AbstractSubHyperplane<Sphere2D, Sphere1D> buildNew(final Hyperplane<Sphere2D> hyperplane,
+                                                                 final Region<Sphere1D> remainingRegion) {
+        return new SubCircle(hyperplane, remainingRegion);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Side side(final Hyperplane<Sphere2D> hyperplane) {
+
+        final Circle    thisCircle  = (Circle) getHyperplane();
+        final Circle    otherCircle = (Circle) hyperplane;
+        final S2Point[] crossings   = thisCircle.intersection(otherCircle);
+
+        if (crossings == null) {
+            // the circles are disjoint
+            final double global = otherCircle.getOffset(thisCircle.getPointAt(0.0));
+            return (global < -1.0e-10) ? Side.MINUS : ((global > 1.0e-10) ? Side.PLUS : Side.HYPER);
+        }
+
+        // the circles do intersect
+        final boolean direct = FastMath.sin(thisCircle.getAngle() - otherCircle.getAngle()) < 0;
+        final S1Point x = thisCircle.toSubSpace(crossings);
+        return getRemainingRegion().side(new Chord(x, direct));
+
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public SplitSubHyperplane<Sphere2D> split(final Hyperplane<Sphere2D> hyperplane) {
+
+        final Circle    thisCircle  = (Circle) getHyperplane();
+        final Circle    otherCircle = (Circle) hyperplane;
+        final S2Point[] crossings   = thisCircle.intersection(otherCircle);
+
+        if (crossings == null) {
+            // the circles are disjoint
+            final double global = otherCircle.getOffset(thisCircle.getPointAt(0.0));
+            return (global < -1.0e-10) ?
+                   new SplitSubHyperplane<Sphere2D>(null, this) :
+                   new SplitSubHyperplane<Sphere2D>(this, null);
+        }
+
+        // the circles do intersect
+        final boolean direct = FastMath.sin(thisCircle.getAngle() - otherCircle.getAngle()) < 0;
+        final S1Point x      = thisCircle.toSubSpace(crossings);
+        final SubHyperplane<Sphere1D> subPlus  = new Chord(x, !direct).wholeHyperplane();
+        final SubHyperplane<Sphere1D> subMinus = new Chord(x,  direct).wholeHyperplane();
+
+        final BSPTree<Sphere1D> splitTree = getRemainingRegion().getTree(false).split(subMinus);
+        final BSPTree<Sphere1D> plusTree  = getRemainingRegion().isEmpty(splitTree.getPlus()) ?
+                                               new BSPTree<Sphere1D>(Boolean.FALSE) :
+                                               new BSPTree<Sphere1D>(subPlus, new BSPTree<Sphere1D>(Boolean.FALSE),
+                                                                        splitTree.getPlus(), null);
+        final BSPTree<Sphere1D> minusTree = getRemainingRegion().isEmpty(splitTree.getMinus()) ?
+                                               new BSPTree<Sphere1D>(Boolean.FALSE) :
+                                               new BSPTree<Sphere1D>(subMinus, new BSPTree<Sphere1D>(Boolean.FALSE),
+                                                                        splitTree.getMinus(), null);
+
+        return new SplitSubHyperplane<Sphere2D>(new SubCircle(thisCircle.copySelf(), new ArcsSet(plusTree)),
+                                                new SubCircle(thisCircle.copySelf(), new ArcsSet(minusTree)));
+
+    }
+
+}

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/SubCircle.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/SubCircle.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/package-info.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/package-info.java?rev=1554648&view=auto
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/package-info.java (added)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/package-info.java Wed Jan  1 17:24:37 2014
@@ -0,0 +1,30 @@
+/*
+ * 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 provides basic geometry components on the 2-sphere.
+ * </p>
+ * <p>
+ * We use here the topologists definition of the 2-sphere (see
+ * <a href="http://mathworld.wolfram.com/Sphere.html">Sphere</a> on
+ * MathWorld), i.e. the 2-sphere is the two-dimensional surface
+ * defined in 3D as x<sup>2</sup>+y<sup>2</sup>+z<sup>2</sup>=1.
+ * </p>
+ *
+ */
+package org.apache.commons.math3.geometry.spherical.twod;

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/twod/package-info.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"