#ifndef PASTELGEOMETRY_HALFMESH_INVARIANTS_HPP
#define PASTELGEOMETRY_HALFMESH_INVARIANTS_HPP
#include "pastel/geometry/halfmesh/halfmesh_invariants.h"
namespace Pastel
{
template <
typename Settings,
template <typename> class Customization>
bool testInvariants(const HalfMesh<Settings, Customization>& mesh)
{
using Mesh = HalfMesh<Settings, Customization>;
using Fwd = Mesh;
PASTEL_FWD(Vertex_ConstIterator);
PASTEL_FWD(Half_ConstIterator);
PASTEL_FWD(Edge_ConstIterator);
PASTEL_FWD(Polygon_ConstIterator);
// Check vertex invariants
{
Vertex_ConstIterator vertex =
mesh.vertexBegin();
Vertex_ConstIterator vertexEnd =
mesh.vertexEnd();
while (vertex != vertexEnd)
{
if (vertex.empty())
{
// A vertex must exist.
return false;
}
if (!vertex.isNormal())
{
// A vertex must be normal.
return false;
}
if (vertex->isolated() != vertex->half().empty())
{
// An isolated vertex must not be connected
// to any half-edge.
return false;
}
if (vertex->isolated() && !vertex->free())
{
// An isolated vertex must be free.
return false;
}
Half_ConstIterator half = vertex->half();
if (!half.empty() && half->origin() != vertex)
{
// If the half-edge exists, the origin of the half-edge
// must be the vertex itself.
return false;
}
++vertex;
}
}
// Check edge invariants
{
Edge_ConstIterator edge =
mesh.edgeBegin();
Edge_ConstIterator edgeEnd =
mesh.edgeEnd();
while (edge != edgeEnd)
{
if (edge.empty())
{
// An edge always exist.
return false;
}
Half_ConstIterator half = edge->half();
if (half.empty())
{
// The half of an edge must exist.
return false;
}
if (half->edge() != edge)
{
// The edge of a half of an edge
// must be the edge itself.
return false;
}
++edge;
}
}
// Check polygon invariants
{
Polygon_ConstIterator polygon =
mesh.polygonBegin();
Polygon_ConstIterator polygonEnd =
mesh.polygonEnd();
while (polygon != polygonEnd)
{
if (polygon.empty())
{
// An polygon always exist.
return false;
}
Half_ConstIterator half = polygon->half();
if (half.empty())
{
// The half of a polygon must exist.
return false;
}
if (half->left() != polygon)
{
// The left of a half must be the
// polygon itself.
return false;
}
++polygon;
}
}
// Check half-edge invariants
{
Half_ConstIterator half =
mesh.halfBegin();
Half_ConstIterator halfEnd =
mesh.halfEnd();
while (half != halfEnd)
{
if (half.empty())
{
// A half-edge always exist.
return false;
}
Half_ConstIterator previous = half->previous();
Half_ConstIterator next = half->next();
Half_ConstIterator pair = half->pair();
if (previous.empty() ||
next.empty() ||
pair.empty() ||
half->origin().empty() ||
half->edge().empty())
{
// All of the fields of a half-edge
// must exist.
return false;
}
if (previous->next() != half ||
next->previous() != half ||
next->left() != half->left() ||
previous->left() != half->left() ||
pair->pair() != half ||
half->origin() != pair->destination() ||
pair->origin() != half->destination() ||
half->edge() != pair->edge())
{
// The fields must be linked to together
// in a bidirectional manner.
return false;
}
++half;
}
}
return true;
}
}
#endif