Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzExt includes
Toshihiro Shimizu 890ddd
#include "ext/plasticskeletondeformation.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// STL includes
Toshihiro Shimizu 890ddd
#include <set></set>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "tcg/tcg_misc.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_pool.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_function_types.h"
Toshihiro Shimizu 890ddd
#include "tcg/tcg_iterator_ops.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "ext/plasticskeleton.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PERSIST_IDENTIFIER(PlasticSkeletonVertex, "PlasticSkeletonVertex")
Toshihiro Shimizu 890ddd
PERSIST_IDENTIFIER(PlasticSkeleton, "PlasticSkeleton")
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DEFINE_CLASS_CODE(PlasticSkeleton, 122)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticSkeletonVertex  implementation
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticSkeletonVertex::PlasticSkeletonVertex()
Shinya Kitaoka 120a6e
    : tcg::Vertex<tpointd>()</tpointd>
Shinya Kitaoka 120a6e
    , m_number(-1)
Shinya Kitaoka 120a6e
    , m_parent(-1)
Shinya Kitaoka 120a6e
    , m_minAngle(-(std::numeric_limits<double>::max)())</double>
Shinya Kitaoka 120a6e
    , m_maxAngle((std::numeric_limits<double>::max)())</double>
Shinya Kitaoka 120a6e
    , m_interpolate(true) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticSkeletonVertex::PlasticSkeletonVertex(const TPointD &pos)
Shinya Kitaoka 120a6e
    : tcg::Vertex<tpointd>(pos)</tpointd>
Shinya Kitaoka 120a6e
    , m_number(-1)
Shinya Kitaoka 120a6e
    , m_parent(-1)
Shinya Kitaoka 120a6e
    , m_minAngle(-(std::numeric_limits<double>::max)())</double>
Shinya Kitaoka 120a6e
    , m_maxAngle((std::numeric_limits<double>::max)())</double>
Shinya Kitaoka 120a6e
    , m_interpolate(true) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeletonVertex::operator PlasticHandle() const {
Shinya Kitaoka 120a6e
  PlasticHandle result(P());
Shinya Kitaoka 120a6e
  result.m_interpolate = m_interpolate;
Shinya Kitaoka 120a6e
  return result;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonVertex::saveData(TOStream &os) {
Shinya Kitaoka 120a6e
  os.child("name") << m_name;
Shinya Kitaoka 120a6e
  os.child("number") << m_number;
Shinya Kitaoka 120a6e
  os.child("pos") << this->P().x << this->P().y;
Shinya Kitaoka 120a6e
  os.child("interpolate") << (int)this->m_interpolate;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_minAngle != -(std::numeric_limits<double>::max)())</double>
Shinya Kitaoka 120a6e
    os.child("minAngle") << m_minAngle;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_maxAngle != (std::numeric_limits<double>::max)())</double>
