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