Add benchmarks for lcc.

This commit is contained in:
Guillaume Damiand 2013-11-13 13:50:35 +01:00
parent 53f02ea00d
commit e6647d3751
48 changed files with 9967 additions and 0 deletions

View File

@ -0,0 +1,73 @@
project(LCC_performance_2)
cmake_minimum_required(VERSION 2.6.2)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/)
add_subdirectory(surface_mesh)
find_package(CGAL REQUIRED)
include(${CGAL_USE_FILE})
include_directories(BEFORE "../../include")
include_directories(BEFORE "./surface_mesh")
include_directories(BEFORE "./cgogn" "./cgogn/include")
LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/cgogn/lib/Release)
include_directories(BEFORE "/usr/include/libxml2/")
# For profilling with gprof
#add_definitions("-pg")
#SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg")
# add_definitions("-g")
# OpenMesh
set(OPENMESH_DIR "${CMAKE_CURRENT_SOURCE_DIR}/openmesh")
find_package(OpenMesh REQUIRED)
include_directories(${OPENMESH_INCLUDE_DIR})
link_directories(${OPENMESH_LIBRARY_DIR})
# Polyhedron
add_executable(polyhedron_performance performance_2.h polyhedron_performance.h polyhedron_performance.cpp)
target_link_libraries(polyhedron_performance ${CGAL_LIBRARIES})
# LCC_2
add_executable(lcc_performance_2 performance_2.h lcc_performance_2.h lcc_performance_2.cpp)
target_link_libraries(lcc_performance_2 ${CGAL_LIBRARIES})
# Surface_mesh
add_executable(surface_mesh_performance performance_2.h surface_mesh_performance.h surface_mesh_performance.cpp)
target_link_libraries(surface_mesh_performance surface_mesh)
# Open_mesh
add_executable(openmesh_performance performance_2.h openmesh_performance.h openmesh_performance.cpp)
target_link_libraries(openmesh_performance ${OPENMESH_LIBRARIES})
# CGoGN
find_package(Qt REQUIRED)
SET(QT_USE_QTSVG TRUE)
SET(QT_USE_QTXML TRUE )
INCLUDE(${QT_USE_FILE})
ADD_DEFINITIONS(${QT_DEFINITIONS})
SET (CGoGN_EXT_INCLUDES ${CGoGN_EXT_INCLUDES} ${QT_INCLUDE_DIR} ${QGLVIEWER_INCLUDE_DIR} )
SET (CGoGN_EXT_LIBS ${CGoGN_EXT_LIBS} ${QT_LIBRARIES} ${QGLVIEWER_LIBRARIES} )
add_executable(cgogn_performance_2 performance_2.h cgogn_performance_2.h cgogn_performance_2.cpp)
target_link_libraries(cgogn_performance_2 algo assimp container nl topology utils Zinri z ${QT_LIBRARIES} ${QGLVIEWER_LIBRARIES} )
# Performance_2
add_executable(performance_2
performance_2.cpp
performance_2.h
polyhedron_performance.h
openmesh_performance.h
surface_mesh_performance.h
cgogn_performance_2.h
lcc_performance_2.h
)
target_link_libraries(performance_2
${CGAL_LIBRARIES}
surface_mesh
algo assimp container nl topology utils Zinri z ${QT_LIBRARIES} ${QGLVIEWER_LIBRARIES}
${OPENMESH_LIBRARIES}
)

View File

@ -0,0 +1,113 @@
//=============================================================================
#ifndef STOPWATCH_HH
#define STOPWATCH_HH
//== INCLUDES =================================================================
#ifdef _WIN32
# include <windows.h>
#else // Unix
# include <sys/time.h>
#endif
#include <iostream>
//== NAMESPACE ================================================================
namespace graphene {
//== CLASS DEFINITION =========================================================
/// Simple class for a stop watch
class StopWatch
{
public:
/// Constructor
StopWatch()
{
#ifdef _WIN32 // Windows
QueryPerformanceFrequency(&freq_);
#endif
}
/// Start time measurement
void start()
{
#ifdef _WIN32 // Windows
QueryPerformanceCounter(&starttime_);
#else // Linux
starttime_ = current_time();
#endif
}
/// Stop time measurement, return elapsed time in ms
double stop()
{
#ifdef _WIN32 // Windows
QueryPerformanceCounter(&endtime_);
#else // Unix
endtime_ = current_time();
#endif
return elapsed();
}
/// Return elapsed time in ms (watch has to be stopped).
double elapsed() const
{
#ifdef _WIN32 // Windows
return ((double)(endtime_.QuadPart - starttime_.QuadPart)
/ (double)freq_.QuadPart * 1000.0f);
#else // Unix
return ((endtime_.tv_sec - starttime_.tv_sec )*1000.0 +
(endtime_.tv_usec - starttime_.tv_usec)*0.001);
#endif
}
private:
#ifdef _WIN32 // Windows
LARGE_INTEGER starttime_, endtime_;
LARGE_INTEGER freq_;
#else // Unix
timeval current_time() const
{
struct timeval tv;
gettimeofday(&tv, 0);
return tv;
}
timeval starttime_, endtime_;
#endif
};
//=============================================================================
/// output a timer to a stream
inline std::ostream&
operator<<(std::ostream& _os, const StopWatch& _timer)
{
_os << _timer.elapsed() << " ms";
return _os;
}
//=============================================================================
} // namespace graphene
//=============================================================================
#endif // STOPWATCH_HH defined
//=============================================================================

View File

@ -0,0 +1 @@
/home/gdamiand/sources/codes-autres/CGoGN/install

View File

@ -0,0 +1,19 @@
//== INCLUDES =================================================================
#include "cgogn_performance_2.h"
//=============================================================================
int main(int argc, char** argv)
{
if (argc < 2)
{
std::cerr << "Usage:\n" << argv[0] << " <input-mesh>\n";
exit(1);
}
for (int i=1; i<argc; ++i)
{
std::cout<<"**************** "<<argv[i]<<" ****************"<<std::endl;
CGoGN_performance_2().run(argv[i], "output_cgogn_2.off");
}
return 0;
}
//=============================================================================

View File

@ -0,0 +1,290 @@
//== INCLUDES =================================================================
#include "performance_2.h"
#include <iostream>
#include "Topology/generic/genericmap.h"
#include "Topology/generic/parameters.h"
#include "Topology/map/embeddedMap2.h"
#include "Topology/generic/traversor2.h"
#include "Topology/generic/traversorCell.h"
#include "Topology/generic/cellmarker.h"
#include "Geometry/vector_gen.h"
#include "Algo/Import/import.h"
#include "Algo/Export/export.h"
#include "Algo/Modelisation/subdivision.h"
//== CLASS DEFINITION =========================================================
using namespace CGoGN ;
struct PFP: public PFP_STANDARD
{
// definition of the map
typedef EmbeddedMap2 MAP;
};
class CGoGN_performance_2 : public Performance_test_2
{
private:
PFP::MAP myMap;
VertexAttribute<PFP::VEC3> position;
VertexAttribute<PFP::VEC3> normalF;
VertexAttribute<PFP::VEC3> normalV;
unsigned int nbv;
void display_info()
{
std::cout << "#Darts=" << myMap.getNbDarts();
std::cout << ", #0-cells=" << myMap.getNbOrbits<VERTEX>();
std::cout << ", #1-cells=" << myMap.getNbOrbits<EDGE>();
std::cout << ", #2-cells=" << myMap.getNbOrbits<FACE>();
std::cout << "\t" << std::endl;
}
public:
CGoGN_performance_2() : Performance_test_2()
{
normalF = myMap.addAttribute<PFP::VEC3, FACE>("normalsF");
normalV = myMap.addAttribute<PFP::VEC3, VERTEX>("normalsV");
}
private:
virtual bool read_mesh(const char* _filename)
{
std::vector<std::string> attrNames ;
if(!Algo::Surface::Import::importMesh<PFP>(myMap, _filename, attrNames))
return false;
position = myMap.getAttribute<PFP::VEC3, VERTEX>(attrNames[0]);
myMap.enableQuickTraversal<VERTEX>();
myMap.enableQuickTraversal<FACE>();
/*myMap.enableQuickLocalIncidentTraversal<PFP::MAP, VERTEX, FACE>(myMap);
myMap.enableQuickLocalIncidentTraversal<PFP::MAP, FACE, VERTEX>(myMap);
myMap.enableQuickLocalAdjacentTraversal<PFP::MAP, VERTEX, EDGE>(myMap);
*/
nbv = position.nbElements();
return true;
}
virtual bool write_mesh(const char* _filename)
{
return Algo::Surface::Export::exportOFF<PFP>(myMap, position, _filename);
}
virtual int circulator_test()
{
int counter = 0;
TraversorV<PFP::MAP> tv(myMap);
for(Dart dit = tv.begin(); dit != tv.end(); dit = tv.next())
{
Traversor2VF<PFP::MAP> trav(myMap, dit);
for(Dart ditF = trav.begin(); ditF != trav.end(); ditF = trav.next())
++counter;
}
TraversorF<PFP::MAP> tf(myMap);
for(Dart dit = tf.begin(); dit != tf.end(); dit = tf.next())
{
Traversor2FV<PFP::MAP> trav(myMap, dit);
for(Dart ditV = trav.begin(); ditV != trav.end(); ditV = trav.next())
--counter;
}
return counter;
}
virtual void barycenter_test(bool draw)
{
PFP::VEC3 p(0.0,0.0,0.0);
unsigned int size = position.end();
unsigned int count = 0;
for(unsigned int i = position.begin(); i != size; position.next(i))
{
p += position[i];
++count;
}
p /= PFP::REAL(count);
for(unsigned int i = position.begin(); i != size; position.next(i))
position[i] -= p;
if ( draw ) std::cout<<"Barycenter: "<<p<<std::endl;
}
virtual void normal_test()
{
TraversorF<PFP::MAP> tf(myMap);
for(Dart dit = tf.begin(); dit != tf.end(); dit = tf.next())
{
const typename PFP::VEC3& p1 = position[dit];
const typename PFP::VEC3& p2 = position[myMap.phi1(dit)];
const typename PFP::VEC3& p3 = position[myMap.phi_1(dit)];
normalF[dit] = ((p2 - p1) ^ (p3 - p1)).normalize();
}
TraversorV<PFP::MAP> tv(myMap);
for(Dart dit = tv.begin(); dit != tv.end(); dit = tv.next())
{
typename PFP::VEC3 n(0.0);
Traversor2VF<PFP::MAP> trav(myMap, dit);
for(Dart ditF = trav.begin(); ditF != trav.end(); ditF = trav.next())
n += normalF[ditF];
normalV[dit] = n.normalize();
}
}
virtual void smoothing_test()
{
TraversorV<PFP::MAP> tv(myMap);
for(Dart dit = tv.begin(); dit != tv.end(); dit = tv.next())
{
typename PFP::VEC3 p(0.0,0.0,0.0);
unsigned int c = 0;
Traversor2VVaE<PFP::MAP> trav2VVaE(myMap, dit);
for(Dart ditVV = trav2VVaE.begin() ; ditVV != trav2VVaE.end() ; ditVV = trav2VVaE.next())
{
p += position[ditVV];
++c;
}
p /= PFP::REAL(c);
position[dit] = p;
}
}
virtual void subdivision_test()
{
VertexAutoAttribute<PFP::VEC3> new_position(myMap);
//compute new positions of old vertices
TraversorV<PFP::MAP> tv(myMap);
for(Dart d = tv.begin(); d != tv.end(); d = tv.next())
{
unsigned int n = 0;
typename PFP::VEC3 p(0.0,0.0,0.0);
Traversor2VVaE<PFP::MAP> trav2VVaE(myMap, d);
for(Dart ditVV = trav2VVaE.begin() ; ditVV != trav2VVaE.end() ; ditVV = trav2VVaE.next())
{
p += position[ditVV];
++n;
}
typename PFP::REAL alpha = (4.0 - 2.0*cos(2.0*M_PI/PFP::REAL(n))) / 9.0;
new_position[d] = (1.0f-alpha)*position[d] + alpha/PFP::REAL(n)*p;
}
Dart last = myMap.end();
//split faces
AttributeHandler<Dart, FACE> qtF(&myMap, myMap.getQuickTraversal<FACE>());
unsigned int nbf = qtF.nbElements();
for(unsigned int i = qtF.begin(); i != nbf; ++i)
{
Dart d = qtF[i];
unsigned int c = 0;
typename PFP::VEC3 p(0.0,0.0,0.0);
//triangule face
Traversor2FV<PFP::MAP> trav(myMap, d);
for(Dart ditV = trav.begin(); ditV != trav.end(); ditV = trav.next())
{
p += position[ditV];
++c;
}
p /= PFP::REAL(c);
Dart cd = Algo::Surface::Modelisation::trianguleFace<PFP>(myMap, d);
new_position[cd] = p;
}
myMap.swapAttributes(position, new_position);
// flip old edges
for(Dart d = myMap.begin(); d != last; myMap.next(d))
{
if(d < myMap.phi2(d))
myMap.flipEdge(d);
}
}
virtual void collapse_test()
{
myMap.updateQuickTraversal<FACE>();
//split faces
DartMarkerNoUnmark me(myMap);
typename PFP::VEC3 p(0,0,0);
AttributeHandler<Dart, FACE> qtF(&myMap, myMap.getQuickTraversal<FACE>());
unsigned int nbf = qtF.end();
for(unsigned int i = qtF.begin(); i != nbf; ++i)
{
Dart d = qtF[i];
Dart cd = Algo::Surface::Modelisation::trianguleFace<PFP>(myMap, d);
position[cd] = p;
me.markOrbit<VERTEX>(cd);
}
myMap.disableQuickTraversal<VERTEX>();
TraversorV<typename PFP::MAP> travV(myMap);
for(Dart d = travV.begin() ; d != travV.end() ; d = travV.next())
{
if(me.isMarked(d))
myMap.deleteVertex(d);
}
}
virtual void remesh_test()
{
unsigned int nbOps = 1000;
TraversorF<typename PFP::MAP> travF(myMap);
for(Dart d = travF.begin(); d != travF.end(); d = travF.next())
{
Dart cd = Algo::Surface::Modelisation::trianguleFace<PFP>(myMap, d);
--nbOps;
if(nbOps == 0)
break;
}
nbOps = 1000;
TraversorE<typename PFP::MAP> travE(myMap);
for(Dart d = travE.begin(); d != travE.end(); d = travE.next())
{
if(myMap.edgeCanCollapse(d))
{
myMap.collapseEdge(d);
--nbOps;
}
if(nbOps == 0)
break;
}
}
};
//=============================================================================

View File

@ -0,0 +1,95 @@
#
# The following module is based on FindVTK.cmake
#
# - Find a CGAL installation or binary tree.
# The following variables are set if CGAL is found. If CGAL is not
# found, CGAL_FOUND is set to false.
#
# CGAL_FOUND - Set to true when CGAL is found.
# CGAL_USE_FILE - CMake file to use CGAL.
#
# Construct consitent error messages for use below.
set(CGAL_DIR_DESCRIPTION "directory containing CGALConfig.cmake. This is either the binary directory where CGAL was configured or PREFIX/lib/CGAL for an installation.")
set(CGAL_DIR_MESSAGE "CGAL not found. Set the CGAL_DIR cmake variable or environment variable to the ${CGAL_DIR_DESCRIPTION}")
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
if ( NOT CGAL_DIR )
# Get the system search path as a list.
if(UNIX)
string(REGEX MATCHALL "[^:]+" CGAL_DIR_SEARCH1 "$ENV{PATH}")
else()
string(REGEX REPLACE "\\\\" "/" CGAL_DIR_SEARCH1 "$ENV{PATH}")
endif()
string(REGEX REPLACE "/;" ";" CGAL_DIR_SEARCH2 "${CGAL_DIR_SEARCH1}")
# Construct a set of paths relative to the system search path.
set(CGAL_DIR_SEARCH "")
foreach(dir ${CGAL_DIR_SEARCH2})
set(CGAL_DIR_SEARCH ${CGAL_DIR_SEARCH} ${dir}/../lib/CGAL )
endforeach()
#
# Look for an installation or build tree.
#
find_path(CGAL_DIR CGALConfig.cmake
# Look for an environment variable CGAL_DIR.
$ENV{CGAL_DIR}
# Look in places relative to the system executable search path.
${CGAL_DIR_SEARCH}
# Look in standard UNIX install locations.
/usr/local/lib/CGAL
/usr/lib/CGAL
# Read from the CMakeSetup registry entries. It is likely that
# CGAL will have been recently built.
[HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild1]
[HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild2]
[HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild3]
[HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild4]
[HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild5]
[HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild6]
[HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild7]
[HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild8]
[HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild9]
[HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\Settings\\StartPath;WhereBuild10]
# Help the user find it if we cannot.
DOC "The ${CGAL_DIR_DESCRIPTION}"
)
endif()
if ( CGAL_DIR )
if ( EXISTS "${CGAL_DIR}/CGALConfig.cmake" )
include( "${CGAL_DIR}/CGALConfig.cmake" )
set( CGAL_FOUND TRUE )
endif()
endif()
if( NOT CGAL_FOUND)
if(CGAL_FIND_REQUIRED)
MESSAGE(FATAL_ERROR ${CGAL_DIR_MESSAGE})
else()
if(NOT CGAL_FIND_QUIETLY)
MESSAGE(STATUS ${CGAL_DIR_MESSAGE})
endif()
endif()
endif()
if(CGAL_FOUND)
message(STATUS "Found CGAL.")
endif()

View File

@ -0,0 +1,32 @@
# Find Mesquite. If found, this will define
#
# MESQUITE_FOUND - Successfully found Mesquite
# MESQUITE_INCLUDE_DIR - Mesquite include directory
# MESQUITE_LIBRARY_DIR - Mesquite library directory
# MESQUITE_LIBRARIES - Mesquite libraries
#
if(DEFINED MESQUITE_INCLUDE_DIR)
set(MESQUITE_FIND_QUIETLY TRUE)
else()
find_path(MESQUITE_INCLUDE_DIR Mesquite_all_headers.hpp
PATHS
/usr/local/include
/usr/include
$ENV{MESQUITE_DIR}/include
${MESQUITE_DIR}/include
)
if(NOT ${MESQUITE_INCLUDE_DIR} STREQUAL "MESQUITE_INCLUDE_DIR-NOTFOUND")
message(STATUS "Found Mesquite: " ${MESQUITE_INCLUDE_DIR})
set(MESQUITE_FOUND true)
set(MESQUITE_LIBRARY_DIR "${MESQUITE_INCLUDE_DIR}/../lib/" CACHE PATH "Mesquite library directory")
set(MESQUITE_LIBRARIES "mesquite" CACHE STRING "Mesquite libraries")
else()
set(MESQUITE_FOUND FALSE)
endif()
endif()

View File

@ -0,0 +1,40 @@
# Find OpenMesh. If found, this will define
#
# OPENMESH_FOUND - Successfully found OpenMesh
# OPENMESH_INCLUDE_DIR - OpenMesh include directory
# OPENMESH_LIBRARIES - OpenMesh libraries
# OPENMESH_LIBRARY_DIR - OpenMesh library directory
#
if(DEFINED OPENMESH_INCLUDE_DIR)
set(OPENMESH_FIND_QUIETLY TRUE)
else()
find_path(OPENMESH_INCLUDE_DIR OpenMesh/Core/Mesh/PolyMeshT.hh
PATHS
/usr/local/include
/usr/include
$ENV{OPENMESH_DIR}/include
${OPENMESH_DIR}/include
)
if(DEFINED OPENMESH_INCLUDE_DIR)
message(STATUS "Found OpenMesh: " ${OPENMESH_INCLUDE_DIR})
set(OPENMESH_FOUND true)
if(WIN32)
set(OPENMESH_LIBRARY_DIR "${OPENMESH_INCLUDE_DIR}/../lib"
CACHE PATH "OpenMesh library directory")
else()
set(OPENMESH_LIBRARY_DIR "${OPENMESH_INCLUDE_DIR}/../lib/OpenMesh"
CACHE PATH "OpenMesh library directory")
endif()
set(OPENMESH_LIBRARIES "OpenMeshCore;OpenMeshTools"
CACHE STRING "OpenMesh libraries")
else()
set(OPENMESH_FOUND FALSE)
endif()
endif()

View File

@ -0,0 +1,20 @@
//== INCLUDES =================================================================
#include "lcc_performance_2.h"
//=============================================================================
int main(int argc, char** argv)
{
if (argc < 2)
{
std::cerr << "Usage:\n" << argv[0] << " <input-mesh>\n";
exit(1);
}
for (int i=1; i<argc; ++i)
{
std::cout<<"**************** "<<argv[i]<<" ****************"<<std::endl;
LCC_performance_2().run(argv[i], "output_lcc_2.off");
}
return 0;
}
//=============================================================================

View File