Shinya Kitaoka 120a6e
    os.child("maxAngle") << m_maxAngle;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeletonVertex::loadData(TIStream &is) {
Shinya Kitaoka 120a6e
  int val;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::string tagName;
Shinya Kitaoka 120a6e
  while (is.openChild(tagName)) {
Shinya Kitaoka 120a6e
    if (tagName == "name")
Shinya Kitaoka 120a6e
      is >> m_name, is.matchEndTag();
Shinya Kitaoka 120a6e
    else if (tagName == "number")
Shinya Kitaoka 120a6e
      is >> m_number, is.matchEndTag();
Shinya Kitaoka 120a6e
    else if (tagName == "pos")
Shinya Kitaoka 120a6e
      is >> this->P().x >> this->P().y, is.matchEndTag();
Shinya Kitaoka 120a6e
    else if (tagName == "interpolate")
Shinya Kitaoka 120a6e
      is >> val, m_interpolate = (bool)val, is.matchEndTag();
Shinya Kitaoka 120a6e
    else if (tagName == "minAngle")
Shinya Kitaoka 120a6e
      is >> m_minAngle, is.matchEndTag();
Shinya Kitaoka 120a6e
    else if (tagName == "maxAngle")
Shinya Kitaoka 120a6e
      is >> m_maxAngle, is.matchEndTag();
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      is.skipCurrentTag();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticSkeleton::Imp  definition
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class PlasticSkeleton::Imp {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  std::set<plasticskeletondeformation *=""> m_deformations;  //!< Registered</plasticskeletondeformation>
Shinya Kitaoka 38fd86
                                                          //! deformations for
Shinya Kitaoka 38fd86
  //! this skeleton (not
Shinya Kitaoka 38fd86
  //! owned)
Shinya Kitaoka 120a6e
  tcg::indices_pool<int></int>
Shinya Kitaoka 120a6e
      m_numbersPool;  //!< Vertex numbers pool (used for naming vertices only)
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Imp() {}
Shinya Kitaoka 120a6e
  Imp(const Imp &other);
Shinya Kitaoka 120a6e
  Imp &operator=(const Imp &other);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  Imp(Imp &&other);
Shinya Kitaoka 120a6e
  Imp &operator=(Imp &&other);
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//===============================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticSkeleton::Imp::Imp(const Imp &other)
Shinya Kitaoka 120a6e
    : m_numbersPool(other.m_numbersPool) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeleton::Imp &PlasticSkeleton::Imp::operator=(const Imp &other) {
Shinya Kitaoka 120a6e
  m_numbersPool = other.m_numbersPool;
Shinya Kitaoka 120a6e
  return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
PlasticSkeleton::Imp::Imp(Imp &&other)
Shinya Kitaoka 120a6e
    : m_numbersPool(std::move(other.m_numbersPool)) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeleton::Imp &PlasticSkeleton::Imp::operator=(Imp &&other) {
Shinya Kitaoka 120a6e
  m_numbersPool = std::move(other.m_numbersPool);
Shinya Kitaoka 120a6e
  return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticSkeleton  implementation
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeleton::PlasticSkeleton() : m_imp(new Imp) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeleton::~PlasticSkeleton() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PlasticSkeleton::PlasticSkeleton(const PlasticSkeleton &other)
Shinya Kitaoka 120a6e
    : mesh_type(other), m_imp(new Imp(*other.m_imp)) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeleton &PlasticSkeleton::operator=(const PlasticSkeleton &other) {
Shinya Kitaoka 120a6e
  assert(m_imp->m_deformations.empty());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  mesh_type::operator=(other);
Shinya Kitaoka 120a6e
  *m_imp             = *other.m_imp;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
PlasticSkeleton::PlasticSkeleton(PlasticSkeleton &&other)
Shinya Kitaoka 120a6e
    : mesh_type(std::forward<mesh_type>(other))</mesh_type>
Shinya Kitaoka 120a6e
    , m_imp(new Imp(std::move(*other.m_imp))) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
PlasticSkeleton &PlasticSkeleton::operator=(PlasticSkeleton &&other) {
Shinya Kitaoka 120a6e
  assert(m_imp->m_deformations.empty());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  mesh_type::operator=(std::forward<mesh_type>(other));</mesh_type>
Shinya Kitaoka 120a6e
  *m_imp             = std::move(*other.m_imp);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return *this;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeleton::addListener(PlasticSkeletonDeformation *deformation) {
Shinya Kitaoka 120a6e
  m_imp->m_deformations.insert(deformation);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeleton::removeListener(PlasticSkeletonDeformation *deformation) {
Shinya Kitaoka 120a6e
  m_imp->m_deformations.erase(deformation);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool PlasticSkeleton::setVertexName(int v, const QString &newName) {
Shinya Kitaoka 120a6e
  assert(!newName.isEmpty());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_vertices[v].m_name == newName) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Traverse the vertices list - if the same name already exists, return false
Shinya Kitaoka 120a6e
  tcg::list<vertex_type>::iterator vt, vEnd(m_vertices.end());</vertex_type>
Shinya Kitaoka 120a6e
  for (vt = m_vertices.begin(); vt != vEnd; ++vt)
Shinya Kitaoka 120a6e
    if (vt.m_idx != v &&
Shinya Kitaoka 120a6e
        vt->m_name == newName)  // v should be skipped in the check
Shinya Kitaoka 120a6e
      return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Notify deformations before changing the name
Shinya Kitaoka 120a6e
  std::set<plasticskeletondeformation *="">::iterator dt,</plasticskeletondeformation>
Shinya Kitaoka 120a6e
      dEnd(m_imp->m_deformations.end());
Shinya Kitaoka 120a6e
  for (dt = m_imp->m_deformations.begin(); dt != dEnd; ++dt)
Shinya Kitaoka 120a6e
    (*dt)->vertexNameChange(this, v, newName);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_vertices[v].m_name = newName;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeleton::moveVertex(int v, const TPointD &pos) {
Shinya Kitaoka 120a6e
  mesh_type::vertex(v).P() = pos;  // Apply new position
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int PlasticSkeleton::addVertex(const PlasticSkeletonVertex &vx, int parent) {
Shinya Kitaoka 120a6e
  // Add the vertex
Shinya Kitaoka 120a6e
  int v = mesh_type::addVertex(vx);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Retrieve a vertex index
Shinya Kitaoka 120a6e
  PlasticSkeletonVertex &vx_ = vertex(v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  vx_.m_number = m_imp->m_numbersPool.acquire();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Assign a name to the vertex in case none was given
Shinya Kitaoka 120a6e
  QString name(vx.name());
Shinya Kitaoka 120a6e
  if (name.isEmpty())
Shinya Kitaoka 120a6e
    name = (v == 0) ? QString("Root")
Shinya Kitaoka 120a6e
                    : "Vertex " +
Shinya Kitaoka 120a6e
                          QString::number(vx_.m_number).rightJustified(3, '_');
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Ensure the name is unique
Shinya Kitaoka 120a6e
  while (!setVertexName(v, name)) name += "_";
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (parent >= 0) {
Shinya Kitaoka 120a6e
    // Link it to the parent
Shinya Kitaoka 120a6e
    mesh_type::addEdge(
Shinya Kitaoka 120a6e
        edge_type(parent, v));  // Observe that parent is always v0
Shinya Kitaoka 120a6e
    vx_.m_parent = parent;
Shinya Kitaoka 120a6e
    assert(parent != v);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Notify deformations
Shinya Kitaoka 120a6e
  std::set<plasticskeletondeformation *="">::iterator dt,</plasticskeletondeformation>
Shinya Kitaoka 120a6e
      dEnd(m_imp->m_deformations.end());
Shinya Kitaoka 120a6e
  for (dt = m_imp->m_deformations.begin(); dt != dEnd; ++dt)
Shinya Kitaoka 120a6e
    (*dt)->addVertex(this, v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return v;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int PlasticSkeleton::insertVertex(const PlasticSkeletonVertex &vx, int parent,
Shinya Kitaoka 120a6e
                                  const std::vector<int> &children) {</int>
Shinya Kitaoka 120a6e
  assert(parent >= 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (children.empty()) return addVertex(vx, parent);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Add the vertex
Shinya Kitaoka 120a6e
  int v = mesh_type::addVertex(vx);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Retrieve a vertex index
Shinya Kitaoka 120a6e
  PlasticSkeletonVertex &vx_ = vertex(v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  vx_.m_number = m_imp->m_numbersPool.acquire();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Assign a name to the vertex in case none was given
Shinya Kitaoka 120a6e
  QString name(vx.name());
Shinya Kitaoka 120a6e
  if (name.isEmpty())
Shinya Kitaoka 120a6e
    name = "Vertex " + QString::number(vx_.m_number).rightJustified(3, '_');
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Ensure the name is unique
Shinya Kitaoka 120a6e
  while (!setVertexName(v, name)) name += "_";
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Link it to the parent
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    PlasticSkeletonVertex &vx_ = vertex(v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    mesh_type::addEdge(
Shinya Kitaoka 120a6e
        edge_type(parent, v));  // Observe that parent is always v0
Shinya Kitaoka 120a6e
    vx_.m_parent = parent;
Shinya Kitaoka 120a6e
    assert(parent != v);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Link it to children
Shinya Kitaoka 120a6e
  int c, cCount = int(children.size());
Shinya Kitaoka 120a6e
  for (c = 0; c != cCount; ++c) {
Shinya Kitaoka 120a6e
    int vChild                     = children[c];
Shinya Kitaoka 120a6e
    PlasticSkeletonVertex &vxChild = vertex(vChild);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    assert(vxChild.parent() == parent);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Remove the edge and substitute it with a new one
Shinya Kitaoka 120a6e
    int e = edgeInciding(parent, vChild);
Shinya Kitaoka 120a6e
    mesh_type::removeEdge(e);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    mesh_type::addEdge(edge_type(v, vChild));
Shinya Kitaoka 120a6e
    vxChild.m_parent = v;
Shinya Kitaoka 120a6e
    assert(v != vChild);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Notify deformations
Shinya Kitaoka 120a6e
  std::set<plasticskeletondeformation *="">::iterator dt,</plasticskeletondeformation>
Shinya Kitaoka 120a6e
      dEnd(m_imp->m_deformations.end());
Shinya Kitaoka 120a6e
  for (dt = m_imp->m_deformations.begin(); dt != dEnd; ++dt)
Shinya Kitaoka 120a6e
    (*dt)->insertVertex(this, v);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return v;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int PlasticSkeleton::insertVertex(const PlasticSkeletonVertex &vx, int e) {
Shinya Kitaoka 120a6e
  const edge_type &ed = edge(e);
Shinya Kitaoka 120a6e
  return insertVertex(vx, ed.vertex(0), std::vector<int>(1, ed.vertex(1)));</int>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeleton::removeVertex(int v) {
Shinya Kitaoka 120a6e
  int vNumber;
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    // Reparent all of v's children to its parent's children, first. This is
Shinya Kitaoka 120a6e
    // needed
Shinya Kitaoka 120a6e
    // to ensure that deformations update vertex deformations correctly.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    PlasticSkeletonVertex vx(
Shinya Kitaoka 120a6e
        vertex(v));  // Note the COPY - not referencing. It's best since
Shinya Kitaoka 120a6e
    // we'll be iterating and erasing vx's edges at the same time
Shinya Kitaoka 120a6e
    int parent = vx.m_parent;
Shinya Kitaoka 120a6e
    if (parent < 0) {
Shinya Kitaoka 120a6e
      // Root case - clear the whole skeleton
Shinya Kitaoka 120a6e
      clear();  // Should ensure that the next inserted vertex has index 0
Shinya Kitaoka 120a6e
      return;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Add edges from parent to vx's children
Shinya Kitaoka 120a6e
    vertex_type::edges_iterator et, eEnd = vx.edgesEnd();
Shinya Kitaoka 120a6e
    for (et = vx.edgesBegin(); et != eEnd; ++et) {
Shinya Kitaoka 120a6e
      int vChild = edge(*et).vertex(1);
Shinya Kitaoka 120a6e
      if (vChild == v) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      mesh_type::removeEdge(*et);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      mesh_type::addEdge(edge_type(parent, vChild));
Shinya Kitaoka 120a6e
      vertex(vChild).m_parent = parent;
Shinya Kitaoka 120a6e
      assert(vChild != parent);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    vNumber = vx.m_number;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Notify deformations BEFORE removing the vertex, so the vertex deformations
Shinya Kitaoka 120a6e
  // are still accessible.
Shinya Kitaoka 120a6e
  std::set<plasticskeletondeformation *="">::iterator dt,</plasticskeletondeformation>
Shinya Kitaoka 120a6e
      dEnd(m_imp->m_deformations.end());
Shinya Kitaoka 120a6e
  for (dt = m_imp->m_deformations.begin(); dt != dEnd; ++dt)
Shinya Kitaoka 120a6e
    (*dt)->deleteVertex(this, v);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Then, erase v. This already ensures that edges connected with v are
Shinya Kitaoka 120a6e
  // destroyed.
Shinya Kitaoka 120a6e
  mesh_type::removeVertex(v);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_imp->m_numbersPool.release(vNumber);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeleton::clear() {
Shinya Kitaoka 120a6e
  mesh_type::clear();
Shinya Kitaoka 120a6e
  m_imp->m_numbersPool.clear();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Notify deformations
Shinya Kitaoka 120a6e
  std::set<plasticskeletondeformation *="">::iterator dt,</plasticskeletondeformation>
Shinya Kitaoka 120a6e
      dEnd(m_imp->m_deformations.end());
Shinya Kitaoka 120a6e
  for (dt = m_imp->m_deformations.begin(); dt != dEnd; ++dt) (*dt)->clear(this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeleton::squeeze() {
Shinya Kitaoka 120a6e
  // Squeeze associated deformations first
Shinya Kitaoka 120a6e
  int v, e;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Update indices
Shinya Kitaoka 120a6e
  tcg::list<vertex_type>::iterator vt, vEnd(m_vertices.end());</vertex_type>
Shinya Kitaoka 120a6e
  for (v = 0, vt = m_vertices.begin(); vt != vEnd; ++vt, ++v) vt->setIndex(v);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  tcg::list<edge_type>::iterator et, eEnd(m_edges.end());</edge_type>
Shinya Kitaoka 120a6e
  for (e = 0, et = m_edges.begin(); et != eEnd; ++et, ++e) et->setIndex(e);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Update stored indices
Shinya Kitaoka 120a6e
  for (et = m_edges.begin(); et != eEnd; ++et) {
Shinya Kitaoka 120a6e
    edge_type &ed = *et;
Shinya Kitaoka 120a6e
    ed.setVertex(0, vertex(ed.vertex(0)).getIndex());
Shinya Kitaoka 120a6e
    ed.setVertex(1, vertex(ed.vertex(1)).getIndex());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (vt = m_vertices.begin(); vt != vEnd; ++vt) {
Shinya Kitaoka 120a6e
    vertex_type &vx = *vt;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (vt->m_parent >= 0) vt->m_parent = vertex(vt->m_parent).getIndex();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    vertex_type::edges_iterator vet, veEnd(vx.edgesEnd());
Shinya Kitaoka 120a6e
    for (vet = vx.edgesBegin(); vet != veEnd; ++vet)
Shinya Kitaoka 120a6e
      *vet = edge(*vet).getIndex();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Finally, rebuild the actual containers
Shinya Kitaoka 120a6e
  if (!m_edges.empty()) {
Shinya Kitaoka 120a6e
    tcg::list<edge_type> temp(m_edges.begin(), m_edges.end());</edge_type>
Shinya Kitaoka 120a6e
    std::swap(m_edges, temp);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_vertices.empty()) {
Shinya Kitaoka 120a6e
    tcg::list<vertex_type> temp(m_vertices.begin(), m_vertices.end());</vertex_type>
Shinya Kitaoka 120a6e
    std::swap(m_vertices, temp);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeleton::saveData(TOStream &os) {
Shinya Kitaoka 120a6e
  // NOTE: Primitives saved by INDEX iteration is NOT COINCIDENTAL - since
Shinya Kitaoka 120a6e
  // the lists' internal linking could have been altered to mismatch the
Shinya Kitaoka 120a6e
  // natural indexing referred to by primitives' data.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_vertices.size() != m_vertices.nodesCount() ||
Shinya Kitaoka 120a6e
      m_edges.size() != m_edges.nodesCount()) {
Shinya Kitaoka 120a6e
    // Ensure that there are no holes in the representation
Shinya Kitaoka 120a6e
    PlasticSkeleton skel(*this);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    skel.squeeze();
Shinya Kitaoka 120a6e
    skel.saveData(os);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Save vertices
Shinya Kitaoka 120a6e
  os.openChild("V");
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    int vCount = int(m_vertices.size());
Shinya Kitaoka 120a6e
    os << vCount;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (int v = 0; v != vCount; ++v) os.child("Vertex") << m_vertices[v];
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  os.closeChild();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Save edges
Shinya Kitaoka 120a6e
  os.openChild("E");
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    int eCount = int(m_edges.size());
Shinya Kitaoka 120a6e
    os << eCount;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (int e = 0; e != eCount; ++e) {
Shinya Kitaoka 120a6e
      PlasticSkeleton::edge_type &ed = m_edges[e];
Shinya Kitaoka 120a6e
      os << ed.vertex(0) << ed.vertex(1);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  os.closeChild();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void PlasticSkeleton::loadData(TIStream &is) {
Shinya Kitaoka 120a6e
  // Ensure the skeleton is clean
Shinya Kitaoka 120a6e
  clear();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Load vertices
Shinya Kitaoka 120a6e
  std::string str;
Shinya Kitaoka 120a6e
  int i, size;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  while (is.openChild(str)) {
Shinya Kitaoka 120a6e
    if (str == "V") {
Shinya Kitaoka 120a6e
      is >> size;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      std::vector<int> acquiredVertexNumbers;</int>
Shinya Kitaoka 120a6e
      acquiredVertexNumbers.reserve(size);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_vertices.reserve(size);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      for (i = 0; i < size; ++i) {
Shinya Kitaoka 120a6e
        if (is.openChild(str) && (str == "Vertex")) {
Shinya Kitaoka 120a6e
          vertex_type vx;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
          is >> vx;
Shinya Kitaoka 120a6e
          int idx = mesh_type::addVertex(vx);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
          if (vx.m_number < 0) vertex(idx).m_number = vx.m_number = idx + 1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
          acquiredVertexNumbers.push_back(vx.m_number);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
          is.matchEndTag();
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          assert(false), is.skipCurrentTag();
Shinya Kitaoka 120a6e
      }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_imp->m_numbersPool = tcg::indices_pool<int>(</int>
Shinya Kitaoka 120a6e
          acquiredVertexNumbers.begin(), acquiredVertexNumbers.end());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      is.matchEndTag();
Shinya Kitaoka 120a6e
    } else if (str == "E") {
Shinya Kitaoka 120a6e
      is >> size;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      m_edges.reserve(size);
Shinya Kitaoka 120a6e
      int v0, v1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      for (i = 0; i < size; ++i) {
Shinya Kitaoka 120a6e
        is >> v0 >> v1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        addEdge(edge_type(v0, v1));
Shinya Kitaoka 120a6e
        vertex(v1).m_parent = v0;
Shinya Kitaoka 120a6e
      }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      is.matchEndTag();
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      assert(false), is.skipCurrentTag();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
//    PlasticSkeleton  utility functions
Toshihiro Shimizu 890ddd
//************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int PlasticSkeleton::closestVertex(const TPointD &pos, double *dist) const {
Shinya Kitaoka 120a6e
  // Traverse vertices
Shinya Kitaoka 120a6e
  double d2, minDist2 = (std::numeric_limits<double>::max)();</double>
Shinya Kitaoka 120a6e
  int v = -1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  tcg::list<vertex_type>::const_iterator vt, vEnd(m_vertices.end());</vertex_type>
Shinya Kitaoka 120a6e
  for (vt = m_vertices.begin(); vt != vEnd; ++vt) {
Shinya Kitaoka 120a6e
    d2                          = tcg::point_ops::dist2(pos, vt->P());
Shinya Kitaoka 120a6e
    if (d2 < minDist2) minDist2 = d2, v = int(vt.m_idx);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (dist && v >= 0) *dist = sqrt(minDist2);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return v;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int PlasticSkeleton::closestEdge(const TPointD &pos, double *dist) const {
Shinya Kitaoka 120a6e
  // Traverse edges
Shinya Kitaoka 120a6e
  double d, minDist = (std::numeric_limits<double>::max)();</double>
Shinya Kitaoka 120a6e
  int e = -1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  tcg::list<edge_type>::const_iterator et, eEnd(m_edges.end());</edge_type>
Shinya Kitaoka 120a6e
  for (et = m_edges.begin(); et != eEnd; ++et) {
Shinya Kitaoka 120a6e
    const TPointD &vp0 = vertex(et->vertex(0)).P(),
Shinya Kitaoka 120a6e
                  &vp1 = vertex(et->vertex(1)).P();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    d                        = tcg::point_ops::segDist(vp0, vp1, pos);
Shinya Kitaoka 120a6e
    if (d < minDist) minDist = d, e = int(et.m_idx);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (dist && e >= 0) *dist = minDist;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return e;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::vector<plastichandle> PlasticSkeleton::verticesToHandles() const {</plastichandle>
Shinya Kitaoka 120a6e
  // Someway, PlasticHandle's EXPLICIT unary constructors are not enough
Shinya Kitaoka 120a6e
  // to disambiguate the direct construction of a vector of PlasticHandles
Shinya Kitaoka 120a6e
  // from m_vertices, at least with *gcc*. I guess it could be a compiler bug.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // So, we'll convert them using an explicit casting iterator...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  typedef tcg::function < PlasticHandle (PlasticSkeletonVertex::*)() const,
Shinya Kitaoka 120a6e
      &PlasticSkeletonVertex::operator PlasticHandle> Func;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return std::vector<plastichandle>(</plastichandle>
Shinya Kitaoka 120a6e
      tcg::make_cast_it(m_vertices.begin(), Func()),
Shinya Kitaoka 120a6e
      tcg::make_cast_it(m_vertices.end(), Func()));
Toshihiro Shimizu 890ddd
}