diff --git a/GUI/ba3d/CMakeLists.txt b/GUI/ba3d/CMakeLists.txt
index ad8e2d64b473a390111e0871f60bc9003e161316..8d0ee02bede3596a1fb101a4192b21da2767e1c2 100644
--- a/GUI/ba3d/CMakeLists.txt
+++ b/GUI/ba3d/CMakeLists.txt
@@ -24,5 +24,3 @@ add_subdirectory (demo)
 set(library_name ba3d)
 set(${library_name}_INCLUDE_DIRS ${include_dirs} PARENT_SCOPE)
 set(${library_name}_LIBRARY ${library_name} PARENT_SCOPE)
-
-# eof
diff --git a/GUI/ba3d/ba3d/CMakeLists.txt b/GUI/ba3d/ba3d/CMakeLists.txt
index b8db2d0594bf05fcc199aec0715377ac20914bac..26daacea80769cab7e209b9ef28e4d112dc5e61c 100644
--- a/GUI/ba3d/ba3d/CMakeLists.txt
+++ b/GUI/ba3d/ba3d/CMakeLists.txt
@@ -1,10 +1,16 @@
 get_filename_component (lib ${CMAKE_CURRENT_SOURCE_DIR} NAME)
 
-file (GLOB_RECURSE files *)
-add_library (${lib} STATIC ${files})
+# --- source, include and resource files ---
+file (GLOB_RECURSE source_files *.cpp)
+file (GLOB_RECURSE include_files *.h)
+
+set(resource_files
+    "shaders.qrc"
+    )
+qt5_add_resources(RC_SHADERS ${resource_files})
+
+add_library (${lib} STATIC ${source_files} ${include_files} ${RC_SHADERS})
 
 target_link_libraries (${lib}
   Qt5::Core Qt5::Widgets Qt5::OpenGL
 )
-
-# eof
diff --git a/GUI/ba3d/ba3d/def.cpp b/GUI/ba3d/ba3d/def.cpp
index c3868c00083f6bf3dcaaac7422ac2aa4b7e81392..7e871410a1849e6611e1b6e60bf2c94c2aad0088 100644
--- a/GUI/ba3d/ba3d/def.cpp
+++ b/GUI/ba3d/ba3d/def.cpp
@@ -17,105 +17,94 @@
 static_assert(QT_VERSION >= QT_VERSION_CHECK(5,5,1),
               "requires Qt >= 5.5.1, have " QT_VERSION_STR);
 