@ -0,0 +1,382 @@
//== INCLUDES =================================================================
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Linear_cell_complex.h>
#include <CGAL/Linear_cell_complex_constructors.h>
#include <iostream>
#include <fstream>
#include "performance_2.h"
// Comment to use cmap with handle
#define CMAP_WITH_INDEX 1
//== CLASS DEFINITION =========================================================
typedef CGAL::Simple_cartesian<double> MyKernelLCC;
typedef MyKernelLCC::Point_3 LCCPoint_3;
typedef MyKernelLCC::Vector_3 LCCVector_3;
typedef CGAL::Linear_cell_complex_traits<3, MyKernelLCC> MyTraitsLCC;
#ifndef CMAP_WITH_INDEX
class MyItemsLCC
{
public:
template <class LCC>
struct Dart_wrapper
{
typedef CGAL::Dart<2, LCC> Dart; // Dim 2 == Polyhedron
typedef CGAL::Cell_attribute_with_point<LCC, LCCVector_3, CGAL::Tag_true> Vertex;
typedef CGAL::Cell_attribute<LCC, LCCVector_3, CGAL::Tag_true> Face;
typedef CGAL::cpp0x::tuple<Vertex,void,Face> Attributes;
};
};
typedef CGAL::Linear_cell_complex<2, 3, MyTraitsLCC, MyItemsLCC> LCC;
#else
class MyItemsLCCWithIndex
{
public:
template <class LCC>
struct Dart_wrapper
{
typedef CGAL::Dart_for_index<2, LCC> Dart; // Dim 2 == Polyhedron
typedef CGAL::Cell_attribute_for_index_with_point<LCC, LCCVector_3, CGAL::Tag_true> Vertex;
typedef CGAL::Cell_attribute_for_index<LCC, LCCVector_3, CGAL::Tag_true> Face;
typedef CGAL::cpp0x::tuple<Vertex,void,Face> Attributes;
};
};
typedef CGAL::Linear_cell_complex_for_index<2, 3, MyTraitsLCC, MyItemsLCCWithIndex> LCC;
#endif
//== CLASS DEFINITION =========================================================
class LCC_performance_2 : public Performance_test_2
{
private:
LCC lcc;
private:
void display_info()
{
lcc.display_characteristics(std::cout);
std::cout << "\t" << std::endl;
}
virtual bool read_mesh(const char* _filename)
{
std::ifstream ifs(_filename);
CGAL::load_off(lcc, ifs);
for ( LCC::Dart_range::iterator dit=lcc.darts().begin(),
dend=lcc.darts().end(); dit!=dend; ++dit )
{
if ( lcc.attribute<2>(dit)==NULL )
lcc.set_attribute<2>(dit, lcc.create_attribute<2>());
}
assert( lcc.is_valid());
return true;
}
virtual bool write_mesh(const char* _filename)
{
std::ofstream ofs(_filename);
CGAL::write_off(lcc, ofs);
return true;
}
virtual int circulator_test()
{
LCC::Vertex_attribute_range::iterator vit, vend = lcc.vertex_attributes().end();
LCC::Attribute_range<2>::type::iterator fit, fend = lcc.attributes<2>().end();
int counter = 0;
for (vit = lcc.vertex_attributes().begin(); vit != vend; ++vit)
{
for( LCC::Dart_of_cell_range<0>::iterator
vhit = lcc.darts_of_cell<0>(vit->dart()).begin(),
vhend = lcc.darts_of_cell<0>(vit->dart()).end();
vhit!=vhend; ++vhit )
{
++counter;
}
}
for (fit = lcc.attributes<2>().begin(); fit != fend; ++fit)
{
for( LCC::Dart_of_cell_range<2>::iterator
fhit = lcc.darts_of_cell<2>(fit->dart()).begin(),
fhend = lcc.darts_of_cell<2>(fit->dart()).end();
fhit!=fhend; ++fhit )
{
--counter;
}
}
return counter;
}
virtual void barycenter_test(bool draw)
{
LCC::Vertex_attribute_range::iterator vit, vend = lcc.vertex_attributes().end();
LCCVector_3 v(CGAL::NULL_VECTOR);
for (vit = lcc.vertex_attributes().begin(); vit != vend; ++vit)
{
v = v + (vit->point() - CGAL::ORIGIN);
}
v = v / lcc.number_of_vertex_attributes();
for (vit = lcc.vertex_attributes().begin(); vit != vend; ++vit)
{
vit->point() = vit->point() - v;
}
if ( draw ) std::cout<<"Barycenter: "<<v<<std::endl;
}
virtual void normal_test()
{
LCC::Vertex_attribute_range::iterator vit, vend = lcc.vertex_attributes().end();
LCC::Attribute_range<2>::type::iterator fit, fend = lcc.attributes<2>().end();
for (fit = lcc.attributes<2>().begin(); fit != fend; ++fit)
{
LCC::Dart_handle dh = fit->dart();
LCCPoint_3& p0 = lcc.point(dh);
dh = lcc.beta<1>(dh);
LCCPoint_3& p1 = lcc.point(dh);
dh = lcc.beta<1>(dh);
LCCPoint_3& p2 = lcc.point(dh);
LCCVector_3 n = cross_product(p0-p1, p2-p1);
n = n / sqrt(n.squared_length());
fit->info() = n;
}
for (vit = lcc.vertex_attributes().begin(); vit != vend; ++vit)
{
LCCVector_3 n(0,0,0);
for( LCC::Dart_of_cell_range<0>::iterator
vhit = lcc.darts_of_cell<0>(vit->dart()).begin(),
vhend = lcc.darts_of_cell<0>(vit->dart()).end();
vhit!=vhend; ++vhit )
{
n = n + lcc.info<2>(vhit);
}
n = n / sqrt(n.squared_length());
vit->info() = n;
}
}
virtual void smoothing_test()
{
LCC::Vertex_attribute_range::iterator vit, vend = lcc.vertex_attributes().end();
for (vit = lcc.vertex_attributes().begin(); vit != vend; ++vit)
{
bool vertex_is_border = false;
LCCVector_3 v(0,0,0);
float c(0);
for( LCC::Dart_of_cell_range<0>::iterator
vhit = lcc.darts_of_cell<0>(vit->dart()).begin(),
vhend = lcc.darts_of_cell<0>(vit->dart()).end();
vhit!=vhend; ++vhit )
{
if (lcc.is_free<2>(vhit))
{
vertex_is_border = true;
break;
}
v = v + (lcc.point(lcc.other_extremity(vhit)) - CGAL::ORIGIN);
++c;
}
if (!vertex_is_border)
vit->point() = CGAL::ORIGIN + (v / c);
}
assert( lcc.is_valid());
}
void flip_edge(LCC::Dart_handle d)
{
LCC::Dart_handle d1 = lcc.beta<1>(d);
LCC::Dart_handle d2 = lcc.beta<2, 1>(d);
CGAL_assertion ( !lcc.is_free<1>(d1) && !lcc.is_free<1>(d2) );
LCC::Dart_handle d3 = lcc.beta<1>(d1);
LCC::Dart_handle d4 = lcc.beta<1>(d2);
// We isolated the edge
lcc.link_beta_1(lcc.beta<0>(d), d2);
lcc.link_beta_1(lcc.beta<2,0>(d), d1);
// Then we push the two extremities.
lcc.basic_link_beta_0(d3, d);
lcc.basic_link_beta_1(d1, lcc.beta<2>(d));
lcc.basic_link_beta_1(d2, d);
lcc.basic_link_beta_0(d4, lcc.beta<2>(d));
// And we update the vertex attribute
lcc.set_vertex_attribute_of_dart(d, lcc.vertex_attribute(d4));
lcc.set_vertex_attribute_of_dart(lcc.beta<2>(d), lcc.vertex_attribute(d3));
}
virtual void subdivision_test()
{
int nv = lcc.number_of_vertex_attributes();
// iterators
LCC::Vertex_attribute_range::iterator vit, vend = lcc.vertex_attributes().end();
LCC::Attribute_range<2>::type::iterator fit, fend = lcc.attributes<2>().end();
LCC::Dart_range::iterator dit, dend =lcc.darts().end();
// compute new positions of old vertices
int i;
std::vector<LCCPoint_3> new_pos(nv);
for (vit = lcc.vertex_attributes().begin(), i=0; vit != vend; ++vit, ++i)
{
bool vertex_is_border = false;
LCCVector_3 v(0,0,0);
float n = 0;
for( LCC::Dart_of_cell_range<0>::iterator
vhit = lcc.darts_of_cell<0>(vit->dart()).begin(),
vhend = lcc.darts_of_cell<0>(vit->dart()).end();
vhit!=vhend; ++vhit )
{
if (lcc.is_free<2>(vhit))
{
vertex_is_border = true;
break;
}
v = v + (lcc.point(lcc.other_extremity(vhit)) - CGAL::ORIGIN);
++n;
}
if (!vertex_is_border)
{
float alpha = (4.0 - 2.0*cos(2.0*M_PI/n)) / 9.0;
v = (1.0f-alpha)*(vit->point() - CGAL::ORIGIN) + alpha/n*v;
new_pos[i] = CGAL::ORIGIN + v;
}
else
{
new_pos[i] = vit->point();
}
}
// adjust end iterators
--vend; --fend; --dend;
// split faces
fit = lcc.attributes<2>().begin();
do
{
lcc.insert_barycenter_in_cell<2>(fit->dart());
}
while (fit++ != fend);
// adjust end iterators
++vend; ++fend; ++dend;
// set new positions of old vertices
for (vit = lcc.vertex_attributes().begin(), i=0; vit != vend; ++vit, ++i)
vit->point() = new_pos[i];
// flip old edges
for (dit = lcc.darts().begin(); dit != dend; ++dit)
{
if (!lcc.is_free<2>(dit) && dit<lcc.beta<2>(dit) )
flip_edge(dit);
}
assert( lcc.is_valid());
}
virtual void collapse_test()
{
LCC::Attribute_range<0>::type::iterator vit, vend = lcc.attributes<0>().end();
LCC::Attribute_range<2>::type::iterator fit, fend = lcc.attributes<2>().end();
// adjust end iterators
--vend; --fend;
fit = lcc.attributes<2>().begin();
do
{
lcc.insert_point_in_cell<2>(fit->dart(), CGAL::ORIGIN);
}
while (fit++ != fend);
// adjust end iterators
++vend;
// collapse new vertices
vit=vend; vend=lcc.attributes<0>().end();
for (; vit!=vend; )
{
LCC::Dart_handle cur = vit->dart();
++vit;
collapse_edge(cur);
}
assert( lcc.is_valid());
}
void contract_face(LCC::Dart_handle dh)
{
CGAL_assertion( dh!=lcc.null_dart_handle );
LCC::Dart_handle d1=lcc.beta<2>(dh);
LCC::Dart_handle d2=lcc.beta<1,2>(dh);
CGAL_assertion(d1!=lcc.null_dart_handle &&
d2!=lcc.null_dart_handle);
lcc.basic_link_beta<2>(d1, d2);
lcc.set_dart_of_attribute<0>(lcc.vertex_attribute(d1), d1);
lcc.set_dart_of_attribute<0>(lcc.vertex_attribute(d2), d2);
lcc.erase_dart(lcc.beta<1>(dh));
lcc.erase_dart(dh);
}
void collapse_edge(LCC::Dart_handle dh)
{
CGAL_assertion( dh!=lcc.null_dart_handle );
CGAL_assertion(!lcc.is_free<2>(dh));
LCC::Dart_handle h1=lcc.beta<0>(dh);
LCC::Dart_handle o1=lcc.beta<2,1>(dh);
lcc.set_attribute<0>(dh, lcc.attribute<0>(lcc.beta<2>(dh)));
lcc.basic_link_beta_1(lcc.beta<2,0>(dh),lcc.beta<2,1>(dh));
lcc.basic_link_beta_1(lcc.beta<0>(dh),lcc.beta<1>(dh));
lcc.erase_dart(lcc.beta<2>(dh));
lcc.erase_dart(dh);
if (lcc.beta<1,1>(h1)==h1)
{
contract_face(h1);
}
if (lcc.beta<1,1>(o1)==o1)
{
contract_face(o1);
}
}
};
//=============================================================================

View File

@ -0,0 +1 @@
/home/gdamiand/sources/codes-autres/OpenMesh/builds/install/

View File

@ -0,0 +1,20 @@
//== INCLUDES =================================================================
#include "openmesh_performance.h"
//=============================================================================
int main(int argc, char** argv)
{
if (argc < 2)
{
std::cerr << "Usage:\n" << argv[0] << " <input-mesh>\n";
exit(1);
}
for (int i=1; i<argc; ++i)
{
std::cout<<"**************** "<<argv[i]<<" ****************"<<std::endl;
OpenMesh_performance().run(argv[i], "output_openmesh.off");
}
return 0;
}
//=============================================================================

View File

@ -0,0 +1,230 @@
//== INCLUDES =================================================================
#include "performance_2.h"
#include "OpenMesh/Core/IO/MeshIO.hh"
#include "OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh"
//== CLASS DEFINITION =========================================================
class OpenMesh_performance : public Performance_test_2
{
public:
OpenMesh_performance() : Performance_test_2()
{
mesh.request_vertex_status();
mesh.request_edge_status();
mesh.request_face_status();
mesh.request_vertex_normals();
mesh.request_face_normals();
}
private:
struct MyTraits : public OpenMesh::DefaultTraits
{
typedef OpenMesh::Vec3d Point;
typedef OpenMesh::Vec3d Normal;
};
typedef OpenMesh::TriMesh_ArrayKernelT<MyTraits> Mesh;
Mesh mesh;
private:
void display_info()
{
std::cout << "#Darts=" << mesh.n_halfedges();
std::cout << ", #0-cells=" << mesh.n_vertices();
std::cout << ", #1-cells=" << mesh.n_edges();
std::cout << ", #2-cells=" << mesh.n_faces();
std::cout << "\t" << std::endl;
}
virtual bool read_mesh(const char* _filename)
{
return OpenMesh::IO::read_mesh(mesh, _filename);
}
virtual bool write_mesh(const char* _filename)
{
return OpenMesh::IO::write_mesh(mesh, _filename);
}
virtual int circulator_test()
{
Mesh::VIter vit, vend=mesh.vertices_end();
Mesh::FIter fit, fend=mesh.faces_end();
int counter = 0;
for (vit=mesh.vertices_begin(); vit!=vend; ++vit)
for (Mesh::VFIter vfit=mesh.vf_iter(vit); vfit; ++vfit)
++counter;
for (fit=mesh.faces_begin(); fit!=fend; ++fit)
for (Mesh::FVIter fvit=mesh.fv_iter(fit); fvit; ++fvit)
--counter;
return counter;
}
virtual void barycenter_test(bool draw)
{
Mesh::VIter vit, vend=mesh.vertices_end();
Mesh::Point p(0,0,0);
for (vit=mesh.vertices_begin(); vit!=vend; ++vit)
p += mesh.point(vit);
p /= mesh.n_vertices();
for (vit=mesh.vertices_begin(); vit!=vend; ++vit)
mesh.point(vit) -= p;
if ( draw ) std::cout<<"Barycenter: "<<p<<std::endl;
}
virtual void normal_test()
{
Mesh::VIter vit, vend=mesh.vertices_end();
Mesh::FIter fit, fend=mesh.faces_end();
Mesh::VFIter vfit;
for (fit=mesh.faces_begin(); fit!=fend; ++fit)
{
Mesh::HalfedgeHandle h = mesh.halfedge_handle(fit);
Mesh::Point p0 = mesh.point(mesh.to_vertex_handle(h));
h = mesh.next_halfedge_handle(h);
Mesh::Point p1 = mesh.point(mesh.to_vertex_handle(h));
h = mesh.next_halfedge_handle(h);
Mesh::Point p2 = mesh.point(mesh.to_vertex_handle(h));
mesh.set_normal(fit, ((p2-=p1)%(p0-=p1)).normalize());
}
for (vit=mesh.vertices_begin(); vit!=vend; ++vit)
{
Mesh::Point n(0,0,0);
for (vfit=mesh.vf_iter(vit); vfit; ++vfit)
n += mesh.normal(vfit);
mesh.set_normal(vit, n.normalize());
}
}
virtual void smoothing_test()
{
Mesh::VIter vit, vend=mesh.vertices_end();
for (vit=mesh.vertices_begin(); vit!=vend; ++vit)
{
if (!mesh.is_boundary(vit))
{
Mesh::Point p(0,0,0);
Mesh::Scalar c(0);
for (Mesh::VVIter vvit = mesh.vv_iter(vit); vvit; ++vvit)
{
p += mesh.point(vvit);
++c;
}
p /= c;
mesh.point(vit) = p;
}
}
}
virtual void subdivision_test()
{
// reserve memory
int nv = mesh.n_vertices();
int ne = mesh.n_edges();
int nf = mesh.n_faces();
mesh.reserve(nv+nf, ne+3*nf, 3*nf);
// iterators
Mesh::VIter vit, vend=mesh.vertices_end();
Mesh::FIter fit, fend=mesh.faces_end();
Mesh::EIter eit, eend=mesh.edges_end();
// compute new positions of old vertices
OpenMesh::VPropHandleT<Mesh::Point> new_pos;
mesh.add_property(new_pos);
for (vit=mesh.vertices_begin(); vit!=vend; ++vit)
{
if (!mesh.is_boundary(vit))
{
Mesh::Scalar n = mesh.valence(vit);
Mesh::Scalar alpha = (4.0 - 2.0*cos(2.0*M_PI/n)) / 9.0;
Mesh::Point p(0,0,0);
for (Mesh::VVIter vvit = mesh.vv_iter(vit); vvit; ++vvit)
p += mesh.point(vvit);
p = (1.0f-alpha)*mesh.point(vit) + alpha/n*p;
mesh.property(new_pos, vit) = p;
}
}
// split faces
for (fit=mesh.faces_begin(); fit!=fend; ++fit)
{
Mesh::Point p(0,0,0);
Mesh::Scalar c(0);
for (Mesh::FVIter fvit=mesh.fv_iter(fit); fvit; ++fvit)
{
p += mesh.point(fvit);
++c;
}
p /= c;
mesh.split(fit, p);
}
// set new positions of old vertices
for (vit=mesh.vertices_begin(); vit!=vend; ++vit)
if (!mesh.is_boundary(vit))
mesh.point(vit) = mesh.property(new_pos, vit);
mesh.remove_property(new_pos);
// flip old edges
for (eit=mesh.edges_begin(); eit!=eend; ++eit)
if (mesh.is_flip_ok(eit))
mesh.flip(eit);
}
virtual void collapse_test()
{
// reserve memory
int nv = mesh.n_vertices();
int ne = mesh.n_edges();
int nf = mesh.n_faces();
mesh.reserve(nv+nf, ne+3*nf, 3*nf);
// iterators
Mesh::VIter vit, vend=mesh.vertices_end();
Mesh::FIter fit, fend=mesh.faces_end();
// split faces
Mesh::Point p(0,0,0);
for (fit=mesh.faces_begin(); fit!=fend; ++fit)
mesh.split(fit, p);
// collapse new edges
vit = vend; vend=mesh.vertices_end();
for (; vit!=vend; ++vit)
mesh.collapse(mesh.halfedge_handle(vit));
// remove deleted items
mesh.garbage_collection();
}
virtual void remesh_test()
{
}
};
//=============================================================================

View File

@ -0,0 +1,47 @@
//== INCLUDES =================================================================
#include "polyhedron_performance.h"
#include "lcc_performance_2.h"
#include "openmesh_performance.h"
#include "surface_mesh_performance.h"
#include "cgogn_performance_2.h"
//=============================================================================
int main(int argc, char** argv)
{
if (argc < 2)
{
std::cerr << "Usage:\nperformance <input-mesh>\n";
exit(1);
}
for (int i=1; i<argc; ++i)
{
std::cout<<"**************** "<<argv[i]<<" ****************"<<std::endl;
{
std::cout << "Polyhedron\t" << std::endl;
Polyhedron_performance().run(argv[i], "output_polyhedron.off");
}
{
std::cout << "LCC_2\t" << std::endl;
LCC_performance_2().run(argv[1], "output_lcc_2.off");
}
{
std::cout << "OpenMesh\t" << std::endl;
OpenMesh_performance().run(argv[1], "output_open_mesh.off");
}
{
std::cout << "Surface_mesh\t" << std::endl;
Surface_mesh_performance().run(argv[1], "output_surface_mesh.off");
}
{
std::cout << "CGoGn_2\t" << std::endl;
CGoGN_performance_2().run(argv[1], "output_cgogn_2.off");
}
}
return 0;
}
//=============================================================================

View File

@ -0,0 +1,99 @@
//=============================================================================
#ifndef PERFORMANCE_2_TEST_H
#define PERFORMANCE_2_TEST_H
//== INCLUDES =================================================================
#include <cstdlib>
#include <iostream>
#include <sys/resource.h>
#include <CGAL/assertions.h>
#include "Stop_watch.h"
//== CLASS DEFINITION =========================================================
class Performance_test_2
{
public:
Performance_test_2() {}
void run(const char* input, const char* output)
{
graphene::StopWatch timer;
timer.start();
if (!read_mesh(input)) { std::cerr << "read error\n"; exit(1); }
timer.stop();
std::cout << "Read mesh : " << timer << std::endl;
display_info();
timer.start();
int c;
for (int i=0; i<100; ++i)
c = circulator_test();
timer.stop();
CGAL_assertion(c==0);
std::cout << "Circulator: "<<c<<"; time: " << timer << std::endl;
timer.start();
for (int i=0; i<1000; ++i)
barycenter_test(i==0);
timer.stop();
std::cout << "Barycenter : " << timer << std::endl;
timer.start();
for (int i=0; i<100; ++i)
normal_test();
timer.stop();
std::cout << "Normals : " << timer << std::endl;
timer.start();
for (int i=0; i<100; ++i)
smoothing_test();
timer.stop();
std::cout << "Smoothing : " << timer << std::endl;
timer.start();
subdivision_test();
timer.stop();
std::cout << "Subdivision : " << timer << std::endl;
display_info();
timer.start();
collapse_test();
timer.stop();
std::cout << "Collapse : " << timer << std::endl;
display_info();
timer.start();
if (!write_mesh(output)) { std::cerr << "write error\n"; exit(1); }
timer.stop();
std::cout << "Write mesh : " << timer << std::endl;
std::cout << std::endl;
}
protected:
virtual bool read_mesh(const char* _filename) = 0;
virtual bool write_mesh(const char* _filename) = 0;
virtual int circulator_test() { return 0; }
virtual void barycenter_test(bool) {}
virtual void normal_test() {}
virtual void smoothing_test() {}
virtual void subdivision_test() {}
virtual void collapse_test() {}
virtual void display_info() {}
};
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,20 @@
//== INCLUDES =================================================================
#include "polyhedron_performance.h"
//=============================================================================
int main(int argc, char** argv)
{
if (argc < 2)
{
std::cerr << "Usage:\n" << argv[0] << " <input-mesh>\n";
exit(1);
}
for (int i=1; i<argc; ++i)
{
std::cout<<"**************** "<<argv[i]<<" ****************"<<std::endl;
Polyhedron_performance().run(argv[i], "output_polyhedron.off");
}
return 0;
}
//=============================================================================

View File

@ -0,0 +1,430 @@
//== INCLUDES =================================================================
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/HalfedgeDS_vector.h>
#include <CGAL/HalfedgeDS_list.h>
#include <CGAL/HalfedgeDS_vertex_base.h>
#include <CGAL/HalfedgeDS_halfedge_base.h>
#include <CGAL/HalfedgeDS_face_base.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <iostream>
#include <fstream>
#include "performance_2.h"
//== CLASS DEFINITION =========================================================
//*****************************************************************************
// control whether Polyhedron stores vertex and face normals
#define HAS_NORMALS 1
//*****************************************************************************
typedef CGAL::Simple_cartesian<double> CGALKernel;
typedef CGALKernel::Point_3 Point_3;
typedef CGAL::Vector_3<CGALKernel> Vector_3;
template <class Refs>
struct MyVertex : public CGAL::HalfedgeDS_vertex_base<Refs, CGAL::Tag_true, Point_3>
{
typedef CGAL::HalfedgeDS_vertex_base<Refs, CGAL::Tag_true, Point_3> Base;
MyVertex() : Base() {}
MyVertex(const Point_3& p) : Base(p) {}
Vector_3 normal;
};
template <class Refs>
struct MyFace : public CGAL::HalfedgeDS_face_base<Refs>
{
Vector_3 normal;
};
class MyItems
{
public:
template <class Refs, class Traits>
struct Vertex_wrapper
{
typedef typename Traits::Point_3 Point;
#if HAS_NORMALS
typedef MyVertex<Refs> Vertex;
#else
typedef CGAL::HalfedgeDS_vertex_base<Refs, CGAL::Tag_true, Point> Vertex;
#endif
};
template <class Refs, class Traits>
struct Halfedge_wrapper
{
typedef CGAL::HalfedgeDS_halfedge_base<Refs> Halfedge;
};
template <class Refs, class Traits>
struct Face_wrapper
{
#if HAS_NORMALS
typedef MyFace<Refs> Face;
#else
typedef CGAL::HalfedgeDS_face_base<Refs> Face;
#endif
};
};
typedef CGAL::Polyhedron_3<CGALKernel, MyItems, CGAL::HalfedgeDS_list> Polyhedron;
//== CLASS DEFINITION =========================================================
class Polyhedron_performance : public Performance_test_2
{
private:
Polyhedron P;
private:
virtual void display_info()
{
std::cout<<"#darts: "<<P.size_of_halfedges()
<<" #0-cells: "<<P.size_of_vertices()
<<" #2-cells: "<<P.size_of_facets()<<std::endl;
}
virtual bool read_mesh(const char* _filename)
{
std::ifstream ifs(_filename);
ifs >> P;
return true;
}
virtual bool write_mesh(const char* _filename)
{
std::ofstream ofs(_filename);
ofs << P;
return true;
}
virtual int circulator_test()
{
Polyhedron::Vertex_iterator vit, vend=P.vertices_end();
Polyhedron::Face_iterator fit, fend=P.facets_end();
Polyhedron::Halfedge_around_vertex_circulator vhit, vhend;
Polyhedron::Halfedge_around_facet_circulator fhit, fhend;
int counter = 0;
for (vit = P.vertices_begin(); vit != vend; ++vit)
{
vhit = vhend = vit->vertex_begin();
do
{
if (!vhit->is_border())
++counter;
}
while (++vhit != vhend);
}
for (fit = P.facets_begin(); fit != fend; ++fit)
{
fhit = fhend = fit->facet_begin();
do
{
--counter;
}
while (++fhit != fhend);
}
return counter;
}
virtual void barycenter_test(bool draw)
{
Polyhedron::Vertex_iterator vit, vend=P.vertices_end();
Vector_3 v(CGAL::NULL_VECTOR);
for (vit = P.vertices_begin(); vit != vend; ++vit)
{
v = v + (vit->point() - CGAL::ORIGIN);
}
v = v / P.size_of_vertices();
for (vit = P.vertices_begin(); vit != vend; ++vit)
{
vit->point() = vit->point() - v;
}
if (draw) std::cout<<"Barycenter="<<v<<std::endl;
}
virtual void normal_test()
{
#if HAS_NORMALS
Polyhedron::Vertex_iterator vit, vend=P.vertices_end();
Polyhedron::Face_iterator fit, fend=P.facets_end();
Polyhedron::Halfedge_around_vertex_circulator vhit, vhend;
for (fit = P.facets_begin(); fit != fend; ++fit)
{
Polyhedron::Halfedge_handle h = fit->halfedge();
Point_3& p0 = h->vertex()->point();
h = h->next();
Point_3& p1 = h->vertex()->point();
h = h->next();
Point_3& p2 = h->vertex()->point();
Vector_3 n = cross_product(p0-p1, p2-p1);
n = n / sqrt(n.squared_length());
fit->normal = n;
}
for (vit=P.vertices_begin(); vit!=vend; ++vit)
{
Vector_3 n(0,0,0);
vhit = vhend = vit->vertex_begin();
do
{
if (!vhit->is_border())
n = n + vhit->face()->normal;
}
while (++vhit != vhend);
n = n / sqrt(n.squared_length());
vit->normal = n;
}
#endif
}
virtual void smoothing_test()
{
Polyhedron::Vertex_iterator vit, vend=P.vertices_end();
for (vit = P.vertices_begin(); vit != vend; ++vit)
{
bool vertex_is_border = false;
Vector_3 v(0,0,0);
float c(0);
Polyhedron::Halfedge_around_vertex_circulator hc = vit->vertex_begin();
do
{
if (hc->is_border() || hc->opposite()->is_border())
{
vertex_is_border = true;
break;
}
v = v + (hc->opposite()->vertex()->point() - CGAL::ORIGIN);
++c;
}
while (++hc != vit->vertex_begin());
if (!vertex_is_border)
vit->point() = CGAL::ORIGIN + (v / c);
}
}
virtual void subdivision_test()
{
int nv = P.size_of_vertices();
int nh = P.size_of_halfedges();
int nf = P.size_of_facets();
P.reserve(nv+nf, nh+6*nf, 3*nf);
// iterators
Polyhedron::Vertex_iterator vit, vend = P.vertices_end();
Polyhedron::Face_iterator fit, fend = P.facets_end();
Polyhedron::Edge_iterator eit, eend = P.edges_end();
// compute new positions of old vertices
int i;
std::vector<Point_3> new_pos(nv);
for (vit=P.vertices_begin(), i=0; vit!=vend; ++vit, ++i)
{
bool is_border = false;
Vector_3 v(0,0,0);
float n = CGAL::circulator_size(vit->vertex_begin());
float alpha = (4.0 - 2.0*cos(2.0*M_PI/n)) / 9.0;
Polyhedron::Halfedge_around_vertex_circulator hc = vit->vertex_begin();
do
{
if (hc->is_border() || hc->opposite()->is_border())
{
is_border = true;
break;
}
v = v + (hc->opposite()->vertex()->point() - CGAL::ORIGIN);
}
while (++hc != vit->vertex_begin());
v = (1.0f-alpha)*(vit->point() - CGAL::ORIGIN) + alpha/n*v;
new_pos[i] = (is_border ? vit->point() : CGAL::ORIGIN + v);
}
// adjust end iterators
--vend; --eend; --fend;
// split faces (a for loop does not work for list-kernel!)
fit = P.facets_begin();
do
{
Vector_3 v(CGAL::NULL_VECTOR);
float c(0);
Polyhedron::Halfedge_around_facet_circulator hc = fit->facet_begin();
Polyhedron::Halfedge_around_facet_circulator hc_end(hc);
do
{
v = v + (hc->vertex()->point() - CGAL::ORIGIN);
++c;
}
while (++hc != hc_end);
v = v / c;
Polyhedron::Halfedge_handle h = P.create_center_vertex(fit->halfedge());
h->vertex()->point() = CGAL::ORIGIN + v;
}
while (fit++ != fend);
// adjust end iterators
++vend; ++eend; ++fend;
// set new positions of old vertices
for (vit=P.vertices_begin(), i=0; vit!=vend; ++vit, ++i)
vit->point() = new_pos[i];
// flip old edges
for (eit = P.edges_begin(); eit!=eend; ++eit)
{
// careful: eit->is_border() does not work
Polyhedron::Halfedge_handle h = eit;
if (!(h->is_border() || h->opposite()->is_border()))
P.flip_edge(h);
}
}
virtual void collapse_test()
{
// reserve memory
int nv = P.size_of_vertices();
int nh = P.size_of_halfedges();
int nf = P.size_of_facets();
P.reserve(nv+nf, nh+6*nf, 3*nf);
// iterators
Polyhedron::Vertex_iterator vit, vend = P.vertices_end();
Polyhedron::Face_iterator fit, fend = P.facets_end();
// adjust end iterators
--vend; --fend;
// split faces (a for loop does not work for list-kernel!)
Point_3 p(0,0,0);
fit = P.facets_begin();
do
{
Polyhedron::Halfedge_handle h = P.create_center_vertex(fit->halfedge());
h->vertex()->point() = p;
}
while (++fit != fend);
// adjust end iterators
++vend; ++fend;
// collapse new edges
vit=vend; vend=P.vertices_end();
for (; vit!=vend; ++vit)
halfedge_collapse(vit->halfedge()->opposite());
}
void halfedge_collapse(Polyhedron::Halfedge_handle pq)
{
// this code is copied from the CGAL surface simplification package
Polyhedron::Halfedge_handle qp = pq->opposite();
Polyhedron::Halfedge_handle pt = pq->prev()->opposite();
Polyhedron::Halfedge_handle qb = qp->prev()->opposite();
bool lTopFaceExists = !pq->is_border() ;
bool lBottomFaceExists = !qp->is_border() ;
bool lTopLeftFaceExists = lTopFaceExists && !pt->is_border() ;
bool lBottomRightFaceExists = lBottomFaceExists && !qb->is_border() ;
Polyhedron::Vertex_handle q = pq->vertex();
Polyhedron::Vertex_handle p = pq->opposite()->vertex();
bool lP_Erased = false, lQ_Erased = false ;
if ( lTopFaceExists )
{
if ( lTopLeftFaceExists )
{
P.join_facet (pt);
}
else
{
P.erase_facet(pt->opposite());
if ( !lBottomFaceExists )
{
lP_Erased = true ;
}
}
}
if ( lBottomFaceExists )
{
if ( lBottomRightFaceExists )
{
P.join_facet (qb);
}
else
{
P.erase_facet(qb->opposite());
if ( !lTopFaceExists )
{
lQ_Erased = true ;
}
}
}
if ( !lP_Erased && !lQ_Erased )
{
P.join_vertex(pq);
lP_Erased = true ;
}
}
};
//=============================================================================

