From 07005515ee97787394311c2e35d72e52ad82280a Mon Sep 17 00:00:00 2001
From: SeH <1s1e1h1@gmail.com>
Date: Sun, 14 Jun 2015 18:41:13 -0400
Subject: [PATCH] octmap refactoring

---
 .../spangraph/spacetime/EarthMap.java         | 13 +++
 .../syncleus/spangraph/spacetime/OctBox.java  | 44 ++++++---
 .../syncleus/spangraph/spacetime/OctMap.java  | 23 ++---
 .../spangraph/spacetime/OctMapGraph.java      | 34 +++++++
 .../syncleus/spangraph/spacetime/OctSet.java  | 99 +++++++++++++++++++
 .../spangraph/spacetime/PlanetMap.java        | 15 +++
 src/main/java/toxi/geom/AABB.java             |  2 +-
 src/main/java/toxi/geom/BezierCurve3D.java    |  2 +-
 src/main/java/toxi/geom/Line3D.java           |  8 +-
 src/main/java/toxi/geom/Plane.java            |  2 +-
 src/main/java/toxi/geom/PointCloud3D.java     |  4 +-
 src/main/java/toxi/geom/PointOctree.java      |  4 +-
 src/main/java/toxi/geom/Ray3D.java            |  2 +-
 .../toxi/geom/SphereIntersectorReflector.java |  4 +-
 src/main/java/toxi/geom/Triangle3D.java       |  8 +-
 src/main/java/toxi/geom/Vec3D.java            | 10 +-
 src/main/java/toxi/geom/XYZ.java              |  4 +-
 .../java/toxi/geom/nurbs/NurbsCreator.java    |  8 +-
 src/main/java/toxi/geom/roVec3D.java          |  8 +-
 .../syncleus/spangraph/geom/OctMapTest.java   |  4 +-
 .../syncleus/spangraph/geom/OctreeTest.java   | 24 ++---
 21 files changed, 249 insertions(+), 73 deletions(-)
 create mode 100644 src/main/java/com/syncleus/spangraph/spacetime/EarthMap.java
 create mode 100644 src/main/java/com/syncleus/spangraph/spacetime/OctMapGraph.java
 create mode 100644 src/main/java/com/syncleus/spangraph/spacetime/OctSet.java
 create mode 100644 src/main/java/com/syncleus/spangraph/spacetime/PlanetMap.java

