1
1
forked from 0ad/0ad
0ad/source/dcdt/se/se_mesh.cpp

239 lines
5.9 KiB
C++

#include "precompiled.h"
#include "0ad_warning_disable.h"
# include "sr_array.h"
# include "se_mesh.h"
# define IFTYPE(t,v,e,f) t==TypeVertex? (v) : t==TypeEdge? (e) : (f)
# define GETINFO(t,x) t==TypeVertex? (SeElement*)x->vertex : t==TypeEdge? (SeElement*)x->edge : (SeElement*)x->face
//================================= static functions =====================================
static void fatal_error ( const char* msg )
{
sr_out.fatal_error ( msg );
}
//============================= SeMeshBase Private Methods =====================================
void SeMeshBase::_defaults ()
{
_first = 0;
_op_last_msg = OpNoErrors;
_curmark = 0;
_marking = false;
_indexing = false;
_vertices = _edges = _faces = 0;
}
SeBase* SeMeshBase::_op_error ( OpMsg m )
{
_op_last_msg = (OpMsg)m;
if ( _output_op_errors )
{ sr_out << "Error in SeMeshBase operation: "
<< translate_op_msg(m) << srnl;
}
return (SeBase*) 0;
}
//============================ SeMeshBase general =====================================
semeshindex se_index_max_value = ((semeshindex)0)-1; // This is the unsigned greatest value;
SeMeshBase::SeMeshBase ( SrClassManagerBase* vtxman, SrClassManagerBase* edgman, SrClassManagerBase* facman )
{
_defaults ();
_output_op_errors = 0;
if ( !vtxman || !edgman || !facman )
fatal_error ( "SeMeshBase::SeMeshBase(): null pointer received!" );
_vtxman = vtxman;
_edgman = edgman;
_facman = facman;
_op_check_parms = 0;
}
SeMeshBase::~SeMeshBase ()
{
destroy ();
_vtxman->unref();
_edgman->unref();
_facman->unref();
}
/* from [mantyla] :
v-e+f = h0-h1+h2 ( Betti numbers )
h0 = shells
h1 = 2 * genus ( every closed curve cut a part of the surface away )
h2 = orientability = h0
==> v-e+f = s-2g+s = 2s-2g = 2(s-g), if s==1, => v-e+f=2-2g */
int SeMeshBase::euler () const
{
return _vertices - _edges + _faces;
}
int SeMeshBase::genus () const
{
return (_vertices-_edges+_faces-2)/(-2);
}
int SeMeshBase::elems ( ElemType type ) const
{
switch ( type )
{ case TypeVertex : return _vertices;
case TypeEdge : return _edges;
case TypeFace : return _faces;
}
return 0;
}
void SeMeshBase::invert_faces ()
{
SeBase *se;
SeElement *edg, *edgi;
int i, j, symedges = _edges*2;
if ( !_first ) return;
SrArray<SeBase*> nse(symedges,symedges);
SrArray<SeBase*> nxt(symedges,symedges);
SrArray<SeBase*> rot(symedges,symedges);
SrArray<SeVertex*> vtx(symedges,symedges);
i=0;
edg = edgi = _first->edg();
do { se = edg->se();
for ( j=0; j<2; j++ )
{ if ( j==1 ) se = se->sym();
vtx[i] = se->nxt()->vtx();
nxt[i] = se->pri();
rot[i] = se->nxt()->sym();
nse[i] = se;
i++;
}
edg = edg->nxt();
} while ( edg!=edgi );
for ( i=0; i<symedges; i++ )
{ //fg_out<<i<<" "<<(int)nse[i]<<fgnl;
nse[i]->_next = nxt[i];
nse[i]->_rotate = rot[i];
nse[i]->_vertex = vtx[i];
vtx[i]->_symedge = nse[i];
}
}
int SeMeshBase::vertices_in_face ( SeBase *e ) const
{
int i;
SeBase *x=e->nxt();
for ( i=1; x!=e; i++ ) x=x->nxt();
return i;
}
int SeMeshBase::vertex_degree ( SeBase *e ) const
{
int i=1;
SeBase *x;
for ( x=e->rot(); x!=e; i++ ) x=x->rot();
return i;
}
float SeMeshBase::mean_vertex_degree () const
{
if ( !_vertices ) return 0;
SeVertex* vi = _first->vtx();
SeVertex* v = vi;
float deg=0;
do { deg += vertex_degree(v->se());
v = v->nxt();
} while ( v!=vi );
return deg / (float)_vertices;
}
//============================ SeMeshBase marking =====================================
// replace _marking and _indexing by _mark_status !!
void SeMeshBase::_normalize_mark () // private method
{
SeElement *ei, *e;
_curmark=1;
if ( !_first ) return;
ei=e=_first->vtx(); do { e->_index=0; e=e->nxt(); } while ( e!=ei );
ei=e=_first->edg(); do { e->_index=0; e=e->nxt(); } while ( e!=ei );
ei=e=_first->fac(); do { e->_index=0; e=e->nxt(); } while ( e!=ei );
}
void SeMeshBase::begin_marking ()
{
if ( _indexing || _marking )
fatal_error("SeMeshBase::begin_marking() not allowed as marking or indexing is already in use!");
_marking = true;
if ( _curmark==se_index_max_value )
{ _normalize_mark ();
}
else _curmark++;
}
void SeMeshBase::end_marking ()
{
_marking = false;
}
bool SeMeshBase::marked ( SeElement* e )
{
if ( !_marking ) fatal_error ( "SeMeshBase::marked(e): marking is not active!\n" );
return e->_index==_curmark? true:false;
}
void SeMeshBase::mark ( SeElement* e )
{
if ( !_marking ) fatal_error ( "SeMeshBase::mark(e): marking is not active!\n" );
e->_index = _curmark;
}
void SeMeshBase::unmark ( SeElement* e )
{
if ( !_marking ) fatal_error ( "SeMeshBase::unmark(e): marking is not active!\n");
e->_index = _curmark-1;
}
//============================ SeMeshBase indexing =====================================
void SeMeshBase::begin_indexing ()
{
if ( _marking || _indexing )
fatal_error("SeMeshBase::begin_indexing() not allowed as marking or indexing is already in use!");
_indexing = true;
}
void SeMeshBase::end_indexing ()
{
_indexing = false;
_normalize_mark ();
}
semeshindex SeMeshBase::index ( SeElement* e )
{
if ( !_indexing ) fatal_error ("SeMeshBase::index(e): indexing is not active!");
return e->_index;
}
void SeMeshBase::index ( SeElement* e, semeshindex i )
{
if ( !_indexing ) fatal_error ("SeMeshBase::index(e,i): indexing is not active!");
e->_index = i;
}
//=== End of File ===================================================================