View File

@ -0,0 +1,10 @@
include_directories(${CMAKE_SOURCE_DIR}/src/)
file(GLOB_RECURSE SRCS ./*.cpp)
file(GLOB_RECURSE HDRS ./*.h)
if(UNIX)
add_library(surface_mesh SHARED ${SRCS} ${HDRS})
elseif(WIN32)
add_library(surface_mesh STATIC ${SRCS} ${HDRS})
endif()

View File

@ -0,0 +1,74 @@
//=============================================================================
// Copyright (C) 2001-2005 by Computer Graphics Group, RWTH Aachen
// Copyright (C) 2011 by Graphics & Geometry Group, Bielefeld University
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License
// as published by the Free Software Foundation, version 2.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
//== INCLUDES =================================================================
#include "IO.h"
//== IMPLEMENTATION ===========================================================
bool read_mesh(Surface_mesh& mesh, const std::string& filename)
{
// clear mesh before reading from file
mesh.clear();
// extract file extension
std::string::size_type dot(filename.rfind("."));
if (dot == std::string::npos) return false;
std::string ext = filename.substr(dot+1, filename.length()-dot-1);
std::transform(ext.begin(), ext.end(), ext.begin(), tolower);
// extension determines reader
if (ext == "off")
{
return read_off(mesh, filename);
}
// we didn't find a reader module
return false;
}
//-----------------------------------------------------------------------------
bool write_mesh(const Surface_mesh& mesh, const std::string& filename)
{
// extract file extension
std::string::size_type dot(filename.rfind("."));
if (dot == std::string::npos) return false;
std::string ext = filename.substr(dot+1, filename.length()-dot-1);
std::transform(ext.begin(), ext.end(), ext.begin(), tolower);
// extension determines reader
if (ext == "off")
{
return write_off(mesh, filename);
}
// we didn't find a writer module
return false;
}
//=============================================================================

View File

@ -0,0 +1,41 @@
//=============================================================================
// Copyright (C) 2001-2005 by Computer Graphics Group, RWTH Aachen
// Copyright (C) 2011 by Graphics & Geometry Group, Bielefeld University
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License
// as published by the Free Software Foundation, version 2.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef SURFACE_MESH_IO_H
#define SURFACE_MESH_IO_H
//== INCLUDES =================================================================
#include <string>
#include "Surface_mesh.h"
//=============================================================================
bool read_mesh(Surface_mesh& mesh, const std::string& filename);
bool read_off(Surface_mesh& mesh, const std::string& filename);
bool write_mesh(const Surface_mesh& mesh, const std::string& filename);
bool write_off(const Surface_mesh& mesh, const std::string& filename);
//=============================================================================
#endif // SURFACE_MESH_IO_H
//=============================================================================

View File

@ -0,0 +1,325 @@
//=============================================================================
// Copyright (C) 2001-2005 by Computer Graphics Group, RWTH Aachen
// Copyright (C) 2011 by Graphics & Geometry Group, Bielefeld University
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License
// as published by the Free Software Foundation, version 2.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
//== INCLUDES =================================================================
#include "IO.h"
#include <stdio.h>
//== IMPLEMENTATION ===========================================================
// helper function
template <typename T> void read(FILE* in, T& t)
{
int err = 0;
err = fread(&t, 1, sizeof(t), in);
}
//-----------------------------------------------------------------------------
bool read_off_ascii(Surface_mesh& mesh,
FILE* in,
const bool has_normals,
const bool has_texcoords,
const bool has_colors)
{
char line[100], *lp;
unsigned int i, j, items, idx, nc;
unsigned int nV, nF, nE;
Vec3f p, n, c;
Vec2f t;
Surface_mesh::Vertex v;
// properties
Surface_mesh::Vertex_property<Normal> normals;
Surface_mesh::Vertex_property<Texture_coordinate> texcoords;
Surface_mesh::Vertex_property<Color> colors;
if (has_normals) normals = mesh.vertex_property<Normal>("v:normal");
if (has_texcoords) texcoords = mesh.vertex_property<Texture_coordinate>("v:texcoord");
if (has_colors) colors = mesh.vertex_property<Color>("v:color");
// #Vertice, #Faces, #Edges
items = fscanf(in, "%d %d %d\n", (int*)&nV, (int*)&nF, (int*)&nE);
mesh.clear();
mesh.reserve(nV, std::max(3*nV, nE), nF);
// read vertices: pos [normal] [color] [texcoord]
for (i=0; i<nV && !feof(in); ++i)
{
// read line
lp = fgets(line, 100, in);
// position
items = sscanf(lp, "%f %f %f%n", &p[0], &p[1], &p[2], &nc);
assert(items==3);
v = mesh.add_vertex((Point)p);
lp += nc;
// normal
if (has_normals)
{
if (sscanf(lp, "%f %f %f%n", &n[0], &n[1], &n[2], &nc) == 3)
{
normals[v] = n;
}
lp += nc;
}
// color
if (has_colors)
{
if (sscanf(lp, "%f %f %f%n", &c[0], &c[1], &c[2], &nc) == 3)
{
if (c[0]>1.0f || c[1]>1.0f || c[2]>1.0f) c *= (1.0/255.0);
colors[v] = c;
}
lp += nc;
}
// tex coord
if (has_texcoords)
{
items = sscanf(lp, "%f %f%n", &t[0], &t[1], &nc);
assert(items == 2);
texcoords[v][0] = t[0];
texcoords[v][1] = t[1];
lp += nc;
}
}
// read faces: #N v[1] v[2] ... v[n-1]
std::vector<Surface_mesh::Vertex> vertices;
for (i=0; i<nF; ++i)
{
// read line
lp = fgets(line, 100, in);
// #vertices
items = sscanf(lp, "%d%n", (int*)&nV, &nc);
assert(items == 1);
vertices.resize(nV);
lp += nc;
// indices
for (j=0; j<nV; ++j)
{
items = sscanf(lp, "%d%n", (int*)&idx, &nc);
assert(items == 1);
vertices[j] = Surface_mesh::Vertex(idx);
lp += nc;
}
mesh.add_face(vertices);
}
return true;
}
//-----------------------------------------------------------------------------
bool read_off_binary(Surface_mesh& mesh,
FILE* in,
const bool has_normals,
const bool has_texcoords,
const bool has_colors)
{
unsigned int i, j, idx;
unsigned int nV, nF, nE;
Vec3f p, n, c;
Vec2f t;
Surface_mesh::Vertex v;
// binary cannot (yet) read colors
if (has_colors) return false;
// properties
Surface_mesh::Vertex_property<Normal> normals;
Surface_mesh::Vertex_property<Texture_coordinate> texcoords;
if (has_normals) normals = mesh.vertex_property<Normal>("v:normal");
if (has_texcoords) texcoords = mesh.vertex_property<Texture_coordinate>("v:texcoord");
// #Vertice, #Faces, #Edges
read(in, nV);
read(in, nF);
read(in, nE);
mesh.clear();
mesh.reserve(nV, std::max(3*nV, nE), nF);
// read vertices: pos [normal] [color] [texcoord]
for (i=0; i<nV && !feof(in); ++i)
{
// position
read(in, p);
v = mesh.add_vertex((Point)p);
// normal
if (has_normals)
{
read(in, n);
normals[v] = n;
}
// tex coord
if (has_texcoords)
{
read(in, t);
texcoords[v][0] = t[0];
texcoords[v][1] = t[1];
}
}
// read faces: #N v[1] v[2] ... v[n-1]
std::vector<Surface_mesh::Vertex> vertices;
for (i=0; i<nF; ++i)
{
read(in, nV);
vertices.resize(nV);
for (j=0; j<nV; ++j)
{
read(in, idx);
vertices[j] = Surface_mesh::Vertex(idx);
}
mesh.add_face(vertices);
}
return true;
}
//-----------------------------------------------------------------------------
bool read_off(Surface_mesh& mesh, const std::string& filename)
{
char line[100];
bool has_texcoords = false;
bool has_normals = false;
bool has_colors = false;
bool has_hcoords = false;
bool has_dim = false;
bool is_binary = false;
// open file (in ASCII mode)
FILE* in = fopen(filename.c_str(), "r");
if (!in) return false;
// read header: [ST][C][N][4][n]OFF BINARY
char *c = fgets(line, 100, in);
assert(c != NULL);
c = line;
if (c[0] == 'S' && c[1] == 'T') { has_texcoords = true; c += 2; }
if (c[0] == 'C') { has_colors = true; ++c; }
if (c[0] == 'N') { has_normals = true; ++c; }
if (c[0] == '4') { has_hcoords = true; ++c; }
if (c[0] == 'n') { has_dim = true; ++c; }
if (strncmp(c, "OFF", 3) != 0) { fclose(in); return false; } // no OFF
if (strncmp(c+4, "BINARY", 6) == 0) is_binary = true;
// homogeneous coords, and vertex dimension != 3 are not supported
if (has_hcoords || has_dim)
{
fclose(in);
return false;
}
// if binary: reopen file in binary mode
if (is_binary)
{
fclose(in);
in = fopen(filename.c_str(), "rb");
c = fgets(line, 100, in);
assert(c != NULL);
}
// read as ASCII or binary
bool ok = (is_binary ?
read_off_binary(mesh, in, has_normals, has_texcoords, has_colors) :
read_off_ascii(mesh, in, has_normals, has_texcoords, has_colors));
fclose(in);
return ok;
}
//-----------------------------------------------------------------------------
bool write_off(const Surface_mesh& mesh, const std::string& filename)
{
FILE* out = fopen(filename.c_str(), "w");
if (!out)
return false;
// header
fprintf(out, "OFF\n%d %d 0\n", mesh.n_vertices(), mesh.n_faces());
// vertices
Surface_mesh::Vertex_property<Point> points = mesh.get_vertex_property<Point>("v:point");
for (Surface_mesh::Vertex_iterator vit=mesh.vertices_begin(); vit!=mesh.vertices_end(); ++vit)
{
const Point& p = points[*vit];
fprintf(out, "%.10f %.10f %.10f\n", p[0], p[1], p[2]);
}
// faces
for (Surface_mesh::Face_iterator fit=mesh.faces_begin(); fit!=mesh.faces_end(); ++fit)
{
int nV = mesh.valence(*fit);
fprintf(out, "%d", nV);
Surface_mesh::Vertex_around_face_circulator fvit=mesh.vertices(*fit), fvend=fvit;
do
{
fprintf(out, " %d", (*fvit).idx());
}
while (++fvit != fvend);
fprintf(out, "\n");
}
fclose(out);
return true;
}
//=============================================================================

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,692 @@
//=============================================================================
// Copyright (C) 2001-2005 by Computer Graphics Group, RWTH Aachen
// Copyright (C) 2011 by Graphics & Geometry Group, Bielefeld University
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License
// as published by the Free Software Foundation, version 2.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef SURFACE_MESH_VECTOR_H
#define SURFACE_MESH_VECTOR_H
//== INCLUDES =================================================================
#include <iostream>
#include <assert.h>
#include <math.h>
#include <limits>
#include <cstring>
#ifdef WIN32
#undef min
#undef max
#endif
/// \addtogroup geometry geometry
/// @{
//== CLASS DEFINITION =========================================================
/** A vector class for an N-dimensional vector of scalar type T.
Elements of a vector v can be accessed by v[0], v[1], ...
For 3D vectors one can also use v.x, v.y and v.z.
*/
template <typename Scalar, int N>
class Vector
{
public:
/// the scalar type of the vector
typedef Scalar value_type;
/// returns the dimension of the vector
static int size() { return N; }
/// default constructor, creates uninitialized values.
Vector() {}
/// construct from scalar s (fills all components with s)
explicit Vector(const Scalar s)
{
for (int i=0; i<N; ++i)
data_[i] = s;
}
/// construct from 2 scalars. only valid for 2D vectors.
Vector(const Scalar x, const Scalar y)
{
assert(N==2);
data_[0]=x;
data_[1]=y;
}
/// construct from 3 scalars. only valid for 2D vectors.
Vector(const Scalar x, const Scalar y, const Scalar z)
{
assert(N==3);
data_[0]=x;
data_[1]=y;
data_[2]=z;
}
/// construct from 4 scalars. only valid for 2D vectors.
Vector(const Scalar x, const Scalar y, const Scalar z, const Scalar w)
{
assert(N==4);
data_[0]=x;
data_[1]=y;
data_[2]=z;
data_[3]=w;
}
/// construct from vector of other scalar type
template <typename OtherScalarType>
explicit Vector(const Vector<OtherScalarType,N>& o)
{
for (int i=0; i<N; ++i)
data_[i] = o.data_[i];
}
/// cast to vector of other scalar type
template <typename OtherScalarType>
operator Vector<OtherScalarType,N>()
{
Vector<OtherScalarType,N> v;
for (int i=0; i<N; ++i)
v[i] = data_[i];
return v;
}
/// cast to Scalar array
operator Scalar*()
{
return data_;
}
/// cast to const Scalar array
operator const Scalar*() const
{
return data_;
}
/// cast to const Scalar array
const Scalar* data() const
{
return data_;
}
/// get i'th element read-write
Scalar& operator[](unsigned int i)
{
assert(i<N);
return data_[i];
}
/// get i'th element read-only
const Scalar operator[](unsigned int i) const
{
assert(i<N);
return data_[i];
}
/// assign a scalar to all componenets
Vector<Scalar,N>& operator=(const Scalar s)
{
for (int i=0; i<N; ++i)
data_[i] = s;
return *this;
}
/// assignment from a vector of different scalar type
template<typename otherScalarType>
Vector<Scalar,N>& operator=(const Vector<otherScalarType,N>& o)
{
for (int i=0; i<N; ++i)
data_[i] = Scalar(o[i]);
return *this;
}
/// component-wise comparison
bool operator==(const Vector<Scalar,N>& other) const
{
for (int i=0; i<N; ++i)
if (data_[i]!=other.data_[i])
return false;
return true;
}
/// component-wise comparison
bool operator!=(const Vector<Scalar,N>& other) const
{
for (int i=0; i<N; ++i)
if (data_[i]!=other.data_[i])
return true;
return false;
}
/// multiply vector by scalar s
Vector<Scalar,N>& operator*=(const Scalar s)
{
for (int i=0; i<N; ++i)
data_[i] *= s;
return *this;
}
/// divide vector by scalar s
Vector<Scalar,N>& operator/=(const Scalar s)
{
for (int i=0; i<N; ++i)
data_[i] /= s;
return *this;
}
/// subtract vector v
Vector<Scalar,N>& operator-=(const Vector<Scalar,N>& v)
{
for (int i=0; i<N; ++i)
data_[i] -= v.data_[i];
return *this;
}
/// add vector v
Vector<Scalar,N>& operator+=(const Vector<Scalar,N>& v)
{
for (int i=0; i<N; ++i)
data_[i] += v.data_[i];
return *this;
}
/// normalize vector, return normalized vector
Vector<Scalar,N>& normalize()
{
Scalar n = norm(*this);
if (n > std::numeric_limits<Scalar>::min())
*this *= 1.0/n;
return *this;
}
/// return vector with minimum of this and other in each component
Vector<Scalar,N> minimize(const Vector<Scalar,N>& other)
{
for (int i = 0; i < N; ++i)
if (other[i] < data_[i])
data_[i] = other[i];
return *this;
}
/// return vector with maximum of this and other in each component
Vector<Scalar,N> maximize(const Vector<Scalar,N>& other)
{
for (int i = 0; i < N; ++i)
if (other[i] > data_[i])
data_[i] = other[i];
return *this;
}
public:
/** The N values of type Scalar are the only data members
of this class. 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 */
Scalar data_[N];
};
//== FUNCTIONS ================================================================
/// read the space-separated components of a vector from a stream
template <typename Scalar,int N>
inline std::istream& operator>>(std::istream& is, Vector<Scalar,N>& vec)
{
for (int i=0; i<N; ++i)
is >> vec[i];
return is;
}
/// output a vector by printing its space-separated compontens
template <typename Scalar,int N>
inline std::ostream& operator<<(std::ostream& os, const Vector<Scalar,N>& vec)
{
for (int i=0; i<N-1; ++i)
os << vec[i] << " ";
os << vec[N-1];
return os;
}
/// negate vector
template <typename Scalar, int N>
inline Vector<Scalar,N> operator-(const Vector<Scalar,N>& v)
{
Vector<Scalar,N> vv;
for (int i=0; i<N; ++i)
vv[i] = -v[i];
return vv;
}
/// scalar * vector
template <typename Scalar, typename Scalar2, int N>
inline Vector<Scalar,N> operator*(const Scalar2 s, const Vector<Scalar,N>& v )
{
return Vector<Scalar,N>(v) *= (Scalar)s;
}
/// vector * scalar
template <typename Scalar, typename Scalar2, int N>
inline Vector<Scalar,N> operator*(const Vector<Scalar,N>& v, const Scalar2 s)
{
return Vector<Scalar,N>(v) *= (Scalar)s;
}
/// vector / scalar
template <typename Scalar, typename Scalar2, int N>
inline Vector<Scalar,N> operator/(const Vector<Scalar,N>& v, const Scalar2 s)
{
return Vector<Scalar,N>(v) /= Scalar(s);
}
/// vector + vector
template <typename Scalar, int N>
inline Vector<Scalar,N> operator+(const Vector<Scalar,N>& v0, const Vector<Scalar,N>& v1)
{
return Vector<Scalar,N>(v0) += v1;
}
/// vector - vector
template <typename Scalar, int N>
inline Vector<Scalar,N> operator-(const Vector<Scalar,N>& v0, const Vector<Scalar,N>& v1)
{
return Vector<Scalar,N>(v0) -= v1;
}
/// compute the Euclidean norm of a vector
template <typename Scalar, int N>
inline Scalar norm(const Vector<Scalar,N>& v)
{
Scalar s = v[0]*v[0];
for (int i=1; i<N; ++i)
s += v[i]*v[i];
return (Scalar)sqrt(s);
}
/// compute the Euclidean norm of a vector
template <typename Scalar, int N>
inline Vector<Scalar,N> normalize(const Vector<Scalar,N>& v)
{
return v/norm(v);
}
/// compute the squared Euclidean norm of a vector
template <typename Scalar, int N>
inline Scalar sqrnorm(const Vector<Scalar,N>& v)
{
Scalar s = v[0]*v[0];
for (int i=1; i<N; ++i)
s += v[i]*v[i];
return s;
}
/// compute the dot product of two vectors
template <typename Scalar, int N>
inline Scalar dot(const Vector<Scalar,N>& v0, const Vector<Scalar,N>& v1)
{
Scalar p = v0[0]*v1[0];
for (int i=1; i<N; ++i)
p += v0[i]*v1[i];
return p;
}
/// compute the Euclidean distance between two points
template <typename Scalar, int N>
inline Scalar distance(const Vector<Scalar,N>& v0, const Vector<Scalar,N>& v1)
{
Scalar dist(0), d;
for (int i=0; i<N; ++i)
{
d = v0[i] - v1[i];
d *= d;
dist += d;
}
return (Scalar)sqrt(dist);
}
/// compute the cross product of two vectors (only valid for 3D vectors)
template <typename Scalar>
inline Vector<Scalar,3> cross(const Vector<Scalar,3>& v0, const Vector<Scalar,3>& v1)
{
return Vector<Scalar,3>(v0[1]*v1[2] - v0[2]*v1[1],
v0[2]*v1[0] - v0[0]*v1[2],
v0[0]*v1[1] - v0[1]*v1[0]);
}
//== TEMPLATE SPECIALIZATIONS FOR 3D ==========================================
#if 1
template <typename Scalar>
class Vector<Scalar,3>
{
public:
typedef Scalar value_type;
static int size() { return 3; }
Vector() {}
explicit Vector(const Scalar s) : x(s), y(s), z(s) {}
Vector(const Scalar xx, const Scalar yy, const Scalar zz)
: x(xx), y(yy), z(zz) {}
template <typename OtherScalarType>
explicit Vector(const Vector<OtherScalarType,3>& o)
: x((Scalar)o.x), y((Scalar)o.y), z((Scalar)o.z) {}
template <typename OtherScalarType>
operator Vector<OtherScalarType,3>()
{
return Vector<OtherScalarType,3>(x,y,z);
}
operator Scalar*() { return &x;}
operator const Scalar*() const { return &x; }
const Scalar* data() const { return &x; }
Scalar& operator[](unsigned int i)
{
assert(i<3);
return (&x)[i];
}
const Scalar operator[](unsigned int i) const
{
assert(i<3);
return (&x)[i];
}
Vector<Scalar,3>& operator=(const Scalar s)
{
x=y=z=s;
return *this;
}
template <typename otherScalarType>
Vector<Scalar,3>& operator=(const Vector<otherScalarType,3>& o)
{
x = (Scalar)o.x;
y = (Scalar)o.y;
z = (Scalar)o.z;
return *this;
}
bool operator==(const Vector<Scalar,3>& o) const
{
if (x != o.x) return false;
if (y != o.y) return false;
if (z != o.z) return false;
return true;
}
bool operator!=(const Vector<Scalar,3>& o) const
{
if (x != o.x) return true;
if (y != o.y) return true;
if (z != o.z) return true;
return false;
}
Vector<Scalar,3>& operator*=(const Scalar s)
{
x *= s;
y *= s;
z *= s;
return *this;
}
Vector<Scalar,3>& operator/=(const Scalar s)
{
x /= s;
y /= s;
z /= s;
return *this;
}
Vector<Scalar,3>& operator-=(const Vector<Scalar,3>& v)
{
x -= v.x;
y -= v.y;
z -= v.z;
return *this;
}
Vector<Scalar,3>& operator+=(const Vector<Scalar,3>& v)
{
x += v.x;
y += v.y;
z += v.z;
return *this;
}
Vector<Scalar,3>& normalize()
{
Scalar n = norm(*this);
n = (n > std::numeric_limits<Scalar>::min()) ? 1.0/n : 0.0;
x *= n;
y *= n;
z *= n;
return *this;
}
Vector<Scalar,3> minimize(const Vector<Scalar,3>& o)
{
if (o.x < x) x = o.x;
if (o.y < y) y = o.y;
if (o.z < z) z = o.z;
return *this;
}
Vector<Scalar,3> maximize(const Vector<Scalar,3>& o)
{
if (o.x > x) x = o.x;
if (o.y > y) y = o.y;
if (o.z > z) z = o.z;
return *this;
}
public:
Scalar x,y,z;
};
template <typename Scalar>
inline Vector<Scalar,3> operator-(const Vector<Scalar,3>& v)
{
return Vector<Scalar,3>(-v.x, -v.y, -v.z);
}
template <typename Scalar, typename Scalar2>
inline Vector<Scalar,3> operator*(const Scalar2 s, const Vector<Scalar,3>& v )
{
return Vector<Scalar,3>(v.x*Scalar(s), v.y*Scalar(s), v.z*Scalar(s));
}
template <typename Scalar, typename Scalar2>
inline Vector<Scalar,3> operator*(const Vector<Scalar,3>& v, const Scalar2 s)
{
return Vector<Scalar,3>(v.x*Scalar(s), v.y*Scalar(s), v.z*Scalar(s));
}
template <typename Scalar, typename Scalar2>
inline Vector<Scalar,3> operator/(const Vector<Scalar,3>& v, const Scalar2 s)
{
return Vector<Scalar,3>(v.x/s, v.y/s, v.z/s);
}
template <typename Scalar>
inline Vector<Scalar,3> operator+(const Vector<Scalar,3>& v0, const Vector<Scalar,3>& v1)
{
return Vector<Scalar,3>(v0.x+v1.x, v0.y+v1.y, v0.z+v1.z);
}
template <typename Scalar>
inline Vector<Scalar,3> operator-(const Vector<Scalar,3>& v0, const Vector<Scalar,3>& v1)
{
return Vector<Scalar,3>(v0.x-v1.x, v0.y-v1.y, v0.z-v1.z);
}
template <typename Scalar>
inline Scalar norm(const Vector<Scalar,3>& v)
{
Scalar s = v.x*v.x;
s += v.y*v.y;
s += v.z*v.z;
return (Scalar)sqrt(s);
}
template <typename Scalar>
inline Scalar sqrnorm(const Vector<Scalar,3>& v)
{
Scalar s = v.x*v.x;
s += v.y*v.y;
s += v.z*v.z;
return s;
}
template <typename Scalar>
inline Vector<Scalar,3> normalize(const Vector<Scalar,3>& v)
{
Scalar n = v.x*v.x;
n += v.y*v.y;
n += v.z*v.z;
n = (Scalar)sqrt(n);
return Vector<Scalar,3>(v.x/n, v.y/n, v.z/n);
}
template <typename Scalar>
inline Scalar dot(const Vector<Scalar,3>& v0, const Vector<Scalar,3>& v1)
{
Scalar s = v0.x*v1.x;
s += v0.y*v1.y;
s += v0.z*v1.z;
return s;
}
template <typename Scalar>
inline Scalar distance(const Vector<Scalar,3>& v0, const Vector<Scalar,3>& v1)
{
Scalar dist(0), d;
for (int i=0; i<3; ++i)
{
d = v0[i] - v1[i];
d *= d;
dist += d;
}
return (Scalar)sqrt(dist);
}
#endif
//== TYPEDEFS =================================================================
/** 2-byte signed vector */
typedef Vector<signed char,2> Vec2c;
/** 2-byte unsigned vector */
typedef Vector<unsigned char,2> Vec2uc;
/** 2-short signed vector */
typedef Vector<signed short int,2> Vec2s;
/** 2-short unsigned vector */
typedef Vector<unsigned short int,2> Vec2us;
/** 2-int signed vector */
typedef Vector<signed int,2> Vec2i;
/** 2-int unsigned vector */
typedef Vector<unsigned int,2> Vec2ui;
/** 2-float vector */
typedef Vector<float,2> Vec2f;
/** 2-double vector */
typedef Vector<double,2> Vec2d;
/** 3-byte signed vector */
typedef Vector<signed char,3> Vec3c;
/** 3-byte unsigned vector */
typedef Vector<unsigned char,3> Vec3uc;
/** 3-short signed vector */
typedef Vector<signed short int,3> Vec3s;
/** 3-short unsigned vector */
typedef Vector<unsigned short int,3> Vec3us;
/** 3-int signed vector */
typedef Vector<signed int,3> Vec3i;
/** 3-int unsigned vector */
typedef Vector<unsigned int,3> Vec3ui;
/** 3-float vector */
typedef Vector<float,3> Vec3f;
/** 3-double vector */
typedef Vector<double,3> Vec3d;
/** 4-byte signed vector */
typedef Vector<signed char,4> Vec4c;
/** 4-byte unsigned vector */
typedef Vector<unsigned char,4> Vec4uc;
/** 4-short signed vector */
typedef Vector<signed short int,4> Vec4s;
/** 4-short unsigned vector */
typedef Vector<unsigned short int,4> Vec4us;
/** 4-int signed vector */
typedef Vector<signed int,4> Vec4i;
/** 4-int unsigned vector */
typedef Vector<unsigned int,4> Vec4ui;
/** 4-float vector */
typedef Vector<float,4> Vec4f;
/** 4-double vector */
typedef Vector<double,4> Vec4d;
//=============================================================================
/// @}
//=============================================================================
#endif // VECTOR_H
//=============================================================================

View File

@ -0,0 +1,413 @@
//=============================================================================
// Copyright (C) 2001-2005 by Computer Graphics Group, RWTH Aachen
// Copyright (C) 2011 by Graphics & Geometry Group, Bielefeld University
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License
// as published by the Free Software Foundation, version 2.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef SURFACE_MESH_PROPERTY_H
#define SURFACE_MESH_PROPERTY_H
//== INCLUDES =================================================================
#include <vector>
#include <string>
#include <algorithm>
#include <typeinfo>
//== CLASS DEFINITION =========================================================
class Base_property_array
{
public:
/// Default constructor
Base_property_array(const std::string& name) : name_(name) {}
/// Destructor.
virtual ~Base_property_array() {}
/// Reserve memory for n elements.
virtual void reserve(size_t n) = 0;
/// Resize storage to hold n elements.
virtual void resize(size_t n) = 0;
/// Free unused memory.
virtual void free_memory() = 0;
/// Extend the number of elements by one.
virtual void push_back() = 0;
/// Let two elements swap their storage place.
virtual void swap(size_t i0, size_t i1) = 0;
/// Return a deep copy of self.
virtual Base_property_array* clone () const = 0;
/// Return the type_info of the property
virtual const std::type_info& type() = 0;
/// Return the name of the property
const std::string& name() const { return name_; }
protected:
std::string name_;
};
//== CLASS DEFINITION =========================================================
template <class T>
class Property_array : public Base_property_array
{
public:
typedef T value_type;
typedef std::vector<value_type> vector_type;
typedef typename vector_type::reference reference;
typedef typename vector_type::const_reference const_reference;
Property_array(const std::string& name, T t=T()) : Base_property_array(name), value_(t) {}
public: // virtual interface of Base_property_array
virtual void reserve(size_t n)
{
data_.reserve(n);
}
virtual void resize(size_t n)
{
data_.resize(n, value_);
}
virtual void push_back()
{
data_.push_back(value_);
}
virtual void free_memory()
{
vector_type(data_).swap(data_);
}
virtual void swap(size_t i0, size_t i1)
{
T d(data_[i0]);
data_[i0]=data_[i1];
data_[i1]=d;
}
virtual Base_property_array* clone() const
{
Property_array<T>* p = new Property_array<T>(name_, value_);
p->data_ = data_;
return p;
}
virtual const std::type_info& type() { return typeid(T); }
public:
/// Get pointer to array (does not work for T==bool)
const T* data() const
{
return &data_[0];
}
/// Access the i'th element. No range check is performed!
reference operator[](int _idx)
{
assert( size_t(_idx) < data_.size() );
return data_[_idx];
}
/// Const access to the i'th element. No range check is performed!
const_reference operator[](int _idx) const
{
assert( size_t(_idx) < data_.size());
return data_[_idx];
}
private:
vector_type data_;
value_type value_;
};
// specialization for bool properties
template <>
inline const bool*
Property_array<bool>::data() const
{
assert(false);
return NULL;
}
//== CLASS DEFINITION =========================================================
template <class T>
class Property
{
public:
typedef typename Property_array<T>::reference reference;
typedef typename Property_array<T>::const_reference const_reference;
friend class Property_container;
friend class Surface_mesh;
public:
Property(Property_array<T>* p=NULL) : parray_(p) {}
void reset()
{
parray_ = NULL;
}
operator bool() const
{
return parray_ != NULL;
}
reference operator[](int i)
{
assert(parray_ != NULL);
return (*parray_)[i];
}
const_reference operator[](int i) const
{
assert(parray_ != NULL);
return (*parray_)[i];
}
const T* data() const
{
assert(parray_ != NULL);
return parray_->data();
}
private:
Property_array<T>& array()
{
assert(parray_ != NULL);
return *parray_;
}
const Property_array<T>& array() const
{
assert(parray_ != NULL);
return *parray_;
}
private:
Property_array<T>* parray_;
};
//== CLASS DEFINITION =========================================================
class Property_container
{
public:
// default constructor
Property_container() : size_(0) {}
// destructor (deletes all property arrays)
virtual ~Property_container() { clear(); }
// copy constructor: performs deep copy of property arrays
Property_container(const Property_container& _rhs) { operator=(_rhs); }
// assignment: performs deep copy of property arrays
Property_container& operator=(const Property_container& _rhs)
{
if (this != &_rhs)
{
clear();
parrays_.resize(_rhs.n_properties());
size_ = _rhs.size();
for (unsigned int i=0; i<parrays_.size(); ++i)
parrays_[i] = _rhs.parrays_[i]->clone();
}
return *this;
}
// returns the current size of the property arrays
size_t size() const { return size_; }
// returns the number of property arrays
size_t n_properties() const { return parrays_.size(); }
// returns a vector of all property names
std::vector<std::string> properties() const
{
std::vector<std::string> names;
for (unsigned int i=0; i<parrays_.size(); ++i)
names.push_back(parrays_[i]->name());
return names;
}
// add a property with name \c name and default value \c t
template <class T> Property<T> add(const std::string& name, const T t=T())
{
// if a property with this name already exists, return an invalid property
for (unsigned int i=0; i<parrays_.size(); ++i)
{
if (parrays_[i]->name() == name)
{
std::cerr << "[Property_container] A property with name \""
<< name << "\" already exists. Returning invalid property.\n";
return Property<T>();
}
}
// otherwise add the property
Property_array<T>* p = new Property_array<T>(name, t);
p->resize(size_);
parrays_.push_back(p);
return Property<T>(p);
}
// get a property by its name. returns invalid property if it does not exist.
template <class T> Property<T> get(const std::string& name) const
{
for (unsigned int i=0; i<parrays_.size(); ++i)
if (parrays_[i]->name() == name)
return Property<T>(dynamic_cast<Property_array<T>*>(parrays_[i]));
return Property<T>();
}
// returns a property if it exists, otherwise it creates it first.
template <class T> Property<T> get_or_add(const std::string& name, const T t=T())
{
Property<T> p = get<T>(name);
if (!p) p = add<T>(name, t);
return p;
}
// get the type of property by its name. returns typeid(void) if it does not exist.
const std::type_info& get_type(const std::string& name)
{
for (unsigned int i=0; i<parrays_.size(); ++i)
if (parrays_[i]->name() == name)
return parrays_[i]->type();
return typeid(void);
}
// delete a property
template <class T> void remove(Property<T>& h)
{
std::vector<Base_property_array*>::iterator it=parrays_.begin(), end=parrays_.end();
for (; it!=end; ++it)
{
if (*it == h.parray_)
{
delete *it;
parrays_.erase(it);
h.reset();
break;
}
}
}
// delete all properties
void clear()
{
for (unsigned int i=0; i<parrays_.size(); ++i)
delete parrays_[i];
parrays_.clear();
size_ = 0;
}
// reserve memory for n entries in all arrays
void reserve(size_t n) const
{
for (unsigned int i=0; i<parrays_.size(); ++i)
parrays_[i]->reserve(n);
}
// resize all arrays to size n
void resize(size_t n)
{
for (unsigned int i=0; i<parrays_.size(); ++i)
parrays_[i]->resize(n);
size_ = n;
}
// free unused space in all arrays
void free_memory() const
{
for (unsigned int i=0; i<parrays_.size(); ++i)
parrays_[i]->free_memory();
}
// add a new element to each vector
void push_back()
{
for (unsigned int i=0; i<parrays_.size(); ++i)
parrays_[i]->push_back();
++size_;
}
// swap elements i0 and i1 in all arrays
void swap(size_t i0, size_t i1) const
{
for (unsigned int i=0; i<parrays_.size(); ++i)
parrays_[i]->swap(i0, i1);
}
private:
std::vector<Base_property_array*> parrays_;
size_t size_;
};
//=============================================================================
#endif // SURFACE_MESH_PROPERTY_H
//=============================================================================

View File

@ -0,0 +1,33 @@
//=============================================================================
#ifndef SURFACE_MESH_TYPES_H
#define SURFACE_MESH_TYPES_H
//== INCLUDES =================================================================
#include "Vector.h"
//== CLASS DEFINITION =========================================================
/// Scalar type
typedef double Scalar;
/// Point type
typedef Vector<Scalar,3> Point;
/// Normal type
typedef Vector<Scalar,3> Normal;
/// Color type
typedef Vector<Scalar,3> Color;
/// Texture coordinate type
typedef Vector<Scalar,3> Texture_coordinate;
//============================================================================
#endif
//============================================================================

View File

@ -0,0 +1,20 @@
//== INCLUDES =================================================================
#include "surface_mesh_performance.h"
//=============================================================================
int main(int argc, char** argv)
{
if (argc < 2)
{
std::cerr << "Usage:\n" << argv[0] << " <input-mesh>\n";
exit(1);
}
for (int i=1; i<argc; ++i)
{
std::cout<<"**************** "<<argv[i]<<" ****************"<<std::endl;
Surface_mesh_performance().run(argv[1], "output_surface_mesh.off");
}
return 0;
}
//=============================================================================

View File

@ -0,0 +1,259 @@
//== INCLUDES =================================================================
#include "performance_2.h"
#include "surface_mesh/Surface_mesh.h"
//== CLASS DEFINITION =========================================================
class Surface_mesh_performance : public Performance_test_2
{
public:
Surface_mesh_performance() : Performance_test_2()
{
points = mesh.vertex_property<Point>("v:point");
vnormals = mesh.vertex_property<Point>("v:normal");
fnormals = mesh.face_property<Point>("f:normal");
}
private:
Surface_mesh mesh;
Surface_mesh::Vertex_property<Point> points;
Surface_mesh::Vertex_property<Point> vnormals;
Surface_mesh::Face_property<Point> fnormals;
private:
void display_info()
{
std::cout << "#Darts=" << mesh.n_halfedges();
std::cout << ", #0-cells=" << mesh.n_vertices();
std::cout << ", #1-cells=" << mesh.n_edges();
std::cout << ", #2-cells=" << mesh.n_faces();
std::cout << "\t" << std::endl;
}
virtual bool read_mesh(const char* _filename)
{
return mesh.read(_filename);
}
virtual bool write_mesh(const char* _filename)
{
return mesh.write(_filename);
}
virtual int circulator_test()
{
Surface_mesh::Vertex_iterator vit, vend=mesh.vertices_end();
Surface_mesh::Face_iterator fit, fend=mesh.faces_end();
Surface_mesh::Face_around_vertex_circulator vfit, vfend;
Surface_mesh::Vertex_around_face_circulator fvit, fvend;
int counter = 0;
for (vit=mesh.vertices_begin(); vit!=vend; ++vit)
{
vfit = vfend = mesh.faces(*vit);
if (vfit) do
{
++counter;
}
while (++vfit != vfend);
}
for (fit=mesh.faces_begin(); fit!=fend; ++fit)
{
fvit = fvend = mesh.vertices(*fit);
do
{
--counter;
}
while (++fvit != fvend);
}
return counter;
}
virtual void barycenter_test(bool draw)
{
Point p(0,0,0);
Surface_mesh::Vertex_iterator vit, vend=mesh.vertices_end();
for (vit=mesh.vertices_begin(); vit!=vend; ++vit)
p += points[*vit];
p /= mesh.n_vertices();
for (vit=mesh.vertices_begin(); vit!=vend; ++vit)
points[*vit] -= p;
if ( draw ) std::cout<<"Barycenter: "<<p<<std::endl;
}
virtual void normal_test()
{
Surface_mesh::Vertex_iterator vit, vend=mesh.vertices_end();
Surface_mesh::Face_iterator fit, fend=mesh.faces_end();
Surface_mesh::Face_around_vertex_circulator vfit, vfend;
for (fit=mesh.faces_begin(); fit!=fend; ++fit)
{
Surface_mesh::Halfedge h = mesh.halfedge(*fit);
Point p0 = points[mesh.to_vertex(h)];
h = mesh.next_halfedge(h);
Point p1 = points[mesh.to_vertex(h)];
p1 -= p0;
h = mesh.next_halfedge(h);
Point p2 = points[mesh.to_vertex(h)];
p2 -= p0;
fnormals[*fit] = cross(p1, p2).normalize();
}
for (vit=mesh.vertices_begin(); vit!=vend; ++vit)
{
Point n(0,0,0);
vfit = vfend = mesh.faces(*vit);
if (vfit) do
{
n += fnormals[*vfit];
}
while (++vfit != vfend);
vnormals[*vit] = n.normalize();
}
}
virtual void smoothing_test()
{
Surface_mesh::Vertex_iterator vit, vend=mesh.vertices_end();
Surface_mesh::Vertex_around_vertex_circulator vvit, vvend;
for (vit=mesh.vertices_begin(); vit!=vend; ++vit)
{
if (!mesh.is_boundary(*vit))
{
Point p(0,0,0);
Scalar c(0);
vvit = vvend = mesh.vertices(*vit);
do
{
p += points[*vvit];
++c;
}
while (++vvit != vvend);
p /= c;
points[*vit] = p;
}
}
}
virtual void subdivision_test()
{
// reserve memory
int nv = mesh.n_vertices();
int ne = mesh.n_edges();
int nf = mesh.n_faces();
mesh.reserve(nv+nf, ne+3*nf, 3*nf);
// iterators
Surface_mesh::Vertex_iterator vit, vend=mesh.vertices_end();
Surface_mesh::Face_iterator fit, fend=mesh.faces_end();
Surface_mesh::Edge_iterator eit, eend=mesh.edges_end();
// compute new positions of old vertices
Surface_mesh::Vertex_property<Point> new_pos = mesh.add_vertex_property<Point>("v:np");
for (vit=mesh.vertices_begin(); vit!=vend; ++vit)
{
if (!mesh.is_boundary(*vit))
{
Scalar n = mesh.valence(*vit);
Scalar alpha = (4.0 - 2.0*cos(2.0*M_PI/n)) / 9.0;
Point p(0,0,0);
Surface_mesh::Vertex_around_vertex_circulator vvit=mesh.vertices(*vit), vvend=vvit;
do
{
p += points[*vvit];
}
while (++vvit != vvend);
p = (1.0f-alpha)*points[*vit] + alpha/n*p;
new_pos[*vit] = p;
}
}
// split faces
for (fit=mesh.faces_begin(); fit!=fend; ++fit)
{
Point p(0,0,0);
Scalar c(0);
Surface_mesh::Vertex_around_face_circulator fvit = mesh.vertices(*fit), fvend=fvit;
do
{
p += points[*fvit];
++c;
}
while (++fvit!=fvend);
p /= c;
mesh.split(*fit, p);
}
// set new positions of old vertices
for (vit=mesh.vertices_begin(); vit!=vend; ++vit)
if (!mesh.is_boundary(*vit))
points[*vit] = new_pos[*vit];
mesh.remove_vertex_property(new_pos);
// flip old edges
for (eit=mesh.edges_begin(); eit!=eend; ++eit)
if (mesh.is_flip_ok(*eit))
mesh.flip(*eit);
}
virtual void collapse_test()
{
// reserve memory
int nv = mesh.n_vertices();
int ne = mesh.n_edges();
int nf = mesh.n_faces();
mesh.reserve(nv+nf, ne+3*nf, 3*nf);
// iterators
Surface_mesh::Vertex_iterator vit, vend=mesh.vertices_end();
Surface_mesh::Face_iterator fit, fend=mesh.faces_end();
// split faces
Point p(0,0,0);
for (fit=mesh.faces_begin(); fit!=fend; ++fit)
mesh.split(*fit, p);
// collapse new edges
vit = vend; vend=mesh.vertices_end();
for (; vit!=vend; ++vit)
mesh.collapse(mesh.halfedge(*vit));
// remove deleted items
mesh.garbage_collection();
}
};
//=============================================================================

View File

@ -0,0 +1,48 @@
project(LCC_performance_3)
cmake_minimum_required(VERSION 2.8)
find_package(CGAL REQUIRED)
include(${CGAL_USE_FILE})
find_package(Boost 1.43.0)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
else()
set (USE_IN_SOURCE_TREE_BOOST true)
endif()
add_subdirectory(openvolumemesh)
include_directories(BEFORE openvolumemesh/src)
include_directories(BEFORE "../../include")
include_directories(BEFORE "./cgogn" "./cgogn/include")
include_directories(BEFORE "/usr/include/libxml2/")
include_directories(BEFORE "/usr/include/eigen3/")
LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/cgogn/lib/Release)
find_package(Qt REQUIRED)
SET(QT_USE_QTSVG TRUE)
SET(QT_USE_QTXML TRUE )
INCLUDE(${QT_USE_FILE})
ADD_DEFINITIONS(${QT_DEFINITIONS})
add_definitions(-DINCLUDE_TEMPLATES)
# Performance_3
add_executable(performance_3 performance_3.cpp)
add_dependencies(performance_3 OpenVolumeMesh)
target_link_libraries(performance_3 OpenVolumeMesh boost_timer boost_system ${CGAL_LIBRARIES} algo assimp container nl topology utils Zinri z xml2 ${QT_LIBRARIES} ${QGLVIEWER_LIBRARIES} ${MAP_VIEWER_LIBRARIES})
# CGoGN
add_executable(cgogn_performance_3 performance_3.h cgogn_performance_3.h cgogn_performance_3.cpp)
target_link_libraries(cgogn_performance_3 algo assimp container nl topology utils Zinri z xml2 ${QT_LIBRARIES} ${QGLVIEWER_LIBRARIES} )
# LCC_3
add_executable(lcc_performance_3 performance_3.h lcc_performance_3.h lcc_performance_3.cpp)
target_link_libraries(lcc_performance_3 ${CGAL_LIBRARIES} ${MAP_VIEWER_LIBRARIES})
# OpenVolumeMesh
add_executable(openvolumemesh_performance performance_3.h openvolumemesh_performance.h openvolumemesh_performance.cpp)
target_link_libraries(openvolumemesh_performance OpenVolumeMesh boost_timer boost_system)