-namespace ba3d {
+namespace RealSpace {
 //------------------------------------------------------------------------------
 
-#ifndef NDEBUG
+Vector3D::Vector3D() : Vector3D(0,0,0) {}
 
-flp::flp(flt f_) : f(f_) {
-  EXPECT(0 <= f)
-}
-
-#endif
-
-//------------------------------------------------------------------------------
-
-xyz::xyz() : xyz(0,0,0) {}
-
-xyz::xyz(flt v) : xyz(v,v,v) {}
+Vector3D::Vector3D(float v) : Vector3D(v,v,v) {}
 
-xyz::xyz(flt x_, flt y_, flt z_) : x(x_), y(y_), z(z_) {}
+Vector3D::Vector3D(float x_, float y_, float z_) : x(x_), y(y_), z(z_) {}
 
-xyz::xyz(QVector3D const& v) : xyz(v.x(), v.y(), v.z()) {}
+Vector3D::Vector3D(QVector3D const& v) : Vector3D(v.x(), v.y(), v.z()) {}
 
-flt xyz::length() const {
+float Vector3D::length() const {
   return QVector3D(*this).length();
 }
 
-xyz xyz::normalized() const {
+Vector3D Vector3D::normalized() const {
   return QVector3D(*this).normalized();
 }
 
-xyz xyz::interpolateTo(rc to, flt rat) const {
+Vector3D Vector3D::interpolateTo(const Vector3D& to, float rat) const {
   return *this * (1 - rat) + to * rat;
 }
 
-ba3d::xyz::operator QVector3D() const {
+RealSpace::Vector3D::operator QVector3D() const {
   return QVector3D(x, y, z);
 }
 
-xyz const xyz::_0(0,0,0), xyz::_1(1,1,1),
-          xyz::_x(1,0,0), xyz::_y(0,1,0), xyz::_z(0,0,1);
+Vector3D const Vector3D::_0(0,0,0), Vector3D::_1(1,1,1),
+          Vector3D::_x(1,0,0), Vector3D::_y(0,1,0), Vector3D::_z(0,0,1);
 
-xyz cross(xyz::rc v1, xyz::rc v2) {
+Vector3D cross(const Vector3D& v1, const Vector3D& v2) {
   return QVector3D::crossProduct(v1, v2);
 }
 
-flt dot(xyz::rc v1, xyz::rc v2) {
+float dot(const Vector3D& v1, const Vector3D& v2) {
   return QVector3D::dotProduct(v1, v2);
 }
 
-xyz operator+(xyz::rc v) {
+Vector3D operator+(const Vector3D& v) {
   return v;
 }
 
-xyz operator-(xyz::rc v) {
-  return xyz::_0 - v;
+Vector3D operator-(const Vector3D& v) {
+  return Vector3D::_0 - v;
 }
 
-xyz operator*(xyz::rc v, flt f) {
-  return xyz(v.x*f, v.y*f, v.z*f);
+Vector3D operator*(const Vector3D& v, float f) {
+  return Vector3D(v.x*f, v.y*f, v.z*f);
 }
 
-xyz operator+(xyz::rc _1, xyz::rc _2) {
-  return xyz(_1.x+_2.x, _1.y+_2.y, _1.z+_2.z);
+Vector3D operator+(const Vector3D& _1, const Vector3D& _2) {
+  return Vector3D(_1.x+_2.x, _1.y+_2.y, _1.z+_2.z);
 }
 
-xyz operator-(xyz::rc _1, xyz::rc _2) {
-  return xyz(_1.x-_2.x, _1.y-_2.y, _1.z-_2.z);
+Vector3D operator-(const Vector3D& _1, const Vector3D& _2) {
+  return Vector3D(_1.x-_2.x, _1.y-_2.y, _1.z-_2.z);
 }
 
 //------------------------------------------------------------------------------
 
-dr::dr(flt r1, flt r2) : min(qMin(r1,r2)), max(qMax(r1,r2)) {}
+Range::Range(float r1, float r2) : min(qMin(r1,r2)), max(qMax(r1,r2)) {}
 
-flt dr::size() const {
+float Range::size() const {
   return max - min;
 }
 
-flt dr::mid() const {
+float Range::mid() const {
   return (min + max) / 2;
 }
 
 //------------------------------------------------------------------------------
 
-dxyz::dxyz(dr x_, dr y_, dr z_) : x(x_), y(y_), z(z_) {}
+VectorRange::VectorRange(Range x_, Range y_, Range z_) : x(x_), y(y_), z(z_) {}
 
-dxyz::dxyz(xyz _1, xyz _2)
-: x(dr(_1.x,_2.x)), y(dr(_1.y,_2.y)), z(dr(_1.z,_2.z)) {}
+VectorRange::VectorRange(Vector3D _1, Vector3D _2)
+: x(Range(_1.x,_2.x)), y(Range(_1.y,_2.y)), z(Range(_1.z,_2.z)) {}
 
-xyz dxyz::size() const {
-  return xyz(x.size(), y.size(), z.size());
+Vector3D VectorRange::size() const {
+  return Vector3D(x.size(), y.size(), z.size());
 }
 
-xyz dxyz::mid() const {
-  return xyz(x.mid(), y.mid(), z.mid());
+Vector3D VectorRange::mid() const {
+  return Vector3D(x.mid(), y.mid(), z.mid());
 }
 
-flt dxyz::length() const {
-  return xyz(x.size(), y.size(), z.size()).length();
+float VectorRange::length() const {
+  return Vector3D(x.size(), y.size(), z.size()).length();
 }
 
 //------------------------------------------------------------------------------
 }
-// eof
diff --git a/GUI/ba3d/ba3d/def.h b/GUI/ba3d/ba3d/def.h
index d3671440f1982985ef9dc894a8f7e3303cca6c8c..8300dfe2c97d55d7e3790cda597375d38253c4d7 100644
--- a/GUI/ba3d/ba3d/def.h
+++ b/GUI/ba3d/ba3d/def.h
@@ -21,134 +21,68 @@
 #pragma GCC diagnostic ignored "-Wfloat-equal"
 #endif
 
-// debug support
-#ifndef NDEBUG
-
-// trace print
-#include <QDebug>
-#define TR(what) qDebug() << what;
-
-#else
-
-#define TR(what) ;
-
-#endif
-
-// trace print
-#define WT(what) TR(#what << what)
-
-// precondition
-#define EXPECT(cond) Q_ASSERT(cond);
-// invariant
-#define ENSURE(cond) Q_ASSERT(cond);
-
-// a handy iteration support
-#ifdef __GNUC__
-
-template <typename T> struct mut_typ          { typedef T typ; };
-template <typename T> struct mut_typ<T const> { typedef T typ; };
-
-#define for_int(i, n) \
-  for (mut_typ<decltype(n)>::typ i = decltype(n)(0), i##End = (n); i < i##End; ++i)
-
-#else // msvc fails the above
-
-#define for_int(i, n) \
-  for (int i = 0, i##End = (n); i < i##End; ++i)
-
-#endif
-
-#define for_i(n) for_int (i, n)
-
-// typedef for a base class
-#define BASE(cls) using base = cls;
-
 //------------------------------------------------------------------------------
 // coordinates
 
 #include <QVector3D>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
-
-// 32b float as in GL; 3 letters as in 'int'
-using flt = float;
-
-#ifndef NDEBUG
-
-// in debug version checked, non-negative flt >= 0: (fl)t (p)ositive
-struct flp {
-  flp(flt);
-  operator flt() const { return f; }
-private:
-  flt f;
-};
-
-#else
-
-typedef flt flp;
-
-#endif
-
+namespace RealSpace {
 //------------------------------------------------------------------------------
 
-struct xyz {
-  flt x, y, z;
-
-  typedef xyz const& rc;
+struct Vector3D {
+  float x, y, z;
 
-  xyz();
-  xyz(flt);
-  xyz(flt, flt, flt);
+  Vector3D();
+  Vector3D(float);
+  Vector3D(float, float, float);
 
-  xyz(rc) = default;
+  Vector3D(const Vector3D&) =default;
 
-  xyz(QVector3D const&);
+  Vector3D(QVector3D const&);
   operator QVector3D() const;
 
-  flt length()     const;
-  xyz normalized() const;
+  float length() const;
+  Vector3D normalized() const;
 
-  xyz interpolateTo(rc, flt) const;
+  Vector3D interpolateTo(const Vector3D&, float) const;
 
-  static xyz const _0, _1, _x, _y, _z;
+  static Vector3D const _0, _1, _x, _y, _z;
 };
 
 // products
-xyz cross(xyz::rc, xyz::rc);
-flt dot(xyz::rc, xyz::rc);
+Vector3D cross(const Vector3D&, const Vector3D&);
+float dot(const Vector3D&, const Vector3D&);
 
-xyz operator+(xyz::rc);
-xyz operator-(xyz::rc);
-xyz operator*(xyz::rc, flt);
+Vector3D operator+(const Vector3D&);
+Vector3D operator-(const Vector3D&);
+Vector3D operator*(const Vector3D&, float);
 
-xyz operator+(xyz::rc, xyz::rc);
-xyz operator-(xyz::rc, xyz::rc);
+Vector3D operator+(const Vector3D&, const Vector3D&);
+Vector3D operator-(const Vector3D&, const Vector3D&);
 
 //------------------------------------------------------------------------------
 
-// (d)ifference or (r)ange
-struct dr {
-  flt min, max;
-  dr(flt, flt);
+// range of float
+struct Range {
+  float min, max;
+  Range(float, float);
 
-  flt size() const;
-  flt mid()  const;
+  float size() const;
+  float mid()  const;
 };
 
-// dr of coordinates
-struct dxyz {
-  dr x, y, z;
-  dxyz(dr, dr, dr);
-  dxyz(xyz, xyz);
+// range of coordinates
+struct VectorRange {
+  Range x, y, z;
+  VectorRange(Range, Range, Range);
+  VectorRange(Vector3D, Vector3D);
 
-  xyz size()   const;
-  xyz mid()    const;
+  Vector3D size()   const;
+  Vector3D mid()    const;
 
-  flt length() const;
+  float length() const;
 };
 
 //------------------------------------------------------------------------------
 }
 #endif
-// eof
diff --git a/GUI/ba3d/ba3d/model/geometry.cpp b/GUI/ba3d/ba3d/model/geometry.cpp
index c1e184b0d66b0d37e8dce6978b506e1d45fc4e7e..671653b02db7c0414f181a8e38350294b5ba2daf 100644
--- a/GUI/ba3d/ba3d/model/geometry.cpp
+++ b/GUI/ba3d/ba3d/model/geometry.cpp
@@ -15,141 +15,139 @@
 #include "geometry.h"
 #include "model.h"
 
-namespace ba3d {
+namespace RealSpace {
 //------------------------------------------------------------------------------
 
-Geometry::vn_t::vn_t(xyz::rc v_, xyz::rc n_) : v(v_), n(n_) {}
+Geometry::Vert_Normal::Vert_Normal(const Vector3D& v_, const Vector3D& n_) : v(v_), n(n_) {}
 
-void Geometry::xyz_vec::addVert(xyz::rc v, int n) {
-  for_i (n)
-    append(v);
+void Geometry::Vertices::addVertex(const Vector3D& v, int n) {
+    for(int i=0; i<n; ++i)
+        append(v);
 }
 
-void Geometry::xyz_vec::addTrig(xyz::rc v1, xyz::rc v2, xyz::rc v3) {
-  append(v1); append(v2); append(v3);
+void Geometry::Vertices::addTriangle(const Vector3D& v1, const Vector3D& v2, const Vector3D& v3) {
+    append(v1); append(v2); append(v3);
 }
 
-void Geometry::xyz_vec::addQuad(xyz::rc v1, xyz::rc v2, xyz::rc v3, xyz::rc v4) {
-  addTrig(v1, v2, v3);
-  addTrig(v3, v4, v1);
+void Geometry::Vertices::addQuad(const Vector3D& v1, const Vector3D& v2,
+                                 const Vector3D& v3, const Vector3D& v4) {
+    addTriangle(v1, v2, v3);
+    addTriangle(v3, v4, v1);
 }
 
-void Geometry::xyz_vec::addQuad(Geometry::xyz_vec::rc vs,
-                                idx i1, idx i2, idx i3, idx i4) {
-  addQuad(vs.at(i1), vs.at(i2), vs.at(i3), vs.at(i4));
+void Geometry::Vertices::addQuad(const Vertices& vs,
+                                 unsigned i1, unsigned i2, unsigned i3, unsigned i4) {
+    addQuad(vs.at(i1), vs.at(i2), vs.at(i3), vs.at(i4));
 }
 
-void Geometry::xyz_vec::addStrip(xyz_vec::rc vs, idx_vec::rc is) {
-  EXPECT(is.count() >= 3) // at least one triangle
-  for_i (is.count() - 2)
-    if (i%2)
-      addTrig(vs.at(is.at(i)), vs.at(is.at(1+i)), vs.at(is.at(2+i)));
-    else
-      addTrig(vs.at(is.at(i)), vs.at(is.at(2+i)), vs.at(is.at(1+i)));
+void Geometry::Vertices::addStrip(const Vertices& vs, const Indices& is) {
+    Q_ASSERT(is.size() >= 3); // at least one triangle
+    for(unsigned i=0; i+2<is.size(); ++i)
+        if (i%2)
+            addTriangle(vs.at(is.at(i)), vs.at(is.at(1+i)), vs.at(is.at(2+i)));
+        else
+            addTriangle(vs.at(is.at(i)), vs.at(is.at(2+i)), vs.at(is.at(1+i)));
 }
 
-void Geometry::xyz_vec::addFan(xyz_vec::rc vs, idx_vec::rc is) {
-  EXPECT(is.count() >= 3) // at least one triangle
-  auto &ctr = vs.at(is.at(0));
-  for_i (is.count() - 2)
-    addTrig(ctr, vs.at(is.at(1+i)),
-                 vs.at(is.at(2+i)));
+void Geometry::Vertices::addFan(const Vertices& vs, const Indices& is) {
+    Q_ASSERT(is.size() >= 3); // at least one triangle
+    auto &ctr = vs.at(is.at(0));
+    for(unsigned i=0; i+2<is.size(); ++i)
+        addTriangle(ctr, vs.at(is.at(1+i)),
+                    vs.at(is.at(2+i)));
 }
 
 //------------------------------------------------------------------------------
 
-Geometry::Geometry(geometry::key key_) : key(key_) {
-  using namespace geometry;
-
-  switch (key.id) {
-  case eid::Plane:
-    mesh = meshPlane();
-    break;
-  case eid::Box:
-    mesh = meshBox();
-    break;
-  case eid::Sphere:
-    mesh = meshSphere(key.p1);
-    break;
-  case eid::Column:
-    mesh = meshColumn(key.p1, key.p2);
-    break;
-  case eid::Icosahedron:
-    mesh = meshIcosahedron();
-    break;
-  case eid::Dodecahedron:
-    mesh = meshDodecahedron();
-    break;
-  case eid::TruncatedBox:
-    mesh = meshTruncBox(key.p1);
-    break;
-  case eid::Cuboctahedron:
-    mesh = meshCuboctahedron(key.p1, key.p2);
-    break;
-  }
+Geometry::Geometry(GeometricID::Key key_) : m_key(key_) {
+    using namespace GeometricID;
+
+    switch (m_key.id) {
+    case BaseShape::Plane:
+        m_mesh = meshPlane();
+        break;
+    case BaseShape::Box:
+        m_mesh = meshBox();
+        break;
+    case BaseShape::Sphere:
+        m_mesh = meshSphere(m_key.p1);
+        break;
+    case BaseShape::Column:
+        m_mesh = meshColumn(m_key.p1, m_key.p2);
+        break;
+    case BaseShape::Icosahedron:
+        m_mesh = meshIcosahedron();
+        break;
+    case BaseShape::Dodecahedron:
+        m_mesh = meshDodecahedron();
+        break;
+    case BaseShape::TruncatedBox:
+        m_mesh = meshTruncBox(m_key.p1);
+        break;
+    case BaseShape::Cuboctahedron:
+        m_mesh = meshCuboctahedron(m_key.p1, m_key.p2);
+        break;
+    }
 }
 
 Geometry::~Geometry() {
-  // remove self from the store
-  geometryStore().geometryDeleted(*this);
+    // remove self from the store
+    geometryStore().geometryDeleted(*this);
 }
 
-Geometry::mesh_t Geometry::makeMesh(xyz_vec::rc vs, xyz_vec const* ns) {
-  int nv = vs.count();
-  EXPECT(0 == nv%3)
-  EXPECT(!ns || nv == ns->count()) // if normals not given, will be computed
+Geometry::Mesh Geometry::makeMesh(const Vertices& vs, Vertices const* ns) {
+    int nv = vs.count();
+    Q_ASSERT(0 == nv%3);
+    Q_ASSERT(!ns || nv == ns->count()); // if normals not given, will be computed
 
-  mesh_t mesh(nv);
+    Mesh mesh(nv);
 
-  for (int i=0 ; i<nv; i+=3) {
-    xyz::rc v0 = vs.at(0+i), v1 = vs.at(1+i), v2 = vs.at(2+i);
-    xyz const *n0, *n1, *n2; xyz nm;
+    for (int i=0 ; i<nv; i+=3) {
+        const Vector3D& v0 = vs.at(0+i), v1 = vs.at(1+i), v2 = vs.at(2+i);
+        const Vector3D *n0, *n1, *n2;
+        Vector3D nm;
 
-    if (ns) {
-      n0 = &ns->at(0+i); n1 = &ns->at(1+i); n2 = &ns->at(2+i);
-    } else {
-      nm = cross((v1 - v0), (v2 - v0));
-      n0 = n1 = n2 = &nm;
-    }
+        if (ns) {
+            n0 = &ns->at(0+i); n1 = &ns->at(1+i); n2 = &ns->at(2+i);
+        } else {
+            nm = cross((v1 - v0), (v2 - v0));
+            n0 = n1 = n2 = &nm;
+        }
 
-    mesh.append(vn_t(v0,*n0));
-    mesh.append(vn_t(v1,*n1));
-    mesh.append(vn_t(v2,*n2));
-  }
+        mesh.append(Vert_Normal(v0,*n0));
+        mesh.append(Vert_Normal(v1,*n1));
+        mesh.append(Vert_Normal(v2,*n2));
+    }
 
-  return mesh;
+    return mesh;
 }
 
-Geometry::mesh_t Geometry::makeMesh(xyz_vec::rc vs, xyz_vec::rc ns) {
-  return makeMesh(vs, &ns);
+Geometry::Mesh Geometry::makeMesh(const Vertices& vs, const Vertices& ns) {
+    return makeMesh(vs, &ns);
 }
 
 //------------------------------------------------------------------------------
 
-shGeo GeometryStore::getGeometry(geometry::key key) {
-  auto it = geometries.find(key);
-  if (geometries.end() != it) {
-    shGeo g = it->toStrongRef();
-    if (g)
-      return g;
-    geometries.erase(it); // it really should not come to this
-  }
-
-  shGeo g = shGeo(new Geometry(key));
-  geometries.insert(key, g.toWeakRef());
-  return g;
+GeometryHandle GeometryStore::getGeometry(GeometricID::Key key) {
+    auto it = m_geometries.find(key);
+    if (m_geometries.end() != it) {
+        if (auto g = it->second.lock())
+            return g;
+    }
+    GeometryHandle g = GeometryHandle(new Geometry(key));
+    m_geometries[key] = GeometryRef(g);
+    return g;
 }
 
 void GeometryStore::geometryDeleted(Geometry const& g) {
-  emit deletingGeometry(&g);
-  geometries.remove(g.key);
+    emit deletingGeometry(&g);
+    m_geometries.erase(g.m_key);
 }
 
 GeometryStore& geometryStore() {
-  static GeometryStore gs;
-  return gs;
+    static GeometryStore gs;
+    return gs;
 }
 
 //------------------------------------------------------------------------------
 }
-// eof
diff --git a/GUI/ba3d/ba3d/model/geometry.h b/GUI/ba3d/ba3d/model/geometry.h
index 9c154ca1b5334fe76d1e2980e0b7acf1891157c1..64ec6bbd3f290a98f54240a6c2664a06289ca93f 100644
--- a/GUI/ba3d/ba3d/model/geometry.h
+++ b/GUI/ba3d/ba3d/model/geometry.h
@@ -18,92 +18,95 @@
 #include "../def.h"
 #include "geometry_inc.h"
 #include <QVector>
+#include <QObject>
+#include <unordered_map>
+#include <vector>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
 class Buffer;
 class GeometryStore;
 
 class Geometry {
-  friend class Buffer;
-  friend class GeometryStore;
+    friend class Buffer;
+    friend class GeometryStore;
 public:
-  // vertex+normal pair
-  struct vn_t {
-    xyz v, n;
-    vn_t() = default;
-    vn_t(xyz::rc v, xyz::rc n);
-  };
-
-  // vertex indices (for GL)
-  typedef quint8 idx;
-  struct idx_vec : QVector<idx> { typedef QVector<idx> base;
-    using base::base;
-    typedef idx_vec const& rc;
-  };
-
-  // vertices (for GL)
-  struct xyz_vec : QVector<xyz> { typedef QVector<xyz> base;
-    using base::base;
-    typedef xyz_vec const& rc;
-
-    void addVert(xyz::rc, int n = 1); // add a vertex, possibly multiple copies
-
-    void addTrig(xyz::rc, xyz::rc, xyz::rc);          // triangle
-    void addQuad(xyz::rc, xyz::rc, xyz::rc, xyz::rc); // quad as 2 triangles
-    void addQuad(xyz_vec::rc, idx, idx, idx, idx);
-    void addStrip(xyz_vec::rc, idx_vec::rc);          // triangle strip
-    void addFan(xyz_vec::rc, idx_vec::rc);            // triangle fan
-
-  };
-
-  // vertex/normal mesh
-  typedef QVector<vn_t> mesh_t;
-
-  Geometry(geometry::key);
-  virtual ~Geometry();
+    // vertex + normal pair
+    struct Vert_Normal {
+        Vector3D v, n;
+        Vert_Normal() =default;
+        Vert_Normal(const Vector3D& v, const Vector3D& n);
+    };
+
+    // vertex indices (for GL)
+    using Indices = std::vector<unsigned>;
+
+    // vertices (for GL)
+    struct Vertices : private QVector<Vector3D>
+    {
+        using QVector::QVector;
+        using QVector::append;
+        using QVector::reserve;
+        using QVector::resize;
+        using QVector::operator[];
+        using QVector::at;
+        using QVector::count;
+        using QVector::begin;
+        using QVector::end;
+
+        void addVertex(const Vector3D&, int n = 1);     // add a vertex, possibly multiple copies
+        void addTriangle(const Vector3D&, const Vector3D&, const Vector3D&);   // triangle
+        void addQuad(const Vector3D&, const Vector3D&,
+                     const Vector3D&, const Vector3D&); // quad as 2 triangles
+        void addQuad(const Vertices&, unsigned, unsigned, unsigned, unsigned); // quad by indices
+        void addStrip(const Vertices&, const Indices&); // triangle strip
+        void addFan(const Vertices&, const Indices&);   // triangle fan
+    };
+
+    // vertex/normal mesh
+    using Mesh = QVector<Vert_Normal>;
+
+    Geometry(GeometricID::Key);
+    virtual ~Geometry();
 
 private:
-  geometry::key key;
-
-  mesh_t mesh;
-  // make a mesh from vectors of vertices on (optionally) normals
-  static mesh_t makeMesh(xyz_vec::rc vs, xyz_vec const* ns = nullptr);
-  static mesh_t makeMesh(xyz_vec::rc vs, xyz_vec::rc ns);
-
-  static mesh_t meshPlane();
-  static mesh_t meshBox();
-  static mesh_t meshSphere(flt cut);
-  static mesh_t meshColumn(flt alpha, flt sides);
-  static mesh_t meshIcosahedron();
-  static mesh_t meshDodecahedron();
-  static mesh_t meshTruncBox(flt tD);
-  static mesh_t meshCuboctahedron(flt rH, flt alpha);
-
-  // mesh params for round shapes
-  static int const RINGS = 12, SLICES = 24;
+    GeometricID::Key m_key;
+
+    Mesh m_mesh;
+    // make a mesh from vectors of vertices and (optionally) normals
+    static Mesh makeMesh(const Vertices& vs, Vertices const* ns = nullptr);
+    static Mesh makeMesh(const Vertices& vs, const Vertices& ns);
+
+    static Mesh meshPlane();
+    static Mesh meshBox();
+    static Mesh meshSphere(float cut);
+    static Mesh meshColumn(float alpha, float sides);
+    static Mesh meshIcosahedron();
+    static Mesh meshDodecahedron();
+    static Mesh meshTruncBox(float tD);
+    static Mesh meshCuboctahedron(float rH, float alpha);
+
+    // mesh params for round shapes
+    static int const RINGS = 12, SLICES = 24;
 };
 
-//------------------------------------------------------------------------------
-
 // a single store keeps existing geometries for sharing
+
 class GeometryStore : public QObject {
   Q_OBJECT
   friend class Geometry;
 public:
-  shGeo getGeometry(geometry::key);
+  GeometryHandle getGeometry(GeometricID::Key);
 
 signals:
   void deletingGeometry(Geometry const*); // signal to canvases
 
 private:
-  QHash<geometry::key,wkGeo> geometries;
+  std::unordered_map<GeometricID::Key, GeometryRef, GeometricID::KeyHash> m_geometries;
   void geometryDeleted(Geometry const&);  // ~Geometry() calls this
 };
 
 GeometryStore& geometryStore(); // simpleton
 
-//------------------------------------------------------------------------------
-}
+}  // namespace RealSpace
 #endif
diff --git a/GUI/ba3d/ba3d/model/geometry/box.cpp b/GUI/ba3d/ba3d/model/geometry/box.cpp
index cab9ba0bc9f80fc95caf7f1e6973e5a450ed7d1f..c709d501cd9001fff1aaaf70b7359b5374f08526 100644
--- a/GUI/ba3d/ba3d/model/geometry/box.cpp
+++ b/GUI/ba3d/ba3d/model/geometry/box.cpp
@@ -14,33 +14,30 @@
 
 #include "../geometry.h"
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
-Geometry::mesh_t Geometry::meshBox() {
-  flt const D = .5f;
+Geometry::Mesh Geometry::meshBox() {
+    float const D = .5f;
 
-  xyz_vec vs_; vs_.reserve(8);
-  for (flt x : {-D, +D})
-    for (flt y : {-D, +D})
-      for (flt z : {-D, +D})
-        vs_.append(xyz(x,y,z));
+    Vertices vs_; vs_.reserve(8);
+    for (float x : {-D, +D})
+        for (float y : {-D, +D})
+            for (float z : {-D, +D})
+                vs_.append(Vector3D(x,y,z));
 
-  ENSURE(8 == vs_.count())
+    Q_ASSERT(8 == vs_.count());
 
-  xyz_vec vs; vs.reserve(36);
+    Vertices vs; vs.reserve(36);
 
-  vs.addQuad(vs_, 0, 2, 6, 4);
-  vs.addQuad(vs_, 1, 5, 7, 3);
-  vs.addQuad(vs_, 0, 1, 3, 2);
-  vs.addQuad(vs_, 4, 6, 7, 5);
-  vs.addQuad(vs_, 0, 4, 5, 1);
-  vs.addQuad(vs_, 2, 3, 7, 6);
+    vs.addQuad(vs_, 0, 2, 6, 4);
+    vs.addQuad(vs_, 1, 5, 7, 3);
+    vs.addQuad(vs_, 0, 1, 3, 2);
+    vs.addQuad(vs_, 4, 6, 7, 5);
+    vs.addQuad(vs_, 0, 4, 5, 1);
+    vs.addQuad(vs_, 2, 3, 7, 6);
 
-  ENSURE(36 == vs.count())
+    Q_ASSERT(36 == vs.count());
 
-  return makeMesh(vs);
-}
-
-//------------------------------------------------------------------------------
+    return makeMesh(vs);
 }
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/model/geometry/column.cpp b/GUI/ba3d/ba3d/model/geometry/column.cpp
index f3cd6059eb5ba8e8e7b9f1a9cba465a3b115eb44..8ff3305b1610648397939493f6bad205d91b2650 100644
--- a/GUI/ba3d/ba3d/model/geometry/column.cpp
+++ b/GUI/ba3d/ba3d/model/geometry/column.cpp
@@ -15,55 +15,53 @@
 #include "../geometry.h"
 #include <qmath.h>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
-Geometry::mesh_t Geometry::meshColumn(flt alpha, flt numSides) {
-  int  const sides  = qRound(numSides);
-  bool const smooth = (0 == sides); // sides: 0->smooth
-  int  const slices = smooth ? SLICES : sides;
+Geometry::Mesh Geometry::meshColumn(float alpha, float numSides) {
+    int  const sides  = qRound(numSides);
+    bool const smooth = (0 == sides); // sides: 0->smooth
+    int  const slices = smooth ? SLICES : sides;
 
-  flt const R = .5f, Rb = R, Rt = Rb - 2*R/tanf(alpha);
+    float const R = .5f, Rb = R, Rt = Rb - 2*R/tanf(alpha);
 
-  // mesh of vertices and normals
-  xyz_vec vb(slices), vt(slices), nbt(slices);
-  flt const nz = (1 - Rt/Rb)*2*R;
-  for_int (s, slices) {
-    flt th = flt(2*M_PI*s/slices), st = sinf(th), ct = cosf(th);
-    xyz vb_(Rb*ct, Rb*st, -R), vt_(Rt*ct, Rt*st, +R);
-    vb[s] = vb_; vt[s] = vt_;
-    if (smooth)
-      nbt[s] = xyz(vb_.x, vb_.y, nz).normalized();
-  }
+    // mesh of vertices and normals
+    Vertices vb(slices), vt(slices), nbt(slices);
+    float const nz = (1 - Rt/Rb)*2*R;
+    for(int s=0; s < slices; ++s) {
+        float th = float(2*M_PI*s/slices), st = sinf(th), ct = cosf(th);
+        Vector3D vb_(Rb*ct, Rb*st, -R), vt_(Rt*ct, Rt*st, +R);
+        vb[s] = vb_; vt[s] = vt_;
+        if (smooth)
+            nbt[s] = Vector3D(vb_.x, vb_.y, nz).normalized();
+    }
 
-  // make into triangles
-  int const nv = 6*2*slices;
-  xyz_vec vs; vs.reserve(nv);
-  xyz_vec ns; if (smooth) ns.reserve(nv);
+    // make into triangles
+    int const nv = 6*2*slices;
+    Vertices vs; vs.reserve(nv);
+    Vertices ns; if (smooth) ns.reserve(nv);
 
-  for_int (s, slices) {
-    int s1 = s, s2 = (s+1) % slices;
+    for(int s=0; s < slices; ++s) {
+        int s1 = s, s2 = (s+1) % slices;
 
-    vs.addTrig(vb.at(s1), xyz(0,0,-R), vb.at(s2));          // bottom
-    if (smooth)
-      ns.addVert(-xyz::_z, 3);
+        vs.addTriangle(vb.at(s1), Vector3D(0,0,-R), vb.at(s2));          // bottom
+        if (smooth)
+            ns.addVertex(-Vector3D::_z, 3);
 
-    vs.addTrig(xyz(0,0,+R), vt.at(s1), vt.at(s2));          // top
-    if (smooth)
-      ns.addVert(+xyz::_z, 3);
+        vs.addTriangle(Vector3D(0,0,+R), vt.at(s1), vt.at(s2));          // top
+        if (smooth)
+            ns.addVertex(+Vector3D::_z, 3);
 
-    vs.addQuad(vb.at(s1), vb.at(s2), vt.at(s2), vt.at(s1)); // side
-    if (smooth) {
-      auto &n1 = nbt.at(s1), &n2 = nbt.at(s2);
-      ns.addQuad(n1, n2, n2, n1);
+        vs.addQuad(vb.at(s1), vb.at(s2), vt.at(s2), vt.at(s1)); // side
+        if (smooth) {
+            auto &n1 = nbt.at(s1), &n2 = nbt.at(s2);
+            ns.addQuad(n1, n2, n2, n1);
+        }
     }
-  }
 
-  ENSURE(vs.count() == nv)
-  ENSURE(!smooth || ns.count() == nv)
+    Q_ASSERT(vs.count() == nv);
+    Q_ASSERT(!smooth || ns.count() == nv);
 
-  return makeMesh(vs, smooth ? &ns : nullptr);
+    return makeMesh(vs, smooth ? &ns : nullptr);
 }
 
-//------------------------------------------------------------------------------
-}
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/model/geometry/cuboctahedron.cpp b/GUI/ba3d/ba3d/model/geometry/cuboctahedron.cpp
index 4c9d0ecdc9432d6fa1339368c9357bda59501d02..da06cec045c724facbe2a418d4ac4de841011c25 100644
--- a/GUI/ba3d/ba3d/model/geometry/cuboctahedron.cpp
+++ b/GUI/ba3d/ba3d/model/geometry/cuboctahedron.cpp
@@ -15,44 +15,42 @@
 #include "../geometry.h"
 #include <qmath.h>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
-
-Geometry::mesh_t Geometry::meshCuboctahedron(flt rH, flt alpha) { // t/D
-  EXPECT(alpha >= flt(M_PI_2))
-  EXPECT(rH >= 0)
-
-  flt const D = .5f, H = 2*D / (rH + 1), t = tanf(alpha - flt(M_PI_2));
-  flt const Db = D - t*H, Dt = D - t*(2*D - H);
-
-  xyz_vec vs_; vs_.reserve(12);
-  flt z[] = {-D, H-D, +D}, d[] = {Db, D, Dt};
-  for_i (3)
-    for (int x : {-1, +1})
-      for (int y : {-1, +1}) {
-        flt di = d[i];
-        vs_.append(xyz(x*di, y*di, z[i]));
-      }
-
-  ENSURE(12 == vs_.count())
-
-  xyz_vec vs; vs.reserve(60);
-
-  vs.addQuad(vs_, 0,  1,  3, 2);
-  vs.addQuad(vs_, 8, 10, 11, 9);
-  vs.addQuad(vs_, 0,  4,  5, 1);
-  vs.addQuad(vs_, 1,  5,  7, 3);
-  vs.addQuad(vs_, 3,  7,  6, 2);
-  vs.addQuad(vs_, 2,  6,  4, 0);
-  vs.addQuad(vs_, 4,  8,  9, 5);
-  vs.addQuad(vs_, 5,  9, 11, 7);
-  vs.addQuad(vs_, 7, 11, 10, 6);
-  vs.addQuad(vs_, 6, 10,  8, 4);
-
-  ENSURE(60 == vs.count())
-
-  return makeMesh(vs);
+namespace RealSpace {
+
+Geometry::Mesh Geometry::meshCuboctahedron(float rH, float alpha) { // t/D
+    Q_ASSERT(alpha >= float(M_PI_2));
+    Q_ASSERT(rH >= 0);
+
+    float const D = .5f, H = 2*D / (rH + 1), t = tanf(alpha - float(M_PI_2));
+    float const Db = D - t*H, Dt = D - t*(2*D - H);
+
+    Vertices vs_; vs_.reserve(12);
+    float z[] = {-D, H-D, +D}, d[] = {Db, D, Dt};
+    for(int i=0; i<3; ++i)
+        for (int x : {-1, +1})
+            for (int y : {-1, +1}) {
+                float di = d[i];
+                vs_.append(Vector3D(x*di, y*di, z[i]));
+            }
+
+    Q_ASSERT(12 == vs_.count());
+
+    Vertices vs; vs.reserve(60);
+
+    vs.addQuad(vs_, 0,  1,  3, 2);
+    vs.addQuad(vs_, 8, 10, 11, 9);
+    vs.addQuad(vs_, 0,  4,  5, 1);
+    vs.addQuad(vs_, 1,  5,  7, 3);
+    vs.addQuad(vs_, 3,  7,  6, 2);
+    vs.addQuad(vs_, 2,  6,  4, 0);
+    vs.addQuad(vs_, 4,  8,  9, 5);
+    vs.addQuad(vs_, 5,  9, 11, 7);
+    vs.addQuad(vs_, 7, 11, 10, 6);
+    vs.addQuad(vs_, 6, 10,  8, 4);
+
+    Q_ASSERT(60 == vs.count());
+
+    return makeMesh(vs);
 }
 
-//------------------------------------------------------------------------------
-}
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/model/geometry/dodecahedron.cpp b/GUI/ba3d/ba3d/model/geometry/dodecahedron.cpp
index 730e220f4f2eaf379d477d1f7e5278b901e91015..2582ef749e979080d9c371fafa36a37a9a22306d 100644
--- a/GUI/ba3d/ba3d/model/geometry/dodecahedron.cpp
+++ b/GUI/ba3d/ba3d/model/geometry/dodecahedron.cpp
@@ -16,63 +16,61 @@
 #include <qmath.h>
 #include <QQuaternion>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
-Geometry::mesh_t Geometry::meshDodecahedron() {
-  flt const G  = geometry::goldenRatio,
-            G1 = 1/G;
+Geometry::Mesh Geometry::meshDodecahedron() {
+    const float GR  = GoldenRatio,
+            G1 = 1/GR;
 
-  xyz_vec vs_; vs_.reserve(20);
-  for (flt x : {-1, +1})
-    for (flt y : {-1, +1})
-      for (flt z : {-1, +1})
-        vs_.append(xyz(x,y,z));
+    Vertices vs_; vs_.reserve(20);
+    for (float x : {-1, +1})
+        for (float y : {-1, +1})
+            for (float z : {-1, +1})
+                vs_.append(Vector3D(x,y,z));
 
-  for (flt g1 : {-G1, +G1})
-    for (flt g : {-G, +G}) {
-      vs_.append(xyz(0, g1, g));
-      vs_.append(xyz(g1, g, 0));
-      vs_.append(xyz(g, 0, g1));
-    }
+    for (float g1 : {-G1, +G1})
+        for (float g : {-GR, +GR}) {
+            vs_.append(Vector3D(0, g1, g));
+            vs_.append(Vector3D(g1, g, 0));
+            vs_.append(Vector3D(g, 0, g1));
+        }
 
-  ENSURE(20 == vs_.count())
+    Q_ASSERT(20 == vs_.count());
 
-  // scale to circumscribed sphere
-  flt const F = .5f / vs_.at(0).length();
-  for (auto& v : vs_)
-    v = v*F;
+    // scale to circumscribed sphere
+    float const F = .5f / vs_.at(0).length();
+    for (auto& v : vs_)
+        v = v*F;
 
-  //face down
-  auto q = QQuaternion::rotationTo(-xyz::_z,
-    cross(vs_.at(8)-vs_.at(0), vs_.at(10)-vs_.at(0)));
-  for_i (20)
-    vs_[i] = q.rotatedVector(vs_.at(i));
+    //face down
+    auto q = QQuaternion::rotationTo(-Vector3D::_z,
+                                     cross(vs_.at(8)-vs_.at(0), vs_.at(10)-vs_.at(0)));
+    for(int i=0; i<20; ++i)
+        vs_[i] = q.rotatedVector(vs_.at(i));
 
-  xyz_vec vs; vs.reserve(180);
+    Vertices vs; vs.reserve(180);
 
-  auto add5 = [&](idx i1, idx i2, idx i3, idx i4, idx i5) {
-    vs.addFan(vs_, {i1, i2, i3, i4, i5, i1});
-  };
+    auto add5 = [&](unsigned i1, unsigned i2, unsigned i3, unsigned i4, unsigned i5) {
+        vs.addFan(vs_, {i1, i2, i3, i4, i5, i1});
+    };
 
-  add5( 1, 11, 17,  3, 16); // bottom
-  add5( 1, 16, 10,  0, 9 );
-  add5(16,  3, 12,  2, 10);
-  add5( 3, 17,  7, 18, 12);
-  add5(17, 11,  5, 19,  7);
-  add5(11,  1,  9, 15,  5);
+    add5( 1, 11, 17,  3, 16); // bottom
+    add5( 1, 16, 10,  0, 9 );
+    add5(16,  3, 12,  2, 10);
+    add5( 3, 17,  7, 18, 12);
+    add5(17, 11,  5, 19,  7);
+    add5(11,  1,  9, 15,  5);
 
-  add5( 8,  4, 15,  9,  0);
-  add5(14,  8,  0, 10,  2);
-  add5( 6, 14,  2, 12, 18);
-  add5(13,  6, 18,  7, 19);
-  add5( 4, 13, 19,  5, 15);
-  add5( 4,  8, 14,  6, 13);  // top
+    add5( 8,  4, 15,  9,  0);
+    add5(14,  8,  0, 10,  2);
+    add5( 6, 14,  2, 12, 18);
+    add5(13,  6, 18,  7, 19);
+    add5( 4, 13, 19,  5, 15);
+    add5( 4,  8, 14,  6, 13);  // top
 
-  ENSURE(144 == vs.count())
+    Q_ASSERT(144 == vs.count());
 
-  return makeMesh(vs);
+    return makeMesh(vs);
 }
 
-//------------------------------------------------------------------------------
-}
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/model/geometry/icosahedron.cpp b/GUI/ba3d/ba3d/model/geometry/icosahedron.cpp
index 8e3d0a64acf48e59870b8d03d06f6e99d9cbf1ad..4b427eed4f0a81bb72f4bc3899ae26c231177ed8 100644
--- a/GUI/ba3d/ba3d/model/geometry/icosahedron.cpp
+++ b/GUI/ba3d/ba3d/model/geometry/icosahedron.cpp
@@ -16,39 +16,37 @@
 #include <qmath.h>
 #include <QQuaternion>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
-Geometry::mesh_t Geometry::meshIcosahedron() {
-  flt const G = geometry::goldenRatio;
+Geometry::Mesh Geometry::meshIcosahedron() {
+    const float GR = GoldenRatio;
 
-  auto q = QQuaternion::rotationTo(-xyz::_z, xyz(0,1,-G));
+    auto q = QQuaternion::rotationTo(-Vector3D::_z, Vector3D(0,1,-GR));
 
-  xyz_vec vs_; vs_.reserve(12);
-  for (flt _1 : {-1, +1})
-    for (flt g : {-G, +G}) {
-      vs_.append(q.rotatedVector(xyz(0, _1, g)));
-      vs_.append(q.rotatedVector(xyz(_1, g, 0)));
-      vs_.append(q.rotatedVector(xyz(g, 0, _1)));
-    }
+    Vertices vs_; vs_.reserve(12);
+    for (float _1 : {-1, +1})
+        for (float g : {-GR, +GR}) {
+            vs_.append(q.rotatedVector(Vector3D(0, _1, g)));
+            vs_.append(q.rotatedVector(Vector3D(_1, g, 0)));
+            vs_.append(q.rotatedVector(Vector3D(g, 0, _1)));
+        }
 
-  ENSURE(12 == vs_.count())
+    Q_ASSERT(12 == vs_.count());
 
-  // scale to circumscribed sphere
-  flt const F = .5f / vs_.at(0).length();
-  for (auto& v : vs_)
-    v = v*F;
+    // scale to circumscribed sphere
+    float const F = .5f / vs_.at(0).length();
+    for (auto& v : vs_)
+        v = v*F;
 
-  xyz_vec vs; vs.reserve(60);
+    Vertices vs; vs.reserve(60);
 
-  vs.addFan(vs_, {0, 1, 2, 6, 5, 7, 1});
-  vs.addFan(vs_, {9, 3, 11, 10, 4, 8, 3});
-  vs.addStrip(vs_, {1, 3, 7, 11, 5, 10, 6, 4, 2, 8, 1, 3});
+    vs.addFan(vs_, {0, 1, 2, 6, 5, 7, 1});
+    vs.addFan(vs_, {9, 3, 11, 10, 4, 8, 3});
+    vs.addStrip(vs_, {1, 3, 7, 11, 5, 10, 6, 4, 2, 8, 1, 3});
 
-  ENSURE(60 == vs.count())
+    Q_ASSERT(60 == vs.count());
 
-  return makeMesh(vs);
+    return makeMesh(vs);
 }
 
-//------------------------------------------------------------------------------
-}
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/model/geometry/plane.cpp b/GUI/ba3d/ba3d/model/geometry/plane.cpp
index d026fe283b9c898f8ea12764a779f8a473449c8b..d11ab8977619519f343328d0c5ffd6bf6c1ce4a8 100644
--- a/GUI/ba3d/ba3d/model/geometry/plane.cpp
+++ b/GUI/ba3d/ba3d/model/geometry/plane.cpp
@@ -14,19 +14,17 @@
 
 #include "../geometry.h"
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
-Geometry::mesh_t Geometry::meshPlane() {
-  flt const D = .5f;
+Geometry::Mesh Geometry::meshPlane() {
+    float const D = .5f;
 
-  xyz_vec vs; vs.reserve(4);
-  vs.addQuad({+D,+D, 0}, {-D,+D, 0}, {-D,-D, 0}, {+D,-D, 0});
+    Vertices vs; vs.reserve(4);
+    vs.addQuad({+D,+D, 0}, {-D,+D, 0}, {-D,-D, 0}, {+D,-D, 0});
 
-  ENSURE(4 == vs.count())
+    Q_ASSERT(4 == vs.count());
 
-  return makeMesh(vs);
+    return makeMesh(vs);
 }
 
-//------------------------------------------------------------------------------
-}
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/model/geometry/sphere.cpp b/GUI/ba3d/ba3d/model/geometry/sphere.cpp
index d3050ab3e85cd07c29903860520b9f9d1d4129f5..79fd563624e8cdc1fd748bd02a90a322b10d26d8 100644
--- a/GUI/ba3d/ba3d/model/geometry/sphere.cpp
+++ b/GUI/ba3d/ba3d/model/geometry/sphere.cpp
@@ -15,96 +15,94 @@
 #include "../geometry.h"
 #include <qmath.h>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
 // cut: 0..1 - how much is cut off off the bottom
-Geometry::mesh_t Geometry::meshSphere(flt cut) {
-  if (1 <= cut)
-    return mesh_t();
-  cut = qMax(0.f, cut);
-  ENSURE(0 <= cut && cut < 1)
-
-  // 'rings' is 1 less than actual rings (due to poles)
-  int rings, slices = SLICES;
-  flt minPh, phRge;
-
-  if (cut > 0) {
-    minPh = asinf(2*cut - 1);
-    phRge = flt(M_PI_2) - minPh;
-    rings = qMax(1, qCeil(qreal(RINGS * phRge) / M_PI));
-  } else {
-    rings = RINGS - 1;
-    minPh = flt(M_PI) / rings - flt(M_PI_2);
-    phRge = flt(M_PI_2) - minPh;
-  }
-
-  ENSURE(qAbs(minPh) < flt(M_PI_2))
-  ENSURE(1 <= rings && 2 <= slices)
-
-  // meshes of vertices and normals, without poles, _[ring][slice]
-  QVector<xyz_vec> vs_(rings), ns_(rings);
-  for (auto& ring: vs_)
-    ring.resize(slices);
-  for (auto& ring: ns_)
-    ring.resize(slices);
-
-  flt const R = .5f;
-
-  for_int (r, rings) {
-    flt ph = minPh + phRge * r/rings;
-    flt cp = cosf(ph), sp = sinf(ph);
-
-    for_int (s, slices) {
-      flt th = flt(2*M_PI*s/slices);
-      xyz v(R*cp*cosf(th), R*cp*sinf(th), R*sp);
-      vs_[r][s] = v;
-      ns_[r][s] = v.normalized();
+Geometry::Mesh Geometry::meshSphere(float cut) {
+    if (1 <= cut)
+        return Mesh();
+    cut = qMax(0.f, cut);
+    Q_ASSERT(0 <= cut && cut < 1);
+
+    // 'rings' is 1 less than actual rings (due to poles)
+    int rings, slices = SLICES;
+    float minPh, phRge;
+
+    if (cut > 0) {
+        minPh = asinf(2*cut - 1);
+        phRge = float(M_PI_2) - minPh;
+        rings = qMax(1, qCeil(qreal(RINGS * phRge) / M_PI));
+    } else {
+        rings = RINGS - 1;
+        minPh = float(M_PI) / rings - float(M_PI_2);
+        phRge = float(M_PI_2) - minPh;
     }
-  }
-
-  // make into triangles
-  int const nv = 6*(rings)*slices;
-  xyz_vec vs; vs.reserve(nv);
-  xyz_vec ns; ns.reserve(nv);
-
-  for_int (r, rings) {
-    auto &vr = vs_.at(r), &nr = ns_.at(r);
-
-    for_int (s, slices) {
-      int s0 = s, s1 = (s+1) % slices;
-
-      auto &v0 = vr.at(s0), &v1 = vr.at(s1);
-      auto &n0 = nr.at(s0), &n1 = nr.at(s1);
-
-      if (r == 0) { // south pole
-        xyz vp, n0, n1, np(-xyz::_z);
-        if (cut > 0) {
-          vp = xyz(0, 0, v0.z);
-          n0 = n1 = np;
-        } else {
-          vp = xyz(0,0,-R);
-          n0 = nr.at(s0); n1 = nr.at(s1);
+
+    Q_ASSERT(qAbs(minPh) < float(M_PI_2));
+    Q_ASSERT(1 <= rings && 2 <= slices);
+
+    // meshes of vertices and normals, without poles, _[ring][slice]
+    QVector<Vertices> vs_(rings), ns_(rings);
+    for (auto& ring: vs_)
+        ring.resize(slices);
+    for (auto& ring: ns_)
+        ring.resize(slices);
+
+    float const R = .5f;
+
+    for(int r=0; r < rings; ++r) {
+        float ph = minPh + phRge * r/rings;
+        float cp = cosf(ph), sp = sinf(ph);
+
+        for(int s=0; s < slices; ++s) {
+            float th = float(2*M_PI*s/slices);
+            Vector3D v(R*cp*cosf(th), R*cp*sinf(th), R*sp);
+            vs_[r][s] = v;
+            ns_[r][s] = v.normalized();
         }
-        vs.addTrig(v0, vp, v1);
-        ns.addTrig(n0, np, n1);
-      }
-
-      if (r+1 == rings) {  // north pole
-        xyz vp(0, 0, +R), np(xyz::_z);
-        vs.addTrig(v0, v1, vp);
-        ns.addTrig(n0, n1, np);
-      } else if (1 < rings) { // in between poles
-        auto &vr1 = vs_.at(r+1), &nr1 = ns_.at(r+1);
-        auto &n2 = nr1.at(s1), &n3 = nr1.at(s0);
-        vs.addQuad(v0, v1, vr1.at(s1), vr1.at(s0));
-        ns.addQuad(n0, n1, n2, n3);
-      }
     }
-  }
 
-  return makeMesh(vs, ns);
-}
+    // make into triangles
+    int const nv = 6*(rings)*slices;
+    Vertices vs; vs.reserve(nv);
+    Vertices ns; ns.reserve(nv);
+
+    for(int r=0; r < rings; ++r) {
+        auto &vr = vs_.at(r), &nr = ns_.at(r);
+
+        for(int s=0; s < slices; ++s) {
+            int s0 = s, s1 = (s+1) % slices;
+
+            auto &v0 = vr.at(s0), &v1 = vr.at(s1);
+            auto &n0 = nr.at(s0), &n1 = nr.at(s1);
+
+            if (r == 0) { // south pole
+                Vector3D vp, n0, n1, np(-Vector3D::_z);
+                if (cut > 0) {
+                    vp = Vector3D(0, 0, v0.z);
+                    n0 = n1 = np;
+                } else {
+                    vp = Vector3D(0,0,-R);
+                    n0 = nr.at(s0); n1 = nr.at(s1);
+                }
+                vs.addTriangle(v0, vp, v1);
+                ns.addTriangle(n0, np, n1);
+            }
+
+            if (r+1 == rings) {  // north pole
+                Vector3D vp(0, 0, +R), np(Vector3D::_z);
+                vs.addTriangle(v0, v1, vp);
+                ns.addTriangle(n0, n1, np);
+            } else if (1 < rings) { // in between poles
+                auto &vr1 = vs_.at(r+1), &nr1 = ns_.at(r+1);
+                auto &n2 = nr1.at(s1), &n3 = nr1.at(s0);
+                vs.addQuad(v0, v1, vr1.at(s1), vr1.at(s0));
+                ns.addQuad(n0, n1, n2, n3);
+            }
+        }
+    }
 
-//------------------------------------------------------------------------------
+    return makeMesh(vs, ns);
 }
+
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/model/geometry/truncbox.cpp b/GUI/ba3d/ba3d/model/geometry/truncbox.cpp
index f0d7d93b20709f2d7876ac63d95a8357168dafd6..ab2335eb2c15a6bc7519251deb685408ad924734 100644
--- a/GUI/ba3d/ba3d/model/geometry/truncbox.cpp
+++ b/GUI/ba3d/ba3d/model/geometry/truncbox.cpp
@@ -14,54 +14,52 @@
 
 #include "../geometry.h"
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
-Geometry::mesh_t Geometry::meshTruncBox(flt tD) { // t/D
-  if (tD <= 0)
-    return meshBox();
+Geometry::Mesh Geometry::meshTruncBox(float tD) { // t/D
+    if (tD <= 0)
+        return meshBox();
 
-  flt const D = .5f, t = D * (1 - qMin(tD, 1.f));
-  xyz_vec vs; vs.reserve(150);
+    float const D = .5f, t = D * (1 - qMin(tD, 1.f));
+    Vertices vs; vs.reserve(150);
 
-  QVector<flt> as({+D, +t, -t, -D, -D, -t, +t, +D});
-  QVector<flt> bs({+t, +D, +D, +t, -t, -D, -D, -t});
+    QVector<float> as({+D, +t, -t, -D, -D, -t, +t, +D});
+    QVector<float> bs({+t, +D, +D, +t, -t, -D, -D, -t});
 
-  auto side = [&](int ax, int ay, int az, int bx, int by, int bz,
-                  xyz::rc d, bool rev) {
-    xyz_vec vs_(8);
-    for_i (8)
-      vs_[rev ? 7-i : i] =
-        xyz(ax*as.at(i) + bx*bs.at(i),
-            ay*as.at(i) + by*bs.at(i),
-            az*as.at(i) + bz*bs.at(i)) + d;
-    vs.addFan(vs_, {0,1,2,3,4,5,6,7,0});
-  };
+    auto side = [&](int ax, int ay, int az, int bx, int by, int bz,
+                const Vector3D& d, bool rev) {
+        Vertices vs_(8);
+        for(int i=0; i<8; ++i)
+            vs_[rev ? 7-i : i] =
+                    Vector3D(ax*as.at(i) + bx*bs.at(i),
+                             ay*as.at(i) + by*bs.at(i),
+                             az*as.at(i) + bz*bs.at(i)) + d;
+        vs.addFan(vs_, {0,1,2,3,4,5,6,7,0});
+    };
 
-  auto corner = [&](int x, int y, int z) {
-    xyz_vec vs_({{D*x,D*y,t*z},{D*x,t*y,D*z},{t*x,D*y,D*z}});
-    if (x*y*z > 0)
-      vs.addTrig(vs_.at(0), vs_.at(2), vs_.at(1));
-    else
-      vs.addTrig(vs_.at(0), vs_.at(1), vs_.at(2));
-  };
+    auto corner = [&](int x, int y, int z) {
+        Vertices vs_({{D*x,D*y,t*z},{D*x,t*y,D*z},{t*x,D*y,D*z}});
+        if (x*y*z > 0)
+            vs.addTriangle(vs_.at(0), vs_.at(2), vs_.at(1));
+        else
+            vs.addTriangle(vs_.at(0), vs_.at(1), vs_.at(2));
+    };
 
-  side(0,1,0, 0,0,1, xyz(+D,0,0), false);
-  side(0,1,0, 0,0,1, xyz(-D,0,0), true);
-  side(1,0,0, 0,0,1, xyz(0,+D,0), true);
-  side(1,0,0, 0,0,1, xyz(0,-D,0), false);
-  side(1,0,0, 0,1,0, xyz(0,0,+D), false);
-  side(1,0,0, 0,1,0, xyz(0,0,-D), true);
+    side(0,1,0, 0,0,1, Vector3D(+D,0,0), false);
+    side(0,1,0, 0,0,1, Vector3D(-D,0,0), true);
+    side(1,0,0, 0,0,1, Vector3D(0,+D,0), true);
+    side(1,0,0, 0,0,1, Vector3D(0,-D,0), false);
+    side(1,0,0, 0,1,0, Vector3D(0,0,+D), false);
+    side(1,0,0, 0,1,0, Vector3D(0,0,-D), true);
 
-  for (int x : {-1, +1})
-    for (int y : {-1, +1})
-      for (int z : {-1, +1})
-        corner(x, y, z);
+    for (int x : {-1, +1})
+        for (int y : {-1, +1})
+            for (int z : {-1, +1})
+                corner(x, y, z);
 
-  ENSURE(150 == vs.count())
+    Q_ASSERT(150 == vs.count());
 
-  return makeMesh(vs);
+    return makeMesh(vs);
 }
 
-//------------------------------------------------------------------------------
-}
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/model/geometry_inc.cpp b/GUI/ba3d/ba3d/model/geometry_inc.cpp
index c2161715a5e0058f104b4643f194c524f924bb98..ee015269d059244c2e623ff97738df7baee0d192 100644
--- a/GUI/ba3d/ba3d/model/geometry_inc.cpp
+++ b/GUI/ba3d/ba3d/model/geometry_inc.cpp
@@ -13,40 +13,32 @@
 // ************************************************************************** //
 
 #include "geometry_inc.h"
-#include <qmath.h>
+#include <cmath>
+#include <functional>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
-flt const geometry::goldenRatio     = flt(1 + qSqrt(5)) / 2;
-flt const geometry::icosahedronL2R  = flt(4 / (10 + 2*qSqrt(5)));
-flt const geometry::dodecahedronL2R = flt(4 / qSqrt(3) / (1+qSqrt(5)));
+// Useful constants:
+const float GoldenRatio     = (1.f + std::sqrt(5.f)) / 2.f;
+const float IcosahedronL2R  = 4.f / (10.f + 2.f*std::sqrt(5.f));
+const float DodecahedronL2R = 4.f / std::sqrt(3.f) / (1.f+std::sqrt(5.f));
 
-//------------------------------------------------------------------------------
-
-geometry::key::key(geometry::eid id) : key(id, 0, 0) {}
-
-geometry::key::key(geometry::eid id, flt p1) : key(id, p1, 0) {}
-
-geometry::key::key(eid id_, flt p1_, flt p2_)
-  : id(id_), p1(p1_), p2(p2_) {
+// Keys and hash:
+GeometricID::Key::Key(BaseShape id_, float p1_, float p2_)
+    : id(id_), p1(p1_), p2(p2_) {
 }
 
-bool geometry::key::operator==(key const& that) const {
-  return id == that.id && p1 == that.p1 && p2 == that.p2;
-}
-
-uint geometry::qHash(geometry::key const& key) {
-  // the hash is simply a bitwise superposition of id, p1, p2
-  union {
-    flt           f;
-    quint32       u;
-    geometry::eid i;
-  } id, p1, p2;
-
-  id.i = key.id; p1.f = key.p1; p2.f = key.p2;
-  return id.u | p1.u | p2.u;
+bool GeometricID::Key::operator==(Key const& other) const {
+    return id == other.id && p1 == other.p1 && p2 == other.p2;
 }
 
-//------------------------------------------------------------------------------
+std::size_t GeometricID::KeyHash::operator()(const GeometricID::Key& key) const noexcept
+{
+    {
+        size_t h1 = std::hash<int>{}(static_cast<int>(key.id));
+        size_t h2 = std::hash<float>{}(key.p1);
+        size_t h3 = std::hash<float>{}(key.p2);
+        return h1 ^ (h2 ^ h3);
+    }
 }
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/model/geometry_inc.h b/GUI/ba3d/ba3d/model/geometry_inc.h
index 8e2017d1e7fa25332295a06abef9660808a6ef7d..3b09c443071471a6b654e55979b2d93b52b29e22 100644
--- a/GUI/ba3d/ba3d/model/geometry_inc.h
+++ b/GUI/ba3d/ba3d/model/geometry_inc.h
@@ -16,46 +16,48 @@
 #define BA3D_GEOMETRY_INC_H
 
 #include "../def.h"
-#include <QSharedPointer>
+#include <memory>
 
 // include to use geometry basics, without details
 
-namespace ba3d {
+namespace RealSpace {
 //------------------------------------------------------------------------------
 
 class Geometry;
 
-typedef QSharedPointer<Geometry> shGeo;
-typedef QWeakPointer<Geometry>   wkGeo;
+typedef std::shared_ptr<Geometry> GeometryHandle;
+typedef std::weak_ptr<Geometry>   GeometryRef;
 
-namespace geometry {
+// some useful constants:
+extern const float GoldenRatio;
+extern const float IcosahedronL2R;  // L/R conversion
+extern const float DodecahedronL2R;
 
-// geometry enumerated id
-enum class eid { Plane, Box, Sphere, Column,
+namespace GeometricID {
+
+// Enum id for basic shapes
+enum class BaseShape { Plane, Box, Sphere, Column,
                  Icosahedron, Dodecahedron, TruncatedBox,
                  Cuboctahedron };
 
-// these come useful
-extern flt const goldenRatio;
-extern flt const icosahedronL2R;  // L/R conversion
-extern flt const dodecahedronL2R;
 
-// geometries may have 1 or 2 flt parameters; together with eid -> hash key
-struct key {
-  key(eid);
-  key(eid, flt);
-  key(eid, flt, flt);
+// Real shapes will be parameterized by BaseShape enum and possibly two floats
+struct Key {
+    Key(BaseShape, float=0.0f, float=0.0f);
 
-  eid id;
-  flt p1, p2;
+    bool operator==(Key const&) const;
 
-  bool operator==(key const&) const;
+    BaseShape id;
+    float p1, p2;
 };
 
-uint qHash(key const&);
+// Hash functor for Key objects
+struct KeyHash
+{
+    std::size_t operator()(const Key& key) const noexcept;
+};
 
-}
+} // namespace GeometricID
+} // namespace RealSpace
 
-//------------------------------------------------------------------------------
-}
-#endif
+#endif // BA3D_GEOMETRY_INC_H
diff --git a/GUI/ba3d/ba3d/model/layer.cpp b/GUI/ba3d/ba3d/model/layer.cpp
index a5cf71c7aceb2e8aabf19448462a2f7c1b17c4ba..733083dd6257a1683a7a26e48cce9e7df233da9e 100644
--- a/GUI/ba3d/ba3d/model/layer.cpp
+++ b/GUI/ba3d/ba3d/model/layer.cpp
@@ -14,12 +14,10 @@
 
 #include "layer.h"
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
-Layer::Layer(dxyz d) : base(geometry::key(geometry::eid::Box)) {
-  transform(d.size(), xyz::_0, d.mid());
-}
-
-//------------------------------------------------------------------------------
+Layer::Layer(VectorRange d) : Object(GeometricID::Key(GeometricID::BaseShape::Box))
+{
+    transform(d.size(), Vector3D::_0, d.mid());
 }
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/model/layer.h b/GUI/ba3d/ba3d/model/layer.h
index a1ad17332545a518daacd57157a73568fd8c7a1c..3c6803ebd34bb26b5aff40a26267a69ecb189bd3 100644
--- a/GUI/ba3d/ba3d/model/layer.h
+++ b/GUI/ba3d/ba3d/model/layer.h
@@ -17,15 +17,13 @@
 
 #include "object.h"
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
 // particle layer: a transparent box
-class Layer : public Object { BASE(Object)
+class Layer : public Object
+{
 public:
-  Layer(dxyz);
+    Layer(VectorRange);
 };
-
-//------------------------------------------------------------------------------
-}
-#endif
+}  // namespace RealSpace
+#endif  // BA3D_LAYER_H
diff --git a/GUI/ba3d/ba3d/model/model.cpp b/GUI/ba3d/ba3d/model/model.cpp
index 1003066529a64ba6baabbc42a599184894ea85e9..207558f6d2f69e62d33885d8e57e2ec8b5f777a4 100644
--- a/GUI/ba3d/ba3d/model/model.cpp
+++ b/GUI/ba3d/ba3d/model/model.cpp
@@ -15,127 +15,126 @@
 #include "model.h"
 #include "geometry.h"
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
-Model::Model() : defCamPos(xyz::_1, xyz::_0, xyz::_z) {}
+Model::Model() : defCamPos(Vector3D::_1, Vector3D::_0, Vector3D::_z) {}
 
 Model::~Model() {
-  for (auto o: objects) {
-    o->model = nullptr;
-    delete o;
-  }
-
-  for (auto o: objectsBlend) {
-    o->model = nullptr;
-    delete o;
-  }
+    for (auto o: objects) {
+        o->model = nullptr;
+        delete o;
+    }
+
+    for (auto o: objectsBlend) {
+        o->model = nullptr;
+        delete o;
+    }
 }
 
 void Model::clearOpaque() {
-  while (!objects.isEmpty())
-    delete objects.first();
-  emit updated(false);
+    while (!objects.isEmpty())
+        delete objects.first();
+    emit updated(false);
 }
 
 void Model::clearBlend() {
-  while (!objectsBlend.isEmpty())
-    delete objectsBlend.first();
-  emit updated(false);
+    while (!objectsBlend.isEmpty())
+        delete objectsBlend.first();
+    emit updated(false);
 }
 
-particle::Particle* Model::newParticle(particle::kind k, flp R) {
-  using namespace particle;
-
-  flp D = 2*R;
-
-  switch (k) {
-  case kind::None:
+Particles::Particle* Model::newParticle(Particles::EShape k, float R) {
+    using namespace Particles;
+
+    float D = 2*R;
+
+    switch (k) {
+    case EShape::None:
+        return nullptr;
+    case EShape::FullSphere:
+        return new FullSphere(R);
+    case EShape::FullSpheroid:
+        return new FullSpheroid(R/2, D);
+    case EShape::Cylinder:
+        return new Cylinder(R, D);
+    case EShape::TruncatedSphere:
+        return new TruncatedSphere(R, D/3);
+    case EShape::TruncatedSpheroid:
+        return new TruncatedSpheroid(R, 2*R, 1.5);
+    case EShape::Cone:
+        return new Cone(R, D, 1.3f);
+    case EShape::Icosahedron:
+        return new Icosahedron(R * IcosahedronL2R);
+    case EShape::Dodecahedron:
+        return new Dodecahedron(R * DodecahedronL2R);
+    case EShape::TruncatedCube:
+        return new TruncatedCube(D, D/3);
+    case EShape::Prism6:
+        return new Prism6(R, D);
+    case EShape::Cone6:
+        return new Cone6(R, D, 1.3f);
+    case EShape::Pyramid:
+        return new Pyramid(D, D, 1.3f);
+    case EShape::Cuboctahedron:
+        return new Cuboctahedron(D, R*3/2, 2.f/3, 2);
+    case EShape::Prism3:
+        return new Prism3(R, D);
+    case EShape::Tetrahedron:
+        return new Tetrahedron(R, D, 1.3f);
+    case EShape::EllipsoidalCylinder:
+        return new EllipsoidalCylinder(R, R/2, D);
+    case EShape::Box:
+        return new Box(D, D, D);
+    case EShape::HemiEllipsoid:
+        return new HemiEllipsoid(R, R, D);
+    case EShape::AnisoPyramid:
+        return new AnisoPyramid(R, D, D, 1.3f);
+    }
     return nullptr;
-  case kind::FullSphere:
-    return new FullSphere(R);
-  case kind::FullSpheroid:
-    return new FullSpheroid(R/2, D);
-  case kind::Cylinder:
-    return new Cylinder(R, D);
-  case kind::TruncatedSphere:
-    return new TruncatedSphere(R, D/3);
-  case kind::TruncatedSpheroid:
-    return new TruncatedSpheroid(R, 2*R, 1.5);
-  case kind::Cone:
-    return new Cone(R, D, 1.3f);
-  case kind::Icosahedron:
-    return new Icosahedron(R * geometry::icosahedronL2R);
-  case kind::Dodecahedron:
-    return new Dodecahedron(R * geometry::dodecahedronL2R);
-  case kind::TruncatedCube:
-    return new TruncatedCube(D, D/3);
-  case kind::Prism6:
-    return new Prism6(R, D);
-  case kind::Cone6:
-    return new Cone6(R, D, 1.3f);
-  case kind::Pyramid:
-    return new Pyramid(D, D, 1.3f);
-  case kind::Cuboctahedron:
-    return new Cuboctahedron(D, R*3/2, 2.f/3, 2);
-  case kind::Prism3:
-    return new Prism3(R, D);
-  case kind::Tetrahedron:
-    return new Tetrahedron(R, D, 1.3f);
-  case kind::EllipsoidalCylinder:
-    return new EllipsoidalCylinder(R, R/2, D);
-  case kind::Box:
-    return new Box(D, D, D);
-  case kind::HemiEllipsoid:
-    return new HemiEllipsoid(R, R, D);
-  case kind::AnisoPyramid:
-    return new AnisoPyramid(R, D, D, 1.3f);
-  }
-
-  return nullptr;
 }
 
 void Model::add(Object* o) {
-  EXPECT(o) EXPECT(!o->model)
-  o->model = this;
-  objects.append(o);
+    Q_ASSERT(o);
+    Q_ASSERT(!o->model);
+    o->model = this;
+    objects.append(o);
 }
 
 void Model::addBlend(Object* o) {
-  EXPECT(o) EXPECT(!o->model)
-  o->model = this;
-  objectsBlend.append(o);
+    Q_ASSERT(o);
+    Q_ASSERT(!o->model);
+    o->model = this;
+    objectsBlend.append(o);
 }
 
 void Model::rem(Object* o) {
-  int i;
-  if ((i = objects.indexOf(o)) >= 0)
-    objects.remove(i);
-  else if ((i = objectsBlend.indexOf(o)) >= 0)
-    objectsBlend.remove(i);
-  else
-    EXPECT(false); // object not found, should not happen, bad caller!
-
-  o->releaseGeometry();
-  o->model = nullptr;
+    int i;
+    if ((i = objects.indexOf(o)) >= 0)
+        objects.remove(i);
+    else if ((i = objectsBlend.indexOf(o)) >= 0)
+        objectsBlend.remove(i);
+    else
+        Q_ASSERT(false); // object not found, should not happen, bad caller!
+
+    o->releaseGeometry();
+    o->model = nullptr;
 }
 
 void Model::releaseGeometries() {
-  for (auto o: objects)
-    o->releaseGeometry();
-  for (auto o: objectsBlend)
-    o->releaseGeometry();
+    for (auto o: objects)
+        o->releaseGeometry();
+    for (auto o: objectsBlend)
+        o->releaseGeometry();
 }
 
 void Model::draw(Canvas& canvas) const {
-  for (auto o: objects)
-    o->draw(canvas);
+    for (auto o: objects)
+        o->draw(canvas);
 }
 
 void Model::drawBlend(Canvas& canvas) const {
-  for (auto o: objectsBlend)
-    o->draw(canvas);
+    for (auto o: objectsBlend)
+        o->draw(canvas);
 }
 
-//------------------------------------------------------------------------------
-}
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/model/model.h b/GUI/ba3d/ba3d/model/model.h
index 7eec36cd33dbbfc3b544e7b912d8c65f0832123b..014aae9531730b6e44f29c484801249db7a7b51a 100644
--- a/GUI/ba3d/ba3d/model/model.h
+++ b/GUI/ba3d/ba3d/model/model.h
@@ -19,48 +19,46 @@
 #include "object.h"
 #include "particles.h"
 #include <QVector>
-#include <QHash>
 
-namespace ba3d {
+namespace RealSpace {
 //------------------------------------------------------------------------------
 
 class Canvas;
 class Object;
 
 class Model : public QObject {
-  Q_OBJECT
-  friend class Canvas;
-  friend class Camera;
-  friend class Object;
+    Q_OBJECT
+    friend class Canvas;
+    friend class Camera;
+    friend class Object;
 public:
-  Model();
-  virtual ~Model();
+    Model();
+    virtual ~Model();
 
-  void clearOpaque();
-  void clearBlend();
+    void clearOpaque();
+    void clearBlend();
 
-  static particle::Particle* newParticle(particle::kind k, ba3d::flp R);
+    static Particles::Particle* newParticle(Particles::EShape k, float R);
 
-  void add(Object*);        // add an opaque object, the model takes ownership
-  void addBlend(Object*);   // add a transparent object, the model takes ownership
-  void rem(Object*);        // removes an object, the caller becomes responsible
+    void add(Object*);        // add an opaque object, the model takes ownership
+    void addBlend(Object*);   // add a transparent object, the model takes ownership
+    void rem(Object*);        // removes an object, the caller becomes responsible
 
-  void releaseGeometries(); // may be called any time
+    void releaseGeometries(); // may be called any time
 
-  virtual void cameraUpdated(Camera const&) {}
+    virtual void cameraUpdated(Camera const&) {}
 
-  Camera::pos_t defCamPos;    // default camera params
+    Camera::Position defCamPos;    // default camera params
 
 signals:
-  void updated(bool withEye);
+    void updated(bool withEye);
 
 private:
-  QVector<Object*> objects, objectsBlend;
+    QVector<Object*> objects, objectsBlend;
 
-  void draw(Canvas&)      const;
-  void drawBlend(Canvas&) const;
+    void draw(Canvas&)      const;
+    void drawBlend(Canvas&) const;
 };
 
-//------------------------------------------------------------------------------
-}
-#endif
+}  // namespace RealSpace
+#endif  // BA3D_MODEL_H
diff --git a/GUI/ba3d/ba3d/model/object.cpp b/GUI/ba3d/ba3d/model/object.cpp
index 55544f74c6d8a571a0d3e0a2efbfa36850fb25e4..8a52f297a478634ca7c3d5c624c4922a9d388429 100644
--- a/GUI/ba3d/ba3d/model/object.cpp
+++ b/GUI/ba3d/ba3d/model/object.cpp
@@ -17,8 +17,7 @@
 #include "geometry.h"
 #include "../view/canvas.h"
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
 #ifdef Q_OS_LINUX
 QColor const clrObject = Qt::lightGray;
@@ -26,52 +25,57 @@ QColor const clrObject = Qt::lightGray;
 QColor const clrObject = Qt::black;
 #endif
 
-Object::Object(geometry::key gky_) : color(clrObject)
-, isNull(false), model(nullptr), gky(gky_) {
-}
+Object::Object(GeometricID::Key gky_)
+    : color(clrObject)
+    , isNull(false), model(nullptr), gky(gky_)
+{}
 
-Object::~Object() {
-  releaseGeometry();
-  if (model)
-    model->rem(this);
+Object::~Object()
+{
+    releaseGeometry();
+    if (model)
+        model->rem(this);
 }
 
-void Object::transform(flt scale, xyz rotate, xyz translate) {
-  transform(xyz(scale,scale,scale), rotate, translate);
+void Object::transform(float scale, Vector3D rotate, Vector3D translate)
+{
+    transform(Vector3D(scale,scale,scale), rotate, translate);
 }
 
-void Object::transform(xyz scale, xyz rotate, xyz translate) {
-  mat.setToIdentity();
-  mat.translate(translate);
-  mat.rotate(QQuaternion::fromEulerAngles(rotate));
-  mat.scale(scale);
+void Object::transform(Vector3D scale, Vector3D rotate, Vector3D translate)
+{
+    mat.setToIdentity();
+    mat.translate(translate);
+    mat.rotate(QQuaternion::fromEulerAngles(rotate));
+    mat.scale(scale);
 }
 
-void Object::transform(xyz turn, xyz scale, xyz rotate, xyz translate) {
-  // 1. turn to align with x/y/z as needed
-  // 2. scale to desired x/y/z size
-  // 3. rotate as needed by the scene
-  // 4. move to the position
-
-  mat.setToIdentity();
-  mat.translate(translate);
-  mat.rotate(QQuaternion::fromEulerAngles(rotate));
-  mat.scale(scale);
-  mat.rotate(QQuaternion::fromEulerAngles(turn));
+void Object::transform(Vector3D turn, Vector3D scale, Vector3D rotate, Vector3D translate)
+{
+    // 1. turn to align with x/y/z as needed
+    // 2. scale to desired x/y/z size
+    // 3. rotate as needed by the scene
+    // 4. move to the position
+    mat.setToIdentity();
+    mat.translate(translate);
+    mat.rotate(QQuaternion::fromEulerAngles(rotate));
+    mat.scale(scale);
+    mat.rotate(QQuaternion::fromEulerAngles(turn));
 }
 
-void Object::releaseGeometry() {
-  geo.clear();
+void Object::releaseGeometry()
+{
+    geo.reset();
 }
 
-void Object::draw(Canvas& canvas) {
-  if (isNull)
-    return;
+void Object::draw(Canvas& canvas)
+{
+    if (isNull)
+        return;
 
-  if (!geo)
-    geo = geometryStore().getGeometry(gky);
-  canvas.draw(color, mat, *geo);
+    if (!geo)
+        geo = geometryStore().getGeometry(gky);
+    canvas.draw(color, mat, *geo);
 }
 
-//------------------------------------------------------------------------------
-}
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/model/object.h b/GUI/ba3d/ba3d/model/object.h
index d7f7304ecb35b242e10ca4b510ce6402572f6ee2..a2174d541e5fb380e0b835ce86d5fce6874567cb 100644
--- a/GUI/ba3d/ba3d/model/object.h
+++ b/GUI/ba3d/ba3d/model/object.h
@@ -20,39 +20,37 @@
 #include <QColor>
 #include <QMatrix4x4>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
 class Model;
 class Canvas;
 
 class Object {
-  friend class Model;
+    friend class Model;
 public:
-  Object(geometry::key);
-  virtual ~Object();
+    Object(GeometricID::Key);
+    virtual ~Object();
 
-  QColor color;
+    QColor color;
 
-  void transform(flt scale, xyz rotate, xyz translate);
-  void transform(xyz scale, xyz rotate, xyz translate);
-  void transform(xyz scale, QQuaternion, xyz translate);
-  void transform(xyz turn, xyz scale, xyz rotate, xyz translate);
+    void transform(float scale, Vector3D rotate, Vector3D translate);
+    void transform(Vector3D scale, Vector3D rotate, Vector3D translate);
+    void transform(Vector3D scale, QQuaternion, Vector3D translate);
+    void transform(Vector3D turn, Vector3D scale, Vector3D rotate, Vector3D translate);
 
 protected:
-  bool isNull;
+    bool isNull;
 
 private:
-  Model *model;
+    Model *model;
 
-  geometry::key gky;
-  shGeo         geo;      // retrieved on demand
-  void releaseGeometry(); // can be released whenever
+    GeometricID::Key gky;
+    GeometryHandle geo;      // retrieved on demand
+    void releaseGeometry(); // can be released whenever
 
-  QMatrix4x4 mat;
-  void draw(Canvas&);
+    QMatrix4x4 mat;
+    void draw(Canvas&);
 };
 
-//------------------------------------------------------------------------------
-}
-#endif
+}  // namespace RealSpace
+#endif  // BA3D_OBJECT_H
diff --git a/GUI/ba3d/ba3d/model/particles.cpp b/GUI/ba3d/ba3d/model/particles.cpp
index f8a818f262663224ed1bb5b2dd85027de2dca0c0..d08922c1e97282ad748ffe398b95d903885b6eca 100644
--- a/GUI/ba3d/ba3d/model/particles.cpp
+++ b/GUI/ba3d/ba3d/model/particles.cpp
@@ -13,166 +13,227 @@
 // ************************************************************************** //
 
 #include "particles.h"
-#include <qmath.h>
-#include <math.h>
+#include <cmath>
 
-namespace ba3d { namespace particle {
-//------------------------------------------------------------------------------
-
-QString const& name(kind k) {
-  static QString names[] = {
-    "", "FullSphere", "FullSpheroid", "Cylinder", "TruncatedSphere",
-    "TruncatedSpheroid", "Cone", "Icosahedron", "Dodecahedron", "TruncatedCube",
-    "Prism6", "Cone6", "Pyramid", "Cuboctahedron", "Prism3", "Tetrahedron",
-    "EllipsoidalCylinder", "Box", "HemiEllipsoid", "AnisoPyramid",
-  };
+namespace RealSpace { namespace Particles {
 
-  return names[uint(k)];
+QString const& name(EShape k)
+{
+    static QString names[] = {
+        "", "FullSphere", "FullSpheroid", "Cylinder", "TruncatedSphere",
+        "TruncatedSpheroid", "Cone", "Icosahedron", "Dodecahedron", "TruncatedCube",
+        "Prism6", "Cone6", "Pyramid", "Cuboctahedron", "Prism3", "Tetrahedron",
+        "EllipsoidalCylinder", "Box", "HemiEllipsoid", "AnisoPyramid",
+    };
+    return names[uint(k)];
 }
 
 //------------------------------------------------------------------------------
 
-using namespace geometry;
+using namespace GeometricID;
 
-Particle::Particle(key key) : base(key), scale(xyz::_1) {}
+Particle::Particle(Key key)
+    : Object(key)
+    , scale(Vector3D::_1)
+{}
 
-void Particle::set() {
-  transform(xyz::_0, xyz::_0);
+void Particle::set()
+{
+    transform(Vector3D::_0, Vector3D::_0);
 }
 
-void Particle::transform(xyz rotate_, xyz translate_) {
-  base::transform(turn, scale,
-                  (rotate = rotate_), offset + (translate = translate_));
+void Particle::transform(Vector3D rotate_, Vector3D translate_)
+{
+    Object::transform(turn, scale, (rotate = rotate_), offset + (translate = translate_));
 }
 
-void Particle::fancy(xyz rotate, flt r) {
-  base::transform(turn, scale*r, rotate, offset + translate);
+void Particle::fancy(Vector3D rotate, float r)
+{
+    Object::transform(turn, scale*r, rotate, offset + translate);
 }
 
 //------------------------------------------------------------------------------
 
-static flt const pi2f   = flt(M_PI_2);
-static flt const sqrt2f = flt(qSqrt(2));
-static flt const sqrt3f = flt(qSqrt(3));
-
-FullSphere::FullSphere(flp R)
-: Particle(key(eid::Sphere, 0)) {
-  isNull = (R <= 0);
-  scale  = xyz(R*2); offset = xyz(0, 0, R); set();
-}
-
-FullSpheroid::FullSpheroid(flp R, flp H)
-: Particle(key(eid::Sphere, 0)) {
-  isNull = (R <= 0 || H <= 0);
-  scale  = xyz(R*2, R*2, H); offset = xyz(0, 0, H/2); set();
-}
-
-Cylinder::Cylinder(flp R, flp H)
-: Particle(key(eid::Column, pi2f, 0)) {
-  isNull = (R <= 0 || H <= 0);
-  scale  = xyz(R*2, R*2, H); offset = xyz(0, 0, H/2); set();
-}
-
-TruncatedSphere::TruncatedSphere(flp R, flp H)
-: Particle(key(eid::Sphere, 1 - H/R/2)) {
-  isNull = (R <= 0 || H <= 0);
-  scale  = xyz(R*2); offset = xyz(0, 0, H-R); set();
-}
-
-TruncatedSpheroid::TruncatedSpheroid(flp R, flp H, flp fp)
-: Particle(key(eid::Sphere, 1 - H/fp/R/2)) {
-  isNull = (R <= 0 || H <= 0 || fp <= 0);
-  scale  = xyz(R*2, R*2, fp*R*2); offset = xyz(0, 0, H-fp*R); set();
-}
-
-Cone::Cone(flp R, flp H, flp alpha)
-: Particle(key(eid::Column, alpha, 0)) {
-  isNull = (R <= 0 || H <= 0 || alpha <= 0);
-  scale  = xyz(R*2, R*2, H); offset = xyz(0, 0, H/2); set();
-}
-
-Icosahedron::Icosahedron(flp L)
-: Particle(key(eid::Icosahedron)) {
-  isNull = (L <= 0);
-  flp R = L / icosahedronL2R;
-  scale  = xyz(R*2, R*2, R*2); offset = xyz(0, 0, R); set();
-}
-
-Dodecahedron::Dodecahedron(flp L)
-: Particle(key(eid::Dodecahedron)) {
-  isNull = (L <= 0);
-  flp R = L / dodecahedronL2R;
-  scale  = xyz(R*2, R*2, R*2); offset = xyz(0, 0, R); set();
-}
-
-TruncatedCube::TruncatedCube(flp L, flp t)
-: Particle(key(eid::TruncatedBox, 2*t/L)) {
-  isNull = (L <= 0);
-  scale  = xyz(L,L,L); offset = xyz(0, 0, L/2); set();
-}
-
-Prism6::Prism6(flp R, flp H)
-: Particle(key(eid::Column, pi2f, 6)) {
-  isNull = (R <= 0 || H <= 0);
-  scale  = xyz(R*2, R*2, H); offset = xyz(0, 0, H/2); set();
-}
-
-Cone6::Cone6(flp R, flp H, flp alpha)
-: Particle(key(eid::Column, alpha, 6)) {
-  isNull = (R <= 0 || H <= 0 || alpha <= 0);
-  scale  = xyz(R*2, R*2, H); offset = xyz(0, 0, H/2); set();
-}
-
-Pyramid::Pyramid(flp L, flp H, flp alpha)
-: Particle(key(eid::Column, alpha, 4)) {
-  isNull = (L <= 0 || H <= 0 || alpha <= 0);
-  flt L2 = L * sqrt2f;
-  turn = xyz(0,0,45); scale  = xyz(L2, L2, H); offset = xyz(0, 0, H/2); set();
-}
-
-Cuboctahedron::Cuboctahedron(flp L, flp H, flp rH, flp alpha)
-: Particle(key(eid::Cuboctahedron, rH, alpha)) {
-  isNull = (L <= 0 || H <= 0 || rH <= 0 || alpha <= pi2f);
-  scale  = xyz(L, L, L); offset = xyz(0, 0, L/2); set();
-}
-
-Prism3::Prism3(flp L, flp H)
-: Particle(key(eid::Column, pi2f, 3)) {
-  isNull = (L <= 0 || H <= 0);
-  flt D = L*2 / sqrt3f;
-  scale = xyz(D*2, D*2, H); offset = xyz(0, 0, H/2); set();
-}
-
-Tetrahedron::Tetrahedron(flp L, flp H, flp alpha)
-: Particle(key(eid::Column, alpha, 3)) {
-  isNull = (L <= 0 || H <= 0 || alpha <= 0);
-  flt D = L*2 / sqrt3f;
-  scale = xyz(D*2, D*2, H); offset = xyz(0, 0, H/2); set();
-}
-
-EllipsoidalCylinder::EllipsoidalCylinder(flp Ra, flp Rb, flp H)
-: Particle(key(eid::Column, pi2f, 0)) {
-  isNull = (Ra <= 0 || Rb <= 0 || H <= 0);
-  scale  = xyz(Ra*2, Rb*2, H); offset = xyz(0, 0, H/2); set();
-}
-
-Box::Box(flp L, flp W, flp H)
-: Particle(key(eid::Column, pi2f, 4)) {
-  isNull = (L < 0 || W < 0 || H < 0) || (L <= 0 && W <= 0 && H <= 0);
-  turn = xyz(0,0,45); scale  = xyz(L*sqrt2f, W*sqrt2f, H); offset = xyz(0, 0, H/2); set();
-}
-
-HemiEllipsoid::HemiEllipsoid(flp Ra, flp Rb, flp H)
-: Particle(key(eid::Sphere, .5f)) {
-  isNull = (Ra <= 0 || Rb <= 0 || H <= 0);
-  scale  = xyz(Ra*2, Rb*2, H*2); set();
-}
-
-AnisoPyramid::AnisoPyramid(flp L, flp W, flp H, flp alpha)
-: Particle(key(eid::Column, alpha, 4)) {
-  isNull = (L <= 0 || W <= 0  || H <= 0 || alpha <= 0);
-  turn = xyz(0,0,45); scale  = xyz(L*sqrt2f, W*sqrt2f, H); offset = xyz(0, 0, H/2); set();
-}
-
-//------------------------------------------------------------------------------
-}}
+static float const pi2f   = float(M_PI_2);
+static float const sqrt2f = std::sqrt(2.f);
+static float const sqrt3f = std::sqrt(3.f);
+
+FullSphere::FullSphere(float R)
+    : Particle(Key(BaseShape::Sphere, 0))
+{
+    isNull = (R <= 0);
+    scale  = Vector3D(R*2);
+    offset = Vector3D(0, 0, R);
+    set();
+}
+
+FullSpheroid::FullSpheroid(float R, float H)
+    : Particle(Key(BaseShape::Sphere, 0))
+{
+    isNull = (R <= 0 || H <= 0);
+    scale  = Vector3D(R*2, R*2, H);
+    offset = Vector3D(0, 0, H/2);
+    set();
+}
+
+Cylinder::Cylinder(float R, float H)
+    : Particle(Key(BaseShape::Column, pi2f, 0))
+{
+    isNull = (R <= 0 || H <= 0);
+    scale  = Vector3D(R*2, R*2, H);
+    offset = Vector3D(0, 0, H/2);
+    set();
+}
+
+TruncatedSphere::TruncatedSphere(float R, float H)
+    : Particle(Key(BaseShape::Sphere, 1 - H/R/2))
+{
+    isNull = (R <= 0 || H <= 0);
+    scale  = Vector3D(R*2);
+    offset = Vector3D(0, 0, H-R);
+    set();
+}
+
+TruncatedSpheroid::TruncatedSpheroid(float R, float H, float fp)
+    : Particle(Key(BaseShape::Sphere, 1 - H/fp/R/2))
+{
+    isNull = (R <= 0 || H <= 0 || fp <= 0);
+    scale  = Vector3D(R*2, R*2, fp*R*2);
+    offset = Vector3D(0, 0, H-fp*R);
+    set();
+}
+
+Cone::Cone(float R, float H, float alpha)
+    : Particle(Key(BaseShape::Column, alpha, 0))
+{
+    isNull = (R <= 0 || H <= 0 || alpha <= 0);
+    scale  = Vector3D(R*2, R*2, H);
+    offset = Vector3D(0, 0, H/2);
+    set();
+}
+
+Icosahedron::Icosahedron(float L)
+    : Particle(Key(BaseShape::Icosahedron))
+{
+    isNull = (L <= 0);
+    float R = L / IcosahedronL2R;
+    scale  = Vector3D(R*2, R*2, R*2);
+    offset = Vector3D(0, 0, R);
+    set();
+}
+
+Dodecahedron::Dodecahedron(float L)
+    : Particle(Key(BaseShape::Dodecahedron))
+{
+    isNull = (L <= 0);
+    float R = L / DodecahedronL2R;
+    scale  = Vector3D(R*2, R*2, R*2);
+    offset = Vector3D(0, 0, R);
+    set();
+}
+
+TruncatedCube::TruncatedCube(float L, float t)
+    : Particle(Key(BaseShape::TruncatedBox, 2*t/L))
+{
+    isNull = (L <= 0);
+    scale  = Vector3D(L,L,L);
+    offset = Vector3D(0, 0, L/2);
+    set();
+}
+
+Prism6::Prism6(float R, float H)
+    : Particle(Key(BaseShape::Column, pi2f, 6))
+{
+    isNull = (R <= 0 || H <= 0);
+    scale  = Vector3D(R*2, R*2, H);
+    offset = Vector3D(0, 0, H/2);
+    set();
+}
+
+Cone6::Cone6(float R, float H, float alpha)
+    : Particle(Key(BaseShape::Column, alpha, 6))
+{
+    isNull = (R <= 0 || H <= 0 || alpha <= 0);
+    scale  = Vector3D(R*2, R*2, H);
+    offset = Vector3D(0, 0, H/2);
+    set();
+}
+
+Pyramid::Pyramid(float L, float H, float alpha)
+    : Particle(Key(BaseShape::Column, alpha, 4))
+{
+    isNull = (L <= 0 || H <= 0 || alpha <= 0);
+    float L2 = L * sqrt2f;
+    turn = Vector3D(0,0,45);
+    scale  = Vector3D(L2, L2, H);
+    offset = Vector3D(0, 0, H/2);
+    set();
+}
+
+Cuboctahedron::Cuboctahedron(float L, float H, float rH, float alpha)
+    : Particle(Key(BaseShape::Cuboctahedron, rH, alpha))
+{
+    isNull = (L <= 0 || H <= 0 || rH <= 0 || alpha <= pi2f);
+    scale  = Vector3D(L, L, L);
+    offset = Vector3D(0, 0, L/2);
+    set();
+}
+
+Prism3::Prism3(float L, float H)
+    : Particle(Key(BaseShape::Column, pi2f, 3))
+{
+    isNull = (L <= 0 || H <= 0);
+    float D = L*2 / sqrt3f;
+    scale = Vector3D(D*2, D*2, H);
+    offset = Vector3D(0, 0, H/2);
+    set();
+}
+
+Tetrahedron::Tetrahedron(float L, float H, float alpha)
+    : Particle(Key(BaseShape::Column, alpha, 3))
+{
+    isNull = (L <= 0 || H <= 0 || alpha <= 0);
+    float D = L*2 / sqrt3f;
+    scale = Vector3D(D*2, D*2, H);
+    offset = Vector3D(0, 0, H/2);
+    set();
+}
+
+EllipsoidalCylinder::EllipsoidalCylinder(float Ra, float Rb, float H)
+    : Particle(Key(BaseShape::Column, pi2f, 0))
+{
+    isNull = (Ra <= 0 || Rb <= 0 || H <= 0);
+    scale  = Vector3D(Ra*2, Rb*2, H);
+    offset = Vector3D(0, 0, H/2);
+    set();
+}
+
+Box::Box(float L, float W, float H)
+    : Particle(Key(BaseShape::Column, pi2f, 4))
+{
+    isNull = (L < 0 || W < 0 || H < 0) || (L <= 0 && W <= 0 && H <= 0);
+    turn = Vector3D(0,0,45);
+    scale  = Vector3D(L*sqrt2f, W*sqrt2f, H);
+    offset = Vector3D(0, 0, H/2);
+    set();
+}
+
+HemiEllipsoid::HemiEllipsoid(float Ra, float Rb, float H)
+    : Particle(Key(BaseShape::Sphere, .5f))
+{
+    isNull = (Ra <= 0 || Rb <= 0 || H <= 0);
+    scale  = Vector3D(Ra*2, Rb*2, H*2);
+    set();
+}
+
+AnisoPyramid::AnisoPyramid(float L, float W, float H, float alpha)
+    : Particle(Key(BaseShape::Column, alpha, 4))
+{
+    isNull = (L <= 0 || W <= 0  || H <= 0 || alpha <= 0);
+    turn = Vector3D(0,0,45);
+    scale  = Vector3D(L*sqrt2f, W*sqrt2f, H);
+    offset = Vector3D(0, 0, H/2);
+    set();
+}
+
+}}  // namespace RealSpace::Particles
diff --git a/GUI/ba3d/ba3d/model/particles.h b/GUI/ba3d/ba3d/model/particles.h
index d77484afffd6e8e0a8aba7e4a2083f11a204c91f..803993418e9a3f768ea474876e10a1f75ae3e778 100644
--- a/GUI/ba3d/ba3d/model/particles.h
+++ b/GUI/ba3d/ba3d/model/particles.h
@@ -17,137 +17,155 @@
 
 #include "object.h"
 
-namespace ba3d { namespace particle {
-//------------------------------------------------------------------------------
+namespace RealSpace { namespace Particles {
 
-enum class kind {
-  None,
-  FullSphere, FullSpheroid, Cylinder, TruncatedSphere, TruncatedSpheroid,
-  Cone, Icosahedron, Dodecahedron, TruncatedCube, Prism6, Cone6, Pyramid,
-  Cuboctahedron, Prism3, Tetrahedron, EllipsoidalCylinder, Box,
-  HemiEllipsoid, AnisoPyramid,
+enum class EShape {
+    None,
+    FullSphere, FullSpheroid, Cylinder, TruncatedSphere, TruncatedSpheroid,
+    Cone, Icosahedron, Dodecahedron, TruncatedCube, Prism6, Cone6, Pyramid,
+    Cuboctahedron, Prism3, Tetrahedron, EllipsoidalCylinder, Box,
+    HemiEllipsoid, AnisoPyramid,
 };
 
-QString const& name(kind);
+QString const& name(EShape);
 
 //------------------------------------------------------------------------------
 
-class Particle : public Object { BASE(Object)
+class Particle : public Object
+{
 protected:
-  Particle(geometry::key);
-  xyz turn,   // turn before scale
-      scale,  // geometries are of 1-size (box 1x1x1, sphere D=1), need scaling
-      offset, // geometries centered around origin; particles stand on z=0 plane
-      rotate, translate;  // remembered
+    Particle(GeometricID::Key);
+    Vector3D turn;   // turn before scale
+    Vector3D scale;  // geometries are of 1-size (box 1x1x1, sphere D=1), need scaling
+    Vector3D offset; // geometries centered around origin; particles stand on z=0 plane
+    Vector3D rotate, translate;  // remembered
 
-  void set();
+    void set();
 
 public:
-  static kind const firstKind = kind::None,
-                    lastKind  = kind::AnisoPyramid;
+    static EShape const firstKind = EShape::None;
+    static EShape const lastKind = EShape::AnisoPyramid;
 
-  void transform(xyz rotate, xyz translate);
-  void fancy(xyz rotate, flt r);
+    void transform(Vector3D rotate, Vector3D translate);
+    void fancy(Vector3D rotate, float r);
 };
 
 //------------------------------------------------------------------------------
 // follow BornAgain manual, chapter 11, Particle form factors
 
-class FullSphere : public Particle {
+class FullSphere : public Particle
+{
 public:
-  FullSphere(flp R);
+    FullSphere(float R);
 };
 
-class FullSpheroid : public Particle {
+class FullSpheroid : public Particle
+{
 public:
-  FullSpheroid(flp R, flp H);
+    FullSpheroid(float R, float H);
 };
 
-class Cylinder : public Particle {
+class Cylinder : public Particle
+{
 public:
-  Cylinder(flp R, flp H);
+    Cylinder(float R, float H);
 };
 
-class TruncatedSphere : public Particle {
+class TruncatedSphere : public Particle
+{
 public:
-  TruncatedSphere(flp R, flp H);
+    TruncatedSphere(float R, float H);
 };
 
-class TruncatedSpheroid : public Particle {
+class TruncatedSpheroid : public Particle
+{
 public:
-  TruncatedSpheroid(flp R, flp H, flp fp);
+    TruncatedSpheroid(float R, float H, float fp);
 };
 
-class Cone : public Particle {
+class Cone : public Particle
+{
 public:
-  Cone(flp R, flp H, flp alpha);
+    Cone(float R, float H, float alpha);
 };
 
-class Icosahedron : public Particle {
+class Icosahedron : public Particle
+{
 public:
-  Icosahedron(flp L);
+    Icosahedron(float L);
 };
 
-class Dodecahedron : public Particle {
+class Dodecahedron : public Particle
+{
 public:
-  Dodecahedron(flp L);
+    Dodecahedron(float L);
 };
 
-class TruncatedCube : public Particle {
+class TruncatedCube : public Particle
+{
 public:
-  TruncatedCube(flp L, flp t);
+    TruncatedCube(float L, float t);
 };
 
-class Prism6 : public Particle {
+class Prism6 : public Particle
+{
 public:
-  Prism6(flp R, flp H);
+    Prism6(float R, float H);
 };
 
-class Cone6 : public Particle {
+class Cone6 : public Particle
+{
 public:
-  Cone6(flp R, flp H, flp alpha);
+    Cone6(float R, float H, float alpha);
 };
 
-class Pyramid : public Particle {
+class Pyramid : public Particle
+{
 public:
-  Pyramid(flp L, flp H, flp alpha);
+    Pyramid(float L, float H, float alpha);
 };
 
-class Cuboctahedron : public Particle {
+class Cuboctahedron : public Particle
+{
 public:
-  Cuboctahedron(flp L, flp H, flp rH, flp alpha);
+    Cuboctahedron(float L, float H, float rH, float alpha);
 };
 
-class Prism3 : public Particle {
+class Prism3 : public Particle
+{
 public:
-  Prism3(flp L, flp H);
+    Prism3(float L, float H);
 };
 
-class Tetrahedron : public Particle {
+class Tetrahedron : public Particle
+{
 public:
-  Tetrahedron(flp L, flp H, flp alpha);
+    Tetrahedron(float L, float H, float alpha);
 };
 
-class EllipsoidalCylinder : public Particle {
+class EllipsoidalCylinder : public Particle
+{
 public:
-  EllipsoidalCylinder(flp Ra, flp Rb, flp H);
+    EllipsoidalCylinder(float Ra, float Rb, float H);
 };
 
-class Box : public Particle {
+class Box : public Particle
+{
 public:
-  Box(flp L, flp W, flp H);
+    Box(float L, float W, float H);
 };
 
-class HemiEllipsoid : public Particle {
+class HemiEllipsoid : public Particle
+{
 public:
-  HemiEllipsoid(flp Ra, flp Rb, flp H);
+    HemiEllipsoid(float Ra, float Rb, float H);
 };
 
-class AnisoPyramid : public Particle {
+class AnisoPyramid : public Particle
+{
 public:
-  AnisoPyramid(flp L, flp W, flp H, flp alpha);
+    AnisoPyramid(float L, float W, float H, float alpha);
 };
 
-//------------------------------------------------------------------------------
-}}
-#endif
+}}  // namespace RealSpace::Particles
+#endif  // BA3D_PARTICLES_H
diff --git a/GUI/ba3d/ba3d/shaders.qrc b/GUI/ba3d/ba3d/shaders.qrc
new file mode 100644
index 0000000000000000000000000000000000000000..da533e63f40300cb1f36ffd6729fdb0b742afecb
--- /dev/null
+++ b/GUI/ba3d/ba3d/shaders.qrc
@@ -0,0 +1,7 @@
+<RCC>
+    <qresource prefix="/">
+        <file>shaders/fragment_shader.frag</file>
+        <file>shaders/vertex_shader.vert</file>
+        <file>shaders/fragment_shader_OSX.frag</file>
+    </qresource>
+</RCC>
diff --git a/GUI/ba3d/ba3d/shaders/fragment_shader.frag b/GUI/ba3d/ba3d/shaders/fragment_shader.frag
new file mode 100644
index 0000000000000000000000000000000000000000..12825592a0ffd6872827c0c1bb3522d39861072b
--- /dev/null
+++ b/GUI/ba3d/ba3d/shaders/fragment_shader.frag
@@ -0,0 +1,12 @@
+uniform highp vec3 lightPos;
+uniform highp vec4 color;
+
+varying highp vec3 vo, nm;
+
+void main() {
+  highp vec3  L  = normalize(lightPos - vo);
+  highp vec3  N  = normalize(nm);
+  highp float NL = dot(N,L);
+  highp vec4  C  = color*(0.4 + NL*0.6);
+  gl_FragColor   = clamp(C, 0.0, 1.0);
+}
diff --git a/GUI/ba3d/ba3d/shaders/fragment_shader_OSX.frag b/GUI/ba3d/ba3d/shaders/fragment_shader_OSX.frag
new file mode 100644
index 0000000000000000000000000000000000000000..a5d368c26f4aed6604999d225978eea23154af6e
--- /dev/null
+++ b/GUI/ba3d/ba3d/shaders/fragment_shader_OSX.frag
@@ -0,0 +1,12 @@
+uniform highp vec3 lightPos;
+uniform highp vec4 color;
+
+varying highp vec3 vo, nm;
+
+void main() {
+  highp vec3  L  = normalize(lightPos - vo);
+  highp vec3  N  = normalize(nm);
+  highp float NL = dot(N,L);
+  highp vec4  C  = color*(0.6 + NL*0.4);  // mix ambient with specular
+  gl_FragColor   = clamp(C, 0.0, 1.0);
+}
diff --git a/GUI/ba3d/ba3d/shaders/vertex_shader.vert b/GUI/ba3d/ba3d/shaders/vertex_shader.vert
new file mode 100644
index 0000000000000000000000000000000000000000..0a71a3cbb7e6d37a788f8cab5a3290a757836b5f
--- /dev/null
+++ b/GUI/ba3d/ba3d/shaders/vertex_shader.vert
@@ -0,0 +1,11 @@
+attribute vec3 vertex;
+attribute vec3 normal;
+uniform   mat4 matProj, matModel, matObject;
+varying   vec3 vo, nm;
+
+void main(void) {
+  vec4 vertObj = matObject * vec4(vertex,1);
+  gl_Position  = matProj * matModel * vertObj;
+  vo = vertObj.xyz;
+  nm = normal;
+}
diff --git a/GUI/ba3d/ba3d/view/buffer.cpp b/GUI/ba3d/ba3d/view/buffer.cpp
index 7fe5c7949613d4e3c4022d8f17fe20bc05e25491..b4a685cf0d3f6be9f25c4f424637e42469c7c1cd 100644
--- a/GUI/ba3d/ba3d/view/buffer.cpp
+++ b/GUI/ba3d/ba3d/view/buffer.cpp
@@ -15,32 +15,30 @@
 #include "buffer.h"
 #include "../model/geometry.h"
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
 Buffer::Buffer(Geometry const& geometry) {
-  initializeOpenGLFunctions();
+    initializeOpenGLFunctions();
 
-  auto &mesh  = geometry.mesh;
-  vertexCount = mesh.count();
+    auto &mesh  = geometry.m_mesh;
+    vertexCount = mesh.count();
 
-  QOpenGLVertexArrayObject::Binder __(&vao);
+    QOpenGLVertexArrayObject::Binder __(&vao);
 
-  glBuffer.create();
-  glBuffer.bind();
-  glBuffer.allocate(mesh.constData(), vertexCount * int(sizeof(Geometry::vn_t)));
+    glBuffer.create();
+    glBuffer.bind();
+    glBuffer.allocate(mesh.constData(), vertexCount * int(sizeof(Geometry::Vert_Normal)));
 
-  glEnableVertexAttribArray(0); // vertices
-  glEnableVertexAttribArray(1); // normals
+    glEnableVertexAttribArray(0); // vertices
+    glEnableVertexAttribArray(1); // normals
 
-  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 2*sizeof(xyz), nullptr);
-  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 2*sizeof(xyz), reinterpret_cast<void *>(sizeof(xyz)));
+    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 2*sizeof(Vector3D), nullptr);
+    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 2*sizeof(Vector3D), reinterpret_cast<void *>(sizeof(Vector3D)));
 }
 
 void Buffer::draw() {
-  QOpenGLVertexArrayObject::Binder __(&vao);
-  glDrawArrays(GL_TRIANGLES, 0, vertexCount);
+    QOpenGLVertexArrayObject::Binder __(&vao);
+    glDrawArrays(GL_TRIANGLES, 0, vertexCount);
 }
 
-//------------------------------------------------------------------------------
-}
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/view/buffer.h b/GUI/ba3d/ba3d/view/buffer.h
index d60cb2fc46a19fa40c427b5c76e6e53e594fa76e..9138761288ebeeed86c98e4e8edd434d0b056964 100644
--- a/GUI/ba3d/ba3d/view/buffer.h
+++ b/GUI/ba3d/ba3d/view/buffer.h
@@ -20,22 +20,20 @@
 #include <QOpenGLFunctions>
 #include <QOpenGLVertexArrayObject>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
 class Geometry;
 
 // GL buffer
 class Buffer final : protected QOpenGLFunctions {
 public:
-  Buffer(Geometry const&);
-  void draw();
+    Buffer(Geometry const&);
+    void draw();
 
 private:
-  int vertexCount;
-  QOpenGLVertexArrayObject vao; QOpenGLBuffer glBuffer;
+    int vertexCount;
+    QOpenGLVertexArrayObject vao; QOpenGLBuffer glBuffer;
 };
 
-//------------------------------------------------------------------------------
-}
-#endif
+}  // namespace RealSpace
+#endif  // BA3D_BUFFER_H
diff --git a/GUI/ba3d/ba3d/view/camera.cpp b/GUI/ba3d/ba3d/view/camera.cpp
index 30d581130f494f041ff8de52220575890ba10ff5..fb2c940d3c4d8b25805d47d02d4258f0c5efe395 100644
--- a/GUI/ba3d/ba3d/view/camera.cpp
+++ b/GUI/ba3d/ba3d/view/camera.cpp
@@ -14,79 +14,82 @@
 
 #include "camera.h"
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
 Camera::Camera()
-: pos(xyz::_z, xyz::_0, xyz::_x), zoom(1)
-, vertAngle(60), nearPlane(1), farPlane(10000)
-, lightPos(pos.eye), lightPosRotated(lightPos) {
-  setAspectRatio(1);
+    : pos(Vector3D::_z, Vector3D::_0, Vector3D::_x)
+    , zoom(1), vertAngle(60), nearPlane(1), farPlane(10000)
+    , lightPos(pos.eye), lightPosRotated(lightPos)
+{
+    setAspectRatio(1);
 }
 
-Camera::pos_t::pos_t() : eye(), ctr(), up() {
-}
+Camera::Position::Position() : eye(), ctr(), up()
+{}
 
-Camera::pos_t::pos_t(xyz::rc eye_, xyz::rc ctr_, xyz::rc up_,
+Camera::Position::Position(const Vector3D& eye_, const Vector3D& ctr_, const Vector3D& up_,
                      QQuaternion const& rot_)
-  : eye(eye_), ctr(ctr_), up(up_), rot(rot_) {
-}
-
-Camera::pos_t Camera::pos_t::interpolateTo(rc to, flt r) const {
-  return pos_t(
-    eye.interpolateTo(to.eye, r),
-    ctr.interpolateTo(to.ctr, r),
-    up.interpolateTo(to.up, r),
-    QQuaternion::slerp(rot, to.rot, r)
-  );
+    : eye(eye_), ctr(ctr_), up(up_), rot(rot_)
+{}
+
+Camera::Position Camera::Position::interpolateTo(const Position& to, float r) const
+{
+    return Position(eye.interpolateTo(to.eye, r),
+                 ctr.interpolateTo(to.ctr, r),
+                 up.interpolateTo(to.up, r),
+                 QQuaternion::slerp(rot, to.rot, r) );
 }
 
-void Camera::lookAt(pos_t::rc pos_) {
-  pos = pos_; lightPos = pos.eye;
-  set();
+void Camera::lookAt(const Position& pos_)
+{
+    pos = pos_;
+    lightPos = pos.eye;
+    set();
 }
 
 // recalculate dependent params
-void Camera::set() {
-  matModel.setToIdentity();
-  matModel.lookAt((pos.eye-pos.ctr)*zoom + pos.ctr, pos.ctr, pos.up);
+void Camera::set()
+{
+    matModel.setToIdentity();
+    matModel.lookAt((pos.eye-pos.ctr)*zoom + pos.ctr, pos.ctr, pos.up);
 
-  QQuaternion rt(pos.rot * addRot);
-  matModel.translate(+pos.ctr);
-  matModel.rotate(rt);
-  matModel.translate(-pos.ctr);
+    QQuaternion rt(pos.rot * addRot);
+    matModel.translate(+pos.ctr);
+    matModel.rotate(rt);
+    matModel.translate(-pos.ctr);
 
-  lightPosRotated = rt.inverted().rotatedVector(lightPos);
+    lightPosRotated = rt.inverted().rotatedVector(lightPos);
 
-  emit updated(*this);
+    emit updated(*this);
 }
 
-void Camera::setAspectRatio(float ratio) {
-  matProj.setToIdentity();
-  matProj.perspective(vertAngle, ratio, nearPlane, farPlane);
+void Camera::setAspectRatio(float ratio)
+{
+    matProj.setToIdentity();
+    matProj.perspective(vertAngle, ratio, nearPlane, farPlane);
 }
 
-void Camera::turnBy(QQuaternion const& rot) {
-  addRot = rot;
-  set();
+void Camera::turnBy(QQuaternion const& rot)
+{
+    addRot = rot;
+    set();
 }
 
-void Camera::zoomBy(flt zoom_) {
-  zoom = zoom_;
-  set();
+void Camera::zoomBy(float zoom_)
+{
+    zoom = zoom_;
+    set();
 }
 
-void Camera::endTransform(bool keep) {
-  if (keep) {
-    pos.rot = (pos.rot * addRot).normalized();
-    pos.eye = pos.eye * zoom; // TODO limit
-  }
-
-  addRot = QQuaternion();
-  zoom = 1;
-
-  set();
+void Camera::endTransform(bool keep)
+{
+    if (keep) {
+        pos.rot = (pos.rot * addRot).normalized();
+        pos.eye = pos.eye * zoom; // TODO limit
+    }
+    addRot = QQuaternion();
+    zoom = 1;
+    set();
 }
 
-//------------------------------------------------------------------------------
-}
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/view/camera.h b/GUI/ba3d/ba3d/view/camera.h
index 569ba0408da187c0926b835b04edc493260e56b2..ff840c2be827d898052ab16b1606bd9510f33e81 100644
--- a/GUI/ba3d/ba3d/view/camera.h
+++ b/GUI/ba3d/ba3d/view/camera.h
@@ -20,63 +20,59 @@
 #include <QMatrix4x4>
 #include <QQuaternion>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
 class Canvas;
 class Program;
 
 class Camera : public QObject {
-  Q_OBJECT
-  friend class Canvas;
-  friend class Program;
+    Q_OBJECT
+    friend class Canvas;
+    friend class Program;
 public:
-  Camera();
+    Camera();
 
-  struct pos_t {
-    typedef pos_t const& rc;
+    struct Position {
 
-    pos_t();
-    pos_t(xyz::rc eye, xyz::rc ctr, xyz::rc up,
-          QQuaternion const& = QQuaternion());
+        Position();
+        Position(const Vector3D& eye, const Vector3D& ctr, const Vector3D& up,
+                 const QQuaternion& = QQuaternion());
 
-    xyz eye, ctr, up;
-    QQuaternion rot;
+        Vector3D eye, ctr, up;
+        QQuaternion rot;
 
-    pos_t interpolateTo(rc, flt) const;
-  };
+        Position interpolateTo(const Position&, float) const;
+    };
 
-  void lookAt(pos_t::rc);
+    void lookAt(const Position&);
 
-  pos_t::rc getPos() const { return pos; }
+    const Position& getPos() const { return pos; }
 
-  void set();
+    void set();
 
 signals:
-  void updated(Camera const&);
+    void updated(Camera const&);
 
 private:
+    void setAspectRatio(float);
 
-  void setAspectRatio(float);
+    // additional transformation
+    void turnBy(QQuaternion const&);
+    void zoomBy(float);
+    void endTransform(bool keep);
 
-  // additional transformation
-  void turnBy(QQuaternion const&);
-  void zoomBy(flt);
-  void endTransform(bool keep);
+    // camera setup
+    Position pos;
+    float zoom;
+    float vertAngle, nearPlane, farPlane;
 
-  // camera setup
-  pos_t pos;
-  flt zoom;
-  flt vertAngle, nearPlane, farPlane;
+    // light
+    Vector3D lightPos, lightPosRotated;
 
-  // light
-  xyz lightPos, lightPosRotated;
-
-  // transformation
-  QQuaternion addRot;        // rotation, additional rotation
-  QMatrix4x4  matModel, matProj;
+    // transformation
+    QQuaternion addRot;        // rotation, additional rotation
+    QMatrix4x4  matModel, matProj;
 };
 
-//------------------------------------------------------------------------------
-}
-#endif
+}  // namespace RealSpace
+#endif  // BA3D_CAMERA_H
diff --git a/GUI/ba3d/ba3d/view/canvas.cpp b/GUI/ba3d/ba3d/view/canvas.cpp
index 1d27d562dea933826c1644f9df18bf81f11bae53..77aa3fbc1dc365a19f5af714f7e7abf1b2835191 100644
--- a/GUI/ba3d/ba3d/view/canvas.cpp
+++ b/GUI/ba3d/ba3d/view/canvas.cpp
@@ -22,179 +22,177 @@
 #include <QMouseEvent>
 #include <qmath.h>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
 Canvas::Canvas()
-: aspectRatio(1), colorBgR(1), colorBgG(1), colorBgB(1)
-, camera(nullptr), program(nullptr), model(nullptr) {
-  connect(&geometryStore(), &GeometryStore::deletingGeometry,
-          this, &Canvas::releaseBuffer);
+    : aspectRatio(1), colorBgR(1), colorBgG(1), colorBgB(1)
+    , camera(nullptr), program(nullptr), model(nullptr) {
+    connect(&geometryStore(), &GeometryStore::deletingGeometry,
+            this, &Canvas::releaseBuffer);
 }
 
 Canvas::~Canvas() {
-  releaseBuffers();
+    releaseBuffers();
 }
 
 void Canvas::setBgColor(QColor const& c) {
-  colorBgR = flt(c.redF());
-  colorBgG = flt(c.greenF());
-  colorBgB = flt(c.blueF());
-  update();
+    colorBgR = float(c.redF());
+    colorBgG = float(c.greenF());
+    colorBgB = float(c.blueF());
+    update();
 }
 
 void Canvas::setCamera(Camera* c) {
-  camera = c;
-  setCamera();
+    camera = c;
+    setCamera();
 }
 
 void Canvas::setProgram(Program* p) {
-  program = p;
-  if (program)
-    program->needsInit();
-  update();
+    program = p;
+    if (program)
+        program->needsInit();
+    update();
 }
 
 void Canvas::setModel(Model* m) {
-  releaseBuffers();
+    releaseBuffers();
 
-  disconnect(modelUpdated);
-  model = m;
-  modelUpdated = connect(model, &Model::updated, [this](bool withEye) {
-    if (withEye)
-      setCamera();
-    else
-      update();
-  });
+    disconnect(modelUpdated);
+    model = m;
+    modelUpdated = connect(model, &Model::updated, [this](bool withEye) {
+        if (withEye)
+            setCamera();
+        else
+            update();
+    });
 
-  setCamera();
+    setCamera();
 }
 
 Model* Canvas::getModel() {
-  return model;
+    return model;
 }
 
 void Canvas::setCamera(bool full) {
-  if (camera) {
-    camera->setAspectRatio(aspectRatio);
-    if (full && model)
-      camera->lookAt(model->defCamPos);
-  }
+    if (camera) {
+        camera->setAspectRatio(aspectRatio);
+        if (full && model)
+            camera->lookAt(model->defCamPos);
+    }
 
-  update();
+    update();
 }
 
 void Canvas::initializeGL() {
-  initializeOpenGLFunctions();
-  glEnable(GL_DEPTH_TEST);
-  glEnable(GL_CULL_FACE);
+    initializeOpenGLFunctions();
+    glEnable(GL_DEPTH_TEST);
+    glEnable(GL_CULL_FACE);
 }
 
 void Canvas::resizeGL(int w, int h) {
-  int w1 = qMax(1, w), h1 = qMax(1, h);
-  viewport.setRect(0, 0, w1, h1);
-  aspectRatio = flt(w1) / flt(h1);
-  setCamera(false);
+    int w1 = qMax(1, w), h1 = qMax(1, h);
+    viewport.setRect(0, 0, w1, h1);
+    aspectRatio = float(w1) / float(h1);
+    setCamera(false);
 }
 
 void Canvas::paintGL() {
-  glClearColor(colorBgR, colorBgG, colorBgB, 1);
-  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glClearColor(colorBgR, colorBgG, colorBgB, 1);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
-  if (camera && program && model) {
-    program->init();
-    program->bind();
-    program->set(*camera);
+    if (camera && program && model) {
+        program->init();
+        program->bind();
+        program->set(*camera);
 
-    // opaque objects
-    model->draw(*this);
+        // opaque objects
+        model->draw(*this);
 
-    // transparent objects
-    glEnable(GL_BLEND); glDepthMask(false);
-    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    model->drawBlend(*this);
-    glDisable(GL_BLEND); glDepthMask(true);
+        // transparent objects
+        glEnable(GL_BLEND); glDepthMask(false);
+        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+        model->drawBlend(*this);
+        glDisable(GL_BLEND); glDepthMask(true);
 
-    program->release();
-  }
+        program->release();
+    }
 }
 
 QVector3D Canvas::unproject(QPoint const& p) {
-  flt x = p.x(), y = viewport.height() - p.y();
-  return QVector3D(x, y, 1).unproject(matModel, matProj, viewport);
+    float x = p.x(), y = viewport.height() - p.y();
+    return QVector3D(x, y, 1).unproject(matModel, matProj, viewport);
 }
 
 void Canvas::mousePressEvent(QMouseEvent* e) {
-  switch (e->button())  {
-  case Qt::LeftButton:
-    mouseButton = btnTURN;
-    break;
-  case Qt::RightButton:
-    mouseButton = btnZOOM;
-    break;
-  default:
-    mouseButton = btnNONE;
-    break;
-  }
-
-  if (camera) {
-    matModel = camera->matModel;
-    matProj  = camera->matProj;
-    lastV    = unproject(e->pos());
-    lastY    = e->y();
-  }
+    switch (e->button())  {
+    case Qt::LeftButton:
+        mouseButton = btnTURN;
+        break;
+    case Qt::RightButton:
+        mouseButton = btnZOOM;
+        break;
+    default:
+        mouseButton = btnNONE;
+        break;
+    }
+
+    if (camera) {
+        matModel = camera->matModel;
+        matProj  = camera->matProj;
+        lastV    = unproject(e->pos());
+        lastY    = e->y();
+    }
 }
 
 void Canvas::mouseMoveEvent(QMouseEvent* e) {
-  if (camera) {
-    auto v = unproject(e->pos());
-    switch (mouseButton) {
-    case btnTURN:
-      camera->turnBy(QQuaternion::rotationTo(v, lastV));
-      break;
-    case btnZOOM: {
-      flt d = (e->y() - lastY) / flt(viewport.height());
-      camera->zoomBy(1+d);
-      break;
-    }
-    default:
-      break;
+    if (camera) {
+        auto v = unproject(e->pos());
+        switch (mouseButton) {
+        case btnTURN:
+            camera->turnBy(QQuaternion::rotationTo(v, lastV));
+            break;
+        case btnZOOM: {
+            float d = (e->y() - lastY) / float(viewport.height());
+            camera->zoomBy(1+d);
+            break;
+        }
+        default:
+            break;
+        }
+
+        update();
     }
-
-    update();
-  }
 }
 
 void Canvas::mouseReleaseEvent(QMouseEvent*) {
-  if (camera) {
-    camera->endTransform(true);
-    update();
-  }
+    if (camera) {
+        camera->endTransform(true);
+        update();
+    }
 }
 
 void Canvas::releaseBuffer(Geometry const* g) {
-  delete buffers.take(g);
+    delete buffers.take(g);
 }
 
 void Canvas::releaseBuffers() {
-  for (auto b: buffers.values())
-    delete b;
-  buffers.clear();
+    for (auto b: buffers.values())
+        delete b;
+    buffers.clear();
 }
 
 void Canvas::draw(QColor const& color, QMatrix4x4 const& mat, Geometry const& geo) {
-  auto it = buffers.find(&geo);
-  Buffer* buf;
-  if (buffers.end() == it)
-    buffers.insert(&geo, buf = new Buffer(geo));  // created on demand
-  else
-    buf = *it;
+    auto it = buffers.find(&geo);
+    Buffer* buf;
+    if (buffers.end() == it)
+        buffers.insert(&geo, buf = new Buffer(geo));  // created on demand
+    else
+        buf = *it;
 
-  EXPECT(program)
-  program->set(color);
-  program->set(mat);
-  buf->draw();
+    Q_ASSERT(program);
+    program->set(color);
+    program->set(mat);
+    buf->draw();
 }
 
-//------------------------------------------------------------------------------
-}
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/view/canvas.h b/GUI/ba3d/ba3d/view/canvas.h
index 680e4cde6ccde4265e22b70640c1f1d156f3c64f..a83b1d9f2f31004d6eae56c3fda5e9e6b1c60f9a 100644
--- a/GUI/ba3d/ba3d/view/canvas.h
+++ b/GUI/ba3d/ba3d/view/canvas.h
@@ -22,61 +22,58 @@
 #include <QOpenGLFunctions>
 #include <QOpenGLShaderProgram>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
 class Camera; class Program; class Model;
 class Geometry; class Buffer; class Object;
 
 class Canvas: public QOpenGLWidget, protected QOpenGLFunctions {
-  BASE(QOpenGLWidget)
-  Q_OBJECT
-  friend class Object;
+    Q_OBJECT
+    friend class Object;
 public:
-  Canvas();
- ~Canvas();
+    Canvas();
+    ~Canvas();
 
-  void setBgColor(QColor const&);
+    void setBgColor(QColor const&);
 
-  // active things, owned elsewhere, may be nullptr
-  void setCamera(Camera*);
-  void setProgram(Program*);
-  void setModel(Model*);
-  Model* getModel();
+    // active things, owned elsewhere, may be nullptr
+    void setCamera(Camera*);
+    void setProgram(Program*);
+    void setModel(Model*);
+    Model* getModel();
 
 private:
-  QRect viewport;
-  flt   aspectRatio, colorBgR, colorBgG, colorBgB;
+    QRect viewport;
+    float aspectRatio, colorBgR, colorBgG, colorBgB;
 
-  void setCamera(bool full = true);
+    void setCamera(bool full = true);
 
-  void initializeGL();
-  void resizeGL(int, int);
-  void paintGL();
+    void initializeGL();
+    void resizeGL(int, int);
+    void paintGL();
 
-  QVector3D lastV;    // unprojected vector
-  flt       lastY;    // screen coordinate
-  QMatrix4x4 matModel, matProj;
-  QVector3D  unproject(QPoint const&);
+    QVector3D lastV;    // unprojected vector
+    float     lastY;    // screen coordinate
+    QMatrix4x4 matModel, matProj;
+    QVector3D  unproject(QPoint const&);
 
-  enum {btnNONE, btnTURN, btnZOOM} mouseButton;
-  void mousePressEvent(QMouseEvent*);
-  void mouseMoveEvent(QMouseEvent*);
-  void mouseReleaseEvent(QMouseEvent*);
+    enum {btnNONE, btnTURN, btnZOOM} mouseButton;
+    void mousePressEvent(QMouseEvent*);
+    void mouseMoveEvent(QMouseEvent*);
+    void mouseReleaseEvent(QMouseEvent*);
 
-  Camera  *camera;
-  Program *program;
-  Model   *model;
+    Camera  *camera;
+    Program *program;
+    Model   *model;
 
-  QMetaObject::Connection modelUpdated;
+    QMetaObject::Connection modelUpdated;
 
-  QHash<Geometry const*, Buffer*> buffers;
-  void releaseBuffer(Geometry const*);
-  void releaseBuffers();
+    QHash<Geometry const*, Buffer*> buffers;
+    void releaseBuffer(Geometry const*);
+    void releaseBuffers();
 
-  void draw(QColor const&, QMatrix4x4 const&, Geometry const&);
+    void draw(QColor const&, QMatrix4x4 const&, Geometry const&);
 };
 
-//------------------------------------------------------------------------------
-}
-#endif
+}  // namespace RealSpace
+#endif  // BA3D_CANVAS_H
diff --git a/GUI/ba3d/ba3d/view/program.cpp b/GUI/ba3d/ba3d/view/program.cpp
index 939c2f3b3fe7d1ab005ae4cae82bbef203dfc272..30d8aab0cccc20f9248580beb3961251cf34656a 100644
--- a/GUI/ba3d/ba3d/view/program.cpp
+++ b/GUI/ba3d/ba3d/view/program.cpp
@@ -16,84 +16,70 @@
 #include "camera.h"
 #include <QMatrix4x4>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
-
-Program::Program() {
-  needsInit();
-}
-
-void Program::needsInit() {
-  doInit = true;
+// The macro call has to be in the global namespace
+inline void InitShaderResources() {
+    Q_INIT_RESOURCE(shaders);
 }
 
-namespace {
-static char const *shaderVertex =
-  "attribute vec3 vertex;"
-  "attribute vec3 normal;"
-  "uniform   mat4 matProj, matModel, matObject;"
-  "varying   vec3 vo, nm;"
+namespace RealSpace {
 
-  "void main() {"
-  "  vec4 vertObj = matObject * vec4(vertex,1);"
-  "  gl_Position  = matProj * matModel * vertObj;"
-  "  vo = vertObj.xyz; nm = normal;"
-  "}";
+Program::Program()
+{
+    // make sure our resource file gets initialized
+    InitShaderResources();
 
-static char const *shaderFragment =
-  "uniform highp vec3 lightPos;"
-  "uniform highp vec4 color;"
+    needsInit();
+}
 
-  "varying highp vec3 vo, nm;"
+void Program::needsInit() {
+    doInit = true;
+}
 
-  "void main() {"
-  "  highp vec3  L  = normalize(lightPos - vo);"
-  "  highp vec3  N  = normalize(nm);"
-  "  highp float NL = dot(N,L);"
+void Program::init() {
+    if (!doInit)
+        return;
+    doInit = false;
+
+    auto shader_found = addShaderFromSourceFile(QOpenGLShader::Vertex,
+                                                ":/shaders/vertex_shader.vert");
+    if (!shader_found)
+        throw std::runtime_error("Vertex shader not loaded");
 #ifdef Q_OS_OSX
-  "  highp vec4  C  = color*(0.6 + NL*0.4);"  // mix ambient with specular
+    shader_found = addShaderFromSourceFile(QOpenGLShader::Fragment,
+                                           ":/shaders/fragment_shader_OSX.frag");
 #else
-  "  highp vec4  C  = color*(0.4 + NL*0.6);"
+    shader_found = addShaderFromSourceFile(QOpenGLShader::Fragment,
+                                           ":/shaders/fragment_shader.frag");
 #endif
-  "  gl_FragColor   = clamp(C, 0.0, 1.0);"
-  "}";
-}
-
-void Program::init() {
-  if (!doInit)
-    return;
-  doInit = false;
-
-  addShaderFromSourceCode(QOpenGLShader::Vertex,   shaderVertex);
-  addShaderFromSourceCode(QOpenGLShader::Fragment, shaderFragment);
+    if (!shader_found)
+        throw std::runtime_error("Fragment shader not loaded");
 
-  bindAttributeLocation("vertex", 0);
-  bindAttributeLocation("normal", 1);
+    bindAttributeLocation("vertex", 0);
+    bindAttributeLocation("normal", 1);
 
-  link();
+    link();
 
-  bind();
-  locMatProj   = uniformLocation("matProj");
-  locMatModel  = uniformLocation("matModel");
-  locMatObject = uniformLocation("matObject");
-  locLightPos  = uniformLocation("lightPos");
-  locColor     = uniformLocation("color");
-  release();
+    bind();
+    locMatProj   = uniformLocation("matProj");
+    locMatModel  = uniformLocation("matModel");
+    locMatObject = uniformLocation("matObject");
+    locLightPos  = uniformLocation("lightPos");
+    locColor     = uniformLocation("color");
+    release();
 }
 
 void Program::set(Camera const& camera) {
-  setUniformValue(locMatProj,  camera.matProj);
-  setUniformValue(locMatModel, camera.matModel);
-  setUniformValue(locLightPos, camera.lightPosRotated);
+    setUniformValue(locMatProj,  camera.matProj);
+    setUniformValue(locMatModel, camera.matModel);
+    setUniformValue(locLightPos, camera.lightPosRotated);
 }
 
 void Program::set(QColor const&color) {
-  setUniformValue(locColor, color);
+    setUniformValue(locColor, color);
 }
 
 void Program::set(QMatrix4x4 const& mat) {
-  setUniformValue(locMatObject, mat);
+    setUniformValue(locMatObject, mat);
 }
 
-//------------------------------------------------------------------------------
-}
+}  // namespace RealSpace
diff --git a/GUI/ba3d/ba3d/view/program.h b/GUI/ba3d/ba3d/view/program.h
index 6d4759b542736e04a0131a6011d44b483cb3a759..d43b93f53552e8534bc46e104f3d815e5168aed1 100644
--- a/GUI/ba3d/ba3d/view/program.h
+++ b/GUI/ba3d/ba3d/view/program.h
@@ -18,30 +18,29 @@
 #include "../def.h"
 #include <QOpenGLShaderProgram>
 
-namespace ba3d {
-//------------------------------------------------------------------------------
+namespace RealSpace {
 
 class Camera;
 class Canvas;
 
-class Program: public QOpenGLShaderProgram { BASE(QOpenGLShaderProgram)
-  friend class Canvas;
+class Program: public QOpenGLShaderProgram
+{
+    friend class Canvas;
 public:
-  Program();
+    Program();
 
 private:
-  void needsInit(); // mark as needed init
-  void init();      // inits, if needed
+    void needsInit(); // mark as needed init
+    void init();      // inits, if needed
 
-  void set(Camera const&);
-  void set(QColor const&);      // object color
-  void set(QMatrix4x4 const&);  // object transf
+    void set(Camera const&);
+    void set(QColor const&);      // object color
+    void set(QMatrix4x4 const&);  // object transf
 
-  bool doInit;
-  int  locMatProj, locMatModel, locMatObject,
-       locLightPos, locColor;
+    bool doInit;
+    int  locMatProj, locMatModel, locMatObject,
+    locLightPos, locColor;
 };
 
-//------------------------------------------------------------------------------
-}
-#endif
+}  // namespace RealSpace
+#endif  // BA3D_PROGRAM_H
diff --git a/GUI/ba3d/ba3d/widget.cpp b/GUI/ba3d/ba3d/widget.cpp
index 71e6beb06ef607bd2ec1ec5e4706c095858a2bfd..ce2a685373630848c309afac1b1a90ca6cea6950 100644
--- a/GUI/ba3d/ba3d/widget.cpp
+++ b/GUI/ba3d/ba3d/widget.cpp
@@ -20,7 +20,7 @@
 
 #include <QBoxLayout>
 
-namespace ba3d {
+namespace RealSpace {
 //------------------------------------------------------------------------------
 
 Widget3D::Widget3D() : canvas(nullptr), camera(nullptr), program(nullptr) {
@@ -44,14 +44,13 @@ void Widget3D::setBackground(QColor const& color) {
 
 void Widget3D::setModel(Model* model) {
   canvas->setModel(model);
-  connect(camera, &ba3d::Camera::updated, model, &Model::cameraUpdated);
+  connect(camera, &RealSpace::Camera::updated, model, &Model::cameraUpdated);
   camera->set();
 }
 
-Model* Widget3D::getModel() {
+Model* Widget3D::model() {
   return canvas->getModel();
 }
 
 //------------------------------------------------------------------------------
 }
-// eof
diff --git a/GUI/ba3d/ba3d/widget.h b/GUI/ba3d/ba3d/widget.h
index 69ce49df9921857bdd72f07333d1e562e2bc3ee3..834b8d000058ae0072e96d67eefadb3403e8f8f5 100644
--- a/GUI/ba3d/ba3d/widget.h
+++ b/GUI/ba3d/ba3d/widget.h
@@ -18,7 +18,7 @@
 #include "def.h"
 #include <QWidget>
 
-namespace ba3d {
+namespace RealSpace {
 //------------------------------------------------------------------------------
 
 class Model;
@@ -26,7 +26,8 @@ class Canvas;
 class Camera;
 class Program;
 
-class Widget3D : public QWidget { BASE(QWidget)
+class Widget3D : public QWidget
+{
   Q_OBJECT
 public:
   Widget3D();
@@ -36,7 +37,7 @@ public:
 
   void setBackground(QColor const&);
   void setModel(Model*); // model owned elsewhere, may be nullptr
-  Model* getModel();
+  Model* model();
 
 private:
   Canvas  *canvas;
@@ -47,4 +48,3 @@ private:
 //------------------------------------------------------------------------------
 }
 #endif
-// eof
diff --git a/GUI/ba3d/demo/CMakeLists.txt b/GUI/ba3d/demo/CMakeLists.txt
index d9e7f0128859fe8f2c1e0c94e34864fe6cbb1c36..4e1b67361de7f9900f5fbcc02ac4a972b9a01def 100644
--- a/GUI/ba3d/demo/CMakeLists.txt
+++ b/GUI/ba3d/demo/CMakeLists.txt
@@ -13,5 +13,3 @@ target_link_libraries (${app}
   Qt5::Core Qt5::Gui Qt5::Widgets
   ${OPENGL_gl_LIBRARY}
 )
-
-# eof
diff --git a/GUI/ba3d/demo/demo_model.cpp b/GUI/ba3d/demo/demo_model.cpp
index dac5452301e1c91c81e91abeef856293f1524abb..540d237cc1a2cb6d5b2fb65cc7414f4efe09ee7a 100644
--- a/GUI/ba3d/demo/demo_model.cpp
+++ b/GUI/ba3d/demo/demo_model.cpp
@@ -18,231 +18,229 @@
 #include <thread>
 #include <qmath.h>
 
-//------------------------------------------------------------------------------
-
-using namespace ba3d;
+using namespace RealSpace;
 
 DemoModel::DemoModel() {
-  setCameraSide();
+    setCameraSide();
 }
 
 void DemoModel::switchBack() {
-  switch (back) {
-  case backNONE:
-    addSubstrate(); back = backSUBSTRATE;
-    break;
-  case backSUBSTRATE:
-    addLayer(); back = backLAYER;
-    break;
-  case backLAYER:
-    super::clearBlend(); back = backNONE;
-    break;
-  }
+    switch (back) {
+    case backNONE:
+        addSubstrate(); back = backSUBSTRATE;
+        break;
+    case backSUBSTRATE:
+        addLayer(); back = backLAYER;
+        break;
+    case backLAYER:
+        super::clearBlend(); back = backNONE;
+        break;
+    }
 
-  snooze(false);
+    snooze(false);
 }
 
 void DemoModel::switchFront() {
-  switch (front) {
-  case frontNONE:
-    one(); front = frontONE;
-    break;
-  case frontONE:
-    super::clearOpaque(); kind = ba3d::particle::kind::None;
-    front = frontSQUARELOW; szSample = 400; square(0);
-    break;
-  case frontSQUARELOW:
-    super::clearOpaque(); ps.clear(); kind = ba3d::particle::kind::None;
-    front = frontSQUAREHIGH; szSample = 800; square(0);
-    break;
-  case frontSQUAREHIGH:
-    super::clearOpaque(); ps.clear(); kind = ba3d::particle::kind::None;
-    front = frontSQUAREINSANE; szSample = 2000; square(0);
-    break;
-  case frontSQUAREINSANE:
-    super::clearOpaque(); ps.clear(); front = frontNONE;
-    break;
-  }
-
-  snooze(false);
+    switch (front) {
+    case frontNONE:
+        one(); front = frontONE;
+        break;
+    case frontONE:
+        super::clearOpaque(); kind = Particles::EShape::None;
+        front = frontSQUARELOW; szSample = 400; square(0);
+        break;
+    case frontSQUARELOW:
+        super::clearOpaque(); ps.clear(); kind = Particles::EShape::None;
+        front = frontSQUAREHIGH; szSample = 800; square(0);
+        break;
+    case frontSQUAREHIGH:
+        super::clearOpaque(); ps.clear(); kind = Particles::EShape::None;
+        front = frontSQUAREINSANE; szSample = 2000; square(0);
+        break;
+    case frontSQUAREINSANE:
+        super::clearOpaque(); ps.clear(); front = frontNONE;
+        break;
+    }
+
+    snooze(false);
 }
 
 void DemoModel::switchOne() {
-  if (frontONE == front)
-    one();
+    if (frontONE == front)
+        one();
 }
 
 void DemoModel::square(float sigma) {
-  if (frontSQUARELOW != front && frontSQUAREHIGH != front && frontSQUAREINSANE != front)
-    return;
-
-  uint n = qFloor(szSample / spacing / 2 - 1);
-  auto mesh = squareLattice(n, sigma);
-  for (auto& m: mesh)
-    m = m  * spacing + xyz(0, 0, -20);
-
-  if (ps.empty()) { // first time - init
-    ps.resize(mesh.count());
-    for (auto& p: ps) {
-      add((p = new particle::TruncatedSphere(R, R)));
-      p->color = QColor(170, 0, 0);
+    if (frontSQUARELOW != front && frontSQUAREHIGH != front && frontSQUAREINSANE != front)
+        return;
+
+    uint n = qFloor(szSample / spacing / 2 - 1);
+    auto mesh = squareLattice(n, sigma);
+    for (auto& m: mesh)
+        m = m  * spacing + Vector3D(0, 0, -20);
+
+    if (ps.empty()) { // first time - init
+        ps.resize(mesh.count());
+        for (auto& p: ps) {
+            add((p = new Particles::TruncatedSphere(R, R)));
+            p->color = QColor(170, 0, 0);
 #ifdef Q_OS_OSX
-      p->color = QColor(70, 0, 0);
+            p->color = QColor(70, 0, 0);
 #endif
+        }
+        activeMesh.clear();
     }
-    activeMesh.clear();
-  }
 
-  EXPECT (ps.count() == mesh.count())
+    Q_ASSERT(ps.count() == mesh.count());
 
-  if (activeMesh.empty()) {
-    activeMesh = mesh;
-    for (uint i=0; i < uint(ps.count()); ++i)
-      ps.at(i)->transform(xyz::_0, activeMesh.at(i));
-
-    uint const steps = 20;
-    for_int (s, steps + 1) {
-      for (uint i=0; i < uint(ps.count()); ++i)
-        ps.at(i)->fancy(xyz::_0, flt(s) / steps);
-      snooze(false);
-    }
-  } else {
-    // back
-    auto home = squareLattice(n, 0), from = activeMesh;
-    for (auto& m: home)
-      m = m  * spacing + xyz(0, 0, -20);
-    uint const steps = 30;
-    for_int (s, steps + 1) {
-      for (uint i=0; i < uint(ps.count()); ++i)
-        ps.at(i)->transform(xyz::_0, from.at(i).interpolateTo(home.at(i), flt(s)/steps));
-      snooze(false);
-    }
+    if (activeMesh.empty()) {
+        activeMesh = mesh;
+        for (uint i=0; i < uint(ps.count()); ++i)
+            ps.at(i)->transform(Vector3D::_0, activeMesh.at(i));
 
-    activeMesh = home;
-
-    float const step = .2; bool go = true;
-    while (go) {
-      go = false;
-      for (uint i=0; i < uint(ps.count()); ++i) {
-        auto& p = ps.at(i);
-        auto& newPos = mesh.at(i);
-        auto& pos = activeMesh[i];
-        auto np = pos + (newPos - pos).normalized() * step;
-        // neigbours
-        auto hasSpace = [&](int xi, int yi) -> bool {
-          int n = activeMesh.n;
-          if (xi < -n || n <= xi || yi < -n || n <= yi)
-            return true;
-          auto p = activeMesh.at(activeMesh.index(xi,yi));
-          return (np-p).length() > 2*R;
-        };
-
-        int xi = activeMesh.ix(i), yi = activeMesh.iy(i);
-        if (hasSpace(xi-1, yi-1) && hasSpace(xi-1, yi-0) && hasSpace(xi-1, yi+1)
-         && hasSpace(xi+1, yi-1) && hasSpace(xi+1, yi-0) && hasSpace(xi+1, yi+1)
-         && hasSpace(xi-0, yi-1) && hasSpace(xi-0, yi+1)
-         && (newPos - np).length() > step*1.001) {
-            go = true;
-            pos = np;
-            p->transform(xyz::_0, pos);
+        int const steps = 20;
+        for(int s=0; s < steps + 1; ++s) {
+            for (uint i=0; i < uint(ps.count()); ++i)
+                ps.at(i)->fancy(Vector3D::_0, float(s) / steps);
+            snooze(false);
+        }
+    } else {
+        // back
+        auto home = squareLattice(n, 0), from = activeMesh;
+        for (auto& m: home)
+            m = m  * spacing + Vector3D(0, 0, -20);
+        int const steps = 30;
+        for(int s=0; s < steps + 1; ++s) {
+            for (uint i=0; i < uint(ps.count()); ++i)
+                ps.at(i)->transform(Vector3D::_0, from.at(i).interpolateTo(home.at(i), float(s)/steps));
+            snooze(false);
         }
-      }
 
-      snooze(false);
+        activeMesh = home;
+
+        float const step = .2f; bool go = true;
+        while (go) {
+            go = false;
+            for (uint i=0; i < uint(ps.count()); ++i) {
+                auto& p = ps.at(i);
+                auto& newPos = mesh.at(i);
+                auto& pos = activeMesh[i];
+                auto np = pos + (newPos - pos).normalized() * step;
+                // neigbours
+                auto hasSpace = [&](int xi, int yi) -> bool {
+                    int n = activeMesh.n;
+                    if (xi < -n || n <= xi || yi < -n || n <= yi)
+                        return true;
+                    auto p = activeMesh.at(activeMesh.index(xi,yi));
+                    return (np-p).length() > 2*R;
+                };
+
+                int xi = activeMesh.ix(i), yi = activeMesh.iy(i);
+                if (hasSpace(xi-1, yi-1) && hasSpace(xi-1, yi-0) && hasSpace(xi-1, yi+1)
+                    && hasSpace(xi+1, yi-1) && hasSpace(xi+1, yi-0) && hasSpace(xi+1, yi+1)
+                    && hasSpace(xi-0, yi-1) && hasSpace(xi-0, yi+1)
+                    && (newPos - np).length() > step*1.001f) {
+                    go = true;
+                    pos = np;
+                    p->transform(Vector3D::_0, pos);
+                }
+            }
+
+            snooze(false);
+        }
     }
-  }
 
-  snooze(false);
+    snooze(false);
 }
 
 void DemoModel::one() {
-  using eKind = ba3d::particle::kind;
-  if (kind != eKind::None)
-    oneOut();
-  if (kind == eKind::AnisoPyramid)
-    kind = eKind::None;
-  else
-    oneIn((kind = eKind(int(kind) + 1)));
+    using eKind = Particles::EShape;
+    if (kind != eKind::None)
+        oneOut();
+    if (kind == eKind::AnisoPyramid)
+        kind = eKind::None;
+    else
+        oneIn((kind = eKind(int(kind) + 1)));
 }
 
 void DemoModel::oneOut() {
-  uint const steps = 40;
-  for_i (steps + 1) {
-    flt a = 360.f / steps * i / 3;
-    p->fancy(xyz(a, a, a), flt(steps-i) / steps);
-    snooze(false);
-  }
-  rem(p);
+    int const steps = 40;
+    for(int i=0; i<steps+1; ++i) {
+        float a = 360.f / steps * i / 3;
+        p->fancy(Vector3D(a, a, a), float(steps-i) / steps);
+        snooze(false);
+    }
+    rem(p);
 }
 
-void DemoModel::oneIn(particle::kind kind) {
-  add((p = newParticle(kind, R)));
+void DemoModel::oneIn(Particles::EShape kind) {
+    add((p = newParticle(kind, R)));
 #ifdef Q_OS_OSX
-  p->color = QColor(70,0,0);
+    p->color = QColor(70,0,0);
 #endif
-  p->transform(xyz::_0, xyz(0, 0, -hgtLayer));
+    p->transform(Vector3D::_0, Vector3D(0, 0, -hgtLayer));
 
-  uint const steps = 140;
-  for_i (steps + 1) {
-    flt a = 360.f / steps * i;
-    p->fancy(xyz(a*2, a, a), flt(i) / steps);
-    snooze(false);
-  }
+    int const steps = 140;
+    for(int i=0; i<steps+1; ++i) {
+        float a = 360.f / steps * i;
+        p->fancy(Vector3D(a*2, a, a), float(i) / steps);
+        snooze(false);
+    }
 }
 
 void DemoModel::setCameraTop(bool animate) {
-  setCamera(Camera::pos_t(xyz(0, 0, szSample), xyz(0, 0, -20), xyz::_y), animate);
+    setCamera(Camera::Position(Vector3D(0, 0, szSample), Vector3D(0, 0, -20), Vector3D::_y), animate);
 }
 
 void DemoModel::setCameraSide(bool animate) {
-  setCamera(Camera::pos_t(xyz(-10, -szSample*1.1, 2*hgtLayer), xyz(0, 0, -20), xyz::_z), animate);
+    setCamera(Camera::Position(Vector3D(-10, -szSample*1.1f, 2*hgtLayer),
+                               Vector3D(0, 0, -20), Vector3D::_z), animate);
 }
 
 void DemoModel::setCameraOne(bool animate) {
-  setCamera(Camera::pos_t(xyz(0, 0, spacing), xyz(0, 0, -20), xyz::_y), animate);
+    setCamera(Camera::Position(Vector3D(0, 0, spacing), Vector3D(0, 0, -20), Vector3D::_y), animate);
 }
 
-void DemoModel::setCamera(Camera::pos_t::rc to, bool animate) {
-  if (animate) {
-    auto from = camPos;
+void DemoModel::setCamera(const Camera::Position& to, bool animate) {
+    if (animate) {
+        auto from = camPos;
 
-    uint const frames = 45;
-    for_i (frames + 1) {
-      defCamPos = from.interpolateTo(to, flt(i) / frames);
-      snooze(true);
+        int const frames = 45;
+        for(int i=0; i<frames+1; ++i) {
+            defCamPos = from.interpolateTo(to, float(i) / frames);
+            snooze(true);
+        }
+    } else {
+        defCamPos = to;
+        snooze(true);
     }
-  } else {
-    defCamPos = to;
-    snooze(true);
-  }
 }
 
 void DemoModel::cameraUpdated(DemoModel::Camera const& cam) {
-  camPos = cam.getPos();
+    camPos = cam.getPos();
 }
 
 void DemoModel::addSubstrate() {
-  QColor clr = Qt::lightGray;
-  addLayer(dr(-hgtLayer, -hgtLayer - hgtSubstrate), clr);
+    QColor clr = Qt::lightGray;
+    addLayer(Range(-hgtLayer, -hgtLayer - hgtSubstrate), clr);
 }
 
 void DemoModel::addLayer() {
-  QColor clr = QColor(0, 100, 0);
-  addLayer(dr(0, -hgtLayer), clr);
+    QColor clr = QColor(0, 100, 0);
+    addLayer(Range(0, -hgtLayer), clr);
 }
 
-void DemoModel::addLayer(dr z, QColor clr) {
-  flt s2 = szSample / 2;
-  auto l = new Layer(dxyz(dr(-s2,+s2), dr(-s2,+s2), z));
-  clr.setAlphaF(.3);
-  l->color = clr;
-  addBlend(l);
+void DemoModel::addLayer(Range z, QColor clr) {
+    float s2 = szSample / 2;
+    auto l = new Layer(VectorRange(Range(-s2,+s2), Range(-s2,+s2), z));
+    clr.setAlphaF(.3);
+    l->color = clr;
+    addBlend(l);
 }
 
 void DemoModel::snooze(bool withEye) {
-  emit updated(withEye);
-  qApp->processEvents();
-  std::this_thread::sleep_for(std::chrono::milliseconds(10));
+    emit updated(withEye);
+    qApp->processEvents();
+    std::this_thread::sleep_for(std::chrono::milliseconds(10));
 }
 
-//------------------------------------------------------------------------------
diff --git a/GUI/ba3d/demo/demo_model.h b/GUI/ba3d/demo/demo_model.h
index 0dd1378237522cca6f4b444053f83690be05bcff..70e166617878e5c62fb1762a6eecf08e10af32d3 100644
--- a/GUI/ba3d/demo/demo_model.h
+++ b/GUI/ba3d/demo/demo_model.h
@@ -20,62 +20,57 @@
 #include "lattice.h"
 #include <QAtomicInteger>
 
-//------------------------------------------------------------------------------
-
-class DemoModel : public ba3d::Model {
+class DemoModel : public RealSpace::Model {
 public:
-  using super = ba3d::Model;
+    using super = RealSpace::Model;
 
-  using xyz = ba3d::xyz;
-  using flt = ba3d::flt;
-  using Particle = ba3d::particle::Particle;
-  using Camera   = ba3d::Camera;
+    using Particle = RealSpace::Particles::Particle;
+    using Camera   = RealSpace::Camera;
 
-  DemoModel();
+    DemoModel();
 
-  void switchBack();
-  void switchFront();
-  void switchOne();
+    void switchBack();
+    void switchFront();
+    void switchOne();
 
-  void square(float sigma);
-  void one();
-  void oneOut();
-  void oneIn(ba3d::particle::kind);
+    void square(float sigma);
+    void one();
+    void oneOut();
+    void oneIn(RealSpace::Particles::EShape);
 
-  void setCameraTop(bool animate = false);
-  void setCameraSide(bool animate = false);
-  void setCameraOne(bool animate = false);
+    void setCameraTop(bool animate = false);
+    void setCameraSide(bool animate = false);
+    void setCameraOne(bool animate = false);
 
-  void setCamera(Camera::pos_t::rc, bool animate = false);
+    void setCamera(const Camera::Position&, bool animate = false);
 
-  void cameraUpdated(Camera const&);
+    void cameraUpdated(Camera const&);
 
 private:
-  void addSubstrate();
-  void addLayer();
+    void addSubstrate();
+    void addLayer();
 
-  enum {backNONE,  backSUBSTRATE, backLAYER }           back  = backNONE;
-  enum {frontNONE, frontONE, frontSQUARELOW,
-                   frontSQUAREHIGH, frontSQUAREINSANE } front = frontNONE;
+    enum {backNONE,  backSUBSTRATE, backLAYER }           back  = backNONE;
+    enum {frontNONE, frontONE, frontSQUARELOW,
+          frontSQUAREHIGH, frontSQUAREINSANE } front = frontNONE;
 
-  flt szSample = 400;
-  flt const spacing  = 20; // of particles
-  flt const R = 6;
-  flt const hgtLayer = 20, hgtSubstrate = 35;
+    float szSample = 400;
+    float const spacing  = 20; // of particles
+    float const R = 6;
+    float const hgtLayer = 20, hgtSubstrate = 35;
 
-  Camera::pos_t camPos;
+    Camera::Position camPos;
 
 private:
-  void addLayer(ba3d::dr, QColor);
+    void addLayer(RealSpace::Range, QColor);
 
-  QVector<Particle*> ps;
-  Particle* p; ba3d::particle::kind kind = ba3d::particle::kind::None;
+    QVector<Particle*> ps;
+    Particle* p; RealSpace::Particles::EShape kind = RealSpace::Particles::EShape::None;
 
-  Lattice activeMesh;
+    Lattice activeMesh;
 
 private:
-  void snooze(bool withEye);
+    void snooze(bool withEye);
 };
 
-//------------------------------------------------------------------------------
-#endif
+#endif  // BA3D_DEMOMODEL_H
diff --git a/GUI/ba3d/demo/lattice.cpp b/GUI/ba3d/demo/lattice.cpp
index 2cbb4377a53e86538c6f674933d5c51737988b98..c2d5ccc12c81c817ca3d99d365175331f400e40c 100644
--- a/GUI/ba3d/demo/lattice.cpp
+++ b/GUI/ba3d/demo/lattice.cpp
@@ -17,112 +17,115 @@
 #include <QTime>
 #include <qmath.h>
 
-//------------------------------------------------------------------------------
-
-Lattice::Lattice() : n(0) {}
-
-Lattice::Lattice(uint n_, uint nn) : super (nn), n(n_) {}
-
-uint Lattice::index(int ix, int iy) {
-  int nx = n, ny = n;
-  EXPECT (-nx <= ix && ix <= +nx)
-  EXPECT (-ny <= iy && iy <= +ny)
-  uint i = (2*nx + 1) * (iy + ny) + (ix + nx);
-  ENSURE (static_cast<int>(i) < count())
-  return i;
+Lattice::Lattice()
+    : n(0)
+{}
+
+Lattice::Lattice(uint n_, uint nn)
+    : super (nn), n(n_)
+{}
+
+uint Lattice::index(int ix, int iy)
+{
+    int nx = n, ny = n;
+    Q_ASSERT(-nx <= ix && ix <= +nx);
+    Q_ASSERT(-ny <= iy && iy <= +ny);
+    uint i = (2*nx + 1) * (iy + ny) + (ix + nx);
+    Q_ASSERT(static_cast<int>(i) < count());
+    return i;
 }
 
-int Lattice::ix(uint i) {
-  int nr = 2*n + 1;
-  return i % nr - n;
+int Lattice::ix(uint i)
+{
+    int nr = 2*n + 1;
+    return i % nr - n;
 }
 
-int Lattice::iy(uint i) {
-  int nr = 2*n + 1;
-  return i / nr - n;
+int Lattice::iy(uint i)
+{
+    int nr = 2*n + 1;
+    return i / nr - n;
 }
 
-Lattice squareLattice(uint n, float sigma) {
-  using flt = ba3d::flt;
-  using xyz = ba3d::xyz;
-
-  auto rand01 = [&]() -> float {
-    static bool seeded = false;
-    if (!seeded) {
-      seeded = true;
-      qsrand(QTime::currentTime().msec());
-    }
-    return qrand() / float(RAND_MAX);
-  };
-
-  auto place00 = [&]() -> xyz {
-    // https://www.taygeta.com/random/gaussian.html
-    float x01, y01, w;
-
-    do {
-      x01 = 2.f * rand01() - 1.f;
-      y01 = 2.f * rand01() - 1.f;
-      w   = x01 * x01 + y01 * y01;
-    } while (w >= 1.f);
-
-    w = sqrt(-2.f * qLn(w) / w);
-    return ba3d::xyz(x01 * w * sigma, y01 * w * sigma, 0.01);
-  };
-
-  auto placeHere = [&](xyz::rc here) -> xyz {
-    return place00() + here;
-  };
-
-  auto placeXY = [&](flt x, flt y) -> xyz {
-    return placeHere(xyz(x, y, 0));
-  };
-
-  uint nn = (2*n + 1) * (2*n + 1); // total number
-
-  auto mesh = Lattice(n, nn);
-
-  auto get = [&](int ix, int iy) -> xyz::rc {
-    return mesh.at(mesh.index(ix, iy));
-  };
-  (void)get;
-
-  auto isMade = [&](int ix, int iy) -> bool {
-    return xyz::_0 != mesh.at(mesh.index(ix, iy));
-  };
-
-  auto put = [&](int ix, int iy) {
-    if (!isMade(ix, iy))
-      mesh[mesh.index(ix, iy)] = placeXY(ix, iy);
-  };
-
-  auto growBy1Quadrant = [&](uint n, int mx, int my) {
-    EXPECT (n > 0)
-    EXPECT (1 == qAbs(mx) && 1 == qAbs(my))
-
-    put(0*mx, n*my); put(n*mx, 0*my);
-
-    for (uint i = 1; i < n; ++i) {
-      put(i*mx, n*my); put(n*mx, i*my);
-    }
-
-    put(n*mx, n*my);
-  };
-
-  auto growBy1 = [&](uint n) {
-    EXPECT (n > 0)
-    growBy1Quadrant(n, +1, +1);
-    growBy1Quadrant(n, +1, -1);
-    growBy1Quadrant(n, -1, +1);
-    growBy1Quadrant(n, -1, -1);
-  };
-
-  auto growTo = [&](uint n) {
-    for (uint i = 1; i <= n; ++i)
-      growBy1(i);
-  };
-
-  growTo(n);
-  return mesh;
+Lattice squareLattice(uint n, float sigma)
+{
+    using RealSpace::Vector3D;
+
+    auto rand01 = [&]() -> float {
+                  static bool seeded = false;
+                  if (!seeded) {
+                  seeded = true;
+                  qsrand(QTime::currentTime().msec());
 }
+                  return qrand() / float(RAND_MAX);
+};
+
+    auto place00 = [&]() -> Vector3D {
+                   // https://www.taygeta.com/random/gaussian.html
+                   float x01, y01, w;
+
+                   do {
+                   x01 = 2.f * rand01() - 1.f;
+                   y01 = 2.f * rand01() - 1.f;
+                   w   = x01 * x01 + y01 * y01;
+} while (w >= 1.f);
+
+                   w = sqrt(-2.f * qLn(w) / w);
+                   return Vector3D(x01 * w * sigma, y01 * w * sigma, 0.01);
+};
+
+    auto placeHere = [&](const Vector3D& here) -> Vector3D {
+        return place00() + here;
+    };
+
+    auto placeXY = [&](float x, float y) -> Vector3D {
+        return placeHere(Vector3D(x, y, 0));
+    };
+
+    uint nn = (2*n + 1) * (2*n + 1); // total number
+
+    auto mesh = Lattice(n, nn);
 
-//------------------------------------------------------------------------------
+    auto get = [&](int ix, int iy) -> const Vector3D& {
+        return mesh.at(mesh.index(ix, iy));
+    };
+    (void)get;
+
+    auto isMade = [&](int ix, int iy) -> bool {
+        return Vector3D::_0 != mesh.at(mesh.index(ix, iy));
+    };
+
+    auto put = [&](int ix, int iy) {
+        if (!isMade(ix, iy))
+            mesh[mesh.index(ix, iy)] = placeXY(ix, iy);
+    };
+
+    auto growBy1Quadrant = [&](uint n, int mx, int my) {
+        Q_ASSERT(n > 0);
+        Q_ASSERT(1 == qAbs(mx) && 1 == qAbs(my));
+
+        put(0*mx, n*my); put(n*mx, 0*my);
+
+        for (uint i = 1; i < n; ++i) {
+            put(i*mx, n*my); put(n*mx, i*my);
+        }
+
+        put(n*mx, n*my);
+    };
+
+    auto growBy1 = [&](uint n) {
+        Q_ASSERT(n > 0);
+        growBy1Quadrant(n, +1, +1);
+        growBy1Quadrant(n, +1, -1);
+        growBy1Quadrant(n, -1, +1);
+        growBy1Quadrant(n, -1, -1);
+    };
+
+    auto growTo = [&](uint n) {
+        for (uint i = 1; i <= n; ++i)
+            growBy1(i);
+    };
+
+    growTo(n);
+    return mesh;
+}
diff --git a/GUI/ba3d/demo/lattice.h b/GUI/ba3d/demo/lattice.h
index 4fe15419af3217bc8408da1501fa29a8f0880bd4..0759d4cd8d3a5cf38f97a6eb6941efaa5741ae1a 100644
--- a/GUI/ba3d/demo/lattice.h
+++ b/GUI/ba3d/demo/lattice.h
@@ -18,22 +18,20 @@
 #include <ba3d/def.h>
 #include <QVector>
 
-//------------------------------------------------------------------------------
-
-class Lattice : public QVector<ba3d::xyz> {
+class Lattice : public QVector<RealSpace::Vector3D>
+{
 public:
-  using super = QVector<ba3d::xyz>;
+    using super = QVector<RealSpace::Vector3D>;
 
-  Lattice();
-  Lattice(uint n, uint nn);
+    Lattice();
+    Lattice(uint n, uint nn);
 
-  uint index(int ix, int iy);
-  int ix(uint);
-  int iy(uint);
-  uint n;
+    uint index(int ix, int iy);
+    int ix(uint);
+    int iy(uint);
+    uint n;
 };
 
 Lattice squareLattice(uint n, float sigma); // n half-size
 
-//------------------------------------------------------------------------------
-#endif
+#endif  // BA3D_LATTICE_H
diff --git a/GUI/ba3d/demo/main.cpp b/GUI/ba3d/demo/main.cpp
index 7b762db464c33082371e302211be52148984c0de..320ea72ea28bda69424cbc0ded039eef312c7b27 100644
--- a/GUI/ba3d/demo/main.cpp
+++ b/GUI/ba3d/demo/main.cpp
@@ -15,41 +15,39 @@
 #include <ba3d/def.h>
 #include <ba3d/view/camera.h>
 
-#include "mainwin.h"
+#include "mainwindow.h"
 #include "demo_model.h"
+#include <memory>
 #include <QApplication>
 
-//------------------------------------------------------------------------------
-
-class App : public QApplication { BASE(QApplication)
+class App : public QApplication
+{
 public:
-  App(int& argc, char* argv[]);
- ~App();
+    App(int& argc, char* argv[]);
+    ~App();
 
-  int exec();
+    int exec();
 };
 
-App::App(int& argc, char* argv[]) : base(argc, argv) {
-  setOrganizationName("c53");
-  setApplicationName("ba3d");
+App::App(int& argc, char* argv[]) : QApplication(argc, argv)
+{
+    setApplicationName("BornAgain real space demo");
 }
 
 App::~App() {}
 
-int App::exec() {
-  MainWin win;
-  win.show();
+int App::exec()
+{
+    MainWindow win;
+    win.show();
 
-  QScopedPointer<DemoModel> model(new DemoModel);
-  win.widg3t().setModel(model.data());
+    std::unique_ptr<DemoModel> model(new DemoModel);
+    win.widget3d().setModel(model.get());
 
-  return base::exec();
+    return QApplication::exec();
 }
 
-//------------------------------------------------------------------------------
-
-int main(int argc, char* argv[]) {
-  App(argc, argv).exec();
+int main(int argc, char* argv[])
+{
+    App(argc, argv).exec();
 }
-
-//------------------------------------------------------------------------------
diff --git a/GUI/ba3d/demo/mainwin.cpp b/GUI/ba3d/demo/mainwin.cpp
deleted file mode 100644
index 2408e014f28f8433cfa7e1a91e4cc9873aea8d27..0000000000000000000000000000000000000000
--- a/GUI/ba3d/demo/mainwin.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-// ************************************************************************** //
-//
-//  BornAgain: simulate and fit scattering at grazing incidence
-//
-//! @file      GUI/ba3d/demo/mainwin.cpp
-//! @brief     Implement MainWin class
-//!
-//! @homepage  http://www.bornagainproject.org
-//! @license   GNU General Public License v3 or higher (see COPYING)
-//! @copyright Forschungszentrum Jülich GmbH 2018
-//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
-//
-// ************************************************************************** //
-
-#include "mainwin.h"
-
-#include <QApplication>
-#include <QBoxLayout>
-#include <QSlider>
-#include <QSettings>
-#include <QPushButton>
-#include <QKeyEvent>
-
-//------------------------------------------------------------------------------
-
-static QString const MAINWIN_GEOMETRY("MainWin Geometry");
-
-MainWin::MainWin() {
-  setWindowTitle(qApp->applicationName());
-  createLayout();
-
-  QSettings s;
-  restoreGeometry(s.value(MAINWIN_GEOMETRY).toByteArray());
-}
-
-void MainWin::closeEvent(QCloseEvent*) {
-  QSettings s;
-  s.setValue(MAINWIN_GEOMETRY, saveGeometry());
-}
-
-void MainWin::keyPressEvent(QKeyEvent* e) {
-  if ("q" == e->text())
-    close();
-}
-
-void MainWin::createLayout() {
-  setCentralWidget(new QWidget);
-
-  auto vb = new QVBoxLayout;
-  centralWidget()->setLayout(vb);
-
-  vb->addWidget((w3d = new ba3d::Widget3D));
-
-#ifdef Q_OS_OSX
-  QColor clrBg(160,160,160);
-#else
-  QColor clrBg(palette().color(QPalette::Background));
-#endif
-  w3d->setBackground(clrBg);
-
-  auto hb = new QHBoxLayout;
-  vb->addLayout(hb);
-
-  auto btnSide  = new QPushButton("side");
-  auto btnTop   = new QPushButton("top");
-  auto btnOne   = new QPushButton("one");
-  auto btn0     = new QPushButton("=");
-  auto btn1     = new QPushButton("1|n");
-  auto btnP     = new QPushButton("p");
-  auto sldSigma = new QSlider(Qt::Horizontal);
-  auto btnSq    = new QPushButton("><");
-
-  hb->addWidget(btnSide);
-  hb->addWidget(btnTop);
-  hb->addWidget(btnOne);
-  hb->addStretch();
-  hb->addWidget(btn0);
-  hb->addWidget(btn1);
-  hb->addWidget(btnP);
-  hb->addStretch();
-  hb->addWidget(sldSigma);
-  hb->addWidget(btnSq);
-
-  sldSigma->setRange(0,30);
-  sldSigma->setSingleStep(5);
-  sldSigma->setTickInterval(5);
-  sldSigma->setTickPosition(QSlider::TicksBelow);
-
-  connect(btnSide, &QPushButton::clicked, [this]() {
-    model()->setCameraSide(true);
-  });
-
-  connect(btnTop, &QPushButton::clicked, [this]() {
-    model()->setCameraTop(true);
-  });
-
-  connect(btnOne, &QPushButton::clicked, [this]() {
-    model()->setCameraOne(true);
-  });
-
-  connect(btn0, &QPushButton::clicked, [this]() {
-    model()->switchBack();
-  });
-
-  connect(btn1, &QPushButton::clicked, [this]() {
-    model()->switchFront();
-  });
-
-  connect(btnP, &QPushButton::clicked, [this]() {
-    model()->switchOne();
-  });
-
-  connect(btnSq, &QPushButton::clicked, [this, sldSigma]() {
-    model()->square(sldSigma->value() / 100.f);
-  });
-}
-
-DemoModel* MainWin::model() {
-  auto model = dynamic_cast<DemoModel*>(w3d->getModel());
-  EXPECT(model)
-  return model;
-}
-
-//------------------------------------------------------------------------------
diff --git a/GUI/ba3d/demo/mainwindow.cpp b/GUI/ba3d/demo/mainwindow.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..35adc80628b9efd2f30e4622c0ed0b2b844caf07
--- /dev/null
+++ b/GUI/ba3d/demo/mainwindow.cpp
@@ -0,0 +1,125 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      GUI/ba3d/demo/mainwindow.cpp
+//! @brief     Implement MainWin class
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2018
+//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
+//
+// ************************************************************************** //
+
+#include "mainwindow.h"
+
+#include <QApplication>
+#include <QBoxLayout>
+#include <QSlider>
+#include <QSettings>
+#include <QPushButton>
+#include <QKeyEvent>
+
+static QString const MAINWIN_GEOMETRY("MainWin Geometry");
+
+MainWindow::MainWindow()
+{
+    setWindowTitle(qApp->applicationName());
+    createLayout();
+
+    QSettings s;
+    restoreGeometry(s.value(MAINWIN_GEOMETRY).toByteArray());
+}
+
+void MainWindow::closeEvent(QCloseEvent*)
+{
+    QSettings s;
+    s.setValue(MAINWIN_GEOMETRY, saveGeometry());
+}
+
+void MainWindow::keyPressEvent(QKeyEvent* e)
+{
+    if ("q" == e->text())
+        close();
+}
+
+void MainWindow::createLayout()
+{
+    setCentralWidget(new QWidget);
+
+    auto vb = new QVBoxLayout;
+    centralWidget()->setLayout(vb);
+
+    vb->addWidget((w3d = new RealSpace::Widget3D));
+
+#ifdef Q_OS_OSX
+    QColor clrBg(160,160,160);
+#else
+    QColor clrBg(palette().color(QPalette::Background));
+#endif
+    w3d->setBackground(clrBg);
+
+    auto hb = new QHBoxLayout;
+    vb->addLayout(hb);
+
+    auto btnSide  = new QPushButton("side");
+    auto btnTop   = new QPushButton("top");
+    auto btnOne   = new QPushButton("one");
+    auto btn0     = new QPushButton("=");
+    auto btn1     = new QPushButton("1|n");
+    auto btnP     = new QPushButton("p");
+    auto sldSigma = new QSlider(Qt::Horizontal);
+    auto btnSq    = new QPushButton("><");
+
+    hb->addWidget(btnSide);
+    hb->addWidget(btnTop);
+    hb->addWidget(btnOne);
+    hb->addStretch();
+    hb->addWidget(btn0);
+    hb->addWidget(btn1);
+    hb->addWidget(btnP);
+    hb->addStretch();
+    hb->addWidget(sldSigma);
+    hb->addWidget(btnSq);
+
+    sldSigma->setRange(0,30);
+    sldSigma->setSingleStep(5);
+    sldSigma->setTickInterval(5);
+    sldSigma->setTickPosition(QSlider::TicksBelow);
+
+    connect(btnSide, &QPushButton::clicked, [this]() {
+        model()->setCameraSide(true);
+    });
+
+    connect(btnTop, &QPushButton::clicked, [this]() {
+        model()->setCameraTop(true);
+    });
+
+    connect(btnOne, &QPushButton::clicked, [this]() {
+        model()->setCameraOne(true);
+    });
+
+    connect(btn0, &QPushButton::clicked, [this]() {
+        model()->switchBack();
+    });
+
+    connect(btn1, &QPushButton::clicked, [this]() {
+        model()->switchFront();
+    });
+
+    connect(btnP, &QPushButton::clicked, [this]() {
+        model()->switchOne();
+    });
+
+    connect(btnSq, &QPushButton::clicked, [this, sldSigma]() {
+        model()->square(sldSigma->value() / 100.f);
+    });
+}
+
+DemoModel* MainWindow::model()
+{
+    auto model = dynamic_cast<DemoModel*>(w3d->model());
+    Q_ASSERT(model);
+    return model;
+}
diff --git a/GUI/ba3d/demo/mainwin.h b/GUI/ba3d/demo/mainwindow.h
similarity index 55%
rename from GUI/ba3d/demo/mainwin.h
rename to GUI/ba3d/demo/mainwindow.h
index 1155ec67841137db1772fb409216188224bfcb80..d8f0599723a37190e9059fc891eafb49e9e8efa4 100644
--- a/GUI/ba3d/demo/mainwin.h
+++ b/GUI/ba3d/demo/mainwindow.h
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
-//! @file      GUI/ba3d/demo/mainwin.h
+//! @file      GUI/ba3d/demo/mainwindow.h
 //! @brief     Defines MainWin class
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -12,36 +12,34 @@
 //
 // ************************************************************************** //
 
-#ifndef BA3D_MAINWIN_H
-#define BA3D_MAINWIN_H
+#ifndef BA3D_MAINWINDOW_H
+#define BA3D_MAINWINDOW_H
 
 #include "demo_model.h"
 #include <ba3d/widget.h>
 #include <ba3d/model/particles.h>
 #include <QMainWindow>
 
-//------------------------------------------------------------------------------
-
 class QSlider;
 
-class MainWin : public QMainWindow { BASE(QMainWindow)
-  Q_OBJECT
+class MainWindow : public QMainWindow
+{
+    Q_OBJECT
 public:
-  MainWin();
+    MainWindow();
 
-  ba3d::Widget3D& widg3t() {
-    return *w3d;
-  }
+    RealSpace::Widget3D& widget3d() {
+        return *w3d;
+    }
 
 private:
-  void closeEvent(QCloseEvent*);
-  void keyPressEvent(QKeyEvent*);
+    void closeEvent(QCloseEvent*);
+    void keyPressEvent(QKeyEvent*);
 
-  void createLayout();
-  ba3d::Widget3D *w3d;
+    void createLayout();
+    RealSpace::Widget3D *w3d;
 
-  class DemoModel* model();
+    class DemoModel* model();
 };
 
-//------------------------------------------------------------------------------
-#endif
+#endif  // BA3D_MAINWINDOW_H
diff --git a/GUI/ba3d/showcase/CMakeLists.txt b/GUI/ba3d/showcase/CMakeLists.txt
index a72d8f66004ee9c26fda30fb6207d34f0fc4a0eb..ad49c0eb8880b2f5194a603f5cc761aa8ec5c72c 100644
--- a/GUI/ba3d/showcase/CMakeLists.txt
+++ b/GUI/ba3d/showcase/CMakeLists.txt
@@ -13,5 +13,3 @@ target_link_libraries (${app}
   Qt5::Core Qt5::Gui Qt5::Widgets
   ${OPENGL_gl_LIBRARY}
 )
-
-# eof
diff --git a/GUI/ba3d/showcase/main.cpp b/GUI/ba3d/showcase/main.cpp
index 8cc400b2e4e0e3d76927285d30aa653fe9874ced..972c07c1a94b5dea5d02698a27e2d4cc247a3604 100644
--- a/GUI/ba3d/showcase/main.cpp
+++ b/GUI/ba3d/showcase/main.cpp
@@ -15,14 +15,15 @@
 #include <ba3d/def.h>
 #include <ba3d/view/camera.h>
 
-#include "mainwin.h"
+#include "mainwindow.h"
 #include "modelLayers.h"
 #include "modelShowcase.h"
 #include <QApplication>
 
 //------------------------------------------------------------------------------
 
-class App : public QApplication { BASE(QApplication)
+class App : public QApplication
+{
 public:
   App(int& argc, char* argv[]);
  ~App();
@@ -30,7 +31,7 @@ public:
   int exec();
 };
 
-App::App(int& argc, char* argv[]) : base(argc, argv) {
+App::App(int& argc, char* argv[]) : QApplication(argc, argv) {
   setOrganizationName("c53");
   setApplicationName("ba3d");
 }
@@ -38,7 +39,7 @@ App::App(int& argc, char* argv[]) : base(argc, argv) {
 App::~App() {}
 
 int App::exec() {
-  MainWin win;
+  MainWindow win;
   win.show();
 
   QScopedPointer<ModelLayers>   ml(new ModelLayers);
@@ -50,14 +51,14 @@ int App::exec() {
   w2.setModel(ml.data());
   w3.setModel(ms.data());
 
-  w2.cam().lookAt(ba3d::Camera::pos_t(
-    ba3d::xyz::_z*90, ba3d::xyz(0,0,0), ba3d::xyz::_y));
+  w2.cam().lookAt(RealSpace::Camera::Position(
+    RealSpace::Vector3D::_z*90, RealSpace::Vector3D(0,0,0), RealSpace::Vector3D::_y));
 
-  connect(&win, &MainWin::showKind, [&](ba3d::particle::kind kind) {
+  connect(&win, &MainWindow::showKind, [&](RealSpace::Particles::EShape kind) {
     ml->showKind(kind); ms->showKind(kind);
   });
 
-  return base::exec();
+  return QApplication::exec();
 }
 
 //------------------------------------------------------------------------------
diff --git a/GUI/ba3d/showcase/mainwin.cpp b/GUI/ba3d/showcase/mainwindow.cpp
similarity index 76%
rename from GUI/ba3d/showcase/mainwin.cpp
rename to GUI/ba3d/showcase/mainwindow.cpp
index 926fcf689461d7d60cb6fca1aaf753e37204ceeb..e7265881f82dea0484d85098646ed4d93d5f4164 100644
--- a/GUI/ba3d/showcase/mainwin.cpp
+++ b/GUI/ba3d/showcase/mainwindow.cpp
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
-//! @file      GUI/ba3d/showcase/mainwin.cpp
+//! @file      GUI/ba3d/showcase/mainwindow.cpp
 //! @brief     Implements MainWin class
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -12,7 +12,7 @@
 //
 // ************************************************************************** //
 
-#include "mainwin.h"
+#include "mainwindow.h"
 
 #include <QAction>
 #include <QApplication>
@@ -26,7 +26,7 @@
 
 static QString const MAINWIN_GEOMETRY("MainWin Geometry");
 
-MainWin::MainWin() {
+MainWindow::MainWindow() {
   setWindowTitle(qApp->applicationName());
   createLayout();
 
@@ -34,19 +34,19 @@ MainWin::MainWin() {
   restoreGeometry(s.value(MAINWIN_GEOMETRY).toByteArray());
 }
 
-void MainWin::closeEvent(QCloseEvent*) {
+void MainWindow::closeEvent(QCloseEvent*) {
   QSettings s;
   s.setValue(MAINWIN_GEOMETRY, saveGeometry());
 }
 
-void MainWin::createLayout() {
+void MainWindow::createLayout() {
   setCentralWidget(new QWidget);
 
   auto hb = new QHBoxLayout;
   centralWidget()->setLayout(hb);
 
   // the thing
-  hb->addWidget((w3d_1 = new ba3d::Widget3D));
+  hb->addWidget((w3d_1 = new RealSpace::Widget3D));
   hb->setStretchFactor(w3d_1, 2);
   w3d_1->setBackground(palette().color(QPalette::Background));
 
@@ -54,21 +54,21 @@ void MainWin::createLayout() {
   hb->addLayout(vb);
   hb->setStretchFactor(vb, 1);
 
-  vb->addWidget((w3d_2 = new ba3d::Widget3D));
+  vb->addWidget((w3d_2 = new RealSpace::Widget3D));
   vb->setStretchFactor(w3d_2, 1);
 
-  vb->addWidget((w3d_3 = new ba3d::Widget3D));
+  vb->addWidget((w3d_3 = new RealSpace::Widget3D));
   vb->setStretchFactor(w3d_3, 1);
 
   vb->addWidget((combo = new QComboBox));
 
   {
-    using namespace ba3d::particle;
+    using namespace RealSpace::Particles;
     connect(combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), [&](int i) {
-      emit showKind(kind(int(Particle::firstKind)+i));
+      emit showKind(EShape(int(Particle::firstKind)+i));
     });
 
-    for (kind k=Particle::firstKind; k <= Particle::lastKind; k = kind(uint(k)+1))
+    for (EShape k=Particle::firstKind; k <= Particle::lastKind; k = EShape(uint(k)+1))
       combo->addItem(name(k));
   }
 }
diff --git a/GUI/ba3d/showcase/mainwin.h b/GUI/ba3d/showcase/mainwindow.h
similarity index 72%
rename from GUI/ba3d/showcase/mainwin.h
rename to GUI/ba3d/showcase/mainwindow.h
index 6f432aa1560da8680e68a857105199d8d89d99ea..9c4985b9fe36b1e99d481abbd37a3c6d359d602f 100644
--- a/GUI/ba3d/showcase/mainwin.h
+++ b/GUI/ba3d/showcase/mainwindow.h
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit scattering at grazing incidence
 //
-//! @file      GUI/ba3d/showcase/mainwin.h
+//! @file      GUI/ba3d/showcase/mainwindow.h
 //! @brief     Defines MainWin class
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -12,8 +12,8 @@
 //
 // ************************************************************************** //
 
-#ifndef BA3D_MAINWIN_H
-#define BA3D_MAINWIN_H
+#ifndef BA3D_MAINWINDOW_H
+#define BA3D_MAINWINDOW_H
 
 #include <ba3d/widget.h>
 #include <ba3d/model/particles.h>
@@ -23,30 +23,31 @@
 
 class QComboBox;
 
-class MainWin : public QMainWindow { BASE(QMainWindow)
-  Q_OBJECT
+class MainWindow : public QMainWindow
+{
+    Q_OBJECT
 public:
-  MainWin();
+  MainWindow();
 
-  ba3d::Widget3D& widg3t_1() {
+  RealSpace::Widget3D& widg3t_1() {
     return *w3d_1;
   }
 
-  ba3d::Widget3D& widg3t_2() {
+  RealSpace::Widget3D& widg3t_2() {
     return *w3d_2;
   }
 
-  ba3d::Widget3D& widg3t_3() {
+  RealSpace::Widget3D& widg3t_3() {
     return *w3d_3;
   }
 
 signals:
-  void showKind(ba3d::particle::kind);
+  void showKind(RealSpace::Particles::EShape);
 
 private:
   void closeEvent(QCloseEvent*);
 
-  ba3d::Widget3D *w3d_1, *w3d_2, *w3d_3;
+  RealSpace::Widget3D *w3d_1, *w3d_2, *w3d_3;
   QComboBox *combo;
 
   void createLayout();
diff --git a/GUI/ba3d/showcase/modelLayers.cpp b/GUI/ba3d/showcase/modelLayers.cpp
index f4feea458be6c0d29bbcd03eba320d6115403c52..957c75ce773263cbfe2a27f17da74f75add10eea 100644
--- a/GUI/ba3d/showcase/modelLayers.cpp
+++ b/GUI/ba3d/showcase/modelLayers.cpp
@@ -18,16 +18,16 @@
 
 //------------------------------------------------------------------------------
 
-using namespace ba3d;
+using namespace RealSpace;
 
-static flt const sz = 100; // half sz
+static float const sz = 100; // half sz
 
 ModelLayers::ModelLayers() {
-  defCamPos = Camera::pos_t(xyz(-10, -140, 20), xyz(0, 0, -30), xyz::_z);
+  defCamPos = Camera::Position(Vector3D(-10, -140, 20), Vector3D(0, 0, -30), Vector3D::_z);
 
   auto layer = [&](int z1, int z2, QColor color) {
-    flt s2 = sz /2;
-    auto l = new Layer(dxyz(dr(-s2,+s2), dr(-s2,+s2), dr(z1, z2)));
+    float s2 = sz /2;
+    auto l = new Layer(VectorRange(Range(-s2,+s2), Range(-s2,+s2), Range(z1, z2)));
     color.setAlphaF(.3);
     l->color = color;
 
@@ -40,22 +40,22 @@ ModelLayers::ModelLayers() {
   layer(-45, -55, Qt::gray);
 }
 
-void ModelLayers::showKind(particle::kind k) {
+void ModelLayers::showKind(Particles::EShape k) {
   for (auto p : ps)
     delete p;
   ps.clear();
 
-  if (particle::kind::None == k)
+  if (Particles::EShape::None == k)
     return;
 
-  flt z[] = {-10, -30, -45};
+  float z[] = {-10, -30, -45};
   ps.reserve(3*9*9);
-  for_int (i, 9)
-    for_int (j, 9)
-      for_int (zi, 3) {
+  for(int i=0; i<9; ++i)
+    for(int j=0; j<9; ++j)
+      for(int zi=0; zi<3; ++zi) {
         auto p = ModelShowcase::newParticle(k, 3);
         add(p); ps.append(p);
-        p->transform(xyz::_0, xyz((i-4)*sz/10, (j-4)*sz/10, z[zi]+.001f));
+        p->transform(Vector3D::_0, Vector3D((i-4)*sz/10, (j-4)*sz/10, z[zi]+.001f));
       }
 
   emit updated(false);
diff --git a/GUI/ba3d/showcase/modelLayers.h b/GUI/ba3d/showcase/modelLayers.h
index 12289679d53c9ebc9dce54348303dc9794a943d9..b2ab775db3d185cd28d119b5234e02d65434d866 100644
--- a/GUI/ba3d/showcase/modelLayers.h
+++ b/GUI/ba3d/showcase/modelLayers.h
@@ -20,13 +20,13 @@
 
 //------------------------------------------------------------------------------
 
-class ModelLayers : public ba3d::Model {
+class ModelLayers : public RealSpace::Model {
 public:
   ModelLayers();
-  void showKind(ba3d::particle::kind);
+  void showKind(RealSpace::Particles::EShape);
 
 private:
-  QVector<ba3d::particle::Particle*> ps;
+  QVector<RealSpace::Particles::Particle*> ps;
 };
 
 //------------------------------------------------------------------------------
diff --git a/GUI/ba3d/showcase/modelShowcase.cpp b/GUI/ba3d/showcase/modelShowcase.cpp
index 63adbc37c531be317865760cf6a36df6a7ea7a71..1ba05e38660fa2038572d945b0766456d3639094 100644
--- a/GUI/ba3d/showcase/modelShowcase.cpp
+++ b/GUI/ba3d/showcase/modelShowcase.cpp
@@ -16,25 +16,25 @@
 
 //------------------------------------------------------------------------------
 
-using namespace ba3d;
+using namespace RealSpace;
 
-static flt const R = 1;
+static float const R = 1;
 
 ModelShowcase::ModelShowcase() : p(nullptr) {
-  defCamPos.eye = xyz(0, -4*R, 0);
-  defCamPos.ctr = xyz(0, 0, R);
+  defCamPos.eye = Vector3D(0, -4*R, 0);
+  defCamPos.ctr = Vector3D(0, 0, R);
 
   Object *o;
 
   // bounding box
-  addBlend(o = new Object(geometry::key(geometry::eid::Box)));
+  addBlend(o = new Object(GeometricID::Key(GeometricID::BaseShape::Box)));
   o->color = QColor(0, 255, 0, 50);
-  o->transform(2*R, xyz::_0, xyz(0,0,R));
+  o->transform(2*R, Vector3D::_0, Vector3D(0,0,R));
 
   // bounding sphere
-  addBlend(o = new Object(geometry::key(geometry::eid::Sphere)));
+  addBlend(o = new Object(GeometricID::Key(GeometricID::BaseShape::Sphere)));
   o->color = QColor(0, 255, 255, 50);
-  o->transform(2*R, xyz::_0, xyz(0,0,R));
+  o->transform(2*R, Vector3D::_0, Vector3D(0,0,R));
 }
 
 void ModelShowcase::showKind(kind k) {
diff --git a/GUI/ba3d/showcase/modelShowcase.h b/GUI/ba3d/showcase/modelShowcase.h
index 65e5527749a56e92aa2aa2c5b980ed1117007f9f..8b5f621622fc40aeb3dba5a97f9a6d2b9572068c 100644
--- a/GUI/ba3d/showcase/modelShowcase.h
+++ b/GUI/ba3d/showcase/modelShowcase.h
@@ -20,10 +20,10 @@
 
 //------------------------------------------------------------------------------
 
-class ModelShowcase : public ba3d::Model {
+class ModelShowcase : public RealSpace::Model {
 public:
-  using Particle = ba3d::particle::Particle;
-  using kind     = ba3d::particle::kind;
+  using Particle = RealSpace::Particles::Particle;
+  using kind     = RealSpace::Particles::EShape;
 
   ModelShowcase();
   void showKind(kind);
diff --git a/GUI/coregui/Views/RealSpaceWidgets/RealSpaceBuilder.cpp b/GUI/coregui/Views/RealSpaceWidgets/RealSpaceBuilder.cpp
index fe195c91d95dc223f14367d985101e1c6be06386..84118238d7b8a5cf8d821257dfc327bc74b56650 100644
--- a/GUI/coregui/Views/RealSpaceWidgets/RealSpaceBuilder.cpp
+++ b/GUI/coregui/Views/RealSpaceWidgets/RealSpaceBuilder.cpp
@@ -25,10 +25,10 @@
 
 void RealSpaceBuilder::populate(RealSpaceModel* model, const SessionItem& item)
 {
-    model->defCamPos = ba3d::Camera::pos_t(
-        ba3d::xyz(-10, -140, 20),   // eye
-        ba3d::xyz(0, 0, -30),       // center
-        ba3d::xyz::_z);             // up vector
+    model->defCamPos = RealSpace::Camera::Position(
+        RealSpace::Vector3D(-10, -140, 20),   // eye
+        RealSpace::Vector3D(0, 0, -30),       // center
+        RealSpace::Vector3D::_z);             // up vector
 
     if (item.modelType() == Constants::MultiLayerType)
         populateMultiLayer(model, item);
@@ -86,7 +86,7 @@ void RealSpaceBuilder::populateParticle(RealSpaceModel* model, const SessionItem
     auto particle = TransformTo3D::createParticle(particleItem);
 
     if (particle) {
-        particle->transform(ba3d::xyz::_0, ba3d::xyz(origin.x(), origin.y(), origin.z()));
+        particle->transform(RealSpace::Vector3D::_0, RealSpace::Vector3D(origin.x(), origin.y(), origin.z()));
         model->add(particle.release());
     }
 }
diff --git a/GUI/coregui/Views/RealSpaceWidgets/RealSpaceModel.h b/GUI/coregui/Views/RealSpaceWidgets/RealSpaceModel.h
index db45bef7b8ba4c79c96a43b08425f35cffe37a97..a82504a6bce18d4d7dde7c3bcc6bf4bdf690f6b2 100644
--- a/GUI/coregui/Views/RealSpaceWidgets/RealSpaceModel.h
+++ b/GUI/coregui/Views/RealSpaceWidgets/RealSpaceModel.h
@@ -18,7 +18,7 @@
 #include "WinDllMacros.h"
 #include <ba3d/model/model.h>
 
-class RealSpaceModel : public ba3d::Model
+class RealSpaceModel : public RealSpace::Model
 {
 public:
 
diff --git a/GUI/coregui/Views/RealSpaceWidgets/RealSpaceView.cpp b/GUI/coregui/Views/RealSpaceWidgets/RealSpaceView.cpp
index 60a274c8dd2b5d7b3417d0539bd47fc1ef2026c4..f3b9888daab464d332669e812cc3b198759817c5 100644
--- a/GUI/coregui/Views/RealSpaceWidgets/RealSpaceView.cpp
+++ b/GUI/coregui/Views/RealSpaceWidgets/RealSpaceView.cpp
@@ -19,7 +19,7 @@
 
 RealSpaceView::RealSpaceView(QWidget* parent)
     : QWidget(parent)
-    , m_3dview(new ba3d::Widget3D)
+    , m_3dview(new RealSpace::Widget3D)
 {
     QVBoxLayout* layout = new QVBoxLayout;
     layout->setMargin(0);
diff --git a/GUI/coregui/Views/RealSpaceWidgets/RealSpaceView.h b/GUI/coregui/Views/RealSpaceWidgets/RealSpaceView.h
index f059a65ccfd39f9b4f1425327f048f8d28ba2587..5ea83bd91b40782f488fe5c89bb2772c06cfd068 100644
--- a/GUI/coregui/Views/RealSpaceWidgets/RealSpaceView.h
+++ b/GUI/coregui/Views/RealSpaceWidgets/RealSpaceView.h
@@ -20,7 +20,7 @@
 
 class RealSpaceModel;
 
-namespace ba3d { class Widget3D;}
+namespace RealSpace { class Widget3D;}
 
 //! Contains 3D view.
 
@@ -34,7 +34,7 @@ public:
     void setModel(RealSpaceModel* model);
 
 private:
-    ba3d::Widget3D* m_3dview;
+    RealSpace::Widget3D* m_3dview;
 };
 
 #endif // REALSPACEVIEW_H
diff --git a/GUI/coregui/Views/RealSpaceWidgets/TransformTo3D.cpp b/GUI/coregui/Views/RealSpaceWidgets/TransformTo3D.cpp
index a963ccdb5ba7f923b8f5bc55c490b814eefafc5e..6fb0cbabe127a4b1ca88de805898cfa163e9060a 100644
--- a/GUI/coregui/Views/RealSpaceWidgets/TransformTo3D.cpp
+++ b/GUI/coregui/Views/RealSpaceWidgets/TransformTo3D.cpp
@@ -54,7 +54,7 @@ double TransformTo3D::visualLayerThickness(const SessionItem& layerItem)
     return thickness == 0.0 ? layer_min_thickness :  thickness;
 }
 
-std::unique_ptr<ba3d::Layer> TransformTo3D::createLayer(const SessionItem& layerItem, const QVector3D& origin)
+std::unique_ptr<RealSpace::Layer> TransformTo3D::createLayer(const SessionItem& layerItem, const QVector3D& origin)
 {
     Q_ASSERT(layerItem.modelType() == Constants::LayerType);
 
@@ -64,8 +64,8 @@ std::unique_ptr<ba3d::Layer> TransformTo3D::createLayer(const SessionItem& layer
     double ztop = origin.z() + thickness;
     double zbottom = origin.z();
 
-    std::unique_ptr<ba3d::Layer> result = std::make_unique<ba3d::Layer>(
-        ba3d::dxyz(ba3d::dr(-s2,+s2), ba3d::dr(-s2,+s2), ba3d::dr(ztop, zbottom)));
+    std::unique_ptr<RealSpace::Layer> result = std::make_unique<RealSpace::Layer>(
+        RealSpace::VectorRange(RealSpace::Range(-s2,+s2), RealSpace::Range(-s2,+s2), RealSpace::Range(ztop, zbottom)));
 
     QColor color = layerItem.getItemValue(LayerItem::P_MATERIAL).value<ExternalProperty>().color();
     color.setAlphaF(.3);
@@ -76,12 +76,12 @@ std::unique_ptr<ba3d::Layer> TransformTo3D::createLayer(const SessionItem& layer
 }
 
 
-std::unique_ptr<ba3d::particle::Particle>
+std::unique_ptr<RealSpace::Particles::Particle>
 TransformTo3D::createParticle(const SessionItem& particleItem)
 {
     Q_ASSERT(particleItem.modelType() == Constants::ParticleType);
 
-    std::unique_ptr<ba3d::particle::Particle> result;
+    std::unique_ptr<RealSpace::Particles::Particle> result;
 
     auto ffItem = static_cast<FormFactorItem*>(
                 particleItem.getGroupItem(ParticleItem::P_FORM_FACTOR));
@@ -89,14 +89,14 @@ TransformTo3D::createParticle(const SessionItem& particleItem)
     if(ffItem->modelType() == Constants::CylinderType) {
         double radius = ffItem->getItemValue(CylinderItem::P_RADIUS).toDouble();
         double height = ffItem->getItemValue(CylinderItem::P_HEIGHT).toDouble();
-        result = std::make_unique<ba3d::particle::Cylinder>(radius, height);
+        result = std::make_unique<RealSpace::Particles::Cylinder>(radius, height);
     }
 
     else if(ffItem->modelType() == Constants::BoxType) {
         double length = ffItem->getItemValue(BoxItem::P_LENGTH).toDouble();
         double width = ffItem->getItemValue(BoxItem::P_WIDTH).toDouble();
         double height = ffItem->getItemValue(BoxItem::P_HEIGHT).toDouble();
-        result = std::make_unique<ba3d::particle::Box>(length, width, height);
+        result = std::make_unique<RealSpace::Particles::Box>(length, width, height);
     }
 
     if(result) {
@@ -110,7 +110,7 @@ TransformTo3D::createParticle(const SessionItem& particleItem)
         double x = positionItem->getItemValue(VectorItem::P_X).toDouble();
         double y = positionItem->getItemValue(VectorItem::P_Y).toDouble();
         double z = positionItem->getItemValue(VectorItem::P_Z).toDouble();
-        result->transform(ba3d::xyz::_0, ba3d::xyz(x, y, z));
+        result->transform(RealSpace::Vector3D::_0, RealSpace::Vector3D(x, y, z));
     }
 
     return result;
diff --git a/GUI/coregui/Views/RealSpaceWidgets/TransformTo3D.h b/GUI/coregui/Views/RealSpaceWidgets/TransformTo3D.h
index e84ffb96b19dd9433a33d6c32c0a9ea28557f8d6..c454f915003df5e0873830dc8186773643e3d589 100644
--- a/GUI/coregui/Views/RealSpaceWidgets/TransformTo3D.h
+++ b/GUI/coregui/Views/RealSpaceWidgets/TransformTo3D.h
@@ -31,11 +31,11 @@ namespace TransformTo3D
 BA_CORE_API_ double visualLayerThickness(const SessionItem& layerItem);
 
 BA_CORE_API_
-std::unique_ptr<ba3d::Layer> createLayer(const SessionItem& layerItem,
+std::unique_ptr<RealSpace::Layer> createLayer(const SessionItem& layerItem,
                                          const QVector3D& origin = QVector3D());
 
 BA_CORE_API_
-std::unique_ptr<ba3d::particle::Particle> createParticle(const SessionItem& particleItem);
+std::unique_ptr<RealSpace::Particles::Particle> createParticle(const SessionItem& particleItem);
 
 }