diff --git a/src/main/java/com/syncleus/spangraph/spacetime/EarthMap.java b/src/main/java/com/syncleus/spangraph/spacetime/EarthMap.java
new file mode 100644
index 0000000..5f04fbc
--- /dev/null
+++ b/src/main/java/com/syncleus/spangraph/spacetime/EarthMap.java
@@ -0,0 +1,13 @@
+package com.syncleus.spangraph.spacetime;
+
+import com.syncleus.spangraph.InfiniPeer;
+import toxi.geom.Vec3D;
+import toxi.geom.XYZ;
+
+/**
+ * PlanetMap preconfigured for Earth's known dimensions and irregular sphericity */
+public class EarthMap<K extends XYZ, V> extends PlanetMap<K,V> {
+    public EarthMap(InfiniPeer p, String id, Vec3D center, Vec3D radius, Vec3D resolution) {
+        super(p, id, center, radius, resolution);
+    }
+}
diff --git a/src/main/java/com/syncleus/spangraph/spacetime/OctBox.java b/src/main/java/com/syncleus/spangraph/spacetime/OctBox.java
index 515f8bd..71127f5 100644
--- a/src/main/java/com/syncleus/spangraph/spacetime/OctBox.java
+++ b/src/main/java/com/syncleus/spangraph/spacetime/OctBox.java
@@ -36,7 +36,7 @@ public class OctBox<V extends XYZ> extends BB implements Shape3D {
      *            half length of the tree volume along a single axis
      */
     private OctBox(OctBox p, Vec3D o, Vec3D halfSize) {
-        super(o.add(halfSize), new Vec3D(halfSize));
+        super(o.plus(halfSize), new Vec3D(halfSize));
         this.parent = p;
         if (parent != null) {
             resolution = parent.resolution;
@@ -71,14 +71,15 @@ public class OctBox<V extends XYZ> extends BB implements Shape3D {
      *            point collection
      * @return how many points were added
      */
-    public int put(final Collection<? extends V> points) {
+    public int putAll(final Collection<? extends V> points) {
         int count = 0;
         for (final V p : points) {
-            if (put(p)) count++;
+            if (ADD(p)!=null) count++;
         }
         return count;
     }
 
+    //TODO memoize this result in a special leaf subclass
     public boolean belowResolution() {
         return extent.x() <= resolution.x ||
                 extent.y() <= resolution.y ||
@@ -90,9 +91,9 @@ public class OctBox<V extends XYZ> extends BB implements Shape3D {
      * instantiation for all intermediate tree levels.
      *
      * @param p
-     * @return true, if point has been added successfully
+     * @return the box it was inserted to, or null if wasn't
      */
-    public boolean put(final V p) {
+    public OctBox<V> ADD(final V p) {
 
 
         // check if point is inside cube
@@ -103,7 +104,7 @@ public class OctBox<V extends XYZ> extends BB implements Shape3D {
                     points = newPointsCollection();
                 }
                 points.add(p);
-                return true;
+                return this;
             } else {
                 if (children == null) {
                     children = new OctBox[8];
@@ -117,10 +118,10 @@ public class OctBox<V extends XYZ> extends BB implements Shape3D {
                     children[octant] = new OctBox(this, off,
                             extent.scale(0.5f));
                 }
-                return children[octant].put(p);
+                return children[octant].ADD(p);
             }
         }
-        return false;
+        return null;
     }
 
     protected Collection<V> newPointsCollection() {
@@ -143,14 +144,16 @@ public class OctBox<V extends XYZ> extends BB implements Shape3D {
         }
     }
 
+
+
     public boolean containsPoint(XYZ p) {
         return p.isInAABB(this);
     }
 
-    public OctBox clear() {
+    public void clear() {
+        zero();
         children = null;
         points = null;
-        return this;
     }
 
     /**
@@ -323,6 +326,12 @@ public class OctBox<V extends XYZ> extends BB implements Shape3D {
             }
         }
     }
+
+    public void forEachNeighbor(V item, XYZ boxRadius, Consumer<OctBox> visitor) {
+        //SOON
+        throw new UnsupportedOperationException();
+    }
+
     public void forEachInSphere(Sphere s, Consumer<XYZ> c) {
 
         if (this.intersectsSphere(s)) {
@@ -342,6 +351,8 @@ public class OctBox<V extends XYZ> extends BB implements Shape3D {
             }
         }
     }
+
+
     /**
      * Selects all stored points within the given sphere volume
      *
@@ -413,12 +424,11 @@ public class OctBox<V extends XYZ> extends BB implements Shape3D {
      * Removes a point from the tree and (optionally) tries to release memory by
      * reducing now empty sub-branches.
      *
-     * @param p
-     *            point to delete
      * @return true, if the point was found & removed
      */
-    public boolean remove(V p) {
+    public boolean remove(Object _p) {
         boolean found = false;
+        V p = (V)_p;
         OctBox leaf = getLeafForPoint(p);
         if (leaf != null) {
             if (leaf.points.remove(p)) {
@@ -431,10 +441,12 @@ public class OctBox<V extends XYZ> extends BB implements Shape3D {
         return found;
     }
 
-    public void removeAll(Collection<V> points) {
-        for (V p : points) {
-            remove(p);
+    public boolean removeAll(Collection<?> points) {
+        boolean allRemoved = true;
+        for (Object p : points) {
+            allRemoved &= remove(p);
         }
+        return allRemoved;
     }
 
     /*
diff --git a/src/main/java/com/syncleus/spangraph/spacetime/OctMap.java b/src/main/java/com/syncleus/spangraph/spacetime/OctMap.java
index 5c2fd3e..ef7f0cc 100644
--- a/src/main/java/com/syncleus/spangraph/spacetime/OctMap.java
+++ b/src/main/java/com/syncleus/spangraph/spacetime/OctMap.java
@@ -11,15 +11,16 @@ import java.util.Map;
 import java.util.Set;
 import java.util.logging.Logger;
 
-public class OctMap<K, V extends XYZ> implements Map<K,V> {
+/** TODO extract infinispan to subclass allowing any Map impl for index */
+public class OctMap<K extends XYZ, V> implements Map<K,V> {
 
     private final Logger logger;
 
     /** holder for _oct for infinispan persistence */
-    protected final Cache<Long, OctBox<V>> _oct;
+    protected final Cache<Long, OctBox<K>> _oct;
 
     protected final Cache<K, V> map;
-    protected final OctBox<V> box;
+    protected final OctBox<K> box;
 
     boolean startupCheck = true;
 
@@ -84,14 +85,14 @@ public class OctMap<K, V extends XYZ> implements Map<K,V> {
         if (removed!=null) {
             octRemove(key, removed);
         }
-        if (!box.put(value)) {
+        if (box.ADD(key)==null) {
             throw new RuntimeException("Octree rejected value=" + value + ", key=" + key );
         }
         return removed;
     }
 
-    private void octRemove(Object key, V v) {
-        if (!box.remove(v)) {
+    private void octRemove(K key, V v) {
+        if (!box.remove(key)) {
             throw new RuntimeException("Octree inconsistency detected on removal key=" + key + ", value=" + v);
         }
     }
@@ -100,7 +101,7 @@ public class OctMap<K, V extends XYZ> implements Map<K,V> {
     public V remove(Object key) {
         V v = map.remove(key);
         if (v!=null) {
-            octRemove(key, v);
+            octRemove((K)key, v);
         }
         return v;
     }
@@ -108,13 +109,13 @@ public class OctMap<K, V extends XYZ> implements Map<K,V> {
     @Override
     public void putAll(Map<? extends K, ? extends V> m) {
         map.putAll(m);
-        box.put(m.values());
+        box.putAll(m.keySet());
     }
 
     @Override
     public void clear() {
         map.clear();
-        box.clear();
+        box.zero();
     }
 
     @Override
@@ -134,8 +135,8 @@ public class OctMap<K, V extends XYZ> implements Map<K,V> {
 
     public void reindex() {
         logger.info("re-indexing " + map.size() + " items");
-        box.clear();
-        box.put(map.values());
+        box.zero();
+        box.putAll(map.keySet());
 
         validate();
     }
diff --git a/src/main/java/com/syncleus/spangraph/spacetime/OctMapGraph.java b/src/main/java/com/syncleus/spangraph/spacetime/OctMapGraph.java
new file mode 100644
index 0000000..bb66167
--- /dev/null
+++ b/src/main/java/com/syncleus/spangraph/spacetime/OctMapGraph.java
@@ -0,0 +1,34 @@
+package com.syncleus.spangraph.spacetime;
+
+import com.syncleus.spangraph.MapGraph;
+import com.tinkerpop.blueprints.Edge;
+import com.tinkerpop.blueprints.Vertex;
+import toxi.geom.XYZ;
+
+/**
+ * OctMapped indexes vertices in a Graph
+ */
+abstract public class OctMapGraph<X extends XYZ> extends MapGraph<X> {
+
+    public interface DistanceFunction3 {
+
+        public float get(XYZ a, XYZ b);
+
+
+        /** allows an implementation to use early termination when
+         * exceeding a minimum value than completely calculating the result
+         */
+        default public boolean lessThan(XYZ a, XYZ b, float minimum) {
+            return get(a, b) < minimum;
+        }
+
+    }
+
+    abstract protected OctMap<X, Edge> newEdgeMap();
+
+    abstract protected OctMap<X, Vertex> newVertexMap();
+
+
+
+
+}
diff --git a/src/main/java/com/syncleus/spangraph/spacetime/OctSet.java b/src/main/java/com/syncleus/spangraph/spacetime/OctSet.java
new file mode 100644
index 0000000..7aeb694
--- /dev/null
+++ b/src/main/java/com/syncleus/spangraph/spacetime/OctSet.java
@@ -0,0 +1,99 @@
+package com.syncleus.spangraph.spacetime;
+
+import toxi.geom.Vec3D;
+import toxi.geom.XYZ;
+
+import java.util.*;
+
+
+public class OctSet<V extends XYZ> extends OctBox<V> implements Set<V> {
+
+
+    final Map<V, OctBox<V>> data = new HashMap();
+
+    public OctSet(Vec3D o, Vec3D extents, Vec3D resolution) {
+        super(o, extents, resolution);
+    }
+
+    @Override
+    public OctBox<V> ADD(V p) {
+        OctBox<V> target = super.ADD(p);
+        if (target!=null) {
+            data.put(p, target);
+            return target;
+        }
+        return null;
+    }
+
+    @Override
+    public boolean remove(Object p) {
+        //TODO use the value in data for fast access
+        if (data.remove(p)!=null) {
+            super.remove(p);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public int size() {
+        return data.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return data.isEmpty();
+    }
+
+    @Override
+    public boolean contains(Object o) {
+        return data.containsKey(o);
+    }
+
+    @Override
+    public Iterator<V> iterator() {
+        return data.keySet().iterator();
+    }
+
+    @Override
+    public Object[] toArray() {
+        return data.keySet().toArray();
+    }
+
+    @Override
+    public <T> T[] toArray(T[] a) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean add(V v) {
+        if (ADD(v)!=null) {
+            return true;
+        }
+        return false;
+    }
+
+
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
+        return data.keySet().containsAll(c);
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends V> c) {
+        return putAll(c) == c.size();
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
+        //SOON
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> points) {
+        //SOON
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/src/main/java/com/syncleus/spangraph/spacetime/PlanetMap.java b/src/main/java/com/syncleus/spangraph/spacetime/PlanetMap.java
new file mode 100644
index 0000000..7d718c1
--- /dev/null
+++ b/src/main/java/com/syncleus/spangraph/spacetime/PlanetMap.java
@@ -0,0 +1,15 @@
+package com.syncleus.spangraph.spacetime;
+
+import com.syncleus.spangraph.InfiniPeer;
+import toxi.geom.Vec3D;
+import toxi.geom.XYZ;
+
+/**
+ * OctMap with special handling for planetary coordinates and spheroid geometry.
+ * 1st dimensions is Latitude, 2nd dimension is Longitude, 3rd dimension is time */
+public class PlanetMap<K extends XYZ, V> extends OctMap<K,V> {
+
+    public PlanetMap(InfiniPeer p, String id, Vec3D center, Vec3D radius, Vec3D resolution) {
+        super(p, id, center, radius, resolution);
+    }
+}
diff --git a/src/main/java/toxi/geom/AABB.java b/src/main/java/toxi/geom/AABB.java
index 4e75248..9ea5cea 100644
--- a/src/main/java/toxi/geom/AABB.java
+++ b/src/main/java/toxi/geom/AABB.java
@@ -459,7 +459,7 @@ public class AABB extends BB implements Shape3D {
         // this is check is necessary for the constructor
         if (extent != null) {
             this.min = this.sub(extent);
-            this.max = this.add(extent);
+            this.max = this.plus(extent);
         }
         return this;
     }
diff --git a/src/main/java/toxi/geom/BezierCurve3D.java b/src/main/java/toxi/geom/BezierCurve3D.java
index 409ab64..fe43171 100644
--- a/src/main/java/toxi/geom/BezierCurve3D.java
+++ b/src/main/java/toxi/geom/BezierCurve3D.java
@@ -67,7 +67,7 @@ public class BezierCurve3D {
             Vec3D de = e.sub(d);
             Vec3D cd2 = cd.interpolateTo(de, 0.5f);
             c.set(d.sub(cd2));
-            e.set(d.add(de.interpolateToSelf(cd, 0.5f)));
+            e.set(d.plus(de.interpolateToSelf(cd, 0.5f)));
         } else {
             throw new IllegalArgumentException("invalid point index");
         }
diff --git a/src/main/java/toxi/geom/Line3D.java b/src/main/java/toxi/geom/Line3D.java
index 49e3734..38a2de9 100644
--- a/src/main/java/toxi/geom/Line3D.java
+++ b/src/main/java/toxi/geom/Line3D.java
@@ -189,8 +189,8 @@ public class Line3D {
         float mua = (float) (numer / denom);
         float mub = (float) ((d1343 + d4321 * mua) / d4343);
 
-        Vec3D pa = a.add(p21.scaleSelf(mua));
-        Vec3D pb = l.a.add(p43.scaleSelf(mub));
+        Vec3D pa = a.plus(p21.scaleSelf(mua));
+        Vec3D pb = l.a.plus(p43.scaleSelf(mub));
         return new LineIntersection(Type.INTERSECTING, new Line3D(pa, pb), mua,
                 mub);
     }
@@ -212,7 +212,7 @@ public class Line3D {
             return b.copy();
         }
         // Return the point between 'a' and 'b'
-        return a.add(v.scaleSelf(t));
+        return a.plus(v.scaleSelf(t));
     }
 
     public Line3D copy() {
@@ -258,7 +258,7 @@ public class Line3D {
     }
 
     public Vec3D getMidPoint() {
-        return a.add(b).scaleSelf(0.5f);
+        return a.plus(b).scaleSelf(0.5f);
     }
 
     public XYZ getNormal() {
diff --git a/src/main/java/toxi/geom/Plane.java b/src/main/java/toxi/geom/Plane.java
index dae1260..b77c033 100644
--- a/src/main/java/toxi/geom/Plane.java
+++ b/src/main/java/toxi/geom/Plane.java
@@ -103,7 +103,7 @@ public class Plane extends Vec3D implements Shape3D {
     public float getDistanceToPoint(Vec3D p) {
         float sn = -normal.dot(p.sub(this));
         float sd = normal.magSquared();
-        Vec3D isec = p.add(normal.scale(sn / sd));
+        Vec3D isec = p.plus(normal.scale(sn / sd));
         return isec.distanceTo(p);
     }
 
diff --git a/src/main/java/toxi/geom/PointCloud3D.java b/src/main/java/toxi/geom/PointCloud3D.java
index 376a5c3..21ee593 100644
--- a/src/main/java/toxi/geom/PointCloud3D.java
+++ b/src/main/java/toxi/geom/PointCloud3D.java
@@ -62,7 +62,7 @@ public class PointCloud3D implements Iterable<Vec3D> {
         points.add(p);
         min.minSelf(p);
         max.maxSelf(p);
-        centroid.set(min.add(max).scaleSelf(0.5f));
+        centroid.set(min.plus(max).scaleSelf(0.5f));
         radiusSquared = MathUtils.max(radiusSquared,
                 p.distanceToSquared(centroid));
         return this;
@@ -194,7 +194,7 @@ public class PointCloud3D implements Iterable<Vec3D> {
             min.minSelf(p);
             max.maxSelf(p);
         }
-        centroid.set(min.add(max).scaleSelf(0.5f));
+        centroid.set(min.plus(max).scaleSelf(0.5f));
         radiusSquared = 0;
         for (roVec3D p : points) {
             radiusSquared = MathUtils.max(radiusSquared,
diff --git a/src/main/java/toxi/geom/PointOctree.java b/src/main/java/toxi/geom/PointOctree.java
index 675162a..e9f5593 100644
--- a/src/main/java/toxi/geom/PointOctree.java
+++ b/src/main/java/toxi/geom/PointOctree.java
@@ -78,7 +78,7 @@ public class PointOctree extends AABB implements Shape3D {
      *            half length of the tree volume along a single axis
      */
     private PointOctree(PointOctree p, Vec3D o, float halfSize) {
-        super(o.add(halfSize, halfSize, halfSize), new Vec3D(halfSize,
+        super(o.plus(halfSize, halfSize, halfSize), new Vec3D(halfSize,
                 halfSize, halfSize));
 
         this.parent = p;
@@ -146,7 +146,7 @@ public class PointOctree extends AABB implements Shape3D {
                 }
                 int octant = getOctantID(plocal);
                 if (children[octant] == null) {
-                    Vec3D off = offset.add(new Vec3D(
+                    Vec3D off = offset.plus(new Vec3D(
                             (octant & 1) != 0 ? halfSize : 0,
                             (octant & 2) != 0 ? halfSize : 0,
                             (octant & 4) != 0 ? halfSize : 0));
diff --git a/src/main/java/toxi/geom/Ray3D.java b/src/main/java/toxi/geom/Ray3D.java
index fadef96..d6c3e0f 100644
--- a/src/main/java/toxi/geom/Ray3D.java
+++ b/src/main/java/toxi/geom/Ray3D.java
@@ -83,7 +83,7 @@ public class Ray3D extends Vec3D {
      * @return vector
      */
     public Vec3D getPointAtDistance(float dist) {
-        return add(dir.scale(dist));
+        return plus(dir.scale(dist));
     }
 
     /**
diff --git a/src/main/java/toxi/geom/SphereIntersectorReflector.java b/src/main/java/toxi/geom/SphereIntersectorReflector.java
index caad360..813e270 100644
--- a/src/main/java/toxi/geom/SphereIntersectorReflector.java
+++ b/src/main/java/toxi/geom/SphereIntersectorReflector.java
@@ -57,7 +57,7 @@ public class SphereIntersectorReflector implements Intersector3D, Reflector3D {
      */
     public roVec3D getReflectedRayPointAtDistance(float dist) {
         if (reflectedDir != null) {
-            return isectData.pos.add(reflectedDir.scale(dist));
+            return isectData.pos.plus(reflectedDir.scale(dist));
         } else {
             return null;
         }
@@ -109,7 +109,7 @@ public class SphereIntersectorReflector implements Intersector3D, Reflector3D {
         isectData.isIntersection = isectData.dist >= 0;
         if (isectData.isIntersection) {
             // get the intersection point
-            isectData.pos = ray.add(ray.getDirection().scale(isectData.dist));
+            isectData.pos = ray.plus(ray.getDirection().scale(isectData.dist));
             // calculate the direction from our point to the intersection pos
             isectData.dir = isectData.pos.sub(ray);
             isectData.normal = sphere.tangentPlaneNormalAt(isectData.pos);
diff --git a/src/main/java/toxi/geom/Triangle3D.java b/src/main/java/toxi/geom/Triangle3D.java
index 162d21c..95f7d5a 100644
--- a/src/main/java/toxi/geom/Triangle3D.java
+++ b/src/main/java/toxi/geom/Triangle3D.java
@@ -135,7 +135,7 @@ public class Triangle3D implements Shape3D {
         // return projection of P onto AB
         if (vc <= 0.0f && snom >= 0.0f && sdenom >= 0.0f) {
             // return a + snom / (snom + sdenom) * ab;
-            return a.add(ab.scaleSelf(snom / (snom + sdenom)));
+            return a.plus(ab.scaleSelf(snom / (snom + sdenom)));
         }
 
         // P is outside (or on) BC if the triple scalar product [N PB PC] <= 0
@@ -144,7 +144,7 @@ public class Triangle3D implements Shape3D {
         // return projection of P onto BC
         if (va <= 0.0f && unom >= 0.0f && udenom >= 0.0f) {
             // return b + unom / (unom + udenom) * bc;
-            return b.add(bc.scaleSelf(unom / (unom + udenom)));
+            return b.plus(bc.scaleSelf(unom / (unom + udenom)));
         }
 
         // P is outside (or on) CA if the triple scalar product [N PC PA] <= 0
@@ -153,7 +153,7 @@ public class Triangle3D implements Shape3D {
         // return projection of P onto CA
         if (vb <= 0.0f && tnom >= 0.0f && tdenom >= 0.0f) {
             // return a + tnom / (tnom + tdenom) * ac;
-            return a.add(ac.scaleSelf(tnom / (tnom + tdenom)));
+            return a.plus(ac.scaleSelf(tnom / (tnom + tdenom)));
         }
 
         // P must project inside face region. Compute Q using barycentric
@@ -166,7 +166,7 @@ public class Triangle3D implements Shape3D {
     }
 
     public Vec3D computeCentroid() {
-        centroid = a.add(b).addSelf(c).scaleSelf(1f / 3);
+        centroid = a.plus(b).addSelf(c).scaleSelf(1f / 3);
         return centroid;
     }
 
diff --git a/src/main/java/toxi/geom/Vec3D.java b/src/main/java/toxi/geom/Vec3D.java
index ed9af6e..18e7c69 100644
--- a/src/main/java/toxi/geom/Vec3D.java
+++ b/src/main/java/toxi/geom/Vec3D.java
@@ -257,15 +257,15 @@ public class Vec3D implements Comparable<roVec3D>, roVec3D, Serializable {
         return this;
     }
 
-    public final Vec3D add(float a, float b, float c) {
+    public final Vec3D plus(float a, float b, float c) {
         return new Vec3D(x + a, y + b, z + c);
     }
 
-    public Vec3D add(roVec3D v) {
+    public Vec3D plus(roVec3D v) {
         return new Vec3D(x + v.x(), y + v.y(), z + v.z());
     }
 
-    public final Vec3D add(Vec3D v) {
+    public final Vec3D plus(Vec3D v) {
         return new Vec3D(x + v.x, y + v.y, z + v.z);
     }
 
@@ -329,7 +329,7 @@ public class Vec3D implements Comparable<roVec3D>, roVec3D, Serializable {
      * 
      * @return itself
      */
-    public roVec3D clear() {
+    public roVec3D zero() {
         x = y = z = 0;
         return this;
     }
@@ -1444,7 +1444,7 @@ public class Vec3D implements Comparable<roVec3D>, roVec3D, Serializable {
         return new Vec4D(x, y, z, w);
     }
 
-    public float[] toArray() {
+    public float[] toArray3() {
         return new float[] {
                 x, y, z
         };
diff --git a/src/main/java/toxi/geom/XYZ.java b/src/main/java/toxi/geom/XYZ.java
index 5ade023..c8ddd21 100644
--- a/src/main/java/toxi/geom/XYZ.java
+++ b/src/main/java/toxi/geom/XYZ.java
@@ -2,10 +2,12 @@ package toxi.geom;
 
 import toxi.math.InterpolateStrategy;
 
+import java.io.Serializable;
+
 /**
  * Created by me on 6/13/15.
  */
-public interface XYZ {
+public interface XYZ extends Serializable {
 
     public float x();
 
diff --git a/src/main/java/toxi/geom/nurbs/NurbsCreator.java b/src/main/java/toxi/geom/nurbs/NurbsCreator.java
index c44f092..25963e2 100644
--- a/src/main/java/toxi/geom/nurbs/NurbsCreator.java
+++ b/src/main/java/toxi/geom/nurbs/NurbsCreator.java
@@ -196,7 +196,7 @@ public final class NurbsCreator {
         cp[3] = cp[0].getInvertedXYZ();
         cp[6] = cp[0].copy();
 
-        cp[1] = new Vec4D(o.yAxis.add(o.xAxis).scaleSelf(r), 0.5f);
+        cp[1] = new Vec4D(o.yAxis.plus(o.xAxis).scaleSelf(r), 0.5f);
         cp[4] = cp[1].getInvertedXYZ();
 
         cp[2] = new Vec4D(o.xAxis.getInverted().addSelf(o.yAxis).scaleSelf(r),
@@ -231,7 +231,7 @@ public final class NurbsCreator {
         cp[4] = cp[0].getInvertedXYZ();
         cp[8] = cp[0].copy();
 
-        cp[1] = new Vec4D(o.xAxis.add(o.yAxis).scaleSelf(r), w);
+        cp[1] = new Vec4D(o.xAxis.plus(o.yAxis).scaleSelf(r), w);
         cp[5] = cp[1].getInvertedXYZ();
 
         cp[2] = new Vec4D(o.yAxis.scale(r), 1);
@@ -491,7 +491,7 @@ public final class NurbsCreator {
         cp[3] = cp[0].getInvertedXYZ();
         cp[0].addXYZSelf(o.origin);
         cp[3].addXYZSelf(o.origin);
-        cp[1] = new Vec4D(o.xAxis.add(o.yAxis).scaleSelf(r).addSelf(o.origin),
+        cp[1] = new Vec4D(o.xAxis.plus(o.yAxis).scaleSelf(r).addSelf(o.origin),
                 0.5f);
         cp[2] = new Vec4D(o.xAxis.getInverted().addSelf(o.yAxis).scaleSelf(r)
                 .addSelf(o.origin), 0.5f);
@@ -742,7 +742,7 @@ public final class NurbsCreator {
             Vec3D top, Vec3D out) {
         Vec3D dir = top.sub(p);
         float hyp = dir.magnitude();
-        out.set(p.add(t.scale(t.dot(dir.normalize()) * hyp)));
+        out.set(p.plus(t.scale(t.dot(dir.normalize()) * hyp)));
     }
 
     private static float[][] surfaceMeshParameters(Vec3D points[][], int n,
diff --git a/src/main/java/toxi/geom/roVec3D.java b/src/main/java/toxi/geom/roVec3D.java
index 0bc4352..0af5fb1 100644
--- a/src/main/java/toxi/geom/roVec3D.java
+++ b/src/main/java/toxi/geom/roVec3D.java
@@ -49,9 +49,9 @@ public interface roVec3D extends XYZ {
      * 
      * @return result as new vector
      */
-    public Vec3D add(float a, float b, float c);
+    public Vec3D plus(float a, float b, float c);
 
-    public Vec3D add(roVec3D v);
+    public Vec3D plus(roVec3D v);
 
     /**
      * Add vector v and returns result as new vector.
@@ -61,7 +61,7 @@ public interface roVec3D extends XYZ {
      * 
      * @return result as new vector
      */
-    public Vec3D add(Vec3D v);
+    public Vec3D plus(Vec3D v);
 
     /**
      * Computes the angle between this vector and vector V. This function
@@ -474,7 +474,7 @@ public interface roVec3D extends XYZ {
      */
     public Vec4D to4D(float w);
 
-    public float[] toArray();
+    public float[] toArray3();
 
     public float[] toArray4(float w);
 
diff --git a/src/test/java/com/syncleus/spangraph/geom/OctMapTest.java b/src/test/java/com/syncleus/spangraph/geom/OctMapTest.java
index cb611f3..65366a4 100644
--- a/src/test/java/com/syncleus/spangraph/geom/OctMapTest.java
+++ b/src/test/java/com/syncleus/spangraph/geom/OctMapTest.java
@@ -62,7 +62,7 @@ public class OctMapTest {
     @Test
     public void test1() {
         InfiniPeer p = InfiniPeer.local("i", "/tmp/t", 1024);
-        OctMap<String,Event> o = new OctMap<>(p, "octmap",
+        OctMap<Event,String> o = new OctMap<>(p, "octmap",
                 new Vec3D(-180f,-90f,0f ), /* AD */
                 new Vec3D(180f,90f,2100f ), /* 0AD .. 2100AD */
                 new Vec3D(1f,0.75f,2f)
@@ -77,7 +77,7 @@ public class OctMapTest {
                 new Event("Earth Destroyed", 0, 10f, 2015f)};
 
         for (Event e  : ee) {
-            o.put(e.name, e);
+            o.put(e, "");
         }
 
         System.out.println(o);
diff --git a/src/test/java/com/syncleus/spangraph/geom/OctreeTest.java b/src/test/java/com/syncleus/spangraph/geom/OctreeTest.java
index ba41a6a..b415656 100644
--- a/src/test/java/com/syncleus/spangraph/geom/OctreeTest.java
+++ b/src/test/java/com/syncleus/spangraph/geom/OctreeTest.java
@@ -24,20 +24,20 @@ public class OctreeTest {
 
         assertEquals(0, o.countPointsRecursively());
 
-        boolean b = o.put(new Vec3D(3,3,3));
-        assertTrue(b);
+        OctBox block = o.ADD(new Vec3D(3, 3, 3));
+        assertTrue(block!=null);
         assertEquals(1, o.countPointsRecursively());
 
-        o.put(new Vec3D(0, 1, 0));
-        o.put(new Vec3D(0, 1, 0));
-        o.put(new Vec3D(0, 0, 1));
-        o.put(new Vec3D(0, 0, 1.25f));
-        o.put(new Vec3D(0, 0, 1.5f));
-        o.put(new Vec3D(0, 0, -1));
-        o.put(new Vec3D(0, 0, -1.25f));
-        o.put(new Vec3D(0, 0, -1.50f));
-        o.put(new Vec3D(0, 0, -1.55f));
-        o.put(new Vec3D(0, 0, -1.575f));
+        o.ADD(new Vec3D(0, 1, 0));
+        o.ADD(new Vec3D(0, 1, 0));
+        o.ADD(new Vec3D(0, 0, 1));
+        o.ADD(new Vec3D(0, 0, 1.25f));
+        o.ADD(new Vec3D(0, 0, 1.5f));
+        o.ADD(new Vec3D(0, 0, -1));
+        o.ADD(new Vec3D(0, 0, -1.25f));
+        o.ADD(new Vec3D(0, 0, -1.50f));
+        o.ADD(new Vec3D(0, 0, -1.55f));
+        o.ADD(new Vec3D(0, 0, -1.575f));
 
         o.forEachInBox(x -> {
 
-- 
GitLab