View File

@ -0,0 +1,113 @@
//=============================================================================
#ifndef STOPWATCH_HH
#define STOPWATCH_HH
//== INCLUDES =================================================================
#ifdef _WIN32
# include <windows.h>
#else // Unix
# include <sys/time.h>
#endif
#include <iostream>
//== NAMESPACE ================================================================
namespace graphene {
//== CLASS DEFINITION =========================================================
/// Simple class for a stop watch
class StopWatch
{
public:
/// Constructor
StopWatch()
{
#ifdef _WIN32 // Windows
QueryPerformanceFrequency(&freq_);
#endif
}
/// Start time measurement
void start()
{
#ifdef _WIN32 // Windows
QueryPerformanceCounter(&starttime_);
#else // Linux
starttime_ = current_time();
#endif
}
/// Stop time measurement, return elapsed time in ms
double stop()
{
#ifdef _WIN32 // Windows
QueryPerformanceCounter(&endtime_);
#else // Unix
endtime_ = current_time();
#endif
return elapsed();
}
/// Return elapsed time in ms (watch has to be stopped).
double elapsed() const
{
#ifdef _WIN32 // Windows
return ((double)(endtime_.QuadPart - starttime_.QuadPart)
/ (double)freq_.QuadPart * 1000.0f);
#else // Unix
return ((endtime_.tv_sec - starttime_.tv_sec )*1000.0 +
(endtime_.tv_usec - starttime_.tv_usec)*0.001);
#endif
}
private:
#ifdef _WIN32 // Windows
LARGE_INTEGER starttime_, endtime_;
LARGE_INTEGER freq_;
#else // Unix
timeval current_time() const
{
struct timeval tv;
gettimeofday(&tv, 0);
return tv;
}
timeval starttime_, endtime_;
#endif
};
//=============================================================================
/// output a timer to a stream
inline std::ostream&
operator<<(std::ostream& _os, const StopWatch& _timer)
{
_os << _timer.elapsed() << " ms";
return _os;
}
//=============================================================================
} // namespace graphene
//=============================================================================
#endif // STOPWATCH_HH defined
//=============================================================================

