mirror of https://github.com/CGAL/cgal
Add benchmarks for lcc.
This commit is contained in:
parent
53f02ea00d
commit
e6647d3751
|
|
@ -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}
|
||||
)
|
||||
|
|
@ -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
|
||||
//=============================================================================
|
||||
|
|
@ -0,0 +1 @@
|
|||
/home/gdamiand/sources/codes-autres/CGoGN/install
|
||||
|
|
@ -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;
|
||||
}
|
||||
//=============================================================================
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
//=============================================================================
|
||||
|
|
@ -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()
|
||||
|
|
@ -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()
|
||||
|
|
@ -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()
|
||||
|
|
@ -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;
|
||||
}
|
||||
//=============================================================================
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
//=============================================================================
|
||||
|
|
@ -0,0 +1 @@
|
|||
/home/gdamiand/sources/codes-autres/OpenMesh/builds/install/
|
||||
|
|
@ -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;
|
||||
}
|
||||
//=============================================================================
|
||||
|
|
@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
//=============================================================================
|
||||
|
|
@ -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;
|
||||
}
|
||||
//=============================================================================
|
||||
|
|
@ -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
|
||||
//=============================================================================
|
||||
|
|
@ -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;
|
||||
}
|
||||
//=============================================================================
|
||||
|
|
@ -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 ;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
|
@ -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()
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
|
@ -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
|
||||
//=============================================================================
|
||||
|
|
@ -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
|
|
@ -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
|
||||
//=============================================================================
|
||||
|
|
@ -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
|
||||
//=============================================================================
|
||||
|
|
@ -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
|
||||
//============================================================================
|
||||
|
|
@ -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;
|
||||
}
|
||||
//=============================================================================
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
};
|
||||
//=============================================================================
|
||||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
//=============================================================================
|
||||
|
|
@ -0,0 +1 @@
|
|||
/home/gdamiand/sources/codes-autres/CGoGN/install
|
||||
|
|
@ -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;
|
||||
}
|
||||
//=============================================================================
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
//=============================================================================
|
||||
|
|
@ -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 ()
|
||||
|
|
@ -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 ()
|
||||
|
|
@ -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)
|
||||
|
|
@ -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 ()
|
||||
|
|
@ -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)
|
||||
|
|
@ -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")
|
||||
|
|
@ -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@")
|
||||
|
|
@ -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;
|
||||
}
|
||||
//=============================================================================
|
||||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
//=============================================================================
|
||||
|
|
@ -0,0 +1 @@
|
|||
/home/gdamiand/sources/codes-autres/OpenVolumeMesh
|
||||
|
|
@ -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;
|
||||
}
|
||||
//=============================================================================
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
//=============================================================================
|
||||
|
|
@ -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;
|
||||
}
|
||||
//=============================================================================
|
||||
|
|
@ -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
|
||||
//=============================================================================
|
||||
|
|
@ -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.
|
||||
Loading…
Reference in New Issue