From 9500e0c26eaee940d3b6f67aee07a0de7faf7226 Mon Sep 17 00:00:00 2001 From: mborne Date: Wed, 16 Jan 2013 15:11:30 +0100 Subject: [PATCH 01/13] track version in header (SFCGAL/version.h) --- CMakeLists.txt | 4 +++- include/SFCGAL/version.h | 11 +++++++++++ include/SFCGAL/version.h.cmake | 11 +++++++++++ sfcgal-config.cmake | 6 ++++++ 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 include/SFCGAL/version.h create mode 100644 include/SFCGAL/version.h.cmake create mode 100644 sfcgal-config.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index e2bfe1e9..273cbba1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ set( CMAKE_DEBUG_POSTFIX "d" ) #-- include finders and co set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules;${CMAKE_MODULE_PATH}" ) +include( sfcgal-config.cmake ) include( PrecompiledHeader ) option( Use_precompiled_headers "Use precompiled headers" OFF ) @@ -105,8 +106,9 @@ elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-pg") endif() -#-- configure the library +#-- generate library headers configure_file( ${CMAKE_SOURCE_DIR}/include/SFCGAL/config.h.cmake ${CMAKE_SOURCE_DIR}/include/SFCGAL/config.h ) +configure_file( ${CMAKE_SOURCE_DIR}/include/SFCGAL/version.h.cmake ${CMAKE_SOURCE_DIR}/include/SFCGAL/version.h ) #-- build the library #note : not available on windows without export/import diff --git a/include/SFCGAL/version.h b/include/SFCGAL/version.h new file mode 100644 index 00000000..8203842c --- /dev/null +++ b/include/SFCGAL/version.h @@ -0,0 +1,11 @@ +#ifndef _SFCGAL_VERSION_H_ +#define _SFCGAL_VERSION_H_ + +/* #undef SFCAL_VERSION_MAJOR */ +/* #undef SFCAL_VERSION_MINOR */ +/* #undef SFCAL_VERSION_PATCH */ + +/* #undef SFCAL_VERSION */ + +#endif + diff --git a/include/SFCGAL/version.h.cmake b/include/SFCGAL/version.h.cmake new file mode 100644 index 00000000..4fef045e --- /dev/null +++ b/include/SFCGAL/version.h.cmake @@ -0,0 +1,11 @@ +#ifndef _SFCGAL_VERSION_H_ +#define _SFCGAL_VERSION_H_ + +#cmakedefine SFCAL_VERSION_MAJOR @SFCAL_VERSION_MAJOR@ +#cmakedefine SFCAL_VERSION_MINOR @SFCAL_VERSION_MINOR@ +#cmakedefine SFCAL_VERSION_PATCH @SFCAL_VERSION_PATCH@ + +#cmakedefine SFCAL_VERSION "@SFCAL_VERSION" + +#endif + diff --git a/sfcgal-config.cmake b/sfcgal-config.cmake new file mode 100644 index 00000000..42d5eb06 --- /dev/null +++ b/sfcgal-config.cmake @@ -0,0 +1,6 @@ +set( SFCGAL_VERSION_MAJOR 0 ) +set( SFCGAL_VERSION_MINOR 1 ) +set( SFCGAL_VERSION_PATCH 0 ) + +set( SFCGAL_VERSION "${SFCGAL_VERSION_MAJOR}.${SFCGAL_VERSION_MINOR}.${SFCGAL_VERSION_PATCH}" ) + From 6ea6ac4689e783ac5d18c997f4846c3a99021474 Mon Sep 17 00:00:00 2001 From: mborne Date: Wed, 16 Jan 2013 15:12:09 +0100 Subject: [PATCH 02/13] allows to replace interior with a other instance (pointers in geometries) --- include/SFCGAL/Polygon.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/include/SFCGAL/Polygon.h b/include/SFCGAL/Polygon.h index c2a6ec53..1f580f0c 100644 --- a/include/SFCGAL/Polygon.h +++ b/include/SFCGAL/Polygon.h @@ -97,7 +97,18 @@ namespace SFCGAL { inline LineString & exteriorRing() { return _rings.front(); } - + /** + * Sets the exterior ring + */ + inline void setExteriorRing( const LineString& ring ){ + _rings.front() = ring ; + } + /** + * Sets the exterior ring (takes ownership) + */ + inline void setExteriorRing( LineString* ring ){ + _rings.replace( 0, ring ); + } /** * Test if the polygon has interior rings From 5d39ebaf6433ce9152a0b1a81c817b7ae6de08fa Mon Sep 17 00:00:00 2001 From: mborne Date: Wed, 16 Jan 2013 15:13:15 +0100 Subject: [PATCH 03/13] add geometry generator (hoch snowflake) for test and demo purposes --- include/SFCGAL/generator/hoch.h | 21 +++++++++++++ src/SFCGAL/generator/hoch.cpp | 56 +++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 include/SFCGAL/generator/hoch.h create mode 100644 src/SFCGAL/generator/hoch.cpp diff --git a/include/SFCGAL/generator/hoch.h b/include/SFCGAL/generator/hoch.h new file mode 100644 index 00000000..8c5690d1 --- /dev/null +++ b/include/SFCGAL/generator/hoch.h @@ -0,0 +1,21 @@ +#ifndef _SFCGAL_GENERATOR_HOCH_H_ +#define _SFCGAL_GENERATOR_HOCH_H_ + +#include + +namespace SFCGAL { + class Polygon ; +} + +namespace SFCGAL { +namespace generator { + + /** + * generate hoch snowflake + */ + std::auto_ptr< Polygon > hoch( const unsigned int & order ) ; + +} // namespace generator +} // namespace SFCGAL + +#endif diff --git a/src/SFCGAL/generator/hoch.cpp b/src/SFCGAL/generator/hoch.cpp new file mode 100644 index 00000000..8ca33a62 --- /dev/null +++ b/src/SFCGAL/generator/hoch.cpp @@ -0,0 +1,56 @@ +#include + +#include + +namespace SFCGAL { +namespace generator { + +std::vector< Kernel::Vector_2 > _hoch( const std::vector< Kernel::Vector_2 > & points ){ + std::vector< Kernel::Vector_2 > result ; + //TODO result.reserve + size_t numPoints = points.size() ; + for ( size_t i = 0; i < numPoints; i++ ){ + const Kernel::Vector_2& a = points[ i ] ; + const Kernel::Vector_2& b = points[ (i + 1) % numPoints ] ; + + Kernel::Vector_2 ab = b - a ; + Kernel::Vector_2 normal( -ab.y(), ab.x() ); + + result.push_back( a ); + result.push_back( a + ab / 3 ); + result.push_back( a + ab / 2 + normal * sqrt(3.0) / 6.0 ); + result.push_back( a + (ab * 2)/3 ); + } + return result ; +} + +/// +/// +/// +std::auto_ptr< Polygon > hoch( const unsigned int & order ) +{ + std::vector< Kernel::Vector_2 > points ; + points.push_back( Kernel::Vector_2( 1.0, sqrt(3.0) ) ); + points.push_back( Kernel::Vector_2( 2.0, 0.0 ) ); + points.push_back( Kernel::Vector_2( 0.0, 0.0 ) ); + + + for ( unsigned int k = 0 ; k < order; k++ ){ + points = _hoch( points ); + } + + std::auto_ptr< Polygon > result( new Polygon() ) ; + std::auto_ptr< LineString > ring( new LineString() ) ; + for ( std::vector< Kernel::Vector_2 >::const_iterator it = points.begin(); it != points.end(); ++it ){ + ring->addPoint( new Point( it->x(), it->y() ) ) ; + } + ring->addPoint( new Point( points.front().x(), points.front().y() ) ) ; + + result->setExteriorRing( ring.release() ); + + return result ; +} + +} // namespace generator +} // namespace SFCGAL + From ddb7747293c82af030c57a2cae3c60ef9faa5a85 Mon Sep 17 00:00:00 2001 From: mborne Date: Wed, 16 Jan 2013 15:14:03 +0100 Subject: [PATCH 04/13] [CMake]SFCGAL_COMPILE_BENCH => SFCGAL_BUILD_BENCH --- test/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 22ba2c10..12a3bc63 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -12,8 +12,8 @@ add_subdirectory( unit ) #-- build regression tests add_subdirectory( regress ) -option( SFCGAL_COMPILE_BENCH "Compile benchmarks" OFF ) -if( SFCGAL_COMPILE_BENCH ) +option( SFCGAL_BUILD_BENCH "Build benchmarks" ON ) +if( ${SFCGAL_BUILD_BENCH} ) add_subdirectory( bench ) endif() From b2009bda3c7793fa84163fb5a0838dfe8ca67e99 Mon Sep 17 00:00:00 2001 From: mborne Date: Wed, 16 Jan 2013 15:14:43 +0100 Subject: [PATCH 05/13] add triangulation bench on hoch snowflake --- test/bench/BenchTriangulation.cpp | 16 ++++++++++++++++ test/bench/CMakeLists.txt | 22 ++++++++-------------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/test/bench/BenchTriangulation.cpp b/test/bench/BenchTriangulation.cpp index 04635f3e..8b435cbb 100644 --- a/test/bench/BenchTriangulation.cpp +++ b/test/bench/BenchTriangulation.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "../test_config.h" @@ -41,6 +42,21 @@ BOOST_AUTO_TEST_CASE( testMultiPointTriangulation ) std::cout << "triangulate "<< N_POINTS << " points : " << timer.format() << std::endl; } +BOOST_AUTO_TEST_CASE( testPolygonTriangulationHoch ) +{ + const int N = 7 ; + std::auto_ptr< Polygon > fractal( generator::hoch(N) ); +// std::cout << fractal->asText(5) << std::endl ; + + boost::timer::cpu_timer timer; + timer.start(); + TriangulatedSurface triangulatedSurface ; + SFCGAL::algorithm::triangulate( *fractal, triangulatedSurface ) ; + timer.stop(); + std::cout << "hoch(" << N << ") "<< triangulatedSurface.numTriangles() << " triangles : " << timer.format() << std::endl; +} + + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/bench/CMakeLists.txt b/test/bench/CMakeLists.txt index 32b5b93a..48b01b43 100644 --- a/test/bench/CMakeLists.txt +++ b/test/bench/CMakeLists.txt @@ -1,19 +1,13 @@ -set(SFCGAL_HME_BENCHS - IntersectionPerfTest.cpp - KernelPerfTest.cpp - BenchWKT.cpp - BenchTriangulation.cpp - TestModule.cpp -) -add_executable( bench-hme ${SFCGAL_HME_BENCHS} ) -target_link_libraries( bench-hme +file( GLOB SFCGAL_BENCHS_SOURCES *.cpp ) +add_executable( bench-SFCGAL ${SFCGAL_BENCHS_SOURCES} ) +target_link_libraries( bench-SFCGAL SFCGAL ${Boost_LIBRARIES} ${CGAL_LIBRARIES} ) -if( ${SFCGAL_WITH_MPFR} ) - target_link_libraries( bench-hme ${MPFR_LIBRARIES} ) -endif( ${SFCGAL_WITH_MPFR} ) -set_target_properties( bench-hme PROPERTIES DEBUG_POSTFIX "d" ) -install( TARGETS bench-hme DESTINATION bin ) +if( SFCGAL_WITH_MPFR ) + target_link_libraries( bench-SFCGAL ${MPFR_LIBRARIES} ${GMP_LIBRARIES} ) +endif() +set_target_properties( bench-SFCGAL PROPERTIES DEBUG_POSTFIX "d" ) +install( TARGETS bench-SFCGAL DESTINATION bin ) From a54a15cd688cb524d233f047c347abd244e50762 Mon Sep 17 00:00:00 2001 From: mborne Date: Wed, 16 Jan 2013 18:03:16 +0100 Subject: [PATCH 06/13] optimize triangulation and add discrete circle generator --- include/SFCGAL/Polygon.h | 4 ++ src/SFCGAL/Polygon.cpp | 9 +++ src/SFCGAL/algorithm/triangulate_polygon.cpp | 14 +--- test/bench/BenchTriangulation.cpp | 70 ++++++++++++++++++++ test/bench/BenchWKT.cpp | 33 +++++---- 5 files changed, 106 insertions(+), 24 deletions(-) diff --git a/include/SFCGAL/Polygon.h b/include/SFCGAL/Polygon.h index 1f580f0c..b5432f21 100644 --- a/include/SFCGAL/Polygon.h +++ b/include/SFCGAL/Polygon.h @@ -36,6 +36,10 @@ namespace SFCGAL { * Constructor with an exterior ring */ Polygon( const LineString & exteriorRing ) ; + /** + * Constructor with an exterior ring (takes ownership) + */ + Polygon( LineString * exteriorRing ) ; /** * Constructor with a Triangle */ diff --git a/src/SFCGAL/Polygon.cpp b/src/SFCGAL/Polygon.cpp index 4afe9d37..b358888a 100644 --- a/src/SFCGAL/Polygon.cpp +++ b/src/SFCGAL/Polygon.cpp @@ -39,6 +39,15 @@ Polygon::Polygon( const LineString & exteriorRing ): _rings.push_back( exteriorRing.clone() ); } +/// +/// +/// +Polygon::Polygon( LineString * exteriorRing ): + Surface() +{ + _rings.push_back( exteriorRing ); +} + /// /// /// diff --git a/src/SFCGAL/algorithm/triangulate_polygon.cpp b/src/SFCGAL/algorithm/triangulate_polygon.cpp index 9d4c7bae..29bb198e 100644 --- a/src/SFCGAL/algorithm/triangulate_polygon.cpp +++ b/src/SFCGAL/algorithm/triangulate_polygon.cpp @@ -210,15 +210,10 @@ void triangulate( const MultiPoint & geometry, TriangulatedSurface & triangulate for ( size_t j = 0; j < geometry.numGeometries(); j++ ) { const Point & point = geometry.pointN( j ); - CGAL::Point_2< Kernel > p2d( - point.x(), - point.y() - ); - /* * insert into triangulation */ - CDT::Vertex_handle vh = cdt.insert( p2d ); + CDT::Vertex_handle vh = cdt.insert( point.toPoint_2() ); vh->info().original = point ; } @@ -362,15 +357,10 @@ void triangulate2D( const Polygon & polygon, TriangulatedSurface & triangulatedS for ( size_t j = 0; j < ring.numPoints(); j++ ) { const Point & point = ring.pointN( j ); - CGAL::Point_2< Kernel > p2d( - point.x(), - point.y() - ); - /* * insert into triangulation */ - CDT::Vertex_handle vh = cdt.insert( p2d ); + CDT::Vertex_handle vh = cdt.insert( point.toPoint_2() ); vh->info().original = point ; // filter first point diff --git a/test/bench/BenchTriangulation.cpp b/test/bench/BenchTriangulation.cpp index 8b435cbb..e64eb02b 100644 --- a/test/bench/BenchTriangulation.cpp +++ b/test/bench/BenchTriangulation.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "../test_config.h" @@ -56,6 +57,75 @@ BOOST_AUTO_TEST_CASE( testPolygonTriangulationHoch ) std::cout << "hoch(" << N << ") "<< triangulatedSurface.numTriangles() << " triangles : " << timer.format() << std::endl; } +BOOST_AUTO_TEST_CASE( testPolygonTriangulationDisc ) +{ + const int N = 20000 ; + + std::auto_ptr< Polygon > disc( generator::disc( Point(0.0,0.0), 1.0, 8U ) ); +// std::cout << fractal->asText(5) << std::endl ; + + boost::timer::cpu_timer timer; + timer.start(); + for ( int i = 0; i < N; i++ ){ + TriangulatedSurface triangulatedSurface ; + SFCGAL::algorithm::triangulate( *disc, triangulatedSurface ) ; + } + timer.stop(); + std::cout << N << " disc triangulation" << timer.format() << std::endl; +} + + + + +BOOST_AUTO_TEST_CASE( testMultiPointTriangulation2D ) +{ + CGAL::Random_points_in_disc_2< Kernel::Point_2, Creator > g( 150.0 ); + + MultiPoint multiPoint ; + for ( int i = 0; i < N_POINTS; i++ ){ + Kernel::Point_2 p = *(++g) ; + multiPoint.addGeometry( new Point( p ) ) ; + } + + boost::timer::cpu_timer timer; + timer.start(); + TriangulatedSurface triangulatedSurface ; + SFCGAL::algorithm::triangulate2D( multiPoint, triangulatedSurface ) ; + timer.stop(); + std::cout << "triangulate2D "<< N_POINTS << " points : " << timer.format() << std::endl; +} + +BOOST_AUTO_TEST_CASE( testPolygonTriangulationHoch2D ) +{ + const int N = 7 ; + std::auto_ptr< Polygon > fractal( generator::hoch(N) ); +// std::cout << fractal->asText(5) << std::endl ; + + boost::timer::cpu_timer timer; + timer.start(); + TriangulatedSurface triangulatedSurface ; + SFCGAL::algorithm::triangulate2D( *fractal, triangulatedSurface ) ; + timer.stop(); + std::cout << "hoch2D(" << N << ") "<< triangulatedSurface.numTriangles() << " triangles : " << timer.format() << std::endl; +} + +BOOST_AUTO_TEST_CASE( testPolygonTriangulationDisc2D ) +{ + const int N = 20000 ; + + std::auto_ptr< Polygon > disc( generator::disc( Point(0.0,0.0), 1.0, 8U ) ); +// std::cout << fractal->asText(5) << std::endl ; + + boost::timer::cpu_timer timer; + timer.start(); + for ( int i = 0; i < N; i++ ){ + TriangulatedSurface triangulatedSurface ; + SFCGAL::algorithm::triangulate2D( *disc, triangulatedSurface ) ; + } + timer.stop(); + std::cout << N << " disc triangulation 2D" << timer.format() << std::endl; +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/bench/BenchWKT.cpp b/test/bench/BenchWKT.cpp index b3746eae..6dc6280b 100644 --- a/test/bench/BenchWKT.cpp +++ b/test/bench/BenchWKT.cpp @@ -14,21 +14,22 @@ using namespace boost::unit_test ; using namespace SFCGAL ; -#define N_WKTS 100000 - BOOST_AUTO_TEST_SUITE( SFCGAL_BenchWKT ) // // Test limit case BOOST_AUTO_TEST_CASE( testReadPoints ) { + const int N = 100000 ; + boost::timer::cpu_timer timer; timer.start(); - for ( int i = 0; i < N_WKTS; i++ ){ + for ( int i = 0; i < N; i++ ){ io::readWkt( "POINT(50000 50000)" ) ; } timer.stop(); - std::cout << N_WKTS << " WKT points : " << timer.format() << std::endl; + + std::cout << N << " WKT points : " << timer.format() << std::endl; } @@ -36,52 +37,60 @@ BOOST_AUTO_TEST_CASE( testReadPoints ) // Test limit case BOOST_AUTO_TEST_CASE( testReadLineString ) { + const int N = 100000 ; + boost::timer::cpu_timer timer; timer.start(); - for ( int i = 0; i < N_WKTS; i++ ){ + for ( int i = 0; i < N; i++ ){ io::readWkt( "LINESTRING(0 0,0 1000,1000 1000)" ) ; } timer.stop(); - std::cout << N_WKTS << " WKT LineStrings : " << timer.format() << std::endl; + std::cout << N << " WKT LineStrings : " << timer.format() << std::endl; } // // Test limit case BOOST_AUTO_TEST_CASE( testReadPolygon ) { + const int N = 100000 ; + boost::timer::cpu_timer timer; timer.start(); - for ( int i = 0; i < N_WKTS; i++ ){ + for ( int i = 0; i < N; i++ ){ io::readWkt( "POLYGON((0 0,0 1000,1000 1000,1000 0,0 0))" ) ; } timer.stop(); - std::cout << N_WKTS << " WKT Polygons : " << timer.format() << std::endl; + std::cout << N << " WKT Polygons : " << timer.format() << std::endl; } // // Test limit case BOOST_AUTO_TEST_CASE( testReadTriangle ) { + const int N = 100000 ; + boost::timer::cpu_timer timer; timer.start(); - for ( int i = 0; i < N_WKTS; i++ ){ + for ( int i = 0; i < N; i++ ){ io::readWkt( "TRIANGLE((0 0,0 1000,1000 1000,1000 0,0 0))" ) ; } timer.stop(); - std::cout << N_WKTS << " WKT Triangles : " << timer.format() << std::endl; + std::cout << N << " WKT Triangles : " << timer.format() << std::endl; } // // Test limit case BOOST_AUTO_TEST_CASE( testReadSolid ) { + const int N = 10000 ; + boost::timer::cpu_timer timer; timer.start(); - for ( int i = 0; i < N_WKTS; i++ ){ + for ( int i = 0; i < N; i++ ){ io::readWkt( "SOLID((((0.0 0.0 0.0,0.0 1.0 0.0,1.0 1.0 0.0,1.0 0.0 0.0,0.0 0.0 0.0),(0.2 0.2 0.0,0.8 0.2 0.0,0.8 0.8 0.0,0.2 0.8 0.0,0.2 0.2 0.0)),((0.0 0.0 1.0,1.0 0.0 1.0,1.0 1.0 1.0,0.0 1.0 1.0,0.0 0.0 1.0),(0.2 0.2 1.0,0.2 0.8 1.0,0.8 0.8 1.0,0.8 0.2 1.0,0.2 0.2 1.0)),((0.0 0.0 0.0,0.0 0.0 1.0,0.0 1.0 1.0,0.0 1.0 0.0,0.0 0.0 0.0)),((0.0 1.0 0.0,0.0 1.0 1.0,1.0 1.0 1.0,1.0 1.0 0.0,0.0 1.0 0.0)),((1.0 1.0 0.0,1.0 1.0 1.0,1.0 0.0 1.0,1.0 0.0 0.0,1.0 1.0 0.0)),((1.0 0.0 0.0,1.0 0.0 1.0,0.0 0.0 1.0,0.0 0.0 0.0,1.0 0.0 0.0)),((0.2 0.2 0.0,0.2 0.2 1.0,0.8 0.2 1.0,0.8 0.2 0.0,0.2 0.2 0.0)),((0.8 0.2 0.0,0.8 0.2 1.0,0.8 0.8 1.0,0.8 0.8 0.0,0.8 0.2 0.0)),((0.8 0.8 0.0,0.8 0.8 1.0,0.2 0.8 1.0,0.2 0.8 0.0,0.8 0.8 0.0)),((0.2 0.8 0.0,0.2 0.8 1.0,0.2 0.2 1.0,0.2 0.2 0.0,0.2 0.8 0.0))))" ) ; } timer.stop(); - std::cout << N_WKTS << " WKT Solids : " << timer.format() << std::endl; + std::cout << N << " WKT Solids : " << timer.format() << std::endl; } From d35d3c7cdb3d52b7226576de1bf791f27264b0a3 Mon Sep 17 00:00:00 2001 From: mborne Date: Thu, 17 Jan 2013 10:34:48 +0100 Subject: [PATCH 07/13] add discrete disc generator --- include/SFCGAL/generator/disc.h | 26 ++++++++++++++++++++++++++ src/SFCGAL/generator/disc.cpp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 include/SFCGAL/generator/disc.h create mode 100644 src/SFCGAL/generator/disc.cpp diff --git a/include/SFCGAL/generator/disc.h b/include/SFCGAL/generator/disc.h new file mode 100644 index 00000000..585282a8 --- /dev/null +++ b/include/SFCGAL/generator/disc.h @@ -0,0 +1,26 @@ +#ifndef _SFCGAL_GENERATOR_DISC_H_ +#define _SFCGAL_GENERATOR_DISC_H_ + +#include + +namespace SFCGAL { + class Point ; + class Polygon ; +} + +namespace SFCGAL { +namespace generator { + + /** + * Generate a discrete circle + */ + std::auto_ptr< Polygon > disc( + const Point& center, + const double & radius, + const unsigned int & nQuadrantSegments = 8U + ) ; + +} // namespace generator +} // namespace SFCGAL + +#endif diff --git a/src/SFCGAL/generator/disc.cpp b/src/SFCGAL/generator/disc.cpp new file mode 100644 index 00000000..859cfb94 --- /dev/null +++ b/src/SFCGAL/generator/disc.cpp @@ -0,0 +1,32 @@ +#include +#include + +namespace SFCGAL { +namespace generator { + +/// +/// +/// +std::auto_ptr< Polygon > disc( + const Point& center, + const double & radius, + const unsigned int & nQuadrantSegments +) +{ + BOOST_ASSERT( nQuadrantSegments > 1 ); + + std::auto_ptr< LineString > exteriorRing( new LineString() ) ; + + double dTheta = M_PI_4 / nQuadrantSegments ; + for ( size_t i = 0; i < nQuadrantSegments * 4; i++ ){ + Kernel::Vector_2 p = center.toVector_2() + Kernel::Vector_2( cos(i*dTheta), sin(i*dTheta) ) ; + exteriorRing->addPoint( new Point( p.x(), p.y() ) ) ; + } + exteriorRing->addPoint( exteriorRing->startPoint() ) ; + + return std::auto_ptr< Polygon >( new Polygon( exteriorRing.release() ) ); +} + +} // namespace generator +} // namespace SFCGAL + From 4712347d03ed79756cf34ac3a86d650f1f0425f6 Mon Sep 17 00:00:00 2001 From: mborne Date: Thu, 17 Jan 2013 13:29:57 +0100 Subject: [PATCH 08/13] fix version header --- include/SFCGAL/version.h | 11 ----------- include/SFCGAL/version.h.cmake | 8 ++++---- 2 files changed, 4 insertions(+), 15 deletions(-) delete mode 100644 include/SFCGAL/version.h diff --git a/include/SFCGAL/version.h b/include/SFCGAL/version.h deleted file mode 100644 index 8203842c..00000000 --- a/include/SFCGAL/version.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _SFCGAL_VERSION_H_ -#define _SFCGAL_VERSION_H_ - -/* #undef SFCAL_VERSION_MAJOR */ -/* #undef SFCAL_VERSION_MINOR */ -/* #undef SFCAL_VERSION_PATCH */ - -/* #undef SFCAL_VERSION */ - -#endif - diff --git a/include/SFCGAL/version.h.cmake b/include/SFCGAL/version.h.cmake index 4fef045e..a57f5a4e 100644 --- a/include/SFCGAL/version.h.cmake +++ b/include/SFCGAL/version.h.cmake @@ -1,11 +1,11 @@ #ifndef _SFCGAL_VERSION_H_ #define _SFCGAL_VERSION_H_ -#cmakedefine SFCAL_VERSION_MAJOR @SFCAL_VERSION_MAJOR@ -#cmakedefine SFCAL_VERSION_MINOR @SFCAL_VERSION_MINOR@ -#cmakedefine SFCAL_VERSION_PATCH @SFCAL_VERSION_PATCH@ +#define SFCAL_VERSION_MAJOR @SFCGAL_VERSION_MAJOR@ +#define SFCAL_VERSION_MINOR @SFCGAL_VERSION_MINOR@ +#define SFCAL_VERSION_PATCH @SFCGAL_VERSION_PATCH@ -#cmakedefine SFCAL_VERSION "@SFCAL_VERSION" +#define SFCAL_VERSION "@SFCGAL_VERSION@" #endif From 460c55dd5c6c47129ccd25e92a7048f237093335 Mon Sep 17 00:00:00 2001 From: mborne Date: Sat, 19 Jan 2013 17:26:11 +0100 Subject: [PATCH 09/13] fix hasPlane (return when normal is found) --- include/SFCGAL/algorithm/plane.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/SFCGAL/algorithm/plane.h b/include/SFCGAL/algorithm/plane.h index 631ed288..851ffbb5 100644 --- a/include/SFCGAL/algorithm/plane.h +++ b/include/SFCGAL/algorithm/plane.h @@ -40,10 +40,11 @@ namespace algorithm { }else if ( n == 2 && ! CGAL::collinear( a, b, p ) ) { c = p ; n++ ; - break; + return true ; } } - return n == 3; + BOOST_ASSERT( n < 3 ); + return false; } /** From 9ef29e933ea7b3ef9fba45ecea14c1aec2f63f99 Mon Sep 17 00:00:00 2001 From: mborne Date: Sun, 20 Jan 2013 19:16:01 +0100 Subject: [PATCH 10/13] optimize 3D polygon triangulation (round normal to double) and fix problem in newell normal --- .gitignore | 4 ++++ include/SFCGAL/algorithm/normal.h | 24 ++++++++++++------- include/SFCGAL/algorithm/plane.h | 9 ++++--- src/SFCGAL/algorithm/triangulate_polygon.cpp | 4 ++-- test/unit/SFCGAL/algorithm/NormalTest.cpp | 25 ++++++++++++++++++++ 5 files changed, 50 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 1a17eb95..eae186a0 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,7 @@ polygon_triangulation2.obj gmon.out + +include/SFCGAL/version.h + + diff --git a/include/SFCGAL/algorithm/normal.h b/include/SFCGAL/algorithm/normal.h index 50b47483..de920e05 100644 --- a/include/SFCGAL/algorithm/normal.h +++ b/include/SFCGAL/algorithm/normal.h @@ -23,33 +23,39 @@ namespace algorithm { /** * Returns the 3D normal to a ring (supposed to be planar and closed). - */ + * @warning exact allows to avoid double rounding at the end of the computation + */ template < typename Kernel > - CGAL::Vector_3< Kernel > normal3D( const LineString & ls ) + CGAL::Vector_3< Kernel > normal3D( const LineString & ls, bool exact = true ) { // Newell's formula typename Kernel::FT nx, ny, nz; nx = ny = nz = 0.0; - for ( size_t i = 0; i < ls.numPoints() - 1; ++i ) + for ( size_t i = 0; i < ls.numPoints(); ++i ) { const Point& pi = ls.pointN(i); const Point& pj = ls.pointN( (i+1) % ls.numPoints() ); - typename Kernel::FT zi = pi.is3D() ? pi.z() : 0.0; - typename Kernel::FT zj = pj.is3D() ? pj.z() : 0.0; + typename Kernel::FT zi = pi.z() ; + typename Kernel::FT zj = pj.z() ; nx += ( pi.y() - pj.y() ) * ( zi + zj ); ny += ( zi - zj ) * ( pi.x() + pj.x() ); nz += ( pi.x() - pj.x() ) * ( pi.y() + pj.y() ); } - return CGAL::Vector_3( nx, ny, nz ); - } + if ( exact ){ + return CGAL::Vector_3( nx, ny, nz ); + }else{ + return CGAL::Vector_3( CGAL::to_double(nx), CGAL::to_double(ny), CGAL::to_double(nz) ); + } + } /** * Returns the 3D normal to a polygon (supposed to be planar). + * @warning exact allows to avoid double rounding at the end of the computation */ template < typename Kernel > - CGAL::Vector_3< Kernel > normal3D( const Polygon & polygon ) + CGAL::Vector_3< Kernel > normal3D( const Polygon & polygon, bool exact = true ) { - return normal3D< Kernel >( polygon.exteriorRing() ); + return normal3D< Kernel >( polygon.exteriorRing(), exact ); } }//algorithm diff --git a/include/SFCGAL/algorithm/plane.h b/include/SFCGAL/algorithm/plane.h index 851ffbb5..f6fa7220 100644 --- a/include/SFCGAL/algorithm/plane.h +++ b/include/SFCGAL/algorithm/plane.h @@ -80,18 +80,17 @@ namespace algorithm { /** * Returns the oriented 3D plane of a polygon (supposed to be planar). + * @warning result is rounded to double if exact is false (avoid huge expression tree) */ template < typename Kernel > - CGAL::Plane_3< Kernel > plane3D( const Polygon & polygon ) + CGAL::Plane_3< Kernel > plane3D( const Polygon & polygon, bool exact = true ) { - CGAL::Vector_3< Kernel > normal = normal3D< Kernel >( polygon ); - return CGAL::Plane_3< Kernel >( polygon.exteriorRing().pointN(0).toPoint_3(), - normal ); + CGAL::Vector_3< Kernel > normal = normal3D< Kernel >( polygon, exact ); + return CGAL::Plane_3< Kernel >( polygon.exteriorRing().pointN(0).toPoint_3(), normal ); } - }//algorithm }//SFCGAL diff --git a/src/SFCGAL/algorithm/triangulate_polygon.cpp b/src/SFCGAL/algorithm/triangulate_polygon.cpp index 29bb198e..ad0b7662 100644 --- a/src/SFCGAL/algorithm/triangulate_polygon.cpp +++ b/src/SFCGAL/algorithm/triangulate_polygon.cpp @@ -262,9 +262,9 @@ void triangulate( const Polygon & polygon, TriangulatedSurface & triangulatedSur // std::cout << "---------------------------------------------------------" << std::endl ; // std::cout << "triangulate polygon : " << polygon.asText() << std::endl; - CGAL::Plane_3< Kernel > polygonPlane = plane3D< Kernel >( polygon ) ; + CGAL::Plane_3< Kernel > polygonPlane = plane3D< Kernel >( polygon, false ) ; if ( polygonPlane.is_degenerate() ){ - BOOST_THROW_EXCEPTION( Exception( + BOOST_THROW_EXCEPTION( Exception( ( boost::format( "can't find plane for polygon %s" ) % polygon.asText() ).str() ) ); } diff --git a/test/unit/SFCGAL/algorithm/NormalTest.cpp b/test/unit/SFCGAL/algorithm/NormalTest.cpp index f8fa1abb..c3eb4f5d 100644 --- a/test/unit/SFCGAL/algorithm/NormalTest.cpp +++ b/test/unit/SFCGAL/algorithm/NormalTest.cpp @@ -58,5 +58,30 @@ BOOST_AUTO_TEST_CASE( testNormal2 ) } } + +BOOST_AUTO_TEST_CASE( testNormal3 ) +{ + std::auto_ptr gA( io::readWkt("POLYGON((0 1 0,0 1 1,1 1 1,1 1 0,0 1 0))") ); + // exact + { + CGAL::Vector_3 normal = algorithm::normal3D( gA->as(), true); + //std::cout << CGAL::exact(normal) << std::endl; + CGAL::Plane_3 plane( gA->as().exteriorRing().startPoint().toPoint_3(), normal ); + //std::cout << CGAL::exact(plane) << std::endl; + BOOST_CHECK( ! plane.is_degenerate() ); + } + // round + { + CGAL::Vector_3 normal = algorithm::normal3D( gA->as(), false); + //std::cout << CGAL::exact(normal) << std::endl; + CGAL::Plane_3 plane( gA->as().exteriorRing().startPoint().toPoint_3(), normal ); + //std::cout << CGAL::exact(plane) << std::endl; + BOOST_CHECK( ! plane.is_degenerate() ); + } + +} + + + BOOST_AUTO_TEST_SUITE_END() From f3d8ce21716a6ccbc9ba690adaf9f318fdbf0297 Mon Sep 17 00:00:00 2001 From: mborne Date: Mon, 21 Jan 2013 09:35:34 +0100 Subject: [PATCH 11/13] ignore version.h --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 1a17eb95..3617f699 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ polygon_triangulation2.obj gmon.out +include/SFCGAL/version.h + From ee8ed5c715dc81d9919910c7a706c027d7421f53 Mon Sep 17 00:00:00 2001 From: mborne Date: Mon, 21 Jan 2013 10:48:02 +0100 Subject: [PATCH 12/13] add bench --- test/bench/BenchContainer.cpp | 154 ++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 test/bench/BenchContainer.cpp diff --git a/test/bench/BenchContainer.cpp b/test/bench/BenchContainer.cpp new file mode 100644 index 00000000..7f8f32e2 --- /dev/null +++ b/test/bench/BenchContainer.cpp @@ -0,0 +1,154 @@ +#include + +#include + +#include +#include + +#include "../test_config.h" + +#include +#include +#include + +using namespace boost::unit_test ; +using namespace SFCGAL ; + +BOOST_AUTO_TEST_SUITE( SFCGAL_BenchContainer ) + +// +// Test limit case +BOOST_AUTO_TEST_CASE( testVectorOfPoint2 ) +{ + const int N = 100000 ; + + boost::timer::cpu_timer timer; + + // create points + timer.start(); + std::vector< Kernel::Point_2 > points ; + points.reserve( N ) ; + for ( int i = 0; i < N; i++ ){ + points.push_back( Kernel::Point_2(i,i) ) ; + } + timer.stop(); + std::cout << "std::vector< Kernel::Point_2 > create " << timer.format() << std::endl ; + + // centroid + timer.start(); + Kernel::FT x = 0 , y = 0 ; + for ( std::vector< Kernel::Point_2 >::const_iterator it = points.begin(); it != points.end(); ++it ){ + x += it->x() ; + y += it->y() ; + } + Kernel::Point_2 centroid( x / Kernel::FT(points.size()), y / Kernel::FT(points.size()) ); + timer.stop(); + std::cout << "std::vector< Kernel::Point_2 > access " << timer.format() << std::endl ; + + // reverse + timer.start(); + std::reverse( points.begin(), points.end() ) ; + timer.stop(); + std::cout << "std::vector< Kernel::Point_2 > reverse " << timer.format() << std::endl ; + + // clear + timer.start(); + points.clear() ; + timer.stop(); + std::cout << "std::vector< Kernel::Point_2 > clear " << timer.format() << std::endl ; +} + +// +// Test limit case +BOOST_AUTO_TEST_CASE( testVectorOfPoint ) +{ + const int N = 100000 ; + + boost::timer::cpu_timer timer; + + // create points + timer.start(); + std::vector< Point > points ; + points.reserve( N ) ; + for ( int i = 0; i < N; i++ ){ + points.push_back( Point(i,i) ) ; + } + timer.stop(); + std::cout << "std::vector< Point > create " << timer.format() << std::endl ; + + // centroid + timer.start(); + Kernel::FT x = 0 , y = 0 ; + for ( std::vector< Point >::const_iterator it = points.begin(); it != points.end(); ++it ){ + x += it->x() ; + y += it->y() ; + } + Point centroid( x / Kernel::FT(points.size()), y / Kernel::FT(points.size()) ); + timer.stop(); + std::cout << "std::vector< Point > access " << timer.format() << std::endl ; + + + // reverse + timer.start(); + std::reverse( points.begin(), points.end() ) ; + timer.stop(); + std::cout << "std::vector< Point > reverse " << timer.format() << std::endl ; + + // clear + timer.start(); + points.clear() ; + timer.stop(); + std::cout << "std::vector< Point > clear " << timer.format() << std::endl ; +} + + +// +// Test limit case +BOOST_AUTO_TEST_CASE( testPtrVectorOfPoint ) +{ + const int N = 100000 ; + + boost::timer::cpu_timer timer; + + // create points + timer.start(); + boost::ptr_vector< Point > points ; + points.reserve( N ) ; + for ( int i = 0; i < N; i++ ){ + points.push_back( new Point(i,i) ) ; + } + timer.stop(); + std::cout << "boost::ptr_vector< Point > create " << timer.format() << std::endl ; + + // centroid + timer.start(); + Kernel::FT x = 0 , y = 0 ; + for ( boost::ptr_vector< Point >::const_iterator it = points.begin(); it != points.end(); ++it ){ + x += it->x() ; + y += it->y() ; + } + Point centroid( x / Kernel::FT(points.size()), y / Kernel::FT(points.size()) ); + timer.stop(); + std::cout << "boost::ptr_vector< Point > access " << timer.format() << std::endl ; + + + // reverse + timer.start(); + std::reverse( points.begin(), points.end() ) ; + timer.stop(); + std::cout << "boost::ptr_vector< Point > reverse " << timer.format() << std::endl ; + + // clear + timer.start(); + points.clear() ; + timer.stop(); + std::cout << "boost::ptr_vector< Point > clear " << timer.format() << std::endl ; +} + + + +BOOST_AUTO_TEST_SUITE_END() + + + + From 86d958124923f11f5918c033cf0816ac040ce4fe Mon Sep 17 00:00:00 2001 From: mborne Date: Mon, 21 Jan 2013 11:04:35 +0100 Subject: [PATCH 13/13] remove SFCGAL_DEBUG* --- src/SFCGAL/algorithm/triangulate_polygon.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/SFCGAL/algorithm/triangulate_polygon.cpp b/src/SFCGAL/algorithm/triangulate_polygon.cpp index ad0b7662..53de7c18 100644 --- a/src/SFCGAL/algorithm/triangulate_polygon.cpp +++ b/src/SFCGAL/algorithm/triangulate_polygon.cpp @@ -278,7 +278,6 @@ void triangulate( const Polygon & polygon, TriangulatedSurface & triangulatedSur CDT::Vertex_handle v_prev ; for ( size_t j = 0; j < ring.numPoints(); j++ ) { const Point & point = ring.pointN( j ); - SFCGAL_DEBUG( boost::format( "insert point %s" ) % point.asText() ); CGAL::Point_3< Kernel > p3d = point.toPoint_3(); /* @@ -314,7 +313,6 @@ void triangulate( const Polygon & polygon, TriangulatedSurface & triangulatedSur if ( ! it->info().in_domain() ){ continue ; } -// assert( it->is_valid() ); const Point & a = it->vertex(0)->info().original ; const Point & b = it->vertex(1)->info().original ;