View File

@ -0,0 +1 @@
/home/gdamiand/sources/codes-autres/CGoGN/install

View File

@ -0,0 +1,20 @@
//== INCLUDES =================================================================
#include "cgogn_performance_3.h"
//=============================================================================
int main(int argc, char** argv)
{
if (argc < 2)
{
std::cerr << "Usage:\n" << argv[0] << " <input-mesh>\n";
exit(1);
}
for (int i=1; i<argc; ++i)
{
std::cout<<"**************** "<<argv[i]<<" ****************"<<std::endl;
CGoGN_performance_3().run(argv[i], "output_cgogn_3.tetmesh");
}
return 0;
}
//=============================================================================

View File

@ -0,0 +1,286 @@
//== INCLUDES =================================================================
#include "performance_3.h"
#include <iostream>
#include "Topology/generic/parameters.h"
#include "Topology/map/embeddedMap3.h"
#include "Topology/generic/traversor3.h"
#include "Topology/generic/traversorCell.h"
#include "Topology/generic/cellmarker.h"
#include "Geometry/vector_gen.h"
#include "Algo/Modelisation/tetrahedralization.h"
#include "Algo/Import/import.h"
#include "Algo/Export/exportVol.h"
#include "Container/fakeAttribute.h"
//== CLASS DEFINITION =========================================================
using namespace CGoGN ;
#define TEST_QUICK 0
#define TEST_MR 1
struct PFP: public PFP_STANDARD
{
// definition of the myMap
typedef EmbeddedMap3 MAP;
};
class CGoGN_performance_3 : public Performance_test_3
{
private:
PFP::MAP myMap;
VertexAttribute<PFP::VEC3> position;
VertexAttribute<PFP::VEC3> position_smooting;
VertexAttribute<int> boundary_vertex;
public:
CGoGN_performance_3() : Performance_test_3()
{
position_smooting = myMap.addAttribute<PFP::VEC3, VERTEX>("positionSmoothing");
}
private:
void display_info()
{
std::cout << "#Darts=" << myMap.getNbDarts();
std::cout << ", #0-cells=" << myMap.getNbOrbits<VERTEX>();
std::cout << ", #1-cells=" << myMap.getNbOrbits<EDGE>();
std::cout << ", #2-cells=" << myMap.getNbOrbits<FACE>();
std::cout << ", #3-cells=" << myMap.getNbOrbits<VOLUME>();
std::cout << "\t" << std::endl;
}
Dart getShortestEdge()
{
double weight = std::numeric_limits<double>::max();
Dart dart = NIL;
bool boundary=false;
TraversorE<PFP::MAP> te(myMap);
for(Dart dit = te.begin() ; dit != te.end() ; dit = te.next())
{
Dart dit1 = myMap.phi1(dit);
boundary=false;
if (boundary_vertex[dit]==0)
{
if (myMap.isBoundaryVertex(dit))
{
boundary=true;
boundary_vertex[dit]=1;
}
else
{
boundary_vertex[dit]=2;
}
}
else
{
boundary = (boundary_vertex[dit]==1);
}
if (boundary_vertex[dit1]==0)
{
if (myMap.isBoundaryVertex(dit1))
{
boundary=true;
boundary_vertex[dit1]=1;
}
else
{
boundary_vertex[dit1]=2;
}
}
else
{
boundary = (boundary_vertex[dit1]==1);
}
if (boundary) continue;
PFP::VEC3 p1 = position[dit];
PFP::VEC3 p0 = position[dit1];
PFP::VEC3 v = (p1 - p0);
double w = sqrt(v.norm2());
if(w < weight)
{
weight = w;
dart = dit;
}
}
return dart;
}
private:
virtual bool read_mesh(const char* _filename)
{
std::vector<std::string> attrNames ;
Algo::Volume::Import::importMesh<PFP>(myMap, _filename, attrNames);
position = myMap.getAttribute<PFP::VEC3, VERTEX>(attrNames[0]);
myMap.enableQuickTraversal<VERTEX>();
myMap.enableQuickTraversal<VOLUME>();
// if enabled, don't forget activate disable functions in split_tet
myMap.enableQuickIncidentTraversal<PFP::MAP, VERTEX, VOLUME>();
myMap.enableQuickIncidentTraversal<PFP::MAP, VOLUME, VERTEX>();
myMap.enableQuickAdjacentTraversal<PFP::MAP, VERTEX, EDGE>();
myMap.enableQuickAdjacentTraversal<PFP::MAP, VERTEX, VOLUME>();
return true;
}
virtual bool write_mesh(const char* _filename)
{
// Algo::Volume::Export::exportTetmesh<PFP>(myMap, position, _filename);
return true;
}
virtual int circulator_test()
{
int counter = 0;
//for each vertex enumerate its incident volumes
TraversorV<PFP::MAP> tv(myMap);
for(Dart dit = tv.begin() ; dit != tv.end() ; dit = tv.next())
{
Traversor3VW<PFP::MAP> tvw(myMap,dit);
for(Dart ditvw = tvw.begin() ; ditvw != tvw.end() ; ditvw = tvw.next())
{
++counter;
}
}
//for each volumes enumerate its vertices
TraversorW<PFP::MAP> tw(myMap);
for(Dart dit = tw.begin() ; dit != tw.end() ; dit = tw.next())
{
Traversor3WV<PFP::MAP> twv(myMap,dit);
for(Dart ditwv = twv.begin() ; ditwv != twv.end() ; ditwv = twv.next())
{
--counter;
}
}
return counter;
}
virtual int circulator2_test()
{
int counter = 0;
//for each vertex enumerate its incident volumes
TraversorV<PFP::MAP> tv(myMap);
for(Dart dit = tv.begin() ; dit != tv.end() ; dit = tv.next())
{
Traversor3VVaW<PFP::MAP> twv(myMap,dit);
for(Dart ditwv = twv.begin() ; ditwv != twv.end() ; ditwv = twv.next())
{
++counter;
}
}
return counter;
}
virtual void barycenter_test(bool draw)
{
PFP::VEC3 sum(0.0, 0.0, 0.0);
TraversorW<PFP::MAP> tw(myMap);
for(Dart dit = tw.begin() ; dit != tw.end() ; dit = tw.next())
{
PFP::VEC3 p = Algo::Surface::Geometry::volumeCentroid<PFP>(myMap,dit,position);
sum += p;
}
if ( draw ) std::cout<<"CGoGn::barycenter: "<<sum<<std::endl;
}
virtual void smoothing_test()
{
//laplacian smoothing
TraversorV<PFP::MAP> tv(myMap);
for(Dart dit = tv.begin() ; dit != tv.end() ; dit = tv.next())
{
PFP::VEC3 p(0.0);
unsigned int c = 0;
Traversor3VVaE<typename PFP::MAP> trav3VVaE(myMap, dit);
for(Dart dit3VVaF = trav3VVaE.begin() ; dit3VVaF != trav3VVaE.end() ; dit3VVaF = trav3VVaE.next())
{
p += position[dit3VVaF];
++c;
}
p /= double(c);
position_smooting[dit] = p;
}
myMap.swapAttributes(position, position_smooting);
}
virtual void split_tet_test()
{
myMap.disableQuickTraversal<VOLUME>();
myMap.disableQuickTraversal<VERTEX>();
myMap.disableQuickIncidentTraversal<VERTEX, VOLUME>();
myMap.disableQuickIncidentTraversal<VOLUME, VERTEX>();
myMap.disableQuickAdjacentTraversal<VERTEX, EDGE>();
myMap.disableQuickAdjacentTraversal<VOLUME, VERTEX>();
TraversorW<typename PFP::MAP> tW(myMap);
for(Dart dit = tW.begin() ; dit != tW.end() ; dit = tW.next())
{
typename PFP::VEC3 volCenter(0.0);
volCenter += position[dit];
volCenter += position[myMap.phi1(dit)];
volCenter += position[myMap.phi_1(dit)];
volCenter += position[myMap.phi_1(myMap.phi2(dit))];
volCenter /= 4;
Dart dres = Algo::Volume::Modelisation::Tetrahedralization::flip1To4<PFP>(myMap, dit);
position[dres] = volCenter;
}
}
virtual void collapse_test(unsigned int n)
{
boundary_vertex = myMap.addAttribute<int, VERTEX>("boundaryVertex");
TraversorE<PFP::MAP> te(myMap);
for(Dart dit = te.begin() ; dit != te.end() ; dit = te.next())
boundary_vertex[dit]=0;
for(unsigned int i = 0; i < n; ++i)
{
Dart dit = getShortestEdge();
if(dit == NIL)
{
std::cerr << "No valid edge anymore, aborting at step "<<i << std::endl;
return;
}
boundary_vertex[dit]=0;
boundary_vertex[myMap.phi_1(dit)]=0;
myMap.collapseEdge(dit);
}
}
};
//=============================================================================

View File

