initial commit

This commit is contained in:
2020-09-22 08:41:49 +02:00
commit aa25b1eaef
248 changed files with 72844 additions and 0 deletions

13134
data/bunnyLowPoly.obj Normal file

File diff suppressed because it is too large Load Diff

38
data/cube.obj Normal file
View File

@ -0,0 +1,38 @@
# Blender v2.83.4 OBJ File: ''
# www.blender.org
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.125000 0.750000
vt 0.875000 0.500000
vt 0.875000 0.750000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/4/2 4/3/2 8/5/2 7/6/2
f 7/6/3 8/5/3 6/7/3 5/8/3
f 5/8/4 6/7/4 2/9/4 1/10/4
f 3/11/5 7/6/5 5/8/5 1/12/5
f 8/5/6 4/13/6 2/14/6 6/7/6

30
fractionnement.pro Normal file
View File

@ -0,0 +1,30 @@
QT += core gui opengl
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = fractionnement
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
CONFIG += debug
unix:!macx {
LIBS += -L $$_PRO_FILE_PWD_/libs/OpenMesh/liblinux/
}
macx {
LIBS += -L $$_PRO_FILE_PWD_/libs/OpenMesh/libosx/
}
LIBS += -lglut -lGLU -lOpenMeshCore -lm
INCLUDEPATH += libs/OpenMesh/inc/ src/
SOURCES += \
src/main.cpp \
src/mainwindow.cpp \
src/meshviewerwidget.cpp \
src/mymesh.cpp
HEADERS += \
src/mainwindow.h \
src/meshviewerwidget.h \
src/mymesh.h
FORMS += \
ui/mainwindow.ui

View File

@ -0,0 +1,75 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Defines
//
//=============================================================================
#ifndef OPENMESH_GEOMETRY_CONFIG_HH
#define OPENMESH_GEOMETRY_CONFIG_HH
//== INCLUDES =================================================================
// OpenMesh Namespace Defines
#include <OpenMesh/Core/System/config.h>
//== NAMESPACES ===============================================================
#define BEGIN_NS_GEOMETRY namespace geometry {
#define END_NS_GEOMETRY }
//=============================================================================
#endif // OPENMESH_GEOMETRY_CONFIG_HH defined
//=============================================================================

View File

@ -0,0 +1,196 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef LOOPSCHEMEMASKT_HH
#define LOOPSCHEMEMASKT_HH
#include <cmath>
#include <vector>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
namespace OpenMesh
{
/** implements cache for the weights of the original Loop scheme
supported:
- vertex projection rule on the next level
- vertex projection rule on the limit surface
- vertex projection rule on the k-th (level) step (Barthe, Kobbelt'2003)
- vertex tangents on the limit surface
*/
template <class T_, unsigned int cache_size_ = 100>
class LoopSchemeMaskT
{
public:
enum { cache_size = cache_size_ };
typedef T_ Scalar;
protected:
Scalar proj_weights_[cache_size];
Scalar limit_weights_[cache_size];
Scalar step_weights_[cache_size];
std::vector<Scalar> tang0_weights_[cache_size];
std::vector<Scalar> tang1_weights_[cache_size];
protected:
inline static Scalar compute_proj_weight(uint _valence)
{
//return pow(3.0 / 2.0 + cos(2.0 * M_PI / _valence), 2) / 2.0 - 1.0;
double denom = (3.0 + 2.0*cos(2.0*M_PI/(double)_valence));
double weight = (64.0*_valence)/(40.0 - denom*denom) - _valence;
return (Scalar) weight;
}
inline static Scalar compute_limit_weight(uint _valence)
{
double proj_weight = compute_proj_weight(_valence);
proj_weight = proj_weight/(proj_weight + _valence);//normalize the proj_weight
double weight = (3.0/8.0)/(1.0 - proj_weight + (3.0/8.0));
return (Scalar)weight;
}
inline static Scalar compute_step_weight(uint _valence)
{
double proj_weight = compute_proj_weight(_valence);
proj_weight = proj_weight/(proj_weight + _valence);//normalize the proj_weight
double weight = proj_weight - (3.0/8.0);
return (Scalar)weight;
}
inline static Scalar compute_tang0_weight(uint _valence, uint _ver_id)
{
return (Scalar)cos(2.0*M_PI*(double)_ver_id/(double)_valence);
}
inline static Scalar compute_tang1_weight(uint _valence, uint _ver_id)
{
return (Scalar)sin(2.0*M_PI*(double)_ver_id/(double)_valence);
}
void cache_weights()
{
proj_weights_[0] = 1;
for (uint k = 1; k < cache_size; ++k)
{
proj_weights_[k] = compute_proj_weight(k);
limit_weights_[k] = compute_limit_weight(k);
step_weights_[k] = compute_step_weight(k);
tang0_weights_[k].resize(k);
tang1_weights_[k].resize(k);
for (uint i = 0; i < k; ++i)
{
tang0_weights_[k][i] = compute_tang0_weight(k,i);
tang1_weights_[k][i] = compute_tang1_weight(k,i);
}
}
}
public:
LoopSchemeMaskT()
{
cache_weights();
}
inline Scalar proj_weight(uint _valence) const
{
assert(_valence < cache_size );
return proj_weights_[_valence];
}
inline Scalar limit_weight(uint _valence) const
{
assert(_valence < cache_size );
return limit_weights_[_valence];
}
inline Scalar step_weight(uint _valence, uint _step) const
{
assert(_valence < cache_size);
return pow(step_weights_[_valence], (int)_step);//can be precomputed
}
inline Scalar tang0_weight(uint _valence, uint _ver_id) const
{
assert(_valence < cache_size );
assert(_ver_id < _valence);
return tang0_weights_[_valence][_ver_id];
}
inline Scalar tang1_weight(uint _valence, uint _ver_id) const
{
assert(_valence < cache_size );
assert(_ver_id < _valence);
return tang1_weights_[_valence][_ver_id];
}
void dump(uint _max_valency = cache_size - 1) const
{
assert(_max_valency <= cache_size - 1);
//CConsole::printf("(k : pw_k, lw_k): ");
for (uint i = 0; i <= _max_valency; ++i)
{
//CConsole::stream() << "(" << i << " : " << proj_weight(i) << ", " << limit_weight(i) << ", " << step_weight(i,1) << "), ";
}
//CConsole::printf("\n");
}
};
typedef LoopSchemeMaskT<double, 100> LoopSchemeMaskDouble;
typedef SingletonT<LoopSchemeMaskDouble> LoopSchemeMaskDoubleSingleton;
}//namespace OpenMesh
#endif//LOOPSCHEMEMASKT_HH

View File

@ -0,0 +1,172 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef MATHDEFS_HH
#define MATHDEFS_HH
#include <cmath>
#include <cfloat>
#ifndef M_PI
#define M_PI 3.14159265359
#endif
namespace OpenMesh
{
/** comparison operators with user-selected precision control
*/
template <class T, typename Real>
inline bool is_zero(const T& _a, Real _eps)
{ return fabs(_a) < _eps; }
template <class T1, class T2, typename Real>
inline bool is_eq(const T1& a, const T2& b, Real _eps)
{ return is_zero(a-b, _eps); }
template <class T1, class T2, typename Real>
inline bool is_gt(const T1& a, const T2& b, Real _eps)
{ return (a > b) && !is_eq(a,b,_eps); }
template <class T1, class T2, typename Real>
inline bool is_ge(const T1& a, const T2& b, Real _eps)
{ return (a > b) || is_eq(a,b,_eps); }
template <class T1, class T2, typename Real>
inline bool is_lt(const T1& a, const T2& b, Real _eps)
{ return (a < b) && !is_eq(a,b,_eps); }
template <class T1, class T2, typename Real>
inline bool is_le(const T1& a, const T2& b, Real _eps)
{ return (a < b) || is_eq(a,b,_eps); }
/*const float flt_eps__ = 10*FLT_EPSILON;
const double dbl_eps__ = 10*DBL_EPSILON;*/
const float flt_eps__ = (float)1e-05;
const double dbl_eps__ = 1e-09;
inline float eps__(float)
{ return flt_eps__; }
inline double eps__(double)
{ return dbl_eps__; }
template <class T>
inline bool is_zero(const T& a)
{ return is_zero(a, eps__(a)); }
template <class T1, class T2>
inline bool is_eq(const T1& a, const T2& b)
{ return is_zero(a-b); }
template <class T1, class T2>
inline bool is_gt(const T1& a, const T2& b)
{ return (a > b) && !is_eq(a,b); }
template <class T1, class T2>
inline bool is_ge(const T1& a, const T2& b)
{ return (a > b) || is_eq(a,b); }
template <class T1, class T2>
inline bool is_lt(const T1& a, const T2& b)
{ return (a < b) && !is_eq(a,b); }
template <class T1, class T2>
inline bool is_le(const T1& a, const T2& b)
{ return (a < b) || is_eq(a,b); }
/// Trigonometry/angles - related
template <class T>
inline T sane_aarg(T _aarg)
{
if (_aarg < -1)
{
_aarg = -1;
}
else if (_aarg > 1)
{
_aarg = 1;
}
return _aarg;
}
/** returns the angle determined by its cos and the sign of its sin
result is positive if the angle is in [0:pi]
and negative if it is in [pi:2pi]
*/
template <class T>
T angle(T _cos_angle, T _sin_angle)
{//sanity checks - otherwise acos will return nan
_cos_angle = sane_aarg(_cos_angle);
return (T) _sin_angle >= 0 ? acos(_cos_angle) : -acos(_cos_angle);
}
template <class T>
inline T positive_angle(T _angle)
{ return _angle < 0 ? (2*M_PI + _angle) : _angle; }
template <class T>
inline T positive_angle(T _cos_angle, T _sin_angle)
{ return positive_angle(angle(_cos_angle, _sin_angle)); }
template <class T>
inline T deg_to_rad(const T& _angle)
{ return M_PI*(_angle/180); }
template <class T>
inline T rad_to_deg(const T& _angle)
{ return 180*(_angle/M_PI); }
inline double log_(double _value)
{ return log(_value); }
}//namespace OpenMesh
#endif//MATHDEFS_HH

View File

@ -0,0 +1,161 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS NormalConeT - IMPLEMENTATION
//
//=============================================================================
#define OPENMESH_NORMALCONE_C
//== INCLUDES =================================================================
#include <math.h>
#include "NormalConeT.hh"
#ifdef max
# undef max
#endif
#ifdef min
# undef min
#endif
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== IMPLEMENTATION ==========================================================
template <typename Scalar>
NormalConeT<Scalar>::
NormalConeT(const Vec3& _center_normal, Scalar _angle)
: center_normal_(_center_normal), angle_(_angle)
{
}
//----------------------------------------------------------------------------
template <typename Scalar>
Scalar
NormalConeT<Scalar>::
max_angle(const Vec3& _norm) const
{
Scalar dotp = (center_normal_ | _norm);
return (dotp >= 1.0 ? 0.0 : (dotp <= -1.0 ? M_PI : acos(dotp)))
+ angle_;
}
//----------------------------------------------------------------------------
template <typename Scalar>
Scalar
NormalConeT<Scalar>::
max_angle(const NormalConeT& _cone) const
{
Scalar dotp = (center_normal_ | _cone.center_normal_);
Scalar centerAngle = dotp >= 1.0 ? 0.0 : (dotp <= -1.0 ? M_PI : acos(dotp));
Scalar sideAngle0 = std::max(angle_-centerAngle, _cone.angle_);
Scalar sideAngle1 = std::max(_cone.angle_-centerAngle, angle_);
return centerAngle + sideAngle0 + sideAngle1;
}
//----------------------------------------------------------------------------
template <typename Scalar>
void
NormalConeT<Scalar>::
merge(const NormalConeT& _cone)
{
Scalar dotp = (center_normal_ | _cone.center_normal_);
if (fabs(dotp) < 0.99999f)
{
// new angle
Scalar centerAngle = acos(dotp);
Scalar minAngle = std::min(-angle(), centerAngle - _cone.angle());
Scalar maxAngle = std::max( angle(), centerAngle + _cone.angle());
angle_ = (maxAngle - minAngle) * Scalar(0.5f);
// axis by SLERP
Scalar axisAngle = Scalar(0.5f) * (minAngle + maxAngle);
center_normal_ = ((center_normal_ * sin(centerAngle-axisAngle)
+ _cone.center_normal_ * sin(axisAngle))
/ sin(centerAngle));
}
else
{
// axes point in same direction
if (dotp > 0.0f)
angle_ = std::max(angle_, _cone.angle_);
// axes point in opposite directions
else
angle_ = Scalar(2.0f * M_PI);
}
}
//=============================================================================
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,132 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS NormalCone
//
//=============================================================================
#ifndef OPENMESH_NORMALCONE_HH
#define OPENMESH_NORMALCONE_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/Geometry/VectorT.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== CLASS DEFINITION =========================================================
/** /class NormalCone NormalCone.hh <ACG/Geometry/Types/NormalCone.hh>
NormalCone that can be merged with other normal cones. Provides
the center normal and the opening angle.
**/
template <typename Scalar>
class NormalConeT
{
public:
// typedefs
typedef VectorT<Scalar, 3> Vec3;
//! default constructor (not initialized)
NormalConeT() {}
//! Initialize cone with center (unit vector) and angle (radius in radians)
NormalConeT(const Vec3& _center_normal, Scalar _angle=0.0);
//! return max. distance (radians) unit vector to cone (distant side)
Scalar max_angle(const Vec3&) const;
//! return max. distance (radians) cone to cone (distant sides)
Scalar max_angle(const NormalConeT&) const;
//! merge _cone; this instance will then enclose both former cones
void merge(const NormalConeT&);
//! returns center normal
const Vec3& center_normal() const { return center_normal_; }
//! returns size of cone (radius in radians)
inline Scalar angle() const { return angle_; }
private:
Vec3 center_normal_;
Scalar angle_;
};
//=============================================================================
} // namespace OpenMesh
//=============================================================================
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_NORMALCONE_C)
#define OPENMESH_NORMALCONE_TEMPLATES
#include "NormalConeT.cc"
#endif
//=============================================================================
#endif // OPENMESH_NORMALCONE_HH defined
//=============================================================================

View File

@ -0,0 +1,124 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS Plane3D
//
//=============================================================================
#ifndef OPENMESH_PLANE3D_HH
#define OPENMESH_PLANE3D_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/Geometry/VectorT.hh>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace VDPM {
//== CLASS DEFINITION =========================================================
/** \class Plane3d Plane3d.hh <OpenMesh/Tools/VDPM/Plane3d.hh>
ax + by + cz + d = 0
*/
class OPENMESHDLLEXPORT Plane3d
{
public:
typedef OpenMesh::Vec3f vector_type;
typedef vector_type::value_type value_type;
public:
Plane3d()
: d_(0)
{ }
Plane3d(const vector_type &_dir, const vector_type &_pnt)
: n_(_dir), d_(0)
{
n_.normalize();
d_ = -dot(n_,_pnt);
}
value_type signed_distance(const OpenMesh::Vec3f &_p)
{
return dot(n_ , _p) + d_;
}
// back compatibility
value_type singed_distance(const OpenMesh::Vec3f &point)
{ return signed_distance( point ); }
public:
vector_type n_;
value_type d_;
};
//=============================================================================
} // namespace VDPM
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_PLANE3D_HH defined
//=============================================================================

View File

@ -0,0 +1,291 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
/** \file Core/Geometry/QuadricT.hh
*/
//=============================================================================
//
// CLASS QuadricT
//
//=============================================================================
#ifndef OPENMESH_GEOMETRY_QUADRIC_HH
#define OPENMESH_GEOMETRY_QUADRIC_HH
//== INCLUDES =================================================================
#include "Config.hh"
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include <OpenMesh/Core/Utils/GenProg.hh>
//== NAMESPACE ================================================================
namespace OpenMesh { //BEGIN_NS_OPENMESH
namespace Geometry { //BEGIN_NS_GEOMETRY
//== CLASS DEFINITION =========================================================
/** /class QuadricT Geometry/QuadricT.hh
Stores a quadric as a 4x4 symmetrix matrix. Used by the
error quadric based mesh decimation algorithms.
**/
template <class Scalar>
class QuadricT
{
public:
typedef Scalar value_type;
typedef QuadricT<Scalar> type;
typedef QuadricT<Scalar> Self;
// typedef VectorInterface<Scalar, VecStorage3<Scalar> > Vec3;
// typedef VectorInterface<Scalar, VecStorage4<Scalar> > Vec4;
//typedef Vector3Elem Vec3;
//typedef Vector4Elem Vec4;
/// construct with upper triangle of symmetrix 4x4 matrix
QuadricT(Scalar _a, Scalar _b, Scalar _c, Scalar _d,
Scalar _e, Scalar _f, Scalar _g,
Scalar _h, Scalar _i,
Scalar _j)
: a_(_a), b_(_b), c_(_c), d_(_d),
e_(_e), f_(_f), g_(_g),
h_(_h), i_(_i),
j_(_j)
{
}
/// constructor from given plane equation: ax+by+cz+d_=0
QuadricT( Scalar _a=0.0, Scalar _b=0.0, Scalar _c=0.0, Scalar _d=0.0 )
: a_(_a*_a), b_(_a*_b), c_(_a*_c), d_(_a*_d),
e_(_b*_b), f_(_b*_c), g_(_b*_d),
h_(_c*_c), i_(_c*_d),
j_(_d*_d)
{}
template <class _Point>
QuadricT(const _Point& _pt)
{
set_distance_to_point(_pt);
}
template <class _Normal, class _Point>
QuadricT(const _Normal& _n, const _Point& _p)
{
set_distance_to_plane(_n,_p);
}
//set operator
void set(Scalar _a, Scalar _b, Scalar _c, Scalar _d,
Scalar _e, Scalar _f, Scalar _g,
Scalar _h, Scalar _i,
Scalar _j)
{
a_ = _a; b_ = _b; c_ = _c; d_ = _d;
e_ = _e; f_ = _f; g_ = _g;
h_ = _h; i_ = _i;
j_ = _j;
}
//sets the quadric representing the squared distance to _pt
template <class _Point>
void set_distance_to_point(const _Point& _pt)
{
set(1, 0, 0, -_pt[0],
1, 0, -_pt[1],
1, -_pt[2],
dot(_pt,_pt));
}
//sets the quadric representing the squared distance to the plane [_a,_b,_c,_d]
void set_distance_to_plane(Scalar _a, Scalar _b, Scalar _c, Scalar _d)
{
a_ = _a*_a; b_ = _a*_b; c_ = _a*_c; d_ = _a*_d;
e_ = _b*_b; f_ = _b*_c; g_ = _b*_d;
h_ = _c*_c; i_ = _c*_d;
j_ = _d*_d;
}
//sets the quadric representing the squared distance to the plane
//determined by the normal _n and the point _p
template <class _Normal, class _Point>
void set_distance_to_plane(const _Normal& _n, const _Point& _p)
{
set_distance_to_plane(_n[0], _n[1], _n[2], -dot(_n,_p));
}
/// set all entries to zero
void clear() { a_ = b_ = c_ = d_ = e_ = f_ = g_ = h_ = i_ = j_ = 0.0; }
/// add quadrics
QuadricT<Scalar>& operator+=( const QuadricT<Scalar>& _q )
{
a_ += _q.a_; b_ += _q.b_; c_ += _q.c_; d_ += _q.d_;
e_ += _q.e_; f_ += _q.f_; g_ += _q.g_;
h_ += _q.h_; i_ += _q.i_;
j_ += _q.j_;
return *this;
}
QuadricT<Scalar> operator+(const QuadricT<Scalar>& _other ) const
{
QuadricT<Scalar> result = *this;
return result += _other;
}
/// multiply by scalar
QuadricT<Scalar>& operator*=( Scalar _s)
{
a_ *= _s; b_ *= _s; c_ *= _s; d_ *= _s;
e_ *= _s; f_ *= _s; g_ *= _s;
h_ *= _s; i_ *= _s;
j_ *= _s;
return *this;
}
QuadricT<Scalar> operator*(Scalar _s) const
{
QuadricT<Scalar> result = *this;
return result *= _s;
}
/// multiply 4D vector from right: Q*v
template <class _Vec4>
_Vec4 operator*(const _Vec4& _v) const
{
Scalar x(_v[0]), y(_v[1]), z(_v[2]), w(_v[3]);
return _Vec4(x*a_ + y*b_ + z*c_ + w*d_,
x*b_ + y*e_ + z*f_ + w*g_,
x*c_ + y*f_ + z*h_ + w*i_,
x*d_ + y*g_ + z*i_ + w*j_);
}
/// evaluate quadric Q at (3D or 4D) vector v: v*Q*v
template <class _Vec>
Scalar operator()(const _Vec& _v) const
{
return evaluate(_v, GenProg::Int2Type<vector_traits<_Vec>::size_>());
}
Scalar a() const { return a_; }
Scalar b() const { return b_; }
Scalar c() const { return c_; }
Scalar d() const { return d_; }
Scalar e() const { return e_; }
Scalar f() const { return f_; }
Scalar g() const { return g_; }
Scalar h() const { return h_; }
Scalar i() const { return i_; }
Scalar j() const { return j_; }
Scalar xx() const { return a_; }
Scalar xy() const { return b_; }
Scalar xz() const { return c_; }
Scalar xw() const { return d_; }
Scalar yy() const { return e_; }
Scalar yz() const { return f_; }
Scalar yw() const { return g_; }
Scalar zz() const { return h_; }
Scalar zw() const { return i_; }
Scalar ww() const { return j_; }
protected:
/// evaluate quadric Q at 3D vector v: v*Q*v
template <class _Vec3>
Scalar evaluate(const _Vec3& _v, GenProg::Int2Type<3>/*_dimension*/) const
{
Scalar x(_v[0]), y(_v[1]), z(_v[2]);
return a_*x*x + 2.0*b_*x*y + 2.0*c_*x*z + 2.0*d_*x
+ e_*y*y + 2.0*f_*y*z + 2.0*g_*y
+ h_*z*z + 2.0*i_*z
+ j_;
}
/// evaluate quadric Q at 4D vector v: v*Q*v
template <class _Vec4>
Scalar evaluate(const _Vec4& _v, GenProg::Int2Type<4>/*_dimension*/) const
{
Scalar x(_v[0]), y(_v[1]), z(_v[2]), w(_v[3]);
return a_*x*x + 2.0*b_*x*y + 2.0*c_*x*z + 2.0*d_*x*w
+ e_*y*y + 2.0*f_*y*z + 2.0*g_*y*w
+ h_*z*z + 2.0*i_*z*w
+ j_*w*w;
}
private:
Scalar a_, b_, c_, d_,
e_, f_, g_,
h_, i_,
j_;
};
/// Quadric using floats
typedef QuadricT<float> Quadricf;
/// Quadric using double
typedef QuadricT<double> Quadricd;
//=============================================================================
} // END_NS_GEOMETRY
} // END_NS_OPENMESH
//============================================================================
#endif // OPENMESH_GEOMETRY_HH defined
//=============================================================================

View File

@ -0,0 +1,886 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
#ifndef OPENMESH_SRC_OPENMESH_CORE_GEOMETRY_VECTOR11T_HH_
#define OPENMESH_SRC_OPENMESH_CORE_GEOMETRY_VECTOR11T_HH_
#include <array>
#include <utility>
#include <algorithm>
#include <numeric>
#include <type_traits>
#include <cmath>
#include <ostream>
#include <istream>
#include <cassert>
#include <cstdlib>
// This header is not needed by this file but expected by others including
// this file.
#include <OpenMesh/Core/System/config.h>
/*
* Helpers for VectorT
*/
namespace {
template<typename ... Ts>
struct are_convertible_to;
template<typename To, typename From, typename ... Froms>
struct are_convertible_to<To, From, Froms...> {
static constexpr bool value = std::is_convertible<From, To>::value
&& are_convertible_to<To, Froms...>::value;
};
template<typename To, typename From>
struct are_convertible_to<To, From> : public std::is_convertible<From, To> {
};
}
namespace OpenMesh {
template<typename Scalar, int DIM>
class VectorT {
static_assert(DIM >= 1, "VectorT requires positive dimensionality.");
private:
using container = std::array<Scalar, DIM>;
container values_;
public:
//---------------------------------------------------------------- class info
/// the type of the scalar used in this template
typedef Scalar value_type;
/// type of this vector
typedef VectorT<Scalar, DIM> vector_type;
/// returns dimension of the vector (deprecated)
static constexpr int dim() {
return DIM;
}
/// returns dimension of the vector
static constexpr size_t size() {
return DIM;
}
static constexpr const size_t size_ = DIM;
//-------------------------------------------------------------- constructors
// Converting constructor: Constructs the vector from DIM values (of
// potentially heterogenous types) which are all convertible to Scalar.
template<typename T, typename ... Ts,
typename = typename std::enable_if<sizeof...(Ts)+1 == DIM>::type,
typename = typename std::enable_if<
are_convertible_to<Scalar, T, Ts...>::value>::type>
constexpr VectorT(T v, Ts... vs) : values_ { {static_cast<Scalar>(v), static_cast<Scalar>(vs)...} } {
static_assert(sizeof...(Ts)+1 == DIM,
"Invalid number of components specified in constructor.");
static_assert(are_convertible_to<Scalar, T, Ts...>::value,
"Not all components are convertible to Scalar.");
}
/// default constructor creates uninitialized values.
constexpr VectorT() {}
/**
* Creates a vector with all components set to v.
*/
explicit VectorT(const Scalar &v) {
vectorize(v);
}
VectorT(const VectorT &rhs) = default;
VectorT(VectorT &&rhs) = default;
VectorT &operator=(const VectorT &rhs) = default;
VectorT &operator=(VectorT &&rhs) = default;
/**
* Only for 4-component vectors with division operator on their
* Scalar: Dehomogenization.
*/
template<typename S = Scalar, int D = DIM>
auto homogenized() const ->
typename std::enable_if<D == 4,
VectorT<decltype(std::declval<S>()/std::declval<S>()), DIM>>::type {
static_assert(D == DIM, "D and DIM need to be identical. (Never "
"override the default template arguments.)");
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
"to be the same type. (Never override the default template "
"arguments.)");
return VectorT(
values_[0]/values_[3],
values_[1]/values_[3],
values_[2]/values_[3],
1);
}
/// construct from a value array or any other iterator
template<typename Iterator,
typename = decltype(
*std::declval<Iterator&>(), void(),
++std::declval<Iterator&>(), void())>
explicit VectorT(Iterator it) {
std::copy_n(it, DIM, values_.begin());
}
/// copy & cast constructor (explicit)
template<typename otherScalarType,
typename = typename std::enable_if<
std::is_convertible<otherScalarType, Scalar>::value>>
explicit VectorT(const VectorT<otherScalarType, DIM>& _rhs) {
operator=(_rhs);
}
//--------------------------------------------------------------------- casts
/// cast from vector with a different scalar type
template<typename OtherScalar,
typename = typename std::enable_if<
std::is_convertible<OtherScalar, Scalar>::value>>
vector_type& operator=(const VectorT<OtherScalar, DIM>& _rhs) {
std::transform(_rhs.cbegin(), _rhs.cend(),
this->begin(), [](OtherScalar rhs) {
return static_cast<Scalar>(std::move(rhs));
});
return *this;
}
/// access to Scalar array
Scalar* data() { return values_.data(); }
/// access to const Scalar array
const Scalar* data() const { return values_.data(); }
//----------------------------------------------------------- element access
/// get i'th element read-write
Scalar& operator[](size_t _i) {
assert(_i < DIM);
return values_[_i];
}
/// get i'th element read-only
const Scalar& operator[](size_t _i) const {
assert(_i < DIM);
return values_[_i];
}
//---------------------------------------------------------------- comparsion
/// component-wise comparison
bool operator==(const vector_type& _rhs) const {
return std::equal(_rhs.values_.cbegin(), _rhs.values_.cend(), values_.cbegin());
}
/// component-wise comparison
bool operator!=(const vector_type& _rhs) const {
return !std::equal(_rhs.values_.cbegin(), _rhs.values_.cend(), values_.cbegin());
}
//---------------------------------------------------------- scalar operators
/// component-wise self-multiplication with scalar
template<typename OtherScalar>
auto operator*=(const OtherScalar& _s) ->
typename std::enable_if<std::is_convertible<
decltype(this->values_[0] * _s), Scalar>::value,
VectorT<Scalar, DIM>&>::type {
for (auto& e : *this) {
e *= _s;
}
return *this;
}
/// component-wise self-division by scalar
template<typename OtherScalar>
auto operator/=(const OtherScalar& _s) ->
typename std::enable_if<std::is_convertible<
decltype(this->values_[0] / _s), Scalar>::value,
VectorT<Scalar, DIM>&>::type {
for (auto& e : *this) {
e /= _s;
}
return *this;
}
/// component-wise multiplication with scalar
template<typename OtherScalar>
typename std::enable_if<std::is_convertible<
decltype(std::declval<Scalar>() * std::declval<OtherScalar>()),
Scalar>::value,
VectorT<Scalar, DIM>>::type
operator*(const OtherScalar& _s) const {
return vector_type(*this) *= _s;
}
/// component-wise division by with scalar
template<typename OtherScalar>
typename std::enable_if<std::is_convertible<
decltype(std::declval<Scalar>() / std::declval<OtherScalar>()),
Scalar>::value,
VectorT<Scalar, DIM>>::type
operator/(const OtherScalar& _s) const {
return vector_type(*this) /= _s;
}
//---------------------------------------------------------- vector operators
/// component-wise self-multiplication
template<typename OtherScalar>
auto operator*=(const VectorT<OtherScalar, DIM>& _rhs) ->
typename std::enable_if<
sizeof(decltype(this->values_[0] * *_rhs.data())) >= 0,
vector_type&>::type {
for (int i = 0; i < DIM; ++i) {
data()[i] *= _rhs.data()[i];
}
return *this;
}
/// component-wise self-division
template<typename OtherScalar>
auto operator/=(const VectorT<OtherScalar, DIM>& _rhs) ->
typename std::enable_if<
sizeof(decltype(this->values_[0] / *_rhs.data())) >= 0,
vector_type&>::type {
for (int i = 0; i < DIM; ++i) {
data()[i] /= _rhs.data()[i];
}
return *this;
}
/// vector difference from this
template<typename OtherScalar>
auto operator-=(const VectorT<OtherScalar, DIM>& _rhs) ->
typename std::enable_if<
sizeof(decltype(this->values_[0] - *_rhs.data())) >= 0,
vector_type&>::type {
for (int i = 0; i < DIM; ++i) {
data()[i] -= _rhs.data()[i];
}
return *this;
}
/// vector self-addition
template<typename OtherScalar>
auto operator+=(const VectorT<OtherScalar, DIM>& _rhs) ->
typename std::enable_if<
sizeof(decltype(this->values_[0] + *_rhs.data())) >= 0,
vector_type&>::type {
for (int i = 0; i < DIM; ++i) {
data()[i] += _rhs.data()[i];
}
return *this;
}
/// component-wise vector multiplication
template<typename OtherScalar>
auto operator*(const VectorT<OtherScalar, DIM>& _rhs) const ->
typename std::enable_if<
sizeof(decltype(this->values_[0] * *_rhs.data())) >= 0,
vector_type>::type {
return vector_type(*this) *= _rhs;
}
/// component-wise vector division
template<typename OtherScalar>
auto operator/(const VectorT<OtherScalar, DIM>& _rhs) const ->
typename std::enable_if<
sizeof(decltype(this->values_[0] / *_rhs.data())) >= 0,
vector_type>::type {
return vector_type(*this) /= _rhs;
}
/// component-wise vector addition
template<typename OtherScalar>
auto operator+(const VectorT<OtherScalar, DIM>& _rhs) const ->
typename std::enable_if<
sizeof(decltype(this->values_[0] + *_rhs.data())) >= 0,
vector_type>::type {
return vector_type(*this) += _rhs;
}
/// component-wise vector difference
template<typename OtherScalar>
auto operator-(const VectorT<OtherScalar, DIM>& _rhs) const ->
typename std::enable_if<
sizeof(decltype(this->values_[0] - *_rhs.data())) >= 0,
vector_type>::type {
return vector_type(*this) -= _rhs;
}
/// unary minus
vector_type operator-(void) const {
vector_type v;
std::transform(values_.begin(), values_.end(), v.values_.begin(),
[](const Scalar &s) { return -s; });
return v;
}
/// cross product: only defined for Vec3* as specialization
/// \see OpenMesh::cross
template<typename OtherScalar>
auto operator% (const VectorT<OtherScalar, DIM> &_rhs) const ->
typename std::enable_if<DIM == 3,
VectorT<decltype((*this)[0] * _rhs[0] -
(*this)[0] * _rhs[0]), DIM>>::type {
return {
values_[1] * _rhs[2] - values_[2] * _rhs[1],
values_[2] * _rhs[0] - values_[0] * _rhs[2],
values_[0] * _rhs[1] - values_[1] * _rhs[0]
};
}
/// compute scalar product
/// \see OpenMesh::dot
template<typename OtherScalar>
auto operator|(const VectorT<OtherScalar, DIM>& _rhs) const ->
decltype(*this->data() * *_rhs.data()) {
return std::inner_product(begin() + 1, begin() + DIM, _rhs.begin() + 1,
*begin() * *_rhs.begin());
}
//------------------------------------------------------------ euclidean norm
/// \name Euclidean norm calculations
//@{
/// compute squared euclidean norm
template<typename S = Scalar>
decltype(std::declval<S>() * std::declval<S>()) sqrnorm() const {
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
"to be the same type. (Never override the default template "
"arguments.)");
typedef decltype(values_[0] * values_[0]) RESULT;
return std::accumulate(values_.cbegin() + 1, values_.cend(),
values_[0] * values_[0],
[](const RESULT &l, const Scalar &r) { return l + r * r; });
}
/// compute euclidean norm
template<typename S = Scalar>
auto norm() const ->
decltype(std::sqrt(std::declval<VectorT<S, DIM>>().sqrnorm())) {
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
"to be the same type. (Never override the default template "
"arguments.)");
return std::sqrt(sqrnorm());
}
template<typename S = Scalar>
auto length() const ->
decltype(std::declval<VectorT<S, DIM>>().norm()) {
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
"to be the same type. (Never override the default template "
"arguments.)");
return norm();
}
/** normalize vector, return normalized vector
*/
template<typename S = Scalar>
auto normalize() ->
decltype(*this /= std::declval<VectorT<S, DIM>>().norm()) {
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
"to be the same type. (Never override the default template "
"arguments.)");
return *this /= norm();
}
/** return normalized vector
*/
template<typename S = Scalar>
auto normalized() const ->
decltype(*this / std::declval<VectorT<S, DIM>>().norm()) {
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
"to be the same type. (Never override the default template "
"arguments.)");
return *this / norm();
}
/** normalize vector, return normalized vector and avoids div by zero
*/
template<typename S = Scalar>
typename std::enable_if<
sizeof(decltype(
static_cast<S>(0),
std::declval<VectorT<S, DIM>>().norm())) >= 0,
vector_type&>::type
normalize_cond() {
static_assert(std::is_same<S, Scalar>::value, "S and Scalar need "
"to be the same type. (Never override the default template "
"arguments.)");
auto n = norm();
if (n != static_cast<decltype(norm())>(0)) {
*this /= n;
}
return *this;
}
//@}
//------------------------------------------------------------ euclidean norm
/// \name Non-Euclidean norm calculations
//@{
/// compute L1 (Manhattan) norm
Scalar l1_norm() const {
return std::accumulate(
values_.cbegin() + 1, values_.cend(), values_[0]);
}
/// compute l8_norm
Scalar l8_norm() const {
return max_abs();
}
//@}
//------------------------------------------------------------ max, min, mean
/// \name Minimum maximum and mean
//@{
/// return the maximal component
Scalar max() const {
return *std::max_element(values_.cbegin(), values_.cend());
}
/// return the maximal absolute component
Scalar max_abs() const {
return std::abs(
*std::max_element(values_.cbegin(), values_.cend(),
[](const Scalar &a, const Scalar &b) {
return std::abs(a) < std::abs(b);
}));
}
/// return the minimal component
Scalar min() const {
return *std::min_element(values_.cbegin(), values_.cend());
}
/// return the minimal absolute component
Scalar min_abs() const {
return std::abs(
*std::min_element(values_.cbegin(), values_.cend(),
[](const Scalar &a, const Scalar &b) {
return std::abs(a) < std::abs(b);
}));
}
/// return arithmetic mean
Scalar mean() const {
return l1_norm()/DIM;
}
/// return absolute arithmetic mean
Scalar mean_abs() const {
return std::accumulate(values_.cbegin() + 1, values_.cend(),
std::abs(values_[0]),
[](const Scalar &l, const Scalar &r) {
return l + std::abs(r);
}) / DIM;
}
/// minimize values: same as *this = min(*this, _rhs), but faster
vector_type& minimize(const vector_type& _rhs) {
std::transform(values_.cbegin(), values_.cend(),
_rhs.values_.cbegin(),
values_.begin(),
[](const Scalar &l, const Scalar &r) {
return std::min(l, r);
});
return *this;
}
/// minimize values and signalize coordinate minimization
bool minimized(const vector_type& _rhs) {
bool result = false;
std::transform(values_.cbegin(), values_.cend(),
_rhs.values_.cbegin(),
values_.begin(),
[&result](const Scalar &l, const Scalar &r) {
if (l < r) {
return l;
} else {
result = true;
return r;
}
});
return result;
}
/// maximize values: same as *this = max(*this, _rhs), but faster
vector_type& maximize(const vector_type& _rhs) {
std::transform(values_.cbegin(), values_.cend(),
_rhs.values_.cbegin(),
values_.begin(),
[](const Scalar &l, const Scalar &r) {
return std::max(l, r);
});
return *this;
}
/// maximize values and signalize coordinate maximization
bool maximized(const vector_type& _rhs) {
bool result = false;
std::transform(values_.cbegin(), values_.cend(),
_rhs.values_.cbegin(),
values_.begin(),
[&result](const Scalar &l, const Scalar &r) {
if (l > r) {
return l;
} else {
result = true;
return r;
}
});
return result;
}
/// component-wise min
inline vector_type min(const vector_type& _rhs) const {
return vector_type(*this).minimize(_rhs);
}
/// component-wise max
inline vector_type max(const vector_type& _rhs) const {
return vector_type(*this).maximize(_rhs);
}
//@}
//------------------------------------------------------------ misc functions
/// component-wise apply function object with Scalar operator()(Scalar).
template<typename Functor>
inline vector_type apply(const Functor& _func) const {
vector_type result;
std::transform(result.values_.cbegin(), result.values_.cend(),
result.values_.begin(), _func);
return result;
}
/// store the same value in each component (e.g. to clear all entries)
vector_type& vectorize(const Scalar& _s) {
std::fill(values_.begin(), values_.end(), _s);
return *this;
}
/// store the same value in each component
static vector_type vectorized(const Scalar& _s) {
return vector_type().vectorize(_s);
}
/// lexicographical comparison
bool operator<(const vector_type& _rhs) const {
return std::lexicographical_compare(
values_.begin(), values_.end(),
_rhs.values_.begin(), _rhs.values_.end());
}
/// swap with another vector
void swap(VectorT& _other)
noexcept(noexcept(std::swap(values_, _other.values_))) {
std::swap(values_, _other.values_);
}
//------------------------------------------------------------ component iterators
/// \name Component iterators
//@{
using iterator = typename container::iterator;
using const_iterator = typename container::const_iterator;
using reverse_iterator = typename container::reverse_iterator;
using const_reverse_iterator = typename container::const_reverse_iterator;
iterator begin() noexcept { return values_.begin(); }
const_iterator begin() const noexcept { return values_.cbegin(); }
const_iterator cbegin() const noexcept { return values_.cbegin(); }
iterator end() noexcept { return values_.end(); }
const_iterator end() const noexcept { return values_.cend(); }
const_iterator cend() const noexcept { return values_.cend(); }
reverse_iterator rbegin() noexcept { return values_.rbegin(); }
const_reverse_iterator rbegin() const noexcept { return values_.crbegin(); }
const_reverse_iterator crbegin() const noexcept { return values_.crbegin(); }
reverse_iterator rend() noexcept { return values_.rend(); }
const_reverse_iterator rend() const noexcept { return values_.crend(); }
const_reverse_iterator crend() const noexcept { return values_.crend(); }
//@}
};
/// Component wise multiplication from the left
template<typename Scalar, int DIM, typename OtherScalar>
auto operator*(const OtherScalar& _s, const VectorT<Scalar, DIM> &rhs) ->
decltype(rhs.operator*(_s)) {
return rhs * _s;
}
/// output a vector by printing its space-separated compontens
template<typename Scalar, int DIM>
auto operator<<(std::ostream& os, const VectorT<Scalar, DIM> &_vec) ->
typename std::enable_if<
sizeof(decltype(os << _vec[0])) >= 0, std::ostream&>::type {
os << _vec[0];
for (int i = 1; i < DIM; ++i) {
os << " " << _vec[i];
}
return os;
}
/// read the space-separated components of a vector from a stream
template<typename Scalar, int DIM>
auto operator>> (std::istream& is, VectorT<Scalar, DIM> &_vec) ->
typename std::enable_if<
sizeof(decltype(is >> _vec[0])) >= 0, std::istream &>::type {
for (int i = 0; i < DIM; ++i)
is >> _vec[i];
return is;
}
/// \relates OpenMesh::VectorT
/// symmetric version of the dot product
template<typename Scalar, int DIM>
Scalar dot(const VectorT<Scalar, DIM>& _v1, const VectorT<Scalar, DIM>& _v2) {
return (_v1 | _v2);
}
/// \relates OpenMesh::VectorT
/// symmetric version of the cross product
template<typename LScalar, typename RScalar, int DIM>
auto
cross(const VectorT<LScalar, DIM>& _v1, const VectorT<RScalar, DIM>& _v2) ->
decltype(_v1 % _v2) {
return (_v1 % _v2);
}
/// \relates OpenMesh::VectorT
/// non-member swap
template<typename Scalar, int DIM>
void swap(VectorT<Scalar, DIM>& _v1, VectorT<Scalar, DIM>& _v2)
noexcept(noexcept(_v1.swap(_v2))) {
_v1.swap(_v2);
}
/// \relates OpenMesh::VectorT
/// non-member norm
template<typename Scalar, int DIM>
Scalar norm(const VectorT<Scalar, DIM>& _v) {
return _v.norm();
}
/// \relates OpenMesh::VectorT
/// non-member sqrnorm
template<typename Scalar, int DIM>
Scalar sqrnorm(const VectorT<Scalar, DIM>& _v) {
return _v.sqrnorm();
}
/// \relates OpenMesh::VectorT
/// non-member vectorize
template<typename Scalar, int DIM, typename OtherScalar>
VectorT<Scalar, DIM>& vectorize(VectorT<Scalar, DIM>& _v, OtherScalar const& _val) {
return _v.vectorize(_val);
}
/// \relates OpenMesh::VectorT
/// non-member normalize
template<typename Scalar, int DIM>
VectorT<Scalar, DIM>& normalize(VectorT<Scalar, DIM>& _v) {
return _v.normalize();
}
/// \relates OpenMesh::VectorT
/// non-member maximize
template<typename Scalar, int DIM>
VectorT<Scalar, DIM>& maximize(VectorT<Scalar, DIM>& _v1, VectorT<Scalar, DIM>& _v2) {
return _v1.maximize(_v2);
}
/// \relates OpenMesh::VectorT
/// non-member minimize
template<typename Scalar, int DIM>
VectorT<Scalar, DIM>& minimize(VectorT<Scalar, DIM>& _v1, VectorT<Scalar, DIM>& _v2) {
return _v1.minimize(_v2);
}
//== TYPEDEFS =================================================================
/** 1-byte signed vector */
typedef VectorT<signed char,1> Vec1c;
/** 1-byte unsigned vector */
typedef VectorT<unsigned char,1> Vec1uc;
/** 1-short signed vector */
typedef VectorT<signed short int,1> Vec1s;
/** 1-short unsigned vector */
typedef VectorT<unsigned short int,1> Vec1us;
/** 1-int signed vector */
typedef VectorT<signed int,1> Vec1i;
/** 1-int unsigned vector */
typedef VectorT<unsigned int,1> Vec1ui;
/** 1-float vector */
typedef VectorT<float,1> Vec1f;
/** 1-double vector */
typedef VectorT<double,1> Vec1d;
/** 2-byte signed vector */
typedef VectorT<signed char,2> Vec2c;
/** 2-byte unsigned vector */
typedef VectorT<unsigned char,2> Vec2uc;
/** 2-short signed vector */
typedef VectorT<signed short int,2> Vec2s;
/** 2-short unsigned vector */
typedef VectorT<unsigned short int,2> Vec2us;
/** 2-int signed vector */
typedef VectorT<signed int,2> Vec2i;
/** 2-int unsigned vector */
typedef VectorT<unsigned int,2> Vec2ui;
/** 2-float vector */
typedef VectorT<float,2> Vec2f;
/** 2-double vector */
typedef VectorT<double,2> Vec2d;
/** 3-byte signed vector */
typedef VectorT<signed char,3> Vec3c;
/** 3-byte unsigned vector */
typedef VectorT<unsigned char,3> Vec3uc;
/** 3-short signed vector */
typedef VectorT<signed short int,3> Vec3s;
/** 3-short unsigned vector */
typedef VectorT<unsigned short int,3> Vec3us;
/** 3-int signed vector */
typedef VectorT<signed int,3> Vec3i;
/** 3-int unsigned vector */
typedef VectorT<unsigned int,3> Vec3ui;
/** 3-float vector */
typedef VectorT<float,3> Vec3f;
/** 3-double vector */
typedef VectorT<double,3> Vec3d;
/** 3-bool vector */
typedef VectorT<bool,3> Vec3b;
/** 4-byte signed vector */
typedef VectorT<signed char,4> Vec4c;
/** 4-byte unsigned vector */
typedef VectorT<unsigned char,4> Vec4uc;
/** 4-short signed vector */
typedef VectorT<signed short int,4> Vec4s;
/** 4-short unsigned vector */
typedef VectorT<unsigned short int,4> Vec4us;
/** 4-int signed vector */
typedef VectorT<signed int,4> Vec4i;
/** 4-int unsigned vector */
typedef VectorT<unsigned int,4> Vec4ui;
/** 4-float vector */
typedef VectorT<float,4> Vec4f;
/** 4-double vector */
typedef VectorT<double,4> Vec4d;
/** 5-byte signed vector */
typedef VectorT<signed char, 5> Vec5c;
/** 5-byte unsigned vector */
typedef VectorT<unsigned char, 5> Vec5uc;
/** 5-short signed vector */
typedef VectorT<signed short int, 5> Vec5s;
/** 5-short unsigned vector */
typedef VectorT<unsigned short int, 5> Vec5us;
/** 5-int signed vector */
typedef VectorT<signed int, 5> Vec5i;
/** 5-int unsigned vector */
typedef VectorT<unsigned int, 5> Vec5ui;
/** 5-float vector */
typedef VectorT<float, 5> Vec5f;
/** 5-double vector */
typedef VectorT<double, 5> Vec5d;
/** 6-byte signed vector */
typedef VectorT<signed char,6> Vec6c;
/** 6-byte unsigned vector */
typedef VectorT<unsigned char,6> Vec6uc;
/** 6-short signed vector */
typedef VectorT<signed short int,6> Vec6s;
/** 6-short unsigned vector */
typedef VectorT<unsigned short int,6> Vec6us;
/** 6-int signed vector */
typedef VectorT<signed int,6> Vec6i;
/** 6-int unsigned vector */
typedef VectorT<unsigned int,6> Vec6ui;
/** 6-float vector */
typedef VectorT<float,6> Vec6f;
/** 6-double vector */
typedef VectorT<double,6> Vec6d;
} // namespace OpenMesh
/**
* Literal operator for inline specification of colors in HTML syntax.
*
* Example:
* \code{.cpp}
* OpenMesh::Vec4f light_blue = 0x1FCFFFFF_htmlColor;
* \endcode
*/
constexpr OpenMesh::Vec4f operator"" _htmlColor(unsigned long long raw_color) {
return OpenMesh::Vec4f(
((raw_color >> 24) & 0xFF) / 255.0f,
((raw_color >> 16) & 0xFF) / 255.0f,
((raw_color >> 8) & 0xFF) / 255.0f,
((raw_color >> 0) & 0xFF) / 255.0f);
}
#endif /* OPENMESH_SRC_OPENMESH_CORE_GEOMETRY_VECTOR11T_HH_ */

View File

@ -0,0 +1,440 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS VectorT
//
//=============================================================================
// Don't parse this header file with doxygen since
// for some reason (obviously due to a bug in doxygen,
// bugreport: https://bugzilla.gnome.org/show_bug.cgi?id=629182)
// macro expansion and preprocessor defines
// don't work properly.
#if ((defined(_MSC_VER) && (_MSC_VER >= 1900)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(OPENMESH_VECTOR_LEGACY)
#include "Vector11T.hh"
#else
#ifndef DOXYGEN
#ifndef OPENMESH_VECTOR_HH
#define OPENMESH_VECTOR_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <ostream>
#include <cmath>
#include <cassert>
#include <cstring>
#if defined(__GNUC__) && defined(__SSE__)
#include <xmmintrin.h>
#endif
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== CLASS DEFINITION =========================================================
/** The N values of the template Scalar type are the only data members
of the class VectorT<Scalar,N>. This guarantees 100% compatibility
with arrays of type Scalar and size N, allowing us to define the
cast operators to and from arrays and array pointers.
In addition, this class will be specialized for Vec4f to be 16 bit
aligned, so that aligned SSE instructions can be used on these
vectors.
*/
template<typename Scalar, int N> class VectorDataT {
public:
Scalar values_[N];
};
#if defined(__GNUC__) && defined(__SSE__)
/// This specialization enables us to use aligned SSE instructions.
template<> class VectorDataT<float, 4> {
public:
union {
__m128 m128;
float values_[4];
};
};
#endif
//== CLASS DEFINITION =========================================================
#define DIM N
#define TEMPLATE_HEADER template <typename Scalar, int N>
#define CLASSNAME VectorT
#define DERIVED VectorDataT<Scalar,N>
#define unroll(expr) for (int i=0; i<N; ++i) expr(i)
/** \class VectorT VectorT.hh <OpenMesh/Core/Math/VectorT.hh>
A vector is an array of \<N\> values of type \<Scalar\>.
The actual data is stored in an VectorDataT, this class just adds
the necessary operators.
*/
#include "VectorT_inc.hh"
#undef DIM
#undef TEMPLATE_HEADER
#undef CLASSNAME
#undef DERIVED
#undef unroll
//== PARTIAL TEMPLATE SPECIALIZATIONS =========================================
#if OM_PARTIAL_SPECIALIZATION
#define TEMPLATE_HEADER template <typename Scalar>
#define CLASSNAME VectorT<Scalar,DIM>
#define DERIVED VectorDataT<Scalar,DIM>
#define DIM 2
#define unroll(expr) expr(0) expr(1)
#define unroll_comb(expr, op) expr(0) op expr(1)
#define unroll_csv(expr) expr(0), expr(1)
#include "VectorT_inc.hh"
#undef DIM
#undef unroll
#undef unroll_comb
#undef unroll_csv
#define DIM 3
#define unroll(expr) expr(0) expr(1) expr(2)
#define unroll_comb(expr, op) expr(0) op expr(1) op expr(2)
#define unroll_csv(expr) expr(0), expr(1), expr(2)
#include "VectorT_inc.hh"
#undef DIM
#undef unroll
#undef unroll_comb
#undef unroll_csv
#define DIM 4
#define unroll(expr) expr(0) expr(1) expr(2) expr(3)
#define unroll_comb(expr, op) expr(0) op expr(1) op expr(2) op expr(3)
#define unroll_csv(expr) expr(0), expr(1), expr(2), expr(3)
#include "VectorT_inc.hh"
#undef DIM
#undef unroll
#undef unroll_comb
#undef unroll_csv
#define DIM 5
#define unroll(expr) expr(0) expr(1) expr(2) expr(3) expr(4)
#define unroll_comb(expr, op) expr(0) op expr(1) op expr(2) op expr(3) op expr(4)
#define unroll_csv(expr) expr(0), expr(1), expr(2), expr(3), expr(4)
#include "VectorT_inc.hh"
#undef DIM
#undef unroll
#undef unroll_comb
#undef unroll_csv
#define DIM 6
#define unroll(expr) expr(0) expr(1) expr(2) expr(3) expr(4) expr(5)
#define unroll_comb(expr, op) expr(0) op expr(1) op expr(2) op expr(3) op expr(4) op expr(5)
#define unroll_csv(expr) expr(0), expr(1), expr(2), expr(3), expr(4), expr(5)
#include "VectorT_inc.hh"
#undef DIM
#undef unroll
#undef unroll_comb
#undef unroll_csv
#undef TEMPLATE_HEADER
#undef CLASSNAME
#undef DERIVED
//== FULL TEMPLATE SPECIALIZATIONS ============================================
#else
/// cross product for Vec3f
template<>
inline VectorT<float,3>
VectorT<float,3>::operator%(const VectorT<float,3>& _rhs) const
{
return
VectorT<float,3>(values_[1]*_rhs.values_[2]-values_[2]*_rhs.values_[1],
values_[2]*_rhs.values_[0]-values_[0]*_rhs.values_[2],
values_[0]*_rhs.values_[1]-values_[1]*_rhs.values_[0]);
}
/// cross product for Vec3d
template<>
inline VectorT<double,3>
VectorT<double,3>::operator%(const VectorT<double,3>& _rhs) const
{
return
VectorT<double,3>(values_[1]*_rhs.values_[2]-values_[2]*_rhs.values_[1],
values_[2]*_rhs.values_[0]-values_[0]*_rhs.values_[2],
values_[0]*_rhs.values_[1]-values_[1]*_rhs.values_[0]);
}
#endif
//== GLOBAL FUNCTIONS =========================================================
/// \relates OpenMesh::VectorT
/// scalar * vector
template<typename Scalar1, typename Scalar2,int N>
inline VectorT<Scalar1,N> operator*(Scalar2 _s, const VectorT<Scalar1,N>& _v) {
return _v*_s;
}
/// \relates OpenMesh::VectorT
/// symmetric version of the dot product
template<typename Scalar, int N>
inline Scalar
dot(const VectorT<Scalar,N>& _v1, const VectorT<Scalar,N>& _v2) {
return (_v1 | _v2);
}
/// \relates OpenMesh::VectorT
/// symmetric version of the cross product
template<typename Scalar, int N>
inline VectorT<Scalar,N>
cross(const VectorT<Scalar,N>& _v1, const VectorT<Scalar,N>& _v2) {
return (_v1 % _v2);
}
/// \relates OpenMesh::VectorT
/// non-member norm
template<typename Scalar, int DIM>
Scalar norm(const VectorT<Scalar, DIM>& _v) {
return _v.norm();
}
/// \relates OpenMesh::VectorT
/// non-member sqrnorm
template<typename Scalar, int DIM>
Scalar sqrnorm(const VectorT<Scalar, DIM>& _v) {
return _v.sqrnorm();
}
/// \relates OpenMesh::VectorT
/// non-member vectorize
template<typename Scalar, int DIM, typename OtherScalar>
VectorT<Scalar, DIM>& vectorize(VectorT<Scalar, DIM>& _v, OtherScalar const& _val) {
return _v.vectorize(_val);
}
/// \relates OpenMesh::VectorT
/// non-member normalize
template<typename Scalar, int DIM>
VectorT<Scalar, DIM>& normalize(VectorT<Scalar, DIM>& _v) {
return _v.normalize();
}
/// \relates OpenMesh::VectorT
/// non-member maximize
template<typename Scalar, int DIM>
VectorT<Scalar, DIM>& maximize(VectorT<Scalar, DIM>& _v1, VectorT<Scalar, DIM>& _v2) {
return _v1.maximize(_v2);
}
/// \relates OpenMesh::VectorT
/// non-member minimize
template<typename Scalar, int DIM>
VectorT<Scalar, DIM>& minimize(VectorT<Scalar, DIM>& _v1, VectorT<Scalar, DIM>& _v2) {
return _v1.minimize(_v2);
}
//== TYPEDEFS =================================================================
/** 1-byte signed vector */
typedef VectorT<signed char,1> Vec1c;
/** 1-byte unsigned vector */
typedef VectorT<unsigned char,1> Vec1uc;
/** 1-short signed vector */
typedef VectorT<signed short int,1> Vec1s;
/** 1-short unsigned vector */
typedef VectorT<unsigned short int,1> Vec1us;
/** 1-int signed vector */
typedef VectorT<signed int,1> Vec1i;
/** 1-int unsigned vector */
typedef VectorT<unsigned int,1> Vec1ui;
/** 1-float vector */
typedef VectorT<float,1> Vec1f;
/** 1-double vector */
typedef VectorT<double,1> Vec1d;
/** 2-byte signed vector */
typedef VectorT<signed char,2> Vec2c;
/** 2-byte unsigned vector */
typedef VectorT<unsigned char,2> Vec2uc;
/** 2-short signed vector */
typedef VectorT<signed short int,2> Vec2s;
/** 2-short unsigned vector */
typedef VectorT<unsigned short int,2> Vec2us;
/** 2-int signed vector */
typedef VectorT<signed int,2> Vec2i;
/** 2-int unsigned vector */
typedef VectorT<unsigned int,2> Vec2ui;
/** 2-float vector */
typedef VectorT<float,2> Vec2f;
/** 2-double vector */
typedef VectorT<double,2> Vec2d;
/** 3-byte signed vector */
typedef VectorT<signed char,3> Vec3c;
/** 3-byte unsigned vector */
typedef VectorT<unsigned char,3> Vec3uc;
/** 3-short signed vector */
typedef VectorT<signed short int,3> Vec3s;
/** 3-short unsigned vector */
typedef VectorT<unsigned short int,3> Vec3us;
/** 3-int signed vector */
typedef VectorT<signed int,3> Vec3i;
/** 3-int unsigned vector */
typedef VectorT<unsigned int,3> Vec3ui;
/** 3-float vector */
typedef VectorT<float,3> Vec3f;
/** 3-double vector */
typedef VectorT<double,3> Vec3d;
/** 3-bool vector */
typedef VectorT<bool,3> Vec3b;
/** 4-byte signed vector */
typedef VectorT<signed char,4> Vec4c;
/** 4-byte unsigned vector */
typedef VectorT<unsigned char,4> Vec4uc;
/** 4-short signed vector */
typedef VectorT<signed short int,4> Vec4s;
/** 4-short unsigned vector */
typedef VectorT<unsigned short int,4> Vec4us;
/** 4-int signed vector */
typedef VectorT<signed int,4> Vec4i;
/** 4-int unsigned vector */
typedef VectorT<unsigned int,4> Vec4ui;
/** 4-float vector */
typedef VectorT<float,4> Vec4f;
/** 4-double vector */
typedef VectorT<double,4> Vec4d;
/** 5-byte signed vector */
typedef VectorT<signed char, 5> Vec5c;
/** 5-byte unsigned vector */
typedef VectorT<unsigned char, 5> Vec5uc;
/** 5-short signed vector */
typedef VectorT<signed short int, 5> Vec5s;
/** 5-short unsigned vector */
typedef VectorT<unsigned short int, 5> Vec5us;
/** 5-int signed vector */
typedef VectorT<signed int, 5> Vec5i;
/** 5-int unsigned vector */
typedef VectorT<unsigned int, 5> Vec5ui;
/** 5-float vector */
typedef VectorT<float, 5> Vec5f;
/** 5-double vector */
typedef VectorT<double, 5> Vec5d;
/** 6-byte signed vector */
typedef VectorT<signed char,6> Vec6c;
/** 6-byte unsigned vector */
typedef VectorT<unsigned char,6> Vec6uc;
/** 6-short signed vector */
typedef VectorT<signed short int,6> Vec6s;
/** 6-short unsigned vector */
typedef VectorT<unsigned short int,6> Vec6us;
/** 6-int signed vector */
typedef VectorT<signed int,6> Vec6i;
/** 6-int unsigned vector */
typedef VectorT<unsigned int,6> Vec6ui;
/** 6-float vector */
typedef VectorT<float,6> Vec6f;
/** 6-double vector */
typedef VectorT<double,6> Vec6d;
//=============================================================================
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_VECTOR_HH defined
//=============================================================================
#endif // DOXYGEN
#endif // C++11

View File

@ -0,0 +1,668 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
// Set template keywords and class names properly when
// parsing with doxygen. This only seems to work this way since
// the scope of preprocessor defines is limited to one file in doxy.
#ifdef DOXYGEN
// Only used for correct doxygen parsing
#define OPENMESH_VECTOR_HH
#define DIM N
#define TEMPLATE_HEADER template <typename Scalar, int N>
#define CLASSNAME VectorT
#define DERIVED VectorDataT<Scalar,N>
#define unroll(expr) for (int i=0; i<N; ++i) expr(i)
#endif
#if defined( OPENMESH_VECTOR_HH )
// ----------------------------------------------------------------------------
TEMPLATE_HEADER
class CLASSNAME : public DERIVED
{
private:
typedef DERIVED Base;
public:
//---------------------------------------------------------------- class info
/// the type of the scalar used in this template
typedef Scalar value_type;
/// type of this vector
typedef VectorT<Scalar,DIM> vector_type;
/// returns dimension of the vector (deprecated)
static inline int dim() { return DIM; }
/// returns dimension of the vector
static inline size_t size() { return DIM; }
static const size_t size_ = DIM;
//-------------------------------------------------------------- constructors
/// default constructor creates uninitialized values.
inline VectorT() {}
/// special constructor for 1D vectors
explicit inline VectorT(const Scalar& v) {
// assert(DIM==1);
// values_[0] = v0;
vectorize(v);
}
#if DIM == 2
/// special constructor for 2D vectors
inline VectorT(const Scalar v0, const Scalar v1) {
Base::values_[0] = v0; Base::values_[1] = v1;
}
#endif
#if DIM == 3
/// special constructor for 3D vectors
inline VectorT(const Scalar v0, const Scalar v1, const Scalar v2) {
Base::values_[0]=v0; Base::values_[1]=v1; Base::values_[2]=v2;
}
#endif
#if DIM == 4
/// special constructor for 4D vectors
inline VectorT(const Scalar v0, const Scalar v1,
const Scalar v2, const Scalar v3) {
Base::values_[0]=v0; Base::values_[1]=v1; Base::values_[2]=v2; Base::values_[3]=v3;
}
VectorT homogenized() const { return VectorT(Base::values_[0]/Base::values_[3], Base::values_[1]/Base::values_[3], Base::values_[2]/Base::values_[3], 1); }
#endif
#if DIM == 5
/// special constructor for 5D vectors
inline VectorT(const Scalar v0, const Scalar v1, const Scalar v2,
const Scalar v3, const Scalar v4) {
Base::values_[0]=v0; Base::values_[1]=v1;Base::values_[2]=v2; Base::values_[3]=v3; Base::values_[4]=v4;
}
#endif
#if DIM == 6
/// special constructor for 6D vectors
inline VectorT(const Scalar v0, const Scalar v1, const Scalar v2,
const Scalar v3, const Scalar v4, const Scalar v5) {
Base::values_[0]=v0; Base::values_[1]=v1; Base::values_[2]=v2;
Base::values_[3]=v3; Base::values_[4]=v4; Base::values_[5]=v5;
}
#endif
/// construct from a value array (explicit)
explicit inline VectorT(const Scalar _values[DIM]) {
memcpy(data(), _values, DIM*sizeof(Scalar));
}
#ifdef OM_CC_MIPS
/// assignment from a vector of the same kind
// mipspro need this method
inline vector_type& operator=(const vector_type& _rhs) {
memcpy(Base::values_, _rhs.Base::values_, DIM*sizeof(Scalar));
return *this;
}
#endif
/// copy & cast constructor (explicit)
template<typename otherScalarType>
explicit inline VectorT(const VectorT<otherScalarType,DIM>& _rhs) {
operator=(_rhs);
}
//--------------------------------------------------------------------- casts
/// cast from vector with a different scalar type
template<typename otherScalarType>
inline vector_type& operator=(const VectorT<otherScalarType,DIM>& _rhs) {
#define expr(i) Base::values_[i] = (Scalar)_rhs[i];
unroll(expr);
#undef expr
return *this;
}
// /// cast to Scalar array
// inline operator Scalar*() { return Base::values_; }
// /// cast to const Scalar array
// inline operator const Scalar*() const { return Base::values_; }
/// access to Scalar array
inline Scalar* data() { return Base::values_; }
/// access to const Scalar array
inline const Scalar*data() const { return Base::values_; }
//----------------------------------------------------------- element access
// /// get i'th element read-write
// inline Scalar& operator[](int _i) {
// assert(_i>=0 && _i<DIM); return Base::values_[_i];
// }
// /// get i'th element read-only
// inline const Scalar& operator[](int _i) const {
// assert(_i>=0 && _i<DIM); return Base::values_[_i];
// }
/// get i'th element read-write
inline Scalar& operator[](size_t _i) {
assert(_i<DIM); return Base::values_[_i];
}
/// get i'th element read-only
inline const Scalar& operator[](size_t _i) const {
assert(_i<DIM); return Base::values_[_i];
}
//---------------------------------------------------------------- comparsion
/// component-wise comparison
inline bool operator==(const vector_type& _rhs) const {
#define expr(i) if(Base::values_[i]!=_rhs.Base::values_[i]) return false;
unroll(expr);
#undef expr
return true;
}
/// component-wise comparison
inline bool operator!=(const vector_type& _rhs) const {
return !(*this == _rhs);
}
//---------------------------------------------------------- scalar operators
/// component-wise self-multiplication with scalar
inline vector_type& operator*=(const Scalar& _s) {
#define expr(i) Base::values_[i] *= _s;
unroll(expr);
#undef expr
return *this;
}
/** component-wise self-division by scalar
\attention v *= (1/_s) is much faster than this */
inline vector_type& operator/=(const Scalar& _s) {
#define expr(i) Base::values_[i] /= _s;
unroll(expr);
#undef expr
return *this;
}
/// component-wise multiplication with scalar
inline vector_type operator*(const Scalar& _s) const {
#if DIM==N
return vector_type(*this) *= _s;
#else
#define expr(i) Base::values_[i] * _s
return vector_type(unroll_csv(expr));
#undef expr
#endif
}
/// component-wise division by with scalar
inline vector_type operator/(const Scalar& _s) const {
#if DIM==N
return vector_type(*this) /= _s;
#else
#define expr(i) Base::values_[i] / _s
return vector_type(unroll_csv(expr));
#undef expr
#endif
}
//---------------------------------------------------------- vector operators
/// component-wise self-multiplication
inline vector_type& operator*=(const vector_type& _rhs) {
#define expr(i) Base::values_[i] *= _rhs[i];
unroll(expr);
#undef expr
return *this;
}
/// component-wise self-division
inline vector_type& operator/=(const vector_type& _rhs) {
#define expr(i) Base::values_[i] /= _rhs[i];
unroll(expr);
#undef expr
return *this;
}
/// vector difference from this
inline vector_type& operator-=(const vector_type& _rhs) {
#define expr(i) Base::values_[i] -= _rhs[i];
unroll(expr);
#undef expr
return *this;
}
/// vector self-addition
inline vector_type& operator+=(const vector_type& _rhs) {
#define expr(i) Base::values_[i] += _rhs[i];
unroll(expr);
#undef expr
return *this;
}
/// component-wise vector multiplication
inline vector_type operator*(const vector_type& _v) const {
#if DIM==N
return vector_type(*this) *= _v;
#else
#define expr(i) Base::values_[i] * _v.Base::values_[i]
return vector_type(unroll_csv(expr));
#undef expr
#endif
}
/// component-wise vector division
inline vector_type operator/(const vector_type& _v) const {
#if DIM==N
return vector_type(*this) /= _v;
#else
#define expr(i) Base::values_[i] / _v.Base::values_[i]
return vector_type(unroll_csv(expr));
#undef expr
#endif
}
/// component-wise vector addition
inline vector_type operator+(const vector_type& _v) const {
#if DIM==N
return vector_type(*this) += _v;
#else
#define expr(i) Base::values_[i] + _v.Base::values_[i]
return vector_type(unroll_csv(expr));
#undef expr
#endif
}
/// component-wise vector difference
inline vector_type operator-(const vector_type& _v) const {
#if DIM==N
return vector_type(*this) -= _v;
#else
#define expr(i) Base::values_[i] - _v.Base::values_[i]
return vector_type(unroll_csv(expr));
#undef expr
#endif
}
/// unary minus
inline vector_type operator-(void) const {
vector_type v;
#define expr(i) v.Base::values_[i] = -Base::values_[i];
unroll(expr);
#undef expr
return v;
}
/// cross product: only defined for Vec3* as specialization
/// \see OpenMesh::cross
inline VectorT<Scalar,3> operator%(const VectorT<Scalar,3>& _rhs) const
#if DIM==3
{
return
VectorT<Scalar,3>(Base::values_[1]*_rhs.Base::values_[2]-Base::values_[2]*_rhs.Base::values_[1],
Base::values_[2]*_rhs.Base::values_[0]-Base::values_[0]*_rhs.Base::values_[2],
Base::values_[0]*_rhs.Base::values_[1]-Base::values_[1]*_rhs.Base::values_[0]);
}
#else
;
#endif
/// compute scalar product
/// \see OpenMesh::dot
inline Scalar operator|(const vector_type& _rhs) const {
Scalar p(0);
#define expr(i) p += Base::values_[i] * _rhs.Base::values_[i];
unroll(expr);
#undef expr
return p;
}
//------------------------------------------------------------ euclidean norm
/// \name Euclidean norm calculations
//@{
/// compute euclidean norm
inline Scalar norm() const { return (Scalar)sqrt(sqrnorm()); }
inline Scalar length() const { return norm(); } // OpenSG interface
/// compute squared euclidean norm
inline Scalar sqrnorm() const
{
#if DIM==N
Scalar s(0);
#define expr(i) s += Base::values_[i] * Base::values_[i];
unroll(expr);
#undef expr
return s;
#else
#define expr(i) Base::values_[i]*Base::values_[i]
return (unroll_comb(expr, +));
#undef expr
#endif
}
/** normalize vector, return normalized vector
*/
inline vector_type& normalize()
{
*this /= norm();
return *this;
}
/** return normalized vector
*/
inline const vector_type normalized() const
{
return *this / norm();
}
/** normalize vector, return normalized vector and avoids div by zero
*/
inline vector_type& normalize_cond()
{
Scalar n = norm();
if (n != (Scalar)0.0)
{
*this /= n;
}
return *this;
}
//@}
//------------------------------------------------------------ euclidean norm
/// \name Non-Euclidean norm calculations
//@{
/// compute L1 (Manhattan) norm
inline Scalar l1_norm() const
{
#if DIM==N
Scalar s(0);
#define expr(i) s += std::abs(Base::values_[i]);
unroll(expr);
#undef expr
return s;
#else
#define expr(i) std::abs(Base::values_[i])
return (unroll_comb(expr, +));
#undef expr
#endif
}
/// compute l8_norm
inline Scalar l8_norm() const
{
return max_abs();
}
//@}
//------------------------------------------------------------ max, min, mean
/// \name Minimum maximum and mean
//@{
/// return the maximal component
inline Scalar max() const
{
Scalar m(Base::values_[0]);
for(int i=1; i<DIM; ++i) if(Base::values_[i]>m) m=Base::values_[i];
return m;
}
/// return the maximal absolute component
inline Scalar max_abs() const
{
Scalar m(std::abs(Base::values_[0]));
for(int i=1; i<DIM; ++i)
if(std::abs(Base::values_[i])>m)
m=std::abs(Base::values_[i]);
return m;
}
/// return the minimal component
inline Scalar min() const
{
Scalar m(Base::values_[0]);
for(int i=1; i<DIM; ++i) if(Base::values_[i]<m) m=Base::values_[i];
return m;
}
/// return the minimal absolute component
inline Scalar min_abs() const
{
Scalar m(std::abs(Base::values_[0]));
for(int i=1; i<DIM; ++i)
if(std::abs(Base::values_[i])<m)
m=std::abs(Base::values_[i]);
return m;
}
/// return arithmetic mean
inline Scalar mean() const {
Scalar m(Base::values_[0]);
for(int i=1; i<DIM; ++i) m+=Base::values_[i];
return m/Scalar(DIM);
}
/// return absolute arithmetic mean
inline Scalar mean_abs() const {
Scalar m(std::abs(Base::values_[0]));
for(int i=1; i<DIM; ++i) m+=std::abs(Base::values_[i]);
return m/Scalar(DIM);
}
/// minimize values: same as *this = min(*this, _rhs), but faster
inline vector_type& minimize(const vector_type& _rhs) {
#define expr(i) if (_rhs[i] < Base::values_[i]) Base::values_[i] = _rhs[i];
unroll(expr);
#undef expr
return *this;
}
/// minimize values and signalize coordinate minimization
inline bool minimized(const vector_type& _rhs) {
bool result(false);
#define expr(i) if (_rhs[i] < Base::values_[i]) { Base::values_[i] = _rhs[i]; result = true; }
unroll(expr);
#undef expr
return result;
}
/// maximize values: same as *this = max(*this, _rhs), but faster
inline vector_type& maximize(const vector_type& _rhs) {
#define expr(i) if (_rhs[i] > Base::values_[i]) Base::values_[i] = _rhs[i];
unroll(expr);
#undef expr
return *this;
}
/// maximize values and signalize coordinate maximization
inline bool maximized(const vector_type& _rhs) {
bool result(false);
#define expr(i) if (_rhs[i] > Base::values_[i]) { Base::values_[i] =_rhs[i]; result = true; }
unroll(expr);
#undef expr
return result;
}
/// component-wise min
inline vector_type min(const vector_type& _rhs) const {
return vector_type(*this).minimize(_rhs);
}
/// component-wise max
inline vector_type max(const vector_type& _rhs) const {
return vector_type(*this).maximize(_rhs);
}
//@}
//------------------------------------------------------------ misc functions
/// component-wise apply function object with Scalar operator()(Scalar).
template<typename Functor>
inline vector_type apply(const Functor& _func) const {
vector_type result;
#define expr(i) result[i] = _func(Base::values_[i]);
unroll(expr);
#undef expr
return result;
}
/// store the same value in each component (e.g. to clear all entries)
vector_type& vectorize(const Scalar& _s) {
#define expr(i) Base::values_[i] = _s;
unroll(expr);
#undef expr
return *this;
}
/// store the same value in each component
static vector_type vectorized(const Scalar& _s) {
return vector_type().vectorize(_s);
}
/// lexicographical comparison
bool operator<(const vector_type& _rhs) const {
#define expr(i) if (Base::values_[i] != _rhs.Base::values_[i]) \
return (Base::values_[i] < _rhs.Base::values_[i]);
unroll(expr);
#undef expr
return false;
}
};
/// read the space-separated components of a vector from a stream
TEMPLATE_HEADER
inline std::istream&
operator>>(std::istream& is, VectorT<Scalar,DIM>& vec)
{
#define expr(i) is >> vec[i];
unroll(expr);
#undef expr
return is;
}
/// output a vector by printing its space-separated compontens
TEMPLATE_HEADER
inline std::ostream&
operator<<(std::ostream& os, const VectorT<Scalar,DIM>& vec)
{
#if DIM==N
for(int i=0; i<N-1; ++i) os << vec[i] << " ";
os << vec[N-1];
#else
#define expr(i) vec[i]
os << unroll_comb(expr, << " " <<);
#undef expr
#endif
return os;
}
// ----------------------------------------------------------------------------
#endif // included by VectorT.hh
//=============================================================================

View File

@ -0,0 +1,315 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
//== INCLUDES =================================================================
// -------------------- STL
#include <algorithm>
#include <iostream>
// -------------------- OpenMesh
#include <OpenMesh/Core/IO/BinaryHelper.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
#ifndef DOXY_IGNORE_THIS
//== IMPLEMENTATION ===========================================================
//-----------------------------------------------------------------------------
short int read_short(FILE* _in, bool _swap)
{
union u1 { short int s; unsigned char c[2]; } sc;
fread((char*)sc.c, 1, 2, _in);
if (_swap) std::swap(sc.c[0], sc.c[1]);
return sc.s;
}
//-----------------------------------------------------------------------------
int read_int(FILE* _in, bool _swap)
{
union u2 { int i; unsigned char c[4]; } ic;
fread((char*)ic.c, 1, 4, _in);
if (_swap) {
std::swap(ic.c[0], ic.c[3]);
std::swap(ic.c[1], ic.c[2]);
}
return ic.i;
}
//-----------------------------------------------------------------------------
float read_float(FILE* _in, bool _swap)
{
union u3 { float f; unsigned char c[4]; } fc;
fread((char*)fc.c, 1, 4, _in);
if (_swap) {
std::swap(fc.c[0], fc.c[3]);
std::swap(fc.c[1], fc.c[2]);
}
return fc.f;
}
//-----------------------------------------------------------------------------
double read_double(FILE* _in, bool _swap)
{
union u4 { double d; unsigned char c[8]; } dc;
fread((char*)dc.c, 1, 8, _in);
if (_swap) {
std::swap(dc.c[0], dc.c[7]);
std::swap(dc.c[1], dc.c[6]);
std::swap(dc.c[2], dc.c[5]);
std::swap(dc.c[3], dc.c[4]);
}
return dc.d;
}
//-----------------------------------------------------------------------------
short int read_short(std::istream& _in, bool _swap)
{
union u1 { short int s; unsigned char c[2]; } sc;
_in.read((char*)sc.c, 2);
if (_swap) std::swap(sc.c[0], sc.c[1]);
return sc.s;
}
//-----------------------------------------------------------------------------
int read_int(std::istream& _in, bool _swap)
{
union u2 { int i; unsigned char c[4]; } ic;
_in.read((char*)ic.c, 4);
if (_swap) {
std::swap(ic.c[0], ic.c[3]);
std::swap(ic.c[1], ic.c[2]);
}
return ic.i;
}
//-----------------------------------------------------------------------------
float read_float(std::istream& _in, bool _swap)
{
union u3 { float f; unsigned char c[4]; } fc;
_in.read((char*)fc.c, 4);
if (_swap) {
std::swap(fc.c[0], fc.c[3]);
std::swap(fc.c[1], fc.c[2]);
}
return fc.f;
}
//-----------------------------------------------------------------------------
double read_double(std::istream& _in, bool _swap)
{
union u4 { double d; unsigned char c[8]; } dc;
_in.read((char*)dc.c, 8);
if (_swap) {
std::swap(dc.c[0], dc.c[7]);
std::swap(dc.c[1], dc.c[6]);
std::swap(dc.c[2], dc.c[5]);
std::swap(dc.c[3], dc.c[4]);
}
return dc.d;
}
//-----------------------------------------------------------------------------
void write_short(short int _i, FILE* _out, bool _swap)
{
union u1 { short int s; unsigned char c[2]; } sc;
sc.s = _i;
if (_swap) std::swap(sc.c[0], sc.c[1]);
fwrite((char*)sc.c, 1, 2, _out);
}
//-----------------------------------------------------------------------------
void write_int(int _i, FILE* _out, bool _swap)
{
union u2 { int i; unsigned char c[4]; } ic;
ic.i = _i;
if (_swap) {
std::swap(ic.c[0], ic.c[3]);
std::swap(ic.c[1], ic.c[2]);
}
fwrite((char*)ic.c, 1, 4, _out);
}
//-----------------------------------------------------------------------------
void write_float(float _f, FILE* _out, bool _swap)
{
union u3 { float f; unsigned char c[4]; } fc;
fc.f = _f;
if (_swap) {
std::swap(fc.c[0], fc.c[3]);
std::swap(fc.c[1], fc.c[2]);
}
fwrite((char*)fc.c, 1, 4, _out);
}
//-----------------------------------------------------------------------------
void write_double(double _d, FILE* _out, bool _swap)
{
union u4 { double d; unsigned char c[8]; } dc;
dc.d = _d;
if (_swap) {
std::swap(dc.c[0], dc.c[7]);
std::swap(dc.c[1], dc.c[6]);
std::swap(dc.c[2], dc.c[5]);
std::swap(dc.c[3], dc.c[4]);
}
fwrite((char*)dc.c, 1, 8, _out);
}
//-----------------------------------------------------------------------------
void write_short(short int _i, std::ostream& _out, bool _swap)
{
union u1 { short int s; unsigned char c[2]; } sc;
sc.s = _i;
if (_swap) std::swap(sc.c[0], sc.c[1]);
_out.write((char*)sc.c, 2);
}
//-----------------------------------------------------------------------------
void write_int(int _i, std::ostream& _out, bool _swap)
{
union u2 { int i; unsigned char c[4]; } ic;
ic.i = _i;
if (_swap) {
std::swap(ic.c[0], ic.c[3]);
std::swap(ic.c[1], ic.c[2]);
}
_out.write((char*)ic.c, 4);
}
//-----------------------------------------------------------------------------
void write_float(float _f, std::ostream& _out, bool _swap)
{
union u3 { float f; unsigned char c[4]; } fc;
fc.f = _f;
if (_swap) {
std::swap(fc.c[0], fc.c[3]);
std::swap(fc.c[1], fc.c[2]);
}
_out.write((char*)fc.c, 4);
}
//-----------------------------------------------------------------------------
void write_double(double _d, std::ostream& _out, bool _swap)
{
union u4 { double d; unsigned char c[8]; } dc;
dc.d = _d;
if (_swap) {
std::swap(dc.c[0], dc.c[7]);
std::swap(dc.c[1], dc.c[6]);
std::swap(dc.c[2], dc.c[5]);
std::swap(dc.c[3], dc.c[4]);
}
_out.write((char*)dc.c, 8);
}
#endif
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,164 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#ifndef OPENMESH_BINARY_HELPER_HH
#define OPENMESH_BINARY_HELPER_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
// -------------------- STL
#if defined( OM_CC_MIPS )
# include <stdio.h>
#else
# include <cstdio>
#endif
#include <iosfwd>
// -------------------- OpenMesh
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
/** \name Handling binary input/output.
These functions take care of swapping bytes to get the right Endian.
*/
//@{
//-----------------------------------------------------------------------------
/** Binary read a \c short from \c _is and perform byte swapping if
\c _swap is true */
short int read_short(FILE* _in, bool _swap=false);
/** Binary read an \c int from \c _is and perform byte swapping if
\c _swap is true */
int read_int(FILE* _in, bool _swap=false);
/** Binary read a \c float from \c _is and perform byte swapping if
\c _swap is true */
float read_float(FILE* _in, bool _swap=false);
/** Binary read a \c double from \c _is and perform byte swapping if
\c _swap is true */
double read_double(FILE* _in, bool _swap=false);
/** Binary read a \c short from \c _is and perform byte swapping if
\c _swap is true */
short int read_short(std::istream& _in, bool _swap=false);
/** Binary read an \c int from \c _is and perform byte swapping if
\c _swap is true */
int read_int(std::istream& _in, bool _swap=false);
/** Binary read a \c float from \c _is and perform byte swapping if
\c _swap is true */
float read_float(std::istream& _in, bool _swap=false);
/** Binary read a \c double from \c _is and perform byte swapping if
\c _swap is true */
double read_double(std::istream& _in, bool _swap=false);
/** Binary write a \c short to \c _os and perform byte swapping if
\c _swap is true */
void write_short(short int _i, FILE* _out, bool _swap=false);
/** Binary write an \c int to \c _os and perform byte swapping if
\c _swap is true */
void write_int(int _i, FILE* _out, bool _swap=false);
/** Binary write a \c float to \c _os and perform byte swapping if
\c _swap is true */
void write_float(float _f, FILE* _out, bool _swap=false);
/** Binary write a \c double to \c _os and perform byte swapping if
\c _swap is true */
void write_double(double _d, FILE* _out, bool _swap=false);
/** Binary write a \c short to \c _os and perform byte swapping if
\c _swap is true */
void write_short(short int _i, std::ostream& _out, bool _swap=false);
/** Binary write an \c int to \c _os and perform byte swapping if
\c _swap is true */
void write_int(int _i, std::ostream& _out, bool _swap=false);
/** Binary write a \c float to \c _os and perform byte swapping if
\c _swap is true */
void write_float(float _f, std::ostream& _out, bool _swap=false);
/** Binary write a \c double to \c _os and perform byte swapping if
\c _swap is true */
void write_double(double _d, std::ostream& _out, bool _swap=false);
//@}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_MESHREADER_HH defined
//=============================================================================

View File

@ -0,0 +1,115 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Helper file for static builds
//
// In opposite to dynamic builds where the instance of every reader module
// is generated within the OpenMesh library, static builds only instanciate
// objects that are at least referenced once. As all reader modules are
// never used directly, they will not be part of a static build, hence
// this file.
//
//=============================================================================
#ifndef __IOINSTANCES_HH__
#define __IOINSTANCES_HH__
#if defined(OM_STATIC_BUILD) || defined(ARCH_DARWIN)
//=============================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
#include <OpenMesh/Core/IO/reader/OBJReader.hh>
#include <OpenMesh/Core/IO/reader/OFFReader.hh>
#include <OpenMesh/Core/IO/reader/PLYReader.hh>
#include <OpenMesh/Core/IO/reader/STLReader.hh>
#include <OpenMesh/Core/IO/reader/OMReader.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
#include <OpenMesh/Core/IO/writer/OBJWriter.hh>
#include <OpenMesh/Core/IO/writer/OFFWriter.hh>
#include <OpenMesh/Core/IO/writer/STLWriter.hh>
#include <OpenMesh/Core/IO/writer/OMWriter.hh>
#include <OpenMesh/Core/IO/writer/PLYWriter.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
// Instanciate every Reader module
static BaseReader* OFFReaderInstance = &OFFReader();
static BaseReader* OBJReaderInstance = &OBJReader();
static BaseReader* PLYReaderInstance = &PLYReader();
static BaseReader* STLReaderInstance = &STLReader();
static BaseReader* OMReaderInstance = &OMReader();
// Instanciate every writer module
static BaseWriter* OBJWriterInstance = &OBJWriter();
static BaseWriter* OFFWriterInstance = &OFFWriter();
static BaseWriter* STLWriterInstance = &STLWriter();
static BaseWriter* OMWriterInstance = &OMWriter();
static BaseWriter* PLYWriterInstance = &PLYWriter();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif // static ?
#endif //__IOINSTANCES_HH__
//=============================================================================

View File

@ -0,0 +1,341 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements the OpenMesh IOManager singleton
//
//=============================================================================
//== INCLUDES =================================================================
#include <OpenMesh/Core/IO/IOManager.hh>
#include <iostream>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
// Destructor never called. Moved into singleton getter function
// _IOManager_ *__IOManager_instance = 0;
_IOManager_& IOManager()
{
static _IOManager_ __IOManager_instance;
//if (!__IOManager_instance)
// __IOManager_instance = new _IOManager_();
return __IOManager_instance;
}
//-----------------------------------------------------------------------------
bool
_IOManager_::
read(const std::string& _filename, BaseImporter& _bi, Options& _opt)
{
std::set<BaseReader*>::const_iterator it = reader_modules_.begin();
std::set<BaseReader*>::const_iterator it_end = reader_modules_.end();
if( it == it_end )
{
omerr() << "[OpenMesh::IO::_IOManager_] No reading modules available!\n";
return false;
}
// Try all registered modules
for(; it != it_end; ++it)
if ((*it)->can_u_read(_filename))
{
_bi.prepare();
bool ok = (*it)->read(_filename, _bi, _opt);
_bi.finish();
return ok;
}
// All modules failed to read
return false;
}
//-----------------------------------------------------------------------------
bool
_IOManager_::
read(std::istream& _is, const std::string& _ext, BaseImporter& _bi, Options& _opt)
{
std::set<BaseReader*>::const_iterator it = reader_modules_.begin();
std::set<BaseReader*>::const_iterator it_end = reader_modules_.end();
// Try all registered modules
for(; it != it_end; ++it)
if ((*it)->BaseReader::can_u_read(_ext)) //Use the extension check only (no file existence)
{
_bi.prepare();
bool ok = (*it)->read(_is, _bi, _opt);
_bi.finish();
return ok;
}
// All modules failed to read
return false;
}
//-----------------------------------------------------------------------------
bool
_IOManager_::
write(const std::string& _filename, BaseExporter& _be, Options _opt, std::streamsize _precision)
{
std::set<BaseWriter*>::const_iterator it = writer_modules_.begin();
std::set<BaseWriter*>::const_iterator it_end = writer_modules_.end();
if ( it == it_end )
{
omerr() << "[OpenMesh::IO::_IOManager_] No writing modules available!\n";
return false;
}
// Try all registered modules
for(; it != it_end; ++it)
{
if ((*it)->can_u_write(_filename))
{
return (*it)->write(_filename, _be, _opt, _precision);
}
}
// All modules failed to save
return false;
}
//-----------------------------------------------------------------------------
bool
_IOManager_::
write(std::ostream& _os,const std::string &_ext, BaseExporter& _be, Options _opt, std::streamsize _precision)
{
std::set<BaseWriter*>::const_iterator it = writer_modules_.begin();
std::set<BaseWriter*>::const_iterator it_end = writer_modules_.end();
if ( it == it_end )
{
omerr() << "[OpenMesh::IO::_IOManager_] No writing modules available!\n";
return false;
}
// Try all registered modules
for(; it != it_end; ++it)
{
if ((*it)->BaseWriter::can_u_write(_ext)) //Restrict test to the extension check
{
return (*it)->write(_os, _be, _opt, _precision);
}
}
// All modules failed to save
return false;
}
//-----------------------------------------------------------------------------
bool
_IOManager_::
can_read( const std::string& _format ) const
{
std::set<BaseReader*>::const_iterator it = reader_modules_.begin();
std::set<BaseReader*>::const_iterator it_end = reader_modules_.end();
std::string filename = "dummy." + _format;
for(; it != it_end; ++it)
if ((*it)->can_u_read(filename))
return true;
return false;
}
//-----------------------------------------------------------------------------
bool
_IOManager_::
can_write( const std::string& _format ) const
{
std::set<BaseWriter*>::const_iterator it = writer_modules_.begin();
std::set<BaseWriter*>::const_iterator it_end = writer_modules_.end();
std::string filename = "dummy." + _format;
// Try all registered modules
for(; it != it_end; ++it)
if ((*it)->can_u_write(filename))
return true;
return false;
}
//-----------------------------------------------------------------------------
const BaseWriter*
_IOManager_::
find_writer(const std::string& _format)
{
using std::string;
string::size_type dot = _format.rfind('.');
string ext;
if (dot == string::npos)
ext = _format;
else
ext = _format.substr(dot+1,_format.length()-(dot+1));
std::set<BaseWriter*>::const_iterator it = writer_modules_.begin();
std::set<BaseWriter*>::const_iterator it_end = writer_modules_.end();
std::string filename = "dummy." + ext;
// Try all registered modules
for(; it != it_end; ++it)
if ((*it)->can_u_write(filename))
return *it;
return NULL;
}
//-----------------------------------------------------------------------------
void
_IOManager_::
update_read_filters()
{
std::set<BaseReader*>::const_iterator it = reader_modules_.begin(),
it_end = reader_modules_.end();
std::string all = "";
std::string filters = "";
for(; it != it_end; ++it)
{
// Initialized with space, as a workaround for debug build with clang on mac
// which crashes if tmp is initialized with an empty string ?!
std::string tmp = " ";
filters += (*it)->get_description() + " (";
std::istringstream iss((*it)->get_extensions());
while (iss && !iss.eof() && (iss >> tmp) )
{
tmp = " *." + tmp; filters += tmp; all += tmp;
}
filters += " );;";
}
all = "All files ( " + all + " );;";
read_filters_ = all + filters;
}
//-----------------------------------------------------------------------------
void
_IOManager_::
update_write_filters()
{
std::set<BaseWriter*>::const_iterator it = writer_modules_.begin(),
it_end = writer_modules_.end();
std::string all;
std::string filters;
for(; it != it_end; ++it)
{
// Initialized with space, as a workaround for debug build with clang on mac
// which crashes if tmp is initialized with an empty string ?!
std::string s = " ";
filters += (*it)->get_description() + " (";
std::istringstream iss((*it)->get_extensions());
while (iss && !iss.eof() && (iss >> s))
{ s = " *." + s; filters += s; all += s; }
filters += " );;";
}
all = "All files ( " + all + " );;";
write_filters_ = all + filters;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,272 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements the OpenMesh IOManager singleton
//
//=============================================================================
#ifndef __IOMANAGER_HH__
#define __IOMANAGER_HH__
//=== INCLUDES ================================================================
// STL
#include <iosfwd>
#include <sstream>
#include <string>
#include <set>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/Options.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
#include <OpenMesh/Core/Utils/SingletonT.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/** This is the real IOManager class that is later encapsulated by
SingletonT to enforce its uniqueness. _IOManager_ is not meant to be used
directly by the programmer - the IOManager alias exists for this task.
All reader/writer modules register themselves at this class. For
reading or writing data all modules are asked to do the job. If no
suitable module is found, an error is returned.
For the sake of reading, the target data structure is hidden
behind the BaseImporter interface that takes care of adding
vertices or faces.
Writing from a source structure is encapsulate similarly behind a
BaseExporter interface, providing iterators over vertices/faces to
the writer modules.
\see \ref mesh_io
*/
class OPENMESHDLLEXPORT _IOManager_
{
private:
/// Constructor has nothing todo for the Manager
_IOManager_() {}
/// Destructor has nothing todo for the Manager
~_IOManager_() {};
/** Declare the singleton getter function as friend to access the private constructor
and destructor
*/
friend OPENMESHDLLEXPORT _IOManager_& IOManager();
public:
/**
Read a mesh from file _filename. The target data structure is specified
by the given BaseImporter. The \c read method consecutively queries all
of its reader modules. True is returned upon success, false if all
reader modules failed to interprete _filename.
*/
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt);
/**
Read a mesh from open std::istream _is. The target data structure is specified
by the given BaseImporter. The \c sread method consecutively queries all
of its reader modules. True is returned upon success, false if all
reader modules failed to use _is.
*/
bool read(std::istream& _filename,
const std::string& _ext,
BaseImporter& _bi,
Options& _opt);
/** Write a mesh to file _filename. The source data structure is specified
by the given BaseExporter. The \c save method consecutively queries all
of its writer modules. True is returned upon success, false if all
writer modules failed to write the requested format.
Options is determined by _filename's extension.
*/
bool write(const std::string& _filename,
BaseExporter& _be,
Options _opt=Options::Default,
std::streamsize _precision = 6);
/** Write a mesh to open std::ostream _os. The source data structure is specified
by the given BaseExporter. The \c save method consecutively queries all
of its writer modules. True is returned upon success, false if all
writer modules failed to write the requested format.
Options is determined by _filename's extension.
*/
bool write(std::ostream& _filename,
const std::string& _ext,
BaseExporter& _be,
Options _opt=Options::Default,
std::streamsize _precision = 6);
/// Returns true if the format is supported by one of the reader modules.
bool can_read( const std::string& _format ) const;
/// Returns true if the format is supported by one of the writer modules.
bool can_write( const std::string& _format ) const;
size_t binary_size(const std::string& _format,
BaseExporter& _be,
Options _opt = Options::Default)
{
const BaseWriter *bw = find_writer(_format);
return bw ? bw->binary_size(_be,_opt) : 0;
}
public: //-- QT convenience function ------------------------------------------
/** Returns all readable file extension + descriptions in one string.
File formats are separated by <c>;;</c>.
Convenience function for Qt file dialogs.
*/
const std::string& qt_read_filters() const { return read_filters_; }
/** Returns all writeable file extension + descriptions in one string.
File formats are separated by <c>;;</c>.
Convenience function for Qt file dialogs.
*/
const std::string& qt_write_filters() const { return write_filters_; }
private:
// collect all readable file extensions
void update_read_filters();
// collect all writeable file extensions
void update_write_filters();
public: //-- SYSTEM PART------------------------------------------------------
/** Registers a new reader module. A call to this function should be
implemented in the constructor of all classes derived from BaseReader.
*/
bool register_module(BaseReader* _bl)
{
reader_modules_.insert(_bl);
update_read_filters();
return true;
}
/** Registers a new writer module. A call to this function should be
implemented in the constructor of all classed derived from BaseWriter.
*/
bool register_module(BaseWriter* _bw)
{
writer_modules_.insert(_bw);
update_write_filters();
return true;
}
private:
const BaseWriter *find_writer(const std::string& _format);
// stores registered reader modules
std::set<BaseReader*> reader_modules_;
// stores registered writer modules
std::set<BaseWriter*> writer_modules_;
// input filters (e.g. for Qt file dialog)
std::string read_filters_;
// output filters (e.g. for Qt file dialog)
std::string write_filters_;
};
//=============================================================================
//_IOManager_* __IOManager_instance; Causes memory leak, as destructor is never called
OPENMESHDLLEXPORT _IOManager_& IOManager();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,296 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OM_MESHIO_HH
#define OM_MESHIO_HH
//=== INCLUDES ================================================================
// -------------------- system settings
#include <OpenMesh/Core/System/config.h>
// -------------------- check include order
#if defined (OPENMESH_TRIMESH_ARRAY_KERNEL_HH) || \
defined (OPENMESH_POLYMESH_ARRAY_KERNEL_HH)
// Issue warning if MeshIO was not included before Mesh Type
// Nobody knows why this order was enforced.
// If somebody encounters an error resulting from a wrong order, please report it to the OpenMesh developers.
// If we don't here about any errors, this check will be removed
// @TODO: Remove after reasonable time
#ifdef WIN32
#pragma message("MeshIO.hh was included after Mesh Type. You may ignore this warning. Please report errors resulting ifrom this order to the developers!")
#else
#warning "MeshIO.hh was included after Mesh Type. You may ignore this warning. Please report errors resulting from this order to the developers!"
#endif
#endif
// -------------------- OpenMesh
#include <OpenMesh/Core/IO/SR_store.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/IO/importer/ImporterT.hh>
#include <OpenMesh/Core/IO/exporter/ExporterT.hh>
//== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/** \name Mesh Reading / Writing
Convenience functions the map to IOManager functions.
\see OpenMesh::IO::_IOManager_
*/
//@{
//-----------------------------------------------------------------------------
/** \brief Read a mesh from file _filename.
The file format is determined by the file extension.
\note If you link statically against OpenMesh, you have to add
the define OM_STATIC_BUILD to your application. This will
ensure that readers and writers get initialized correctly.
@param _mesh The target mesh that will be filled with the read data
@param _filename fill to load
@return Successful?
*/
template <class Mesh>
bool
read_mesh(Mesh& _mesh,
const std::string& _filename)
{
Options opt;
return read_mesh(_mesh, _filename, opt, true);
}
/** \brief Read a mesh from file _filename.
The file format is determined by the file extension.
\note If you link statically against OpenMesh, you have to add
the define OM_STATIC_BUILD to your application. This will
ensure that readers and writers get initialized correctly.
@param _mesh The target mesh that will be filled with the read data
@param _filename fill to load
@param _opt Reader options (e.g. skip loading of normals ... depends
on the reader capabilities). Note that simply passing an
Options::Flag enum is not sufficient.
@param _clear Clear the target data before filling it (allows to
load multiple files into one Mesh). If you only want to read a mesh
without clearing set _clear to false. Providing a default Options
object is sufficient in this case.
@return Successful?
*/
template <class Mesh>
bool
read_mesh(Mesh& _mesh,
const std::string& _filename,
Options& _opt,
bool _clear = true)
{
if (_clear) _mesh.clear();
ImporterT<Mesh> importer(_mesh);
return IOManager().read(_filename, importer, _opt);
}
/** \brief Read a mesh from file open std::istream.
The file format is determined by parameter _ext. _ext has to include
".[format]" in order to work properly (e.g. ".OFF")
\note If you link statically against OpenMesh, you have to add
the define OM_STATIC_BUILD to your application. This will
ensure that readers and writers get initialized correctly.
@param _mesh The target mesh that will be filled with the read data
@param _is stream to load the data from
@param _ext The file format that is written to the stream
@param _opt Reader options (e.g. skip loading of normals ... depends
on the reader capabilities)
@param _clear Clear the target data before filling it (allows to
load multiple files into one Mesh)
@return Successful?
*/
template <class Mesh>
bool
read_mesh(Mesh& _mesh,
std::istream& _is,
const std::string& _ext,
Options& _opt,
bool _clear = true)
{
if (_clear) _mesh.clear();
ImporterT<Mesh> importer(_mesh);
return IOManager().read(_is,_ext, importer, _opt);
}
//-----------------------------------------------------------------------------
/** \brief Write a mesh to the file _filename.
The file format is determined by _filename's extension.
\note If you link statically against OpenMesh, you have to add
the define OM_STATIC_BUILD to your application. This will
ensure that readers and writers get initialized correctly.
@param _mesh The mesh that will be written to file
@param _filename output filename
@param _opt Writer options (e.g. writing of normals ... depends
on the writer capabilities)
@param _precision specifies stream precision for ascii files
@return Successful?
*/
template <class Mesh>
bool write_mesh(const Mesh& _mesh,
const std::string& _filename,
Options _opt = Options::Default,
std::streamsize _precision = 6)
{
ExporterT<Mesh> exporter(_mesh);
return IOManager().write(_filename, exporter, _opt, _precision);
}
//-----------------------------------------------------------------------------
/** Write a mesh to an open std::ostream.
The file format is determined by parameter _ext. _ext has to include
".[format]" in order to work properly (e.g. ".OFF")
\note If you link statically against OpenMesh, you have to add
the define OM_STATIC_BUILD to your application. This will
ensure that readers and writers get initialized correctly.
@param _mesh The mesh that will be written to file
@param _os output stream to write into
@param _ext extension defining the type of output
@param _opt Writer options (e.g. writing of normals ... depends
on the writer capabilities)
@param _precision specifies stream precision for ascii files
@return Successful?
*/
template <class Mesh>
bool write_mesh(const Mesh& _mesh,
std::ostream& _os,
const std::string& _ext,
Options _opt = Options::Default,
std::streamsize _precision = 6)
{
ExporterT<Mesh> exporter(_mesh);
return IOManager().write(_os,_ext, exporter, _opt, _precision);
}
//-----------------------------------------------------------------------------
/** \brief Get binary size of data
This function calls the corresponding writer which calculates the size
of the data that would be written to a binary file
The file format is determined by parameter _ext. _ext has to include
".[format]" in order to work properly (e.g. ".OFF")
@param _mesh Mesh to write
@param _ext extension of the file (used to determine the writing module)
@param _opt Writer options (e.g. writing of normals ... depends
on the writer capabilities)
@return Binary size in bytes used when writing the data
*/
template <class Mesh>
size_t binary_size(const Mesh& _mesh,
const std::string& _ext,
Options _opt = Options::Default)
{
ExporterT<Mesh> exporter(_mesh);
return IOManager().binary_size(_ext, exporter, _opt);
}
//-----------------------------------------------------------------------------
//@}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#if defined(OM_STATIC_BUILD) || defined(ARCH_DARWIN)
# include <OpenMesh/Core/IO/IOInstances.hh>
#endif
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,99 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OPENMESH_IO_OFFFORMAT_HH
#define OPENMESH_IO_OFFFORMAT_HH
//=== INCLUDES ================================================================
// OpenMesh
#include <OpenMesh/Core/System/config.h>
//== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/** \name Mesh Reading / Writing
Option for writer modules.
*/
//@{
//-----------------------------------------------------------------------------
#ifndef DOXY_IGNORE_THIS
struct OPENMESHDLLEXPORT OFFFormat
{
typedef int integer_type;
typedef float float_type;
};
#endif
//@}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,247 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
//== INCLUDES =================================================================
#include <OpenMesh/Core/IO/OMFormat.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
namespace OMFormat {
//== IMPLEMENTATION ===========================================================
Chunk::Integer_Size needed_bits( size_t s )
{
if (s <= 0x000100) return Chunk::Integer_8;
if (s <= 0x010000) return Chunk::Integer_16;
#if 0
// !Not tested yet! This most probably won't work!
// NEED a 64bit system!
if ( (sizeof( size_t ) == 8) && (s >= 0x100000000) )
return Chunk::Integer_64;
#endif
return Chunk::Integer_32;
}
//-----------------------------------------------------------------------------
uint16&
operator << (uint16& val, const Chunk::Header& hdr)
{
val = 0;
val |= hdr.name_ << OMFormat::Chunk::OFF_NAME;
val |= hdr.entity_ << OMFormat::Chunk::OFF_ENTITY;
val |= hdr.type_ << OMFormat::Chunk::OFF_TYPE;
val |= hdr.signed_ << OMFormat::Chunk::OFF_SIGNED;
val |= hdr.float_ << OMFormat::Chunk::OFF_FLOAT;
val |= hdr.dim_ << OMFormat::Chunk::OFF_DIM;
val |= hdr.bits_ << OMFormat::Chunk::OFF_BITS;
return val;
}
//-----------------------------------------------------------------------------
Chunk::Header&
operator << (Chunk::Header& hdr, const uint16 val)
{
hdr.reserved_ = 0;
hdr.name_ = val >> OMFormat::Chunk::OFF_NAME;
hdr.entity_ = val >> OMFormat::Chunk::OFF_ENTITY;
hdr.type_ = val >> OMFormat::Chunk::OFF_TYPE;
hdr.signed_ = val >> OMFormat::Chunk::OFF_SIGNED;
hdr.float_ = val >> OMFormat::Chunk::OFF_FLOAT;
hdr.dim_ = val >> OMFormat::Chunk::OFF_DIM;
hdr.bits_ = val >> OMFormat::Chunk::OFF_BITS;
return hdr;
}
//-----------------------------------------------------------------------------
const char *as_string(Chunk::Entity e)
{
switch(e)
{
case Chunk::Entity_Vertex: return "Vertex";
case Chunk::Entity_Mesh: return "Mesh";
case Chunk::Entity_Edge: return "Edge";
case Chunk::Entity_Halfedge: return "Halfedge";
case Chunk::Entity_Face: return "Face";
default:
std::clog << "as_string(Chunk::Entity): Invalid value!";
}
return NULL;
}
//-----------------------------------------------------------------------------
const char *as_string(Chunk::Type t)
{
switch(t)
{
case Chunk::Type_Pos: return "Pos";
case Chunk::Type_Normal: return "Normal";
case Chunk::Type_Texcoord: return "Texcoord";
case Chunk::Type_Status: return "Status";
case Chunk::Type_Color: return "Color";
case Chunk::Type_Custom: return "Custom";
case Chunk::Type_Topology: return "Topology";
}
return NULL;
}
//-----------------------------------------------------------------------------
const char *as_string(Chunk::Dim d)
{
switch(d)
{
case Chunk::Dim_1D: return "1D";
case Chunk::Dim_2D: return "2D";
case Chunk::Dim_3D: return "3D";
case Chunk::Dim_4D: return "4D";
case Chunk::Dim_5D: return "5D";
case Chunk::Dim_6D: return "6D";
case Chunk::Dim_7D: return "7D";
case Chunk::Dim_8D: return "8D";
}
return NULL;
}
//-----------------------------------------------------------------------------
const char *as_string(Chunk::Integer_Size d)
{
switch(d)
{
case Chunk::Integer_8 : return "8";
case Chunk::Integer_16 : return "16";
case Chunk::Integer_32 : return "32";
case Chunk::Integer_64 : return "64";
}
return NULL;
}
const char *as_string(Chunk::Float_Size d)
{
switch(d)
{
case Chunk::Float_32 : return "32";
case Chunk::Float_64 : return "64";
case Chunk::Float_128: return "128";
}
return NULL;
}
//-----------------------------------------------------------------------------
std::ostream& operator << ( std::ostream& _os, const Chunk::Header& _c )
{
_os << "Chunk Header : 0x" << std::setw(4)
<< std::hex << (*(uint16*)(&_c)) << std::dec << '\n';
_os << "entity = "
<< as_string(Chunk::Entity(_c.entity_)) << '\n';
_os << "type = "
<< as_string(Chunk::Type(_c.type_));
if ( Chunk::Type(_c.type_)!=Chunk::Type_Custom)
{
_os << '\n'
<< "signed = "
<< _c.signed_ << '\n';
_os << "float = "
<< _c.float_ << '\n';
_os << "dim = "
<< as_string(Chunk::Dim(_c.dim_)) << '\n';
_os << "bits = "
<< (_c.float_
? as_string(Chunk::Float_Size(_c.bits_))
: as_string(Chunk::Integer_Size(_c.bits_)));
}
return _os;
}
//-----------------------------------------------------------------------------
std::ostream& operator << ( std::ostream& _os, const Header& _h )
{
_os << "magic = '" << _h.magic_[0] << _h.magic_[1] << "'\n"
<< "mesh = '" << _h.mesh_ << "'\n"
<< "version = 0x" << std::hex << (uint16)_h.version_ << std::dec
<< " (" << major_version(_h.version_)
<< "." << minor_version(_h.version_) << ")\n"
<< "#V = " << _h.n_vertices_ << '\n'
<< "#F = " << _h.n_faces_ << '\n'
<< "#E = " << _h.n_edges_;
return _os;
}
} // namespace OMFormat
// --------------------------------------------------------------------------
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,751 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OPENMESH_IO_OMFORMAT_HH
#define OPENMESH_IO_OMFORMAT_HH
//=== INCLUDES ================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/IO/SR_store.hh>
#include <OpenMesh/Core/Utils/GenProg.hh>
#include <OpenMesh/Core/Utils/Endian.hh>
#include <OpenMesh/Core/Utils/vector_traits.hh>
// --------------------
#include <iostream>
#if defined(OM_CC_GCC) && (OM_GCC_VERSION < 30000)
# include <OpenMesh/Tools/Utils/NumLimitsT.hh>
# define OM_MISSING_HEADER_LIMITS 1
#else
# include <limits>
#endif
//== NAMESPACES ==============================================================
#ifndef DOXY_IGNORE_THIS
namespace OpenMesh {
namespace IO {
namespace OMFormat {
//=== IMPLEMENTATION ==========================================================
/** \name Mesh Reading / Writing
*/
//@{
//-----------------------------------------------------------------------------
// <:Header>
// <:Comment>
// Chunk 0
// <:ChunkHeader>
// <:Comment>
// data
// Chunk 1
// <:ChunkHeader>
// <:Comment>
// data
// .
// .
// .
// Chunk N
//
// NOTICE!
//
// The usage of data types who differ in size
// on different pc architectures (32/64 bit) and/or
// operating systems, e.g. (unsigned) long, size_t,
// is not recommended because of inconsistencies
// in case of cross writing and reading.
//
// Basic types that are supported are:
typedef unsigned char uchar;
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;
typedef float32_t float32;
typedef float64_t float64;
struct Header
{
uchar magic_[2]; // OM
uchar mesh_; // [T]riangles, [Q]uads, [P]olygonals
uint8 version_;
uint32 n_vertices_;
uint32 n_faces_;
uint32 n_edges_;
size_t store( std::ostream& _os, bool _swap ) const
{
_os.write( (char*)this, 4); // magic_, mesh_, version_
size_t bytes = 4;
bytes += binary<uint32_t>::store( _os, n_vertices_, _swap );
bytes += binary<uint32_t>::store( _os, n_faces_, _swap );
bytes += binary<uint32_t>::store( _os, n_edges_, _swap );
return bytes;
}
size_t restore( std::istream& _is, bool _swap )
{
if (_is.read( (char*)this, 4 ).eof())
return 0;
size_t bytes = 4;
bytes += binary<uint32_t>::restore( _is, n_vertices_, _swap );
bytes += binary<uint32_t>::restore( _is, n_faces_, _swap );
bytes += binary<uint32_t>::restore( _is, n_edges_, _swap );
return bytes;
}
};
struct Chunk
{
// Hardcoded this size to an uint32 to make the system 32/64 bit compatible.
// Needs further investigation!
typedef uint32 esize_t; // element size, used for custom properties
enum Type {
Type_Pos = 0x00,
Type_Normal = 0x01,
Type_Texcoord = 0x02,
Type_Status = 0x03,
Type_Color = 0x04,
Type_Custom = 0x06,
Type_Topology = 0x07
};
enum Entity {
Entity_Vertex = 0x00,
Entity_Mesh = 0x01,
Entity_Face = 0x02,
Entity_Edge = 0x04,
Entity_Halfedge = 0x06,
Entity_Sentinel = 0x07
};
enum Dim {
Dim_1D = 0x00,
Dim_2D = 0x01,
Dim_3D = 0x02,
Dim_4D = 0x03,
Dim_5D = 0x04,
Dim_6D = 0x05,
Dim_7D = 0x06,
Dim_8D = 0x07
};
enum Integer_Size {
Integer_8 = 0x00, // 1 byte for (unsigned) char
Integer_16 = 0x01, // 2 bytes for short
Integer_32 = 0x02, // 4 bytes for long
Integer_64 = 0x03 // 8 bytes for long long
};
enum Float_Size {
Float_32 = 0x00, // 4 bytes for float
Float_64 = 0x01, // 8 bytes for double
Float_128 = 0x02 // 16 bytes for long double (an assumption!)
};
static const int SIZE_RESERVED = 1; // 1
static const int SIZE_NAME = 1; // 2
static const int SIZE_ENTITY = 3; // 5
static const int SIZE_TYPE = 4; // 9
static const int SIZE_SIGNED = 1; // 10
static const int SIZE_FLOAT = 1; // 11
static const int SIZE_DIM = 3; // 14
static const int SIZE_BITS = 2; // 16
static const int OFF_RESERVED = 0; // 0
static const int OFF_NAME = SIZE_RESERVED + OFF_RESERVED; // 2
static const int OFF_ENTITY = SIZE_NAME + OFF_NAME; // 3
static const int OFF_TYPE = SIZE_ENTITY + OFF_ENTITY; // 5
static const int OFF_SIGNED = SIZE_TYPE + OFF_TYPE; // 9
static const int OFF_FLOAT = SIZE_SIGNED + OFF_SIGNED; // 10
static const int OFF_DIM = SIZE_FLOAT + OFF_FLOAT; // 11
static const int OFF_BITS = SIZE_DIM + OFF_DIM; // 14
// !Attention! When changing the bit size, the operators
// << (uint16, Header) and << (Header, uint16) must be changed as well
//
// Entries signed_, float_, dim_, bits_ are not used when type_
// equals Type_Custom
//
struct Header // 16 bits long
{
unsigned reserved_: SIZE_RESERVED;
unsigned name_ : SIZE_NAME; // 1 named property, 0 anonymous
unsigned entity_ : SIZE_ENTITY; // 0 vertex, 1 mesh, 2 edge,
// 4 halfedge, 6 face
unsigned type_ : SIZE_TYPE; // 0 pos, 1 normal, 2 texcoord,
// 3 status, 4 color 6 custom 7 topology
unsigned signed_ : SIZE_SIGNED; // bool
unsigned float_ : SIZE_FLOAT; // bool
unsigned dim_ : SIZE_DIM; // 0 1D, 1 2D, 2 3D, .., 7 8D
unsigned bits_ : SIZE_BITS; // {8, 16, 32, 64} | {32, 64, 128}
// (integer) (float)
unsigned unused_ : 16; // fill up to 32 bits
}; // struct Header
class PropertyName : public std::string
{
public:
static const size_t size_max = 256;
PropertyName( ) { }
PropertyName( const std::string& _name ) { *this = _name; }
bool is_valid() const { return is_valid( size() ); }
static bool is_valid( size_t _s ) { return _s <= size_max; }
PropertyName& operator = ( const std::string& _rhs )
{
assert( is_valid( _rhs.size() ) );
if ( is_valid( _rhs.size() ) )
std::string::operator = ( _rhs );
else
{
omerr() << "Warning! Property name too long. Will be shortened!\n";
this->std::string::operator = ( _rhs.substr(0, size_max) );
}
return *this;
}
};
}; // Chunk
// ------------------------------------------------------------ Helper
// -------------------- get size information
/// Return size of header in bytes.
inline size_t header_size(void) { return sizeof(Header); }
/// Return size of chunk header in bytes.
inline size_t chunk_header_size( void ) { return sizeof(uint16); }
/// Return the size of a scale in bytes.
inline size_t scalar_size( const Chunk::Header& _hdr )
{
return _hdr.float_ ? (0x01 << _hdr.bits_) : (0x04 << _hdr.bits_);
}
/// Return the dimension of the vector in a chunk
inline size_t dimensions(const Chunk::Header& _chdr) { return _chdr.dim_+1; }
/// Return the size of a vector in bytes.
inline size_t vector_size( const Chunk::Header& _chdr )
{
return dimensions(_chdr)*scalar_size(_chdr);
}
/// Return the size of chunk data in bytes
inline size_t chunk_data_size( Header& _hdr, Chunk::Header& _chunk_hdr )
{
size_t C;
switch( _chunk_hdr.entity_ )
{
case Chunk::Entity_Vertex: C = _hdr.n_vertices_; break;
case Chunk::Entity_Face: C = _hdr.n_faces_; break;
case Chunk::Entity_Halfedge: C = _hdr.n_edges_*2; break;
case Chunk::Entity_Edge: C = _hdr.n_edges_; break;
case Chunk::Entity_Mesh: C = 1; break;
default:
C = 0;
std::cerr << "Invalid value in _chunk_hdr.entity_\n";
assert( false );
break;
}
return C * vector_size( _chunk_hdr );
}
inline size_t chunk_size( Header& _hdr, Chunk::Header& _chunk_hdr )
{
return chunk_header_size() + chunk_data_size( _hdr, _chunk_hdr );
}
// -------------------- convert from Chunk::Header to storage type
uint16& operator << (uint16& val, const Chunk::Header& hdr);
Chunk::Header& operator << (Chunk::Header& hdr, const uint16 val);
// -------------------- type information
template <typename T> bool is_float(const T&)
{
#if defined(OM_MISSING_HEADER_LIMITS)
return !Utils::NumLimitsT<T>::is_integer();
#else
return !std::numeric_limits<T>::is_integer;
#endif
}
template <typename T> bool is_integer(const T)
{
#if defined(OM_MISSING_HEADER_LIMITS)
return Utils::NumLimitsT<T>::is_integer();
#else
return std::numeric_limits<T>::is_integer;
#endif
}
template <typename T> bool is_signed(const T&)
{
#if defined(OM_MISSING_HEADER_LIMITS)
return Utils::NumLimitsT<T>::is_signed();
#else
return std::numeric_limits<T>::is_signed;
#endif
}
// -------------------- conversions (format type <- type/value)
template <typename VecType>
inline
Chunk::Dim dim( VecType )
{
assert( vector_traits< VecType >::size() < 9 );
return static_cast<Chunk::Dim>(vector_traits< VecType >::size() - 1);
}
template <typename VecType>
inline
Chunk::Dim dim( const Chunk::Header& _hdr )
{
return static_cast<Chunk::Dim>( _hdr.dim_ );
}
// calc minimum (power-of-2) number of bits needed
Chunk::Integer_Size needed_bits( size_t s );
// Convert size of type to Integer_Size
#ifdef NDEBUG
template <typename T> Chunk::Integer_Size integer_size(const T&)
#else
template <typename T> Chunk::Integer_Size integer_size(const T& d)
#endif
{
#ifndef NDEBUG
assert( is_integer(d) );
#endif
switch( sizeof(T) )
{
case 1: return OMFormat::Chunk::Integer_8;
case 2: return OMFormat::Chunk::Integer_16;
case 4: return OMFormat::Chunk::Integer_32;
case 8: return OMFormat::Chunk::Integer_64;
default:
std::cerr << "Invalid value in integer_size\n";
assert( false );
break;
}
return Chunk::Integer_Size(0);
}
// Convert size of type to FLoat_Size
#ifdef NDEBUG
template <typename T> Chunk::Float_Size float_size(const T&)
#else
template <typename T> Chunk::Float_Size float_size(const T& d)
#endif
{
#ifndef NDEBUG
assert( is_float(d) );
#endif
switch( sizeof(T) )
{
case 4: return OMFormat::Chunk::Float_32;
case 8: return OMFormat::Chunk::Float_64;
case 16: return OMFormat::Chunk::Float_128;
default:
std::cerr << "Invalid value in float_size\n";
assert( false );
break;
}
return Chunk::Float_Size(0);
}
// Return the storage type (Chunk::Header::bits_)
template <typename T>
inline
unsigned int bits(const T& val)
{
return is_integer(val)
? (static_cast<unsigned int>(integer_size(val)))
: (static_cast<unsigned int>(float_size(val)));
}
// -------------------- create/read version
inline uint8 mk_version(const uint16 major, const uint16 minor)
{ return (major & 0x07) << 5 | (minor & 0x1f); }
inline uint16 major_version(const uint8 version)
{ return (version >> 5) & 0x07; }
inline uint16 minor_version(const uint8 version)
{ return (version & 0x001f); }
// ---------------------------------------- convenience functions
const char *as_string(Chunk::Type t);
const char *as_string(Chunk::Entity e);
const char *as_string(Chunk::Dim d);
const char *as_string(Chunk::Integer_Size d);
const char *as_string(Chunk::Float_Size d);
std::ostream& operator << ( std::ostream& _os, const Header& _h );
std::ostream& operator << ( std::ostream& _os, const Chunk::Header& _c );
//@}
} // namespace OMFormat
// -------------------- (re-)store header
template <> inline
size_t store( std::ostream& _os, const OMFormat::Header& _hdr, bool _swap)
{ return _hdr.store( _os, _swap ); }
template <> inline
size_t restore( std::istream& _is, OMFormat::Header& _hdr, bool _swap )
{ return _hdr.restore( _is, _swap ); }
// -------------------- (re-)store chunk header
template <> inline
size_t
store( std::ostream& _os, const OMFormat::Chunk::Header& _hdr, bool _swap)
{
OMFormat::uint16 val; val << _hdr;
return binary<uint16_t>::store( _os, val, _swap );
}
template <> inline
size_t
restore( std::istream& _is, OMFormat::Chunk::Header& _hdr, bool _swap )
{
OMFormat::uint16 val;
size_t bytes = binary<uint16_t>::restore( _is, val, _swap );
_hdr << val;
return bytes;
}
// -------------------- (re-)store integer with wanted number of bits (bytes)
typedef GenProg::TrueType t_signed;
typedef GenProg::FalseType t_unsigned;
// helper to store a an integer
template< typename T >
size_t
store( std::ostream& _os,
const T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_signed);
// helper to store a an unsigned integer
template< typename T >
size_t
store( std::ostream& _os,
const T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_unsigned);
/// Store an integer with a wanted number of bits
template< typename T >
inline
size_t
store( std::ostream& _os,
const T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap)
{
assert( OMFormat::is_integer( _val ) );
if ( OMFormat::is_signed( _val ) )
return store( _os, _val, _b, _swap, t_signed() );
return store( _os, _val, _b, _swap, t_unsigned() );
}
// helper to store a an integer
template< typename T > inline
size_t restore( std::istream& _is,
T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_signed);
// helper to store a an unsigned integer
template< typename T > inline
size_t restore( std::istream& _is,
T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_unsigned);
/// Restore an integer with a wanted number of bits
template< typename T >
inline
size_t
restore( std::istream& _is,
T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap)
{
assert( OMFormat::is_integer( _val ) );
if ( OMFormat::is_signed( _val ) )
return restore( _is, _val, _b, _swap, t_signed() );
return restore( _is, _val, _b, _swap, t_unsigned() );
}
//
// ---------------------------------------- storing vectors
template <typename VecT> inline
size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<2>,
bool _swap )
{
size_t bytes = store( _os, _vec[0], _swap );
bytes += store( _os, _vec[1], _swap );
return bytes;
}
template <typename VecT> inline
size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<3>,
bool _swap )
{
size_t bytes = store( _os, _vec[0], _swap );
bytes += store( _os, _vec[1], _swap );
bytes += store( _os, _vec[2], _swap );
return bytes;
}
template <typename VecT> inline
size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<4>,
bool _swap )
{
size_t bytes = store( _os, _vec[0], _swap );
bytes += store( _os, _vec[1], _swap );
bytes += store( _os, _vec[2], _swap );
bytes += store( _os, _vec[3], _swap );
return bytes;
}
template <typename VecT> inline
size_t store( std::ostream& _os, const VecT& _vec, GenProg::Int2Type<1>,
bool _swap )
{
return store( _os, _vec[0], _swap );
}
/// storing a vector type
template <typename VecT> inline
size_t vector_store( std::ostream& _os, const VecT& _vec, bool _swap )
{
return store( _os, _vec,
GenProg::Int2Type< vector_traits<VecT>::size_ >(),
_swap );
}
// ---------------------------------------- restoring vectors
template <typename VecT>
inline
size_t
restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<2>,
bool _swap )
{
size_t bytes = restore( _is, _vec[0], _swap );
bytes += restore( _is, _vec[1], _swap );
return bytes;
}
template <typename VecT>
inline
size_t
restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<3>,
bool _swap )
{
typedef typename vector_traits<VecT>::value_type scalar_type;
size_t bytes;
bytes = binary<scalar_type>::restore( _is, _vec[0], _swap );
bytes += binary<scalar_type>::restore( _is, _vec[1], _swap );
bytes += binary<scalar_type>::restore( _is, _vec[2], _swap );
return bytes;
}
template <typename VecT>
inline
size_t
restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<4>,
bool _swap )
{
typedef typename vector_traits<VecT>::value_type scalar_type;
size_t bytes;
bytes = binary<scalar_type>::restore( _is, _vec[0], _swap );
bytes += binary<scalar_type>::restore( _is, _vec[1], _swap );
bytes += binary<scalar_type>::restore( _is, _vec[2], _swap );
bytes += binary<scalar_type>::restore( _is, _vec[3], _swap );
return bytes;
}
template <typename VecT>
inline
size_t
restore( std::istream& _is, VecT& _vec, GenProg::Int2Type<1>,
bool _swap )
{
return restore( _is, _vec[0], _swap );
}
/// Restoring a vector type
template <typename VecT>
inline
size_t
vector_restore( std::istream& _is, VecT& _vec, bool _swap )
{
return restore( _is, _vec,
GenProg::Int2Type< vector_traits<VecT>::size_ >(),
_swap );
}
// ---------------------------------------- storing property names
template <>
inline
size_t store( std::ostream& _os, const OMFormat::Chunk::PropertyName& _pn,
bool _swap )
{
store( _os, _pn.size(), OMFormat::Chunk::Integer_8, _swap ); // 1 byte
if ( _pn.size() )
_os.write( _pn.c_str(), _pn.size() ); // size bytes
return _pn.size() + 1;
}
template <>
inline
size_t restore( std::istream& _is, OMFormat::Chunk::PropertyName& _pn,
bool _swap )
{
size_t size;
restore( _is, size, OMFormat::Chunk::Integer_8, _swap); // 1 byte
assert( OMFormat::Chunk::PropertyName::is_valid( size ) );
if ( size > 0 )
{
char buf[256];
_is.read( buf, size ); // size bytes
buf[size] = '\0';
_pn.resize(size);
_pn = buf;
}
return size+1;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
#endif
//=============================================================================
#if defined(OM_MISSING_HEADER_LIMITS)
# undef OM_MISSING_HEADER_LIMITS
#endif
//=============================================================================
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_IO_OMFORMAT_CC)
# define OPENMESH_IO_OMFORMAT_TEMPLATES
# include "OMFormatT.cc"
#endif
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,245 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#define OPENMESH_IO_OMFORMAT_CC
//== INCLUDES =================================================================
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <algorithm>
#include <iomanip>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
// helper to store a an integer
template< typename T >
size_t
store( std::ostream& _os,
const T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_signed)
{
assert( OMFormat::is_integer( _val ) );
switch( _b )
{
case OMFormat::Chunk::Integer_8:
{
OMFormat::int8 v = static_cast<OMFormat::int8>(_val);
return store( _os, v, _swap );
}
case OMFormat::Chunk::Integer_16:
{
OMFormat::int16 v = static_cast<OMFormat::int16>(_val);
return store( _os, v, _swap );
}
case OMFormat::Chunk::Integer_32:
{
OMFormat::int32 v = static_cast<OMFormat::int32>(_val);
return store( _os, v, _swap );
}
case OMFormat::Chunk::Integer_64:
{
OMFormat::int64 v = static_cast<OMFormat::int64>(_val);
return store( _os, v, _swap );
}
}
return 0;
}
// helper to store a an unsigned integer
template< typename T >
size_t
store( std::ostream& _os,
const T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_unsigned)
{
assert( OMFormat::is_integer( _val ) );
switch( _b )
{
case OMFormat::Chunk::Integer_8:
{
OMFormat::uint8 v = static_cast<OMFormat::uint8>(_val);
return store( _os, v, _swap );
}
case OMFormat::Chunk::Integer_16:
{
OMFormat::uint16 v = static_cast<OMFormat::uint16>(_val);
return store( _os, v, _swap );
}
case OMFormat::Chunk::Integer_32:
{
OMFormat::uint32 v = static_cast<OMFormat::uint32>(_val);
return store( _os, v, _swap );
}
case OMFormat::Chunk::Integer_64:
{
OMFormat::uint64 v = static_cast<OMFormat::uint64>(_val);
return store( _os, v, _swap );
}
}
return 0;
}
// helper to restore a an integer
template< typename T >
size_t
restore( std::istream& _is,
T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_signed)
{
assert( OMFormat::is_integer( _val ) );
size_t bytes = 0;
switch( _b )
{
case OMFormat::Chunk::Integer_8:
{
OMFormat::int8 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
break;
}
case OMFormat::Chunk::Integer_16:
{
OMFormat::int16 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
break;
}
case OMFormat::Chunk::Integer_32:
{
OMFormat::int32 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
break;
}
case OMFormat::Chunk::Integer_64:
{
OMFormat::int64 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
break;
}
}
return bytes;
}
// helper to restore a an unsigned integer
template< typename T >
size_t
restore( std::istream& _is,
T& _val,
OMFormat::Chunk::Integer_Size _b,
bool _swap,
t_unsigned)
{
assert( OMFormat::is_integer( _val ) );
size_t bytes = 0;
switch( _b )
{
case OMFormat::Chunk::Integer_8:
{
OMFormat::uint8 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
break;
}
case OMFormat::Chunk::Integer_16:
{
OMFormat::uint16 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
break;
}
case OMFormat::Chunk::Integer_32:
{
OMFormat::uint32 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
break;
}
case OMFormat::Chunk::Integer_64:
{
OMFormat::uint64 v;
bytes = restore( _is, v, _swap );
_val = static_cast<T>(v);
break;
}
}
return bytes;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,250 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OPENMESH_IO_OPTIONS_HH
#define OPENMESH_IO_OPTIONS_HH
//=== INCLUDES ================================================================
// OpenMesh
#include <OpenMesh/Core/System/config.h>
//== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/** \name Mesh Reading / Writing
Option for reader and writer modules.
*/
//@{
//-----------------------------------------------------------------------------
/** \brief Set options for reader/writer modules.
*
* The class is used in a twofold way.
* -# In combination with reader modules the class is used
* - to pass hints to the reading module, whether the input is
* binary and what byte ordering the binary data has
* - to retrieve information about the file contents after
* succesful reading.
* -# In combination with write modules the class gives directions to
* the writer module, whether to
* - use binary mode or not and what byte order to use
* - store one of the standard properties.
*
* The option are defined in \c Options::Flag as bit values and stored in
* an \c int value as a bitset.
*/
class Options
{
public:
typedef int enum_type;
typedef enum_type value_type;
/// Definitions of %Options for reading and writing. The options can be
/// or'ed.
enum Flag {
Default = 0x0000, ///< No options
Binary = 0x0001, ///< Set binary mode for r/w
MSB = 0x0002, ///< Assume big endian byte ordering
LSB = 0x0004, ///< Assume little endian byte ordering
Swap = 0x0008, ///< Swap byte order in binary mode
VertexNormal = 0x0010, ///< Has (r) / store (w) vertex normals
VertexColor = 0x0020, ///< Has (r) / store (w) vertex colors
VertexTexCoord = 0x0040, ///< Has (r) / store (w) texture coordinates
EdgeColor = 0x0080, ///< Has (r) / store (w) edge colors
FaceNormal = 0x0100, ///< Has (r) / store (w) face normals
FaceColor = 0x0200, ///< Has (r) / store (w) face colors
FaceTexCoord = 0x0400, ///< Has (r) / store (w) face texture coordinates
ColorAlpha = 0x0800, ///< Has (r) / store (w) alpha values for colors
ColorFloat = 0x1000, ///< Has (r) / store (w) float values for colors (currently only implemented for PLY and OFF files)
Custom = 0x2000 ///< Has (r) custom properties (currently only implemented in PLY Reader ASCII version)
};
public:
/// Default constructor
Options() : flags_( Default )
{ }
/// Copy constructor
Options(const Options& _opt) : flags_(_opt.flags_)
{ }
/// Initializing constructor setting a single option
Options(Flag _flg) : flags_( _flg)
{ }
/// Initializing constructor setting multiple options
Options(const value_type _flgs) : flags_( _flgs)
{ }
~Options()
{ }
/// Restore state after default constructor.
void cleanup(void)
{ flags_ = Default; }
/// Clear all bits.
void clear(void)
{ flags_ = 0; }
/// Returns true if all bits are zero.
bool is_empty(void) const { return !flags_; }
public:
//@{
/// Copy options defined in _rhs.
Options& operator = ( const Options& _rhs )
{ flags_ = _rhs.flags_; return *this; }
Options& operator = ( const value_type _rhs )
{ flags_ = _rhs; return *this; }
//@}
//@{
/// Unset options defined in _rhs.
Options& operator -= ( const value_type _rhs )
{ flags_ &= ~_rhs; return *this; }
Options& unset( const value_type _rhs)
{ return (*this -= _rhs); }
//@}
//@{
/// Set options defined in _rhs
Options& operator += ( const value_type _rhs )
{ flags_ |= _rhs; return *this; }
Options& set( const value_type _rhs)
{ return (*this += _rhs); }
//@}
public:
// Check if an option or several options are set.
bool check(const value_type _rhs) const
{
return (flags_ & _rhs)==_rhs;
}
bool is_binary() const { return check(Binary); }
bool vertex_has_normal() const { return check(VertexNormal); }
bool vertex_has_color() const { return check(VertexColor); }
bool vertex_has_texcoord() const { return check(VertexTexCoord); }
bool edge_has_color() const { return check(EdgeColor); }
bool face_has_normal() const { return check(FaceNormal); }
bool face_has_color() const { return check(FaceColor); }
bool face_has_texcoord() const { return check(FaceTexCoord); }
bool color_has_alpha() const { return check(ColorAlpha); }
bool color_is_float() const { return check(ColorFloat); }
/// Returns true if _rhs has the same options enabled.
bool operator == (const value_type _rhs) const
{ return flags_ == _rhs; }
/// Returns true if _rhs does not have the same options enabled.
bool operator != (const value_type _rhs) const
{ return flags_ != _rhs; }
/// Returns the option set.
operator value_type () const { return flags_; }
private:
bool operator && (const value_type _rhs) const;
value_type flags_;
};
//-----------------------------------------------------------------------------
//@}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,136 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#ifndef OPENMESH_SR_BINARY_HH
#define OPENMESH_SR_BINARY_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
// -------------------- STL
#include <typeinfo>
#include <stdexcept>
#include <sstream>
#include <numeric> // accumulate
// -------------------- OpenMesh
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
//-----------------------------------------------------------------------------
const static size_t UnknownSize(size_t(-1));
//-----------------------------------------------------------------------------
// struct binary, helper for storing/restoring
#define X \
std::ostringstream msg; \
msg << "Type not supported: " << typeid(value_type).name(); \
throw std::logic_error(msg.str())
/// \struct binary SR_binary.hh <OpenMesh/Core/IO/SR_binary.hh>
///
/// The struct defines how to store and restore the type T.
/// It's used by the OM reader/writer modules.
///
/// The following specialization are provided:
/// - Fundamental types except \c long \c double
/// - %OpenMesh vector types
/// - %OpenMesh::StatusInfo
/// - std::string (max. length 65535)
///
/// \todo Complete documentation of members
template < typename T > struct binary
{
typedef T value_type;
static const bool is_streamable = false;
static size_t size_of(void) { return UnknownSize; }
static size_t size_of(const value_type&) { return UnknownSize; }
static
size_t store( std::ostream& /* _os */,
const value_type& /* _v */,
bool /* _swap=false */)
{ X; return 0; }
static
size_t restore( std::istream& /* _is */,
value_type& /* _v */,
bool /* _swap=false */)
{ X; return 0; }
};
#undef X
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_SR_RBO_HH defined
//=============================================================================

View File

@ -0,0 +1,329 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#ifndef OPENMESH_SR_BINARY_SPEC_HH
#define OPENMESH_SR_BINARY_SPEC_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
// -------------------- STL
#include <iterator>
#include <string>
#if defined(OM_CC_GCC) && (OM_CC_VERSION < 30000)
# include <OpenMesh/Tools/Utils/NumLimitsT.hh>
#else
# include <limits>
#endif
#include <vector>
#include <stdexcept> // logic_error
#include <numeric> // accumulate
// -------------------- OpenMesh
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include <OpenMesh/Core/Mesh/Status.hh>
#include <OpenMesh/Core/IO/SR_types.hh>
#include <OpenMesh/Core/IO/SR_rbo.hh>
#include <OpenMesh/Core/IO/SR_binary.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
#ifndef DOXY_IGNORE_THIS
//-----------------------------------------------------------------------------
// struct binary, helper for storing/restoring
#define SIMPLE_BINARY( T ) \
template <> struct binary< T > { \
typedef T value_type; \
static const bool is_streamable = true; \
static size_t size_of(const value_type&) { return sizeof(value_type); } \
static size_t size_of(void) { return sizeof(value_type); } \
static size_t store( std::ostream& _os, const value_type& _val, \
bool _swap=false) { \
value_type tmp = _val; \
if (_swap) reverse_byte_order(tmp); \
_os.write( (const char*)&tmp, sizeof(value_type) ); \
return _os.good() ? sizeof(value_type) : 0; \
} \
\
static size_t restore( std::istream& _is, value_type& _val, \
bool _swap=false) { \
_is.read( (char*)&_val, sizeof(value_type) ); \
if (_swap) reverse_byte_order(_val); \
return _is.good() ? sizeof(value_type) : 0; \
} \
}
SIMPLE_BINARY(bool);
//SIMPLE_BINARY(int);
// Why is this needed? Should not be used as not 32 bit compatible
//SIMPLE_BINARY(unsigned long);
SIMPLE_BINARY(float);
SIMPLE_BINARY(double);
SIMPLE_BINARY(long double);
SIMPLE_BINARY(char);
SIMPLE_BINARY(int8_t);
SIMPLE_BINARY(int16_t);
SIMPLE_BINARY(int32_t);
SIMPLE_BINARY(int64_t);
SIMPLE_BINARY(uint8_t);
SIMPLE_BINARY(uint16_t);
SIMPLE_BINARY(uint32_t);
SIMPLE_BINARY(uint64_t);
#undef SIMPLE_BINARY
// For unsigned long which is of size 64 bit on 64 bit
// architectures: convert into 32 bit unsigned integer value
// in order to stay compatible between 32/64 bit architectures.
// This allows cross reading BUT forbids storing unsigned longs
// as data type since higher order word (4 bytes) will be truncated.
// Does not work in case the data type that is to be stored
// exceeds the value range of unsigned int in size, which is improbable...
#define SIMPLE_BINARY( T ) \
template <> struct binary< T > { \
typedef T value_type; \
static const bool is_streamable = true; \
static size_t size_of(const value_type&) { return sizeof(value_type); } \
static size_t size_of(void) { return sizeof(value_type); } \
static size_t store( std::ostream& _os, const value_type& _val, \
bool _swap=false) { \
value_type tmp = _val; \
if (_swap) reverse_byte_order(tmp); \
/* Convert unsigned long to unsigned int for compatibility reasons */ \
unsigned int t1 = static_cast<unsigned int>(tmp); \
_os.write( (const char*)&t1, sizeof(unsigned int) ); \
return _os.good() ? sizeof(unsigned int) : 0; \
} \
\
static size_t restore( std::istream& _is, value_type& _val, \
bool _swap=false) { \
unsigned int t1; \
_is.read( (char*)&t1, sizeof(unsigned int) ); \
_val = t1; \
if (_swap) reverse_byte_order(_val); \
return _is.good() ? sizeof(unsigned int) : 0; \
} \
}
SIMPLE_BINARY(unsigned long);
#undef SIMPLE_BINARY
#define VECTORT_BINARY( T ) \
template <> struct binary< T > { \
typedef T value_type; \
static const bool is_streamable = true; \
static size_t size_of(void) { return sizeof(value_type); } \
static size_t size_of(const value_type&) { return size_of(); } \
static size_t store( std::ostream& _os, const value_type& _val, \
bool _swap=false) { \
value_type tmp = _val; \
size_t i, b = size_of(_val), N = value_type::size_; \
if (_swap) for (i=0; i<N; ++i) \
reverse_byte_order( tmp[i] ); \
_os.write( (const char*)&tmp[0], b ); \
return _os.good() ? b : 0; \
} \
\
static size_t restore( std::istream& _is, value_type& _val, \
bool _swap=false) { \
size_t i, N=value_type::size_; \
size_t b = N * sizeof(value_type::value_type); \
_is.read( (char*)&_val[0], b ); \
if (_swap) for (i=0; i<N; ++i) \
reverse_byte_order( _val[i] ); \
return _is.good() ? b : 0; \
} \
}
#define VECTORTS_BINARY( N ) \
VECTORT_BINARY( Vec##N##c ); \
VECTORT_BINARY( Vec##N##uc ); \
VECTORT_BINARY( Vec##N##s ); \
VECTORT_BINARY( Vec##N##us ); \
VECTORT_BINARY( Vec##N##i ); \
VECTORT_BINARY( Vec##N##ui ); \
VECTORT_BINARY( Vec##N##f ); \
VECTORT_BINARY( Vec##N##d );
VECTORTS_BINARY( 1 )
VECTORTS_BINARY( 2 )
VECTORTS_BINARY( 3 )
VECTORTS_BINARY( 4 )
VECTORTS_BINARY( 6 )
#undef VECTORTS_BINARY
#undef VECTORT_BINARY
template <> struct binary< std::string > {
typedef std::string value_type;
typedef uint16_t length_t;
static const bool is_streamable = true;
static size_t size_of() { return UnknownSize; }
static size_t size_of(const value_type &_v)
{ return sizeof(length_t) + _v.size(); }
static
size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
{
#if defined(OM_CC_GCC) && (OM_CC_VERSION < 30000)
if (_v.size() < Utils::NumLimitsT<length_t>::max() )
#else
if (_v.size() < std::numeric_limits<length_t>::max() )
#endif
{
length_t len = length_t(_v.size());
size_t bytes = binary<length_t>::store( _os, len, _swap );
_os.write( _v.data(), len );
return _os.good() ? len+bytes : 0;
}
throw std::runtime_error("Cannot store string longer than 64Kb");
}
static
size_t restore(std::istream& _is, value_type& _val, bool _swap=false)
{
length_t len;
size_t bytes = binary<length_t>::restore( _is, len, _swap );
_val.resize(len);
_is.read( const_cast<char*>(_val.data()), len );
return _is.good() ? (len+bytes) : 0;
}
};
template <> struct binary<OpenMesh::Attributes::StatusInfo>
{
typedef OpenMesh::Attributes::StatusInfo value_type;
typedef value_type::value_type status_t;
static const bool is_streamable = true;
static size_t size_of() { return sizeof(status_t); }
static size_t size_of(const value_type&) { return size_of(); }
static size_t n_bytes(size_t _n_elem)
{ return _n_elem*sizeof(status_t); }
static
size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
{
status_t v=_v.bits();
return binary<status_t>::store(_os, v, _swap);
}
static
size_t restore( std::istream& _os, value_type& _v, bool _swap=false)
{
status_t v;
size_t b = binary<status_t>::restore(_os, v, _swap);
_v.set_bits(v);
return b;
}
};
//-----------------------------------------------------------------------------
// std::vector<T> specializations for struct binary<>
template <typename T>
struct FunctorStore {
FunctorStore( std::ostream& _os, bool _swap) : os_(_os), swap_(_swap) { }
size_t operator () ( size_t _v1, const T& _s2 )
{ return _v1+binary<T>::store(os_, _s2, swap_ ); }
std::ostream& os_;
bool swap_;
};
template <typename T>
struct FunctorRestore {
FunctorRestore( std::istream& _is, bool _swap) : is_(_is), swap_(_swap) { }
size_t operator () ( size_t _v1, T& _s2 )
{ return _v1+binary<T>::restore(is_, _s2, swap_ ); }
std::istream& is_;
bool swap_;
};
#include <OpenMesh/Core/IO/SR_binary_vector_of_fundamentals.inl>
#include <OpenMesh/Core/IO/SR_binary_vector_of_string.inl>
#include <OpenMesh/Core/IO/SR_binary_vector_of_bool.inl>
// ----------------------------------------------------------------------------
#endif // DOXY_IGNORE_THIS
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_SR_BINARY_SPEC_HH defined
//=============================================================================

View File

@ -0,0 +1,98 @@
template <> struct binary< std::vector<bool> >
{
typedef std::vector< bool > value_type;
typedef value_type::value_type elem_type;
static const bool is_streamable = true;
static size_t size_of(void) { return UnknownSize; }
static size_t size_of(const value_type& _v)
{
return _v.size() / 8 + ((_v.size() % 8)!=0);
}
static
size_t store( std::ostream& _ostr, const value_type& _v, bool )
{
size_t bytes = 0;
size_t N = _v.size() / 8;
size_t R = _v.size() % 8;
size_t idx; // element index
unsigned char bits; // bitset
for (idx=0; idx < N; ++idx)
{
bits = static_cast<unsigned char>(_v[idx])
| (static_cast<unsigned char>(_v[idx+1]) << 1)
| (static_cast<unsigned char>(_v[idx+2]) << 2)
| (static_cast<unsigned char>(_v[idx+3]) << 3)
| (static_cast<unsigned char>(_v[idx+4]) << 4)
| (static_cast<unsigned char>(_v[idx+5]) << 5)
| (static_cast<unsigned char>(_v[idx+6]) << 6)
| (static_cast<unsigned char>(_v[idx+7]) << 7);
_ostr << bits;
}
bytes = N;
if (R)
{
bits = 0;
switch(R)
{
case 7: bits |= (static_cast<unsigned char>(_v[idx+6]) << 6);
case 6: bits |= (static_cast<unsigned char>(_v[idx+5]) << 5);
case 5: bits |= (static_cast<unsigned char>(_v[idx+4]) << 4);
case 4: bits |= (static_cast<unsigned char>(_v[idx+3]) << 3);
case 3: bits |= (static_cast<unsigned char>(_v[idx+2]) << 2);
case 2: bits |= (static_cast<unsigned char>(_v[idx+1]) << 1);
case 1: bits |= static_cast<unsigned char>(_v[idx+0]);
}
_ostr << bits;
++bytes;
}
assert( bytes == size_of(_v) );
return bytes;
}
static
size_t restore( std::istream& _istr, value_type& _v, bool )
{
size_t bytes = 0;
size_t N = _v.size() / 8;
size_t R = _v.size() % 8;
size_t idx; // element index
unsigned char bits; // bitset
for (idx=0; idx < N; ++idx)
{
_istr >> bits;
_v[idx+0] = ((bits & 0x01)!=0);
_v[idx+1] = ((bits & 0x02)!=0);
_v[idx+2] = ((bits & 0x04)!=0);
_v[idx+3] = ((bits & 0x08)!=0);
_v[idx+4] = ((bits & 0x10)!=0);
_v[idx+5] = ((bits & 0x20)!=0);
_v[idx+6] = ((bits & 0x40)!=0);
_v[idx+7] = ((bits & 0x80)!=0);
}
bytes = N;
if (R)
{
_istr >> bits;
for(; idx < _v.size(); ++idx)
_v[idx] = (bits & (1 << (idx%8)))!=0;
++bytes;
}
return bytes;
}
};

View File

@ -0,0 +1,53 @@
#define BINARY_VECTOR( T ) \
template <> struct binary< std::vector< T > > { \
typedef std::vector< T > value_type; \
typedef value_type::value_type elem_type; \
\
static const bool is_streamable = true; \
\
static size_t size_of(void) \
{ return IO::UnknownSize; } \
\
static size_t size_of(const value_type& _v) \
{ return sizeof(elem_type)*_v.size(); } \
\
static \
size_t store(std::ostream& _os, const value_type& _v, bool _swap=false) { \
size_t bytes=0; \
\
if (_swap) \
bytes = std::accumulate( _v.begin(), _v.end(), bytes, \
FunctorStore<elem_type>(_os,_swap) ); \
else { \
bytes = size_of(_v); \
_os.write( reinterpret_cast<const char*>(&_v[0]), bytes ); \
} \
return _os.good() ? bytes : 0; \
} \
\
static size_t restore(std::istream& _is, value_type& _v, bool _swap=false) { \
size_t bytes=0; \
\
if ( _swap) \
bytes = std::accumulate( _v.begin(), _v.end(), size_t(0), \
FunctorRestore<elem_type>(_is, _swap) ); \
else \
{ \
bytes = size_of(_v); \
_is.read( reinterpret_cast<char*>(&_v[0]), bytes ); \
} \
return _is.good() ? bytes : 0; \
} \
}
BINARY_VECTOR( short );
BINARY_VECTOR( unsigned short );
BINARY_VECTOR( int );
BINARY_VECTOR( unsigned int );
BINARY_VECTOR( long );
BINARY_VECTOR( unsigned long );
BINARY_VECTOR( float );
BINARY_VECTOR( double );
#undef BINARY_VECTOR

View File

@ -0,0 +1,39 @@
template <> struct binary< std::vector< std::string > >
{
// struct binary interface
typedef std::vector< std::string > value_type;
typedef value_type::value_type elem_type;
static const bool is_streamable = true;
// Helper
struct Sum
{
size_t operator() ( size_t _v1, const elem_type& _s2 )
{ return _v1 + binary<elem_type>::size_of(_s2); }
};
// struct binary interface
static size_t size_of(void) { return UnknownSize; }
static size_t size_of(const value_type& _v)
{ return std::accumulate( _v.begin(), _v.end(), size_t(0), Sum() ); }
static
size_t store(std::ostream& _os, const value_type& _v, bool _swap=false)
{
return std::accumulate( _v.begin(), _v.end(), size_t(0),
FunctorStore<elem_type>(_os, _swap) );
}
static
size_t restore(std::istream& _is, value_type& _v, bool _swap=false)
{
return std::accumulate( _v.begin(), _v.end(), size_t(0),
FunctorRestore<elem_type>(_is, _swap) );
}
};

View File

@ -0,0 +1,256 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#ifndef OPENMESH_SR_RBO_HH
#define OPENMESH_SR_RBO_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
// -------------------- STL
#if defined(OM_CC_MIPS)
# include <stdio.h> // size_t
#else
# include <cstdio> // size_t
#endif
#include <algorithm>
#include <typeinfo>
// -------------------- OpenMesh
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/IO/SR_types.hh>
#include <OpenMesh/Core/Utils/GenProg.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
/** \name Handling binary input/output.
These functions take care of swapping bytes to get the right Endian.
*/
//@{
//-----------------------------------------------------------------------------
/** this does not compile for g++3.4 and higher, hence we comment the
function body which will result in a linker error */
template < size_t N > inline
void _reverse_byte_order_N(uint8_t* _val);
template <> inline
void _reverse_byte_order_N<1>(uint8_t* /*_val*/) { }
template <> inline
void _reverse_byte_order_N<2>(uint8_t* _val)
{
_val[0] ^= _val[1]; _val[1] ^= _val[0]; _val[0] ^= _val[1];
}
template <> inline
void _reverse_byte_order_N<4>(uint8_t* _val)
{
_val[0] ^= _val[3]; _val[3] ^= _val[0]; _val[0] ^= _val[3]; // 0 <-> 3
_val[1] ^= _val[2]; _val[2] ^= _val[1]; _val[1] ^= _val[2]; // 1 <-> 2
}
template <> inline
void _reverse_byte_order_N<8>(uint8_t* _val)
{
_val[0] ^= _val[7]; _val[7] ^= _val[0]; _val[0] ^= _val[7]; // 0 <-> 7
_val[1] ^= _val[6]; _val[6] ^= _val[1]; _val[1] ^= _val[6]; // 1 <-> 6
_val[2] ^= _val[5]; _val[5] ^= _val[2]; _val[2] ^= _val[5]; // 2 <-> 5
_val[3] ^= _val[4]; _val[4] ^= _val[3]; _val[3] ^= _val[4]; // 3 <-> 4
}
template <> inline
void _reverse_byte_order_N<12>(uint8_t* _val)
{
_val[0] ^= _val[11]; _val[11] ^= _val[0]; _val[0] ^= _val[11]; // 0 <-> 11
_val[1] ^= _val[10]; _val[10] ^= _val[1]; _val[1] ^= _val[10]; // 1 <-> 10
_val[2] ^= _val[ 9]; _val[ 9] ^= _val[2]; _val[2] ^= _val[ 9]; // 2 <-> 9
_val[3] ^= _val[ 8]; _val[ 8] ^= _val[3]; _val[3] ^= _val[ 8]; // 3 <-> 8
_val[4] ^= _val[ 7]; _val[ 7] ^= _val[4]; _val[4] ^= _val[ 7]; // 4 <-> 7
_val[5] ^= _val[ 6]; _val[ 6] ^= _val[5]; _val[5] ^= _val[ 6]; // 5 <-> 6
}
template <> inline
void _reverse_byte_order_N<16>(uint8_t* _val)
{
_reverse_byte_order_N<8>(_val);
_reverse_byte_order_N<8>(_val+8);
std::swap(*(uint64_t*)_val, *(((uint64_t*)_val)+1));
}
//-----------------------------------------------------------------------------
// wrapper for byte reordering
// reverting pointers makes no sense, hence forbid it.
/** this does not compile for g++3.4 and higher, hence we comment the
function body which will result in a linker error */
template <typename T> inline T* reverse_byte_order(T* t);
// Should never reach this point. If so, then some operator were not
// overloaded. Especially check for IO::binary<> specialization on
// custom data types.
inline void compile_time_error__no_fundamental_type()
{
// we should never reach this point
assert(false);
}
// default action for byte reversal: cause an error to avoid
// surprising behaviour!
template <typename T> T& reverse_byte_order( T& _t )
{
omerr() << "Not defined for type " << typeid(T).name() << std::endl;
compile_time_error__no_fundamental_type();
return _t;
}
template <> inline bool& reverse_byte_order(bool & _t) { return _t; }
template <> inline char& reverse_byte_order(char & _t) { return _t; }
#if defined(OM_CC_GCC)
template <> inline signed char& reverse_byte_order(signed char & _t) { return _t; }
#endif
template <> inline uchar& reverse_byte_order(uchar& _t) { return _t; }
// Instead do specializations for the necessary types
#define REVERSE_FUNDAMENTAL_TYPE( T ) \
template <> inline T& reverse_byte_order( T& _t ) {\
_reverse_byte_order_N<sizeof(T)>( reinterpret_cast<uint8_t*>(&_t) ); \
return _t; \
}
// REVERSE_FUNDAMENTAL_TYPE(bool)
// REVERSE_FUNDAMENTAL_TYPE(char)
// REVERSE_FUNDAMENTAL_TYPE(uchar)
REVERSE_FUNDAMENTAL_TYPE(int16_t)
REVERSE_FUNDAMENTAL_TYPE(uint16_t)
// REVERSE_FUNDAMENTAL_TYPE(int)
// REVERSE_FUNDAMENTAL_TYPE(uint)
REVERSE_FUNDAMENTAL_TYPE(unsigned long)
REVERSE_FUNDAMENTAL_TYPE(int32_t)
REVERSE_FUNDAMENTAL_TYPE(uint32_t)
REVERSE_FUNDAMENTAL_TYPE(int64_t)
REVERSE_FUNDAMENTAL_TYPE(uint64_t)
REVERSE_FUNDAMENTAL_TYPE(float)
REVERSE_FUNDAMENTAL_TYPE(double)
REVERSE_FUNDAMENTAL_TYPE(long double)
#undef REVERSE_FUNDAMENTAL_TYPE
#if 0
#define REVERSE_VECTORT_TYPE( T ) \
template <> inline T& reverse_byte_order(T& _v) {\
for (size_t i; i< T::size_; ++i) \
_reverse_byte_order_N< sizeof(T::value_type) >( reinterpret_cast<uint8_t*>(&_v[i])); \
return _v; \
}
#define REVERSE_VECTORT_TYPES( N ) \
REVERSE_VECTORT_TYPE( Vec##N##c ) \
REVERSE_VECTORT_TYPE( Vec##N##uc ) \
REVERSE_VECTORT_TYPE( Vec##N##s ) \
REVERSE_VECTORT_TYPE( Vec##N##us ) \
REVERSE_VECTORT_TYPE( Vec##N##i ) \
REVERSE_VECTORT_TYPE( Vec##N##ui ) \
REVERSE_VECTORT_TYPE( Vec##N##f ) \
REVERSE_VECTORT_TYPE( Vec##N##d ) \
REVERSE_VECTORT_TYPES(1)
REVERSE_VECTORT_TYPES(2)
REVERSE_VECTORT_TYPES(3)
REVERSE_VECTORT_TYPES(4)
REVERSE_VECTORT_TYPES(6)
#undef REVERSE_VECTORT_TYPES
#undef REVERSE_VECTORT_TYPE
#endif
template <typename T> inline
T reverse_byte_order(const T& a)
{
compile_timer_error__const_means_const(a);
return a;
}
//@}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_SR_RBO_HH defined
//=============================================================================

View File

@ -0,0 +1,72 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#ifndef OPENMESH_SR_STORE_HH
#define OPENMESH_SR_STORE_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/SR_types.hh>
#include <OpenMesh/Core/IO/SR_rbo.hh>
#include <OpenMesh/Core/IO/SR_binary.hh>
#include <OpenMesh/Core/IO/SR_binary_spec.hh>
#include <OpenMesh/Core/IO/StoreRestore.hh>
//=============================================================================
#endif // OPENMESH_STORE_HH defined
//=============================================================================

View File

@ -0,0 +1,112 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#ifndef OPENMESH_SR_TYPES_HH
#define OPENMESH_SR_TYPES_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
/** \name Handling binary input/output.
These functions take care of swapping bytes to get the right Endian.
*/
//@{
//-----------------------------------------------------------------------------
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned long ulong;
typedef signed char int8_t; typedef unsigned char uint8_t;
typedef short int16_t; typedef unsigned short uint16_t;
// Int should be 32 bit on all archs.
// long is 32 under windows but 64 under unix 64 bit
typedef int int32_t; typedef unsigned int uint32_t;
#if defined(OM_CC_MSVC)
typedef __int64 int64_t; typedef unsigned __int64 uint64_t;
#else
typedef long long int64_t; typedef unsigned long long uint64_t;
#endif
typedef float float32_t;
typedef double float64_t;
typedef uint8_t rgb_t[3];
typedef uint8_t rgba_t[4];
//@}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_MESHREADER_HH defined
//=============================================================================

View File

@ -0,0 +1,117 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Helper Functions for binary reading / writing
//
//=============================================================================
#ifndef OPENMESH_STORERESTORE_HH
#define OPENMESH_STORERESTORE_HH
//== INCLUDES =================================================================
#include <stdexcept>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/SR_binary.hh>
#include <OpenMesh/Core/IO/SR_binary_spec.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
/** \name Handling binary input/output.
These functions take care of swapping bytes to get the right Endian.
*/
//@{
//-----------------------------------------------------------------------------
// StoreRestore definitions
template <typename T> inline
bool is_streamable(void)
{ return binary< T >::is_streamable; }
template <typename T> inline
bool is_streamable( const T& )
{ return binary< T >::is_streamable; }
template <typename T> inline
size_t size_of( const T& _v )
{ return binary< T >::size_of(_v); }
template <typename T> inline
size_t size_of(void)
{ return binary< T >::size_of(); }
template <typename T> inline
size_t store( std::ostream& _os, const T& _v, bool _swap=false)
{ return binary< T >::store( _os, _v, _swap ); }
template <typename T> inline
size_t restore( std::istream& _is, T& _v, bool _swap=false)
{ return binary< T >::restore( _is, _v, _swap ); }
//@}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_MESHREADER_HH defined
//=============================================================================

View File

@ -0,0 +1,165 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements the baseclass for MeshWriter exporter modules
//
//=============================================================================
#ifndef __BASEEXPORTER_HH__
#define __BASEEXPORTER_HH__
//=== INCLUDES ================================================================
// STL
#include <vector>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include <OpenMesh/Core/Mesh/BaseKernel.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== EXPORTER ================================================================
/**
Base class for exporter modules.
The exporter modules provide an interface between the writer modules and
the target data structure.
*/
class OPENMESHDLLEXPORT BaseExporter
{
public:
virtual ~BaseExporter() { }
// get vertex data
virtual Vec3f point(VertexHandle _vh) const = 0;
virtual Vec3f normal(VertexHandle _vh) const = 0;
virtual Vec3uc color(VertexHandle _vh) const = 0;
virtual Vec4uc colorA(VertexHandle _vh) const = 0;
virtual Vec3ui colori(VertexHandle _vh) const = 0;
virtual Vec4ui colorAi(VertexHandle _vh) const = 0;
virtual Vec3f colorf(VertexHandle _vh) const = 0;
virtual Vec4f colorAf(VertexHandle _vh) const = 0;
virtual Vec2f texcoord(VertexHandle _vh) const = 0;
virtual Vec2f texcoord(HalfedgeHandle _heh) const = 0;
// get face data
virtual unsigned int
get_vhandles(FaceHandle _fh,
std::vector<VertexHandle>& _vhandles) const=0;
///
/// \brief getHeh returns the HalfEdgeHandle that belongs to the face
/// specified by _fh and has a toVertexHandle that corresponds to _vh.
/// \param _fh FaceHandle that is used to search for the half edge handle
/// \param _vh to_vertex_handle of the searched heh
/// \return HalfEdgeHandle or invalid HalfEdgeHandle if none is found.
///
virtual HalfedgeHandle getHeh(FaceHandle _fh, VertexHandle _vh) const = 0;
virtual unsigned int
get_face_texcoords(std::vector<Vec2f>& _hehandles) const = 0;
virtual Vec3f normal(FaceHandle _fh) const = 0;
virtual Vec3uc color (FaceHandle _fh) const = 0;
virtual Vec4uc colorA(FaceHandle _fh) const = 0;
virtual Vec3ui colori(FaceHandle _fh) const = 0;
virtual Vec4ui colorAi(FaceHandle _fh) const = 0;
virtual Vec3f colorf(FaceHandle _fh) const = 0;
virtual Vec4f colorAf(FaceHandle _fh) const = 0;
// get edge data
virtual Vec3uc color(EdgeHandle _eh) const = 0;
virtual Vec4uc colorA(EdgeHandle _eh) const = 0;
virtual Vec3ui colori(EdgeHandle _eh) const = 0;
virtual Vec4ui colorAi(EdgeHandle _eh) const = 0;
virtual Vec3f colorf(EdgeHandle _eh) const = 0;
virtual Vec4f colorAf(EdgeHandle _eh) const = 0;
// get reference to base kernel
virtual const BaseKernel* kernel() { return 0; }
// query number of faces, vertices, normals, texcoords
virtual size_t n_vertices() const = 0;
virtual size_t n_faces() const = 0;
virtual size_t n_edges() const = 0;
// property information
virtual bool is_triangle_mesh() const { return false; }
virtual bool has_vertex_normals() const { return false; }
virtual bool has_vertex_colors() const { return false; }
virtual bool has_vertex_texcoords() const { return false; }
virtual bool has_edge_colors() const { return false; }
virtual bool has_face_normals() const { return false; }
virtual bool has_face_colors() const { return false; }
};
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,338 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements an exporter module for arbitrary OpenMesh meshes
//
//=============================================================================
#ifndef __EXPORTERT_HH__
#define __EXPORTERT_HH__
//=== INCLUDES ================================================================
// C++
#include <vector>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include <OpenMesh/Core/Utils/GenProg.hh>
#include <OpenMesh/Core/Utils/vector_cast.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== EXPORTER CLASS ==========================================================
/**
* This class template provides an exporter module for OpenMesh meshes.
*/
template <class Mesh>
class ExporterT : public BaseExporter
{
public:
// Constructor
ExporterT(const Mesh& _mesh) : mesh_(_mesh) {}
// get vertex data
Vec3f point(VertexHandle _vh) const
{
return vector_cast<Vec3f>(mesh_.point(_vh));
}
Vec3f normal(VertexHandle _vh) const
{
return (mesh_.has_vertex_normals()
? vector_cast<Vec3f>(mesh_.normal(_vh))
: Vec3f(0.0f, 0.0f, 0.0f));
}
Vec3uc color(VertexHandle _vh) const
{
return (mesh_.has_vertex_colors()
? color_cast<Vec3uc>(mesh_.color(_vh))
: Vec3uc(0, 0, 0));
}
Vec4uc colorA(VertexHandle _vh) const
{
return (mesh_.has_vertex_colors()
? color_cast<Vec4uc>(mesh_.color(_vh))
: Vec4uc(0, 0, 0, 0));
}
Vec3ui colori(VertexHandle _vh) const
{
return (mesh_.has_vertex_colors()
? color_cast<Vec3ui>(mesh_.color(_vh))
: Vec3ui(0, 0, 0));
}
Vec4ui colorAi(VertexHandle _vh) const
{
return (mesh_.has_vertex_colors()
? color_cast<Vec4ui>(mesh_.color(_vh))
: Vec4ui(0, 0, 0, 0));
}
Vec3f colorf(VertexHandle _vh) const
{
return (mesh_.has_vertex_colors()
? color_cast<Vec3f>(mesh_.color(_vh))
: Vec3f(0, 0, 0));
}
Vec4f colorAf(VertexHandle _vh) const
{
return (mesh_.has_vertex_colors()
? color_cast<Vec4f>(mesh_.color(_vh))
: Vec4f(0, 0, 0, 0));
}
Vec2f texcoord(VertexHandle _vh) const
{
#if defined(OM_CC_GCC) && (OM_CC_VERSION<30000)
// Workaround!
// gcc 2.95.3 exits with internal compiler error at the
// code below!??? **)
if (mesh_.has_vertex_texcoords2D())
return vector_cast<Vec2f>(mesh_.texcoord2D(_vh));
return Vec2f(0.0f, 0.0f);
#else // **)
return (mesh_.has_vertex_texcoords2D()
? vector_cast<Vec2f>(mesh_.texcoord2D(_vh))
: Vec2f(0.0f, 0.0f));
#endif
}
Vec2f texcoord(HalfedgeHandle _heh) const
{
return (mesh_.has_halfedge_texcoords2D()
? vector_cast<Vec2f>(mesh_.texcoord2D(_heh))
: Vec2f(0.0f, 0.0f));
}
// get edge data
Vec3uc color(EdgeHandle _eh) const
{
return (mesh_.has_edge_colors()
? color_cast<Vec3uc>(mesh_.color(_eh))
: Vec3uc(0, 0, 0));
}
Vec4uc colorA(EdgeHandle _eh) const
{
return (mesh_.has_edge_colors()
? color_cast<Vec4uc>(mesh_.color(_eh))
: Vec4uc(0, 0, 0, 0));
}
Vec3ui colori(EdgeHandle _eh) const
{
return (mesh_.has_edge_colors()
? color_cast<Vec3ui>(mesh_.color(_eh))
: Vec3ui(0, 0, 0));
}
Vec4ui colorAi(EdgeHandle _eh) const
{
return (mesh_.has_edge_colors()
? color_cast<Vec4ui>(mesh_.color(_eh))
: Vec4ui(0, 0, 0, 0));
}
Vec3f colorf(EdgeHandle _eh) const
{
return (mesh_.has_vertex_colors()
? color_cast<Vec3f>(mesh_.color(_eh))
: Vec3f(0, 0, 0));
}
Vec4f colorAf(EdgeHandle _eh) const
{
return (mesh_.has_vertex_colors()
? color_cast<Vec4f>(mesh_.color(_eh))
: Vec4f(0, 0, 0, 0));
}
// get face data
unsigned int get_vhandles(FaceHandle _fh,
std::vector<VertexHandle>& _vhandles) const
{
unsigned int count(0);
_vhandles.clear();
for (typename Mesh::CFVIter fv_it=mesh_.cfv_iter(_fh); fv_it.is_valid(); ++fv_it)
{
_vhandles.push_back(*fv_it);
++count;
}
return count;
}
unsigned int get_face_texcoords(std::vector<Vec2f>& _hehandles) const
{
unsigned int count(0);
_hehandles.clear();
for(typename Mesh::CHIter he_it=mesh_.halfedges_begin();
he_it != mesh_.halfedges_end(); ++he_it)
{
_hehandles.push_back(vector_cast<Vec2f>(mesh_.texcoord2D( *he_it)));
++count;
}
return count;
}
HalfedgeHandle getHeh(FaceHandle _fh, VertexHandle _vh) const
{
typename Mesh::ConstFaceHalfedgeIter fh_it;
for(fh_it = mesh_.cfh_iter(_fh); fh_it.is_valid();++fh_it)
{
if(mesh_.to_vertex_handle(*fh_it) == _vh)
return *fh_it;
}
return *fh_it;
}
Vec3f normal(FaceHandle _fh) const
{
return (mesh_.has_face_normals()
? vector_cast<Vec3f>(mesh_.normal(_fh))
: Vec3f(0.0f, 0.0f, 0.0f));
}
Vec3uc color(FaceHandle _fh) const
{
return (mesh_.has_face_colors()
? color_cast<Vec3uc>(mesh_.color(_fh))
: Vec3uc(0, 0, 0));
}
Vec4uc colorA(FaceHandle _fh) const
{
return (mesh_.has_face_colors()
? color_cast<Vec4uc>(mesh_.color(_fh))
: Vec4uc(0, 0, 0, 0));
}
Vec3ui colori(FaceHandle _fh) const
{
return (mesh_.has_face_colors()
? color_cast<Vec3ui>(mesh_.color(_fh))
: Vec3ui(0, 0, 0));
}
Vec4ui colorAi(FaceHandle _fh) const
{
return (mesh_.has_face_colors()
? color_cast<Vec4ui>(mesh_.color(_fh))
: Vec4ui(0, 0, 0, 0));
}
Vec3f colorf(FaceHandle _fh) const
{
return (mesh_.has_vertex_colors()
? color_cast<Vec3f>(mesh_.color(_fh))
: Vec3f(0, 0, 0));
}
Vec4f colorAf(FaceHandle _fh) const
{
return (mesh_.has_vertex_colors()
? color_cast<Vec4f>(mesh_.color(_fh))
: Vec4f(0, 0, 0, 0));
}
virtual const BaseKernel* kernel() { return &mesh_; }
// query number of faces, vertices, normals, texcoords
size_t n_vertices() const { return mesh_.n_vertices(); }
size_t n_faces() const { return mesh_.n_faces(); }
size_t n_edges() const { return mesh_.n_edges(); }
// property information
bool is_triangle_mesh() const
{ return Mesh::is_triangles(); }
bool has_vertex_normals() const { return mesh_.has_vertex_normals(); }
bool has_vertex_colors() const { return mesh_.has_vertex_colors(); }
bool has_vertex_texcoords() const { return mesh_.has_vertex_texcoords2D(); }
bool has_edge_colors() const { return mesh_.has_edge_colors(); }
bool has_face_normals() const { return mesh_.has_face_normals(); }
bool has_face_colors() const { return mesh_.has_face_colors(); }
private:
const Mesh& mesh_;
};
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,205 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements the baseclass for IOManager importer modules
//
//=============================================================================
#ifndef __BASEIMPORTER_HH__
#define __BASEIMPORTER_HH__
//=== INCLUDES ================================================================
// STL
#include <vector>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include <OpenMesh/Core/Mesh/BaseKernel.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/** Base class for importer modules. Importer modules provide an
* interface between the loader modules and the target data
* structure. This is basically a wrapper providing virtual versions
* for the required mesh functions.
*/
class OPENMESHDLLEXPORT BaseImporter
{
public:
// base class needs virtual destructor
virtual ~BaseImporter() {}
// add a vertex with coordinate \c _point
virtual VertexHandle add_vertex(const Vec3f& _point) = 0;
// add a vertex without coordinate. Use set_point to set the position deferred
virtual VertexHandle add_vertex() = 0;
// add a face with indices _indices refering to vertices
typedef std::vector<VertexHandle> VHandles;
virtual FaceHandle add_face(const VHandles& _indices) = 0;
// add texture coordinates per face, _vh references the first texcoord
virtual void add_face_texcoords( FaceHandle _fh, VertexHandle _vh, const std::vector<Vec2f>& _face_texcoords) = 0;
// add texture 3d coordinates per face, _vh references the first texcoord
virtual void add_face_texcoords( FaceHandle _fh, VertexHandle _vh, const std::vector<Vec3f>& _face_texcoords) = 0;
// Set the texture index for a face
virtual void set_face_texindex( FaceHandle _fh, int _texId ) = 0;
// Set coordinate of the given vertex. Use this function, if you created a vertex without coordinate
virtual void set_point(VertexHandle _vh, const Vec3f& _point) = 0;
// set vertex normal
virtual void set_normal(VertexHandle _vh, const Vec3f& _normal) = 0;
// set vertex color
virtual void set_color(VertexHandle _vh, const Vec3uc& _color) = 0;
// set vertex color
virtual void set_color(VertexHandle _vh, const Vec4uc& _color) = 0;
// set vertex color
virtual void set_color(VertexHandle _vh, const Vec3f& _color) = 0;
// set vertex color
virtual void set_color(VertexHandle _vh, const Vec4f& _color) = 0;
// set vertex texture coordinate
virtual void set_texcoord(VertexHandle _vh, const Vec2f& _texcoord) = 0;
// set vertex texture coordinate
virtual void set_texcoord(HalfedgeHandle _heh, const Vec2f& _texcoord) = 0;
// set 3d vertex texture coordinate
virtual void set_texcoord(VertexHandle _vh, const Vec3f& _texcoord) = 0;
// set 3d vertex texture coordinate
virtual void set_texcoord(HalfedgeHandle _heh, const Vec3f& _texcoord) = 0;
// set edge color
virtual void set_color(EdgeHandle _eh, const Vec3uc& _color) = 0;
// set edge color
virtual void set_color(EdgeHandle _eh, const Vec4uc& _color) = 0;
// set edge color
virtual void set_color(EdgeHandle _eh, const Vec3f& _color) = 0;
// set edge color
virtual void set_color(EdgeHandle _eh, const Vec4f& _color) = 0;
// set face normal
virtual void set_normal(FaceHandle _fh, const Vec3f& _normal) = 0;
// set face color
virtual void set_color(FaceHandle _fh, const Vec3uc& _color) = 0;
// set face color
virtual void set_color(FaceHandle _fh, const Vec4uc& _color) = 0;
// set face color
virtual void set_color(FaceHandle _fh, const Vec3f& _color) = 0;
// set face color
virtual void set_color(FaceHandle _fh, const Vec4f& _color) = 0;
// Store a property in the mesh mapping from an int to a texture file
// Use set_face_texindex to set the index for each face
virtual void add_texture_information( int _id , std::string _name ) = 0;
// get reference to base kernel
virtual BaseKernel* kernel() { return 0; }
virtual bool is_triangle_mesh() const { return false; }
// reserve mem for elements
virtual void reserve( unsigned int /* nV */,
unsigned int /* nE */,
unsigned int /* nF */) {}
// query number of faces, vertices, normals, texcoords
virtual size_t n_vertices() const = 0;
virtual size_t n_faces() const = 0;
virtual size_t n_edges() const = 0;
// pre-processing
virtual void prepare() {}
// post-processing
virtual void finish() {}
};
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,408 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements an importer module for arbitrary OpenMesh meshes
//
//=============================================================================
#ifndef __IMPORTERT_HH__
#define __IMPORTERT_HH__
//=== INCLUDES ================================================================
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/Utils/vector_cast.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
#include <OpenMesh/Core/Mesh/Attributes.hh>
#include <OpenMesh/Core/System/omstream.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
* This class template provides an importer module for OpenMesh meshes.
*/
template <class Mesh>
class ImporterT : public BaseImporter
{
public:
typedef typename Mesh::Point Point;
typedef typename Mesh::Normal Normal;
typedef typename Mesh::Color Color;
typedef typename Mesh::TexCoord2D TexCoord2D;
typedef typename Mesh::TexCoord3D TexCoord3D;
typedef std::vector<VertexHandle> VHandles;
ImporterT(Mesh& _mesh) : mesh_(_mesh), halfedgeNormals_() {}
virtual VertexHandle add_vertex(const Vec3f& _point)
{
return mesh_.add_vertex(vector_cast<Point>(_point));
}
virtual VertexHandle add_vertex()
{
return mesh_.new_vertex();
}
virtual FaceHandle add_face(const VHandles& _indices)
{
FaceHandle fh;
if (_indices.size() > 2)
{
VHandles::const_iterator it, it2, end(_indices.end());
// test for valid vertex indices
for (it=_indices.begin(); it!=end; ++it)
if (! mesh_.is_valid_handle(*it))
{
omerr() << "ImporterT: Face contains invalid vertex index\n";
return fh;
}
// don't allow double vertices
for (it=_indices.begin(); it!=end; ++it)
for (it2=it+1; it2!=end; ++it2)
if (*it == *it2)
{
omerr() << "ImporterT: Face has equal vertices\n";
return fh;
}
// try to add face
fh = mesh_.add_face(_indices);
// separate non-manifold faces and mark them
if (!fh.is_valid())
{
VHandles vhandles(_indices.size());
// double vertices
for (unsigned int j=0; j<_indices.size(); ++j)
{
// DO STORE p, reference may not work since vertex array
// may be relocated after adding a new vertex !
Point p = mesh_.point(_indices[j]);
vhandles[j] = mesh_.add_vertex(p);
// Mark vertices of failed face as non-manifold
if (mesh_.has_vertex_status()) {
mesh_.status(vhandles[j]).set_fixed_nonmanifold(true);
}
}
// add face
fh = mesh_.add_face(vhandles);
// Mark failed face as non-manifold
if (mesh_.has_face_status())
mesh_.status(fh).set_fixed_nonmanifold(true);
// Mark edges of failed face as non-two-manifold
if (mesh_.has_edge_status()) {
typename Mesh::FaceEdgeIter fe_it = mesh_.fe_iter(fh);
for(; fe_it.is_valid(); ++fe_it) {
mesh_.status(*fe_it).set_fixed_nonmanifold(true);
}
}
}
//write the half edge normals
if (mesh_.has_halfedge_normals())
{
//iterate over all incoming haldedges of the added face
for (typename Mesh::FaceHalfedgeIter fh_iter = mesh_.fh_begin(fh);
fh_iter != mesh_.fh_end(fh); ++fh_iter)
{
//and write the normals to it
typename Mesh::HalfedgeHandle heh = *fh_iter;
typename Mesh::VertexHandle vh = mesh_.to_vertex_handle(heh);
typename std::map<VertexHandle,Normal>::iterator it_heNs = halfedgeNormals_.find(vh);
if (it_heNs != halfedgeNormals_.end())
mesh_.set_normal(heh,it_heNs->second);
}
halfedgeNormals_.clear();
}
}
return fh;
}
// vertex attributes
virtual void set_point(VertexHandle _vh, const Vec3f& _point)
{
mesh_.set_point(_vh,vector_cast<Point>(_point));
}
virtual void set_normal(VertexHandle _vh, const Vec3f& _normal)
{
if (mesh_.has_vertex_normals())
mesh_.set_normal(_vh, vector_cast<Normal>(_normal));
//saves normals for half edges.
//they will be written, when the face is added
if (mesh_.has_halfedge_normals())
halfedgeNormals_[_vh] = vector_cast<Normal>(_normal);
}
virtual void set_color(VertexHandle _vh, const Vec4uc& _color)
{
if (mesh_.has_vertex_colors())
mesh_.set_color(_vh, color_cast<Color>(_color));
}
virtual void set_color(VertexHandle _vh, const Vec3uc& _color)
{
if (mesh_.has_vertex_colors())
mesh_.set_color(_vh, color_cast<Color>(_color));
}
virtual void set_color(VertexHandle _vh, const Vec4f& _color)
{
if (mesh_.has_vertex_colors())
mesh_.set_color(_vh, color_cast<Color>(_color));
}
virtual void set_color(VertexHandle _vh, const Vec3f& _color)
{
if (mesh_.has_vertex_colors())
mesh_.set_color(_vh, color_cast<Color>(_color));
}
virtual void set_texcoord(VertexHandle _vh, const Vec2f& _texcoord)
{
if (mesh_.has_vertex_texcoords2D())
mesh_.set_texcoord2D(_vh, vector_cast<TexCoord2D>(_texcoord));
}
virtual void set_texcoord(HalfedgeHandle _heh, const Vec2f& _texcoord)
{
if (mesh_.has_halfedge_texcoords2D())
mesh_.set_texcoord2D(_heh, vector_cast<TexCoord2D>(_texcoord));
}
virtual void set_texcoord(VertexHandle _vh, const Vec3f& _texcoord)
{
if (mesh_.has_vertex_texcoords3D())
mesh_.set_texcoord3D(_vh, vector_cast<TexCoord3D>(_texcoord));
}
virtual void set_texcoord(HalfedgeHandle _heh, const Vec3f& _texcoord)
{
if (mesh_.has_halfedge_texcoords3D())
mesh_.set_texcoord3D(_heh, vector_cast<TexCoord3D>(_texcoord));
}
// edge attributes
virtual void set_color(EdgeHandle _eh, const Vec4uc& _color)
{
if (mesh_.has_edge_colors())
mesh_.set_color(_eh, color_cast<Color>(_color));
}
virtual void set_color(EdgeHandle _eh, const Vec3uc& _color)
{
if (mesh_.has_edge_colors())
mesh_.set_color(_eh, color_cast<Color>(_color));
}
virtual void set_color(EdgeHandle _eh, const Vec4f& _color)
{
if (mesh_.has_edge_colors())
mesh_.set_color(_eh, color_cast<Color>(_color));
}
virtual void set_color(EdgeHandle _eh, const Vec3f& _color)
{
if (mesh_.has_edge_colors())
mesh_.set_color(_eh, color_cast<Color>(_color));
}
// face attributes
virtual void set_normal(FaceHandle _fh, const Vec3f& _normal)
{
if (mesh_.has_face_normals())
mesh_.set_normal(_fh, vector_cast<Normal>(_normal));
}
virtual void set_color(FaceHandle _fh, const Vec3uc& _color)
{
if (mesh_.has_face_colors())
mesh_.set_color(_fh, color_cast<Color>(_color));
}
virtual void set_color(FaceHandle _fh, const Vec4uc& _color)
{
if (mesh_.has_face_colors())
mesh_.set_color(_fh, color_cast<Color>(_color));
}
virtual void set_color(FaceHandle _fh, const Vec3f& _color)
{
if (mesh_.has_face_colors())
mesh_.set_color(_fh, color_cast<Color>(_color));
}
virtual void set_color(FaceHandle _fh, const Vec4f& _color)
{
if (mesh_.has_face_colors())
mesh_.set_color(_fh, color_cast<Color>(_color));
}
virtual void add_face_texcoords( FaceHandle _fh, VertexHandle _vh, const std::vector<Vec2f>& _face_texcoords)
{
// get first halfedge handle
HalfedgeHandle cur_heh = mesh_.halfedge_handle(_fh);
HalfedgeHandle end_heh = mesh_.prev_halfedge_handle(cur_heh);
// find start heh
while( mesh_.to_vertex_handle(cur_heh) != _vh && cur_heh != end_heh )
cur_heh = mesh_.next_halfedge_handle( cur_heh);
for(unsigned int i=0; i<_face_texcoords.size(); ++i)
{
set_texcoord( cur_heh, _face_texcoords[i]);
cur_heh = mesh_.next_halfedge_handle( cur_heh);
}
}
virtual void add_face_texcoords( FaceHandle _fh, VertexHandle _vh, const std::vector<Vec3f>& _face_texcoords)
{
// get first halfedge handle
HalfedgeHandle cur_heh = mesh_.halfedge_handle(_fh);
HalfedgeHandle end_heh = mesh_.prev_halfedge_handle(cur_heh);
// find start heh
while( mesh_.to_vertex_handle(cur_heh) != _vh && cur_heh != end_heh )
cur_heh = mesh_.next_halfedge_handle( cur_heh);
for(unsigned int i=0; i<_face_texcoords.size(); ++i)
{
set_texcoord( cur_heh, _face_texcoords[i]);
cur_heh = mesh_.next_halfedge_handle( cur_heh);
}
}
virtual void set_face_texindex( FaceHandle _fh, int _texId ) {
if ( mesh_.has_face_texture_index() ) {
mesh_.set_texture_index(_fh , _texId);
}
}
virtual void add_texture_information( int _id , std::string _name ) {
OpenMesh::MPropHandleT< std::map< int, std::string > > property;
if ( !mesh_.get_property_handle(property,"TextureMapping") ) {
mesh_.add_property(property,"TextureMapping");
}
if ( mesh_.property(property).find( _id ) == mesh_.property(property).end() )
mesh_.property(property)[_id] = _name;
}
// low-level access to mesh
virtual BaseKernel* kernel() { return &mesh_; }
bool is_triangle_mesh() const
{ return Mesh::is_triangles(); }
void reserve(unsigned int nV, unsigned int nE, unsigned int nF)
{
mesh_.reserve(nV, nE, nF);
}
// query number of faces, vertices, normals, texcoords
size_t n_vertices() const { return mesh_.n_vertices(); }
size_t n_faces() const { return mesh_.n_faces(); }
size_t n_edges() const { return mesh_.n_edges(); }
void prepare() { }
void finish() { }
private:
Mesh& mesh_;
// stores normals for halfedges of the next face
std::map<VertexHandle,Normal> halfedgeNormals_;
};
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,132 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=== INCLUDES ================================================================
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
#if defined(OM_CC_MIPS)
# include <ctype.h>
#else
#endif
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
static inline char tolower(char c)
{
using namespace std;
return ::tolower(c);
}
//-----------------------------------------------------------------------------
bool
BaseReader::
can_u_read(const std::string& _filename) const
{
// get file extension
std::string extension;
std::string::size_type pos(_filename.rfind("."));
if (pos != std::string::npos)
extension = _filename.substr(pos+1, _filename.length()-pos-1);
else
extension = _filename; //check, if the whole filename defines the extension
std::transform( extension.begin(), extension.end(),
extension.begin(), tolower );
// locate extension in extension string
return (get_extensions().find(extension) != std::string::npos);
}
//-----------------------------------------------------------------------------
bool
BaseReader::
check_extension(const std::string& _fname, const std::string& _ext) const
{
std::string cmpExt(_ext);
std::transform( _ext.begin(), _ext.end(), cmpExt.begin(), tolower );
std::string::size_type pos(_fname.rfind("."));
if (pos != std::string::npos && !_ext.empty() )
{
std::string ext;
// extension without dot!
ext = _fname.substr(pos+1, _fname.length()-pos-1);
std::transform( ext.begin(), ext.end(), ext.begin(), tolower );
return ext == cmpExt;
}
return false;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,213 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements the baseclass for IOManager file access modules
//
//=============================================================================
#ifndef __BASEREADER_HH__
#define __BASEREADER_HH__
//=== INCLUDES ================================================================
// STD C++
#include <iosfwd>
#include <string>
#include <cctype>
#include <functional>
#include <algorithm>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/Options.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/Utils/SingletonT.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
Base class for reader modules.
Reader modules access persistent data and pass them to the desired
data structure by the means of a BaseImporter derivative.
All reader modules must be derived from this class.
*/
class OPENMESHDLLEXPORT BaseReader
{
public:
/// Destructor
virtual ~BaseReader() {};
/// Returns a brief description of the file type that can be parsed.
virtual std::string get_description() const = 0;
/** Returns a string with the accepted file extensions separated by a
whitespace and in small caps.
*/
virtual std::string get_extensions() const = 0;
/// Return magic bits used to determine file format
virtual std::string get_magic() const { return std::string(""); }
/** Reads a mesh given by a filename. Usually this method opens a stream
and passes it to stream read method. Acceptance checks by filename
extension can be placed here.
Options can be passed via _opt. After execution _opt contains the Options
that were available
*/
virtual bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt) = 0;
/** Reads a mesh given by a std::stream. This method usually uses the same stream reading method
that read uses. Options can be passed via _opt. After execution _opt contains the Options
that were available.
Please make sure that if _is is std::ifstream, the correct std::ios_base::openmode flags are set.
*/
virtual bool read(std::istream& _is,
BaseImporter& _bi,
Options& _opt) = 0;
/** \brief Returns true if writer can parse _filename (checks extension).
* _filename can also provide an extension without a name for a file e.g. _filename == "om" checks, if the reader can read the "om" extension
* @param _filename complete name of a file or just the extension
* @result true, if reader can read data with the given extension
*/
virtual bool can_u_read(const std::string& _filename) const;
protected:
// case insensitive search for _ext in _fname.
bool check_extension(const std::string& _fname,
const std::string& _ext) const;
};
/** \brief Trim left whitespace
*
* Removes whitespace at the beginning of the string
*
* @param _string input string
* @return trimmed string
*/
static inline std::string &left_trim(std::string &_string) {
// Find out if the compiler supports CXX11
#if ( __cplusplus >= 201103L || _MSVC_LANG >= 201103L )
// as with CXX11 we can use lambda expressions
_string.erase(_string.begin(), std::find_if(_string.begin(), _string.end(), [](int i)->int { return ! std::isspace(i); }));
#else
// we do what we did before
_string.erase(_string.begin(), std::find_if(_string.begin(), _string.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
#endif
return _string;
}
/** \brief Trim right whitespace
*
* Removes whitespace at the end of the string
*
* @param _string input string
* @return trimmed string
*/
static inline std::string &right_trim(std::string &_string) {
// Find out if the compiler supports CXX11
#if ( __cplusplus >= 201103L || _MSVC_LANG >= 201103L )
// as with CXX11 we can use lambda expressions
_string.erase(std::find_if(_string.rbegin(), _string.rend(), [](int i)->int { return ! std::isspace(i); } ).base(), _string.end());
#else
// we do what we did before
_string.erase(std::find_if(_string.rbegin(), _string.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), _string.end());
#endif
return _string;
}
/** \brief Trim whitespace
*
* Removes whitespace at the beginning and end of the string
*
* @param _string input string
* @return trimmed string
*/
static inline std::string &trim(std::string &_string) {
return left_trim(right_trim(_string));
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,808 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
// OpenMesh
#include <OpenMesh/Core/IO/reader/OBJReader.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/Utils/vector_cast.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
// STL
#if defined(OM_CC_MIPS)
# include <ctype.h>
/// \bug Workaround for STLPORT 4.6: isspace seems not to be in namespace std!
#elif defined(_STLPORT_VERSION) && (_STLPORT_VERSION==0x460)
# include <cctype>
#else
using std::isspace;
#endif
#ifndef WIN32
#endif
#include <fstream>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
_OBJReader_ __OBJReaderInstance;
_OBJReader_& OBJReader() { return __OBJReaderInstance; }
//=== IMPLEMENTATION ==========================================================
//-----------------------------------------------------------------------------
void trimString( std::string& _string) {
// Trim Both leading and trailing spaces
size_t start = _string.find_first_not_of(" \t\r\n");
size_t end = _string.find_last_not_of(" \t\r\n");
if(( std::string::npos == start ) || ( std::string::npos == end))
_string = "";
else
_string = _string.substr( start, end-start+1 );
}
//-----------------------------------------------------------------------------
// remove duplicated indices from one face
void remove_duplicated_vertices(BaseImporter::VHandles& _indices)
{
BaseImporter::VHandles::iterator endIter = _indices.end();
for (BaseImporter::VHandles::iterator iter = _indices.begin(); iter != endIter; ++iter)
endIter = std::remove(iter+1, endIter, *(iter));
_indices.erase(endIter,_indices.end());
}
//-----------------------------------------------------------------------------
_OBJReader_::
_OBJReader_()
{
IOManager().register_module(this);
}
//-----------------------------------------------------------------------------
bool
_OBJReader_::
read(const std::string& _filename, BaseImporter& _bi, Options& _opt)
{
std::fstream in( _filename.c_str(), std::ios_base::in );
if (!in.is_open() || !in.good())
{
omerr() << "[OBJReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
{
#if defined(WIN32)
std::string::size_type dot = _filename.find_last_of("\\/");
#else
std::string::size_type dot = _filename.rfind("/");
#endif
path_ = (dot == std::string::npos)
? "./"
: std::string(_filename.substr(0,dot+1));
}
bool result = read(in, _bi, _opt);
in.close();
return result;
}
//-----------------------------------------------------------------------------
bool
_OBJReader_::
read_material(std::fstream& _in)
{
std::string line;
std::string keyWrd;
std::string textureName;
std::stringstream stream;
std::string key;
Material mat;
float f1,f2,f3;
bool indef = false;
int textureId = 1;
materials_.clear();
mat.cleanup();
while( _in && !_in.eof() )
{
std::getline(_in,line);
if ( _in.bad() ){
omerr() << " Warning! Could not read file properly!\n";
return false;
}
if ( line.empty() )
continue;
stream.str(line);
stream.clear();
stream >> keyWrd;
if( ( isspace(line[0]) && line[0] != '\t' ) || line[0] == '#' )
{
if (indef && !key.empty() && mat.is_valid())
{
materials_[key] = mat;
mat.cleanup();
}
}
else if (keyWrd == "newmtl") // begin new material definition
{
stream >> key;
indef = true;
}
else if (keyWrd == "Kd") // diffuse color
{
stream >> f1; stream >> f2; stream >> f3;
if( !stream.fail() )
mat.set_Kd(f1,f2,f3);
}
else if (keyWrd == "Ka") // ambient color
{
stream >> f1; stream >> f2; stream >> f3;
if( !stream.fail() )
mat.set_Ka(f1,f2,f3);
}
else if (keyWrd == "Ks") // specular color
{
stream >> f1; stream >> f2; stream >> f3;
if( !stream.fail() )
mat.set_Ks(f1,f2,f3);
}
#if 0
else if (keyWrd == "illum") // diffuse/specular shading model
{
; // just skip this
}
else if (keyWrd == "Ns") // Shininess [0..200]
{
; // just skip this
}
else if (keyWrd == "map_") // map images
{
// map_Ks, specular map
// map_Ka, ambient map
// map_Bump, bump map
// map_d, opacity map
; // just skip this
}
#endif
else if (keyWrd == "map_Kd" ) {
// Get the rest of the line, removing leading or trailing spaces
// This will define the filename of the texture
std::getline(stream,textureName);
trimString(textureName);
if ( ! textureName.empty() )
mat.set_map_Kd( textureName, textureId++ );
}
else if (keyWrd == "Tr") // transparency value
{
stream >> f1;
if( !stream.fail() )
mat.set_Tr(f1);
}
else if (keyWrd == "d") // transparency value
{
stream >> f1;
if( !stream.fail() )
mat.set_Tr(f1);
}
if ( _in && indef && mat.is_valid() && !key.empty())
materials_[key] = mat;
}
return true;
}
//-----------------------------------------------------------------------------
bool
_OBJReader_::
read_vertices(std::istream& _in, BaseImporter& _bi, Options& _opt,
std::vector<Vec3f> & normals,
std::vector<Vec3f> & colors,
std::vector<Vec3f> & texcoords3d,
std::vector<Vec2f> & texcoords,
std::vector<VertexHandle> & vertexHandles,
Options & fileOptions)
{
float x, y, z, u, v, w;
float r, g, b;
std::string line;
std::string keyWrd;
std::stringstream stream;
// Options supplied by the user
const Options & userOptions = _opt;
while( _in && !_in.eof() )
{
std::getline(_in,line);
if ( _in.bad() ){
omerr() << " Warning! Could not read file properly!\n";
return false;
}
// Trim Both leading and trailing spaces
trimString(line);
// comment
if ( line.size() == 0 || line[0] == '#' || isspace(line[0]) ) {
continue;
}
stream.str(line);
stream.clear();
stream >> keyWrd;
// vertex
if (keyWrd == "v")
{
stream >> x; stream >> y; stream >> z;
if ( !stream.fail() )
{
vertexHandles.push_back(_bi.add_vertex(OpenMesh::Vec3f(x,y,z)));
stream >> r; stream >> g; stream >> b;
if ( !stream.fail() )
{
if ( userOptions.vertex_has_color() ) {
fileOptions += Options::VertexColor;
colors.push_back(OpenMesh::Vec3f(r,g,b));
}
}
}
}
// texture coord
else if (keyWrd == "vt")
{
stream >> u; stream >> v;
if ( !stream.fail() ){
if ( userOptions.vertex_has_texcoord() || userOptions.face_has_texcoord() ) {
texcoords.push_back(OpenMesh::Vec2f(u, v));
// Can be used for both!
fileOptions += Options::VertexTexCoord;
fileOptions += Options::FaceTexCoord;
// try to read the w component as it is optional
stream >> w;
if ( !stream.fail() )
texcoords3d.push_back(OpenMesh::Vec3f(u, v, w));
}
}else{
omerr() << "Only single 2D or 3D texture coordinate per vertex"
<< "allowed!" << std::endl;
return false;
}
}
// color per vertex
else if (keyWrd == "vc")
{
stream >> r; stream >> g; stream >> b;
if ( !stream.fail() ){
if ( userOptions.vertex_has_color() ) {
colors.push_back(OpenMesh::Vec3f(r,g,b));
fileOptions += Options::VertexColor;
}
}
}
// normal
else if (keyWrd == "vn")
{
stream >> x; stream >> y; stream >> z;
if ( !stream.fail() ) {
if (userOptions.vertex_has_normal() ){
normals.push_back(OpenMesh::Vec3f(x,y,z));
fileOptions += Options::VertexNormal;
}
}
}
}
return true;
}
//-----------------------------------------------------------------------------
bool
_OBJReader_::
read(std::istream& _in, BaseImporter& _bi, Options& _opt)
{
std::string line;
std::string keyWrd;
std::vector<Vec3f> normals;
std::vector<Vec3f> colors;
std::vector<Vec3f> texcoords3d;
std::vector<Vec2f> texcoords;
std::vector<VertexHandle> vertexHandles;
BaseImporter::VHandles vhandles;
std::vector<Vec3f> face_texcoords3d;
std::vector<Vec2f> face_texcoords;
std::string matname;
std::stringstream stream, lineData, tmp;
// Options supplied by the user
Options userOptions = _opt;
// Options collected via file parsing
Options fileOptions;
// pass 1: read vertices
if ( !read_vertices(_in, _bi, _opt,
normals, colors, texcoords3d, texcoords,
vertexHandles, fileOptions) ){
return false;
}
// reset stream for second pass
_in.clear();
_in.seekg(0, std::ios::beg);
int nCurrentPositions = 0,
nCurrentTexcoords = 0,
nCurrentNormals = 0;
// pass 2: read faces
while( _in && !_in.eof() )
{
std::getline(_in,line);
if ( _in.bad() ){
omerr() << " Warning! Could not read file properly!\n";
return false;
}
// Trim Both leading and trailing spaces
trimString(line);
// comment
if ( line.size() == 0 || line[0] == '#' || isspace(line[0]) ) {
continue;
}
stream.str(line);
stream.clear();
stream >> keyWrd;
// material file
if (keyWrd == "mtllib")
{
std::string matFile;
// Get the rest of the line, removing leading or trailing spaces
// This will define the filename of the texture
std::getline(stream,matFile);
trimString(matFile);
matFile = path_ + matFile;
//omlog() << "Load material file " << matFile << std::endl;
std::fstream matStream( matFile.c_str(), std::ios_base::in );
if ( matStream ){
if ( !read_material( matStream ) )
omerr() << " Warning! Could not read file properly!\n";
matStream.close();
}else
omerr() << " Warning! Material file '" << matFile << "' not found!\n";
//omlog() << " " << materials_.size() << " materials loaded.\n";
for ( MaterialList::iterator material = materials_.begin(); material != materials_.end(); ++material )
{
// Save the texture information in a property
if ( (*material).second.has_map_Kd() )
_bi.add_texture_information( (*material).second.map_Kd_index() , (*material).second.map_Kd() );
}
}
// usemtl
else if (keyWrd == "usemtl")
{
stream >> matname;
if (materials_.find(matname)==materials_.end())
{
omerr() << "Warning! Material '" << matname
<< "' not defined in material file.\n";
matname="";
}
}
// track current number of parsed vertex attributes,
// to allow for OBJs negative indices
else if (keyWrd == "v")
{
++nCurrentPositions;
}
else if (keyWrd == "vt")
{
++nCurrentTexcoords;
}
else if (keyWrd == "vn")
{
++nCurrentNormals;
}
// faces
else if (keyWrd == "f")
{
int component(0), nV(0);
int value;
vhandles.clear();
face_texcoords.clear();
face_texcoords3d.clear();
// read full line after detecting a face
std::string faceLine;
std::getline(stream,faceLine);
lineData.str( faceLine );
lineData.clear();
FaceHandle fh;
BaseImporter::VHandles faceVertices;
// work on the line until nothing left to read
while ( !lineData.eof() )
{
// read one block from the line ( vertex/texCoord/normal )
std::string vertex;
lineData >> vertex;
do{
//get the component (vertex/texCoord/normal)
size_t found=vertex.find("/");
// parts are seperated by '/' So if no '/' found its the last component
if( found != std::string::npos ){
// read the index value
tmp.str( vertex.substr(0,found) );
tmp.clear();
// If we get an empty string this property is undefined in the file
if ( vertex.substr(0,found).empty() ) {
// Switch to next field
vertex = vertex.substr(found+1);
// Now we are at the next component
++component;
// Skip further processing of this component
continue;
}
// Read current value
tmp >> value;
// remove the read part from the string
vertex = vertex.substr(found+1);
} else {
// last component of the vertex, read it.
tmp.str( vertex );
tmp.clear();
tmp >> value;
// Clear vertex after finished reading the line
vertex="";
// Nothing to read here ( garbage at end of line )
if ( tmp.fail() ) {
continue;
}
}
// store the component ( each component is referenced by the index here! )
switch (component)
{
case 0: // vertex
if ( value < 0 ) {
// Calculation of index :
// -1 is the last vertex in the list
// As obj counts from 1 and not zero add +1
value = nCurrentPositions + value + 1;
}
// Obj counts from 1 and not zero .. array counts from zero therefore -1
vhandles.push_back(VertexHandle(value-1));
faceVertices.push_back(VertexHandle(value-1));
if (fileOptions.vertex_has_color()) {
if ((unsigned int)(value - 1) < colors.size()) {
_bi.set_color(vhandles.back(), colors[value - 1]);
}
else {
omerr() << "Error setting vertex color" << std::endl;
}
}
break;
case 1: // texture coord
if ( value < 0 ) {
// Calculation of index :
// -1 is the last vertex in the list
// As obj counts from 1 and not zero add +1
value = nCurrentTexcoords + value + 1;
}
assert(!vhandles.empty());
if ( fileOptions.vertex_has_texcoord() && userOptions.vertex_has_texcoord() ) {
if (!texcoords.empty() && (unsigned int) (value - 1) < texcoords.size()) {
// Obj counts from 1 and not zero .. array counts from zero therefore -1
_bi.set_texcoord(vhandles.back(), texcoords[value - 1]);
if(!texcoords3d.empty() && (unsigned int) (value -1) < texcoords3d.size())
_bi.set_texcoord(vhandles.back(), texcoords3d[value - 1]);
} else {
omerr() << "Error setting Texture coordinates" << std::endl;
}
}
if (fileOptions.face_has_texcoord() && userOptions.face_has_texcoord() ) {
if (!texcoords.empty() && (unsigned int) (value - 1) < texcoords.size()) {
face_texcoords.push_back( texcoords[value-1] );
if(!texcoords3d.empty() && (unsigned int) (value -1) < texcoords3d.size())
face_texcoords3d.push_back( texcoords3d[value-1] );
} else {
omerr() << "Error setting Texture coordinates" << std::endl;
}
}
break;
case 2: // normal
if ( value < 0 ) {
// Calculation of index :
// -1 is the last vertex in the list
// As obj counts from 1 and not zero add +1
value = nCurrentNormals + value + 1;
}
// Obj counts from 1 and not zero .. array counts from zero therefore -1
if (fileOptions.vertex_has_normal() ) {
assert(!vhandles.empty());
if ((unsigned int)(value - 1) < normals.size()) {
_bi.set_normal(vhandles.back(), normals[value - 1]);
}
else {
omerr() << "Error setting vertex normal" << std::endl;
}
}
break;
}
// Prepare for reading next component
++component;
// Read until line does not contain any other info
} while ( !vertex.empty() );
component = 0;
nV++;
}
// note that add_face can possibly triangulate the faces, which is why we have to
// store the current number of faces first
size_t n_faces = _bi.n_faces();
remove_duplicated_vertices(faceVertices);
//A minimum of three vertices are required.
if (faceVertices.size() > 2)
fh = _bi.add_face(faceVertices);
if (!vhandles.empty() && fh.is_valid() )
{
_bi.add_face_texcoords(fh, vhandles[0], face_texcoords);
_bi.add_face_texcoords(fh, vhandles[0], face_texcoords3d);
}
if ( !matname.empty() )
{
std::vector<FaceHandle> newfaces;
for( size_t i=0; i < _bi.n_faces()-n_faces; ++i )
newfaces.push_back(FaceHandle(int(n_faces+i)));
Material& mat = materials_[matname];
if ( mat.has_Kd() ) {
Vec3uc fc = color_cast<Vec3uc, Vec3f>(mat.Kd());
if ( userOptions.face_has_color()) {
for (std::vector<FaceHandle>::iterator it = newfaces.begin(); it != newfaces.end(); ++it)
_bi.set_color(*it, fc);
fileOptions += Options::FaceColor;
}
}
// Set the texture index in the face index property
if ( mat.has_map_Kd() ) {
if (userOptions.face_has_texcoord()) {
for (std::vector<FaceHandle>::iterator it = newfaces.begin(); it != newfaces.end(); ++it)
_bi.set_face_texindex(*it, mat.map_Kd_index());
fileOptions += Options::FaceTexCoord;
}
} else {
// If we don't have the info, set it to no texture
if (userOptions.face_has_texcoord()) {
for (std::vector<FaceHandle>::iterator it = newfaces.begin(); it != newfaces.end(); ++it)
_bi.set_face_texindex(*it, 0);
}
}
} else {
std::vector<FaceHandle> newfaces;
for( size_t i=0; i < _bi.n_faces()-n_faces; ++i )
newfaces.push_back(FaceHandle(int(n_faces+i)));
// Set the texture index to zero as we don't have any information
if ( userOptions.face_has_texcoord() )
for (std::vector<FaceHandle>::iterator it = newfaces.begin(); it != newfaces.end(); ++it)
_bi.set_face_texindex(*it, 0);
}
}
}
// If we do not have any faces,
// assume this is a point cloud and read the normals and colors directly
if (_bi.n_faces() == 0)
{
int i = 0;
// add normal per vertex
if (normals.size() == _bi.n_vertices()) {
if ( fileOptions.vertex_has_normal() && userOptions.vertex_has_normal() ) {
for (std::vector<VertexHandle>::iterator it = vertexHandles.begin(); it != vertexHandles.end(); ++it, i++)
_bi.set_normal(*it, normals[i]);
}
}
// add color per vertex
i = 0;
if (colors.size() >= _bi.n_vertices())
if (fileOptions.vertex_has_color() && userOptions.vertex_has_color()) {
for (std::vector<VertexHandle>::iterator it = vertexHandles.begin(); it != vertexHandles.end(); ++it, i++)
_bi.set_color(*it, colors[i]);
}
}
// Return, what we actually read
_opt = fileOptions;
return true;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,201 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements an reader module for OBJ files
//
//=============================================================================
#ifndef __OBJREADER_HH__
#define __OBJREADER_HH__
//=== INCLUDES ================================================================
#include <iosfwd>
#include <string>
#include <map>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== IMPLEMENTATION ===========================================================
/**
Implementation of the OBJ format reader.
*/
class OPENMESHDLLEXPORT _OBJReader_ : public BaseReader
{
public:
_OBJReader_();
virtual ~_OBJReader_() { }
std::string get_description() const { return "Alias/Wavefront"; }
std::string get_extensions() const { return "obj"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt);
bool read(std::istream& _in,
BaseImporter& _bi,
Options& _opt);
private:
#ifndef DOXY_IGNORE_THIS
class Material
{
public:
Material() { cleanup(); }
void cleanup()
{
Kd_is_set_ = false;
Ka_is_set_ = false;
Ks_is_set_ = false;
Tr_is_set_ = false;
map_Kd_is_set_ = false;
}
bool is_valid(void) const
{ return Kd_is_set_ || Ka_is_set_ || Ks_is_set_ || Tr_is_set_ || map_Kd_is_set_; }
bool has_Kd(void) { return Kd_is_set_; }
bool has_Ka(void) { return Ka_is_set_; }
bool has_Ks(void) { return Ks_is_set_; }
bool has_Tr(void) { return Tr_is_set_; }
bool has_map_Kd(void) { return map_Kd_is_set_; }
void set_Kd( float r, float g, float b )
{ Kd_=Vec3f(r,g,b); Kd_is_set_=true; }
void set_Ka( float r, float g, float b )
{ Ka_=Vec3f(r,g,b); Ka_is_set_=true; }
void set_Ks( float r, float g, float b )
{ Ks_=Vec3f(r,g,b); Ks_is_set_=true; }
void set_Tr( float t )
{ Tr_=t; Tr_is_set_=true; }
void set_map_Kd( std::string _name, int _index_Kd )
{ map_Kd_ = _name, index_Kd_ = _index_Kd; map_Kd_is_set_ = true; };
const Vec3f& Kd( void ) const { return Kd_; }
const Vec3f& Ka( void ) const { return Ka_; }
const Vec3f& Ks( void ) const { return Ks_; }
float Tr( void ) const { return Tr_; }
const std::string& map_Kd( void ) { return map_Kd_ ; }
const int& map_Kd_index( void ) { return index_Kd_ ; }
private:
Vec3f Kd_; bool Kd_is_set_; // diffuse
Vec3f Ka_; bool Ka_is_set_; // ambient
Vec3f Ks_; bool Ks_is_set_; // specular
float Tr_; bool Tr_is_set_; // transperency
std::string map_Kd_; int index_Kd_; bool map_Kd_is_set_; // Texture
};
#endif
typedef std::map<std::string, Material> MaterialList;
MaterialList materials_;
bool read_material( std::fstream& _in );
private:
bool read_vertices(std::istream& _in, BaseImporter& _bi, Options& _opt,
std::vector<Vec3f> & normals,
std::vector<Vec3f> & colors,
std::vector<Vec3f> & texcoords3d,
std::vector<Vec2f> & texcoords,
std::vector<VertexHandle> & vertexHandles,
Options & fileOptions);
std::string path_;
};
//== TYPE DEFINITION ==========================================================
extern _OBJReader_ __OBJReaderInstance;
OPENMESHDLLEXPORT _OBJReader_& OBJReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,689 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#define LINE_LEN 4096
//== INCLUDES =================================================================
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/IO/reader/OFFReader.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
// #include <OpenMesh/Core/IO/BinaryHelper.hh>
//STL
#include <iostream>
#include <fstream>
#include <memory>
#include <cstring>
#if defined(OM_CC_MIPS)
# include <ctype.h>
/// \bug Workaround for STLPORT 4.6: isspace seems not to be in namespace std!
#elif defined(_STLPORT_VERSION) && (_STLPORT_VERSION==0x460)
# include <cctype>
#else
using std::isspace;
#endif
#ifndef WIN32
#endif
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=============================================================================
//=== INSTANCIATE =============================================================
_OFFReader_ __OFFReaderInstance;
_OFFReader_& OFFReader() { return __OFFReaderInstance; }
//=== IMPLEMENTATION ==========================================================
_OFFReader_::_OFFReader_()
{
IOManager().register_module(this);
}
//-----------------------------------------------------------------------------
bool
_OFFReader_::read(const std::string& _filename, BaseImporter& _bi,
Options& _opt)
{
std::ifstream ifile(_filename.c_str(), (options_.is_binary() ? std::ios::binary | std::ios::in
: std::ios::in) );
if (!ifile.is_open() || !ifile.good())
{
omerr() << "[OFFReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
assert(ifile);
bool result = read(ifile, _bi, _opt);
ifile.close();
return result;
}
//-----------------------------------------------------------------------------
bool
_OFFReader_::read(std::istream& _in, BaseImporter& _bi, Options& _opt )
{
if (!_in.good())
{
omerr() << "[OMReader] : cannot not use stream "
<< std::endl;
return false;
}
// filter relevant options for reading
bool swap = _opt.check( Options::Swap );
userOptions_ = _opt;
// build options to be returned
_opt.clear();
if (options_.vertex_has_normal() && userOptions_.vertex_has_normal()) _opt += Options::VertexNormal;
if (options_.vertex_has_texcoord() && userOptions_.vertex_has_texcoord()) _opt += Options::VertexTexCoord;
if (options_.vertex_has_color() && userOptions_.vertex_has_color()) _opt += Options::VertexColor;
if (options_.face_has_color() && userOptions_.face_has_color()) _opt += Options::FaceColor;
if (options_.is_binary()) _opt += Options::Binary;
//force user-choice for the alpha value when reading binary
if ( options_.is_binary() && userOptions_.color_has_alpha() )
options_ += Options::ColorAlpha;
return (options_.is_binary() ?
read_binary(_in, _bi, _opt, swap) :
read_ascii(_in, _bi, _opt));
}
//-----------------------------------------------------------------------------
bool
_OFFReader_::read_ascii(std::istream& _in, BaseImporter& _bi, Options& _opt) const
{
unsigned int i, j, k, l, idx;
unsigned int nV, nF, dummy;
OpenMesh::Vec3f v, n;
OpenMesh::Vec2f t;
OpenMesh::Vec3i c3;
OpenMesh::Vec3f c3f;
OpenMesh::Vec4i c4;
OpenMesh::Vec4f c4f;
BaseImporter::VHandles vhandles;
VertexHandle vh;
std::stringstream stream;
std::string trash;
// read header line
std::string header;
std::getline(_in,header);
// + #Vertice, #Faces, #Edges
_in >> nV;
_in >> nF;
_in >> dummy;
_bi.reserve(nV, 3*nV, nF);
// read vertices: coord [hcoord] [normal] [color] [texcoord]
for (i=0; i<nV && !_in.eof(); ++i)
{
// Always read VERTEX
_in >> v[0]; _in >> v[1]; _in >> v[2];
vh = _bi.add_vertex(v);
//perhaps read NORMAL
if ( options_.vertex_has_normal() ){
_in >> n[0]; _in >> n[1]; _in >> n[2];
if ( userOptions_.vertex_has_normal() )
_bi.set_normal(vh, n);
}
//take the rest of the line and check how colors are defined
std::string line;
std::getline(_in,line);
int colorType = getColorType(line, options_.vertex_has_texcoord() );
stream.str(line);
stream.clear();
//perhaps read COLOR
if ( options_.vertex_has_color() ){
switch (colorType){
case 0 : break; //no color
case 1 : stream >> trash; break; //one int (isn't handled atm)
case 2 : stream >> trash; stream >> trash; break; //corrupt format (ignore)
// rgb int
case 3 : stream >> c3[0]; stream >> c3[1]; stream >> c3[2];
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, Vec3uc( c3 ) );
break;
// rgba int
case 4 : stream >> c4[0]; stream >> c4[1]; stream >> c4[2]; stream >> c4[3];
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, Vec4uc( c4 ) );
break;
// rgb floats
case 5 : stream >> c3f[0]; stream >> c3f[1]; stream >> c3f[2];
if ( userOptions_.vertex_has_color() ) {
_bi.set_color( vh, c3f );
_opt += Options::ColorFloat;
}
break;
// rgba floats
case 6 : stream >> c4f[0]; stream >> c4f[1]; stream >> c4f[2]; stream >> c4f[3];
if ( userOptions_.vertex_has_color() ) {
_bi.set_color( vh, c4f );
_opt += Options::ColorFloat;
}
break;
default:
std::cerr << "Error in file format (colorType = " << colorType << ")\n";
break;
}
}
//perhaps read TEXTURE COORDs
if ( options_.vertex_has_texcoord() ){
stream >> t[0]; stream >> t[1];
if ( userOptions_.vertex_has_texcoord() )
_bi.set_texcoord(vh, t);
}
}
// faces
// #N <v1> <v2> .. <v(n-1)> [color spec]
for (i=0; i<nF; ++i)
{
// nV = number of Vertices for current face
_in >> nV;
if (nV == 3)
{
vhandles.resize(3);
_in >> j;
_in >> k;
_in >> l;
vhandles[0] = VertexHandle(j);
vhandles[1] = VertexHandle(k);
vhandles[2] = VertexHandle(l);
}
else
{
vhandles.clear();
for (j=0; j<nV; ++j)
{
_in >> idx;
vhandles.push_back(VertexHandle(idx));
}
}
FaceHandle fh = _bi.add_face(vhandles);
//perhaps read face COLOR
if ( options_.face_has_color() ){
//take the rest of the line and check how colors are defined
std::string line;
std::getline(_in,line);
int colorType = getColorType(line, false );
stream.str(line);
stream.clear();
switch (colorType){
case 0 : break; //no color
case 1 : stream >> trash; break; //one int (isn't handled atm)
case 2 : stream >> trash; stream >> trash; break; //corrupt format (ignore)
// rgb int
case 3 : stream >> c3[0]; stream >> c3[1]; stream >> c3[2];
if ( userOptions_.face_has_color() )
_bi.set_color( fh, Vec3uc( c3 ) );
break;
// rgba int
case 4 : stream >> c4[0]; stream >> c4[1]; stream >> c4[2]; stream >> c4[3];
if ( userOptions_.face_has_color() )
_bi.set_color( fh, Vec4uc( c4 ) );
break;
// rgb floats
case 5 : stream >> c3f[0]; stream >> c3f[1]; stream >> c3f[2];
if ( userOptions_.face_has_color() ) {
_bi.set_color( fh, c3f );
_opt += Options::ColorFloat;
}
break;
// rgba floats
case 6 : stream >> c4f[0]; stream >> c4f[1]; stream >> c4f[2]; stream >> c4f[3];
if ( userOptions_.face_has_color() ) {
_bi.set_color( fh, c4f );
_opt += Options::ColorFloat;
}
break;
default:
std::cerr << "Error in file format (colorType = " << colorType << ")\n";
break;
}
}
}
// File was successfully parsed.
return true;
}
//-----------------------------------------------------------------------------
int _OFFReader_::getColorType(std::string& _line, bool _texCoordsAvailable) const
{
/*
0 : no Color
1 : one int (e.g colormap index)
2 : two items (error!)
3 : 3 ints
4 : 3 ints
5 : 3 floats
6 : 4 floats
*/
// Check if we have any additional information here
if ( _line.size() < 1 )
return 0;
//first remove spaces at start/end of the line
while (_line.size() > 0 && std::isspace(_line[0]))
_line = _line.substr(1);
while (_line.size() > 0 && std::isspace(_line[ _line.length()-1 ]))
_line = _line.substr(0, _line.length()-1);
//count the remaining items in the line
size_t found;
int count = 0;
found=_line.find_first_of(" ");
while (found!=std::string::npos){
count++;
found=_line.find_first_of(" ",found+1);
}
if (!_line.empty()) count++;
if (_texCoordsAvailable) count -= 2;
if (count == 3 || count == 4){
//get first item
found = _line.find(" ");
std::string c1 = _line.substr (0,found);
if (c1.find(".") != std::string::npos){
if (count == 3)
count = 5;
else
count = 6;
}
}
return count;
}
void _OFFReader_::readValue(std::istream& _in, float& _value) const{
float32_t tmp;
restore( _in , tmp, false ); //assuming LSB byte order
_value = tmp;
}
void _OFFReader_::readValue(std::istream& _in, int& _value) const{
uint32_t tmp;
restore( _in , tmp, false ); //assuming LSB byte order
_value = tmp;
}
void _OFFReader_::readValue(std::istream& _in, unsigned int& _value) const{
uint32_t tmp;
restore( _in , tmp, false ); //assuming LSB byte order
_value = tmp;
}
bool
_OFFReader_::read_binary(std::istream& _in, BaseImporter& _bi, Options& _opt, bool /*_swap*/) const
{
unsigned int i, j, k, l, idx;
unsigned int nV, nF, dummy;
OpenMesh::Vec3f v, n;
OpenMesh::Vec3i c;
OpenMesh::Vec4i cA;
OpenMesh::Vec3f cf;
OpenMesh::Vec4f cAf;
OpenMesh::Vec2f t;
BaseImporter::VHandles vhandles;
VertexHandle vh;
// read header line
std::string header;
std::getline(_in,header);
// + #Vertice, #Faces, #Edges
readValue(_in, nV);
readValue(_in, nF);
readValue(_in, dummy);
_bi.reserve(nV, 3*nV, nF);
// read vertices: coord [hcoord] [normal] [color] [texcoord]
for (i=0; i<nV && !_in.eof(); ++i)
{
// Always read Vertex
readValue(_in, v[0]);
readValue(_in, v[1]);
readValue(_in, v[2]);
vh = _bi.add_vertex(v);
if ( options_.vertex_has_normal() ) {
readValue(_in, n[0]);
readValue(_in, n[1]);
readValue(_in, n[2]);
if ( userOptions_.vertex_has_normal() )
_bi.set_normal(vh, n);
}
if ( options_.vertex_has_color() ) {
if ( userOptions_.color_is_float() ) {
_opt += Options::ColorFloat;
//with alpha
if ( options_.color_has_alpha() ){
readValue(_in, cAf[0]);
readValue(_in, cAf[1]);
readValue(_in, cAf[2]);
readValue(_in, cAf[3]);
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, cAf );
}else{
//without alpha
readValue(_in, cf[0]);
readValue(_in, cf[1]);
readValue(_in, cf[2]);
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, cf );
}
} else {
//with alpha
if ( options_.color_has_alpha() ){
readValue(_in, cA[0]);
readValue(_in, cA[1]);
readValue(_in, cA[2]);
readValue(_in, cA[3]);
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, Vec4uc( cA ) );
}else{
//without alpha
readValue(_in, c[0]);
readValue(_in, c[1]);
readValue(_in, c[2]);
if ( userOptions_.vertex_has_color() )
_bi.set_color( vh, Vec3uc( c ) );
}
}
}
if ( options_.vertex_has_texcoord()) {
readValue(_in, t[0]);
readValue(_in, t[1]);
if ( userOptions_.vertex_has_texcoord() )
_bi.set_texcoord(vh, t);
}
}
// faces
// #N <v1> <v2> .. <v(n-1)> [color spec]
// So far color spec is unsupported!
for (i=0; i<nF; ++i)
{
readValue(_in, nV);
if (nV == 3)
{
vhandles.resize(3);
readValue(_in, j);
readValue(_in, k);
readValue(_in, l);
vhandles[0] = VertexHandle(j);
vhandles[1] = VertexHandle(k);
vhandles[2] = VertexHandle(l);
} else {
vhandles.clear();
for (j=0; j<nV; ++j)
{
readValue(_in, idx);
vhandles.push_back(VertexHandle(idx));
}
}
FaceHandle fh = _bi.add_face(vhandles);
//face color
if ( _opt.face_has_color() ) {
if ( userOptions_.color_is_float() ) {
_opt += Options::ColorFloat;
//with alpha
if ( options_.color_has_alpha() ){
readValue(_in, cAf[0]);
readValue(_in, cAf[1]);
readValue(_in, cAf[2]);
readValue(_in, cAf[3]);
if ( userOptions_.face_has_color() )
_bi.set_color( fh , cAf );
}else{
//without alpha
readValue(_in, cf[0]);
readValue(_in, cf[1]);
readValue(_in, cf[2]);
if ( userOptions_.face_has_color() )
_bi.set_color( fh, cf );
}
} else {
//with alpha
if ( options_.color_has_alpha() ){
readValue(_in, cA[0]);
readValue(_in, cA[1]);
readValue(_in, cA[2]);
readValue(_in, cA[3]);
if ( userOptions_.face_has_color() )
_bi.set_color( fh , Vec4uc( cA ) );
}else{
//without alpha
readValue(_in, c[0]);
readValue(_in, c[1]);
readValue(_in, c[2]);
if ( userOptions_.face_has_color() )
_bi.set_color( fh, Vec3uc( c ) );
}
}
}
}
// File was successfully parsed.
return true;
}
//-----------------------------------------------------------------------------
bool _OFFReader_::can_u_read(const std::string& _filename) const
{
// !!! Assuming BaseReader::can_u_parse( std::string& )
// does not call BaseReader::read_magic()!!!
if (BaseReader::can_u_read(_filename))
{
std::ifstream ifs(_filename.c_str());
if (ifs.is_open() && can_u_read(ifs))
{
ifs.close();
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
bool _OFFReader_::can_u_read(std::istream& _is) const
{
options_.cleanup();
// read 1st line
char line[LINE_LEN], *p;
_is.getline(line, LINE_LEN);
p = line;
std::streamsize remainingChars = _is.gcount();
bool vertexDimensionTooHigh = false;
// check header: [ST][C][N][4][n]OFF BINARY
if ( ( remainingChars > 1 ) && ( p[0] == 'S' && p[1] == 'T') )
{ options_ += Options::VertexTexCoord; p += 2; remainingChars -= 2; }
if ( ( remainingChars > 0 ) && ( p[0] == 'C') )
{ options_ += Options::VertexColor;
options_ += Options::FaceColor; ++p; --remainingChars; }
if ( ( remainingChars > 0 ) && ( p[0] == 'N') )
{ options_ += Options::VertexNormal; ++p; --remainingChars; }
if ( ( remainingChars > 0 ) && (p[0] == '4' ) )
{ vertexDimensionTooHigh = true; ++p; --remainingChars; }
if ( ( remainingChars > 0 ) && ( p[0] == 'n') )
{ vertexDimensionTooHigh = true; ++p; --remainingChars; }
if ( ( remainingChars < 3 ) || (!(p[0] == 'O' && p[1] == 'F' && p[2] == 'F') ) )
return false;
p += 4;
// Detect possible garbage and make sure, we don't have an underflow
if ( remainingChars >= 4 )
remainingChars -= 4;
else
remainingChars = 0;
if ( ( remainingChars >= 6 ) && ( strncmp(p, "BINARY", 6) == 0 ) )
options_+= Options::Binary;
// vertex Dimensions != 3 are currently not supported
if (vertexDimensionTooHigh)
return false;
return true;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,171 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a reader module for OFF files
//
//=============================================================================
#ifndef __OFFREADER_HH__
#define __OFFREADER_HH__
//=== INCLUDES ================================================================
#include <iosfwd>
#include <string>
#include <cstdio>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== FORWARDS =================================================================
class BaseImporter;
//== IMPLEMENTATION ===========================================================
/**
Implementation of the OFF format reader. This class is singleton'ed by
SingletonT to OFFReader.
By passing Options to the read function you can manipulate the reading behavoir.
The following options can be set:
VertexNormal
VertexColor
VertexTexCoord
FaceColor
ColorAlpha [only when reading binary]
These options define if the corresponding data should be read (if available)
or if it should be omitted.
After execution of the read function. The options object contains information about
what was actually read.
e.g. if VertexNormal was true when the read function was called, but the file
did not contain vertex normals then it is false afterwards.
When reading a binary off with Color Flag in the header it is assumed that all vertices
and faces have colors in the format "int int int".
If ColorAlpha is set the format "int int int int" is assumed.
*/
class OPENMESHDLLEXPORT _OFFReader_ : public BaseReader
{
public:
_OFFReader_();
/// Destructor
virtual ~_OFFReader_() {};
std::string get_description() const { return "Object File Format"; }
std::string get_extensions() const { return "off"; }
std::string get_magic() const { return "OFF"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt);
bool can_u_read(const std::string& _filename) const;
bool read(std::istream& _in, BaseImporter& _bi, Options& _opt );
private:
bool can_u_read(std::istream& _is) const;
bool read_ascii(std::istream& _in, BaseImporter& _bi, Options& _opt) const;
bool read_binary(std::istream& _in, BaseImporter& _bi, Options& _opt, bool swap) const;
void readValue(std::istream& _in, float& _value) const;
void readValue(std::istream& _in, int& _value) const;
void readValue(std::istream& _in, unsigned int& _value) const;
int getColorType(std::string & _line, bool _texCoordsAvailable) const;
//available options for reading
mutable Options options_;
//options that the user wants to read
mutable Options userOptions_;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the OFF reader
extern _OFFReader_ __OFFReaderInstance;
OPENMESHDLLEXPORT _OFFReader_& OFFReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,591 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
//STL
#include <vector>
#include <istream>
#include <fstream>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Utils/Endian.hh>
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <OpenMesh/Core/IO/reader/OMReader.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the OMReader singleton with MeshReader
_OMReader_ __OMReaderInstance;
_OMReader_& OMReader() { return __OMReaderInstance; }
//=== IMPLEMENTATION ==========================================================
_OMReader_::_OMReader_()
{
IOManager().register_module(this);
}
//-----------------------------------------------------------------------------
bool _OMReader_::read(const std::string& _filename, BaseImporter& _bi, Options& _opt)
{
// check whether importer can give us an OpenMesh BaseKernel
if (!_bi.kernel())
return false;
_opt += Options::Binary; // only binary format supported!
fileOptions_ = Options::Binary;
// Open file
std::ifstream ifs(_filename.c_str(), std::ios::binary);
/* Clear formatting flag skipws (Skip whitespaces). If set, operator>> will
* skip bytes set to whitespace chars (e.g. 0x20 bytes) in
* Property<bool>::restore.
*/
ifs.unsetf(std::ios::skipws);
if (!ifs.is_open() || !ifs.good()) {
omerr() << "[OMReader] : cannot not open file " << _filename << std::endl;
return false;
}
// Pass stream to read method, remember result
bool result = read(ifs, _bi, _opt);
// close input stream
ifs.close();
_opt = _opt & fileOptions_;
return result;
}
//-----------------------------------------------------------------------------
bool _OMReader_::read(std::istream& _is, BaseImporter& _bi, Options& _opt)
{
// check whether importer can give us an OpenMesh BaseKernel
if (!_bi.kernel())
return false;
_opt += Options::Binary; // only binary format supported!
fileOptions_ = Options::Binary;
if (!_is.good()) {
omerr() << "[OMReader] : cannot read from stream " << std::endl;
return false;
}
// Pass stream to read method, remember result
bool result = read_binary(_is, _bi, _opt);
if (result)
_opt += Options::Binary;
_opt = _opt & fileOptions_;
return result;
}
//-----------------------------------------------------------------------------
bool _OMReader_::read_ascii(std::istream& /* _is */, BaseImporter& /* _bi */, Options& /* _opt */) const
{
// not supported yet!
return false;
}
//-----------------------------------------------------------------------------
bool _OMReader_::read_binary(std::istream& _is, BaseImporter& _bi, Options& _opt) const
{
bool swap = _opt.check(Options::Swap) || (Endian::local() == Endian::MSB);
// Initialize byte counter
bytes_ = 0;
bytes_ += restore(_is, header_, swap);
while (!_is.eof()) {
bytes_ += restore(_is, chunk_header_, swap);
if (_is.eof())
break;
// Is this a named property restore the name
if (chunk_header_.name_) {
OMFormat::Chunk::PropertyName pn;
bytes_ += restore(_is, property_name_, swap);
}
// Read in the property data. If it is an anonymous or unknown named
// property, then skip data.
switch (chunk_header_.entity_) {
case OMFormat::Chunk::Entity_Vertex:
if (!read_binary_vertex_chunk(_is, _bi, _opt, swap))
return false;
break;
case OMFormat::Chunk::Entity_Face:
if (!read_binary_face_chunk(_is, _bi, _opt, swap))
return false;
break;
case OMFormat::Chunk::Entity_Edge:
if (!read_binary_edge_chunk(_is, _bi, _opt, swap))
return false;
break;
case OMFormat::Chunk::Entity_Halfedge:
if (!read_binary_halfedge_chunk(_is, _bi, _opt, swap))
return false;
break;
case OMFormat::Chunk::Entity_Mesh:
if (!read_binary_mesh_chunk(_is, _bi, _opt, swap))
return false;
break;
case OMFormat::Chunk::Entity_Sentinel:
return true;
default:
return false;
}
}
// File was successfully parsed.
return true;
}
//-----------------------------------------------------------------------------
bool _OMReader_::can_u_read(const std::string& _filename) const
{
// !!! Assuming BaseReader::can_u_parse( std::string& )
// does not call BaseReader::read_magic()!!!
if (this->BaseReader::can_u_read(_filename)) {
std::ifstream ifile(_filename.c_str());
if (ifile && can_u_read(ifile))
return true;
}
return false;
}
//-----------------------------------------------------------------------------
bool _OMReader_::can_u_read(std::istream& _is) const
{
std::vector<char> evt;
evt.reserve(20);
// read first 4 characters into a buffer
while (evt.size() < 4)
evt.push_back(static_cast<char>(_is.get()));
// put back all read characters
std::vector<char>::reverse_iterator it = evt.rbegin();
while (it != evt.rend())
_is.putback(*it++);
// evaluate header information
OMFormat::Header *hdr = (OMFormat::Header*) &evt[0];
// first two characters must be 'OM'
if (hdr->magic_[0] != 'O' || hdr->magic_[1] != 'M')
return false;
// 3rd characters defines the mesh type:
switch (hdr->mesh_) {
case 'T': // Triangle Mesh
case 'Q': // Quad Mesh
case 'P': // Polygonal Mesh
break;
default: // ?
return false;
}
// 4th characters encodes the version
return supports(hdr->version_);
}
//-----------------------------------------------------------------------------
bool _OMReader_::supports(const OMFormat::uint8 /* version */) const
{
return true;
}
//-----------------------------------------------------------------------------
bool _OMReader_::read_binary_vertex_chunk(std::istream &_is, BaseImporter &_bi, Options &_opt, bool _swap) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Vertex);
OpenMesh::Vec3f v3f;
OpenMesh::Vec2f v2f;
OpenMesh::Vec3uc v3uc; // rgb
OMFormat::Chunk::PropertyName custom_prop;
size_t vidx = 0;
switch (chunk_header_.type_) {
case Chunk::Type_Pos:
assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim()));
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
bytes_ += vector_restore(_is, v3f, _swap);
_bi.add_vertex(v3f);
}
break;
case Chunk::Type_Normal:
assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim()));
fileOptions_ += Options::VertexNormal;
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
bytes_ += vector_restore(_is, v3f, _swap);
if (fileOptions_.vertex_has_normal() && _opt.vertex_has_normal())
_bi.set_normal(VertexHandle(int(vidx)), v3f);
}
break;
case Chunk::Type_Texcoord:
assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec2f::dim()));
fileOptions_ += Options::VertexTexCoord;
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
bytes_ += vector_restore(_is, v2f, _swap);
if (fileOptions_.vertex_has_texcoord() && _opt.vertex_has_texcoord())
_bi.set_texcoord(VertexHandle(int(vidx)), v2f);
}
break;
case Chunk::Type_Color:
assert( OMFormat::dimensions(chunk_header_) == 3);
fileOptions_ += Options::VertexColor;
for (; vidx < header_.n_vertices_ && !_is.eof(); ++vidx) {
bytes_ += vector_restore(_is, v3uc, _swap);
if (fileOptions_.vertex_has_color() && _opt.vertex_has_color())
_bi.set_color(VertexHandle(int(vidx)), v3uc);
}
break;
case Chunk::Type_Custom:
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_vprop(property_name_), header_.n_vertices_, _swap);
vidx = header_.n_vertices_;
break;
default: // skip unknown chunks
{
omerr() << "Unknown chunk type ignored!\n";
size_t size_of = header_.n_vertices_ * OMFormat::vector_size(chunk_header_);
_is.ignore(size_of);
bytes_ += size_of;
}
}
// all chunk data has been read..?!
return vidx == header_.n_vertices_;
}
//-----------------------------------------------------------------------------
bool _OMReader_::read_binary_face_chunk(std::istream &_is, BaseImporter &_bi, Options &_opt, bool _swap) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Face);
size_t fidx = 0;
OpenMesh::Vec3f v3f; // normal
OpenMesh::Vec3uc v3uc; // rgb
switch (chunk_header_.type_) {
case Chunk::Type_Topology: {
BaseImporter::VHandles vhandles;
size_t nV = 0;
size_t vidx = 0;
switch (header_.mesh_) {
case 'T':
nV = 3;
break;
case 'Q':
nV = 4;
break;
}
for (; fidx < header_.n_faces_; ++fidx) {
if (header_.mesh_ == 'P')
bytes_ += restore(_is, nV, Chunk::Integer_16, _swap);
vhandles.clear();
for (size_t j = 0; j < nV; ++j) {
bytes_ += restore(_is, vidx, Chunk::Integer_Size(chunk_header_.bits_), _swap);
vhandles.push_back(VertexHandle(int(vidx)));
}
_bi.add_face(vhandles);
}
}
break;
case Chunk::Type_Normal:
assert( OMFormat::dimensions(chunk_header_) == size_t(OpenMesh::Vec3f::dim()));
fileOptions_ += Options::FaceNormal;
for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
bytes_ += vector_restore(_is, v3f, _swap);
if( fileOptions_.face_has_normal() && _opt.face_has_normal())
_bi.set_normal(FaceHandle(int(fidx)), v3f);
}
break;
case Chunk::Type_Color:
assert( OMFormat::dimensions(chunk_header_) == 3);
fileOptions_ += Options::FaceColor;
for (; fidx < header_.n_faces_ && !_is.eof(); ++fidx) {
bytes_ += vector_restore(_is, v3uc, _swap);
if( fileOptions_.face_has_color() && _opt.face_has_color())
_bi.set_color(FaceHandle(int(fidx)), v3uc);
}
break;
case Chunk::Type_Custom:
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_fprop(property_name_), header_.n_faces_, _swap);
fidx = header_.n_faces_;
break;
default: // skip unknown chunks
{
omerr() << "Unknown chunk type ignore!\n";
size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
_is.ignore(size_of);
bytes_ += size_of;
}
}
return fidx == header_.n_faces_;
}
//-----------------------------------------------------------------------------
bool _OMReader_::read_binary_edge_chunk(std::istream &_is, BaseImporter &_bi, Options &/*_opt */, bool _swap) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Edge);
size_t b = bytes_;
switch (chunk_header_.type_) {
case Chunk::Type_Custom:
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_eprop(property_name_), header_.n_edges_, _swap);
break;
default:
// skip unknown type
size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
_is.ignore(size_of);
bytes_ += size_of;
}
return b < bytes_;
}
//-----------------------------------------------------------------------------
bool _OMReader_::read_binary_halfedge_chunk(std::istream &_is, BaseImporter &_bi, Options &/* _opt */, bool _swap) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Halfedge);
size_t b = bytes_;
switch (chunk_header_.type_) {
case Chunk::Type_Custom:
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_hprop(property_name_), 2 * header_.n_edges_, _swap);
break;
default:
// skip unknown chunk
omerr() << "Unknown chunk type ignored!\n";
size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
_is.ignore(size_of);
bytes_ += size_of;
}
return b < bytes_;
}
//-----------------------------------------------------------------------------
bool _OMReader_::read_binary_mesh_chunk(std::istream &_is, BaseImporter &_bi, Options & /* _opt */, bool _swap) const
{
using OMFormat::Chunk;
assert( chunk_header_.entity_ == Chunk::Entity_Mesh);
size_t b = bytes_;
switch (chunk_header_.type_) {
case Chunk::Type_Custom:
bytes_ += restore_binary_custom_data(_is, _bi.kernel()->_get_mprop(property_name_), 1, _swap);
break;
default:
// skip unknown chunk
size_t size_of = OMFormat::chunk_data_size(header_, chunk_header_);
_is.ignore(size_of);
bytes_ += size_of;
}
return b < bytes_;
}
//-----------------------------------------------------------------------------
size_t _OMReader_::restore_binary_custom_data(std::istream& _is, BaseProperty* _bp, size_t _n_elem, bool _swap) const
{
assert( !_bp || (_bp->name() == property_name_));
using OMFormat::Chunk;
size_t bytes = 0;
Chunk::esize_t block_size;
Chunk::PropertyName custom_prop;
bytes += restore(_is, block_size, OMFormat::Chunk::Integer_32, _swap);
if (_bp) {
size_t n_bytes = _bp->size_of(_n_elem);
if (((n_bytes == BaseProperty::UnknownSize) || (n_bytes == block_size))
&& (_bp->element_size() == BaseProperty::UnknownSize || (_n_elem * _bp->element_size() == block_size))) {
#if defined(OM_DEBUG)
size_t b;
bytes += (b=_bp->restore( _is, _swap ));
#else
bytes += _bp->restore(_is, _swap);
#endif
#if defined(OM_DEBUG)
assert( block_size == b );
#endif
assert( block_size == _bp->size_of());
block_size = 0;
} else {
omerr() << "Warning! Property " << _bp->name() << " not loaded: " << "Mismatching data sizes!n";
}
}
if (block_size) {
_is.ignore(block_size);
bytes += block_size;
}
return bytes;
}
//-----------------------------------------------------------------------------
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,178 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a reader module for OFF files
//
//=============================================================================
#ifndef __OMREADER_HH__
#define __OMREADER_HH__
//=== INCLUDES ================================================================
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/IO/importer/BaseImporter.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
// STD C++
#include <iosfwd>
#include <string>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== IMPLEMENTATION ===========================================================
/**
Implementation of the OM format reader. This class is singleton'ed by
SingletonT to OMReader.
*/
class OPENMESHDLLEXPORT _OMReader_ : public BaseReader
{
public:
_OMReader_();
virtual ~_OMReader_() { }
std::string get_description() const { return "OpenMesh File Format"; }
std::string get_extensions() const { return "om"; }
std::string get_magic() const { return "OM"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt );
//! Stream Reader for std::istream input in binary format
bool read(std::istream& _is,
BaseImporter& _bi,
Options& _opt );
virtual bool can_u_read(const std::string& _filename) const;
virtual bool can_u_read(std::istream& _is) const;
private:
bool supports( const OMFormat::uint8 version ) const;
bool read_ascii(std::istream& _is, BaseImporter& _bi, Options& _opt) const;
bool read_binary(std::istream& _is, BaseImporter& _bi, Options& _opt) const;
typedef OMFormat::Header Header;
typedef OMFormat::Chunk::Header ChunkHeader;
typedef OMFormat::Chunk::PropertyName PropertyName;
// initialized/updated by read_binary*/read_ascii*
mutable size_t bytes_;
mutable Options fileOptions_;
mutable Header header_;
mutable ChunkHeader chunk_header_;
mutable PropertyName property_name_;
bool read_binary_vertex_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
bool read_binary_face_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
bool read_binary_edge_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
bool read_binary_halfedge_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
bool read_binary_mesh_chunk( std::istream &_is,
BaseImporter &_bi,
Options &_opt,
bool _swap) const;
size_t restore_binary_custom_data( std::istream& _is,
BaseProperty* _bp,
size_t _n_elem,
bool _swap) const;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the OM reader.
extern _OMReader_ __OMReaderInstance;
OPENMESHDLLEXPORT _OMReader_& OMReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,244 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a reader module for OFF files
//
//=============================================================================
#ifndef __PLYREADER_HH__
#define __PLYREADER_HH__
//=== INCLUDES ================================================================
#include <iosfwd>
#include <string>
#include <cstdio>
#include <vector>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
#include <OpenMesh/Core/Utils/GenProg.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== FORWARDS =================================================================
class BaseImporter;
//== IMPLEMENTATION ===========================================================
/**
Implementation of the PLY format reader. This class is singleton'ed by
SingletonT to OFFReader. It can read custom properties, accessible via the name
of the custom properties. List properties has the type std::vector<Type>.
*/
class OPENMESHDLLEXPORT _PLYReader_ : public BaseReader
{
public:
_PLYReader_();
std::string get_description() const { return "PLY polygon file format"; }
std::string get_extensions() const { return "ply"; }
std::string get_magic() const { return "PLY"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt);
bool read(std::istream& _is,
BaseImporter& _bi,
Options& _opt);
bool can_u_read(const std::string& _filename) const;
enum ValueType {
Unsupported,
ValueTypeINT8, ValueTypeCHAR,
ValueTypeUINT8, ValueTypeUCHAR,
ValueTypeINT16, ValueTypeSHORT,
ValueTypeUINT16, ValueTypeUSHORT,
ValueTypeINT32, ValueTypeINT,
ValueTypeUINT32, ValueTypeUINT,
ValueTypeFLOAT32, ValueTypeFLOAT,
ValueTypeFLOAT64, ValueTypeDOUBLE
};
private:
bool can_u_read(std::istream& _is) const;
bool read_ascii(std::istream& _in, BaseImporter& _bi, const Options& _opt) const;
bool read_binary(std::istream& _in, BaseImporter& _bi, bool swap, const Options& _opt) const;
float readToFloatValue(ValueType _type , std::fstream& _in) const;
void readValue(ValueType _type , std::istream& _in, float& _value) const;
void readValue(ValueType _type , std::istream& _in, double& _value) const;
void readValue(ValueType _type , std::istream& _in, unsigned int& _value) const;
void readValue(ValueType _type , std::istream& _in, unsigned short& _value) const;
void readValue(ValueType _type , std::istream& _in, unsigned char& _value) const;
void readValue(ValueType _type , std::istream& _in, int& _value) const;
void readValue(ValueType _type , std::istream& _in, short& _value) const;
void readValue(ValueType _type , std::istream& _in, signed char& _value) const;
void readInteger(ValueType _type, std::istream& _in, int& _value) const;
void readInteger(ValueType _type, std::istream& _in, unsigned int& _value) const;
/// Read unsupported properties in PLY file
void consume_input(std::istream& _in, int _count) const {
_in.read(reinterpret_cast<char*>(&buff[0]), _count);
}
mutable unsigned char buff[8];
/// Available per file options for reading
mutable Options options_;
/// Options that the user wants to read
mutable Options userOptions_;
mutable unsigned int vertexCount_;
mutable unsigned int faceCount_;
mutable uint vertexDimension_;
enum Property {
XCOORD,YCOORD,ZCOORD,
TEXX,TEXY,
COLORRED,COLORGREEN,COLORBLUE,COLORALPHA,
XNORM,YNORM,ZNORM, CUSTOM_PROP, VERTEX_INDICES,
UNSUPPORTED
};
/// Stores sizes of property types
mutable std::map<ValueType, int> scalar_size_;
// Number of vertex properties
struct PropertyInfo
{
Property property;
ValueType value;
std::string name;//for custom properties
ValueType listIndexType;//if type is unsupported, the poerty is not a list. otherwise, it the index type
PropertyInfo():property(UNSUPPORTED),value(Unsupported),name(""),listIndexType(Unsupported){}
PropertyInfo(Property _p, ValueType _v):property(_p),value(_v),name(""),listIndexType(Unsupported){}
PropertyInfo(Property _p, ValueType _v, const std::string& _n):property(_p),value(_v),name(_n),listIndexType(Unsupported){}
};
enum Element {
VERTEX,
FACE,
UNKNOWN
};
// Information on the elements
struct ElementInfo
{
Element element_;
std::string name_;
unsigned int count_;
std::vector< PropertyInfo > properties_;
};
mutable std::vector< ElementInfo > elements_;
template<typename T>
inline void read(_PLYReader_::ValueType _type, std::istream& _in, T& _value, OpenMesh::GenProg::TrueType /*_binary*/) const
{
readValue(_type, _in, _value);
}
template<typename T>
inline void read(_PLYReader_::ValueType _type, std::istream& _in, T& _value, OpenMesh::GenProg::FalseType /*_binary*/) const
{
_in >> _value;
}
//read and assign custom properties with the given type. Also creates property, if not exist
template<bool binary, typename T, typename Handle>
void readCreateCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const ValueType _valueType, const ValueType _listType) const;
template<bool binary, typename Handle>
void readCustomProperty(std::istream& _in, BaseImporter& _bi, Handle _h, const std::string& _propName, const _PLYReader_::ValueType _valueType, const _PLYReader_::ValueType _listIndexType) const;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the PLY reader
extern _PLYReader_ __PLYReaderInstance;
OPENMESHDLLEXPORT _PLYReader_& PLYReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,520 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
// STL
#include <map>
#include <float.h>
#include <fstream>
#include <cstring>
// OpenMesh
#include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/IO/reader/STLReader.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
//comppare strings crossplatform ignorign case
#ifdef _WIN32
#define strnicmp _strnicmp
#else
#define strnicmp strncasecmp
#endif
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the STLReader singleton with MeshReader
_STLReader_ __STLReaderInstance;
_STLReader_& STLReader() { return __STLReaderInstance; }
//=== IMPLEMENTATION ==========================================================
_STLReader_::
_STLReader_()
: eps_(FLT_MIN)
{
IOManager().register_module(this);
}
//-----------------------------------------------------------------------------
bool
_STLReader_::
read(const std::string& _filename, BaseImporter& _bi, Options& _opt)
{
bool result = false;
STL_Type file_type = NONE;
if ( check_extension( _filename, "stla" ) )
{
file_type = STLA;
}
else if ( check_extension( _filename, "stlb" ) )
{
file_type = STLB;
}
else if ( check_extension( _filename, "stl" ) )
{
file_type = check_stl_type(_filename);
}
switch (file_type)
{
case STLA:
{
result = read_stla(_filename, _bi, _opt);
_opt -= Options::Binary;
break;
}
case STLB:
{
result = read_stlb(_filename, _bi, _opt);
_opt += Options::Binary;
break;
}
default:
{
result = false;
break;
}
}
return result;
}
bool
_STLReader_::read(std::istream& _is,
BaseImporter& _bi,
Options& _opt)
{
bool result = false;
if (_opt & Options::Binary)
result = read_stlb(_is, _bi, _opt);
else
result = read_stla(_is, _bi, _opt);
return result;
}
//-----------------------------------------------------------------------------
#ifndef DOXY_IGNORE_THIS
class CmpVec
{
public:
explicit CmpVec(float _eps=FLT_MIN) : eps_(_eps) {}
bool operator()( const Vec3f& _v0, const Vec3f& _v1 ) const
{
if (fabs(_v0[0] - _v1[0]) <= eps_)
{
if (fabs(_v0[1] - _v1[1]) <= eps_)
{
return (_v0[2] < _v1[2] - eps_);
}
else return (_v0[1] < _v1[1] - eps_);
}
else return (_v0[0] < _v1[0] - eps_);
}
private:
float eps_;
};
#endif
//-----------------------------------------------------------------------------
void trimStdString( std::string& _string) {
// Trim Both leading and trailing spaces
size_t start = _string.find_first_not_of(" \t\r\n");
size_t end = _string.find_last_not_of(" \t\r\n");
if(( std::string::npos == start ) || ( std::string::npos == end))
_string = "";
else
_string = _string.substr( start, end-start+1 );
}
//-----------------------------------------------------------------------------
bool
_STLReader_::
read_stla(const std::string& _filename, BaseImporter& _bi, Options& _opt) const
{
std::fstream in( _filename.c_str(), std::ios_base::in );
if (!in)
{
omerr() << "[STLReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
bool res = read_stla(in, _bi, _opt);
if (in)
in.close();
return res;
}
//-----------------------------------------------------------------------------
bool
_STLReader_::
read_stla(std::istream& _in, BaseImporter& _bi, Options& _opt) const
{
unsigned int i;
OpenMesh::Vec3f v;
OpenMesh::Vec3f n;
BaseImporter::VHandles vhandles;
CmpVec comp(eps_);
std::map<Vec3f, VertexHandle, CmpVec> vMap(comp);
std::map<Vec3f, VertexHandle, CmpVec>::iterator vMapIt;
std::string line;
std::string garbage;
std::stringstream strstream;
bool facet_normal(false);
while( _in && !_in.eof() ) {
// Get one line
std::getline(_in, line);
if ( _in.bad() ){
omerr() << " Warning! Could not read stream properly!\n";
return false;
}
// Trim Both leading and trailing spaces
trimStdString(line);
// Normal found?
if (line.find("facet normal") != std::string::npos) {
strstream.str(line);
strstream.clear();
// facet
strstream >> garbage;
// normal
strstream >> garbage;
strstream >> n[0];
strstream >> n[1];
strstream >> n[2];
facet_normal = true;
}
// Detected a triangle
if ( (line.find("outer") != std::string::npos) || (line.find("OUTER") != std::string::npos ) ) {
vhandles.clear();
for (i=0; i<3; ++i) {
// Get one vertex
std::getline(_in, line);
trimStdString(line);
strstream.str(line);
strstream.clear();
strstream >> garbage;
strstream >> v[0];
strstream >> v[1];
strstream >> v[2];
// has vector been referenced before?
if ((vMapIt=vMap.find(v)) == vMap.end())
{
// No : add vertex and remember idx/vector mapping
VertexHandle handle = _bi.add_vertex(v);
vhandles.push_back(handle);
vMap[v] = handle;
}
else
// Yes : get index from map
vhandles.push_back(vMapIt->second);
}
// Add face only if it is not degenerated
if ((vhandles[0] != vhandles[1]) &&
(vhandles[0] != vhandles[2]) &&
(vhandles[1] != vhandles[2])) {
FaceHandle fh = _bi.add_face(vhandles);
// set the normal if requested
// if a normal was requested but could not be found we unset the option
if (facet_normal) {
if (fh.is_valid() && _opt.face_has_normal())
_bi.set_normal(fh, n);
} else
_opt -= Options::FaceNormal;
}
facet_normal = false;
}
}
return true;
}
//-----------------------------------------------------------------------------
bool
_STLReader_::
read_stlb(const std::string& _filename, BaseImporter& _bi, Options& _opt) const
{
std::fstream in( _filename.c_str(), std::ios_base::in | std::ios_base::binary);
if (!in)
{
omerr() << "[STLReader] : cannot not open file "
<< _filename
<< std::endl;
return false;
}
bool res = read_stlb(in, _bi, _opt);
if (in)
in.close();
return res;
}
//-----------------------------------------------------------------------------
bool
_STLReader_::
read_stlb(std::istream& _in, BaseImporter& _bi, Options& _opt) const
{
char dummy[100];
bool swapFlag;
unsigned int i, nT;
OpenMesh::Vec3f v, n;
BaseImporter::VHandles vhandles;
std::map<Vec3f, VertexHandle, CmpVec> vMap;
std::map<Vec3f, VertexHandle, CmpVec>::iterator vMapIt;
// check size of types
if ((sizeof(float) != 4) || (sizeof(int) != 4)) {
omerr() << "[STLReader] : wrong type size\n";
return false;
}
// determine endian mode
union { unsigned int i; unsigned char c[4]; } endian_test;
endian_test.i = 1;
swapFlag = (endian_test.c[3] == 1);
// read number of triangles
_in.read(dummy, 80);
nT = read_int(_in, swapFlag);
// read triangles
while (nT)
{
vhandles.clear();
// read triangle normal
n[0] = read_float(_in, swapFlag);
n[1] = read_float(_in, swapFlag);
n[2] = read_float(_in, swapFlag);
// triangle's vertices
for (i=0; i<3; ++i)
{
v[0] = read_float(_in, swapFlag);
v[1] = read_float(_in, swapFlag);
v[2] = read_float(_in, swapFlag);
// has vector been referenced before?
if ((vMapIt=vMap.find(v)) == vMap.end())
{
// No : add vertex and remember idx/vector mapping
VertexHandle handle = _bi.add_vertex(v);
vhandles.push_back(handle);
vMap[v] = handle;
}
else
// Yes : get index from map
vhandles.push_back(vMapIt->second);
}
// Add face only if it is not degenerated
if ((vhandles[0] != vhandles[1]) &&
(vhandles[0] != vhandles[2]) &&
(vhandles[1] != vhandles[2])) {
FaceHandle fh = _bi.add_face(vhandles);
if (fh.is_valid() && _opt.face_has_normal())
_bi.set_normal(fh, n);
}
_in.read(dummy, 2);
--nT;
}
return true;
}
//-----------------------------------------------------------------------------
_STLReader_::STL_Type
_STLReader_::
check_stl_type(const std::string& _filename) const
{
// open file
std::ifstream ifs (_filename.c_str(), std::ifstream::binary);
if(!ifs.good())
{
omerr() << "could not open file" << _filename << std::endl;
return NONE;
}
//find first non whitespace character
std::string line = "";
std::size_t firstChar;
while(line.empty() && ifs.good())
{
std::getline(ifs,line);
firstChar = line.find_first_not_of("\t ");
}
//check for ascii keyword solid
if(strnicmp("solid",&line[firstChar],5) == 0)
{
return STLA;
}
ifs.close();
//if the file does not start with solid it is probably STLB
//check the file size to verify it.
//open the file
FILE* in = fopen(_filename.c_str(), "rb");
if (!in) return NONE;
// determine endian mode
union { unsigned int i; unsigned char c[4]; } endian_test;
endian_test.i = 1;
bool swapFlag = (endian_test.c[3] == 1);
// read number of triangles
char dummy[100];
fread(dummy, 1, 80, in);
size_t nT = read_int(in, swapFlag);
// compute file size from nT
size_t binary_size = 84 + nT*50;
// get actual file size
size_t file_size(0);
rewind(in);
while (!feof(in))
file_size += fread(dummy, 1, 100, in);
fclose(in);
// if sizes match -> it's STLB
return (binary_size == file_size ? STLB : NONE);
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,151 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements an reader module for STL files
//
//=============================================================================
#ifndef __STLREADER_HH__
#define __STLREADER_HH__
//=== INCLUDES ================================================================
#include <stdio.h>
#include <string>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/reader/BaseReader.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//== FORWARDS =================================================================
class BaseImporter;
//== IMPLEMENTATION ===========================================================
/**
Implementation of the STL format reader. This class is singleton'ed by
SingletonT to STLReader.
*/
class OPENMESHDLLEXPORT _STLReader_ : public BaseReader
{
public:
// constructor
_STLReader_();
/// Destructor
virtual ~_STLReader_() {};
std::string get_description() const
{ return "Stereolithography Interface Format"; }
std::string get_extensions() const { return "stl stla stlb"; }
bool read(const std::string& _filename,
BaseImporter& _bi,
Options& _opt);
bool read(std::istream& _in,
BaseImporter& _bi,
Options& _opt);
/** Set the threshold to be used for considering two point to be equal.
Can be used to merge small gaps */
void set_epsilon(float _eps) { eps_=_eps; }
/// Returns the threshold to be used for considering two point to be equal.
float epsilon() const { return eps_; }
private:
enum STL_Type { STLA, STLB, NONE };
STL_Type check_stl_type(const std::string& _filename) const;
bool read_stla(const std::string& _filename, BaseImporter& _bi, Options& _opt) const;
bool read_stla(std::istream& _in, BaseImporter& _bi, Options& _opt) const;
bool read_stlb(const std::string& _filename, BaseImporter& _bi, Options& _opt) const;
bool read_stlb(std::istream& _in, BaseImporter& _bi, Options& _opt) const;
private:
float eps_;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the STL reader
extern _STLReader_ __STLReaderInstance;
OPENMESHDLLEXPORT _STLReader_& STLReader();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,107 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=== INCLUDES ================================================================
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
#if defined(OM_CC_MIPS)
# include <ctype.h>
#else
#endif
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
#ifndef DOXY_IGNORE_THIS
static inline char tolower(char c)
{
using namespace std;
return ::tolower(c);
}
#endif
//-----------------------------------------------------------------------------
bool
BaseWriter::
can_u_write(const std::string& _filename) const
{
// get file extension
std::string extension;
std::string::size_type pos(_filename.rfind("."));
if (pos != std::string::npos)
extension = _filename.substr(pos+1, _filename.length()-pos-1);
else
extension = _filename; //check, if the whole filename defines the extension
std::transform( extension.begin(), extension.end(),
extension.begin(), tolower );
// locate extension in extension string
return (get_extensions().find(extension) != std::string::npos);
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,155 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements the baseclass for IOManager writer modules
//
//=============================================================================
#ifndef __BASEWRITER_HH__
#define __BASEWRITER_HH__
//=== INCLUDES ================================================================
// STD C++
#include <iosfwd>
#include <string>
// OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/IO/Options.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
Base class for all writer modules. The module should register itself at
the IOManager by calling the register_module function.
*/
class OPENMESHDLLEXPORT BaseWriter
{
public:
typedef unsigned int Option;
/// Destructor
virtual ~BaseWriter() {};
/// Return short description of the supported file format.
virtual std::string get_description() const = 0;
/// Return file format's extension.
virtual std::string get_extensions() const = 0;
/** \brief Returns true if writer can write _filename (checks extension).
* _filename can also provide an extension without a name for a file e.g. _filename == "om" checks, if the writer can write the "om" extension
* @param _filename complete name of a file or just the extension
* @result true, if writer can write data with the given extension
*/
virtual bool can_u_write(const std::string& _filename) const;
/** Write to a file
* @param _filename write to file with the given filename
* @param _be BaseExporter, which specifies the data source
* @param _opt writing options
* @param _precision can be used to specify the precision of the floating point notation.
*/
virtual bool write(const std::string& _filename,
BaseExporter& _be,
Options _opt,
std::streamsize _precision = 6) const = 0;
/** Write to a std::ostream
* @param _os write to std::ostream
* @param _be BaseExporter, which specifies the data source
* @param _opt writing options
* @param _precision can be used to specify the precision of the floating point notation.
*/
virtual bool write(std::ostream& _os,
BaseExporter& _be,
Options _opt,
std::streamsize _precision = 6) const = 0;
/// Returns expected size of file if binary format is supported else 0.
virtual size_t binary_size(BaseExporter&, Options) const { return 0; }
protected:
bool check(BaseExporter& _be, Options _opt) const
{
return (_opt.check(Options::VertexNormal ) <= _be.has_vertex_normals())
&& (_opt.check(Options::VertexTexCoord)<= _be.has_vertex_texcoords())
&& (_opt.check(Options::VertexColor) <= _be.has_vertex_colors())
&& (_opt.check(Options::FaceNormal) <= _be.has_face_normals())
&& (_opt.check(Options::FaceColor) <= _be.has_face_colors());
}
};
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,401 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
//STL
#include <fstream>
#include <limits>
// OpenMesh
#include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/IO/writer/OBJWriter.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the OBJLoader singleton with MeshLoader
_OBJWriter_ __OBJWriterinstance;
_OBJWriter_& OBJWriter() { return __OBJWriterinstance; }
//=== IMPLEMENTATION ==========================================================
_OBJWriter_::_OBJWriter_() { IOManager().register_module(this); }
//-----------------------------------------------------------------------------
bool
_OBJWriter_::
write(const std::string& _filename, BaseExporter& _be, Options _opt, std::streamsize _precision) const
{
std::fstream out(_filename.c_str(), std::ios_base::out );
if (!out)
{
omerr() << "[OBJWriter] : cannot open file "
<< _filename << std::endl;
return false;
}
out.precision(_precision);
{
#if defined(WIN32)
std::string::size_type dot = _filename.find_last_of("\\/");
#else
std::string::size_type dot = _filename.rfind("/");
#endif
if (dot == std::string::npos){
path_ = "./";
objName_ = _filename;
}else{
path_ = _filename.substr(0,dot+1);
objName_ = _filename.substr(dot+1);
}
//remove the file extension
dot = objName_.find_last_of(".");
if(dot != std::string::npos)
objName_ = objName_.substr(0,dot);
}
bool result = write(out, _be, _opt, _precision);
out.close();
return result;
}
//-----------------------------------------------------------------------------
size_t _OBJWriter_::getMaterial(OpenMesh::Vec3f _color) const
{
for (size_t i=0; i < material_.size(); i++)
if(material_[i] == _color)
return i;
//not found add new material
material_.push_back( _color );
return material_.size()-1;
}
//-----------------------------------------------------------------------------
size_t _OBJWriter_::getMaterial(OpenMesh::Vec4f _color) const
{
for (size_t i=0; i < materialA_.size(); i++)
if(materialA_[i] == _color)
return i;
//not found add new material
materialA_.push_back( _color );
return materialA_.size()-1;
}
//-----------------------------------------------------------------------------
bool
_OBJWriter_::
writeMaterial(std::ostream& _out, BaseExporter& _be, Options _opt) const
{
OpenMesh::Vec3f c;
OpenMesh::Vec4f cA;
material_.clear();
materialA_.clear();
//iterate over faces
for (size_t i=0, nF=_be.n_faces(); i<nF; ++i)
{
//color with alpha
if ( _opt.color_has_alpha() ){
cA = color_cast<OpenMesh::Vec4f> (_be.colorA( FaceHandle(int(i)) ));
getMaterial(cA);
}else{
//and without alpha
c = color_cast<OpenMesh::Vec3f> (_be.color( FaceHandle(int(i)) ));
getMaterial(c);
}
}
//write the materials
if ( _opt.color_has_alpha() )
for (size_t i=0; i < materialA_.size(); i++){
_out << "newmtl " << "mat" << i << '\n';
_out << "Ka 0.5000 0.5000 0.5000" << '\n';
_out << "Kd " << materialA_[i][0] << ' ' << materialA_[i][1] << ' ' << materialA_[i][2] << '\n';
_out << "Tr " << materialA_[i][3] << '\n';
_out << "illum 1" << '\n';
}
else
for (size_t i=0; i < material_.size(); i++){
_out << "newmtl " << "mat" << i << '\n';
_out << "Ka 0.5000 0.5000 0.5000" << '\n';
_out << "Kd " << material_[i][0] << ' ' << material_[i][1] << ' ' << material_[i][2] << '\n';
_out << "illum 1" << '\n';
}
return true;
}
//-----------------------------------------------------------------------------
bool
_OBJWriter_::
write(std::ostream& _out, BaseExporter& _be, Options _opt, std::streamsize _precision) const
{
unsigned int idx;
size_t i, j,nV, nF;
Vec3f v, n;
Vec2f t;
VertexHandle vh;
std::vector<VertexHandle> vhandles;
bool useMatrial = false;
OpenMesh::Vec3f c;
OpenMesh::Vec4f cA;
omlog() << "[OBJWriter] : write file\n";
_out.precision(_precision);
// check exporter features
if (!check( _be, _opt))
return false;
// No binary mode for OBJ
if ( _opt.check(Options::Binary) ) {
omout() << "[OBJWriter] : Warning, Binary mode requested for OBJ Writer (No support for Binary mode), falling back to standard." << std::endl;
}
// check for unsupported writer features
if (_opt.check(Options::FaceNormal) ) {
omerr() << "[OBJWriter] : FaceNormal not supported by OBJ Writer" << std::endl;
return false;
}
// check for unsupported writer features
if (_opt.check(Options::VertexColor) ) {
omerr() << "[OBJWriter] : VertexColor not supported by OBJ Writer" << std::endl;
return false;
}
//create material file if needed
if ( _opt.check(Options::FaceColor) ){
std::string matFile = path_ + objName_ + ".mat";
std::fstream matStream(matFile.c_str(), std::ios_base::out );
if (!matStream)
{
omerr() << "[OBJWriter] : cannot write material file " << matFile << std::endl;
}else{
useMatrial = writeMaterial(matStream, _be, _opt);
matStream.close();
}
}
// header
_out << "# " << _be.n_vertices() << " vertices, ";
_out << _be.n_faces() << " faces" << '\n';
// material file
if (useMatrial && _opt.check(Options::FaceColor) )
_out << "mtllib " << objName_ << ".mat" << '\n';
std::map<Vec2f,int> texMap;
//collect Texturevertices from halfedges
if(_opt.check(Options::FaceTexCoord))
{
std::vector<Vec2f> texCoords;
//add all texCoords to map
unsigned int num = _be.get_face_texcoords(texCoords);
for(unsigned int i = 0; i < num ; ++i)
{
texMap[texCoords[i]] = i;
}
}
//collect Texture coordinates from vertices
if(_opt.check(Options::VertexTexCoord))
{
for (size_t i=0, nV=_be.n_vertices(); i<nV; ++i)
{
vh = VertexHandle(static_cast<int>(i));
t = _be.texcoord(vh);
texMap[t] = static_cast<int>(i);
}
}
// assign each texcoord in the map its id
// and write the vt entries
if(_opt.check(Options::VertexTexCoord) || _opt.check(Options::FaceTexCoord))
{
int texCount = 0;
for(std::map<Vec2f,int>::iterator it = texMap.begin(); it != texMap.end() ; ++it)
{
_out << "vt " << it->first[0] << " " << it->first[1] << '\n';
it->second = ++texCount;
}
}
// vertex data (point, normals, texcoords)
for (i=0, nV=_be.n_vertices(); i<nV; ++i)
{
vh = VertexHandle(int(i));
v = _be.point(vh);
n = _be.normal(vh);
t = _be.texcoord(vh);
_out << "v " << v[0] <<" "<< v[1] <<" "<< v[2] << '\n';
if (_opt.check(Options::VertexNormal))
_out << "vn " << n[0] <<" "<< n[1] <<" "<< n[2] << '\n';
}
size_t lastMat = std::numeric_limits<std::size_t>::max();
// we do not want to write seperators if we only write vertex indices
bool onlyVertices = !_opt.check(Options::VertexTexCoord)
&& !_opt.check(Options::VertexNormal)
&& !_opt.check(Options::FaceTexCoord);
// faces (indices starting at 1 not 0)
for (i=0, nF=_be.n_faces(); i<nF; ++i)
{
if (useMatrial && _opt.check(Options::FaceColor) ){
size_t material = std::numeric_limits<std::size_t>::max();
//color with alpha
if ( _opt.color_has_alpha() ){
cA = color_cast<OpenMesh::Vec4f> (_be.colorA( FaceHandle(int(i)) ));
material = getMaterial(cA);
} else{
//and without alpha
c = color_cast<OpenMesh::Vec3f> (_be.color( FaceHandle(int(i)) ));
material = getMaterial(c);
}
// if we are ina a new material block, specify in the file which material to use
if(lastMat != material) {
_out << "usemtl mat" << material << '\n';
lastMat = material;
}
}
_out << "f";
_be.get_vhandles(FaceHandle(int(i)), vhandles);
for (j=0; j< vhandles.size(); ++j)
{
// Write vertex index
idx = vhandles[j].idx() + 1;
_out << " " << idx;
if (!onlyVertices) {
// write separator
_out << "/" ;
//write texCoords index from halfedge
if(_opt.check(Options::FaceTexCoord))
{
_out << texMap[_be.texcoord(_be.getHeh(FaceHandle(int(i)),vhandles[j]))];
}
else
{
// write vertex texture coordinate index
if (_opt.check(Options::VertexTexCoord))
_out << texMap[_be.texcoord(vhandles[j])];
}
// write vertex normal index
if ( _opt.check(Options::VertexNormal) ) {
// write separator
_out << "/" ;
_out << idx;
}
}
}
_out << '\n';
}
material_.clear();
materialA_.clear();
return true;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,136 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements an IOManager writer module for OBJ files
//
//=============================================================================
#ifndef __OBJWRITER_HH__
#define __OBJWRITER_HH__
//=== INCLUDES ================================================================
#include <string>
#include <fstream>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
This class defines the OBJ writer. This class is further singleton'ed
by SingletonT to OBJWriter.
*/
class OPENMESHDLLEXPORT _OBJWriter_ : public BaseWriter
{
public:
_OBJWriter_();
/// Destructor
virtual ~_OBJWriter_() {};
std::string get_description() const { return "Alias/Wavefront"; }
std::string get_extensions() const { return "obj"; }
bool write(const std::string&, BaseExporter&, Options, std::streamsize _precision = 6) const;
bool write(std::ostream&, BaseExporter&, Options, std::streamsize _precision = 6) const;
size_t binary_size(BaseExporter&, Options) const { return 0; }
private:
mutable std::string path_;
mutable std::string objName_;
mutable std::vector< OpenMesh::Vec3f > material_;
mutable std::vector< OpenMesh::Vec4f > materialA_;
size_t getMaterial(OpenMesh::Vec3f _color) const;
size_t getMaterial(OpenMesh::Vec4f _color) const;
bool writeMaterial(std::ostream& _out, BaseExporter&, Options) const;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the OBJ writer
extern _OBJWriter_ __OBJWriterinstance;
OPENMESHDLLEXPORT _OBJWriter_& OBJWriter();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,527 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
#include <fstream>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Utils/Endian.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/IO/writer/OFFWriter.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the OFFLoader singleton with MeshLoader
_OFFWriter_ __OFFWriterInstance;
_OFFWriter_& OFFWriter() { return __OFFWriterInstance; }
//=== IMPLEMENTATION ==========================================================
_OFFWriter_::_OFFWriter_() { IOManager().register_module(this); }
//-----------------------------------------------------------------------------
bool
_OFFWriter_::
write(const std::string& _filename, BaseExporter& _be, Options _opt, std::streamsize _precision) const
{
std::ofstream out(_filename.c_str(), (_opt.check(Options::Binary) ? std::ios_base::binary | std::ios_base::out
: std::ios_base::out) );
return write(out, _be, _opt, _precision);
}
//-----------------------------------------------------------------------------
bool
_OFFWriter_::
write(std::ostream& _os, BaseExporter& _be, Options _opt, std::streamsize _precision) const
{
// check exporter features
if ( !check( _be, _opt ) )
return false;
// check writer features
if ( _opt.check(Options::FaceNormal) ) // not supported by format
return false;
if (!_os.good())
{
omerr() << "[OFFWriter] : cannot write to stream "
<< std::endl;
return false;
}
// write header line
if (_opt.check(Options::VertexTexCoord)) _os << "ST";
if (_opt.check(Options::VertexColor) || _opt.check(Options::FaceColor)) _os << "C";
if (_opt.check(Options::VertexNormal)) _os << "N";
_os << "OFF";
if (_opt.check(Options::Binary)) _os << " BINARY";
_os << "\n";
if (!_opt.check(Options::Binary))
_os.precision(_precision);
// write to file
bool result = (_opt.check(Options::Binary) ?
write_binary(_os, _be, _opt) :
write_ascii(_os, _be, _opt));
// return result
return result;
}
//-----------------------------------------------------------------------------
bool
_OFFWriter_::
write_ascii(std::ostream& _out, BaseExporter& _be, Options _opt) const
{
unsigned int i, nV, nF;
Vec3f v, n;
Vec2f t;
OpenMesh::Vec3i c;
OpenMesh::Vec4i cA;
OpenMesh::Vec3f cf;
OpenMesh::Vec4f cAf;
VertexHandle vh;
std::vector<VertexHandle> vhandles;
// #vertices, #faces
_out << _be.n_vertices() << " ";
_out << _be.n_faces() << " ";
_out << 0 << "\n";
if (_opt.color_is_float())
_out << std::fixed;
// vertex data (point, normals, colors, texcoords)
for (i=0, nV=int(_be.n_vertices()); i<nV; ++i)
{
vh = VertexHandle(i);
v = _be.point(vh);
//Vertex
_out << v[0] << " " << v[1] << " " << v[2];
// VertexNormal
if ( _opt.vertex_has_normal() ) {
n = _be.normal(vh);
_out << " " << n[0] << " " << n[1] << " " << n[2];
}
// VertexColor
if ( _opt.vertex_has_color() ) {
if ( _opt.color_is_float() ) {
//with alpha
if ( _opt.color_has_alpha() ){
cAf = _be.colorAf(vh);
_out << " " << cAf;
}else{
//without alpha
cf = _be.colorf(vh);
_out << " " << cf;
}
} else {
//with alpha
if ( _opt.color_has_alpha() ){
cA = _be.colorA(vh);
_out << " " << cA;
}else{
//without alpha
c = _be.color(vh);
_out << " " << c;
}
}
}
// TexCoord
if (_opt.vertex_has_texcoord() ) {
t = _be.texcoord(vh);
_out << " " << t[0] << " " << t[1];
}
_out << '\n';
}
// faces (indices starting at 0)
if (_be.is_triangle_mesh())
{
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
{
_be.get_vhandles(FaceHandle(i), vhandles);
_out << 3 << " ";
_out << vhandles[0].idx() << " ";
_out << vhandles[1].idx() << " ";
_out << vhandles[2].idx();
//face color
if ( _opt.face_has_color() ){
if ( _opt.color_is_float() ) {
//with alpha
if ( _opt.color_has_alpha() ){
cAf = _be.colorAf( FaceHandle(i) );
_out << " " << cAf;
}else{
//without alpha
cf = _be.colorf( FaceHandle(i) );
_out << " " << cf;
}
} else {
//with alpha
if ( _opt.color_has_alpha() ){
cA = _be.colorA( FaceHandle(i) );
_out << " " << cA;
}else{
//without alpha
c = _be.color( FaceHandle(i) );
_out << " " << c;
}
}
}
_out << '\n';
}
}
else
{
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
{
nV = _be.get_vhandles(FaceHandle(i), vhandles);
_out << nV << " ";
for (size_t j=0; j<vhandles.size(); ++j)
_out << vhandles[j].idx() << " ";
//face color
if ( _opt.face_has_color() ){
if ( _opt.color_is_float() ) {
//with alpha
if ( _opt.color_has_alpha() ){
cAf = _be.colorAf( FaceHandle(i) );
_out << " " << cAf;
}else{
//without alpha
cf = _be.colorf( FaceHandle(i) );
_out << " " << cf;
}
} else {
//with alpha
if ( _opt.color_has_alpha() ){
cA = _be.colorA( FaceHandle(i) );
_out << " " << cA;
}else{
//without alpha
c = _be.color( FaceHandle(i) );
_out << " " << c;
}
}
}
_out << '\n';
}
}
return true;
}
//-----------------------------------------------------------------------------
void _OFFWriter_::writeValue(std::ostream& _out, int value) const {
uint32_t tmp = value;
store(_out, tmp, false);
}
void _OFFWriter_::writeValue(std::ostream& _out, unsigned int value) const {
uint32_t tmp = value;
store(_out, tmp, false);
}
void _OFFWriter_::writeValue(std::ostream& _out, float value) const {
float32_t tmp = value;
store(_out, tmp, false);
}
bool
_OFFWriter_::
write_binary(std::ostream& _out, BaseExporter& _be, Options _opt) const
{
unsigned int i, nV, nF;
Vec3f v, n;
Vec2f t;
OpenMesh::Vec4i c;
OpenMesh::Vec4f cf;
VertexHandle vh;
std::vector<VertexHandle> vhandles;
// #vertices, #faces
writeValue(_out, (uint)_be.n_vertices() );
writeValue(_out, (uint) _be.n_faces() );
writeValue(_out, 0 );
// vertex data (point, normals, texcoords)
for (i=0, nV=int(_be.n_vertices()); i<nV; ++i)
{
vh = VertexHandle(i);
v = _be.point(vh);
//vertex
writeValue(_out, v[0]);
writeValue(_out, v[1]);
writeValue(_out, v[2]);
// vertex normal
if ( _opt.vertex_has_normal() ) {
n = _be.normal(vh);
writeValue(_out, n[0]);
writeValue(_out, n[1]);
writeValue(_out, n[2]);
}
// vertex color
if ( _opt.vertex_has_color() ) {
if ( _opt.color_is_float() ) {
cf = _be.colorAf(vh);
writeValue(_out, cf[0]);
writeValue(_out, cf[1]);
writeValue(_out, cf[2]);
if ( _opt.color_has_alpha() )
writeValue(_out, cf[3]);
} else {
c = _be.colorA(vh);
writeValue(_out, c[0]);
writeValue(_out, c[1]);
writeValue(_out, c[2]);
if ( _opt.color_has_alpha() )
writeValue(_out, c[3]);
}
}
// texCoords
if (_opt.vertex_has_texcoord() ) {
t = _be.texcoord(vh);
writeValue(_out, t[0]);
writeValue(_out, t[1]);
}
}
// faces (indices starting at 0)
if (_be.is_triangle_mesh())
{
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
{
//face
_be.get_vhandles(FaceHandle(i), vhandles);
writeValue(_out, 3);
writeValue(_out, vhandles[0].idx());
writeValue(_out, vhandles[1].idx());
writeValue(_out, vhandles[2].idx());
//face color
if ( _opt.face_has_color() ){
if ( _opt.color_is_float() ) {
cf = _be.colorAf( FaceHandle(i) );
writeValue(_out, cf[0]);
writeValue(_out, cf[1]);
writeValue(_out, cf[2]);
if ( _opt.color_has_alpha() )
writeValue(_out, cf[3]);
} else {
c = _be.colorA( FaceHandle(i) );
writeValue(_out, c[0]);
writeValue(_out, c[1]);
writeValue(_out, c[2]);
if ( _opt.color_has_alpha() )
writeValue(_out, c[3]);
}
}
}
}
else
{
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
{
//face
nV = _be.get_vhandles(FaceHandle(i), vhandles);
writeValue(_out, nV);
for (size_t j=0; j<vhandles.size(); ++j)
writeValue(_out, vhandles[j].idx() );
//face color
if ( _opt.face_has_color() ){
if ( _opt.color_is_float() ) {
cf = _be.colorAf( FaceHandle(i) );
writeValue(_out, cf[0]);
writeValue(_out, cf[1]);
writeValue(_out, cf[2]);
if ( _opt.color_has_alpha() )
writeValue(_out, cf[3]);
} else {
c = _be.colorA( FaceHandle(i) );
writeValue(_out, c[0]);
writeValue(_out, c[1]);
writeValue(_out, c[2]);
if ( _opt.color_has_alpha() )
writeValue(_out, c[3]);
}
}
}
}
return true;
}
// ----------------------------------------------------------------------------
size_t
_OFFWriter_::
binary_size(BaseExporter& _be, Options _opt) const
{
size_t header(0);
size_t data(0);
size_t _3floats(3*sizeof(float));
size_t _3ui(3*sizeof(unsigned int));
size_t _4ui(4*sizeof(unsigned int));
if ( !_opt.is_binary() )
return 0;
else
{
size_t _3longs(3*sizeof(long));
header += 11; // 'OFF BINARY\n'
header += _3longs; // #V #F #E
data += _be.n_vertices() * _3floats; // vertex data
}
if ( _opt.vertex_has_normal() && _be.has_vertex_normals() )
{
header += 1; // N
data += _be.n_vertices() * _3floats;
}
if ( _opt.vertex_has_color() && _be.has_vertex_colors() )
{
header += 1; // C
data += _be.n_vertices() * _3floats;
}
if ( _opt.vertex_has_texcoord() && _be.has_vertex_texcoords() )
{
size_t _2floats(2*sizeof(float));
header += 2; // ST
data += _be.n_vertices() * _2floats;
}
// topology
if (_be.is_triangle_mesh())
{
data += _be.n_faces() * _4ui;
}
else
{
unsigned int i, nF;
std::vector<VertexHandle> vhandles;
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
data += _be.get_vhandles(FaceHandle(i), vhandles) * sizeof(unsigned int);
}
// face colors
if ( _opt.face_has_color() && _be.has_face_colors() ){
if ( _opt.color_has_alpha() )
data += _be.n_faces() * _4ui;
else
data += _be.n_faces() * _3ui;
}
return header+data;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,138 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a writer module for OFF files
//
//=============================================================================
#ifndef __OFFWRITER_HH__
#define __OFFWRITER_HH__
//=== INCLUDES ================================================================
#include <string>
#include <ostream>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
Implementation of the OFF format writer. This class is singleton'ed by
SingletonT to OFFWriter.
By passing Options to the write function you can manipulate the writing behavoir.
The following options can be set:
Binary
VertexNormal
VertexColor
VertexTexCoord
FaceColor
ColorAlpha
*/
class OPENMESHDLLEXPORT _OFFWriter_ : public BaseWriter
{
public:
_OFFWriter_();
virtual ~_OFFWriter_() {};
std::string get_description() const { return "no description"; }
std::string get_extensions() const { return "off"; }
bool write(const std::string&, BaseExporter&, Options, std::streamsize _precision = 6) const;
bool write(std::ostream&, BaseExporter&, Options, std::streamsize _precision = 6) const;
size_t binary_size(BaseExporter& _be, Options _opt) const;
protected:
void writeValue(std::ostream& _out, int value) const;
void writeValue(std::ostream& _out, unsigned int value) const;
void writeValue(std::ostream& _out, float value) const;
bool write_ascii(std::ostream& _in, BaseExporter&, Options) const;
bool write_binary(std::ostream& _in, BaseExporter&, Options) const;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the OFF writer.
extern _OFFWriter_ __OFFWriterInstance;
OPENMESHDLLEXPORT _OFFWriter_& OFFWriter();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,515 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
// -------------------- STL
#if defined( OM_CC_MIPS )
#include <time.h>
#include <string.h>
#else
#include <ctime>
#include <cstring>
#endif
#include <fstream>
#include <vector>
// -------------------- OpenMesh
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
#include <OpenMesh/Core/IO/writer/OMWriter.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the OMLoader singleton with MeshLoader
_OMWriter_ __OMWriterInstance;
_OMWriter_& OMWriter() { return __OMWriterInstance; }
//=== IMPLEMENTATION ==========================================================
const OMFormat::uchar _OMWriter_::magic_[3] = "OM";
const OMFormat::uint8 _OMWriter_::version_ = OMFormat::mk_version(1,2);
_OMWriter_::
_OMWriter_()
{
IOManager().register_module(this);
}
bool
_OMWriter_::write(const std::string& _filename, BaseExporter& _be,
Options _opt, std::streamsize /*_precision*/) const
{
// check whether exporter can give us an OpenMesh BaseKernel
if (!_be.kernel()) return false;
// check for om extension in filename, we can only handle OM
if (_filename.rfind(".om") == std::string::npos)
return false;
_opt += Options::Binary; // only binary format supported
std::ofstream ofs(_filename.c_str(), std::ios::binary);
// check if file is open
if (!ofs.is_open())
{
omerr() << "[OMWriter] : cannot open file " << _filename << std::endl;
return false;
}
// call stream save method
bool rc = write(ofs, _be, _opt);
// close filestream
ofs.close();
// return success/failure notice
return rc;
}
//-----------------------------------------------------------------------------
bool
_OMWriter_::write(std::ostream& _os, BaseExporter& _be, Options _opt, std::streamsize /*_precision*/) const
{
// std::clog << "[OMWriter]::write( stream )\n";
// check exporter features
if ( !check( _be, _opt ) )
{
omerr() << "[OMWriter]: exporter does not support wanted feature!\n";
return false;
}
// Maybe an ascii version will be implemented in the future.
// For now, support only a binary format
if ( !_opt.check( Options::Binary ) )
_opt += Options::Binary;
// Ignore LSB/MSB bit. Always store in LSB (little endian)
_opt += Options::LSB;
_opt -= Options::MSB;
return write_binary(_os, _be, _opt);
}
//-----------------------------------------------------------------------------
#ifndef DOXY_IGNORE_THIS
template <typename T> struct Enabler
{
explicit Enabler( T& obj ) : obj_(obj)
{}
~Enabler() { obj_.enable(); }
T& obj_;
};
#endif
bool _OMWriter_::write_binary(std::ostream& _os, BaseExporter& _be,
Options _opt) const
{
#ifndef DOXY_IGNORE_THIS
Enabler<mostream> enabler(omlog());
#endif
size_t bytes = 0;
bool swap = _opt.check(Options::Swap) || (Endian::local() == Endian::MSB);
unsigned int i, nV, nF;
Vec3f v;
Vec2f t;
std::vector<VertexHandle> vhandles;
// -------------------- write header
OMFormat::Header header;
header.magic_[0] = 'O';
header.magic_[1] = 'M';
header.mesh_ = _be.is_triangle_mesh() ? 'T' : 'P';
header.version_ = version_;
header.n_vertices_ = int(_be.n_vertices());
header.n_faces_ = int(_be.n_faces());
header.n_edges_ = int(_be.n_edges());
bytes += store( _os, header, swap );
// ---------------------------------------- write chunks
OMFormat::Chunk::Header chunk_header;
// -------------------- write vertex data
// ---------- write vertex position
if (_be.n_vertices())
{
v = _be.point(VertexHandle(0));
chunk_header.reserved_ = 0;
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
chunk_header.type_ = OMFormat::Chunk::Type_Pos;
chunk_header.signed_ = OMFormat::is_signed(v[0]);
chunk_header.float_ = OMFormat::is_float(v[0]);
chunk_header.dim_ = OMFormat::dim(v);
chunk_header.bits_ = OMFormat::bits(v[0]);
bytes += store( _os, chunk_header, swap );
for (i=0, nV=header.n_vertices_; i<nV; ++i)
bytes += vector_store( _os, _be.point(VertexHandle(i)), swap );
}
// ---------- write vertex normal
if (_be.n_vertices() && _opt.check( Options::VertexNormal ))
{
Vec3f n = _be.normal(VertexHandle(0));
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
chunk_header.type_ = OMFormat::Chunk::Type_Normal;
chunk_header.signed_ = OMFormat::is_signed(n[0]);
chunk_header.float_ = OMFormat::is_float(n[0]);
chunk_header.dim_ = OMFormat::dim(n);
chunk_header.bits_ = OMFormat::bits(n[0]);
bytes += store( _os, chunk_header, swap );
for (i=0, nV=header.n_vertices_; i<nV; ++i)
bytes += vector_store( _os, _be.normal(VertexHandle(i)), swap );
}
// ---------- write vertex color
if (_be.n_vertices() && _opt.check( Options::VertexColor ) && _be.has_vertex_colors() )
{
Vec3uc c = _be.color(VertexHandle(0));
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
chunk_header.type_ = OMFormat::Chunk::Type_Color;
chunk_header.signed_ = OMFormat::is_signed( c[0] );
chunk_header.float_ = OMFormat::is_float( c[0] );
chunk_header.dim_ = OMFormat::dim( c );
chunk_header.bits_ = OMFormat::bits( c[0] );
bytes += store( _os, chunk_header, swap );
for (i=0, nV=header.n_vertices_; i<nV; ++i)
bytes += vector_store( _os, _be.color(VertexHandle(i)), swap );
}
// ---------- write vertex texture coords
if (_be.n_vertices() && _opt.check(Options::VertexTexCoord)) {
t = _be.texcoord(VertexHandle(0));
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Vertex;
chunk_header.type_ = OMFormat::Chunk::Type_Texcoord;
chunk_header.signed_ = OMFormat::is_signed(t[0]);
chunk_header.float_ = OMFormat::is_float(t[0]);
chunk_header.dim_ = OMFormat::dim(t);
chunk_header.bits_ = OMFormat::bits(t[0]);
// std::clog << chunk_header << std::endl;
bytes += store(_os, chunk_header, swap);
for (i = 0, nV = header.n_vertices_; i < nV; ++i)
bytes += vector_store(_os, _be.texcoord(VertexHandle(i)), swap);
}
// -------------------- write face data
// ---------- write topology
{
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
chunk_header.type_ = OMFormat::Chunk::Type_Topology;
chunk_header.signed_ = 0;
chunk_header.float_ = 0;
chunk_header.dim_ = OMFormat::Chunk::Dim_1D; // ignored
chunk_header.bits_ = OMFormat::needed_bits(_be.n_vertices());
bytes += store( _os, chunk_header, swap );
for (i=0, nF=header.n_faces_; i<nF; ++i)
{
//nV = _be.get_vhandles(FaceHandle(i), vhandles);
_be.get_vhandles(FaceHandle(i), vhandles);
if ( header.mesh_ == 'P' )
bytes += store( _os, vhandles.size(), OMFormat::Chunk::Integer_16, swap );
for (size_t j=0; j < vhandles.size(); ++j)
{
using namespace OMFormat;
using namespace GenProg;
bytes += store( _os, vhandles[j].idx(), Chunk::Integer_Size(chunk_header.bits_), swap );
}
}
}
// ---------- write face normals
if (_be.n_faces() && _be.has_face_normals() && _opt.check(Options::FaceNormal) )
{
#define NEW_STYLE 0
#if NEW_STYLE
const BaseProperty *bp = _be.kernel()._get_fprop("f:normals");
if (bp)
{
#endif
Vec3f n = _be.normal(FaceHandle(0));
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
chunk_header.type_ = OMFormat::Chunk::Type_Normal;
chunk_header.signed_ = OMFormat::is_signed(n[0]);
chunk_header.float_ = OMFormat::is_float(n[0]);
chunk_header.dim_ = OMFormat::dim(n);
chunk_header.bits_ = OMFormat::bits(n[0]);
bytes += store( _os, chunk_header, swap );
#if !NEW_STYLE
for (i=0, nF=header.n_faces_; i<nF; ++i)
bytes += vector_store( _os, _be.normal(FaceHandle(i)), swap );
#else
bytes += bp->store(_os, swap );
}
else
return false;
#endif
#undef NEW_STYLE
}
// ---------- write face color
if (_be.n_faces() && _be.has_face_colors() && _opt.check( Options::FaceColor ))
{
#define NEW_STYLE 0
#if NEW_STYLE
const BaseProperty *bp = _be.kernel()._get_fprop("f:colors");
if (bp)
{
#endif
Vec3uc c;
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Face;
chunk_header.type_ = OMFormat::Chunk::Type_Color;
chunk_header.signed_ = OMFormat::is_signed( c[0] );
chunk_header.float_ = OMFormat::is_float( c[0] );
chunk_header.dim_ = OMFormat::dim( c );
chunk_header.bits_ = OMFormat::bits( c[0] );
bytes += store( _os, chunk_header, swap );
#if !NEW_STYLE
for (i=0, nF=header.n_faces_; i<nF; ++i)
bytes += vector_store( _os, _be.color(FaceHandle(i)), swap );
#else
bytes += bp->store(_os, swap);
}
else
return false;
#endif
}
// -------------------- write custom properties
BaseKernel::const_prop_iterator prop;
for (prop = _be.kernel()->vprops_begin();
prop != _be.kernel()->vprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Vertex, swap );
}
for (prop = _be.kernel()->fprops_begin();
prop != _be.kernel()->fprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Face, swap );
}
for (prop = _be.kernel()->eprops_begin();
prop != _be.kernel()->eprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Edge, swap );
}
for (prop = _be.kernel()->hprops_begin();
prop != _be.kernel()->hprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Halfedge, swap );
}
for (prop = _be.kernel()->mprops_begin();
prop != _be.kernel()->mprops_end(); ++prop)
{
if ( !*prop ) continue;
if ( (*prop)->name()[1]==':') continue;
bytes += store_binary_custom_chunk(_os, **prop,
OMFormat::Chunk::Entity_Mesh, swap );
}
memset(&chunk_header, 0, sizeof(chunk_header));
chunk_header.name_ = false;
chunk_header.entity_ = OMFormat::Chunk::Entity_Sentinel;
bytes += store(_os, chunk_header, swap);
std::clog << "#bytes written: " << bytes << std::endl;
return true;
}
// ----------------------------------------------------------------------------
size_t _OMWriter_::store_binary_custom_chunk(std::ostream& _os,
const BaseProperty& _bp,
OMFormat::Chunk::Entity _entity,
bool _swap) const
{
//omlog() << "Custom Property " << OMFormat::as_string(_entity) << " property ["
// << _bp.name() << "]" << std::endl;
// Don't store if
// 1. it is not persistent
// 2. it's name is empty
if ( !_bp.persistent() || _bp.name().empty() )
{
//omlog() << " skipped\n";
return 0;
}
size_t bytes = 0;
OMFormat::Chunk::esize_t element_size = OMFormat::Chunk::esize_t(_bp.element_size());
OMFormat::Chunk::Header chdr;
// set header
chdr.name_ = true;
chdr.entity_ = _entity;
chdr.type_ = OMFormat::Chunk::Type_Custom;
chdr.signed_ = 0;
chdr.float_ = 0;
chdr.dim_ = OMFormat::Chunk::Dim_1D; // ignored
chdr.bits_ = element_size;
// write custom chunk
// 1. chunk header
bytes += store( _os, chdr, _swap );
// 2. property name
bytes += store( _os, OMFormat::Chunk::PropertyName(_bp.name()), _swap );
// 3. block size
bytes += store( _os, _bp.size_of(), OMFormat::Chunk::Integer_32, _swap );
//omlog() << " n_bytes = " << _bp.size_of() << std::endl;
// 4. data
{
size_t b;
bytes += ( b=_bp.store( _os, _swap ) );
//omlog() << " b = " << b << std::endl;
assert( b == _bp.size_of() );
}
return bytes;
}
// ----------------------------------------------------------------------------
size_t _OMWriter_::binary_size(BaseExporter& /* _be */, Options /* _opt */) const
{
// std::clog << "[OMWriter]: binary_size()" << std::endl;
size_t bytes = sizeof( OMFormat::Header );
// !!!TODO!!!
return bytes;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,147 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a writer module for OM files
//
//=============================================================================
#ifndef __OMWRITER_HH__
#define __OMWRITER_HH__
//=== INCLUDES ================================================================
// STD C++
#include <iosfwd>
#include <string>
// OpenMesh
#include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/OMFormat.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== FORWARDS ================================================================
class BaseExporter;
//=== IMPLEMENTATION ==========================================================
/**
* Implementation of the OM format writer. This class is singleton'ed by
* SingletonT to OMWriter.
*/
class OPENMESHDLLEXPORT _OMWriter_ : public BaseWriter
{
public:
/// Constructor
_OMWriter_();
/// Destructor
virtual ~_OMWriter_() {};
std::string get_description() const
{ return "OpenMesh Format"; }
std::string get_extensions() const
{ return "om"; }
bool write(std::ostream&, BaseExporter&, Options, std::streamsize _precision = 6) const;
size_t binary_size(BaseExporter& _be, Options _opt) const;
protected:
static const OMFormat::uchar magic_[3];
static const OMFormat::uint8 version_;
bool write(const std::string&, BaseExporter&, Options, std::streamsize _precision = 6) const;
bool write_binary(std::ostream&, BaseExporter&, Options) const;
size_t store_binary_custom_chunk( std::ostream&, const BaseProperty&,
OMFormat::Chunk::Entity, bool) const;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the OM writer.
extern _OMWriter_ __OMWriterInstance;
OPENMESHDLLEXPORT _OMWriter_& OMWriter();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,721 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
#include <fstream>
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Utils/Endian.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/IO/writer/PLYWriter.hh>
#include <iostream>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
// register the PLYLoader singleton with MeshLoader
_PLYWriter_ __PLYWriterInstance;
_PLYWriter_& PLYWriter() { return __PLYWriterInstance; }
//=== IMPLEMENTATION ==========================================================
_PLYWriter_::_PLYWriter_()
{
IOManager().register_module(this);
nameOfType_[Unsupported] = "";
nameOfType_[ValueTypeCHAR] = "char";
nameOfType_[ValueTypeUCHAR] = nameOfType_[ValueTypeUINT8] = "uchar";
nameOfType_[ValueTypeUSHORT] = "ushort";
nameOfType_[ValueTypeSHORT] = "short";
nameOfType_[ValueTypeUINT] = "uint";
nameOfType_[ValueTypeINT] = "int";
nameOfType_[ValueTypeFLOAT32] = nameOfType_[ValueTypeFLOAT] = "float";
nameOfType_[ValueTypeDOUBLE] = "double";
}
//-----------------------------------------------------------------------------
bool
_PLYWriter_::
write(const std::string& _filename, BaseExporter& _be, Options _opt, std::streamsize _precision) const
{
// open file
std::ofstream out(_filename.c_str(), (_opt.check(Options::Binary) ? std::ios_base::binary | std::ios_base::out
: std::ios_base::out) );
return write(out, _be, _opt, _precision);
}
//-----------------------------------------------------------------------------
bool
_PLYWriter_::
write(std::ostream& _os, BaseExporter& _be, Options _opt, std::streamsize _precision) const
{
// check exporter features
if ( !check( _be, _opt ) )
return false;
// check writer features
if ( _opt.check(Options::FaceNormal) ) {
// Face normals are not supported
// Uncheck these options and output message that
// they are not written out even though they were requested
_opt.unset(Options::FaceNormal);
omerr() << "[PLYWriter] : Warning: Face normals are not supported and thus not exported! " << std::endl;
}
if ( _opt.check(Options::FaceColor) ) {
// Face normals are not supported
// Uncheck these options and output message that
// they are not written out even though they were requested
_opt.unset(Options::FaceColor);
omerr() << "[PLYWriter] : Warning: Face colors are not supported and thus not exported! " << std::endl;
}
options_ = _opt;
if (!_os.good())
{
omerr() << "[PLYWriter] : cannot write to stream "
<< std::endl;
return false;
}
if (!_opt.check(Options::Binary))
_os.precision(_precision);
// write to file
bool result = (_opt.check(Options::Binary) ?
write_binary(_os, _be, _opt) :
write_ascii(_os, _be, _opt));
return result;
}
//-----------------------------------------------------------------------------
// helper function for casting a property
template<typename T>
const PropertyT<T>* castProperty(const BaseProperty* _prop)
{
return dynamic_cast< const PropertyT<T>* >(_prop);
}
//-----------------------------------------------------------------------------
std::vector<_PLYWriter_::CustomProperty> _PLYWriter_::writeCustomTypeHeader(std::ostream& _out, BaseKernel::const_prop_iterator _begin, BaseKernel::const_prop_iterator _end) const
{
std::vector<CustomProperty> customProps;
for (;_begin != _end; ++_begin)
{
BaseProperty* prop = *_begin;
// check, if property is persistant
if (!prop || !prop->persistent())
continue;
// identify type of property
CustomProperty cProp(prop);
size_t propSize = prop->element_size();
switch (propSize)
{
case 1:
{
assert_compile(sizeof(char) == 1);
//check, if prop is a char or unsigned char by dynamic_cast
//char, unsigned char and signed char are 3 distinct types
if (castProperty<signed char>(prop) != 0 || castProperty<char>(prop) != 0) //treat char as signed char
cProp.type = ValueTypeCHAR;
else if (castProperty<unsigned char>(prop) != 0)
cProp.type = ValueTypeUCHAR;
break;
}
case 2:
{
assert_compile (sizeof(short) == 2);
if (castProperty<signed short>(prop) != 0)
cProp.type = ValueTypeSHORT;
else if (castProperty<unsigned short>(prop) != 0)
cProp.type = ValueTypeUSHORT;
break;
}
case 4:
{
assert_compile (sizeof(int) == 4);
assert_compile (sizeof(float) == 4);
if (castProperty<signed int>(prop) != 0)
cProp.type = ValueTypeINT;
else if (castProperty<unsigned int>(prop) != 0)
cProp.type = ValueTypeUINT;
else if (castProperty<float>(prop) != 0)
cProp.type = ValueTypeFLOAT;
break;
}
case 8:
assert_compile (sizeof(double) == 8);
if (castProperty<double>(prop) != 0)
cProp.type = ValueTypeDOUBLE;
break;
default:
break;
}
if (cProp.type != Unsupported)
{
// property type was identified and it is persistant, write into header
customProps.push_back(cProp);
_out << "property " << nameOfType_[cProp.type] << " " << cProp.property->name() << "\n";
}
}
return customProps;
}
//-----------------------------------------------------------------------------
template<bool binary>
void _PLYWriter_::write_customProp(std::ostream& _out, const CustomProperty& _prop, size_t _index) const
{
if (_prop.type == ValueTypeCHAR)
writeProxy(_prop.type,_out, castProperty<signed char>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
else if (_prop.type == ValueTypeUCHAR || _prop.type == ValueTypeUINT8)
writeProxy(_prop.type,_out, castProperty<unsigned char>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
else if (_prop.type == ValueTypeSHORT)
writeProxy(_prop.type,_out, castProperty<signed short>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
else if (_prop.type == ValueTypeUSHORT)
writeProxy(_prop.type,_out, castProperty<unsigned short>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
else if (_prop.type == ValueTypeUINT)
writeProxy(_prop.type,_out, castProperty<unsigned int>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
else if (_prop.type == ValueTypeINT || _prop.type == ValueTypeINT32)
writeProxy(_prop.type,_out, castProperty<signed int>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
else if (_prop.type == ValueTypeFLOAT || _prop.type == ValueTypeFLOAT32)
writeProxy(_prop.type,_out, castProperty<float>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
else if (_prop.type == ValueTypeDOUBLE)
writeProxy(_prop.type,_out, castProperty<double>(_prop.property)->data()[_index], OpenMesh::GenProg::Bool2Type<binary>());
}
//-----------------------------------------------------------------------------
void _PLYWriter_::write_header(std::ostream& _out, BaseExporter& _be, Options& _opt, std::vector<CustomProperty>& _ovProps, std::vector<CustomProperty>& _ofProps) const {
//writing header
_out << "ply" << '\n';
if (_opt.is_binary()) {
_out << "format ";
if ( options_.check(Options::MSB) )
_out << "binary_big_endian ";
else
_out << "binary_little_endian ";
_out << "1.0" << '\n';
} else
_out << "format ascii 1.0" << '\n';
_out << "element vertex " << _be.n_vertices() << '\n';
_out << "property float x" << '\n';
_out << "property float y" << '\n';
_out << "property float z" << '\n';
if ( _opt.vertex_has_normal() ){
_out << "property float nx" << '\n';
_out << "property float ny" << '\n';
_out << "property float nz" << '\n';
}
if ( _opt.vertex_has_texcoord() ){
_out << "property float u" << '\n';
_out << "property float v" << '\n';
}
if ( _opt.vertex_has_color() ){
if ( _opt.color_is_float() ) {
_out << "property float red" << '\n';
_out << "property float green" << '\n';
_out << "property float blue" << '\n';
if ( _opt.color_has_alpha() )
_out << "property float alpha" << '\n';
} else {
_out << "property uchar red" << '\n';
_out << "property uchar green" << '\n';
_out << "property uchar blue" << '\n';
if ( _opt.color_has_alpha() )
_out << "property uchar alpha" << '\n';
}
}
_ovProps = writeCustomTypeHeader(_out, _be.kernel()->vprops_begin(), _be.kernel()->vprops_end());
_out << "element face " << _be.n_faces() << '\n';
_out << "property list uchar int vertex_indices" << '\n';
_ofProps = writeCustomTypeHeader(_out, _be.kernel()->fprops_begin(), _be.kernel()->fprops_end());
_out << "end_header" << '\n';
}
//-----------------------------------------------------------------------------
bool
_PLYWriter_::
write_ascii(std::ostream& _out, BaseExporter& _be, Options _opt) const
{
unsigned int i, nV, nF;
Vec3f v, n;
OpenMesh::Vec3ui c;
OpenMesh::Vec4ui cA;
OpenMesh::Vec3f cf;
OpenMesh::Vec4f cAf;
OpenMesh::Vec2f t;
VertexHandle vh;
std::vector<VertexHandle> vhandles;
std::vector<CustomProperty> vProps;
std::vector<CustomProperty> fProps;
write_header(_out, _be, _opt, vProps, fProps);
if (_opt.color_is_float())
_out << std::fixed;
// vertex data (point, normals, colors, texcoords)
for (i=0, nV=int(_be.n_vertices()); i<nV; ++i)
{
vh = VertexHandle(i);
v = _be.point(vh);
//Vertex
_out << v[0] << " " << v[1] << " " << v[2];
// Vertex Normals
if ( _opt.vertex_has_normal() ){
n = _be.normal(vh);
_out << " " << n[0] << " " << n[1] << " " << n[2];
}
// Vertex TexCoords
if ( _opt.vertex_has_texcoord() ) {
t = _be.texcoord(vh);
_out << " " << t[0] << " " << t[1];
}
// VertexColor
if ( _opt.vertex_has_color() ) {
//with alpha
if ( _opt.color_has_alpha() ){
if (_opt.color_is_float()) {
cAf = _be.colorAf(vh);
_out << " " << cAf;
} else {
cA = _be.colorAi(vh);
_out << " " << cA;
}
}else{
//without alpha
if (_opt.color_is_float()) {
cf = _be.colorf(vh);
_out << " " << cf;
} else {
c = _be.colori(vh);
_out << " " << c;
}
}
}
// write custom properties for vertices
for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
write_customProp<false>(_out,*iter,i);
_out << "\n";
}
// faces (indices starting at 0)
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
{
// write vertex indices per face
nV = _be.get_vhandles(FaceHandle(i), vhandles);
_out << nV;
for (size_t j=0; j<vhandles.size(); ++j)
_out << " " << vhandles[j].idx();
// write custom props
for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
write_customProp<false>(_out,*iter,i);
_out << "\n";
}
return true;
}
//-----------------------------------------------------------------------------
void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, int value) const {
uint32_t tmp32;
uint8_t tmp8;
switch (_type) {
case ValueTypeINT:
case ValueTypeINT32:
tmp32 = value;
store(_out, tmp32, options_.check(Options::MSB) );
break;
// case ValueTypeUINT8:
default :
tmp8 = value;
store(_out, tmp8, options_.check(Options::MSB) );
break;
// default :
// std::cerr << "unsupported conversion type to int: " << _type << std::endl;
// break;
}
}
void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, unsigned int value) const {
uint32_t tmp32;
uint8_t tmp8;
switch (_type) {
case ValueTypeINT:
case ValueTypeINT32:
tmp32 = value;
store(_out, tmp32, options_.check(Options::MSB) );
break;
// case ValueTypeUINT8:
default :
tmp8 = value;
store(_out, tmp8, options_.check(Options::MSB) );
break;
// default :
// std::cerr << "unsupported conversion type to int: " << _type << std::endl;
// break;
}
}
void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, float value) const {
float32_t tmp;
switch (_type) {
case ValueTypeFLOAT32:
case ValueTypeFLOAT:
tmp = value;
store( _out , tmp, options_.check(Options::MSB) );
break;
default :
std::cerr << "unsupported conversion type to float: " << _type << std::endl;
break;
}
}
void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, double value) const {
float64_t tmp;
switch (_type) {
case ValueTypeDOUBLE:
tmp = value;
store( _out , tmp, options_.check(Options::MSB) );
break;
default :
std::cerr << "unsupported conversion type to float: " << _type << std::endl;
break;
}
}
void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, signed char value) const{
int8_t tmp;
switch (_type) {
case ValueTypeCHAR:
tmp = value;
store(_out, tmp, options_.check(Options::MSB) );
break;
default :
std::cerr << "unsupported conversion type to int: " << _type << std::endl;
break;
}
}
void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, unsigned char value) const{
uint8_t tmp;
switch (_type) {
case ValueTypeUCHAR:
tmp = value;
store(_out, tmp, options_.check(Options::MSB) );
break;
default :
std::cerr << "unsupported conversion type to int: " << _type << std::endl;
break;
}
}
void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, short value) const{
int16_t tmp;
switch (_type) {
case ValueTypeSHORT:
tmp = value;
store(_out, tmp, options_.check(Options::MSB) );
break;
default :
std::cerr << "unsupported conversion type to int: " << _type << std::endl;
break;
}
}
void _PLYWriter_::writeValue(ValueType _type, std::ostream& _out, unsigned short value) const{
uint16_t tmp;
switch (_type) {
case ValueTypeUSHORT:
tmp = value;
store(_out, tmp, options_.check(Options::MSB) );
break;
default :
std::cerr << "unsupported conversion type to int: " << _type << std::endl;
break;
}
}
bool
_PLYWriter_::
write_binary(std::ostream& _out, BaseExporter& _be, Options _opt) const
{
unsigned int i, nV, nF;
Vec3f v, n;
Vec2f t;
OpenMesh::Vec4uc c;
OpenMesh::Vec4f cf;
VertexHandle vh;
std::vector<VertexHandle> vhandles;
// vProps and fProps will be empty, until custom properties are supported by the binary writer
std::vector<CustomProperty> vProps;
std::vector<CustomProperty> fProps;
write_header(_out, _be, _opt, vProps, fProps);
// vertex data (point, normals, texcoords)
for (i=0, nV=int(_be.n_vertices()); i<nV; ++i)
{
vh = VertexHandle(i);
v = _be.point(vh);
//vertex
writeValue(ValueTypeFLOAT, _out, v[0]);
writeValue(ValueTypeFLOAT, _out, v[1]);
writeValue(ValueTypeFLOAT, _out, v[2]);
// Vertex Normal
if ( _opt.vertex_has_normal() ){
n = _be.normal(vh);
writeValue(ValueTypeFLOAT, _out, n[0]);
writeValue(ValueTypeFLOAT, _out, n[1]);
writeValue(ValueTypeFLOAT, _out, n[2]);
}
// Vertex TexCoords
if ( _opt.vertex_has_texcoord() ) {
t = _be.texcoord(vh);
writeValue(ValueTypeFLOAT, _out, t[0]);
writeValue(ValueTypeFLOAT, _out, t[1]);
}
// vertex color
if ( _opt.vertex_has_color() ) {
if ( _opt.color_is_float() ) {
cf = _be.colorAf(vh);
writeValue(ValueTypeFLOAT, _out, cf[0]);
writeValue(ValueTypeFLOAT, _out, cf[1]);
writeValue(ValueTypeFLOAT, _out, cf[2]);
if ( _opt.color_has_alpha() )
writeValue(ValueTypeFLOAT, _out, cf[3]);
} else {
c = _be.colorA(vh);
writeValue(ValueTypeUCHAR, _out, (int)c[0]);
writeValue(ValueTypeUCHAR, _out, (int)c[1]);
writeValue(ValueTypeUCHAR, _out, (int)c[2]);
if ( _opt.color_has_alpha() )
writeValue(ValueTypeUCHAR, _out, (int)c[3]);
}
}
for (std::vector<CustomProperty>::iterator iter = vProps.begin(); iter < vProps.end(); ++iter)
write_customProp<true>(_out,*iter,i);
}
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
{
//face
nV = _be.get_vhandles(FaceHandle(i), vhandles);
writeValue(ValueTypeUINT8, _out, nV);
for (size_t j=0; j<vhandles.size(); ++j)
writeValue(ValueTypeINT32, _out, vhandles[j].idx() );
for (std::vector<CustomProperty>::iterator iter = fProps.begin(); iter < fProps.end(); ++iter)
write_customProp<true>(_out,*iter,i);
}
return true;
}
// ----------------------------------------------------------------------------
size_t
_PLYWriter_::
binary_size(BaseExporter& _be, Options _opt) const
{
size_t header(0);
size_t data(0);
size_t _3floats(3*sizeof(float));
size_t _3ui(3*sizeof(unsigned int));
size_t _4ui(4*sizeof(unsigned int));
if ( !_opt.is_binary() )
return 0;
else
{
size_t _3longs(3*sizeof(long));
header += 11; // 'OFF BINARY\n'
header += _3longs; // #V #F #E
data += _be.n_vertices() * _3floats; // vertex data
}
if ( _opt.vertex_has_normal() && _be.has_vertex_normals() )
{
header += 1; // N
data += _be.n_vertices() * _3floats;
}
if ( _opt.vertex_has_color() && _be.has_vertex_colors() )
{
header += 1; // C
data += _be.n_vertices() * _3floats;
}
if ( _opt.vertex_has_texcoord() && _be.has_vertex_texcoords() )
{
size_t _2floats(2*sizeof(float));
header += 2; // ST
data += _be.n_vertices() * _2floats;
}
// topology
if (_be.is_triangle_mesh())
{
data += _be.n_faces() * _4ui;
}
else
{
unsigned int i, nF;
std::vector<VertexHandle> vhandles;
for (i=0, nF=int(_be.n_faces()); i<nF; ++i)
{
data += _be.get_vhandles(FaceHandle(i), vhandles) * sizeof(unsigned int);
}
}
// face colors
if ( _opt.face_has_color() && _be.has_face_colors() ){
if ( _opt.color_has_alpha() )
data += _be.n_faces() * _4ui;
else
data += _be.n_faces() * _3ui;
}
return header+data;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,177 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a writer module for PLY files
//
//=============================================================================
#ifndef __PLYWRITER_HH__
#define __PLYWRITER_HH__
//=== INCLUDES ================================================================
#include <string>
#include <ostream>
#include <vector>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
#include <OpenMesh/Core/Utils/GenProg.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
Implementation of the PLY format writer. This class is singleton'ed by
SingletonT to PLYWriter.
currently supported options:
- VertexColors
- Binary
- Binary -> MSB
*/
class OPENMESHDLLEXPORT _PLYWriter_ : public BaseWriter
{
public:
_PLYWriter_();
/// Destructor
virtual ~_PLYWriter_() {};
std::string get_description() const { return "PLY polygon file format"; }
std::string get_extensions() const { return "ply"; }
bool write(const std::string&, BaseExporter&, Options, std::streamsize _precision = 6) const;
bool write(std::ostream&, BaseExporter&, Options, std::streamsize _precision = 6) const;
size_t binary_size(BaseExporter& _be, Options _opt) const;
enum ValueType {
Unsupported = 0,
ValueTypeFLOAT32, ValueTypeFLOAT,
ValueTypeINT32, ValueTypeINT , ValueTypeUINT,
ValueTypeUCHAR, ValueTypeCHAR, ValueTypeUINT8,
ValueTypeUSHORT, ValueTypeSHORT,
ValueTypeDOUBLE
};
private:
mutable Options options_;
struct CustomProperty
{
ValueType type;
const BaseProperty* property;
CustomProperty(const BaseProperty* const _p):type(Unsupported),property(_p){}
};
const char* nameOfType_[12];
/// write custom persistant properties into the header for the current element, returns all properties, which were written sorted
std::vector<CustomProperty> writeCustomTypeHeader(std::ostream& _out, BaseKernel::const_prop_iterator _begin, BaseKernel::const_prop_iterator _end) const;
template<bool binary>
void write_customProp(std::ostream& _our, const CustomProperty& _prop, size_t _index) const;
template<typename T>
void writeProxy(ValueType _type, std::ostream& _out, T _value, OpenMesh::GenProg::TrueType /*_binary*/) const
{
writeValue(_type, _out, _value);
}
template<typename T>
void writeProxy(ValueType _type, std::ostream& _out, T _value, OpenMesh::GenProg::FalseType /*_binary*/) const
{
_out << " " << _value;
}
protected:
void writeValue(ValueType _type, std::ostream& _out, signed char value) const;
void writeValue(ValueType _type, std::ostream& _out, unsigned char value) const;
void writeValue(ValueType _type, std::ostream& _out, short value) const;
void writeValue(ValueType _type, std::ostream& _out, unsigned short value) const;
void writeValue(ValueType _type, std::ostream& _out, int value) const;
void writeValue(ValueType _type, std::ostream& _out, unsigned int value) const;
void writeValue(ValueType _type, std::ostream& _out, float value) const;
void writeValue(ValueType _type, std::ostream& _out, double value) const;
bool write_ascii(std::ostream& _out, BaseExporter&, Options) const;
bool write_binary(std::ostream& _out, BaseExporter&, Options) const;
/// write header into the stream _out. Returns custom properties (vertex and face) which are written into the header
void write_header(std::ostream& _out, BaseExporter& _be, Options& _opt, std::vector<CustomProperty>& _ovProps, std::vector<CustomProperty>& _ofProps) const;
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the PLY writer.
extern _PLYWriter_ __PLYWriterInstance;
OPENMESHDLLEXPORT _PLYWriter_& PLYWriter();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,440 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//== INCLUDES =================================================================
//STL
#include <fstream>
// OpenMesh
#include <OpenMesh/Core/System/omstream.hh>
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/IO/writer/STLWriter.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANCIATE =============================================================
_STLWriter_ __STLWriterInstance;
_STLWriter_& STLWriter() { return __STLWriterInstance; }
//=== IMPLEMENTATION ==========================================================
_STLWriter_::_STLWriter_() { IOManager().register_module(this); }
//-----------------------------------------------------------------------------
bool
_STLWriter_::
write(const std::string& _filename, BaseExporter& _be, Options _opt, std::streamsize _precision) const
{
// binary or ascii ?
if (_filename.rfind(".stla") != std::string::npos)
{
_opt -= Options::Binary;
}
else if (_filename.rfind(".stlb") != std::string::npos)
{
_opt += Options::Binary;
}
// open file
std::fstream out(_filename.c_str(), (_opt.check(Options::Binary) ? std::ios_base::binary | std::ios_base::out
: std::ios_base::out) );
bool result = write(out, _be, _opt, _precision);
out.close();
return result;
}
//-----------------------------------------------------------------------------
bool
_STLWriter_::
write(std::ostream& _os, BaseExporter& _be, Options _opt, std::streamsize _precision) const
{
// check exporter features
if (!check(_be, _opt)) return false;
// check writer features
if (_opt.check(Options::VertexNormal) ||
_opt.check(Options::VertexTexCoord) ||
_opt.check(Options::FaceColor))
return false;
if (!_opt.check(Options::Binary))
_os.precision(_precision);
if (_opt & Options::Binary)
return write_stlb(_os, _be, _opt);
else
return write_stla(_os, _be, _opt);
return false;
}
//-----------------------------------------------------------------------------
bool
_STLWriter_::
write_stla(const std::string& _filename, BaseExporter& _be, Options /* _opt */) const
{
omlog() << "[STLWriter] : write ascii file\n";
// open file
FILE* out = fopen(_filename.c_str(), "w");
if (!out)
{
omerr() << "[STLWriter] : cannot open file " << _filename << std::endl;
return false;
}
int i, nF(int(_be.n_faces()));
Vec3f a, b, c, n;
std::vector<VertexHandle> vhandles;
FaceHandle fh;
// header
fprintf(out, "solid \n");
// write face set
for (i=0; i<nF; ++i)
{
fh = FaceHandle(i);
const int nV = _be.get_vhandles(fh, vhandles);
if (nV == 3)
{
a = _be.point(vhandles[0]);
b = _be.point(vhandles[1]);
c = _be.point(vhandles[2]);
n = (_be.has_face_normals() ?
_be.normal(fh) :
((c-b) % (a-b)).normalize());
fprintf(out, "facet normal %f %f %f\nouter loop\n", n[0], n[1], n[2]);
fprintf(out, "vertex %.10f %.10f %.10f\n", a[0], a[1], a[2]);
fprintf(out, "vertex %.10f %.10f %.10f\n", b[0], b[1], b[2]);
fprintf(out, "vertex %.10f %.10f %.10f", c[0], c[1], c[2]);
}
else
omerr() << "[STLWriter] : Warning non-triangle data!\n";
fprintf(out, "\nendloop\nendfacet\n");
}
fprintf(out, "endsolid\n");
fclose(out);
return true;
}
//-----------------------------------------------------------------------------
bool
_STLWriter_::
write_stla(std::ostream& _out, BaseExporter& _be, Options /* _opt */, std::streamsize _precision) const
{
omlog() << "[STLWriter] : write ascii file\n";
int i, nF(int(_be.n_faces()));
Vec3f a, b, c, n;
std::vector<VertexHandle> vhandles;
FaceHandle fh;
_out.precision(_precision);
// header
_out << "solid \n";
// write face set
for (i=0; i<nF; ++i)
{
fh = FaceHandle(i);
const int nV = _be.get_vhandles(fh, vhandles);
if (nV == 3)
{
a = _be.point(vhandles[0]);
b = _be.point(vhandles[1]);
c = _be.point(vhandles[2]);
n = (_be.has_face_normals() ?
_be.normal(fh) :
((c-b) % (a-b)).normalize());
_out << "facet normal " << n[0] << " " << n[1] << " " << n[2] << "\nouter loop\n";
_out.precision(10);
_out << "vertex " << a[0] << " " << a[1] << " " << a[2] << "\n";
_out << "vertex " << b[0] << " " << b[1] << " " << b[2] << "\n";
_out << "vertex " << c[0] << " " << c[1] << " " << c[2] << "\n";
} else {
omerr() << "[STLWriter] : Warning non-triangle data!\n";
}
_out << "\nendloop\nendfacet\n";
}
_out << "endsolid\n";
return true;
}
//-----------------------------------------------------------------------------
bool
_STLWriter_::
write_stlb(const std::string& _filename, BaseExporter& _be, Options /* _opt */) const
{
omlog() << "[STLWriter] : write binary file\n";
// open file
FILE* out = fopen(_filename.c_str(), "wb");
if (!out)
{
omerr() << "[STLWriter] : cannot open file " << _filename << std::endl;
return false;
}
int i, nF(int(_be.n_faces()));
Vec3f a, b, c, n;
std::vector<VertexHandle> vhandles;
FaceHandle fh;
// write header
const char header[80] =
"binary stl file"
" ";
fwrite(header, 1, 80, out);
// number of faces
write_int( int(_be.n_faces()), out);
// write face set
for (i=0; i<nF; ++i)
{
fh = FaceHandle(i);
const int nV = _be.get_vhandles(fh, vhandles);
if (nV == 3)
{
a = _be.point(vhandles[0]);
b = _be.point(vhandles[1]);
c = _be.point(vhandles[2]);
n = (_be.has_face_normals() ?
_be.normal(fh) :
((c-b) % (a-b)).normalize());
// face normal
write_float(n[0], out);
write_float(n[1], out);
write_float(n[2], out);
// face vertices
write_float(a[0], out);
write_float(a[1], out);
write_float(a[2], out);
write_float(b[0], out);
write_float(b[1], out);
write_float(b[2], out);
write_float(c[0], out);
write_float(c[1], out);
write_float(c[2], out);
// space filler
write_short(0, out);
}
else
omerr() << "[STLWriter] : Warning: Skipped non-triangle data!\n";
}
fclose(out);
return true;
}
//-----------------------------------------------------------------------------
bool
_STLWriter_::
write_stlb(std::ostream& _out, BaseExporter& _be, Options /* _opt */, std::streamsize _precision) const
{
omlog() << "[STLWriter] : write binary file\n";
int i, nF(int(_be.n_faces()));
Vec3f a, b, c, n;
std::vector<VertexHandle> vhandles;
FaceHandle fh;
_out.precision(_precision);
// write header
const char header[80] =
"binary stl file"
" ";
_out.write(header, 80);
// number of faces
write_int(int(_be.n_faces()), _out);
// write face set
for (i=0; i<nF; ++i)
{
fh = FaceHandle(i);
const int nV = _be.get_vhandles(fh, vhandles);
if (nV == 3)
{
a = _be.point(vhandles[0]);
b = _be.point(vhandles[1]);
c = _be.point(vhandles[2]);
n = (_be.has_face_normals() ?
_be.normal(fh) :
((c-b) % (a-b)).normalize());
// face normal
write_float(n[0], _out);
write_float(n[1], _out);
write_float(n[2], _out);
// face vertices
write_float(a[0], _out);
write_float(a[1], _out);
write_float(a[2], _out);
write_float(b[0], _out);
write_float(b[1], _out);
write_float(b[2], _out);
write_float(c[0], _out);
write_float(c[1], _out);
write_float(c[2], _out);
// space filler
write_short(0, _out);
}
else
omerr() << "[STLWriter] : Warning: Skipped non-triangle data!\n";
}
return true;
}
//-----------------------------------------------------------------------------
size_t
_STLWriter_::
binary_size(BaseExporter& _be, Options /* _opt */) const
{
size_t bytes(0);
size_t _12floats(12*sizeof(float));
bytes += 80; // header
bytes += 4; // #faces
int i, nF(int(_be.n_faces()));
std::vector<VertexHandle> vhandles;
for (i=0; i<nF; ++i)
if (_be.get_vhandles(FaceHandle(i), vhandles) == 3)
bytes += _12floats + sizeof(short);
else
omerr() << "[STLWriter] : Warning: Skipped non-triangle data!\n";
return bytes;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,126 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// Implements a writer module for STL ascii files
//
//=============================================================================
// $Id: STLWriter.hh,v 1.2 2007-05-18 15:17:43 habbecke Exp $
#ifndef __STLWRITER_HH__
#define __STLWRITER_HH__
//=== INCLUDES ================================================================
// -------------------- STL
#include <iosfwd>
#include <string>
// -------------------- OpenMesh
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
/**
Implementation of the STL format writer. This class is singleton'ed by
SingletonT to STLWriter.
*/
class OPENMESHDLLEXPORT _STLWriter_ : public BaseWriter
{
public:
_STLWriter_();
/// Destructor
virtual ~_STLWriter_() {};
std::string get_description() const { return "Stereolithography Format"; }
std::string get_extensions() const { return "stl stla stlb"; }
bool write(const std::string&, BaseExporter&, Options, std::streamsize _precision = 6) const;
bool write(std::ostream&, BaseExporter&, Options, std::streamsize _precision = 6) const;
size_t binary_size(BaseExporter&, Options) const;
private:
bool write_stla(const std::string&, BaseExporter&, Options) const;
bool write_stla(std::ostream&, BaseExporter&, Options, std::streamsize _precision = 6) const;
bool write_stlb(const std::string&, BaseExporter&, Options) const;
bool write_stlb(std::ostream&, BaseExporter&, Options, std::streamsize _precision = 6) const;
};
//== TYPE DEFINITION ==========================================================
// Declare the single entity of STL writer.
extern _STLWriter_ __STLWriterInstance;
OPENMESHDLLEXPORT _STLWriter_& STLWriter();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,103 @@
//== INCLUDES =================================================================
#include <fstream>
#include <limits>
#include <OpenMesh/Core/IO/BinaryHelper.hh>
#include <OpenMesh/Core/IO/writer/VTKWriter.hh>
#include <OpenMesh/Core/IO/IOManager.hh>
#include <OpenMesh/Core/Utils/color_cast.hh>
//=== NAMESPACES ==============================================================
namespace OpenMesh {
namespace IO {
//=== INSTANTIATE =============================================================
_VTKWriter_ __VTKWriterinstance;
_VTKWriter_& VTKWriter() { return __VTKWriterinstance; }
//=== IMPLEMENTATION ==========================================================
_VTKWriter_::_VTKWriter_() { IOManager().register_module(this); }
//-----------------------------------------------------------------------------
bool _VTKWriter_::write(const std::string& _filename, BaseExporter& _be, Options _opt, std::streamsize _precision) const
{
std::ofstream out(_filename.c_str());
if (!out) {
omerr() << "[VTKWriter] : cannot open file " << _filename << std::endl;
return false;
}
return write(out, _be, _opt, _precision);
}
//-----------------------------------------------------------------------------
bool _VTKWriter_::write(std::ostream& _out, BaseExporter& _be, Options _opt, std::streamsize _precision) const
{
Vec3f v, n;
Vec2f t;
VertexHandle vh;
OpenMesh::Vec3f c;
OpenMesh::Vec4f cA;
// check exporter features
if (!check(_be, _opt)) {
return false;
}
// check writer features
if (!_opt.is_empty()) {
omlog() << "[VTKWriter] : writer does not support any options\n";
return false;
}
omlog() << "[VTKWriter] : write file\n";
_out.precision(_precision);
std::vector<VertexHandle> vhandles;
size_t polygon_table_size = 0;
size_t nf = _be.n_faces();
for (size_t i = 0; i < nf; ++i) {
polygon_table_size += _be.get_vhandles(FaceHandle(int(i)), vhandles);
}
polygon_table_size += nf;
// header
_out << "# vtk DataFile Version 3.0\n";
_out << "Generated by OpenMesh\n";
_out << "ASCII\n";
_out << "DATASET POLYDATA\n";
// points
_out << "POINTS " << _be.n_vertices() << " float\n";
size_t nv = _be.n_vertices();
for (size_t i = 0; i < nv; ++i) {
Vec3f v = _be.point(VertexHandle(int(i)));
_out << v[0] << ' ' << v[1] << ' ' << v[2] << '\n';
}
// faces
_out << "POLYGONS " << nf << ' ' << polygon_table_size << '\n';
for (size_t i = 0; i < nf; ++i) {
_be.get_vhandles(FaceHandle(int(i)), vhandles);
_out << vhandles.size() << ' ';
for (size_t j = 0; j < vhandles.size(); ++j) {
_out << " " << vhandles[j].idx();
}
_out << '\n';
}
return true;
}
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,52 @@
//=============================================================================
//
// Implements an IOManager writer module for VTK files
//
//=============================================================================
#ifndef __VTKWRITER_HH__
#define __VTKWRITER_HH__
//=== INCLUDES ================================================================
#include <string>
#include <iosfwd>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/SingletonT.hh>
#include <OpenMesh/Core/IO/exporter/BaseExporter.hh>
#include <OpenMesh/Core/IO/writer/BaseWriter.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace IO {
//=== IMPLEMENTATION ==========================================================
class OPENMESHDLLEXPORT _VTKWriter_ : public BaseWriter
{
public:
_VTKWriter_();
std::string get_description() const { return "VTK"; }
std::string get_extensions() const { return "vtk"; }
bool write(const std::string&, BaseExporter&, Options, std::streamsize _precision = 6) const;
bool write(std::ostream&, BaseExporter&, Options, std::streamsize _precision = 6) const;
size_t binary_size(BaseExporter&, Options) const { return 0; }
};
//== TYPE DEFINITION ==========================================================
/// Declare the single entity of the OBJ writer
extern _VTKWriter_ __VTKWriterinstance;
OPENMESHDLLEXPORT _VTKWriter_& VTKWriter();
//=============================================================================
} // namespace IO
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,130 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OPENMESH_ARRAY_ITEMS_HH
#define OPENMESH_ARRAY_ITEMS_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/GenProg.hh>
#include <OpenMesh/Core/Mesh/Handles.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== CLASS DEFINITION =========================================================
/// Definition of mesh items for use in the ArrayKernel
struct ArrayItems
{
//------------------------------------------------------ internal vertex type
/// The vertex item
class Vertex
{
friend class ArrayKernel;
HalfedgeHandle halfedge_handle_;
};
//---------------------------------------------------- internal halfedge type
#ifndef DOXY_IGNORE_THIS
class Halfedge_without_prev
{
friend class ArrayKernel;
FaceHandle face_handle_;
VertexHandle vertex_handle_;
HalfedgeHandle next_halfedge_handle_;
};
#endif
#ifndef DOXY_IGNORE_THIS
class Halfedge_with_prev : public Halfedge_without_prev
{
friend class ArrayKernel;
HalfedgeHandle prev_halfedge_handle_;
};
#endif
//TODO: should be selected with config.h define
typedef Halfedge_with_prev Halfedge;
typedef GenProg::Bool2Type<true> HasPrevHalfedge;
//-------------------------------------------------------- internal edge type
#ifndef DOXY_IGNORE_THIS
class Edge
{
friend class ArrayKernel;
Halfedge halfedges_[2];
};
#endif
//-------------------------------------------------------- internal face type
#ifndef DOXY_IGNORE_THIS
class Face
{
friend class ArrayKernel;
HalfedgeHandle halfedge_handle_;
};
};
#endif
//=============================================================================
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_ITEMS_HH defined
//=============================================================================

View File

@ -0,0 +1,259 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#include <OpenMesh/Core/Mesh/ArrayKernel.hh>
namespace OpenMesh
{
ArrayKernel::ArrayKernel()
: refcount_vstatus_(0), refcount_hstatus_(0),
refcount_estatus_(0), refcount_fstatus_(0)
{
init_bit_masks(); //Status bit masks initialization
}
ArrayKernel::~ArrayKernel()
{
clear();
}
// ArrayKernel::ArrayKernel(const ArrayKernel& _rhs)
// : BaseKernel(_rhs),
// vertices_(_rhs.vertices_), edges_(_rhs.edges_), faces_(_rhs.faces_),
// vertex_status_(_rhs.vertex_status_), halfedge_status_(_rhs.halfedge_status_),
// edge_status_(_rhs.edge_status_), face_status_(_rhs.face_status_),
// refcount_vstatus_(_rhs.refcount_vstatus_), refcount_hstatus_(_rhs.refcount_hstatus_),
// refcount_estatus_(_rhs.refcount_estatus_), refcount_fstatus_(_rhs.refcount_fstatus_)
// {}
void ArrayKernel::assign_connectivity(const ArrayKernel& _other)
{
vertices_ = _other.vertices_;
edges_ = _other.edges_;
faces_ = _other.faces_;
vprops_resize(n_vertices());
hprops_resize(n_halfedges());
eprops_resize(n_edges());
fprops_resize(n_faces());
//just copy status properties for now,
//until a proper solution for refcounted
//properties is available
vertex_status_ = _other.vertex_status_;
halfedge_status_ = _other.halfedge_status_;
edge_status_ = _other.edge_status_;
face_status_ = _other.face_status_;
//initialize refcounter to 1 for the new mesh,
//if status is available.
refcount_estatus_ = _other.refcount_estatus_ > 0 ? 1 : 0;
refcount_vstatus_ = _other.refcount_vstatus_ > 0 ? 1 : 0;
refcount_hstatus_ = _other.refcount_hstatus_ > 0 ? 1 : 0;
refcount_fstatus_ = _other.refcount_fstatus_ > 0 ? 1 : 0;
}
// --- handle -> item ---
VertexHandle ArrayKernel::handle(const Vertex& _v) const
{
return VertexHandle( int( &_v - &vertices_.front()));
}
HalfedgeHandle ArrayKernel::handle(const Halfedge& _he) const
{
// Calculate edge belonging to given halfedge
// There are two halfedges stored per edge
// Get memory position inside edge vector and devide by size of an edge
// to get the corresponding edge for the requested halfedge
size_t eh = ( (char*)&_he - (char*)&edges_.front() ) / sizeof(Edge) ;
assert((&_he == &edges_[eh].halfedges_[0]) ||
(&_he == &edges_[eh].halfedges_[1]));
return ((&_he == &edges_[eh].halfedges_[0]) ?
HalfedgeHandle( int(eh)<<1) : HalfedgeHandle((int(eh)<<1)+1));
}
EdgeHandle ArrayKernel::handle(const Edge& _e) const
{
return EdgeHandle( int(&_e - &edges_.front() ) );
}
FaceHandle ArrayKernel::handle(const Face& _f) const
{
return FaceHandle( int(&_f - &faces_.front()) );
}
#define SIGNED(x) signed( (x) )
bool ArrayKernel::is_valid_handle(VertexHandle _vh) const
{
return 0 <= _vh.idx() && _vh.idx() < SIGNED(n_vertices());
}
bool ArrayKernel::is_valid_handle(HalfedgeHandle _heh) const
{
return 0 <= _heh.idx() && _heh.idx() < SIGNED(n_edges()*2);
}
bool ArrayKernel::is_valid_handle(EdgeHandle _eh) const
{
return 0 <= _eh.idx() && _eh.idx() < SIGNED(n_edges());
}
bool ArrayKernel::is_valid_handle(FaceHandle _fh) const
{
return 0 <= _fh.idx() && _fh.idx() < SIGNED(n_faces());
}
#undef SIGNED
unsigned int ArrayKernel::delete_isolated_vertices()
{
assert(has_vertex_status());//this function requires vertex status property
unsigned int n_isolated = 0;
for (KernelVertexIter v_it = vertices_begin(); v_it != vertices_end(); ++v_it)
{
if (is_isolated(handle(*v_it)))
{
status(handle(*v_it)).set_deleted(true);
n_isolated++;
}
}
return n_isolated;
}
void ArrayKernel::garbage_collection(bool _v, bool _e, bool _f)
{
std::vector<VertexHandle*> empty_vh;
std::vector<HalfedgeHandle*> empty_hh;
std::vector<FaceHandle*> empty_fh;
garbage_collection( empty_vh,empty_hh,empty_fh,_v, _e, _f);
}
void ArrayKernel::clean_keep_reservation()
{
vertices_.clear();
edges_.clear();
faces_.clear();
}
void ArrayKernel::clean()
{
vertices_.clear();
VertexContainer().swap( vertices_ );
edges_.clear();
EdgeContainer().swap( edges_ );
faces_.clear();
FaceContainer().swap( faces_ );
}
void ArrayKernel::clear()
{
vprops_clear();
eprops_clear();
hprops_clear();
fprops_clear();
clean();
}
void ArrayKernel::resize( size_t _n_vertices, size_t _n_edges, size_t _n_faces )
{
vertices_.resize(_n_vertices);
edges_.resize(_n_edges);
faces_.resize(_n_faces);
vprops_resize(n_vertices());
hprops_resize(n_halfedges());
eprops_resize(n_edges());
fprops_resize(n_faces());
}
void ArrayKernel::reserve(size_t _n_vertices, size_t _n_edges, size_t _n_faces )
{
vertices_.reserve(_n_vertices);
edges_.reserve(_n_edges);
faces_.reserve(_n_faces);
vprops_reserve(_n_vertices);
hprops_reserve(_n_edges*2);
eprops_reserve(_n_edges);
fprops_reserve(_n_faces);
}
// Status Sets API
void ArrayKernel::init_bit_masks(BitMaskContainer& _bmc)
{
for (unsigned int i = Attributes::UNUSED; i != 0; i <<= 1)
{
_bmc.push_back(i);
}
}
void ArrayKernel::init_bit_masks()
{
init_bit_masks(vertex_bit_masks_);
edge_bit_masks_ = vertex_bit_masks_;//init_bit_masks(edge_bit_masks_);
face_bit_masks_ = vertex_bit_masks_;//init_bit_masks(face_bit_masks_);
halfedge_bit_masks_= vertex_bit_masks_;//init_bit_masks(halfedge_bit_masks_);
}
};

View File

@ -0,0 +1,915 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS ArrayKernel
//
//=============================================================================
#ifndef OPENMESH_ARRAY_KERNEL_HH
#define OPENMESH_ARRAY_KERNEL_HH
//== INCLUDES =================================================================
#include <vector>
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/GenProg.hh>
#include <OpenMesh/Core/Mesh/ArrayItems.hh>
#include <OpenMesh/Core/Mesh/BaseKernel.hh>
#include <OpenMesh/Core/Mesh/Status.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== CLASS DEFINITION =========================================================
/** \ingroup mesh_kernels_group
Mesh kernel using arrays for mesh item storage.
This mesh kernel uses the std::vector as container to store the
mesh items. Therefore all handle types are internally represented
by integers. To get the index from a handle use the handle's \c
idx() method.
\note For a description of the minimal kernel interface see
OpenMesh::Mesh::BaseKernel.
\note You do not have to use this class directly, use the predefined
mesh-kernel combinations in \ref mesh_types_group.
\see OpenMesh::Concepts::KernelT, \ref mesh_type
*/
class OPENMESHDLLEXPORT ArrayKernel : public BaseKernel, public ArrayItems
{
public:
// handles
typedef OpenMesh::VertexHandle VertexHandle;
typedef OpenMesh::HalfedgeHandle HalfedgeHandle;
typedef OpenMesh::EdgeHandle EdgeHandle;
typedef OpenMesh::FaceHandle FaceHandle;
typedef Attributes::StatusInfo StatusInfo;
typedef VPropHandleT<StatusInfo> VertexStatusPropertyHandle;
typedef HPropHandleT<StatusInfo> HalfedgeStatusPropertyHandle;
typedef EPropHandleT<StatusInfo> EdgeStatusPropertyHandle;
typedef FPropHandleT<StatusInfo> FaceStatusPropertyHandle;
public:
// --- constructor/destructor ---
ArrayKernel();
virtual ~ArrayKernel();
/** ArrayKernel uses the default copy constructor and assignment operator, which means
that the connectivity and all properties are copied, including reference
counters, allocated bit status masks, etc.. In contrast assign_connectivity
copies only the connectivity, i.e. vertices, edges, faces and their status fields.
NOTE: The geometry (the points property) is NOT copied. Poly/TriConnectivity
override(and hide) that function to provide connectivity consistence.*/
void assign_connectivity(const ArrayKernel& _other);
// --- handle -> item ---
VertexHandle handle(const Vertex& _v) const;
HalfedgeHandle handle(const Halfedge& _he) const;
EdgeHandle handle(const Edge& _e) const;
FaceHandle handle(const Face& _f) const;
///checks handle validity - useful for debugging
bool is_valid_handle(VertexHandle _vh) const;
///checks handle validity - useful for debugging
bool is_valid_handle(HalfedgeHandle _heh) const;
///checks handle validity - useful for debugging
bool is_valid_handle(EdgeHandle _eh) const;
///checks handle validity - useful for debugging
bool is_valid_handle(FaceHandle _fh) const;
// --- item -> handle ---
const Vertex& vertex(VertexHandle _vh) const
{
assert(is_valid_handle(_vh));
return vertices_[_vh.idx()];
}
Vertex& vertex(VertexHandle _vh)
{
assert(is_valid_handle(_vh));
return vertices_[_vh.idx()];
}
const Halfedge& halfedge(HalfedgeHandle _heh) const
{
assert(is_valid_handle(_heh));
return edges_[_heh.idx() >> 1].halfedges_[_heh.idx() & 1];
}
Halfedge& halfedge(HalfedgeHandle _heh)
{
assert(is_valid_handle(_heh));
return edges_[_heh.idx() >> 1].halfedges_[_heh.idx() & 1];
}
const Edge& edge(EdgeHandle _eh) const
{
assert(is_valid_handle(_eh));
return edges_[_eh.idx()];
}
Edge& edge(EdgeHandle _eh)
{
assert(is_valid_handle(_eh));
return edges_[_eh.idx()];
}
const Face& face(FaceHandle _fh) const
{
assert(is_valid_handle(_fh));
return faces_[_fh.idx()];
}
Face& face(FaceHandle _fh)
{
assert(is_valid_handle(_fh));
return faces_[_fh.idx()];
}
// --- get i'th items ---
VertexHandle vertex_handle(unsigned int _i) const
{ return (_i < n_vertices()) ? handle( vertices_[_i] ) : VertexHandle(); }
HalfedgeHandle halfedge_handle(unsigned int _i) const
{
return (_i < n_halfedges()) ?
halfedge_handle(edge_handle(_i/2), _i%2) : HalfedgeHandle();
}
EdgeHandle edge_handle(unsigned int _i) const
{ return (_i < n_edges()) ? handle(edges_[_i]) : EdgeHandle(); }
FaceHandle face_handle(unsigned int _i) const
{ return (_i < n_faces()) ? handle(faces_[_i]) : FaceHandle(); }
public:
/**
* \brief Add a new vertex.
*
* If you are rebuilding a mesh that you previously erased using clean() or
* clean_keep_reservation() you probably want to use new_vertex_dirty()
* instead.
*
* \sa new_vertex_dirty()
*/
inline VertexHandle new_vertex()
{
vertices_.push_back(Vertex());
vprops_resize(n_vertices());//TODO:should it be push_back()?
return handle(vertices_.back());
}
/**
* Same as new_vertex() but uses PropertyContainer::resize_if_smaller() to
* resize the vertex property container.
*
* If you are rebuilding a mesh that you erased with clean() or
* clean_keep_reservation() using this method instead of new_vertex() saves
* reallocation and reinitialization of property memory.
*
* \sa new_vertex()
*/
inline VertexHandle new_vertex_dirty()
{
vertices_.push_back(Vertex());
vprops_resize_if_smaller(n_vertices());//TODO:should it be push_back()?
return handle(vertices_.back());
}
inline HalfedgeHandle new_edge(VertexHandle _start_vh, VertexHandle _end_vh)
{
// assert(_start_vh != _end_vh);
edges_.push_back(Edge());
eprops_resize(n_edges());//TODO:should it be push_back()?
hprops_resize(n_halfedges());//TODO:should it be push_back()?
EdgeHandle eh(handle(edges_.back()));
HalfedgeHandle heh0(halfedge_handle(eh, 0));
HalfedgeHandle heh1(halfedge_handle(eh, 1));
set_vertex_handle(heh0, _end_vh);
set_vertex_handle(heh1, _start_vh);
return heh0;
}
inline FaceHandle new_face()
{
faces_.push_back(Face());
fprops_resize(n_faces());
return handle(faces_.back());
}
inline FaceHandle new_face(const Face& _f)
{
faces_.push_back(_f);
fprops_resize(n_faces());
return handle(faces_.back());
}
public:
// --- resize/reserve ---
void resize( size_t _n_vertices, size_t _n_edges, size_t _n_faces );
void reserve(size_t _n_vertices, size_t _n_edges, size_t _n_faces );
// --- deletion ---
/** \brief garbage collection
*
* Usually if you delete primitives in OpenMesh, they are only flagged as deleted.
* Only when you call garbage collection, they will be actually removed.
*
* \note Garbage collection invalidates all handles. If you need to keep track of
* a set of handles, you can pass them to the second garbage collection
* function, which will update a vector of handles.
* See also \ref deletedElements.
*
* @param _v Remove deleted vertices?
* @param _e Remove deleted edges?
* @param _f Remove deleted faces?
*
*/
void garbage_collection(bool _v=true, bool _e=true, bool _f=true);
/** \brief garbage collection with handle tracking
*
* Usually if you delete primitives in OpenMesh, they are only flagged as deleted.
* Only when you call garbage collection, they will be actually removed.
*
* \note Garbage collection invalidates all handles. If you need to keep track of
* a set of handles, you can pass them to this function. The handles that the
* given pointers point to are updated in place.
* See also \ref deletedElements.
*
* @param vh_to_update Pointers to vertex handles that should get updated
* @param hh_to_update Pointers to halfedge handles that should get updated
* @param fh_to_update Pointers to face handles that should get updated
* @param _v Remove deleted vertices?
* @param _e Remove deleted edges?
* @param _f Remove deleted faces?
*/
template<typename std_API_Container_VHandlePointer,
typename std_API_Container_HHandlePointer,
typename std_API_Container_FHandlePointer>
void garbage_collection(std_API_Container_VHandlePointer& vh_to_update,
std_API_Container_HHandlePointer& hh_to_update,
std_API_Container_FHandlePointer& fh_to_update,
bool _v=true, bool _e=true, bool _f=true);
/// \brief Does the same as clean() and in addition erases all properties.
void clear();
/** \brief Remove all vertices, edges and faces and deallocates their memory.
*
* In contrast to clear() this method does neither erases the properties
* nor clears the property vectors. Depending on how you add any new entities
* to the mesh after calling this method, your properties will be initialized
* with old values.
*
* \sa clean_keep_reservation()
*/
void clean();
/** \brief Remove all vertices, edges and faces but keep memory allocated.
*
* This method behaves like clean() (also regarding the properties) but
* leaves the memory used for vertex, edge and face storage allocated. This
* leads to no reduction in memory consumption but allows for faster
* performance when rebuilding the mesh.
*/
void clean_keep_reservation();
// --- number of items ---
size_t n_vertices() const { return vertices_.size(); }
size_t n_halfedges() const { return 2*edges_.size(); }
size_t n_edges() const { return edges_.size(); }
size_t n_faces() const { return faces_.size(); }
bool vertices_empty() const { return vertices_.empty(); }
bool halfedges_empty() const { return edges_.empty(); }
bool edges_empty() const { return edges_.empty(); }
bool faces_empty() const { return faces_.empty(); }
// --- vertex connectivity ---
HalfedgeHandle halfedge_handle(VertexHandle _vh) const
{ return vertex(_vh).halfedge_handle_; }
void set_halfedge_handle(VertexHandle _vh, HalfedgeHandle _heh)
{
// assert(is_valid_handle(_heh));
vertex(_vh).halfedge_handle_ = _heh;
}
bool is_isolated(VertexHandle _vh) const
{ return !halfedge_handle(_vh).is_valid(); }
void set_isolated(VertexHandle _vh)
{ vertex(_vh).halfedge_handle_.invalidate(); }
unsigned int delete_isolated_vertices();
// --- halfedge connectivity ---
VertexHandle to_vertex_handle(HalfedgeHandle _heh) const
{ return halfedge(_heh).vertex_handle_; }
VertexHandle from_vertex_handle(HalfedgeHandle _heh) const
{ return to_vertex_handle(opposite_halfedge_handle(_heh)); }
void set_vertex_handle(HalfedgeHandle _heh, VertexHandle _vh)
{
// assert(is_valid_handle(_vh));
halfedge(_heh).vertex_handle_ = _vh;
}
FaceHandle face_handle(HalfedgeHandle _heh) const
{ return halfedge(_heh).face_handle_; }
void set_face_handle(HalfedgeHandle _heh, FaceHandle _fh)
{
// assert(is_valid_handle(_fh));
halfedge(_heh).face_handle_ = _fh;
}
void set_boundary(HalfedgeHandle _heh)
{ halfedge(_heh).face_handle_.invalidate(); }
/// Is halfedge _heh a boundary halfedge (is its face handle invalid) ?
bool is_boundary(HalfedgeHandle _heh) const
{ return !face_handle(_heh).is_valid(); }
HalfedgeHandle next_halfedge_handle(HalfedgeHandle _heh) const
{ return halfedge(_heh).next_halfedge_handle_; }
void set_next_halfedge_handle(HalfedgeHandle _heh, HalfedgeHandle _nheh)
{
assert(is_valid_handle(_nheh));
// assert(to_vertex_handle(_heh) == from_vertex_handle(_nheh));
halfedge(_heh).next_halfedge_handle_ = _nheh;
set_prev_halfedge_handle(_nheh, _heh);
}
void set_prev_halfedge_handle(HalfedgeHandle _heh, HalfedgeHandle _pheh)
{
assert(is_valid_handle(_pheh));
set_prev_halfedge_handle(_heh, _pheh, HasPrevHalfedge());
}
void set_prev_halfedge_handle(HalfedgeHandle _heh, HalfedgeHandle _pheh,
GenProg::TrueType)
{ halfedge(_heh).prev_halfedge_handle_ = _pheh; }
void set_prev_halfedge_handle(HalfedgeHandle /* _heh */, HalfedgeHandle /* _pheh */,
GenProg::FalseType)
{}
HalfedgeHandle prev_halfedge_handle(HalfedgeHandle _heh) const
{ return prev_halfedge_handle(_heh, HasPrevHalfedge() ); }
HalfedgeHandle prev_halfedge_handle(HalfedgeHandle _heh, GenProg::TrueType) const
{ return halfedge(_heh).prev_halfedge_handle_; }
HalfedgeHandle prev_halfedge_handle(HalfedgeHandle _heh, GenProg::FalseType) const
{
if (is_boundary(_heh))
{//iterating around the vertex should be faster than iterating the boundary
HalfedgeHandle curr_heh(opposite_halfedge_handle(_heh));
HalfedgeHandle next_heh(next_halfedge_handle(curr_heh));
do
{
curr_heh = opposite_halfedge_handle(next_heh);
next_heh = next_halfedge_handle(curr_heh);
}
while (next_heh != _heh);
return curr_heh;
}
else
{
HalfedgeHandle heh(_heh);
HalfedgeHandle next_heh(next_halfedge_handle(heh));
while (next_heh != _heh) {
heh = next_heh;
next_heh = next_halfedge_handle(next_heh);
}
return heh;
}
}
HalfedgeHandle opposite_halfedge_handle(HalfedgeHandle _heh) const
{ return HalfedgeHandle(_heh.idx() ^ 1); }
HalfedgeHandle ccw_rotated_halfedge_handle(HalfedgeHandle _heh) const
{ return opposite_halfedge_handle(prev_halfedge_handle(_heh)); }
HalfedgeHandle cw_rotated_halfedge_handle(HalfedgeHandle _heh) const
{ return next_halfedge_handle(opposite_halfedge_handle(_heh)); }
// --- edge connectivity ---
static HalfedgeHandle s_halfedge_handle(EdgeHandle _eh, unsigned int _i)
{
assert(_i<=1);
return HalfedgeHandle((_eh.idx() << 1) + _i);
}
static EdgeHandle s_edge_handle(HalfedgeHandle _heh)
{ return EdgeHandle(_heh.idx() >> 1); }
HalfedgeHandle halfedge_handle(EdgeHandle _eh, unsigned int _i) const
{
return s_halfedge_handle(_eh, _i);
}
EdgeHandle edge_handle(HalfedgeHandle _heh) const
{ return s_edge_handle(_heh); }
// --- face connectivity ---
HalfedgeHandle halfedge_handle(FaceHandle _fh) const
{ return face(_fh).halfedge_handle_; }
void set_halfedge_handle(FaceHandle _fh, HalfedgeHandle _heh)
{
// assert(is_valid_handle(_heh));
face(_fh).halfedge_handle_ = _heh;
}
/// Status Query API
//------------------------------------------------------------ vertex status
const StatusInfo& status(VertexHandle _vh) const
{ return property(vertex_status_, _vh); }
StatusInfo& status(VertexHandle _vh)
{ return property(vertex_status_, _vh); }
/**
* Reinitializes the status of all vertices using the StatusInfo default
* constructor, i.e. all flags will be set to false.
*/
void reset_status() {
PropertyT<StatusInfo> &status_prop = property(vertex_status_);
PropertyT<StatusInfo>::vector_type &sprop_v = status_prop.data_vector();
std::fill(sprop_v.begin(), sprop_v.begin() + n_vertices(), StatusInfo());
}
//----------------------------------------------------------- halfedge status
const StatusInfo& status(HalfedgeHandle _hh) const
{ return property(halfedge_status_, _hh); }
StatusInfo& status(HalfedgeHandle _hh)
{ return property(halfedge_status_, _hh); }
//--------------------------------------------------------------- edge status
const StatusInfo& status(EdgeHandle _eh) const
{ return property(edge_status_, _eh); }
StatusInfo& status(EdgeHandle _eh)
{ return property(edge_status_, _eh); }
//--------------------------------------------------------------- face status
const StatusInfo& status(FaceHandle _fh) const
{ return property(face_status_, _fh); }
StatusInfo& status(FaceHandle _fh)
{ return property(face_status_, _fh); }
inline bool has_vertex_status() const
{ return vertex_status_.is_valid(); }
inline bool has_halfedge_status() const
{ return halfedge_status_.is_valid(); }
inline bool has_edge_status() const
{ return edge_status_.is_valid(); }
inline bool has_face_status() const
{ return face_status_.is_valid(); }
inline VertexStatusPropertyHandle vertex_status_pph() const
{ return vertex_status_; }
inline HalfedgeStatusPropertyHandle halfedge_status_pph() const
{ return halfedge_status_; }
inline EdgeStatusPropertyHandle edge_status_pph() const
{ return edge_status_; }
inline FaceStatusPropertyHandle face_status_pph() const
{ return face_status_; }
/// status property by handle
inline VertexStatusPropertyHandle status_pph(VertexHandle /*_hnd*/) const
{ return vertex_status_pph(); }
inline HalfedgeStatusPropertyHandle status_pph(HalfedgeHandle /*_hnd*/) const
{ return halfedge_status_pph(); }
inline EdgeStatusPropertyHandle status_pph(EdgeHandle /*_hnd*/) const
{ return edge_status_pph(); }
inline FaceStatusPropertyHandle status_pph(FaceHandle /*_hnd*/) const
{ return face_status_pph(); }
/// Status Request API
void request_vertex_status()
{
if (!refcount_vstatus_++)
add_property( vertex_status_, "v:status" );
}
void request_halfedge_status()
{
if (!refcount_hstatus_++)
add_property( halfedge_status_, "h:status" );
}
void request_edge_status()
{
if (!refcount_estatus_++)
add_property( edge_status_, "e:status" );
}
void request_face_status()
{
if (!refcount_fstatus_++)
add_property( face_status_, "f:status" );
}
/// Status Release API
void release_vertex_status()
{
if ((refcount_vstatus_ > 0) && (! --refcount_vstatus_))
remove_property(vertex_status_);
}
void release_halfedge_status()
{
if ((refcount_hstatus_ > 0) && (! --refcount_hstatus_))
remove_property(halfedge_status_);
}
void release_edge_status()
{
if ((refcount_estatus_ > 0) && (! --refcount_estatus_))
remove_property(edge_status_);
}
void release_face_status()
{
if ((refcount_fstatus_ > 0) && (! --refcount_fstatus_))
remove_property(face_status_);
}
/// --- StatusSet API ---
/*!
Implements a set of connectivity entities (vertex, edge, face, halfedge)
using the available bits in the corresponding mesh status field.
Status-based sets are much faster than std::set<> and equivalent
in performance to std::vector<bool>, but much more convenient.
*/
template <class HandleT>
class StatusSetT
{
public:
typedef HandleT Handle;
protected:
ArrayKernel& kernel_;
public:
const unsigned int bit_mask_;
public:
StatusSetT(ArrayKernel& _kernel, const unsigned int _bit_mask)
: kernel_(_kernel), bit_mask_(_bit_mask)
{}
~StatusSetT()
{}
inline bool is_in(Handle _hnd) const
{ return kernel_.status(_hnd).is_bit_set(bit_mask_); }
inline void insert(Handle _hnd)
{ kernel_.status(_hnd).set_bit(bit_mask_); }
inline void erase(Handle _hnd)
{ kernel_.status(_hnd).unset_bit(bit_mask_); }
//! Note: 0(n) complexity
size_t size() const
{
const int n = kernel_.status_pph(Handle()).is_valid() ?
(int)kernel_.property(kernel_.status_pph(Handle())).n_elements() : 0;
size_t sz = 0;
for (int i = 0; i < n; ++i)
sz += (size_t)is_in(Handle(i));
return sz;
}
//! Note: O(n) complexity
void clear()
{
const int n = kernel_.status_pph(Handle()).is_valid() ?
(int)kernel_.property(kernel_.status_pph(Handle())).n_elements() : 0;
for (int i = 0; i < n; ++i)
erase(Handle(i));
}
};
friend class StatusSetT<VertexHandle>;
friend class StatusSetT<EdgeHandle>;
friend class StatusSetT<FaceHandle>;
friend class StatusSetT<HalfedgeHandle>;
//! AutoStatusSetT: A status set that automatically picks a status bit
template <class HandleT>
class AutoStatusSetT : public StatusSetT<HandleT>
{
private:
typedef HandleT Handle;
typedef StatusSetT<Handle> Base;
public:
AutoStatusSetT(ArrayKernel& _kernel)
: StatusSetT<Handle>(_kernel, _kernel.pop_bit_mask(Handle()))
{ /*assert(size() == 0);*/ } //the set should be empty on creation
~AutoStatusSetT()
{
//assert(size() == 0);//the set should be empty on leave?
Base::kernel_.push_bit_mask(Handle(), Base::bit_mask_);
}
};
friend class AutoStatusSetT<VertexHandle>;
friend class AutoStatusSetT<EdgeHandle>;
friend class AutoStatusSetT<FaceHandle>;
friend class AutoStatusSetT<HalfedgeHandle>;
typedef AutoStatusSetT<VertexHandle> VertexStatusSet;
typedef AutoStatusSetT<EdgeHandle> EdgeStatusSet;
typedef AutoStatusSetT<FaceHandle> FaceStatusSet;
typedef AutoStatusSetT<HalfedgeHandle> HalfedgeStatusSet;
//! ExtStatusSet: A status set augmented with an array
template <class HandleT>
class ExtStatusSetT : public AutoStatusSetT<HandleT>
{
public:
typedef HandleT Handle;
typedef AutoStatusSetT<Handle> Base;
protected:
typedef std::vector<Handle> HandleContainer;
HandleContainer handles_;
public:
typedef typename HandleContainer::iterator
iterator;
typedef typename HandleContainer::const_iterator
const_iterator;
public:
ExtStatusSetT(ArrayKernel& _kernel, size_t _capacity_hint = 0)
: Base(_kernel)
{ handles_.reserve(_capacity_hint); }
~ExtStatusSetT()
{ clear(); }
// Complexity: O(1)
inline void insert(Handle _hnd)
{
if (!is_in(_hnd))
{
Base::insert(_hnd);
handles_.push_back(_hnd);
}
}
//! Complexity: O(k), (k - number of the elements in the set)
inline void erase(Handle _hnd)
{
if (is_in(_hnd))
{
iterator it = std::find(begin(), end(), _hnd);
erase(it);
}
}
//! Complexity: O(1)
inline void erase(iterator _it)
{
assert(_it != end() && is_in(*_it));
Base::erase(*_it);
*_it = handles_.back();
_it.pop_back();
}
inline void clear()
{
for (iterator it = begin(); it != end(); ++it)
{
assert(is_in(*it));
Base::erase(*it);
}
handles_.clear();
}
/// Complexity: 0(1)
inline unsigned int size() const
{ return handles_.size(); }
inline bool empty() const
{ return handles_.empty(); }
//Vector API
inline iterator begin()
{ return handles_.begin(); }
inline const_iterator begin() const
{ return handles_.begin(); }
inline iterator end()
{ return handles_.end(); }
inline const_iterator end() const
{ return handles_.end(); }
inline Handle& front()
{ return handles_.front(); }
inline const Handle& front() const
{ return handles_.front(); }
inline Handle& back()
{ return handles_.back(); }
inline const Handle& back() const
{ return handles_.back(); }
};
typedef ExtStatusSetT<FaceHandle> ExtFaceStatusSet;
typedef ExtStatusSetT<VertexHandle> ExtVertexStatusSet;
typedef ExtStatusSetT<EdgeHandle> ExtEdgeStatusSet;
typedef ExtStatusSetT<HalfedgeHandle> ExtHalfedgeStatusSet;
private:
// iterators
typedef std::vector<Vertex> VertexContainer;
typedef std::vector<Edge> EdgeContainer;
typedef std::vector<Face> FaceContainer;
typedef VertexContainer::iterator KernelVertexIter;
typedef VertexContainer::const_iterator KernelConstVertexIter;
typedef EdgeContainer::iterator KernelEdgeIter;
typedef EdgeContainer::const_iterator KernelConstEdgeIter;
typedef FaceContainer::iterator KernelFaceIter;
typedef FaceContainer::const_iterator KernelConstFaceIter;
typedef std::vector<unsigned int> BitMaskContainer;
KernelVertexIter vertices_begin() { return vertices_.begin(); }
KernelConstVertexIter vertices_begin() const { return vertices_.begin(); }
KernelVertexIter vertices_end() { return vertices_.end(); }
KernelConstVertexIter vertices_end() const { return vertices_.end(); }
KernelEdgeIter edges_begin() { return edges_.begin(); }
KernelConstEdgeIter edges_begin() const { return edges_.begin(); }
KernelEdgeIter edges_end() { return edges_.end(); }
KernelConstEdgeIter edges_end() const { return edges_.end(); }
KernelFaceIter faces_begin() { return faces_.begin(); }
KernelConstFaceIter faces_begin() const { return faces_.begin(); }
KernelFaceIter faces_end() { return faces_.end(); }
KernelConstFaceIter faces_end() const { return faces_.end(); }
/// bit mask container by handle
inline BitMaskContainer& bit_masks(VertexHandle /*_dummy_hnd*/)
{ return vertex_bit_masks_; }
inline BitMaskContainer& bit_masks(EdgeHandle /*_dummy_hnd*/)
{ return edge_bit_masks_; }
inline BitMaskContainer& bit_masks(FaceHandle /*_dummy_hnd*/)
{ return face_bit_masks_; }
inline BitMaskContainer& bit_masks(HalfedgeHandle /*_dummy_hnd*/)
{ return halfedge_bit_masks_; }
template <class Handle>
unsigned int pop_bit_mask(Handle _hnd)
{
assert(!bit_masks(_hnd).empty());//check if the client request too many status sets
unsigned int bit_mask = bit_masks(_hnd).back();
bit_masks(_hnd).pop_back();
return bit_mask;
}
template <class Handle>
void push_bit_mask(Handle _hnd, unsigned int _bit_mask)
{
assert(std::find(bit_masks(_hnd).begin(), bit_masks(_hnd).end(), _bit_mask) ==
bit_masks(_hnd).end());//this mask should be not already used
bit_masks(_hnd).push_back(_bit_mask);
}
void init_bit_masks(BitMaskContainer& _bmc);
void init_bit_masks();
protected:
VertexStatusPropertyHandle vertex_status_;
HalfedgeStatusPropertyHandle halfedge_status_;
EdgeStatusPropertyHandle edge_status_;
FaceStatusPropertyHandle face_status_;
unsigned int refcount_vstatus_;
unsigned int refcount_hstatus_;
unsigned int refcount_estatus_;
unsigned int refcount_fstatus_;
private:
VertexContainer vertices_;
EdgeContainer edges_;
FaceContainer faces_;
BitMaskContainer halfedge_bit_masks_;
BitMaskContainer edge_bit_masks_;
BitMaskContainer vertex_bit_masks_;
BitMaskContainer face_bit_masks_;
};
//=============================================================================
} // namespace OpenMesh
//=============================================================================
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_ARRAY_KERNEL_C)
# define OPENMESH_ARRAY_KERNEL_TEMPLATES
# include "ArrayKernelT.cc"
#endif
//=============================================================================
#endif // OPENMESH_ARRAY_KERNEL_HH defined
//=============================================================================

View File

@ -0,0 +1,315 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision: 362 $ *
* $Date: 2011-01-26 10:21:12 +0100 (Mi, 26 Jan 2011) $ *
* *
\*===========================================================================*/
#define OPENMESH_ARRAY_KERNEL_C
//== INCLUDES =================================================================
#include <OpenMesh/Core/Mesh/ArrayKernel.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh
{
//== IMPLEMENTATION ==========================================================
template<typename std_API_Container_VHandlePointer,
typename std_API_Container_HHandlePointer,
typename std_API_Container_FHandlePointer>
void ArrayKernel::garbage_collection(std_API_Container_VHandlePointer& vh_to_update,
std_API_Container_HHandlePointer& hh_to_update,
std_API_Container_FHandlePointer& fh_to_update,
bool _v, bool _e, bool _f)
{
#ifdef DEBUG
#ifndef OM_GARBAGE_NO_STATUS_WARNING
if ( !this->has_vertex_status() )
omerr() << "garbage_collection: No vertex status available. You can request it: mesh.request_vertex_status() or define OM_GARBAGE_NO_STATUS_WARNING to silence this warning." << std::endl;
if ( !this->has_edge_status() )
omerr() << "garbage_collection: No edge status available. You can request it: mesh.request_edge_status() or define OM_GARBAGE_NO_STATUS_WARNING to silence this warning." << std::endl;
if ( !this->has_face_status() )
omerr() << "garbage_collection: No face status available. You can request it: mesh.request_face_status() or define OM_GARBAGE_NO_STATUS_WARNING to silence this warning." << std::endl;
#endif
#endif
const bool track_vhandles = ( !vh_to_update.empty() );
const bool track_hhandles = ( !hh_to_update.empty() );
const bool track_fhandles = ( !fh_to_update.empty() );
int i, i0, i1;
int nV = int(n_vertices());
int nE = int(n_edges());
int nH = int(2*n_edges());
int nF = (int(n_faces()));
std::vector<VertexHandle> vh_map;
std::vector<HalfedgeHandle> hh_map;
std::vector<FaceHandle> fh_map;
std::map <int, int> vertex_inverse_map;
std::map <int, int> halfedge_inverse_map;
std::map <int, int> face_inverse_map;
// setup handle mapping:
vh_map.reserve(nV);
for (i=0; i<nV; ++i) vh_map.push_back(VertexHandle(i));
hh_map.reserve(nH);
for (i=0; i<nH; ++i) hh_map.push_back(HalfedgeHandle(i));
fh_map.reserve(nF);
for (i=0; i<nF; ++i) fh_map.push_back(FaceHandle(i));
// remove deleted vertices
if (_v && n_vertices() > 0 && this->has_vertex_status() )
{
i0=0; i1=nV-1;
while (1)
{
// find 1st deleted and last un-deleted
while (!status(VertexHandle(i0)).deleted() && i0 < i1) ++i0;
while ( status(VertexHandle(i1)).deleted() && i0 < i1) --i1;
if (i0 >= i1) break;
// If we keep track of the vertex handles for updates,
// we need to have the opposite direction
if ( track_vhandles ) {
vertex_inverse_map[i1] = i0;
vertex_inverse_map[i0] = -1;
}
// swap
std::swap(vertices_[i0], vertices_[i1]);
std::swap(vh_map[i0], vh_map[i1]);
vprops_swap(i0, i1);
};
vertices_.resize(status(VertexHandle(i0)).deleted() ? i0 : i0+1);
vprops_resize(n_vertices());
}
// remove deleted edges
if (_e && n_edges() > 0 && this->has_edge_status() )
{
i0=0; i1=nE-1;
while (1)
{
// find 1st deleted and last un-deleted
while (!status(EdgeHandle(i0)).deleted() && i0 < i1) ++i0;
while ( status(EdgeHandle(i1)).deleted() && i0 < i1) --i1;
if (i0 >= i1) break;
// If we keep track of the vertex handles for updates,
// we need to have the opposite direction
if ( track_hhandles ) {
halfedge_inverse_map[2*i1] = 2 * i0;
halfedge_inverse_map[2*i0] = -1;
halfedge_inverse_map[2*i1 + 1] = 2 * i0 + 1;
halfedge_inverse_map[2*i0 + 1] = -1;
}
// swap
std::swap(edges_[i0], edges_[i1]);
std::swap(hh_map[2*i0], hh_map[2*i1]);
std::swap(hh_map[2*i0+1], hh_map[2*i1+1]);
eprops_swap(i0, i1);
hprops_swap(2*i0, 2*i1);
hprops_swap(2*i0+1, 2*i1+1);
};
edges_.resize(status(EdgeHandle(i0)).deleted() ? i0 : i0+1);
eprops_resize(n_edges());
hprops_resize(n_halfedges());
}
// remove deleted faces
if (_f && n_faces() > 0 && this->has_face_status() )
{
i0=0; i1=nF-1;
while (1)
{
// find 1st deleted and last un-deleted
while (!status(FaceHandle(i0)).deleted() && i0 < i1) ++i0;
while ( status(FaceHandle(i1)).deleted() && i0 < i1) --i1;
if (i0 >= i1) break;
// If we keep track of the face handles for updates,
// we need to have the opposite direction
if ( track_fhandles ) {
face_inverse_map[i1] = i0;
face_inverse_map[i0] = -1;
}
// swap
std::swap(faces_[i0], faces_[i1]);
std::swap(fh_map[i0], fh_map[i1]);
fprops_swap(i0, i1);
};
faces_.resize(status(FaceHandle(i0)).deleted() ? i0 : i0+1);
fprops_resize(n_faces());
}
// update handles of vertices
if (_e)
{
KernelVertexIter v_it(vertices_begin()), v_end(vertices_end());
VertexHandle vh;
for (; v_it!=v_end; ++v_it)
{
vh = handle(*v_it);
if (!is_isolated(vh))
{
set_halfedge_handle(vh, hh_map[halfedge_handle(vh).idx()]);
}
}
}
HalfedgeHandle hh;
// update handles of halfedges
for (KernelEdgeIter e_it(edges_begin()); e_it != edges_end(); ++e_it)
{//in the first pass update the (half)edges vertices
hh = halfedge_handle(handle(*e_it), 0);
set_vertex_handle(hh, vh_map[to_vertex_handle(hh).idx()]);
hh = halfedge_handle(handle(*e_it), 1);
set_vertex_handle(hh, vh_map[to_vertex_handle(hh).idx()]);
}
for (KernelEdgeIter e_it(edges_begin()); e_it != edges_end(); ++e_it)
{//in the second pass update the connectivity of the (half)edges
hh = halfedge_handle(handle(*e_it), 0);
set_next_halfedge_handle(hh, hh_map[next_halfedge_handle(hh).idx()]);
if (!is_boundary(hh))
{
set_face_handle(hh, fh_map[face_handle(hh).idx()]);
}
hh = halfedge_handle(handle(*e_it), 1);
set_next_halfedge_handle(hh, hh_map[next_halfedge_handle(hh).idx()]);
if (!is_boundary(hh))
{
set_face_handle(hh, fh_map[face_handle(hh).idx()]);
}
}
// update handles of faces
if (_e)
{
KernelFaceIter f_it(faces_begin()), f_end(faces_end());
FaceHandle fh;
for (; f_it!=f_end; ++f_it)
{
fh = handle(*f_it);
set_halfedge_handle(fh, hh_map[halfedge_handle(fh).idx()]);
}
}
const int vertexCount = int(vertices_.size());
const int halfedgeCount = int(edges_.size() * 2);
const int faceCount = int(faces_.size());
// Update the vertex handles in the vertex handle vector
typename std_API_Container_VHandlePointer::iterator v_it(vh_to_update.begin()), v_it_end(vh_to_update.end());
for(; v_it != v_it_end; ++v_it)
{
// Only changed vertices need to be considered
if ( (*v_it)->idx() != vh_map[(*v_it)->idx()].idx() ) {
*(*v_it) = VertexHandle(vertex_inverse_map[(*v_it)->idx()]);
// Vertices above the vertex count have to be already mapped, or they are invalid now!
} else if ( ((*v_it)->idx() >= vertexCount) && (vertex_inverse_map.find((*v_it)->idx()) == vertex_inverse_map.end()) ) {
(*v_it)->invalidate();
}
}
// Update the halfedge handles in the halfedge handle vector
typename std_API_Container_HHandlePointer::iterator hh_it(hh_to_update.begin()), hh_it_end(hh_to_update.end());
for(; hh_it != hh_it_end; ++hh_it)
{
// Only changed faces need to be considered
if ( (*hh_it)->idx() != hh_map[(*hh_it)->idx()].idx() ) {
*(*hh_it) = HalfedgeHandle(halfedge_inverse_map[(*hh_it)->idx()]);
// Vertices above the face count have to be already mapped, or they are invalid now!
} else if ( ((*hh_it)->idx() >= halfedgeCount) && (halfedge_inverse_map.find((*hh_it)->idx()) == halfedge_inverse_map.end()) ) {
(*hh_it)->invalidate();
}
}
// Update the face handles in the face handle vector
typename std_API_Container_FHandlePointer::iterator fh_it(fh_to_update.begin()), fh_it_end(fh_to_update.end());
for(; fh_it != fh_it_end; ++fh_it)
{
// Only changed faces need to be considered
if ( (*fh_it)->idx() != fh_map[(*fh_it)->idx()].idx() ) {
*(*fh_it) = FaceHandle(face_inverse_map[(*fh_it)->idx()]);
// Vertices above the face count have to be already mapped, or they are invalid now!
} else if ( ((*fh_it)->idx() >= faceCount) && (face_inverse_map.find((*fh_it)->idx()) == face_inverse_map.end()) ) {
(*fh_it)->invalidate();
}
}
}
}

View File

@ -0,0 +1,782 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OPENMESH_ATTRIBKERNEL_HH
#define OPENMESH_ATTRIBKERNEL_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/Mesh/Attributes.hh>
#include <OpenMesh/Core/Utils/GenProg.hh>
#include <OpenMesh/Core/Utils/vector_traits.hh>
#include <vector>
#include <algorithm>
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== CLASS DEFINITION =========================================================
/** \class AttribKernelT AttribKernelT.hh <OpenMesh/Mesh/AttribKernelT.hh>
The attribute kernel adds all standard properties to the kernel. Therefore
the functions/types defined here provide a subset of the kernel
interface as described in Concepts::KernelT.
\see Concepts::KernelT
*/
template <class MeshItems, class Connectivity>
class AttribKernelT : public Connectivity
{
public:
//---------------------------------------------------------------- item types
typedef MeshItems MeshItemsT;
typedef Connectivity ConnectivityT;
typedef typename Connectivity::Vertex Vertex;
typedef typename Connectivity::Halfedge Halfedge;
typedef typename Connectivity::Edge Edge;
typedef typename Connectivity::Face Face;
typedef typename MeshItems::Point Point;
typedef typename MeshItems::Normal Normal;
typedef typename MeshItems::Color Color;
typedef typename MeshItems::TexCoord1D TexCoord1D;
typedef typename MeshItems::TexCoord2D TexCoord2D;
typedef typename MeshItems::TexCoord3D TexCoord3D;
typedef typename MeshItems::Scalar Scalar;
typedef typename MeshItems::TextureIndex TextureIndex;
typedef typename MeshItems::VertexData VertexData;
typedef typename MeshItems::HalfedgeData HalfedgeData;
typedef typename MeshItems::EdgeData EdgeData;
typedef typename MeshItems::FaceData FaceData;
typedef AttribKernelT<MeshItems,Connectivity> AttribKernel;
enum Attribs {
VAttribs = MeshItems::VAttribs,
HAttribs = MeshItems::HAttribs,
EAttribs = MeshItems::EAttribs,
FAttribs = MeshItems::FAttribs
};
typedef VPropHandleT<VertexData> DataVPropHandle;
typedef HPropHandleT<HalfedgeData> DataHPropHandle;
typedef EPropHandleT<EdgeData> DataEPropHandle;
typedef FPropHandleT<FaceData> DataFPropHandle;
public:
//-------------------------------------------------- constructor / destructor
AttribKernelT()
: refcount_vnormals_(0),
refcount_vcolors_(0),
refcount_vtexcoords1D_(0),
refcount_vtexcoords2D_(0),
refcount_vtexcoords3D_(0),
refcount_htexcoords1D_(0),
refcount_htexcoords2D_(0),
refcount_htexcoords3D_(0),
refcount_henormals_(0),
refcount_hecolors_(0),
refcount_ecolors_(0),
refcount_fnormals_(0),
refcount_fcolors_(0),
refcount_ftextureIndex_(0)
{
this->add_property( points_, "v:points" );
if (VAttribs & Attributes::Normal)
request_vertex_normals();
if (VAttribs & Attributes::Color)
request_vertex_colors();
if (VAttribs & Attributes::TexCoord1D)
request_vertex_texcoords1D();
if (VAttribs & Attributes::TexCoord2D)
request_vertex_texcoords2D();
if (VAttribs & Attributes::TexCoord3D)
request_vertex_texcoords3D();
if (HAttribs & Attributes::TexCoord1D)
request_halfedge_texcoords1D();
if (HAttribs & Attributes::TexCoord2D)
request_halfedge_texcoords2D();
if (HAttribs & Attributes::TexCoord3D)
request_halfedge_texcoords3D();
if (HAttribs & Attributes::Color)
request_halfedge_colors();
if (VAttribs & Attributes::Status)
Connectivity::request_vertex_status();
if (HAttribs & Attributes::Status)
Connectivity::request_halfedge_status();
if (HAttribs & Attributes::Normal)
request_halfedge_normals();
if (EAttribs & Attributes::Status)
Connectivity::request_edge_status();
if (EAttribs & Attributes::Color)
request_edge_colors();
if (FAttribs & Attributes::Normal)
request_face_normals();
if (FAttribs & Attributes::Color)
request_face_colors();
if (FAttribs & Attributes::Status)
Connectivity::request_face_status();
if (FAttribs & Attributes::TextureIndex)
request_face_texture_index();
//FIXME: data properties might actually cost storage even
//if there are no data traits??
this->add_property(data_vpph_);
this->add_property(data_fpph_);
this->add_property(data_hpph_);
this->add_property(data_epph_);
}
virtual ~AttribKernelT()
{
// should remove properties, but this will be done in
// BaseKernel's destructor anyway...
}
/** Assignment from another mesh of \em another type.
\note All that's copied is connectivity and vertex positions.
All other information (like e.g. attributes or additional
elements from traits classes) is not copied.
\note If you want to copy all information, including *custom* properties,
use PolyMeshT::operator=() instead.
*/
template <class _AttribKernel>
void assign(const _AttribKernel& _other, bool copyStandardProperties = false)
{
//copy standard properties if necessary
if(copyStandardProperties)
this->copy_all_kernel_properties(_other);
this->assign_connectivity(_other);
for (typename Connectivity::VertexIter v_it = Connectivity::vertices_begin();
v_it != Connectivity::vertices_end(); ++v_it)
{//assumes Point constructor supports cast from _AttribKernel::Point
set_point(*v_it, (Point)_other.point(*v_it));
}
//initialize standard properties if necessary
if(copyStandardProperties)
initializeStandardProperties();
}
//-------------------------------------------------------------------- points
const Point* points() const
{ return this->property(points_).data(); }
const Point& point(VertexHandle _vh) const
{ return this->property(points_, _vh); }
Point& point(VertexHandle _vh)
{ return this->property(points_, _vh); }
void set_point(VertexHandle _vh, const Point& _p)
{ this->property(points_, _vh) = _p; }
//------------------------------------------------------------ vertex normals
const Normal* vertex_normals() const
{ return this->property(vertex_normals_).data(); }
const Normal& normal(VertexHandle _vh) const
{ return this->property(vertex_normals_, _vh); }
void set_normal(VertexHandle _vh, const Normal& _n)
{ this->property(vertex_normals_, _vh) = _n; }
//------------------------------------------------------------- vertex colors
const Color* vertex_colors() const
{ return this->property(vertex_colors_).data(); }
const Color& color(VertexHandle _vh) const
{ return this->property(vertex_colors_, _vh); }
void set_color(VertexHandle _vh, const Color& _c)
{ this->property(vertex_colors_, _vh) = _c; }
//------------------------------------------------------- vertex 1D texcoords
const TexCoord1D* texcoords1D() const {
return this->property(vertex_texcoords1D_).data();
}
const TexCoord1D& texcoord1D(VertexHandle _vh) const {
return this->property(vertex_texcoords1D_, _vh);
}
void set_texcoord1D(VertexHandle _vh, const TexCoord1D& _t) {
this->property(vertex_texcoords1D_, _vh) = _t;
}
//------------------------------------------------------- vertex 2D texcoords
const TexCoord2D* texcoords2D() const {
return this->property(vertex_texcoords2D_).data();
}
const TexCoord2D& texcoord2D(VertexHandle _vh) const {
return this->property(vertex_texcoords2D_, _vh);
}
void set_texcoord2D(VertexHandle _vh, const TexCoord2D& _t) {
this->property(vertex_texcoords2D_, _vh) = _t;
}
//------------------------------------------------------- vertex 3D texcoords
const TexCoord3D* texcoords3D() const {
return this->property(vertex_texcoords3D_).data();
}
const TexCoord3D& texcoord3D(VertexHandle _vh) const {
return this->property(vertex_texcoords3D_, _vh);
}
void set_texcoord3D(VertexHandle _vh, const TexCoord3D& _t) {
this->property(vertex_texcoords3D_, _vh) = _t;
}
//.------------------------------------------------------ halfedge 1D texcoords
const TexCoord1D* htexcoords1D() const {
return this->property(halfedge_texcoords1D_).data();
}
const TexCoord1D& texcoord1D(HalfedgeHandle _heh) const {
return this->property(halfedge_texcoords1D_, _heh);
}
void set_texcoord1D(HalfedgeHandle _heh, const TexCoord1D& _t) {
this->property(halfedge_texcoords1D_, _heh) = _t;
}
//------------------------------------------------------- halfedge 2D texcoords
const TexCoord2D* htexcoords2D() const {
return this->property(halfedge_texcoords2D_).data();
}
const TexCoord2D& texcoord2D(HalfedgeHandle _heh) const {
return this->property(halfedge_texcoords2D_, _heh);
}
void set_texcoord2D(HalfedgeHandle _heh, const TexCoord2D& _t) {
this->property(halfedge_texcoords2D_, _heh) = _t;
}
//------------------------------------------------------- halfedge 3D texcoords
const TexCoord3D* htexcoords3D() const {
return this->property(halfedge_texcoords3D_).data();
}
const TexCoord3D& texcoord3D(HalfedgeHandle _heh) const {
return this->property(halfedge_texcoords3D_, _heh);
}
void set_texcoord3D(HalfedgeHandle _heh, const TexCoord3D& _t) {
this->property(halfedge_texcoords3D_, _heh) = _t;
}
//------------------------------------------------------------- edge colors
const Color* edge_colors() const
{ return this->property(edge_colors_).data(); }
const Color& color(EdgeHandle _eh) const
{ return this->property(edge_colors_, _eh); }
void set_color(EdgeHandle _eh, const Color& _c)
{ this->property(edge_colors_, _eh) = _c; }
//------------------------------------------------------------- halfedge normals
const Normal& normal(HalfedgeHandle _heh) const
{ return this->property(halfedge_normals_, _heh); }
void set_normal(HalfedgeHandle _heh, const Normal& _n)
{ this->property(halfedge_normals_, _heh) = _n; }
//------------------------------------------------------------- halfedge colors
const Color* halfedge_colors() const
{ return this->property(halfedge_colors_).data(); }
const Color& color(HalfedgeHandle _heh) const
{ return this->property(halfedge_colors_, _heh); }
void set_color(HalfedgeHandle _heh, const Color& _c)
{ this->property(halfedge_colors_, _heh) = _c; }
//-------------------------------------------------------------- face normals
const Normal& normal(FaceHandle _fh) const
{ return this->property(face_normals_, _fh); }
void set_normal(FaceHandle _fh, const Normal& _n)
{ this->property(face_normals_, _fh) = _n; }
//-------------------------------------------------------------- per Face Texture index
const TextureIndex& texture_index(FaceHandle _fh) const
{ return this->property(face_texture_index_, _fh); }
void set_texture_index(FaceHandle _fh, const TextureIndex& _t)
{ this->property(face_texture_index_, _fh) = _t; }
//--------------------------------------------------------------- face colors
const Color& color(FaceHandle _fh) const
{ return this->property(face_colors_, _fh); }
void set_color(FaceHandle _fh, const Color& _c)
{ this->property(face_colors_, _fh) = _c; }
//------------------------------------------------ request / alloc properties
void request_vertex_normals()
{
if (!refcount_vnormals_++)
this->add_property( vertex_normals_, "v:normals" );
}
void request_vertex_colors()
{
if (!refcount_vcolors_++)
this->add_property( vertex_colors_, "v:colors" );
}
void request_vertex_texcoords1D()
{
if (!refcount_vtexcoords1D_++)
this->add_property( vertex_texcoords1D_, "v:texcoords1D" );
}
void request_vertex_texcoords2D()
{
if (!refcount_vtexcoords2D_++)
this->add_property( vertex_texcoords2D_, "v:texcoords2D" );
}
void request_vertex_texcoords3D()
{
if (!refcount_vtexcoords3D_++)
this->add_property( vertex_texcoords3D_, "v:texcoords3D" );
}
void request_halfedge_texcoords1D()
{
if (!refcount_htexcoords1D_++)
this->add_property( halfedge_texcoords1D_, "h:texcoords1D" );
}
void request_halfedge_texcoords2D()
{
if (!refcount_htexcoords2D_++)
this->add_property( halfedge_texcoords2D_, "h:texcoords2D" );
}
void request_halfedge_texcoords3D()
{
if (!refcount_htexcoords3D_++)
this->add_property( halfedge_texcoords3D_, "h:texcoords3D" );
}
void request_edge_colors()
{
if (!refcount_ecolors_++)
this->add_property( edge_colors_, "e:colors" );
}
void request_halfedge_normals()
{
if (!refcount_henormals_++)
this->add_property( halfedge_normals_, "h:normals" );
}
void request_halfedge_colors()
{
if (!refcount_hecolors_++)
this->add_property( halfedge_colors_, "h:colors" );
}
void request_face_normals()
{
if (!refcount_fnormals_++)
this->add_property( face_normals_, "f:normals" );
}
void request_face_colors()
{
if (!refcount_fcolors_++)
this->add_property( face_colors_, "f:colors" );
}
void request_face_texture_index()
{
if (!refcount_ftextureIndex_++)
this->add_property( face_texture_index_, "f:textureindex" );
}
//------------------------------------------------- release / free properties
void release_vertex_normals()
{
if ((refcount_vnormals_ > 0) && (! --refcount_vnormals_))
this->remove_property(vertex_normals_);
}
void release_vertex_colors()
{
if ((refcount_vcolors_ > 0) && (! --refcount_vcolors_))
this->remove_property(vertex_colors_);
}
void release_vertex_texcoords1D() {
if ((refcount_vtexcoords1D_ > 0) && (! --refcount_vtexcoords1D_))
this->remove_property(vertex_texcoords1D_);
}
void release_vertex_texcoords2D() {
if ((refcount_vtexcoords2D_ > 0) && (! --refcount_vtexcoords2D_))
this->remove_property(vertex_texcoords2D_);
}
void release_vertex_texcoords3D() {
if ((refcount_vtexcoords3D_ > 0) && (! --refcount_vtexcoords3D_))
this->remove_property(vertex_texcoords3D_);
}
void release_halfedge_texcoords1D() {
if ((refcount_htexcoords1D_ > 0) && (! --refcount_htexcoords1D_))
this->remove_property(halfedge_texcoords1D_);
}
void release_halfedge_texcoords2D() {
if ((refcount_htexcoords2D_ > 0) && (! --refcount_htexcoords2D_))
this->remove_property(halfedge_texcoords2D_);
}
void release_halfedge_texcoords3D() {
if ((refcount_htexcoords3D_ > 0) && (! --refcount_htexcoords3D_))
this->remove_property(halfedge_texcoords3D_);
}
void release_edge_colors()
{
if ((refcount_ecolors_ > 0) && (! --refcount_ecolors_))
this->remove_property(edge_colors_);
}
void release_halfedge_normals()
{
if ((refcount_henormals_ > 0) && (! --refcount_henormals_))
this->remove_property(halfedge_normals_);
}
void release_halfedge_colors()
{
if ((refcount_hecolors_ > 0) && (! --refcount_hecolors_))
this->remove_property(halfedge_colors_);
}
void release_face_normals()
{
if ((refcount_fnormals_ > 0) && (! --refcount_fnormals_))
this->remove_property(face_normals_);
}
void release_face_colors()
{
if ((refcount_fcolors_ > 0) && (! --refcount_fcolors_))
this->remove_property(face_colors_);
}
void release_face_texture_index()
{
if ((refcount_ftextureIndex_ > 0) && (! --refcount_ftextureIndex_))
this->remove_property(face_texture_index_);
}
//---------------------------------------------- dynamic check for properties
bool has_vertex_normals() const { return vertex_normals_.is_valid(); }
bool has_vertex_colors() const { return vertex_colors_.is_valid(); }
bool has_vertex_texcoords1D() const { return vertex_texcoords1D_.is_valid(); }
bool has_vertex_texcoords2D() const { return vertex_texcoords2D_.is_valid(); }
bool has_vertex_texcoords3D() const { return vertex_texcoords3D_.is_valid(); }
bool has_halfedge_texcoords1D() const { return halfedge_texcoords1D_.is_valid();}
bool has_halfedge_texcoords2D() const { return halfedge_texcoords2D_.is_valid();}
bool has_halfedge_texcoords3D() const { return halfedge_texcoords3D_.is_valid();}
bool has_edge_colors() const { return edge_colors_.is_valid(); }
bool has_halfedge_normals() const { return halfedge_normals_.is_valid(); }
bool has_halfedge_colors() const { return halfedge_colors_.is_valid(); }
bool has_face_normals() const { return face_normals_.is_valid(); }
bool has_face_colors() const { return face_colors_.is_valid(); }
bool has_face_texture_index() const { return face_texture_index_.is_valid(); }
public:
typedef VPropHandleT<Point> PointsPropertyHandle;
typedef VPropHandleT<Normal> VertexNormalsPropertyHandle;
typedef VPropHandleT<Color> VertexColorsPropertyHandle;
typedef VPropHandleT<TexCoord1D> VertexTexCoords1DPropertyHandle;
typedef VPropHandleT<TexCoord2D> VertexTexCoords2DPropertyHandle;
typedef VPropHandleT<TexCoord3D> VertexTexCoords3DPropertyHandle;
typedef HPropHandleT<TexCoord1D> HalfedgeTexCoords1DPropertyHandle;
typedef HPropHandleT<TexCoord2D> HalfedgeTexCoords2DPropertyHandle;
typedef HPropHandleT<TexCoord3D> HalfedgeTexCoords3DPropertyHandle;
typedef EPropHandleT<Color> EdgeColorsPropertyHandle;
typedef HPropHandleT<Normal> HalfedgeNormalsPropertyHandle;
typedef HPropHandleT<Color> HalfedgeColorsPropertyHandle;
typedef FPropHandleT<Normal> FaceNormalsPropertyHandle;
typedef FPropHandleT<Color> FaceColorsPropertyHandle;
typedef FPropHandleT<TextureIndex> FaceTextureIndexPropertyHandle;
public:
//standard vertex properties
PointsPropertyHandle points_pph() const
{ return points_; }
VertexNormalsPropertyHandle vertex_normals_pph() const
{ return vertex_normals_; }
VertexColorsPropertyHandle vertex_colors_pph() const
{ return vertex_colors_; }
VertexTexCoords1DPropertyHandle vertex_texcoords1D_pph() const
{ return vertex_texcoords1D_; }
VertexTexCoords2DPropertyHandle vertex_texcoords2D_pph() const
{ return vertex_texcoords2D_; }
VertexTexCoords3DPropertyHandle vertex_texcoords3D_pph() const
{ return vertex_texcoords3D_; }
//standard halfedge properties
HalfedgeTexCoords1DPropertyHandle halfedge_texcoords1D_pph() const
{ return halfedge_texcoords1D_; }
HalfedgeTexCoords2DPropertyHandle halfedge_texcoords2D_pph() const
{ return halfedge_texcoords2D_; }
HalfedgeTexCoords3DPropertyHandle halfedge_texcoords3D_pph() const
{ return halfedge_texcoords3D_; }
// standard edge properties
HalfedgeNormalsPropertyHandle halfedge_normals_pph() const
{ return halfedge_normals_; }
// standard edge properties
HalfedgeColorsPropertyHandle halfedge_colors_pph() const
{ return halfedge_colors_; }
// standard edge properties
EdgeColorsPropertyHandle edge_colors_pph() const
{ return edge_colors_; }
//standard face properties
FaceNormalsPropertyHandle face_normals_pph() const
{ return face_normals_; }
FaceColorsPropertyHandle face_colors_pph() const
{ return face_colors_; }
FaceTextureIndexPropertyHandle face_texture_index_pph() const
{ return face_texture_index_; }
VertexData& data(VertexHandle _vh)
{ return this->property(data_vpph_, _vh); }
const VertexData& data(VertexHandle _vh) const
{ return this->property(data_vpph_, _vh); }
FaceData& data(FaceHandle _fh)
{ return this->property(data_fpph_, _fh); }
const FaceData& data(FaceHandle _fh) const
{ return this->property(data_fpph_, _fh); }
EdgeData& data(EdgeHandle _eh)
{ return this->property(data_epph_, _eh); }
const EdgeData& data(EdgeHandle _eh) const
{ return this->property(data_epph_, _eh); }
HalfedgeData& data(HalfedgeHandle _heh)
{ return this->property(data_hpph_, _heh); }
const HalfedgeData& data(HalfedgeHandle _heh) const
{ return this->property(data_hpph_, _heh); }
private:
//standard vertex properties
PointsPropertyHandle points_;
VertexNormalsPropertyHandle vertex_normals_;
VertexColorsPropertyHandle vertex_colors_;
VertexTexCoords1DPropertyHandle vertex_texcoords1D_;
VertexTexCoords2DPropertyHandle vertex_texcoords2D_;
VertexTexCoords3DPropertyHandle vertex_texcoords3D_;
//standard halfedge properties
HalfedgeTexCoords1DPropertyHandle halfedge_texcoords1D_;
HalfedgeTexCoords2DPropertyHandle halfedge_texcoords2D_;
HalfedgeTexCoords3DPropertyHandle halfedge_texcoords3D_;
HalfedgeNormalsPropertyHandle halfedge_normals_;
HalfedgeColorsPropertyHandle halfedge_colors_;
// standard edge properties
EdgeColorsPropertyHandle edge_colors_;
//standard face properties
FaceNormalsPropertyHandle face_normals_;
FaceColorsPropertyHandle face_colors_;
FaceTextureIndexPropertyHandle face_texture_index_;
//data properties handles
DataVPropHandle data_vpph_;
DataHPropHandle data_hpph_;
DataEPropHandle data_epph_;
DataFPropHandle data_fpph_;
unsigned int refcount_vnormals_;
unsigned int refcount_vcolors_;
unsigned int refcount_vtexcoords1D_;
unsigned int refcount_vtexcoords2D_;
unsigned int refcount_vtexcoords3D_;
unsigned int refcount_htexcoords1D_;
unsigned int refcount_htexcoords2D_;
unsigned int refcount_htexcoords3D_;
unsigned int refcount_henormals_;
unsigned int refcount_hecolors_;
unsigned int refcount_ecolors_;
unsigned int refcount_fnormals_;
unsigned int refcount_fcolors_;
unsigned int refcount_ftextureIndex_;
/**
* @brief initializeStandardProperties Initializes the standard properties
* and sets refcount to 1 if found. (e.g. when the copy constructor was used)
*/
void initializeStandardProperties()
{
if(!this->get_property_handle(points_,
"v:points"))
{
//mesh has no points?
}
refcount_vnormals_ = this->get_property_handle(vertex_normals_,
"v:normals") ? 1 : 0 ;
refcount_vcolors_ = this->get_property_handle(vertex_colors_,
"v:colors") ? 1 : 0 ;
refcount_vtexcoords1D_ = this->get_property_handle(vertex_texcoords1D_,
"v:texcoords1D") ? 1 : 0 ;
refcount_vtexcoords2D_ = this->get_property_handle(vertex_texcoords2D_,
"v:texcoords2D") ? 1 : 0 ;
refcount_vtexcoords3D_ = this->get_property_handle(vertex_texcoords3D_,
"v:texcoords3D") ? 1 : 0 ;
refcount_htexcoords1D_ = this->get_property_handle(halfedge_texcoords1D_,
"h:texcoords1D") ? 1 : 0 ;
refcount_htexcoords2D_ = this->get_property_handle(halfedge_texcoords2D_,
"h:texcoords2D") ? 1 : 0 ;
refcount_htexcoords3D_ = this->get_property_handle(halfedge_texcoords3D_,
"h:texcoords3D") ? 1 : 0 ;
refcount_henormals_ = this->get_property_handle(halfedge_normals_,
"h:normals") ? 1 : 0 ;
refcount_hecolors_ = this->get_property_handle(halfedge_colors_,
"h:colors") ? 1 : 0 ;
refcount_ecolors_ = this->get_property_handle(edge_colors_,
"e:colors") ? 1 : 0 ;
refcount_fnormals_ = this->get_property_handle(face_normals_,
"f:normals") ? 1 : 0 ;
refcount_fcolors_ = this->get_property_handle(face_colors_,
"f:colors") ? 1 : 0 ;
refcount_ftextureIndex_ = this->get_property_handle(face_texture_index_,
"f:textureindex") ? 1 : 0 ;
}
};
//=============================================================================
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_ATTRIBKERNEL_HH defined
//=============================================================================

View File

@ -0,0 +1,103 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
/**
\file Attributes.hh
This file provides some macros containing attribute usage.
*/
#ifndef OPENMESH_ATTRIBUTES_HH
#define OPENMESH_ATTRIBUTES_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Mesh/Status.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace Attributes {
//== CLASS DEFINITION ========================================================
/** Attribute bits
*
* Use the bits to define a standard property at compile time using traits.
*
* \include traits5.cc
*
* \see \ref mesh_type
*/
enum AttributeBits
{
None = 0, ///< Clear all attribute bits
Normal = 1, ///< Add normals to mesh item (vertices/faces)
Color = 2, ///< Add colors to mesh item (vertices/faces/edges)
PrevHalfedge = 4, ///< Add storage for previous halfedge (halfedges). The bit is set by default in the DefaultTraits.
Status = 8, ///< Add status to mesh item (all items)
TexCoord1D = 16, ///< Add 1D texture coordinates (vertices, halfedges)
TexCoord2D = 32, ///< Add 2D texture coordinates (vertices, halfedges)
TexCoord3D = 64, ///< Add 3D texture coordinates (vertices, halfedges)
TextureIndex = 128 ///< Add texture index (faces)
};
//=============================================================================
} // namespace Attributes
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_ATTRIBUTES_HH defined
//=============================================================================

View File

@ -0,0 +1,239 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#include <OpenMesh/Core/Mesh/BaseKernel.hh>
#include <iostream>
namespace OpenMesh
{
void BaseKernel::property_stats() const
{
property_stats(std::clog);
}
void BaseKernel::property_stats(std::ostream& _ostr) const
{
const PropertyContainer::Properties& vps = vprops_.properties();
const PropertyContainer::Properties& hps = hprops_.properties();
const PropertyContainer::Properties& eps = eprops_.properties();
const PropertyContainer::Properties& fps = fprops_.properties();
const PropertyContainer::Properties& mps = mprops_.properties();
PropertyContainer::Properties::const_iterator it;
_ostr << vprops_.size() << " vprops:\n";
for (it=vps.begin(); it!=vps.end(); ++it)
{
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
}
_ostr << hprops_.size() << " hprops:\n";
for (it=hps.begin(); it!=hps.end(); ++it)
{
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
}
_ostr << eprops_.size() << " eprops:\n";
for (it=eps.begin(); it!=eps.end(); ++it)
{
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
}
_ostr << fprops_.size() << " fprops:\n";
for (it=fps.begin(); it!=fps.end(); ++it)
{
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
}
_ostr << mprops_.size() << " mprops:\n";
for (it=mps.begin(); it!=mps.end(); ++it)
{
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
}
}
void BaseKernel::vprop_stats( std::string& _string ) const
{
_string.clear();
PropertyContainer::Properties::const_iterator it;
const PropertyContainer::Properties& vps = vprops_.properties();
for (it=vps.begin(); it!=vps.end(); ++it)
if ( *it == NULL )
_string += "[deleted] \n";
else {
_string += (*it)->name();
_string += "\n";
}
}
void BaseKernel::hprop_stats( std::string& _string ) const
{
_string.clear();
PropertyContainer::Properties::const_iterator it;
const PropertyContainer::Properties& hps = hprops_.properties();
for (it=hps.begin(); it!=hps.end(); ++it)
if ( *it == NULL )
_string += "[deleted] \n";
else {
_string += (*it)->name();
_string += "\n";
}
}
void BaseKernel::eprop_stats( std::string& _string ) const
{
_string.clear();
PropertyContainer::Properties::const_iterator it;
const PropertyContainer::Properties& eps = eprops_.properties();
for (it=eps.begin(); it!=eps.end(); ++it)
if ( *it == NULL )
_string += "[deleted] \n";
else {
_string += (*it)->name();
_string += "\n";
}
}
void BaseKernel::fprop_stats( std::string& _string ) const
{
_string.clear();
PropertyContainer::Properties::const_iterator it;
const PropertyContainer::Properties& fps = fprops_.properties();
for (it=fps.begin(); it!=fps.end(); ++it)
if ( *it == NULL )
_string += "[deleted] \n";
else {
_string += (*it)->name();
_string += "\n";
}
}
void BaseKernel::mprop_stats( std::string& _string ) const
{
_string.clear();
PropertyContainer::Properties::const_iterator it;
const PropertyContainer::Properties& mps = mprops_.properties();
for (it=mps.begin(); it!=mps.end(); ++it)
if ( *it == NULL )
_string += "[deleted] \n";
else {
_string += (*it)->name();
_string += "\n";
}
}
void BaseKernel::vprop_stats() const
{
vprop_stats(std::clog);
}
void BaseKernel::vprop_stats(std::ostream& _ostr ) const
{
PropertyContainer::Properties::const_iterator it;
const PropertyContainer::Properties& vps = vprops_.properties();
for (it=vps.begin(); it!=vps.end(); ++it)
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
}
void BaseKernel::hprop_stats() const
{
hprop_stats(std::clog);
}
void BaseKernel::hprop_stats(std::ostream& _ostr ) const
{
PropertyContainer::Properties::const_iterator it;
const PropertyContainer::Properties& hps = hprops_.properties();
for (it=hps.begin(); it!=hps.end(); ++it)
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
}
void BaseKernel::eprop_stats() const
{
eprop_stats(std::clog);
}
void BaseKernel::eprop_stats(std::ostream& _ostr ) const
{
PropertyContainer::Properties::const_iterator it;
const PropertyContainer::Properties& eps = eprops_.properties();
for (it=eps.begin(); it!=eps.end(); ++it)
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
}
void BaseKernel::fprop_stats() const
{
fprop_stats(std::clog);
}
void BaseKernel::fprop_stats(std::ostream& _ostr ) const
{
PropertyContainer::Properties::const_iterator it;
const PropertyContainer::Properties& fps = fprops_.properties();
for (it=fps.begin(); it!=fps.end(); ++it)
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
}
void BaseKernel::mprop_stats() const
{
mprop_stats(std::clog);
}
void BaseKernel::mprop_stats(std::ostream& _ostr ) const
{
PropertyContainer::Properties::const_iterator it;
const PropertyContainer::Properties& mps = mprops_.properties();
for (it=mps.begin(); it!=mps.end(); ++it)
*it == NULL ? (void)(_ostr << "[deleted]" << "\n") : (*it)->stats(_ostr);
}
}

View File

@ -0,0 +1,826 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS BaseKernel
//
//=============================================================================
#ifndef OPENMESH_BASE_KERNEL_HH
#define OPENMESH_BASE_KERNEL_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
// --------------------
#include <vector>
#include <string>
#include <algorithm>
#include <iosfwd>
// --------------------
#include <OpenMesh/Core/Utils/PropertyContainer.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== CLASS DEFINITION =========================================================
/// This class provides low-level property management like adding/removing
/// properties and access to properties. Under most circumstances, it is
/// advisable to use the high-level property management provided by
/// PropertyManager, instead.
///
/// All operations provided by %BaseKernel need at least a property handle
/// (VPropHandleT, EPropHandleT, HPropHandleT, FPropHandleT, MPropHandleT).
/// which keeps the data type of the property, too.
///
/// There are two types of properties:
/// -# Standard properties - mesh data (e.g. vertex normal or face color)
/// -# Custom properties - user defined data
///
/// The differentiation is only semantically, technically both are
/// equally handled. Therefore the methods provided by the %BaseKernel
/// are applicable to both property types.
///
/// \attention Since the class PolyMeshT derives from a kernel, hence all public
/// elements of %BaseKernel are usable.
class OPENMESHDLLEXPORT BaseKernel
{
public: //-------------------------------------------- constructor / destructor
BaseKernel() {}
virtual ~BaseKernel() {
vprops_.clear();
eprops_.clear();
hprops_.clear();
fprops_.clear();
}
public: //-------------------------------------------------- add new properties
/// \name Add a property to a mesh item
//@{
/** You should not use this function directly. Instead, use the convenient
* PropertyManager wrapper and/or one of its helper functions such as
* makePropertyManagerFromNew, makePropertyManagerFromExisting, or
* makePropertyManagerFromExistingOrNew.
*
* Adds a property
*
* Depending on the property handle type a vertex, (half-)edge, face or
* mesh property is added to the mesh. If the action fails the handle
* is invalid.
* On success the handle must be used to access the property data with
* property().
*
* \param _ph A property handle defining the data type to bind to mesh.
* On success the handle is valid else invalid.
* \param _name Optional name of property. Following restrictions apply
* to the name:
* -# Maximum length of name is 256 characters
* -# The prefixes matching "^[vhefm]:" are reserved for
* internal usage.
* -# The expression "^<.*>$" is reserved for internal usage.
*
*/
template <class T>
void add_property( VPropHandleT<T>& _ph, const std::string& _name="<vprop>")
{
_ph = VPropHandleT<T>( vprops_.add(T(), _name) );
vprops_.resize(n_vertices());
}
template <class T>
void add_property( HPropHandleT<T>& _ph, const std::string& _name="<hprop>")
{
_ph = HPropHandleT<T>( hprops_.add(T(), _name) );
hprops_.resize(n_halfedges());
}
template <class T>
void add_property( EPropHandleT<T>& _ph, const std::string& _name="<eprop>")
{
_ph = EPropHandleT<T>( eprops_.add(T(), _name) );
eprops_.resize(n_edges());
}
template <class T>
void add_property( FPropHandleT<T>& _ph, const std::string& _name="<fprop>")
{
_ph = FPropHandleT<T>( fprops_.add(T(), _name) );
fprops_.resize(n_faces());
}
template <class T>
void add_property( MPropHandleT<T>& _ph, const std::string& _name="<mprop>")
{
_ph = MPropHandleT<T>( mprops_.add(T(), _name) );
mprops_.resize(1);
}
//@}
public: //--------------------------------------------------- remove properties
/// \name Removing a property from a mesh tiem
//@{
/** You should not use this function directly. Instead, use the convenient
* PropertyManager wrapper to manage (and remove) properties.
*
* Remove a property.
*
* Removes the property represented by the handle from the apropriate
* mesh item.
* \param _ph Property to be removed. The handle is invalid afterwords.
*/
template <typename T>
void remove_property(VPropHandleT<T>& _ph)
{
if (_ph.is_valid())
vprops_.remove(_ph);
_ph.reset();
}
template <typename T>
void remove_property(HPropHandleT<T>& _ph)
{
if (_ph.is_valid())
hprops_.remove(_ph);
_ph.reset();
}
template <typename T>
void remove_property(EPropHandleT<T>& _ph)
{
if (_ph.is_valid())
eprops_.remove(_ph);
_ph.reset();
}
template <typename T>
void remove_property(FPropHandleT<T>& _ph)
{
if (_ph.is_valid())
fprops_.remove(_ph);
_ph.reset();
}
template <typename T>
void remove_property(MPropHandleT<T>& _ph)
{
if (_ph.is_valid())
mprops_.remove(_ph);
_ph.reset();
}
//@}
public: //------------------------------------------------ get handle from name
/// \name Get property handle by name
//@{
/** You should not use this function directly. Instead, use the convenient
* PropertyManager wrapper (e.g. PropertyManager::propertyExists) or one of
* its higher level helper functions such as
* makePropertyManagerFromExisting, or makePropertyManagerFromExistingOrNew.
*
* Retrieves the handle to a named property by it's name.
*
* \param _ph A property handle. On success the handle is valid else
* invalid.
* \param _name Name of wanted property.
* \return \c true if such a named property is available, else \c false.
*/
template <class T>
bool get_property_handle(VPropHandleT<T>& _ph,
const std::string& _name) const
{
return (_ph = VPropHandleT<T>(vprops_.handle(T(), _name))).is_valid();
}
template <class T>
bool get_property_handle(HPropHandleT<T>& _ph,
const std::string& _name) const
{
return (_ph = HPropHandleT<T>(hprops_.handle(T(), _name))).is_valid();
}
template <class T>
bool get_property_handle(EPropHandleT<T>& _ph,
const std::string& _name) const
{
return (_ph = EPropHandleT<T>(eprops_.handle(T(), _name))).is_valid();
}
template <class T>
bool get_property_handle(FPropHandleT<T>& _ph,
const std::string& _name) const
{
return (_ph = FPropHandleT<T>(fprops_.handle(T(), _name))).is_valid();
}
template <class T>
bool get_property_handle(MPropHandleT<T>& _ph,
const std::string& _name) const
{
return (_ph = MPropHandleT<T>(mprops_.handle(T(), _name))).is_valid();
}
//@}
public: //--------------------------------------------------- access properties
/// \name Access a property
//@{
/** In most cases you should use the convenient PropertyManager wrapper
* and use of this function should not be necessary. Under some
* circumstances, however (i.e. making a property persistent), it might be
* necessary to use this function.
*
* Access a property
*
* This method returns a reference to property. The property handle
* must be valid! The result is unpredictable if the handle is invalid!
*
* \param _ph A \em valid (!) property handle.
* \return The wanted property if the handle is valid.
*/
template <class T>
PropertyT<T>& property(VPropHandleT<T> _ph) {
return vprops_.property(_ph);
}
template <class T>
const PropertyT<T>& property(VPropHandleT<T> _ph) const {
return vprops_.property(_ph);
}
template <class T>
PropertyT<T>& property(HPropHandleT<T> _ph) {
return hprops_.property(_ph);
}
template <class T>
const PropertyT<T>& property(HPropHandleT<T> _ph) const {
return hprops_.property(_ph);
}
template <class T>
PropertyT<T>& property(EPropHandleT<T> _ph) {
return eprops_.property(_ph);
}
template <class T>
const PropertyT<T>& property(EPropHandleT<T> _ph) const {
return eprops_.property(_ph);
}
template <class T>
PropertyT<T>& property(FPropHandleT<T> _ph) {
return fprops_.property(_ph);
}
template <class T>
const PropertyT<T>& property(FPropHandleT<T> _ph) const {
return fprops_.property(_ph);
}
template <class T>
PropertyT<T>& mproperty(MPropHandleT<T> _ph) {
return mprops_.property(_ph);
}
template <class T>
const PropertyT<T>& mproperty(MPropHandleT<T> _ph) const {
return mprops_.property(_ph);
}
//@}
public: //-------------------------------------------- access property elements
/// \name Access a property element using a handle to a mesh item
//@{
/** You should not use this function directly. Instead, use the convenient
* PropertyManager wrapper.
*
* Return value of property for an item
*/
template <class T>
typename VPropHandleT<T>::reference
property(VPropHandleT<T> _ph, VertexHandle _vh) {
return vprops_.property(_ph)[_vh.idx()];
}
template <class T>
typename VPropHandleT<T>::const_reference
property(VPropHandleT<T> _ph, VertexHandle _vh) const {
return vprops_.property(_ph)[_vh.idx()];
}
template <class T>
typename HPropHandleT<T>::reference
property(HPropHandleT<T> _ph, HalfedgeHandle _hh) {
return hprops_.property(_ph)[_hh.idx()];
}
template <class T>
typename HPropHandleT<T>::const_reference
property(HPropHandleT<T> _ph, HalfedgeHandle _hh) const {
return hprops_.property(_ph)[_hh.idx()];
}
template <class T>
typename EPropHandleT<T>::reference
property(EPropHandleT<T> _ph, EdgeHandle _eh) {
return eprops_.property(_ph)[_eh.idx()];
}
template <class T>
typename EPropHandleT<T>::const_reference
property(EPropHandleT<T> _ph, EdgeHandle _eh) const {
return eprops_.property(_ph)[_eh.idx()];
}
template <class T>
typename FPropHandleT<T>::reference
property(FPropHandleT<T> _ph, FaceHandle _fh) {
return fprops_.property(_ph)[_fh.idx()];
}
template <class T>
typename FPropHandleT<T>::const_reference
property(FPropHandleT<T> _ph, FaceHandle _fh) const {
return fprops_.property(_ph)[_fh.idx()];
}
template <class T>
typename MPropHandleT<T>::reference
property(MPropHandleT<T> _ph) {
return mprops_.property(_ph)[0];
}
template <class T>
typename MPropHandleT<T>::const_reference
property(MPropHandleT<T> _ph) const {
return mprops_.property(_ph)[0];
}
//@}
public: //------------------------------------------------ copy property
/** You should not use this function directly. Instead, use the convenient
* PropertyManager wrapper (e.g. PropertyManager::copy_to or
* PropertyManager::copy).
*
* Copies a single property from one mesh element to another (of the same type)
*
* @param _ph A vertex property handle
* @param _vh_from From vertex handle
* @param _vh_to To vertex handle
*/
template <class T>
void copy_property(VPropHandleT<T>& _ph, VertexHandle _vh_from, VertexHandle _vh_to) {
if(_vh_from.is_valid() && _vh_to.is_valid())
vprops_.property(_ph)[_vh_to.idx()] = vprops_.property(_ph)[_vh_from.idx()];
}
/** You should not use this function directly. Instead, use the convenient
* PropertyManager wrapper (e.g. PropertyManager::copy_to or
* PropertyManager::copy).
*
* Copies a single property from one mesh element to another (of the same type)
*
* @param _ph A halfedge property handle
* @param _hh_from From halfedge handle
* @param _hh_to To halfedge handle
*/
template <class T>
void copy_property(HPropHandleT<T> _ph, HalfedgeHandle _hh_from, HalfedgeHandle _hh_to) {
if(_hh_from.is_valid() && _hh_to.is_valid())
hprops_.property(_ph)[_hh_to.idx()] = hprops_.property(_ph)[_hh_from.idx()];
}
/** You should not use this function directly. Instead, use the convenient
* PropertyManager wrapper (e.g. PropertyManager::copy_to or
* PropertyManager::copy).
*
* Copies a single property from one mesh element to another (of the same type)
*
* @param _ph An edge property handle
* @param _eh_from From edge handle
* @param _eh_to To edge handle
*/
template <class T>
void copy_property(EPropHandleT<T> _ph, EdgeHandle _eh_from, EdgeHandle _eh_to) {
if(_eh_from.is_valid() && _eh_to.is_valid())
eprops_.property(_ph)[_eh_to.idx()] = eprops_.property(_ph)[_eh_from.idx()];
}
/** You should not use this function directly. Instead, use the convenient
* PropertyManager wrapper (e.g. PropertyManager::copy_to or
* PropertyManager::copy).
*
* Copies a single property from one mesh element to another (of the same type)
*
* @param _ph A face property handle
* @param _fh_from From face handle
* @param _fh_to To face handle
*/
template <class T>
void copy_property(FPropHandleT<T> _ph, FaceHandle _fh_from, FaceHandle _fh_to) {
if(_fh_from.is_valid() && _fh_to.is_valid())
fprops_.property(_ph)[_fh_to.idx()] = fprops_.property(_ph)[_fh_from.idx()];
}
public:
//------------------------------------------------ copy all properties
/** Copies all properties from one mesh element to another (of the same type)
*
*
* @param _vh_from A vertex handle - source
* @param _vh_to A vertex handle - target
* @param _copyBuildIn Should the internal properties (position, normal, texture coordinate,..) be copied?
*/
void copy_all_properties(VertexHandle _vh_from, VertexHandle _vh_to, bool _copyBuildIn = false) {
for( PropertyContainer::iterator p_it = vprops_.begin();
p_it != vprops_.end(); ++p_it) {
// Copy all properties, if build in is true
// Otherwise, copy only properties without build in specifier
if ( *p_it && ( _copyBuildIn || (*p_it)->name().substr(0,2) != "v:" ) )
(*p_it)->copy(_vh_from.idx(), _vh_to.idx());
}
}
/** Copies all properties from one mesh element to another (of the same type)
*
* @param _hh_from A halfedge handle - source
* @param _hh_to A halfedge handle - target
* @param _copyBuildIn Should the internal properties (position, normal, texture coordinate,..) be copied?
*/
void copy_all_properties(HalfedgeHandle _hh_from, HalfedgeHandle _hh_to, bool _copyBuildIn = false) {
for( PropertyContainer::iterator p_it = hprops_.begin();
p_it != hprops_.end(); ++p_it) {
// Copy all properties, if build in is true
// Otherwise, copy only properties without build in specifier
if ( *p_it && ( _copyBuildIn || (*p_it)->name().substr(0,2) != "h:") )
(*p_it)->copy(_hh_from.idx(), _hh_to.idx());
}
}
/** Copies all properties from one mesh element to another (of the same type)
*
* @param _eh_from An edge handle - source
* @param _eh_to An edge handle - target
* @param _copyBuildIn Should the internal properties (position, normal, texture coordinate,..) be copied?
*/
void copy_all_properties(EdgeHandle _eh_from, EdgeHandle _eh_to, bool _copyBuildIn = false) {
for( PropertyContainer::iterator p_it = eprops_.begin();
p_it != eprops_.end(); ++p_it) {
// Copy all properties, if build in is true
// Otherwise, copy only properties without build in specifier
if ( *p_it && ( _copyBuildIn || (*p_it)->name().substr(0,2) != "e:") )
(*p_it)->copy(_eh_from.idx(), _eh_to.idx());
}
}
/** Copies all properties from one mesh element to another (of the same type)
*
* @param _fh_from A face handle - source
* @param _fh_to A face handle - target
* @param _copyBuildIn Should the internal properties (position, normal, texture coordinate,..) be copied?
*
*/
void copy_all_properties(FaceHandle _fh_from, FaceHandle _fh_to, bool _copyBuildIn = false) {
for( PropertyContainer::iterator p_it = fprops_.begin();
p_it != fprops_.end(); ++p_it) {
// Copy all properties, if build in is true
// Otherwise, copy only properties without build in specifier
if ( *p_it && ( _copyBuildIn || (*p_it)->name().substr(0,2) != "f:") )
(*p_it)->copy(_fh_from.idx(), _fh_to.idx());
}
}
/**
* @brief copy_all_kernel_properties uses the = operator to copy all properties from a given other BaseKernel.
* @param _other Another BaseKernel, to copy the properties from.
*/
void copy_all_kernel_properties(const BaseKernel & _other)
{
this->vprops_ = _other.vprops_;
this->eprops_ = _other.eprops_;
this->hprops_ = _other.hprops_;
this->fprops_ = _other.fprops_;
}
protected: //------------------------------------------------- low-level access
public: // used by non-native kernel and MeshIO, should be protected
size_t n_vprops(void) const { return vprops_.size(); }
size_t n_eprops(void) const { return eprops_.size(); }
size_t n_hprops(void) const { return hprops_.size(); }
size_t n_fprops(void) const { return fprops_.size(); }
size_t n_mprops(void) const { return mprops_.size(); }
BaseProperty* _get_vprop( const std::string& _name)
{ return vprops_.property(_name); }
BaseProperty* _get_eprop( const std::string& _name)
{ return eprops_.property(_name); }
BaseProperty* _get_hprop( const std::string& _name)
{ return hprops_.property(_name); }
BaseProperty* _get_fprop( const std::string& _name)
{ return fprops_.property(_name); }
BaseProperty* _get_mprop( const std::string& _name)
{ return mprops_.property(_name); }
const BaseProperty* _get_vprop( const std::string& _name) const
{ return vprops_.property(_name); }
const BaseProperty* _get_eprop( const std::string& _name) const
{ return eprops_.property(_name); }
const BaseProperty* _get_hprop( const std::string& _name) const
{ return hprops_.property(_name); }
const BaseProperty* _get_fprop( const std::string& _name) const
{ return fprops_.property(_name); }
const BaseProperty* _get_mprop( const std::string& _name) const
{ return mprops_.property(_name); }
BaseProperty& _vprop( size_t _idx ) { return vprops_._property( _idx ); }
BaseProperty& _eprop( size_t _idx ) { return eprops_._property( _idx ); }
BaseProperty& _hprop( size_t _idx ) { return hprops_._property( _idx ); }
BaseProperty& _fprop( size_t _idx ) { return fprops_._property( _idx ); }
BaseProperty& _mprop( size_t _idx ) { return mprops_._property( _idx ); }
const BaseProperty& _vprop( size_t _idx ) const
{ return vprops_._property( _idx ); }
const BaseProperty& _eprop( size_t _idx ) const
{ return eprops_._property( _idx ); }
const BaseProperty& _hprop( size_t _idx ) const
{ return hprops_._property( _idx ); }
const BaseProperty& _fprop( size_t _idx ) const
{ return fprops_._property( _idx ); }
const BaseProperty& _mprop( size_t _idx ) const
{ return mprops_._property( _idx ); }
size_t _add_vprop( BaseProperty* _bp ) { return vprops_._add( _bp ); }
size_t _add_eprop( BaseProperty* _bp ) { return eprops_._add( _bp ); }
size_t _add_hprop( BaseProperty* _bp ) { return hprops_._add( _bp ); }
size_t _add_fprop( BaseProperty* _bp ) { return fprops_._add( _bp ); }
size_t _add_mprop( BaseProperty* _bp ) { return mprops_._add( _bp ); }
protected: // low-level access non-public
BaseProperty& _vprop( BaseHandle _h )
{ return vprops_._property( _h.idx() ); }
BaseProperty& _eprop( BaseHandle _h )
{ return eprops_._property( _h.idx() ); }
BaseProperty& _hprop( BaseHandle _h )
{ return hprops_._property( _h.idx() ); }
BaseProperty& _fprop( BaseHandle _h )
{ return fprops_._property( _h.idx() ); }
BaseProperty& _mprop( BaseHandle _h )
{ return mprops_._property( _h.idx() ); }
const BaseProperty& _vprop( BaseHandle _h ) const
{ return vprops_._property( _h.idx() ); }
const BaseProperty& _eprop( BaseHandle _h ) const
{ return eprops_._property( _h.idx() ); }
const BaseProperty& _hprop( BaseHandle _h ) const
{ return hprops_._property( _h.idx() ); }
const BaseProperty& _fprop( BaseHandle _h ) const
{ return fprops_._property( _h.idx() ); }
const BaseProperty& _mprop( BaseHandle _h ) const
{ return mprops_._property( _h.idx() ); }
public: //----------------------------------------------------- element numbers
virtual size_t n_vertices() const { return 0; }
virtual size_t n_halfedges() const { return 0; }
virtual size_t n_edges() const { return 0; }
virtual size_t n_faces() const { return 0; }
protected: //------------------------------------------- synchronize properties
/// Reserves space for \p _n elements in all vertex property vectors.
void vprops_reserve(size_t _n) const { vprops_.reserve(_n); }
/// Resizes all vertex property vectors to the specified size.
void vprops_resize(size_t _n) const { vprops_.resize(_n); }
/**
* Same as vprops_resize() but ignores vertex property vectors that have
* a size larger than \p _n.
*
* Use this method instead of vprops_resize() if you plan to frequently reduce
* and enlarge the property container and you don't want to waste time
* reallocating the property vectors every time.
*/
void vprops_resize_if_smaller(size_t _n) const { vprops_.resize_if_smaller(_n); }
void vprops_clear() {
vprops_.clear();
}
void vprops_swap(unsigned int _i0, unsigned int _i1) const {
vprops_.swap(_i0, _i1);
}
void hprops_reserve(size_t _n) const { hprops_.reserve(_n); }
void hprops_resize(size_t _n) const { hprops_.resize(_n); }
void hprops_clear() {
hprops_.clear();
}
void hprops_swap(unsigned int _i0, unsigned int _i1) const {
hprops_.swap(_i0, _i1);
}
void eprops_reserve(size_t _n) const { eprops_.reserve(_n); }
void eprops_resize(size_t _n) const { eprops_.resize(_n); }
void eprops_clear() {
eprops_.clear();
}
void eprops_swap(unsigned int _i0, unsigned int _i1) const {
eprops_.swap(_i0, _i1);
}
void fprops_reserve(size_t _n) const { fprops_.reserve(_n); }
void fprops_resize(size_t _n) const { fprops_.resize(_n); }
void fprops_clear() {
fprops_.clear();
}
void fprops_swap(unsigned int _i0, unsigned int _i1) const {
fprops_.swap(_i0, _i1);
}
void mprops_resize(size_t _n) const { mprops_.resize(_n); }
void mprops_clear() {
mprops_.clear();
}
public:
// uses std::clog as output stream
void property_stats() const;
void property_stats(std::ostream& _ostr) const;
void vprop_stats( std::string& _string ) const;
void hprop_stats( std::string& _string ) const;
void eprop_stats( std::string& _string ) const;
void fprop_stats( std::string& _string ) const;
void mprop_stats( std::string& _string ) const;
// uses std::clog as output stream
void vprop_stats() const;
void hprop_stats() const;
void eprop_stats() const;
void fprop_stats() const;
void mprop_stats() const;
void vprop_stats(std::ostream& _ostr) const;
void hprop_stats(std::ostream& _ostr) const;
void eprop_stats(std::ostream& _ostr) const;
void fprop_stats(std::ostream& _ostr) const;
void mprop_stats(std::ostream& _ostr) const;
public:
typedef PropertyContainer::iterator prop_iterator;
typedef PropertyContainer::const_iterator const_prop_iterator;
prop_iterator vprops_begin() { return vprops_.begin(); }
prop_iterator vprops_end() { return vprops_.end(); }
const_prop_iterator vprops_begin() const { return vprops_.begin(); }
const_prop_iterator vprops_end() const { return vprops_.end(); }
prop_iterator eprops_begin() { return eprops_.begin(); }
prop_iterator eprops_end() { return eprops_.end(); }
const_prop_iterator eprops_begin() const { return eprops_.begin(); }
const_prop_iterator eprops_end() const { return eprops_.end(); }
prop_iterator hprops_begin() { return hprops_.begin(); }
prop_iterator hprops_end() { return hprops_.end(); }
const_prop_iterator hprops_begin() const { return hprops_.begin(); }
const_prop_iterator hprops_end() const { return hprops_.end(); }
prop_iterator fprops_begin() { return fprops_.begin(); }
prop_iterator fprops_end() { return fprops_.end(); }
const_prop_iterator fprops_begin() const { return fprops_.begin(); }
const_prop_iterator fprops_end() const { return fprops_.end(); }
prop_iterator mprops_begin() { return mprops_.begin(); }
prop_iterator mprops_end() { return mprops_.end(); }
const_prop_iterator mprops_begin() const { return mprops_.begin(); }
const_prop_iterator mprops_end() const { return mprops_.end(); }
private:
PropertyContainer vprops_;
PropertyContainer hprops_;
PropertyContainer eprops_;
PropertyContainer fprops_;
PropertyContainer mprops_;
};
//=============================================================================
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_BASE_KERNEL_HH defined
//=============================================================================

View File

@ -0,0 +1,97 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS BaseMesh
//
//=============================================================================
#ifndef OPENMESH_BASEMESH_HH
#define OPENMESH_BASEMESH_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Mesh/IteratorsT.hh>
#include <OpenMesh/Core/Mesh/CirculatorsT.hh>
#include <OpenMesh/Core/Mesh/Attributes.hh>
#include <vector>
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== CLASS DEFINITION =========================================================
/** \class BaseMesh BaseMesh.hh <OpenMesh/Mesh/BaseMesh.hh>
Base class for all meshes.
*/
class BaseMesh {
public:
virtual ~BaseMesh(void) {;}
};
//=============================================================================
} // namespace OpenMesh
//=============================================================================
//=============================================================================
#endif // OPENMESH_BASEMESH_HH defined
//=============================================================================

View File

@ -0,0 +1,77 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OPENMESH_CASTS_HH
#define OPENMESH_CASTS_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh
{
template <class Traits>
inline TriMesh_ArrayKernelT<Traits>& TRIMESH_CAST(PolyMesh_ArrayKernelT<Traits>& _poly_mesh)
{ return reinterpret_cast< TriMesh_ArrayKernelT<Traits>& >(_poly_mesh); }
template <class Traits>
inline const TriMesh_ArrayKernelT<Traits>& TRIMESH_CAST(const PolyMesh_ArrayKernelT<Traits>& _poly_mesh)
{ return reinterpret_cast< const TriMesh_ArrayKernelT<Traits>& >(_poly_mesh); }
template <class Traits>
inline PolyMesh_ArrayKernelT<Traits>& POLYMESH_CAST(TriMesh_ArrayKernelT<Traits>& _tri_mesh)
{ return reinterpret_cast< PolyMesh_ArrayKernelT<Traits>& >(_tri_mesh); }
template <class Traits>
inline const PolyMesh_ArrayKernelT<Traits>& POLYMESH_CAST(const TriMesh_ArrayKernelT<Traits>& _tri_mesh)
{ return reinterpret_cast< const PolyMesh_ArrayKernelT<Traits>& >(_tri_mesh); }
};
#endif//OPENMESH_CASTS_HH

View File

@ -0,0 +1,598 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OPENMESH_CIRCULATORS_HH
#define OPENMESH_CIRCULATORS_HH
//=============================================================================
//
// Vertex and Face circulators for PolyMesh/TriMesh
//
//=============================================================================
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <cassert>
#include <cstddef>
#include <iterator>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace Iterators {
template<class Mesh, class CenterEntityHandle, bool CW>
class GenericCirculator_CenterEntityFnsT {
public:
static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter);
static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter);
};
template<class Mesh>
class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::VertexHandle, true> {
public:
inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
heh = mesh->cw_rotated_halfedge_handle(heh);
if (heh == start) ++lap_counter;
}
inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
if (heh == start) --lap_counter;
heh = mesh->ccw_rotated_halfedge_handle(heh);
}
};
template<class Mesh>
class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::FaceHandle, true> {
public:
inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
heh = mesh->next_halfedge_handle(heh);
if (heh == start) ++lap_counter;
}
inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
if (heh == start) --lap_counter;
heh = mesh->prev_halfedge_handle(heh);
}
};
/////////////////////////////////////////////////////////////
// CCW
template<class Mesh>
class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::VertexHandle, false> {
public:
inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
heh = mesh->ccw_rotated_halfedge_handle(heh);
if (heh == start) ++lap_counter;
}
inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
if (heh == start) --lap_counter;
heh = mesh->cw_rotated_halfedge_handle(heh);
}
};
template<class Mesh>
class GenericCirculator_CenterEntityFnsT<Mesh, typename Mesh::FaceHandle, false> {
public:
inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
heh = mesh->prev_halfedge_handle(heh);
if (heh == start) ++lap_counter;
}
inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
if (heh == start) --lap_counter;
heh = mesh->next_halfedge_handle(heh);
}
};
/////////////////////////////////////////////////////////////
template<class Mesh, class CenterEntityHandle, class ValueHandle>
class GenericCirculator_DereferenciabilityCheckT {
public:
//inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int &lap_counter);
};
template<class Mesh>
class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::FaceHandle, typename Mesh::FaceHandle> {
public:
inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
return mesh->face_handle(mesh->opposite_halfedge_handle(heh)).is_valid();
}
};
template<class Mesh>
class GenericCirculator_DereferenciabilityCheckT<Mesh, typename Mesh::VertexHandle, typename Mesh::FaceHandle> {
public:
inline static bool isDereferenciable(const Mesh *mesh, const typename Mesh::HalfedgeHandle &heh) {
return mesh->face_handle(heh).is_valid();
}
};
template<class Mesh, class CenterEntityHandle, class ValueHandle, bool CW = true>
class GenericCirculator_ValueHandleFnsT {
public:
inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
return ( heh.is_valid() && (lap_counter == 0 ) );
}
inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {};
inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::increment(mesh, heh, start, lap_counter);
}
inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::decrement(mesh, heh, start, lap_counter);
}
};
template<class Mesh, class CenterEntityHandle, bool CW>
class GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle, CW> {
public:
typedef GenericCirculator_DereferenciabilityCheckT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> GenericCirculator_DereferenciabilityCheck;
inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const int lap_counter) {
return ( heh.is_valid() && (lap_counter == 0));
}
inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
increment(mesh, heh, start, lap_counter);
};
inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
do {
GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::increment(mesh, heh, start, lap_counter);
} while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
}
inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
do {
GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, CW>::decrement(mesh, heh, start, lap_counter);
} while (is_valid(heh, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
}
};
template<class Mesh>
class GenericCirculatorBaseT {
public:
typedef const Mesh* mesh_ptr;
typedef const Mesh& mesh_ref;
public:
GenericCirculatorBaseT() : mesh_(0), lap_counter_(0) {}
GenericCirculatorBaseT(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
mesh_(&mesh), start_(heh), heh_(heh), lap_counter_(static_cast<int>(end && heh.is_valid())) {}
GenericCirculatorBaseT(const GenericCirculatorBaseT &rhs) :
mesh_(rhs.mesh_), start_(rhs.start_), heh_(rhs.heh_), lap_counter_(rhs.lap_counter_) {}
inline typename Mesh::FaceHandle toFaceHandle() const {
return mesh_->face_handle(heh_);
}
inline typename Mesh::FaceHandle toOppositeFaceHandle() const {
return mesh_->face_handle(toOppositeHalfedgeHandle());
}
inline typename Mesh::EdgeHandle toEdgeHandle() const {
return mesh_->edge_handle(heh_);
}
inline typename Mesh::HalfedgeHandle toHalfedgeHandle() const {
return heh_;
}
inline typename Mesh::HalfedgeHandle toOppositeHalfedgeHandle() const {
return mesh_->opposite_halfedge_handle(heh_);
}
inline typename Mesh::VertexHandle toVertexHandle() const {
return mesh_->to_vertex_handle(heh_);
}
inline GenericCirculatorBaseT &operator=(const GenericCirculatorBaseT &rhs) {
mesh_ = rhs.mesh_;
start_ = rhs.start_;
heh_ = rhs.heh_;
lap_counter_ = rhs.lap_counter_;
return *this;
}
inline bool operator==(const GenericCirculatorBaseT &rhs) const {
return mesh_ == rhs.mesh_ && start_ == rhs.start_ && heh_ == rhs.heh_ && lap_counter_ == rhs.lap_counter_;
}
inline bool operator!=(const GenericCirculatorBaseT &rhs) const {
return !operator==(rhs);
}
protected:
mesh_ptr mesh_;
typename Mesh::HalfedgeHandle start_, heh_;
int lap_counter_;
};
template<class Mesh, class CenterEntityHandle, class ValueHandle,
ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const, bool CW = true >
class GenericCirculatorT : protected GenericCirculatorBaseT<Mesh> {
public:
typedef std::ptrdiff_t difference_type;
typedef ValueHandle value_type;
typedef const value_type& reference;
typedef const value_type* pointer;
typedef std::bidirectional_iterator_tag iterator_category;
typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
typedef GenericCirculator_ValueHandleFnsT<Mesh, CenterEntityHandle, ValueHandle, CW> GenericCirculator_ValueHandleFns;
public:
GenericCirculatorT() {}
GenericCirculatorT(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
}
GenericCirculatorT(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
}
GenericCirculatorT(const GenericCirculatorT &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
friend class GenericCirculatorT<Mesh,CenterEntityHandle,ValueHandle,Handle2Value,!CW>;
explicit GenericCirculatorT( const GenericCirculatorT<Mesh,CenterEntityHandle,ValueHandle,Handle2Value,!CW>& rhs )
:GenericCirculatorBaseT<Mesh>(rhs){}
GenericCirculatorT& operator++() {
assert(this->mesh_);
GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
return *this;
}
GenericCirculatorT& operator--() {
assert(this->mesh_);
GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
return *this;
}
/// Post-increment
GenericCirculatorT operator++(int) {
assert(this->mesh_);
GenericCirculatorT cpy(*this);
++(*this);
return cpy;
}
/// Post-decrement
GenericCirculatorT operator--(int) {
assert(this->mesh_);
GenericCirculatorT cpy(*this);
--(*this);
return cpy;
}
/// Standard dereferencing operator.
value_type operator*() const {
// We can't use this due to a GCC6 compiler bug
const GenericCirculatorBaseT<Mesh>* self = this;
#ifndef NDEBUG
assert(this->heh_.is_valid());
value_type res = (self->*Handle2Value)();
assert(res.is_valid());
return res;
#else
return (self->*Handle2Value)();
#endif
}
/**
* @brief Pointer dereferentiation.
*
* This returns a pointer which points to a handle
* that loses its validity once this dereferentiation is
* invoked again. Thus, do not store the result of
* this operation.
*/
pointer operator->() const {
pointer_deref_value = **this;
return &pointer_deref_value;
}
GenericCirculatorT &operator=(const GenericCirculatorT &rhs) {
GenericCirculatorBaseT<Mesh>::operator=(rhs);
return *this;
};
bool operator==(const GenericCirculatorT &rhs) const {
return GenericCirculatorBaseT<Mesh>::operator==(rhs);
}
bool operator!=(const GenericCirculatorT &rhs) const {
return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
}
bool is_valid() const {
return GenericCirculator_ValueHandleFns::is_valid(this->heh_, this->lap_counter_);
}
template<typename STREAM>
friend STREAM &operator<< (STREAM &s, const GenericCirculatorT &self) {
return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
}
private:
mutable value_type pointer_deref_value;
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////// OLD ///////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// OLD CIRCULATORS
// deprecated circulators, will be removed soon
// if you remove these circulators and go to the old ones, PLEASE ENABLE FOLLOWING UNITTESTS:
//
// OpenMeshTrimeshCirculatorVertexIHalfEdge.VertexIHalfEdgeIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorVertexEdge.VertexEdgeIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorVertexVertex.VertexVertexIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorVertexOHalfEdge.VertexOHalfEdgeIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorVertexFace.VertexFaceIterWithoutHolesDecrement
// OpenMeshTrimeshCirculatorFaceEdge.FaceEdgeIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorFaceFace.FaceFaceIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterWithoutHolesIncrement
// OpenMeshTrimeshCirculatorFaceVertex.FaceVertexIterCheckInvalidationAtEnds
// OpenMeshTrimeshCirculatorFaceHalfEdge.FaceHalfedgeIterCheckInvalidationAtEnds
//
template<class Mesh, class CenterEntityHandle, class ValueHandle>
class GenericCirculator_ValueHandleFnsT_DEPRECATED {
public:
inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh,const typename Mesh::HalfedgeHandle &start, const int lap_counter) {
return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )) );
}
inline static void init(const Mesh*, typename Mesh::HalfedgeHandle&, typename Mesh::HalfedgeHandle&, int&) {};
inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::increment(mesh, heh, start, lap_counter);
}
inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::decrement(mesh, heh, start, lap_counter);
}
};
template<class Mesh, class CenterEntityHandle>
class GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> {
public:
typedef GenericCirculator_DereferenciabilityCheckT<Mesh, CenterEntityHandle, typename Mesh::FaceHandle> GenericCirculator_DereferenciabilityCheck;
inline static bool is_valid(const typename Mesh::HalfedgeHandle &heh, const typename Mesh::HalfedgeHandle &start, const int lap_counter) {
return ( heh.is_valid() && ((start != heh) || (lap_counter == 0 )));
}
inline static void init(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
if (heh.is_valid() && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh) && lap_counter == 0 )
increment(mesh, heh, start, lap_counter);
};
inline static void increment(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
do {
GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::increment(mesh, heh, start, lap_counter);
} while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
}
inline static void decrement(const Mesh *mesh, typename Mesh::HalfedgeHandle &heh, typename Mesh::HalfedgeHandle &start, int &lap_counter) {
do {
GenericCirculator_CenterEntityFnsT<Mesh, CenterEntityHandle, true>::decrement(mesh, heh, start, lap_counter);
} while (is_valid(heh, start, lap_counter) && !GenericCirculator_DereferenciabilityCheck::isDereferenciable(mesh, heh));
}
};
template<class Mesh, class CenterEntityHandle, class ValueHandle,
ValueHandle (GenericCirculatorBaseT<Mesh>::*Handle2Value)() const>
class GenericCirculatorT_DEPRECATED : protected GenericCirculatorBaseT<Mesh> {
public:
typedef std::ptrdiff_t difference_type;
typedef ValueHandle value_type;
typedef const value_type& reference;
typedef const value_type* pointer;
typedef std::bidirectional_iterator_tag iterator_category;
typedef typename GenericCirculatorBaseT<Mesh>::mesh_ptr mesh_ptr;
typedef typename GenericCirculatorBaseT<Mesh>::mesh_ref mesh_ref;
typedef GenericCirculator_ValueHandleFnsT_DEPRECATED<Mesh, CenterEntityHandle, ValueHandle> GenericCirculator_ValueHandleFns;
public:
GenericCirculatorT_DEPRECATED() {}
GenericCirculatorT_DEPRECATED(mesh_ref mesh, CenterEntityHandle start, bool end = false) :
GenericCirculatorBaseT<Mesh>(mesh, mesh.halfedge_handle(start), end) {
GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
}
GenericCirculatorT_DEPRECATED(mesh_ref mesh, HalfedgeHandle heh, bool end = false) :
GenericCirculatorBaseT<Mesh>(mesh, heh, end) {
GenericCirculator_ValueHandleFns::init(this->mesh_, this->heh_, this->start_, this->lap_counter_);
}
GenericCirculatorT_DEPRECATED(const GenericCirculatorT_DEPRECATED &rhs) : GenericCirculatorBaseT<Mesh>(rhs) {}
GenericCirculatorT_DEPRECATED& operator++() {
assert(this->mesh_);
GenericCirculator_ValueHandleFns::increment(this->mesh_, this->heh_, this->start_, this->lap_counter_);
return *this;
}
#ifndef NO_DECREMENT_DEPRECATED_WARNINGS
#define DECREMENT_DEPRECATED_WARNINGS_TEXT "The current decrement operator has the unintended behavior that it stays\
valid when iterating below the start and will visit the first entity\
twice before getting invalid. Furthermore it gets valid again, if you\
increment at the end.\
When you are sure that you don't iterate below the start anywhere in\
your code or rely on this behaviour, you can disable this warning by\
setting the define NO_DECREMENT_DEPRECATED_WARNINGS at the command line (or enable it via the\
cmake flags).\
To be save, you can use the CW/CCW circulator definitions, which behave\
the same as the original ones, without the previously mentioned issues."
DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
#endif // NO_DECREMENT_DEPRECATED_WARNINGS
GenericCirculatorT_DEPRECATED& operator--() {
assert(this->mesh_);
GenericCirculator_ValueHandleFns::decrement(this->mesh_, this->heh_, this->start_, this->lap_counter_);
return *this;
}
/// Post-increment
GenericCirculatorT_DEPRECATED operator++(int) {
assert(this->mesh_);
GenericCirculatorT_DEPRECATED cpy(*this);
++(*this);
return cpy;
}
/// Post-decrement
#ifndef NO_DECREMENT_DEPRECATED_WARNINGS
DEPRECATED( DECREMENT_DEPRECATED_WARNINGS_TEXT )
#undef DECREMENT_DEPRECATED_WARNINGS_TEXT
#endif //NO_DECREMENT_DEPRECATED_WARNINGS
GenericCirculatorT_DEPRECATED operator--(int) {
assert(this->mesh_);
GenericCirculatorT_DEPRECATED cpy(*this);
--(*this);
return cpy;
}
/// Standard dereferencing operator.
value_type operator*() const {
// We can't use this due to a GCC6 compiler bug
const GenericCirculatorBaseT<Mesh>* self = this;
#ifndef NDEBUG
assert(this->heh_.is_valid());
value_type res = (self->*Handle2Value)();
assert(res.is_valid());
return res;
#else
return (self->*Handle2Value)();
#endif
}
/**
* @brief Pointer dereferentiation.
*
* This returns a pointer which points to a handle
* that loses its validity once this dereferentiation is
* invoked again. Thus, do not store the result of
* this operation.
*/
pointer operator->() const {
pointer_deref_value = **this;
return &pointer_deref_value;
}
GenericCirculatorT_DEPRECATED &operator=(const GenericCirculatorT_DEPRECATED &rhs) {
GenericCirculatorBaseT<Mesh>::operator=(rhs);
return *this;
};
bool operator==(const GenericCirculatorT_DEPRECATED &rhs) const {
return GenericCirculatorBaseT<Mesh>::operator==(rhs);
}
bool operator!=(const GenericCirculatorT_DEPRECATED &rhs) const {
return GenericCirculatorBaseT<Mesh>::operator!=(rhs);
}
bool is_valid() const {
return GenericCirculator_ValueHandleFns::is_valid(this->heh_,this->start_, this->lap_counter_);
}
DEPRECATED("current_halfedge_handle() is an implementation detail and should not be accessed from outside the iterator class.")
/**
* \deprecated
* current_halfedge_handle() is an implementation detail and should not
* be accessed from outside the iterator class.
*/
const HalfedgeHandle &current_halfedge_handle() const {
return this->heh_;
}
DEPRECATED("Do not use this error prone implicit cast. Compare to end-iterator or use is_valid(), instead.")
/**
* \deprecated
* Do not use this error prone implicit cast. Compare to the
* end-iterator or use is_valid() instead.
*/
operator bool() const {
return is_valid();
}
/**
* \brief Return the handle of the current target.
* \deprecated
* This function clutters your code. Use dereferencing operators -> and * instead.
*/
DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.")
value_type handle() const {
return **this;
}
/**
* \brief Cast to the handle of the current target.
* \deprecated
* Implicit casts of iterators are unsafe. Use dereferencing operators
* -> and * instead.
*/
DEPRECATED("Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.")
operator value_type() const {
return **this;
}
template<typename STREAM>
friend STREAM &operator<< (STREAM &s, const GenericCirculatorT_DEPRECATED &self) {
return s << self.mesh_ << ", " << self.start_.idx() << ", " << self.heh_.idx() << ", " << self.lap_counter_;
}
private:
mutable value_type pointer_deref_value;
};
} // namespace Iterators
} // namespace OpenMesh
#endif

View File

@ -0,0 +1,227 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OPENMESH_MESH_ITEMS_HH
#define OPENMESH_MESH_ITEMS_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Utils/GenProg.hh>
#include <OpenMesh/Core/Utils/vector_traits.hh>
#include <OpenMesh/Core/Mesh/Handles.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== CLASS DEFINITION =========================================================
/// Definition of the mesh entities (items).
template <class Traits, bool IsTriMesh>
struct FinalMeshItemsT
{
//--- build Refs structure ---
#ifndef DOXY_IGNORE_THIS
struct Refs
{
typedef typename Traits::Point Point;
typedef typename vector_traits<Point>::value_type Scalar;
typedef typename Traits::Normal Normal;
typedef typename Traits::Color Color;
typedef typename Traits::TexCoord1D TexCoord1D;
typedef typename Traits::TexCoord2D TexCoord2D;
typedef typename Traits::TexCoord3D TexCoord3D;
typedef typename Traits::TextureIndex TextureIndex;
typedef OpenMesh::VertexHandle VertexHandle;
typedef OpenMesh::FaceHandle FaceHandle;
typedef OpenMesh::EdgeHandle EdgeHandle;
typedef OpenMesh::HalfedgeHandle HalfedgeHandle;
};
#endif
//--- export Refs types ---
typedef typename Refs::Point Point;
typedef typename Refs::Scalar Scalar;
typedef typename Refs::Normal Normal;
typedef typename Refs::Color Color;
typedef typename Refs::TexCoord1D TexCoord1D;
typedef typename Refs::TexCoord2D TexCoord2D;
typedef typename Refs::TexCoord3D TexCoord3D;
typedef typename Refs::TextureIndex TextureIndex;
//--- get attribute bits from Traits ---
enum Attribs
{
VAttribs = Traits::VertexAttributes,
HAttribs = Traits::HalfedgeAttributes,
EAttribs = Traits::EdgeAttributes,
FAttribs = Traits::FaceAttributes
};
//--- merge internal items with traits items ---
/*
typedef typename GenProg::IF<
(bool)(HAttribs & Attributes::PrevHalfedge),
typename InternalItems::Halfedge_with_prev,
typename InternalItems::Halfedge_without_prev
>::Result InternalHalfedge;
*/
//typedef typename InternalItems::Vertex InternalVertex;
//typedef typename InternalItems::template Edge<Halfedge> InternalEdge;
//typedef typename InternalItems::template Face<IsTriMesh> InternalFace;
class ITraits
{};
typedef typename Traits::template VertexT<ITraits, Refs> VertexData;
typedef typename Traits::template HalfedgeT<ITraits, Refs> HalfedgeData;
typedef typename Traits::template EdgeT<ITraits, Refs> EdgeData;
typedef typename Traits::template FaceT<ITraits, Refs> FaceData;
};
#ifndef DOXY_IGNORE_THIS
namespace {
namespace TM {
template<typename Lhs, typename Rhs> struct TypeEquality;
template<typename Lhs> struct TypeEquality<Lhs, Lhs> {};
template<typename LhsTraits, typename RhsTraits> struct ItemsEquality {
TypeEquality<typename LhsTraits::Point, typename RhsTraits::Point> te1;
TypeEquality<typename LhsTraits::Scalar, typename RhsTraits::Scalar> te2;
TypeEquality<typename LhsTraits::Normal, typename RhsTraits::Normal> te3;
TypeEquality<typename LhsTraits::Color, typename RhsTraits::Color> te4;
TypeEquality<typename LhsTraits::TexCoord1D, typename RhsTraits::TexCoord1D> te5;
TypeEquality<typename LhsTraits::TexCoord2D, typename RhsTraits::TexCoord2D> te6;
TypeEquality<typename LhsTraits::TexCoord3D, typename RhsTraits::TexCoord3D> te7;
TypeEquality<typename LhsTraits::TextureIndex, typename RhsTraits::TextureIndex> te8;
};
} /* namespace TM */
} /* anonymous namespace */
#endif
/**
* @brief Cast a mesh with different but identical traits into each other.
*
* Note that there exists a syntactically more convenient global method
* mesh_cast().
*
* Example:
* @code{.cpp}
* struct TriTraits1 : public OpenMesh::DefaultTraits {
* typedef Vec3d Point;
* };
* struct TriTraits2 : public OpenMesh::DefaultTraits {
* typedef Vec3d Point;
* };
* struct TriTraits3 : public OpenMesh::DefaultTraits {
* typedef Vec3f Point;
* };
*
* TriMesh_ArrayKernelT<TriTraits1> a;
* TriMesh_ArrayKernelT<TriTraits2> &b = MeshCast<TriMesh_ArrayKernelT<TriTraits2>&, TriMesh_ArrayKernelT<TriTraits1>&>::cast(a); // OK
* TriMesh_ArrayKernelT<TriTraits3> &c = MeshCast<TriMesh_ArrayKernelT<TriTraits3>&, TriMesh_ArrayKernelT<TriTraits1>&>::cast(a); // ERROR
* @endcode
*
* @see mesh_cast()
*
* @param rhs
* @return
*/
template<typename LhsMeshT, typename RhsMeshT> struct MeshCast;
template<typename LhsMeshT, typename RhsMeshT>
struct MeshCast<LhsMeshT&, RhsMeshT&> {
static LhsMeshT &cast(RhsMeshT &rhs) {
(void)sizeof(TM::ItemsEquality<typename LhsMeshT::MeshItemsT, typename RhsMeshT::MeshItemsT>);
(void)sizeof(TM::TypeEquality<typename LhsMeshT::ConnectivityT, typename RhsMeshT::ConnectivityT>);
return reinterpret_cast<LhsMeshT&>(rhs);
}
};
template<typename LhsMeshT, typename RhsMeshT>
struct MeshCast<const LhsMeshT&, const RhsMeshT&> {
static const LhsMeshT &cast(const RhsMeshT &rhs) {
(void)sizeof(TM::ItemsEquality<typename LhsMeshT::MeshItemsT, typename RhsMeshT::MeshItemsT>);
(void)sizeof(TM::TypeEquality<typename LhsMeshT::ConnectivityT, typename RhsMeshT::ConnectivityT>);
return reinterpret_cast<const LhsMeshT&>(rhs);
}
};
template<typename LhsMeshT, typename RhsMeshT>
struct MeshCast<LhsMeshT*, RhsMeshT*> {
static LhsMeshT *cast(RhsMeshT *rhs) {
(void)sizeof(TM::ItemsEquality<typename LhsMeshT::MeshItemsT, typename RhsMeshT::MeshItemsT>);
(void)sizeof(TM::TypeEquality<typename LhsMeshT::ConnectivityT, typename RhsMeshT::ConnectivityT>);
return reinterpret_cast<LhsMeshT*>(rhs);
}
};
template<typename LhsMeshT, typename RhsMeshT>
struct MeshCast<const LhsMeshT*, const RhsMeshT*> {
static const LhsMeshT *cast(const RhsMeshT *rhs) {
(void)sizeof(TM::ItemsEquality<typename LhsMeshT::MeshItemsT, typename RhsMeshT::MeshItemsT>);
(void)sizeof(TM::TypeEquality<typename LhsMeshT::ConnectivityT, typename RhsMeshT::ConnectivityT>);
return reinterpret_cast<const LhsMeshT*>(rhs);
}
};
//=============================================================================
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_MESH_ITEMS_HH defined
//=============================================================================

View File

@ -0,0 +1,238 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OPENMESH_HANDLES_HH
#define OPENMESH_HANDLES_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <ostream>
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== CLASS DEFINITION =========================================================
/// Base class for all handle types
class BaseHandle
{
public:
explicit BaseHandle(int _idx=-1) : idx_(_idx) {}
/// Get the underlying index of this handle
int idx() const { return idx_; }
/// The handle is valid iff the index is not negative.
bool is_valid() const { return idx_ >= 0; }
/// reset handle to be invalid
void reset() { idx_=-1; }
/// reset handle to be invalid
void invalidate() { idx_ = -1; }
bool operator==(const BaseHandle& _rhs) const {
return (this->idx_ == _rhs.idx_);
}
bool operator!=(const BaseHandle& _rhs) const {
return (this->idx_ != _rhs.idx_);
}
bool operator<(const BaseHandle& _rhs) const {
return (this->idx_ < _rhs.idx_);
}
// this is to be used only by the iterators
void __increment() { ++idx_; }
void __decrement() { --idx_; }
void __increment(int amount) { idx_ += amount; }
void __decrement(int amount) { idx_ -= amount; }
private:
int idx_;
};
// this is used by boost::unordered_set/map
inline size_t hash_value(const BaseHandle& h) { return h.idx(); }
//-----------------------------------------------------------------------------
/// Write handle \c _hnd to stream \c _os
inline std::ostream& operator<<(std::ostream& _os, const BaseHandle& _hnd)
{
return (_os << _hnd.idx());
}
//-----------------------------------------------------------------------------
/// Handle for a vertex entity
struct VertexHandle : public BaseHandle
{
explicit VertexHandle(int _idx=-1) : BaseHandle(_idx) {}
};
/// Handle for a halfedge entity
struct HalfedgeHandle : public BaseHandle
{
explicit HalfedgeHandle(int _idx=-1) : BaseHandle(_idx) {}
};
/// Handle for a edge entity
struct EdgeHandle : public BaseHandle
{
explicit EdgeHandle(int _idx=-1) : BaseHandle(_idx) {}
};
/// Handle for a face entity
struct FaceHandle : public BaseHandle
{
explicit FaceHandle(int _idx=-1) : BaseHandle(_idx) {}
};
//=============================================================================
} // namespace OpenMesh
//=============================================================================
#ifdef OM_HAS_HASH
#include <functional>
namespace std {
#if defined(_MSVC_VER)
# pragma warning(push)
# pragma warning(disable:4099) // For VC++ it is class hash
#endif
template <>
struct hash<OpenMesh::BaseHandle >
{
typedef OpenMesh::BaseHandle argument_type;
typedef std::size_t result_type;
std::size_t operator()(const OpenMesh::BaseHandle& h) const
{
return h.idx();
}
};
template <>
struct hash<OpenMesh::VertexHandle >
{
typedef OpenMesh::VertexHandle argument_type;
typedef std::size_t result_type;
std::size_t operator()(const OpenMesh::VertexHandle& h) const
{
return h.idx();
}
};
template <>
struct hash<OpenMesh::HalfedgeHandle >
{
typedef OpenMesh::HalfedgeHandle argument_type;
typedef std::size_t result_type;
std::size_t operator()(const OpenMesh::HalfedgeHandle& h) const
{
return h.idx();
}
};
template <>
struct hash<OpenMesh::EdgeHandle >
{
typedef OpenMesh::EdgeHandle argument_type;
typedef std::size_t result_type;
std::size_t operator()(const OpenMesh::EdgeHandle& h) const
{
return h.idx();
}
};
template <>
struct hash<OpenMesh::FaceHandle >
{
typedef OpenMesh::FaceHandle argument_type;
typedef std::size_t result_type;
std::size_t operator()(const OpenMesh::FaceHandle& h) const
{
return h.idx();
}
};
#if defined(_MSVC_VER)
# pragma warning(pop)
#endif
}
#endif // OM_HAS_HASH
#endif // OPENMESH_HANDLES_HH
//=============================================================================

View File

@ -0,0 +1,259 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OPENMESH_ITERATORS_HH
#define OPENMESH_ITERATORS_HH
//=============================================================================
//
// Iterators for PolyMesh/TriMesh
//
//=============================================================================
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Mesh/Status.hh>
#include <cassert>
#include <cstddef>
#include <iterator>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace Iterators {
//== FORWARD DECLARATIONS =====================================================
template <class Mesh> class ConstVertexIterT;
template <class Mesh> class VertexIterT;
template <class Mesh> class ConstHalfedgeIterT;
template <class Mesh> class HalfedgeIterT;
template <class Mesh> class ConstEdgeIterT;
template <class Mesh> class EdgeIterT;
template <class Mesh> class ConstFaceIterT;
template <class Mesh> class FaceIterT;
template <class Mesh, class ValueHandle, class MemberOwner, bool (MemberOwner::*PrimitiveStatusMember)() const, size_t (MemberOwner::*PrimitiveCountMember)() const>
class GenericIteratorT {
public:
//--- Typedefs ---
typedef ValueHandle value_handle;
typedef value_handle value_type;
typedef std::bidirectional_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
typedef const value_type& reference;
typedef const value_type* pointer;
typedef const Mesh* mesh_ptr;
typedef const Mesh& mesh_ref;
/// Default constructor.
GenericIteratorT()
: mesh_(0), skip_bits_(0)
{}
/// Construct with mesh and a target handle.
GenericIteratorT(mesh_ref _mesh, value_handle _hnd, bool _skip=false)
: mesh_(&_mesh), hnd_(_hnd), skip_bits_(0)
{
if (_skip) enable_skipping();
}
/// Standard dereferencing operator.
reference operator*() const {
return hnd_;
}
/// Standard pointer operator.
pointer operator->() const {
return &hnd_;
}
/**
* \brief Get the handle of the item the iterator refers to.
* \deprecated
* This function clutters your code. Use dereferencing operators -> and * instead.
*/
DEPRECATED("This function clutters your code. Use dereferencing operators -> and * instead.")
value_handle handle() const {
return hnd_;
}
/**
* \brief Cast to the handle of the item the iterator refers to.
* \deprecated
* Implicit casts of iterators are unsafe. Use dereferencing operators
* -> and * instead.
*/
DEPRECATED("Implicit casts of iterators are unsafe. Use dereferencing operators -> and * instead.")
operator value_handle() const {
return hnd_;
}
/// Are two iterators equal? Only valid if they refer to the same mesh!
bool operator==(const GenericIteratorT& _rhs) const {
return ((mesh_ == _rhs.mesh_) && (hnd_ == _rhs.hnd_));
}
/// Not equal?
bool operator!=(const GenericIteratorT& _rhs) const {
return !operator==(_rhs);
}
/// Standard pre-increment operator
GenericIteratorT& operator++() {
hnd_.__increment();
if (skip_bits_)
skip_fwd();
return *this;
}
/// Standard post-increment operator
GenericIteratorT operator++(int) {
GenericIteratorT cpy(*this);
++(*this);
return cpy;
}
#if ((defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(OPENMESH_VECTOR_LEGACY)
template<class T = value_handle>
auto operator+=(int amount) ->
typename std::enable_if<
sizeof(decltype(std::declval<T>().__increment(amount))) >= 0,
GenericIteratorT&>::type {
static_assert(std::is_same<T, value_handle>::value,
"Template parameter must not deviate from default.");
if (skip_bits_)
throw std::logic_error("Skipping iterators do not support "
"random access.");
hnd_.__increment(amount);
return *this;
}
template<class T = value_handle>
auto operator+(int rhs) ->
typename std::enable_if<
sizeof(decltype(std::declval<T>().__increment(rhs), void (), int {})) >= 0,
GenericIteratorT>::type {
static_assert(std::is_same<T, value_handle>::value,
"Template parameter must not deviate from default.");
if (skip_bits_)
throw std::logic_error("Skipping iterators do not support "
"random access.");
GenericIteratorT result = *this;
result.hnd_.__increment(rhs);
return result;
}
#endif
/// Standard pre-decrement operator
GenericIteratorT& operator--() {
hnd_.__decrement();
if (skip_bits_)
skip_bwd();
return *this;
}
/// Standard post-decrement operator
GenericIteratorT operator--(int) {
GenericIteratorT cpy(*this);
--(*this);
return cpy;
}
/// Turn on skipping: automatically skip deleted/hidden elements
void enable_skipping() {
if (mesh_ && (mesh_->*PrimitiveStatusMember)()) {
Attributes::StatusInfo status;
status.set_deleted(true);
status.set_hidden(true);
skip_bits_ = status.bits();
skip_fwd();
} else
skip_bits_ = 0;
}
/// Turn on skipping: automatically skip deleted/hidden elements
void disable_skipping() {
skip_bits_ = 0;
}
private:
void skip_fwd() {
assert(mesh_ && skip_bits_);
while ((hnd_.idx() < (signed) (mesh_->*PrimitiveCountMember)())
&& (mesh_->status(hnd_).bits() & skip_bits_))
hnd_.__increment();
}
void skip_bwd() {
assert(mesh_ && skip_bits_);
while ((hnd_.idx() >= 0) && (mesh_->status(hnd_).bits() & skip_bits_))
hnd_.__decrement();
}
protected:
mesh_ptr mesh_;
value_handle hnd_;
unsigned int skip_bits_;
};
//=============================================================================
} // namespace Iterators
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,463 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS PolyMeshT - IMPLEMENTATION
//
//=============================================================================
#define OPENMESH_POLYMESH_C
//== INCLUDES =================================================================
#include <OpenMesh/Core/Mesh/PolyMeshT.hh>
#include <OpenMesh/Core/Geometry/LoopSchemeMaskT.hh>
#include <OpenMesh/Core/Utils/GenProg.hh>
#include <OpenMesh/Core/Utils/vector_cast.hh>
#include <OpenMesh/Core/Utils/vector_traits.hh>
#include <OpenMesh/Core/System/omstream.hh>
#include <vector>
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== IMPLEMENTATION ==========================================================
template <class Kernel>
uint PolyMeshT<Kernel>::find_feature_edges(Scalar _angle_tresh)
{
assert(Kernel::has_edge_status());//this function needs edge status property
uint n_feature_edges = 0;
for (EdgeIter e_it = Kernel::edges_begin(); e_it != Kernel::edges_end(); ++e_it)
{
if (fabs(calc_dihedral_angle(*e_it)) > _angle_tresh)
{//note: could be optimized by comparing cos(dih_angle) vs. cos(_angle_tresh)
this->status(*e_it).set_feature(true);
n_feature_edges++;
}
else
{
this->status(*e_it).set_feature(false);
}
}
return n_feature_edges;
}
//-----------------------------------------------------------------------------
template <class Kernel>
typename PolyMeshT<Kernel>::Normal
PolyMeshT<Kernel>::calc_face_normal(FaceHandle _fh) const
{
return calc_face_normal_impl(_fh, typename GenProg::IF<
vector_traits<PolyMeshT<Kernel>::Point>::size_ == 3,
PointIs3DTag,
PointIsNot3DTag
>::Result());
}
template <class Kernel>
typename PolyMeshT<Kernel>::Normal
PolyMeshT<Kernel>::calc_face_normal_impl(FaceHandle _fh, PointIs3DTag) const
{
assert(this->halfedge_handle(_fh).is_valid());
ConstFaceVertexIter fv_it(this->cfv_iter(_fh));
// Safeguard for 1-gons
if (!(++fv_it).is_valid()) return Normal(0, 0, 0);
// Safeguard for 2-gons
if (!(++fv_it).is_valid()) return Normal(0, 0, 0);
// use Newell's Method to compute the surface normal
Normal n(0,0,0);
for(fv_it = this->cfv_iter(_fh); fv_it.is_valid(); ++fv_it)
{
// next vertex
ConstFaceVertexIter fv_itn = fv_it;
++fv_itn;
if (!fv_itn.is_valid())
fv_itn = this->cfv_iter(_fh);
// http://www.opengl.org/wiki/Calculating_a_Surface_Normal
const Point a = this->point(*fv_it) - this->point(*fv_itn);
const Point b = this->point(*fv_it) + this->point(*fv_itn);
// Due to traits, the value types of normals and points can be different.
// Therefore we cast them here.
n[0] += static_cast<typename vector_traits<Normal>::value_type>(a[1] * b[2]);
n[1] += static_cast<typename vector_traits<Normal>::value_type>(a[2] * b[0]);
n[2] += static_cast<typename vector_traits<Normal>::value_type>(a[0] * b[1]);
}
const typename vector_traits<Normal>::value_type length = norm(n);
// The expression ((n *= (1.0/norm)),n) is used because the OpenSG
// vector class does not return self after component-wise
// self-multiplication with a scalar!!!
return (length != typename vector_traits<Normal>::value_type(0))
? ((n *= (typename vector_traits<Normal>::value_type(1)/length)), n)
: Normal(0, 0, 0);
}
template <class Kernel>
typename PolyMeshT<Kernel>::Normal
PolyMeshT<Kernel>::calc_face_normal_impl(FaceHandle, PointIsNot3DTag) const
{
// Dummy fallback implementation
return Normal(typename Normal::value_type(0));
}
//-----------------------------------------------------------------------------
template <class Kernel>
typename PolyMeshT<Kernel>::Normal
PolyMeshT<Kernel>::
calc_face_normal(const Point& _p0,
const Point& _p1,
const Point& _p2) const
{
return calc_face_normal_impl(_p0, _p1, _p2, typename GenProg::IF<
vector_traits<PolyMeshT<Kernel>::Point>::size_ == 3,
PointIs3DTag,
PointIsNot3DTag
>::Result());
}
template <class Kernel>
typename PolyMeshT<Kernel>::Normal
PolyMeshT<Kernel>::
calc_face_normal_impl(const Point& _p0,
const Point& _p1,
const Point& _p2,
PointIs3DTag) const
{
#if 1
// The OpenSG <Vector>::operator -= () does not support the type Point
// as rhs. Therefore use vector_cast at this point!!!
// Note! OpenSG distinguishes between Normal and Point!!!
Normal p1p0(vector_cast<Normal>(_p0)); p1p0 -= vector_cast<Normal>(_p1);
Normal p1p2(vector_cast<Normal>(_p2)); p1p2 -= vector_cast<Normal>(_p1);
Normal n = cross(p1p2, p1p0);
typename vector_traits<Normal>::value_type length = norm(n);
// The expression ((n *= (1.0/norm)),n) is used because the OpenSG
// vector class does not return self after component-wise
// self-multiplication with a scalar!!!
return (length != typename vector_traits<Normal>::value_type(0))
? ((n *= (typename vector_traits<Normal>::value_type(1)/length)),n)
: Normal(0,0,0);
#else
Point p1p0 = _p0; p1p0 -= _p1;
Point p1p2 = _p2; p1p2 -= _p1;
Normal n = vector_cast<Normal>(cross(p1p2, p1p0));
typename vector_traits<Normal>::value_type length = norm(n);
return (length != 0.0) ? n *= (1.0/length) : Normal(0,0,0);
#endif
}
template <class Kernel>
typename PolyMeshT<Kernel>::Normal
PolyMeshT<Kernel>::calc_face_normal_impl(const Point&, const Point&, const Point&, PointIsNot3DTag) const
{
return Normal(typename Normal::value_type(0));
}
//-----------------------------------------------------------------------------
template <class Kernel>
typename PolyMeshT<Kernel>::Point
PolyMeshT<Kernel>::
calc_face_centroid(FaceHandle _fh) const
{
Point _pt;
vectorize(_pt, 0);
Scalar valence = 0.0;
for (ConstFaceVertexIter cfv_it = this->cfv_iter(_fh); cfv_it.is_valid(); ++cfv_it, valence += 1.0)
{
_pt += this->point(*cfv_it);
}
_pt /= valence;
return _pt;
}
//-----------------------------------------------------------------------------
template <class Kernel>
void
PolyMeshT<Kernel>::
update_normals()
{
// Face normals are required to compute the vertex and the halfedge normals
if (Kernel::has_face_normals() ) {
update_face_normals();
if (Kernel::has_vertex_normals() ) update_vertex_normals();
if (Kernel::has_halfedge_normals()) update_halfedge_normals();
}
}
//-----------------------------------------------------------------------------
template <class Kernel>
void
PolyMeshT<Kernel>::
update_face_normals()
{
FaceIter f_it(Kernel::faces_sbegin()), f_end(Kernel::faces_end());
for (; f_it != f_end; ++f_it)
this->set_normal(*f_it, calc_face_normal(*f_it));
}
//-----------------------------------------------------------------------------
template <class Kernel>
void
PolyMeshT<Kernel>::
update_halfedge_normals(const double _feature_angle)
{
HalfedgeIter h_it(Kernel::halfedges_begin()), h_end(Kernel::halfedges_end());
for (; h_it != h_end; ++h_it)
this->set_normal(*h_it, calc_halfedge_normal(*h_it, _feature_angle));
}
//-----------------------------------------------------------------------------
template <class Kernel>
typename PolyMeshT<Kernel>::Normal
PolyMeshT<Kernel>::
calc_halfedge_normal(HalfedgeHandle _heh, const double _feature_angle) const
{
if(Kernel::is_boundary(_heh))
return Normal(0,0,0);
else
{
std::vector<FaceHandle> fhs; fhs.reserve(10);
HalfedgeHandle heh = _heh;
// collect CW face-handles
do
{
fhs.push_back(Kernel::face_handle(heh));
heh = Kernel::next_halfedge_handle(heh);
heh = Kernel::opposite_halfedge_handle(heh);
}
while(heh != _heh && !Kernel::is_boundary(heh) && !is_estimated_feature_edge(heh, _feature_angle));
// collect CCW face-handles
if(heh != _heh && !is_estimated_feature_edge(_heh, _feature_angle))
{
heh = Kernel::opposite_halfedge_handle(_heh);
if ( !Kernel::is_boundary(heh) ) {
do
{
fhs.push_back(Kernel::face_handle(heh));
heh = Kernel::prev_halfedge_handle(heh);
heh = Kernel::opposite_halfedge_handle(heh);
}
while(!Kernel::is_boundary(heh) && !is_estimated_feature_edge(heh, _feature_angle));
}
}
Normal n(0,0,0);
for(unsigned int i=0; i<fhs.size(); ++i)
n += Kernel::normal(fhs[i]);
return normalize(n);
}
}
//-----------------------------------------------------------------------------
template <class Kernel>
bool
PolyMeshT<Kernel>::
is_estimated_feature_edge(HalfedgeHandle _heh, const double _feature_angle) const
{
EdgeHandle eh = Kernel::edge_handle(_heh);
if(Kernel::has_edge_status())
{
if(Kernel::status(eh).feature())
return true;
}
if(Kernel::is_boundary(eh))
return false;
// compute angle between faces
FaceHandle fh0 = Kernel::face_handle(_heh);
FaceHandle fh1 = Kernel::face_handle(Kernel::opposite_halfedge_handle(_heh));
Normal fn0 = Kernel::normal(fh0);
Normal fn1 = Kernel::normal(fh1);
// dihedral angle above angle threshold
return ( dot(fn0,fn1) < cos(_feature_angle) );
}
//-----------------------------------------------------------------------------
template <class Kernel>
typename PolyMeshT<Kernel>::Normal
PolyMeshT<Kernel>::
calc_vertex_normal(VertexHandle _vh) const
{
Normal n;
calc_vertex_normal_fast(_vh,n);
Scalar length = norm(n);
if (length != 0.0) n *= (Scalar(1.0)/length);
return n;
}
//-----------------------------------------------------------------------------
template <class Kernel>
void PolyMeshT<Kernel>::
calc_vertex_normal_fast(VertexHandle _vh, Normal& _n) const
{
vectorize(_n, 0.0);
for (ConstVertexFaceIter vf_it = this->cvf_iter(_vh); vf_it.is_valid(); ++vf_it)
_n += this->normal(*vf_it);
}
//-----------------------------------------------------------------------------
template <class Kernel>
void PolyMeshT<Kernel>::
calc_vertex_normal_correct(VertexHandle _vh, Normal& _n) const
{
vectorize(_n, 0.0);
ConstVertexIHalfedgeIter cvih_it = this->cvih_iter(_vh);
if (! cvih_it.is_valid() )
{//don't crash on isolated vertices
return;
}
Normal in_he_vec;
calc_edge_vector(*cvih_it, in_he_vec);
for ( ; cvih_it.is_valid(); ++cvih_it)
{//calculates the sector normal defined by cvih_it and adds it to _n
if (this->is_boundary(*cvih_it))
{
continue;
}
HalfedgeHandle out_heh(this->next_halfedge_handle(*cvih_it));
Normal out_he_vec;
calc_edge_vector(out_heh, out_he_vec);
_n += cross(in_he_vec, out_he_vec);//sector area is taken into account
in_he_vec = out_he_vec;
in_he_vec *= -1;//change the orientation
}
}
//-----------------------------------------------------------------------------
template <class Kernel>
void PolyMeshT<Kernel>::
calc_vertex_normal_loop(VertexHandle _vh, Normal& _n) const
{
static const LoopSchemeMaskDouble& loop_scheme_mask__ =
LoopSchemeMaskDoubleSingleton::Instance();
Normal t_v(0.0,0.0,0.0), t_w(0.0,0.0,0.0);
unsigned int vh_val = this->valence(_vh);
unsigned int i = 0;
for (ConstVertexOHalfedgeIter cvoh_it = this->cvoh_iter(_vh); cvoh_it.is_valid(); ++cvoh_it, ++i)
{
VertexHandle r1_v( this->to_vertex_handle(*cvoh_it) );
t_v += (typename vector_traits<Point>::value_type)(loop_scheme_mask__.tang0_weight(vh_val, i))*this->point(r1_v);
t_w += (typename vector_traits<Point>::value_type)(loop_scheme_mask__.tang1_weight(vh_val, i))*this->point(r1_v);
}
_n = cross(t_w, t_v);//hack: should be cross(t_v, t_w), but then the normals are reversed?
}
//-----------------------------------------------------------------------------
template <class Kernel>
void
PolyMeshT<Kernel>::
update_vertex_normals()
{
VertexIter v_it(Kernel::vertices_begin()), v_end(Kernel::vertices_end());
for (; v_it!=v_end; ++v_it)
this->set_normal(*v_it, calc_vertex_normal(*v_it));
}
//=============================================================================
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,638 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS PolyMeshT
//
//=============================================================================
#ifndef OPENMESH_POLYMESHT_HH
#define OPENMESH_POLYMESHT_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Geometry/MathDefs.hh>
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
#include <OpenMesh/Core/Mesh/FinalMeshItemsT.hh>
#include <vector>
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== CLASS DEFINITION =========================================================
/** \class PolyMeshT PolyMeshT.hh <OpenMesh/Mesh/PolyMeshT.hh>
Base type for a polygonal mesh.
This is the base class for a polygonal mesh. It is parameterized
by a mesh kernel that is given as a template argument. This class
inherits all methods from its mesh kernel.
\param Kernel: template argument for the mesh kernel
\note You should use the predefined mesh-kernel combinations in
\ref mesh_types_group
\see \ref mesh_type
*/
template <class Kernel>
class PolyMeshT : public Kernel
{
public:
/// Self type. Used to specify iterators/circulators.
typedef PolyMeshT<Kernel> This;
//--- item types ---
//@{
/// Determine whether this is a PolyMeshT or TriMeshT ( This function does not check the per face vertex count! It only checks if the datatype is PolyMeshT or TriMeshT )
enum { IsPolyMesh = 1 };
enum { IsTriMesh = 0 };
static bool is_polymesh() { return true; }
static bool is_trimesh() { return false; }
//@}
/// \name Mesh Items
//@{
/// Scalar type
typedef typename Kernel::Scalar Scalar;
/// Coordinate type
typedef typename Kernel::Point Point;
/// Normal type
typedef typename Kernel::Normal Normal;
/// Color type
typedef typename Kernel::Color Color;
/// TexCoord1D type
typedef typename Kernel::TexCoord1D TexCoord1D;
/// TexCoord2D type
typedef typename Kernel::TexCoord2D TexCoord2D;
/// TexCoord3D type
typedef typename Kernel::TexCoord3D TexCoord3D;
/// Vertex type
typedef typename Kernel::Vertex Vertex;
/// Halfedge type
typedef typename Kernel::Halfedge Halfedge;
/// Edge type
typedef typename Kernel::Edge Edge;
/// Face type
typedef typename Kernel::Face Face;
//@}
//--- handle types ---
/// Handle for referencing the corresponding item
typedef typename Kernel::VertexHandle VertexHandle;
typedef typename Kernel::HalfedgeHandle HalfedgeHandle;
typedef typename Kernel::EdgeHandle EdgeHandle;
typedef typename Kernel::FaceHandle FaceHandle;
typedef typename Kernel::VertexIter VertexIter;
typedef typename Kernel::HalfedgeIter HalfedgeIter;
typedef typename Kernel::EdgeIter EdgeIter;
typedef typename Kernel::FaceIter FaceIter;
typedef typename Kernel::ConstVertexIter ConstVertexIter;
typedef typename Kernel::ConstHalfedgeIter ConstHalfedgeIter;
typedef typename Kernel::ConstEdgeIter ConstEdgeIter;
typedef typename Kernel::ConstFaceIter ConstFaceIter;
//@}
//--- circulators ---
/** \name Mesh Circulators
Refer to OpenMesh::Mesh::Iterators or \ref mesh_iterators
for documentation.
*/
//@{
/// Circulator
typedef typename Kernel::VertexVertexIter VertexVertexIter;
typedef typename Kernel::VertexOHalfedgeIter VertexOHalfedgeIter;
typedef typename Kernel::VertexIHalfedgeIter VertexIHalfedgeIter;
typedef typename Kernel::VertexEdgeIter VertexEdgeIter;
typedef typename Kernel::VertexFaceIter VertexFaceIter;
typedef typename Kernel::FaceVertexIter FaceVertexIter;
typedef typename Kernel::FaceHalfedgeIter FaceHalfedgeIter;
typedef typename Kernel::FaceEdgeIter FaceEdgeIter;
typedef typename Kernel::FaceFaceIter FaceFaceIter;
typedef typename Kernel::ConstVertexVertexIter ConstVertexVertexIter;
typedef typename Kernel::ConstVertexOHalfedgeIter ConstVertexOHalfedgeIter;
typedef typename Kernel::ConstVertexIHalfedgeIter ConstVertexIHalfedgeIter;
typedef typename Kernel::ConstVertexEdgeIter ConstVertexEdgeIter;
typedef typename Kernel::ConstVertexFaceIter ConstVertexFaceIter;
typedef typename Kernel::ConstFaceVertexIter ConstFaceVertexIter;
typedef typename Kernel::ConstFaceHalfedgeIter ConstFaceHalfedgeIter;
typedef typename Kernel::ConstFaceEdgeIter ConstFaceEdgeIter;
typedef typename Kernel::ConstFaceFaceIter ConstFaceFaceIter;
//@}
// --- constructor/destructor
PolyMeshT() {}
template<typename T>
explicit PolyMeshT(const T& t) : Kernel(t) {}
virtual ~PolyMeshT() {}
/** Uses default copy and assignment operator.
Use them to assign two meshes of \b equal type.
If the mesh types vary, use PolyMeshT::assign() instead. */
// --- creation ---
/**
* \brief Adds a new default-initialized vertex.
*
* \sa new_vertex(const Point&), new_vertex_dirty()
*/
inline VertexHandle new_vertex()
{ return Kernel::new_vertex(); }
/**
* \brief Adds a new vertex initialized to a custom position.
*
* \sa new_vertex(), new_vertex_dirty()
*/
inline VertexHandle new_vertex(const Point& _p)
{
VertexHandle vh(Kernel::new_vertex());
this->set_point(vh, _p);
return vh;
}
/**
* Same as new_vertex(const Point&) but never shrinks, only enlarges the
* vertex property vectors.
*
* If you are rebuilding a mesh that you erased with ArrayKernel::clean() or
* ArrayKernel::clean_keep_reservation() using this method instead of
* new_vertex(const Point &) saves reallocation and reinitialization of
* property memory.
*
* \sa new_vertex(const Point &)
*/
inline VertexHandle new_vertex_dirty(const Point& _p)
{
VertexHandle vh(Kernel::new_vertex_dirty());
this->set_point(vh, _p);
return vh;
}
/// Alias for new_vertex(const Point&).
inline VertexHandle add_vertex(const Point& _p)
{ return new_vertex(_p); }
/// Alias for new_vertex_dirty().
inline VertexHandle add_vertex_dirty(const Point& _p)
{ return new_vertex_dirty(_p); }
// --- normal vectors ---
/** \name Normal vector computation
*/
//@{
/** \brief Compute normals for all primitives
*
* Calls update_face_normals() , update_halfedge_normals() and update_vertex_normals() if
* the normals (i.e. the properties) exist.
*
* \note Face normals are required to compute vertex and halfedge normals!
*/
void update_normals();
/// Update normal for face _fh
void update_normal(FaceHandle _fh)
{ this->set_normal(_fh, calc_face_normal(_fh)); }
/** \brief Update normal vectors for all faces.
*
* \attention Needs the Attributes::Normal attribute for faces.
* Call request_face_normals() before using it!
*/
void update_face_normals();
/** Calculate normal vector for face _fh. */
virtual Normal calc_face_normal(FaceHandle _fh) const;
/** Calculate normal vector for face (_p0, _p1, _p2). */
Normal calc_face_normal(const Point& _p0, const Point& _p1,
const Point& _p2) const;
/// calculates the average of the vertices defining _fh
void calc_face_centroid(FaceHandle _fh, Point& _pt) const {
_pt = calc_face_centroid(_fh);
}
/// Computes and returns the average of the vertices defining _gh
Point calc_face_centroid(FaceHandle _fh) const;
/// Update normal for halfedge _heh
void update_normal(HalfedgeHandle _heh, const double _feature_angle = 0.8)
{ this->set_normal(_heh, calc_halfedge_normal(_heh,_feature_angle)); }
/** \brief Update normal vectors for all halfedges.
*
* Uses the existing face normals to compute halfedge normals
*
* \note Face normals have to be computed first!
*
* \attention Needs the Attributes::Normal attribute for faces and halfedges.
* Call request_face_normals() and request_halfedge_normals() before using it!
*/
void update_halfedge_normals(const double _feature_angle = 0.8);
/** \brief Calculate halfedge normal for one specific halfedge
*
* Calculate normal vector for halfedge _heh.
*
* \note Face normals have to be computed first!
*
* \attention Needs the Attributes::Normal attribute for faces and vertices.
* Call request_face_normals() and request_halfedge_normals() before using it!
*
* @param _heh Handle of the halfedge
* @param _feature_angle If the dihedral angle across this edge is greater than this value, the edge is considered as a feature edge (angle in radians)
*/
virtual Normal calc_halfedge_normal(HalfedgeHandle _heh, const double _feature_angle = 0.8) const;
/** identifies feature edges w.r.t. the minimal dihedral angle for feature edges (in radians) */
/** and the status feature tag */
bool is_estimated_feature_edge(HalfedgeHandle _heh, const double _feature_angle) const;
/// Update normal for vertex _vh
void update_normal(VertexHandle _vh)
{ this->set_normal(_vh, calc_vertex_normal(_vh)); }
/** \brief Update normal vectors for all vertices.
*
* Uses existing face normals to calculate new vertex normals.
*
* \note Face normals have to be computed first!
*
* \attention Needs the Attributes::Normal attribute for faces and vertices.
* Call request_face_normals() and request_vertex_normals() before using it!
*/
void update_vertex_normals();
/** \brief Calculate vertex normal for one specific vertex
*
* Calculate normal vector for vertex _vh by averaging normals
* of adjacent faces.
*
* \note Face normals have to be computed first!
*
* \attention Needs the Attributes::Normal attribute for faces and vertices.
* Call request_face_normals() and request_vertex_normals() before using it!
*
* @param _vh Handle of the vertex
*/
Normal calc_vertex_normal(VertexHandle _vh) const;
/** Different methods for calculation of the normal at _vh:
- ..._fast - the default one - the same as calc vertex_normal()
- needs the Attributes::Normal attribute for faces
- ..._correct - works properly for non-triangular meshes
- does not need any attributes
- ..._loop - calculates loop surface normals
- does not need any attributes */
void calc_vertex_normal_fast(VertexHandle _vh, Normal& _n) const;
void calc_vertex_normal_correct(VertexHandle _vh, Normal& _n) const;
void calc_vertex_normal_loop(VertexHandle _vh, Normal& _n) const;
//@}
// --- Geometry API - still in development ---
/** Calculates the edge vector as the vector defined by
the halfedge with id #0 (see below) */
void calc_edge_vector(EdgeHandle _eh, Normal& _edge_vec) const
{
_edge_vec = calc_edge_vector(_eh);
}
/** Calculates the edge vector as the vector defined by
the halfedge with id #0 (see below) */
Normal calc_edge_vector(EdgeHandle _eh) const
{
return calc_edge_vector(this->halfedge_handle(_eh,0));
}
/** Calculates the edge vector as the difference of the
the points defined by to_vertex_handle() and from_vertex_handle() */
void calc_edge_vector(HalfedgeHandle _heh, Normal& _edge_vec) const
{
_edge_vec = calc_edge_vector(_heh);
}
/** Calculates the edge vector as the difference of the
the points defined by to_vertex_handle() and from_vertex_handle() */
Normal calc_edge_vector(HalfedgeHandle _heh) const
{
return this->point(this->to_vertex_handle(_heh)) -
this->point(this->from_vertex_handle(_heh));
}
// Calculates the length of the edge _eh
Scalar calc_edge_length(EdgeHandle _eh) const
{ return calc_edge_length(this->halfedge_handle(_eh,0)); }
/** Calculates the length of the edge _heh
*/
Scalar calc_edge_length(HalfedgeHandle _heh) const
{ return (Scalar)sqrt(calc_edge_sqr_length(_heh)); }
Scalar calc_edge_sqr_length(EdgeHandle _eh) const
{ return calc_edge_sqr_length(this->halfedge_handle(_eh,0)); }
Scalar calc_edge_sqr_length(HalfedgeHandle _heh) const
{
Normal edge_vec;
calc_edge_vector(_heh, edge_vec);
return sqrnorm(edge_vec);
}
/** Calculates the midpoint of the halfedge _heh, defined by the positions of
the two incident vertices */
Point calc_edge_midpoint(HalfedgeHandle _heh) const
{
VertexHandle vh0 = this->from_vertex_handle(_heh);
VertexHandle vh1 = this->to_vertex_handle(_heh);
return 0.5 * (this->point(vh0) + this->point(vh1));
}
/** Calculates the midpoint of the edge _eh, defined by the positions of the
two incident vertices */
Point calc_edge_midpoint(EdgeHandle _eh) const
{
return calc_edge_midpoint(this->halfedge_handle(_eh, 0));
}
/** defines a consistent representation of a sector geometry:
the halfedge _in_heh defines the sector orientation
the vertex pointed by _in_heh defines the sector center
_vec0 and _vec1 are resp. the first and the second vectors defining the sector */
void calc_sector_vectors(HalfedgeHandle _in_heh, Normal& _vec0, Normal& _vec1) const
{
calc_edge_vector(this->next_halfedge_handle(_in_heh), _vec0);//p2 - p1
calc_edge_vector(this->opposite_halfedge_handle(_in_heh), _vec1);//p0 - p1
}
/** calculates the sector angle.\n
* The vertex pointed by _in_heh defines the sector center
* The angle will be calculated between the given halfedge and the next halfedge.\n
* Seen from the center vertex this will be the next halfedge in clockwise direction.\n
NOTE: only boundary concave sectors are treated correctly */
Scalar calc_sector_angle(HalfedgeHandle _in_heh) const
{
Normal v0, v1;
calc_sector_vectors(_in_heh, v0, v1);
Scalar denom = norm(v0)*norm(v1);
if ( denom == Scalar(0))
{
return 0;
}
Scalar cos_a = dot(v0 , v1) / denom;
if (this->is_boundary(_in_heh))
{//determine if the boundary sector is concave or convex
FaceHandle fh(this->face_handle(this->opposite_halfedge_handle(_in_heh)));
Normal f_n(calc_face_normal(fh));//this normal is (for convex fh) OK
Scalar sign_a = dot(cross(v0, v1), f_n);
return angle(cos_a, sign_a);
}
else
{
return acos(sane_aarg(cos_a));
}
}
// calculate the cos and the sin of angle <(_in_heh,next_halfedge(_in_heh))
/*
void calc_sector_angle_cos_sin(HalfedgeHandle _in_heh, Scalar& _cos_a, Scalar& _sin_a) const
{
Normal in_vec, out_vec;
calc_edge_vector(_in_heh, in_vec);
calc_edge_vector(next_halfedge_handle(_in_heh), out_vec);
Scalar denom = norm(in_vec)*norm(out_vec);
if (is_zero(denom))
{
_cos_a = 1;
_sin_a = 0;
}
else
{
_cos_a = dot(in_vec, out_vec)/denom;
_sin_a = norm(cross(in_vec, out_vec))/denom;
}
}
*/
/** calculates the normal (non-normalized) of the face sector defined by
the angle <(_in_heh,next_halfedge(_in_heh)) */
void calc_sector_normal(HalfedgeHandle _in_heh, Normal& _sector_normal) const
{
Normal vec0, vec1;
calc_sector_vectors(_in_heh, vec0, vec1);
_sector_normal = cross(vec0, vec1);//(p2-p1)^(p0-p1)
}
/** calculates the area of the face sector defined by
the angle <(_in_heh,next_halfedge(_in_heh))
NOTE: special cases (e.g. concave sectors) are not handled correctly */
Scalar calc_sector_area(HalfedgeHandle _in_heh) const
{
Normal sector_normal;
calc_sector_normal(_in_heh, sector_normal);
return norm(sector_normal)/2;
}
/** calculates the dihedral angle on the halfedge _heh
\attention Needs the Attributes::Normal attribute for faces */
Scalar calc_dihedral_angle_fast(HalfedgeHandle _heh) const
{
// Make sure that we have face normals on the mesh
assert(Kernel::has_face_normals());
if (this->is_boundary(this->edge_handle(_heh)))
{//the dihedral angle at a boundary edge is 0
return 0;
}
const Normal& n0 = this->normal(this->face_handle(_heh));
const Normal& n1 = this->normal(this->face_handle(this->opposite_halfedge_handle(_heh)));
Normal he;
calc_edge_vector(_heh, he);
Scalar da_cos = dot(n0, n1);
//should be normalized, but we need only the sign
Scalar da_sin_sign = dot(cross(n0, n1), he);
return angle(da_cos, da_sin_sign);
}
/** calculates the dihedral angle on the edge _eh
\attention Needs the Attributes::Normal attribute for faces */
Scalar calc_dihedral_angle_fast(EdgeHandle _eh) const
{ return calc_dihedral_angle_fast(this->halfedge_handle(_eh,0)); }
// calculates the dihedral angle on the halfedge _heh
Scalar calc_dihedral_angle(HalfedgeHandle _heh) const
{
if (this->is_boundary(this->edge_handle(_heh)))
{//the dihedral angle at a boundary edge is 0
return 0;
}
Normal n0, n1, he;
calc_sector_normal(_heh, n0);
calc_sector_normal(this->opposite_halfedge_handle(_heh), n1);
calc_edge_vector(_heh, he);
Scalar denom = norm(n0)*norm(n1);
if (denom == Scalar(0))
{
return 0;
}
Scalar da_cos = dot(n0, n1)/denom;
//should be normalized, but we need only the sign
Scalar da_sin_sign = dot(cross(n0, n1), he);
return angle(da_cos, da_sin_sign);
}
// calculates the dihedral angle on the edge _eh
Scalar calc_dihedral_angle(EdgeHandle _eh) const
{ return calc_dihedral_angle(this->halfedge_handle(_eh,0)); }
/** tags an edge as a feature if its dihedral angle is larger than _angle_tresh
returns the number of the found feature edges, requires edge_status property*/
unsigned int find_feature_edges(Scalar _angle_tresh = OpenMesh::deg_to_rad(44.0));
// --- misc ---
/// Face split (= 1-to-n split)
inline void split(FaceHandle _fh, const Point& _p)
{ Kernel::split(_fh, add_vertex(_p)); }
inline void split(FaceHandle _fh, VertexHandle _vh)
{ Kernel::split(_fh, _vh); }
inline void split(EdgeHandle _eh, const Point& _p)
{ Kernel::split_edge(_eh, add_vertex(_p)); }
inline void split(EdgeHandle _eh, VertexHandle _vh)
{ Kernel::split_edge(_eh, _vh); }
private:
struct PointIs3DTag {};
struct PointIsNot3DTag {};
Normal calc_face_normal_impl(FaceHandle, PointIs3DTag) const;
Normal calc_face_normal_impl(FaceHandle, PointIsNot3DTag) const;
Normal calc_face_normal_impl(const Point&, const Point&, const Point&, PointIs3DTag) const;
Normal calc_face_normal_impl(const Point&, const Point&, const Point&, PointIsNot3DTag) const;
};
/**
* @brief Cast a mesh with different but identical traits into each other.
*
* Example:
* @code{.cpp}
* struct TriTraits1 : public OpenMesh::DefaultTraits {
* typedef Vec3d Point;
* };
* struct TriTraits2 : public OpenMesh::DefaultTraits {
* typedef Vec3d Point;
* };
* struct TriTraits3 : public OpenMesh::DefaultTraits {
* typedef Vec3f Point;
* };
*
* TriMesh_ArrayKernelT<TriTraits1> a;
* TriMesh_ArrayKernelT<TriTraits2> &b = mesh_cast<TriMesh_ArrayKernelT<TriTraits2>&>(a); // OK
* TriMesh_ArrayKernelT<TriTraits3> &c = mesh_cast<TriMesh_ArrayKernelT<TriTraits3>&>(a); // ERROR
* @endcode
*
* @see MeshCast
*
* @param rhs
* @return
*/
template<typename LHS, typename KERNEL>
LHS mesh_cast(PolyMeshT<KERNEL> &rhs) {
return MeshCast<LHS, PolyMeshT<KERNEL>&>::cast(rhs);
}
template<typename LHS, typename KERNEL>
LHS mesh_cast(PolyMeshT<KERNEL> *rhs) {
return MeshCast<LHS, PolyMeshT<KERNEL>*>::cast(rhs);
}
template<typename LHS, typename KERNEL>
const LHS mesh_cast(const PolyMeshT<KERNEL> &rhs) {
return MeshCast<LHS, const PolyMeshT<KERNEL>&>::cast(rhs);
}
template<typename LHS, typename KERNEL>
const LHS mesh_cast(const PolyMeshT<KERNEL> *rhs) {
return MeshCast<LHS, const PolyMeshT<KERNEL>*>::cast(rhs);
}
//=============================================================================
} // namespace OpenMesh
//=============================================================================
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_POLYMESH_C)
# define OPENMESH_POLYMESH_TEMPLATES
# include "PolyMeshT.cc"
#endif
//=============================================================================
#endif // OPENMESH_POLYMESHT_HH defined
//=============================================================================

View File

@ -0,0 +1,118 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS PolyMesh_ArrayKernelT
//
//=============================================================================
#ifndef OPENMESH_POLY_MESH_ARRAY_KERNEL_HH
#define OPENMESH_POLY_MESH_ARRAY_KERNEL_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
#include <OpenMesh/Core/Mesh/Traits.hh>
#include <OpenMesh/Core/Mesh/FinalMeshItemsT.hh>
#include <OpenMesh/Core/Mesh/AttribKernelT.hh>
#include <OpenMesh/Core/Mesh/PolyMeshT.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
template<class Traits>
class TriMesh_ArrayKernelT;
//== CLASS DEFINITION =========================================================
/// Helper class to build a PolyMesh-type
template <class Traits>
struct PolyMesh_ArrayKernel_GeneratorT
{
typedef FinalMeshItemsT<Traits, false> MeshItems;
typedef AttribKernelT<MeshItems, PolyConnectivity> AttribKernel;
typedef PolyMeshT<AttribKernel> Mesh;
};
/** \class PolyMesh_ArrayKernelT PolyMesh_ArrayKernelT.hh <OpenMesh/Mesh/Types/PolyMesh_ArrayKernelT.hh>
\ingroup mesh_types_group
Polygonal mesh based on the ArrayKernel.
\see OpenMesh::PolyMeshT
\see OpenMesh::ArrayKernel
*/
template <class Traits = DefaultTraits>
class PolyMesh_ArrayKernelT
: public PolyMesh_ArrayKernel_GeneratorT<Traits>::Mesh
{
public:
PolyMesh_ArrayKernelT() {}
template<class OtherTraits>
PolyMesh_ArrayKernelT( const TriMesh_ArrayKernelT<OtherTraits> & t)
{
//assign the connectivity and standard properties
this->assign(t, true);
}
};
//=============================================================================
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_POLY_MESH_ARRAY_KERNEL_HH
//=============================================================================

View File

@ -0,0 +1,183 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS Status
//
//=============================================================================
#ifndef OPENMESH_ATTRIBUTE_STATUS_HH
#define OPENMESH_ATTRIBUTE_STATUS_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace Attributes {
//== CLASS DEFINITION ========================================================
/** Status bits used by the Status class.
* \see OpenMesh::Attributes::StatusInfo
*/
enum StatusBits {
DELETED = 1, ///< Item has been deleted
LOCKED = 2, ///< Item is locked.
SELECTED = 4, ///< Item is selected.
HIDDEN = 8, ///< Item is hidden.
FEATURE = 16, ///< Item is a feature or belongs to a feature.
TAGGED = 32, ///< Item is tagged.
TAGGED2 = 64, ///< Alternate bit for tagging an item.
FIXEDNONMANIFOLD = 128, ///< Item was non-two-manifold and had to be fixed
UNUSED = 256 ///< Unused
};
/** \class StatusInfo Status.hh <OpenMesh/Attributes/Status.hh>
*
* Add status information to a base class.
*
* \see StatusBits
*/
class StatusInfo
{
public:
typedef unsigned int value_type;
StatusInfo() : status_(0) {}
/// is deleted ?
bool deleted() const { return is_bit_set(DELETED); }
/// set deleted
void set_deleted(bool _b) { change_bit(DELETED, _b); }
/// is locked ?
bool locked() const { return is_bit_set(LOCKED); }
/// set locked
void set_locked(bool _b) { change_bit(LOCKED, _b); }
/// is selected ?
bool selected() const { return is_bit_set(SELECTED); }
/// set selected
void set_selected(bool _b) { change_bit(SELECTED, _b); }
/// is hidden ?
bool hidden() const { return is_bit_set(HIDDEN); }
/// set hidden
void set_hidden(bool _b) { change_bit(HIDDEN, _b); }
/// is feature ?
bool feature() const { return is_bit_set(FEATURE); }
/// set feature
void set_feature(bool _b) { change_bit(FEATURE, _b); }
/// is tagged ?
bool tagged() const { return is_bit_set(TAGGED); }
/// set tagged
void set_tagged(bool _b) { change_bit(TAGGED, _b); }
/// is tagged2 ? This is just one more tag info.
bool tagged2() const { return is_bit_set(TAGGED2); }
/// set tagged
void set_tagged2(bool _b) { change_bit(TAGGED2, _b); }
/// is fixed non-manifold ?
bool fixed_nonmanifold() const { return is_bit_set(FIXEDNONMANIFOLD); }
/// set fixed non-manifold
void set_fixed_nonmanifold(bool _b) { change_bit(FIXEDNONMANIFOLD, _b); }
/// return whole status
unsigned int bits() const { return status_; }
/// set whole status at once
void set_bits(unsigned int _bits) { status_ = _bits; }
/// is a certain bit set ?
bool is_bit_set(unsigned int _s) const { return (status_ & _s) > 0; }
/// set a certain bit
void set_bit(unsigned int _s) { status_ |= _s; }
/// unset a certain bit
void unset_bit(unsigned int _s) { status_ &= ~_s; }
/// set or unset a certain bit
void change_bit(unsigned int _s, bool _b) {
if (_b) status_ |= _s; else status_ &= ~_s; }
private:
value_type status_;
};
//=============================================================================
} // namespace Attributes
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_ATTRIBUTE_STATUS_HH defined
//=============================================================================

View File

@ -0,0 +1,245 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
/** \file Core/Mesh/Traits.hh
This file defines the default traits and some convenience macros.
*/
//=============================================================================
//
// CLASS Traits
//
//=============================================================================
#ifndef OPENMESH_TRAITS_HH
#define OPENMESH_TRAITS_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Geometry/VectorT.hh>
#include <OpenMesh/Core/Mesh/Attributes.hh>
#include <OpenMesh/Core/Mesh/Handles.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== CLASS DEFINITION =========================================================
/// Macro for defining the vertex attributes. See \ref mesh_type.
#define VertexAttributes(_i) enum { VertexAttributes = _i }
/// Macro for defining the halfedge attributes. See \ref mesh_type.
#define HalfedgeAttributes(_i) enum { HalfedgeAttributes = _i }
/// Macro for defining the edge attributes. See \ref mesh_type.
#define EdgeAttributes(_i) enum { EdgeAttributes = _i }
/// Macro for defining the face attributes. See \ref mesh_type.
#define FaceAttributes(_i) enum { FaceAttributes = _i }
/// Macro for defining the vertex traits. See \ref mesh_type.
#define VertexTraits \
template <class Base, class Refs> struct VertexT : public Base
/// Macro for defining the halfedge traits. See \ref mesh_type.
#define HalfedgeTraits \
template <class Base, class Refs> struct HalfedgeT : public Base
/// Macro for defining the edge traits. See \ref mesh_type.
#define EdgeTraits \
template <class Base, class Refs> struct EdgeT : public Base
/// Macro for defining the face traits. See \ref mesh_type.
#define FaceTraits \
template <class Base, class Refs> struct FaceT : public Base
//== CLASS DEFINITION =========================================================
/** \class DefaultTraits Traits.hh <OpenMesh/Mesh/Traits.hh>
Base class for all traits. All user traits should be derived from
this class. You may enrich all basic items by additional
properties or define one or more of the types \c Point, \c Normal,
\c TexCoord, or \c Color.
\see The Mesh docu section on \ref mesh_type.
\see Traits.hh for a list of macros for traits classes.
*/
struct DefaultTraits
{
/// The default coordinate type is OpenMesh::Vec3f.
typedef Vec3f Point;
/// The default normal type is OpenMesh::Vec3f.
typedef Vec3f Normal;
/// The default 1D texture coordinate type is float.
typedef float TexCoord1D;
/// The default 2D texture coordinate type is OpenMesh::Vec2f.
typedef Vec2f TexCoord2D;
/// The default 3D texture coordinate type is OpenMesh::Vec3f.
typedef Vec3f TexCoord3D;
/// The default texture index type
typedef int TextureIndex;
/// The default color type is OpenMesh::Vec3uc.
typedef Vec3uc Color;
#ifndef DOXY_IGNORE_THIS
VertexTraits {};
HalfedgeTraits {};
EdgeTraits {};
FaceTraits {};
#endif
VertexAttributes(0);
HalfedgeAttributes(Attributes::PrevHalfedge);
EdgeAttributes(0);
FaceAttributes(0);
};
//== CLASS DEFINITION =========================================================
/** Helper class to merge two mesh traits.
* \internal
*
* With the help of this class it's possible to merge two mesh traits.
* Whereby \c _Traits1 overrides equally named symbols of \c _Traits2.
*
* For your convenience use the provided defines \c OM_Merge_Traits
* and \c OM_Merge_Traits_In_Template instead.
*
* \see OM_Merge_Traits, OM_Merge_Traits_In_Template
*/
template <class _Traits1, class _Traits2> struct MergeTraits
{
#ifndef DOXY_IGNORE_THIS
struct Result
{
// Mipspro needs this (strange) typedef
typedef _Traits1 T1;
typedef _Traits2 T2;
VertexAttributes ( T1::VertexAttributes | T2::VertexAttributes );
HalfedgeAttributes ( T1::HalfedgeAttributes | T2::HalfedgeAttributes );
EdgeAttributes ( T1::EdgeAttributes | T2::EdgeAttributes );
FaceAttributes ( T1::FaceAttributes | T2::FaceAttributes );
typedef typename T1::Point Point;
typedef typename T1::Normal Normal;
typedef typename T1::Color Color;
typedef typename T1::TexCoord TexCoord;
template <class Base, class Refs> class VertexT :
public T1::template VertexT<
typename T2::template VertexT<Base, Refs>, Refs>
{};
template <class Base, class Refs> class HalfedgeT :
public T1::template HalfedgeT<
typename T2::template HalfedgeT<Base, Refs>, Refs>
{};
template <class Base, class Refs> class EdgeT :
public T1::template EdgeT<
typename T2::template EdgeT<Base, Refs>, Refs>
{};
template <class Base, class Refs> class FaceT :
public T1::template FaceT<
typename T2::template FaceT<Base, Refs>, Refs>
{};
};
#endif
};
/**
Macro for merging two traits classes _S1 and _S2 into one traits class _D.
Note that in case of ambiguities class _S1 overrides _S2, especially
the point/normal/color/texcoord type to be used is taken from _S1::Point /
_S1::Normal / _S1::Color / _S1::TexCoord
*/
#define OM_Merge_Traits(_S1, _S2, _D) \
typedef OpenMesh::MergeTraits<_S1, _S2>::Result _D;
/**
Macro for merging two traits classes _S1 and _S2 into one traits class _D.
Same as OM_Merge_Traits, but this can be used inside template classes.
*/
#define OM_Merge_Traits_In_Template(_S1, _S2, _D) \
typedef typename OpenMesh::MergeTraits<_S1, _S2>::Result _D;
//=============================================================================
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_TRAITS_HH defined
//=============================================================================

View File

@ -0,0 +1,521 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
// CLASS TriMeshT - IMPLEMENTATION
#include <OpenMesh/Core/Mesh/TriConnectivity.hh>
namespace OpenMesh
{
TriConnectivity::FaceHandle
TriConnectivity::add_face(const VertexHandle* _vertex_handles, size_t _vhs_size)
{
// need at least 3 vertices
if (_vhs_size < 3) return InvalidFaceHandle;
/// face is triangle -> ok
if (_vhs_size == 3)
return PolyConnectivity::add_face(_vertex_handles, _vhs_size);
/// face is not a triangle -> triangulate
else
{
//omlog() << "triangulating " << _vhs_size << "_gon\n";
VertexHandle vhandles[3];
vhandles[0] = _vertex_handles[0];
FaceHandle fh;
unsigned int i(1);
--_vhs_size;
while (i < _vhs_size)
{
vhandles[1] = _vertex_handles[i];
vhandles[2] = _vertex_handles[++i];
fh = PolyConnectivity::add_face(vhandles, 3);
}
return fh;
}
}
//-----------------------------------------------------------------------------
FaceHandle TriConnectivity::add_face(const std::vector<VertexHandle>& _vhandles)
{
return add_face(&_vhandles.front(), _vhandles.size());
}
//-----------------------------------------------------------------------------
FaceHandle TriConnectivity::add_face(VertexHandle _vh0, VertexHandle _vh1, VertexHandle _vh2)
{
VertexHandle vhs[3] = { _vh0, _vh1, _vh2 };
return PolyConnectivity::add_face(vhs, 3);
}
//-----------------------------------------------------------------------------
bool TriConnectivity::is_collapse_ok(HalfedgeHandle v0v1)
{
// is the edge already deleted?
if ( status(edge_handle(v0v1)).deleted() )
return false;
HalfedgeHandle v1v0(opposite_halfedge_handle(v0v1));
VertexHandle v0(to_vertex_handle(v1v0));
VertexHandle v1(to_vertex_handle(v0v1));
// are vertices already deleted ?
if (status(v0).deleted() || status(v1).deleted())
return false;
VertexHandle vl, vr;
HalfedgeHandle h1, h2;
// the edges v1-vl and vl-v0 must not be both boundary edges
if (!is_boundary(v0v1))
{
h1 = next_halfedge_handle(v0v1);
h2 = next_halfedge_handle(h1);
vl = to_vertex_handle(h1);
if (is_boundary(opposite_halfedge_handle(h1)) &&
is_boundary(opposite_halfedge_handle(h2)))
{
return false;
}
}
// the edges v0-vr and vr-v1 must not be both boundary edges
if (!is_boundary(v1v0))
{
h1 = next_halfedge_handle(v1v0);
h2 = next_halfedge_handle(h1);
vr = to_vertex_handle(h1);
if (is_boundary(opposite_halfedge_handle(h1)) &&
is_boundary(opposite_halfedge_handle(h2)))
return false;
}
// if vl and vr are equal or both invalid -> fail
if (vl == vr) return false;
VertexVertexIter vv_it;
// test intersection of the one-rings of v0 and v1
for (vv_it = vv_iter(v0); vv_it.is_valid(); ++vv_it)
status(*vv_it).set_tagged(false);
for (vv_it = vv_iter(v1); vv_it.is_valid(); ++vv_it)
status(*vv_it).set_tagged(true);
for (vv_it = vv_iter(v0); vv_it.is_valid(); ++vv_it)
if (status(*vv_it).tagged() && *vv_it != vl && *vv_it != vr)
return false;
// edge between two boundary vertices should be a boundary edge
if ( is_boundary(v0) && is_boundary(v1) &&
!is_boundary(v0v1) && !is_boundary(v1v0))
return false;
// passed all tests
return true;
}
//-----------------------------------------------------------------------------
TriConnectivity::HalfedgeHandle
TriConnectivity::vertex_split(VertexHandle v0, VertexHandle v1,
VertexHandle vl, VertexHandle vr)
{
HalfedgeHandle v1vl, vlv1, vrv1, v0v1;
// build loop from halfedge v1->vl
if (vl.is_valid())
{
v1vl = find_halfedge(v1, vl);
assert(v1vl.is_valid());
vlv1 = insert_loop(v1vl);
}
// build loop from halfedge vr->v1
if (vr.is_valid())
{
vrv1 = find_halfedge(vr, v1);
assert(vrv1.is_valid());
insert_loop(vrv1);
}
// handle boundary cases
if (!vl.is_valid())
vlv1 = prev_halfedge_handle(halfedge_handle(v1));
if (!vr.is_valid())
vrv1 = prev_halfedge_handle(halfedge_handle(v1));
// split vertex v1 into edge v0v1
v0v1 = insert_edge(v0, vlv1, vrv1);
return v0v1;
}
//-----------------------------------------------------------------------------
TriConnectivity::HalfedgeHandle
TriConnectivity::insert_loop(HalfedgeHandle _hh)
{
HalfedgeHandle h0(_hh);
HalfedgeHandle o0(opposite_halfedge_handle(h0));
VertexHandle v0(to_vertex_handle(o0));
VertexHandle v1(to_vertex_handle(h0));
HalfedgeHandle h1 = new_edge(v1, v0);
HalfedgeHandle o1 = opposite_halfedge_handle(h1);
FaceHandle f0 = face_handle(h0);
FaceHandle f1 = new_face();
// halfedge -> halfedge
set_next_halfedge_handle(prev_halfedge_handle(h0), o1);
set_next_halfedge_handle(o1, next_halfedge_handle(h0));
set_next_halfedge_handle(h1, h0);
set_next_halfedge_handle(h0, h1);
// halfedge -> face
set_face_handle(o1, f0);
set_face_handle(h0, f1);
set_face_handle(h1, f1);
// face -> halfedge
set_halfedge_handle(f1, h0);
if (f0.is_valid())
set_halfedge_handle(f0, o1);
// vertex -> halfedge
adjust_outgoing_halfedge(v0);
adjust_outgoing_halfedge(v1);
return h1;
}
//-----------------------------------------------------------------------------
TriConnectivity::HalfedgeHandle
TriConnectivity::insert_edge(VertexHandle _vh, HalfedgeHandle _h0, HalfedgeHandle _h1)
{
assert(_h0.is_valid() && _h1.is_valid());
VertexHandle v0 = _vh;
VertexHandle v1 = to_vertex_handle(_h0);
assert( v1 == to_vertex_handle(_h1));
HalfedgeHandle v0v1 = new_edge(v0, v1);
HalfedgeHandle v1v0 = opposite_halfedge_handle(v0v1);
// vertex -> halfedge
set_halfedge_handle(v0, v0v1);
set_halfedge_handle(v1, v1v0);
// halfedge -> halfedge
set_next_halfedge_handle(v0v1, next_halfedge_handle(_h0));
set_next_halfedge_handle(_h0, v0v1);
set_next_halfedge_handle(v1v0, next_halfedge_handle(_h1));
set_next_halfedge_handle(_h1, v1v0);
// halfedge -> vertex
for (VertexIHalfedgeIter vih_it(vih_iter(v0)); vih_it.is_valid(); ++vih_it)
set_vertex_handle(*vih_it, v0);
// halfedge -> face
set_face_handle(v0v1, face_handle(_h0));
set_face_handle(v1v0, face_handle(_h1));
// face -> halfedge
if (face_handle(v0v1).is_valid())
set_halfedge_handle(face_handle(v0v1), v0v1);
if (face_handle(v1v0).is_valid())
set_halfedge_handle(face_handle(v1v0), v1v0);
// vertex -> halfedge
adjust_outgoing_halfedge(v0);
adjust_outgoing_halfedge(v1);
return v0v1;
}
//-----------------------------------------------------------------------------
bool TriConnectivity::is_flip_ok(EdgeHandle _eh) const
{
// boundary edges cannot be flipped
if (is_boundary(_eh)) return false;
HalfedgeHandle hh = halfedge_handle(_eh, 0);
HalfedgeHandle oh = halfedge_handle(_eh, 1);
// check if the flipped edge is already present
// in the mesh
VertexHandle ah = to_vertex_handle(next_halfedge_handle(hh));
VertexHandle bh = to_vertex_handle(next_halfedge_handle(oh));
if (ah == bh) // this is generally a bad sign !!!
return false;
for (ConstVertexVertexIter vvi(*this, ah); vvi.is_valid(); ++vvi)
if (*vvi == bh)
return false;
return true;
}
//-----------------------------------------------------------------------------
void TriConnectivity::flip(EdgeHandle _eh)
{
// CAUTION : Flipping a halfedge may result in
// a non-manifold mesh, hence check for yourself
// whether this operation is allowed or not!
assert(is_flip_ok(_eh));//let's make it sure it is actually checked
assert(!is_boundary(_eh));
HalfedgeHandle a0 = halfedge_handle(_eh, 0);
HalfedgeHandle b0 = halfedge_handle(_eh, 1);
HalfedgeHandle a1 = next_halfedge_handle(a0);
HalfedgeHandle a2 = next_halfedge_handle(a1);
HalfedgeHandle b1 = next_halfedge_handle(b0);
HalfedgeHandle b2 = next_halfedge_handle(b1);
VertexHandle va0 = to_vertex_handle(a0);
VertexHandle va1 = to_vertex_handle(a1);
VertexHandle vb0 = to_vertex_handle(b0);
VertexHandle vb1 = to_vertex_handle(b1);
FaceHandle fa = face_handle(a0);
FaceHandle fb = face_handle(b0);
set_vertex_handle(a0, va1);
set_vertex_handle(b0, vb1);
set_next_halfedge_handle(a0, a2);
set_next_halfedge_handle(a2, b1);
set_next_halfedge_handle(b1, a0);
set_next_halfedge_handle(b0, b2);
set_next_halfedge_handle(b2, a1);
set_next_halfedge_handle(a1, b0);
set_face_handle(a1, fb);
set_face_handle(b1, fa);
set_halfedge_handle(fa, a0);
set_halfedge_handle(fb, b0);
if (halfedge_handle(va0) == b0)
set_halfedge_handle(va0, a1);
if (halfedge_handle(vb0) == a0)
set_halfedge_handle(vb0, b1);
}
//-----------------------------------------------------------------------------
void TriConnectivity::split(EdgeHandle _eh, VertexHandle _vh)
{
HalfedgeHandle h0 = halfedge_handle(_eh, 0);
HalfedgeHandle o0 = halfedge_handle(_eh, 1);
VertexHandle v2 = to_vertex_handle(o0);
HalfedgeHandle e1 = new_edge(_vh, v2);
HalfedgeHandle t1 = opposite_halfedge_handle(e1);
FaceHandle f0 = face_handle(h0);
FaceHandle f3 = face_handle(o0);
set_halfedge_handle(_vh, h0);
set_vertex_handle(o0, _vh);
if (!is_boundary(h0))
{
HalfedgeHandle h1 = next_halfedge_handle(h0);
HalfedgeHandle h2 = next_halfedge_handle(h1);
VertexHandle v1 = to_vertex_handle(h1);
HalfedgeHandle e0 = new_edge(_vh, v1);
HalfedgeHandle t0 = opposite_halfedge_handle(e0);
FaceHandle f1 = new_face();
set_halfedge_handle(f0, h0);
set_halfedge_handle(f1, h2);
set_face_handle(h1, f0);
set_face_handle(t0, f0);
set_face_handle(h0, f0);
set_face_handle(h2, f1);
set_face_handle(t1, f1);
set_face_handle(e0, f1);
set_next_halfedge_handle(h0, h1);
set_next_halfedge_handle(h1, t0);
set_next_halfedge_handle(t0, h0);
set_next_halfedge_handle(e0, h2);
set_next_halfedge_handle(h2, t1);
set_next_halfedge_handle(t1, e0);
}
else
{
set_next_halfedge_handle(prev_halfedge_handle(h0), t1);
set_next_halfedge_handle(t1, h0);
// halfedge handle of _vh already is h0
}
if (!is_boundary(o0))
{
HalfedgeHandle o1 = next_halfedge_handle(o0);
HalfedgeHandle o2 = next_halfedge_handle(o1);
VertexHandle v3 = to_vertex_handle(o1);
HalfedgeHandle e2 = new_edge(_vh, v3);
HalfedgeHandle t2 = opposite_halfedge_handle(e2);
FaceHandle f2 = new_face();
set_halfedge_handle(f2, o1);
set_halfedge_handle(f3, o0);
set_face_handle(o1, f2);
set_face_handle(t2, f2);
set_face_handle(e1, f2);
set_face_handle(o2, f3);
set_face_handle(o0, f3);
set_face_handle(e2, f3);
set_next_halfedge_handle(e1, o1);
set_next_halfedge_handle(o1, t2);
set_next_halfedge_handle(t2, e1);
set_next_halfedge_handle(o0, e2);
set_next_halfedge_handle(e2, o2);
set_next_halfedge_handle(o2, o0);
}
else
{
set_next_halfedge_handle(e1, next_halfedge_handle(o0));
set_next_halfedge_handle(o0, e1);
set_halfedge_handle(_vh, e1);
}
if (halfedge_handle(v2) == h0)
set_halfedge_handle(v2, t1);
}
//-----------------------------------------------------------------------------
void TriConnectivity::split_copy(EdgeHandle _eh, VertexHandle _vh)
{
const VertexHandle v0 = to_vertex_handle(halfedge_handle(_eh, 0));
const VertexHandle v1 = to_vertex_handle(halfedge_handle(_eh, 1));
const int nf = n_faces();
// Split the halfedge ( handle will be preserved)
split(_eh, _vh);
// Copy the properties of the original edge to all neighbor edges that
// have been created
for(VEIter ve_it = ve_iter(_vh); ve_it.is_valid(); ++ve_it)
copy_all_properties(_eh, *ve_it, true);
for (auto vh : {v0, v1})
{
// get the halfedge pointing from new vertex to old vertex
const HalfedgeHandle h = find_halfedge(_vh, vh);
if (!is_boundary(h)) // for boundaries there are no faces whose properties need to be copied
{
FaceHandle fh0 = face_handle(h);
FaceHandle fh1 = face_handle(opposite_halfedge_handle(prev_halfedge_handle(h)));
if (fh0.idx() >= nf) // is fh0 the new face?
std::swap(fh0, fh1);
// copy properties from old face to new face
copy_all_properties(fh0, fh1, true);
}
}
}
}// namespace OpenMesh

View File

@ -0,0 +1,211 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OPENMESH_TRICONNECTIVITY_HH
#define OPENMESH_TRICONNECTIVITY_HH
#include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
namespace OpenMesh {
/** \brief Connectivity Class for Triangle Meshes
*/
class OPENMESHDLLEXPORT TriConnectivity : public PolyConnectivity
{
public:
TriConnectivity() {}
virtual ~TriConnectivity() {}
inline static bool is_triangles()
{ return true; }
/** assign_connectivity() methods. See ArrayKernel::assign_connectivity()
for more details. When the source connectivity is not triangles, in
addition "fan" connectivity triangulation is performed*/
inline void assign_connectivity(const TriConnectivity& _other)
{ PolyConnectivity::assign_connectivity(_other); }
inline void assign_connectivity(const PolyConnectivity& _other)
{
PolyConnectivity::assign_connectivity(_other);
triangulate();
}
/** \name Addding items to a mesh
*/
//@{
/** \brief Add a face with arbitrary valence to the triangle mesh
*
* Override OpenMesh::Mesh::PolyMeshT::add_face(). Faces that aren't
* triangles will be triangulated and added. In this case an
* invalid face handle will be returned.
*
*
* */
FaceHandle add_face(const VertexHandle* _vhandles, size_t _vhs_size);
/** \brief Add a face with arbitrary valence to the triangle mesh
*
* Override OpenMesh::Mesh::PolyMeshT::add_face(). Faces that aren't
* triangles will be triangulated and added. In this case an
* invalid face handle will be returned.
*
*
* */
FaceHandle add_face(const std::vector<VertexHandle>& _vhandles);
/** \brief Add a face to the mesh (triangle)
*
* This function adds a triangle to the mesh. The triangle is passed directly
* to the underlying PolyConnectivity as we don't explicitly need to triangulate something.
*
* @param _vh0 VertexHandle 1
* @param _vh1 VertexHandle 2
* @param _vh2 VertexHandle 3
* @return FaceHandle of the added face (invalid, if the operation failed)
*/
FaceHandle add_face(VertexHandle _vh0, VertexHandle _vh1, VertexHandle _vh2);
//@}
/** Returns the opposite vertex to the halfedge _heh in the face
referenced by _heh returns InvalidVertexHandle if the _heh is
boundary */
inline VertexHandle opposite_vh(HalfedgeHandle _heh) const
{
return is_boundary(_heh) ? InvalidVertexHandle :
to_vertex_handle(next_halfedge_handle(_heh));
}
/** Returns the opposite vertex to the opposite halfedge of _heh in
the face referenced by it returns InvalidVertexHandle if the
opposite halfedge is boundary */
VertexHandle opposite_he_opposite_vh(HalfedgeHandle _heh) const
{ return opposite_vh(opposite_halfedge_handle(_heh)); }
/** \name Topology modifying operators
*/
//@{
/** Returns whether collapsing halfedge _heh is ok or would lead to
topological inconsistencies.
\attention This method need the Attributes::Status attribute and
changes the \em tagged bit. */
bool is_collapse_ok(HalfedgeHandle _heh);
/// Vertex Split: inverse operation to collapse().
HalfedgeHandle vertex_split(VertexHandle v0, VertexHandle v1,
VertexHandle vl, VertexHandle vr);
/// Check whether flipping _eh is topologically correct.
bool is_flip_ok(EdgeHandle _eh) const;
/** Flip edge _eh.
Check for topological correctness first using is_flip_ok(). */
void flip(EdgeHandle _eh);
/** \brief Edge split (= 2-to-4 split)
*
*
* The function will introduce two new faces ( non-boundary case) or
* one additional face (if edge is boundary)
*
* \note The properties of the new edges, halfedges, and faces will be undefined!
*
* @param _eh Edge handle that should be splitted
* @param _vh Vertex handle that will be inserted at the edge
*/
void split(EdgeHandle _eh, VertexHandle _vh);
/** \brief Edge split (= 2-to-4 split)
*
* The function will introduce two new faces ( non-boundary case) or
* one additional face (if edge is boundary)
*
* \note The properties of the new edges will be adjusted to the properties of the original edge
* \note The properties of the new faces and halfedges will be undefined
*
* @param _eh Edge handle that should be splitted
* @param _vh Vertex handle that will be inserted at the edge
*/
void split_copy(EdgeHandle _eh, VertexHandle _vh);
/** \brief Face split (= 1-to-3) split, calls corresponding PolyMeshT function).
*
* @param _fh Face handle that should be splitted
* @param _vh Vertex handle that will be inserted at the face
*/
inline void split(FaceHandle _fh, VertexHandle _vh)
{ PolyConnectivity::split(_fh, _vh); }
/** \brief Face split (= 1-to-3) split, calls corresponding PolyMeshT function).
*
* @param _fh Face handle that should be splitted
* @param _vh Vertex handle that will be inserted at the face
*/
inline void split_copy(FaceHandle _fh, VertexHandle _vh)
{ PolyConnectivity::split_copy(_fh, _vh); }
//@}
private:
/// Helper for vertex split
HalfedgeHandle insert_loop(HalfedgeHandle _hh);
/// Helper for vertex split
HalfedgeHandle insert_edge(VertexHandle _vh,
HalfedgeHandle _h0, HalfedgeHandle _h1);
};
}
#endif//OPENMESH_TRICONNECTIVITY_HH

View File

@ -0,0 +1,93 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS TriMeshT - IMPLEMENTATION
//
//=============================================================================
#define OPENMESH_TRIMESH_C
//== INCLUDES =================================================================
#include <OpenMesh/Core/Mesh/TriMeshT.hh>
#include <OpenMesh/Core/System/omstream.hh>
#include <vector>
//== NAMESPACES ==============================================================
namespace OpenMesh {
//== IMPLEMENTATION ==========================================================
template <class Kernel>
typename TriMeshT<Kernel>::Normal
TriMeshT<Kernel>::
calc_face_normal(FaceHandle _fh) const
{
assert(this->halfedge_handle(_fh).is_valid());
ConstFaceVertexIter fv_it(this->cfv_iter(_fh));
const Point& p0(this->point(*fv_it)); ++fv_it;
const Point& p1(this->point(*fv_it)); ++fv_it;
const Point& p2(this->point(*fv_it));
return PolyMesh::calc_face_normal(p0, p1, p2);
}
//=============================================================================
} // namespace OpenMesh
//=============================================================================

View File

@ -0,0 +1,438 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS TriMeshT
//
//=============================================================================
#ifndef OPENMESH_TRIMESH_HH
#define OPENMESH_TRIMESH_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Mesh/PolyMeshT.hh>
#include <vector>
//== NAMESPACES ===============================================================
namespace OpenMesh {
//== CLASS DEFINITION =========================================================
/** \class TriMeshT TriMeshT.hh <OpenMesh/Mesh/TriMeshT.hh>
Base type for a triangle mesh.
Base type for a triangle mesh, parameterized by a mesh kernel. The
mesh inherits all methods from the kernel class and the
more general polygonal mesh PolyMeshT. Therefore it provides
the same types for items, handles, iterators and so on.
\param Kernel: template argument for the mesh kernel
\note You should use the predefined mesh-kernel combinations in
\ref mesh_types_group
\see \ref mesh_type
\see OpenMesh::PolyMeshT
*/
template <class Kernel>
class TriMeshT : public PolyMeshT<Kernel>
{
public:
// self
typedef TriMeshT<Kernel> This;
typedef PolyMeshT<Kernel> PolyMesh;
//@{
/// Determine whether this is a PolyMeshT or TriMeshT ( This function does not check the per face vertex count! It only checks if the datatype is PolyMeshT or TriMeshT )
enum { IsPolyMesh = 0 };
enum { IsTriMesh = 1 };
static bool is_polymesh() { return false; }
static bool is_trimesh() { return true; }
//@}
//--- items ---
typedef typename PolyMesh::Scalar Scalar;
typedef typename PolyMesh::Point Point;
typedef typename PolyMesh::Normal Normal;
typedef typename PolyMesh::Color Color;
typedef typename PolyMesh::TexCoord1D TexCoord1D;
typedef typename PolyMesh::TexCoord2D TexCoord2D;
typedef typename PolyMesh::TexCoord3D TexCoord3D;
typedef typename PolyMesh::Vertex Vertex;
typedef typename PolyMesh::Halfedge Halfedge;
typedef typename PolyMesh::Edge Edge;
typedef typename PolyMesh::Face Face;
//--- handles ---
typedef typename PolyMesh::VertexHandle VertexHandle;
typedef typename PolyMesh::HalfedgeHandle HalfedgeHandle;
typedef typename PolyMesh::EdgeHandle EdgeHandle;
typedef typename PolyMesh::FaceHandle FaceHandle;
//--- iterators ---
typedef typename PolyMesh::VertexIter VertexIter;
typedef typename PolyMesh::ConstVertexIter ConstVertexIter;
typedef typename PolyMesh::EdgeIter EdgeIter;
typedef typename PolyMesh::ConstEdgeIter ConstEdgeIter;
typedef typename PolyMesh::FaceIter FaceIter;
typedef typename PolyMesh::ConstFaceIter ConstFaceIter;
//--- circulators ---
typedef typename PolyMesh::VertexVertexIter VertexVertexIter;
typedef typename PolyMesh::VertexOHalfedgeIter VertexOHalfedgeIter;
typedef typename PolyMesh::VertexIHalfedgeIter VertexIHalfedgeIter;
typedef typename PolyMesh::VertexEdgeIter VertexEdgeIter;
typedef typename PolyMesh::VertexFaceIter VertexFaceIter;
typedef typename PolyMesh::FaceVertexIter FaceVertexIter;
typedef typename PolyMesh::FaceHalfedgeIter FaceHalfedgeIter;
typedef typename PolyMesh::FaceEdgeIter FaceEdgeIter;
typedef typename PolyMesh::FaceFaceIter FaceFaceIter;
typedef typename PolyMesh::ConstVertexVertexIter ConstVertexVertexIter;
typedef typename PolyMesh::ConstVertexOHalfedgeIter ConstVertexOHalfedgeIter;
typedef typename PolyMesh::ConstVertexIHalfedgeIter ConstVertexIHalfedgeIter;
typedef typename PolyMesh::ConstVertexEdgeIter ConstVertexEdgeIter;
typedef typename PolyMesh::ConstVertexFaceIter ConstVertexFaceIter;
typedef typename PolyMesh::ConstFaceVertexIter ConstFaceVertexIter;
typedef typename PolyMesh::ConstFaceHalfedgeIter ConstFaceHalfedgeIter;
typedef typename PolyMesh::ConstFaceEdgeIter ConstFaceEdgeIter;
typedef typename PolyMesh::ConstFaceFaceIter ConstFaceFaceIter;
// --- constructor/destructor
/// Default constructor
TriMeshT() : PolyMesh() {}
explicit TriMeshT(PolyMesh rhs) : PolyMesh((rhs.triangulate(), rhs))
{
}
/// Destructor
virtual ~TriMeshT() {}
//--- halfedge collapse / vertex split ---
/** \brief Vertex Split: inverse operation to collapse().
*
* Insert the new vertex at position v0. The vertex will be added
* as the inverse of the vertex split. The faces above the split
* will be correctly attached to the two new edges
*
* Before:
* v_l v0 v_r
* x x x
* \ /
* \ /
* \ /
* \ /
* \ /
* \ /
* x
* v1
*
* After:
* v_l v0 v_r
* x------x------x
* \ | /
* \ | /
* \ | /
* \ | /
* \ | /
* \|/
* x
* v1
*
* @param _v0_point Point position for the new point
* @param _v1 Vertex that will be split
* @param _vl Left vertex handle
* @param _vr Right vertex handle
* @return Newly inserted halfedge
*/
inline HalfedgeHandle vertex_split(Point _v0_point, VertexHandle _v1,
VertexHandle _vl, VertexHandle _vr)
{ return PolyMesh::vertex_split(this->add_vertex(_v0_point), _v1, _vl, _vr); }
/** \brief Vertex Split: inverse operation to collapse().
*
* Insert the new vertex at position v0. The vertex will be added
* as the inverse of the vertex split. The faces above the split
* will be correctly attached to the two new edges
*
* Before:
* v_l v0 v_r
* x x x
* \ /
* \ /
* \ /
* \ /
* \ /
* \ /
* x
* v1
*
* After:
* v_l v0 v_r
* x------x------x
* \ | /
* \ | /
* \ | /
* \ | /
* \ | /
* \|/
* x
* v1
*
* @param _v0 Vertex handle for the newly inserted point (Input has to be unconnected!)
* @param _v1 Vertex that will be split
* @param _vl Left vertex handle
* @param _vr Right vertex handle
* @return Newly inserted halfedge
*/
inline HalfedgeHandle vertex_split(VertexHandle _v0, VertexHandle _v1,
VertexHandle _vl, VertexHandle _vr)
{ return PolyMesh::vertex_split(_v0, _v1, _vl, _vr); }
/** \brief Edge split (= 2-to-4 split)
*
* The properties of the new edges will be undefined!
*
*
* @param _eh Edge handle that should be splitted
* @param _p New point position that will be inserted at the edge
* @return Vertex handle of the newly added vertex
*/
inline VertexHandle split(EdgeHandle _eh, const Point& _p)
{
//Do not call PolyMeshT function below as this does the wrong operation
const VertexHandle vh = this->add_vertex(_p); Kernel::split(_eh, vh); return vh;
}
/** \brief Edge split (= 2-to-4 split)
*
* The properties of the new edges will be adjusted to the properties of the original edge
*
* @param _eh Edge handle that should be splitted
* @param _p New point position that will be inserted at the edge
* @return Vertex handle of the newly added vertex
*/
inline VertexHandle split_copy(EdgeHandle _eh, const Point& _p)
{
//Do not call PolyMeshT function below as this does the wrong operation
const VertexHandle vh = this->add_vertex(_p); Kernel::split_copy(_eh, vh); return vh;
}
/** \brief Edge split (= 2-to-4 split)
*
* The properties of the new edges will be undefined!
*
* @param _eh Edge handle that should be splitted
* @param _vh Vertex handle that will be inserted at the edge
*/
inline void split(EdgeHandle _eh, VertexHandle _vh)
{
//Do not call PolyMeshT function below as this does the wrong operation
Kernel::split(_eh, _vh);
}
/** \brief Edge split (= 2-to-4 split)
*
* The properties of the new edges will be adjusted to the properties of the original edge
*
* @param _eh Edge handle that should be splitted
* @param _vh Vertex handle that will be inserted at the edge
*/
inline void split_copy(EdgeHandle _eh, VertexHandle _vh)
{
//Do not call PolyMeshT function below as this does the wrong operation
Kernel::split_copy(_eh, _vh);
}
/** \brief Face split (= 1-to-3 split, calls corresponding PolyMeshT function).
*
* The properties of the new faces will be undefined!
*
* @param _fh Face handle that should be splitted
* @param _p New point position that will be inserted in the face
*
* @return Vertex handle of the new vertex
*/
inline VertexHandle split(FaceHandle _fh, const Point& _p)
{ const VertexHandle vh = this->add_vertex(_p); PolyMesh::split(_fh, vh); return vh; }
/** \brief Face split (= 1-to-3 split, calls corresponding PolyMeshT function).
*
* The properties of the new faces will be adjusted to the properties of the original face
*
* @param _fh Face handle that should be splitted
* @param _p New point position that will be inserted in the face
*
* @return Vertex handle of the new vertex
*/
inline VertexHandle split_copy(FaceHandle _fh, const Point& _p)
{ const VertexHandle vh = this->add_vertex(_p); PolyMesh::split_copy(_fh, vh); return vh; }
/** \brief Face split (= 1-to-4) split, splits edges at midpoints and adds 4 new faces in the interior).
*
* @param _fh Face handle that should be splitted
*/
inline void split(FaceHandle _fh)
{
// Collect halfedges of face
HalfedgeHandle he0 = this->halfedge_handle(_fh);
HalfedgeHandle he1 = this->next_halfedge_handle(he0);
HalfedgeHandle he2 = this->next_halfedge_handle(he1);
EdgeHandle eh0 = this->edge_handle(he0);
EdgeHandle eh1 = this->edge_handle(he1);
EdgeHandle eh2 = this->edge_handle(he2);
// Collect points of face
VertexHandle p0 = this->to_vertex_handle(he0);
VertexHandle p1 = this->to_vertex_handle(he1);
VertexHandle p2 = this->to_vertex_handle(he2);
// Calculate midpoint coordinates
const Point new0 = (this->point(p0) + this->point(p2)) * static_cast<typename vector_traits<Point>::value_type >(0.5);
const Point new1 = (this->point(p0) + this->point(p1)) * static_cast<typename vector_traits<Point>::value_type >(0.5);
const Point new2 = (this->point(p1) + this->point(p2)) * static_cast<typename vector_traits<Point>::value_type >(0.5);
// Add vertices at midpoint coordinates
VertexHandle v0 = this->add_vertex(new0);
VertexHandle v1 = this->add_vertex(new1);
VertexHandle v2 = this->add_vertex(new2);
const bool split0 = !this->is_boundary(eh0);
const bool split1 = !this->is_boundary(eh1);
const bool split2 = !this->is_boundary(eh2);
// delete original face
this->delete_face(_fh);
// split boundary edges of deleted face ( if not boundary )
if ( split0 ) {
this->split(eh0,v0);
}
if ( split1 ) {
this->split(eh1,v1);
}
if ( split2 ) {
this->split(eh2,v2);
}
// Retriangulate
this->add_face(v0 , p0, v1);
this->add_face(p2, v0 , v2);
this->add_face(v2,v1,p1);
this->add_face(v2 , v0, v1);
}
/** \brief Face split (= 1-to-3 split, calls corresponding PolyMeshT function).
*
* The properties of the new faces will be undefined!
*
* @param _fh Face handle that should be splitted
* @param _vh Vertex handle that will be inserted at the face
*/
inline void split(FaceHandle _fh, VertexHandle _vh)
{ PolyMesh::split(_fh, _vh); }
/** \brief Face split (= 1-to-3 split, calls corresponding PolyMeshT function).
*
* The properties of the new faces will be adjusted to the properties of the original face
*
* @param _fh Face handle that should be splitted
* @param _vh Vertex handle that will be inserted at the face
*/
inline void split_copy(FaceHandle _fh, VertexHandle _vh)
{ PolyMesh::split_copy(_fh, _vh); }
/** \name Normal vector computation
*/
//@{
/** Calculate normal vector for face _fh (specialized for TriMesh). */
Normal calc_face_normal(FaceHandle _fh) const;
//@}
};
//=============================================================================
} // namespace OpenMesh
//=============================================================================
#if defined(OM_INCLUDE_TEMPLATES) && !defined(OPENMESH_TRIMESH_C)
#define OPENMESH_TRIMESH_TEMPLATES
#include "TriMeshT.cc"
#endif
//=============================================================================
#endif // OPENMESH_TRIMESH_HH defined
//=============================================================================

View File

@ -0,0 +1,117 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS TriMesh_ArrayKernelT
//
//=============================================================================
#ifndef OPENMESH_TRIMESH_ARRAY_KERNEL_HH
#define OPENMESH_TRIMESH_ARRAY_KERNEL_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Mesh/TriConnectivity.hh>
#include <OpenMesh/Core/Mesh/Traits.hh>
#include <OpenMesh/Core/Mesh/FinalMeshItemsT.hh>
#include <OpenMesh/Core/Mesh/AttribKernelT.hh>
#include <OpenMesh/Core/Mesh/TriMeshT.hh>
//== NAMESPACES ===============================================================
namespace OpenMesh {
template<class Traits>
class PolyMesh_ArrayKernelT;
//== CLASS DEFINITION =========================================================
/// Helper class to create a TriMesh-type based on ArrayKernelT
template <class Traits>
struct TriMesh_ArrayKernel_GeneratorT
{
typedef FinalMeshItemsT<Traits, true> MeshItems;
typedef AttribKernelT<MeshItems, TriConnectivity> AttribKernel;
typedef TriMeshT<AttribKernel> Mesh;
};
/** \ingroup mesh_types_group
Triangle mesh based on the ArrayKernel.
\see OpenMesh::TriMeshT
\see OpenMesh::ArrayKernelT
*/
template <class Traits = DefaultTraits>
class TriMesh_ArrayKernelT
: public TriMesh_ArrayKernel_GeneratorT<Traits>::Mesh
{
public:
TriMesh_ArrayKernelT() {}
template<class OtherTraits>
TriMesh_ArrayKernelT( const PolyMesh_ArrayKernelT<OtherTraits> & t)
{
//assign the connectivity and standard properties
this->assign(t,true);
}
};
//=============================================================================
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_TRIMESH_ARRAY_KERNEL_HH
//=============================================================================

View File

@ -0,0 +1,98 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OPENMESH_CIRCULATORS_HH
#define OPENMESH_CIRCULATORS_HH
//=============================================================================
//
// Vertex and Face circulators for PolyMesh/TriMesh
//
//=============================================================================
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <cassert>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace Iterators {
//== FORWARD DECLARATIONS =====================================================
template <class Mesh> class VertexVertexIterT;
template <class Mesh> class VertexIHalfedgeIterT;
template <class Mesh> class VertexOHalfedgeIterT;
template <class Mesh> class VertexEdgeIterT;
template <class Mesh> class VertexFaceIterT;
template <class Mesh> class ConstVertexVertexIterT;
template <class Mesh> class ConstVertexIHalfedgeIterT;
template <class Mesh> class ConstVertexOHalfedgeIterT;
template <class Mesh> class ConstVertexEdgeIterT;
template <class Mesh> class ConstVertexFaceIterT;
template <class Mesh> class FaceVertexIterT;
template <class Mesh> class FaceHalfedgeIterT;
template <class Mesh> class FaceEdgeIterT;
template <class Mesh> class FaceFaceIterT;
template <class Mesh> class ConstFaceVertexIterT;
template <class Mesh> class ConstFaceHalfedgeIterT;
template <class Mesh> class ConstFaceEdgeIterT;
template <class Mesh> class ConstFaceFaceIterT;

View File

@ -0,0 +1,190 @@
//== CLASS DEFINITION =========================================================
/** \class CirculatorT CirculatorsT.hh <OpenMesh/Mesh/Iterators/CirculatorsT.hh>
Circulator.
*/
template <class Mesh>
class CirculatorT
{
public:
//--- Typedefs ---
typedef typename Mesh::HalfedgeHandle HalfedgeHandle;
typedef TargetType value_type;
typedef TargetHandle value_handle;
#if IsConst
typedef const Mesh& mesh_ref;
typedef const Mesh* mesh_ptr;
typedef const TargetType& reference;
typedef const TargetType* pointer;
#else
typedef Mesh& mesh_ref;
typedef Mesh* mesh_ptr;
typedef TargetType& reference;
typedef TargetType* pointer;
#endif
/// Default constructor
CirculatorT() : mesh_(0), active_(false) {}
/// Construct with mesh and a SourceHandle
CirculatorT(mesh_ref _mesh, SourceHandle _start) :
mesh_(&_mesh),
start_(_mesh.halfedge_handle(_start)),
heh_(start_),
active_(false)
{ post_init; }
/// Construct with mesh and start halfedge
CirculatorT(mesh_ref _mesh, HalfedgeHandle _heh) :
mesh_(&_mesh),
start_(_heh),
heh_(_heh),
active_(false)
{ post_init; }
/// Copy constructor
CirculatorT(const CirculatorT& _rhs) :
mesh_(_rhs.mesh_),
start_(_rhs.start_),
heh_(_rhs.heh_),
active_(_rhs.active_)
{ post_init; }
/// Assignment operator
CirculatorT& operator=(const CirculatorT<Mesh>& _rhs)
{
mesh_ = _rhs.mesh_;
start_ = _rhs.start_;
heh_ = _rhs.heh_;
active_ = _rhs.active_;
return *this;
}
#if IsConst
/// construct from non-const circulator type
CirculatorT(const NonConstCircT<Mesh>& _rhs) :
mesh_(_rhs.mesh_),
start_(_rhs.start_),
heh_(_rhs.heh_),
active_(_rhs.active_)
{ post_init; }
/// assign from non-const circulator
CirculatorT& operator=(const NonConstCircT<Mesh>& _rhs)
{
mesh_ = _rhs.mesh_;
start_ = _rhs.start_;
heh_ = _rhs.heh_;
active_ = _rhs.active_;
return *this;
}
#else
friend class ConstCircT<Mesh>;
#endif
/// Equal ?
bool operator==(const CirculatorT& _rhs) const {
return ((mesh_ == _rhs.mesh_) &&
(start_ == _rhs.start_) &&
(heh_ == _rhs.heh_) &&
(active_ == _rhs.active_));
}
/// Not equal ?
bool operator!=(const CirculatorT& _rhs) const {
return !operator==(_rhs);
}
/// Pre-Increment (next cw target)
CirculatorT& operator++() {
assert(mesh_);
active_ = true;
increment;
return *this;
}
/// Pre-Decrement (next ccw target)
CirculatorT& operator--() {
assert(mesh_);
active_ = true;
decrement;
return *this;
}
/** Get the current halfedge. There are \c Vertex*Iters and \c
Face*Iters. For both the current state is defined by the
current halfedge. This is what this method returns.
*/
HalfedgeHandle current_halfedge_handle() const {
return heh_;
}
/// Return the handle of the current target.
TargetHandle handle() const {
assert(mesh_);
return get_handle;
}
/// Cast to the handle of the current target.
operator TargetHandle() const {
assert(mesh_);
return get_handle;
}
/// Return a reference to the current target.
reference operator*() const {
assert(mesh_);
return mesh_->deref(handle());
}
/// Return a pointer to the current target.
pointer operator->() const {
assert(mesh_);
return &mesh_->deref(handle());
}
/** Returns whether the circulator is still valid.
After one complete round around a vertex/face the circulator becomes
invalid, i.e. this function will return \c false. Nevertheless you
can continue circulating. This method just tells you whether you
have completed the first round.
*/
operator bool() const {
return heh_.is_valid() && ((start_ != heh_) || (!active_));
}
private:
mesh_ptr mesh_;
HalfedgeHandle start_, heh_;
bool active_;
};

View File

@ -0,0 +1,6 @@
//=============================================================================
} // namespace Iterators
} // namespace OpenMesh
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,175 @@
#!/bin/bash
#------------------------------------------------------------------------------
# generate_iterator( TargetType, n_elements, has_element_status )
function generate_iterator
{
NonConstIter=$1"IterT"
ConstIter="Const"$NonConstIter
TargetType="typename Mesh::"$1
TargetHandle="typename Mesh::"$1"Handle"
cat iterators_template.hh \
| sed -e "s/IteratorT/$NonConstIter/; s/IteratorT/$NonConstIter/;
s/NonConstIterT/$NonConstIter/;
s/ConstIterT/$ConstIter/;
s/TargetType/$TargetType/;
s/TargetHandle/$TargetHandle/;
s/IsConst/0/;
s/n_elements/$2/;
s/has_element_status/$3/;"
cat iterators_template.hh \
| sed -e "s/IteratorT/$ConstIter/; s/IteratorT/$ConstIter/;
s/NonConstIterT/$NonConstIter/;
s/ConstIterT/$ConstIter/;
s/TargetType/$TargetType/;
s/TargetHandle/$TargetHandle/;
s/IsConst/1/;
s/n_elements/$2/;
s/has_element_status/$3/;"
}
#------------------------------------------------------------------------------
# generate_circulator( NonConstName, SourceType, TargetType,
# post_init,
# increment, decrement,
# get_handle,
# [Name] )
function generate_circulator
{
NonConstCirc=$1
ConstCirc="Const"$NonConstCirc
SourceHandle="typename Mesh::"$2"Handle"
TargetHandle="typename Mesh::"$3"Handle"
TargetType="typename Mesh::"$3
cat circulators_template.hh \
| sed -e "s/CirculatorT/$NonConstCirc/; s/CirculatorT/$NonConstCirc/;
s/NonConstCircT/$NonConstCirc/;
s/ConstCircT/$ConstCirc/;
s/SourceHandle/$SourceHandle/;
s/TargetHandle/$TargetHandle/;
s/TargetType/$TargetType/;
s/IsConst/0/;
s/post_init/$4/;
s/increment/$5/;
s/decrement/$6/;
s/get_handle/$7/;"
cat circulators_template.hh \
| sed -e "s/CirculatorT/$ConstCirc/; s/CirculatorT/$ConstCirc/;
s/NonConstCircT/$NonConstCirc/;
s/ConstCircT/$ConstCirc/;
s/SourceHandle/$SourceHandle/;
s/TargetHandle/$TargetHandle/;
s/TargetType/$TargetType/;
s/IsConst/1/;
s/post_init/$4/;
s/increment/$5/;
s/decrement/$6/;
s/get_handle/$7/;"
}
#------------------------------------------------------------------------------
### Generate IteratorsT.hh
cat iterators_header.hh > IteratorsT.hh
generate_iterator Vertex n_vertices has_vertex_status >> IteratorsT.hh
generate_iterator Halfedge n_halfedges has_halfedge_status >> IteratorsT.hh
generate_iterator Edge n_edges has_edge_status >> IteratorsT.hh
generate_iterator Face n_faces has_face_status >> IteratorsT.hh
cat footer.hh >> IteratorsT.hh
#------------------------------------------------------------------------------
### Generate CirculatorsT.hh
cat circulators_header.hh > CirculatorsT.hh
generate_circulator VertexVertexIterT Vertex Vertex \
" " \
"heh_=mesh_->cw_rotated_halfedge_handle(heh_);" \
"heh_=mesh_->ccw_rotated_halfedge_handle(heh_);" \
"mesh_->to_vertex_handle(heh_);" \
>> CirculatorsT.hh
generate_circulator VertexOHalfedgeIterT Vertex Halfedge \
" " \
"heh_=mesh_->cw_rotated_halfedge_handle(heh_);" \
"heh_=mesh_->ccw_rotated_halfedge_handle(heh_);" \
"heh_" \
>> CirculatorsT.hh
generate_circulator VertexIHalfedgeIterT Vertex Halfedge \
" " \
"heh_=mesh_->cw_rotated_halfedge_handle(heh_);" \
"heh_=mesh_->ccw_rotated_halfedge_handle(heh_);" \
"mesh_->opposite_halfedge_handle(heh_)" \
>> CirculatorsT.hh
generate_circulator VertexEdgeIterT Vertex Edge \
" " \
"heh_=mesh_->cw_rotated_halfedge_handle(heh_);" \
"heh_=mesh_->ccw_rotated_halfedge_handle(heh_);" \
"mesh_->edge_handle(heh_)" \
>> CirculatorsT.hh
generate_circulator VertexFaceIterT Vertex Face \
"if (heh_.is_valid() \&\& !handle().is_valid()) operator++();" \
"do heh_=mesh_->cw_rotated_halfedge_handle(heh_); while ((*this) \&\& (!handle().is_valid()));" \
"do heh_=mesh_->ccw_rotated_halfedge_handle(heh_); while ((*this) \&\& (!handle().is_valid()));" \
"mesh_->face_handle(heh_)" \
>> CirculatorsT.hh
generate_circulator FaceVertexIterT Face Vertex \
" " \
"heh_=mesh_->next_halfedge_handle(heh_);" \
"heh_=mesh_->prev_halfedge_handle(heh_);" \
"mesh_->to_vertex_handle(heh_)" \
>> CirculatorsT.hh
generate_circulator FaceHalfedgeIterT Face Halfedge \
" " \
"heh_=mesh_->next_halfedge_handle(heh_);" \
"heh_=mesh_->prev_halfedge_handle(heh_);" \
"heh_" \
>> CirculatorsT.hh
generate_circulator FaceEdgeIterT Face Edge \
" " \
"heh_=mesh_->next_halfedge_handle(heh_);" \
"heh_=mesh_->prev_halfedge_handle(heh_);" \
"mesh_->edge_handle(heh_)" \
>> CirculatorsT.hh
generate_circulator FaceFaceIterT Face Face \
"if (heh_.is_valid() \&\& !handle().is_valid()) operator++();" \
"do heh_=mesh_->next_halfedge_handle(heh_); while ((*this) \&\& (!handle().is_valid()));" \
"do heh_=mesh_->prev_halfedge_handle(heh_); while ((*this) \&\& (!handle().is_valid()));" \
"mesh_->face_handle(mesh_->opposite_halfedge_handle(heh_))" \
>> CirculatorsT.hh
cat footer.hh >> CirculatorsT.hh
#------------------------------------------------------------------------------

View File

@ -0,0 +1,87 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OPENMESH_ITERATORS_HH
#define OPENMESH_ITERATORS_HH
//=============================================================================
//
// Iterators for PolyMesh/TriMesh
//
//=============================================================================
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <OpenMesh/Core/Attributes/Status.hh>
#include <cassert>
//== NAMESPACES ===============================================================
namespace OpenMesh {
namespace Iterators {
//== FORWARD DECLARATIONS =====================================================
template <class Mesh> class VertexIterT;
template <class Mesh> class ConstVertexIterT;
template <class Mesh> class HalfedgeIterT;
template <class Mesh> class ConstHalfedgeIterT;
template <class Mesh> class EdgeIterT;
template <class Mesh> class ConstEdgeIterT;
template <class Mesh> class FaceIterT;
template <class Mesh> class ConstFaceIterT;

View File

@ -0,0 +1,162 @@
//== CLASS DEFINITION =========================================================
/** \class IteratorT IteratorsT.hh <OpenMesh/Mesh/Iterators/IteratorsT.hh>
Linear iterator.
*/
template <class Mesh>
class IteratorT
{
public:
//--- Typedefs ---
typedef TargetType value_type;
typedef TargetHandle value_handle;
#if IsConst
typedef const value_type& reference;
typedef const value_type* pointer;
typedef const Mesh* mesh_ptr;
typedef const Mesh& mesh_ref;
#else
typedef value_type& reference;
typedef value_type* pointer;
typedef Mesh* mesh_ptr;
typedef Mesh& mesh_ref;
#endif
/// Default constructor.
IteratorT()
: mesh_(0), skip_bits_(0)
{}
/// Construct with mesh and a target handle.
IteratorT(mesh_ref _mesh, value_handle _hnd, bool _skip=false)
: mesh_(&_mesh), hnd_(_hnd), skip_bits_(0)
{
if (_skip) enable_skipping();
}
/// Copy constructor
IteratorT(const IteratorT& _rhs)
: mesh_(_rhs.mesh_), hnd_(_rhs.hnd_), skip_bits_(_rhs.skip_bits_)
{}
/// Assignment operator
IteratorT& operator=(const IteratorT<Mesh>& _rhs)
{
mesh_ = _rhs.mesh_;
hnd_ = _rhs.hnd_;
skip_bits_ = _rhs.skip_bits_;
return *this;
}
#if IsConst
/// Construct from a non-const iterator
IteratorT(const NonConstIterT<Mesh>& _rhs)
: mesh_(_rhs.mesh_), hnd_(_rhs.hnd_), skip_bits_(_rhs.skip_bits_)
{}
/// Assignment from non-const iterator
IteratorT& operator=(const NonConstIterT<Mesh>& _rhs)
{
mesh_ = _rhs.mesh_;
hnd_ = _rhs.hnd_;
skip_bits_ = _rhs.skip_bits_;
return *this;
}
#else
friend class ConstIterT<Mesh>;
#endif
/// Standard dereferencing operator.
reference operator*() const { return mesh_->deref(hnd_); }
/// Standard pointer operator.
pointer operator->() const { return &(mesh_->deref(hnd_)); }
/// Get the handle of the item the iterator refers to.
value_handle handle() const { return hnd_; }
/// Cast to the handle of the item the iterator refers to.
operator value_handle() const { return hnd_; }
/// Are two iterators equal? Only valid if they refer to the same mesh!
bool operator==(const IteratorT& _rhs) const
{ return ((mesh_ == _rhs.mesh_) && (hnd_ == _rhs.hnd_)); }
/// Not equal?
bool operator!=(const IteratorT& _rhs) const
{ return !operator==(_rhs); }
/// Standard pre-increment operator
IteratorT& operator++()
{ hnd_.__increment(); if (skip_bits_) skip_fwd(); return *this; }
/// Standard pre-decrement operator
IteratorT& operator--()
{ hnd_.__decrement(); if (skip_bits_) skip_bwd(); return *this; }
/// Turn on skipping: automatically skip deleted/hidden elements
void enable_skipping()
{
if (mesh_ && mesh_->has_element_status())
{
Attributes::StatusInfo status;
status.set_deleted(true);
status.set_hidden(true);
skip_bits_ = status.bits();
skip_fwd();
}
else skip_bits_ = 0;
}
/// Turn on skipping: automatically skip deleted/hidden elements
void disable_skipping() { skip_bits_ = 0; }
private:
void skip_fwd()
{
assert(mesh_ && skip_bits_);
while ((hnd_.idx() < (signed) mesh_->n_elements()) &&
(mesh_->status(hnd_).bits() & skip_bits_))
hnd_.__increment();
}
void skip_bwd()
{
assert(mesh_ && skip_bits_);
while ((hnd_.idx() >= 0) &&
(mesh_->status(hnd_).bits() & skip_bits_))
hnd_.__decrement();
}
private:
mesh_ptr mesh_;
value_handle hnd_;
unsigned int skip_bits_;
};

View File

@ -0,0 +1,72 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision: 566 $ *
* $Date: 2012-03-23 18:00:57 +0100 (Fr, 23 Mär 2012) $ *
* *
\*===========================================================================*/
// Disable the warnings about needs to have DLL interface as we have tons of vector templates
#ifdef _MSC_VER
#pragma warning( disable: 4251 )
#endif
#ifndef OPENMESHDLLEXPORT
#ifdef WIN32
#ifdef OPENMESHDLL
#ifdef BUILDOPENMESHDLL
#define OPENMESHDLLEXPORT __declspec(dllexport)
#define OPENMESHDLLEXPORTONLY __declspec(dllexport)
#else
#define OPENMESHDLLEXPORT __declspec(dllimport)
#define OPENMESHDLLEXPORTONLY
#endif
#else
#define OPENMESHDLLEXPORT
#define OPENMESHDLLEXPORTONLY
#endif
#else
#define OPENMESHDLLEXPORT
#define OPENMESHDLLEXPORTONLY
#endif
#endif

View File

@ -0,0 +1,178 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#ifndef OPENMESH_COMPILER_H
#define OPENMESH_COMPILER_H
//=============================================================================
#if defined(ACGMAKE_STATIC_BUILD)
# define OM_STATIC_BUILD 1
#endif
//=============================================================================
#if defined(_DEBUG) || defined(DEBUG)
# define OM_DEBUG
#endif
//=============================================================================
// Workaround for Intel Compiler with MS VC++ 6
#if defined(_MSC_VER) && \
( defined(__ICL) || defined(__INTEL_COMPILER) || defined(__ICC) )
# if !defined(__INTEL_COMPILER)
# define __INTEL_COMPILER __ICL
# endif
# define OM_USE_INTEL_COMPILER 1
#endif
// --------------------------------------------------------- MS Visual C++ ----
// Compiler _MSC_VER
// .NET 2002 1300
// .NET 2003 1310
// .NET 2005 1400
#if defined(_MSC_VER) && !defined(OM_USE_INTEL_COMPILER)
# if (_MSC_VER == 1300)
# define OM_CC_MSVC
# define OM_TYPENAME
# define OM_OUT_OF_CLASS_TEMPLATE 0
# define OM_PARTIAL_SPECIALIZATION 0
# define OM_INCLUDE_TEMPLATES 1
# elif (_MSC_VER == 1310)
# define OM_CC_MSVC
# define OM_TYPENAME
# define OM_OUT_OF_CLASS_TEMPLATE 1
# define OM_PARTIAL_SPECIALIZATION 1
# define OM_INCLUDE_TEMPLATES 1
# elif (_MSC_VER >= 1400) // settings for .NET 2005 (NOTE: not fully tested)
# define OM_TYPENAME
# define OM_OUT_OF_CLASS_TEMPLATE 1
# define OM_PARTIAL_SPECIALIZATION 1
# define OM_INCLUDE_TEMPLATES 1
# else
# error "Version 7 (.NET 2002) or higher of the MS VC++ is required!"
# endif
// currently no windows dll supported
# define OM_STATIC_BUILD 1
# if defined(_MT)
# define OM_REENTRANT 1
# endif
# define OM_CC "MSVC++"
# define OM_CC_VERSION _MSC_VER
// Does not work stable because the define _CPPRTTI sometimes does not exist,
// though the option /GR is set!?
# if defined(__cplusplus) && !defined(_CPPRTTI)
# error "Enable Runtime Type Information (Compiler Option /GR)!"
# endif
# if !defined(_USE_MATH_DEFINES)
# error "You have to define _USE_MATH_DEFINES in the compiler settings!"
# endif
// ------------------------------------------------------------- Borland C ----
#elif defined(__BORLANDC__)
# error "Borland Compiler are not supported yet!"
// ------------------------------------------------------------- GNU C/C++ ----
#elif defined(__GNUC__) && !defined(__ICC)
# define OM_CC_GCC
# define OM_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 )
# define OM_GCC_MAJOR __GNUC__
# define OM_GCC_MINOR __GNUC_MINOR__
# if (OM_GCC_VERSION >= 30200)
# define OM_TYPENAME typename
# define OM_OUT_OF_CLASS_TEMPLATE 1
# define OM_PARTIAL_SPECIALIZATION 1
# define OM_INCLUDE_TEMPLATES 1
# else
# error "Version 3.2.0 or better of the GNU Compiler is required!"
# endif
# if defined(_REENTRANT)
# define OM_REENTRANT 1
# endif
# define OM_CC "GCC"
# define OM_CC_VERSION OM_GCC_VERSION
// ------------------------------------------------------------- Intel icc ----
#elif defined(__ICC) || defined(__INTEL_COMPILER)
# define OM_CC_ICC
# define OM_TYPENAME typename
# define OM_OUT_OF_CLASS_TEMPLATE 1
# define OM_PARTIAL_SPECIALIZATION 1
# define OM_INCLUDE_TEMPLATES 1
# if defined(_REENTRANT) || defined(_MT)
# define OM_REENTRANT 1
# endif
# define OM_CC "ICC"
# define OM_CC_VERSION __INTEL_COMPILER
// currently no windows dll supported
# if defined(_MSC_VER) || defined(WIN32)
# define OM_STATIC_BUILD 1
# endif
// ------------------------------------------------------ MIPSpro Compiler ----
#elif defined(__MIPS_ISA) || defined(__mips)
// _MIPS_ISA
// _COMPILER_VERSION e.g. 730, 7 major, 3 minor
// _MIPS_FPSET 32|64
// _MIPS_SZINT 32|64
// _MIPS_SZLONG 32|64
// _MIPS_SZPTR 32|64
# define OM_CC_MIPS
# define OM_TYPENAME typename
# define OM_OUT_OF_CLASS_TEMPLATE 1
# define OM_PARTIAL_SPECIALIZATION 1
# define OM_INCLUDE_TEMPLATES 0
# define OM_CC "MIPS"
# define OM_CC_VERSION _COMPILER_VERSION
// ------------------------------------------------------------------ ???? ----
#else
# error "You're using an unsupported compiler!"
#endif
//=============================================================================
#endif // OPENMESH_COMPILER_H defined
//=============================================================================

View File

@ -0,0 +1,107 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
/** \file config.h
* \todo Move content to config.hh and include it to be compatible with old
* source.
*/
//=============================================================================
#ifndef OPENMESH_CONFIG_H
#define OPENMESH_CONFIG_H
//=============================================================================
#include <assert.h>
#include <OpenMesh/Core/System/compiler.hh>
#include <OpenMesh/Core/System/OpenMeshDLLMacros.hh>
// ----------------------------------------------------------------------------
#define OM_VERSION 0x70100
#define OM_GET_VER ((OM_VERSION & 0xf0000) >> 16)
#define OM_GET_MAJ ((OM_VERSION & 0x0ff00) >> 8)
#define OM_GET_MIN (OM_VERSION & 0x000ff)
#ifdef WIN32
# ifdef min
# pragma message("Detected min macro! OpenMesh does not compile with min/max macros active! Please add a define NOMINMAX to your compiler flags or add #undef min before including OpenMesh headers !")
# error min macro active
# endif
# ifdef max
# pragma message("Detected max macro! OpenMesh does not compile with min/max macros active! Please add a define NOMINMAX to your compiler flags or add #undef max before including OpenMesh headers !")
# error max macro active
# endif
#endif
#if defined(_MSC_VER)
# define DEPRECATED(msg) __declspec(deprecated(msg))
#elif defined(__GNUC__)
# if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 40500 /* Test for GCC >= 4.5.0 */
# define DEPRECATED(msg) __attribute__ ((deprecated(msg)))
# else
# define DEPRECATED(msg) __attribute__ ((deprecated))
# endif
#elif defined(__clang__)
# define DEPRECATED(msg) __attribute__ ((deprecated(msg)))
#else
# define DEPRECATED(msg)
#endif
typedef unsigned int uint;
#if ((defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined(__GXX_EXPERIMENTAL_CXX0X__))
#define OM_HAS_HASH
#endif
//=============================================================================
#endif // OPENMESH_CONFIG_H defined
//=============================================================================

View File

@ -0,0 +1,49 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
#include <OpenMesh/Core/System/config.h>

View File

@ -0,0 +1,330 @@
/* ========================================================================= *
* *
* OpenMesh *
* Copyright (c) 2001-2015, RWTH-Aachen University *
* Department of Computer Graphics and Multimedia *
* All rights reserved. *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
*---------------------------------------------------------------------------*
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* *
* 1. Redistributions of source code must retain the above copyright notice, *
* this list of conditions and the following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in the *
* documentation and/or other materials provided with the distribution. *
* *
* 3. Neither the name of the copyright holder nor the names of its *
* contributors may be used to endorse or promote products derived from *
* this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
* *
* ========================================================================= */
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
//=============================================================================
//
// multiplex streams & ultilities
//
//=============================================================================
#ifndef OPENMESH_MOSTREAM_HH
#define OPENMESH_MOSTREAM_HH
//== INCLUDES =================================================================
#include <OpenMesh/Core/System/config.h>
#include <ostream>
#if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
# include <streambuf.h>
#else
# include <streambuf>
#endif
#include <vector>
#include <map>
#include <string>
#include <algorithm>
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
#include <mutex>
#endif
//== NAMESPACES ===============================================================
namespace OpenMesh {
#ifndef DOXY_IGNORE_THIS
//== CLASS DEFINITION =========================================================
class basic_multiplex_target
{
public:
virtual ~basic_multiplex_target() {}
virtual void operator<<(const std::string& _s) = 0;
};
template <class T>
class multiplex_target : public basic_multiplex_target
{
public:
explicit multiplex_target(T& _t) : target_(_t) {}
virtual void operator<<(const std::string& _s) { target_ << _s; }
private:
T& target_;
};
//== CLASS DEFINITION =========================================================
#if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
# define STREAMBUF streambuf
# define INT_TYPE int
# define TRAITS_TYPE
#else
# define STREAMBUF std::basic_streambuf<char>
#endif
class multiplex_streambuf : public STREAMBUF
{
public:
typedef STREAMBUF base_type;
#if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
typedef int int_type;
struct traits_type
{
static int_type eof() { return -1; }
static char to_char_type(int_type c) { return char(c); }
};
#else
typedef base_type::int_type int_type;
typedef base_type::traits_type traits_type;
#endif
// Constructor
multiplex_streambuf() : enabled_(true) { buffer_.reserve(100); }
// Destructor
~multiplex_streambuf()
{
tmap_iter t_it(target_map_.begin()), t_end(target_map_.end());
for (; t_it!=t_end; ++t_it)
delete t_it->second;
}
// buffer enable/disable
bool is_enabled() const { return enabled_; }
void enable() { enabled_ = true; }
void disable() { enabled_ = false; }
// construct multiplex_target<T> and add it to targets
template <class T> bool connect(T& _target)
{
void* key = (void*) &_target;
if (target_map_.find(key) != target_map_.end())
return false;
target_type* mtarget = new multiplex_target<T>(_target);
target_map_[key] = mtarget;
__connect(mtarget);
return true;
}
// disconnect target from multiplexer
template <class T> bool disconnect(T& _target)
{
void* key = (void*) &_target;
tmap_iter t_it = target_map_.find(key);
if (t_it != target_map_.end())
{
__disconnect(t_it->second);
target_map_.erase(t_it);
return true;
}
return false;
}
protected:
// output what's in buffer_
virtual int sync()
{
// If working on multiple threads, we need to serialize the output correctly (requires c++11 headers)
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
std::lock_guard<std::mutex> lck (serializer_);
#endif
if (!buffer_.empty())
{
if (enabled_) multiplex();
#if defined( OM_CC_GCC ) && OM_CC_VERSION < 30000
buffer_ = ""; // member clear() not available!
#else
buffer_.clear();
#endif
}
return base_type::sync();
}
// take on char and add it to buffer_
// if '\n' is encountered, trigger a sync()
virtual
int_type overflow(int_type _c = multiplex_streambuf::traits_type::eof())
{
char c = traits_type::to_char_type(_c);
// If working on multiple threads, we need to serialize the output correctly (requires c++11 headers)
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
{
std::lock_guard<std::mutex> lck (serializer_);
buffer_.push_back(c);
}
#else
buffer_.push_back(c);
#endif
if (c == '\n') sync();
return 0;
}
private:
typedef basic_multiplex_target target_type;
typedef std::vector<target_type*> target_list;
typedef target_list::iterator tlist_iter;
typedef std::map<void*, target_type*> target_map;
typedef target_map::iterator tmap_iter;
// add _target to list of multiplex targets
void __connect(target_type* _target) { targets_.push_back(_target); }
// remove _target from list of multiplex targets
void __disconnect(target_type* _target) {
targets_.erase(std::find(targets_.begin(), targets_.end(), _target));
}
// multiplex output of buffer_ to all targets
void multiplex()
{
tlist_iter t_it(targets_.begin()), t_end(targets_.end());
for (; t_it!=t_end; ++t_it)
**t_it << buffer_;
}
private:
target_list targets_;
target_map target_map_;
std::string buffer_;
bool enabled_;
// If working on multiple threads, we need to serialize the output correctly (requires c++11 headers)
#if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || __cplusplus > 199711L || defined( __GXX_EXPERIMENTAL_CXX0X__ )
std::mutex serializer_;
#endif
};
#undef STREAMBUF
//== CLASS DEFINITION =========================================================
/** \class mostream mostream.hh <OpenMesh/Core/System/mostream.hh>
This class provides streams that can easily be multiplexed (using
the connect() method) and toggled on/off (using enable() /
disable()).
\see omlog, omout, omerr
*/
class mostream : public std::ostream
{
public:
/// Explicit constructor
explicit mostream() : std::ostream(NULL) { init(&streambuffer_); }
/// Connect target to multiplexer
template <class T> bool connect(T& _target)
{
return streambuffer_.connect(_target);
}
/// Disconnect target from multiplexer
template <class T> bool disconnect(T& _target)
{
return streambuffer_.disconnect(_target);
}
/// is buffer enabled
bool is_enabled() const { return streambuffer_.is_enabled(); }
/// enable this buffer
void enable() { streambuffer_.enable(); }
/// disable this buffer
void disable() { streambuffer_.disable(); }
private:
multiplex_streambuf streambuffer_;
};
//=============================================================================
#endif
} // namespace OpenMesh
//=============================================================================
#endif // OPENMESH_MOSTREAM_HH defined
//=============================================================================

Some files were not shown because too many files have changed in this diff Show More