@ -0,0 +1,578 @@
if (EXISTS ${CMAKE_SOURCE_DIR}/${CMAKE_PROJECT_NAME}.cmake)
include (${CMAKE_SOURCE_DIR}/${CMAKE_PROJECT_NAME}.cmake)
endif ()
# prevent build in source directory
if ("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
message (SEND_ERROR "Building in the source directory is not supported.")
message (FATAL_ERROR "Please remove the created \"CMakeCache.txt\" file, the \"CMakeFiles\" directory and create a build directory and call \"${CMAKE_COMMAND} <path to the sources>\".")
endif ("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
# allow only Debug and Release builds
set (CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)
mark_as_advanced (CMAKE_CONFIGURATION_TYPES)
# set Debus as default build target
if (NOT CMAKE_BUILD_TYPE)
set (CMAKE_BUILD_TYPE Debug CACHE STRING
"Choose the type of build, options are: Debug, Release."
FORCE)
endif ()
# create our output directroy
if (NOT EXISTS ${CMAKE_BINARY_DIR}/Build)
file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Build)
endif ()
# read version from file
macro (acg_get_version)
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${ARGN}/VERSION")
file (READ "${CMAKE_CURRENT_SOURCE_DIR}/${ARGN}/VERSION" _file)
else ()
file (READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" _file)
endif ()
string (
REGEX REPLACE
"^.*ID=([^\n]*).*$" "\\1"
_id ${_file}
)
string (
REGEX REPLACE
"^.*VERSION=([^\n]*).*$" "\\1"
_version ${_file}
)
string (
REGEX REPLACE
"^.*MAJOR=([^\n]*).*$" "\\1"
_major ${_file}
)
string (
REGEX REPLACE
"^.*MINOR=([^\n]*).*$" "\\1"
_minor ${_file}
)
string (
REGEX REPLACE
"^.*PATCH=([^\n]*).*$" "\\1"
_patch ${_file}
)
set (${_id}_VERSION ${_version})
set (${_id}_VERSION_MAJOR ${_major})
set (${_id}_VERSION_MINOR ${_minor})
set (${_id}_VERSION_PATCH ${_patch})
endmacro ()
# set directory structures for the different platforms
if (WIN32)
set (ACG_PROJECT_DATADIR ".")
set (ACG_PROJECT_LIBDIR "lib")
set (ACG_PROJECT_BINDIR ".")
set (ACG_PROJECT_PLUGINDIR "Plugins")
if (NOT EXISTS ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR})
file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR})
endif ()
else ()
set (ACG_PROJECT_DATADIR "share/${CMAKE_PROJECT_NAME}")
set (ACG_PROJECT_LIBDIR "lib/${CMAKE_PROJECT_NAME}")
set (ACG_PROJECT_PLUGINDIR "lib/${CMAKE_PROJECT_NAME}/plugins")
set (ACG_PROJECT_BINDIR "bin")
endif ()
if( NOT APPLE )
# check 64 bit
if( CMAKE_SIZEOF_VOID_P MATCHES 4 )
set( HAVE_64_BIT 0 )
else( CMAKE_SIZEOF_VOID_P MATCHES 4 )
set( HAVE_64_BIT 1 )
endif( CMAKE_SIZEOF_VOID_P MATCHES 4 )
endif ( NOT APPLE )
# allow a project to modify the directories
if (COMMAND acg_modify_project_dirs)
acg_modify_project_dirs ()
endif ()
if (NOT EXISTS ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_DATADIR})
file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_DATADIR})
endif ()
# sets default build properties
macro (acg_set_target_props target)
if (WIN32)
set_target_properties (
${target} PROPERTIES
BUILD_WITH_INSTALL_RPATH 1
SKIP_BUILD_RPATH 0
)
elseif (APPLE AND NOT ACG_PROJECT_MACOS_BUNDLE)
set_target_properties (
${target} PROPERTIES
#INSTALL_NAME_DIR "@executable_path/../lib/${CMAKE_PROJECT_NAME}"
INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib/${CMAKE_PROJECT_NAME}"
# BUILD_WITH_INSTALL_RPATH 1
SKIP_BUILD_RPATH 0
)
elseif (NOT APPLE)
set_target_properties (
${target} PROPERTIES
INSTALL_RPATH "$ORIGIN/../lib/${CMAKE_PROJECT_NAME}"
BUILD_WITH_INSTALL_RPATH 1
SKIP_BUILD_RPATH 0
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_BINDIR}"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}"
)
endif ()
endmacro ()
include (AddFileDependencies)
include (ACGCompiler)
# define INCLUDE_TEMPLATES for everything we build
add_definitions (-DINCLUDE_TEMPLATES)
# look for selected qt dependencies
macro (acg_qt4)
if (NOT QT4_FOUND)
find_package (Qt4 COMPONENTS QtCore QtGui ${ARGN})
set (QT_USE_QTOPENGL 1)
set (QT_USE_QTNETWORK 1)
set (QT_USE_QTSCRIPT 1)
set (QT_USE_QTSQL 1)
set (QT_USE_QTXML 1)
set (QT_USE_QTXMLPATTERNS 1)
set (QT_USE_QTHELP 1)
set (QT_USE_QTWEBKIT 1)
set (QT_USE_QTUITOOLS 1)
include (${QT_USE_FILE})
endif ()
endmacro ()
# unsets the given variable
macro (acg_unset var)
set (${var} "" CACHE INTERNAL "")
endmacro ()
# sets the given variable
macro (acg_set var value)
set (${var} ${value} CACHE INTERNAL "")
endmacro ()
# test for OpenMP
macro (acg_openmp)
if (NOT OPENMP_NOTFOUND)
find_package(OpenMP)
if (OPENMP_FOUND)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
add_definitions(-DUSE_OPENMP)
else ()
set (OPENMP_NOTFOUND 1)
endif ()
endif ()
endmacro ()
# test for FTGL
macro (acg_ftgl)
find_package (Freetype)
if (FREETYPE_FOUND)
find_package (FTGL)
if (FTGL_FOUND)
add_definitions (-DUSE_FTGL)
include_directories (${FTGL_INCLUDE_DIR} ${FREETYPE_INCLUDE_DIR_freetype2})
set (FTGL_LIBS ${FREETYPE_LIBRARIES} ${FTGL_LIBRARIES})
endif ()
endif ()
endmacro ()
# append all files with extension "ext" in the "dirs" directories to "ret"
# excludes all files starting with a '.' (dot)
macro (acg_append_files ret ext)
foreach (_dir ${ARGN})
file (GLOB _files "${_dir}/${ext}")
foreach (_file ${_files})
get_filename_component (_filename ${_file} NAME)
if (_filename MATCHES "^[.]")
list (REMOVE_ITEM _files ${_file})
endif ()
endforeach ()
list (APPEND ${ret} ${_files})
endforeach ()
endmacro ()
# append all files with extension "ext" in the "dirs" directories and its subdirectories to "ret"
# excludes all files starting with a '.' (dot)
macro (acg_append_files_recursive ret ext)
foreach (_dir ${ARGN})
file (GLOB_RECURSE _files "${_dir}/${ext}")
foreach (_file ${_files})
get_filename_component (_filename ${_file} NAME)
if (_filename MATCHES "^[.]")
list (REMOVE_ITEM _files ${_file})
endif ()
endforeach ()
list (APPEND ${ret} ${_files})
endforeach ()
endmacro ()
# drop all "*T.cc" files from list
macro (acg_drop_templates list)
foreach (_file ${${list}})
if (_file MATCHES "T.cc$")
list (REMOVE_ITEM ${list} ${_file})
endif ()
endforeach ()
endmacro ()
# generate moc targets for sources in list
macro (acg_qt4_automoc moc_SRCS)
qt4_get_moc_flags (_moc_INCS)
set (_matching_FILES )
foreach (_current_FILE ${ARGN})
get_filename_component (_abs_FILE ${_current_FILE} ABSOLUTE)
# if "SKIP_AUTOMOC" is set to true, we will not handle this file here.
# here. this is required to make bouic work correctly:
# we need to add generated .cpp files to the sources (to compile them),
# but we cannot let automoc handle them, as the .cpp files don't exist yet when
# cmake is run for the very first time on them -> however the .cpp files might
# exist at a later run. at that time we need to skip them, so that we don't add two
# different rules for the same moc file
get_source_file_property (_skip ${_abs_FILE} SKIP_AUTOMOC)
if ( NOT _skip AND EXISTS ${_abs_FILE} )
file (READ ${_abs_FILE} _contents)
get_filename_component (_abs_PATH ${_abs_FILE} PATH)
string (REGEX MATCHALL "Q_OBJECT" _match "${_contents}")
if (_match)
get_filename_component (_basename ${_current_FILE} NAME_WE)
set (_header ${_abs_FILE})
set (_moc ${CMAKE_CURRENT_BINARY_DIR}/moc_${_basename}.cpp)
add_custom_command (OUTPUT ${_moc}
COMMAND ${QT_MOC_EXECUTABLE}
ARGS ${_moc_INCS} ${_header} -o ${_moc}
DEPENDS ${_header}
)
add_file_dependencies (${_abs_FILE} ${_moc})
set (${moc_SRCS} ${${moc_SRCS}} ${_moc})
endif ()
endif ()
endforeach ()
endmacro ()
# generate uic targets for sources in list
macro (acg_qt4_autouic uic_SRCS)
set (_matching_FILES )
foreach (_current_FILE ${ARGN})
get_filename_component (_abs_FILE ${_current_FILE} ABSOLUTE)
if ( EXISTS ${_abs_FILE} )
file (READ ${_abs_FILE} _contents)
get_filename_component (_abs_PATH ${_abs_FILE} PATH)
get_filename_component (_basename ${_current_FILE} NAME_WE)
string (REGEX REPLACE "Ui$" "" _cbasename ${_basename})
set (_outfile ${CMAKE_CURRENT_BINARY_DIR}/ui_${_basename}.hh)
set (_header ${_basename}.hh)
set (_source ${_abs_PATH}/${_cbasename}.cc)
add_custom_command (OUTPUT ${_outfile}
COMMAND ${QT_UIC_EXECUTABLE}
ARGS -o ${_outfile} ${_abs_FILE}
DEPENDS ${_abs_FILE})
add_file_dependencies (${_source} ${_outfile})
set (${uic_SRCS} ${${uic_SRCS}} ${_outfile})
endif ()
endforeach ()
endmacro ()
# generate qrc targets for sources in list
macro (acg_qt4_autoqrc qrc_SRCS)
set (_matching_FILES )
foreach (_current_FILE ${ARGN})
get_filename_component (_abs_FILE ${_current_FILE} ABSOLUTE)
if ( EXISTS ${_abs_FILE} )
file (READ ${_abs_FILE} _contents)
get_filename_component (_abs_PATH ${_abs_FILE} PATH)
get_filename_component (_basename ${_current_FILE} NAME_WE)
set (_outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${_basename}.cpp)
add_custom_command (OUTPUT ${_outfile}
COMMAND ${QT_RCC_EXECUTABLE}
ARGS -o ${_outfile} ${_abs_FILE}
DEPENDS ${_abs_FILE})
add_file_dependencies (${_source} ${_outfile})
set (${qrc_SRCS} ${${qrc_SRCS}} ${_outfile})
endif ()
endforeach ()
endmacro ()
# get all files in directory, but ignore svn
macro (acg_get_files_in_dir ret dir)
file (GLOB_RECURSE __files RELATIVE "${dir}" "${dir}/*")
foreach (_file ${__files})
if (NOT _file MATCHES ".*svn.*")
list (APPEND ${ret} "${_file}")
endif ()
endforeach ()
endmacro ()
# copy the whole directory without svn files
function (acg_copy_after_build target src dst)
acg_unset (_files)
acg_get_files_in_dir (_files ${src})
foreach (_file ${_files})
add_custom_command(TARGET ${target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${src}/${_file}" "${dst}/${_file}"
)
endforeach ()
endfunction ()
# install the whole directory without svn files
function (acg_install_dir src dst)
acg_unset (_files)
acg_get_files_in_dir (_files ${src})
foreach (_file ${_files})
get_filename_component (_file_PATH ${_file} PATH)
install(FILES "${src}/${_file}"
DESTINATION "${dst}/${_file_PATH}"
)
endforeach ()
endfunction ()
# extended version of add_executable that also copies output to out Build directory
function (acg_add_executable _target)
add_executable (${_target} ${ARGN})
# set common target properties defined in common.cmake
acg_set_target_props (${_target})
if (WIN32)
# copy exe file to "Build" directory
# Visual studio will create this file in a subdirectory so we can't use
# RUNTIME_OUTPUT_DIRECTORY directly here
add_custom_command (TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${_target}.exe
${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_BINDIR}/${_target}.exe)
elseif (APPLE AND NOT ACG_PROJECT_MACOS_BUNDLE)
add_custom_command (TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${_target}
${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_BINDIR}/${_target})
endif ()
if (NOT ACG_PROJECT_MACOS_BUNDLE OR NOT APPLE)
install (TARGETS ${_target} DESTINATION ${ACG_PROJECT_BINDIR})
endif ()
endfunction ()
# extended version of add_library that also copies output to out Build directory
function (acg_add_library _target _libtype)
if (${_libtype} STREQUAL SHAREDANDSTATIC)
set (_type SHARED)
if (NOT WIN32)
set (_and_static 1)
else ()
set (_and_static 0)
endif ()
else ()
set (_type ${_libtype})
set (_and_static 0)
endif ()
add_library (${_target} ${_type} ${ARGN} )
# set common target properties defined in common.cmake
acg_set_target_props (${_target})
if (_and_static)
add_library (${_target}Static STATIC ${ARGN})
# set common target properties defined in common.cmake
acg_set_target_props (${_target}Static)
if (NOT APPLE)
set_target_properties (${_target}Static PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}"
)
endif ()
endif ()
if (WIN32)
# copy exe file to "Build" directory
# Visual studio will create this file in a subdirectory so we can't use
# RUNTIME_OUTPUT_DIRECTORY directly here
if (${_type} STREQUAL SHARED)
add_custom_command (TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${_target}.dll
${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_BINDIR}/${_target}.dll)
elseif (${_type} STREQUAL MODULE)
if (NOT EXISTS ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_PLUGINDIR})
file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_PLUGINDIR})
endif ()
add_custom_command (TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${_target}.dll
${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_PLUGINDIR}/${_target}.dll)
endif ()
if (${_type} STREQUAL SHARED OR ${_type} STREQUAL STATIC)
add_custom_command (TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${_target}.lib
${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}/${_target}.lib)
endif ()
elseif (APPLE AND NOT ACG_PROJECT_MACOS_BUNDLE)
if (${_type} STREQUAL SHARED)
add_custom_command (TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${_target}.dylib
${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}/lib${_target}.dylib)
elseif (${_type} STREQUAL MODULE)
if (NOT EXISTS ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_PLUGINDIR})
file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_PLUGINDIR})
endif ()
add_custom_command (TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${_target}.so
${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_PLUGINDIR}/lib${_target}.so)
elseif (${_type} STREQUAL STATIC)
add_custom_command (TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${_target}.a
${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}/lib${_target}.a)
endif ()
if (_and_static)
add_custom_command (TARGET ${_target}Static POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${_target}Static.a
${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}/lib${_target}.a)
endif ()
elseif (NOT APPLE AND _and_static)
add_custom_command (TARGET ${_target}Static POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${_target}Static.a
${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}/lib${_target}.a)
endif ()
# Block installation of libraries by setting ACG_NO_LIBRARY_INSTALL
if ( NOT ACG_NO_LIBRARY_INSTALL )
if (NOT ACG_PROJECT_MACOS_BUNDLE OR NOT APPLE)
if (${_type} STREQUAL SHARED OR ${_type} STREQUAL STATIC )
install (TARGETS ${_target}
RUNTIME DESTINATION ${ACG_PROJECT_BINDIR}
LIBRARY DESTINATION ${ACG_PROJECT_LIBDIR}
ARCHIVE DESTINATION ${ACG_PROJECT_LIBDIR})
if (_and_static)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${_target}Static.a
DESTINATION ${ACG_PROJECT_LIBDIR}
RENAME lib${_target}.a
PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
endif ()
elseif (${_type} STREQUAL MODULE)
install (TARGETS ${_target} DESTINATION ${ACG_PROJECT_PLUGINDIR})
endif ()
endif ()
endif()
endfunction ()
#generates qt translations
function (acg_add_translations _target _languages _sources)
string (TOUPPER ${_target} _TARGET)
# generate/use translation files
# run with UPDATE_TRANSLATIONS set to on to build qm files
option (UPDATE_TRANSLATIONS_${_TARGET} "Update source translation *.ts files (WARNING: make clean will delete the source .ts files! Danger!)")
set (_new_ts_files)
set (_ts_files)
foreach (lang ${_languages})
if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/translations/${_target}_${lang}.ts" OR UPDATE_TRANSLATIONS_${_TARGET})
list (APPEND _new_ts_files "translations/${_target}_${lang}.ts")
else ()
list (APPEND _ts_files "translations/${_target}_${lang}.ts")
endif ()
endforeach ()
set (_qm_files)
if ( _new_ts_files )
qt4_create_translation(_qm_files ${_sources} ${_new_ts_files})
endif ()
if ( _ts_files )
qt4_add_translation(_qm_files2 ${_ts_files})
list (APPEND _qm_files ${_qm_files2})
endif ()
# create a target for the translation files ( and object files )
# Use this target, to update only the translations
add_custom_target (translations_target_${_target} DEPENDS ${_qm_files})
# Build translations with the application
add_dependencies(${_target} translations_target_${_target} )
if (NOT EXISTS ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_DATADIR}/Translations)
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_DATADIR}/Translations )
endif ()
foreach (_qm ${_qm_files})
get_filename_component (_qm_name "${_qm}" NAME)
add_custom_command (TARGET translations_target_${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E
copy_if_different
${_qm}
${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_DATADIR}/Translations/${_qm_name})
endforeach ()
if (NOT ACG_PROJECT_MACOS_BUNDLE OR NOT APPLE)
install (FILES ${_qm_files} DESTINATION "${ACG_PROJECT_DATADIR}/Translations")
endif ()
endfunction ()

View File

@ -0,0 +1,151 @@
################################################################################
# Custom settings for compiler flags and similar
################################################################################
if (UNIX)
set ( ADDITIONAL_CXX_DEBUG_FLAGS )
set ( ADDITIONAL_CXX_RELEASE_FLAGS )
set ( ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS )
set ( ADDITIONAL_C_DEBUG_FLAGS )
set ( ADDITIONAL_C_RELEASE_FLAGS )
set ( ADDITIONAL_C_RELWITHDEBINFO_FLAGS )
################################################################################
# Defaults
################################################################################
# add our standard flags for Template inclusion
list(APPEND ADDITIONAL_CXX_DEBUG_FLAGS "-DINCLUDE_TEMPLATES" )
list(APPEND ADDITIONAL_CXX_RELEASE_FLAGS "-DINCLUDE_TEMPLATES" )
list(APPEND ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS "-DINCLUDE_TEMPLATES" )
# add our standard flags for Template inclusion
list(APPEND ADDITIONAL_C_DEBUG_FLAGS "-DINCLUDE_TEMPLATES" )
list(APPEND ADDITIONAL_C_RELEASE_FLAGS "-DINCLUDE_TEMPLATES" )
list(APPEND ADDITIONAL_C_RELWITHDEBINFO_FLAGS "-DINCLUDE_TEMPLATES" )
# Increase the template depth as this might be exceeded from time to time
IF( NOT CMAKE_SYSTEM MATCHES "SunOS*")
list(APPEND ADDITIONAL_CXX_DEBUG_FLAGS "-ftemplate-depth-100" )
list(APPEND ADDITIONAL_CXX_RELEASE_FLAGS "-ftemplate-depth-100" )
list(APPEND ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS "-ftemplate-depth-100" )
ENDIF()
################################################################################
# OS Defines
################################################################################
if (APPLE)
add_definitions( -DARCH_DARWIN )
endif()
################################################################################
# Build/Release Defines
################################################################################
IF( NOT CMAKE_SYSTEM MATCHES "SunOS*")
list(APPEND ADDITIONAL_CXX_DEBUG_FLAGS "-DDEBUG" )
list(APPEND ADDITIONAL_CXX_RELEASE_FLAGS "-DNDEBUG" )
list(APPEND ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS "-DDEBUG" )
list(APPEND ADDITIONAL_C_DEBUG_FLAGS "-DDEBUG" )
list(APPEND ADDITIONAL_C_RELEASE_FLAGS "-DNDEBUG" )
list(APPEND ADDITIONAL_C_RELWITHDEBINFO_FLAGS "-DDEBUG" )
ENDIF()
################################################################################
# Warnings
################################################################################
IF( NOT CMAKE_SYSTEM MATCHES "SunOS*")
list(APPEND ADDITIONAL_CXX_DEBUG_FLAGS "-W" "-Wall" "-Wno-unused" )
list(APPEND ADDITIONAL_CXX_RELEASE_FLAGS "-W" "-Wall" "-Wno-unused" )
list(APPEND ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS "-W" "-Wall" "-Wno-unused" )
list(APPEND ADDITIONAL_C_DEBUG_FLAGS "-W" "-Wall" "-Wno-unused" )
list(APPEND ADDITIONAL_C_RELEASE_FLAGS "-W" "-Wall" "-Wno-unused" )
list(APPEND ADDITIONAL_C_RELWITHDEBINFO_FLAGS "-W" "-Wall" "-Wno-unused" )
ENDIF()
if (APPLE)
list(APPEND ADDITIONAL_CXX_DEBUG_FLAGS "-Wno-non-virtual-dtor" )
list(APPEND ADDITIONAL_CXX_RELEASE_FLAGS "-Wno-non-virtual-dtor" )
list(APPEND ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS "-Wno-non-virtual-dtor" )
endif ()
################################################################################
# STL Vector checks
################################################################################
# Pre initialize stl vector check variable
if ( NOT STL_VECTOR_CHECKS )
set ( STL_VECTOR_CHECKS false CACHE BOOL "Include full stl vector checks in debug mode (This option is only used in debug Mode!)" )
endif ( NOT STL_VECTOR_CHECKS )
# Add a flag to check stl vectors in debugging mode
if ( STL_VECTOR_CHECKS AND NOT CMAKE_SYSTEM MATCHES "SunOS*" )
list(APPEND ADDITIONAL_CXX_DEBUG_FLAGS "-D_GLIBCXX_DEBUG" )
list(APPEND ADDITIONAL_CXX_DEBUG_FLAGS "-D_GLIBCXX_DEBUG_PEDANTIC")
list(APPEND ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS "-D_GLIBCXX_DEBUG" )
list(APPEND ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS "-D_GLIBCXX_DEBUG_PEDANTIC")
list(APPEND ADDITIONAL_C_DEBUG_FLAGS "-D_GLIBCXX_DEBUG" )
list(APPEND ADDITIONAL_C_DEBUG_FLAGS "-D_GLIBCXX_DEBUG_PEDANTIC")
list(APPEND ADDITIONAL_C_RELWITHDEBINFO_FLAGS "-D_GLIBCXX_DEBUG" )
list(APPEND ADDITIONAL_C_RELWITHDEBINFO_FLAGS "-D_GLIBCXX_DEBUG_PEDANTIC")
endif()
################################################################################
# Process the additional flags:
################################################################################
# Add the debug flags
foreach( flag ${ADDITIONAL_CXX_DEBUG_FLAGS} )
if( NOT CMAKE_CXX_FLAGS_DEBUG MATCHES "${flag}" )
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${flag} ")
endif()
endforeach()
# Add the release flags
foreach( flag ${ADDITIONAL_CXX_RELEASE_FLAGS} )
if( NOT CMAKE_CXX_FLAGS_RELEASE MATCHES "${flag}" )
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${flag} ")
endif()
endforeach()
# Add the release with debug info flags
foreach( flag ${ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS} )
if( NOT CMAKE_CXX_FLAGS_RELWITHDEBINFO MATCHES "${flag}" )
set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${flag} ")
endif()
endforeach()
# Add the debug flags
foreach( flag ${ADDITIONAL_C_DEBUG_FLAGS} )
if( NOT CMAKE_C_FLAGS_DEBUG MATCHES "${flag}" )
set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${flag} ")
endif()
endforeach()
# Add the release flags
foreach( flag ${ADDITIONAL_C_RELEASE_FLAGS} )
if( NOT CMAKE_C_FLAGS_RELEASE MATCHES "${flag}" )
set( CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${flag} ")
endif()
endforeach()
# Add the release with debug info flags
foreach( flag ${ADDITIONAL_C_RELWITHDEBINFO_FLAGS} )
if( NOT CMAKE_C_FLAGS_RELWITHDEBINFO MATCHES "${flag}" )
set( CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${flag} ")
endif()
endforeach()
#TODO : Test and remove it?!
IF( CMAKE_SYSTEM MATCHES "SunOS*")
set (CMAKE_CFLAGS_RELEASE "-xO3")
set (CMAKE_CXX_FLAGS_RELEASE "-xO3")
endif ( CMAKE_SYSTEM MATCHES "SunOS*" )
endif ()

View File

@ -0,0 +1,122 @@
# -helper macro to add a "doc" target with CMake build system.
# and configure doxy.config.in to doxy.config
#
# target "doc" allows building the documentation with doxygen/dot on WIN32 and Linux
# Creates .chm windows help file if MS HTML help workshop
# (available from http://msdn.microsoft.com/workshop/author/htmlhelp)
# is installed with its DLLs in PATH.
#
#
# Please note, that the tools, e.g.:
# doxygen, dot, latex, dvips, makeindex, gswin32, etc.
# must be in path.
#
# Note about Visual Studio Projects:
# MSVS hast its own path environment which may differ from the shell.
# See "Menu Tools/Options/Projects/VC++ Directories" in VS 7.1
#
# author Jan Woetzel 2004-2006
# www.mip.informatik.uni-kiel.de/~jw
FIND_PACKAGE(Doxygen)
IF (DOXYGEN_FOUND)
# click+jump in Emacs and Visual Studio (for doxy.config) (jw)
IF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
SET(DOXY_WARN_FORMAT "\"$file($line) : $text \"")
ELSE (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
SET(DOXY_WARN_FORMAT "\"$file:$line: $text \"")
ENDIF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
# we need latex for doxygen because of the formulas
FIND_PACKAGE(LATEX)
IF (NOT LATEX_COMPILER)
MESSAGE(STATUS "latex command LATEX_COMPILER not found but usually required. You will probably get warnings and user inetraction on doxy run.")
ENDIF (NOT LATEX_COMPILER)
IF (NOT MAKEINDEX_COMPILER)
MESSAGE(STATUS "makeindex command MAKEINDEX_COMPILER not found but usually required.")
ENDIF (NOT MAKEINDEX_COMPILER)
IF (NOT DVIPS_CONVERTER)
MESSAGE(STATUS "dvips command DVIPS_CONVERTER not found but usually required.")
ENDIF (NOT DVIPS_CONVERTER)
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
MESSAGE(STATUS "configured ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in --> ${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in
${CMAKE_CURRENT_BINARY_DIR}/doxy.config
@ONLY )
# use (configured) doxy.config from (out of place) BUILD tree:
SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
# use static hand-edited doxy.config from SOURCE tree:
SET(DOXY_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
MESSAGE(STATUS "WARNING: using existing ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config instead of configuring from doxy.config.in file.")
ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
IF (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
# using template doxy.config.in
MESSAGE(STATUS "configured ${CMAKE_CMAKE_MODULE_PATH}/doxy.config.in --> ${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
CONFIGURE_FILE(${CMAKE_MODULE_PATH}/doxy.config.in
${CMAKE_CURRENT_BINARY_DIR}/doxy.config
@ONLY )
SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
ELSE (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
# failed completely...
MESSAGE(SEND_ERROR "Please create ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in (or doxy.config as fallback)")
ENDIF(EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
ADD_CUSTOM_TARGET(doc ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG})
# create a windows help .chm file using hhc.exe
# HTMLHelp DLL must be in path!
# fallback: use hhw.exe interactively
IF (WIN32)
FIND_PACKAGE(HTMLHelp)
IF (HTML_HELP_COMPILER)
SET (TMP "${CMAKE_CURRENT_BINARY_DIR}\\Doc\\html\\index.hhp")
STRING(REGEX REPLACE "[/]" "\\\\" HHP_FILE ${TMP} )
# MESSAGE(SEND_ERROR "DBG HHP_FILE=${HHP_FILE}")
ADD_CUSTOM_TARGET(winhelp ${HTML_HELP_COMPILER} ${HHP_FILE})
ADD_DEPENDENCIES (winhelp doc)
IF (NOT TARGET_DOC_SKIP_INSTALL)
# install windows help?
# determine useful name for output file
# should be project and version unique to allow installing
# multiple projects into one global directory
IF (EXISTS "${PROJECT_BINARY_DIR}/Doc/html/index.chm")
IF (PROJECT_NAME)
SET(OUT "${PROJECT_NAME}")
ELSE (PROJECT_NAME)
SET(OUT "Documentation") # default
ENDIF(PROJECT_NAME)
IF (${PROJECT_NAME}_VERSION_MAJOR)
SET(OUT "${OUT}-${${PROJECT_NAME}_VERSION_MAJOR}")
IF (${PROJECT_NAME}_VERSION_MINOR)
SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_MINOR}")
IF (${PROJECT_NAME}_VERSION_PATCH)
SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_PATCH}")
ENDIF(${PROJECT_NAME}_VERSION_PATCH)
ENDIF(${PROJECT_NAME}_VERSION_MINOR)
ENDIF(${PROJECT_NAME}_VERSION_MAJOR)
# keep suffix
SET(OUT "${OUT}.chm")
#MESSAGE("DBG ${PROJECT_BINARY_DIR}/Doc/html/index.chm \n${OUT}")
# create target used by install and package commands
INSTALL(FILES "${PROJECT_BINARY_DIR}/Doc/html/index.chm"
DESTINATION "doc"
RENAME "${OUT}"
)
ENDIF(EXISTS "${PROJECT_BINARY_DIR}/Doc/html/index.chm")
ENDIF(NOT TARGET_DOC_SKIP_INSTALL)
ENDIF(HTML_HELP_COMPILER)
# MESSAGE(SEND_ERROR "HTML_HELP_COMPILER=${HTML_HELP_COMPILER}")
ENDIF (WIN32)
ENDIF(DOXYGEN_FOUND)

View File

@ -0,0 +1,38 @@
# fill string with spaces
macro (acg_format_string str length return)
string (LENGTH "${str}" _str_len)
math (EXPR _add_chr "${length} - ${_str_len}")
set (${return} "${str}")
while (_add_chr GREATER 0)
set (${return} "${${return}} ")
math (EXPR _add_chr "${_add_chr} - 1")
endwhile ()
endmacro ()
# print message with color escape sequences if CMAKE_COLOR_MAKEFILE is set
string (ASCII 27 _escape)
function (acg_color_message _str)
if (CMAKE_COLOR_MAKEFILE AND NOT WIN32)
message (${_str})
else ()
string (REGEX REPLACE "${_escape}.[0123456789;]*m" "" __str ${_str})
message (${__str})
endif ()
endfunction ()
# info header
function (acg_print_configure_header _id _name)
acg_format_string ("${_name}" 40 _project)
acg_format_string ("${${_id}_VERSION}" 40 _version)
acg_color_message ("\n${_escape}[40;37m************************************************************${_escape}[0m")
acg_color_message ("${_escape}[40;37m* ${_escape}[1;31mACG ${_escape}[0;40;34mBuildsystem${_escape}[0m${_escape}[40;37m *${_escape}[0m")
acg_color_message ("${_escape}[40;37m* *${_escape}[0m")
acg_color_message ("${_escape}[40;37m* Package : ${_escape}[32m${_project} ${_escape}[37m *${_escape}[0m")
acg_color_message ("${_escape}[40;37m* Version : ${_escape}[32m${_version} ${_escape}[37m *${_escape}[0m")
acg_color_message ("${_escape}[40;37m************************************************************${_escape}[0m")
endfunction ()
# info line
function (acg_print_configure_footer)
acg_color_message ("${_escape}[40;37m************************************************************${_escape}[0m\n")
endfunction ()

View File

@ -0,0 +1,95 @@
# Locate and configure the Google Test libraries.
#
# Defines the following variable:
#
# GTEST_FOUND - Found the Google Test libraries
# GTEST_INCLUDE_DIRS - The directories needed on the include paths
# GTEST_LIBRARIES - The libraries to link to test executables
# GTEST_MAIN_LIBRARIES - The libraries to link for automatic main() provision
#
# Copyright 2008 Chandler Carruth
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy
# of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
if(GTEST_INCLUDE_DIRS AND GTEST_LIBRARIES AND GTEST_MAIN_LIBRARIES)
set(GTEST_FOUND true)
else(GTEST_INCLUDE_DIRS AND GTEST_LIBRARIES AND GTEST_MAIN_LIBRARIES)
set(GTEST_PREFIX "" CACHE PATH "Installation prefix for Google Test")
if(GTEST_PREFIX)
find_path(_GTEST_INCLUDE_DIR "gtest/gtest.h"
PATHS "${GTEST_PREFIX}/include"
NO_DEFAULT_PATH)
find_library(_GTEST_LIBRARY gtest
PATHS "${GTEST_PREFIX}/lib"
NO_DEFAULT_PATH)
find_library(_GTEST_MAIN_LIBRARY gtest_main
PATHS "${GTEST_PREFIX}/lib"
NO_DEFAULT_PATH)
if ( _GTEST_LIBRARY )
get_filename_component(_GTEST_LIBRARY_DIR ${_GTEST_LIBRARY} PATH CACHE )
endif()
else(GTEST_PREFIX)
find_path(_GTEST_INCLUDE_DIR "gtest/gtest.h"
PATHS
~/sw/gtest/include
/opt/local/include
/usr/local/include
"C:/libs/win32/gtest/include")
find_library(_GTEST_LIBRARY gtest
PATHS
~/sw/gtest/lib
/opt/local/lib
/usr/local/lib
"C:/libs/win32/gtest/lib")
find_library(_GTEST_MAIN_LIBRARY gtest_main
PATHS
~/sw/gtest/lib
/opt/local/lib
/usr/local/lib
"C:/libs/win32/gtest/lib")
if ( _GTEST_LIBRARY )
get_filename_component(_GTEST_LIBRARY_DIR ${_GTEST_LIBRARY} PATH CACHE )
endif()
endif(GTEST_PREFIX)
if(_GTEST_INCLUDE_DIR AND _GTEST_LIBRARY AND _GTEST_MAIN_LIBRARY)
set(GTEST_FOUND true)
set(GTEST_INCLUDE_DIRS ${_GTEST_INCLUDE_DIR} CACHE PATH
"Include directories for Google Test framework")
if ( NOT WIN32 )
set(GTEST_LIBRARIES ${_GTEST_LIBRARY} CACHE FILEPATH
"Libraries to link for Google Test framework")
set(GTEST_MAIN_LIBRARIES ${_GTEST_MAIN_LIBRARY} CACHE FILEPATH
"Libraries to link for Google Test automatic main() definition")
else()
set(GTEST_LIBRARIES "optimized;gtest;debug;gtestd" CACHE FILEPATH
"Libraries to link for Google Test framework")
set(GTEST_MAIN_LIBRARIES "optimized;gtest_main;debug;gtest_maind" CACHE FILEPATH
"Libraries to link for Google Test automatic main() definition")
endif()
set(GTEST_LIBRARY_DIR ${_GTEST_LIBRARY_DIR} CACHE FILEPATH
"Library dir containing Google Test libraries")
mark_as_advanced(GTEST_INCLUDE_DIRS GTEST_LIBRARIES GTEST_MAIN_LIBRARIES GTEST_LIBRARY_DIR )
if(NOT GoogleTest_FIND_QUIETLY)
message(STATUS "Found Google Test: ${GTEST_LIBRARIES}")
endif(NOT GoogleTest_FIND_QUIETLY)
else(_GTEST_INCLUDE_DIR AND _GTEST_LIBRARY AND _GTEST_MAIN_LIBRARY)
if(GoogleTest_FIND_REQUIRED)
message(FATAL_ERROR "Could not find the Google Test framework")
endif(GoogleTest_FIND_REQUIRED)
endif(_GTEST_INCLUDE_DIR AND _GTEST_LIBRARY AND _GTEST_MAIN_LIBRARY)
endif(GTEST_INCLUDE_DIRS AND GTEST_LIBRARIES AND GTEST_MAIN_LIBRARIES)

View File

@ -0,0 +1,57 @@
# gp_item_default_embedded_path_override item default_embedded_path_var
#
# Return the path that others should refer to the item by when the item
# is embedded inside a bundle.
#
# This is a project-specific override of BundleUtilities.cmake's
# gp_item_default_embedded_path
#
function(gp_item_default_embedded_path_override item default_embedded_path_var)
# By default, embed items as set by gp_item_default_embedded_path:
#
set(path "${${default_embedded_path_var}}")
# But for OpenFlipper...
#
# ...embed *.dylib in the Libraries folder:
#
if(item MATCHES "\\.dylib$")
set(path "@executable_path/../Libraries")
endif()
# ...embed qt plugins in the Libraries folder:
#
if(item MATCHES "@QT_PLUGINS_DIR@" AND item MATCHES "\\.bundle")
file (RELATIVE_PATH _plugin "@QT_PLUGINS_DIR@" "${item}")
get_filename_component(_dir "${_plugin}" PATH)
set(path "@executable_path/../Resources/QtPlugins/${_dir}")
endif()
# ...embed *.so in the Plugins folder:
#
if(item MATCHES "\\.so$")
set(path "@executable_path/../Resources/Plugins")
endif()
set(${default_embedded_path_var} "${path}" PARENT_SCOPE)
endfunction(gp_item_default_embedded_path_override)
include (BundleUtilities)
# copy qt plugins to bundle
file (GLOB _plugins "@CMAKE_BINARY_DIR@/Build/OpenFlipper.app/Contents/Resources/Plugins/*.so")
file (GLOB_RECURSE _qtplugins "@QT_PLUGINS_DIR@/*.bundle")
foreach (_qtp ${_qtplugins})
get_filename_component(_dir "${_qtp}" PATH)
list(APPEND _qtdirs "${_dir}")
endforeach ()
# Get library paths
get_filename_component(_GlutDir "@GLUT_glut_LIBRARY@" PATH)
# fix all dependencies
fixup_bundle (@CMAKE_BINARY_DIR@/Build/bin/QtViewer "${_qtplugins}" "/usr/lib;${_qtdirs};${_GlutDir}")
# create qt plugin configuration file
# file(WRITE "@CMAKE_BINARY_DIR@/Build/OpenVolumeMesh.app/Contents/Resources/qt.conf" "[Paths]\nPlugins = Resources/QtPlugins")

View File

@ -0,0 +1,24 @@
# gp_item_default_embedded_path_override item default_embedded_path_var
#
# Return the path that others should refer to the item by when the item
# is embedded inside a bundle.
#
# This is a project-specific override of BundleUtilities.cmake's
# gp_item_default_embedded_path
#
function(gp_item_default_embedded_path_override item default_embedded_path_var)
# By default, embed items as set by gp_item_default_embedded_path:
#
set(path "${${default_embedded_path_var}}")
set(${default_embedded_path_var} "${path}" PARENT_SCOPE)
endfunction(gp_item_default_embedded_path_override)
include (BundleUtilities)
# Get library paths
get_filename_component(_GlutDir "@GLUT_glut_LIBRARY@" PATH)
# fix all dependencies
fixup_bundle ("@CMAKE_BINARY_DIR@/Build/QtViewer.exe" "" "${_GlutDir};@QT_BINARY_DIR@")

View File

@ -0,0 +1,20 @@
//== INCLUDES =================================================================
#include "lcc_performance_3.h"
//=============================================================================
int main(int argc, char** argv)
{
if (argc < 2)
{
std::cerr << "Usage:\n" << argv[0] << " <input-mesh>\n";
exit(1);
}
for (int i=1; i<argc; ++i)
{
std::cout<<"**************** "<<argv[i]<<" ****************"<<std::endl;
LCC_performance_3().run(argv[i], "output_lcc_3.off");
}
return 0;
}
//=============================================================================

View File

@ -0,0 +1,697 @@
//== INCLUDES =================================================================
#include <CGAL/Linear_cell_complex.h>
#include <CGAL/Linear_cell_complex_operations.h>
#include <CGAL/Linear_cell_complex_constructors.h>
#include <CGAL/Cell_attribute.h>
#include <iostream>
#include <algorithm>
#include <fstream>
#include <vector>
#include "performance_3.h"
// Comment to use cmap with handle
#define CMAP_WITH_INDEX 1
//== CLASS DEFINITION =========================================================
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point_3;
typedef CGAL::Vector_3<Kernel> Vector_3;
struct Info_for_vertex
{
Info_for_vertex() : v(CGAL::NULL_VECTOR), m(0)
{}
Vector_3 v;
int m;
};
struct Info_for_volume
{
Info_for_volume() : m(0)
{}
int m;
};
#ifndef CMAP_WITH_INDEX
struct MyItem
{
template<class Refs>
struct Dart_wrapper
{
typedef CGAL::Dart<3, Refs> Dart;
typedef CGAL::Cell_attribute_with_point<Refs, Info_for_vertex, CGAL::Tag_true> Vertex_attribute;
typedef CGAL::Cell_attribute<Refs, Info_for_volume, CGAL::Tag_true> Vol_attribute;
typedef CGAL::cpp0x::tuple<Vertex_attribute, void, void, Vol_attribute> Attributes;
};
};
typedef CGAL::Linear_cell_complex<3,3,CGAL::Linear_cell_complex_traits<3,Kernel>, MyItem> LCC_3;
#else
struct MyItem
{
template<class Refs>
struct Dart_wrapper
{
typedef CGAL::Dart_for_index<3, Refs> Dart;
typedef CGAL::Cell_attribute_for_index_with_point<Refs, Info_for_vertex, CGAL::Tag_true> Vertex_attribute;
typedef CGAL::Cell_attribute_for_index<Refs, Info_for_volume, CGAL::Tag_true> Vol_attribute;
typedef CGAL::cpp0x::tuple<Vertex_attribute, void, void, Vol_attribute> Attributes;
};
};
typedef CGAL::Linear_cell_complex_for_index<3,3,CGAL::Linear_cell_complex_traits<3,Kernel>, MyItem> LCC_3;
#endif
typedef LCC_3::Dart_handle Dart_handle;
typedef LCC_3::Vertex_attribute_handle Vertex_handle;
typedef LCC_3::Attribute_handle<3>::type Volume_handle;
typedef LCC_3::Point Point;
typedef LCC_3::Vector Vector;
typedef LCC_3::FT FT;
//== CLASS DEFINITION =========================================================
class LCC_performance_3 : public Performance_test_3
{
private:
LCC_3 lcc;
CGAL::Unique_hash_map<Vertex_handle, std::vector<Vertex_handle>,
typename LCC_3::Hash_function > adjacent_vertices;
private:
void update_accelerators()
{
// We use accelerators, similarly than in cgogn. the only difference is that in cgogn
// they are use internally (i.e inside the library) while here they are use externally
// (i.e. inside the benchmarks).
// Note that in the current bench, they use 4 accelerators:
// 1) indicent VERTEX, VOLUME; 2) incident VOLUME, VERTEX;
// 3) adjacent VERTEX, EDGE; 4) adjacent VERTEX, VOLUME
// Here we only use adjacent VERTEX, EDGE and indicent VERTEX, VOLUME.
// First we update all adjacent vertices
adjacent_vertices.clear();
for (LCC_3::Vertex_attribute_range::iterator vit = lcc.vertex_attributes().begin(),
vend = lcc.vertex_attributes().end(); vit != vend; ++vit)
{
std::vector<Vertex_handle> adj;
for(LCC_3::One_dart_per_incident_cell_range<1,0>::iterator
it = lcc.one_dart_per_incident_cell<1,0>(vit->dart()).begin(),
itend = lcc.one_dart_per_incident_cell<1,0>(vit->dart()).end();
it != itend; ++it)
{
if ( lcc.vertex_attribute(it)==vit )
{
adj.push_back(lcc.vertex_attribute(lcc.other_extremity(it)));
}
else
{
adj.push_back(lcc.vertex_attribute(it));
}
}
adjacent_vertices[vit]=adj;
}
}
void display_info()
{
lcc.display_characteristics(std::cout);
std::cout << "\t" << std::endl;
}
void collapse(Dart_handle dart)
{
std::vector<Dart_handle> tet_ring;
// Get ring of tets
// incident to the current edge
Dart_handle iter = dart;
do
{
tet_ring.push_back(iter);
// Go over to adjacent tet in tet-ring
iter = lcc.beta<2,3>(iter);
}
while(iter != dart);
// Get top vertex
Dart_handle topVertex = dart;
Dart_handle botVertex = lcc.beta<1>(dart);
// Get barycenter of current edge
Point bc = lcc.barycenter<1>(dart);
// Set geometry of top and bottom vertex to barycenter of former edge
lcc.point(topVertex) = bc;
lcc.point(botVertex) = bc;
// 0=not known; 1=boundary; 2=no boundary
if ( lcc.info<0>(topVertex).m==1 )
lcc.info<0>(botVertex).m = 1;
else if ( lcc.info<0>(topVertex).m==0 )
lcc.info<0>(botVertex).m = 0;
if ( lcc.info<0>(botVertex).m==1 )
lcc.info<0>(topVertex).m = 1;
else if ( lcc.info<0>(botVertex).m==0 )
lcc.info<0>(topVertex).m = 0;
// Delete tets in ring
for(std::vector<Dart_handle>::const_iterator cr_it = tet_ring.begin(),
cr_end = tet_ring.end();
cr_it != cr_end;
++cr_it)
{
Dart_handle top = lcc.beta<1,2,3>(*cr_it);
Dart_handle bottom = lcc.beta<0,2,3>(*cr_it);
CGAL::remove_cell<LCC_3, 3>(lcc, *cr_it);
lcc.sew<3>(top,bottom);
}
}
Dart_handle create_face(Dart_handle old1,
Vertex_handle v1, Vertex_handle v2, Vertex_handle v3,
Volume_handle vol)
{
Dart_handle old2 = lcc.beta<2>(old1);
Dart_handle d1=lcc.create_dart(v1);
Dart_handle d2=lcc.create_dart(v2);
Dart_handle d3=lcc.create_dart(v3);
lcc.set_dart_attribute<3>(d1,vol);
lcc.set_dart_attribute<3>(d2,vol);
lcc.set_dart_attribute<3>(d3,vol);
lcc.basic_link_beta_1(d1,d2);
lcc.basic_link_beta_1(d2,d3);
lcc.basic_link_beta_1(d3,d1);
Dart_handle dd1=lcc.create_dart(v2);
Dart_handle dd2=lcc.create_dart(v1);
Dart_handle dd3=lcc.create_dart(v3);
lcc.set_dart_attribute<3>(dd1,vol);
lcc.set_dart_attribute<3>(dd2,vol);
lcc.set_dart_attribute<3>(dd3,vol);
lcc.basic_link_beta_1(dd1,dd2);
lcc.basic_link_beta_1(dd2,dd3);
lcc.basic_link_beta_1(dd3,dd1);
lcc.basic_link_beta_for_involution<3>(d1,dd1);
lcc.basic_link_beta_for_involution<3>(d2,dd3);
lcc.basic_link_beta_for_involution<3>(d3,dd2);
lcc.basic_link_beta_for_involution<2>(old1,d1);
lcc.basic_link_beta_for_involution<2>(old2,dd1);
return lcc.beta<1>(d1);
}
Dart_handle tet_split(Dart_handle d1)
{
Point_3 c = LCC_3::Traits::Construct_translated_point()
(CGAL::ORIGIN, barycenter_3(d1));
Dart_handle d2=lcc.beta<1,2>(d1);
Dart_handle d3=lcc.beta<2>(d1);
Dart_handle d4=lcc.beta<1,2>(d3);
Vertex_handle v0 = lcc.create_vertex_attribute(c);
Vertex_handle v1 = lcc.vertex_attribute(d1);
Vertex_handle v2 = lcc.vertex_attribute(d2);
Vertex_handle v3 = lcc.vertex_attribute(d3);
Vertex_handle v4 = lcc.vertex_attribute(d4);
Dart_handle n1 = create_face(d1, v3, v1, v0, lcc.attribute<3>(d1));
Dart_handle n2 = create_face(d2, v3, v2, v0, lcc.attribute<3>(d1));
Dart_handle n3 = create_face(lcc.beta<0>(d1), v1, v2, v0, lcc.attribute<3>(d1));
Dart_handle n4 = create_face(lcc.beta<0>(d2), v4, v2, v0, lcc.attribute<3>(d1));
Dart_handle n5 = create_face(d4, v1, v4, v0, lcc.attribute<3>(d1));
Dart_handle n6 = create_face(lcc.beta<1>(d2), v4, v3, v0, lcc.attribute<3>(d1));
lcc.basic_link_beta_for_involution<2>(n1, lcc.beta<1>(n3));
lcc.basic_link_beta_for_involution<2>(lcc.beta<1>(n1),lcc.beta<1,3>(n2));
lcc.basic_link_beta_for_involution<2>(lcc.beta<3>(n1),lcc.beta<1,3>(n5));
lcc.basic_link_beta_for_involution<2>(lcc.beta<1,3>(n1),lcc.beta<3>(n6));
lcc.basic_link_beta_for_involution<2>(n2, lcc.beta<1>(n4));
lcc.basic_link_beta_for_involution<2>(lcc.beta<1>(n2), n6);
lcc.basic_link_beta_for_involution<2>(lcc.beta<3>(n2), n3);
lcc.basic_link_beta_for_involution<2>(lcc.beta<3>(n3), lcc.beta<1,3>(n4));
lcc.basic_link_beta_for_involution<2>(lcc.beta<1,3>(n3), lcc.beta<1>(n5));
lcc.basic_link_beta_for_involution<2>(lcc.beta<3>(n4), n5);
lcc.basic_link_beta_for_involution<2>(n4, lcc.beta<1>(n6));
lcc.basic_link_beta_for_involution<2>(lcc.beta<3>(n5), lcc.beta<1,3>(n6));
lcc.set_attribute<3>(d2, lcc.create_attribute<3>());
lcc.set_attribute<3>(d3, lcc.create_attribute<3>());
lcc.set_attribute<3>(d4, lcc.create_attribute<3>());
return d1;
}
bool isBoundary(const Dart_handle& _dart)
{
// 0=not known; 1=boundary; 2=no boundary
if ( lcc.info<0>(_dart).m==1 ||
lcc.info<0>(lcc.beta<1>(_dart)).m==1 ) return true;
// Both endpoints have to lie in the interior of the mesh
if ( lcc.info<0>(_dart).m==0 )
{
for(LCC_3::Dart_of_cell_range<0>::iterator
vv_it = lcc.darts_of_cell<0>(_dart).begin(),
vv_itend = lcc.darts_of_cell<0>(_dart).end();
vv_it != vv_itend; ++vv_it)
{
if(lcc.is_free<3>(vv_it))
{
lcc.info<0>(_dart).m = 1;
return true;
}
}
lcc.info<0>(_dart).m = 2;
}
if ( lcc.info<0>(lcc.beta<1>(_dart)).m==0 )
{
for(LCC_3::Dart_of_cell_range<0>::iterator
vv_it = lcc.darts_of_cell<0>(lcc.beta<1>(_dart)).begin(),
vv_itend = lcc.darts_of_cell<0>(lcc.beta<1>(_dart)).end();
vv_it != vv_itend; ++vv_it)
{
if (lcc.is_free<3>(vv_it))
{
lcc.info<0>(vv_it).m = 1;
return true;
}
}
lcc.info<0>(lcc.beta<1>(_dart)).m = 2;
}
return false;
}
Dart_handle getShortestEdge()
{
double weight = std::numeric_limits<double>::max();
Dart_handle dart = lcc.null_dart_handle;
int m=lcc.get_new_mark();
for (typename LCC_3::Dart_range::iterator e_it=lcc.darts().begin(), e_end=lcc.darts().end();
e_it != e_end; ++e_it)
{
if ( !lcc.is_marked(e_it, m) )
{
CGAL::mark_cell<LCC_3, 1>(lcc, e_it, m);
if( !isBoundary(e_it) )
{
Point p1 = lcc.point(e_it);
Point p0 = lcc.point(lcc.other_extremity(e_it));
Vector v = (p1 - p0);
double w = sqrt(v.squared_length());
if(w < weight)
{
weight = w;
dart = e_it;
}
}
}
}
lcc.free_mark(m);
return dart;
}
private:
virtual bool read_mesh(const char* _filename)
{
// variables
size_t i, num_vertices, num_tetras;
std::vector<Point> points;
std::string line;
std::stringstream sStream;
// try to open the file
std::ifstream fin(_filename);
if(!fin)
return false;
// load number of vertices
// skip Vertices label
std::getline(fin, line);
std::getline(fin, line); // num_vertices x
sStream << line;
sStream >> num_vertices;
sStream.clear();
// reverse the order of the vertices
points.reserve(num_vertices);
for(i = 0; i < num_vertices; ++i)
{
float x, y, z;
std::getline(fin, line);
sStream << line;
sStream >> x >> y >> z;
std::getline(sStream, line);
sStream.clear();
points.push_back(LCC_3::Point(x,y,z));
}
// skip Tetrahedra label
std::getline(fin, line);
// read number of tetraeders
std::getline(fin, line); // num_tetras x
sStream << line;
sStream >> num_tetras;
sStream.clear();
for(i = 0; i < num_tetras; ++i)
{
int v0,v1,v2,v3;
//int m;
std::getline(fin, line);
sStream << line;
sStream >> v0 >> v1 >> v2 >> v3;
std::getline(sStream, line);
sStream.clear();
Dart_handle dart=
lcc.make_tetrahedron(points[v0-1], points[v1-1], points[v2-1], points[v3-1]);
lcc.set_attribute<3>(dart, lcc.create_attribute<3>());
}
lcc.sew3_same_facets();
// close file
fin.close();
// finished
// display_lcc(lcc);
update_accelerators();
return true;
}
virtual bool write_mesh(const char *_filename)
{
return true;
}
virtual int circulator_test()
{
int counter = 0;
int m = lcc.get_new_mark();
//for each vertex enumerate its incident volumes
for (LCC_3::Vertex_attribute_range::iterator vit = lcc.vertex_attributes().begin(),
vend = lcc.vertex_attributes().end(); vit != vend; ++vit)
{
for (LCC_3::Dart_of_cell_basic_range<0>::iterator
vv_it = lcc.darts_of_cell_basic<0>(vit->dart(), m).begin(),
vv_itend = lcc.darts_of_cell_basic<0>(vit->dart(), m).end();
vv_it != vv_itend; ++vv_it)
{
lcc.mark(vv_it, m);
if (!lcc.info<3>(vv_it).m)
{
lcc.info<3>(vv_it).m = 1;
++counter;
}
}
lcc.negate_mark(m);
for (LCC_3::Dart_of_cell_basic_range<0>::iterator
vv_it = lcc.darts_of_cell_basic<0>(vit->dart(), m).begin(),
vv_itend = lcc.darts_of_cell_basic<0>(vit->dart(), m).end();
vv_it != vv_itend; ++vv_it)
{
lcc.mark(vv_it, m);
if (lcc.info<3>(vv_it).m)
{
lcc.info<3>(vv_it).m = 0;
}
}
lcc.negate_mark(m);
}
assert( lcc.is_whole_map_unmarked(m) );
//for each volume enumerate its incident vertices
for (LCC_3::Attribute_range<3>::type::iterator vit = lcc.attributes<3>().begin(),
vend = lcc.attributes<3>().end(); vit != vend; ++vit)
{
for (LCC_3::Dart_of_cell_basic_range<3>::iterator
vv_it = lcc.darts_of_cell_basic<3>(vit->dart(), m).begin(),
vv_itend = lcc.darts_of_cell_basic<3>(vit->dart(), m).end();
vv_it != vv_itend; ++vv_it)
{
if (!lcc.info<0>(vv_it).m)
{
lcc.info<0>(vv_it).m = 1;
--counter;
}
}
lcc.negate_mark(m);
for (LCC_3::Dart_of_cell_basic_range<3>::iterator
vv_it = lcc.darts_of_cell_basic<3>(vit->dart(), m).begin(),
vv_itend = lcc.darts_of_cell_basic<3>(vit->dart(), m).end();
vv_it != vv_itend; ++vv_it)
{
if (lcc.info<0>(vv_it).m)
{
lcc.info<0>(vv_it).m = 0;
}
}
lcc.negate_mark(m);
}
assert( lcc.is_whole_map_unmarked(m) );
lcc.free_mark(m);
return counter;
}
virtual int circulator2_test()
{
int counter = 0;
//for each vertex enumerate its vertices adjacent through a common volume.
int m = lcc.get_new_mark();
int m2 = lcc.get_new_mark();
for (LCC_3::Vertex_attribute_range::iterator vit = lcc.vertex_attributes().begin(),
vend = lcc.vertex_attributes().end(); vit != vend; ++vit)
{
vit->info().m = 1;
for (LCC_3::Dart_of_cell_basic_range<0>::iterator
v_it = lcc.darts_of_cell_basic<0>(vit->dart(), m).begin(),
v_itend = lcc.darts_of_cell_basic<0>(vit->dart(), m).end();
v_it != v_itend; ++v_it)
{
if ( !lcc.is_marked(v_it, m2) )
{
for (LCC_3::Dart_of_cell_basic_range<3>::iterator
vv_it = lcc.darts_of_cell_basic<3>(v_it, m2).begin(),
vv_itend = lcc.darts_of_cell_basic<3>(v_it, m2).end();
vv_it != vv_itend; ++vv_it)
{
lcc.mark(vv_it, m2);
if (!lcc.info<0>(vv_it).m)
{
lcc.info<0>(vv_it).m = 1;
++counter;
}
}
}
}
// Here we unmark things
lcc.negate_mark(m);
lcc.negate_mark(m2);
vit->info().m = 0;
for (LCC_3::Dart_of_cell_basic_range<0>::iterator
v_it = lcc.darts_of_cell_basic<0>(vit->dart(), m).begin(),
v_itend = lcc.darts_of_cell_basic<0>(vit->dart(), m).end();
v_it != v_itend; ++v_it)
{
if ( !lcc.is_marked(v_it, m2) )
{
for (LCC_3::Dart_of_cell_basic_range<3>::iterator
vv_it = lcc.darts_of_cell_basic<3>(v_it, m2).begin(),
vv_itend = lcc.darts_of_cell_basic<3>(v_it, m2).end();
vv_it != vv_itend; ++vv_it)
{
lcc.mark(vv_it, m2);
if (lcc.info<0>(vv_it).m)
{
lcc.info<0>(vv_it).m = 0;
}
}
}
}
lcc.negate_mark(m2);
lcc.negate_mark(m);
}
assert( lcc.is_whole_map_unmarked(m) );
assert( lcc.is_whole_map_unmarked(m2) );
lcc.free_mark(m);
lcc.free_mark(m2);
return counter;
}
virtual void barycenter_test(bool draw)
{
Vector_3 s(CGAL::NULL_VECTOR);
for (LCC_3::Attribute_range<3>::type::iterator vit = lcc.attributes<3>().begin(),
vend = lcc.attributes<3>().end(); vit != vend; ++vit)
{
s = s + barycenter_3(vit->dart());
}
if (draw) std::cout<<"LCC::barycenter: "<<s<<std::endl;
}
virtual void smoothing_test()
{
for (LCC_3::Vertex_attribute_range::iterator vit = lcc.vertex_attributes().begin(),
vend = lcc.vertex_attributes().end(); vit != vend; ++vit )
{
Vector_3 v(0.0, 0.0, 0.0);
int valence = 0;
for (std::vector<Vertex_handle>::iterator it= adjacent_vertices[vit].begin(),
itend=adjacent_vertices[vit].end(); it!=itend; ++it )
{
v = v + (lcc.point_of_vertex_attribute(*it) - CGAL::ORIGIN);
++valence;
}
v = v / double(valence);
vit->info().v = v;
}
// Update all vertices's positions
for (LCC_3::Vertex_attribute_range::iterator vit = lcc.vertex_attributes().begin(),
vend = lcc.vertex_attributes().end(); vit != vend; ++vit)
{
lcc.point_of_vertex_attribute(vit) = CGAL::ORIGIN + lcc.info_of_attribute<0>(vit).v;
}
}
virtual void split_tet_test()
{
LCC_3::Attribute_range<3>::type::iterator vit = lcc.attributes<3>().begin(),
vend = lcc.attributes<3>().end();
--vend;
while ( vit!=vend )
{
Dart_handle d = vit->dart();
++vit;
tet_split(d);
}
tet_split(vend->dart());
}
virtual void collapse_test(unsigned int n)
{
for(unsigned int i = 0; i < n; ++i)
{
Dart_handle dart = getShortestEdge();
if(dart == lcc.null_dart_handle)
{
std::cerr << "No valid edge anymore, aborting at step "<<i << std::endl;
return;
}
// 0=not known; 1=boundary; 2=no boundary
lcc.info<0>(dart).m = 0;
lcc.info<0>(lcc.other_extremity(dart)).m = 0;
CGAL::contract_cell<LCC_3,1>(lcc, dart);
}
for (LCC_3::Vertex_attribute_range::iterator vit = lcc.vertex_attributes().begin(),
vend = lcc.vertex_attributes().end(); vit != vend; ++vit)
{
vit->info().m = 0;
}
}
Vector_3 barycenter_3(Dart_handle d)
{
int m = lcc.get_new_mark();
Vector_3 v = CGAL::NULL_VECTOR;
int count=0;
for (LCC_3::Dart_of_cell_basic_range<3>::iterator
vv_it = lcc.darts_of_cell_basic<3>(d, m).begin(),
vv_itend = lcc.darts_of_cell_basic<3>(d, m).end();
vv_it != vv_itend; ++vv_it)
{
if (!lcc.info<0>(vv_it).m)
{
lcc.info<0>(vv_it).m = 1;
v = v + (lcc.point(vv_it)- CGAL::ORIGIN);
++count;
}
}
// Unmark
lcc.negate_mark(m);
for (LCC_3::Dart_of_cell_basic_range<3>::iterator
vv_it = lcc.darts_of_cell_basic<3>(d, m).begin(),
vv_itend = lcc.darts_of_cell_basic<3>(d, m).end();
vv_it != vv_itend; ++vv_it)
{
if (lcc.info<0>(vv_it).m)
{
lcc.info<0>(vv_it).m = 0;
}
}
lcc.free_mark(m);
return v/count;
}
};
//=============================================================================

View File

@ -0,0 +1 @@
/home/gdamiand/sources/codes-autres/OpenVolumeMesh

View File

@ -0,0 +1,20 @@
//== INCLUDES =================================================================
#include "openvolumemesh_performance.h"
//=============================================================================
int main(int argc, char** argv)
{
if (argc < 2)
{
std::cerr << "Usage:\n" << argv[0] << " <input-mesh>\n";
exit(1);
}
for (int i=1; i<argc; ++i)
{
std::cout<<"**************** "<<argv[i]<<" ****************"<<std::endl;
OpenVolumeMesh_performance().run(argv[i], "output_openvolumemesh.ovm");
}
return 0;
}
//=============================================================================

View File

@ -0,0 +1,662 @@
//== INCLUDES =================================================================
#define INCLUDE_TEMPLATES
#include <iostream>
#include <vector>
#include <limits>
#include "performance_3.h"
#include <OpenVolumeMesh/Geometry/VectorT.hh>
#include <OpenVolumeMesh/Mesh/PolyhedralMesh.hh>
#include <OpenVolumeMesh/Attribs/StatusAttrib.hh>
#include <OpenVolumeMesh/FileManager/FileManager.hh>
//== CLASS DEFINITION =========================================================
using namespace OpenVolumeMesh;
class OpenVolumeMesh_performance : public Performance_test_3
{
private:
typedef Geometry::Vec3d Vec3d;
typedef GeometryKernel<Vec3d> Mesh;
Mesh mesh;
OpenVolumeMesh::VertexPropertyT<int>* boundary_vertex;
public:
OpenVolumeMesh_performance() : Performance_test_3()
{
}
private:
void display_info()
{
std::cout << "#0-cells=" << mesh.n_vertices();
std::cout << ", #1-cells=" << mesh.n_edges();
std::cout << ", #2-cells=" << mesh.n_faces();
std::cout << ", #3-cells=" << mesh.n_cells();
std::cout << "\t" << std::endl;
}
void edge_collapse(const EdgeHandle& _eh)
{
Vec3d p = mesh.barycenter(_eh);
// Get vertices incident to edge _eh
const VertexHandle cvh = mesh.edge(_eh).from_vertex();
const VertexHandle tvh = mesh.edge(_eh).to_vertex();
const HalfEdgeHandle he = mesh.halfedge_handle(_eh, 0);
std::set<CellHandle> toBeProcessed;
// Get all cells incident to the center vertex
for(VertexCellIter vc_it = mesh.vc_iter(cvh); vc_it.valid(); ++vc_it)
{
toBeProcessed.insert(*vc_it);
}
// Exclude cells incident to edge _eh from this set
// These are the cells that need new geometry
for(HalfEdgeCellIter hec_it = mesh.hec_iter(he); hec_it.valid(); ++hec_it)
{
toBeProcessed.erase(*hec_it);
}
// Create a new cell for each of the cells in toBeProcessed
// The new cells are now incident to the top vertex instead
// of the one in the center
std::vector< std::vector<VertexHandle> > newCells;
for(std::set<CellHandle>::const_iterator c_it = toBeProcessed.begin(), c_end = toBeProcessed.end(); c_it != c_end; ++c_it)
{
std::vector<VertexHandle> newVertices;
const std::vector<HalfFaceHandle>& hfs = mesh.cell(*c_it).halffaces();
for(HalfFaceVertexIter hfv_it = mesh.hfv_iter(*hfs.begin()); hfv_it.valid(); ++hfv_it)
{
VertexHandle nvh = (*hfv_it == cvh ? tvh : *hfv_it);
nvh.idx((nvh.idx() > cvh.idx() ? nvh.idx() - 1 : nvh.idx()));
newVertices.push_back(nvh);
}
HalfFaceHandle curHF = *hfs.begin();
HalfEdgeHandle curHE = *mesh.halfface(curHF).halfedges().begin();
curHF = mesh.adjacent_halfface_in_cell(curHF, curHE);
curHE = mesh.opposite_halfedge_handle(curHE);
curHE = mesh.next_halfedge_in_halfface(curHE, curHF);
VertexHandle nextVH = mesh.halfedge(curHE).to_vertex();
nextVH = (nextVH == cvh ? tvh : nextVH);
nextVH.idx((nextVH.idx() > cvh.idx() ? nextVH.idx() - 1 : nextVH.idx()));
newVertices.push_back(nextVH);
newCells.push_back(newVertices);
}
// Set position of top vertex to be the barycenter
// of edge _eh
mesh.set_vertex(tvh, p);
// Delete center vertex
// This deletes all incident edges, faces, and cells, too
mesh.delete_vertex(cvh);
// Create a new tet for each of the cells in toBeProcessed
for(std::vector< std::vector<VertexHandle> >::const_iterator nc_it = newCells.begin(),
nc_end = newCells.end(); nc_it != nc_end; ++nc_it)
{
if(!createTet(*nc_it))
{
std::cerr << "Error: Could not create tet!" << std::endl;
return;
}
}
}
// Find the mesh's shortest edge
EdgeHandle getShortestEdge()
{
double max_weight = std::numeric_limits<double>::max();
EdgeHandle eh = Mesh::InvalidEdgeHandle;
bool boundary=false;
for(OpenVolumeMesh::EdgeIter e_it = mesh.edges_begin(),
e_end = mesh.edges_end(); e_it != e_end; ++e_it)
{
const OpenVolumeMesh::VertexHandle& v0 = mesh.edge(*e_it).from_vertex();
const OpenVolumeMesh::VertexHandle& v1 = mesh.edge(*e_it).to_vertex();
boundary=false;
if ((*boundary_vertex)[v0]==0)
{
if (mesh.is_boundary(v0))
{
boundary=true;
(*boundary_vertex)[v0]=1;
}
else
{
(*boundary_vertex)[v0]=2;
}
}
else
{
boundary = ((*boundary_vertex)[v0]==1);
}
if ((*boundary_vertex)[v1]==0)
{
if (mesh.is_boundary(v1))
{
boundary=true;
(*boundary_vertex)[v1]=1;
}
else
{
(*boundary_vertex)[v1]=2;
}
}
else
{
boundary = ((*boundary_vertex)[v1]==1);
}
if (boundary) continue;
double l = mesh.length(*e_it);
if(l < max_weight)
{
max_weight = l;
eh = *e_it;
}
}
return eh;
}
/*
* Create a new tetrahedron with the specified vertices.
*
* v2 v3
* O--O
* / \ |
* / \|
* O-----O
* v0 v1
*
* The vertices have to be in the order depicted above.
*/
CellHandle createTet(const std::vector<VertexHandle>& _vs)
{
std::vector<VertexHandle> tvs;
tvs.resize(3);
tvs[0] = _vs[0];
tvs[1] = _vs[1];
tvs[2] = _vs[2];
HalfFaceHandle hf0 = mesh.halfface(tvs);
if(!hf0.is_valid())
{
// Create face
hf0 = mesh.halfface_handle(mesh.add_face(tvs), 0);
}
tvs[0] = _vs[0];
tvs[1] = _vs[2];
tvs[2] = _vs[3];
HalfFaceHandle hf1 = mesh.halfface(tvs);
if(!hf1.is_valid())
{
// Create face
hf1 = mesh.halfface_handle(mesh.add_face(tvs), 0);
}
tvs[0] = _vs[1];
tvs[1] = _vs[3];
tvs[2] = _vs[2];
HalfFaceHandle hf2 = mesh.halfface(tvs);
if(!hf2.is_valid())
{
// Create face
hf2 = mesh.halfface_handle(mesh.add_face(tvs), 0);
}
tvs[0] = _vs[0];
tvs[1] = _vs[3];
tvs[2] = _vs[1];
HalfFaceHandle hf3 = mesh.halfface(tvs);
if(!hf3.is_valid())
{
// Create face
hf3 = mesh.halfface_handle(mesh.add_face(tvs), 0);
}
if(hf0.is_valid() && hf1.is_valid() &&
hf2.is_valid() && hf3.is_valid())
{
std::vector<HalfFaceHandle> hfs;
hfs.push_back(hf0); hfs.push_back(hf1);
hfs.push_back(hf2); hfs.push_back(hf3);
return mesh.add_cell(hfs, true);
}
std::cerr << "Could not create cell!" << std::endl;
return Mesh::InvalidCellHandle;
}
private:
virtual bool read_mesh(const char* _filename)
{
bool checkTopo = false;
bool computeBottomUpIncidences = true; // Incidence Dependent Iterators need bottom-up incidences to be computed before they can be used.
IO::FileManager fileManager;
bool res = fileManager.readFile(_filename, mesh, checkTopo, computeBottomUpIncidences);
return res;
}
virtual bool write_mesh(const char* _filename)
{
// IO::FileManager fileManager;
// return fileManager.writeFile(_filename, mesh);
return true;
}
virtual int circulator_test()
{
int counter = 0;
//for each vertex enumerate its incident volumes
for(VertexIter v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); ++v_it)
{
for(VertexCellIter vc_it = mesh.vc_iter(*v_it); vc_it.valid(); ++vc_it)
{
++counter;
}
}
//for each volumes enumerate its vertices
for(CellIter c_it = mesh.cells_begin(); c_it != mesh.cells_end(); ++c_it)
{
for(CellVertexIter cv_it = mesh.cv_iter(*c_it); cv_it.valid(); ++cv_it)
{
--counter;
}
}
return counter;
}
virtual int circulator2_test()
{
int counter = 0;
//for each vertex enumerate its vertices adjacent through a common volume.
for(VertexIter v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); ++v_it)
{
for(VertexCellIter vc_it = mesh.vc_iter(*v_it); vc_it.valid(); ++vc_it)
{
for(CellVertexIter cv_it = mesh.cv_iter(*vc_it); cv_it.valid(); ++cv_it)
{
++counter;
}
}
}
return counter;
}
virtual void barycenter_test(bool draw)
{
Vec3d sum(0.0, 0.0, 0.0);
//for each volumes
for(CellIter c_it = mesh.cells_begin(); c_it != mesh.cells_end(); ++c_it)
{
Vec3d p = mesh.barycenter(*c_it);
sum += p;
}
if ( draw ) std::cout<<"OVM::barycenter: "<<sum<<std::endl;
}
virtual void smoothing_test()
{
VertexPropertyT<Vec3d> position_smoothing = mesh.request_vertex_property<Vec3d>("positionSmoothing");
for(VertexIter v_it = mesh.vertices_begin(), v_end = mesh.vertices_end() ;
v_it != v_end ;
++v_it)
{
Vec3d p(0.0);
unsigned int c = 0;
for(VertexOHalfEdgeIter vh_it = mesh.voh_iter(*v_it); vh_it.valid(); ++vh_it)
{
p += mesh.vertex(mesh.halfedge(*vh_it).to_vertex());
++c;
}
p /= double(c);
position_smoothing[*v_it] = p;
}
// Update positions
for(VertexIter v_it = mesh.vertices_begin(), v_end = mesh.vertices_end(); v_it != v_end; ++v_it)
{
mesh.set_vertex(*v_it, position_smoothing[*v_it]);
}
}
virtual void split_tet_test()
{
mesh.enable_edge_bottom_up_incidences(false);
unsigned int n = mesh.n_cells();
const unsigned int n_c = n;
for(CellIter c_it = mesh.cells_begin(); n-- > 0; ++c_it)
{
/*
* Compute geometry of inner cells and add them
* to the mesh afterwards
*
* In the end, all cells up until cell
* with index n_c will be deleted in one chunk
*/
Vec3d c = mesh.barycenter(*c_it);
// Center vertex
VertexHandle vhc = mesh.add_vertex(c);
// Get first half-face
HalfFaceHandle curHF = *mesh.cell(*c_it).halffaces().begin();
HalfFaceHandle ohf0, ohf1, ohf2, ohf3;
ohf0 = curHF;
// Get first half-edge
HalfEdgeHandle curHE = *mesh.halfface(curHF).halfedges().begin();
VertexHandle vh0 = mesh.halfedge(curHE).from_vertex();
curHE = mesh.next_halfedge_in_halfface(curHE, curHF);
VertexHandle vh1 = mesh.halfedge(curHE).from_vertex();
curHE = mesh.next_halfedge_in_halfface(curHE, curHF);
VertexHandle vh2 = mesh.halfedge(curHE).from_vertex();
curHF = mesh.adjacent_halfface_in_cell(curHF, curHE);
curHE = mesh.opposite_halfedge_handle(curHE);
curHE = mesh.next_halfedge_in_halfface(curHE, curHF);
VertexHandle vh3 = mesh.halfedge(curHE).to_vertex();
ohf3 = curHF;
curHF = mesh.adjacent_halfface_in_cell(curHF, curHE);
curHE = mesh.opposite_halfedge_handle(curHE);
curHE = mesh.next_halfedge_in_halfface(curHE, curHF);
curHE = mesh.next_halfedge_in_halfface(curHE, curHF);
ohf1 = curHF;
curHF = mesh.adjacent_halfface_in_cell(curHF, curHE);
ohf2 = curHF;
std::vector<VertexHandle> vs(3);
vs[0] = vh2; vs[1] = vh1; vs[2] = vhc;
FaceHandle fh0 = mesh.add_face(vs);
vs[0] = vh0; vs[1] = vh2; vs[2] = vhc;
FaceHandle fh1 = mesh.add_face(vs);
vs[0] = vh1; vs[1] = vh0; vs[2] = vhc;
FaceHandle fh2 = mesh.add_face(vs);
vs[0] = vh2; vs[1] = vh3; vs[2] = vhc;
FaceHandle fh3 = mesh.add_face(vs);
vs[0] = vh3; vs[1] = vh1; vs[2] = vhc;
FaceHandle fh4 = mesh.add_face(vs);
vs[0] = vh3; vs[1] = vh0; vs[2] = vhc;
FaceHandle fh5 = mesh.add_face(vs);
std::vector<HalfFaceHandle> hfs(4);
hfs[0] = mesh.halfface_handle(fh0, 0);
hfs[1] = mesh.halfface_handle(fh1, 0);
hfs[2] = mesh.halfface_handle(fh2, 0);
hfs[3] = ohf0;
mesh.add_cell(hfs);
hfs[0] = mesh.halfface_handle(fh3, 0);
hfs[1] = mesh.halfface_handle(fh4, 0);
hfs[2] = mesh.halfface_handle(fh0, 1);
hfs[3] = ohf1;
mesh.add_cell(hfs);
hfs[0] = mesh.halfface_handle(fh2, 1);
hfs[1] = mesh.halfface_handle(fh4, 1);
hfs[2] = mesh.halfface_handle(fh5, 0);
hfs[3] = ohf2;
mesh.add_cell(hfs);
hfs[0] = mesh.halfface_handle(fh1, 1);
hfs[1] = mesh.halfface_handle(fh3, 1);
hfs[2] = mesh.halfface_handle(fh5, 1);
hfs[3] = ohf3;
mesh.add_cell(hfs);
}
CellIter first = mesh.cells_begin();
CellIter last = mesh.cells_begin();
// Delete all former cells in one chunk
last += n_c;
mesh.delete_cell_range(first, last);
mesh.enable_edge_bottom_up_incidences(true);
}
virtual void collapse_test(unsigned int n)
{
OpenVolumeMesh::VertexPropertyT<int> tmp= mesh.request_vertex_property<int>("boundaryVertex");
boundary_vertex = &tmp;
for(VertexIter v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); ++v_it)
(*boundary_vertex)[*v_it] = 0;
mesh.enable_bottom_up_incidences(true);
for(unsigned int i = 0; i < n; ++i)
{
EdgeHandle eh = getShortestEdge();
if(!eh.is_valid())
{
std::cerr << "No valid edge anymore, aborting at step "<<i << std::endl;
return;
}
(*boundary_vertex)[mesh.edge(eh).from_vertex()]=0;
(*boundary_vertex)[mesh.edge(eh).to_vertex()]=0;
edge_collapse(eh);
}
boundary_vertex = NULL;
}
virtual void collapse_test()
{
std::vector<HalfEdgeHandle> save;
unsigned int n = mesh.n_cells();
const unsigned int n_c = n;
for(CellIter c_it = mesh.cells_begin(); n-- > 0; ++c_it)
{
//
// Compute geometry of inner cells and add them
// to the mesh afterwards
//
// In the end, all cells up until cell
// with index n_c will be deleted in one chunk
///
Vec3d c = mesh.barycenter(*c_it);
// Center vertex
VertexHandle vhc = mesh.add_vertex(c);
// Get first half-face
HalfFaceHandle curHF = *mesh.cell(*c_it).halffaces().begin();
HalfFaceHandle ohf0, ohf1, ohf2, ohf3;
ohf0 = curHF;
// Get first half-edge
HalfEdgeHandle curHE = *mesh.halfface(curHF).halfedges().begin();
VertexHandle vh0 = mesh.halfedge(curHE).from_vertex();
curHE = mesh.next_halfedge_in_halfface(curHE, curHF);
VertexHandle vh1 = mesh.halfedge(curHE).from_vertex();
curHE = mesh.next_halfedge_in_halfface(curHE, curHF);
VertexHandle vh2 = mesh.halfedge(curHE).from_vertex();
curHF = mesh.adjacent_halfface_in_cell(curHF, curHE);
curHE = mesh.opposite_halfedge_handle(curHE);
curHE = mesh.next_halfedge_in_halfface(curHE, curHF);
VertexHandle vh3 = mesh.halfedge(curHE).to_vertex();
ohf3 = curHF;
curHF = mesh.adjacent_halfface_in_cell(curHF, curHE);
curHE = mesh.opposite_halfedge_handle(curHE);
curHE = mesh.next_halfedge_in_halfface(curHE, curHF);
curHE = mesh.next_halfedge_in_halfface(curHE, curHF);
ohf1 = curHF;
curHF = mesh.adjacent_halfface_in_cell(curHF, curHE);
ohf2 = curHF;
std::vector<VertexHandle> vs(3);
vs[0] = vh2; vs[1] = vh1; vs[2] = vhc;
FaceHandle fh0 = mesh.add_face(vs);
vs[0] = vh0; vs[1] = vh2; vs[2] = vhc;
FaceHandle fh1 = mesh.add_face(vs);
vs[0] = vh1; vs[1] = vh0; vs[2] = vhc;
FaceHandle fh2 = mesh.add_face(vs);
vs[0] = vh2; vs[1] = vh3; vs[2] = vhc;
FaceHandle fh3 = mesh.add_face(vs);
vs[0] = vh3; vs[1] = vh1; vs[2] = vhc;
FaceHandle fh4 = mesh.add_face(vs);
vs[0] = vh3; vs[1] = vh0; vs[2] = vhc;
FaceHandle fh5 = mesh.add_face(vs);
std::vector<HalfFaceHandle> hfs(4);
hfs[0] = mesh.halfface_handle(fh0, 0);
hfs[1] = mesh.halfface_handle(fh1, 0);
hfs[2] = mesh.halfface_handle(fh2, 0);
hfs[3] = ohf0;
mesh.add_cell(hfs);
// Save center half edge handle
//HalfEdgeHandle t = *mesh.halfface(hfs[2]).halfedges().begin();
//HalfEdgeHandle t2 = mesh.next_halfedge_in_halfface(t,hfs[2]);
HalfEdgeHandle t2 = mesh.halfedge(vhc, vh0);
save.push_back(t2);
hfs[0] = mesh.halfface_handle(fh3, 0);
hfs[1] = mesh.halfface_handle(fh4, 0);
hfs[2] = mesh.halfface_handle(fh0, 1);
hfs[3] = ohf1;
mesh.add_cell(hfs);
hfs[0] = mesh.halfface_handle(fh2, 1);
hfs[1] = mesh.halfface_handle(fh4, 1);
hfs[2] = mesh.halfface_handle(fh5, 0);
hfs[3] = ohf2;
mesh.add_cell(hfs);
hfs[0] = mesh.halfface_handle(fh1, 1);
hfs[1] = mesh.halfface_handle(fh3, 1);
hfs[2] = mesh.halfface_handle(fh5, 1);
hfs[3] = ohf3;
mesh.add_cell(hfs);
}
CellIter first = mesh.cells_begin();
CellIter last = mesh.cells_begin();
// Delete all former cells in one chunk
last += n_c;
mesh.delete_cell_range(first, last);
//std::cout << "size = " << save.size() << std::endl;
//int count = 0;
//delete edges
for(std::vector<HalfEdgeHandle>::iterator it = save.begin() ;
it != save.end();
++it)
{
EdgeHandle eh = mesh.edge_handle(*it);
//edge_collapse(eh);
//++count;
//std::cout << count << std::endl;
}
}
};
//=============================================================================

View File

@ -0,0 +1,38 @@
//== INCLUDES =================================================================
#include "cgogn_performance_3.h"
#include "lcc_performance_3.h"
#include "openvolumemesh_performance.h"
//=============================================================================
int main(int argc, char** argv)
{
if (argc < 2)
{
std::cerr << "Usage:\nperformance <input-mesh>\n";
exit(1);
}
for (int i=1; i<argc; ++i)
{
std::cout<<"**************** "<<argv[i]<<" ****************"<<std::endl;
{
std::cout << "LCC_3\t" << std::endl;
LCC_performance_3().run(argv[i], "output_lcc_3.tetmesh");
}
{
std::cout << "CGoGN_3\t" << std::endl;
CGoGN_performance_3().run(argv[i], "output_cgogn_3.tetmesh");
}
{
std::string filename(argv[i]);
size_t pos = filename.rfind("."); // position of "." in filename
filename.replace (pos, std::string::npos, ".ovm");
std::cout << "OpenVolumeMesh\t" << std::endl;
OpenVolumeMesh_performance().run(filename.c_str(), "output_openvolumemesh.ovm");
}
}
return 0;
}
//=============================================================================

View File

@ -0,0 +1,94 @@
//=============================================================================
#ifndef PERFORMANCE_TEST_3_H
#define PERFORMANCE_TEST_3_H
//== INCLUDES =================================================================
#include <cstdlib>
#include <iostream>
#include <assert.h>
#include <sys/resource.h>
#include "Stop_watch.h"
//== CLASS DEFINITION =========================================================
class Performance_test_3
{
public:
Performance_test_3() {}
void run(const char* input, const char* output)
{
graphene::StopWatch timer;
timer.start();
if (!read_mesh(input)) { std::cerr << "read error\n"; exit(1); }
timer.stop();
std::cout << "Read mesh : " << timer << std::endl;
display_info();
timer.start();
int c;
for (int i=0; i<7; ++i)
c = circulator_test();
timer.stop();
assert(c==0);
std::cout << "Circulator: "<<c<<"; time: " << timer << std::endl;
for (int i=0; i<7; ++i)
c = circulator2_test();
timer.stop();
std::cout << "Circulator2: "<<c<<"; time: " << timer << std::endl;
timer.start();
for (int i=0; i<7; ++i)
barycenter_test(i==0);
timer.stop();
std::cout << "Barycenter : " << timer << std::endl;
timer.start();
for (int i=0; i<7; ++i)
smoothing_test();
timer.stop();
std::cout << "Smoothing : " << timer << std::endl;
timer.start();
split_tet_test();
timer.stop();
std::cout << "Split tetrahedra : " << timer << std::endl;
display_info();
timer.start();
collapse_test(7);
timer.stop();
std::cout << "Collapse : " << timer << std::endl;
display_info();
std::cout << std::endl;
}
protected:
virtual bool read_mesh(const char*) = 0;
virtual bool write_mesh(const char*) = 0;
virtual int circulator_test() { return 0; }
virtual int circulator2_test() { return 0; }
virtual void barycenter_test(bool) {}
virtual void smoothing_test() {}
virtual void split_tet_test() {}
virtual void collapse_test() {}
virtual void collapse_test(unsigned int n) {}
virtual void display_info() {}
};
//=============================================================================
#endif
//=============================================================================

View File

@ -0,0 +1,57 @@
Benchmarks to compare Linear_cell_complex with other libraries:
In 2D:
* Polyhedron_3 (from CGAL)
* OpenMesh
* SurfaceMesh
* CGoGN
In 3D:
* OpenVolumeMesh
* CGoGN
INSTALLATION:
==============
1) Install all the following libraries:
CGAL: http://www.cgal.org/
CGoGN: http://cgogn.u-strasbg.fr/
OpenMesh: http://www.openmesh.org/
OpenVolumeMesh: http://www.openvolumemesh.org/
2) create links (or copy directory):
* in the 2D directory:
one link called cgogn through the install directory of CGoGN;
one link called openmesh through the install directory of OpenMesh.
* in the 3D directory:
one link called cgogn through the install directory of CGoGN;
one link called openvolumemesh through the openvolumemesh directory itself.
3) Compile the benchmarks
* create a build directory; cd build; cmake -DCGAL_DIR=CGAL_BUILD_DIR ..
CGAL_BUILD_DIR being the build directory of the CGAL library.
4) run the benchmarks.
* In 2D, the programs take off files as input.
* In 3D, lcc and cgogn take tetmesh and OpenVolumeMesh takes ovm.
You can create a tetmesh file using tetgen programm with an off file as input (http://tetgen.berlios.de/) with option -g to generate XXX.mesh file. Rename this file into XXX.tetmesh. Modify the file to keep only the two following sections:
**********************
Vertices
26002
...
Tetrahedra
174445
...
**********************
And for each tetrahedra line, remove the last column.
You obtain the tetmesh file. Then you can use the FileConverter/file_converter programm in the OpenVolumeMesh library to convert it into the corresponding ovm file.