From 5141abe2c32a2105809a14a1fd8ef3eec238c0c0 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Fri, 20 Apr 2018 12:33:23 +0200 Subject: [PATCH 001/150] qr factorization --- .../Optimal_bounding_box/linear_algebra.h | 51 ++++++++++++++++ .../test/Optimal_bounding_box/CMakeLists.txt | 59 +++++++++++++++++++ .../test_linear_algebra_functions.cpp | 58 ++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h create mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt create mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h new file mode 100644 index 00000000000..8570964f2f1 --- /dev/null +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h @@ -0,0 +1,51 @@ +// Copyright (c) 2018 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Konstantinos Katrioplas + +#ifndef CGAL_OPTIMAL_BOUNDING_BOX_H +#define CGAL_OPTIMAL_BOUNDING_BOX_H + + +#include + + +namespace CGAL { +namespace Optimal_bounding_box { + + +template +void qr_factorization(EigenMatrix& A, EigenMatrix& Q) +{ + Eigen::HouseholderQR qr(A); + Q = qr.householderQ(); +} + + + +}} + + + + + + +#endif //CGAL_OPTIMAL_BOUNDING_BOX_H + + diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt new file mode 100644 index 00000000000..378a96457e6 --- /dev/null +++ b/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt @@ -0,0 +1,59 @@ +# Created by the script cgal_create_CMakeLists +# This is the CMake script for compiling a set of CGAL applications. + +project( Optimal_bounding_box_Tests ) + + +cmake_minimum_required(VERSION 2.6.2) +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6) + if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3) + cmake_policy(VERSION 2.8.4) + else() + cmake_policy(VERSION 2.6) + endif() +endif() + + +# CGAL and its components +find_package( CGAL QUIET COMPONENTS ) + +if ( NOT CGAL_FOUND ) + + message(STATUS "This project requires the CGAL library, and will not be compiled.") + return() + +endif() + +# include helper file +include( ${CGAL_USE_FILE} ) + + +# Boost and its components +find_package( Boost REQUIRED ) + +if ( NOT Boost_FOUND ) + + message(STATUS "This project requires the Boost library, and will not be compiled.") + + return() + +endif() + +# include for local directory + +# include for local package +include_directories( BEFORE ../../include ) + +find_package(Eigen3 3.2.0) #(requires 3.2.0 or greater) + +find_package( TBB ) + +include( CGAL_CreateSingleSourceCGALProgram ) +if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) + + create_single_source_cgal_program("test_linear_algebra_functions.cpp") + +endif(EIGEN3_FOUND) + + diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp new file mode 100644 index 00000000000..435c8a755da --- /dev/null +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -0,0 +1,58 @@ +#include +#include + +#include + +#include +#include + +#include + +//typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +//typedef CGAL::Surface_mesh Surface_mesh; + +typedef Eigen::MatrixXf MatrixXf; + + +bool assert_doubles(double d1, double d2, double epsilon) +{ + return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; +} + + +void test_qr_factorization() +{ + + MatrixXf A(3, 3); + A << 0.3011944, 0.9932761, 0.5483701, + 0.5149142, 0.5973263, 0.5162336, + 0.0039213, 0.0202949, 0.9240308; + + MatrixXf Q; + CGAL::Optimal_bounding_box::qr_factorization(A, Q); + + double epsilon = 1e-6; + CGAL_assertion(assert_doubles(Q(0,0), -0.504895, epsilon)); + CGAL_assertion(assert_doubles(Q(0,1), 0.862834, epsilon)); + CGAL_assertion(assert_doubles(Q(0,2), -0.024447, epsilon)); + CGAL_assertion(assert_doubles(Q(1,0), -0.863156, epsilon)); + CGAL_assertion(assert_doubles(Q(1,1), -0.504894, epsilon)); + CGAL_assertion(assert_doubles(Q(1,2), 0.006687, epsilon)); + CGAL_assertion(assert_doubles(Q(2,0), -0.006573, epsilon)); + CGAL_assertion(assert_doubles(Q(2,1), 0.024478, epsilon)); + CGAL_assertion(assert_doubles(Q(2,2), 0.999679, epsilon)); + + +} + + + + + +int main() +{ + + test_qr_factorization(); + + return 0; +} From 4f64c44c83e55e1b99ce8d0ab85bbb340241572d Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Fri, 20 Apr 2018 14:48:14 +0200 Subject: [PATCH 002/150] fitness function --- .../Optimal_bounding_box/fitness_function.h | 85 +++++++++++++++++++ .../Optimal_bounding_box/linear_algebra.h | 3 +- .../test_linear_algebra_functions.cpp | 22 +++++ 3 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h new file mode 100644 index 00000000000..87b4c662a44 --- /dev/null +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -0,0 +1,85 @@ +// Copyright (c) 2018 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Konstantinos Katrioplas + +#ifndef CGAL_FITNESS_FUNCTION_H +#define CGAL_FITNESS_FUNCTION_H + +#include +#include + + +namespace CGAL { +namespace Optimal_bounding_box { + +template +const double compute_fitness(Matrix& R, Matrix& data) +{ + + // R: rotation matrix + CGAL_assertion(R.cols() == 3); + CGAL_assertion(R.rows() == 3); + // data: points + CGAL_assertion(data.cols() == 3); + CGAL_assertion(data.rows() >= 3); + + CGAL_assertion(R.rows() == data.cols()); + + // rotate points + Matrix RT = R.transpose(); + Matrix rotated_data = data * RT; + CGAL_assertion(rotated_data.cols() == data.cols()); + CGAL_assertion(rotated_data.rows() == data.rows()); + + // AABB: take mins and maxs + double xmin = rotated_data.col(0).minCoeff(); + double xmax = rotated_data.col(0).maxCoeff(); + double ymin = rotated_data.col(1).minCoeff(); + double ymax = rotated_data.col(1).maxCoeff(); + double zmin = rotated_data.col(2).minCoeff(); + double zmax = rotated_data.col(2).maxCoeff(); + + double x_dim = abs(xmax - xmin); + double y_dim = abs(ymax - ymin); + double z_dim = abs(zmax - zmin); + + // volume + return (x_dim * y_dim * z_dim); + +} + + + + + + + + +}} // end namespaces + + + + + + +#endif //CGAL_FITNESS_FUNCTION_H + + + diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h index 8570964f2f1..83be8c79885 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h @@ -38,8 +38,7 @@ void qr_factorization(EigenMatrix& A, EigenMatrix& Q) } - -}} +}} // end namespaces diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index 435c8a755da..27b00e3229f 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -46,6 +47,26 @@ void test_qr_factorization() } +void test_fitness_function() +{ + MatrixXf data_points(4, 3); + data_points << 0.866802, 0.740808, 0.895304, + 0.912651, 0.761565, 0.160330, + 0.093661, 0.892578, 0.737412, + 0.166461, 0.149912, 0.364944; + + MatrixXf rotation(3, 3); + rotation << -0.809204, 0.124296, 0.574230, + -0.574694, 0.035719, -0.817589, + -0.122134, -0.991602, 0.042528; + + double fitness = CGAL::Optimal_bounding_box::compute_fitness(rotation, data_points); + CGAL_assertion(assert_doubles(fitness, 0.58606, 1e-6)); + +} + + + @@ -53,6 +74,7 @@ int main() { test_qr_factorization(); + test_fitness_function(); return 0; } From 460a17f950e78909f1120de975f4b199aa5d270d Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Fri, 20 Apr 2018 16:52:08 +0200 Subject: [PATCH 003/150] simplex functions refection, contraction, etc --- .../Optimal_bounding_box/fitness_function.h | 4 -- .../Optimal_bounding_box/linear_algebra.h | 54 ++++++++++++++-- .../test_linear_algebra_functions.cpp | 62 ++++++++++++++++++- 3 files changed, 111 insertions(+), 9 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 87b4c662a44..1f9a5b7372f 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -68,10 +68,6 @@ const double compute_fitness(Matrix& R, Matrix& data) - - - - }} // end namespaces diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h index 83be8c79885..7dd2145a602 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h @@ -22,7 +22,7 @@ #ifndef CGAL_OPTIMAL_BOUNDING_BOX_H #define CGAL_OPTIMAL_BOUNDING_BOX_H - +#include #include @@ -30,13 +30,59 @@ namespace CGAL { namespace Optimal_bounding_box { -template -void qr_factorization(EigenMatrix& A, EigenMatrix& Q) +template +void qr_factorization(Matrix& A, Matrix& Q) { - Eigen::HouseholderQR qr(A); + Eigen::HouseholderQR qr(A); Q = qr.householderQ(); } +template +const Matrix reflection(Matrix& S_centroid, Matrix& S_worst) +{ + CGAL_assertion(S_centroid.rows() == 3); + CGAL_assertion(S_centroid.rows() == 3); + CGAL_assertion(S_worst.cols() == 3); + CGAL_assertion(S_worst.cols() == 3); + + return S_centroid * S_worst.transpose() * S_centroid; +} + +template +const Matrix expansion(Matrix& S_centroid, Matrix& S_worst, Matrix& S_reflection) +{ + CGAL_assertion(S_centroid.rows() == 3); + CGAL_assertion(S_centroid.rows() == 3); + CGAL_assertion(S_worst.cols() == 3); + CGAL_assertion(S_worst.cols() == 3); + CGAL_assertion(S_reflection.cols() == 3); + CGAL_assertion(S_reflection.cols() == 3); + + return S_centroid * S_worst.transpose() * S_reflection; +} + +template +const Matrix constraction(Matrix& S_centroid, Matrix& S_worst) +{ + // same API for reduction + CGAL_assertion(S_centroid.rows() == 3); + CGAL_assertion(S_centroid.rows() == 3); + CGAL_assertion(S_worst.cols() == 3); + CGAL_assertion(S_worst.cols() == 3); + + Matrix contract = 0.5 * S_centroid + 0.5 * S_worst; + Matrix Q; + qr_factorization(contract, Q); + double det = Q.determinant(); + return Q / det; +} + + + + + + + }} // end namespaces diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index 27b00e3229f..8a52a0ca29c 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -61,11 +61,70 @@ void test_fitness_function() -0.122134, -0.991602, 0.042528; double fitness = CGAL::Optimal_bounding_box::compute_fitness(rotation, data_points); - CGAL_assertion(assert_doubles(fitness, 0.58606, 1e-6)); + CGAL_assertion(assert_doubles(fitness, 0.58606, 1e-5)); } +void test_simplex_operations() +{ + MatrixXf Sc(3, 3); + Sc << -0.809204, 0.124296, 0.574230, + -0.574694, 0.035719, -0.817589, + -0.122134, -0.991602, 0.042528; + + MatrixXf S_worst(3, 3); + S_worst << -0.45070, -0.32769, -0.83035, + -0.13619, -0.89406, 0.42675, + -0.88222, 0.30543, 0.35833; + + MatrixXf Sr = CGAL::Optimal_bounding_box::reflection(Sc, S_worst); + double epsilon = 1e-5; + CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); + CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); + CGAL_assertion(assert_doubles(Sr(0,2), -0.24664, epsilon)); + CGAL_assertion(assert_doubles(Sr(1,0), -0.60307, epsilon)); + CGAL_assertion(assert_doubles(Sr(1,1), -0.11875, epsilon)); + CGAL_assertion(assert_doubles(Sr(1,2), 0.78880, epsilon)); + CGAL_assertion(assert_doubles(Sr(2,0), -0.78642, epsilon)); + CGAL_assertion(assert_doubles(Sr(2,1), 0.25411, epsilon)); + CGAL_assertion(assert_doubles(Sr(2,2), -0.56300, epsilon)); + + MatrixXf Se = CGAL::Optimal_bounding_box::expansion(Sc, S_worst, Sr); + CGAL_assertion(assert_doubles(Se(0,0), -0.87991, epsilon)); + CGAL_assertion(assert_doubles(Se(0,1), 0.36105, epsilon)); + CGAL_assertion(assert_doubles(Se(0,2), -0.30888, epsilon)); + CGAL_assertion(assert_doubles(Se(1,0), -0.11816, epsilon)); + CGAL_assertion(assert_doubles(Se(1,1), -0.79593, epsilon)); + CGAL_assertion(assert_doubles(Se(1,2), -0.59375, epsilon)); + CGAL_assertion(assert_doubles(Se(2,0), -0.460215, epsilon)); + CGAL_assertion(assert_doubles(Se(2,1), -0.48595, epsilon)); + CGAL_assertion(assert_doubles(Se(2,2), 0.74300, epsilon)); + + + MatrixXf S_a(3, 3); + S_a << -0.277970, 0.953559, 0.116010, + -0.567497, -0.065576, -0.820760, + -0.775035, -0.293982, 0.559370; + + MatrixXf S_b(3, 3); + S_b << -0.419979, 0.301765, -0.855894, + -0.653011, -0.755415, 0.054087, + -0.630234, 0.581624, 0.514314; + + MatrixXf S_c = CGAL::Optimal_bounding_box::constraction(S_a, S_b); + CGAL_assertion(assert_doubles(S_c(0,0), -0.35111, epsilon)); + CGAL_assertion(assert_doubles(S_c(0,1), 0.79308, epsilon)); + CGAL_assertion(assert_doubles(S_c(0,2), -0.49774, epsilon)); + CGAL_assertion(assert_doubles(S_c(1,0), -0.61398, epsilon)); + CGAL_assertion(assert_doubles(S_c(1,1), -0.59635, epsilon)); + CGAL_assertion(assert_doubles(S_c(1,2), -0.51710, epsilon)); + CGAL_assertion(assert_doubles(S_c(2,0), -0.70693, epsilon)); + CGAL_assertion(assert_doubles(S_c(2,1), 0.12405, epsilon)); + CGAL_assertion(assert_doubles(S_c(2,2), 0.69632, epsilon)); + +} + @@ -75,6 +134,7 @@ int main() test_qr_factorization(); test_fitness_function(); + test_simplex_operations(); return 0; } From 82aeb8336fe03747a6b3ddca8358c558942e30a0 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Fri, 20 Apr 2018 17:17:05 +0200 Subject: [PATCH 004/150] centroid function --- .../Optimal_bounding_box/linear_algebra.h | 11 +++++++ .../test_linear_algebra_functions.cpp | 33 ++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h index 7dd2145a602..641b81302b6 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h @@ -77,6 +77,17 @@ const Matrix constraction(Matrix& S_centroid, Matrix& S_worst) return Q / det; } +template +const Matrix centroid(Matrix& S1, Matrix& S2, Matrix& S3) +{ + Matrix mean = (S1 + S2 + S3) / 3.0; + Matrix Q; + qr_factorization(mean, Q); + double det = Q.determinant(); + return Q / det; +} + + diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index 8a52a0ca29c..53b0f355d78 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -101,7 +101,6 @@ void test_simplex_operations() CGAL_assertion(assert_doubles(Se(2,1), -0.48595, epsilon)); CGAL_assertion(assert_doubles(Se(2,2), 0.74300, epsilon)); - MatrixXf S_a(3, 3); S_a << -0.277970, 0.953559, 0.116010, -0.567497, -0.065576, -0.820760, @@ -125,6 +124,37 @@ void test_simplex_operations() } +void test_centroid() +{ + MatrixXf S_a(3, 3); + S_a << -0.588443, 0.807140, -0.047542, + -0.786228, -0.584933, -0.199246, + -0.188629, -0.079867, 0.978795; + + MatrixXf S_b(3, 3); + S_b << -0.2192721, 0.2792986, -0.9348326, + -0.7772152, -0.6292092, -0.0056861, + -0.5897934, 0.7253193, 0.3550431; + + MatrixXf S_c(3, 3); + S_c << -0.32657, -0.60013, -0.73020, + -0.20022, -0.71110, 0.67398, + -0.92372, 0.36630, 0.11207; + + + MatrixXf S_centroid = CGAL::Optimal_bounding_box::centroid(S_a, S_b, S_c); + double epsilon = 1e-5; + CGAL_assertion(assert_doubles(S_centroid(0,0), -0.419979, epsilon)); + CGAL_assertion(assert_doubles(S_centroid(0,1), 0.301765, epsilon)); + CGAL_assertion(assert_doubles(S_centroid(0,2), -0.855894, epsilon)); + CGAL_assertion(assert_doubles(S_centroid(1,0), -0.653011, epsilon)); + CGAL_assertion(assert_doubles(S_centroid(1,1), -0.755415, epsilon)); + CGAL_assertion(assert_doubles(S_centroid(1,2), 0.054087, epsilon)); + CGAL_assertion(assert_doubles(S_centroid(2,0), -0.630234, epsilon)); + CGAL_assertion(assert_doubles(S_centroid(2,1), 0.581624, epsilon)); + CGAL_assertion(assert_doubles(S_centroid(2,2), 0.514314, epsilon)); + +} @@ -135,6 +165,7 @@ int main() test_qr_factorization(); test_fitness_function(); test_simplex_operations(); + test_centroid(); return 0; } From 3e732160923196ad6b8ee0e06a6b02c6eaf6c4e1 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Mon, 23 Apr 2018 14:39:03 +0200 Subject: [PATCH 005/150] population class --- .../CGAL/Optimal_bounding_box/population.h | 126 ++++++++++++++++++ .../test_linear_algebra_functions.cpp | 19 +++ 2 files changed, 145 insertions(+) create mode 100644 Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h new file mode 100644 index 00000000000..a5418acc663 --- /dev/null +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -0,0 +1,126 @@ +// Copyright (c) 2018 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Konstantinos Katrioplas + +#ifndef CGAL_OPTIMAL_BOUNDING_BOX_POPULATION_H +#define CGAL_OPTIMAL_BOUNDING_BOX_POPULATION_H + +#include +#include + + +namespace CGAL { + +namespace Optimal_bounding_box { + + + +template +class Population +{ + + typedef std::vector Individual; + +public: + Population(std::size_t size) : n(size) + { + // reserve pop space + pop.reserve(n); + + // create individuals + for(std::size_t i = 0 ; i < n; ++i) + { + Individual member(4); + create_individual(member); + CGAL_assertion(member.size() == 4); + pop.push_back(member); + } + } + + void show_population() + { + std::size_t id = 0; + for(const Individual i : pop) + { + CGAL_assertion(i.size() == 4); + std:: cout << "Individual: "<< id++ << std::endl; + for(const Matrix R : i) + { + std::cout << R; // eigen out + std::cout << "\n\n"; + } + + std:: cout << std:: endl; + } + } + + std::size_t size() + { + return n; + } + +private: + void create_individual(Individual& member) + { + CGAL_assertion(member.size() == 4); + + for(std::size_t i = 0; i < 4; ++i) + { + // create matrix + Matrix R(3,3); + create_simplex(R); + member[i] = R; + } + + CGAL_assertion(member.size() == 4); + } + + void create_simplex(Matrix& R) + { + CGAL_assertion(R.rows() == 3); + CGAL_assertion(R.cols() == 3); + + for(std::size_t i = 0; i < 3; ++i) + { + for(std::size_t j = 0; j < 3; ++j) + { + R(i, j) = random_generator.get_double(); + } + } + } + + + CGAL::Random random_generator; + std::size_t n; + std::vector pop; + +}; + + + +} } // end namespaces + + + + + + + +#endif //CGAL_OPTIMAL_BOUNDING_BOX_POPULATION_H diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index 53b0f355d78..3c9c7777a41 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -158,6 +159,21 @@ void test_centroid() +void test_population() +{ + + CGAL::Optimal_bounding_box::Population pop(5); + + //pop.show_population(); + + CGAL_assertion(pop.size() == 5); + + + +} + + + int main() { @@ -167,5 +183,8 @@ int main() test_simplex_operations(); test_centroid(); + test_population(); + + return 0; } From 704c3b77c653c6fa79efc9753b7e31786e9949ba Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Tue, 24 Apr 2018 14:53:52 +0200 Subject: [PATCH 006/150] nelder-mead algorithm --- .../Optimal_bounding_box/fitness_function.h | 2 +- .../Optimal_bounding_box/linear_algebra.h | 16 +- .../optimization_algorithms.h | 180 ++++++++++++++++++ .../CGAL/Optimal_bounding_box/population.h | 19 ++ .../test/Optimal_bounding_box/CMakeLists.txt | 1 + .../test_linear_algebra_functions.cpp | 16 +- .../test_optimization_algorithms.cpp | 127 ++++++++++++ 7 files changed, 337 insertions(+), 24 deletions(-) create mode 100644 Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h create mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 1f9a5b7372f..93f7b12e9f5 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -30,7 +30,7 @@ namespace CGAL { namespace Optimal_bounding_box { template -const double compute_fitness(Matrix& R, Matrix& data) +const double compute_fitness(const Matrix& R, const Matrix& data) { // R: rotation matrix diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h index 641b81302b6..121e0124ebf 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h @@ -38,7 +38,7 @@ void qr_factorization(Matrix& A, Matrix& Q) } template -const Matrix reflection(Matrix& S_centroid, Matrix& S_worst) +const Matrix reflection(const Matrix& S_centroid, const Matrix& S_worst) { CGAL_assertion(S_centroid.rows() == 3); CGAL_assertion(S_centroid.rows() == 3); @@ -49,7 +49,7 @@ const Matrix reflection(Matrix& S_centroid, Matrix& S_worst) } template -const Matrix expansion(Matrix& S_centroid, Matrix& S_worst, Matrix& S_reflection) +const Matrix expansion(const Matrix& S_centroid, const Matrix& S_worst, const Matrix& S_reflection) { CGAL_assertion(S_centroid.rows() == 3); CGAL_assertion(S_centroid.rows() == 3); @@ -62,15 +62,15 @@ const Matrix expansion(Matrix& S_centroid, Matrix& S_worst, Matrix& S_reflection } template -const Matrix constraction(Matrix& S_centroid, Matrix& S_worst) +Matrix mean(const Matrix& m1, const Matrix& m2) // mean { // same API for reduction - CGAL_assertion(S_centroid.rows() == 3); - CGAL_assertion(S_centroid.rows() == 3); - CGAL_assertion(S_worst.cols() == 3); - CGAL_assertion(S_worst.cols() == 3); + CGAL_assertion(m1.rows() == 3); + CGAL_assertion(m1.rows() == 3); + CGAL_assertion(m2.cols() == 3); + CGAL_assertion(m2.cols() == 3); - Matrix contract = 0.5 * S_centroid + 0.5 * S_worst; + Matrix contract = 0.5 * m1 + 0.5 * m2; Matrix Q; qr_factorization(contract, Q); double det = Q.determinant(); diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h new file mode 100644 index 00000000000..8e02c925125 --- /dev/null +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h @@ -0,0 +1,180 @@ +// Copyright (c) 2018 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Konstantinos Katrioplas + +#ifndef CGAL_OPTIMAL_BOUNDING_BOX_OPTIMIZATION_ALGORITHMS_H +#define CGAL_OPTIMAL_BOUNDING_BOX_OPTIMIZATION_ALGORITHMS_H + +#include +#include +#include + +#include +#include + + +namespace CGAL { + +namespace Optimal_bounding_box { + + +template +struct Comparator +{ + Comparator(std::vector in) : fitness(in) {} + + inline bool operator() (std::size_t& i, std::size_t& j) + { + return fitness[i] < fitness[j]; + } + + std::vector fitness; +}; + + + +// points: point coords +// simplex: 4 roation matrices are its vertices +template +void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_iterations) +{ + + CGAL_assertion(simplex.size() == 4); // tetrahedron + + std::vector fitness(4); + std::vector indices( boost::counting_iterator( 0 ), + boost::counting_iterator( simplex.size() ) ); + + + for(std::size_t t = 0; t < nb_iterations; ++t) + { + + for(int i = 0; i < 4; ++i) + { + fitness[i] = compute_fitness(simplex[i], points); + } + + /* + for(const Matrix& v : simplex) + fitness.push_back(compute_fitness(v, points)); + */ + CGAL_assertion(fitness.size() == 4); + CGAL_assertion(indices.size() == 4); + + + // get indices of sorted sequence + Comparator compare_indices(fitness); + std::sort(indices.begin(), indices.end(), compare_indices); + + + /* + for(int i =0 ; i < 4; ++i) + { + std::cout << simplex[i] << "\n"; + std::cout << "fitness= " << fitness[i] << "\n"; + std::cout << "index= " << indices[i] << "\n\n"; + } + std::cout << std::endl; + */ + + + // new sorted simplex & fitness + std::vector s_simplex(4); + std::vector s_fitness(4); + for(int i = 0; i < 4; ++i) + { + s_simplex[i] = simplex[indices[i]]; + s_fitness[i] = fitness[indices[i]]; + } + + simplex = s_simplex; // swap? + fitness = s_fitness; + + // centroid + const Matrix v_centroid = centroid(simplex[0], simplex[1], simplex[2]); + + // find worst's vertex reflection + const Matrix v_worst = simplex[3]; + const Matrix v_refl = reflection(v_centroid, v_worst); + const double f_refl = compute_fitness(v_refl, points); + + if(f_refl < fitness[2]) + { + if(f_refl >= fitness[0]) // if reflected point is not better than the best + { + // do reflection + simplex[3] = v_refl; + } + else + { + // expansion + const Matrix v_expand = expansion(v_centroid, v_worst, v_refl); + const double f_expand = compute_fitness(v_expand, points); + if(f_expand < f_refl) + simplex[3] = v_expand; + else + simplex[3] = v_refl; + } + } + else // if reflected vertex is not better + { + const Matrix v_mean = mean(v_centroid, v_worst); + const double f_mean = compute_fitness(v_mean, points); + if(f_mean <= fitness[3]) + // contraction of worst + simplex[3] = v_mean; + else + { + // reduction: move all vertices towards the best + for(int i=1; i < 4; ++i) + { + simplex[i] = mean(simplex[i], simplex[0]); // todo: test order of addition + } + } + } + + CGAL_assertion(simplex.size() == 4); // tetrahedron + + + } // iterations + + + + +} + + + + + + + + + + +} } // end namespaces + + + + + + + +#endif //CGAL_OPTIMAL_BOUNDING_BOX_OPTIMIZATION_ALGORITHMS_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index a5418acc663..375021b0768 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -25,6 +25,8 @@ #include #include +#include + namespace CGAL { @@ -76,7 +78,24 @@ public: return n; } + + // access individual + Individual& operator[](std::size_t i) + { + CGAL_assertion(i < n); + return pop[i]; + } + + const Individual& operator[](std::size_t i) const + { + CGAL_assertion(i < n); + return pop[i]; + } + + private: + + // create random population void create_individual(Individual& member) { CGAL_assertion(member.size() == 4); diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt index 378a96457e6..57c961df417 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt +++ b/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt @@ -53,6 +53,7 @@ if (EIGEN3_FOUND) include( ${EIGEN3_USE_FILE} ) create_single_source_cgal_program("test_linear_algebra_functions.cpp") + create_single_source_cgal_program("test_optimization_algorithms.cpp") endif(EIGEN3_FOUND) diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index 3c9c7777a41..bfb618d7731 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -112,7 +112,7 @@ void test_simplex_operations() -0.653011, -0.755415, 0.054087, -0.630234, 0.581624, 0.514314; - MatrixXf S_c = CGAL::Optimal_bounding_box::constraction(S_a, S_b); + MatrixXf S_c = CGAL::Optimal_bounding_box::mean(S_a, S_b); CGAL_assertion(assert_doubles(S_c(0,0), -0.35111, epsilon)); CGAL_assertion(assert_doubles(S_c(0,1), 0.79308, epsilon)); CGAL_assertion(assert_doubles(S_c(0,2), -0.49774, epsilon)); @@ -159,19 +159,6 @@ void test_centroid() -void test_population() -{ - - CGAL::Optimal_bounding_box::Population pop(5); - - //pop.show_population(); - - CGAL_assertion(pop.size() == 5); - - - -} - @@ -183,7 +170,6 @@ int main() test_simplex_operations(); test_centroid(); - test_population(); return 0; diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp new file mode 100644 index 00000000000..7504038a3de --- /dev/null +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -0,0 +1,127 @@ +#include +#include + +#include +#include + +#include +#include + +#include + + +typedef Eigen::MatrixXf MatrixXf; + +bool assert_doubles(double d1, double d2, double epsilon) +{ + return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; +} + + +void test_population() +{ + + CGAL::Optimal_bounding_box::Population pop(5); + + //pop.show_population(); + + CGAL_assertion(pop.size() == 5); +} + +void test_nelder_mead() +{ + + MatrixXf data_points(4, 3); + data_points << 0.866802, 0.740808, 0.895304, + 0.912651, 0.761565, 0.160330, + 0.093661, 0.892578, 0.737412, + 0.166461, 0.149912, 0.364944; + + // one simplex + std::vector simplex(4); + + MatrixXf v0(3, 3); + v0 << -0.2192721, 0.2792986, -0.9348326, + -0.7772152, -0.6292092, -0.0056861, + -0.5897934, 0.7253193, 0.3550431; + + MatrixXf v1(3, 3); + v1 << -0.588443, 0.807140, -0.047542, + -0.786228, -0.584933, -0.199246, + -0.188629, -0.079867, 0.978795; + + MatrixXf v2(3, 3); + v2 << -0.277970, 0.953559, 0.116010, + -0.567497, -0.065576, -0.820760, + -0.775035, -0.293982, 0.559370; + + MatrixXf v3(3, 3); + v3 << -0.32657, -0.60013, -0.73020, + -0.20022, -0.71110, 0.67398, + -0.92372, 0.36630, 0.11207; + + simplex[0] = v0; + simplex[1] = v1; + simplex[2] = v2; + simplex[3] = v3; + + std::size_t iterations = 19; + CGAL::Optimal_bounding_box::nelder_mead(simplex, data_points, iterations); + + double epsilon = 1e-5; + + MatrixXf v0_new = simplex[0]; + CGAL_assertion(assert_doubles(v0_new(0,0), -0.288975, epsilon)); + CGAL_assertion(assert_doubles(v0_new(0,1), 0.7897657, epsilon)); + CGAL_assertion(assert_doubles(v0_new(0,2), -0.541076, epsilon)); + CGAL_assertion(assert_doubles(v0_new(1,0), -0.9407046, epsilon)); + CGAL_assertion(assert_doubles(v0_new(1,1), -0.3391466, epsilon)); + CGAL_assertion(assert_doubles(v0_new(1,2), 0.0073817, epsilon)); + CGAL_assertion(assert_doubles(v0_new(2,0), -0.1776743, epsilon)); + CGAL_assertion(assert_doubles(v0_new(2,1), 0.5111260, epsilon)); + CGAL_assertion(assert_doubles(v0_new(2,2), 0.84094, epsilon)); + + MatrixXf v1_new = simplex[1]; + CGAL_assertion(assert_doubles(v1_new(0,0), -0.458749, epsilon)); + CGAL_assertion(assert_doubles(v1_new(0,1), 0.823283, epsilon)); + CGAL_assertion(assert_doubles(v1_new(0,2), -0.334296, epsilon)); + CGAL_assertion(assert_doubles(v1_new(1,0), -0.885235, epsilon)); + CGAL_assertion(assert_doubles(v1_new(1,1), -0.455997, epsilon)); + CGAL_assertion(assert_doubles(v1_new(1,2), 0.091794, epsilon)); + CGAL_assertion(assert_doubles(v1_new(2,0), -0.076866, epsilon)); + CGAL_assertion(assert_doubles(v1_new(2,1), 0.338040, epsilon)); + CGAL_assertion(assert_doubles(v1_new(2,2), 0.937987, epsilon)); + + MatrixXf v2_new = simplex[2]; + CGAL_assertion(assert_doubles(v2_new(0,0), -0.346582, epsilon)); + CGAL_assertion(assert_doubles(v2_new(0,1), 0.878534, epsilon)); + CGAL_assertion(assert_doubles(v2_new(0,2), -0.328724, epsilon)); + CGAL_assertion(assert_doubles(v2_new(1,0), -0.936885, epsilon)); + CGAL_assertion(assert_doubles(v2_new(1,1), -0.341445, epsilon)); + CGAL_assertion(assert_doubles(v2_new(1,2), 0.075251, epsilon)); + CGAL_assertion(assert_doubles(v2_new(2,0), -0.046131, epsilon)); + CGAL_assertion(assert_doubles(v2_new(2,1), 0.334057, epsilon)); + CGAL_assertion(assert_doubles(v2_new(2,2), 0.941423, epsilon)); + + MatrixXf v3_new = simplex[3]; + CGAL_assertion(assert_doubles(v3_new(0,0), -0.394713, epsilon)); + CGAL_assertion(assert_doubles(v3_new(0,1), 0.791782, epsilon)); + CGAL_assertion(assert_doubles(v3_new(0,2), -0.466136, epsilon)); + CGAL_assertion(assert_doubles(v3_new(1,0), -0.912112, epsilon)); + CGAL_assertion(assert_doubles(v3_new(1,1), -0.398788, epsilon)); + CGAL_assertion(assert_doubles(v3_new(1,2), 0.094972, epsilon)); + CGAL_assertion(assert_doubles(v3_new(2,0), -0.110692, epsilon)); + CGAL_assertion(assert_doubles(v3_new(2,1), 0.462655, epsilon)); + CGAL_assertion(assert_doubles(v3_new(2,2), 0.879601, epsilon)); + +} + + +int main() +{ + test_population(); + test_nelder_mead(); + + + return 0; +} From efbb1be89078b16a47ed706338e1e1b4a913cf2c Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Wed, 25 Apr 2018 12:29:04 +0200 Subject: [PATCH 007/150] genetic algorithm --- .../optimization_algorithms.h | 154 ++++++++++++++++++ .../CGAL/Optimal_bounding_box/population.h | 11 +- .../test_optimization_algorithms.cpp | 21 +++ 3 files changed, 184 insertions(+), 2 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h index 8e02c925125..4742c7a4bce 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h @@ -23,11 +23,13 @@ #define CGAL_OPTIMAL_BOUNDING_BOX_OPTIMIZATION_ALGORITHMS_H #include +#include #include #include #include #include +#include namespace CGAL { @@ -155,7 +157,141 @@ void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_it } // iterations +} +struct Random_int_generator +{ + Random_int_generator(int l, int h) : low(l), high(h) {} + + int operator() () + { + return random_gen.get_int(low, high); + } + + CGAL::Random random_gen; + int low; + int high; +}; + + +template +void genetic_algorithm(Population& pop, Simplex& points) +{ + // random permutations + std::size_t m = pop.size(); + + //groups 1,2 : size m/2 groups 3,4 : size (m - m/2). m/2 is floored + std::size_t size_first_group = m/2; + std::size_t size_second_group = m - m/2; + + std::vector ids1(m/2), ids2(m/2); + std::vector ids3(m - m/2), ids4(m - m/2); + + CGAL::Random rng; + + //Random_int_generator rgen(0, m); + //std::generate(indices.begin(), indices.end(), rgen); + + std::generate(ids1.begin(), ids1.end(), + [&rng, &m] () + { return rng.get_int(0, m); }); + + std::generate(ids2.begin(), ids2.end(), + [&rng, &m] () + { return rng.get_int(0, m); }); + + std::generate(ids3.begin(), ids3.end(), + [&rng, &m] () + { return rng.get_int(0, m); }); + + std::generate(ids4.begin(), ids4.end(), + [&rng, &m] () + { return rng.get_int(0, m); }); + + + Population group1(m/2), group2(m/2); + Population group3(m - m/2), group4(m - m/2); + + for(std::size_t i = 0; i < ids1.size(); ++i) + group1[i] = pop[ids1[i]]; + + for(std::size_t i = 0; i < ids2.size(); ++i) + group2[i] = pop[ids2[i]]; + + for(std::size_t i = 0; i < ids3.size(); ++i) + group3[i] = pop[ids3[i]]; + + for(std::size_t i = 0; i < ids4.size(); ++i) + group4[i] = pop[ids4[i]]; + + + + + // crossover I + Population offspringsA(size_first_group); + double bias = 0.1; + + for(int i = 0; i < size_first_group; ++i) + { + std::vector offspring(4); + for(int j = 0; j < 4; ++j) + { + double r = rng.get_double(); + double fitnessA = compute_fitness(group1[i][j], points); + double fitnessB = compute_fitness(group2[i][j], points); + double threshold; + if(fitnessA < fitnessB) + threshold = 0.5 + bias; + else + threshold = 0.5 - bias; + if(r < threshold) // choose A + offspring[j] = group1[i][j]; + else // choose B + offspring[j] = group2[i][j]; + } + offspringsA[i] = offspring; + } + + + // crossover II + Population offspringsB(size_second_group); + bias = 0.1; + + for(int i = 0; i < size_second_group; ++i) + { + std::vector offspring(4); + for(int j = 0; j < 4; ++j) + { + double fitnessA = compute_fitness(group3[i][j], points); + double fitnessB = compute_fitness(group4[i][j], points); + double lambda; + if(fitnessA < fitnessB) + lambda = 0.5 + bias; + else + lambda = 0.5 - bias; + // combine information from A and B + offspring[j] = lambda * group3[i][j] + lambda * group4[i][j]; + + } + offspringsB[i] = offspring; + } + + + CGAL_assertion(offspringsA.size() == size_first_group); + CGAL_assertion(offspringsB.size() == size_second_group); + CGAL_assertion(offspringsA.size() + offspringsB.size() == pop.size()); + + + // next generatrion + for(std::size_t i = 0; i < size_first_group; ++i) + { + pop[i] = offspringsA[i]; + } + + for(std::size_t i = 0; i < size_second_group; ++i) + { + pop[size_first_group + i] = offspringsB[i]; + } } @@ -163,6 +299,24 @@ void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_it +template +void find_global_minimum(Population& pop, Simplex points) +{ + + genetic_algorithm(pop, points); + + std::size_t nelder_mead_iterations = 1; + + for(Simplex s : pop) + nelder_mead(s, points, nelder_mead_iterations); + + //optional random mutations + + +} + + + diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index 375021b0768..2d952554602 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -26,6 +26,7 @@ #include #include +#include namespace CGAL { @@ -41,8 +42,10 @@ class Population typedef std::vector Individual; public: - Population(std::size_t size) : n(size) + Population(std::size_t size) : n(size), random_generator(CGAL::Random(1)) { + //std::cout << "seed= " << random_generator.get_seed() << std::endl; + // reserve pop space pop.reserve(n); @@ -105,7 +108,9 @@ private: // create matrix Matrix R(3,3); create_simplex(R); - member[i] = R; + Matrix Q; + qr_factorization(R, Q); + member[i] = Q; } CGAL_assertion(member.size() == 4); @@ -126,6 +131,8 @@ private: } + + CGAL::Random random_generator; std::size_t n; std::vector pop; diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 7504038a3de..696b7ea2486 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -116,11 +116,32 @@ void test_nelder_mead() } +void test_genetic_algorithm() +{ + + MatrixXf data_points(4, 3); + data_points << 0.866802, 0.740808, 0.895304, + 0.912651, 0.761565, 0.160330, + 0.093661, 0.892578, 0.737412, + 0.166461, 0.149912, 0.364944; + + CGAL::Optimal_bounding_box::Population pop(5); + CGAL::Optimal_bounding_box::genetic_algorithm(pop, data_points); + CGAL_assertion(pop.size() == 5); +} + + int main() { test_population(); test_nelder_mead(); + test_genetic_algorithm(); + + + + + return 0; From 1ef55a86f8850b9a4cd327541349f3325d4678a4 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Wed, 25 Apr 2018 14:45:19 +0200 Subject: [PATCH 008/150] visualization --- .../include/CGAL/Optimal_bounding_box/obb.h | 102 ++++++++++++++++++ .../optimization_algorithms.h | 16 --- .../test_optimization_algorithms.cpp | 17 +++ 3 files changed, 119 insertions(+), 16 deletions(-) create mode 100644 Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h new file mode 100644 index 00000000000..f2661db44f9 --- /dev/null +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -0,0 +1,102 @@ +// Copyright (c) 2018 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Konstantinos Katrioplas + +#ifndef CGAL_OBB_H +#define CGAL_OBB_H + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace CGAL { +namespace Optimal_bounding_box { + + + +template +void find_global_minimum(Population& pop, Simplex points) +{ + + genetic_algorithm(pop, points); + + std::size_t nelder_mead_iterations = 1; + + for(Simplex s : pop) + nelder_mead(s, points, nelder_mead_iterations); + + //optional random mutations +} + + +template +void visualize_obb(Simplex data_points) +{ + + + typedef CGAL::Simple_cartesian K; + typedef K::Point_3 Point; + typedef CGAL::Surface_mesh Mesh; + + // Simplex -> std::vector + std::vector points; + + for(int i = 0; i < data_points.rows(); ++i) + { + Point p(data_points(i, 0), data_points(i, 1), data_points(i, 2)); + points.push_back(p); + } + + + CGAL::Bbox_3 bbox; + bbox = bbox_3(points.begin(), points.end()); + K::Iso_cuboid_3 ic(bbox); + + Mesh mesh; + CGAL::make_hexahedron(ic[0], ic[1], ic[2], ic[3], ic[4], ic[5], ic[6], ic[7], mesh); + + std::ofstream out("/tmp/box.off"); + out << mesh; + out.close(); + + +} + + + + + +}} // end namespaces + + + + + + +#endif //CGAL_OBB_H + + + diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h index 4742c7a4bce..4bc152a72db 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h @@ -299,22 +299,6 @@ void genetic_algorithm(Population& pop, Simplex& points) -template -void find_global_minimum(Population& pop, Simplex points) -{ - - genetic_algorithm(pop, points); - - std::size_t nelder_mead_iterations = 1; - - for(Simplex s : pop) - nelder_mead(s, points, nelder_mead_iterations); - - //optional random mutations - - -} - diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 696b7ea2486..78c00d2032f 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -130,6 +131,19 @@ void test_genetic_algorithm() CGAL_assertion(pop.size() == 5); } +void test_visualization() +{ + MatrixXf data_points(4, 3); + data_points << 0.866802, 0.740808, 0.895304, + 0.912651, 0.761565, 0.160330, + 0.093661, 0.892578, 0.737412, + 0.166461, 0.149912, 0.364944; + + + CGAL::Optimal_bounding_box::visualize_obb(data_points); + + +} int main() @@ -139,6 +153,9 @@ int main() test_genetic_algorithm(); + test_visualization(); + + From ea994650ec087a66334917128878cd2ae5b1330e Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Thu, 26 Apr 2018 14:22:45 +0200 Subject: [PATCH 009/150] it works! --- .../Optimal_bounding_box/fitness_function.h | 57 +++++- .../Optimal_bounding_box/linear_algebra.h | 12 ++ .../include/CGAL/Optimal_bounding_box/obb.h | 168 ++++++++++++++++-- .../optimization_algorithms.h | 39 ++++ .../CGAL/Optimal_bounding_box/population.h | 5 +- .../test/Optimal_bounding_box/data/tetra3.off | 12 ++ .../test_optimization_algorithms.cpp | 132 +++++++++++++- 7 files changed, 401 insertions(+), 24 deletions(-) create mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/data/tetra3.off diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 93f7b12e9f5..6b2cd7b5bb5 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -24,7 +24,8 @@ #include #include - +#include +#include namespace CGAL { namespace Optimal_bounding_box { @@ -40,8 +41,6 @@ const double compute_fitness(const Matrix& R, const Matrix& data) CGAL_assertion(data.cols() == 3); CGAL_assertion(data.rows() >= 3); - CGAL_assertion(R.rows() == data.cols()); - // rotate points Matrix RT = R.transpose(); Matrix rotated_data = data * RT; @@ -56,7 +55,7 @@ const double compute_fitness(const Matrix& R, const Matrix& data) double zmin = rotated_data.col(2).minCoeff(); double zmax = rotated_data.col(2).maxCoeff(); - double x_dim = abs(xmax - xmin); + double x_dim = abs(xmax - xmin); // abs needed? double y_dim = abs(ymax - ymin); double z_dim = abs(zmax - zmin); @@ -65,6 +64,56 @@ const double compute_fitness(const Matrix& R, const Matrix& data) } +template +struct Fitness_map // -> a free function +{ + Fitness_map(Population& p, Matrix& points) : pop(p), points(points) + {} + + Matrix get_best() + { + std::size_t count_vertices = 0; + + std::size_t simplex_id; + std::size_t vertex_id; + double best_fitness = std::numeric_limits::max(); + for(std::size_t i = 0; i < pop.size(); ++i) + { + const std::vector simplex = pop[i]; + for(std::size_t j =0; j < 4; ++j) + { + const Matrix vertex = simplex[j]; + //std::cout << "i= "<< i << " j=" << j<<"\n vertex= " << vertex << std::endl; + ++count_vertices; + //std::cout << "vertex = " << vertex << std::endl; + + const double fitness = compute_fitness(vertex, points); + //std::cout << "fitness = " << fitness << std::endl; + if (fitness < best_fitness) + { + simplex_id = i; + vertex_id = j; + best_fitness = fitness; + std::cout << "best fitness = " << best_fitness << std::endl; + } + + } + } + + std::vector best_simplex = pop[simplex_id]; + Matrix temp = best_simplex[vertex_id]; + + return temp; + } + + + const Matrix points; + Population pop; +}; + + + + diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h index 121e0124ebf..d78eda5fc31 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h @@ -24,6 +24,7 @@ #include #include +#include namespace CGAL { @@ -37,6 +38,17 @@ void qr_factorization(Matrix& A, Matrix& Q) Q = qr.householderQ(); } +template +void qr_factorization(std::vector& Simplex) +{ + for(int i = 0; i < Simplex.size(); ++i) + { + Eigen::HouseholderQR qr(Simplex[i]); + Matrix Q = qr.householderQ(); + Simplex[i] = Q; + } +} + template const Matrix reflection(const Matrix& S_centroid, const Matrix& S_worst) { diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index f2661db44f9..cd90c110f12 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -23,6 +23,7 @@ #define CGAL_OBB_H #include +#include #include #include #include @@ -37,25 +38,56 @@ namespace Optimal_bounding_box { -template -void find_global_minimum(Population& pop, Simplex points) +template +void evolution(Matrix& R, Matrix& points) { + std::size_t generations = 7; + std::size_t nelder_mead_iterations = 20; - genetic_algorithm(pop, points); + Population pop(50); - std::size_t nelder_mead_iterations = 1; + //std::cout << "initial pop" << std::endl; + //pop.show_population(); + //std::cout << std::endl; + //std::cin.get(); - for(Simplex s : pop) - nelder_mead(s, points, nelder_mead_iterations); + for(std::size_t t = 0; t < generations; ++t) + { + genetic_algorithm(pop, points); + + //std::cout << "pop after genetic" << std::endl; + // pop.show_population(); + // std::cout << std::endl; + //std::cin.get(); + + + for(std::size_t s = 0; s < pop.size(); ++s) + nelder_mead(pop[s], points, nelder_mead_iterations); + + //std::cout << "pop after nelder mead: " << std::endl; + //pop.show_population(); + //std::cout << std::endl; + //std::cin.get(); + + + // debugging + Fitness_map fitness_map(pop, points); + Matrix R_now = fitness_map.get_best(); + std::cout << "det= " << R_now.determinant() << std::endl; + + } + + // compute fitness of entire population + Fitness_map fitness_map(pop, points); + R = fitness_map.get_best(); - //optional random mutations } -template -void visualize_obb(Simplex data_points) -{ +template +void visualize_obb(Simplex data_points, std::string filename) +{ typedef CGAL::Simple_cartesian K; typedef K::Point_3 Point; @@ -78,13 +110,127 @@ void visualize_obb(Simplex data_points) Mesh mesh; CGAL::make_hexahedron(ic[0], ic[1], ic[2], ic[3], ic[4], ic[5], ic[6], ic[7], mesh); - std::ofstream out("/tmp/box.off"); + std::ofstream out(filename); out << mesh; out.close(); } +template +void find_and_rotate_aabb(SurfaceMesh& sm, Matrix& R, Matrix& OBB) +{ + // get vector + typedef typename boost::property_map::const_type Vpm; + typedef typename boost::property_traits::value_type Point; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + Vpm vpm = get(boost::vertex_point, sm); + + std::vector points; + points.resize(vertices(sm).size()); + std::size_t i = 0; + for(vertex_descriptor v : vertices(sm)) + { + Point p = get(vpm, v); + points[i] = p; + ++i; + } + + CGAL_assertion(points.size() == vertices(sm).size()); + + + // get AABB + typedef CGAL::Simple_cartesian K; + CGAL::Bbox_3 bbox; + bbox = bbox_3(points.begin(), points.end()); + K::Iso_cuboid_3 ic(bbox); + + + + // rotate AABB -> OBB + Matrix aabb(8,3); //hexahedron + for(int i = 0; i < 8; ++i) + { + aabb(i, 0) = ic[i].x(); + aabb(i, 1) = ic[i].y(); + aabb(i, 2) = ic[i].z(); + } + + + + OBB = aabb * R.transpose(); + CGAL_assertion(OBB.cols() == aabb.cols()); + CGAL_assertion(OBB.rows() == aabb.rows()); + + //std::cout << OBB << std::endl; +} + + +template +void post_processing(Matrix& points, Matrix& R, Matrix& obb) +{ + + // 1) rotate points with R + + Matrix rotated_points(points.rows(), points.cols()); + rotated_points = points * R.transpose(); + + // 2) get AABB from rotated points + + typedef CGAL::Simple_cartesian K; + typedef K::Point_3 Point; + std::vector v_points; // Simplex -> std::vector + for(int i = 0; i < rotated_points.rows(); ++i) + { + Point p(rotated_points(i, 0), rotated_points(i, 1), rotated_points(i, 2)); + v_points.push_back(p); + } + CGAL::Bbox_3 bbox; + bbox = bbox_3(v_points.begin(), v_points.end()); + K::Iso_cuboid_3 ic(bbox); + + Matrix aabb(8, 3); + for(int i = 0; i < 8; ++i) + { + aabb(i, 0) = ic[i].x(); + aabb(i, 1) = ic[i].y(); + aabb(i, 2) = ic[i].z(); + } + + // 3) apply inverse rotation to rotated AABB + + obb = aabb * R; + + +} + +template +void matrix_to_mesh_and_draw(Matrix& data_points, std::string filename) +{ + + typedef CGAL::Simple_cartesian K; + typedef K::Point_3 Point; + typedef CGAL::Surface_mesh Mesh; + + // Simplex -> std::vector + std::vector points; + + for(int i = 0; i < data_points.rows(); ++i) + { + Point p(data_points(i, 0), data_points(i, 1), data_points(i, 2)); + points.push_back(p); + } + + + Mesh mesh; + CGAL::make_hexahedron(points[0], points[1], points[2], points[3], points[4], points[5], + points[6], points[7], mesh); + + std::ofstream out(filename); + out << mesh; + out.close(); + +} diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h index 4bc152a72db..980b6c10491 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h @@ -226,6 +226,13 @@ void genetic_algorithm(Population& pop, Simplex& points) + /* + check_det(group1); + check_det(group2); + check_det(group3); + check_det(group4); + */ + // crossover I Population offspringsA(size_first_group); @@ -253,6 +260,14 @@ void genetic_algorithm(Population& pop, Simplex& points) } + /* + std::cout << "offspringsA: \n" ; + check_det(offspringsA); + std::cin.get(); + */ + + + // crossover II Population offspringsB(size_second_group); bias = 0.1; @@ -273,10 +288,22 @@ void genetic_algorithm(Population& pop, Simplex& points) offspring[j] = lambda * group3[i][j] + lambda * group4[i][j]; } + + // qr factorization of the offspring + qr_factorization(offspring); offspringsB[i] = offspring; } + + + /* + std::cout << "offspringsB: \n" ; + check_det(offspringsB); + std::cin.get(); + */ + + CGAL_assertion(offspringsA.size() == size_first_group); CGAL_assertion(offspringsB.size() == size_second_group); CGAL_assertion(offspringsA.size() + offspringsB.size() == pop.size()); @@ -297,6 +324,18 @@ void genetic_algorithm(Population& pop, Simplex& points) } +template +void check_det(Population& pop) +{ + for(int i = 0; i < pop.size(); ++i) + { + for(int j = 0; j < 4; ++j) + { + auto A = pop[i][j]; + std::cout << A.determinant() << std::endl; + } + } +} diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index 2d952554602..76231016eba 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -82,7 +82,7 @@ public: } - // access individual + // access simplex Individual& operator[](std::size_t i) { CGAL_assertion(i < n); @@ -95,7 +95,6 @@ public: return pop[i]; } - private: // create random population @@ -132,6 +131,8 @@ private: + Individual somebody; //temp + CGAL::Random random_generator; std::size_t n; diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/data/tetra3.off b/Optimal_bounding_box/test/Optimal_bounding_box/data/tetra3.off new file mode 100644 index 00000000000..d83aa004308 --- /dev/null +++ b/Optimal_bounding_box/test/Optimal_bounding_box/data/tetra3.off @@ -0,0 +1,12 @@ +OFF +4 4 0 + +0 1 0 +1 0 0 +0 0 0 +0 0 1 +3 0 1 2 +3 2 3 0 +3 1 3 2 +3 0 3 1 + diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 78c00d2032f..a29b7c092eb 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -13,6 +13,9 @@ typedef Eigen::MatrixXf MatrixXf; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + + bool assert_doubles(double d1, double d2, double epsilon) { return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; @@ -131,29 +134,144 @@ void test_genetic_algorithm() CGAL_assertion(pop.size() == 5); } -void test_visualization() + + + +void find_obb() { - MatrixXf data_points(4, 3); + + MatrixXf data_points(4, 3); // there are on the convex hull data_points << 0.866802, 0.740808, 0.895304, 0.912651, 0.761565, 0.160330, 0.093661, 0.892578, 0.737412, 0.166461, 0.149912, 0.364944; - CGAL::Optimal_bounding_box::visualize_obb(data_points); + CGAL::Optimal_bounding_box::visualize_obb(data_points, "/tmp/original.off"); + + + MatrixXf rotation(3, 3); + CGAL::Optimal_bounding_box::evolution(rotation, data_points); + + // rotate + MatrixXf rotated_points(4, 3); + rotated_points = data_points * rotation.transpose(); + + CGAL_assertion(rotated_points.cols() == data_points.cols()); + CGAL_assertion(rotated_points.rows() == data_points.rows()); + + std::cout << "rotation matrix= \n" << rotation << std::endl << std::endl; + std::cout << "rotated_points= \n" << rotated_points << std::endl; + + CGAL::Optimal_bounding_box::visualize_obb(rotated_points, "/tmp/rotated.off"); } + + +template +void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) +{ + typedef typename boost::property_map::const_type Vpm; + typedef typename boost::property_traits::reference Point_ref; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + Vpm vpm = get(boost::vertex_point, sm); + + mat.resize(vertices(sm).size(), 3); + std::size_t i = 0; + for(vertex_descriptor v : vertices(sm)) + { + Point_ref p = get(vpm, v); + mat(i, 0) = p.x(); + mat(i, 1) = p.y(); + mat(i, 2) = p.z(); + ++i; + } +} + + +void test_tetrahedron(const char* fname) +{ + std::ifstream input(fname); + CGAL::Surface_mesh mesh; + if (!input || !(input >> mesh) || mesh.is_empty()) { + std::cerr << fname << " is not a valid off file.\n"; + exit(1); + } + + // points in a matrix + MatrixXf points; + sm_to_matrix(mesh, points); + + MatrixXf R(3, 3); + CGAL::Optimal_bounding_box::evolution(R, points); + std:: cout << "R= " << R << std::endl; + std:: cout << "det(evolution)= " << R.determinant() << std::endl; + + // postprocessing + MatrixXf obb(8, 3); + CGAL::Optimal_bounding_box::post_processing(points, R, obb); + CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, "data/OBB.off"); + + +} + + +void rotate_tetrahedron(const char* fname, const char* Rname) +{ + + std::ifstream input(fname); + CGAL::Surface_mesh mesh; + if (!input || !(input >> mesh) || mesh.is_empty()) { + std::cerr << fname << " is not a valid off file.\n"; + exit(1); + } + + MatrixXf R(3, 3); + std::ifstream input_R(Rname); + double x, y, z; + std::size_t i = 0; + while (input_R >> x >> y >> z) + { + R(i, 0) = x; + R(i, 1) = y; + R(i, 2) = z; + ++i; + } + std:: cout << "det(benchmark)= " << R.determinant() << std::endl; + + + // points in a matrix + MatrixXf points; + sm_to_matrix(mesh, points); + + // just rotate once + //MatrixXf rotated_points = points * R.transpose(); + //CGAL::Optimal_bounding_box::visualize_obb(rotated_points, "data/rotated_points_benchmark.off"); + + + // postprocessing + MatrixXf obb(8, 3); + CGAL::Optimal_bounding_box::post_processing(points, R, obb); + CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, "data/inverse_rotated.off"); + + +} + + + int main() { - test_population(); - test_nelder_mead(); - test_genetic_algorithm(); + //test_population(); + //test_nelder_mead(); + //test_genetic_algorithm(); + //find_obb(); - test_visualization(); + test_tetrahedron("data/random_tetra.off"); + //rotate_tetrahedron("data/random_tetra.off", "data/rotation.dat"); From 617051fbf51ba77ae81801f38c08fb77c955eb35 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Fri, 27 Apr 2018 13:50:53 +0200 Subject: [PATCH 010/150] tests --- .../Optimal_bounding_box/fitness_function.h | 1 - .../include/CGAL/Optimal_bounding_box/obb.h | 13 +- .../data/long_tetrahedron.off | 11 ++ .../data/random_unit_tetra.off | 11 ++ .../{tetra3.off => reference_tetrahedron.off} | 0 .../test_optimization_algorithms.cpp | 151 +++++++++++------- 6 files changed, 130 insertions(+), 57 deletions(-) create mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/data/long_tetrahedron.off create mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/data/random_unit_tetra.off rename Optimal_bounding_box/test/Optimal_bounding_box/data/{tetra3.off => reference_tetrahedron.off} (100%) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 6b2cd7b5bb5..40ceb55e45f 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -94,7 +94,6 @@ struct Fitness_map // -> a free function simplex_id = i; vertex_id = j; best_fitness = fitness; - std::cout << "best fitness = " << best_fitness << std::endl; } } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index cd90c110f12..bff18be74f7 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -39,9 +39,15 @@ namespace Optimal_bounding_box { template -void evolution(Matrix& R, Matrix& points) +void evolution(Matrix& R, Matrix& points, std::size_t generations) { - std::size_t generations = 7; + + CGAL_assertion(points.rows() >= 3); + CGAL_assertion(points.cols() = 3); + CGAL_assertion(R.rows() = 3); + CGAL_assertion(R.cols() = 3); + + std::size_t nelder_mead_iterations = 20; Population pop(50); @@ -71,9 +77,12 @@ void evolution(Matrix& R, Matrix& points) // debugging + /* Fitness_map fitness_map(pop, points); Matrix R_now = fitness_map.get_best(); std::cout << "det= " << R_now.determinant() << std::endl; + */ + } diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/data/long_tetrahedron.off b/Optimal_bounding_box/test/Optimal_bounding_box/data/long_tetrahedron.off new file mode 100644 index 00000000000..ad966ac795e --- /dev/null +++ b/Optimal_bounding_box/test/Optimal_bounding_box/data/long_tetrahedron.off @@ -0,0 +1,11 @@ +OFF +4 4 0 + +-1 -0.1 0 +-1 0.1 0 +1 0 -0.1 +1 0 0.1 +3 0 1 2 +3 2 3 0 +3 1 3 2 +3 0 3 1 \ No newline at end of file diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/data/random_unit_tetra.off b/Optimal_bounding_box/test/Optimal_bounding_box/data/random_unit_tetra.off new file mode 100644 index 00000000000..270289e2c6e --- /dev/null +++ b/Optimal_bounding_box/test/Optimal_bounding_box/data/random_unit_tetra.off @@ -0,0 +1,11 @@ +OFF +4 4 0 + +0.866802 0.740808 0.895304 +0.912651 0.761565 0.160330 +0.093661 0.892578 0.737412 +0.166461 0.149912 0.364944 +3 0 1 2 +3 2 3 0 +3 1 3 2 +3 0 3 1 \ No newline at end of file diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/data/tetra3.off b/Optimal_bounding_box/test/Optimal_bounding_box/data/reference_tetrahedron.off similarity index 100% rename from Optimal_bounding_box/test/Optimal_bounding_box/data/tetra3.off rename to Optimal_bounding_box/test/Optimal_bounding_box/data/reference_tetrahedron.off diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index a29b7c092eb..0f3fca91a30 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -21,6 +21,25 @@ bool assert_doubles(double d1, double d2, double epsilon) return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; } +template +void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) +{ + typedef typename boost::property_map::const_type Vpm; + typedef typename boost::property_traits::reference Point_ref; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + Vpm vpm = get(boost::vertex_point, sm); + + mat.resize(vertices(sm).size(), 3); + std::size_t i = 0; + for(vertex_descriptor v : vertices(sm)) + { + Point_ref p = get(vpm, v); + mat(i, 0) = p.x(); + mat(i, 1) = p.y(); + mat(i, 2) = p.z(); + ++i; + } +} void test_population() { @@ -34,7 +53,6 @@ void test_population() void test_nelder_mead() { - MatrixXf data_points(4, 3); data_points << 0.866802, 0.740808, 0.895304, 0.912651, 0.761565, 0.160330, @@ -122,7 +140,6 @@ void test_nelder_mead() void test_genetic_algorithm() { - MatrixXf data_points(4, 3); data_points << 0.866802, 0.740808, 0.895304, 0.912651, 0.761565, 0.160330, @@ -134,65 +151,53 @@ void test_genetic_algorithm() CGAL_assertion(pop.size() == 5); } - - - -void find_obb() +void test_random_unit_tetra() { - - MatrixXf data_points(4, 3); // there are on the convex hull + MatrixXf data_points(4, 3); // points on their convex hull data_points << 0.866802, 0.740808, 0.895304, 0.912651, 0.761565, 0.160330, 0.093661, 0.892578, 0.737412, 0.166461, 0.149912, 0.364944; + typedef CGAL::Simple_cartesian K; + typedef K::Point_3 Point; + typedef CGAL::Surface_mesh Mesh; - CGAL::Optimal_bounding_box::visualize_obb(data_points, "/tmp/original.off"); + // make a mesh and export it + Mesh mesh; + Point p1(0.866802, 0.740808, 0.895304); + Point p2(0.912651, 0.761565, 0.160330); + Point p3(0.093661, 0.892578, 0.737412); + Point p4(0.166461, 0.149912, 0.364944); + CGAL::make_tetrahedron(p1, p2, p3, p4, mesh); + std::ofstream out("data/random_unit_tetra.off"); + out << mesh; + out.close(); + MatrixXf R(3, 3); + std::size_t generations = 10; + CGAL::Optimal_bounding_box::evolution(R, data_points, generations); - MatrixXf rotation(3, 3); - CGAL::Optimal_bounding_box::evolution(rotation, data_points); - - // rotate - MatrixXf rotated_points(4, 3); - rotated_points = data_points * rotation.transpose(); - - CGAL_assertion(rotated_points.cols() == data_points.cols()); - CGAL_assertion(rotated_points.rows() == data_points.rows()); - - std::cout << "rotation matrix= \n" << rotation << std::endl << std::endl; - std::cout << "rotated_points= \n" << rotated_points << std::endl; - - CGAL::Optimal_bounding_box::visualize_obb(rotated_points, "/tmp/rotated.off"); + std::cout << R << std::endl; + double epsilon = 1e-5; + CGAL_assertion(assert_doubles(R.determinant(), 1, epsilon)); + CGAL_assertion(assert_doubles(R(0,0), -0.25791, epsilon)); + CGAL_assertion(assert_doubles(R(0,1), 0.796512, epsilon)); + CGAL_assertion(assert_doubles(R(0,2), -0.546855, epsilon)); + CGAL_assertion(assert_doubles(R(1,0), -0.947128, epsilon)); + CGAL_assertion(assert_doubles(R(1,1), -0.320242, epsilon)); + CGAL_assertion(assert_doubles(R(1,2), -0.0197553, epsilon)); + CGAL_assertion(assert_doubles(R(2,0), -0.190861, epsilon)); + CGAL_assertion(assert_doubles(R(2,1), 0.512847, epsilon)); + CGAL_assertion(assert_doubles(R(2,2), 0.836992, epsilon)); + MatrixXf obb(8, 3); + CGAL::Optimal_bounding_box::post_processing(data_points, R, obb); + CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, "data/random_unit_tetra_result.off"); } - - - -template -void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) -{ - typedef typename boost::property_map::const_type Vpm; - typedef typename boost::property_traits::reference Point_ref; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - Vpm vpm = get(boost::vertex_point, sm); - - mat.resize(vertices(sm).size(), 3); - std::size_t i = 0; - for(vertex_descriptor v : vertices(sm)) - { - Point_ref p = get(vpm, v); - mat(i, 0) = p.x(); - mat(i, 1) = p.y(); - mat(i, 2) = p.z(); - ++i; - } -} - - -void test_tetrahedron(const char* fname) +void test_reference_tetrahedron(const char* fname) { std::ifstream input(fname); CGAL::Surface_mesh mesh; @@ -206,18 +211,55 @@ void test_tetrahedron(const char* fname) sm_to_matrix(mesh, points); MatrixXf R(3, 3); - CGAL::Optimal_bounding_box::evolution(R, points); - std:: cout << "R= " << R << std::endl; - std:: cout << "det(evolution)= " << R.determinant() << std::endl; + std::size_t generations = 10; + CGAL::Optimal_bounding_box::evolution(R, points, generations); + double epsilon = 1e-5; + std::cout << R << std::endl; + CGAL_assertion(assert_doubles(R.determinant(), 1, epsilon)); // postprocessing MatrixXf obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points, R, obb); CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, "data/OBB.off"); - } +void test_long_tetrahedron(std::string fname) +{ + std::ifstream input(fname); + CGAL::Surface_mesh mesh; + if (!input || !(input >> mesh) || mesh.is_empty()) { + std::cerr << fname << " is not a valid off file.\n"; + exit(1); + } + + // points in a matrix + MatrixXf points; + sm_to_matrix(mesh, points); + + MatrixXf R(3, 3); + std::size_t generations = 10; + CGAL::Optimal_bounding_box::evolution(R, points, generations); + double epsilon = 1e-5; + std::cout << R << std::endl; + CGAL_assertion(assert_doubles(R.determinant(), 1, epsilon)); + CGAL_assertion(assert_doubles(R(0,0), -1, epsilon)); + CGAL_assertion(assert_doubles(R(0,1), 0, epsilon)); + CGAL_assertion(assert_doubles(R(0,2), 0, epsilon)); + CGAL_assertion(assert_doubles(R(1,0), 0, epsilon)); + CGAL_assertion(assert_doubles(R(1,1), -0.707107, epsilon)); + CGAL_assertion(assert_doubles(R(1,2), 0.707106, epsilon) || + assert_doubles(R(1,2), -0.707106, epsilon)); + CGAL_assertion(assert_doubles(R(2,0), 0, epsilon)); + CGAL_assertion(assert_doubles(R(2,1), 0.707106, epsilon) || + assert_doubles(R(1,2), -0.707106, epsilon)); + CGAL_assertion(assert_doubles(R(2,2), 0.707107, epsilon)); + + // postprocessing + MatrixXf obb(8, 3); + CGAL::Optimal_bounding_box::post_processing(points, R, obb); + CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, fname + "result.off"); +} void rotate_tetrahedron(const char* fname, const char* Rname) { @@ -267,10 +309,11 @@ int main() //test_population(); //test_nelder_mead(); //test_genetic_algorithm(); - //find_obb(); + //test_random_unit_tetra(); - test_tetrahedron("data/random_tetra.off"); + test_reference_tetrahedron("data/reference_tetrahedron.off"); + //test_long_tetrahedron("data/long_tetrahedron.off"); //rotate_tetrahedron("data/random_tetra.off", "data/rotation.dat"); From 01b6ce0c579830705d7331765b36a22147a2bfe6 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Fri, 27 Apr 2018 16:47:51 +0200 Subject: [PATCH 011/150] polyhedron demo plugin --- .../include/CGAL/Optimal_bounding_box/obb.h | 54 +++++++- .../Optimal_bounding_box/maintainer | 1 + .../test_optimization_algorithms.cpp | 13 +- .../Polyhedron/Plugins/PCA/CMakeLists.txt | 3 + .../Plugins/PCA/Create_obb_mesh_plugin.cpp | 130 ++++++++++++++++++ 5 files changed, 190 insertions(+), 11 deletions(-) create mode 100644 Optimal_bounding_box/package_info/Optimal_bounding_box/maintainer create mode 100644 Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index bff18be74f7..3a2ac86ae5d 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -32,20 +32,24 @@ #include #include +#include + namespace CGAL { namespace Optimal_bounding_box { + + template -void evolution(Matrix& R, Matrix& points, std::size_t generations) +void evolution(Matrix& R, Matrix& points, std::size_t generations) // todo: points is const { CGAL_assertion(points.rows() >= 3); - CGAL_assertion(points.cols() = 3); - CGAL_assertion(R.rows() = 3); - CGAL_assertion(R.cols() = 3); + CGAL_assertion(points.cols() == 3); + CGAL_assertion(R.rows() == 3); + CGAL_assertion(R.cols() == 3); std::size_t nelder_mead_iterations = 20; @@ -94,6 +98,9 @@ void evolution(Matrix& R, Matrix& points, std::size_t generations) + + + template void visualize_obb(Simplex data_points, std::string filename) { @@ -213,6 +220,45 @@ void post_processing(Matrix& points, Matrix& R, Matrix& obb) } + + +template +void find_obb(std::vector& points, std::vector& obb_points) +{ + CGAL_assertion(points.size() >= 3); + CGAL_assertion(obb_points.size() == 8); + + // points: vector -> matrix + typedef Eigen::MatrixXf MatrixXf; + + MatrixXf points_mat(points.size(), 3); + for(std::size_t i = 0; i < points.size(); ++i) + { + Point p = points[i]; + points_mat(i, 0) = p.x(); + points_mat(i, 1) = p.y(); + points_mat(i, 2) = p.z(); + } + + + MatrixXf R(3, 3); + std::size_t generations = 10; + CGAL::Optimal_bounding_box::evolution(R, points_mat, generations); + + MatrixXf obb(8, 3); + CGAL::Optimal_bounding_box::post_processing(points_mat, R, obb); + + // matrix -> vector + for(std::size_t i = 0; i < 8; ++i) + { + Point p(obb(i, 0), obb(i, 1), obb(i, 2)); + obb_points[i] = p; + } + +} + + + template void matrix_to_mesh_and_draw(Matrix& data_points, std::string filename) { diff --git a/Optimal_bounding_box/package_info/Optimal_bounding_box/maintainer b/Optimal_bounding_box/package_info/Optimal_bounding_box/maintainer new file mode 100644 index 00000000000..f45b28bc165 --- /dev/null +++ b/Optimal_bounding_box/package_info/Optimal_bounding_box/maintainer @@ -0,0 +1 @@ +Konstantinos Katrioplas diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 0f3fca91a30..7c5e0e23efa 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -306,15 +306,14 @@ void rotate_tetrahedron(const char* fname, const char* Rname) int main() { - //test_population(); - //test_nelder_mead(); - //test_genetic_algorithm(); - //test_random_unit_tetra(); - + test_population(); + test_nelder_mead(); + test_genetic_algorithm(); + test_random_unit_tetra(); test_reference_tetrahedron("data/reference_tetrahedron.off"); - //test_long_tetrahedron("data/long_tetrahedron.off"); - //rotate_tetrahedron("data/random_tetra.off", "data/rotation.dat"); + test_long_tetrahedron("data/long_tetrahedron.off"); + rotate_tetrahedron("data/random_tetra.off", "data/rotation.dat"); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt index 978cbfa2c0b..9fa0fd20cae 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt @@ -20,6 +20,9 @@ target_link_libraries(clipping_box_plugin PUBLIC scene_edit_box_item ) polyhedron_demo_plugin(create_bbox_mesh_plugin Create_bbox_mesh_plugin) target_link_libraries(create_bbox_mesh_plugin PUBLIC scene_surface_mesh_item scene_polyhedron_item) +polyhedron_demo_plugin(create_obb_mesh_plugin Create_obb_mesh_plugin) +target_link_libraries(create_obb_mesh_plugin PUBLIC scene_surface_mesh_item scene_polyhedron_item) + qt5_wrap_ui( volumesUI_FILES Basic_generator_widget.ui) polyhedron_demo_plugin(basic_generator_plugin Basic_generator_plugin ${volumesUI_FILES}) target_link_libraries(basic_generator_plugin PUBLIC scene_surface_mesh_item scene_polyhedron_item scene_points_with_normal_item scene_polylines_item) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp new file mode 100644 index 00000000000..22af3fa7a0b --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp @@ -0,0 +1,130 @@ +#include + +#include +#include + +#include +#include +#include + +#include "Scene_polyhedron_item.h" +#include "Scene_surface_mesh_item.h" +#include "Polyhedron_type.h" +#include + +#include +#include + +using namespace CGAL::Three; + +typedef Scene_surface_mesh_item::Face_graph FaceGraph; +typedef Polyhedron::Point_3 Point_3; + + +class Create_obb_mesh_plugin : + public QObject, + public CGAL::Three::Polyhedron_demo_plugin_interface +{ + Q_OBJECT + Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) + Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") + +public: + void init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*); + QList actions() const; + + bool applicable(QAction*) const { + if(scene->mainSelectionIndex() != -1 + && scene->item(scene->mainSelectionIndex())->isFinite()) + return true; + return false;} + +protected: + template + void gather_mesh_points(std::vector& points); + void obb(); + +public Q_SLOTS: + void createObb() { + QApplication::setOverrideCursor(Qt::WaitCursor); + obb(); + QApplication::restoreOverrideCursor(); + } + +private: + Scene_interface* scene; + QMainWindow* mw; + QAction* actionObb; + +}; // end Create_obb_mesh_plugin class + + + +void Create_obb_mesh_plugin::init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*) +{ + scene = scene_interface; + mw = mainWindow; + actionObb = new QAction(tr("Create &Optimal Bbox Mesh"), mainWindow); + actionObb->setObjectName("createObbMeshAction"); + connect(actionObb, SIGNAL(triggered()), this, SLOT(createObb())); +} + +QList Create_obb_mesh_plugin::actions() const { + return QList() << actionObb; +} + +template +void Create_obb_mesh_plugin::gather_mesh_points(std::vector& points) +{ + const Scene_interface::Item_id index = scene->mainSelectionIndex(); + FaceGraph_item* poly_item = qobject_cast(scene->item(index)); + + if(poly_item != NULL) + { + typedef typename FaceGraph_item::Face_graph FaceGraph; + typedef typename boost::property_map::type PointPMap; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + FaceGraph& pmesh = *poly_item->polyhedron(); + PointPMap pmap = get(boost::vertex_point, pmesh); + BOOST_FOREACH(vertex_descriptor v, vertices(pmesh)) + points.push_back(get(pmap, v )); + } +} + +void Create_obb_mesh_plugin::obb() +{ + + // gather point coordinates + std::vector points; + if(mw->property("is_polyhedron_mode").toBool()) + { + gather_mesh_points(points); + } + else + { + gather_mesh_points(points); + } + + // find obb + std::vector obb_points(8); + CGAL::Optimal_bounding_box::find_obb(points, obb_points); + + Scene_item* item; + if(mw->property("is_polyhedorn_mode").toBool()){ + Polyhedron* p = new Polyhedron; + CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], + obb_points[4], obb_points[5], obb_points[6], obb_points[7], *p); + item = new Scene_polyhedron_item(p); + } else { + SMesh* p = new SMesh; + CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], + obb_points[4], obb_points[5], obb_points[6], obb_points[7], *p); + item = new Scene_surface_mesh_item(p); + } + + item->setName("Optimal bbox mesh"); + item->setRenderingMode(Wireframe); + scene->addItem(item); +} + +#include "Create_obb_mesh_plugin.moc" From 07a6d3ae4d45786bdcea37a7c2b983d36b06bf0d Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Mon, 30 Apr 2018 17:02:28 +0200 Subject: [PATCH 012/150] cleaning --- .../include/CGAL/Optimal_bounding_box/obb.h | 95 ++----------------- .../test_optimization_algorithms.cpp | 10 +- 2 files changed, 10 insertions(+), 95 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index 3a2ac86ae5d..48e03ee2ece 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -97,91 +97,7 @@ void evolution(Matrix& R, Matrix& points, std::size_t generations) // todo: poin } - - - - -template -void visualize_obb(Simplex data_points, std::string filename) -{ - - typedef CGAL::Simple_cartesian K; - typedef K::Point_3 Point; - typedef CGAL::Surface_mesh Mesh; - - // Simplex -> std::vector - std::vector points; - - for(int i = 0; i < data_points.rows(); ++i) - { - Point p(data_points(i, 0), data_points(i, 1), data_points(i, 2)); - points.push_back(p); - } - - - CGAL::Bbox_3 bbox; - bbox = bbox_3(points.begin(), points.end()); - K::Iso_cuboid_3 ic(bbox); - - Mesh mesh; - CGAL::make_hexahedron(ic[0], ic[1], ic[2], ic[3], ic[4], ic[5], ic[6], ic[7], mesh); - - std::ofstream out(filename); - out << mesh; - out.close(); - - -} - -template -void find_and_rotate_aabb(SurfaceMesh& sm, Matrix& R, Matrix& OBB) -{ - // get vector - typedef typename boost::property_map::const_type Vpm; - typedef typename boost::property_traits::value_type Point; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - Vpm vpm = get(boost::vertex_point, sm); - - std::vector points; - points.resize(vertices(sm).size()); - std::size_t i = 0; - for(vertex_descriptor v : vertices(sm)) - { - Point p = get(vpm, v); - points[i] = p; - ++i; - } - - CGAL_assertion(points.size() == vertices(sm).size()); - - - // get AABB - typedef CGAL::Simple_cartesian K; - CGAL::Bbox_3 bbox; - bbox = bbox_3(points.begin(), points.end()); - K::Iso_cuboid_3 ic(bbox); - - - - // rotate AABB -> OBB - Matrix aabb(8,3); //hexahedron - for(int i = 0; i < 8; ++i) - { - aabb(i, 0) = ic[i].x(); - aabb(i, 1) = ic[i].y(); - aabb(i, 2) = ic[i].z(); - } - - - - OBB = aabb * R.transpose(); - CGAL_assertion(OBB.cols() == aabb.cols()); - CGAL_assertion(OBB.rows() == aabb.rows()); - - //std::cout << OBB << std::endl; -} - - +// works on matrices only template void post_processing(Matrix& points, Matrix& R, Matrix& obb) { @@ -221,11 +137,15 @@ void post_processing(Matrix& points, Matrix& R, Matrix& obb) } - +/// @param points point coordinates of the input mesh +/// @param obb_points the 8 points of the obb. template void find_obb(std::vector& points, std::vector& obb_points) { CGAL_assertion(points.size() >= 3); + + if(obb_points.size() != 8) // temp sanity until the API is decided + obb_points.resize(8); CGAL_assertion(obb_points.size() == 8); // points: vector -> matrix @@ -257,8 +177,7 @@ void find_obb(std::vector& points, std::vector& obb_points) } - - +// it is called after post processing template void matrix_to_mesh_and_draw(Matrix& data_points, std::string filename) { diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 7c5e0e23efa..8e646c68479 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -275,7 +275,7 @@ void rotate_tetrahedron(const char* fname, const char* Rname) std::ifstream input_R(Rname); double x, y, z; std::size_t i = 0; - while (input_R >> x >> y >> z) + while (input_R >> x >> y >> z) // not safe, but it's going away { R(i, 0) = x; R(i, 1) = y; @@ -289,11 +289,6 @@ void rotate_tetrahedron(const char* fname, const char* Rname) MatrixXf points; sm_to_matrix(mesh, points); - // just rotate once - //MatrixXf rotated_points = points * R.transpose(); - //CGAL::Optimal_bounding_box::visualize_obb(rotated_points, "data/rotated_points_benchmark.off"); - - // postprocessing MatrixXf obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points, R, obb); @@ -306,6 +301,7 @@ void rotate_tetrahedron(const char* fname, const char* Rname) int main() { + test_population(); test_nelder_mead(); test_genetic_algorithm(); @@ -313,7 +309,7 @@ int main() test_reference_tetrahedron("data/reference_tetrahedron.off"); test_long_tetrahedron("data/long_tetrahedron.off"); - rotate_tetrahedron("data/random_tetra.off", "data/rotation.dat"); + rotate_tetrahedron("data/random_unit_tetra.off", "data/rotation.dat"); From f2c774d3275adf72862a9cfb38c13a13b2817a56 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Wed, 2 May 2018 13:28:47 +0200 Subject: [PATCH 013/150] use convex hull --- .../include/CGAL/Optimal_bounding_box/obb.h | 48 +++++++++---- .../test_optimization_algorithms.cpp | 70 ++++++++++++++++++- .../Plugins/PCA/Create_obb_mesh_plugin.cpp | 2 +- 3 files changed, 104 insertions(+), 16 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index 48e03ee2ece..fb936a53491 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -26,14 +26,17 @@ #include #include #include -#include -#include #include #include #include +#include #include +#include +#include +#include +#include namespace CGAL { namespace Optimal_bounding_box { @@ -136,11 +139,23 @@ void post_processing(Matrix& points, Matrix& R, Matrix& obb) } +template +void fill_matrix(std::vector& v_points, Matrix& points_mat) +{ + points_mat.resize(v_points.size(), 3); + for(std::size_t i = 0; i < v_points.size(); ++i) + { + Point p = v_points[i]; + points_mat(i, 0) = p.x(); + points_mat(i, 1) = p.y(); + points_mat(i, 2) = p.z(); + } +} /// @param points point coordinates of the input mesh /// @param obb_points the 8 points of the obb. template -void find_obb(std::vector& points, std::vector& obb_points) +void find_obb(std::vector& points, std::vector& obb_points, bool use_ch) { CGAL_assertion(points.size() >= 3); @@ -148,18 +163,27 @@ void find_obb(std::vector& points, std::vector& obb_points) obb_points.resize(8); CGAL_assertion(obb_points.size() == 8); - // points: vector -> matrix - typedef Eigen::MatrixXf MatrixXf; - MatrixXf points_mat(points.size(), 3); - for(std::size_t i = 0; i < points.size(); ++i) + typedef Eigen::MatrixXf MatrixXf; // using eigen internally + MatrixXf points_mat; + + // get the ch3 + if(use_ch) { - Point p = points[i]; - points_mat(i, 0) = p.x(); - points_mat(i, 1) = p.y(); - points_mat(i, 2) = p.z(); - } + // find the ch - todo: template kernel + typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; + CGAL::Polyhedron_3 poly; + convex_hull_3(points.begin(), points.end(), poly); + std::vector ch_points(poly.points_begin(), poly.points_end()); + // points: vector -> matrix + fill_matrix(ch_points, points_mat); + } + else + { + // points: vector -> matrix + fill_matrix(points, points_mat); + } MatrixXf R(3, 3); std::size_t generations = 10; diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 8e646c68479..caf02e2334c 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -41,6 +41,16 @@ void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) } } +template +void gather_mesh_points(SurfaceMesh& mesh, std::vector& points) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::property_map::type PointPMap; + PointPMap pmap = get(boost::vertex_point, mesh); + BOOST_FOREACH(vertex_descriptor v, vertices(mesh)) + points.push_back(get(pmap, v)); +} + void test_population() { @@ -293,7 +303,63 @@ void rotate_tetrahedron(const char* fname, const char* Rname) MatrixXf obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points, R, obb); CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, "data/inverse_rotated.off"); +} +void test_find_obb(std::string fname) +{ + std::ifstream input(fname); + CGAL::Surface_mesh mesh; + if (!input || !(input >> mesh) || mesh.is_empty()) { + std::cerr << fname << " is not a valid off file.\n"; + exit(1); + } + + // get mesh points + std::vector sm_points; + gather_mesh_points(mesh, sm_points); + + std::vector obb_points; + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true); + + double epsilon = 1e-4; + CGAL_assertion(assert_doubles(obb_points[0].x(), 1.01752, epsilon)); + CGAL_assertion(assert_doubles(obb_points[0].y(), 0.437675, epsilon)); + CGAL_assertion(assert_doubles(obb_points[0].z(), 0.382697, epsilon)); + CGAL_assertion(assert_doubles(obb_points[1].x(), 0.912648, epsilon)); + CGAL_assertion(assert_doubles(obb_points[1].y(), 0.761563, epsilon)); + CGAL_assertion(assert_doubles(obb_points[1].z(), 0.160329, epsilon)); + CGAL_assertion(assert_doubles(obb_points[2].x(), 0.0615854, epsilon)); + CGAL_assertion(assert_doubles(obb_points[2].y(), 0.473799, epsilon)); + CGAL_assertion(assert_doubles(obb_points[2].z(), 0.142574, epsilon)); + CGAL_assertion(assert_doubles(obb_points[3].x(), 0.166461, epsilon)); + CGAL_assertion(assert_doubles(obb_points[3].y(), 0.149911, epsilon)); + CGAL_assertion(assert_doubles(obb_points[3].z(), 0.364943, epsilon)); + CGAL_assertion(assert_doubles(obb_points[4].x(), 0.0316104, epsilon)); + CGAL_assertion(assert_doubles(obb_points[4].y(), 0.512247, epsilon)); + CGAL_assertion(assert_doubles(obb_points[4].z(), 0.956296, epsilon)); + CGAL_assertion(assert_doubles(obb_points[5].x(), 0.882673, epsilon)); + CGAL_assertion(assert_doubles(obb_points[5].y(), 0.800011, epsilon)); + CGAL_assertion(assert_doubles(obb_points[5].z(), 0.97405, epsilon)); + CGAL_assertion(assert_doubles(obb_points[6].x(), 0.777797, epsilon)); + CGAL_assertion(assert_doubles(obb_points[6].y(), 1.1239, epsilon)); + CGAL_assertion(assert_doubles(obb_points[6].z(), 0.751681, epsilon)); + CGAL_assertion(assert_doubles(obb_points[7].x(), -0.0732647, epsilon)); + CGAL_assertion(assert_doubles(obb_points[7].y(), 0.836134, epsilon)); + CGAL_assertion(assert_doubles(obb_points[7].z(), 0.733927, epsilon)); + + /* debug + for(int i = 0; i < 8; ++i) + { + std::cout << obb_points[i].x() << " " << obb_points[i].y() << " " << obb_points[i].z() << "\n" ; + } + CGAL::Surface_mesh result_mesh; + CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], + obb_points[4], obb_points[5], obb_points[6], obb_points[7], result_mesh); + + std::ofstream out("data/obb_result.off"); + out << result_mesh; + out.close(); + */ } @@ -306,12 +372,10 @@ int main() test_nelder_mead(); test_genetic_algorithm(); test_random_unit_tetra(); - test_reference_tetrahedron("data/reference_tetrahedron.off"); test_long_tetrahedron("data/long_tetrahedron.off"); rotate_tetrahedron("data/random_unit_tetra.off", "data/rotation.dat"); - - + test_find_obb("data/random_unit_tetra.off"); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp index 22af3fa7a0b..35c98a4d74f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp @@ -107,7 +107,7 @@ void Create_obb_mesh_plugin::obb() // find obb std::vector obb_points(8); - CGAL::Optimal_bounding_box::find_obb(points, obb_points); + CGAL::Optimal_bounding_box::find_obb(points, obb_points, true); Scene_item* item; if(mw->property("is_polyhedorn_mode").toBool()){ From 7f23b19f300ebc7e04512b66cec8fd8ec70cb78f Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Thu, 3 May 2018 10:15:02 +0200 Subject: [PATCH 014/150] selection of faces on the plugin --- .../Polyhedron/Plugins/PCA/CMakeLists.txt | 2 +- .../Plugins/PCA/Create_obb_mesh_plugin.cpp | 95 ++++++++++++++----- 2 files changed, 70 insertions(+), 27 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt index 9fa0fd20cae..205e7a38b62 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt @@ -21,7 +21,7 @@ polyhedron_demo_plugin(create_bbox_mesh_plugin Create_bbox_mesh_plugin) target_link_libraries(create_bbox_mesh_plugin PUBLIC scene_surface_mesh_item scene_polyhedron_item) polyhedron_demo_plugin(create_obb_mesh_plugin Create_obb_mesh_plugin) -target_link_libraries(create_obb_mesh_plugin PUBLIC scene_surface_mesh_item scene_polyhedron_item) +target_link_libraries(create_obb_mesh_plugin PUBLIC scene_surface_mesh_item scene_polyhedron_item scene_polyhedron_selection_item) qt5_wrap_ui( volumesUI_FILES Basic_generator_widget.ui) polyhedron_demo_plugin(basic_generator_plugin Basic_generator_plugin ${volumesUI_FILES}) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp index 35c98a4d74f..8e2ff5ea293 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp @@ -7,19 +7,21 @@ #include #include -#include "Scene_polyhedron_item.h" #include "Scene_surface_mesh_item.h" #include "Polyhedron_type.h" +#include "Scene_polyhedron_item.h" #include +#include "Scene_polyhedron_selection_item.h" #include #include -using namespace CGAL::Three; +//typedef Scene_surface_mesh_item Scene_facegraph_item; +//typedef Scene_facegraph_item Scene_facegraph_item; -typedef Scene_surface_mesh_item::Face_graph FaceGraph; +typedef Scene_facegraph_item::Face_graph FaceGraph; typedef Polyhedron::Point_3 Point_3; - +using namespace CGAL::Three; class Create_obb_mesh_plugin : public QObject, @@ -34,13 +36,30 @@ public: QList actions() const; bool applicable(QAction*) const { + + if (scene->selectionIndices().size() == 1) + { + return qobject_cast(scene->item(scene->mainSelectionIndex())) + || qobject_cast(scene->item(scene->mainSelectionIndex())); + } + + Q_FOREACH(int index, scene->selectionIndices()) + { + if (qobject_cast(scene->item(index))) + return true; + } + return false; + + /* if(scene->mainSelectionIndex() != -1 && scene->item(scene->mainSelectionIndex())->isFinite()) return true; - return false;} + return false; + */ + +} protected: - template void gather_mesh_points(std::vector& points); void obb(); @@ -73,49 +92,73 @@ QList Create_obb_mesh_plugin::actions() const { return QList() << actionObb; } -template + void Create_obb_mesh_plugin::gather_mesh_points(std::vector& points) { const Scene_interface::Item_id index = scene->mainSelectionIndex(); - FaceGraph_item* poly_item = qobject_cast(scene->item(index)); - if(poly_item != NULL) + Scene_facegraph_item* poly_item = + qobject_cast(scene->item(index)); + + Scene_polyhedron_selection_item* selection_item = + qobject_cast(scene->item(index)); + + if(poly_item || selection_item) { - typedef typename FaceGraph_item::Face_graph FaceGraph; - typedef typename boost::property_map::type PointPMap; + typedef typename boost::property_map::type PointPMap; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - FaceGraph& pmesh = *poly_item->polyhedron(); - PointPMap pmap = get(boost::vertex_point, pmesh); - BOOST_FOREACH(vertex_descriptor v, vertices(pmesh)) - points.push_back(get(pmap, v )); + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + std::vector selected_vertices; + + if(poly_item != NULL) + { + FaceGraph& pmesh = *poly_item->polyhedron(); + selected_vertices.assign(vertices(pmesh).begin(), vertices(pmesh).end()); + PointPMap pmap = get(CGAL::vertex_point, pmesh); + BOOST_FOREACH(vertex_descriptor v, selected_vertices) + points.push_back(get(pmap, v )); + + } + else if(selection_item != NULL) // using selection of faces + { + FaceGraph& pmesh = *selection_item->polyhedron(); + BOOST_FOREACH(face_descriptor f, selection_item->selected_facets) + { + BOOST_FOREACH(vertex_descriptor v, vertices_around_face(halfedge(f, pmesh), pmesh)) + { + selected_vertices.push_back(v); + } + } + + PointPMap pmap = get(CGAL::vertex_point, pmesh); + BOOST_FOREACH(vertex_descriptor v, selected_vertices) + points.push_back(get(pmap, v )); + } + CGAL_assertion(points.size() >= 3); } } + void Create_obb_mesh_plugin::obb() { - // gather point coordinates std::vector points; - if(mw->property("is_polyhedron_mode").toBool()) - { - gather_mesh_points(points); - } - else - { - gather_mesh_points(points); - } + gather_mesh_points(points); // find obb std::vector obb_points(8); CGAL::Optimal_bounding_box::find_obb(points, obb_points, true); Scene_item* item; - if(mw->property("is_polyhedorn_mode").toBool()){ + if(mw->property("is_polyhedorn_mode").toBool()) + { Polyhedron* p = new Polyhedron; CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], obb_points[4], obb_points[5], obb_points[6], obb_points[7], *p); item = new Scene_polyhedron_item(p); - } else { + } + else { SMesh* p = new SMesh; CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], obb_points[4], obb_points[5], obb_points[6], obb_points[7], *p); From 319c8079ad06624b548af1fc98ef452407cf4741 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Thu, 3 May 2018 12:12:30 +0200 Subject: [PATCH 015/150] stopping criteria on generations --- .../Optimal_bounding_box/fitness_function.h | 7 ++++ .../include/CGAL/Optimal_bounding_box/obb.h | 35 ++++++++++++------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 40ceb55e45f..51a06289d99 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -106,6 +106,13 @@ struct Fitness_map // -> a free function } + double get_best_fitness_value(const Matrix& data) + { + Matrix best_mat = get_best(); + return compute_fitness(best_mat, data); + } + + const Matrix points; Population pop; }; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index fb936a53491..42760894665 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -46,7 +46,7 @@ namespace Optimal_bounding_box { template -void evolution(Matrix& R, Matrix& points, std::size_t generations) // todo: points is const +void evolution(Matrix& R, Matrix& points, std::size_t max_generations) // todo: points is const { CGAL_assertion(points.rows() >= 3); @@ -59,12 +59,12 @@ void evolution(Matrix& R, Matrix& points, std::size_t generations) // todo: poin Population pop(50); - //std::cout << "initial pop" << std::endl; - //pop.show_population(); - //std::cout << std::endl; - //std::cin.get(); + double prev_fit_value = 0; + double new_fit_value = 0; + double tolerance = 1e-2; + int stale = 0; - for(std::size_t t = 0; t < generations; ++t) + for(std::size_t t = 0; t < max_generations; ++t) { genetic_algorithm(pop, points); @@ -73,7 +73,6 @@ void evolution(Matrix& R, Matrix& points, std::size_t generations) // todo: poin // std::cout << std::endl; //std::cin.get(); - for(std::size_t s = 0; s < pop.size(); ++s) nelder_mead(pop[s], points, nelder_mead_iterations); @@ -82,7 +81,6 @@ void evolution(Matrix& R, Matrix& points, std::size_t generations) // todo: poin //std::cout << std::endl; //std::cin.get(); - // debugging /* Fitness_map fitness_map(pop, points); @@ -90,13 +88,23 @@ void evolution(Matrix& R, Matrix& points, std::size_t generations) // todo: poin std::cout << "det= " << R_now.determinant() << std::endl; */ + // stopping criteria + Fitness_map fitness_map(pop, points); + new_fit_value = fitness_map.get_best_fitness_value(points); + double difference = new_fit_value - prev_fit_value; + if(abs(difference) < tolerance * new_fit_value) + stale++; + + if(stale == 5) + break; + + prev_fit_value = new_fit_value; } // compute fitness of entire population Fitness_map fitness_map(pop, points); R = fitness_map.get_best(); - } @@ -152,8 +160,11 @@ void fill_matrix(std::vector& v_points, Matrix& points_mat) } } -/// @param points point coordinates of the input mesh +/// @param points point coordinates of the input mesh. /// @param obb_points the 8 points of the obb. +/// @param use convex hull or not. +/// +/// todo named parameters: max iterations template void find_obb(std::vector& points, std::vector& obb_points, bool use_ch) { @@ -186,8 +197,8 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u } MatrixXf R(3, 3); - std::size_t generations = 10; - CGAL::Optimal_bounding_box::evolution(R, points_mat, generations); + std::size_t max_generations = 100; + CGAL::Optimal_bounding_box::evolution(R, points_mat, max_generations); MatrixXf obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points_mat, R, obb); From 37446e467265d126ad3113800bb286d59ce77c46 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Thu, 3 May 2018 12:12:51 +0200 Subject: [PATCH 016/150] cleaning --- .../Optimal_bounding_box/fitness_function.h | 9 +- .../Optimal_bounding_box/linear_algebra.h | 9 +- .../include/CGAL/Optimal_bounding_box/obb.h | 43 ++--- .../optimization_algorithms.h | 41 +---- .../CGAL/Optimal_bounding_box/population.h | 5 - .../test_optimization_algorithms.cpp | 173 ++++++++++-------- .../Plugins/PCA/Create_obb_mesh_plugin.cpp | 1 - 7 files changed, 129 insertions(+), 152 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 51a06289d99..791ab2f9279 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -79,10 +79,10 @@ struct Fitness_map // -> a free function double best_fitness = std::numeric_limits::max(); for(std::size_t i = 0; i < pop.size(); ++i) { - const std::vector simplex = pop[i]; + //const std::vector simplex = pop[i]; for(std::size_t j =0; j < 4; ++j) { - const Matrix vertex = simplex[j]; + const Matrix vertex = pop[i][j]; //std::cout << "i= "<< i << " j=" << j<<"\n vertex= " << vertex << std::endl; ++count_vertices; //std::cout << "vertex = " << vertex << std::endl; @@ -95,14 +95,13 @@ struct Fitness_map // -> a free function vertex_id = j; best_fitness = fitness; } - } } std::vector best_simplex = pop[simplex_id]; - Matrix temp = best_simplex[vertex_id]; + //Matrix temp = best_simplex[vertex_id]; - return temp; + return best_simplex[vertex_id]; } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h index d78eda5fc31..e10aaa7c24b 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h @@ -74,7 +74,7 @@ const Matrix expansion(const Matrix& S_centroid, const Matrix& S_worst, const Ma } template -Matrix mean(const Matrix& m1, const Matrix& m2) // mean +Matrix mean(const Matrix& m1, const Matrix& m2) { // same API for reduction CGAL_assertion(m1.rows() == 3); @@ -100,13 +100,6 @@ const Matrix centroid(Matrix& S1, Matrix& S2, Matrix& S3) } - - - - - - - }} // end namespaces diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index 42760894665..f3564144794 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -33,8 +33,8 @@ #include -#include -#include +#include // used draw mesh +#include // used to get the ch #include #include @@ -42,9 +42,6 @@ namespace CGAL { namespace Optimal_bounding_box { - - - template void evolution(Matrix& R, Matrix& points, std::size_t max_generations) // todo: points is const { @@ -54,10 +51,8 @@ void evolution(Matrix& R, Matrix& points, std::size_t max_generations) // todo: CGAL_assertion(R.rows() == 3); CGAL_assertion(R.cols() == 3); - - std::size_t nelder_mead_iterations = 20; - Population pop(50); + std::size_t nelder_mead_iterations = 20; double prev_fit_value = 0; double new_fit_value = 0; @@ -66,27 +61,32 @@ void evolution(Matrix& R, Matrix& points, std::size_t max_generations) // todo: for(std::size_t t = 0; t < max_generations; ++t) { + +#ifdef OBB_DEBUG + std::cout << "generation= " << t << "\n"; +#endif + genetic_algorithm(pop, points); +#ifdef OBB_DEBUG //std::cout << "pop after genetic" << std::endl; - // pop.show_population(); - // std::cout << std::endl; - //std::cin.get(); + //pop.show_population(); + //std::cout << std::endl; +#endif for(std::size_t s = 0; s < pop.size(); ++s) nelder_mead(pop[s], points, nelder_mead_iterations); +#ifdef OBB_DEBUG //std::cout << "pop after nelder mead: " << std::endl; //pop.show_population(); //std::cout << std::endl; - //std::cin.get(); // debugging - /* Fitness_map fitness_map(pop, points); Matrix R_now = fitness_map.get_best(); std::cout << "det= " << R_now.determinant() << std::endl; - */ +#endif // stopping criteria Fitness_map fitness_map(pop, points); @@ -102,7 +102,6 @@ void evolution(Matrix& R, Matrix& points, std::size_t max_generations) // todo: prev_fit_value = new_fit_value; } - // compute fitness of entire population Fitness_map fitness_map(pop, points); R = fitness_map.get_best(); } @@ -164,7 +163,7 @@ void fill_matrix(std::vector& v_points, Matrix& points_mat) /// @param obb_points the 8 points of the obb. /// @param use convex hull or not. /// -/// todo named parameters: max iterations +/// todo named parameters: max iterations, population size, tolerance. template void find_obb(std::vector& points, std::vector& obb_points, bool use_ch) { @@ -175,8 +174,8 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u CGAL_assertion(obb_points.size() == 8); - typedef Eigen::MatrixXf MatrixXf; // using eigen internally - MatrixXf points_mat; + typedef Eigen::MatrixXd MatrixXd; // using eigen internally + MatrixXd points_mat; // get the ch3 if(use_ch) @@ -196,11 +195,11 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u fill_matrix(points, points_mat); } - MatrixXf R(3, 3); + MatrixXd R(3, 3); std::size_t max_generations = 100; CGAL::Optimal_bounding_box::evolution(R, points_mat, max_generations); - MatrixXf obb(8, 3); + MatrixXd obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points_mat, R, obb); // matrix -> vector @@ -209,14 +208,12 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u Point p(obb(i, 0), obb(i, 1), obb(i, 2)); obb_points[i] = p; } - } // it is called after post processing template void matrix_to_mesh_and_draw(Matrix& data_points, std::string filename) { - typedef CGAL::Simple_cartesian K; typedef K::Point_3 Point; typedef CGAL::Surface_mesh Mesh; @@ -230,7 +227,6 @@ void matrix_to_mesh_and_draw(Matrix& data_points, std::string filename) points.push_back(p); } - Mesh mesh; CGAL::make_hexahedron(points[0], points[1], points[2], points[3], points[4], points[5], points[6], points[7], mesh); @@ -238,7 +234,6 @@ void matrix_to_mesh_and_draw(Matrix& data_points, std::string filename) std::ofstream out(filename); out << mesh; out.close(); - } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h index 980b6c10491..384ab5cafcb 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h @@ -154,9 +154,7 @@ void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_it CGAL_assertion(simplex.size() == 4); // tetrahedron - } // iterations - } struct Random_int_generator @@ -224,15 +222,12 @@ void genetic_algorithm(Population& pop, Simplex& points) for(std::size_t i = 0; i < ids4.size(); ++i) group4[i] = pop[ids4[i]]; - - - /* +#ifdef OBB_DEBUG check_det(group1); check_det(group2); check_det(group3); check_det(group4); - */ - +#endif // crossover I Population offspringsA(size_first_group); @@ -259,14 +254,11 @@ void genetic_algorithm(Population& pop, Simplex& points) offspringsA[i] = offspring; } - - /* +#ifdef OBB_DEBUG std::cout << "offspringsA: \n" ; check_det(offspringsA); std::cin.get(); - */ - - +#endif // crossover II Population offspringsB(size_second_group); @@ -294,21 +286,15 @@ void genetic_algorithm(Population& pop, Simplex& points) offspringsB[i] = offspring; } - - - - /* +#ifdef OBB_DEBUG std::cout << "offspringsB: \n" ; check_det(offspringsB); - std::cin.get(); - */ - +#endif CGAL_assertion(offspringsA.size() == size_first_group); CGAL_assertion(offspringsB.size() == size_second_group); CGAL_assertion(offspringsA.size() + offspringsB.size() == pop.size()); - // next generatrion for(std::size_t i = 0; i < size_first_group; ++i) { @@ -320,10 +306,9 @@ void genetic_algorithm(Population& pop, Simplex& points) pop[size_first_group + i] = offspringsB[i]; } - } - +#ifdef OBB_DEBUG template void check_det(Population& pop) { @@ -331,20 +316,12 @@ void check_det(Population& pop) { for(int j = 0; j < 4; ++j) { - auto A = pop[i][j]; + auto A = pop[i][j]; // Simplex std::cout << A.determinant() << std::endl; } } } - - - - - - - - - +#endif } } // end namespaces diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index 76231016eba..6ea889b2466 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -129,11 +129,6 @@ private: } } - - - Individual somebody; //temp - - CGAL::Random random_generator; std::size_t n; std::vector pop; diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index caf02e2334c..c8569c758e9 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -11,7 +11,7 @@ #include -typedef Eigen::MatrixXf MatrixXf; +typedef Eigen::MatrixXd MatrixXd; typedef CGAL::Exact_predicates_inexact_constructions_kernel K; @@ -51,43 +51,49 @@ void gather_mesh_points(SurfaceMesh& mesh, std::vector& points) points.push_back(get(pmap, v)); } +template +double calculate_volume(std::vector points) +{ + CGAL::Bbox_3 bbox; + bbox = bbox_3(points.begin(), points.end()); + K::Iso_cuboid_3 ic(bbox); + return ic.volume(); +} + void test_population() { - - CGAL::Optimal_bounding_box::Population pop(5); - + CGAL::Optimal_bounding_box::Population pop(5); //pop.show_population(); - CGAL_assertion(pop.size() == 5); } void test_nelder_mead() { - MatrixXf data_points(4, 3); + MatrixXd data_points(4, 3); data_points << 0.866802, 0.740808, 0.895304, 0.912651, 0.761565, 0.160330, 0.093661, 0.892578, 0.737412, 0.166461, 0.149912, 0.364944; // one simplex - std::vector simplex(4); + std::vector simplex(4); - MatrixXf v0(3, 3); + MatrixXd v0(3, 3); v0 << -0.2192721, 0.2792986, -0.9348326, -0.7772152, -0.6292092, -0.0056861, -0.5897934, 0.7253193, 0.3550431; - MatrixXf v1(3, 3); + MatrixXd v1(3, 3); v1 << -0.588443, 0.807140, -0.047542, -0.786228, -0.584933, -0.199246, -0.188629, -0.079867, 0.978795; - MatrixXf v2(3, 3); + MatrixXd v2(3, 3); v2 << -0.277970, 0.953559, 0.116010, -0.567497, -0.065576, -0.820760, -0.775035, -0.293982, 0.559370; - MatrixXf v3(3, 3); + MatrixXd v3(3, 3); v3 << -0.32657, -0.60013, -0.73020, -0.20022, -0.71110, 0.67398, -0.92372, 0.36630, 0.11207; @@ -102,7 +108,7 @@ void test_nelder_mead() double epsilon = 1e-5; - MatrixXf v0_new = simplex[0]; + MatrixXd v0_new = simplex[0]; CGAL_assertion(assert_doubles(v0_new(0,0), -0.288975, epsilon)); CGAL_assertion(assert_doubles(v0_new(0,1), 0.7897657, epsilon)); CGAL_assertion(assert_doubles(v0_new(0,2), -0.541076, epsilon)); @@ -113,7 +119,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v0_new(2,1), 0.5111260, epsilon)); CGAL_assertion(assert_doubles(v0_new(2,2), 0.84094, epsilon)); - MatrixXf v1_new = simplex[1]; + MatrixXd v1_new = simplex[1]; CGAL_assertion(assert_doubles(v1_new(0,0), -0.458749, epsilon)); CGAL_assertion(assert_doubles(v1_new(0,1), 0.823283, epsilon)); CGAL_assertion(assert_doubles(v1_new(0,2), -0.334296, epsilon)); @@ -124,7 +130,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v1_new(2,1), 0.338040, epsilon)); CGAL_assertion(assert_doubles(v1_new(2,2), 0.937987, epsilon)); - MatrixXf v2_new = simplex[2]; + MatrixXd v2_new = simplex[2]; CGAL_assertion(assert_doubles(v2_new(0,0), -0.346582, epsilon)); CGAL_assertion(assert_doubles(v2_new(0,1), 0.878534, epsilon)); CGAL_assertion(assert_doubles(v2_new(0,2), -0.328724, epsilon)); @@ -135,7 +141,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v2_new(2,1), 0.334057, epsilon)); CGAL_assertion(assert_doubles(v2_new(2,2), 0.941423, epsilon)); - MatrixXf v3_new = simplex[3]; + MatrixXd v3_new = simplex[3]; CGAL_assertion(assert_doubles(v3_new(0,0), -0.394713, epsilon)); CGAL_assertion(assert_doubles(v3_new(0,1), 0.791782, epsilon)); CGAL_assertion(assert_doubles(v3_new(0,2), -0.466136, epsilon)); @@ -145,25 +151,24 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v3_new(2,0), -0.110692, epsilon)); CGAL_assertion(assert_doubles(v3_new(2,1), 0.462655, epsilon)); CGAL_assertion(assert_doubles(v3_new(2,2), 0.879601, epsilon)); - } void test_genetic_algorithm() { - MatrixXf data_points(4, 3); + MatrixXd data_points(4, 3); data_points << 0.866802, 0.740808, 0.895304, 0.912651, 0.761565, 0.160330, 0.093661, 0.892578, 0.737412, 0.166461, 0.149912, 0.364944; - CGAL::Optimal_bounding_box::Population pop(5); + CGAL::Optimal_bounding_box::Population pop(5); CGAL::Optimal_bounding_box::genetic_algorithm(pop, data_points); CGAL_assertion(pop.size() == 5); } void test_random_unit_tetra() { - MatrixXf data_points(4, 3); // points on their convex hull + MatrixXd data_points(4, 3); // points on their convex hull data_points << 0.866802, 0.740808, 0.895304, 0.912651, 0.761565, 0.160330, 0.093661, 0.892578, 0.737412, @@ -180,17 +185,18 @@ void test_random_unit_tetra() Point p3(0.093661, 0.892578, 0.737412); Point p4(0.166461, 0.149912, 0.364944); CGAL::make_tetrahedron(p1, p2, p3, p4, mesh); + +#ifdef OBB_DEBUG_TEST std::ofstream out("data/random_unit_tetra.off"); out << mesh; out.close(); +#endif - MatrixXf R(3, 3); + MatrixXd R(3, 3); std::size_t generations = 10; CGAL::Optimal_bounding_box::evolution(R, data_points, generations); - std::cout << R << std::endl; - - double epsilon = 1e-5; + double epsilon = 1e-3; CGAL_assertion(assert_doubles(R.determinant(), 1, epsilon)); CGAL_assertion(assert_doubles(R(0,0), -0.25791, epsilon)); CGAL_assertion(assert_doubles(R(0,1), 0.796512, epsilon)); @@ -202,9 +208,12 @@ void test_random_unit_tetra() CGAL_assertion(assert_doubles(R(2,1), 0.512847, epsilon)); CGAL_assertion(assert_doubles(R(2,2), 0.836992, epsilon)); - MatrixXf obb(8, 3); +#ifdef OBB_DEBUG_TEST + // postprocessing + MatrixXd obb(8, 3); CGAL::Optimal_bounding_box::post_processing(data_points, R, obb); CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, "data/random_unit_tetra_result.off"); +#endif } void test_reference_tetrahedron(const char* fname) @@ -217,21 +226,21 @@ void test_reference_tetrahedron(const char* fname) } // points in a matrix - MatrixXf points; + MatrixXd points; sm_to_matrix(mesh, points); - MatrixXf R(3, 3); + MatrixXd R(3, 3); std::size_t generations = 10; CGAL::Optimal_bounding_box::evolution(R, points, generations); double epsilon = 1e-5; - std::cout << R << std::endl; CGAL_assertion(assert_doubles(R.determinant(), 1, epsilon)); + #ifdef OBB_DEBUG_TEST // postprocessing - MatrixXf obb(8, 3); + MatrixXd obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points, R, obb); CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, "data/OBB.off"); - + #endif } void test_long_tetrahedron(std::string fname) @@ -244,14 +253,13 @@ void test_long_tetrahedron(std::string fname) } // points in a matrix - MatrixXf points; + MatrixXd points; sm_to_matrix(mesh, points); - MatrixXf R(3, 3); + MatrixXd R(3, 3); std::size_t generations = 10; CGAL::Optimal_bounding_box::evolution(R, points, generations); - double epsilon = 1e-5; - std::cout << R << std::endl; + double epsilon = 1e-3; CGAL_assertion(assert_doubles(R.determinant(), 1, epsilon)); CGAL_assertion(assert_doubles(R(0,0), -1, epsilon)); CGAL_assertion(assert_doubles(R(0,1), 0, epsilon)); @@ -265,44 +273,12 @@ void test_long_tetrahedron(std::string fname) assert_doubles(R(1,2), -0.707106, epsilon)); CGAL_assertion(assert_doubles(R(2,2), 0.707107, epsilon)); + #ifdef OBB_DEBUG_TEST // postprocessing - MatrixXf obb(8, 3); + MatrixXd obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points, R, obb); CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, fname + "result.off"); -} - -void rotate_tetrahedron(const char* fname, const char* Rname) -{ - - std::ifstream input(fname); - CGAL::Surface_mesh mesh; - if (!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << fname << " is not a valid off file.\n"; - exit(1); - } - - MatrixXf R(3, 3); - std::ifstream input_R(Rname); - double x, y, z; - std::size_t i = 0; - while (input_R >> x >> y >> z) // not safe, but it's going away - { - R(i, 0) = x; - R(i, 1) = y; - R(i, 2) = z; - ++i; - } - std:: cout << "det(benchmark)= " << R.determinant() << std::endl; - - - // points in a matrix - MatrixXf points; - sm_to_matrix(mesh, points); - - // postprocessing - MatrixXf obb(8, 3); - CGAL::Optimal_bounding_box::post_processing(points, R, obb); - CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, "data/inverse_rotated.off"); + #endif } void test_find_obb(std::string fname) @@ -321,7 +297,8 @@ void test_find_obb(std::string fname) std::vector obb_points; CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true); - double epsilon = 1e-4; + double epsilon = 1e-3; + /* CGAL_assertion(assert_doubles(obb_points[0].x(), 1.01752, epsilon)); CGAL_assertion(assert_doubles(obb_points[0].y(), 0.437675, epsilon)); CGAL_assertion(assert_doubles(obb_points[0].z(), 0.382697, epsilon)); @@ -346,8 +323,12 @@ void test_find_obb(std::string fname) CGAL_assertion(assert_doubles(obb_points[7].x(), -0.0732647, epsilon)); CGAL_assertion(assert_doubles(obb_points[7].y(), 0.836134, epsilon)); CGAL_assertion(assert_doubles(obb_points[7].z(), 0.733927, epsilon)); + */ - /* debug + double vol = calculate_volume(obb_points); + CGAL_assertion(assert_doubles(vol, 0.883371, epsilon)); + + #ifdef OBB_DEBUG_TEST for(int i = 0; i < 8; ++i) { std::cout << obb_points[i].x() << " " << obb_points[i].y() << " " << obb_points[i].z() << "\n" ; @@ -359,27 +340,65 @@ void test_find_obb(std::string fname) std::ofstream out("data/obb_result.off"); out << result_mesh; out.close(); - */ + #endif +} + +void +bench(const char* fname) +{ + std::vector sm_points, obb_points; + std::ifstream in(fname); + //double x,y,z; + K::Point_3 p; + int i = 0; + while(in >> p){ + + if(i % 2 == 0) + { + sm_points.push_back(p); + } + + ++i; + } + + std::cout << "input data (points + normals)= " << i << std::endl; + std::cout << "number of points= " << sm_points.size() << std::endl; + + + std::cout.precision(17); + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true); + +/* + for(int i =0; i < obb_points.size(); i ++){ + std::cout << obb_points[i] << std::endl; + } + */ + + CGAL::Surface_mesh mesh; + CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], obb_points[4], obb_points[5], + obb_points[6], obb_points[7], mesh); + + std::ofstream out("/tmp/octopus_result.off"); + out << mesh; + out.close(); } -int main() +int main(int argc, char* argv[]) { - + /* test_population(); test_nelder_mead(); test_genetic_algorithm(); test_random_unit_tetra(); test_reference_tetrahedron("data/reference_tetrahedron.off"); test_long_tetrahedron("data/long_tetrahedron.off"); - rotate_tetrahedron("data/random_unit_tetra.off", "data/rotation.dat"); test_find_obb("data/random_unit_tetra.off"); + */ - - - + bench(argv[1]); return 0; } diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp index 8e2ff5ea293..39f9fb0fb0f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp @@ -139,7 +139,6 @@ void Create_obb_mesh_plugin::gather_mesh_points(std::vector& points) } } - void Create_obb_mesh_plugin::obb() { // gather point coordinates From 2da405114c55c473cb0fb1b56aa1aff89ba47606 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Thu, 3 May 2018 15:52:18 +0200 Subject: [PATCH 017/150] demo plugin: works on point set data --- .../Polyhedron/Plugins/PCA/CMakeLists.txt | 2 +- .../Plugins/PCA/Create_obb_mesh_plugin.cpp | 24 ++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt index 205e7a38b62..cc1a8db9bf4 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt @@ -21,7 +21,7 @@ polyhedron_demo_plugin(create_bbox_mesh_plugin Create_bbox_mesh_plugin) target_link_libraries(create_bbox_mesh_plugin PUBLIC scene_surface_mesh_item scene_polyhedron_item) polyhedron_demo_plugin(create_obb_mesh_plugin Create_obb_mesh_plugin) -target_link_libraries(create_obb_mesh_plugin PUBLIC scene_surface_mesh_item scene_polyhedron_item scene_polyhedron_selection_item) +target_link_libraries(create_obb_mesh_plugin PUBLIC scene_surface_mesh_item scene_polyhedron_item scene_polyhedron_selection_item scene_points_with_normal_item) qt5_wrap_ui( volumesUI_FILES Basic_generator_widget.ui) polyhedron_demo_plugin(basic_generator_plugin Basic_generator_plugin ${volumesUI_FILES}) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp index 39f9fb0fb0f..e8accbf0dbd 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp @@ -12,6 +12,7 @@ #include "Scene_polyhedron_item.h" #include #include "Scene_polyhedron_selection_item.h" +#include "Scene_points_with_normal_item.h" #include #include @@ -37,6 +38,7 @@ public: bool applicable(QAction*) const { + /* if (scene->selectionIndices().size() == 1) { return qobject_cast(scene->item(scene->mainSelectionIndex())) @@ -49,13 +51,12 @@ public: return true; } return false; + */ - /* if(scene->mainSelectionIndex() != -1 && scene->item(scene->mainSelectionIndex())->isFinite()) return true; return false; - */ } @@ -103,6 +104,9 @@ void Create_obb_mesh_plugin::gather_mesh_points(std::vector& points) Scene_polyhedron_selection_item* selection_item = qobject_cast(scene->item(index)); + Scene_points_with_normal_item* point_set_item = + qobject_cast(scene->item(index)); + if(poly_item || selection_item) { typedef typename boost::property_map::type PointPMap; @@ -117,7 +121,7 @@ void Create_obb_mesh_plugin::gather_mesh_points(std::vector& points) selected_vertices.assign(vertices(pmesh).begin(), vertices(pmesh).end()); PointPMap pmap = get(CGAL::vertex_point, pmesh); BOOST_FOREACH(vertex_descriptor v, selected_vertices) - points.push_back(get(pmap, v )); + points.push_back(get(pmap, v)); } else if(selection_item != NULL) // using selection of faces @@ -137,6 +141,20 @@ void Create_obb_mesh_plugin::gather_mesh_points(std::vector& points) } CGAL_assertion(points.size() >= 3); } + + if(point_set_item) + { + Point_set* points_set = point_set_item->point_set(); + if(points_set == NULL) + return; + + std::cout << "points_set->size()= " << points_set->size() << std::endl; + BOOST_FOREACH(Point_3 p, points_set->points()) + { + points.push_back(p); + } + } + } void Create_obb_mesh_plugin::obb() From 91e49fe995ee9878439acb313fa03890822b12b1 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Fri, 4 May 2018 10:50:35 +0200 Subject: [PATCH 018/150] cleaning --- .../Optimal_bounding_box/fitness_function.h | 26 ++++---- .../include/CGAL/Optimal_bounding_box/obb.h | 46 ++++++++------- .../optimization_algorithms.h | 30 +++++----- .../CGAL/Optimal_bounding_box/population.h | 59 ++++++++----------- .../test_linear_algebra_functions.cpp | 57 +++++------------- .../test_optimization_algorithms.cpp | 49 ++++++++------- .../Plugins/PCA/Create_obb_mesh_plugin.cpp | 1 - 7 files changed, 118 insertions(+), 150 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 791ab2f9279..249ef98e069 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -30,8 +30,8 @@ namespace CGAL { namespace Optimal_bounding_box { -template -const double compute_fitness(const Matrix& R, const Matrix& data) +template +const double compute_fitness(const Vertex& R, const Matrix& data) { // R: rotation matrix @@ -42,8 +42,9 @@ const double compute_fitness(const Matrix& R, const Matrix& data) CGAL_assertion(data.rows() >= 3); // rotate points - Matrix RT = R.transpose(); - Matrix rotated_data = data * RT; + Vertex RT = R.transpose(); + Matrix rotated_data; + rotated_data = data * RT; CGAL_assertion(rotated_data.cols() == data.cols()); CGAL_assertion(rotated_data.rows() == data.rows()); @@ -64,13 +65,13 @@ const double compute_fitness(const Matrix& R, const Matrix& data) } -template +template struct Fitness_map // -> a free function { - Fitness_map(Population& p, Matrix& points) : pop(p), points(points) + Fitness_map(Population& p, Matrix& points) : pop(p), points(points) {} - Matrix get_best() + Vertex get_best() { std::size_t count_vertices = 0; @@ -79,10 +80,9 @@ struct Fitness_map // -> a free function double best_fitness = std::numeric_limits::max(); for(std::size_t i = 0; i < pop.size(); ++i) { - //const std::vector simplex = pop[i]; for(std::size_t j =0; j < 4; ++j) { - const Matrix vertex = pop[i][j]; + const Vertex vertex = pop[i][j]; //std::cout << "i= "<< i << " j=" << j<<"\n vertex= " << vertex << std::endl; ++count_vertices; //std::cout << "vertex = " << vertex << std::endl; @@ -98,7 +98,7 @@ struct Fitness_map // -> a free function } } - std::vector best_simplex = pop[simplex_id]; + std::vector best_simplex = pop[simplex_id]; //Matrix temp = best_simplex[vertex_id]; return best_simplex[vertex_id]; @@ -107,13 +107,13 @@ struct Fitness_map // -> a free function double get_best_fitness_value(const Matrix& data) { - Matrix best_mat = get_best(); + Vertex best_mat = get_best(); return compute_fitness(best_mat, data); } - const Matrix points; - Population pop; + const Matrix points; // or just a reference? + Population pop; }; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index f3564144794..c6b4050650e 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -42,16 +42,15 @@ namespace CGAL { namespace Optimal_bounding_box { -template -void evolution(Matrix& R, Matrix& points, std::size_t max_generations) // todo: points is const +template +void evolution(Vertex& R, Matrix& points, std::size_t max_generations) // todo: points is const { - CGAL_assertion(points.rows() >= 3); CGAL_assertion(points.cols() == 3); CGAL_assertion(R.rows() == 3); CGAL_assertion(R.cols() == 3); - Population pop(50); + Population pop(50); std::size_t nelder_mead_iterations = 20; double prev_fit_value = 0; @@ -89,7 +88,7 @@ void evolution(Matrix& R, Matrix& points, std::size_t max_generations) // todo: #endif // stopping criteria - Fitness_map fitness_map(pop, points); + Fitness_map fitness_map(pop, points); new_fit_value = fitness_map.get_best_fitness_value(points); double difference = new_fit_value - prev_fit_value; @@ -102,27 +101,30 @@ void evolution(Matrix& R, Matrix& points, std::size_t max_generations) // todo: prev_fit_value = new_fit_value; } - Fitness_map fitness_map(pop, points); + Fitness_map fitness_map(pop, points); R = fitness_map.get_best(); } // works on matrices only -template -void post_processing(Matrix& points, Matrix& R, Matrix& obb) +template +void post_processing(Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) { + CGAL_assertion(points.cols() == 3); + CGAL_assertion(R.rows() == 3); + CGAL_assertion(R.cols() == 3); + CGAL_assertion(obb.rows() == 8); + CGAL_assertion(obb.cols() == 3); // 1) rotate points with R - - Matrix rotated_points(points.rows(), points.cols()); + Matrix_dynamic rotated_points(points.rows(), points.cols()); rotated_points = points * R.transpose(); // 2) get AABB from rotated points - typedef CGAL::Simple_cartesian K; typedef K::Point_3 Point; std::vector v_points; // Simplex -> std::vector - for(int i = 0; i < rotated_points.rows(); ++i) + for(std::size_t i = 0; i < rotated_points.rows(); ++i) { Point p(rotated_points(i, 0), rotated_points(i, 1), rotated_points(i, 2)); v_points.push_back(p); @@ -131,8 +133,12 @@ void post_processing(Matrix& points, Matrix& R, Matrix& obb) bbox = bbox_3(v_points.begin(), v_points.end()); K::Iso_cuboid_3 ic(bbox); - Matrix aabb(8, 3); - for(int i = 0; i < 8; ++i) + Matrix_fixed aabb; + // preallocate sanity: if Matrix is not preallocated in compile time + if(aabb.cols() != 3 && aabb.rows() != 8) + aabb.resize(8, 3); + + for(std::size_t i = 0; i < 8; ++i) { aabb(i, 0) = ic[i].x(); aabb(i, 1) = ic[i].y(); @@ -140,10 +146,7 @@ void post_processing(Matrix& points, Matrix& R, Matrix& obb) } // 3) apply inverse rotation to rotated AABB - obb = aabb * R; - - } template @@ -173,8 +176,9 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u obb_points.resize(8); CGAL_assertion(obb_points.size() == 8); - - typedef Eigen::MatrixXd MatrixXd; // using eigen internally + // using eigen internally + typedef Eigen::MatrixXd MatrixXd; // for point data + typedef Eigen::Matrix3d Matrix3d; // for matrices in simplices MatrixXd points_mat; // get the ch3 @@ -195,11 +199,11 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u fill_matrix(points, points_mat); } - MatrixXd R(3, 3); + Matrix3d R; std::size_t max_generations = 100; CGAL::Optimal_bounding_box::evolution(R, points_mat, max_generations); - MatrixXd obb(8, 3); + Eigen::Matrix obb; CGAL::Optimal_bounding_box::post_processing(points_mat, R, obb); // matrix -> vector diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h index 384ab5cafcb..7fbaff60052 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h @@ -37,7 +37,6 @@ namespace CGAL { namespace Optimal_bounding_box { -template struct Comparator { Comparator(std::vector in) : fitness(in) {} @@ -54,8 +53,8 @@ struct Comparator // points: point coords // simplex: 4 roation matrices are its vertices -template -void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_iterations) +template +void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_iterations) { CGAL_assertion(simplex.size() == 4); // tetrahedron @@ -68,7 +67,7 @@ void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_it for(std::size_t t = 0; t < nb_iterations; ++t) { - for(int i = 0; i < 4; ++i) + for(std::size_t i = 0; i < 4; ++i) { fitness[i] = compute_fitness(simplex[i], points); } @@ -82,7 +81,7 @@ void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_it // get indices of sorted sequence - Comparator compare_indices(fitness); + Comparator compare_indices(fitness); std::sort(indices.begin(), indices.end(), compare_indices); @@ -98,7 +97,7 @@ void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_it // new sorted simplex & fitness - std::vector s_simplex(4); + std::vector s_simplex(4); std::vector s_fitness(4); for(int i = 0; i < 4; ++i) { @@ -110,11 +109,11 @@ void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_it fitness = s_fitness; // centroid - const Matrix v_centroid = centroid(simplex[0], simplex[1], simplex[2]); + const Vertex v_centroid = centroid(simplex[0], simplex[1], simplex[2]); // find worst's vertex reflection - const Matrix v_worst = simplex[3]; - const Matrix v_refl = reflection(v_centroid, v_worst); + const Vertex v_worst = simplex[3]; + const Vertex v_refl = reflection(v_centroid, v_worst); const double f_refl = compute_fitness(v_refl, points); if(f_refl < fitness[2]) @@ -127,7 +126,7 @@ void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_it else { // expansion - const Matrix v_expand = expansion(v_centroid, v_worst, v_refl); + const Vertex v_expand = expansion(v_centroid, v_worst, v_refl); const double f_expand = compute_fitness(v_expand, points); if(f_expand < f_refl) simplex[3] = v_expand; @@ -137,7 +136,7 @@ void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_it } else // if reflected vertex is not better { - const Matrix v_mean = mean(v_centroid, v_worst); + const Vertex v_mean = mean(v_centroid, v_worst); const double f_mean = compute_fitness(v_mean, points); if(f_mean <= fitness[3]) // contraction of worst @@ -145,9 +144,9 @@ void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_it else { // reduction: move all vertices towards the best - for(int i=1; i < 4; ++i) + for(std::size_t i=1; i < 4; ++i) { - simplex[i] = mean(simplex[i], simplex[0]); // todo: test order of addition + simplex[i] = mean(simplex[i], simplex[0]); } } } @@ -172,8 +171,8 @@ struct Random_int_generator }; -template -void genetic_algorithm(Population& pop, Simplex& points) +template +void genetic_algorithm(Population& pop, Matrix& points) { // random permutations std::size_t m = pop.size(); @@ -206,7 +205,6 @@ void genetic_algorithm(Population& pop, Simplex& points) [&rng, &m] () { return rng.get_int(0, m); }); - Population group1(m/2), group2(m/2); Population group3(m - m/2), group4(m - m/2); diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index 6ea889b2466..af3450df557 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -24,54 +24,47 @@ #include #include - #include #include namespace CGAL { - namespace Optimal_bounding_box { - template class Population { - - typedef std::vector Individual; + typedef std::vector Simplex; public: - Population(std::size_t size) : n(size), random_generator(CGAL::Random(1)) + Population(std::size_t size) : n(size), random_generator(CGAL::Random()) { - //std::cout << "seed= " << random_generator.get_seed() << std::endl; - // reserve pop space pop.reserve(n); - // create individuals + // create simplices for(std::size_t i = 0 ; i < n; ++i) { - Individual member(4); - create_individual(member); - CGAL_assertion(member.size() == 4); - pop.push_back(member); + Simplex simplex(4); + create_simplex(simplex); + CGAL_assertion(simplex.size() == 4); + pop.push_back(simplex); } } void show_population() { std::size_t id = 0; - for(const Individual i : pop) + for(const Simplex i : pop) { CGAL_assertion(i.size() == 4); - std:: cout << "Individual: "<< id++ << std::endl; + std:: cout << "Simplex: "<< id++ << std::endl; for(const Matrix R : i) { std::cout << R; // eigen out std::cout << "\n\n"; } - std:: cout << std:: endl; } } @@ -81,15 +74,14 @@ public: return n; } - // access simplex - Individual& operator[](std::size_t i) + Simplex& operator[](std::size_t i) { CGAL_assertion(i < n); return pop[i]; } - const Individual& operator[](std::size_t i) const + const Simplex& operator[](std::size_t i) const { CGAL_assertion(i < n); return pop[i]; @@ -98,24 +90,26 @@ public: private: // create random population - void create_individual(Individual& member) + void create_simplex(Simplex& simplex) { - CGAL_assertion(member.size() == 4); - + CGAL_assertion(simplex.size() == 4); for(std::size_t i = 0; i < 4; ++i) { - // create matrix - Matrix R(3,3); - create_simplex(R); - Matrix Q; - qr_factorization(R, Q); - member[i] = Q; - } + Matrix R; + // R may be preallocated, if Vertex is Matrix3d, + // but Vertex may not, if Vertex is MatrixXd and R is constructed with MatrixXd R(3,3) + if(R.cols() == 0 || R.rows() == 0) + R.resize(3, 3); - CGAL_assertion(member.size() == 4); + create_vertex(R); + Matrix Q; // no allocation + qr_factorization(R, Q); + simplex[i] = Q; + } + CGAL_assertion(simplex.size() == 4); } - void create_simplex(Matrix& R) + void create_vertex(Matrix& R) { CGAL_assertion(R.rows() == 3); CGAL_assertion(R.cols() == 3); @@ -131,8 +125,7 @@ private: CGAL::Random random_generator; std::size_t n; - std::vector pop; - + std::vector pop; }; diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index bfb618d7731..a36313eacce 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -1,36 +1,26 @@ -#include -#include - #include #include #include - #include #include - #include -//typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -//typedef CGAL::Surface_mesh Surface_mesh; - -typedef Eigen::MatrixXf MatrixXf; +typedef Eigen::Matrix3d Matrix3d; bool assert_doubles(double d1, double d2, double epsilon) { return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; } - void test_qr_factorization() { - - MatrixXf A(3, 3); + Matrix3d A(3, 3); A << 0.3011944, 0.9932761, 0.5483701, 0.5149142, 0.5973263, 0.5162336, 0.0039213, 0.0202949, 0.9240308; - MatrixXf Q; + Matrix3d Q; CGAL::Optimal_bounding_box::qr_factorization(A, Q); double epsilon = 1e-6; @@ -43,20 +33,17 @@ void test_qr_factorization() CGAL_assertion(assert_doubles(Q(2,0), -0.006573, epsilon)); CGAL_assertion(assert_doubles(Q(2,1), 0.024478, epsilon)); CGAL_assertion(assert_doubles(Q(2,2), 0.999679, epsilon)); - - } - void test_fitness_function() { - MatrixXf data_points(4, 3); + Eigen::Matrix data_points(4, 3); data_points << 0.866802, 0.740808, 0.895304, 0.912651, 0.761565, 0.160330, 0.093661, 0.892578, 0.737412, 0.166461, 0.149912, 0.364944; - MatrixXf rotation(3, 3); + Matrix3d rotation(3, 3); rotation << -0.809204, 0.124296, 0.574230, -0.574694, 0.035719, -0.817589, -0.122134, -0.991602, 0.042528; @@ -66,20 +53,19 @@ void test_fitness_function() } - void test_simplex_operations() { - MatrixXf Sc(3, 3); + Matrix3d Sc(3, 3); Sc << -0.809204, 0.124296, 0.574230, -0.574694, 0.035719, -0.817589, -0.122134, -0.991602, 0.042528; - MatrixXf S_worst(3, 3); + Matrix3d S_worst(3, 3); S_worst << -0.45070, -0.32769, -0.83035, -0.13619, -0.89406, 0.42675, -0.88222, 0.30543, 0.35833; - MatrixXf Sr = CGAL::Optimal_bounding_box::reflection(Sc, S_worst); + Matrix3d Sr = CGAL::Optimal_bounding_box::reflection(Sc, S_worst); double epsilon = 1e-5; CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); @@ -91,7 +77,7 @@ void test_simplex_operations() CGAL_assertion(assert_doubles(Sr(2,1), 0.25411, epsilon)); CGAL_assertion(assert_doubles(Sr(2,2), -0.56300, epsilon)); - MatrixXf Se = CGAL::Optimal_bounding_box::expansion(Sc, S_worst, Sr); + Matrix3d Se = CGAL::Optimal_bounding_box::expansion(Sc, S_worst, Sr); CGAL_assertion(assert_doubles(Se(0,0), -0.87991, epsilon)); CGAL_assertion(assert_doubles(Se(0,1), 0.36105, epsilon)); CGAL_assertion(assert_doubles(Se(0,2), -0.30888, epsilon)); @@ -102,17 +88,17 @@ void test_simplex_operations() CGAL_assertion(assert_doubles(Se(2,1), -0.48595, epsilon)); CGAL_assertion(assert_doubles(Se(2,2), 0.74300, epsilon)); - MatrixXf S_a(3, 3); + Matrix3d S_a(3, 3); S_a << -0.277970, 0.953559, 0.116010, -0.567497, -0.065576, -0.820760, -0.775035, -0.293982, 0.559370; - MatrixXf S_b(3, 3); + Matrix3d S_b(3, 3); S_b << -0.419979, 0.301765, -0.855894, -0.653011, -0.755415, 0.054087, -0.630234, 0.581624, 0.514314; - MatrixXf S_c = CGAL::Optimal_bounding_box::mean(S_a, S_b); + Matrix3d S_c = CGAL::Optimal_bounding_box::mean(S_a, S_b); CGAL_assertion(assert_doubles(S_c(0,0), -0.35111, epsilon)); CGAL_assertion(assert_doubles(S_c(0,1), 0.79308, epsilon)); CGAL_assertion(assert_doubles(S_c(0,2), -0.49774, epsilon)); @@ -122,28 +108,26 @@ void test_simplex_operations() CGAL_assertion(assert_doubles(S_c(2,0), -0.70693, epsilon)); CGAL_assertion(assert_doubles(S_c(2,1), 0.12405, epsilon)); CGAL_assertion(assert_doubles(S_c(2,2), 0.69632, epsilon)); - } void test_centroid() { - MatrixXf S_a(3, 3); + Matrix3d S_a(3, 3); S_a << -0.588443, 0.807140, -0.047542, -0.786228, -0.584933, -0.199246, -0.188629, -0.079867, 0.978795; - MatrixXf S_b(3, 3); + Matrix3d S_b(3, 3); S_b << -0.2192721, 0.2792986, -0.9348326, -0.7772152, -0.6292092, -0.0056861, -0.5897934, 0.7253193, 0.3550431; - MatrixXf S_c(3, 3); + Matrix3d S_c(3, 3); S_c << -0.32657, -0.60013, -0.73020, -0.20022, -0.71110, 0.67398, -0.92372, 0.36630, 0.11207; - - MatrixXf S_centroid = CGAL::Optimal_bounding_box::centroid(S_a, S_b, S_c); + Matrix3d S_centroid = CGAL::Optimal_bounding_box::centroid(S_a, S_b, S_c); double epsilon = 1e-5; CGAL_assertion(assert_doubles(S_centroid(0,0), -0.419979, epsilon)); CGAL_assertion(assert_doubles(S_centroid(0,1), 0.301765, epsilon)); @@ -154,23 +138,14 @@ void test_centroid() CGAL_assertion(assert_doubles(S_centroid(2,0), -0.630234, epsilon)); CGAL_assertion(assert_doubles(S_centroid(2,1), 0.581624, epsilon)); CGAL_assertion(assert_doubles(S_centroid(2,2), 0.514314, epsilon)); - } - - - - - int main() { - test_qr_factorization(); test_fitness_function(); test_simplex_operations(); test_centroid(); - - return 0; } diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index c8569c758e9..e2d555d6403 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -1,17 +1,15 @@ #include #include - #include #include #include - #include #include - #include typedef Eigen::MatrixXd MatrixXd; +typedef Eigen::Matrix3d Matrix3d; typedef CGAL::Exact_predicates_inexact_constructions_kernel K; @@ -62,38 +60,38 @@ double calculate_volume(std::vector points) void test_population() { - CGAL::Optimal_bounding_box::Population pop(5); + CGAL::Optimal_bounding_box::Population pop(5); //pop.show_population(); CGAL_assertion(pop.size() == 5); } void test_nelder_mead() { - MatrixXd data_points(4, 3); + Eigen::Matrix data_points(4, 3); data_points << 0.866802, 0.740808, 0.895304, 0.912651, 0.761565, 0.160330, 0.093661, 0.892578, 0.737412, 0.166461, 0.149912, 0.364944; // one simplex - std::vector simplex(4); + std::vector simplex(4); - MatrixXd v0(3, 3); + Matrix3d v0; v0 << -0.2192721, 0.2792986, -0.9348326, -0.7772152, -0.6292092, -0.0056861, -0.5897934, 0.7253193, 0.3550431; - MatrixXd v1(3, 3); + Matrix3d v1; v1 << -0.588443, 0.807140, -0.047542, -0.786228, -0.584933, -0.199246, -0.188629, -0.079867, 0.978795; - MatrixXd v2(3, 3); + Matrix3d v2; v2 << -0.277970, 0.953559, 0.116010, -0.567497, -0.065576, -0.820760, -0.775035, -0.293982, 0.559370; - MatrixXd v3(3, 3); + Matrix3d v3; v3 << -0.32657, -0.60013, -0.73020, -0.20022, -0.71110, 0.67398, -0.92372, 0.36630, 0.11207; @@ -108,7 +106,7 @@ void test_nelder_mead() double epsilon = 1e-5; - MatrixXd v0_new = simplex[0]; + Matrix3d v0_new = simplex[0]; CGAL_assertion(assert_doubles(v0_new(0,0), -0.288975, epsilon)); CGAL_assertion(assert_doubles(v0_new(0,1), 0.7897657, epsilon)); CGAL_assertion(assert_doubles(v0_new(0,2), -0.541076, epsilon)); @@ -119,7 +117,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v0_new(2,1), 0.5111260, epsilon)); CGAL_assertion(assert_doubles(v0_new(2,2), 0.84094, epsilon)); - MatrixXd v1_new = simplex[1]; + Matrix3d v1_new = simplex[1]; CGAL_assertion(assert_doubles(v1_new(0,0), -0.458749, epsilon)); CGAL_assertion(assert_doubles(v1_new(0,1), 0.823283, epsilon)); CGAL_assertion(assert_doubles(v1_new(0,2), -0.334296, epsilon)); @@ -130,7 +128,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v1_new(2,1), 0.338040, epsilon)); CGAL_assertion(assert_doubles(v1_new(2,2), 0.937987, epsilon)); - MatrixXd v2_new = simplex[2]; + Matrix3d v2_new = simplex[2]; CGAL_assertion(assert_doubles(v2_new(0,0), -0.346582, epsilon)); CGAL_assertion(assert_doubles(v2_new(0,1), 0.878534, epsilon)); CGAL_assertion(assert_doubles(v2_new(0,2), -0.328724, epsilon)); @@ -141,7 +139,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v2_new(2,1), 0.334057, epsilon)); CGAL_assertion(assert_doubles(v2_new(2,2), 0.941423, epsilon)); - MatrixXd v3_new = simplex[3]; + Matrix3d v3_new = simplex[3]; CGAL_assertion(assert_doubles(v3_new(0,0), -0.394713, epsilon)); CGAL_assertion(assert_doubles(v3_new(0,1), 0.791782, epsilon)); CGAL_assertion(assert_doubles(v3_new(0,2), -0.466136, epsilon)); @@ -155,20 +153,20 @@ void test_nelder_mead() void test_genetic_algorithm() { - MatrixXd data_points(4, 3); + Eigen::Matrix data_points(4, 3); data_points << 0.866802, 0.740808, 0.895304, 0.912651, 0.761565, 0.160330, 0.093661, 0.892578, 0.737412, 0.166461, 0.149912, 0.364944; - CGAL::Optimal_bounding_box::Population pop(5); + CGAL::Optimal_bounding_box::Population pop(5); CGAL::Optimal_bounding_box::genetic_algorithm(pop, data_points); CGAL_assertion(pop.size() == 5); } void test_random_unit_tetra() { - MatrixXd data_points(4, 3); // points on their convex hull + Eigen::Matrix data_points(4, 3); // points on their convex hull data_points << 0.866802, 0.740808, 0.895304, 0.912651, 0.761565, 0.160330, 0.093661, 0.892578, 0.737412, @@ -192,7 +190,7 @@ void test_random_unit_tetra() out.close(); #endif - MatrixXd R(3, 3); + Matrix3d R; std::size_t generations = 10; CGAL::Optimal_bounding_box::evolution(R, data_points, generations); @@ -229,7 +227,7 @@ void test_reference_tetrahedron(const char* fname) MatrixXd points; sm_to_matrix(mesh, points); - MatrixXd R(3, 3); + Matrix3d R(3, 3); std::size_t generations = 10; CGAL::Optimal_bounding_box::evolution(R, points, generations); double epsilon = 1e-5; @@ -256,7 +254,7 @@ void test_long_tetrahedron(std::string fname) MatrixXd points; sm_to_matrix(mesh, points); - MatrixXd R(3, 3); + MatrixXd R(3, 3); // test with dynamic size std::size_t generations = 10; CGAL::Optimal_bounding_box::evolution(R, points, generations); double epsilon = 1e-3; @@ -348,7 +346,6 @@ bench(const char* fname) { std::vector sm_points, obb_points; std::ifstream in(fname); - //double x,y,z; K::Point_3 p; int i = 0; while(in >> p){ @@ -365,20 +362,20 @@ bench(const char* fname) std::cout << "number of points= " << sm_points.size() << std::endl; - std::cout.precision(17); CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true); -/* + /* + std::cout.precision(17); for(int i =0; i < obb_points.size(); i ++){ std::cout << obb_points[i] << std::endl; } - */ + */ CGAL::Surface_mesh mesh; CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], obb_points[4], obb_points[5], obb_points[6], obb_points[7], mesh); - std::ofstream out("/tmp/octopus_result.off"); + std::ofstream out("/tmp/result_obb.off"); out << mesh; out.close(); @@ -388,6 +385,7 @@ bench(const char* fname) int main(int argc, char* argv[]) { + /* test_population(); test_nelder_mead(); @@ -398,6 +396,7 @@ int main(int argc, char* argv[]) test_find_obb("data/random_unit_tetra.off"); */ + bench(argv[1]); return 0; diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp index e8accbf0dbd..6c158b9e8a8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp @@ -1,5 +1,4 @@ #include - #include #include From eb9cb4b8ebdae475c735c63e8289dc123f3648c4 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 4 May 2018 11:23:40 +0100 Subject: [PATCH 019/150] VC++ has a problem accessing matrix entries with operator() --- .../include/CGAL/Optimal_bounding_box/obb.h | 16 ++++++++-------- .../CGAL/Optimal_bounding_box/population.h | 2 +- .../test_optimization_algorithms.cpp | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index c6b4050650e..c0a295638d3 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -126,7 +126,7 @@ void post_processing(Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) std::vector v_points; // Simplex -> std::vector for(std::size_t i = 0; i < rotated_points.rows(); ++i) { - Point p(rotated_points(i, 0), rotated_points(i, 1), rotated_points(i, 2)); + Point p(rotated_points.coeff(i, 0), rotated_points.coeff(i, 1), rotated_points.coeff(i, 2)); v_points.push_back(p); } CGAL::Bbox_3 bbox; @@ -140,9 +140,9 @@ void post_processing(Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) for(std::size_t i = 0; i < 8; ++i) { - aabb(i, 0) = ic[i].x(); - aabb(i, 1) = ic[i].y(); - aabb(i, 2) = ic[i].z(); + aabb.coeffRef(i, 0) = ic[i].x(); + aabb.coeffRef(i, 1) = ic[i].y(); + aabb.coeffRef(i, 2) = ic[i].z(); } // 3) apply inverse rotation to rotated AABB @@ -156,9 +156,9 @@ void fill_matrix(std::vector& v_points, Matrix& points_mat) for(std::size_t i = 0; i < v_points.size(); ++i) { Point p = v_points[i]; - points_mat(i, 0) = p.x(); - points_mat(i, 1) = p.y(); - points_mat(i, 2) = p.z(); + points_mat.coeffRef(i, 0) = p.x(); + points_mat.coeffRef(i, 1) = p.y(); + points_mat.coeffRef(i, 2) = p.z(); } } @@ -209,7 +209,7 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u // matrix -> vector for(std::size_t i = 0; i < 8; ++i) { - Point p(obb(i, 0), obb(i, 1), obb(i, 2)); + Point p(obb.coeff(i, 0), obb.coeff(i, 1), obb.coeff(i, 2)); obb_points[i] = p; } } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index af3450df557..ab5e27299c8 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -118,7 +118,7 @@ private: { for(std::size_t j = 0; j < 3; ++j) { - R(i, j) = random_generator.get_double(); + R.coeffRef(i, j) = random_generator.get_double(); } } } diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index e2d555d6403..ef3a076aba5 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -32,9 +32,9 @@ void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) for(vertex_descriptor v : vertices(sm)) { Point_ref p = get(vpm, v); - mat(i, 0) = p.x(); - mat(i, 1) = p.y(); - mat(i, 2) = p.z(); + mat.coeffRef(i, 0) = p.x(); + mat.coeffRef(i, 1) = p.y(); + mat.coeffRef(i, 2) = p.z(); ++i; } } From 0fef43ef0344566c87ee89bb78e3ff8b3dd4e624 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 4 May 2018 13:53:30 +0100 Subject: [PATCH 020/150] Do not do a matrix-matrix multiplication, but do N matrix-vector multiplications as we only want min and max --- .../Optimal_bounding_box/fitness_function.h | 25 ++++++++++++++++++- .../test_optimization_algorithms.cpp | 8 +++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 249ef98e069..a9592dde168 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -42,6 +42,27 @@ const double compute_fitness(const Vertex& R, const Matrix& data) CGAL_assertion(data.rows() >= 3); // rotate points + +#if 1 + double xmin, xmax, ymin, ymax, zmin, zmax; + for(int i = 0; i < data.rows(); i++){ + Eigen::Vector3d vec = data.row(i); + vec = R * vec; + if(i == 0){ + xmin = xmax = vec.coeff(0); + ymin = ymax = vec.coeff(1); + zmin = zmax = vec.coeff(2); + }else { + if(vec.coeff(0) < xmin) xmin = vec.coeff(0); + if(vec.coeff(1) < ymin) ymin = vec.coeff(1); + if(vec.coeff(2) < zmin) zmin = vec.coeff(2); + if(vec.coeff(0) > xmax) xmax = vec.coeff(0); + if(vec.coeff(1) > ymax) ymax = vec.coeff(1); + if(vec.coeff(2) > zmax) zmax = vec.coeff(2); + } + } + +#else Vertex RT = R.transpose(); Matrix rotated_data; rotated_data = data * RT; @@ -55,7 +76,9 @@ const double compute_fitness(const Vertex& R, const Matrix& data) double ymax = rotated_data.col(1).maxCoeff(); double zmin = rotated_data.col(2).minCoeff(); double zmax = rotated_data.col(2).maxCoeff(); - + +#endif + double x_dim = abs(xmax - xmin); // abs needed? double y_dim = abs(ymax - ymin); double z_dim = abs(zmax - zmin); diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index ef3a076aba5..27e05b709a7 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -362,14 +362,14 @@ bench(const char* fname) std::cout << "number of points= " << sm_points.size() << std::endl; - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true); + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, false); - /* + std::cout.precision(17); for(int i =0; i < obb_points.size(); i ++){ std::cout << obb_points[i] << std::endl; } - */ + /* CGAL::Surface_mesh mesh; CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], obb_points[4], obb_points[5], @@ -378,7 +378,7 @@ bench(const char* fname) std::ofstream out("/tmp/result_obb.off"); out << mesh; out.close(); - + */ } From 7b79685c275709d6e3ffa68daaf81f2cc4e1af8e Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Fri, 4 May 2018 15:47:42 +0200 Subject: [PATCH 021/150] cleaning --- .../Optimal_bounding_box/fitness_function.h | 67 ++------- .../include/CGAL/Optimal_bounding_box/obb.h | 55 ++++---- .../optimization_algorithms.h | 29 +--- .../test_optimization_algorithms.cpp | 127 +++++++----------- 4 files changed, 94 insertions(+), 184 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index a9592dde168..96146b6cb58 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -30,10 +30,9 @@ namespace CGAL { namespace Optimal_bounding_box { -template +template const double compute_fitness(const Vertex& R, const Matrix& data) { - // R: rotation matrix CGAL_assertion(R.cols() == 3); CGAL_assertion(R.rows() == 3); @@ -41,13 +40,12 @@ const double compute_fitness(const Vertex& R, const Matrix& data) CGAL_assertion(data.cols() == 3); CGAL_assertion(data.rows() >= 3); - // rotate points - -#if 1 double xmin, xmax, ymin, ymax, zmin, zmax; for(int i = 0; i < data.rows(); i++){ + Eigen::Vector3d vec = data.row(i); vec = R * vec; + if(i == 0){ xmin = xmax = vec.coeff(0); ymin = ymax = vec.coeff(1); @@ -62,56 +60,30 @@ const double compute_fitness(const Vertex& R, const Matrix& data) } } -#else - Vertex RT = R.transpose(); - Matrix rotated_data; - rotated_data = data * RT; - CGAL_assertion(rotated_data.cols() == data.cols()); - CGAL_assertion(rotated_data.rows() == data.rows()); - - // AABB: take mins and maxs - double xmin = rotated_data.col(0).minCoeff(); - double xmax = rotated_data.col(0).maxCoeff(); - double ymin = rotated_data.col(1).minCoeff(); - double ymax = rotated_data.col(1).maxCoeff(); - double zmin = rotated_data.col(2).minCoeff(); - double zmax = rotated_data.col(2).maxCoeff(); - -#endif - - double x_dim = abs(xmax - xmin); // abs needed? - double y_dim = abs(ymax - ymin); - double z_dim = abs(zmax - zmin); + CGAL_assertion(xmax > xmin); + CGAL_assertion(ymax > ymin); + CGAL_assertion(zmax > zmin); // volume - return (x_dim * y_dim * z_dim); - + return ((xmax - xmin) * (ymax - ymin) * (zmax - zmin)); } template -struct Fitness_map // -> a free function +struct Fitness_map { Fitness_map(Population& p, Matrix& points) : pop(p), points(points) {} - Vertex get_best() + const Vertex get_best() { - std::size_t count_vertices = 0; - - std::size_t simplex_id; - std::size_t vertex_id; + std::size_t simplex_id, vertex_id; double best_fitness = std::numeric_limits::max(); for(std::size_t i = 0; i < pop.size(); ++i) { for(std::size_t j =0; j < 4; ++j) { const Vertex vertex = pop[i][j]; - //std::cout << "i= "<< i << " j=" << j<<"\n vertex= " << vertex << std::endl; - ++count_vertices; - //std::cout << "vertex = " << vertex << std::endl; - const double fitness = compute_fitness(vertex, points); - //std::cout << "fitness = " << fitness << std::endl; if (fitness < best_fitness) { simplex_id = i; @@ -121,30 +93,19 @@ struct Fitness_map // -> a free function } } - std::vector best_simplex = pop[simplex_id]; - //Matrix temp = best_simplex[vertex_id]; - - return best_simplex[vertex_id]; + return pop[simplex_id][vertex_id]; } - - double get_best_fitness_value(const Matrix& data) + const double get_best_fitness_value(const Matrix& data) { Vertex best_mat = get_best(); return compute_fitness(best_mat, data); } - - const Matrix points; // or just a reference? - Population pop; + const Matrix& points; + Population& pop; }; - - - - - - }} // end namespaces diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index c0a295638d3..c58a5c2adfb 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -30,14 +30,13 @@ #include #include #include - -#include - -#include // used draw mesh #include // used to get the ch #include #include +#include + + namespace CGAL { namespace Optimal_bounding_box { @@ -105,7 +104,6 @@ void evolution(Vertex& R, Matrix& points, std::size_t max_generations) // todo: R = fitness_map.get_best(); } - // works on matrices only template void post_processing(Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) @@ -179,6 +177,7 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u // using eigen internally typedef Eigen::MatrixXd MatrixXd; // for point data typedef Eigen::Matrix3d Matrix3d; // for matrices in simplices + MatrixXd points_mat; // get the ch3 @@ -214,35 +213,41 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u } } -// it is called after post processing -template -void matrix_to_mesh_and_draw(Matrix& data_points, std::string filename) +/// @param pmesh the input mesh. +/// @param obbmesh the obb in a hexahedron pmesh. +/// @param use convex hull or not. +/// +/// todo named parameters: max iterations, population size, tolerance. +template +void find_obb(PolygonMesh& pmesh , PolygonMesh& obbmesh, bool use_ch) { - typedef CGAL::Simple_cartesian K; - typedef K::Point_3 Point; - typedef CGAL::Surface_mesh Mesh; + CGAL_assertion(vertices(pmesh).size() >= 3); - // Simplex -> std::vector - std::vector points; - - for(int i = 0; i < data_points.rows(); ++i) + if(vertices(pmesh).size() <= 3) { - Point p(data_points(i, 0), data_points(i, 1), data_points(i, 2)); - points.push_back(p); + std::cerr << "Not enough points in the mesh!\n"; + return; } - Mesh mesh; - CGAL::make_hexahedron(points[0], points[1], points[2], points[3], points[4], points[5], - points[6], points[7], mesh); + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::property_map::type Vpm; + typedef typename boost::property_traits::value_type Point; + //typedef typename Kernel_traits::Kernel Kernel; - std::ofstream out(filename); - out << mesh; - out.close(); + std::vector points; + Vpm pmap = get(boost::vertex_point, pmesh); + BOOST_FOREACH(vertex_descriptor v, vertices(pmesh)) + points.push_back(get(pmap, v)); + + std::vector obb_points; + find_obb(points, obb_points, use_ch); + + CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], + obb_points[4], obb_points[5], + obb_points[6], obb_points[7], obbmesh); } - - }} // end namespaces diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h index 7fbaff60052..3e7b45ddd11 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h @@ -49,12 +49,10 @@ struct Comparator std::vector fitness; }; - - // points: point coords -// simplex: 4 roation matrices are its vertices +// simplex: 4 rotation matrices are its vertices template -void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_iterations) +void nelder_mead(std::vector& simplex, const Matrix& points, std::size_t nb_iterations) { CGAL_assertion(simplex.size() == 4); // tetrahedron @@ -63,39 +61,20 @@ void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_it std::vector indices( boost::counting_iterator( 0 ), boost::counting_iterator( simplex.size() ) ); - for(std::size_t t = 0; t < nb_iterations; ++t) { - for(std::size_t i = 0; i < 4; ++i) { fitness[i] = compute_fitness(simplex[i], points); } - /* - for(const Matrix& v : simplex) - fitness.push_back(compute_fitness(v, points)); - */ CGAL_assertion(fitness.size() == 4); CGAL_assertion(indices.size() == 4); - // get indices of sorted sequence Comparator compare_indices(fitness); std::sort(indices.begin(), indices.end(), compare_indices); - - /* - for(int i =0 ; i < 4; ++i) - { - std::cout << simplex[i] << "\n"; - std::cout << "fitness= " << fitness[i] << "\n"; - std::cout << "index= " << indices[i] << "\n\n"; - } - std::cout << std::endl; - */ - - // new sorted simplex & fitness std::vector s_simplex(4); std::vector s_fitness(4); @@ -105,7 +84,7 @@ void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_it s_fitness[i] = fitness[indices[i]]; } - simplex = s_simplex; // swap? + simplex = s_simplex; fitness = s_fitness; // centroid @@ -172,7 +151,7 @@ struct Random_int_generator template -void genetic_algorithm(Population& pop, Matrix& points) +void genetic_algorithm(Population& pop, const Matrix& points) { // random permutations std::size_t m = pop.size(); diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 27e05b709a7..bb72757c76f 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -7,7 +7,6 @@ #include #include - typedef Eigen::MatrixXd MatrixXd; typedef Eigen::Matrix3d Matrix3d; @@ -39,14 +38,30 @@ void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) } } -template -void gather_mesh_points(SurfaceMesh& mesh, std::vector& points) +// it is called after post processing +template +void matrix_to_mesh_and_draw(Matrix& data_points, std::string filename) { - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::property_map::type PointPMap; - PointPMap pmap = get(boost::vertex_point, mesh); - BOOST_FOREACH(vertex_descriptor v, vertices(mesh)) - points.push_back(get(pmap, v)); + typedef CGAL::Simple_cartesian K; + typedef K::Point_3 Point; + typedef CGAL::Surface_mesh Mesh; + + // Simplex -> std::vector + std::vector points; + + for(int i = 0; i < data_points.rows(); ++i) + { + Point p(data_points(i, 0), data_points(i, 1), data_points(i, 2)); + points.push_back(p); + } + + Mesh mesh; + CGAL::make_hexahedron(points[0], points[1], points[2], points[3], points[4], points[5], + points[6], points[7], mesh); + + std::ofstream out(filename); + out << mesh; + out.close(); } template @@ -210,7 +225,7 @@ void test_random_unit_tetra() // postprocessing MatrixXd obb(8, 3); CGAL::Optimal_bounding_box::post_processing(data_points, R, obb); - CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, "data/random_unit_tetra_result.off"); + matrix_to_mesh_and_draw(obb, "data/random_unit_tetra_result.off"); #endif } @@ -237,7 +252,7 @@ void test_reference_tetrahedron(const char* fname) // postprocessing MatrixXd obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points, R, obb); - CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, "data/OBB.off"); + matrix_to_mesh_and_draw(obb, "data/OBB.off"); #endif } @@ -275,14 +290,15 @@ void test_long_tetrahedron(std::string fname) // postprocessing MatrixXd obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points, R, obb); - CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, fname + "result.off"); + matrix_to_mesh_and_draw(obb, fname + "result.off"); #endif } void test_find_obb(std::string fname) { std::ifstream input(fname); - CGAL::Surface_mesh mesh; + typedef CGAL::Surface_mesh SMesh; + SMesh mesh; if (!input || !(input >> mesh) || mesh.is_empty()) { std::cerr << fname << " is not a valid off file.\n"; exit(1); @@ -290,39 +306,16 @@ void test_find_obb(std::string fname) // get mesh points std::vector sm_points; - gather_mesh_points(mesh, sm_points); + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::property_map::const_type PointPMap; + PointPMap pmap = get(boost::vertex_point, mesh); + BOOST_FOREACH(vertex_descriptor v, vertices(mesh)) + sm_points.push_back(get(pmap, v)); std::vector obb_points; CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true); double epsilon = 1e-3; - /* - CGAL_assertion(assert_doubles(obb_points[0].x(), 1.01752, epsilon)); - CGAL_assertion(assert_doubles(obb_points[0].y(), 0.437675, epsilon)); - CGAL_assertion(assert_doubles(obb_points[0].z(), 0.382697, epsilon)); - CGAL_assertion(assert_doubles(obb_points[1].x(), 0.912648, epsilon)); - CGAL_assertion(assert_doubles(obb_points[1].y(), 0.761563, epsilon)); - CGAL_assertion(assert_doubles(obb_points[1].z(), 0.160329, epsilon)); - CGAL_assertion(assert_doubles(obb_points[2].x(), 0.0615854, epsilon)); - CGAL_assertion(assert_doubles(obb_points[2].y(), 0.473799, epsilon)); - CGAL_assertion(assert_doubles(obb_points[2].z(), 0.142574, epsilon)); - CGAL_assertion(assert_doubles(obb_points[3].x(), 0.166461, epsilon)); - CGAL_assertion(assert_doubles(obb_points[3].y(), 0.149911, epsilon)); - CGAL_assertion(assert_doubles(obb_points[3].z(), 0.364943, epsilon)); - CGAL_assertion(assert_doubles(obb_points[4].x(), 0.0316104, epsilon)); - CGAL_assertion(assert_doubles(obb_points[4].y(), 0.512247, epsilon)); - CGAL_assertion(assert_doubles(obb_points[4].z(), 0.956296, epsilon)); - CGAL_assertion(assert_doubles(obb_points[5].x(), 0.882673, epsilon)); - CGAL_assertion(assert_doubles(obb_points[5].y(), 0.800011, epsilon)); - CGAL_assertion(assert_doubles(obb_points[5].z(), 0.97405, epsilon)); - CGAL_assertion(assert_doubles(obb_points[6].x(), 0.777797, epsilon)); - CGAL_assertion(assert_doubles(obb_points[6].y(), 1.1239, epsilon)); - CGAL_assertion(assert_doubles(obb_points[6].z(), 0.751681, epsilon)); - CGAL_assertion(assert_doubles(obb_points[7].x(), -0.0732647, epsilon)); - CGAL_assertion(assert_doubles(obb_points[7].y(), 0.836134, epsilon)); - CGAL_assertion(assert_doubles(obb_points[7].z(), 0.733927, epsilon)); - */ - double vol = calculate_volume(obb_points); CGAL_assertion(assert_doubles(vol, 0.883371, epsilon)); @@ -341,52 +334,27 @@ void test_find_obb(std::string fname) #endif } -void -bench(const char* fname) +void test_find_obb_mesh(std::string fname) { - std::vector sm_points, obb_points; - std::ifstream in(fname); - K::Point_3 p; - int i = 0; - while(in >> p){ - - if(i % 2 == 0) - { - sm_points.push_back(p); - } - - ++i; + std::ifstream input(fname); + CGAL::Surface_mesh mesh; + if (!input || !(input >> mesh) || mesh.is_empty()) { + std::cerr << fname << " is not a valid off file.\n"; + exit(1); } - std::cout << "input data (points + normals)= " << i << std::endl; - std::cout << "number of points= " << sm_points.size() << std::endl; + CGAL::Surface_mesh obbmesh; + CGAL::Optimal_bounding_box::find_obb(mesh, obbmesh, true); - - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, false); - - - std::cout.precision(17); - for(int i =0; i < obb_points.size(); i ++){ - std::cout << obb_points[i] << std::endl; - } - /* - - CGAL::Surface_mesh mesh; - CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], obb_points[4], obb_points[5], - obb_points[6], obb_points[7], mesh); - - std::ofstream out("/tmp/result_obb.off"); - out << mesh; + #ifdef OBB_DEBUG_TEST + std::ofstream out("/tmp/result_elephant.off"); + out << obbmesh; out.close(); - */ + #endif } - - int main(int argc, char* argv[]) { - - /* test_population(); test_nelder_mead(); test_genetic_algorithm(); @@ -394,10 +362,7 @@ int main(int argc, char* argv[]) test_reference_tetrahedron("data/reference_tetrahedron.off"); test_long_tetrahedron("data/long_tetrahedron.off"); test_find_obb("data/random_unit_tetra.off"); - */ - - - bench(argv[1]); + test_find_obb_mesh("data/elephant.off"); return 0; } From 8f497d664f1cebdce589339c5350411eeac359bd Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Mon, 7 May 2018 14:33:31 +0200 Subject: [PATCH 022/150] benchmarks --- .../Optimal_bounding_box/CMakeLists.txt | 61 + .../Optimal_bounding_box/bench_custom.cpp | 64 + .../Optimal_bounding_box/bench_obb.cpp | 138 + .../Optimal_bounding_box/bench_perfomance.cpp | 78 + .../Optimal_bounding_box/data/elephant.off | 8337 +++++++++++++++++ .../Optimal_bounding_box/data/sphere_1k.xyz | 1050 +++ .../Optimal_bounding_box/data/elephant.off | 8337 +++++++++++++++++ 7 files changed, 18065 insertions(+) create mode 100644 Optimal_bounding_box/benchmark/Optimal_bounding_box/CMakeLists.txt create mode 100644 Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp create mode 100644 Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp create mode 100644 Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp create mode 100644 Optimal_bounding_box/benchmark/Optimal_bounding_box/data/elephant.off create mode 100644 Optimal_bounding_box/benchmark/Optimal_bounding_box/data/sphere_1k.xyz create mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/data/elephant.off diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/benchmark/Optimal_bounding_box/CMakeLists.txt new file mode 100644 index 00000000000..dd9fbe32d76 --- /dev/null +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/CMakeLists.txt @@ -0,0 +1,61 @@ +# Created by the script cgal_create_CMakeLists +# This is the CMake script for compiling a set of CGAL applications. + +project( Optimal_bounding_box_Benchmark ) + + +cmake_minimum_required(VERSION 2.6.2) +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6) + if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3) + cmake_policy(VERSION 2.8.4) + else() + cmake_policy(VERSION 2.6) + endif() +endif() + + +# CGAL and its components +find_package( CGAL QUIET COMPONENTS ) + +if ( NOT CGAL_FOUND ) + + message(STATUS "This project requires the CGAL library, and will not be compiled.") + return() + +endif() + +# include helper file +include( ${CGAL_USE_FILE} ) + + +# Boost and its components +find_package( Boost REQUIRED ) + +if ( NOT Boost_FOUND ) + + message(STATUS "This project requires the Boost library, and will not be compiled.") + + return() + +endif() + +# include for local directory + +# include for local package +include_directories( BEFORE ../../include ) + +find_package(Eigen3 3.2.0) #(requires 3.2.0 or greater) + +find_package( TBB ) + +include( CGAL_CreateSingleSourceCGALProgram ) +if (EIGEN3_FOUND) + include( ${EIGEN3_USE_FILE} ) + + create_single_source_cgal_program("bench_obb.cpp") + create_single_source_cgal_program("bench_perfomance.cpp") + create_single_source_cgal_program("bench_custom.cpp") + +endif(EIGEN3_FOUND) + + diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp new file mode 100644 index 00000000000..38d9413ca8c --- /dev/null +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//#define OBB_DEBUG_BENCHMARK + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +void +bench(const char* fname) +{ + std::vector sm_points, obb_points; + std::ifstream in(fname); + + K::Point_3 p; + int i = 0; + while(in >> p){ + + if(i % 2 == 0) // avoid normals + { + sm_points.push_back(p); + } + ++i; + } + + std::cout << "input data (points + normals)= " << i << std::endl; + std::cout << "number of points= " << sm_points.size() << std::endl; + + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, false); + + std::cout << "done" << '\n'; + +#ifdef OBB_DEBUG_BENCHMARK + std::cout.precision(17); + for(int i =0; i < obb_points.size(); i++) + { + std::cout << obb_points[i] << std::endl; + } + + CGAL::Surface_mesh mesh; + CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], obb_points[4], obb_points[5], + obb_points[6], obb_points[7], mesh); + + std::ofstream out("/tmp/result_obb.off"); + out << mesh; + out.close(); +#endif + +} + +int main(int argc, char* argv[]) +{ + bench(argv[1]); + + return 0; +} diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp new file mode 100644 index 00000000000..d4ad8de002a --- /dev/null +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//#define OBB_DEBUG_BENCHMARK + + +typedef Eigen::MatrixXd MatrixXd; +typedef Eigen::Matrix3d Matrix3d; + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + + +bool assert_doubles(double d1, double d2, double epsilon) +{ + return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; +} + +/* +template +void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) +{ + typedef typename boost::property_map::const_type Vpm; + typedef typename boost::property_traits::reference Point_ref; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + Vpm vpm = get(boost::vertex_point, sm); + + mat.resize(vertices(sm).size(), 3); + std::size_t i = 0; + for(vertex_descriptor v : vertices(sm)) + { + Point_ref p = get(vpm, v); + mat(i, 0) = p.x(); + mat(i, 1) = p.y(); + mat(i, 2) = p.z(); + ++i; + } +} +*/ + +template +void gather_mesh_points(SurfaceMesh& mesh, std::vector& points) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::property_map::type PointPMap; + PointPMap pmap = get(boost::vertex_point, mesh); + BOOST_FOREACH(vertex_descriptor v, vertices(mesh)) + points.push_back(get(pmap, v)); +} + +template +double calculate_volume(std::vector points) +{ + CGAL::Bbox_3 bbox; + bbox = bbox_3(points.begin(), points.end()); + K::Iso_cuboid_3 ic(bbox); + return ic.volume(); +} + +void bench_finding_obb(std::string fname) +{ + std::ifstream input(fname); + + std::vector sm_points; + + // import a mesh + CGAL::Surface_mesh mesh; + if (!input || !(input >> mesh) || mesh.is_empty()) { + std::cerr << fname << " is not a valid off file.\n"; + exit(1); + } + // get mesh points + gather_mesh_points(mesh, sm_points); + + CGAL::Timer timer; + timer.start(); + + // 1) using convex hull + std::vector obb_points1; + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points1, true); + + timer.stop(); + std::cout << "found obb with convex hull: " << timer.time() << " seconds\n"; + + timer.reset(); + timer.start(); + + // 2) without convex hull + std::vector obb_points2; + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points2, false); + + timer.stop(); + + std::cout << "found obb without convex hull: " << timer.time() << " seconds\n"; + timer.reset(); + + + double epsilon = 1e-3; + double vol1 = calculate_volume(obb_points1); + double vol2 = calculate_volume(obb_points2); + //std::cout << "vol1= " << vol1 << " -- " << "vol2= " << vol2 << std::endl; + + +#ifdef OBB_DEBUG_BENCHMARK + CGAL::Surface_mesh result_mesh1; + CGAL::make_hexahedron(obb_points1[0], obb_points1[1], obb_points1[2], obb_points1[3], + obb_points1[4], obb_points1[5], obb_points1[6], obb_points1[7], + result_mesh1); + + + CGAL::Surface_mesh result_mesh2; + CGAL::make_hexahedron(obb_points2[0], obb_points2[1], obb_points2[2], obb_points2[3], + obb_points2[4], obb_points2[5], obb_points2[6], obb_points2[7], + result_mesh2); + + std::ofstream out1("data/obb_result1.off"); + out1 << result_mesh1; + out1.close(); + + std::ofstream out2("data/obb_result2.off"); + out2 << result_mesh2; + out2.close(); +#endif +} + +int main(int argc, char* argv[]) +{ + bench_finding_obb("data/elephant.off"); + + return 0; +} diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp new file mode 100644 index 00000000000..71b8b86be7c --- /dev/null +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//#define OBB_DEBUG_BENCHMARK + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +void bench_finding_obb(std::string fname) +{ + std::ifstream input(fname); + + // import a mesh + CGAL::Surface_mesh mesh; + if (!input || !(input >> mesh) || mesh.is_empty()) { + std::cerr << fname << " is not a valid off file.\n"; + exit(1); + } + + CGAL::Timer timer; + std::size_t measurements = 4; + + for (std::size_t t = 0; t < measurements; ++t) + { + std::cout << "#vertices= " << vertices(mesh).size() << " |"; + + timer.start(); + + // 1) using convex hull + CGAL::Surface_mesh obb_mesh1; + CGAL::Optimal_bounding_box::find_obb(mesh, obb_mesh1, true); + + timer.stop(); + std::cout << " with ch: " << timer.time() << " s |"; + + timer.reset(); + timer.start(); + + // 2) without convex hull + CGAL::Surface_mesh obb_mesh2; + CGAL::Optimal_bounding_box::find_obb(mesh, obb_mesh2, false); + + timer.stop(); + + std::cout << " without ch: " << timer.time() << " s\n"; + timer.reset(); + + // 3) subdivision + CGAL::Subdivision_method_3::CatmullClark_subdivision(mesh, + CGAL::parameters::number_of_iterations(1)); + } + + +#ifdef OBB_DEBUG_BENCHMARK + std::ofstream out1("data/obb_result1.off"); + out1 << obb_points1; + out1.close(); + + std::ofstream out2("data/obb_result2.off"); + out2 << obb_points2; + out2.close(); +#endif +} + +int main(int argc, char* argv[]) +{ + bench_finding_obb("data/elephant.off"); + + return 0; +} diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/elephant.off b/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/elephant.off new file mode 100644 index 00000000000..cf7cc2b68ca --- /dev/null +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/elephant.off @@ -0,0 +1,8337 @@ +OFF +2775 5558 0 + +0.262933 0.102269 0.138247 +0.0843142 0.0418575 -0.0419302 +0.0676609 -0.0308717 0.133371 +0.202895 0.468475 0.0802072 +0.113075 -0.465378 -0.0546734 +0.225577 -0.277149 -0.193776 +-0.146525 -0.22403 -0.169286 +-0.0249865 -0.129931 -0.13238 +-0.160965 -0.480027 -0.0707824 +0.0794063 -0.415277 -0.0839096 +0.0469116 -0.050008 0.252355 +-0.0998372 -0.193745 -0.16268 +-0.111131 -0.104825 -0.14166 +-0.061459 -0.0977343 -0.133353 +-0.247783 -0.131539 0.0722694 +-0.145972 -0.486627 -0.0633275 +0.0916759 0.0333604 -0.133002 +-0.184954 -0.325468 -0.133853 +0.0847778 -0.432659 -0.0978527 +-0.210776 -0.299151 0.0751516 +-0.151539 -0.388715 0.01282 +-0.154564 -0.438244 -0.0249412 +-0.123411 -0.0182656 0.0135824 +0.00773278 -0.053391 -0.0428874 +-0.0774524 -0.292395 -0.106335 +0.0201594 -0.263586 0.119859 +-0.105646 -0.0365155 -0.0770751 +-0.113391 -0.41896 -0.0906771 +-0.128213 -0.46259 -0.0994907 +-0.160526 -0.468057 -0.0393445 +0.197609 -0.127492 -0.0574767 +0.0757306 -0.449539 -0.0614557 +0.147148 -0.412461 -0.0801639 +0.103782 -0.333007 0.0288926 +0.108917 -0.401981 -0.00841926 +0.11392 -0.408931 -0.0973654 +0.129733 -0.31331 -0.0672325 +0.0904388 -0.356531 -0.0803906 +0.0359798 -0.255445 -0.113562 +-0.22312 -0.107007 -0.0611904 +-0.163408 -0.433458 -0.0704785 +-0.0915185 -0.473885 -0.0165533 +-0.141417 -0.474418 -0.0834065 +-0.0944539 -0.479454 -0.0663683 +-0.085985 -0.101282 0.158093 +-0.0225438 -0.0889567 -0.0848587 +0.092707 -0.109496 -0.114561 +-0.159213 -0.159272 -0.138793 +-0.24541 -0.230248 -0.110578 +0.183744 -0.231931 0.0176086 +0.294273 -0.0955008 0.116328 +-0.16477 -0.385872 -0.0413331 +-0.185303 -0.313456 -0.00374653 +-0.297084 -0.262835 -0.00415653 +0.167756 -0.128776 0.197921 +-0.0273811 0.0608812 -0.0989637 +0.208303 0.00452459 -0.0746544 +-0.150831 -0.448909 -0.0901866 +-0.0720206 -0.147118 -0.154796 +-0.0197986 -0.210658 -0.154154 +-0.130593 -0.498558 -0.021161 +0.129662 -0.373473 -0.0794411 +-0.120692 -0.481168 -0.0685411 +-0.108692 -0.494274 -0.0429275 +-0.0970902 -0.252938 -0.14843 +-0.0098054 -0.335319 -0.0147292 +0.0769246 -0.410346 -0.0391239 +-0.132409 -0.464154 -0.0197707 +-0.102806 -0.4217 0.00855496 +-0.0760332 -0.34128 0.100617 +-0.104435 -0.377391 0.0553722 +-0.14788 -0.33188 0.0922673 +-0.151409 -0.218926 0.165812 +-0.111518 -0.286925 0.148566 +-0.0458796 -0.210094 0.18627 +0.0439919 -0.147905 0.137964 +-0.0358575 -0.361749 0.0457868 +0.0284346 -0.311464 0.0537885 +0.0409609 -0.0869988 -0.085353 +0.118462 -0.0465078 -0.0483438 +-0.141108 -0.422593 -0.0846889 +-0.129145 -0.379198 -0.0712284 +-0.149426 -0.329507 -0.0473837 +-0.212723 -0.300322 -0.0706413 +-0.156151 -0.403775 -0.0651516 +-0.077704 -0.400019 -0.0437424 +-0.0783601 -0.342543 -0.0687412 +-0.0202922 -0.309739 -0.0758353 +0.0501325 -0.290557 -0.0430839 +0.0954448 -0.256567 0.0733017 +0.144565 -0.158299 0.0913557 +0.0562207 -0.179498 -0.140905 +0.16863 -0.175124 -0.176771 +0.121523 -0.241503 -0.138152 +0.196749 0.136407 0.00365942 +0.14057 0.277481 0.154966 +0.156168 -0.385879 -0.0324162 +-0.146564 -0.288069 -0.168907 +-0.212533 -0.256019 -0.170893 +0.0775241 -0.353084 -0.0221894 +-0.161054 -0.48311 -0.0516067 +-0.151386 -0.488726 -0.0297486 +-0.167299 -0.464731 -0.058517 +-0.167494 -0.44542 -0.0440266 +-0.166175 -0.416312 -0.0405929 +-0.155665 -0.409399 -0.0112037 +-0.130777 -0.428881 -0.00549876 +-0.162855 -0.460869 -0.0783452 +-0.0949104 -0.0628065 -0.118829 +-0.171364 -0.0681205 -0.104606 +-0.189411 -0.0391257 -0.0301772 +-0.201329 -0.0450332 0.0672375 +-0.0621659 -0.0595357 -0.0819357 +-0.0724451 -0.0386843 -0.0212262 +-0.0317016 -0.00827391 0.0812953 +0.125617 -0.445138 -0.086335 +0.16914 -0.45638 -0.0514974 +-0.188699 -0.102786 0.151505 +-0.127982 -0.406882 0.0143939 +-0.130706 -0.384 0.0373578 +-0.17253 -0.34721 0.0442322 +-0.136499 -0.357829 0.0655808 +-0.101729 -0.398953 0.0314689 +-0.06477 -0.393705 0.00175031 +-0.0683606 -0.382507 0.0422398 +-0.0619729 -0.361557 0.0725343 +-0.0129886 -0.329893 0.099078 +-0.0485077 -0.306718 0.14972 +-0.0586671 -0.359537 -0.0297503 +-0.105132 -0.354471 0.0834642 +-0.111953 -0.324339 0.110194 +-0.146952 -0.298663 0.122985 +-0.147935 -0.259899 0.146585 +-0.224685 -0.230598 0.12386 +-0.194785 -0.274899 0.125615 +-0.1144 -0.250007 0.185149 +-0.10665 -0.185071 0.204627 +-0.155805 -0.154327 0.174517 +-0.215755 -0.165279 0.142947 +-0.0743299 -0.277016 0.17853 +-0.0218198 -0.257755 0.16445 +0.000800113 -0.199671 0.138749 +-0.0254547 -0.133829 0.140633 +0.0635315 -0.20852 0.111271 +-0.0256804 -0.0569419 0.140514 +-0.0948894 -0.0414189 0.110395 +-0.0705488 -0.0374163 0.0415111 +-0.00760713 -0.0195458 0.0164934 +0.0499878 0.0289775 0.0673286 +0.140466 0.0718009 0.144428 +-0.00188983 0.0792593 -0.003093 +0.0559872 -0.0140882 -0.011506 +-0.227407 -0.0888195 0.0117762 +-0.273528 -0.167121 -0.0102922 +-0.0402782 -0.263586 -0.140793 +-0.137564 -0.296782 -0.109847 +-0.166109 -0.381665 -0.0120175 +-0.16983 -0.360755 0.0137933 +-0.16456 -0.354211 -0.0308766 +-0.185156 -0.334386 0.0190529 +-0.207978 -0.298552 0.0310885 +-0.252507 -0.243462 0.0511336 +-0.223388 -0.268692 -0.019703 +-0.193938 -0.322649 0.048456 +-0.175095 -0.332532 0.0736524 +-0.176111 -0.310734 0.103586 +-0.147337 -0.494175 -0.0467278 +-0.129359 -0.490613 -0.0537016 +-0.148829 -0.364106 -0.0543963 +-0.120087 -0.343197 -0.0662243 +-0.130345 -0.305692 -0.0722136 +-0.171529 -0.299424 -0.0833938 +-0.181343 -0.292949 -0.0416997 +0.207831 -0.217496 -0.0966998 +0.180453 0.174523 0.151623 +0.0997558 -0.44202 -0.0211251 +0.141829 -0.427452 -0.0246256 +0.231902 -0.0518172 0.0262484 +0.222165 -0.00765217 0.131632 +0.257605 0.0468554 0.0496674 +0.134457 -0.362329 0.00455646 +0.162364 -0.298449 0.0119315 +0.167632 -0.334853 -0.0258239 +0.166781 -0.258058 -0.0451734 +0.196618 -0.203737 -0.0367216 +0.204966 -0.148702 0.029823 +0.188775 -0.0899398 0.0842549 +0.118735 -0.0897053 0.120666 +0.108518 -0.0623755 0.19827 +0.0943505 -0.134977 0.262277 +0.0987744 0.0186293 0.19077 +0.164162 -0.016078 0.17849 +0.217401 -0.0732307 0.174029 +0.244384 -0.159022 0.158735 +0.0938974 -0.414078 -0.0986619 +0.0882094 -0.386204 -0.0874415 +0.110237 -0.433985 -0.106491 +0.0752909 -0.377302 -0.0545033 +0.136893 -0.424401 -0.103861 +0.101623 -0.446793 -0.0879738 +0.0803589 -0.447974 -0.0828166 +0.0955794 -0.458697 -0.0690652 +0.0852254 -0.472952 -0.043714 +0.0423481 -0.131534 -0.117698 +0.0102534 -0.163639 -0.135844 +-0.0294235 -0.16777 -0.154302 +-0.0581903 -0.19678 -0.162941 +-0.0495263 -0.23206 -0.157295 +0.0213258 -0.204668 -0.142847 +0.0591534 -0.221375 -0.128414 +0.094939 -0.204956 -0.158559 +0.102368 -0.149902 -0.152017 +0.161838 -0.127189 -0.119413 +0.0883157 -0.255475 -0.0965547 +0.00337956 -0.243572 -0.138992 +-0.00441584 -0.28038 -0.109802 +0.139454 -0.244447 -0.0884262 +0.17799 -0.253819 -0.13106 +0.239512 -0.249475 -0.139746 +0.239769 -0.199663 -0.201225 +0.139899 -0.220537 -0.184787 +0.188104 -0.214287 -0.208834 +0.241446 -0.186766 -0.139849 +0.209446 -0.161297 -0.101029 +-0.199048 -0.317265 -0.100601 +-0.293252 -0.31357 -0.122798 +-0.243299 -0.355691 -0.130502 +-0.247594 -0.319033 -0.0988683 +-0.291668 -0.287409 -0.0637038 +-0.248832 -0.272185 -0.0865389 +-0.259174 -0.220646 -0.0469428 +-0.282126 -0.263379 -0.124759 +-0.269731 -0.294935 -0.18724 +-0.247297 -0.165961 -0.0866554 +0.0601914 -0.0464014 -0.0549033 +-0.211085 -0.18579 -0.128927 +-0.200721 -0.132547 -0.108259 +-0.0634953 -0.15489 0.179525 +0.153912 -0.0887253 -0.0733484 +0.185145 -0.0471144 -0.0260532 +0.211443 0.0144377 0.0032337 +0.139575 0.0029693 0.000737671 +0.166751 0.0710484 -0.0323169 +0.107842 0.107181 0.0410238 +0.241648 0.0800111 -0.0150955 +-0.140262 -0.4992 -0.033581 +-0.123763 -0.497978 -0.0364981 +-0.108133 -0.495253 -0.0202341 +-0.1219 -0.481038 -0.0158085 +-0.110456 -0.461331 -0.014079 +-0.087635 -0.441699 -0.0445804 +-0.0916102 -0.451765 -0.0239283 +-0.0811529 -0.421697 -0.020421 +-0.0723115 -0.470105 -0.0423155 +-0.102577 -0.44033 -0.0062072 +-0.139118 -0.480546 -0.0199347 +-0.149266 -0.466768 -0.0254061 +0.222317 -0.0925366 -0.0161067 +-0.0417433 -0.361447 0.00632817 +-0.00965295 -0.347119 0.0218202 +0.0216724 -0.318231 0.010836 +-0.00474667 -0.341486 0.0613973 +0.0698488 -0.285166 0.0205835 +-0.108371 -0.29389 -0.0941984 +-0.11094 -0.279255 -0.127432 +-0.0852691 -0.31423 -0.083395 +-0.0516331 -0.309713 -0.0908278 +-0.0463843 -0.329032 -0.0615785 +-0.13427 -0.295211 -0.140976 +-0.16029 -0.312528 -0.151535 +-0.208046 -0.313472 -0.188061 +-0.177638 -0.29982 -0.178676 +-0.173332 -0.259819 -0.179118 +-0.186949 -0.225139 -0.161631 +-0.121077 -0.271737 -0.158365 +-0.222098 -0.229029 -0.143015 +-0.254895 -0.254361 -0.158387 +-0.119307 -0.241249 -0.168619 +-0.0940058 -0.224454 -0.161034 +-0.119452 -0.213541 -0.164903 +-0.133444 -0.181194 -0.153714 +-0.123212 -0.142937 -0.146434 +-0.154852 -0.114002 -0.127562 +-0.16919 -0.193253 -0.151916 +-0.202578 -0.281459 -0.18846 +-0.238459 -0.276537 -0.185897 +-0.240282 -0.308392 -0.197824 +-0.31592 -0.411023 -0.222975 +-0.28556 -0.354091 -0.210885 +-0.235315 -0.349789 -0.176342 +-0.247249 -0.413591 -0.205119 +-0.313616 -0.39085 -0.145549 +-0.265064 -0.38952 -0.162643 +-0.137308 -0.0765217 -0.126585 +-0.138269 -0.043252 -0.101811 +-0.149787 -0.024537 -0.0569204 +-0.190238 -0.325155 -0.164883 +-0.214126 -0.342005 -0.145019 +-0.11169 -0.0249744 -0.0351987 +-0.154494 -0.0206052 -0.0150451 +-0.170024 -0.0235376 0.033341 +-0.149964 -0.0212297 0.0915499 +-0.146292 -0.0570396 0.143171 +-0.204533 -0.050976 0.0222898 +-0.222839 -0.0748301 0.0497298 +-0.218112 -0.0836084 0.106186 +-0.241131 -0.10804 0.0423425 +-0.253857 -0.126023 0.000914005 +-0.268045 -0.155579 0.0359862 +-0.254096 -0.191499 0.0837602 +-0.284127 -0.206805 0.0257642 +-0.255388 -0.139415 -0.0455141 +-0.266486 -0.179542 -0.0496151 +-0.255448 -0.200689 -0.0776309 +-0.238672 -0.192995 -0.107883 +-0.225097 -0.163824 -0.109937 +-0.22995 -0.135947 -0.0896828 +-0.209528 -0.114818 -0.0862766 +-0.197715 -0.0771741 -0.074156 +-0.18152 -0.102481 -0.104911 +-0.212552 -0.0754645 -0.0336012 +-0.179069 -0.0426745 -0.0757348 +-0.191113 -0.0400122 0.118805 +0.0761558 -0.344791 -0.0536197 +0.0734921 -0.316433 -0.0291825 +0.0865869 -0.298841 -0.0691012 +0.0805876 -0.328744 0.0029047 +0.0952029 -0.361348 0.00820626 +0.11906 -0.273469 -0.0673767 +0.0841053 -0.310717 0.0264162 +0.125408 -0.292597 0.041066 +0.0878905 -0.285295 0.052224 +0.0491288 -0.272854 0.0806291 +0.143869 -0.242882 0.0528378 +0.117789 -0.207199 0.0870858 +0.169353 -0.193132 0.0552639 +0.0969256 -0.166289 0.115505 +0.054006 -0.288058 0.0505697 +0.0199581 -0.301066 0.0971587 +-0.00766116 -0.296894 0.132807 +0.0766599 -0.302889 0.00259846 +0.0459981 -0.299327 0.00649094 +0.0275534 -0.307808 -0.0222832 +0.0149271 -0.300169 -0.0594622 +0.0407712 -0.276916 -0.0798141 +0.0598138 -0.291021 -0.0166231 +0.105499 -0.310063 0.042044 +0.129965 -0.318676 0.0271739 +-0.0843085 -0.494264 -0.0321529 +-0.0752323 -0.238787 0.196776 +-0.295928 -0.43397 -0.176216 +0.0851801 -0.382062 -0.0130588 +0.0187394 -0.0952484 0.145146 +0.0700063 -0.10227 0.135872 +0.0221841 -0.0461712 0.144279 +0.0234739 0.0145751 0.123876 +-0.00955997 -0.0145334 0.135796 +-0.0455413 -0.0274983 0.116817 +-0.0630042 -0.0646849 0.123712 +-0.0996182 -0.0685448 0.139479 +-0.129134 -0.0937854 0.159793 +-0.112763 -0.133107 0.183753 +-0.0586283 -0.0384282 0.0801443 +-0.0976008 -0.0306336 0.0712047 +-0.187313 -0.236737 0.146886 +-0.186919 -0.194456 0.158247 +-0.276732 -0.200888 -0.0224537 +-0.291326 -0.23573 -0.0313163 +-0.262172 -0.26119 -0.0228289 +-0.244304 -0.258186 0.0138536 +-0.238049 -0.253808 -0.053252 +-0.278468 -0.245353 0.0237178 +-0.250374 -0.233381 -0.0762153 +-0.317786 -0.266287 -0.0397057 +-0.29694 -0.227134 0.00135872 +-0.28761 -0.282597 -0.0302299 +-0.0768305 -0.203891 0.202176 +-0.107975 -0.220055 0.202264 +-0.134773 -0.20066 0.190676 +-0.13214 -0.167949 0.192848 +-0.157713 -0.187173 0.17141 +-0.0792541 -0.17391 0.197354 +-0.103166 -0.157466 0.196315 +-0.0861693 -0.139966 0.183699 +-0.0642112 -0.126048 0.16286 +-0.0525585 -0.0978366 0.139755 +0.173523 -0.0454835 0.124705 +0.124762 -0.0100876 0.132612 +0.0801162 0.0231847 0.117816 +0.0903158 0.0691509 0.0824377 +0.111706 0.138719 0.113497 +0.109897 0.0476799 0.0291314 +0.0568194 0.0789592 0.018431 +0.166721 0.186565 0.0672199 +0.252858 0.160254 0.0700128 +0.103948 0.0891733 -0.0142249 +0.151331 0.103958 0.00831307 +0.156258 0.148984 0.0332697 +0.195526 0.176469 0.0301312 +0.246249 0.159404 0.0147221 +0.272985 0.107792 0.0403664 +0.220496 0.208803 0.0718273 +0.172006 0.242405 0.105809 +0.284857 0.213191 0.163319 +0.220004 0.262975 0.168971 +0.243752 0.187223 0.124992 +0.303317 0.156118 0.132187 +0.124557 0.160014 0.070217 +0.145476 0.178627 0.113721 +0.143822 0.145597 0.146983 +0.199699 0.112576 0.148784 +0.221259 0.0552492 0.134196 +0.124553 0.109697 0.139987 +0.100062 0.0751807 0.125633 +0.107686 0.0453443 0.15701 +0.152453 0.0251604 0.154394 +0.160741 0.1045 0.158385 +0.183054 0.0708926 0.1447 +0.188656 0.0314673 0.13741 +0.286002 0.0789154 0.0896861 +0.044874 0.0868553 -0.0397086 +0.0292084 0.0351428 -0.0773123 +-0.00652383 0.0868322 -0.0563984 +0.153395 -0.330946 0.00521793 +0.165687 0.227811 0.159326 +0.176713 -0.253714 -0.180764 +0.276141 0.126578 0.0974557 +-0.0329659 -0.0648403 -0.0508016 +-0.022748 -0.0460692 -0.0136176 +-0.0397109 -0.0394184 0.0195973 +0.00993129 -0.0278328 -0.0155697 +0.0270531 -0.00832198 0.0106523 +0.0103826 0.00500549 0.0538795 +0.0666135 0.0125544 0.0261568 +0.103369 0.00889595 0.155654 +0.11659 -0.0298082 0.170544 +0.153029 -0.0696813 0.168481 +0.113461 -0.0186162 0.216944 +0.10035 -0.0580327 0.251516 +0.150235 -0.084971 0.233939 +0.0675669 -0.0946043 0.253879 +0.0719166 -0.0391569 0.214813 +0.10687 -0.103697 0.22877 +0.136543 -0.144876 0.235107 +0.147147 -0.0351617 0.149371 +0.1197 -0.0491892 0.122959 +0.148505 -0.0696344 0.112799 +0.152678 -0.114026 0.101195 +0.181641 -0.136376 0.0700095 +0.177794 -0.0667748 0.102185 +0.219377 -0.0856118 0.124697 +0.231869 -0.0572983 0.0801841 +0.250938 -0.00881912 0.0578761 +0.198815 -0.0628459 0.124187 +0.177363 -0.0676828 0.147605 +0.177944 -0.101552 0.169756 +0.213844 -0.114113 0.199683 +0.250347 -0.109904 0.165803 +0.259893 -0.130195 0.122038 +0.180633 -0.0723966 0.203599 +0.114076 -0.0955963 0.272717 +0.201886 -0.0333539 0.161782 +0.240288 -0.0485439 0.141813 +0.261312 -0.0227503 0.104643 +0.273982 -0.0593402 0.119899 +0.280362 -0.074792 0.0701015 +0.238595 0.0177583 0.0951404 +0.14643 -0.0478943 0.212489 +-0.227331 -0.265687 0.0979085 +-0.244646 -0.230401 0.0887962 +-0.293688 -0.268968 -0.164669 +-0.297979 -0.308788 -0.162348 +-0.312868 -0.346598 -0.144794 +-0.344082 -0.367401 -0.192127 +-0.317302 -0.337357 -0.184462 +-0.280828 -0.350074 -0.123607 +0.105148 0.105807 0.112878 +0.112708 0.122082 0.0774818 +0.133565 0.128779 0.0503619 +-0.153371 -0.370618 0.0324641 +0.254239 -0.0926281 0.0998171 +-0.0128437 0.0136567 0.10826 +0.0175667 0.0217155 0.0871281 +0.0477136 0.0340255 0.104217 +0.0750182 0.0489044 0.100742 +0.0776037 0.0433948 0.0700673 +0.0973389 0.0603657 0.0539823 +0.0861821 0.0686274 0.0252903 +0.0735784 0.0589072 -0.0094551 +0.0829016 0.102631 0.0164944 +0.0811061 0.0911963 0.0569078 +0.0940457 0.0476479 0.121838 +0.105428 0.0231317 0.131003 +0.0916425 -0.00738665 0.126455 +0.0604145 5.34629e-005 0.128347 +0.10359 0.0595398 0.00049955 +0.144344 0.0457444 0.00327488 +0.122523 0.0419513 -0.0300499 +0.11811 0.0162342 -0.0830375 +0.170091 0.0155571 -0.145681 +0.138389 0.0626357 -0.0743287 +0.165069 0.0235027 -0.0532363 +0.177768 0.0409007 -0.100742 +0.136707 0.0380317 -0.122381 +0.124141 0.00775387 -0.157586 +0.154959 -0.000810753 -0.105169 +0.105591 0.0562623 -0.100272 +0.0594242 0.0548004 -0.106957 +0.201162 -0.0168583 -0.120783 +0.0976411 0.0972697 0.0801317 +0.0943337 0.0848541 0.102457 +0.0890479 0.0650811 0.109825 +0.0389773 0.0745551 -0.0779593 +0.0138551 0.0593589 -0.108474 +0.0773146 0.0765993 -0.0629692 +0.118409 0.00125651 -0.11931 +0.14578 -0.0101392 -0.137264 +0.178622 -0.0192175 -0.148664 +0.15461 0.0388676 -0.0266866 +0.193622 0.0322602 -0.0272748 +0.1942 0.050466 -0.0642106 +0.173634 0.0303747 -0.00069076 +0.179101 -0.0110744 -0.00523936 +0.230507 0.0422098 -0.0173425 +0.202418 0.070871 -0.0135348 +0.22302 0.0184239 -0.0441485 +0.215157 -0.0248187 0.00288885 +0.233855 -0.00344678 0.0259658 +0.238719 0.033163 0.0205233 +0.25481 0.0672767 0.0179763 +0.222129 -0.0581209 -0.00731524 +0.227145 -0.0819987 0.0145053 +0.219253 -0.118982 0.0109807 +0.211654 -0.158762 -0.0192499 +0.210611 -0.101269 0.0490966 +0.200451 -0.190104 0.0116714 +0.203938 -0.0712158 -0.0282028 +0.173774 -0.0735362 -0.0475631 +0.2027 -0.10102 -0.0400541 +0.212795 -0.129107 -0.0298945 +0.206091 -0.151217 -0.0455168 +0.202467 -0.150775 -0.0745887 +0.209378 -0.187531 -0.0743719 +0.181149 -0.126003 -0.0892617 +0.205972 -0.177843 -0.0383337 +0.188301 -0.142819 -0.114464 +0.208779 -0.164491 -0.140437 +0.171227 -0.151151 -0.147387 +0.136617 -0.138704 -0.143839 +0.131975 -0.166643 -0.169617 +0.128263 -0.113939 -0.11894 +0.116875 -0.0858965 -0.091059 +0.0786764 -0.0829677 -0.090746 +0.187859 -0.214057 -0.0686071 +0.175679 -0.237132 -0.0957975 +0.178163 -0.10588 -0.0665832 +0.269129 0.0763722 0.0451229 +0.27889 0.058723 0.0679827 +0.267652 0.0453551 0.105512 +0.2613 0.0363273 0.0775663 +0.250278 0.0199214 0.0566543 +0.250269 0.00638094 0.0769677 +0.262967 -0.0160504 0.0796628 +0.285344 -0.0433845 0.0872574 +0.24971 -0.0386027 0.0640826 +0.229012 -0.0528564 0.0533874 +0.210073 -0.0746435 0.0657137 +0.221889 -0.0775407 0.0410909 +0.302572 -0.0710887 0.0949218 +0.236871 -0.0290995 0.0413907 +0.21774 0.0486965 -0.0445342 +0.224846 0.0339602 -0.0740774 +0.244042 0.0044793 -0.10874 +0.254336 0.102378 0.0100739 +0.220262 0.108437 -0.00385435 +0.184431 0.103867 -0.0063665 +0.227766 0.138272 0.00117268 +0.21603 0.168687 0.00560537 +0.214962 0.252952 4.36931e-005 +0.24674 0.211475 0.00674743 +0.208103 0.206716 0.00898043 +0.198252 0.239152 0.0425261 +0.241235 0.183275 -0.00372162 +0.24846 0.187657 0.0253371 +0.236173 0.217937 0.0406376 +0.208251 0.202717 0.0430183 +0.190765 0.204953 0.0676283 +0.199822 0.228771 0.0907818 +0.212055 0.262964 0.121847 +0.167888 0.20936 0.0941323 +0.230768 0.216285 0.106419 +0.226441 0.220307 0.1523 +0.160904 0.217518 0.126833 +0.151535 0.251202 0.133586 +0.158786 0.306935 0.0984538 +0.193903 0.396086 0.195106 +0.119767 0.364922 0.154966 +0.158434 0.284691 0.125614 +0.188265 0.327264 0.175224 +0.139712 0.323472 0.144742 +0.247398 0.226772 0.208026 +0.162628 0.357991 0.158091 +0.132463 0.334186 0.215838 +0.184892 0.418747 0.128073 +0.148158 0.405567 0.1589 +0.116952 0.392105 0.208798 +0.128904 0.307582 0.18276 +0.173163 0.280669 0.197839 +0.237808 0.190239 0.0542196 +0.242415 0.187695 0.0885314 +0.257589 0.159811 0.105872 +0.25799 0.149475 0.1552 +0.249199 0.167605 0.0439231 +0.270589 0.141138 0.0478035 +0.291007 0.120776 0.0668204 +0.27986 0.0943457 0.0648346 +0.262028 0.128688 0.0220064 +0.283888 0.104244 0.08796 +0.278117 0.09277 0.114653 +0.296211 0.119268 0.134225 +0.25745 0.0686993 0.129638 +0.231499 0.0874258 0.144645 +0.23624 0.121986 0.150481 +0.21822 0.158716 0.152133 +0.276736 0.0681718 0.110294 +0.286087 0.0545245 0.0921962 +0.114064 0.342002 0.184102 +0.184346 0.361594 0.187357 +0.161147 0.378013 0.229421 +0.186402 0.32651 0.232026 +0.224199 0.278314 0.231623 +0.178684 0.387524 0.165454 +0.207571 0.416517 0.162223 +0.115261 0.360345 0.210089 +0.111327 0.375408 0.183082 +0.123148 0.405595 0.17979 +0.161317 0.441861 0.200022 +0.134075 0.42215 0.208124 +0.166581 0.413272 0.221996 +0.184888 0.467555 0.155941 +0.139501 0.435526 0.173911 +0.158717 0.435906 0.144337 +0.167498 0.45215 0.103084 +0.137763 0.359978 0.22921 +0.165611 0.348074 0.227085 +0.15984 0.318857 0.217125 +0.185554 0.304169 0.211919 +0.205103 0.278784 0.204981 +0.244841 0.279219 0.196675 +0.226891 0.25345 0.209087 +0.216714 0.31142 0.225032 +0.18164 0.33693 0.20427 +0.203702 0.303717 0.18726 +0.193627 0.296232 0.146589 +0.191637 0.257284 0.18429 +0.157803 0.257523 0.177293 +0.175634 0.311565 0.125155 +0.161107 0.457828 0.173386 +0.194169 0.447882 0.185268 +0.194408 0.477711 0.118315 +0.219599 0.449898 0.13857 +0.135294 0.387364 0.228733 +0.145147 0.282789 0.187345 +0.143956 0.303159 0.203618 +0.177446 0.366384 0.212315 +0.179329 0.391491 0.217312 +0.18672 0.412483 0.210145 +0.202606 0.421792 0.189409 +0.174085 0.42914 0.210627 +0.153641 0.426813 0.21312 +0.144424 0.408706 0.223131 +0.190464 0.428693 0.201747 +0.178837 0.441581 0.19921 +0.169704 0.452082 0.187978 +0.180705 0.459908 0.173619 +0.202088 0.458198 0.166952 +0.151672 0.449754 0.186725 +0.142475 0.436806 0.198199 +0.127991 0.425256 0.188222 +0.210178 0.437176 0.172385 +0.119636 0.410278 0.199562 +0.206557 0.46857 0.145869 +0.215386 0.468035 0.123827 +0.207969 0.436894 0.106764 +0.212477 0.477963 0.10116 +0.128023 0.4054 0.215288 +0.223073 0.454408 0.0921651 +0.184017 0.321535 0.149004 +0.164058 0.339436 0.133054 +0.141763 0.356765 0.138374 +0.138767 0.331395 0.111494 +0.18387 0.5 0.0894472 +0.178253 0.341112 0.15974 +0.158692 0.397227 0.229447 +0.261987 0.258572 0.22454 +0.209557 0.191204 0.156985 +0.19703 0.220129 0.168363 +0.114158 0.395299 0.191384 +0.237163 0.239354 0.0176536 +0.22873 0.228755 -0.0079498 +0.204237 0.229854 -0.000985107 +0.191898 0.248869 0.0164149 +0.195144 0.299533 0.0501168 +0.211408 0.277777 0.0261684 +0.181525 0.269092 0.042102 +0.232338 -0.0296485 0.018274 +0.220704 0.448894 0.117889 +0.211836 0.430361 0.128709 +0.200007 0.22745 0.0221073 +0.206622 0.221816 0.0395427 +0.223655 0.239447 0.0484776 +0.206846 0.263872 0.061817 +0.192412 0.289403 0.0880222 +0.200823 -0.0669613 0.089238 +0.1998 0.487191 0.0879627 +0.178418 0.478766 0.0726805 +0.171907 0.478 0.098484 +0.179607 0.4432 0.070784 +0.215421 0.44036 0.0572748 +0.206111 0.438517 0.081171 +0.184196 0.432818 0.0953164 +0.172787 0.433405 0.115219 +0.16681 0.454422 0.128591 +0.158037 0.463512 0.080819 +0.300027 -0.106441 0.0798503 +0.301565 -0.138608 0.110073 +0.223785 -0.0676095 0.104371 +0.244386 -0.0720528 0.0937201 +0.25624 -0.0594904 0.0758547 +0.271472 -0.0437947 0.0690266 +0.283677 -0.0568988 0.0744319 +0.294284 -0.0698767 0.0795338 +0.293906 -0.0887216 0.0736412 +0.275743 -0.101071 0.0877101 +0.309738 -0.0894098 0.0874741 +0.287014 -0.123527 0.0945964 +0.311125 -0.118131 0.0991123 +0.298899 -0.117613 0.118193 +0.276193 -0.109289 0.135451 +0.270493 -0.137621 0.153632 +0.286312 -0.136798 0.132025 +0.257826 -0.0797919 0.144654 +0.303792 -0.0864306 0.104131 +0.28817 -0.0747287 0.113826 +0.276632 -0.0878111 0.128274 +0.30695 -0.103289 0.107245 +0.287682 -0.0559229 0.10414 +0.272738 -0.0407993 0.108633 +0.253435 -0.0365139 0.124117 +0.295415 -0.0573592 0.0898843 +0.270105 -0.0629299 0.0693418 +0.263375 -0.0783235 0.0820667 +-0.216962 -0.20051 0.140681 +-0.236047 -0.180496 0.115013 +-0.230292 -0.136771 0.112494 +-0.247625 -0.159292 0.0914591 +-0.209896 -0.129892 0.141237 +0.222682 0.288177 0.190351 +0.233778 0.296853 0.212089 +0.209365 0.287061 0.167624 +0.208618 0.271128 0.146657 +0.223776 0.247151 0.14266 +0.250594 0.280585 0.221005 +0.215525 0.238928 0.164607 +0.248724 0.243405 0.176599 +0.282927 0.23674 0.194658 +0.253819 0.208937 0.178714 +0.265424 0.184312 0.155732 +0.308614 0.169998 0.183237 +0.273365 0.179729 0.192265 +0.265912 0.204786 0.204674 +0.300509 0.203464 0.194384 +0.281969 0.151677 0.177526 +0.279246 0.127373 0.158699 +0.31079 0.143896 0.162421 +0.30954 0.171009 0.155179 +0.288086 0.1804 0.137744 +0.264265 0.175268 0.132545 +0.241184 0.168571 0.143536 +0.282052 0.162312 0.123541 +0.290218 0.138764 0.11928 +0.232003 0.191432 0.146429 +0.237199 0.211128 0.131059 +0.175486 0.13591 0.157401 +0.244193 0.0453066 0.121153 +0.216838 0.0295154 0.115567 +0.0778181 0.0182774 -0.0959304 +0.132697 0.385267 0.165833 +0.155812 0.38306 0.160495 +-0.00373338 0.0386319 -0.0871428 +0.0052284 0.0508015 -0.0521262 +-0.0272532 0.0521944 -0.0650671 +-0.0417118 0.0760468 -0.0274796 +0.0432101 0.0478592 -0.0430105 +0.0360437 0.064037 -0.0095129 +0.0264403 0.0878588 0.0105855 +0.0200841 0.0963175 -0.0204482 +0.0508265 0.0939603 -0.0091335 +0.0753367 0.087282 -0.0290458 +-0.0114666 0.0989277 -0.0268583 +0.189464 0.426182 0.111762 +-0.04038 -0.0265907 0.0536548 +0.188037 0.19051 0.048384 +0.170897 0.170857 0.0404072 +0.180803 0.154042 0.0195245 +0.168583 0.128396 0.0100026 +0.150344 0.161847 0.0580756 +0.146195 0.173828 0.0846654 +0.123104 0.163389 0.100752 +0.131952 0.158423 0.126057 +0.154039 0.169296 0.137953 +0.163282 0.191526 0.127822 +0.170691 0.206066 0.147249 +0.123979 0.136658 0.135 +0.136161 0.125537 0.148878 +0.153818 0.131557 0.161379 +0.111897 0.12133 0.126074 +0.111889 0.144276 0.0890707 +0.11658 0.140768 0.0690434 +0.119959 0.124948 0.0613596 +0.107779 0.107117 0.0626571 +0.122618 0.115267 0.0466942 +0.127454 0.104238 0.0219653 +0.136258 0.119892 0.0320023 +0.129073 0.0915077 -0.00265103 +0.130797 0.0780035 -0.0369633 +0.10768 0.094992 0.00979378 +0.163926 0.154671 0.152149 +0.0894836 0.0909923 0.00058556 +0.0689505 0.0963924 0.00171312 +0.0612997 0.100634 0.0224348 +0.0675451 0.0846698 0.038694 +0.0795109 0.103357 0.0384133 +0.0848094 0.0754581 0.0444653 +0.110567 0.10366 0.130086 +0.12281 0.0864143 0.139975 +0.117855 0.062854 0.143513 +0.13666 0.0472165 0.155281 +0.128164 0.0235742 0.176647 +0.163067 0.0498951 0.143567 +0.143932 0.0949004 0.145284 +0.179917 0.317727 0.0742859 +0.183725 0.275085 0.0676723 +0.16838 0.29297 0.0787056 +0.0930951 0.102542 0.05002 +0.100339 0.0681106 0.0373411 +0.102886 0.0622715 0.0197467 +0.121511 0.0540863 0.0117598 +0.124719 0.0242285 0.0166428 +0.0967861 -0.00310471 -0.0020113 +0.12138 0.0519179 -0.0102922 +0.0990646 0.0492208 -0.022422 +0.0873807 -0.0275369 -0.03209 +0.200694 -0.191636 -0.0546067 +0.206298 -0.170055 -0.0598788 +0.209964 -0.168421 -0.0791806 +0.221182 -0.183261 -0.0963771 +0.222775 -0.172837 -0.120159 +0.235715 -0.195921 -0.115182 +0.253933 -0.218526 -0.134037 +0.311213 -0.253911 -0.191866 +0.279294 -0.244732 -0.16099 +0.266185 -0.201338 -0.169529 +0.285572 -0.216415 -0.213382 +0.273765 -0.285731 -0.187819 +0.259679 -0.265381 -0.248632 +0.24894 -0.227823 -0.231771 +0.232153 -0.25966 -0.225227 +0.254118 -0.290735 -0.220386 +0.336364 -0.328047 -0.241676 +0.281317 -0.319577 -0.26697 +0.295033 -0.317038 -0.218433 +0.327766 -0.263669 -0.27537 +0.320681 -0.238904 -0.235706 +0.333487 -0.28367 -0.222752 +0.25789 -0.299076 -0.25318 +0.280382 -0.278404 -0.287734 +0.262726 -0.334272 -0.234674 +0.315714 -0.303377 -0.28762 +0.358898 -0.298323 -0.270079 +0.292961 -0.250812 -0.263064 +0.260427 0.269097 0.206442 +0.273912 0.251948 0.207483 +0.274266 0.226866 0.218876 +0.254508 0.262332 0.186312 +0.268737 0.247011 0.182676 +0.278883 0.230014 0.174886 +0.292676 0.216891 0.181537 +0.301666 0.196568 0.170643 +0.235991 0.25839 0.179999 +0.216996 0.262302 0.191107 +0.233602 0.240223 0.192553 +0.26623 0.217767 0.166603 +0.291208 0.219735 0.206357 +0.285626 0.200003 0.208179 +0.295054 0.181857 0.198439 +-0.119559 -0.0454446 0.130205 +-0.148541 -0.0288065 0.124554 +-0.122421 -0.0280036 0.104512 +-0.169628 -0.0428483 0.136658 +-0.192691 -0.0700149 0.138018 +-0.165949 -0.0805689 0.151606 +-0.157867 -0.111652 0.162619 +-0.182289 -0.134815 0.160033 +-0.171616 -0.0265274 0.119564 +-0.182821 -0.0294707 0.089096 +-0.207158 -0.0941133 0.130893 +-0.0813687 -0.408143 0.0168626 +-0.0493082 -0.255289 0.183439 +-0.0417823 -0.281988 0.16825 +-0.0232624 -0.242141 -0.150317 +0.237084 0.148575 0.150278 +0.21825 0.135883 0.152701 +0.196547 0.147262 0.152063 +0.248839 0.134889 0.149793 +0.25417 0.116897 0.146677 +0.154738 -0.248351 -0.113516 +0.149894 -0.252291 -0.14374 +0.127807 -0.247316 -0.112579 +0.100037 -0.239188 -0.118127 +0.171952 -0.258325 -0.155783 +0.206243 -0.267544 -0.164319 +0.152779 -0.244265 -0.170212 +0.238869 -0.271194 -0.164355 +0.19948 -0.240785 -0.114164 +0.228533 -0.228656 -0.117975 +0.0806348 -0.448964 -0.0364622 +0.092817 -0.46403 -0.0236687 +0.131465 -0.464547 -0.0186627 +0.111576 -0.45856 -0.0162136 +0.12236 -0.437795 -0.0167687 +0.116113 -0.473014 -0.0333379 +0.141834 -0.466374 -0.0462667 +0.15629 -0.45187 -0.0265272 +0.162053 -0.430562 -0.0436087 +0.170805 -0.433786 -0.074571 +0.150694 -0.440322 -0.089161 +0.142403 -0.453672 -0.0687084 +0.20922 0.0225383 -0.118012 +0.245897 0.00269769 -0.0710137 +-0.0868896 -0.445579 -0.0827631 +-0.0899978 -0.418668 -0.0662628 +-0.0919895 -0.382051 -0.0731611 +-0.286076 -0.18977 0.00251657 +0.166397 -0.235956 -0.0665238 +0.18289 -0.231659 -0.0402536 +0.183601 -0.256036 -0.0114407 +0.19304 -0.222737 -0.0114233 +0.168396 -0.264129 0.0198747 +0.175145 -0.292863 -0.0261367 +0.159612 -0.311932 -0.0502102 +0.151795 -0.349231 -0.058414 +0.168467 0.120276 0.165442 +0.179322 0.109989 0.151163 +0.191745 0.091503 0.1476 +0.207409 0.0731218 0.143583 +0.170472 0.088013 0.148441 +0.198308 0.0526608 0.137187 +-0.288444 -0.322548 -0.196751 +-0.258254 -0.336596 -0.201797 +-0.260706 -0.370334 -0.191889 +-0.262012 -0.38355 -0.234182 +0.169409 0.331718 0.106522 +-0.0883279 -0.427369 -0.00320489 +-0.0757242 -0.410706 -0.00350047 +-0.0694098 -0.396348 -0.0215868 +-0.339105 -0.28249 -0.133907 +0.14338 -0.190029 -0.185968 +0.113197 -0.189729 -0.178573 +0.161752 -0.208101 -0.1989 +0.163143 -0.233988 -0.192556 +0.187542 -0.24244 -0.20457 +0.214342 -0.231174 -0.221761 +0.200695 -0.263551 -0.191549 +0.0888974 -0.174918 -0.165344 +0.0728578 -0.155488 -0.148655 +0.0857975 -0.13271 -0.133069 +0.0496654 -0.153477 -0.133288 +0.208417 -0.252602 -0.211864 +0.214499 -0.20684 -0.209109 +0.212326 -0.182246 -0.176825 +0.196622 -0.193456 -0.194925 +-0.0366034 0.0848157 -0.0747335 +-0.0106036 0.0767347 -0.0825468 +-0.248014 -0.143811 -0.0711582 +0.156176 -0.353723 -0.00967102 +0.161881 -0.35946 -0.0354879 +0.154192 -0.374021 -0.054565 +0.153835 -0.401954 -0.0551512 +0.147106 -0.376782 -0.0111704 +0.141013 -0.401853 -0.0175381 +0.127378 -0.38782 -0.00428773 +0.152558 -0.410563 -0.0345712 +0.144573 -0.387551 -0.0699167 +0.129797 -0.395951 -0.0860393 +0.110844 -0.383365 -0.0877166 +0.111358 -0.362136 -0.0828181 +0.10863 -0.332992 -0.0757964 +0.131091 -0.348484 -0.0736181 +0.114528 -0.372564 0.00601769 +0.116893 -0.350867 0.0177725 +0.143657 -0.369483 -0.0686154 +0.0433039 -0.239647 0.0998892 +-0.318832 -0.357055 -0.211401 +-0.299837 -0.377374 -0.238049 +-0.340344 -0.383626 -0.224893 +-0.356366 -0.419986 -0.188103 +-0.285529 -0.404192 -0.228972 +-0.356375 -0.393121 -0.201407 +-0.349321 -0.392013 -0.165399 +-0.328811 -0.42272 -0.163607 +-0.345548 -0.417553 -0.216974 +-0.322795 -0.427865 -0.195551 +-0.33518 -0.363207 -0.161311 +-0.0812327 -0.396788 0.0342935 +-0.065289 -0.38943 0.0224745 +-0.0508718 -0.371639 0.0298172 +-0.260668 -0.216401 0.0653687 +-0.2704 -0.185201 0.0538295 +0.187032 0.486356 0.0996338 +0.279593 -0.136382 0.110973 +0.26837 -0.117918 0.105466 +0.248285 -0.109463 0.116456 +0.232397 -0.125931 0.141691 +0.210603 -0.141776 0.171116 +0.137574 -0.108705 0.207737 +0.169921 0.29167 0.0522744 +0.00992085 -0.113945 -0.0964453 +0.258261 -0.257702 -0.154872 +0.275321 -0.267702 -0.17038 +0.295633 -0.272896 -0.184932 +0.295815 -0.294739 -0.20199 +0.314713 -0.27743 -0.201437 +0.327332 -0.256197 -0.214678 +0.340385 -0.261017 -0.241446 +0.313356 -0.232789 -0.209684 +0.296344 -0.226073 -0.182212 +0.31592 -0.301772 -0.216769 +0.318635 -0.326842 -0.222796 +0.307178 -0.325937 -0.251416 +0.274745 -0.303144 -0.21295 +0.263287 -0.308346 -0.232527 +0.255382 -0.319889 -0.248754 +0.332002 -0.310475 -0.229091 +0.353636 -0.307458 -0.245121 +0.335859 -0.313851 -0.265914 +0.340499 -0.300896 -0.286697 +0.344989 -0.280039 -0.276203 +0.327449 -0.28026 -0.295194 +0.304942 -0.268737 -0.28762 +0.34983 -0.283684 -0.251927 +0.343136 -0.265469 -0.261534 +0.326713 -0.248963 -0.256716 +0.307917 -0.24034 -0.252462 +0.279159 -0.231625 -0.241522 +0.300353 -0.229376 -0.234338 +0.311358 -0.251222 -0.26759 +0.299024 -0.289572 -0.301481 +0.279907 -0.305571 -0.290358 +0.263002 -0.29286 -0.276914 +0.260616 -0.313748 -0.268771 +0.275922 -0.322371 -0.224156 +0.284975 -0.33259 -0.244221 +0.303023 -0.336946 -0.233483 +0.289605 -0.333838 -0.221905 +0.166435 0.39886 0.154509 +0.189152 0.404825 0.153461 +0.197133 0.400723 0.1737 +0.17424 0.413608 0.143911 +0.169142 0.426834 0.132439 +0.188725 0.386035 0.180698 +0.186219 0.378081 0.198788 +-0.267025 -0.372115 -0.138391 +-0.248022 -0.367522 -0.158602 +0.174505 0.292586 0.0990952 +0.186251 0.309263 0.0928235 +0.181697 0.30513 0.109614 +0.189499 0.279776 0.119317 +0.172647 0.294457 0.120787 +0.158057 0.303956 0.130265 +0.143476 0.291331 0.139139 +0.131312 0.30031 0.159002 +0.186095 0.298863 0.131041 +0.198975 0.28677 0.132576 +0.172236 0.277192 0.117866 +0.184313 0.260452 0.109718 +0.15755 0.265746 0.122578 +0.145983 0.269471 0.137935 +0.151234 0.256355 0.155644 +0.124293 0.323596 0.164277 +0.126678 0.342635 0.150186 +0.129524 0.341544 0.128525 +0.146576 0.349856 0.118779 +0.192269 0.30374 0.0759625 +0.202728 0.285813 0.0690781 +0.210479 0.281567 0.0483558 +0.222196 0.26209 0.0407369 +0.224073 0.261141 0.0186008 +0.162756 0.306191 0.114529 +0.149682 0.318744 0.121136 +0.152677 0.341974 0.100993 +0.164071 0.331208 0.0841361 +0.146523 0.323278 0.093798 +0.15695 0.312461 0.0714443 +0.22266 -0.203518 -0.100877 +0.262076 -0.292278 -0.202356 +0.249754 -0.28212 -0.183581 +0.242451 -0.284733 -0.203885 +0.229725 -0.273053 -0.211906 +0.243386 -0.275428 -0.225419 +0.255999 -0.283472 -0.239546 +-0.261873 -0.405224 -0.222848 +-0.280772 -0.420055 -0.201182 +-0.274389 -0.414773 -0.173401 +-0.298626 -0.411672 -0.158377 +-0.28738 -0.389898 -0.148508 +-0.300008 -0.369107 -0.135836 +-0.257381 -0.39915 -0.185758 +-0.257531 -0.421709 -0.186727 +-0.319983 -0.369357 -0.146016 +-0.25404 -0.39271 -0.206532 +-0.269186 -0.375948 -0.213104 +0.171129 0.312683 0.0555484 +0.186538 0.309469 0.0612947 +0.17697 0.322584 0.0897939 +0.180094 0.317456 0.102692 +0.0389455 -0.294719 0.0707663 +0.19085 0.129482 0.148059 +0.26893 -0.330546 -0.250405 +0.261495 -0.324416 -0.260179 +0.163955 0.0845671 -0.00775852 +0.172992 0.467003 0.114773 +0.17962 0.47069 0.135115 +0.167392 0.460661 0.148013 +0.0927702 -0.0102964 0.178794 +0.0791092 -0.00358862 0.211868 +0.0484002 -0.0727004 0.143042 +0.0857054 -0.0664246 0.132462 +0.170606 0.462905 0.162683 +0.107346 -0.291576 0.0507084 +0.123054 -0.26548 0.0555752 +0.1033 -0.273351 0.0618915 +-0.217347 -0.0684085 0.0793768 +-0.232534 -0.1003 0.0785864 +0.160705 0.203815 0.112095 +0.157448 0.189802 0.0951937 +0.163855 0.222961 0.107992 +0.178039 0.226994 0.0939715 +0.157779 0.236558 0.121407 +0.156862 0.233096 0.141593 +0.254115 0.147478 0.0328869 +0.246739 0.139758 0.0163119 +-0.313249 -0.26088 -0.138114 +-0.319034 -0.272336 -0.0954566 +-0.312031 -0.286413 -0.151154 +-0.318615 -0.301412 -0.127758 +-0.31358 -0.30952 -0.0911544 +-0.342054 -0.297563 -0.104135 +-0.285707 -0.289103 -0.098473 +-0.332554 -0.290038 -0.0650158 +0.224391 0.444149 0.0748945 +0.224127 0.466497 0.0733316 +0.00933378 -0.0890982 -0.073455 +-0.196836 -0.0544369 -0.0547609 +-0.268852 -0.35939 -0.204575 +-0.134821 -0.144762 0.184037 +-0.134018 -0.119846 0.172991 +-0.108849 -0.110436 0.169417 +-0.142893 -0.258813 -0.176858 +0.163435 0.422628 0.144619 +0.149105 0.425301 0.157986 +0.151653 0.445126 0.160854 +0.205634 0.453218 0.0682861 +0.196116 0.437078 0.0613117 +0.305429 0.136514 0.131635 +0.304223 0.128705 0.150462 +0.294739 0.1352 0.16485 +0.29983 0.148475 0.176204 +0.293633 0.16134 0.186506 +0.312816 0.146868 0.144611 +0.290574 0.119539 0.149687 +0.280449 0.10933 0.137413 +0.285959 0.112117 0.117297 +0.154398 0.116961 0.162863 +0.147042 0.108372 0.152274 +0.179394 0.214392 0.162515 +0.185651 0.194518 0.157404 +0.180628 0.232354 0.173507 +0.198969 0.238329 0.174545 +0.207694 0.253512 0.177641 +0.203869 0.264161 0.186147 +0.189501 0.273156 0.193533 +0.17312 0.263127 0.188581 +-0.206119 -0.0619918 0.116346 +-0.201545 -0.0465532 0.095691 +0.256266 0.152102 0.0503785 +0.264034 0.143148 0.0672501 +0.26342 0.152022 0.0867622 +0.269601 0.144159 0.103885 +0.281713 0.137095 0.0629023 +0.296165 0.127981 0.0376256 +0.300117 0.13462 0.0559043 +0.287642 0.140563 0.0456708 +0.278661 0.132147 0.0309413 +0.271646 0.118273 0.028754 +0.262921 0.1025 0.0261376 +0.261118 0.0855637 0.0169037 +0.25422 0.0767023 0.000233527 +0.237362 0.0575218 0.00198963 +0.283388 0.119704 0.0383643 +0.282941 0.112062 0.0540402 +0.249937 0.0937398 -0.00575339 +0.231931 0.0954578 -0.0107377 +0.210437 0.0914748 -0.0140972 +0.239252 0.109782 0.000233887 +0.191402 0.0870306 -0.0134669 +0.184376 0.0704441 -0.0225342 +0.184719 0.0606504 -0.044543 +0.166145 0.0578967 -0.0668264 +0.200251 0.061117 -0.0313226 +0.217304 0.057967 -0.0199728 +0.227686 0.12158 0.00370932 +0.20937 0.123042 0.000300618 +0.244333 0.124524 0.00810813 +0.295429 0.120597 0.0522453 +0.178132 0.0791963 -0.0112798 +0.177197 -0.279627 -0.000252101 +0.173639 -0.299787 -0.00606886 +0.172196 -0.313975 -0.0223573 +0.166117 -0.326159 -0.00858114 +0.168079 -0.321719 -0.0379096 +0.162521 -0.339731 -0.0445028 +0.151373 -0.32895 -0.0576036 +0.312369 -0.105021 0.0899766 +0.306 -0.11652 0.0866674 +0.301418 -0.129182 0.0942967 +0.290875 -0.135236 0.101483 +0.289966 -0.143698 0.1109 +0.295915 -0.13953 0.122573 +0.279108 -0.148197 0.122497 +0.27841 -0.152315 0.142258 +0.265867 -0.157983 0.158785 +0.256687 -0.14661 0.137703 +0.25422 -0.140442 0.172759 +0.232237 -0.161116 0.192798 +0.192807 -0.160413 0.202508 +0.178601 -0.140578 0.237092 +0.154384 -0.117167 0.24831 +0.13004 -0.134226 0.269277 +0.17845 -0.105479 0.223698 +0.247464 -0.158843 0.179106 +0.226891 -0.158442 0.171794 +0.209982 -0.159856 0.187271 +0.217821 -0.141328 0.207646 +0.23745 -0.141109 0.186416 +0.229503 -0.142546 0.156329 +0.214657 -0.125289 0.155947 +0.193847 -0.12199 0.171057 +0.217246 -0.105649 0.140104 +0.198069 -0.0856194 0.142621 +0.193693 -0.14343 0.18682 +0.198045 -0.145975 0.222277 +0.178989 -0.164931 0.225321 +0.158831 -0.146831 0.218292 +0.158889 -0.159611 0.244735 +0.138513 -0.154491 0.257842 +0.156487 -0.13924 0.256434 +-0.290841 -0.208347 -0.00770324 +-0.29533 -0.224009 -0.017137 +-0.30561 -0.24462 -0.0155011 +-0.278365 -0.220452 -0.0277869 +-0.267819 -0.241114 -0.0357093 +-0.286737 -0.259306 -0.0462551 +-0.310093 -0.264404 -0.0203987 +-0.307167 -0.250649 -0.0341839 +-0.307612 -0.281242 -0.0310235 +-0.321036 -0.286281 -0.0471544 +-0.310491 -0.270102 -0.0639157 +-0.311345 -0.301149 -0.0633156 +-0.297683 -0.291436 -0.0450671 +-0.294949 -0.304108 -0.0790095 +-0.285459 -0.27779 -0.0488974 +-0.296472 -0.275126 -0.0168658 +-0.276222 -0.270671 -0.00788631 +-0.246454 -0.248267 -0.0329014 +-0.244456 -0.252303 -0.00937036 +-0.304286 -0.259682 -0.0492577 +-0.294933 -0.27203 -0.0604957 +-0.300998 -0.278796 -0.0743602 +-0.316674 -0.274623 -0.0789273 +-0.337714 -0.280945 -0.0853892 +-0.325825 -0.275251 -0.0655092 +-0.332977 -0.302425 -0.0833069 +-0.293564 -0.290291 -0.0772666 +-0.298024 -0.281309 -0.0905074 +-0.293634 -0.272694 -0.109468 +-0.270428 -0.274072 -0.107657 +-0.256077 -0.253991 -0.120812 +-0.261078 -0.296954 -0.0999473 +-0.2381 -0.297373 -0.0849839 +-0.232752 -0.278906 -0.0645746 +-0.272041 -0.319246 -0.10842 +-0.21032 -0.284441 -0.0448701 +-0.256436 -0.341131 -0.11181 +-0.225098 -0.336223 -0.113241 +-0.200175 -0.288996 -0.0158483 +-0.223009 -0.317757 -0.0905879 +-0.301096 -0.262202 -0.123506 +-0.32405 -0.263071 -0.116908 +-0.292477 -0.257052 -0.14263 +-0.270149 -0.255918 -0.142108 +-0.275486 -0.258003 -0.162669 +-0.259523 -0.2674 -0.178244 +-0.251069 -0.250018 -0.0970302 +-0.24056 -0.260706 -0.172311 +-0.232499 -0.247239 -0.154361 +-0.34182 -0.274562 -0.107339 +-0.294559 -0.307923 -0.0994756 +-0.275844 -0.269552 -0.0355918 +-0.227344 -0.270897 -0.045083 +0.25093 0.170443 0.120028 +0.248384 0.184009 0.106523 +0.235777 0.198062 0.103222 +0.23641 0.211305 0.086191 +0.221152 0.226047 0.0898201 +0.223243 0.24123 0.111495 +0.203883 0.250541 0.105061 +0.226958 0.225862 0.123117 +0.219737 0.240254 0.12789 +0.214138 0.253162 0.132941 +0.232275 0.224561 0.138088 +0.109391 -0.247931 -0.0995264 +0.104952 -0.262437 -0.0820427 +0.080763 -0.274056 -0.0783487 +0.0604155 -0.262392 -0.0950373 +-0.227936 -0.329497 -0.190147 +-0.214125 -0.337031 -0.170051 +0.263325 -0.0528405 0.0685009 +0.251926 -0.0484757 0.0715634 +0.237277 -0.0480579 0.0658708 +0.244491 -0.055646 0.0790843 +0.239659 -0.0616442 0.0888399 +0.226162 -0.0616059 0.0920824 +0.21522 -0.0631162 0.0781895 +0.212545 -0.0629682 0.0966232 +0.196781 -0.0599901 0.105959 +0.210127 -0.0657511 0.11188 +0.250495 -0.0660959 0.0846797 +0.234672 -0.0671026 0.0978575 +0.237261 -0.0846396 0.108485 +0.25989 -0.0423809 0.0666642 +0.259987 -0.0257531 0.0664908 +0.247883 -0.0247631 0.0554477 +0.242689 -0.0135836 0.0440572 +0.246291 0.00496067 0.0457059 +0.245187 0.0234669 0.0372413 +0.250061 0.17416 0.133813 +0.259114 0.167602 0.148828 +0.26511 0.166925 0.171546 +0.238618 0.181672 0.138204 +0.229669 0.176644 0.149535 +0.262049 0.187134 0.176237 +0.261795 0.200868 0.165371 +0.276513 0.199318 0.153854 +0.292677 0.199982 0.157209 +0.302715 0.186361 0.157188 +0.308755 0.181779 0.171774 +0.305926 0.190608 0.185482 +0.312423 0.167782 0.169221 +0.31381 0.157653 0.158921 +0.310783 0.154703 0.171639 +0.301108 0.177938 0.144841 +0.293264 0.189309 0.147256 +0.279322 0.188458 0.145304 +0.262483 0.193127 0.192418 +0.274289 0.192768 0.20161 +0.254841 0.206509 0.193978 +0.245154 0.222549 0.189318 +0.253012 0.22552 0.174345 +0.265429 0.23121 0.17081 +-0.253206 -0.236908 -0.0443888 +0.149428 0.386275 0.232451 +0.147867 0.371017 0.232576 +0.152926 0.356705 0.229375 +0.149032 0.338169 0.225131 +0.166114 0.363727 0.223417 +0.172256 0.353426 0.215568 +0.179541 0.338962 0.221969 +0.181625 0.354174 0.201921 +0.186426 0.343494 0.187951 +0.192075 0.328517 0.215563 +0.192453 0.320313 0.195502 +0.17815 0.351274 0.174302 +0.17655 0.370022 0.172318 +0.165276 0.33179 0.225541 +0.00939661 -0.323412 0.0804555 +0.117561 -0.144032 0.250595 +0.120353 -0.125008 0.233582 +0.111251 -0.145731 0.271784 +0.11093 -0.120815 0.285658 +0.0754192 -0.0921393 0.301481 +0.0769558 -0.124739 0.290267 +0.0748528 -0.117401 0.265004 +0.0426218 -0.103655 0.282975 +0.0504123 -0.0659143 0.287583 +0.0836935 -0.0669285 0.279976 +0.0588543 -0.11803 0.279938 +0.0586609 -0.105277 0.297458 +0.0557269 -0.0839063 0.29826 +0.0381914 -0.083198 0.286361 +0.0371995 -0.0680895 0.266535 +0.047335 -0.0888232 0.265922 +0.05563 -0.0732275 0.247968 +0.0616189 -0.0543441 0.232231 +0.0811821 -0.0784737 0.231059 +0.0764784 -0.0353683 0.254905 +0.0689625 -0.0703705 0.29266 +0.0661415 -0.0548095 0.278244 +0.0608765 -0.028919 0.235586 +0.087271 -0.018263 0.234864 +0.0756435 -0.10953 0.298971 +0.0951645 -0.0988538 0.288259 +0.0930654 -0.116235 0.295574 +0.0947803 -0.133863 0.284699 +0.0966033 -0.0830131 0.273711 +0.113798 -0.076403 0.258582 +0.127442 -0.0600385 0.234949 +0.132794 -0.0953943 0.252522 +0.0489111 -0.0556973 0.272686 +0.0606107 -0.0431898 0.263976 +0.0971312 -0.036293 0.245012 +0.110687 -0.0488392 0.23675 +0.126176 -0.0414728 0.221378 +0.136057 -0.0243951 0.201716 +0.122078 0.00127519 0.196707 +0.142291 0.00027007 0.178375 +0.0664164 -0.0191578 0.217877 +0.0802696 -0.0234954 0.199319 +0.0910082 -0.0454502 0.20083 +0.0798776 -0.132726 0.273919 +0.102454 0.00166634 0.210465 +0.0802091 -0.00534582 0.192641 +0.0863635 0.00814252 0.179895 +0.0946306 0.0282399 0.168655 +0.0981336 0.029523 0.148764 +0.101777 0.0395859 0.135111 +0.102082 0.0581642 0.134881 +0.0956437 0.0321468 0.122829 +0.0938658 0.0161985 0.122282 +0.107901 0.00369122 0.128399 +0.078491 0.00576055 0.124425 +0.0841199 0.0382034 0.11313 +0.0659972 0.0331947 0.109714 +0.0520056 0.0196069 0.12098 +0.108345 -0.0142416 0.126349 +0.0915975 -0.0313276 0.129913 +0.122833 -0.0287943 0.124051 +0.146418 -0.0426624 0.119895 +0.142658 -0.0228961 0.131632 +0.132595 -0.0194368 0.150249 +0.160419 -0.0327892 0.133975 +0.163125 -0.050543 0.147173 +0.060233 0.0422739 0.0970401 +0.0469107 0.0353785 0.0851224 +0.0330985 0.0252247 0.0760721 +0.0344131 0.0145341 0.0525338 +0.0185411 0.0141735 0.0691085 +-0.00651953 0.00766464 0.081092 +0.0314926 0.0314677 0.0951056 +0.0155266 0.0258059 0.107793 +0.11957 0.0050674 0.144577 +0.11348 -0.010764 0.15919 +0.0864989 0.00930931 0.196192 +0.112679 0.0343949 0.172228 +0.110056 0.0172326 0.144505 +-0.231861 -0.256194 -0.0373807 +-0.233847 -0.249852 -0.0220477 +-0.230235 -0.258784 -0.00973726 +-0.217151 -0.280061 0.00814621 +-0.228026 -0.273051 0.0389012 +-0.222798 -0.271648 -0.00409819 +-0.229682 -0.268052 0.0118625 +-0.212876 -0.279385 -0.0140325 +-0.214439 -0.277583 -0.0303969 +-0.199886 -0.285356 -0.0320197 +-0.187179 -0.295224 -0.0255156 +-0.167219 -0.315028 -0.0304058 +-0.156845 -0.302235 -0.0544314 +-0.236758 -0.254924 0.00227314 +0.0884351 -0.404348 -0.0195924 +0.0722252 -0.268984 0.0670772 +0.070147 -0.245252 0.0862941 +0.0966471 -0.229612 0.0882203 +0.0926053 -0.203806 0.103764 +0.0777673 -0.186021 0.118999 +0.0417862 -0.182948 0.126604 +0.0709209 -0.158179 0.128709 +0.095465 -0.128791 0.124296 +0.0102764 -0.16375 0.133447 +-0.0233099 -0.171526 0.153541 +-0.0499934 -0.0465621 -0.00582837 +-0.0749973 -0.0355191 0.0101971 +-0.0645299 -0.324704 -0.077104 +0.221779 0.470802 0.0892895 +0.219761 0.464582 0.1032 +0.246597 0.0246927 0.0795416 +0.253586 0.0320272 0.0977802 +0.252394 0.0305168 0.0670227 +0.261064 0.0424817 0.0637394 +0.267205 0.0556508 0.058182 +0.262106 0.0615289 0.0436471 +0.250683 0.0500973 0.0298185 +0.272972 0.0454164 0.0731281 +0.274554 0.0385023 0.090004 +0.285852 0.0505507 0.0780368 +0.287544 0.066644 0.0791877 +0.280213 0.0764884 0.0661465 +0.226162 0.0537579 -0.00800313 +0.231726 0.0372941 0.00212281 +0.226833 0.070796 -0.0125112 +-0.0228881 0.0822405 -0.0141151 +-0.0164496 0.062439 -0.0353807 +-0.0311204 0.09353 -0.0291259 +-0.0468617 0.0890411 -0.0503417 +-0.0192694 0.0958145 -0.0445491 +-0.0451838 0.0631149 -0.0497516 +-0.0349277 0.0970377 -0.0439657 +-0.0281121 0.0908295 -0.0597278 +-0.0422149 0.0875756 -0.0360098 +-0.0493018 0.0748281 -0.0407497 +-0.0508974 0.0756362 -0.0555946 +-0.045787 0.0616401 -0.0714534 +-0.0463878 0.0860458 -0.0643425 +-0.0469 0.0754389 -0.0734442 +-0.0361876 0.0721397 -0.0877453 +-0.0344753 0.0506229 -0.0835042 +-0.0209274 0.0429352 -0.0951495 +-0.00835098 0.0548898 -0.109767 +-0.0439408 0.0675081 -0.0809412 +-0.0384794 0.0604865 -0.0888934 +-0.0325578 0.0529818 -0.0938199 +-0.0250287 0.0507859 -0.100857 +-0.0171358 0.0586173 -0.103485 +-0.00108771 0.0669554 -0.09638 +0.0141047 0.0764389 -0.0789872 +-0.0166767 0.0687863 -0.0931008 +-0.0154196 0.0443974 -0.106822 +0.00804033 0.0334573 -0.118139 +-0.00353356 0.0420783 -0.115203 +0.00267945 0.0333406 -0.10199 +0.0284162 0.0260832 -0.102463 +0.0140719 0.0342408 -0.0876383 +0.01206 0.042083 -0.0690778 +0.0262722 0.0834922 -0.057317 +0.052314 0.0257381 -0.0888721 +0.0550064 0.0153199 -0.121681 +0.0742668 0.0307726 -0.0684202 +0.0254542 0.0462258 -0.0537161 +0.0192751 0.0579365 -0.0299961 +0.043388 0.0389601 -0.0621497 +0.0632571 0.0407552 -0.0511604 +0.0628168 0.0511918 -0.0295138 +-0.00769957 0.0468719 -0.0674097 +0.0356439 0.036944 -0.129564 +0.00985644 0.0486694 -0.11871 +0.0293481 0.0500299 -0.116265 +0.034304 0.0639803 -0.0982281 +0.0203799 0.0394103 -0.126099 +0.0274107 0.0238815 -0.120304 +-0.00989932 0.038173 -0.0977698 +0.0409915 0.0204434 -0.130582 +0.0603476 0.0361414 -0.135064 +0.0745924 0.0111822 -0.144256 +0.0995383 0.0164619 -0.152082 +0.079494 0.0098491 -0.119596 +0.109969 -0.00178903 -0.14121 +0.128369 -0.00667529 -0.145234 +0.147176 -0.000628591 -0.159936 +0.143478 0.0207956 -0.143584 +0.15945 -0.0140125 -0.151421 +0.167046 -0.013357 -0.130058 +0.175024 -0.000463673 -0.161193 +0.200548 0.00730904 -0.144289 +0.228188 0.00606999 -0.13371 +0.232374 -0.0225206 -0.12062 +0.217352 -0.0205681 -0.149989 +0.196446 -0.0094088 -0.159916 +0.0468892 0.0318746 -0.136603 +0.0588847 0.0194871 -0.141629 +0.0497176 0.0425705 -0.12546 +0.067316 0.0466181 -0.121528 +0.0829023 0.0554408 -0.10632 +0.0702884 0.0671402 -0.0864572 +0.0736048 0.0280122 -0.141966 +-0.0393368 0.0927115 -0.058201 +-0.074253 -0.462729 -0.0674302 +-0.0882268 -0.46748 -0.0836924 +-0.10265 -0.454789 -0.102517 +-0.100302 -0.434985 -0.0953132 +-0.123508 -0.439573 -0.0964816 +0.30376 -0.329009 -0.220778 +-0.34576 -0.287787 -0.1184 +-0.333412 -0.299886 -0.118936 +-0.318278 -0.306436 -0.109371 +-0.342798 -0.273541 -0.122349 +-0.330946 -0.265681 -0.13448 +-0.32759 -0.278136 -0.147142 +-0.313986 -0.269795 -0.152301 +-0.304937 -0.277784 -0.160852 +-0.289134 -0.290053 -0.171285 +-0.300398 -0.29313 -0.159904 +-0.305136 -0.304081 -0.143109 +-0.303823 -0.326091 -0.148763 +-0.297334 -0.338307 -0.131821 +-0.0297344 -0.320795 0.126249 +-0.0440833 -0.337561 0.102751 +-0.0635963 -0.3222 0.124646 +-0.0820192 -0.303394 0.145977 +-0.0280108 -0.346215 0.0792887 +0.190023 -0.166658 -0.160984 +0.187606 0.489479 0.0788413 +0.169798 0.492699 0.0805537 +0.160239 0.479513 0.0724411 +0.160997 0.477019 0.0876359 +0.167909 0.48647 0.0907839 +0.168839 0.465921 0.0685027 +0.185848 0.461592 0.0756332 +0.163713 0.449815 0.0719867 +0.171034 0.442192 0.0868531 +0.172622 0.439121 0.100638 +0.176648 -0.0540189 0.138439 +0.191763 0.435033 0.0761478 +0.150024 0.450095 0.173316 +0.142684 0.444609 0.180888 +0.134925 0.435737 0.185852 +0.0901553 -0.0455623 0.257862 +0.0764097 -0.0467149 0.266788 +0.218445 0.190081 -0.00453558 +0.212983 0.187132 0.0158667 +0.234912 0.203072 -0.0090602 +0.217724 0.208098 -0.00630956 +0.209095 0.231498 0.0538229 +0.223398 0.222537 0.0510417 +0.229495 0.205818 0.051858 +0.241614 0.200114 0.0387668 +0.245196 0.212463 0.0252865 +0.232616 0.199508 0.066443 +0.245867 0.187445 0.0704899 +0.218046 0.211438 0.0580939 +0.206013 0.207163 0.0667587 +0.208167 0.217137 0.0808695 +0.189985 0.216171 0.0819923 +-0.328288 -0.282754 -0.0562593 +-0.321215 -0.270892 -0.0527491 +-0.321885 -0.294532 -0.0580289 +-0.324301 -0.301836 -0.070993 +-0.309665 -0.294095 -0.0515043 +-0.298437 -0.298535 -0.0585809 +-0.293755 -0.297175 -0.0685565 +-0.301865 -0.303693 -0.0670723 +-0.312242 -0.307406 -0.0760424 +0.113855 0.0103494 0.135894 +0.117356 -0.000872108 0.134011 +0.24192 0.231796 0.179613 +0.236568 0.24336 0.180529 +0.226028 0.250706 0.186633 +0.280884 -0.220307 -0.163899 +0.26654 -0.211351 -0.150233 +0.265056 -0.233891 -0.14678 +0.318482 -0.331697 -0.239506 +0.324395 -0.322699 -0.253479 +0.31194 -0.314679 -0.269415 +0.329739 -0.334727 -0.229668 +0.336703 -0.323152 -0.229076 +0.344428 -0.313085 -0.23571 +0.342498 -0.293727 -0.236916 +0.350543 -0.322922 -0.2465 +0.353252 -0.314 -0.261759 +0.347047 -0.326986 -0.235121 +0.0827363 -0.465408 -0.0592863 +0.0757733 -0.45735 -0.0483001 +0.0758332 -0.442944 -0.0486429 +0.0763754 -0.427162 -0.064874 +0.0810297 -0.429275 -0.0354104 +0.0760881 -0.402196 -0.0628009 +0.0803331 -0.462498 -0.0366385 +0.075746 -0.427719 -0.0496393 +0.213629 0.454927 0.154222 +0.216172 0.433851 0.152191 +0.213875 -0.163106 0.208849 +0.228479 0.0837143 -0.0171959 +0.214862 0.0777937 -0.0178642 +0.203914 0.0820668 -0.0169156 +0.213551 0.066976 -0.0133462 +-0.291696 -0.291685 -0.053913 +-0.288445 -0.286967 -0.0453936 +-0.283457 -0.280518 -0.0392925 +0.198493 0.267303 0.113918 +-0.00816198 -0.315253 0.11742 +0.312224 -0.337685 -0.224702 +0.0776115 -0.0114015 0.225043 +0.094616 -0.00802053 0.222738 +0.212523 -0.00317223 -0.153514 +0.228944 -0.0069181 -0.146501 +0.230166 -0.0223035 -0.138067 +0.212902 -0.0238532 -0.132712 +0.194522 -0.0219296 -0.138137 +0.240306 -0.00819778 -0.130311 +0.24497 -0.0122967 -0.113875 +0.221562 -0.0094445 -0.0973672 +0.242491 -0.00970392 -0.0927411 +-0.195428 -0.293105 -0.0588105 +-0.174639 -0.293714 -0.0615636 +-0.159198 -0.295096 -0.0708856 +-0.150745 -0.297027 -0.0916319 +-0.165094 -0.309633 -0.116063 +-0.129532 -0.293794 -0.0901166 +-0.12154 -0.29002 -0.105668 +-0.103655 -0.284754 -0.110478 +-0.083304 -0.273535 -0.126518 +-0.126229 -0.291149 -0.124142 +-0.0551206 -0.282297 -0.123125 +-0.0279253 -0.280704 -0.123568 +-0.0254074 -0.296918 -0.100527 +-0.143636 -0.296672 -0.0765836 +0.228772 0.249576 0.00807469 +0.246793 0.197559 -0.000456927 +0.249351 0.185655 0.00965958 +0.077471 -0.38535 -0.0716786 +0.0780138 -0.366405 -0.0698751 +0.0796117 -0.349597 -0.0694382 +0.0817673 -0.324046 -0.067713 +0.0920794 -0.339278 -0.0766687 +0.0745961 -0.308674 -0.0513846 +0.0686559 -0.285979 -0.0584538 +0.0701691 -0.296007 -0.0346939 +0.0958416 -0.324563 -0.0739969 +0.111686 -0.315208 -0.0712996 +0.118212 -0.295045 -0.0671537 +0.145789 -0.285221 -0.0572786 +0.142444 -0.258951 -0.0651148 +0.125807 -0.256448 -0.0777825 +0.0725557 -0.302564 -0.0188272 +0.0757738 -0.318738 -0.0113816 +0.0755625 -0.334153 -0.022547 +0.0716925 -0.292684 -0.00740334 +0.0574002 -0.292216 -0.00131701 +0.0442788 -0.29974 -0.0118635 +0.0322898 -0.309073 -0.00126775 +0.0158934 -0.319374 -0.00927168 +0.00270388 -0.318254 -0.036966 +0.00321031 -0.33353 0.006095 +0.0101246 -0.330737 0.0331595 +0.0571801 -0.291727 0.0142738 +0.0411549 -0.302632 0.0323113 +0.0568056 -0.290026 0.0325413 +0.0726196 -0.279494 0.0399911 +0.0843075 -0.293947 0.0355701 +0.0802412 -0.296732 0.0208207 +0.0757523 -0.290551 0.00911073 +0.0904109 -0.307387 0.0401159 +0.0937218 -0.321431 0.0333001 +0.0876185 -0.332554 0.0196986 +-0.261918 -0.356193 -0.123562 +-0.274572 -0.363058 -0.128675 +-0.283885 -0.374671 -0.137095 +0.0993425 -0.475253 -0.0345906 +0.105878 -0.470302 -0.022596 +0.161209 0.00758193 -0.157082 +0.162861 -0.00496129 -0.160125 +0.14622 0.0234899 0.00861402 +0.16407 0.00688456 0.00334424 +0.187476 0.0108016 -0.000104135 +0.198618 0.0267239 -0.00776275 +0.213159 0.032032 -0.0211609 +0.229764 0.0271876 -0.0288068 +0.229938 0.0432028 -0.0342052 +0.231973 0.0361819 -0.05417 +0.241585 0.0230077 -0.0674939 +0.235826 0.0200922 -0.0913851 +0.229532 0.00831192 -0.0604593 +0.228417 0.0182383 -0.11087 +0.214387 0.0313739 -0.095916 +0.23826 0.0319925 -0.0407356 +0.240603 0.0153722 -0.0478262 +0.185434 0.0390225 -0.0120783 +0.174046 0.035224 -0.0278333 +0.183039 0.0254835 -0.0435084 +0.185088 0.013208 -0.0664572 +0.184517 -0.00115634 -0.0944301 +0.15883 0.0112792 -0.0789407 +0.166768 0.0454452 -0.0125857 +0.149871 0.0473393 -0.0127261 +0.24097 0.0273212 -0.0523021 +0.244689 0.0183228 -0.0578172 +0.239121 0.00955592 -0.0564169 +0.23067 0.0133196 -0.0511149 +0.217815 0.013095 -0.0555127 +0.202953 0.0215885 -0.0445658 +0.223255 0.0309758 -0.00933388 +0.246338 0.00680161 -0.0920968 +-0.29666 -0.251794 -0.0420083 +-0.282377 -0.246563 -0.0382484 +-0.274248 -0.257163 -0.0411355 +0.121069 0.3764 0.220244 +0.124178 0.361607 0.222425 +0.12316 0.347289 0.21517 +0.120818 0.335014 0.200629 +0.131773 0.318764 0.203442 +0.240354 -0.189104 -0.174254 +0.226426 -0.17846 -0.157236 +0.25469 -0.197929 -0.186668 +0.262527 -0.207499 -0.20859 +0.275709 -0.206748 -0.189755 +0.268196 -0.218714 -0.226562 +0.252109 -0.214264 -0.221034 +0.231966 -0.219863 -0.222417 +0.16439 -0.290409 -0.045741 +0.174232 0.353361 0.161991 +0.167416 0.346038 0.151615 +0.153417 0.351454 0.147309 +0.141711 0.365653 0.160008 +0.174784 0.33351 0.146976 +0.172695 0.32064 0.137876 +0.171538 0.327653 0.122668 +-0.153467 -0.465689 -0.0917447 +-0.142244 -0.458217 -0.0978282 +-0.137315 -0.444624 -0.0945322 +-0.142546 -0.468457 -0.0929801 +-0.130113 -0.470071 -0.0887414 +-0.111868 -0.466578 -0.0912306 +-0.129822 -0.476932 -0.0773011 +-0.116192 -0.47396 -0.0799073 +-0.102072 -0.471199 -0.0816089 +0.0648327 -0.288276 0.006469 +0.290523 -0.14969 0.120852 +0.286341 -0.149084 0.132395 +0.276561 -0.154417 0.131433 +0.266874 -0.144863 0.128327 +0.266123 -0.155511 0.139202 +0.254682 -0.156501 0.14847 +0.243072 -0.144724 0.147014 +0.246658 -0.132891 0.13506 +0.271484 -0.158645 0.148826 +0.262513 -0.161728 0.150556 +0.255383 -0.163883 0.160093 +0.258182 -0.154155 0.170424 +0.247063 -0.165211 0.168804 +0.236375 -0.166699 0.177267 +0.223809 -0.16596 0.182974 +0.219971 -0.167303 0.19665 +0.224247 -0.15536 0.203023 +0.206877 -0.166582 0.198203 +0.201256 -0.167208 0.210293 +0.187949 -0.165778 0.214542 +0.175727 -0.151043 0.207983 +0.205839 -0.156778 0.218275 +0.191606 -0.158183 0.226132 +0.180969 -0.154585 0.235065 +0.170507 -0.150398 0.244702 +0.167678 -0.135398 0.246604 +0.174695 -0.121433 0.234619 +0.192199 -0.123695 0.219574 +0.161002 -0.150315 0.252813 +0.149901 -0.156196 0.25282 +0.145756 -0.15618 0.238445 +0.158231 -0.157867 0.22927 +0.148019 -0.147104 0.261177 +0.14318 -0.132144 0.260892 +0.131504 -0.114456 0.261736 +0.136414 -0.145181 0.266602 +0.124033 -0.152215 0.261533 +0.128756 -0.151616 0.248741 +0.169715 -0.162656 0.235355 +0.125332 -0.145025 0.270918 +0.118124 -0.13431 0.277651 +0.122928 -0.121301 0.271952 +0.113017 -0.148351 0.260498 +0.105868 -0.137752 0.254904 +0.0970603 -0.116879 0.246491 +0.113377 -0.13188 0.244126 +0.102989 -0.14407 0.26402 +0.09993 -0.141861 0.276203 +-0.208269 -0.22401 0.141633 +-0.20692 -0.250284 0.132437 +0.0965268 -0.427234 -0.105996 +0.0991486 -0.439673 -0.0998914 +0.19126 -0.17619 0.0390751 +0.184715 -0.204433 0.0324441 +0.164304 -0.221583 0.0465757 +0.1444 -0.208807 0.0686986 +0.0226172 -0.0147867 0.137076 +-0.142255 -0.49298 -0.0216335 +0.233691 0.0208001 -0.0385404 +-0.192672 -0.315988 0.0839294 +-0.202286 -0.295403 0.104035 +-0.212462 -0.276423 0.111373 +-0.218066 -0.285356 0.0914372 +-0.230517 -0.270625 0.068595 +0.136055 0.0355608 0.0131192 +0.121886 0.0399552 0.0198872 +0.106186 0.0275039 0.0255554 +0.0928691 0.0373146 0.0446539 +0.107832 0.0113031 0.0106037 +0.0853288 0.00897116 0.0135994 +0.0648776 -0.00152148 0.00684991 +0.301901 0.1917 0.196837 +0.304498 0.181718 0.192274 +0.29757 0.171529 0.192207 +0.283611 0.170157 0.190984 +0.17589 0.332048 0.230978 +0.176274 0.318104 0.221305 +0.189786 0.308195 0.22975 +0.199452 0.291101 0.221444 +0.210647 0.278153 0.221165 +0.212403 0.290739 0.232707 +0.229872 0.295702 0.229994 +0.238851 0.283146 0.23072 +0.237981 0.260514 0.227763 +0.248013 0.243086 0.221386 +0.245976 0.271423 0.230129 +0.237201 0.240055 0.208931 +0.239318 0.292509 0.222434 +0.244312 0.28734 0.210021 +0.234086 0.289095 0.199595 +0.221914 0.298769 0.201947 +0.1778 0.322602 0.229777 +0.232474 0.299285 0.221376 +0.223334 0.304746 0.213608 +0.207337 0.311267 0.204764 +0.224642 0.304397 0.226583 +0.214619 0.302742 0.233384 +0.203769 0.313465 0.232857 +0.204968 0.319702 0.218324 +0.201735 0.298965 0.232154 +-0.0492057 -0.0812756 -0.10551 +-0.0710597 -0.075701 -0.12067 +-0.0879497 -0.0905516 -0.13677 +-0.0843511 -0.119489 -0.147588 +-0.0762899 -0.059326 -0.102542 +-0.0985707 -0.0477827 -0.098696 +-0.118275 -0.0536394 -0.113913 +-0.11441 -0.0717159 -0.128365 +0.179503 0.303256 0.0436704 +0.192013 0.290229 0.0290644 +0.17689 0.287515 0.0370015 +0.192038 0.271729 0.0156116 +0.209167 0.267708 0.00969983 +0.200133 0.255704 0.00478026 +-0.247504 -0.392344 -0.224787 +-0.247477 -0.405986 -0.218212 +-0.243099 -0.400741 -0.206484 +-0.246703 -0.405341 -0.193269 +-0.249065 -0.417066 -0.193806 +-0.263856 -0.417281 -0.202583 +-0.253854 -0.410374 -0.185389 +-0.264275 -0.407223 -0.177693 +-0.272044 -0.40206 -0.166216 +-0.284666 -0.409799 -0.163624 +-0.28689 -0.423019 -0.170791 +-0.283285 -0.428723 -0.186577 +-0.301536 -0.424549 -0.197331 +-0.276684 -0.426319 -0.176604 +-0.270204 -0.426002 -0.18843 +-0.267033 -0.421163 -0.178871 +-0.28572 -0.431162 -0.176917 +0.0984334 0.0428629 0.147655 +0.0984512 0.0370662 0.158757 +-0.324734 -0.278381 -0.0492733 +-0.319049 -0.278035 -0.0388895 +-0.314693 -0.271902 -0.0298211 +-0.0814975 -0.486596 -0.0514846 +-0.0716057 -0.47534 -0.0576231 +-0.0807984 -0.475501 -0.0687174 +-0.0782273 -0.46782 -0.0773567 +-0.0794515 -0.454639 -0.076562 +-0.0865219 -0.442019 -0.0638219 +-0.0826697 -0.456554 -0.0896798 +-0.0913604 -0.446861 -0.0969099 +-0.0924184 -0.432044 -0.0753911 +-0.098273 -0.416607 -0.0817744 +-0.111942 -0.395187 -0.0818225 +-0.0923505 -0.401008 -0.0727607 +-0.110463 -0.376831 -0.0757945 +-0.0955645 -0.358515 -0.0727168 +-0.0748788 -0.367775 -0.053732 +-0.099584 -0.336657 -0.0718408 +-0.0617229 -0.346951 -0.0508932 +-0.0372908 -0.340191 -0.0358611 +-0.187209 -0.0514446 0.134371 +-0.172275 -0.062062 0.144345 +-0.181772 -0.0387772 0.12984 +0.27325 0.225257 0.167666 +0.283037 0.221467 0.169903 +0.141164 -0.00931766 -0.150578 +0.223335 -0.262546 -0.149684 +0.199958 -0.258684 -0.141852 +0.218212 -0.249649 -0.131577 +-0.0730224 -0.485274 -0.0383372 +-0.0765985 -0.473674 -0.025717 +-0.0833487 -0.485599 -0.0202509 +-0.0969784 -0.487241 -0.0157338 +-0.106328 -0.475595 -0.0156679 +-0.107519 -0.486132 -0.0147883 +-0.117398 -0.491224 -0.0155421 +-0.11866 -0.497871 -0.0255495 +0.192205 -0.0198585 -0.151725 +0.281772 0.238327 0.210562 +0.269826 0.243309 0.222088 +0.243244 0.207816 -0.00325363 +0.239729 0.221932 -0.000908316 +0.243256 0.225044 0.0142927 +0.235434 0.23543 0.00346349 +0.158954 -0.447934 -0.074517 +0.164 -0.440163 -0.0849532 +0.160645 -0.422992 -0.0839209 +0.160099 -0.41995 -0.0633914 +0.170063 -0.432118 -0.0580684 +0.170775 -0.442201 -0.0470561 +0.167356 -0.452883 -0.036848 +0.157537 -0.464023 -0.0432353 +0.154265 -0.458207 -0.0582632 +0.146921 -0.466798 -0.0291891 +0.17099 -0.445942 -0.0649823 +0.152813 -0.426396 -0.0985179 +0.142833 -0.435406 -0.0989063 +0.126573 -0.436557 -0.100225 +0.120949 -0.42189 -0.103936 +0.130685 -0.411647 -0.0938972 +0.160351 -0.460975 -0.0324222 +0.164884 -0.460693 -0.0398836 +0.167083 -0.430709 -0.0834012 +0.161089 -0.432508 -0.0931652 +0.165433 -0.424956 -0.0749657 +0.155909 -0.417913 -0.0743018 +0.149825 -0.407366 -0.067413 +0.142015 -0.399818 -0.0764637 +0.153043 -0.435416 -0.0966096 +0.148842 -0.431897 -0.101759 +0.145045 -0.424265 -0.10134 +0.147732 -0.418014 -0.0911084 +0.138977 -0.417451 -0.0965307 +0.139635 -0.411036 -0.0878314 +0.14174 -0.430413 -0.104765 +0.134784 -0.434536 -0.101822 +0.135086 -0.440748 -0.0918112 +0.13766 -0.447456 -0.0800542 +0.122938 -0.455334 -0.0698495 +0.127914 -0.428797 -0.106691 +0.135671 -0.430083 -0.106069 +-0.0268041 -0.304928 0.142542 +-0.0182344 -0.281255 0.151927 +0.000262015 -0.258244 0.142866 +0.0151742 -0.229959 0.128466 +-0.00970849 -0.227931 0.154073 +0.0337917 -0.209923 0.115845 +0.0199495 -0.192987 0.125832 +-0.154293 -0.0335699 -0.082135 +-0.129631 -0.0324487 -0.0813475 +-0.120097 -0.027431 -0.0586998 +-0.0956922 -0.0340394 -0.0533561 +-0.0814148 -0.0448428 -0.0722969 +-0.0594432 -0.0515596 -0.0534184 +-0.160793 -0.0482086 -0.0989707 +-0.166155 -0.0307425 -0.0663998 +-0.169924 -0.0270352 -0.0414151 +-0.183311 -0.0375758 -0.0551581 +-0.174206 -0.0274939 -0.0203147 +-0.192353 -0.0397338 -0.00141151 +-0.170447 -0.0249801 0.0063437 +-0.211587 -0.0636911 -0.00501259 +-0.0018753 -0.187141 -0.149775 +0.0183103 -0.182965 -0.142326 +0.0322217 -0.167313 -0.134641 +0.0236675 -0.146992 -0.123167 +-0.00232452 -0.142332 -0.126149 +0.0375806 -0.18533 -0.140019 +0.0530379 -0.201545 -0.137283 +0.0772348 -0.20845 -0.140694 +0.0988175 -0.224384 -0.140468 +0.119251 -0.222512 -0.162731 +0.03788 -0.218276 -0.135529 +0.0772845 -0.19139 -0.155355 +0.080882 -0.225907 -0.127445 +0.0653619 -0.242778 -0.113036 +0.0731805 -0.173068 -0.155239 +0.0897045 -0.191329 -0.166141 +0.102707 -0.199007 -0.171074 +0.119058 -0.208637 -0.176942 +0.127514 -0.196293 -0.185172 +0.13998 -0.205302 -0.190755 +0.149824 -0.215626 -0.194546 +0.161245 -0.221969 -0.199237 +0.175364 -0.230409 -0.20401 +0.173584 -0.215336 -0.204853 +0.178202 -0.198362 -0.197173 +0.188397 -0.22907 -0.211289 +0.202734 -0.22056 -0.215065 +0.199745 -0.239634 -0.214151 +0.0815106 -0.18364 -0.162988 +-0.172104 -0.359269 -0.00938238 +-0.172319 -0.335226 -0.0164663 +-0.16873 -0.368903 -0.0231312 +-0.292266 -0.291505 -0.0889456 +-0.288266 -0.299574 -0.0955502 +-0.280983 -0.308012 -0.105167 +-0.278654 -0.297571 -0.101297 +-0.274336 -0.285615 -0.103446 +-0.260134 -0.28158 -0.0989442 +-0.257005 -0.265144 -0.10215 +-0.26942 -0.305285 -0.10276 +-0.257003 -0.309674 -0.100476 +-0.244993 -0.306014 -0.0938734 +-0.249351 -0.292113 -0.0926885 +-0.25954 -0.322424 -0.104282 +-0.267093 -0.332079 -0.111051 +-0.283312 -0.328944 -0.119574 +-0.249017 -0.331591 -0.10481 +-0.232981 -0.32784 -0.100164 +-0.240291 -0.342062 -0.113719 +-0.229688 -0.345883 -0.126712 +-0.23058 -0.352629 -0.145077 +-0.21352 -0.337371 -0.127344 +-0.269191 -0.344874 -0.117105 +-0.208623 -0.327937 -0.112241 +-0.191793 -0.321843 -0.117022 +-0.180909 -0.311277 -0.104708 +0.11012 0.10505 0.0238496 +0.213679 0.221732 0.163906 +-0.0357839 -0.0025294 0.108473 +-0.0312254 -0.0135193 0.128152 +-0.0238807 -0.033229 0.139313 +-0.00300831 -0.046529 0.144036 +-0.00364169 -0.0760125 0.145155 +-0.0103288 -0.10643 0.141831 +0.015326 -0.129347 0.142131 +-0.041062 -0.0443202 0.130625 +-0.0555252 -0.0465254 0.114753 +-0.0556686 -0.0325657 0.0996413 +-0.0768736 -0.0422105 0.0949058 +-0.0167984 0.000564353 0.123722 +0.00524698 0.0020139 0.129964 +-0.0281137 -0.0861213 0.139333 +-0.0785841 -0.0379469 0.0747431 +-0.0762529 -0.0505618 0.114297 +-0.032521 -0.108383 0.136839 +-0.0633754 -0.0458183 0.101476 +-0.0250298 0.00663901 0.112981 +-0.0219675 0.00393164 0.0935556 +-0.147404 -0.304789 -0.127071 +0.192111 0.473304 0.143665 +0.202701 0.475169 0.131787 +0.206558 0.475874 0.120017 +0.202492 0.480449 0.108775 +0.157654 -0.366957 -0.0205798 +0.26661 -0.307414 -0.281977 +0.270077 -0.295571 -0.288815 +0.283263 -0.291236 -0.297392 +0.290598 -0.279448 -0.297082 +0.304158 -0.276932 -0.29882 +0.315035 -0.2885 -0.301158 +0.307588 -0.298676 -0.297006 +0.297613 -0.307939 -0.283621 +0.293787 -0.301201 -0.295424 +0.318389 -0.297707 -0.296483 +0.328066 -0.301032 -0.289042 +0.324582 -0.309109 -0.276338 +0.33579 -0.291676 -0.2964 +0.346867 -0.288071 -0.287976 +0.353956 -0.299169 -0.28317 +0.345495 -0.307423 -0.274703 +0.352866 -0.288693 -0.277818 +0.351312 -0.284395 -0.265224 +0.355354 -0.294774 -0.257468 +0.360217 -0.304818 -0.260578 +0.35682 -0.308388 -0.269609 +0.359106 -0.312264 -0.252967 +0.356474 -0.316127 -0.245135 +0.351445 -0.319298 -0.237976 +-0.26647 -0.314705 -0.199507 +-0.27426 -0.329739 -0.204261 +-0.290128 -0.337563 -0.206145 +-0.303723 -0.332243 -0.195363 +-0.303858 -0.323407 -0.176279 +-0.302757 -0.349394 -0.210447 +-0.304665 -0.364526 -0.223447 +-0.321319 -0.375627 -0.232938 +-0.285437 -0.371465 -0.224735 +-0.28011 -0.37957 -0.242654 +-0.314609 -0.397575 -0.24523 +-0.31498 -0.344154 -0.199865 +-0.330892 -0.351901 -0.189469 +-0.332902 -0.388937 -0.243068 +-0.348245 -0.402805 -0.233911 +-0.328232 -0.404959 -0.235266 +-0.273541 -0.396265 -0.240028 +-0.293049 -0.39498 -0.245656 +-0.355214 -0.402159 -0.217135 +-0.360108 -0.415844 -0.205721 +-0.346381 -0.42668 -0.201491 +-0.340374 -0.436455 -0.180032 +-0.360217 -0.406031 -0.193698 +-0.356506 -0.391255 -0.182727 +-0.356512 -0.407116 -0.177427 +-0.347384 -0.421732 -0.172779 +-0.348669 -0.37532 -0.17511 +-0.341266 -0.408591 -0.160307 +-0.332592 -0.391247 -0.153464 +-0.323849 -0.407723 -0.153687 +-0.349384 -0.43169 -0.189135 +-0.335815 -0.43119 -0.192046 +-0.324454 -0.435806 -0.181733 +-0.331465 -0.433295 -0.170921 +-0.314528 -0.431132 -0.168412 +-0.260177 -0.397767 -0.235 +-0.252953 -0.401301 -0.227678 +-0.247407 -0.394723 -0.238053 +-0.24372 -0.401046 -0.225417 +-0.243948 -0.396615 -0.216223 +-0.258003 -0.38952 -0.247437 +-0.272162 -0.387844 -0.252537 +-0.287147 -0.384539 -0.255755 +-0.302942 -0.384129 -0.252391 +-0.315505 -0.382766 -0.24459 +-0.323099 -0.390444 -0.249836 +-0.312399 -0.390336 -0.253745 +-0.328503 -0.399215 -0.245058 +-0.340635 -0.398589 -0.24271 +-0.266346 -0.382624 -0.244488 +-0.267321 -0.391914 -0.245578 +-0.0266812 0.0695328 -0.0242573 +-0.00773299 0.0681739 -0.0184911 +0.0122858 0.0669077 -0.0123781 +0.0150035 0.0767227 0.00239352 +0.0141467 0.0954062 -0.00215996 +0.0325338 0.098411 -0.00617133 +0.0450676 0.0983028 0.010086 +0.0314473 0.0730983 0.00401189 +0.0505593 0.0686309 0.00292132 +0.0698817 0.067505 0.00832925 +0.145383 0.180744 0.0984363 +0.132189 0.17376 0.0925198 +0.121241 0.164951 0.0850023 +0.133425 0.169934 0.0774819 +0.11505 0.153676 0.07879 +-0.083942 -0.368893 -0.0674225 +-0.0809876 -0.385027 -0.0581697 +-0.0723248 -0.382058 -0.0416794 +-0.00904893 0.0914446 -0.0120745 +0.00504523 0.0987359 -0.0150796 +0.0060609 0.0932522 -0.034057 +0.0248461 0.0873188 -0.0377031 +0.0363994 0.089055 -0.023789 +0.00213821 0.0914225 -0.00482177 +0.0092558 0.0863088 0.00212053 +0.106375 0.0274106 0.14138 +-0.263884 -0.385451 -0.252252 +0.258755 0.24689 0.225661 +0.259085 0.23306 0.219814 +0.249971 0.25591 0.228242 +-0.322841 -0.345115 -0.164492 +-0.323706 -0.355326 -0.152393 +-0.279169 -0.265328 -0.0439542 +-0.285416 -0.267917 -0.0516616 +-0.294745 -0.263175 -0.0517725 +0.23393 -0.0149701 -0.10397 +0.219738 -0.0165453 -0.112039 +0.204608 -0.00981825 -0.104246 +0.187184 -0.00954937 -0.110855 +0.228145 0.230452 0.102316 +0.214447 0.238029 0.0983297 +0.23229 0.220992 0.0943503 +0.215398 0.247623 0.105271 +0.217938 0.25177 0.117669 +0.210276 0.258003 0.111405 +0.220949 0.241286 0.103103 +0.290344 -0.337843 -0.233955 +0.276226 -0.337233 -0.22831 +0.296573 -0.339782 -0.226215 +0.227663 0.461812 0.0838481 +0.234265 0.455281 0.0718225 +0.229698 0.445794 0.0603386 +0.225781 0.470182 0.0813133 +0.214396 0.4698 0.0788369 +0.208406 0.478123 0.0862021 +0.214031 0.460896 0.0711899 +0.217085 0.451741 0.0628259 +0.219354 0.474333 0.0827819 +0.21619 0.47758 0.0903862 +0.217994 0.472178 0.097233 +0.209525 0.481852 0.0939712 +0.227208 0.456115 0.0633709 +0.234329 0.451682 0.0642008 +0.23166 0.462658 0.0759848 +0.273713 -0.249314 -0.252993 +0.274317 -0.268417 -0.267071 +0.263304 -0.282613 -0.260934 +-0.240326 -0.404033 -0.2139 +-0.241182 -0.408607 -0.207233 +0.243855 0.194683 0.113624 +0.235959 0.206195 0.114609 +-0.329827 -0.30598 -0.098469 +-0.057071 -0.0425853 0.0117122 +-0.0551192 -0.0420888 0.0309046 +-0.0534835 -0.0402863 0.0500454 +-0.0435993 -0.0469165 0.00748095 +-0.0255629 -0.0374196 0.00481763 +-0.00817324 -0.0328811 -0.0061182 +-0.00350439 -0.0437548 -0.0255784 +-0.0349503 -0.0490115 -0.00492533 +-0.0419875 -0.0536475 -0.0293419 +-0.0139014 -0.0607747 -0.0378374 +-0.0105205 -0.0780801 -0.0585195 +-0.0335249 -0.0540562 -0.0180409 +-0.0278411 -0.0595083 -0.0313207 +0.193253 0.49569 0.0858481 +0.189805 0.494474 0.0949255 +0.179559 0.491992 0.0947812 +0.19709 0.487808 0.0978913 +0.174576 0.497081 0.0879734 +0.179584 0.496616 0.0784813 +0.175502 0.48892 0.0725035 +0.169475 0.481635 0.069206 +0.164994 0.474033 0.0669237 +0.155945 0.469227 0.0714265 +0.159639 0.459314 0.0671634 +0.160451 -0.0544036 0.113535 +0.0454737 -0.0938547 0.293886 +0.0481458 -0.104952 0.292926 +0.0550885 -0.114349 0.29062 +0.0654216 -0.120788 0.289843 +0.0691263 -0.126298 0.278339 +0.0372417 -0.0943784 0.286279 +0.0377118 -0.088702 0.274623 +0.179652 -0.262284 0.0054219 +0.186087 -0.244472 0.00347757 +0.246807 -0.00615903 -0.103541 +0.242297 -0.0135206 -0.100916 +0.240802 -0.0172339 -0.108388 +0.232593 -0.0188607 -0.112191 +0.240348 -0.0194541 -0.117278 +0.238974 -0.018297 -0.127651 +-0.164632 -0.397326 -0.024693 +0.0813645 -0.458079 -0.0716845 +0.302397 0.127887 0.0470846 +0.298473 0.138148 0.0455108 +0.292313 0.136477 0.0386335 +0.288054 0.130079 0.0326142 +0.28271 0.137427 0.0379629 +0.271939 0.136706 0.038053 +0.261008 0.14116 0.0404912 +0.28194 0.12422 0.0312108 +0.300876 0.126279 0.0551937 +0.295306 0.129324 0.0632115 +0.286846 0.130603 0.0706512 +0.282604 0.11846 0.0804122 +0.273418 0.134767 0.0747422 +0.296205 0.121995 0.0600976 +0.289869 0.116278 0.0576534 +0.283444 0.108666 0.0679441 +0.208186 0.435058 0.0678801 +0.218992 0.437774 0.0675136 +0.20517 0.444041 0.0615 +0.195457 0.447135 0.0675955 +0.224157 0.438328 0.0597838 +0.221367 0.446069 0.0584788 +0.168291 -0.443724 -0.076199 +-0.239169 -0.248023 -0.0426243 +-0.246509 -0.244281 -0.0523825 +-0.245933 -0.250709 -0.0701381 +-0.252213 -0.23035 -0.0598084 +-0.256922 -0.212794 -0.063622 +-0.26443 -0.20039 -0.048456 +-0.236601 -0.248665 -0.0331221 +-0.248238 -0.244973 -0.04299 +-0.257005 -0.243536 -0.0363368 +-0.264619 -0.253098 -0.0324677 +-0.260909 -0.234911 -0.0387305 +-0.270856 -0.228969 -0.0335016 +-0.268106 -0.214873 -0.0367573 +-0.255525 -0.250409 -0.0291707 +-0.246354 -0.252152 -0.0213798 +-0.25421 -0.258055 -0.0140562 +-0.253371 -0.258976 0.00135493 +-0.263391 -0.256528 0.0180325 +-0.264412 -0.265611 -0.0106557 +-0.268835 -0.263918 0.00476582 +-0.24972 -0.252323 0.0327963 +-0.239732 -0.259608 0.0493553 +-0.242639 -0.251027 0.0706418 +-0.27192 -0.270836 -0.02103 +-0.264888 -0.241199 0.0366373 +-0.279792 -0.22631 0.033251 +-0.274206 -0.207933 0.0474852 +-0.283361 -0.276288 -0.0174295 +-0.267659 -0.226048 0.0482271 +0.202151 0.274483 0.19338 +0.194908 0.283204 0.198963 +-0.157532 -0.273615 -0.179435 +-0.176899 -0.279729 -0.184503 +-0.188947 -0.290942 -0.187096 +-0.192598 -0.3074 -0.18306 +-0.203551 -0.297799 -0.190929 +-0.222085 -0.288246 -0.191352 +-0.217908 -0.303036 -0.194268 +-0.355074 -0.426501 -0.195973 +-0.354866 -0.423993 -0.205337 +-0.355569 -0.419108 -0.214528 +-0.353763 -0.412061 -0.224887 +-0.346029 -0.286085 -0.1062 +-0.341227 -0.288967 -0.0947058 +-0.336277 -0.278132 -0.0971269 +-0.328988 -0.269127 -0.105169 +-0.340297 -0.292656 -0.0831052 +-0.335578 -0.266756 -0.115188 +-0.339311 -0.299368 -0.0917431 +0.212569 0.261061 0.18216 +0.216886 0.255854 0.175009 +0.219484 0.251322 0.162982 +0.212289 0.247584 0.170006 +0.218513 0.26322 0.154269 +0.225667 0.261532 0.178216 +0.218436 0.276817 0.178562 +0.234042 0.273996 0.185236 +0.223426 0.242038 0.154678 +0.21181 0.288948 0.181391 +0.220498 0.257755 0.18435 +0.211254 0.266563 0.187703 +0.211739 0.26954 0.199826 +0.278409 -0.209413 -0.174692 +0.233056 0.457965 0.0658843 +0.227063 0.46182 0.0682472 +0.220168 0.458063 0.0666597 +-0.0481392 -0.0447802 0.0166181 +0.131516 0.0530135 0.000672445 +0.12038 0.0567042 0.000376152 +0.134766 0.046581 0.0097546 +0.0956782 -0.141364 0.26837 +0.0877085 -0.13595 0.269242 +0.0854698 -0.124959 0.261926 +0.0839071 -0.111836 0.253439 +0.0904091 -0.099649 0.239147 +0.0872053 -0.136949 0.279095 +0.085161 -0.130401 0.287023 +0.0763801 -0.13103 0.282851 +-0.00884361 -0.0890856 -0.0728998 +-0.00654069 -0.102279 -0.0895079 +-0.0290648 -0.104665 -0.111248 +-0.0100257 -0.116287 -0.107029 +0.0875054 -0.104584 0.297054 +0.191386 -0.264049 -0.175252 +0.190045 -0.262732 -0.156889 +0.204589 -0.269071 -0.178679 +0.222111 -0.273266 -0.172895 +0.189235 0.0753918 -0.0129238 +0.0782752 -0.467624 -0.0498343 +0.0759673 -0.46177 -0.0555898 +0.0772195 -0.460605 -0.0642783 +0.151932 0.323656 0.079912 +0.153175 0.313215 0.0881136 +0.161272 0.302381 0.0857396 +0.163146 0.324848 0.0718597 +0.151557 0.334415 0.0880604 +0.142886 0.334889 0.0972586 +0.140662 0.34411 0.107021 +0.133598 0.347717 0.117582 +0.131314 0.355467 0.129074 +0.127988 0.361743 0.142546 +0.123763 0.348981 0.138438 +0.119822 0.353337 0.149718 +0.116288 0.351928 0.168204 +0.226419 0.174912 -0.00671405 +0.232006 0.15884 0.00199041 +0.243933 0.169091 0.00253819 +0.237571 0.172786 -0.00612936 +0.183717 0.142245 0.147062 +0.183533 0.157982 0.153224 +0.200684 0.169917 0.154336 +0.175927 0.14817 0.154877 +0.164064 0.143191 0.159694 +0.181391 0.132744 0.149775 +0.177453 0.123521 0.157312 +0.108424 0.0602759 0.0311611 +0.101691 0.0511896 0.042029 +0.297187 0.12858 0.124591 +0.286869 0.125817 0.115842 +0.279264 0.13651 0.11071 +0.277464 0.150893 0.114839 +0.267972 0.163015 0.116989 +0.29066 -0.215317 -0.195858 +-0.0439761 -0.143405 -0.149346 +0.0959309 0.0199379 0.158053 +0.0941358 0.00844127 0.16726 +0.273991 -0.158318 0.138404 +0.280108 -0.155995 0.136908 +0.28311 -0.154668 0.131232 +0.287165 -0.152142 0.126309 +0.291082 -0.145525 0.127381 +0.258354 -0.329753 -0.2515 +0.256649 -0.327468 -0.240856 +0.265642 -0.321399 -0.233195 +0.269005 -0.32965 -0.227653 +0.204877 0.287044 0.0357487 +0.289139 -0.339472 -0.226774 +0.282728 -0.335989 -0.224475 +0.283065 -0.327384 -0.221193 +0.28398 -0.316486 -0.219293 +0.289461 -0.305296 -0.210924 +0.2738 -0.310998 -0.221733 +0.2646 -0.301502 -0.221281 +0.282981 -0.339471 -0.231684 +0.275544 -0.336339 -0.239462 +0.259131 -0.2954 -0.232139 +0.281853 -0.296955 -0.202405 +0.287258 -0.287693 -0.192682 +0.301236 -0.282638 -0.194913 +0.23745 0.0270265 -0.0333549 +0.234865 0.0358956 -0.0292661 +0.240774 0.0243245 -0.0402136 +0.034599 -0.0884904 0.28182 +0.0345637 -0.0787252 0.277243 +0.0422003 -0.0728232 0.283477 +0.048607 -0.0763619 0.292696 +0.0395236 -0.0802562 0.266836 +0.0486856 -0.0788086 0.257578 +0.044992 -0.0647291 0.254151 +0.0587204 -0.0731238 0.296598 +0.068389 -0.0812067 0.300077 +0.0829644 -0.0808872 0.290453 +0.0435251 -0.0559756 0.262078 +0.20354 0.276522 0.016541 +-0.0980428 -0.240155 0.197738 +-0.0924965 -0.26196 0.186819 +-0.109853 -0.270124 0.168775 +-0.253582 -0.386742 -0.238773 +-0.0267016 0.0982672 -0.0374627 +0.214024 0.433945 0.0622105 +0.204736 0.432758 0.058829 +0.201109 0.433103 0.0655996 +0.201809 0.436011 0.073894 +0.193477 0.433855 0.0682907 +0.185218 0.436354 0.0703184 +0.180836 0.436291 0.0819631 +0.191166 0.440882 0.0659291 +0.187348 0.447071 0.070626 +0.179215 0.453739 0.0726364 +0.193028 0.454826 0.0736221 +0.173421 0.440644 0.0776765 +-0.147031 -0.496444 -0.028386 +-0.151597 -0.495421 -0.0374969 +-0.157627 -0.484775 -0.0397619 +-0.140246 -0.499465 -0.0256815 +-0.132401 -0.5 -0.0296698 +-0.132703 -0.497498 -0.0384881 +-0.126331 -0.494492 -0.0452588 +-0.11646 -0.490117 -0.0524448 +-0.101295 -0.487303 -0.0547567 +-0.136101 -0.494007 -0.0471871 +-0.13938 -0.490039 -0.0561432 +-0.133381 -0.483866 -0.0661423 +-0.15577 -0.492035 -0.0446482 +-0.153261 -0.490282 -0.0555144 +0.197755 0.272342 0.0690149 +0.190382 0.263313 0.0560052 +0.0686632 -0.292912 -0.0237205 +0.056243 -0.29127 -0.0303266 +0.0398126 -0.298058 -0.030698 +0.0315681 -0.295788 -0.0489563 +0.043708 -0.285681 -0.061727 +0.0621136 -0.289132 -0.040881 +0.0722108 -0.295077 -0.0484755 +0.0577034 -0.286988 -0.0524253 +0.0569935 -0.281989 -0.0659264 +0.064236 -0.290328 -0.0328163 +-0.0127838 0.0757233 -0.00921143 +0.0935192 0.0772038 0.0642915 +0.169714 0.302879 0.0497006 +0.163659 0.300165 0.0640716 +0.172929 0.295611 0.0434924 +0.049865 0.0913802 0.0221499 +0.0418831 0.0808731 0.013212 +0.0368549 0.0913191 0.0145569 +0.0319565 0.0968433 0.00544037 +0.310435 0.13526 0.142507 +0.026474 0.0305763 -0.129196 +0.017822 0.0292426 -0.122273 +0.0163904 0.0280919 -0.108702 +0.0350495 0.0278097 -0.132911 +0.178361 0.286185 0.0866978 +0.184473 0.288229 0.0959947 +0.0746028 -0.0119842 0.202652 +0.0770488 -0.00198153 0.201878 +0.0861829 0.00359659 0.206228 +0.0964676 0.00912576 0.20305 +0.110414 0.00821695 0.200752 +0.119478 0.0159283 0.18886 +-0.0749585 -0.470198 -0.0703816 +-0.0722579 -0.469101 -0.0627931 +-0.0775597 -0.45771 -0.0519849 +-0.0725204 -0.466379 -0.0530837 +-0.0822617 -0.458336 -0.0360309 +0.11796 -0.00196684 -0.151498 +0.110489 0.008862 -0.155734 +0.119387 0.0273131 -0.141295 +0.100036 0.00317869 -0.149099 +0.0946498 0.00360487 -0.130289 +0.0996271 0.00897841 -0.108462 +0.0876406 0.00969553 -0.149119 +0.0889673 0.0239205 -0.144401 +0.103773 0.0275171 -0.140968 +0.112143 0.0407687 -0.122665 +0.128275 -0.00210722 -0.155193 +0.136944 0.00690927 -0.158099 +0.1315 0.01712 -0.150046 +0.148823 0.0111196 -0.154092 +0.137878 -0.00286061 -0.157253 +0.0812501 0.0180999 -0.148671 +0.0723702 0.0199576 -0.146504 +0.0894465 0.0177562 -0.14994 +-0.244247 -0.411744 -0.197734 +0.0532101 -0.0425986 0.239458 +0.0614299 -0.034607 0.250277 +0.0718515 -0.0264935 0.244569 +0.0612036 -0.0408317 0.227838 +0.211416 0.21985 0.0506815 +0.209629 0.209187 0.0516229 +0.197715 0.200596 0.0531448 +0.210711 0.212673 0.041983 +0.209533 0.205981 0.0261421 +0.207685 0.214484 0.0320655 +0.204793 0.215907 0.019768 +0.207322 0.190012 0.0316877 +0.210424 0.206724 0.0353988 +0.209086 0.197885 0.0355421 +0.19948 0.191764 0.0420701 +0.206287 0.1798 0.0239909 +0.199532 0.162119 0.0159658 +0.0889829 0.0153312 0.187549 +0.0895058 0.0194699 0.175832 +0.0997882 0.0258376 0.180178 +0.0912633 -0.43583 -0.104962 +0.0893849 -0.44209 -0.0966632 +0.0818551 -0.438899 -0.0891003 +0.0775492 -0.435915 -0.0759439 +0.0805228 -0.426773 -0.087989 +0.0848008 -0.421093 -0.0971385 +0.0844397 -0.410175 -0.0930928 +0.0796444 -0.399052 -0.082153 +0.096306 -0.399151 -0.0928503 +0.0992866 -0.434977 -0.10667 +-0.038871 -0.095203 0.134909 +-0.0453136 -0.074362 0.132403 +-0.0642973 -0.0816285 0.135216 +0.128958 0.371237 0.164377 +0.114324 0.368213 0.169385 +0.110394 0.358489 0.182698 +0.119359 0.382173 0.172221 +0.244566 0.0274799 0.091132 +0.236517 0.0321023 0.108593 +0.228129 0.0154777 0.110489 +0.243652 -0.0044318 0.106704 +0.215089 0.0116198 0.126655 +0.193164 -0.00203925 0.149761 +0.295901 -0.145148 0.11649 +0.181002 0.326878 0.162405 +0.192626 0.308402 0.164847 +0.180295 0.335983 0.171005 +0.215019 0.222685 -0.0085752 +0.216226 0.238327 -0.00679645 +0.204842 0.243639 -0.00108745 +0.197086 0.237151 0.00943393 +0.207737 0.21475 -0.00125832 +0.200663 0.225332 0.00994825 +0.227239 0.239308 -0.00361834 +0.210369 0.205349 -0.000451507 +0.212421 0.195338 0.00658041 +0.0965367 0.0723068 0.0490018 +-0.263237 -0.382248 -0.20077 +-0.334935 -0.395374 -0.246716 +0.0666968 0.0983382 0.0352739 +0.0735768 0.104043 0.0256427 +0.0854137 0.105714 0.0280147 +0.0966684 0.103408 0.0197312 +-0.293219 -0.246559 0.00868918 +-0.284829 -0.260543 0.00656712 +0.231694 -0.239358 -0.229883 +0.249173 -0.248287 -0.23972 +-0.313753 -0.278534 -0.156686 +-0.167921 -0.0222432 0.100354 +-0.166557 -0.0217484 0.0804222 +-0.137191 -0.0189498 0.0544508 +-0.183157 -0.0297007 0.0652393 +-0.193717 -0.0386652 0.0428719 +-0.162262 -0.0205653 0.0563587 +-0.148465 -0.0201145 0.071316 +-0.122512 -0.0229086 0.0762312 +-0.112808 -0.0225311 0.0535636 +-0.15755 -0.0225071 0.112728 +-0.13968 -0.0242143 0.109228 +-0.128528 -0.0323847 0.121144 +-0.137944 -0.0426964 0.133983 +0.338353 -0.331842 -0.233 +0.197716 0.0369013 -0.0158252 +0.225598 0.0269623 0.107608 +0.227611 0.0352699 0.116368 +0.216481 0.0416846 0.126455 +0.20366 0.0291575 0.127785 +0.197706 0.0139181 0.138946 +0.177004 0.0154396 0.15063 +0.196436 0.0406475 0.130552 +0.183582 0.0465791 0.137895 +0.171962 0.0340634 0.144092 +0.209838 0.0350513 0.1214 +0.122018 -0.0147207 0.202688 +0.134625 -0.010294 0.190699 +0.150345 -0.0204184 0.190322 +0.171467 -0.0443352 0.191435 +0.124137 -0.0275222 0.21069 +0.115004 -0.0324307 0.220668 +0.103488 -0.0235525 0.230568 +-0.234966 -0.250492 -0.00657503 +0.230136 -0.0629922 0.010065 +0.22781 -0.0439028 0.0052695 +0.226758 -0.0758146 -0.00318988 +0.218119 -0.0755566 -0.0185995 +0.210925 -0.0881128 -0.0299059 +0.195391 -0.0835698 -0.0397083 +0.187049 -0.0970928 -0.0513544 +0.215909 -0.10623 -0.0275177 +0.221663 -0.111792 -0.00835326 +0.21689 -0.135734 -0.006698 +0.187289 -0.0668273 -0.0361071 +0.170089 -0.0549841 -0.0384156 +0.158135 -0.0292105 -0.0224101 +0.144698 -0.0631652 -0.0561794 +0.210349 -0.156804 0.00619425 +0.122465 -0.0210506 -0.020971 +0.25102 0.0827579 -0.00901225 +0.246076 0.0717907 -0.00732438 +0.248146 0.0653429 0.00439784 +0.245544 0.0538898 0.0151974 +0.255748 0.0868229 -0.000826293 +-0.125725 -0.258433 -0.170214 +0.151089 -0.0268375 0.140451 +0.244155 0.0131187 -0.0533056 +0.246127 0.0105937 -0.0612737 +0.239403 0.00492409 -0.0645919 +0.228547 -0.00190445 -0.0800819 +0.236042 0.000460551 -0.073323 +0.244455 -0.00400961 -0.0816292 +0.225173 0.00380285 -0.0703884 +0.247885 -0.00234363 -0.0902777 +0.247838 0.00379159 -0.0839495 +0.243353 0.0148187 -0.0838177 +0.236031 0.0244971 -0.0791546 +0.225616 0.0291453 -0.0875646 +-0.29518 -0.390079 -0.254006 +-0.303646 -0.394416 -0.248506 +-0.302477 -0.403327 -0.233435 +-0.298023 -0.412267 -0.217588 +-0.29425 -0.38151 -0.250683 +-0.302074 -0.390767 -0.254186 +0.191342 0.435898 0.0636941 +-0.0964353 -0.460913 -0.0144457 +0.137532 -0.0116873 0.139128 +0.343547 -0.294973 -0.292923 +0.137424 0.0947211 0.0118894 +0.147115 0.0902563 -0.00271409 +0.147874 0.0802052 -0.0226835 +0.255027 -0.310713 -0.257667 +0.257498 -0.300887 -0.266482 +0.220835 -0.0105204 -0.15317 +0.210403 -0.014095 -0.156518 +0.204562 -0.0228168 -0.148776 +-0.117774 -0.20207 0.202016 +3 575 1215 1225 +3 902 137 1166 +3 2122 17 2125 +3 1333 1332 328 +3 1031 1037 1032 +3 1235 1234 736 +3 986 1231 182 +3 532 534 185 +3 534 448 185 +3 1588 1570 1587 +3 674 675 639 +3 1130 1225 242 +3 279 6 280 +3 6 283 280 +3 621 954 955 +3 235 273 275 +3 2565 1747 2566 +3 2225 2224 2223 +3 11 206 278 +3 922 93 2080 +3 530 2723 2724 +3 2144 2146 2139 +3 1374 1376 766 +3 1361 1374 766 +3 1775 525 1893 +3 2626 1649 2625 +3 2338 2265 2339 +3 992 96 990 +3 103 21 104 +3 1681 1682 31 +3 1686 1682 1681 +3 2064 2065 295 +3 747 748 464 +3 597 1084 1086 +3 1003 2191 2190 +3 2184 1003 2190 +3 214 38 215 +3 2202 2205 473 +3 2725 257 2728 +3 216 554 944 +3 554 553 944 +3 1457 1456 445 +3 986 2154 96 +3 458 1022 1021 +3 961 1949 2534 +3 625 1514 1515 +3 1786 1791 518 +3 1586 2773 2006 +3 52 1485 1486 +3 2101 52 1486 +3 2368 2374 1380 +3 2054 1499 74 +3 329 326 1762 +3 933 934 176 +3 527 569 705 +3 2004 247 2003 +3 414 1966 1967 +3 853 544 184 +3 1136 354 352 +3 1896 1895 134 +3 5 978 1108 +3 1344 1342 726 +3 80 27 1599 +3 1489 1683 175 +3 1952 1953 2619 +3 21 105 104 +3 21 103 29 +3 2180 959 1164 +3 288 2180 1164 +3 294 1940 1941 +3 1263 1865 443 +3 1755 1756 337 +3 696 1187 1185 +3 1186 696 1185 +3 1489 66 1683 +3 68 907 122 +3 260 1748 341 +3 1340 1341 451 +3 806 397 478 +3 1337 750 728 +3 1516 419 1515 +3 279 11 278 +3 277 279 278 +3 226 2120 2119 +3 258 259 76 +3 686 683 719 +3 1232 950 1230 +3 1597 1598 1978 +3 91 2073 977 +3 724 734 1233 +3 724 732 734 +3 47 281 280 +3 85 1982 2246 +3 207 154 64 +3 2000 1998 1999 +3 553 853 184 +3 76 261 1618 +3 259 261 76 +3 682 706 1504 +3 660 706 682 +3 296 17 297 +3 17 2122 297 +3 554 216 916 +3 381 383 382 +3 271 269 296 +3 269 17 296 +3 1082 656 1823 +3 115 199 196 +3 1056 1049 880 +3 1520 2574 2248 +3 212 550 238 +3 1980 1598 27 +3 364 72 365 +3 674 657 673 +3 82 168 158 +3 1133 641 1171 +3 440 1406 1411 +3 804 803 398 +3 178 2662 461 +3 159 2100 157 +3 1657 1659 1658 +3 1659 1280 1658 +3 1499 141 1498 +3 2144 2137 2146 +3 358 2137 2144 +3 567 534 531 +3 64 264 274 +3 137 365 380 +3 379 137 380 +3 117 903 902 +3 377 376 136 +3 88 2566 2567 +3 83 1299 1306 +3 1819 692 1822 +3 1642 584 710 +3 645 602 1808 +3 503 500 502 +3 1855 1263 54 +3 1706 1580 517 +3 1169 1069 1068 +3 42 1825 1828 +3 21 67 106 +3 81 80 84 +3 20 105 118 +3 20 156 105 +3 67 21 256 +3 1015 258 1016 +3 259 258 65 +3 649 890 1665 +3 2021 116 2020 +3 1146 402 1147 +3 126 1615 1618 +3 164 1894 163 +3 120 164 163 +3 2774 378 377 +3 1796 1893 525 +3 510 511 413 +3 1143 754 305 +3 1257 1024 1260 +3 866 1816 1815 +3 2685 1816 866 +3 574 1222 1221 +3 1673 1038 1672 +3 158 168 51 +3 793 1560 1561 +3 750 730 465 +3 729 730 750 +3 996 998 61 +3 280 281 11 +3 919 93 918 +3 590 2300 1322 +3 1305 1478 1482 +3 68 122 118 +3 238 537 555 +3 138 365 903 +3 1536 1562 1535 +3 264 1720 268 +3 2079 2080 93 +3 6 273 283 +3 2554 63 246 +3 236 317 319 +3 40 84 80 +3 84 40 104 +3 778 1357 1356 +3 1359 778 1356 +3 170 263 265 +3 1986 170 265 +3 21 106 105 +3 944 183 1740 +3 944 945 183 +3 1894 164 165 +3 67 249 106 +3 283 235 47 +3 63 2005 246 +3 314 235 275 +3 435 436 188 +3 1746 1747 345 +3 1161 2431 2432 +3 2459 594 1102 +3 1484 1305 1482 +3 2 1136 1137 +3 1062 2510 2511 +3 1811 219 1809 +3 1736 997 1732 +3 264 268 274 +3 439 1427 1247 +3 526 2722 530 +3 2722 2721 530 +3 118 105 106 +3 164 120 121 +3 71 131 165 +3 63 247 2005 +3 1894 165 1895 +3 2054 2052 2053 +3 2285 2432 2286 +3 254 106 249 +3 254 68 106 +3 685 661 670 +3 1498 75 2135 +3 989 180 991 +3 263 24 265 +3 2021 2020 932 +3 1724 170 1487 +3 124 1016 76 +3 277 278 64 +3 431 151 430 +3 2225 2757 2189 +3 818 407 478 +3 1499 237 74 +3 1994 1576 2611 +3 2697 904 897 +3 904 899 897 +3 377 378 135 +3 132 72 364 +3 282 109 293 +3 109 282 319 +3 224 83 1306 +3 74 381 376 +3 2054 2053 141 +3 2226 2678 2224 +3 1134 1438 1437 +3 412 814 813 +3 2624 1641 709 +3 126 1618 261 +3 999 34 991 +3 899 1991 1989 +3 98 1315 275 +3 928 1767 931 +3 144 2131 2136 +3 23 234 78 +3 603 800 707 +3 337 1490 332 +3 1490 1491 332 +3 1348 1341 727 +3 1591 16 1590 +3 547 92 549 +3 2194 2226 2189 +3 2236 2582 2581 +3 378 72 135 +3 1796 1784 1893 +3 278 206 207 +3 170 82 1487 +3 265 24 266 +3 308 153 943 +3 310 308 943 +3 569 565 177 +3 267 1987 1502 +3 236 316 317 +3 1895 165 134 +3 1898 2388 1479 +3 163 159 120 +3 1464 1468 1463 +3 756 903 117 +3 138 903 756 +3 951 1231 986 +3 987 951 986 +3 2670 700 2672 +3 445 187 446 +3 1722 154 910 +3 256 21 29 +3 84 168 81 +3 1283 2386 2684 +3 2736 79 852 +3 146 363 2143 +3 1323 1324 2271 +3 68 118 106 +3 1043 1038 1673 +3 2773 1585 1705 +3 1231 1232 1230 +3 1337 729 750 +3 922 917 93 +3 825 395 824 +3 510 389 511 +3 763 1188 2128 +3 833 831 487 +3 560 1355 179 +3 560 1354 1355 +3 899 904 1991 +3 639 1133 1138 +3 674 639 1138 +3 1250 1243 1254 +3 2715 2714 1433 +3 502 499 503 +3 1690 1213 1212 +3 1342 451 1341 +3 1397 1025 443 +3 929 928 930 +3 1855 1854 1262 +3 1854 1857 1262 +3 2733 2736 241 +3 1001 987 993 +3 2662 2708 191 +3 1470 2764 1459 +3 264 1717 1720 +3 264 1718 1717 +3 346 330 1139 +3 1137 1136 353 +3 1514 557 1515 +3 2045 115 2026 +3 143 1494 1495 +3 1487 1713 1724 +3 211 974 975 +3 319 318 109 +3 319 317 318 +3 2081 2077 209 +3 1015 123 258 +3 207 59 910 +3 1770 241 848 +3 857 222 1810 +3 546 857 1810 +3 87 343 1750 +3 621 915 622 +3 393 803 806 +3 977 976 975 +3 2016 992 934 +3 992 176 934 +3 1794 2744 2745 +3 278 207 64 +3 524 1692 1691 +3 2772 1702 2771 +3 1702 2772 1586 +3 1107 1105 1106 +3 190 2593 2594 +3 802 393 586 +3 1777 1783 1793 +3 476 816 390 +3 2159 1049 1048 +3 516 515 1576 +3 321 2057 2063 +3 476 477 509 +3 1180 773 1181 +3 553 184 945 +3 1227 1228 949 +3 1892 255 101 +3 1919 600 2258 +3 124 1014 1015 +3 273 98 275 +3 225 1612 1613 +3 48 313 314 +3 539 2728 2729 +3 2728 539 538 +3 1897 1896 468 +3 1810 1809 980 +3 794 2238 2237 +3 307 39 311 +3 39 307 320 +3 1531 1533 1538 +3 1583 1702 1582 +3 410 954 621 +3 2519 2333 2332 +3 541 854 855 +3 459 439 1249 +3 529 1511 2740 +3 1259 450 1258 +3 1677 2170 2175 +3 509 389 510 +3 1704 1703 1707 +3 1703 1583 1707 +3 1644 1645 584 +3 463 562 2660 +3 175 929 930 +3 262 1756 1755 +3 1756 262 1757 +3 380 72 378 +3 365 72 380 +3 128 2247 1985 +3 2532 135 2533 +3 128 1985 1987 +3 1121 2187 288 +3 891 1663 1377 +3 135 132 2533 +3 76 1016 258 +3 117 902 901 +3 132 135 72 +3 908 139 909 +3 125 76 1618 +3 76 125 124 +3 737 736 745 +3 30 541 543 +3 30 540 541 +3 395 826 824 +3 260 1751 1749 +3 341 1746 1753 +3 173 553 554 +3 1141 331 1139 +3 1756 1490 337 +3 2668 2667 700 +3 1751 1752 259 +3 230 1380 2377 +3 281 282 12 +3 2137 2138 2146 +3 1689 1852 1850 +3 588 1697 1083 +3 1069 1169 641 +3 1149 424 1088 +3 11 279 280 +3 919 1331 213 +3 1626 715 3 +3 2374 2368 2367 +3 178 2661 2707 +3 2094 2093 2092 +3 320 318 39 +3 318 317 39 +3 754 14 755 +3 6 272 273 +3 2172 1047 1051 +3 1058 2163 2162 +3 237 1499 142 +3 1799 523 1518 +3 591 695 781 +3 696 695 2128 +3 234 23 430 +3 800 720 683 +3 236 282 47 +3 235 236 47 +3 23 1162 2312 +3 2192 2678 2227 +3 2681 2680 832 +3 236 319 282 +3 817 390 808 +3 509 510 476 +3 1661 1474 492 +3 1278 1659 1657 +3 191 2715 2716 +3 1138 1133 1171 +3 835 840 412 +3 840 1184 412 +3 1898 1897 468 +3 138 756 754 +3 22 2069 300 +3 309 755 1018 +3 1651 586 589 +3 1147 1651 589 +3 1771 2733 241 +3 2733 1771 522 +3 379 380 378 +3 1749 1751 65 +3 1729 1728 197 +3 2092 2093 970 +3 300 2069 2068 +3 903 137 902 +3 25 332 1002 +3 236 235 315 +3 1162 78 1027 +3 1163 318 320 +3 147 429 801 +3 360 359 302 +3 2285 1172 3 +3 637 669 677 +3 754 1143 14 +3 2706 2709 418 +3 1213 575 574 +3 1215 575 1213 +3 2186 2223 2192 +3 2364 718 2365 +3 535 184 544 +3 610 1197 394 +3 1401 2331 2444 +3 839 149 837 +3 956 149 839 +3 181 330 347 +3 674 1138 657 +3 340 326 329 +3 1430 1415 1635 +3 2664 1822 692 +3 173 554 924 +3 944 553 945 +3 535 544 533 +3 1740 216 944 +3 334 90 336 +3 2475 783 2480 +3 927 1767 929 +3 1267 310 943 +3 2479 952 783 +3 1144 592 1146 +3 929 175 927 +3 323 1731 1730 +3 2280 2292 2430 +3 1811 1813 1812 +3 1733 1735 2570 +3 222 857 858 +3 346 1139 1760 +3 809 808 390 +3 292 1073 1072 +3 1113 1959 1962 +3 1765 1764 1116 +3 2285 2286 1172 +3 1961 1012 287 +3 1754 77 1752 +3 509 820 844 +3 417 839 2710 +3 1260 1024 1252 +3 1463 1468 483 +3 2734 2732 537 +3 568 742 734 +3 2060 2059 298 +3 187 1137 353 +3 1438 1414 441 +3 469 133 753 +3 901 902 360 +3 902 1166 360 +3 592 1144 811 +3 151 234 430 +3 2321 715 2322 +3 1648 1643 1642 +3 498 786 2606 +3 1501 2696 146 +3 2699 145 898 +3 373 1970 1273 +3 1229 985 182 +3 384 237 142 +3 1025 1263 443 +3 1273 1275 1282 +3 900 1989 1193 +3 381 237 383 +3 839 837 415 +3 755 753 754 +3 138 754 753 +3 2719 437 1701 +3 789 1562 1536 +3 2604 2607 1573 +3 820 509 477 +3 780 2484 2485 +3 1184 840 416 +3 2717 1433 2713 +3 437 2717 2713 +3 1216 1219 1217 +3 394 1195 612 +3 238 550 551 +3 1206 529 1207 +3 1442 1472 2637 +3 1472 190 2637 +3 1778 1794 2745 +3 1082 1078 656 +3 1709 2266 2265 +3 498 497 1 +3 1235 735 1234 +3 526 527 705 +3 624 620 558 +3 393 589 586 +3 2128 1188 696 +3 501 497 498 +3 616 1204 1205 +3 825 514 798 +3 293 2063 294 +3 215 343 87 +3 853 854 544 +3 854 853 542 +3 2769 1060 1129 +3 212 547 548 +3 121 479 119 +3 784 620 411 +3 1320 610 1321 +3 419 618 624 +3 1518 2740 528 +3 410 953 954 +3 957 2709 2705 +3 1662 1470 1661 +3 619 2484 1174 +3 2672 708 2670 +3 893 771 887 +3 1418 2622 1700 +3 2306 2307 428 +3 1348 1342 1341 +3 527 528 1355 +3 455 436 454 +3 1704 1705 1585 +3 1703 1704 1585 +3 1900 848 1901 +3 1259 1257 455 +3 401 1323 1646 +3 422 2250 1553 +3 2250 422 1524 +3 668 666 671 +3 1469 482 481 +3 1449 1662 1661 +3 622 912 410 +3 844 2681 832 +3 454 1630 453 +3 463 748 747 +3 467 1433 2717 +3 735 1021 733 +3 909 2051 140 +3 1216 524 1219 +3 840 956 416 +3 408 811 1144 +3 739 740 738 +3 449 446 447 +3 2731 536 2726 +3 576 1223 1221 +3 461 2716 192 +3 598 2665 2664 +3 1144 1146 589 +3 627 1392 1393 +3 569 177 705 +3 1390 1391 651 +3 1799 1518 240 +3 1089 606 626 +3 1776 1220 523 +3 462 461 192 +3 1505 561 560 +3 192 459 456 +3 701 581 704 +3 673 676 636 +3 1022 1349 480 +3 2722 177 2721 +3 462 178 461 +3 611 1358 1357 +3 625 624 558 +3 2322 1621 2321 +3 1630 1460 386 +3 2727 537 2726 +3 748 178 462 +3 480 733 1021 +3 983 1543 1545 +3 531 534 532 +3 778 611 1357 +3 2607 2604 2605 +3 1463 485 148 +3 567 565 566 +3 748 462 464 +3 412 816 834 +3 743 746 464 +3 566 534 567 +3 606 663 1808 +3 1770 1771 241 +3 834 835 412 +3 420 798 514 +3 1454 1662 1449 +3 2306 428 2309 +3 763 2128 591 +3 625 558 1513 +3 477 476 390 +3 817 477 390 +3 1526 1523 1528 +3 1562 1521 791 +3 551 46 552 +3 700 2670 2669 +3 497 501 518 +3 790 1562 1552 +3 1212 574 1214 +3 1588 1587 1571 +3 2736 849 241 +3 2039 2024 2038 +3 123 128 258 +3 128 123 965 +3 1726 1727 582 +3 550 46 551 +3 274 2742 64 +3 1779 1781 2755 +3 1781 1782 2755 +3 503 506 500 +3 709 1641 581 +3 1563 1589 1587 +3 505 498 515 +3 2238 2239 392 +3 807 2243 2241 +3 818 477 817 +3 1589 1565 507 +3 1736 325 1737 +3 1530 1531 1525 +3 872 1052 1051 +3 1800 2753 2752 +3 534 186 448 +3 603 1069 721 +3 2665 653 687 +3 1513 559 1512 +3 1782 520 571 +3 2473 1727 399 +3 2748 2750 2747 +3 240 1773 1799 +3 1773 1774 1799 +3 753 752 138 +3 1 497 851 +3 1070 627 1393 +3 1071 627 1070 +3 744 743 464 +3 803 397 806 +3 1086 1084 1085 +3 402 1086 1085 +3 1020 458 1021 +3 854 540 544 +3 540 533 544 +3 811 810 174 +3 729 562 563 +3 1351 562 729 +3 731 749 568 +3 749 746 568 +3 1338 564 1350 +3 1337 1338 1350 +3 455 1257 54 +3 1198 2486 426 +3 817 2244 818 +3 239 530 536 +3 242 1225 1216 +3 1582 499 938 +3 50 737 745 +3 735 724 1234 +3 540 539 533 +3 539 540 30 +3 901 1990 900 +3 223 541 855 +3 541 540 854 +3 715 1620 3 +3 212 548 550 +3 545 543 541 +3 223 545 541 +3 2456 2455 1680 +3 545 546 547 +3 223 546 545 +3 1163 110 2066 +3 212 545 547 +3 945 946 183 +3 549 548 547 +3 2748 2747 2749 +3 217 917 920 +3 173 924 925 +3 855 542 856 +3 855 854 542 +3 46 203 552 +3 1081 95 662 +3 173 542 553 +3 149 956 840 +3 1505 560 1507 +3 742 50 745 +3 2749 1710 2751 +3 561 562 452 +3 179 1509 1508 +3 1507 560 179 +3 2574 150 2248 +3 665 638 693 +3 571 1778 2754 +3 727 751 480 +3 705 177 2722 +3 885 882 765 +3 177 565 567 +3 402 1326 587 +3 556 1516 1509 +3 1690 1691 1213 +3 742 745 734 +3 725 1235 736 +3 1374 769 1375 +3 1361 769 1374 +3 1343 566 565 +3 451 1343 565 +3 707 1066 603 +3 707 632 1066 +3 1076 656 1078 +3 584 1643 1644 +3 705 2722 526 +3 1326 402 1085 +3 1148 1086 402 +3 598 652 2665 +3 2636 2635 577 +3 773 611 914 +3 611 773 772 +3 914 622 915 +3 1925 1924 757 +3 680 697 605 +3 663 646 645 +3 732 724 733 +3 833 490 831 +3 677 669 636 +3 618 617 1182 +3 617 618 419 +3 844 490 509 +3 697 680 635 +3 566 713 186 +3 1070 595 1071 +3 1825 107 57 +3 814 409 813 +3 636 672 673 +3 2349 2348 1203 +3 900 117 901 +3 1206 573 1205 +3 658 679 675 +3 2653 1821 596 +3 410 621 622 +3 2738 2737 1207 +3 649 1665 891 +3 620 0 621 +3 680 678 635 +3 674 658 675 +3 598 2664 2666 +3 1807 602 1806 +3 698 710 584 +3 710 698 1096 +3 395 798 828 +3 1365 1372 1364 +3 1371 1372 1365 +3 409 2479 827 +3 1321 610 609 +3 1151 616 1223 +3 2177 2176 1044 +3 0 915 621 +3 2664 2665 687 +3 2672 2671 580 +3 733 724 735 +3 2737 1211 2741 +3 1346 453 1345 +3 2351 1209 1204 +3 845 2676 833 +3 2323 715 1625 +3 1151 1150 616 +3 2352 2344 1201 +3 2273 2274 588 +3 615 1516 556 +3 557 1516 1515 +3 744 50 743 +3 1145 1144 589 +3 1181 1182 619 +3 1182 1181 618 +3 2546 2545 1626 +3 620 621 411 +3 1374 1375 770 +3 405 1356 1320 +3 1359 1356 405 +3 145 2144 2139 +3 1353 452 1352 +3 1469 2141 355 +3 137 379 1165 +3 784 558 620 +3 670 693 638 +3 668 671 672 +3 2753 1779 2754 +3 1069 722 721 +3 654 1187 1188 +3 637 678 680 +3 1687 1688 660 +3 813 390 816 +3 671 667 658 +3 667 679 658 +3 2350 1195 613 +3 607 646 663 +3 665 595 666 +3 638 666 668 +3 711 1096 1095 +3 769 1361 1358 +3 758 1924 1925 +3 597 1086 1087 +3 1989 900 1990 +3 1183 1184 416 +3 708 581 701 +3 1420 1407 2330 +3 637 680 685 +3 672 671 658 +3 669 670 638 +3 636 669 668 +3 669 638 668 +3 637 670 669 +3 1919 1921 600 +3 816 412 813 +3 693 628 665 +3 1082 1077 1078 +3 636 668 672 +3 666 595 667 +3 1641 1642 710 +3 884 648 881 +3 1688 707 660 +3 637 685 670 +3 145 359 2144 +3 1908 1907 895 +3 706 660 707 +3 1861 1247 1860 +3 731 568 734 +3 721 722 642 +3 606 1089 1081 +3 1352 452 1351 +3 2152 682 1504 +3 857 546 223 +3 717 1627 2545 +3 1780 1797 2750 +3 747 746 563 +3 881 694 882 +3 1133 639 1132 +3 489 829 2680 +3 1548 1537 1564 +3 965 964 252 +3 490 844 832 +3 1175 1176 1180 +3 1557 1559 793 +3 2547 2542 1628 +3 1726 1639 2009 +3 992 990 176 +3 859 222 858 +3 1667 222 859 +3 732 465 731 +3 465 730 731 +3 566 186 534 +3 357 2130 2129 +3 465 732 733 +3 1366 768 1368 +3 746 749 563 +3 731 734 732 +3 743 568 746 +3 568 743 742 +3 1579 516 1994 +3 878 2164 2165 +3 773 1176 772 +3 956 839 417 +3 50 742 743 +3 1233 736 1234 +3 751 733 480 +3 903 365 137 +3 465 733 751 +3 751 728 750 +3 465 751 750 +3 752 365 138 +3 1922 1923 758 +3 1389 2666 1392 +3 575 805 94 +3 881 762 694 +3 1442 2492 1134 +3 887 886 765 +3 406 776 1371 +3 954 417 955 +3 590 1322 1323 +3 2661 178 2659 +3 137 1165 1166 +3 773 1180 1176 +3 622 914 911 +3 439 467 1426 +3 782 591 781 +3 765 893 887 +3 413 835 834 +3 809 813 409 +3 805 823 397 +3 1356 777 1320 +3 1020 1236 1237 +3 793 1558 1557 +3 2686 2685 866 +3 965 123 964 +3 703 1096 1097 +3 2317 1019 2316 +3 1557 421 1559 +3 286 2179 232 +3 1676 2176 2177 +3 354 2133 352 +3 393 802 803 +3 407 806 478 +3 954 956 417 +3 777 2488 1320 +3 1212 1211 244 +3 2238 2580 2237 +3 813 809 390 +3 1184 1183 814 +3 835 149 840 +3 478 821 819 +3 392 2579 2580 +3 1127 2481 953 +3 819 821 820 +3 818 819 477 +3 818 478 819 +3 805 396 823 +3 819 820 477 +3 1211 573 2741 +3 397 823 478 +3 395 825 798 +3 2236 829 797 +3 831 392 487 +3 2681 489 2680 +3 798 829 828 +3 956 953 416 +3 953 956 954 +3 2128 695 591 +3 1184 814 412 +3 1943 2576 1122 +3 487 846 845 +3 1904 1903 849 +3 542 853 553 +3 16 2608 1593 +3 1048 2160 2159 +3 1586 2772 2773 +3 856 223 855 +3 978 867 1108 +3 2194 2189 2758 +3 239 536 2731 +3 2295 2296 865 +3 2170 2166 1046 +3 1138 1171 657 +3 873 1055 1035 +3 2046 2045 936 +3 2134 2145 142 +3 1167 44 360 +3 875 2296 2770 +3 2165 2164 2167 +3 1051 1052 1034 +3 914 915 773 +3 306 14 1143 +3 623 913 912 +3 2695 2694 301 +3 2353 2354 614 +3 694 762 1920 +3 1906 1907 1367 +3 1142 304 1143 +3 906 117 900 +3 756 117 906 +3 931 1767 1766 +3 754 756 906 +3 214 910 59 +3 911 912 622 +3 1129 870 1128 +3 77 337 1126 +3 917 217 916 +3 917 916 918 +3 1001 998 951 +3 1392 1818 1393 +3 1739 1740 183 +3 1075 1124 1125 +3 1414 440 1412 +3 964 963 252 +3 1494 1496 1495 +3 2708 2662 2707 +3 1881 1882 2437 +3 396 2766 822 +3 823 396 822 +3 2711 415 2708 +3 417 2710 957 +3 1008 473 1005 +3 289 1073 960 +3 71 130 131 +3 2223 1004 2222 +3 2050 339 2051 +3 1625 715 1626 +3 2520 2333 2519 +3 2407 2197 2408 +3 2197 2407 2198 +3 1226 2334 948 +3 2678 2192 2224 +3 2433 2305 2302 +3 124 1015 1016 +3 248 255 60 +3 473 1003 1005 +3 2191 1003 473 +3 2348 613 1202 +3 2036 993 2035 +3 123 907 964 +3 907 123 1015 +3 1207 2739 2738 +3 1242 1838 1839 +3 926 1681 1680 +3 1109 865 1110 +3 868 1109 1110 +3 2320 1621 2319 +3 1037 1038 1043 +3 2768 2767 1130 +3 1986 265 86 +3 1984 1986 86 +3 2107 1298 2108 +3 2377 2375 1271 +3 1380 2375 2377 +3 2195 2229 2214 +3 1294 1153 1289 +3 995 61 994 +3 1253 1856 1689 +3 2113 1299 229 +3 2423 889 2421 +3 1274 1273 1269 +3 373 1273 1274 +3 1610 1611 1154 +3 1610 471 1611 +3 2120 226 2121 +3 2535 1524 1526 +3 1375 894 770 +3 2072 204 2073 +3 2601 2604 2602 +3 2601 1575 2604 +3 981 980 979 +3 981 979 221 +3 922 425 920 +3 425 922 970 +3 2142 2145 2134 +3 2650 2145 2142 +3 970 922 220 +3 113 2062 2060 +3 2451 921 1996 +3 1996 217 2451 +3 217 920 2451 +3 57 1826 1825 +3 2168 2171 2169 +3 208 2081 214 +3 770 2258 600 +3 2258 770 883 +3 2085 975 974 +3 549 974 211 +3 335 1888 1887 +3 1334 2084 213 +3 976 548 211 +3 2079 2078 210 +3 1755 337 1754 +3 1332 213 1331 +3 869 1672 1669 +3 281 58 11 +3 58 281 1938 +3 1815 1816 219 +3 1816 979 219 +3 1812 1815 219 +3 998 1232 951 +3 1997 1996 1995 +3 2094 2096 2093 +3 2096 2094 221 +3 2098 978 971 +3 978 973 971 +3 2093 2096 971 +3 2096 2098 971 +3 2098 2096 2097 +3 1619 547 546 +3 1996 921 1995 +3 2096 221 2097 +3 1821 601 1820 +3 1769 1577 1768 +3 1581 1769 1768 +3 925 924 1997 +3 984 316 233 +3 303 2692 2068 +3 2692 300 2068 +3 2129 2130 2147 +3 1529 1525 792 +3 1530 1529 1523 +3 729 563 730 +3 2728 257 2729 +3 2673 699 2668 +3 699 2667 2668 +3 1541 1540 55 +3 1536 1540 1541 +3 1533 1531 1530 +3 348 1971 1998 +3 1523 1532 1530 +3 2250 2251 1553 +3 2251 2250 796 +3 676 657 1632 +3 1633 676 1632 +3 1527 422 983 +3 2248 150 2253 +3 2249 2248 2253 +3 2693 2689 2694 +3 2693 2691 2689 +3 22 298 299 +3 2656 697 635 +3 787 2656 635 +3 2599 1972 2597 +3 1972 1973 2597 +3 316 39 317 +3 316 984 39 +3 984 311 39 +3 1393 1818 601 +3 37 195 1729 +3 2052 2054 140 +3 1120 2218 1949 +3 989 990 96 +3 990 989 991 +3 1684 9 1682 +3 998 1001 61 +3 66 1686 1683 +3 990 930 176 +3 930 990 34 +3 930 933 176 +3 298 2059 295 +3 444 1460 1461 +3 444 2743 1460 +3 195 996 995 +3 2158 1049 2159 +3 1677 1676 1045 +3 985 180 989 +3 180 985 423 +3 333 89 1140 +3 333 1492 89 +3 695 1186 2477 +3 1186 174 2477 +3 2062 2061 2060 +3 991 34 990 +3 1699 1063 1669 +3 930 928 933 +3 33 347 346 +3 33 1000 347 +3 1030 1032 860 +3 1030 2515 1032 +3 1886 2640 2649 +3 2640 1885 2649 +3 1161 2432 2285 +3 993 987 988 +3 987 96 988 +3 143 1491 1492 +3 1493 143 1492 +3 1493 334 336 +3 734 745 1233 +3 38 1334 344 +3 927 926 1685 +3 1867 1265 1864 +3 1679 4 202 +3 2050 127 1614 +3 127 1616 1614 +3 922 920 917 +3 195 37 996 +3 1731 1736 1732 +3 1757 329 1760 +3 351 34 999 +3 327 351 999 +3 774 1179 1369 +3 1233 745 736 +3 1491 1002 332 +3 2565 88 2569 +3 323 197 99 +3 996 997 998 +3 999 991 180 +3 1000 999 180 +3 1000 327 999 +3 2140 356 2141 +3 1743 1742 324 +3 1000 180 423 +3 347 1000 423 +3 33 327 1000 +3 987 1001 951 +3 351 99 197 +3 1029 864 1030 +3 2773 1706 2006 +3 2605 2606 1574 +3 960 292 1117 +3 1073 292 960 +3 1959 1958 1114 +3 2272 1326 2274 +3 2002 249 248 +3 249 67 248 +3 2201 1006 2203 +3 2200 2210 2211 +3 1939 1935 1936 +3 1939 112 1935 +3 1533 982 1534 +3 1538 1533 1534 +3 2206 2203 2204 +3 70 124 125 +3 1014 124 70 +3 2028 994 2042 +3 2041 2028 2042 +3 2192 1005 2186 +3 1962 1960 1963 +3 1965 350 1960 +3 2187 961 2188 +3 77 1395 261 +3 41 2000 1999 +3 1014 907 1015 +3 122 907 1014 +3 70 122 1014 +3 350 1114 2213 +3 2209 2200 2204 +3 2209 2204 1006 +3 2668 700 2669 +3 141 2053 2056 +3 2321 2320 1620 +3 2321 1621 2320 +3 1010 2213 2208 +3 2299 1321 1322 +3 405 1321 2299 +3 706 707 683 +3 2301 1157 1602 +3 831 490 2679 +3 490 832 2679 +3 287 1012 1011 +3 1010 2206 2204 +3 1013 2191 473 +3 2205 1013 473 +3 2561 166 2560 +3 2201 2202 1008 +3 2203 2202 2201 +3 2369 2368 2370 +3 1896 1897 1895 +3 102 40 107 +3 2394 1283 53 +3 1283 2394 2390 +3 985 2154 986 +3 2076 2072 2073 +3 2076 208 2072 +3 308 310 1018 +3 755 308 1018 +3 308 755 14 +3 1848 1849 1251 +3 2345 1200 2346 +3 737 740 1238 +3 740 737 738 +3 1020 1021 735 +3 738 737 50 +3 50 744 738 +3 454 1259 455 +3 1337 1350 729 +3 480 1021 1022 +3 738 744 741 +3 457 738 741 +3 1841 1840 193 +3 1840 1841 1242 +3 1693 1691 1519 +3 1025 442 188 +3 1257 1256 1024 +3 453 450 1259 +3 928 931 2022 +3 931 932 2022 +3 2055 2056 2053 +3 2056 2055 1495 +3 336 1497 1496 +3 2701 1678 1673 +3 1672 2701 1673 +3 436 455 1025 +3 188 436 1025 +3 459 467 439 +3 702 1123 1093 +3 1026 842 843 +3 1093 1123 841 +3 1945 2578 1943 +3 2684 2384 371 +3 2384 2684 2386 +3 1526 1524 1527 +3 2537 2538 1173 +3 2252 796 2235 +3 1076 1125 656 +3 691 2316 2315 +3 704 842 1026 +3 342 1747 1748 +3 1747 341 1748 +3 1163 320 110 +3 190 2639 2637 +3 2065 2064 2066 +3 2079 93 919 +3 2078 2077 2082 +3 2077 91 2082 +3 1231 1230 182 +3 1678 2178 1674 +3 1048 2168 2167 +3 1676 2177 2178 +3 2177 1044 2178 +3 2500 2508 1041 +3 190 2594 2595 +3 377 136 2774 +3 874 1033 1032 +3 1710 2265 2337 +3 2336 1710 2337 +3 2158 1057 2157 +3 1057 2163 2157 +3 1236 735 1235 +3 1815 1812 1814 +3 499 1578 503 +3 2315 2316 714 +3 1620 2315 714 +3 382 1165 379 +3 1033 873 1035 +3 1033 1034 873 +3 1238 725 737 +3 861 1030 860 +3 1036 861 860 +3 1035 1036 860 +3 1938 2490 58 +3 861 1029 1030 +3 1285 2720 1488 +3 1801 1286 1274 +3 367 1801 1274 +3 937 2013 2021 +3 1673 1674 1043 +3 1415 1430 2622 +3 1430 1419 2622 +3 2161 1057 2160 +3 1037 871 1038 +3 28 1599 1597 +3 1830 28 1597 +3 2025 2044 2043 +3 2161 2162 2163 +3 2173 2172 1050 +3 2172 2173 879 +3 1095 703 2502 +3 1169 604 1170 +3 1169 1065 604 +3 971 425 970 +3 658 674 673 +3 788 604 1065 +3 631 788 1065 +3 659 2153 1019 +3 2153 2318 1019 +3 425 971 973 +3 1059 2155 2770 +3 868 1105 1107 +3 1109 868 1107 +3 35 2028 2027 +3 2028 198 2027 +3 2132 356 2131 +3 331 1756 1757 +3 2014 2032 2031 +3 2032 2015 2031 +3 1047 2171 2168 +3 1046 2166 2165 +3 1048 1049 872 +3 1834 1759 262 +3 873 1053 1055 +3 1715 155 1714 +3 2509 2508 1040 +3 2731 2726 537 +3 1705 1704 1584 +3 616 2349 1203 +3 238 543 212 +3 1047 872 1051 +3 2171 2172 879 +3 1050 1051 1034 +3 1708 1707 572 +3 2090 2089 967 +3 1681 31 1680 +3 2513 1031 2514 +3 1031 2515 2514 +3 2508 2500 1061 +3 2500 2501 1061 +3 1033 874 1034 +3 1034 1052 873 +3 1052 1053 873 +3 1052 1056 1053 +3 1055 863 1035 +3 1032 1033 860 +3 1033 1035 860 +3 1054 863 1055 +3 1049 2295 880 +3 2295 1049 876 +3 1967 1444 2491 +3 1056 1052 872 +3 1706 508 2268 +3 1580 1706 2268 +3 1814 863 1054 +3 1788 1790 1789 +3 1056 880 1053 +3 2016 2017 2033 +3 1054 1053 880 +3 2194 1011 2193 +3 2095 969 967 +3 2091 2092 970 +3 2091 969 2092 +3 2618 2616 2608 +3 2618 2607 2616 +3 2167 1046 2165 +3 2162 2161 878 +3 2644 2643 9 +3 2025 2038 2037 +3 2008 2257 2258 +3 883 2008 2258 +3 1004 2185 2187 +3 673 672 658 +3 940 1979 1976 +3 199 1886 196 +3 2769 875 2770 +3 1106 864 1029 +3 923 1106 1029 +3 2506 2508 1061 +3 640 1171 1170 +3 1171 641 1170 +3 2224 2192 2223 +3 2770 2155 1060 +3 2155 870 1060 +3 240 528 527 +3 1518 528 240 +3 220 2088 2090 +3 2088 2089 2090 +3 2035 993 988 +3 2099 2085 974 +3 2564 1742 1745 +3 2165 2166 878 +3 2013 2046 936 +3 937 2046 2013 +3 1684 1686 66 +3 631 1065 1066 +3 1067 631 1066 +3 667 1067 632 +3 1067 1066 632 +3 595 1067 667 +3 1091 2468 2466 +3 1170 641 1169 +3 1066 1068 603 +3 1066 1065 1068 +3 1170 635 640 +3 604 635 1170 +3 1934 1932 1912 +3 1928 1927 758 +3 1067 595 1070 +3 1068 1065 1169 +3 471 1612 1611 +3 1612 225 1611 +3 1067 1070 631 +3 2399 271 2400 +3 665 664 1071 +3 664 665 628 +3 2125 2126 224 +3 102 103 40 +3 712 1075 2589 +3 2588 712 2589 +3 612 399 583 +3 399 612 1150 +3 1076 1078 1074 +3 673 657 676 +3 1084 597 1078 +3 1115 1765 1116 +3 291 1115 1116 +3 653 1083 1082 +3 687 653 1082 +3 656 1824 1823 +3 1077 1082 1083 +3 1075 1125 1076 +3 1094 1093 712 +3 711 710 1096 +3 2274 2273 2272 +3 1094 702 1093 +3 584 2011 698 +3 2011 584 1645 +3 1087 1080 597 +3 1080 1087 95 +3 593 1087 1086 +3 593 1088 1087 +3 1078 1077 1084 +3 1179 1174 406 +3 1911 1394 645 +3 1911 1926 1394 +3 690 2463 1102 +3 1076 1074 2589 +3 1822 1823 688 +3 173 1104 542 +3 1091 1090 2468 +3 1099 599 1091 +3 690 1099 1091 +3 1529 1528 1523 +3 594 1098 1099 +3 1077 1085 1084 +3 2570 325 1733 +3 597 1080 1079 +3 1963 1960 1112 +3 424 655 1088 +3 1079 1080 599 +3 1080 1081 599 +3 2423 2422 757 +3 2422 2423 2421 +3 404 2422 2421 +3 760 653 759 +3 760 1083 653 +3 48 314 275 +3 1149 1088 593 +3 2589 1075 1076 +3 2588 2589 1074 +3 1085 1077 1697 +3 1146 1148 402 +3 1146 592 1148 +3 1641 711 581 +3 711 2563 581 +3 591 782 1330 +3 1146 1147 589 +3 1147 402 587 +3 1087 1088 95 +3 1088 655 95 +3 655 662 95 +3 1820 601 1819 +3 2291 2281 2365 +3 2286 2291 2365 +3 1527 982 1594 +3 962 1124 1101 +3 1203 1204 616 +3 1093 841 1075 +3 1091 599 1090 +3 599 1089 1090 +3 2469 1090 2470 +3 1103 2461 1122 +3 2458 2461 1103 +3 399 2472 2473 +3 2472 399 1151 +3 2060 2061 26 +3 794 2237 2232 +3 599 1081 1089 +3 603 721 800 +3 721 720 800 +3 2117 2114 2115 +3 2466 2468 2467 +3 689 2466 2467 +3 2468 1090 2469 +3 2467 2468 2469 +3 626 2470 1089 +3 688 1092 689 +3 1820 689 1821 +3 1099 1079 599 +3 1126 332 338 +3 332 25 338 +3 706 686 1504 +3 683 686 706 +3 702 1094 1095 +3 962 1100 1092 +3 1078 1079 1098 +3 1079 1078 597 +3 2566 1747 342 +3 1074 1098 594 +3 1074 1078 1098 +3 594 1099 1102 +3 2562 2563 711 +3 841 1124 1075 +3 1098 1079 1099 +3 1460 1630 1461 +3 1760 329 1761 +3 249 2002 2763 +3 254 249 2763 +3 1628 1629 642 +3 1628 720 1629 +3 925 1104 173 +3 1823 1824 688 +3 1125 1124 962 +3 677 1633 1634 +3 1183 815 814 +3 1503 2282 2287 +3 2288 1503 2287 +3 2717 2718 1432 +3 856 542 1104 +3 858 856 1104 +3 858 857 856 +3 858 1104 925 +3 858 925 859 +3 594 2459 2460 +3 1102 1099 690 +3 2578 1026 2576 +3 1671 1039 870 +3 1107 1106 5 +3 1108 1107 5 +3 2277 2505 2501 +3 2277 2504 2505 +3 2505 1061 2501 +3 1672 1038 1699 +3 2367 370 1475 +3 2014 936 2032 +3 521 1791 1785 +3 1814 1054 866 +3 1815 1814 866 +3 1608 1607 470 +3 1607 1608 2687 +3 1154 2687 1608 +3 1108 867 1109 +3 1107 1108 1109 +3 1030 2514 2515 +3 1281 2262 1696 +3 2262 1281 2263 +3 1825 8 107 +3 1956 1955 1117 +3 2185 2184 288 +3 1003 2184 2185 +3 2224 2225 2189 +3 2226 2224 2189 +3 88 2565 2566 +3 185 448 1887 +3 1174 780 406 +3 286 232 285 +3 1834 1753 1746 +3 116 2021 2023 +3 2021 2013 2023 +3 1954 1963 1112 +3 1833 1832 1830 +3 620 624 618 +3 2760 1004 2188 +3 799 1524 2535 +3 2210 2200 2209 +3 1116 1119 291 +3 2416 1190 1189 +3 1521 2230 1525 +3 8 102 107 +3 1118 1953 1955 +3 1954 1953 1118 +3 1007 2196 2195 +3 1116 475 1613 +3 1113 1956 1957 +3 1952 1951 1120 +3 1950 290 1111 +3 882 2007 765 +3 1955 1964 1118 +3 1445 1444 1966 +3 1008 2202 473 +3 896 2699 2700 +3 683 707 800 +3 2242 2241 2243 +3 675 1687 681 +3 639 675 681 +3 1525 1529 1530 +3 2546 1626 3 +3 2461 841 1122 +3 912 913 1127 +3 912 1127 410 +3 953 410 1127 +3 810 827 174 +3 827 2476 174 +3 2481 2480 783 +3 2481 1127 2480 +3 845 846 2482 +3 2352 2353 2357 +3 1229 182 1228 +3 182 1230 1228 +3 1069 641 722 +3 641 1133 722 +3 2320 2319 691 +3 722 1132 1131 +3 1132 722 1133 +3 361 383 1167 +3 1902 391 1901 +3 431 147 432 +3 1229 181 423 +3 2316 2318 714 +3 2318 2316 1019 +3 1131 659 1019 +3 1131 1132 659 +3 2716 459 192 +3 1136 2 354 +3 461 2662 191 +3 536 2725 2726 +3 484 485 1462 +3 484 389 485 +3 973 2452 2450 +3 2452 921 2450 +3 2141 1891 355 +3 1440 1701 437 +3 1936 1935 13 +3 1409 2520 2519 +3 355 494 1453 +3 346 1760 1761 +3 329 1758 340 +3 1847 193 1845 +3 1846 1847 1845 +3 1856 1853 1689 +3 1247 1266 1860 +3 1395 1126 338 +3 153 366 943 +3 366 1267 943 +3 1798 525 1774 +3 2696 2690 2695 +3 363 2696 2695 +3 898 2695 301 +3 94 805 804 +3 1194 111 1142 +3 633 1805 1804 +3 1737 997 1736 +3 1517 1208 1518 +3 523 1517 1518 +3 715 2321 1620 +3 582 2474 2471 +3 582 2473 2474 +3 111 304 1142 +3 303 304 2692 +3 111 1194 905 +3 1498 2135 142 +3 2136 357 2137 +3 304 306 1143 +3 152 306 304 +3 408 810 811 +3 2476 2478 2475 +3 913 2476 2475 +3 593 1148 1149 +3 592 1149 1148 +3 808 408 2241 +3 1148 593 1086 +3 594 2460 1074 +3 2459 1103 2460 +3 1558 2231 1521 +3 810 408 809 +3 809 408 808 +3 2275 2270 2272 +3 886 885 765 +3 1149 592 812 +3 592 811 812 +3 2145 385 384 +3 142 2145 384 +3 1197 610 1198 +3 2517 1776 523 +3 2724 2723 257 +3 56 2267 1709 +3 471 2183 1612 +3 227 2112 2111 +3 1608 1609 1610 +3 470 1609 1608 +3 314 313 233 +3 313 312 233 +3 1310 1309 231 +3 276 1310 1297 +3 1292 2413 2415 +3 48 372 313 +3 471 1610 1609 +3 2387 2388 161 +3 2391 2387 161 +3 225 1603 1155 +3 321 2066 2064 +3 1163 2066 321 +3 2261 472 2260 +3 1606 1154 1155 +3 1603 1602 1155 +3 1083 1697 1077 +3 2263 1281 1287 +3 1281 228 1287 +3 1611 225 1155 +3 1310 231 1297 +3 1306 1299 2112 +3 1277 1288 1289 +3 1288 1294 1289 +3 1694 1695 1279 +3 1695 1694 1281 +3 643 661 1804 +3 1382 661 643 +3 1279 1275 1656 +3 1278 1654 1655 +3 1156 1660 1292 +3 1291 1652 1653 +3 1291 1277 1289 +3 228 1288 1287 +3 228 1293 1288 +3 1970 1275 1273 +3 2347 2348 2346 +3 2291 2432 2431 +3 2432 2291 2286 +3 2013 2366 2023 +3 366 153 312 +3 2372 366 312 +3 370 2368 2369 +3 472 2261 1119 +3 1951 2297 2218 +3 2217 2297 1950 +3 2297 2217 2218 +3 1365 1366 775 +3 1166 1167 360 +3 361 1167 1166 +3 2206 2207 1009 +3 277 6 279 +3 277 1168 6 +3 444 1459 2743 +3 268 97 274 +3 821 823 822 +3 1458 1460 2743 +3 1460 1458 1457 +3 1005 2227 2193 +3 2159 1057 2158 +3 1919 2258 2257 +3 2169 1046 2765 +3 720 721 1629 +3 657 1171 1632 +3 1627 2547 1628 +3 2466 2465 1091 +3 2466 1092 2465 +3 1523 1594 1532 +3 426 2485 1182 +3 617 426 1182 +3 1196 2356 1199 +3 2356 1196 1197 +3 1181 0 618 +3 0 620 618 +3 1180 619 1175 +3 741 192 457 +3 1250 1254 1244 +3 1176 774 1177 +3 773 915 1181 +3 1636 1405 1635 +3 619 1180 1181 +3 462 192 741 +3 646 1911 645 +3 1911 646 1912 +3 771 1367 888 +3 629 1387 1910 +3 1926 629 1910 +3 1371 775 406 +3 1179 406 775 +3 1369 1179 775 +3 1440 2592 1701 +3 2590 1437 1436 +3 712 1093 1075 +3 1176 1175 774 +3 2484 619 1182 +3 2485 2484 1182 +3 2486 2487 780 +3 779 780 2487 +3 780 779 406 +3 98 272 284 +3 272 2399 284 +3 424 1187 655 +3 38 2084 1334 +3 494 493 1450 +3 1192 654 1191 +3 799 2535 1522 +3 812 1185 424 +3 1149 812 424 +3 1808 663 645 +3 812 1186 1185 +3 812 174 1186 +3 811 174 812 +3 1404 1428 2521 +3 1666 1668 861 +3 1189 654 1188 +3 2417 1189 2419 +3 884 2423 648 +3 647 1913 2397 +3 655 1187 1192 +3 2426 890 2416 +3 654 1189 1190 +3 270 2402 2401 +3 1193 906 900 +3 271 2398 97 +3 2417 2416 1189 +3 2426 2416 2417 +3 1191 2397 607 +3 654 1190 1191 +3 305 906 1193 +3 906 305 754 +3 654 1192 1187 +3 1936 108 1939 +3 1192 662 655 +3 607 662 1192 +3 662 607 663 +3 2446 1027 2448 +3 1570 2587 1587 +3 2587 1563 1587 +3 647 1914 1913 +3 1142 1143 305 +3 1193 1142 305 +3 2595 2639 190 +3 1473 2639 2595 +3 322 905 1194 +3 1194 1142 1193 +3 1196 394 1197 +3 915 0 1181 +3 2676 486 2575 +3 615 556 400 +3 1206 1205 556 +3 529 1206 556 +3 1205 400 556 +3 2211 350 2213 +3 2211 1961 350 +3 577 2471 2472 +3 576 577 2472 +3 805 397 804 +3 1195 394 1196 +3 2486 2485 426 +3 913 623 2477 +3 2636 577 94 +3 1631 719 720 +3 719 1631 2539 +3 1195 1196 613 +3 1196 1199 613 +3 616 2350 2349 +3 616 1150 2350 +3 528 2740 1511 +3 1209 1224 1210 +3 1224 2358 1210 +3 2242 407 2244 +3 83 1711 1302 +3 1300 83 1302 +3 1727 1726 579 +3 1645 579 2011 +3 1516 557 1509 +3 1221 1222 576 +3 1222 94 576 +3 613 1199 1202 +3 170 1716 263 +3 1355 528 1511 +3 1210 400 1209 +3 2767 2768 824 +3 2221 2196 2756 +3 2196 2221 2220 +3 570 1217 1219 +3 1217 570 520 +3 2739 1207 529 +3 1219 1693 1220 +3 1219 524 1693 +3 207 910 154 +3 1212 1213 574 +3 2358 1224 2357 +3 1204 400 1205 +3 1204 1209 400 +3 613 2349 2350 +3 2351 1203 2347 +3 1203 2348 2347 +3 399 1727 583 +3 501 1788 1787 +3 1971 1973 1972 +3 396 575 1130 +3 575 1225 1130 +3 2352 2357 1224 +3 1639 1726 582 +3 520 1218 1217 +3 497 518 1792 +3 2348 1202 2346 +3 242 1217 1218 +3 1208 2739 2740 +3 2739 529 2740 +3 277 2742 1168 +3 519 1785 1786 +3 1772 522 1771 +3 1218 825 242 +3 825 1218 500 +3 2023 2366 935 +3 242 1216 1217 +3 782 1327 1330 +3 56 1788 1789 +3 2631 2633 2628 +3 2631 2634 2633 +3 233 312 984 +3 1786 1785 1791 +3 1793 1784 1794 +3 570 1220 1776 +3 1223 616 573 +3 616 1205 573 +3 1776 2517 1783 +3 574 1221 1214 +3 1199 2356 2354 +3 1214 1223 573 +3 1223 1214 1221 +3 1211 1214 573 +3 419 624 625 +3 1515 419 625 +3 1150 1195 2350 +3 2455 1685 1680 +3 2286 2362 1172 +3 1695 1696 375 +3 1219 1220 570 +3 2359 615 1210 +3 2358 2359 1210 +3 1509 557 1512 +3 1236 725 1237 +3 949 946 1226 +3 183 946 949 +3 36 1232 998 +3 997 36 998 +3 874 1037 1043 +3 1226 1227 949 +3 1226 181 1227 +3 1123 702 1943 +3 740 739 1240 +3 1836 740 1240 +3 354 2 1891 +3 1229 1227 181 +3 1229 1228 1227 +3 1909 769 1358 +3 772 1909 1358 +3 923 1029 1028 +3 2178 1044 1674 +3 1232 36 950 +3 859 925 218 +3 925 1997 218 +3 924 217 1996 +3 1817 949 1230 +3 945 184 947 +3 2044 2048 2049 +3 2048 2044 2026 +3 2734 537 238 +3 1836 2496 2497 +3 1236 1020 735 +3 18 2642 2644 +3 1844 1839 1843 +3 1839 1844 1840 +3 1235 725 1236 +3 1243 1846 739 +3 1251 193 1847 +3 1366 1365 888 +3 1846 1250 1847 +3 1022 1842 1023 +3 458 1838 1242 +3 1842 1242 1841 +3 739 457 1243 +3 737 725 736 +3 2383 2386 2385 +3 2382 2383 2385 +3 1845 193 1840 +3 1255 193 1251 +3 184 535 947 +3 947 535 49 +3 535 1888 49 +3 1237 1239 1020 +3 1839 1838 1837 +3 1243 1250 1846 +3 192 456 457 +3 458 1242 1842 +3 1251 1252 1024 +3 339 2052 2051 +3 110 2065 2066 +3 1616 1617 130 +3 69 1616 130 +3 448 90 335 +3 1842 1841 1023 +3 2622 1418 2621 +3 1268 1270 367 +3 909 2050 2051 +3 2050 909 127 +3 1255 1841 193 +3 1247 1869 1868 +3 456 1254 457 +3 2552 60 2551 +3 1253 1254 456 +3 456 459 1249 +3 1249 439 1247 +3 1835 2496 1239 +3 2496 1835 2497 +3 1243 457 1254 +3 1496 1494 336 +3 2418 2419 763 +3 1277 1291 1653 +3 1909 1908 895 +3 1497 187 353 +3 2574 2230 2231 +3 1864 1865 1264 +3 1864 1265 1865 +3 440 2524 1412 +3 1254 1851 1244 +3 2308 2307 430 +3 1691 1692 1213 +3 1692 1215 1213 +3 1691 1690 1519 +3 450 1022 1258 +3 1909 1178 1908 +3 1263 1855 1262 +3 1024 1255 1251 +3 454 453 1259 +3 90 448 447 +3 448 186 447 +3 1256 1255 1024 +3 1255 1256 1023 +3 186 449 447 +3 1257 1260 54 +3 1023 1258 1022 +3 1023 1256 1258 +3 1256 1257 1258 +3 1258 1257 1259 +3 1245 1260 1252 +3 1488 2383 1285 +3 2383 1488 369 +3 1253 456 1862 +3 1861 1246 1862 +3 1367 768 1366 +3 1907 768 1367 +3 2764 1458 2743 +3 1459 2764 2743 +3 25 2052 339 +3 1263 1262 1866 +3 1519 1690 244 +3 1690 1212 244 +3 1457 386 1460 +3 1298 2110 2111 +3 1403 2327 2332 +3 2333 1403 2332 +3 2214 2219 2534 +3 2229 2219 2214 +3 2375 2380 2376 +3 140 74 908 +3 74 140 2054 +3 338 25 339 +3 520 570 571 +3 2598 250 2600 +3 1699 1038 1600 +3 1481 1479 369 +3 56 1789 2267 +3 1267 1270 1268 +3 1270 1267 366 +3 374 1267 1268 +3 433 1905 431 +3 1004 2186 2185 +3 351 1489 34 +3 1272 1801 1802 +3 2379 230 2378 +3 230 2377 2378 +3 1282 2394 53 +3 371 2683 2684 +3 1296 2107 2108 +3 1658 1293 228 +3 1314 98 285 +3 375 1282 1275 +3 1279 375 1275 +3 469 468 133 +3 1017 469 309 +3 1018 1017 309 +3 2393 1017 1018 +3 2684 2683 53 +3 2733 2732 2734 +3 551 2734 238 +3 555 537 2727 +3 2107 1296 1295 +3 1158 2107 1295 +3 1159 1291 1290 +3 1291 1289 1290 +3 1273 1282 53 +3 1269 1273 53 +3 1292 1159 2413 +3 312 153 311 +3 2125 17 1715 +3 2119 2120 1304 +3 2401 271 296 +3 1288 1277 1287 +3 2122 2125 2124 +3 375 1279 1695 +3 1656 1657 1279 +3 1656 1278 1657 +3 373 1969 1970 +3 424 1185 1187 +3 716 1623 642 +3 1131 716 642 +3 288 2184 2181 +3 2184 2182 2181 +3 1360 778 1359 +3 369 2384 2383 +3 2028 35 994 +3 370 1300 1319 +3 158 2100 2101 +3 227 2118 1306 +3 828 489 2682 +3 52 160 1478 +3 1305 52 1478 +3 1036 2429 1666 +3 1270 2378 367 +3 2378 1270 2379 +3 2730 2735 533 +3 1271 2375 2376 +3 1802 1271 1803 +3 1271 2376 1803 +3 1152 1307 1309 +3 1307 231 1309 +3 315 314 233 +3 231 1307 1295 +3 2111 2114 227 +3 1802 1803 1272 +3 2560 166 2549 +3 1158 2104 2106 +3 1158 2103 2104 +3 1153 1290 1289 +3 984 312 311 +3 1710 1709 2265 +3 1309 1311 470 +3 1153 1294 1295 +3 289 1336 2121 +3 2384 2386 2383 +3 1336 297 2121 +3 1300 229 1299 +3 83 1300 1299 +3 1607 1309 470 +3 48 1297 1313 +3 2272 1325 2275 +3 1325 2272 2273 +3 1422 1423 1399 +3 1114 1115 291 +3 1603 2301 1602 +3 1605 1308 1152 +3 1012 2211 2210 +3 371 2384 2391 +3 1116 1764 475 +3 1306 2112 227 +3 1280 1293 1658 +3 1603 225 1317 +3 1156 1603 1317 +3 475 1764 1763 +3 162 1476 1475 +3 2685 972 1816 +3 978 972 2685 +3 2114 2111 1301 +3 1315 1314 276 +3 1315 1297 275 +3 275 1297 48 +3 1315 276 1297 +3 2076 91 2077 +3 91 2076 2073 +3 2221 2760 2188 +3 1319 1302 1483 +3 369 1479 2387 +3 2384 369 2387 +3 160 52 159 +3 469 753 309 +3 1989 1991 322 +3 543 555 30 +3 555 2727 30 +3 189 1881 2437 +3 2396 1191 1190 +3 1009 2203 2206 +3 2106 2107 1158 +3 2107 2106 1298 +3 1290 2410 2413 +3 367 1802 1801 +3 1153 1295 1308 +3 1308 1295 1307 +3 1308 1307 1152 +3 47 280 283 +3 372 48 1313 +3 230 2370 1380 +3 1610 1154 1608 +3 1311 1309 1310 +3 235 314 315 +3 283 273 235 +3 2110 1301 2111 +3 98 1314 1315 +3 1311 276 1312 +3 276 1311 1310 +3 1660 1280 1659 +3 1312 1314 285 +3 1314 1312 276 +3 1301 2116 2115 +3 2115 2123 1303 +3 2123 1763 1303 +3 1010 2208 2206 +3 2410 2415 2413 +3 2651 2650 2142 +3 2412 2411 1153 +3 966 1155 1602 +3 1304 2120 2122 +3 1602 1157 1601 +3 2301 1292 2415 +3 1316 2409 2411 +3 2756 2196 2757 +3 647 2397 2396 +3 1357 777 1356 +3 1357 767 777 +3 911 778 623 +3 912 911 623 +3 611 911 914 +3 587 1650 1651 +3 805 575 396 +3 2478 783 2475 +3 952 2479 815 +3 405 1320 1321 +3 782 781 405 +3 2261 1013 1119 +3 1360 623 778 +3 1116 472 1119 +3 1322 1321 609 +3 1042 1129 2498 +3 1042 2769 1129 +3 2372 2379 366 +3 2379 1270 366 +3 2084 919 213 +3 2012 2673 1725 +3 1323 1322 609 +3 782 2299 2300 +3 1064 1600 871 +3 2274 1697 588 +3 2505 2506 1061 +3 1324 587 2270 +3 2400 284 2399 +3 2402 284 2400 +3 2074 977 2073 +3 977 2074 203 +3 2270 2269 1324 +3 404 2417 2418 +3 2417 2419 2418 +3 2563 2562 842 +3 2396 2397 1191 +3 1819 1822 688 +3 1330 1327 1328 +3 761 1330 1328 +3 1801 2264 1286 +3 2373 1475 1476 +3 918 1331 919 +3 1331 918 216 +3 1732 1730 1731 +3 2215 1950 1111 +3 77 1126 1395 +3 1757 1760 331 +3 1760 1139 331 +3 324 323 1744 +3 296 1336 270 +3 297 1336 296 +3 1038 871 1600 +3 1538 1534 1539 +3 728 1338 1337 +3 1340 1338 728 +3 1338 1340 1339 +3 1339 564 1338 +3 1339 569 564 +3 569 1339 565 +3 1346 1344 726 +3 564 1351 1350 +3 1351 564 1352 +3 451 1339 1340 +3 1339 451 565 +3 2168 2169 2765 +3 1349 1348 727 +3 450 1346 726 +3 955 957 411 +3 508 2267 2268 +3 453 1346 450 +3 1341 1347 727 +3 449 186 713 +3 1345 449 713 +3 1347 751 727 +3 451 1342 1343 +3 1349 727 480 +3 1343 713 566 +3 1344 713 1343 +3 713 1344 1345 +3 746 747 464 +3 463 2660 748 +3 2717 1432 467 +3 1344 1343 1342 +3 1347 728 751 +3 2660 178 748 +3 2659 178 2660 +3 1340 728 1347 +3 1340 1347 1341 +3 386 1345 453 +3 1345 1344 1346 +3 726 1342 1348 +3 726 1348 1349 +3 726 1349 450 +3 741 464 462 +3 741 744 464 +3 450 1349 1022 +3 1350 1351 729 +3 452 1353 1354 +3 1353 527 1354 +3 781 1360 1359 +3 411 2705 784 +3 569 1352 564 +3 1006 2201 2198 +3 497 1792 850 +3 887 888 403 +3 419 1516 615 +3 522 1772 526 +3 569 1353 1352 +3 452 1354 560 +3 561 452 560 +3 463 747 563 +3 776 406 779 +3 2443 1423 1422 +3 1379 885 886 +3 1362 1363 767 +3 1394 1910 644 +3 1910 1387 644 +3 1361 766 1362 +3 1576 1994 516 +3 590 1323 2271 +3 1357 1358 767 +3 1358 1361 767 +3 1407 1420 1400 +3 911 611 778 +3 611 772 1358 +3 1927 1922 758 +3 2331 1406 1402 +3 767 1361 1362 +3 888 1365 1364 +3 892 1363 1362 +3 1363 892 403 +3 1364 1363 403 +3 888 1364 403 +3 1177 772 1176 +3 766 892 1362 +3 774 1369 1370 +3 1177 774 1370 +3 1370 1368 768 +3 1178 1370 768 +3 1178 1177 1370 +3 1366 1368 775 +3 772 1177 1178 +3 2174 879 2173 +3 2174 2175 879 +3 2282 1161 2283 +3 2279 2282 1503 +3 1369 775 1368 +3 1370 1369 1368 +3 781 1359 405 +3 767 1363 1373 +3 709 708 2629 +3 1650 587 1324 +3 1646 608 1643 +3 1733 323 324 +3 1363 1364 1372 +3 2299 1322 2300 +3 767 1373 777 +3 1373 776 777 +3 1326 1697 2274 +3 1373 1363 1372 +3 1371 776 1372 +3 776 1373 1372 +3 1360 2477 623 +3 770 600 1376 +3 1374 770 1376 +3 1378 764 1379 +3 764 885 1379 +3 600 1377 1376 +3 1376 1377 766 +3 1234 724 1233 +3 1377 1378 766 +3 696 1186 695 +3 600 891 1377 +3 1028 1668 218 +3 554 217 924 +3 1378 1379 892 +3 766 1378 892 +3 1993 886 887 +3 1381 628 693 +3 670 1381 693 +3 1381 670 661 +3 1914 630 1915 +3 630 1916 1915 +3 1428 1417 1429 +3 1941 293 294 +3 1382 628 1381 +3 661 1382 1381 +3 2508 2509 1041 +3 2509 2512 1041 +3 980 219 979 +3 1809 219 980 +3 664 1388 1071 +3 651 1387 1390 +3 645 1384 602 +3 1072 1765 1115 +3 629 1390 1387 +3 629 1933 1390 +3 1870 1871 1265 +3 1874 1871 1870 +3 643 1804 1805 +3 2524 1410 2525 +3 644 1386 1385 +3 644 1387 1386 +3 628 1385 664 +3 644 1385 1383 +3 1383 1385 1382 +3 1385 628 1382 +3 1383 1382 643 +3 2523 1411 2333 +3 651 1388 1386 +3 1387 651 1386 +3 1934 1931 1932 +3 1931 650 1932 +3 2654 2653 596 +3 2654 2656 2653 +3 1615 1616 69 +3 1761 33 346 +3 644 1383 1384 +3 1929 1928 1925 +3 1391 1929 652 +3 598 1391 652 +3 598 1389 1391 +3 1388 1389 627 +3 1071 1388 627 +3 601 1818 1819 +3 1393 788 631 +3 1393 601 788 +3 290 1950 2298 +3 1388 664 1386 +3 1910 1394 1926 +3 1388 651 1389 +3 1407 2329 2330 +3 629 1926 1912 +3 1926 1911 1912 +3 638 665 666 +3 1389 651 1391 +3 440 1402 1406 +3 1666 862 1667 +3 862 1666 2429 +3 2672 700 2671 +3 92 1619 981 +3 1392 627 1389 +3 1394 644 1384 +3 1923 762 881 +3 1669 1672 1699 +3 200 2641 199 +3 126 261 1395 +3 260 1754 1752 +3 2123 475 1763 +3 475 2123 2116 +3 1263 1866 1865 +3 1496 353 75 +3 1497 353 1496 +3 1916 1922 1927 +3 1432 1431 1426 +3 1476 2720 1285 +3 2720 1476 1477 +3 2141 356 1891 +3 1441 1442 1134 +3 909 139 127 +3 838 837 1473 +3 306 152 307 +3 25 1002 2053 +3 189 1878 1881 +3 2328 2329 1407 +3 1436 441 2623 +3 2130 2131 356 +3 1411 1403 2333 +3 383 384 44 +3 1040 2513 1105 +3 1617 1616 127 +3 2449 1421 2528 +3 1410 2521 1428 +3 2521 1410 2520 +3 1811 862 1813 +3 1411 1406 1403 +3 1918 2259 1920 +3 630 1918 1920 +3 920 425 2450 +3 1439 2331 1402 +3 2331 1439 2444 +3 10 1413 2525 +3 1413 1412 2525 +3 1425 1424 460 +3 381 74 237 +3 1868 1869 1248 +3 2327 1408 2522 +3 1414 1413 441 +3 1418 1436 2623 +3 2701 1672 869 +3 1635 1415 1636 +3 2399 2398 271 +3 1409 2521 2520 +3 1416 1417 1404 +3 2314 2308 2311 +3 2330 1401 1420 +3 147 430 2307 +3 147 431 430 +3 1404 1417 1428 +3 353 1136 352 +3 1165 361 1166 +3 2332 2327 1409 +3 237 384 383 +3 2331 1401 2330 +3 188 442 1414 +3 349 74 376 +3 753 133 752 +3 133 1883 752 +3 1424 438 1405 +3 438 1424 1425 +3 2055 1002 143 +3 2053 1002 2055 +3 1879 2441 442 +3 579 583 1727 +3 2131 2130 2136 +3 1636 1415 1429 +3 1437 1441 1134 +3 1401 2443 1422 +3 439 1426 1427 +3 1426 1425 1427 +3 2260 2191 1013 +3 2443 2444 2442 +3 1807 1808 602 +3 1431 438 1426 +3 1431 1430 438 +3 2717 437 2718 +3 2714 2713 1433 +3 364 365 1883 +3 2525 2529 10 +3 2525 1410 2529 +3 1878 1880 1396 +3 838 2595 1435 +3 1879 189 2439 +3 460 1424 1421 +3 1881 1877 1398 +3 1877 1881 1878 +3 1434 2713 2714 +3 356 2140 2130 +3 1880 443 1396 +3 1397 443 1880 +3 442 1025 1397 +3 467 1432 1426 +3 1399 1423 1875 +3 1867 1870 1265 +3 1870 1867 1868 +3 1427 1425 460 +3 1248 1876 1875 +3 444 1461 436 +3 1426 438 1425 +3 2524 2525 1412 +3 2530 1947 1946 +3 1947 2530 703 +3 1807 633 626 +3 2133 2132 144 +3 2404 286 2403 +3 108 1936 1937 +3 1419 1701 1700 +3 600 1921 891 +3 1700 1701 1135 +3 1417 1636 1429 +3 1406 2331 2330 +3 2620 2623 1413 +3 1913 1914 1915 +3 714 2290 2284 +3 2290 714 2318 +3 1703 2771 1702 +3 1405 1636 1417 +3 1416 1405 1417 +3 1919 1918 649 +3 2259 1918 1919 +3 2716 467 459 +3 66 351 197 +3 351 66 1489 +3 132 73 2533 +3 1438 435 188 +3 1459 435 1471 +3 441 1437 1438 +3 2652 44 385 +3 2444 1439 2442 +3 265 266 1502 +3 266 267 1502 +3 1500 2302 2305 +3 2440 2439 1402 +3 1437 441 1436 +3 1447 491 1451 +3 188 1414 1438 +3 1134 435 1438 +3 2593 1440 2594 +3 2201 1008 2198 +3 2651 2136 358 +3 2652 2651 358 +3 2492 2491 434 +3 1977 1596 1597 +3 2637 2638 1442 +3 434 1474 1470 +3 1450 493 1448 +3 2 493 494 +3 1445 491 1447 +3 492 1445 1447 +3 2595 838 1473 +3 2639 2638 2637 +3 2639 1443 2638 +3 413 491 1446 +3 413 511 491 +3 1446 836 413 +3 413 836 835 +3 414 836 1446 +3 491 1445 1446 +3 1447 1448 492 +3 1448 1449 492 +3 445 1455 1137 +3 485 389 486 +3 926 1680 1685 +3 388 1447 1451 +3 2598 2600 253 +3 1472 2592 2593 +3 190 1472 2593 +3 493 1449 1448 +3 485 486 1902 +3 1448 388 1450 +3 1454 1455 1456 +3 1134 2492 1471 +3 1451 511 484 +3 511 1451 491 +3 511 389 484 +3 1447 388 1448 +3 482 1467 481 +3 1966 1444 1967 +3 1451 484 1452 +3 1454 1449 493 +3 388 1453 1450 +3 388 1452 1453 +3 2485 2486 780 +3 1456 387 1454 +3 1455 2 1137 +3 551 79 2734 +3 552 79 551 +3 1906 1367 771 +3 1456 1455 445 +3 1902 486 2483 +3 780 1174 2484 +3 1458 387 1456 +3 1457 1458 1456 +3 1459 444 435 +3 1452 1462 483 +3 1452 484 1462 +3 1457 445 446 +3 521 1785 1773 +3 1324 2269 2271 +3 2269 590 2271 +3 1471 1470 1459 +3 1134 1471 435 +3 1470 1471 434 +3 2766 826 822 +3 2744 1784 1795 +3 939 2746 2748 +3 1794 1784 2744 +3 1452 483 1453 +3 1462 1463 483 +3 1469 355 1468 +3 482 1469 1468 +3 485 1463 1462 +3 619 2583 1175 +3 1174 2583 619 +3 830 829 2236 +3 2680 829 830 +3 392 2580 2238 +3 1466 1467 482 +3 942 1984 2245 +3 2255 1445 492 +3 1561 2238 794 +3 1465 431 432 +3 433 431 1465 +3 1466 432 1467 +3 60 2552 2005 +3 2552 246 2005 +3 1465 1464 148 +3 1455 493 2 +3 255 1892 60 +3 415 837 838 +3 355 1453 483 +3 1468 355 483 +3 482 1468 1464 +3 2133 2142 2134 +3 476 834 816 +3 476 413 834 +3 476 510 413 +3 1284 2374 2367 +3 2168 2765 2167 +3 2765 1046 2167 +3 2141 481 2140 +3 1469 481 2141 +3 1664 889 764 +3 2689 301 2694 +3 493 1455 1454 +3 2638 2492 1442 +3 2492 2638 2491 +3 2491 2638 1443 +3 836 149 835 +3 414 837 836 +3 414 1473 837 +3 837 149 836 +3 1712 171 1713 +3 2398 1168 97 +3 1168 2398 272 +3 1305 1485 52 +3 2265 2266 2339 +3 1476 162 1477 +3 66 197 1684 +3 2368 1380 2370 +3 370 2367 2368 +3 1302 1484 1483 +3 1319 162 1475 +3 1475 370 1319 +3 1902 2483 391 +3 2395 1017 2393 +3 19 1898 1479 +3 2389 161 2388 +3 1478 1479 1481 +3 1478 160 1479 +3 2723 531 257 +3 2750 1797 56 +3 930 34 175 +3 34 1489 175 +3 2369 2370 372 +3 1482 1483 1484 +3 1482 162 1483 +3 1716 1714 155 +3 1717 1716 155 +3 1305 1484 1485 +3 1484 172 1485 +3 2730 2729 532 +3 2303 1501 146 +3 2303 2302 1501 +3 147 2307 2306 +3 1566 1544 512 +3 1501 1500 113 +3 220 2080 2088 +3 2726 2725 538 +3 2392 2395 2393 +3 1477 1480 1488 +3 172 1486 1485 +3 1486 172 1487 +3 1017 2389 469 +3 161 2389 1017 +3 1712 1487 172 +3 1487 1712 1713 +3 1480 1481 1488 +3 2727 538 30 +3 538 539 30 +3 2727 2726 538 +3 536 2724 2725 +3 2724 257 2725 +3 1493 1492 334 +3 1858 1246 1859 +3 1025 54 1263 +3 1493 336 1494 +3 143 1493 1494 +3 2306 2309 2305 +3 2309 1500 2305 +3 26 2058 2059 +3 140 908 909 +3 1879 1878 189 +3 430 23 2308 +3 1498 1495 75 +3 90 1497 336 +3 234 151 852 +3 447 187 1497 +3 90 447 1497 +3 1025 455 54 +3 1495 1498 2056 +3 1498 141 2056 +3 2136 2130 357 +3 2308 2314 428 +3 2138 114 362 +3 771 888 887 +3 2294 2295 865 +3 2294 880 2295 +3 2322 2323 1622 +3 2686 865 1109 +3 463 563 562 +3 1506 1513 558 +3 1513 1506 559 +3 466 561 1505 +3 559 1505 1507 +3 1355 1511 179 +3 523 1220 1517 +3 2129 2148 114 +3 2704 2703 2658 +3 2705 2704 784 +3 2657 1506 2658 +3 1506 784 2658 +3 1440 2713 1434 +3 2594 1440 1434 +3 2660 466 2659 +3 556 1510 529 +3 1509 1510 556 +3 1509 179 1510 +3 1508 1512 559 +3 1509 1512 1508 +3 2703 466 2658 +3 2703 2659 466 +3 1726 2009 579 +3 579 2009 2010 +3 1222 574 575 +3 2707 418 2708 +3 2705 785 2704 +3 557 1514 1512 +3 2435 2434 847 +3 1786 501 1787 +3 1510 1511 529 +3 179 1511 1510 +3 530 2721 2723 +3 2721 531 2723 +3 536 530 2724 +3 730 749 731 +3 730 563 749 +3 625 1513 1514 +3 1514 1513 1512 +3 2129 2147 2148 +3 452 562 1351 +3 1207 2741 1206 +3 2251 420 1553 +3 295 2058 2057 +3 806 2243 807 +3 393 806 807 +3 269 268 2149 +3 486 389 2575 +3 389 509 2575 +3 1561 488 2238 +3 408 1145 2240 +3 408 1144 1145 +3 144 2132 2131 +3 787 1821 2653 +3 1445 2255 1444 +3 1554 1559 421 +3 792 1520 1522 +3 2708 1435 191 +3 1545 1542 55 +3 1542 1541 55 +3 2222 2756 2761 +3 1546 1541 1542 +3 1536 1541 1546 +3 2231 2230 1521 +3 2691 905 2689 +3 2515 1031 1032 +3 2325 1627 723 +3 1528 792 1522 +3 583 1645 1644 +3 1527 1524 422 +3 303 152 304 +3 2690 2694 2695 +3 2697 301 2688 +3 1164 1121 288 +3 2677 1121 1164 +3 1532 982 1533 +3 1530 1532 1533 +3 434 2491 1474 +3 2057 2058 294 +3 299 298 295 +3 791 1525 1531 +3 2541 1631 2542 +3 1555 1570 1588 +3 1572 1555 1588 +3 1999 253 2600 +3 421 1551 1550 +3 2585 2584 1568 +3 2584 2585 1567 +3 789 1536 1569 +3 704 1026 1945 +3 982 983 1534 +3 2059 2058 295 +3 2541 2540 1631 +3 2064 2057 321 +3 1531 1539 1535 +3 1539 1531 1538 +3 2057 2064 295 +3 1937 1942 108 +3 1406 2329 1403 +3 2329 2328 1403 +3 282 281 47 +3 1723 215 87 +3 1546 1548 1569 +3 1551 789 1549 +3 2670 1948 2669 +3 1562 791 1535 +3 1587 1589 1571 +3 1543 1544 513 +3 1552 1557 790 +3 1097 578 1947 +3 578 1097 1725 +3 1547 1548 1564 +3 1548 1547 1549 +3 1560 793 1559 +3 1622 2324 1623 +3 2324 723 1623 +3 498 1 1556 +3 1546 1537 1548 +3 677 678 637 +3 677 1634 678 +3 513 1537 1543 +3 1942 12 293 +3 293 12 282 +3 1540 1539 55 +3 1543 1542 1545 +3 1543 1537 1542 +3 1545 55 1534 +3 1539 1534 55 +3 798 420 797 +3 422 1544 983 +3 512 1553 420 +3 1557 1558 790 +3 1937 1938 12 +3 421 1552 1551 +3 131 132 134 +3 1544 1543 983 +3 1054 880 2294 +3 1534 983 1545 +3 1540 1535 1539 +3 1536 1535 1540 +3 843 842 2588 +3 1565 1564 513 +3 1537 1546 1542 +3 512 420 514 +3 1567 1565 1563 +3 1565 1567 1564 +3 1591 2610 16 +3 1556 1 1560 +3 498 1556 786 +3 1946 1948 701 +3 2323 2324 1622 +3 321 2063 109 +3 1552 421 1557 +3 1579 1580 516 +3 1569 1536 1546 +3 1162 23 78 +3 2587 2584 1563 +3 2587 1568 2584 +3 1551 1552 789 +3 1171 640 1632 +3 422 1553 1544 +3 1558 1521 790 +3 2254 795 2234 +3 1120 1951 2218 +3 512 1544 1553 +3 1549 789 1569 +3 2609 16 2610 +3 2281 2364 2365 +3 234 552 78 +3 1121 961 2187 +3 1554 1550 1555 +3 2460 2577 843 +3 499 2614 1578 +3 2614 499 1768 +3 494 1450 1453 +3 482 1464 1466 +3 794 2232 1558 +3 796 2252 2251 +3 793 794 1558 +3 504 2601 2602 +3 2613 504 2602 +3 488 2239 2238 +3 1905 151 431 +3 1 1561 1560 +3 1 851 1561 +3 1561 851 488 +3 2063 2057 294 +3 1552 1562 789 +3 790 1521 1562 +3 506 1591 1592 +3 1550 1551 2586 +3 2586 2585 1568 +3 1570 1568 2587 +3 1550 1568 1555 +3 1555 1574 786 +3 1569 1548 1549 +3 2603 2613 2602 +3 1574 2606 786 +3 787 788 1821 +3 1554 421 1550 +3 1565 1566 507 +3 1566 1565 513 +3 1544 1566 513 +3 843 2588 1074 +3 2586 1568 1550 +3 982 1532 1594 +3 281 12 1938 +3 1567 1563 2584 +3 1570 1555 1568 +3 2491 1444 1474 +3 1555 1572 1574 +3 976 211 975 +3 2604 1575 2605 +3 507 1591 1590 +3 46 976 203 +3 516 505 515 +3 1573 2618 2608 +3 1582 1581 499 +3 684 2289 2288 +3 951 1232 1231 +3 1575 515 2605 +3 1790 505 1789 +3 2319 2317 691 +3 2287 2282 2283 +3 1779 2753 1800 +3 572 1779 1800 +3 206 205 59 +3 1577 2612 2614 +3 1768 1577 2614 +3 2611 2601 504 +3 69 129 125 +3 1583 1582 938 +3 2742 277 64 +3 1580 505 516 +3 218 1995 923 +3 1581 1768 499 +3 1708 2341 1707 +3 2659 785 2661 +3 1772 240 526 +3 240 527 526 +3 2170 1045 2166 +3 1064 871 2505 +3 238 555 543 +3 1230 949 1228 +3 876 2158 2157 +3 1809 1810 222 +3 862 1809 222 +3 979 972 2097 +3 972 2098 2097 +3 972 978 2098 +3 1817 1739 183 +3 2287 2283 2284 +3 1050 2172 1051 +3 2164 2160 2167 +3 2160 1048 2167 +3 848 1900 1899 +3 2357 2353 614 +3 2342 2102 51 +3 2342 156 2102 +3 183 949 1817 +3 578 1948 1947 +3 1620 714 3 +3 446 2326 1457 +3 2671 2674 580 +3 1709 2747 56 +3 1121 2677 1120 +3 517 1580 1579 +3 1585 2772 2771 +3 1300 1302 1319 +3 1707 1583 572 +3 1789 505 2268 +3 1781 1583 938 +3 543 545 212 +3 1200 1224 1209 +3 1563 1565 1589 +3 507 1566 1592 +3 1590 1589 507 +3 1571 1589 1590 +3 786 1554 1555 +3 507 1592 1591 +3 1554 786 1556 +3 604 788 787 +3 1554 1556 1559 +3 1556 1560 1559 +3 1588 1571 1593 +3 1590 1593 1571 +3 1590 16 1593 +3 2217 2216 1949 +3 1527 1594 1526 +3 1594 1523 1526 +3 2400 2401 2402 +3 2324 2323 2325 +3 1132 639 2150 +3 1978 1598 940 +3 1598 1979 940 +3 1980 1979 1598 +3 926 1683 1681 +3 1838 458 1020 +3 1156 1292 2301 +3 940 1976 1975 +3 1598 1599 27 +3 869 1669 1670 +3 2597 1595 2599 +3 2643 31 1682 +3 1828 1825 1826 +3 1829 28 1830 +3 1113 1957 1958 +3 1963 1954 1118 +3 2559 42 1831 +3 1599 1598 1597 +3 101 2550 2549 +3 2264 1287 1286 +3 1801 1272 2264 +3 1277 1286 1287 +3 1294 1158 1295 +3 1611 1155 1154 +3 2194 2227 2226 +3 206 58 205 +3 58 2490 205 +3 966 1605 1606 +3 966 1606 1155 +3 2087 2086 968 +3 2086 974 968 +3 2084 2083 919 +3 311 153 307 +3 958 471 1609 +3 232 958 1609 +3 1013 2207 1119 +3 1604 966 1601 +3 966 1602 1601 +3 2227 1005 2192 +3 1607 1152 1309 +3 1152 1607 1605 +3 1606 1605 1607 +3 143 1002 1491 +3 1609 1312 232 +3 470 1312 1609 +3 1311 1312 470 +3 1013 2261 2260 +3 1617 127 139 +3 2008 883 2007 +3 503 2610 506 +3 1614 1616 1615 +3 125 1615 69 +3 1615 125 1618 +3 1764 1072 1763 +3 2774 136 379 +3 694 2008 882 +3 2257 2008 694 +3 2015 2033 2031 +3 73 1617 139 +3 73 132 131 +3 2214 2534 2216 +3 2534 1949 2216 +3 130 73 131 +3 130 1617 73 +3 129 69 130 +3 71 129 130 +3 2002 248 2003 +3 2669 1948 578 +3 2668 2669 578 +3 126 1614 1615 +3 217 554 916 +3 318 321 109 +3 141 1499 2054 +3 2534 2219 2228 +3 961 2534 2228 +3 2284 2283 3 +3 689 1092 2466 +3 2465 690 1091 +3 1634 1633 640 +3 677 676 1633 +3 676 677 636 +3 1632 640 1633 +3 472 1612 2260 +3 2544 2545 2546 +3 2363 2544 2546 +3 723 1628 642 +3 721 642 1629 +3 1630 386 453 +3 1624 1623 716 +3 1102 2463 2462 +3 2458 1102 2462 +3 1173 2543 2363 +3 962 1101 1100 +3 1101 2462 1100 +3 963 68 254 +3 722 1131 642 +3 1623 723 642 +3 1103 2459 2458 +3 2459 1102 2458 +3 1461 1630 454 +3 2579 830 2236 +3 2067 299 2065 +3 2070 2068 110 +3 2068 2070 303 +3 2067 2065 110 +3 2691 300 2692 +3 2446 45 2445 +3 152 2070 320 +3 320 2070 110 +3 111 2691 2692 +3 2362 2363 1172 +3 678 1634 640 +3 1621 1622 1623 +3 2183 2260 1612 +3 2257 2259 1919 +3 2257 694 2259 +3 438 1635 1405 +3 2667 2671 700 +3 1920 2259 694 +3 1413 1414 1412 +3 1635 438 1430 +3 1435 1434 2714 +3 1324 1323 401 +3 1650 1324 401 +3 1145 393 807 +3 711 1641 710 +3 1291 1159 1652 +3 502 938 499 +3 401 1646 1648 +3 1649 401 1648 +3 1647 608 1646 +3 2559 62 167 +3 2634 802 2626 +3 1647 1646 1323 +3 1648 1646 1643 +3 608 612 583 +3 1644 608 583 +3 1642 1643 584 +3 585 2634 2626 +3 2627 2629 2632 +3 585 2627 2632 +3 586 1649 2626 +3 802 586 2626 +3 1647 394 612 +3 612 608 1647 +3 394 1647 609 +3 2489 1036 1035 +3 613 2348 2349 +3 609 1647 1323 +3 401 1649 1650 +3 1654 1656 1276 +3 1649 586 1651 +3 1649 1651 1650 +3 2564 1735 1742 +3 2408 1011 2407 +3 1277 1653 1286 +3 1275 1276 1656 +3 1159 1654 1652 +3 1652 1654 1276 +3 157 479 120 +3 159 157 120 +3 479 121 120 +3 2101 82 158 +3 1293 1294 1288 +3 1660 1659 1278 +3 1899 496 1770 +3 1654 1278 1656 +3 1655 1660 1278 +3 1970 1969 1275 +3 1329 588 760 +3 2100 159 2101 +3 159 52 2101 +3 1486 82 2101 +3 2117 227 2114 +3 1294 2103 1158 +3 1662 1454 387 +3 1474 1661 1470 +3 2124 1304 2122 +3 1660 1655 1292 +3 1470 1662 387 +3 1663 1378 1377 +3 1378 1663 764 +3 2425 2422 759 +3 2425 757 2422 +3 1664 891 1665 +3 891 1664 1663 +3 1664 764 1663 +3 2421 2417 404 +3 889 884 764 +3 2417 2421 2426 +3 1667 1668 1666 +3 1668 1667 859 +3 1814 1812 863 +3 1666 861 1036 +3 2686 1109 867 +3 1029 861 1028 +3 1668 859 218 +3 1371 1365 775 +3 861 1668 1028 +3 1677 2175 2174 +3 2176 1677 2174 +3 1670 1669 1039 +3 1044 1675 1674 +3 1675 1043 1674 +3 958 232 2179 +3 46 550 976 +3 1675 1050 1034 +3 1845 1241 1846 +3 2162 1671 870 +3 872 1049 1056 +3 1671 1670 1039 +3 2295 1059 2296 +3 1059 2295 876 +3 1095 2502 702 +3 1722 1721 154 +3 874 1675 1034 +3 2174 2173 1044 +3 2176 2174 1044 +3 1122 1123 1943 +3 1037 874 1032 +3 1045 1670 1671 +3 874 1043 1675 +3 1834 262 1753 +3 1670 1676 869 +3 1670 1045 1676 +3 2335 946 947 +3 946 945 947 +3 201 4 1679 +3 1673 1678 1674 +3 2018 116 2023 +3 519 1774 2702 +3 662 663 606 +3 2664 692 2666 +3 1890 90 334 +3 1687 660 681 +3 1729 197 323 +3 2568 2567 343 +3 387 1458 2764 +3 2643 1682 9 +3 200 199 201 +3 2343 200 201 +3 119 118 122 +3 250 941 85 +3 250 1976 941 +3 1999 1998 253 +3 681 660 682 +3 2647 195 2648 +3 2008 2007 882 +3 175 1683 926 +3 927 175 926 +3 1686 1684 1682 +3 32 2035 2034 +3 32 2036 2035 +3 1614 1698 2050 +3 1595 2598 2599 +3 1683 1686 1681 +3 1866 1262 1873 +3 1262 1858 1873 +3 2017 2023 935 +3 1848 1250 1244 +3 1400 2527 1408 +3 1923 881 648 +3 679 632 1688 +3 679 667 632 +3 679 1688 1687 +3 675 679 1687 +3 603 1068 1069 +3 1688 632 707 +3 1852 1252 1850 +3 1882 2442 2437 +3 1861 1860 1246 +3 1693 1519 1517 +3 1519 1208 1517 +3 1220 1693 1517 +3 524 1691 1693 +3 1772 1771 521 +3 938 1782 1781 +3 1696 1318 375 +3 1657 1694 1279 +3 1657 228 1694 +3 1658 228 1657 +3 1281 1694 228 +3 1696 1695 1281 +3 1059 876 2156 +3 1326 1085 1697 +3 1096 703 1095 +3 1698 338 339 +3 1698 1395 338 +3 126 1395 1698 +3 126 1698 1614 +3 1706 1705 508 +3 1300 370 2369 +3 1436 1700 1135 +3 1700 1436 1418 +3 1582 1702 1586 +3 1581 1582 1586 +3 2007 893 765 +3 883 893 2007 +3 1418 2623 2620 +3 952 815 1183 +3 1817 950 1739 +3 2269 2275 1325 +3 2275 2269 2270 +3 1679 202 2455 +3 1790 1788 501 +3 1583 1703 1702 +3 379 378 2774 +3 2738 244 2737 +3 1711 172 1484 +3 1302 1711 1484 +3 826 2127 822 +3 2490 7 205 +3 2733 2734 79 +3 2474 2473 2472 +3 2471 2474 2472 +3 833 2575 490 +3 833 2676 2575 +3 1214 1211 1212 +3 849 2736 852 +3 2729 531 532 +3 2341 1584 1704 +3 1707 2341 1704 +3 2266 1584 2339 +3 2341 2340 1584 +3 2280 2430 2293 +3 156 2100 2102 +3 2100 158 2102 +3 171 83 224 +3 171 1711 83 +3 243 822 2127 +3 821 822 243 +3 172 1711 1712 +3 82 1486 1487 +3 1732 997 996 +3 1721 1719 154 +3 1713 171 1714 +3 1719 64 154 +3 171 1712 1711 +3 1476 1285 2381 +3 701 2670 708 +3 82 170 169 +3 272 98 273 +3 17 269 1715 +3 823 821 478 +3 155 1720 1717 +3 2448 1027 2075 +3 2447 2446 2448 +3 1717 263 1716 +3 263 1717 1718 +3 1719 1718 264 +3 1719 24 1718 +3 64 1719 264 +3 24 263 1718 +3 2075 7 2448 +3 2447 2448 7 +3 209 2083 2084 +3 38 209 2084 +3 266 1721 1723 +3 1721 266 24 +3 266 1723 87 +3 2645 2644 9 +3 1722 214 215 +3 1721 1722 1723 +3 1758 1759 340 +3 1714 1724 1713 +3 1724 1714 1716 +3 1716 170 1724 +3 1097 698 1725 +3 2675 1637 1638 +3 1637 1639 582 +3 576 1151 1223 +3 576 2472 1151 +3 994 2036 2042 +3 2010 1639 699 +3 2010 2009 1639 +3 1639 1640 699 +3 1578 2603 503 +3 2170 1677 1045 +3 2172 2171 1047 +3 2038 2024 2037 +3 261 259 1752 +3 820 243 844 +3 1729 1730 37 +3 323 1730 1729 +3 325 1333 328 +3 1333 325 1734 +3 1736 1731 325 +3 1733 1731 323 +3 1744 323 99 +3 2230 2574 1520 +3 792 2230 1520 +3 2564 2565 2573 +3 2565 2564 345 +3 325 1738 1737 +3 1743 326 340 +3 93 917 918 +3 260 341 1754 +3 1743 324 1744 +3 36 1738 1739 +3 1730 1732 37 +3 37 1732 996 +3 38 344 215 +3 325 328 1738 +3 1733 324 1735 +3 1126 337 332 +3 2573 2565 2569 +3 1741 1331 216 +3 1041 2512 875 +3 213 1333 1334 +3 36 997 1737 +3 340 1745 1742 +3 345 1745 1746 +3 1741 1332 1331 +3 2746 2750 2748 +3 2750 2746 1780 +3 1737 1738 36 +3 1070 1393 631 +3 1392 692 1818 +3 1891 2 494 +3 1889 335 1890 +3 355 1891 494 +3 36 1739 950 +3 1741 328 1332 +3 1072 226 1763 +3 1739 1738 328 +3 1740 1739 328 +3 1741 1740 328 +3 916 216 918 +3 216 1740 1741 +3 2142 144 2651 +3 1742 1743 340 +3 326 1743 1744 +3 99 326 1744 +3 327 326 99 +3 1754 337 77 +3 1734 325 2570 +3 2569 88 2571 +3 2570 2569 2571 +3 1750 343 2567 +3 342 1750 2567 +3 460 1421 1399 +3 1751 259 65 +3 260 1749 1748 +3 342 1748 1749 +3 1749 65 1750 +3 1750 342 1749 +3 2431 2430 2291 +3 327 99 351 +3 77 261 1752 +3 260 1752 1751 +3 341 1753 1754 +3 1753 1755 1754 +3 347 330 346 +3 1758 329 1757 +3 331 1141 1490 +3 1756 331 1490 +3 1141 89 1490 +3 1491 1490 89 +3 1492 1491 89 +3 1141 1140 89 +3 1753 262 1755 +3 948 330 181 +3 948 1140 330 +3 1850 1849 1244 +3 1850 1252 1849 +3 2020 2030 2029 +3 2030 2019 2029 +3 2018 2023 2017 +3 262 1759 1758 +3 262 1758 1757 +3 948 333 1140 +3 33 1762 327 +3 1762 326 327 +3 1762 33 1761 +3 329 1762 1761 +3 1613 475 2116 +3 1072 1073 226 +3 472 1116 1613 +3 40 103 104 +3 1115 292 1072 +3 4 931 1766 +3 1765 1072 1764 +3 1612 472 1613 +3 4 1766 202 +3 927 1685 202 +3 1766 927 202 +3 129 70 125 +3 931 4 932 +3 929 1767 928 +3 121 70 129 +3 1777 571 570 +3 549 92 967 +3 517 1769 1581 +3 1586 517 1581 +3 1769 517 1579 +3 1776 1777 570 +3 2658 784 2704 +3 2662 178 2707 +3 242 2768 1130 +3 496 521 1770 +3 1327 590 2269 +3 1353 569 527 +3 1773 1772 521 +3 1772 1773 240 +3 163 1894 19 +3 1774 525 1775 +3 1710 2747 1709 +3 530 239 526 +3 1786 518 501 +3 1208 1519 2738 +3 571 1777 1778 +3 2751 1710 2336 +3 1787 1788 1798 +3 2752 2749 2751 +3 1800 2752 2751 +3 571 2754 2755 +3 610 394 609 +3 502 500 1218 +3 938 502 1782 +3 1327 2269 1325 +3 2657 2658 466 +3 1776 1783 1777 +3 1505 2657 466 +3 1518 1208 2740 +3 1775 2517 523 +3 523 1799 1775 +3 382 383 361 +3 1211 2737 244 +3 1774 1775 1799 +3 1786 1787 519 +3 1789 2268 2267 +3 2336 2337 1708 +3 505 1790 498 +3 1580 2268 505 +3 501 498 1790 +3 502 520 1782 +3 521 496 1791 +3 1705 1706 2773 +3 1791 1792 518 +3 1791 496 1792 +3 2333 2520 2523 +3 2517 1775 2516 +3 2517 2516 1783 +3 2519 2332 1409 +3 2738 1519 244 +3 313 2371 2372 +3 2266 1709 2267 +3 1780 1795 1796 +3 2523 1410 2524 +3 1793 1794 1778 +3 1777 1793 1778 +3 1798 1774 519 +3 1787 1798 519 +3 1795 1784 1796 +3 56 1797 1788 +3 526 239 522 +3 525 1797 1796 +3 1796 1797 1780 +3 2752 2753 939 +3 1788 1797 1798 +3 525 1798 1797 +3 313 372 2371 +3 2262 2263 1272 +3 1272 1803 2262 +3 1274 1269 367 +3 372 2370 2371 +3 661 605 1804 +3 661 685 605 +3 2419 1188 763 +3 2611 1576 2601 +3 1804 605 633 +3 605 634 633 +3 633 1806 1805 +3 643 1805 1806 +3 643 1806 602 +3 1384 643 602 +3 688 962 1092 +3 1824 962 688 +3 1383 643 1384 +3 606 1808 1807 +3 1125 1824 656 +3 1809 862 1811 +3 708 2672 2630 +3 652 759 2665 +3 652 1925 757 +3 699 1640 2667 +3 980 1619 1810 +3 1810 1619 546 +3 104 2342 51 +3 218 923 1028 +3 219 1811 1812 +3 1816 972 979 +3 1054 1055 1053 +3 2327 2328 1407 +3 474 2182 2190 +3 1230 950 1817 +3 2289 1503 2288 +3 1508 559 1507 +3 1082 1823 687 +3 42 8 1825 +3 1080 95 1081 +3 689 1820 688 +3 1819 688 1820 +3 94 577 576 +3 634 605 697 +3 2656 634 697 +3 634 2656 2654 +3 664 1385 1386 +3 601 1821 788 +3 962 1824 1125 +3 1955 1952 1117 +3 1827 80 1599 +3 1979 941 1976 +3 80 57 40 +3 1827 57 80 +3 1831 1829 1832 +3 1831 62 2559 +3 1745 1834 1746 +3 1826 1827 28 +3 1827 1599 28 +3 292 1115 1957 +3 1827 1826 57 +3 1832 62 1831 +3 42 1828 1829 +3 1828 28 1829 +3 1828 1826 28 +3 1415 2621 1429 +3 2622 2621 1415 +3 1759 1745 340 +3 1745 1759 1834 +3 1888 1889 49 +3 1595 1975 1976 +3 57 107 40 +3 42 1829 1831 +3 100 2561 2560 +3 8 2561 100 +3 2550 100 2560 +3 102 29 103 +3 1832 1833 43 +3 78 203 1027 +3 2335 49 948 +3 2334 2335 948 +3 946 2335 2334 +3 1838 1020 1239 +3 1837 1838 1239 +3 535 1887 1888 +3 738 457 739 +3 1839 1840 1242 +3 458 1842 1022 +3 1844 1241 1845 +3 1844 1843 1241 +3 1841 1255 1023 +3 1229 423 985 +3 2494 1240 2493 +3 1240 1843 2493 +3 1836 1240 2494 +3 2494 2493 1837 +3 1849 1848 1244 +3 1847 1848 1251 +3 1245 1855 1260 +3 1247 1427 1869 +3 1844 1845 1840 +3 1843 1240 739 +3 1241 1843 739 +3 739 1846 1241 +3 1245 1252 1852 +3 78 552 203 +3 2020 2022 932 +3 347 423 181 +3 2139 2146 362 +3 2146 2138 362 +3 1849 1252 1251 +3 1851 1850 1244 +3 1851 1689 1850 +3 1254 1253 1851 +3 1253 1689 1851 +3 1847 1250 1848 +3 1260 1855 54 +3 1245 1853 1854 +3 1853 1245 1852 +3 1855 1245 1854 +3 1869 1876 1248 +3 333 334 1492 +3 1139 1140 1141 +3 330 1140 1139 +3 1253 1862 1261 +3 1862 1246 1261 +3 1857 1854 1853 +3 1856 1857 1853 +3 1852 1689 1853 +3 1261 1857 1856 +3 1246 1858 1261 +3 1858 1857 1261 +3 1266 1247 1868 +3 1253 1261 1856 +3 1864 1264 1863 +3 769 1909 895 +3 1858 1859 1873 +3 25 2053 2052 +3 1859 1246 1860 +3 1249 1862 456 +3 1249 1861 1862 +3 895 1907 1906 +3 436 1461 454 +3 1266 1868 1867 +3 1863 1859 1860 +3 1266 1863 1860 +3 1864 1863 1867 +3 1266 1867 1863 +3 1866 1264 1865 +3 1859 1863 1264 +3 349 139 908 +3 1868 1248 1870 +3 2051 2052 140 +3 1872 1396 443 +3 1872 1865 1265 +3 1865 1872 443 +3 1872 1265 1871 +3 1871 1396 1872 +3 1264 1866 1873 +3 1873 1859 1264 +3 1858 1262 1857 +3 1875 1876 1399 +3 1248 1874 1870 +3 1876 460 1399 +3 460 1876 1869 +3 2440 2441 1879 +3 1874 1877 1871 +3 1398 1877 1874 +3 1877 1396 1871 +3 318 1163 321 +3 1495 2055 143 +3 1398 1874 1875 +3 1874 1248 1875 +3 1879 2439 2440 +3 1875 1423 1882 +3 1398 1875 1882 +3 1879 1397 1880 +3 1878 1879 1880 +3 1869 1427 460 +3 442 1397 1879 +3 1878 1396 1877 +3 45 2447 1935 +3 2438 189 2437 +3 1881 1398 1882 +3 1883 365 752 +3 133 1884 1883 +3 1884 364 1883 +3 134 364 1884 +3 198 2043 2049 +3 1698 339 2050 +3 2498 2499 1042 +3 1128 877 2498 +3 877 2499 2498 +3 960 2677 1164 +3 2641 2640 1886 +3 1885 194 35 +3 2027 198 2048 +3 2040 2024 2039 +3 214 1722 910 +3 539 2730 533 +3 857 223 856 +3 1887 448 335 +3 948 49 1889 +3 333 948 1889 +3 335 1889 1888 +3 1890 333 1889 +3 334 333 1890 +3 335 90 1890 +3 1895 1897 19 +3 101 2549 2548 +3 532 2735 2730 +3 1006 2204 2203 +3 164 71 165 +3 121 71 164 +3 119 70 121 +3 121 129 71 +3 479 20 119 +3 134 1884 1896 +3 1884 468 1896 +3 468 1884 133 +3 19 1894 1895 +3 1423 2442 1882 +3 1423 2443 2442 +3 177 531 2721 +3 531 177 567 +3 160 19 1479 +3 134 132 364 +3 1488 1481 369 +3 1770 848 1899 +3 850 495 851 +3 1903 241 849 +3 241 1903 848 +3 1901 848 1903 +3 1900 1901 391 +3 1902 1904 433 +3 1902 1901 1904 +3 86 1985 2245 +3 86 1987 1985 +3 148 485 1902 +3 497 850 851 +3 495 488 851 +3 2648 2646 2647 +3 1903 1904 1901 +3 1904 1905 433 +3 793 1561 794 +3 849 1905 1904 +3 849 151 1905 +3 849 852 151 +3 1137 187 445 +3 883 894 893 +3 893 894 771 +3 894 1906 771 +3 769 895 1375 +3 894 895 1906 +3 1375 895 894 +3 1178 768 1908 +3 1908 768 1907 +3 1249 1247 1861 +3 1909 772 1178 +3 1488 2720 1477 +3 191 2716 461 +3 1929 650 1928 +3 1933 650 1929 +3 1394 1384 645 +3 2424 763 591 +3 2341 1708 2340 +3 649 630 1914 +3 630 649 1918 +3 758 1925 1928 +3 671 666 667 +3 2260 474 2191 +3 649 891 1921 +3 1924 1923 648 +3 630 1920 1917 +3 1921 1919 649 +3 474 2190 2191 +3 2262 1318 1696 +3 764 884 885 +3 884 881 882 +3 885 884 882 +3 762 1917 1920 +3 934 2018 2017 +3 1026 2577 2576 +3 1916 1917 1922 +3 1917 762 1922 +3 630 1917 1916 +3 814 815 409 +3 1188 1187 696 +3 1923 1922 762 +3 2019 116 2018 +3 1700 2622 1419 +3 1923 1924 758 +3 1913 1934 1912 +3 1916 1927 1930 +3 1927 1928 1930 +3 1931 1930 650 +3 1930 1928 650 +3 1390 1933 1391 +3 1916 1930 1931 +3 1915 1916 1931 +3 1407 1400 1408 +3 2528 2527 1400 +3 1933 1929 1391 +3 595 665 1071 +3 1931 1934 1915 +3 1932 1933 629 +3 1932 629 1912 +3 1913 1912 646 +3 112 45 1935 +3 1932 650 1933 +3 2621 1418 2620 +3 1913 1915 1934 +3 1936 13 1937 +3 1937 13 1938 +3 1967 2491 1443 +3 1473 1967 1443 +3 108 1941 1940 +3 1942 293 1941 +3 108 1942 1941 +3 1940 1939 108 +3 2247 2246 1985 +3 2278 1064 2503 +3 1527 983 982 +3 1944 1943 702 +3 1944 1945 1943 +3 2670 701 1948 +3 2503 2276 2278 +3 1335 289 959 +3 959 289 960 +3 2533 139 2532 +3 2222 2761 2225 +3 1625 2325 2323 +3 703 1097 1947 +3 1946 1947 1948 +3 2576 2577 1122 +3 1062 2511 1128 +3 1944 1946 1945 +3 1946 704 1945 +3 1172 2363 2546 +3 635 678 640 +3 701 704 1946 +3 449 2326 446 +3 1955 1953 1952 +3 1164 959 960 +3 1120 1949 1121 +3 1949 961 1121 +3 1117 1952 1120 +3 1115 1114 1958 +3 292 1956 1117 +3 2186 1004 2223 +3 2197 1005 2193 +3 1012 2199 1011 +3 1113 1964 1956 +3 2221 2188 2220 +3 1111 290 1954 +3 1953 1954 290 +3 2144 359 358 +3 359 2652 358 +3 1114 350 1959 +3 1111 1954 1112 +3 1962 1965 1960 +3 1965 1962 1959 +3 1956 292 1957 +3 2226 2227 2678 +3 1964 1113 1962 +3 1964 1962 1963 +3 1956 1964 1955 +3 1965 1959 350 +3 42 15 8 +3 1959 1113 1958 +3 1112 1960 1961 +3 2561 15 2558 +3 1960 350 1961 +3 166 2558 2557 +3 2561 2558 166 +3 8 15 2561 +3 1963 1118 1964 +3 388 1451 1452 +3 414 1446 1966 +3 1445 1966 1446 +3 1652 1276 1968 +3 1653 1652 1968 +3 1201 1199 2353 +3 1201 1202 1199 +3 1969 1276 1275 +3 373 1653 1969 +3 1653 373 1286 +3 1653 1968 1969 +3 1968 1276 1969 +3 2557 2554 2553 +3 1286 373 1274 +3 348 63 2556 +3 1971 348 2556 +3 31 200 2343 +3 2457 31 2343 +3 2596 1595 2597 +3 62 1832 43 +3 681 2150 639 +3 1977 940 1975 +3 1977 1974 1596 +3 1977 1975 1974 +3 1596 43 1833 +3 2640 2641 18 +3 1596 1974 1973 +3 1975 1595 1974 +3 1596 1973 43 +3 1980 941 1979 +3 1982 1981 942 +3 1981 1982 1980 +3 1978 940 1977 +3 1597 1978 1977 +3 1833 1597 1596 +3 1830 1597 1833 +3 2247 85 2246 +3 942 2246 1982 +3 2245 2246 942 +3 2648 195 995 +3 18 1885 2640 +3 1885 18 2645 +3 169 1986 1984 +3 1983 169 1984 +3 420 2251 2252 +3 685 680 605 +3 1991 904 322 +3 1194 1193 322 +3 1193 1989 322 +3 80 81 1981 +3 80 1981 27 +3 1981 1980 27 +3 1982 941 1980 +3 2247 128 965 +3 85 941 1982 +3 1988 65 258 +3 2697 2698 301 +3 897 2698 2697 +3 1988 258 128 +3 1981 1983 942 +3 1981 81 1983 +3 965 85 2247 +3 1984 942 1983 +3 2233 795 2254 +3 169 81 168 +3 81 169 1983 +3 265 1502 86 +3 1502 1987 86 +3 169 170 1986 +3 1988 128 1987 +3 197 1728 1684 +3 1750 65 1988 +3 267 1750 1988 +3 87 1750 267 +3 267 1988 1987 +3 796 2250 2249 +3 799 2249 2250 +3 1992 1379 886 +3 588 1329 2273 +3 2270 587 1326 +3 1573 2608 2609 +3 1328 1327 1325 +3 1992 892 1379 +3 2611 2615 1994 +3 887 403 1993 +3 892 1992 403 +3 1992 1993 403 +3 2298 2619 290 +3 2619 2298 1951 +3 218 1997 1995 +3 1106 2453 5 +3 1996 1997 924 +3 1766 1767 927 +3 2454 1215 1692 +3 2454 1216 1225 +3 1215 2454 1225 +3 524 2454 1692 +3 2454 524 1216 +3 963 251 252 +3 964 907 963 +3 348 1998 2000 +3 247 348 2001 +3 63 348 247 +3 348 2000 2001 +3 2001 2000 41 +3 2001 2003 247 +3 1619 92 547 +3 2006 517 1586 +3 2005 2004 60 +3 247 2004 2005 +3 2004 248 60 +3 122 70 119 +3 248 2004 2003 +3 517 2006 1706 +3 2772 1585 2773 +3 2033 2017 935 +3 1367 1366 888 +3 2528 1416 2527 +3 2019 2018 934 +3 243 820 821 +3 1807 1806 633 +3 2345 2346 1202 +3 2631 2628 1638 +3 2016 2033 2034 +3 877 2500 2499 +3 923 2453 1106 +3 1040 2508 2506 +3 196 2027 2048 +3 1885 2027 196 +3 2048 198 2049 +3 2026 115 196 +3 35 2027 1885 +3 2044 2045 2026 +3 2045 2044 2025 +3 199 2047 201 +3 2016 934 2017 +3 2034 2033 2015 +3 2043 2038 2025 +3 2043 2039 2038 +3 96 987 986 +3 96 992 988 +3 1081 662 606 +3 933 2019 934 +3 2021 932 937 +3 2020 116 2030 +3 116 2019 2030 +3 2041 198 2028 +3 1679 2343 201 +3 1679 2457 2343 +3 2040 2039 2041 +3 61 993 994 +3 2042 2036 32 +3 202 1685 2455 +3 1699 2278 1063 +3 1998 1971 1972 +3 2044 2049 2043 +3 2041 2039 198 +3 1042 2500 1041 +3 2048 2026 196 +3 2029 2022 2020 +3 2022 2029 933 +3 2029 2019 933 +3 1503 1504 686 +3 2279 1503 686 +3 933 928 2022 +3 2014 2031 935 +3 2031 2033 935 +3 2035 2016 2034 +3 2035 988 2016 +3 2513 2507 1031 +3 2161 2160 2164 +3 2013 936 2014 +3 988 992 2016 +3 2511 877 1128 +3 1110 2296 875 +3 2512 1110 875 +3 2040 2042 32 +3 2015 2032 2024 +3 2032 2037 2024 +3 2032 936 2037 +3 2502 1944 702 +3 1946 1944 2530 +3 2451 920 2450 +3 994 993 2036 +3 2015 2040 32 +3 32 2034 2015 +3 2040 2015 2024 +3 993 61 1001 +3 2037 936 2025 +3 2046 115 2045 +3 198 2039 2043 +3 868 1110 2512 +3 2042 2040 2041 +3 936 2045 2025 +3 1039 1063 1062 +3 1039 1062 870 +3 1669 1063 1039 +3 1601 1157 2409 +3 1045 1671 2166 +3 4 201 2047 +3 937 2047 2046 +3 2046 2047 115 +3 287 2758 2759 +3 878 2161 2164 +3 199 115 2047 +3 932 2047 937 +3 4 2047 932 +3 2309 2313 1500 +3 428 2313 2309 +3 2310 1500 2313 +3 26 1940 2058 +3 1940 294 2058 +3 2308 23 2311 +3 791 1531 1535 +3 113 2060 298 +3 2060 26 2059 +3 26 2061 1940 +3 1940 2061 1939 +3 2061 112 1939 +3 2062 112 2061 +3 427 112 2062 +3 112 427 45 +3 113 1500 2310 +3 2310 2062 113 +3 307 152 320 +3 2069 22 299 +3 299 295 2065 +3 2068 2069 2067 +3 2069 299 2067 +3 2068 2067 110 +3 343 215 344 +3 975 91 977 +3 2085 91 975 +3 205 204 2071 +3 479 157 20 +3 59 208 214 +3 208 59 2071 +3 22 1501 298 +3 1501 113 298 +3 152 303 2070 +3 2082 210 2078 +3 210 2082 2086 +3 2083 2079 919 +3 203 2074 1027 +3 204 2074 2073 +3 2075 2074 204 +3 1027 2074 2075 +3 2446 2445 1162 +3 2071 59 205 +3 2075 204 205 +3 7 2075 205 +3 24 1719 1721 +3 1422 1421 2449 +3 1421 1422 1399 +3 2080 2079 210 +3 214 2081 38 +3 549 211 548 +3 2081 209 38 +3 220 922 2080 +3 2078 2079 2083 +3 208 2077 2081 +3 2076 2077 208 +3 220 2091 970 +3 2078 2083 209 +3 2077 2078 209 +3 203 976 977 +3 157 156 20 +3 156 157 2100 +3 204 2072 2071 +3 2085 2082 91 +3 1317 1280 1156 +3 210 2086 2087 +3 2087 2088 2080 +3 2088 2087 968 +3 2087 2080 210 +3 549 967 2089 +3 968 549 2089 +3 968 2089 2088 +3 969 2090 967 +3 969 2091 2090 +3 2091 220 2090 +3 970 2093 971 +3 2072 208 2071 +3 206 59 207 +3 2095 92 981 +3 2097 221 979 +3 967 92 2095 +3 969 2094 2092 +3 11 58 206 +3 2095 981 221 +3 980 981 1619 +3 221 2094 2095 +3 969 2095 2094 +3 2686 2294 865 +3 2085 2099 2082 +3 2086 2099 974 +3 2082 2099 2086 +3 1317 225 2105 +3 1293 2103 1294 +3 2102 158 51 +3 2103 1293 1280 +3 2104 2103 1280 +3 1280 1317 2104 +3 1317 2105 2104 +3 1296 231 1295 +3 1297 2109 1313 +3 2108 229 2109 +3 1296 2108 2109 +3 2113 2112 1299 +3 2124 2125 224 +3 2110 1298 2106 +3 2105 2110 2106 +3 2108 2113 229 +3 1298 2112 2113 +3 2111 2112 1298 +3 1297 1296 2109 +3 231 1296 1297 +3 2106 2104 2105 +3 2105 1301 2110 +3 2123 2115 2116 +3 232 1312 285 +3 1298 2113 2108 +3 2124 2118 1304 +3 2118 2124 1306 +3 84 51 168 +3 227 2117 2118 +3 1301 2115 2114 +3 226 1073 2121 +3 1303 2119 2117 +3 2119 2118 2117 +3 2119 1304 2118 +3 1156 1280 1660 +3 1303 226 2119 +3 1303 1763 226 +3 2105 225 2116 +3 2105 2116 1301 +3 225 1613 2116 +3 1073 289 2121 +3 1336 289 1335 +3 2117 2115 1303 +3 297 2120 2121 +3 297 2122 2120 +3 2126 1715 171 +3 224 1306 2124 +3 82 169 168 +3 2125 1715 2126 +3 1714 171 1715 +3 171 224 2126 +3 2682 489 2681 +3 828 2682 826 +3 395 828 826 +3 826 2682 2127 +3 487 845 833 +3 1467 2148 481 +3 2148 2147 481 +3 2143 2139 362 +3 2135 2134 142 +3 787 2653 2656 +3 2502 2530 1944 +3 2502 703 2530 +3 302 359 896 +3 2700 302 896 +3 2537 1173 2362 +3 1891 2132 354 +3 1891 356 2132 +3 352 2134 2135 +3 354 2132 2133 +3 1508 1507 179 +3 2650 2651 385 +3 2133 2134 352 +3 2524 1411 2523 +3 2320 691 2315 +3 357 2129 2138 +3 1499 1498 142 +3 147 2306 429 +3 353 352 2135 +3 357 2138 2137 +3 2129 114 2138 +3 898 145 363 +3 2147 2130 2140 +3 155 2149 1720 +3 2149 268 1720 +3 300 2691 2693 +3 2149 155 1715 +3 2142 2133 144 +3 385 44 384 +3 2688 904 2697 +3 411 621 955 +3 2143 363 2139 +3 363 145 2139 +3 114 801 362 +3 242 825 2768 +3 2143 2304 146 +3 626 606 1807 +3 2689 905 2688 +3 301 2689 2688 +3 1528 1529 792 +3 2140 481 2147 +3 1715 269 2149 +3 268 269 97 +3 1132 2150 2151 +3 2150 681 2151 +3 659 1132 2151 +3 2152 1504 684 +3 2153 2152 684 +3 691 2317 2316 +3 2151 681 682 +3 2152 2151 682 +3 2283 2285 3 +3 1161 2285 2283 +3 714 2284 3 +3 659 2152 2153 +3 659 2151 2152 +3 1621 1623 1624 +3 1019 716 1131 +3 985 989 2154 +3 96 2154 989 +3 182 985 986 +3 2157 2156 876 +3 1060 870 1129 +3 293 109 2063 +3 1058 870 2155 +3 867 2685 2686 +3 2215 2216 2217 +3 287 1011 2194 +3 1059 2156 2155 +3 878 1671 2162 +3 2158 876 1049 +3 2166 1671 878 +3 872 1047 1048 +3 2160 1057 2159 +3 1110 865 2296 +3 2162 870 1058 +3 2169 2171 879 +3 2168 1048 1047 +3 2175 2169 879 +3 2175 2170 2169 +3 2176 1676 1677 +3 2170 1046 2169 +3 2279 2293 2282 +3 2293 1161 2282 +3 1044 2173 1675 +3 2173 1050 1675 +3 1201 2345 1202 +3 1204 1203 2351 +3 1201 2344 2345 +3 1318 2262 1803 +3 1678 1676 2178 +3 1676 1678 869 +3 2179 286 959 +3 286 1335 959 +3 2181 958 2180 +3 2180 958 2179 +3 959 2180 2179 +3 2222 1004 2760 +3 1898 19 1897 +3 2220 2188 2228 +3 2759 1961 287 +3 2266 2267 508 +3 2181 2182 958 +3 958 2183 471 +3 958 2182 2183 +3 2182 474 2183 +3 2698 898 301 +3 1420 2449 1400 +3 2449 2528 1400 +3 894 883 770 +3 2186 1005 1003 +3 2185 2186 1003 +3 2202 1009 2205 +3 966 1604 1605 +3 1008 1005 2197 +3 2188 1004 2187 +3 2184 2190 2182 +3 711 1094 2562 +3 711 1095 1094 +3 2181 2180 288 +3 2187 2185 288 +3 2195 2220 2229 +3 2198 1008 2197 +3 2230 792 1525 +3 2407 2406 2198 +3 1112 2759 1007 +3 2579 831 2679 +3 830 2579 2679 +3 1009 1013 2205 +3 2208 2207 2206 +3 2211 2213 2212 +3 2213 1114 2208 +3 2550 2560 2549 +3 2200 2212 2204 +3 2200 2211 2212 +3 2548 2549 245 +3 1316 2414 1604 +3 2412 1153 1308 +3 2549 166 245 +3 291 1119 2207 +3 2416 2427 1190 +3 1013 1009 2207 +3 291 2208 1114 +3 2208 291 2207 +3 1655 1159 1292 +3 2002 2003 2001 +3 1654 1159 1655 +3 2210 2209 2199 +3 1012 2210 2199 +3 1010 2204 2212 +3 2213 1010 2212 +3 8 100 102 +3 1012 1961 2211 +3 2298 2297 1951 +3 2298 1950 2297 +3 2215 2217 1950 +3 843 2577 1026 +3 296 270 2401 +3 1111 2195 2214 +3 2194 2193 2227 +3 1111 2214 2215 +3 2183 474 2260 +3 353 2135 75 +3 2757 2758 2189 +3 1111 1112 1007 +3 2195 1111 1007 +3 2214 2216 2215 +3 1336 1335 270 +3 2218 2217 1949 +3 1830 1832 1829 +3 2641 1886 199 +3 2232 2231 1558 +3 2222 2225 2223 +3 97 269 271 +3 18 2641 2642 +3 1335 286 2404 +3 961 2228 2188 +3 1520 799 1522 +3 2583 1179 774 +3 2232 2233 150 +3 795 2582 2234 +3 2581 2582 795 +3 2253 2254 2234 +3 1465 432 1466 +3 1465 1466 1464 +3 2243 806 407 +3 2583 1174 1179 +3 2679 2680 830 +3 148 1902 433 +3 2237 795 2233 +3 2233 2254 150 +3 2234 2235 796 +3 2249 2234 796 +3 1175 2583 774 +3 393 1145 589 +3 2467 2469 596 +3 2579 2581 2580 +3 2579 2236 2581 +3 1473 414 1967 +3 148 433 1465 +3 2581 795 2580 +3 392 2239 487 +3 828 829 489 +3 2239 488 495 +3 487 2239 495 +3 846 487 495 +3 2241 2242 808 +3 817 808 2242 +3 2243 407 2242 +3 2240 807 2241 +3 2241 408 2240 +3 2242 2244 817 +3 807 2240 1145 +3 797 2252 2235 +3 266 87 267 +3 2245 1984 86 +3 1524 799 2250 +3 2648 995 35 +3 194 2648 35 +3 2245 1985 2246 +3 1520 2248 799 +3 118 119 20 +3 2254 2253 150 +3 150 2231 2232 +3 1821 2467 596 +3 2579 392 831 +3 2576 1943 2578 +3 2237 2233 2232 +3 797 420 2252 +3 2249 2253 2234 +3 2255 1474 1444 +3 492 1474 2255 +3 2220 2228 2256 +3 2229 2220 2256 +3 2219 2256 2228 +3 2229 2256 2219 +3 2155 2156 1058 +3 2157 1058 2156 +3 272 6 1168 +3 285 98 2403 +3 2402 2404 2403 +3 2404 2402 270 +3 2198 2406 2405 +3 1006 2198 2405 +3 2535 1526 1522 +3 284 2402 2403 +3 2163 1058 2157 +3 1272 2263 2264 +3 2263 1287 2264 +3 572 1583 1781 +3 2340 2339 1584 +3 2340 2338 2339 +3 1708 2338 2340 +3 1584 2266 1705 +3 2266 508 1705 +3 533 2735 535 +3 2735 1887 535 +3 1993 1992 886 +3 2270 1326 2272 +3 405 2299 782 +3 704 2563 842 +3 2273 1328 1325 +3 1329 1328 2273 +3 761 1328 1329 +3 1063 2276 1062 +3 2507 1040 2506 +3 2507 2513 1040 +3 2500 877 2501 +3 2277 877 2511 +3 2510 2277 2511 +3 2503 1064 2504 +3 2365 718 2286 +3 2278 1600 1064 +3 2278 1699 1600 +3 718 2362 2286 +3 2366 2014 935 +3 2322 715 2323 +3 2284 2288 2287 +3 684 2290 2153 +3 1403 2328 2327 +3 2290 2288 2284 +3 382 361 1165 +3 1504 2289 684 +3 719 1160 686 +3 684 2288 2290 +3 1504 1503 2289 +3 1154 1606 2687 +3 1606 1607 2687 +3 2319 1621 1624 +3 2315 1620 2320 +3 2280 1160 2292 +3 2279 1160 2280 +3 686 1160 2279 +3 2279 2280 2293 +3 2011 579 2010 +3 2012 2011 2010 +3 2671 1640 2674 +3 1725 698 2012 +3 698 2011 2012 +3 698 1097 1096 +3 500 514 825 +3 2291 2292 2281 +3 2292 1160 2281 +3 2430 2431 2293 +3 2431 1161 2293 +3 2300 1327 782 +3 2300 590 1327 +3 2411 2410 1290 +3 2411 2409 2410 +3 1290 2413 1159 +3 1603 1156 2301 +3 1521 1525 791 +3 801 2303 2304 +3 801 429 2303 +3 146 2304 2303 +3 2304 2143 362 +3 801 2304 362 +3 2434 496 2436 +3 2062 2310 427 +3 2314 2310 2313 +3 2314 427 2310 +3 1500 1501 2302 +3 2311 23 2312 +3 427 2311 2312 +3 429 2306 2305 +3 428 2307 2308 +3 428 2314 2313 +3 2311 427 2314 +3 1496 75 1495 +3 45 427 2312 +3 2446 2447 45 +3 1027 2446 1162 +3 2449 1420 1422 +3 1420 1401 1422 +3 2529 1410 1428 +3 870 1062 1128 +3 2317 716 1019 +3 1624 716 2317 +3 2322 1622 1621 +3 2318 2153 2290 +3 2319 1624 2317 +3 1410 2523 2520 +3 1578 2613 2603 +3 513 1564 1537 +3 1173 2363 2362 +3 386 1457 2326 +3 2002 2001 41 +3 2763 2002 41 +3 2366 2013 2014 +3 2541 2542 717 +3 2544 2541 717 +3 2434 1792 496 +3 850 1792 2434 +3 2303 429 2433 +3 626 633 2655 +3 2324 2325 723 +3 1625 1627 2325 +3 2327 1407 1408 +3 386 449 1345 +3 386 2326 449 +3 2329 1406 2330 +3 2445 2312 1162 +3 2312 2445 45 +3 136 382 379 +3 136 381 382 +3 1836 2494 2495 +3 2496 1836 2495 +3 1226 946 2334 +3 2496 2495 1239 +3 136 376 381 +3 572 2336 1708 +3 2335 947 49 +3 506 1592 514 +3 514 500 506 +3 2195 2196 2220 +3 2344 1200 2345 +3 572 1800 2336 +3 287 2194 2758 +3 531 2729 257 +3 2750 56 2747 +3 2337 2338 1708 +3 2337 2265 2338 +3 2725 2728 538 +3 447 446 187 +3 1667 862 222 +3 156 2342 105 +3 51 84 104 +3 2607 2605 1572 +3 2342 104 105 +3 2462 2463 1100 +3 1971 43 1973 +3 2641 200 2642 +3 2752 939 2749 +3 1795 2746 2745 +3 2745 2744 1795 +3 2344 1224 1200 +3 2344 2352 1224 +3 1209 2347 1200 +3 2347 2346 1200 +3 615 400 1210 +3 2347 1209 2351 +3 2745 2746 939 +3 1778 2745 939 +3 2545 1625 1626 +3 2352 1201 2353 +3 617 615 2359 +3 617 419 615 +3 2356 2355 2354 +3 426 2355 2356 +3 2354 2353 1199 +3 777 779 2488 +3 779 777 776 +3 426 617 2355 +3 1197 426 2356 +3 426 1197 1198 +3 2355 617 2359 +3 2359 2358 614 +3 2357 614 2358 +3 2355 2359 614 +3 2354 2355 614 +3 718 2364 2536 +3 2537 718 2536 +3 2360 2539 2538 +3 2360 719 2539 +3 2360 2538 2537 +3 2536 2360 2537 +3 718 2537 2362 +3 717 2545 2544 +3 719 2360 2361 +3 719 2361 1160 +3 2364 2281 1160 +3 2361 2364 1160 +3 1313 2369 372 +3 2109 229 1313 +3 229 2369 1313 +3 1300 2369 229 +3 315 316 236 +3 2370 230 2371 +3 2367 1475 2373 +3 312 313 2372 +3 1284 2367 2373 +3 315 233 316 +3 2381 2373 1476 +3 2382 1285 2383 +3 2374 2375 1380 +3 1284 2375 2374 +3 2378 1802 367 +3 2378 1271 1802 +3 2381 2380 1284 +3 1284 2373 2381 +3 1803 2376 1318 +3 2379 2372 230 +3 2371 230 2372 +3 2375 1284 2380 +3 310 1267 374 +3 2392 310 374 +3 2389 468 469 +3 468 2389 1898 +3 2378 2377 1271 +3 2380 368 2376 +3 1479 2388 2387 +3 2380 2382 368 +3 2381 2382 2380 +3 1283 2385 2386 +3 162 1480 1477 +3 2388 1898 2389 +3 2381 1285 2382 +3 2382 2385 368 +3 2384 2387 2391 +3 19 160 163 +3 163 160 159 +3 1478 1481 1480 +3 2392 2391 2395 +3 310 2392 2393 +3 368 2390 1318 +3 2376 368 1318 +3 2390 368 2385 +3 2385 1283 2390 +3 1480 162 1482 +3 1478 1480 1482 +3 1483 162 1319 +3 1283 2684 53 +3 2397 646 607 +3 646 2397 1913 +3 375 2390 2394 +3 375 1318 2390 +3 371 2391 2392 +3 310 2393 1018 +3 375 2394 1282 +3 2391 161 2395 +3 79 2736 2733 +3 1925 652 1929 +3 1665 890 2426 +3 2399 272 2398 +3 98 284 2403 +3 271 2401 2400 +3 2405 2199 2209 +3 1006 2405 2209 +3 2403 286 285 +3 1011 2406 2407 +3 2406 1011 2199 +3 2406 2199 2405 +3 2193 1011 2408 +3 2408 2197 2193 +3 1153 2411 1290 +3 1308 1605 2414 +3 1308 2414 2412 +3 2412 2414 1316 +3 1605 1604 2414 +3 1009 2202 2203 +3 1316 1601 2409 +3 1604 1601 1316 +3 1157 2410 2409 +3 2411 2412 1316 +3 1157 2415 2410 +3 2415 1157 2301 +3 2427 2396 1190 +3 2426 2421 1665 +3 2421 889 1665 +3 2422 404 759 +3 2424 591 1330 +3 1665 889 1664 +3 761 2420 2424 +3 2420 2418 2424 +3 761 1329 2420 +3 652 2425 759 +3 652 757 2425 +3 1189 1188 2419 +3 2418 2420 404 +3 760 759 2420 +3 759 404 2420 +3 760 588 1083 +3 1329 760 2420 +3 2424 1330 761 +3 1914 2428 649 +3 2423 884 889 +3 2418 763 2424 +3 890 2427 2416 +3 2427 2428 2396 +3 2427 890 2428 +3 2428 647 2396 +3 1914 647 2428 +3 1924 2423 757 +3 890 649 2428 +3 648 2423 1924 +3 862 2429 1813 +3 2291 2430 2292 +3 429 2305 2433 +3 2433 2302 2303 +3 2439 1439 1402 +3 2435 847 495 +3 847 846 495 +3 850 2435 495 +3 2482 2483 845 +3 486 845 2483 +3 2436 1900 847 +3 2434 2436 847 +3 1130 2767 396 +3 2767 2766 396 +3 850 2434 2435 +3 1899 1900 2436 +3 496 1899 2436 +3 391 2483 2482 +3 440 2440 1402 +3 440 2441 2440 +3 440 1414 2441 +3 189 2438 2439 +3 2438 1439 2439 +3 1414 442 2441 +3 1401 2444 2443 +3 1439 2438 2442 +3 2438 2437 2442 +3 2447 7 13 +3 1935 2447 13 +3 2566 342 2567 +3 425 973 2450 +3 996 61 995 +3 921 2451 2450 +3 2453 923 1995 +3 2453 1995 921 +3 2452 2453 921 +3 2452 5 2453 +3 973 5 2452 +3 978 5 973 +3 1103 1122 2577 +3 1972 253 1998 +3 2456 2457 1679 +3 2456 31 2457 +3 2455 2456 1679 +3 250 85 252 +3 907 68 963 +3 1026 2578 1945 +3 843 1074 2460 +3 2542 720 1628 +3 2461 1101 841 +3 1101 1124 841 +3 1100 2463 2464 +3 690 2464 2463 +3 2458 1101 2461 +3 2458 2462 1101 +3 2464 1092 1100 +3 2470 2654 596 +3 2469 2470 596 +3 626 2655 2470 +3 690 2465 2464 +3 2465 1092 2464 +3 1821 689 2467 +3 1222 575 94 +3 2470 1090 1089 +3 799 2248 2249 +3 2361 2536 2364 +3 2471 1637 582 +3 1127 913 2475 +3 952 1183 416 +3 2476 913 2477 +3 1057 2161 2163 +3 952 416 953 +3 2481 952 953 +3 520 502 1218 +3 1637 1640 1639 +3 577 1637 2471 +3 1638 1637 577 +3 1727 2473 582 +3 2477 174 2476 +3 810 409 827 +3 2540 2762 1173 +3 2538 2540 1173 +3 1173 2762 2543 +3 2762 2541 2543 +3 1781 1779 572 +3 952 2481 783 +3 809 409 810 +3 815 2479 409 +3 1360 695 2477 +3 695 1360 781 +3 2478 2476 827 +3 2479 2478 827 +3 2478 2479 783 +3 2767 824 2766 +3 2480 1127 2475 +3 847 391 2482 +3 1900 391 847 +3 2482 846 847 +3 1320 2488 610 +3 2710 418 2709 +3 957 2710 2709 +3 785 2712 2706 +3 2712 2709 2706 +3 2709 2712 2705 +3 610 2488 1198 +3 1813 2429 2489 +3 1035 863 2489 +3 1198 2487 2486 +3 863 1813 2489 +3 1813 863 1812 +3 2488 2487 1198 +3 2488 779 2487 +3 2429 1036 2489 +3 2609 2608 16 +3 7 2490 13 +3 13 2490 1938 +3 2493 1839 1837 +3 1974 1595 2596 +3 252 85 965 +3 2596 1973 1974 +3 2493 1843 1839 +3 2495 2494 1837 +3 1237 1835 1239 +3 948 181 1226 +3 2495 1837 1239 +3 2497 1238 740 +3 2646 2645 9 +3 2497 740 1836 +3 1128 2498 1129 +3 2770 2296 1059 +3 2769 2770 1060 +3 877 2277 2501 +3 2504 1064 2505 +3 868 2512 2509 +3 2499 2500 1042 +3 1105 864 1106 +3 2506 2505 871 +3 2507 871 1037 +3 2506 871 2507 +3 1031 2507 1037 +3 1105 2509 1040 +3 2509 1105 868 +3 2276 1063 2278 +3 2510 2276 2503 +3 2504 2510 2503 +3 2504 2277 2510 +3 875 1042 1041 +3 2276 2510 1062 +3 864 2513 2514 +3 2513 864 1105 +3 864 2514 1030 +3 1775 1893 2516 +3 2738 2739 1208 +3 1778 2753 2754 +3 2518 1893 1784 +3 2518 2516 1893 +3 1793 2518 1784 +3 1793 1783 2518 +3 1783 2516 2518 +3 1167 383 44 +3 1990 302 899 +3 901 302 1990 +3 360 302 901 +3 1409 2522 2521 +3 2521 2522 1404 +3 1989 1990 899 +3 2327 2522 1409 +3 440 1411 2524 +3 1424 1405 2528 +3 2528 1405 1416 +3 1421 1424 2528 +3 2522 1408 2526 +3 2522 2526 1404 +3 2526 1416 1404 +3 2526 2527 1416 +3 2526 1408 2527 +3 1678 2701 869 +3 376 377 349 +3 377 2531 349 +3 165 131 134 +3 377 135 2531 +3 135 2532 2531 +3 2532 349 2531 +3 139 349 2532 +3 73 139 2533 +3 74 349 908 +3 270 1335 2404 +3 2552 2551 245 +3 2360 2536 2361 +3 720 2542 1631 +3 251 254 2763 +3 841 1123 1122 +3 251 2763 41 +3 41 1999 251 +3 1631 2540 2539 +3 2540 2538 2539 +3 963 254 251 +3 2541 2544 2543 +3 2543 2544 2363 +3 2547 1627 717 +3 723 1627 1628 +3 1627 1625 2545 +3 1172 2546 3 +3 719 683 720 +3 2542 2547 717 +3 1892 101 2548 +3 29 100 2550 +3 100 29 102 +3 345 2564 1745 +3 256 2550 101 +3 256 29 2550 +3 60 1892 2551 +3 245 2553 2552 +3 2553 246 2552 +3 245 2551 2548 +3 2551 1892 2548 +3 167 2557 2558 +3 167 2554 2557 +3 67 255 248 +3 2556 63 2555 +3 2554 246 2553 +3 167 62 2555 +3 167 2555 2554 +3 2555 63 2554 +3 255 256 101 +3 67 256 255 +3 2557 2553 245 +3 166 2557 245 +3 2556 62 43 +3 1971 2556 43 +3 1680 31 2456 +3 62 2556 2555 +3 2558 2559 167 +3 2559 2558 15 +3 15 42 2559 +3 2562 1094 712 +3 842 2562 712 +3 2574 2231 150 +3 587 1651 1147 +3 2563 704 581 +3 2565 345 1747 +3 1735 324 1742 +3 2570 2571 1734 +3 2568 2571 88 +3 2571 2568 2572 +3 1735 2564 2573 +3 341 1747 1746 +3 88 2567 2568 +3 343 344 2568 +3 2569 1735 2573 +3 2569 2570 1735 +3 1734 2571 2572 +3 1333 213 1332 +3 432 147 801 +3 1731 1733 325 +3 1333 1734 2572 +3 2572 1334 1333 +3 1334 2572 344 +3 344 2572 2568 +3 432 801 114 +3 432 114 1467 +3 1467 114 2148 +3 2575 509 490 +3 1464 1463 148 +3 2235 2582 2236 +3 1103 2577 2460 +3 243 2682 2681 +3 844 243 2681 +3 2582 2235 2234 +3 2236 797 2235 +3 2237 2580 795 +3 2244 407 818 +3 1942 1937 12 +3 1549 1547 2586 +3 2586 1547 2585 +3 2585 1547 1567 +3 1547 1564 1567 +3 2586 1551 1549 +3 2588 842 712 +3 2590 1436 1135 +3 2590 2591 1441 +3 1472 1441 2591 +3 1472 1442 1441 +3 2593 2592 1440 +3 2590 1135 2591 +3 1701 2592 1135 +3 2591 1135 2592 +3 1437 2590 1441 +3 1472 2591 2592 +3 308 306 307 +3 2595 1434 1435 +3 2492 434 1471 +3 2595 2594 1434 +3 2600 251 1999 +3 2597 1973 2596 +3 2598 1595 1976 +3 251 250 252 +3 2600 250 251 +3 2598 1976 250 +3 1972 2599 253 +3 2599 2598 253 +3 550 548 976 +3 2617 1588 1593 +3 1591 506 2610 +3 2602 2604 1573 +3 974 549 968 +3 1572 2605 1574 +3 2602 1573 2603 +3 2612 2613 2614 +3 2613 1578 2614 +3 79 552 234 +3 852 79 234 +3 2605 515 2606 +3 2609 2603 1573 +3 2609 2610 2603 +3 515 498 2606 +3 2603 2610 503 +3 2616 1593 2608 +3 2612 2611 504 +3 2612 2615 2611 +3 1952 2619 1951 +3 2607 1572 2616 +3 1576 515 1575 +3 1576 1575 2601 +3 2613 2612 504 +3 2612 1577 2615 +3 1577 1994 2615 +3 1577 1579 1994 +3 1769 1579 1577 +3 1573 2607 2618 +3 2619 1953 290 +3 2616 2617 1593 +3 1572 2617 2616 +3 2617 1572 1588 +3 2620 1413 10 +3 2621 2620 10 +3 1429 2621 10 +3 10 2529 1429 +3 2529 1428 1429 +3 441 1413 2623 +3 585 2626 2625 +3 1642 1641 2624 +3 1648 1642 2624 +3 585 2625 2627 +3 608 1644 1643 +3 2625 1649 1648 +3 708 709 581 +3 398 2634 2631 +3 2635 2631 1638 +3 2629 2627 709 +3 2630 2628 2629 +3 2627 2624 709 +3 2627 2625 2624 +3 1648 2624 2625 +3 2629 708 2630 +3 2635 1638 577 +3 2628 2630 580 +3 398 803 802 +3 2633 2634 585 +3 2633 585 2632 +3 398 2631 2635 +3 2632 2629 2628 +3 2633 2632 2628 +3 398 802 2634 +3 1151 399 1150 +3 1195 1150 612 +3 2636 94 804 +3 845 486 2676 +3 2639 1473 1443 +3 215 1723 1722 +3 2643 2644 2642 +3 2145 2650 385 +3 200 31 2643 +3 200 2643 2642 +3 2645 18 2644 +3 1886 2649 196 +3 2647 2646 9 +3 1684 1728 2647 +3 1728 195 2647 +3 2645 194 1885 +3 1684 2647 9 +3 995 994 35 +3 2646 2648 194 +3 2645 2646 194 +3 1728 1729 195 +3 2649 1885 196 +3 2136 2137 358 +3 2651 2652 385 +3 144 2136 2651 +3 359 44 2652 +3 360 44 359 +3 604 787 635 +3 2655 2654 2470 +3 2655 634 2654 +3 2655 633 634 +3 1526 1528 1522 +3 785 2703 2704 +3 785 2659 2703 +3 559 2657 1505 +3 1506 2657 559 +3 2707 2706 418 +3 1433 467 2715 +3 2706 2661 785 +3 466 2660 561 +3 561 2660 562 +3 558 784 1506 +3 1835 1237 2663 +3 2663 1237 725 +3 725 1238 2663 +3 1835 1238 2497 +3 1835 2663 1238 +3 2664 687 1822 +3 687 1823 1822 +3 692 1819 1818 +3 692 1392 2666 +3 1389 598 2666 +3 2630 2672 580 +3 1191 607 1192 +3 653 2665 759 +3 512 1592 1566 +3 797 829 798 +3 1592 512 514 +3 397 803 804 +3 2012 2010 699 +3 2668 578 2673 +3 1640 2671 2667 +3 2012 699 2673 +3 578 1725 2673 +3 2760 2756 2222 +3 1638 2628 2675 +3 2675 2628 580 +3 580 2674 2675 +3 398 2636 804 +3 398 2635 2636 +3 1637 2675 2674 +3 2674 1640 1637 +3 1645 583 579 +3 1120 2677 1117 +3 2756 2760 2221 +3 1957 1115 1958 +3 1117 2677 960 +3 2682 243 2127 +3 832 2680 2679 +3 2392 374 2683 +3 371 2392 2683 +3 53 2683 1269 +3 367 1269 1268 +3 1269 374 1268 +3 374 1269 2683 +3 867 978 2685 +3 1054 2686 866 +3 1054 2294 2686 +3 905 904 2688 +3 905 322 904 +3 146 2696 363 +3 2691 111 905 +3 2690 2693 2694 +3 896 145 2699 +3 2690 300 2693 +3 2690 22 300 +3 363 2695 898 +3 2690 2696 22 +3 2692 304 111 +3 2699 898 2698 +3 2698 897 2699 +3 1501 22 2696 +3 359 145 896 +3 2700 2699 897 +3 899 2700 897 +3 302 2700 899 +3 2702 1774 1773 +3 1785 2702 1773 +3 2702 1785 519 +3 435 444 436 +3 2713 1440 437 +3 521 1771 1770 +3 527 1355 1354 +3 2715 467 2716 +3 2710 839 2711 +3 1800 2751 2336 +3 957 2705 411 +3 2707 2661 2706 +3 417 957 955 +3 2705 2712 785 +3 2708 415 1435 +3 415 838 1435 +3 1795 1780 2746 +3 2711 2708 418 +3 2710 2711 418 +3 492 1449 1661 +3 839 415 2711 +3 191 1435 2715 +3 2715 1435 2714 +3 1431 2719 1430 +3 1430 2719 1419 +3 1431 2718 2719 +3 2718 1431 1432 +3 2718 437 2719 +3 1701 1419 2719 +3 753 755 309 +3 14 306 308 +3 1017 2395 161 +3 308 307 153 +3 539 2729 2730 +3 2732 2731 537 +3 239 2731 2732 +3 2735 185 1887 +3 532 185 2735 +3 2733 522 239 +3 2733 239 2732 +3 97 2742 274 +3 2742 97 1168 +3 2741 573 1206 +3 1207 2737 2741 +3 939 2748 2749 +3 2753 1778 939 +3 2749 2747 1710 +3 1782 571 2755 +3 1779 2755 2754 +3 2541 2762 2540 +3 2196 2758 2757 +3 1007 2758 2196 +3 2758 1007 2759 +3 2759 1112 1961 +3 2225 2761 2757 +3 2756 2757 2761 +3 387 2764 1470 +3 2766 824 826 +3 825 824 2768 +3 1703 1585 2771 +3 1042 875 2769 + diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/sphere_1k.xyz b/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/sphere_1k.xyz new file mode 100644 index 00000000000..a1920b8715a --- /dev/null +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/sphere_1k.xyz @@ -0,0 +1,1050 @@ +0.748052 0.293582 -0.586328 0.746260 0.285982 -0.601091 +0.832701 -0.472254 -0.261020 0.831240 -0.487561 -0.267066 +-0.173357 0.316477 0.924039 -0.150178 0.307026 0.939777 +-0.468581 0.882306 -0.004226 -0.498209 0.866785 -0.021726 +0.484252 -0.720995 -0.493822 0.487524 -0.709459 -0.508910 +-0.452730 -0.093155 -0.879732 -0.434008 -0.106864 -0.894549 +-0.371034 0.902823 -0.178977 -0.383887 0.902117 -0.197019 +0.183252 0.864272 0.435263 0.182196 0.873873 0.450722 +0.693880 0.636597 -0.315980 0.683869 0.619657 -0.385161 +0.351572 -0.891785 0.257646 0.378041 -0.885904 0.268810 +-0.110856 -0.887300 -0.440125 -0.131974 -0.890397 -0.435634 +0.730884 -0.086189 0.665670 0.722093 -0.107381 0.683411 +-0.538180 -0.616870 0.562904 -0.537570 -0.642418 0.546185 +-0.173869 0.420246 -0.879298 -0.158952 0.419640 -0.893665 +0.125559 -0.235558 0.951804 0.187779 -0.220976 0.957031 +0.613435 0.598196 -0.495148 0.607112 0.621329 -0.495344 +-0.310011 -0.894333 0.289143 -0.328622 -0.903093 0.276462 +-0.535261 0.831053 0.089400 -0.574469 0.812120 0.102212 +-0.154098 0.751957 -0.629241 -0.142209 0.771787 -0.619775 +0.756763 0.642667 0.063766 0.742436 0.662766 0.097621 +-0.918407 -0.299361 0.229935 -0.905633 -0.351780 0.236812 +0.183206 0.458097 0.859909 0.193370 0.446458 0.873661 +-0.624272 0.725728 -0.271082 -0.639645 0.723214 -0.260415 +-0.139710 0.889359 -0.410575 -0.121492 0.890047 -0.439381 +0.586611 0.790761 -0.102887 0.572578 0.815069 -0.088413 +0.766574 -0.206341 0.601215 0.745101 -0.239645 0.622410 +0.642088 -0.551254 -0.527230 0.636238 -0.522054 -0.568033 +0.395635 0.901093 -0.108326 0.426639 0.895620 -0.125871 +-0.098559 0.137904 0.972393 -0.117189 0.124775 0.985240 +0.456499 -0.504672 0.721109 0.481083 -0.536500 0.693345 +-0.834278 0.533635 -0.072964 -0.841761 0.537948 -0.045282 +0.256261 0.955595 -0.124435 0.263182 0.953329 -0.147986 +0.425691 0.312085 0.838013 0.428204 0.318194 0.845810 +0.189883 -0.443123 -0.866059 0.187856 -0.446250 -0.874969 +0.467407 0.786758 0.387506 0.443928 0.784099 0.433724 +0.592655 0.668363 0.431990 0.612709 0.667188 0.423613 +-0.439587 0.142649 0.884326 -0.426553 0.117086 0.896852 +-0.400619 -0.527633 0.740750 -0.404981 -0.505651 0.761779 +-0.020303 0.918140 0.366576 -0.021868 0.935209 0.353420 +0.953269 0.147773 0.226913 0.968331 0.131267 0.212376 +-0.457837 0.655958 -0.587824 -0.475261 0.667082 -0.573698 +-0.816809 0.539999 0.147183 -0.833024 0.530733 0.156186 +-0.968194 0.036151 -0.219085 -0.983045 0.006639 -0.183243 +0.732867 -0.327724 0.580941 0.739101 -0.329644 0.587422 +-0.832584 -0.191605 0.512407 -0.843347 -0.186140 0.504101 +-0.076057 -0.691483 -0.712497 -0.099298 -0.684461 -0.722255 +0.078457 -0.949775 0.250465 0.070561 -0.963791 0.257152 +0.381237 0.767638 0.487463 0.371468 0.772146 0.515560 +-0.347249 -0.745400 -0.572054 -0.330059 -0.739774 -0.586341 +-0.497964 0.110103 -0.863467 -0.465590 0.150178 -0.872165 +0.489013 0.093028 0.860060 0.514407 0.114069 0.849926 +-0.690048 0.485818 -0.523464 -0.698891 0.499432 -0.511976 +0.986750 -0.048901 0.058781 0.997239 -0.044184 0.059688 +0.965185 -0.009981 -0.275580 0.951784 -0.011104 -0.306569 +0.181883 0.570371 0.790234 0.238095 0.593464 0.768838 +0.350416 -0.937921 -0.007279 0.365031 -0.930854 0.016227 +-0.366849 0.174527 -0.907564 -0.372111 0.194338 -0.907615 +-0.614297 -0.782161 -0.050026 -0.622636 -0.780789 -0.051901 +-0.541907 0.521936 0.646070 -0.524769 0.506795 0.683942 +-0.604428 0.034464 0.786571 -0.622697 0.018840 0.782236 +0.316201 -0.011032 0.945992 0.273864 -0.041505 0.960872 +-0.063792 -0.063818 -0.986343 -0.052852 -0.070457 -0.996114 +-0.236714 0.901089 -0.335733 -0.216568 0.907625 -0.359604 +-0.390487 -0.895922 0.170682 -0.397059 -0.891373 0.218630 +-0.244774 0.217231 -0.939694 -0.251643 0.257630 -0.932900 +0.415798 0.614034 0.660365 0.404881 0.621908 0.670300 +0.936873 0.314072 -0.056981 0.955882 0.288871 -0.053324 +0.828015 -0.375303 0.389740 0.851215 -0.349457 0.391550 +0.848444 -0.176627 -0.479183 0.870400 -0.157169 -0.466585 +0.210727 -0.269036 0.924310 0.219696 -0.282522 0.933764 +-0.651564 -0.542071 0.513750 -0.655540 -0.531255 0.536690 +0.262708 0.675581 -0.683440 0.266077 0.693394 -0.669633 +0.876917 0.194366 -0.432052 0.878036 0.206786 -0.431617 +0.590085 -0.140791 0.784464 0.624445 -0.140437 0.768339 +-0.966821 -0.074797 -0.211010 -0.975551 -0.105703 -0.192684 +-0.363808 -0.898417 -0.218693 -0.350029 -0.910035 -0.222074 +-0.140519 0.251436 -0.950405 -0.111961 0.286079 -0.951642 +-0.478797 -0.151840 0.849405 -0.481115 -0.142174 0.865052 +0.532339 0.801587 0.261641 0.566202 0.782268 0.259752 +-0.276469 -0.629390 0.721082 -0.291425 -0.635084 0.715360 +0.672767 -0.431893 0.588605 0.679453 -0.433691 0.591824 +-0.941250 -0.089293 0.318885 -0.952456 -0.070037 0.296517 +-0.840597 -0.496807 0.154458 -0.859504 -0.477753 0.181676 +0.884264 -0.428000 -0.165477 0.889675 -0.428019 -0.158990 +0.278655 0.288350 0.910441 0.304198 0.286164 0.908611 +0.916542 -0.388508 -0.060387 0.932488 -0.356644 -0.057195 +0.016745 -0.989933 0.028103 -0.006323 -0.999980 0.000326 +0.416103 -0.092705 0.904704 0.422440 -0.088414 0.902068 +-0.663823 -0.294215 -0.674127 -0.669425 -0.312980 -0.673731 +0.161458 0.692235 -0.695286 0.156971 0.694363 -0.702297 +-0.480397 0.298751 -0.814339 -0.460625 0.314142 -0.830144 +0.406562 -0.910597 -0.102821 0.433190 -0.895931 -0.098252 +-0.010398 -0.816317 0.570937 -0.007661 -0.847898 0.530104 +0.209289 0.896045 -0.370132 0.208074 0.910715 -0.356797 +0.968307 -0.067608 0.194980 0.975250 -0.053170 0.214615 +0.935254 -0.170913 0.265351 0.947845 -0.165443 0.272430 +0.361802 -0.773098 -0.510717 0.311149 -0.809999 -0.497079 +-0.778965 0.607582 -0.128919 -0.799619 0.587789 -0.122937 +-0.744475 -0.384063 0.539070 -0.720417 -0.402963 0.564464 +-0.661381 0.561064 0.490094 -0.656079 0.577978 0.485285 +0.301623 0.337635 -0.892957 0.340210 0.347659 -0.873722 +0.770643 -0.501489 -0.370759 0.763088 -0.531991 -0.366991 +-0.954253 -0.221637 0.172868 -0.950680 -0.258982 0.170695 +-0.568127 0.696803 0.428936 -0.546904 0.691941 0.471289 +-0.247620 0.718741 0.639635 -0.241889 0.709061 0.662362 +-0.953413 -0.264716 0.033703 -0.958341 -0.284505 0.025268 +-0.873999 0.443966 0.116113 -0.882201 0.451252 0.134506 +-0.351005 -0.707172 0.603203 -0.354890 -0.725565 0.589584 +-0.875467 -0.480907 -0.114841 -0.879733 -0.448250 -0.158559 +-0.290525 0.649200 0.693091 -0.305719 0.651545 0.694280 +0.374026 -0.563990 -0.729882 0.368650 -0.556205 -0.744804 +-0.703796 -0.337360 0.613617 -0.681232 -0.356972 0.639135 +0.866582 -0.472233 0.118261 0.859771 -0.499217 0.107594 +0.400036 -0.626284 -0.664309 0.398165 -0.629150 -0.667559 +-0.014273 0.641077 -0.762309 -0.030571 0.632769 -0.773737 +-0.970819 0.191727 -0.088407 -0.973114 0.208575 -0.097701 +0.745355 -0.347838 -0.556700 0.732548 -0.338212 -0.590750 +-0.162560 -0.921908 0.329217 -0.145160 -0.924326 0.352916 +0.328007 -0.486594 -0.802671 0.349005 -0.458101 -0.817520 +0.262387 -0.961363 -0.083823 0.209597 -0.972578 -0.100802 +0.643390 0.407114 0.642012 0.628050 0.426698 0.650755 +-0.288652 -0.345910 0.890093 -0.260276 -0.380983 0.887191 +0.497424 -0.620595 0.592044 0.487134 -0.602535 0.632181 +0.837389 -0.041879 -0.523997 0.828361 -0.042240 -0.558601 +-0.514803 0.829062 -0.205243 -0.510828 0.838485 -0.189732 +-0.623114 -0.746371 -0.214016 -0.602692 -0.774897 -0.190521 +-0.904993 0.146420 -0.389394 -0.902533 0.198402 -0.382193 +-0.913528 0.279677 0.254451 -0.922663 0.263384 0.281640 +-0.844380 0.438613 -0.278297 -0.862432 0.428813 -0.268944 +-0.057709 0.737538 -0.662816 -0.077609 0.759753 -0.645563 +-0.861316 0.472231 -0.154120 -0.867790 0.476753 -0.140165 +0.709619 0.242937 -0.656958 0.712941 0.227775 -0.663200 +0.804715 0.521467 -0.271396 0.808222 0.488802 -0.328404 +-0.418597 -0.682260 -0.596379 -0.431087 -0.670233 -0.604112 +-0.901326 -0.199138 -0.352471 -0.895360 -0.233925 -0.378959 +0.075339 0.799362 0.579194 0.099181 0.811553 0.575799 +0.487437 0.862037 0.134678 0.513034 0.853249 0.093612 +-0.358959 0.850449 -0.367667 -0.382132 0.844550 -0.375115 +0.327463 -0.534093 0.769975 0.333631 -0.550339 0.765387 +-0.228841 0.793982 -0.551696 -0.231358 0.811806 -0.536138 +-0.900824 -0.254921 0.339009 -0.903831 -0.259238 0.340420 +0.045221 0.053695 0.989026 0.019530 0.051924 0.998460 +-0.577328 -0.072373 -0.806801 -0.606207 -0.065384 -0.792615 +-0.491310 -0.359584 0.782358 -0.500509 -0.364343 0.785331 +-0.595181 0.629370 0.493064 -0.583254 0.643450 0.495769 +0.229610 0.803742 -0.542846 0.220886 0.810903 -0.541891 +-0.312143 0.558582 0.756999 -0.328295 0.560786 0.760093 +-0.744907 0.083389 0.652841 -0.734597 0.069878 0.674896 +0.545714 -0.490343 -0.665794 0.557738 -0.474260 -0.681180 +0.706388 -0.537028 -0.451687 0.728765 -0.528787 -0.435071 +0.067410 0.628273 0.768587 0.073480 0.654181 0.752760 +0.628140 -0.481194 -0.599095 0.658633 -0.444338 -0.607261 +0.640817 0.448053 -0.614660 0.659032 0.454243 -0.599450 +-0.026617 0.800371 0.586377 0.001328 0.795528 0.605915 +-0.805677 -0.579992 0.067503 -0.797995 -0.590247 0.121709 +-0.088217 0.807777 -0.569396 -0.073163 0.840909 -0.536208 +-0.176977 -0.765273 -0.610441 -0.163116 -0.746222 -0.645403 +-0.233331 -0.492316 -0.828432 -0.253260 -0.527563 -0.810886 +0.901631 0.411230 -0.081158 0.930706 0.361005 -0.058835 +0.783564 0.056766 -0.597021 0.784994 0.030055 -0.618775 +0.776646 -0.617338 -0.025200 0.775181 -0.630364 -0.041665 +-0.286041 -0.441267 0.843332 -0.271236 -0.467709 0.841237 +0.838078 0.353322 0.404783 0.845741 0.356731 0.396818 +0.945758 0.157427 -0.255411 0.942537 0.209142 -0.260546 +0.799206 0.588142 -0.132456 0.768615 0.625419 -0.134474 +-0.533844 0.669722 -0.499510 -0.556473 0.660935 -0.503491 +0.371295 -0.750444 0.540968 0.386027 -0.734882 0.557612 +0.034721 -0.638931 -0.764630 0.053636 -0.642731 -0.764212 +-0.247584 0.899526 0.339973 -0.263120 0.900474 0.346286 +-0.363580 0.681774 -0.626894 -0.359867 0.673979 -0.645173 +-0.160053 0.737951 0.642554 -0.164521 0.732786 0.660271 +-0.903702 0.391089 -0.101515 -0.920904 0.369394 -0.124436 +-0.277182 0.244312 0.930887 -0.271926 0.210907 0.938922 +0.129717 -0.443060 0.873830 0.130892 -0.420310 0.897890 +0.342932 0.908718 0.232519 0.311487 0.915042 0.256268 +0.272305 -0.739724 -0.606918 0.278487 -0.759812 -0.587478 +-0.808080 0.136738 0.560237 -0.823942 0.153763 0.545414 +0.198636 0.358107 -0.915006 0.213599 0.380329 -0.899848 +-0.297770 0.835333 0.445363 -0.307484 0.842214 0.442866 +0.438574 -0.791313 -0.417305 0.402852 -0.802826 -0.439523 +0.673232 -0.399099 -0.607645 0.678551 -0.410497 -0.609148 +0.644703 -0.060113 0.753466 0.650485 -0.091375 0.754002 +0.528394 -0.385506 -0.745432 0.558672 -0.381573 -0.736402 +0.540641 -0.262656 -0.786047 0.577934 -0.281816 -0.765880 +0.400655 0.850867 0.328174 0.421703 0.829369 0.366487 +0.407825 0.604969 -0.678475 0.409961 0.622222 -0.666912 +-0.792885 -0.255692 -0.536952 -0.805684 -0.231542 -0.545217 +-0.864602 0.041950 0.485279 -0.869657 0.080209 0.487098 +0.038732 0.974905 0.170983 0.013626 0.982752 0.184426 +-0.633526 0.765097 0.043033 -0.645606 0.763164 0.027804 +-0.902900 0.211487 0.350294 -0.916633 0.215603 0.336598 +-0.130276 0.904436 0.381180 -0.144086 0.915184 0.376400 +-0.902583 -0.064000 -0.405791 -0.896583 -0.102835 -0.430771 +-0.970322 0.104677 0.185519 -0.972937 0.124296 0.194792 +-0.559328 -0.741660 0.333905 -0.541327 -0.767691 0.342952 +-0.727867 -0.472213 -0.490889 -0.741096 -0.458788 -0.490194 +0.646399 0.676059 0.323057 0.672459 0.674634 0.304415 +-0.259815 0.845976 -0.445447 -0.284068 0.851099 -0.441515 +0.712218 -0.578605 0.399887 0.699084 -0.573474 0.427094 +-0.773690 0.389109 0.491659 -0.793241 0.390933 0.466841 +0.327561 0.867452 -0.369128 0.316952 0.875355 -0.365096 +0.773452 -0.491491 0.392871 0.779734 -0.481191 0.400587 +0.802052 -0.297624 0.494799 0.829517 -0.274743 0.486229 +-0.356499 0.801077 -0.466917 -0.355482 0.813400 -0.460449 +-0.443143 0.807922 0.378523 -0.439437 0.815089 0.377525 +-0.506099 -0.535190 0.667152 -0.520266 -0.542091 0.659895 +-0.545221 0.440282 0.700107 -0.546256 0.467077 0.695301 +-0.902457 0.242662 -0.341216 -0.902210 0.261964 -0.342625 +0.500089 0.852611 -0.041965 0.511641 0.855856 -0.075721 +-0.502864 0.811844 0.288082 -0.506373 0.805726 0.307233 +0.168711 -0.930801 0.289835 0.147824 -0.949505 0.276747 +-0.452058 -0.724849 -0.516064 -0.487597 -0.714382 -0.501903 +-0.482636 -0.256333 0.822406 -0.494051 -0.249746 0.832791 +0.678110 -0.161211 0.705746 0.688563 -0.164365 0.706304 +0.635469 0.509468 0.570296 0.634818 0.517855 0.573439 +0.210662 -0.739105 0.630259 0.219622 -0.752936 0.620365 +-0.886872 -0.285971 -0.329138 -0.888762 -0.251912 -0.382940 +0.345478 -0.921985 0.128959 0.377420 -0.913216 0.153592 +-0.125678 -0.973177 0.173870 -0.127570 -0.974353 0.185372 +0.708464 0.698695 -0.009095 0.678285 0.734174 0.030306 +-0.553798 0.822996 -0.011788 -0.571370 0.820595 -0.012669 +-0.184430 0.322848 -0.919389 -0.177484 0.312928 -0.933046 +0.287411 -0.404704 -0.860206 0.292562 -0.407359 -0.865139 +0.401835 0.180682 -0.890867 0.428964 0.162090 -0.888660 +-0.206728 0.970704 0.118357 -0.135800 0.985120 0.105345 +0.472071 0.528689 -0.702361 0.480694 0.549664 -0.683230 +0.391312 -0.587457 0.697293 0.398149 -0.591320 0.701297 +-0.574210 -0.467774 0.658125 -0.584424 -0.470928 0.660814 +0.155745 0.757363 0.615686 0.169958 0.774002 0.609947 +-0.656848 -0.650136 -0.375581 -0.636751 -0.652762 -0.410426 +0.116731 0.389190 0.904953 0.121300 0.378039 0.917808 +-0.102838 0.973798 0.153151 -0.089487 0.984434 0.151268 +0.968273 -0.144415 -0.189083 0.976820 -0.140616 -0.161401 +0.114624 0.979855 -0.160119 0.105462 0.981663 -0.158794 +-0.630348 -0.378561 -0.670936 -0.627715 -0.355454 -0.692551 +0.858225 0.510088 -0.056254 0.853959 0.518370 -0.045232 +0.638931 -0.665421 0.385933 0.631788 -0.685650 0.361564 +-0.498374 -0.447693 0.732571 -0.511873 -0.448733 0.732547 +-0.545123 0.783022 -0.287527 -0.548769 0.775662 -0.311769 +-0.426399 -0.351845 -0.827652 -0.406641 -0.366274 -0.836951 +-0.090944 -0.756201 -0.635243 -0.091078 -0.757107 -0.646912 +0.680034 0.544071 0.473940 0.668346 0.557352 0.492617 +0.784550 -0.156745 -0.584673 0.777438 -0.146993 -0.611542 +0.900750 0.013699 0.411720 0.921954 -0.032297 0.385951 +0.464820 -0.699947 0.536589 0.480198 -0.668670 0.567706 +0.722365 -0.125592 -0.665024 0.729674 -0.125277 -0.672221 +-0.707625 0.699132 0.065555 -0.713041 0.699673 0.045044 +0.685688 -0.715386 0.097229 0.704094 -0.703911 0.093601 +-0.385060 0.349834 -0.845965 -0.380786 0.343174 -0.858623 +0.905774 0.384195 0.134690 0.923226 0.361750 0.129581 +0.275970 -0.667834 -0.689280 0.264137 -0.650204 -0.712367 +0.823606 -0.549685 0.056258 0.846215 -0.531950 0.030820 +0.282073 0.197260 0.937381 0.274684 0.245064 0.929781 +0.662820 -0.737157 -0.109478 0.693224 -0.713711 -0.100285 +0.062084 -0.982672 0.131865 0.064245 -0.988176 0.139217 +-0.631177 0.471986 -0.612023 -0.627046 0.477846 -0.615204 +0.561806 -0.770656 -0.294329 0.569132 -0.770419 -0.287304 +-0.443963 -0.047331 0.883614 -0.416977 -0.047681 0.907666 +0.480380 0.244394 -0.834601 0.491508 0.255622 -0.832513 +0.146036 0.765804 -0.617908 0.128890 0.785982 -0.604666 +0.853889 0.497978 -0.169003 0.843917 0.509346 -0.168434 +0.807422 -0.107220 0.574463 0.792974 -0.167146 0.585878 +0.033535 -0.102959 -0.983658 0.030201 -0.076453 -0.996616 +0.303078 -0.276932 0.898660 0.263402 -0.280064 0.923138 +-0.273087 -0.930520 -0.178514 -0.281911 -0.945738 -0.161574 +0.678585 -0.193115 -0.696060 0.686670 -0.174742 -0.705655 +-0.640428 0.756648 -0.060384 -0.649176 0.760217 -0.025293 +-0.763835 -0.648309 -0.015572 -0.744916 -0.666443 0.030882 +-0.679645 -0.181428 0.698967 -0.687771 -0.180212 0.703203 +0.940926 0.269382 0.150977 0.952301 0.267755 0.146388 +0.523488 -0.831375 0.123477 0.522525 -0.840531 0.143094 +0.353037 0.794364 -0.492700 0.360762 0.778736 -0.513245 +0.609977 0.684447 -0.372860 0.633004 0.658938 -0.406333 +0.569403 -0.738690 0.339955 0.550310 -0.766787 0.330449 +0.202014 -0.883149 0.412911 0.213742 -0.890177 0.402368 +0.902194 0.415623 0.028496 0.928407 0.368173 0.050089 +-0.468752 0.396763 -0.779092 -0.488510 0.413001 -0.768627 +-0.573335 0.323328 -0.744293 -0.571179 0.315515 -0.757763 +0.282690 -0.657188 0.688317 0.297934 -0.666234 0.683643 +-0.537522 0.446963 -0.704367 -0.529984 0.433390 -0.728897 +-0.728233 0.048413 -0.673323 -0.753795 0.061272 -0.654247 +-0.683184 0.388207 -0.610746 -0.691572 0.396892 -0.603494 +0.010847 0.012546 -0.987996 0.028582 -0.030369 -0.999130 +-0.941396 0.301323 -0.075229 -0.938930 0.322209 -0.120800 +0.986556 -0.091030 -0.051300 0.995839 -0.091129 0.000402 +-0.577870 -0.545460 0.595883 -0.583229 -0.536693 0.609758 +-0.118708 -0.885005 0.429643 -0.078960 -0.903522 0.421205 +0.001333 -0.927085 0.337126 0.014199 -0.936451 0.350510 +0.798784 0.597845 -0.014516 0.796294 0.604655 0.017545 +-0.468884 0.582133 0.650786 -0.464841 0.579289 0.669587 +0.621506 0.362829 -0.690938 0.631046 0.340627 -0.696961 +0.210179 -0.373025 0.892772 0.173649 -0.371845 0.911908 +0.494407 0.712927 0.480238 0.504995 0.704054 0.499288 +-0.995489 0.082237 -0.007831 -0.994241 0.106047 0.015429 +0.671362 0.727041 -0.129222 0.658595 0.738804 -0.142907 +-0.556737 -0.804126 -0.174868 -0.533309 -0.824831 -0.187712 +0.645206 0.714492 0.230900 0.665383 0.706918 0.239859 +-0.068414 -0.605999 -0.788282 -0.117825 -0.635916 -0.762711 +-0.857353 0.186069 0.459799 -0.884156 0.169421 0.435389 +0.055719 0.696731 -0.707918 0.033565 0.692178 -0.720946 +0.462322 -0.512885 -0.711390 0.488694 -0.493693 -0.719337 +0.222595 -0.601558 0.764001 0.243414 -0.609861 0.754201 +0.324379 0.619346 -0.710893 0.316963 0.628136 -0.710619 +-0.119200 0.513064 -0.839066 -0.111061 0.530155 -0.840595 +0.481226 0.618642 -0.611211 0.535667 0.609895 -0.584029 +0.855512 -0.502113 -0.071196 0.863011 -0.501567 -0.060354 +0.103860 0.287252 -0.948573 0.040222 0.291803 -0.955632 +-0.695143 -0.718255 -0.012958 -0.705057 -0.708101 0.038577 +0.442634 -0.860236 0.195256 0.440146 -0.875129 0.201049 +-0.457978 -0.530615 -0.710148 -0.446201 -0.543320 -0.711132 +-0.378779 0.605325 0.687751 -0.385206 0.610265 0.692238 +0.408193 0.319952 -0.853179 0.455898 0.302626 -0.837003 +0.853997 0.082521 -0.502895 0.853540 0.054475 -0.518172 +-0.542431 -0.674080 -0.489901 -0.562517 -0.663936 -0.492711 +-0.793359 -0.054881 0.602183 -0.783121 -0.038547 0.620673 +0.727270 0.423653 -0.524576 0.738882 0.432457 -0.516753 +-0.090948 -0.601315 0.783428 -0.095193 -0.579700 0.809250 +-0.856470 -0.179694 -0.450978 -0.879985 -0.190753 -0.435017 +-0.885502 -0.402759 0.184545 -0.896227 -0.394221 0.203390 +0.423624 0.053537 -0.893933 0.427743 0.055136 -0.902217 +-0.152553 0.841296 -0.501229 -0.165260 0.856567 -0.488858 +0.755263 -0.412875 0.487739 0.783950 -0.398745 0.475842 +-0.836250 0.304765 0.433576 -0.858257 0.304580 0.413070 +-0.676849 0.028839 0.726261 -0.665498 -0.013188 0.746283 +0.412839 0.696223 0.574116 0.380504 0.716120 0.585140 +-0.360719 -0.012880 -0.922781 -0.338349 -0.026317 -0.940652 +0.146669 0.084968 0.979701 0.153157 0.060117 0.986372 +0.010393 0.442995 0.885025 0.015481 0.425598 0.904780 +-0.984554 -0.154319 0.082805 -0.981581 -0.166362 0.093930 +-0.316193 -0.110853 -0.926310 -0.307815 -0.117456 -0.944169 +0.544737 0.685412 -0.465338 0.578145 0.679682 -0.451421 +-0.481716 0.309846 0.815537 -0.519916 0.306921 0.797175 +-0.365282 0.779318 0.493000 -0.374310 0.781181 0.499649 +0.062623 0.590589 -0.796779 0.035880 0.611170 -0.790686 +0.896906 -0.351912 -0.253945 0.900576 -0.340070 -0.270767 +-0.366233 0.355151 0.859399 -0.327597 0.415135 0.848730 +-0.149587 -0.070307 0.977439 -0.141208 -0.072429 0.987327 +0.621863 0.038877 0.775258 0.626245 0.049922 0.778027 +-0.230051 0.139988 0.953495 -0.185087 0.133791 0.973572 +-0.622154 -0.742524 0.217105 -0.624940 -0.749793 0.217395 +0.714604 -0.595014 -0.345967 0.739958 -0.585797 -0.330612 +0.783256 0.169698 -0.585877 0.793600 0.155842 -0.588143 +0.970620 0.167840 0.100913 0.981172 0.142193 0.130697 +0.514069 0.414600 -0.744687 0.514884 0.441747 -0.734679 +-0.840874 -0.381737 -0.354919 -0.863116 -0.342174 -0.371414 +0.692537 0.525220 -0.467406 0.689915 0.551020 -0.469461 +-0.082821 -0.193212 0.970601 -0.118601 -0.159803 0.979998 +0.242553 0.634011 0.716926 0.245029 0.644068 0.724664 +-0.203620 -0.958587 -0.083611 -0.200624 -0.974578 -0.099740 +0.736155 0.644709 0.159074 0.701201 0.689964 0.179632 +0.898080 -0.380729 0.195760 0.912547 -0.355359 0.202430 +-0.064461 0.038181 0.982162 -0.072513 0.063743 0.995328 +-0.809430 -0.481336 -0.323001 -0.805475 -0.459983 -0.373666 +0.553708 0.562276 0.605302 0.552399 0.549397 0.626912 +0.277945 0.498113 0.807768 0.245416 0.523692 0.815793 +-0.611063 0.544172 0.568597 -0.583658 0.527382 0.617423 +-0.828022 -0.562375 -0.042144 -0.800072 -0.598251 -0.044504 +-0.661835 -0.735926 -0.123789 -0.645251 -0.750912 -0.140651 +-0.945246 0.198692 0.219198 -0.947175 0.214995 0.237985 +-0.342324 -0.932981 0.087351 -0.320510 -0.937334 0.136667 +0.381542 -0.045091 -0.913855 0.423896 -0.035128 -0.905030 +-0.340662 0.121538 0.929638 -0.316482 0.052043 0.947170 +0.380591 0.509813 0.758080 0.367369 0.519108 0.771730 +-0.092374 -0.404370 0.899508 -0.111882 -0.433341 0.894258 +-0.154945 -0.638224 -0.741633 -0.195254 -0.649024 -0.735285 +0.640483 0.270470 -0.712499 0.656011 0.228302 -0.719395 +0.677015 0.710018 0.137354 0.671984 0.730197 0.123488 +0.169102 0.982853 -0.077565 0.166486 0.983368 -0.072600 +0.389876 0.678451 -0.616151 0.381495 0.700277 -0.603385 +-0.387023 0.237012 0.891799 -0.360720 0.223243 0.905562 +0.324431 -0.932723 -0.177465 0.333444 -0.922033 -0.196650 +0.739497 0.536892 0.386164 0.720359 0.558855 0.410810 +0.916619 0.007225 -0.401741 0.887001 -0.019436 -0.461358 +0.638853 0.518702 -0.554542 0.662024 0.527957 -0.531964 +-0.237153 0.938664 -0.216653 -0.254842 0.938400 -0.233369 +0.145647 0.680269 0.705197 0.170136 0.704366 0.689146 +0.691070 0.365147 -0.617022 0.699514 0.390779 -0.598308 +-0.736789 -0.014679 0.667077 -0.705691 -0.026090 0.708039 +-0.836418 -0.286743 -0.436778 -0.859617 -0.258956 -0.440454 +-0.328560 -0.871366 -0.343932 -0.341475 -0.887316 -0.309943 +-0.121367 0.023475 -0.984003 -0.136917 0.014801 -0.990472 +0.422224 -0.697565 -0.575296 0.399343 -0.716150 -0.572411 +-0.808689 0.036053 0.580762 -0.784592 0.033842 0.619088 +0.477037 0.390426 0.778328 0.490994 0.379442 0.784187 +-0.905556 0.039441 -0.421413 -0.899315 0.033104 -0.436048 +0.112543 -0.987477 0.048372 0.064648 -0.997147 0.038976 +0.831776 -0.316708 -0.450187 0.832165 -0.330156 -0.445531 +0.886049 -0.451719 0.017201 0.886115 -0.463127 0.017694 +0.718558 0.348549 0.585218 0.726457 0.350956 0.590839 +-0.282693 -0.305829 -0.901957 -0.298715 -0.291767 -0.908648 +-0.325601 0.268195 -0.895598 -0.321741 0.268073 -0.908086 +0.757299 -0.637474 0.093887 0.771387 -0.627960 0.103099 +-0.354391 -0.018328 0.926215 -0.356271 -0.045162 0.933291 +0.814832 0.379902 -0.409128 0.829178 0.381445 -0.408611 +-0.361868 -0.792318 -0.487930 -0.366464 -0.797665 -0.478994 +0.890877 -0.202207 -0.383577 0.889716 -0.230167 -0.394244 +-0.802826 0.169825 -0.555183 -0.791117 0.206827 -0.575635 +0.129059 -0.280909 -0.946187 0.124515 -0.327051 -0.936768 +0.897802 0.312784 -0.276785 0.918074 0.290274 -0.269964 +0.464467 0.693672 -0.540360 0.494947 0.676196 -0.545698 +-0.680250 -0.670847 -0.287614 -0.677479 -0.677593 -0.286164 +0.983273 0.056191 0.051856 0.995605 0.056345 0.074799 +0.013491 -0.803008 -0.583141 0.016598 -0.790448 -0.612304 +-0.213667 0.483492 0.837207 -0.202025 0.483456 0.851737 +0.158166 0.617765 -0.766273 0.156474 0.634403 -0.756999 +0.243455 0.115766 0.961130 0.232118 0.128487 0.964164 +-0.042500 0.324910 -0.936531 -0.061731 0.351296 -0.934227 +0.423315 0.430176 -0.794202 0.433814 0.435665 -0.788671 +0.044069 0.169300 0.974505 0.017031 0.184630 0.982661 +0.624925 -0.753698 0.173892 0.627523 -0.759771 0.170184 +-0.754346 0.503897 0.410764 -0.794105 0.461536 0.395451 +0.893963 -0.166374 0.373473 0.911586 -0.181699 0.368777 +0.095725 -0.967495 -0.190617 0.072515 -0.978666 -0.192238 +-0.807925 0.543628 -0.208740 -0.799515 0.552901 -0.234682 +-0.643599 0.209400 -0.723567 -0.665753 0.202688 -0.718116 +0.155587 0.972916 0.123882 0.104752 0.985126 0.136211 +-0.087175 -0.160442 -0.975679 -0.066309 -0.106367 -0.992114 +-0.197532 0.859822 0.460682 -0.232010 0.853995 0.465687 +-0.325638 -0.399067 -0.847793 -0.322732 -0.430261 -0.843042 +0.720364 -0.661238 0.206242 0.724137 -0.657236 0.208966 +-0.934903 -0.098751 -0.314371 -0.939593 -0.129091 -0.317018 +0.599207 -0.410143 -0.673974 0.605598 -0.416507 -0.678065 +-0.803202 -0.413338 0.427884 -0.811916 -0.421083 0.404329 +0.980576 0.126512 -0.034660 0.988799 0.146195 -0.030067 +-0.172068 -0.953735 -0.187149 -0.160656 -0.974168 -0.158704 +0.611361 0.594525 0.506702 0.613230 0.598162 0.515898 +-0.380451 -0.256511 0.876895 -0.396688 -0.263118 0.879436 +0.803379 0.570678 0.152779 0.804281 0.573847 0.154374 +0.654059 0.741103 0.060716 0.657971 0.750265 0.064626 +-0.685098 0.672692 0.271911 -0.663516 0.690749 0.287424 +0.033240 0.965726 -0.226473 0.024802 0.957904 -0.286016 +-0.638861 -0.681518 0.340107 -0.613233 -0.704458 0.357328 +0.482988 0.619467 0.607256 0.494341 0.630656 0.598248 +-0.717753 0.689167 -0.027030 -0.734794 0.676900 -0.043416 +-0.429557 -0.187320 -0.876300 -0.385243 -0.184724 -0.904138 +-0.295877 -0.209956 -0.919949 -0.295878 -0.177513 -0.938587 +-0.352744 -0.636533 0.679824 -0.339078 -0.626527 0.701776 +-0.462635 -0.785094 0.371566 -0.467276 -0.798884 0.378731 +-0.562592 0.225607 -0.787067 -0.579601 0.255602 -0.773777 +-0.426582 0.493732 -0.742631 -0.424055 0.508091 -0.749681 +0.646649 -0.586677 0.483005 0.641803 -0.553587 0.530689 +0.270032 0.911994 -0.287513 0.270642 0.915542 -0.297548 +0.933240 0.272252 -0.164909 0.955153 0.251360 -0.156527 +0.825804 0.222325 -0.508968 0.825856 0.250970 -0.504951 +-0.734457 -0.672518 0.068057 -0.741912 -0.666056 0.077046 +-0.207436 -0.943908 0.231753 -0.218287 -0.950852 0.219618 +0.196312 0.950164 -0.215871 0.182589 0.951984 -0.245739 +-0.037055 0.571899 0.810860 -0.082588 0.567550 0.819187 +-0.226703 0.503444 -0.823494 -0.213922 0.507638 -0.834590 +-0.111800 0.963044 -0.199173 -0.125319 0.966119 -0.225632 +-0.459974 0.872482 -0.115240 -0.454042 0.882403 -0.123331 +-0.147173 -0.288371 -0.948305 -0.154720 -0.259692 -0.953217 +-0.797829 0.254256 0.534539 -0.793520 0.247006 0.556160 +0.156331 -0.968535 0.159666 0.110950 -0.979857 0.166044 +0.069320 0.297621 0.943910 0.096525 0.330812 0.938747 +0.031562 0.773688 -0.623674 0.006511 0.771927 -0.635677 +0.887197 -0.080606 -0.432298 0.877905 -0.080470 -0.472025 +-0.253957 0.384751 0.882217 -0.222467 0.387521 0.894615 +0.936579 -0.113505 -0.319414 0.931464 -0.127142 -0.340895 +0.292976 0.956751 0.074309 0.243492 0.964678 0.100539 +-0.173440 -0.559923 -0.801961 -0.213473 -0.592008 -0.777146 +-0.982259 -0.134410 -0.041647 -0.985557 -0.147782 -0.082698 +0.268654 -0.898797 0.337341 0.206094 -0.917131 0.341169 +0.261942 0.514865 -0.813065 0.278236 0.513381 -0.811803 +-0.037562 0.953482 0.255234 -0.038454 0.962301 0.269254 +0.180917 -0.830799 0.514389 0.178991 -0.834252 0.521523 +0.719813 0.138070 -0.668629 0.740023 0.104335 -0.664440 +0.595934 -0.647505 -0.476698 0.623615 -0.627642 -0.466015 +-0.399034 0.603822 -0.677722 -0.409778 0.607287 -0.680650 +0.146174 0.162248 -0.972999 0.136718 0.119207 -0.983411 +0.106864 -0.341405 0.925235 0.102146 -0.347110 0.932245 +0.087327 0.385640 -0.914899 0.049414 0.372516 -0.926709 +0.482161 0.845879 -0.157950 0.494147 0.858906 -0.134534 +-0.334103 0.468799 0.808891 -0.348981 0.489715 0.798994 +0.690696 0.141339 0.703917 0.689044 0.174384 0.703426 +0.416852 0.026271 0.904082 0.432282 0.071190 0.898924 +-0.187899 0.658617 0.715320 -0.164831 0.647824 0.743744 +-0.169756 0.976144 -0.087665 -0.188266 0.978292 -0.086611 +0.334501 0.686319 0.634680 0.316179 0.720259 0.617461 +-0.262721 -0.918954 -0.268109 -0.282659 -0.922394 -0.263235 +-0.186205 -0.173569 0.959800 -0.190894 -0.126188 0.973466 +-0.682940 -0.081979 0.715091 -0.692712 -0.079223 0.716850 +-0.932508 0.345181 0.044838 -0.943260 0.330108 0.035900 +-0.123846 0.984913 0.022068 -0.079050 0.996175 0.037242 +0.164753 -0.924552 -0.319844 0.119493 -0.930910 -0.345150 +-0.452454 -0.847480 0.225190 -0.452261 -0.843509 0.289744 +-0.020514 0.992193 -0.126222 -0.032196 0.994211 -0.102505 +0.414945 -0.651094 0.626281 0.438187 -0.620539 0.650326 +-0.166494 -0.832428 -0.517491 -0.118035 -0.854645 -0.505618 +-0.087312 0.675107 -0.725353 -0.108945 0.672988 -0.731586 +-0.999087 -0.031905 -0.001808 -0.999107 -0.020705 -0.036843 +-0.532579 0.602022 -0.583660 -0.516594 0.622129 -0.588291 +-0.532122 -0.842875 0.027221 -0.569288 -0.822050 -0.012034 +-0.114254 -0.958192 -0.258390 -0.126050 -0.959560 -0.251707 +0.022288 -0.433957 -0.899689 0.059909 -0.422749 -0.904265 +0.414625 -0.252679 0.871453 0.402512 -0.249700 0.880701 +-0.655375 -0.283990 0.687373 -0.663072 -0.258015 0.702683 +-0.963972 -0.157202 -0.148384 -0.975146 -0.145659 -0.166954 +0.953484 -0.252260 0.076859 0.960497 -0.256438 0.108094 +0.723148 -0.259008 -0.629475 0.700406 -0.275390 -0.658477 +-0.455736 0.806721 -0.350644 -0.458423 0.802521 -0.381849 +-0.256729 -0.852395 -0.442547 -0.276927 -0.868020 -0.412133 +-0.970857 0.008529 0.225155 -0.963217 0.035622 0.266352 +-0.538413 -0.035126 0.831099 -0.566613 -0.046801 0.822654 +-0.864513 0.395200 0.271767 -0.889651 0.378551 0.255383 +-0.243017 0.000438 -0.957036 -0.238434 -0.041667 -0.970264 +-0.058377 -0.973808 -0.146374 -0.064458 -0.992089 -0.107722 +0.448328 -0.327073 -0.818932 0.463678 -0.342676 -0.817053 +-0.897656 -0.166628 0.402609 -0.906435 -0.171630 0.385899 +-0.040329 -0.507380 0.846680 -0.050226 -0.499832 0.864665 +-0.772408 -0.599997 0.163623 -0.781086 -0.595690 0.187237 +0.567158 -0.555847 -0.596657 0.585471 -0.516131 -0.625166 +-0.219975 -0.376719 -0.894704 -0.266095 -0.385121 -0.883671 +-0.417640 0.731775 -0.526092 -0.456915 0.720749 -0.521296 +0.237087 -0.966404 0.079917 0.204871 -0.976223 0.070831 +-0.517992 0.201899 0.829893 -0.539385 0.182956 0.821943 +0.028036 -0.602443 0.790707 0.021073 -0.609154 0.792772 +-0.314132 0.740138 0.582003 -0.301263 0.741813 0.599128 +-0.592871 0.118667 -0.790117 -0.614271 0.113255 -0.780925 +0.364532 0.123871 0.923060 0.364151 0.130663 0.922128 +-0.190131 -0.693668 -0.682327 -0.206496 -0.678070 -0.705394 +-0.645278 -0.629006 0.415472 -0.623214 -0.663466 0.414026 +-0.372194 0.891837 0.254330 -0.368267 0.881806 0.294614 +0.264783 0.136259 -0.949789 0.269285 0.093248 -0.958536 +0.869560 -0.088140 0.466929 0.893813 -0.114076 0.433687 +-0.483693 -0.863643 0.116867 -0.479036 -0.860458 0.173600 +-0.784933 -0.293869 0.541243 -0.754247 -0.314754 0.576230 +0.348691 -0.842689 -0.395667 0.302384 -0.862805 -0.405131 +0.684120 -0.663462 -0.280676 0.704293 -0.663093 -0.253533 +0.505371 -0.009379 -0.854807 0.534213 -0.002954 -0.845345 +-0.688182 0.406968 0.594591 -0.663309 0.425986 0.615270 +-0.294567 -0.782408 0.532208 -0.300196 -0.804826 0.511993 +0.777803 -0.562570 0.290871 0.756432 -0.586227 0.290085 +0.781522 0.104413 0.622144 0.767545 0.118220 0.629999 +0.171545 -0.122846 0.968201 0.198698 -0.133539 0.970920 +0.056201 0.123486 -0.986954 0.035415 0.097231 -0.994632 +-0.945741 -0.255213 -0.093827 -0.963060 -0.244311 -0.113257 +0.249459 -0.929360 -0.259991 0.214062 -0.942101 -0.258116 +-0.248136 0.970031 0.011251 -0.226006 0.973695 0.028955 +0.736372 0.209261 0.634391 0.729719 0.223035 0.646348 +-0.581937 -0.244656 0.761947 -0.589424 -0.242358 0.770612 +-0.940852 -0.184758 0.275261 -0.950686 -0.150992 0.270921 +-0.228398 -0.958698 0.119921 -0.245558 -0.959327 0.139256 +0.304111 -0.835180 0.453701 0.321882 -0.831461 0.452841 +0.515655 -0.827886 -0.215536 0.530919 -0.826537 -0.186981 +0.374234 -0.200948 -0.901099 0.400992 -0.197531 -0.894532 +-0.931285 -0.324409 0.125762 -0.933252 -0.333988 0.132261 +-0.398600 0.678601 0.604850 -0.408645 0.694612 0.592050 +-0.254237 -0.720835 0.638895 -0.239146 -0.715145 0.656793 +0.804005 0.193955 0.549077 0.788716 0.217670 0.574932 +-0.274048 -0.227008 0.926532 -0.269092 -0.226212 0.936172 +-0.507949 -0.691153 0.495236 -0.512423 -0.734426 0.445019 +-0.836244 -0.300191 0.450715 -0.841015 -0.336487 0.423639 +-0.901397 -0.048137 0.420767 -0.905452 -0.032743 0.423184 +0.177195 -0.095474 -0.973871 0.167046 -0.101966 -0.980662 +-0.681132 0.115105 -0.712095 -0.681520 0.141580 -0.717973 +0.561957 0.738317 0.351067 0.571612 0.743984 0.346047 +0.739696 0.663758 -0.096503 0.704783 0.706911 -0.059647 +-0.200954 0.576579 0.780017 -0.220295 0.577945 0.785780 +0.757188 0.612355 -0.226401 0.725802 0.637234 -0.259124 +-0.601696 -0.120431 0.776372 -0.592855 -0.142516 0.792599 +0.445481 0.865203 0.233076 0.432045 0.862222 0.264407 +0.641196 -0.731582 -0.219023 0.666583 -0.708170 -0.232728 +-0.597958 -0.735971 -0.307381 -0.602099 -0.747849 -0.279640 +-0.587501 -0.699870 -0.395088 -0.578668 -0.706283 -0.407808 +0.710197 0.038394 -0.686277 0.723959 0.022031 -0.689491 +0.077029 0.897427 -0.409506 0.033229 0.916985 -0.397536 +0.778475 -0.422562 -0.452670 0.780014 -0.402252 -0.479344 +0.566686 0.118903 -0.803842 0.560054 0.115790 -0.820325 +0.769011 0.432389 0.452637 0.756535 0.459998 0.464820 +0.684632 0.689188 -0.225499 0.654108 0.721392 -0.227455 +-0.104757 0.503130 0.848395 -0.098137 0.497507 0.861891 +-0.762544 0.115793 -0.625380 -0.767337 0.116711 -0.630534 +0.660382 -0.621552 -0.413787 0.698732 -0.612109 -0.370265 +-0.752806 -0.366297 -0.536211 -0.756456 -0.345876 -0.555108 +0.265698 0.737135 -0.610601 0.267748 0.744352 -0.611760 +0.173875 0.814959 0.525977 0.193041 0.829483 0.524112 +-0.927040 -0.269545 -0.224228 -0.935599 -0.249361 -0.249947 +-0.794953 -0.490680 0.352786 -0.815847 -0.485510 0.314123 +0.316368 0.950948 -0.031440 0.362270 0.928851 -0.077440 +0.570819 -0.660697 0.480464 0.553202 -0.684571 0.474690 +0.942641 0.312955 0.052241 0.958237 0.281716 0.049179 +0.067123 0.854814 0.494252 0.094470 0.856489 0.507447 +-0.073370 0.411919 -0.897858 -0.104663 0.414951 -0.903804 +0.181785 0.307522 0.927122 0.153856 0.296842 0.942451 +-0.698743 -0.031036 -0.703902 -0.703040 -0.040308 -0.710007 +0.942057 0.081059 -0.324813 0.930578 0.083138 -0.356528 +0.504333 -0.413396 0.749582 0.539101 -0.415273 0.732747 +-0.176568 -0.087250 -0.969187 -0.228422 -0.091716 -0.969232 +0.537159 0.639690 0.533615 0.549122 0.630557 0.548510 +-0.502193 -0.261238 -0.822164 -0.524151 -0.219224 -0.822925 +0.202819 0.975132 0.017810 0.183777 0.982809 0.017695 +-0.302422 -0.924798 0.195525 -0.309272 -0.915174 0.258473 +0.479782 -0.600027 -0.631570 0.481646 -0.597004 -0.641563 +0.837271 0.006434 0.543331 0.846693 -0.010763 0.531973 +0.923669 0.249430 0.259208 0.941002 0.228292 0.249796 +-0.799428 -0.589655 -0.136962 -0.768534 -0.615531 -0.174577 +0.891818 0.391499 -0.187721 0.912725 0.372711 -0.167391 +-0.468212 0.748666 0.449724 -0.456824 0.754796 0.470739 +-0.637854 0.681431 0.352155 -0.665334 0.657368 0.353834 +0.575515 0.484334 0.649948 0.597749 0.492652 0.632448 +0.974849 -0.140692 0.115583 0.985980 -0.100321 0.133341 +0.334864 0.602055 0.709002 0.325955 0.606293 0.725371 +-0.030912 0.346003 0.928863 -0.030113 0.344279 0.938384 +0.632922 0.049360 -0.759988 0.634348 0.046999 -0.771618 +0.974473 0.055674 0.156815 0.987988 0.047005 0.147208 +-0.109720 -0.830827 0.534081 -0.110427 -0.839473 0.532063 +-0.019661 0.987832 0.073350 -0.013169 0.990818 0.134558 +0.909983 0.214162 -0.331339 0.904169 0.275552 -0.326419 +0.100946 -0.884509 -0.425405 0.105801 -0.891046 -0.441410 +0.840977 -0.401287 -0.351654 0.850778 -0.407972 -0.331264 +-0.744501 0.341171 -0.555111 -0.770091 0.316862 -0.553677 +-0.679778 -0.426730 -0.591688 -0.667499 -0.419785 -0.615000 +0.571525 0.224089 -0.780542 0.595936 0.188871 -0.780505 +-0.048299 0.871070 0.477553 -0.043860 0.873286 0.485229 +0.531518 0.277731 0.788286 0.546773 0.271208 0.792140 +-0.507820 -0.744566 -0.422493 -0.525277 -0.737861 -0.423845 +0.691500 -0.502419 0.511010 0.685719 -0.488489 0.539601 +0.517787 0.762463 -0.368653 0.531828 0.767588 -0.357726 +0.463813 -0.830357 -0.321521 0.481136 -0.800041 -0.358389 +-0.726142 0.516980 -0.432158 -0.714359 0.543754 -0.440481 +-0.332204 -0.832594 0.421115 -0.351824 -0.841401 0.410201 +0.520606 -0.847288 0.017195 0.507677 -0.860308 0.046186 +-0.073577 -0.765105 0.638384 -0.083912 -0.749749 0.656380 +-0.854799 -0.469812 -0.225810 -0.839808 -0.460453 -0.287588 +0.000128 -0.733540 -0.674146 -0.050764 -0.738852 -0.671953 +0.020433 -0.406163 0.901818 0.060514 -0.402520 0.913409 +0.214765 -0.329979 -0.912947 0.181738 -0.341626 -0.922097 +0.542806 0.320331 -0.771127 0.553916 0.314471 -0.770899 +0.278073 -0.595099 -0.747222 0.283956 -0.612673 -0.737564 +0.673951 0.615568 0.389520 0.670196 0.645319 0.366608 +0.418388 -0.434277 -0.789645 0.458102 -0.411377 -0.787979 +-0.155551 -0.976491 0.051274 -0.166712 -0.985690 0.024968 +-0.988040 -0.036493 -0.105321 -0.991650 -0.070932 -0.107698 +0.844338 -0.440350 0.300803 0.868897 -0.403628 0.286534 +0.549604 0.614011 -0.551518 0.580101 0.626179 -0.520945 +-0.736030 -0.669935 -0.100805 -0.707202 -0.700963 -0.092284 +0.612054 0.779483 -0.014496 0.610080 0.792229 -0.013227 +-0.741110 -0.236514 0.619557 -0.737051 -0.219215 0.639297 +-0.731402 0.309148 0.603250 -0.748006 0.319180 0.581902 +-0.571289 -0.802074 0.140341 -0.585403 -0.795629 0.155818 +0.217957 -0.005510 0.974025 0.229513 -0.010143 0.973253 +-0.616068 -0.612937 -0.486977 -0.615143 -0.623262 -0.482849 +0.121579 -0.779529 0.609868 0.117869 -0.790876 0.600519 +0.547733 -0.009035 0.834202 0.564838 -0.001653 0.825201 +-0.201901 -0.593420 0.770162 -0.220667 -0.592321 0.774895 +-0.104808 -0.696836 0.702698 -0.104828 -0.679775 0.725890 +-0.332023 0.894542 -0.275013 -0.346904 0.894634 -0.281580 +-0.818815 0.498331 0.269254 -0.857176 0.450865 0.248938 +0.376402 0.411841 0.822870 0.397030 0.406156 0.823046 +-0.347752 0.945307 0.036154 -0.340608 0.939721 0.030175 +-0.670294 0.295702 -0.671599 -0.692402 0.256743 -0.674287 +0.701551 0.443106 0.541197 0.712122 0.463646 0.527176 +-0.485185 0.743895 -0.433746 -0.497847 0.742452 -0.448233 +-0.802053 0.444425 -0.377174 -0.796997 0.461697 -0.389399 +0.540128 -0.792922 0.233848 0.549632 -0.799976 0.240714 +-0.779813 0.618706 -0.021945 -0.772162 0.635426 -0.000091 +0.170116 -0.686947 0.704087 0.137424 -0.690412 0.710243 +-0.547274 -0.168768 -0.816109 -0.562450 -0.172282 -0.808683 +0.277041 0.383193 0.875184 0.285456 0.375779 0.881649 +0.355204 -0.888011 -0.290594 0.370266 -0.878658 -0.301434 +-0.094080 -0.978986 -0.037315 -0.124495 -0.990760 -0.053803 +0.513708 -0.221946 0.822854 0.502602 -0.241080 0.830224 +0.139338 -0.976922 -0.089396 0.088306 -0.993346 -0.073928 +-0.895315 0.360365 -0.216512 -0.895977 0.378198 -0.232789 +-0.864946 0.339956 -0.347333 -0.871714 0.335055 -0.357565 +0.600183 -0.795267 -0.032524 0.620877 -0.783889 -0.005521 +-0.552180 -0.703643 0.422101 -0.516740 -0.736234 0.436966 +0.677354 0.291285 0.662467 0.672247 0.302959 0.675499 +-0.532467 -0.835438 -0.082317 -0.549517 -0.829313 -0.101343 +0.248208 -0.937875 0.214299 0.247553 -0.945070 0.213449 +0.986159 -0.046006 -0.149720 0.993018 -0.039267 -0.111240 +0.953299 0.020895 0.251318 0.968647 0.008188 0.248304 +0.415400 0.823393 -0.377325 0.437257 0.820061 -0.369197 +-0.922696 -0.373041 -0.017712 -0.933004 -0.359589 0.014104 +-0.850003 0.231581 -0.456937 -0.830419 0.281033 -0.481067 +-0.296618 0.640611 -0.699450 -0.304271 0.670525 -0.676620 +-0.747753 0.194430 0.630713 -0.737442 0.196448 0.646211 +-0.393815 -0.847261 0.312657 -0.418378 -0.848704 0.323514 +0.075232 0.942558 0.285791 0.062318 0.948407 0.310871 +0.474811 0.520578 0.702558 0.446951 0.524468 0.724685 +-0.831385 -0.471750 0.264202 -0.839388 -0.482871 0.249526 +0.727615 -0.646969 -0.198336 0.744642 -0.635213 -0.204972 +-0.151663 -0.442635 -0.883460 -0.195581 -0.437028 -0.877926 +0.061195 0.736725 0.664643 0.102612 0.759372 0.642514 +-0.729036 -0.600642 0.317512 -0.743244 -0.600208 0.295531 +0.933948 -0.256380 0.197613 0.941576 -0.231368 0.244754 +-0.295665 -0.533853 0.784300 -0.269575 -0.537483 0.799025 +-0.177209 -0.508976 0.830619 -0.173544 -0.508057 0.843659 +0.437661 -0.891061 0.055126 0.480386 -0.873157 0.082620 +-0.721010 -0.209528 -0.644295 -0.725307 -0.193049 -0.660804 +0.698836 0.042654 0.708708 0.671132 0.079589 0.737053 +0.426182 -0.881046 -0.215977 0.445793 -0.869329 -0.213392 +0.101534 -0.910242 0.381838 0.080324 -0.927950 0.363946 +-0.573753 -0.361938 0.721301 -0.591909 -0.354183 0.724015 +-0.370696 -0.142160 0.904957 -0.385968 -0.150647 0.910129 +-0.080345 -0.502876 -0.861192 -0.135152 -0.522473 -0.841877 +-0.084122 -0.819146 -0.554904 -0.070235 -0.828939 -0.554912 +-0.539206 0.603167 0.577024 -0.532167 0.616359 0.580431 +-0.875122 0.309188 0.341113 -0.890960 0.303581 0.337683 +0.417768 -0.781551 0.453662 0.441373 -0.780383 0.442936 +0.318883 -0.385208 0.856640 0.274230 -0.384046 0.881650 +-0.463099 -0.650380 0.593363 -0.482765 -0.653052 0.583490 +-0.819575 0.422136 0.375453 -0.839704 0.403333 0.363621 +0.865656 0.107456 0.477792 0.883557 0.071073 0.462899 +0.541459 -0.739150 -0.398422 0.577509 -0.712495 -0.398540 +-0.915304 -0.367702 -0.147306 -0.944600 -0.299121 -0.135120 +0.844287 0.420911 -0.308422 0.833618 0.419261 -0.359585 +-0.008117 -0.680993 0.725171 -0.020038 -0.671750 0.740507 +-0.284184 -0.947878 -0.009712 -0.246762 -0.966362 -0.072476 +0.581175 -0.578904 0.562081 0.570228 -0.555817 0.604903 +-0.068035 0.733686 0.663387 -0.079382 0.747687 0.659289 +0.834839 0.441205 0.321554 0.835476 0.458465 0.302969 +0.344289 -0.688462 -0.635046 0.347095 -0.681248 -0.644536 +-0.741812 0.580675 0.326047 -0.763837 0.560267 0.320397 +0.928412 0.085920 0.320951 0.947283 0.080877 0.310023 +-0.853099 -0.083286 0.518019 -0.827980 -0.095635 0.552542 +-0.943110 0.125450 -0.304862 -0.928763 0.166169 -0.331341 +0.648563 0.160335 -0.735116 0.664958 0.157823 -0.730015 +-0.241766 0.713201 -0.648904 -0.211441 0.712119 -0.669462 +0.586432 -0.035265 -0.797856 0.595106 0.005197 -0.803631 +-0.880978 -0.470593 0.023228 -0.897490 -0.437401 0.056498 +0.881697 -0.297474 -0.353507 0.880073 -0.300123 -0.367964 +-0.442608 -0.880300 -0.120320 -0.425067 -0.893645 -0.143935 +-0.286988 0.948187 -0.112519 -0.283097 0.943534 -0.172045 +-0.717072 0.207301 -0.650721 -0.736995 0.222286 -0.638300 +0.645072 -0.324068 -0.676950 0.640070 -0.336946 -0.690491 +-0.656228 -0.113997 -0.733597 -0.688526 -0.127242 -0.713962 +0.694353 -0.260934 0.662251 0.683640 -0.256893 0.683112 +0.074390 -0.942398 -0.301493 0.083886 -0.945372 -0.315016 +0.086941 -0.688045 0.718647 0.074777 -0.698933 0.711267 +0.854486 0.236355 0.451462 0.875307 0.245949 0.416350 +0.788698 0.314897 0.511453 0.780689 0.324111 0.534300 +0.615687 -0.248812 -0.734575 0.630260 -0.262026 -0.730831 +-0.430023 0.049481 0.896361 -0.429582 0.045150 0.901898 +0.170697 0.861329 -0.465635 0.133550 0.881786 -0.452347 +-0.453930 0.207357 -0.859619 -0.468851 0.249648 -0.847263 +-0.888339 0.441954 -0.009481 -0.896936 0.441077 0.030938 +0.603596 -0.789979 0.065467 0.584122 -0.807773 0.079397 +0.906365 0.170354 0.368777 0.926359 0.148758 0.346020 +-0.901749 -0.407950 0.096344 -0.910003 -0.386257 0.150663 +-0.355112 -0.634008 -0.678664 -0.346577 -0.636779 -0.688765 +-0.562472 0.749770 0.344764 -0.567909 0.725159 0.389388 +-0.387991 -0.276332 -0.874552 -0.389095 -0.243366 -0.888469 +0.297012 -0.127741 -0.941601 0.309028 -0.135372 -0.941369 +-0.671895 -0.723172 0.113387 -0.689340 -0.709280 0.147418 +-0.260989 -0.594908 -0.747286 -0.243389 -0.601664 -0.760764 +0.934985 -0.311127 -0.146162 0.944896 -0.281854 -0.166523 +0.926119 -0.060280 0.326805 0.944514 -0.090012 0.315899 +-0.790392 -0.564741 -0.235685 -0.775889 -0.576897 -0.255315 +-0.873039 -0.379046 0.274484 -0.880995 -0.401629 0.250084 +-0.006168 -0.972365 0.201956 0.035010 -0.978407 0.203699 +0.083802 0.991515 0.031814 0.072880 0.996552 0.039651 +0.457718 -0.109240 -0.875260 0.475661 -0.108751 -0.872880 +0.450485 -0.341280 0.821257 0.419968 -0.344934 0.839433 +-0.014560 -0.886891 0.447801 -0.057981 -0.905725 0.419882 +0.275297 -0.008235 -0.953893 0.265755 0.016255 -0.963904 +0.740083 0.555717 -0.352040 0.730729 0.563502 -0.385359 +-0.223699 0.589682 -0.768146 -0.224566 0.589946 -0.775586 +-0.724264 0.644393 -0.239763 -0.713558 0.644632 -0.274380 +0.079266 0.524501 0.840457 0.099202 0.539850 0.835895 +-0.027251 0.543523 -0.833864 -0.063343 0.528944 -0.846290 +0.221287 -0.500092 0.830584 0.219501 -0.454992 0.863019 +-0.073732 -0.951162 0.269760 -0.033184 -0.955925 0.291728 +0.567970 -0.319861 0.751372 0.594142 -0.292996 0.749099 +-0.035738 0.248045 0.960445 -0.029675 0.231854 0.972298 +-0.581078 -0.568866 -0.576971 -0.601785 -0.571976 -0.557403 +-0.323731 0.940519 0.145043 -0.336876 0.925891 0.171000 +0.901506 0.105061 -0.412161 0.906264 0.101906 -0.410244 +-0.478625 0.558905 -0.662767 -0.469764 0.566042 -0.677435 +0.393192 -0.448141 0.799223 0.404558 -0.463976 0.788073 +-0.473944 -0.845524 -0.201776 -0.484372 -0.851159 -0.202265 +0.351978 -0.320867 -0.873849 0.351784 -0.357640 -0.865067 +-0.625214 0.756193 -0.180463 -0.649332 0.739406 -0.177897 +0.558238 0.544300 -0.616697 0.559200 0.547434 -0.622584 +0.081009 0.898619 0.402323 0.094973 0.915422 0.391130 +-0.193798 -0.412815 0.881922 -0.184092 -0.424967 0.886292 +0.965313 0.226138 -0.004641 0.974577 0.223629 -0.013812 +0.258652 -0.803682 -0.518593 0.235261 -0.832668 -0.501314 +0.583472 -0.794374 -0.139971 0.579237 -0.806290 -0.119924 +-0.033058 -0.063332 0.983358 -0.075542 -0.022973 0.996878 +-0.407016 0.075019 -0.909798 -0.375187 0.046727 -0.925771 +0.793365 0.325738 -0.496139 0.798844 0.343966 -0.493494 +-0.193319 -0.191082 -0.951885 -0.200337 -0.176434 -0.963710 +-0.378184 0.922313 -0.056966 -0.418151 0.906755 -0.054262 +-0.791445 -0.151286 -0.570446 -0.819341 -0.171656 -0.547005 +0.177474 -0.979646 -0.005340 0.135653 -0.990741 0.005582 +0.807537 -0.556443 -0.152949 0.801877 -0.580309 -0.142249 +0.833958 -0.193434 0.504821 0.855991 -0.221546 0.467115 +0.830926 -0.506050 0.212103 0.827555 -0.526546 0.194683 +-0.758970 -0.139509 0.628264 -0.743742 -0.172016 0.645955 +0.849023 0.518237 0.064999 0.850983 0.520048 0.073338 +0.933180 -0.242915 -0.249268 0.922978 -0.274709 -0.269530 +0.191711 -0.959055 -0.188646 0.116725 -0.978083 -0.172419 +-0.781307 -0.558852 0.250731 -0.787717 -0.569497 0.234894 +0.442420 0.759682 -0.468107 0.437027 0.765688 -0.471942 +0.605202 0.733165 -0.281162 0.607355 0.740506 -0.287698 +0.494304 0.817826 -0.262780 0.494739 0.842759 -0.212108 +-0.703132 0.687000 -0.134416 -0.703104 0.696899 -0.141337 +-0.749981 -0.522181 -0.395406 -0.767521 -0.496593 -0.405348 +-0.533516 -0.441499 -0.717805 -0.519121 -0.435442 -0.735462 +-0.939044 0.117853 0.288121 -0.930416 0.164654 0.327439 +-0.704127 0.478265 0.521894 -0.700551 0.487262 0.521348 +0.282608 0.840583 -0.456478 0.300738 0.848847 -0.434759 +0.096819 -0.184124 -0.972927 0.081726 -0.177335 -0.980751 +-0.003544 -0.858016 -0.503402 0.005005 -0.846673 -0.532089 +-0.316168 0.751733 -0.571545 -0.310706 0.755548 -0.576723 +-0.604697 -0.465201 -0.642395 -0.599599 -0.430199 -0.674841 +-0.252610 -0.882151 0.381491 -0.284449 -0.882864 0.373684 +-0.002712 -0.902947 -0.414308 0.010940 -0.903053 -0.429391 +-0.215273 -0.838419 0.485603 -0.258361 -0.839426 0.478136 +-0.540748 -0.534326 -0.647879 -0.574576 -0.513707 -0.637156 +-0.279582 -0.709234 -0.642325 -0.271224 -0.694737 -0.666166 +0.324451 0.428255 -0.841871 0.324182 0.428725 -0.843268 +0.120024 -0.380758 -0.906240 0.140817 -0.380923 -0.913821 +-0.241594 0.938233 0.222977 -0.183993 0.937510 0.295334 +-0.657100 0.608589 -0.420617 -0.666367 0.604427 -0.436604 +-0.899489 0.104184 0.395337 -0.915650 0.120378 0.383528 +-0.000336 -0.969046 -0.224791 0.020133 -0.983461 -0.179999 +0.267497 -0.780598 0.552072 0.271078 -0.783447 0.559220 +-0.771022 0.623732 0.083760 -0.776213 0.627686 0.059189 +0.988143 0.017973 -0.060565 0.999070 0.008309 -0.042311 +-0.591056 -0.627351 0.491238 -0.601891 -0.634829 0.484479 +0.108981 -0.033608 0.988366 0.093496 -0.036407 0.994954 +0.094216 -0.759842 -0.637580 0.079729 -0.766410 -0.637385 +0.898081 0.362958 0.251169 0.923058 0.309074 0.228993 +0.124793 0.935385 -0.299492 0.097616 0.932979 -0.346442 +0.895423 -0.301091 0.294807 0.891962 -0.301505 0.336896 +-0.723779 -0.656355 -0.203654 -0.694507 -0.678746 -0.238672 +-0.662423 0.662933 -0.331098 -0.655047 0.664970 -0.358786 +0.046947 -0.981669 -0.073165 0.024375 -0.995856 -0.087613 +0.973240 -0.205744 -0.104938 0.973105 -0.218931 -0.071660 +0.589673 0.786532 0.164937 0.613153 0.771568 0.169487 +-0.988304 0.071325 -0.104952 -0.991504 0.085276 -0.098224 +-0.289567 0.106220 -0.943397 -0.255635 0.114819 -0.959931 +0.865686 0.292924 -0.392368 0.855755 0.326752 -0.401144 +0.862667 -0.265166 0.395264 0.875869 -0.265532 0.402922 +0.042701 -0.151803 0.981717 0.043240 -0.154733 0.987010 +0.301518 0.837062 0.421448 0.290604 0.845211 0.448517 +-0.935163 0.014291 0.325104 -0.937189 0.031241 0.347422 +0.627386 -0.128149 -0.757960 0.621503 -0.114151 -0.775051 +-0.606751 0.608967 -0.489888 -0.632584 0.606061 -0.482211 +-0.100769 0.638339 0.752189 -0.123506 0.642112 0.756597 +-0.111395 0.599653 -0.786672 -0.106800 0.610797 -0.784552 +-0.948475 0.261416 0.128866 -0.948577 0.292620 0.120727 +-0.610046 0.751115 0.247606 -0.581881 0.776228 0.242662 +-0.364092 -0.552092 -0.741056 -0.324404 -0.542198 -0.775102 +-0.833583 0.029649 -0.543256 -0.827361 -0.011763 -0.561548 +-0.715302 -0.668678 0.175168 -0.726736 -0.655741 0.204593 +-0.511311 -0.636241 -0.570836 -0.516956 -0.642935 -0.565148 +-0.673170 0.612065 0.405949 -0.674236 0.600456 0.429951 +-0.796466 -0.389702 -0.444023 -0.818963 -0.362887 -0.444535 +0.891015 0.282408 0.352320 0.899456 0.236734 0.367336 +0.765509 0.007816 0.641567 0.723649 -0.036621 0.689196 +0.126698 -0.609683 0.784963 0.143767 -0.584225 0.798757 +-0.621701 0.467444 0.622141 -0.596250 0.478069 0.644931 +-0.720015 -0.548640 0.408546 -0.708026 -0.571605 0.414689 +-0.569833 0.340512 0.737067 -0.573009 0.367048 0.732759 +-0.141488 0.945576 0.261403 -0.110091 0.958187 0.264117 +-0.525524 -0.351573 -0.767152 -0.565561 -0.343896 -0.749584 +-0.736844 -0.106814 -0.652796 -0.752481 -0.102527 -0.650585 +0.415286 0.906920 0.019261 0.438640 0.898642 -0.006087 +0.279289 -0.254457 -0.923409 0.242376 -0.252527 -0.936741 +-0.531221 -0.793575 0.251123 -0.499851 -0.814347 0.294938 +0.178162 0.947431 0.235321 0.153965 0.951701 0.265632 +0.197568 -0.210641 -0.956137 0.173931 -0.217775 -0.960376 +0.154743 0.210582 0.958807 0.114984 0.222574 0.968111 +-0.188834 -0.307680 0.929210 -0.221717 -0.302727 0.926929 +0.223271 -0.532319 -0.806315 0.246341 -0.536125 -0.807394 +0.115505 -0.507601 -0.847189 0.132791 -0.497964 -0.856971 +-0.355486 0.855573 0.362281 -0.345658 0.858325 0.379209 +-0.140609 0.813963 0.554549 -0.169073 0.804694 0.569106 +-0.522740 0.089398 0.844318 -0.559569 0.055035 0.826955 +-0.559532 0.813573 -0.115899 -0.582319 0.804713 -0.115510 +-0.172695 -0.772631 0.603715 -0.196430 -0.783562 0.589445 +-0.119342 0.404302 0.898903 -0.095969 0.408294 0.907792 +-0.274778 0.368349 -0.878908 -0.229096 0.371661 -0.899657 +-0.332727 0.551005 -0.756115 -0.339178 0.577935 -0.742260 +0.602969 -0.501626 0.607491 0.579340 -0.510273 0.635600 +-0.074134 -0.372092 -0.928598 -0.024162 -0.383376 -0.923276 +-0.942078 0.018773 -0.325141 -0.945586 0.027864 -0.324178 +-0.976603 0.159428 0.082582 -0.980163 0.188800 0.060296 +0.031458 -0.321670 -0.940254 0.064452 -0.300760 -0.951519 +0.798007 -0.253726 -0.538662 0.793326 -0.258299 -0.551285 +-0.733052 -0.461844 0.483301 -0.735976 -0.443351 0.511644 +-0.684875 -0.584249 -0.428025 -0.662363 -0.606502 -0.439807 +0.277717 0.769823 0.548502 0.258583 0.806987 0.530949 +-0.005552 0.932592 -0.328643 -0.020927 0.937716 -0.346771 +0.619927 0.219012 0.738371 0.617398 0.203339 0.759916 +-0.612766 0.768731 0.147277 -0.595278 0.790987 0.141365 +0.199657 -0.856162 -0.450050 0.221101 -0.862469 -0.455260 +-0.629387 -0.770355 0.048568 -0.620229 -0.782817 0.050129 +-0.447799 0.424503 0.778302 -0.461026 0.473595 0.750442 +0.717977 0.634451 0.257197 0.718172 0.648771 0.251645 +-0.152829 0.226267 0.955990 -0.138745 0.224963 0.964439 +-0.422252 -0.718974 0.531666 -0.446713 -0.738805 0.504593 +0.471866 -0.807838 0.323469 0.496657 -0.820525 0.282967 +-0.593828 -0.293734 -0.741348 -0.634906 -0.283804 -0.718575 +-0.321910 -0.490040 -0.798812 -0.311779 -0.488711 -0.814835 +-0.049465 0.104154 -0.986571 -0.029412 0.085317 -0.995920 +0.267518 0.945220 0.176739 0.241235 0.946402 0.214775 +0.464302 -0.213647 -0.851284 0.470560 -0.213346 -0.856187 +0.776748 0.555807 0.279551 0.745936 0.604023 0.280598 +0.657336 0.610622 -0.413850 0.673720 0.586631 -0.449405 +0.363290 0.526912 -0.765045 0.378454 0.540769 -0.751226 +-0.777836 -0.014276 -0.616502 -0.790877 0.000491 -0.611975 +0.623657 -0.694632 -0.348186 0.639286 -0.687080 -0.345304 +0.323872 0.233036 -0.915663 0.330779 0.202405 -0.921747 +-0.599126 0.240692 0.758289 -0.612441 0.231181 0.755957 +0.858997 0.470877 0.190293 0.866374 0.472280 0.162318 +0.766550 -0.567762 -0.263831 0.761451 -0.586945 -0.275116 +0.965874 0.162020 -0.137190 0.969836 0.193327 -0.148467 +0.485230 0.126395 -0.853904 0.511349 0.091482 -0.854490 +0.547168 0.418259 0.717001 0.583866 0.408988 0.701305 +0.574118 -0.441024 0.677188 0.582250 -0.472786 0.661406 +-0.737090 -0.593736 -0.319080 -0.756433 -0.576808 -0.308385 +-0.582039 0.700821 -0.388489 -0.585915 0.700244 -0.407874 +-0.847273 -0.074398 -0.503791 -0.842235 -0.100309 -0.529696 +-0.645570 0.353776 0.670548 -0.629898 0.367750 0.684097 +-0.480859 0.849078 0.188654 -0.499078 0.844932 0.192382 +-0.427030 0.900665 0.092043 -0.448763 0.889922 0.081556 +-0.823527 0.324716 -0.445246 -0.826719 0.330881 -0.455032 +0.189956 0.912287 0.335204 0.189560 0.906783 0.376578 +-0.653177 -0.520237 -0.544959 -0.679466 -0.503531 -0.533650 +0.398295 0.871395 -0.268133 0.396763 0.879292 -0.263484 +-0.006879 -0.225993 -0.968472 -0.028131 -0.189659 -0.981447 +0.086396 -0.527346 0.836863 0.053143 -0.529191 0.846837 +-0.118611 0.934807 -0.309928 -0.124456 0.929681 -0.346704 +-0.782923 0.534048 -0.303535 -0.776315 0.539028 -0.326780 +-0.994572 -0.048979 0.115930 -0.992976 -0.053615 0.105474 +0.687754 -0.720652 -0.006922 0.688341 -0.725368 0.005293 +0.564793 0.467630 -0.673011 0.576169 0.474339 -0.665606 +0.128319 -0.821297 -0.540822 0.142343 -0.850490 -0.506365 +0.146925 -0.600073 -0.781028 0.172880 -0.568424 -0.804368 +0.512746 -0.733442 0.428386 0.491128 -0.747805 0.446746 +-0.431580 0.858038 -0.261046 -0.409841 0.877657 -0.248494 +-0.963891 0.237206 0.015715 -0.964267 0.264871 0.005711 +0.265400 -0.132313 0.942719 0.233688 -0.176177 0.956217 +0.979820 0.056656 -0.190130 0.990043 0.052405 -0.130646 +-0.860898 0.114104 -0.488498 -0.832127 0.103775 -0.544789 +0.477342 0.197217 0.846175 0.504826 0.212732 0.836598 +-0.397961 -0.353640 0.841654 -0.408050 -0.354986 0.841118 +-0.176271 0.663669 -0.718371 -0.187062 0.660796 -0.726881 +0.293419 0.894676 0.316966 0.273456 0.899555 0.340622 +0.508318 -0.106894 0.848441 0.516685 -0.101180 0.850176 +-0.005540 0.842739 -0.519497 -0.015305 0.859748 -0.510489 +0.728152 -0.666188 -0.105298 0.731848 -0.666982 -0.139763 +0.186447 -0.750045 -0.632770 0.185075 -0.781954 -0.595227 +-0.265512 -0.085044 0.953784 -0.269342 -0.092361 0.958606 +-0.428180 -0.802976 -0.399050 -0.438338 -0.804742 -0.400312 +0.337251 0.081211 -0.929737 0.371293 0.059628 -0.926599 +0.620127 -0.237862 0.739318 0.655226 -0.200696 0.728286 +-0.438249 -0.598003 0.662194 -0.447371 -0.589858 0.672255 +0.101546 -0.692895 -0.713857 0.085127 -0.715523 -0.693383 +-0.765528 0.256097 -0.571943 -0.779072 0.277151 -0.562347 +-0.991231 0.047771 0.095694 -0.990211 0.087159 0.109024 +-0.256324 -0.793341 -0.553805 -0.198738 -0.792669 -0.576350 +-0.607863 0.141212 0.776484 -0.632754 0.089322 0.769184 +-0.634385 -0.393839 0.649824 -0.621281 -0.422553 0.659893 +0.136139 0.519771 -0.843457 0.116003 0.518667 -0.847070 +0.068639 0.999029 -0.067901 0.088326 0.994231 -0.060861 +0.494964 -0.861780 -0.081969 0.511622 -0.857748 -0.050120 +-0.421044 -0.853648 -0.277645 -0.415418 -0.876094 -0.244718 +-0.939335 -0.185155 -0.257363 -0.946214 -0.199430 -0.254770 +-0.039262 0.889076 -0.431541 -0.017335 0.895053 -0.445623 +0.375755 -0.845917 0.362443 0.403371 -0.841995 0.358239 +-0.852811 -0.359382 0.363838 -0.855164 -0.396975 0.333323 +0.192280 -0.675583 -0.710356 0.194046 -0.679605 -0.707449 +-0.023263 0.998310 -0.027704 -0.068859 0.997216 -0.028596 +0.705162 -0.460187 -0.526406 0.697975 -0.464236 -0.545267 +-0.280307 0.035246 0.949147 -0.300023 0.010765 0.953871 +-0.969926 -0.097793 0.215886 -0.974491 -0.050803 0.218603 +-0.558727 0.520903 -0.637740 -0.543696 0.531788 -0.649304 +-0.516667 -0.795984 -0.299154 -0.496196 -0.817741 -0.291702 +-0.489563 0.679681 0.529927 -0.467145 0.684955 0.559117 +0.596638 0.331651 0.718500 0.625726 0.324099 0.709526 +0.951246 -0.286984 -0.036265 0.956351 -0.290929 -0.027457 +-0.462176 -0.604195 -0.645034 -0.458236 -0.628687 -0.628309 +0.328706 0.913112 -0.201044 0.379479 0.901859 -0.206512 +-0.008723 0.685100 0.719887 -0.034932 0.700654 0.712646 +-0.643031 0.024040 -0.757980 -0.681410 0.027185 -0.731397 +0.351653 0.741241 -0.565358 0.360486 0.730854 -0.579571 +-0.678598 0.251811 0.687517 -0.677661 0.250136 0.691525 +0.108117 -0.012789 -0.982248 0.095419 -0.019075 -0.995254 +0.680364 -0.050054 -0.716072 0.698990 -0.042648 -0.713859 +-0.332056 0.454233 -0.820876 -0.321816 0.440673 -0.837999 +0.240445 0.714627 0.640600 0.247069 0.734387 0.632166 +0.074380 -0.849918 0.510727 0.043834 -0.875360 0.481481 +-0.180075 -0.914260 -0.341525 -0.190400 -0.928801 -0.317926 +-0.688021 -0.667496 0.259151 -0.679196 -0.682856 0.269074 +0.020532 0.242388 -0.964027 0.017221 0.244346 -0.969535 +0.256252 -0.887151 -0.365562 0.194239 -0.900035 -0.390140 +-0.472067 -0.001524 -0.883237 -0.465281 -0.050744 -0.883707 +0.378725 0.232949 0.889354 0.423794 0.272420 0.863821 +0.762131 0.470461 -0.412147 0.756881 0.484032 -0.439140 +0.022083 -0.539336 -0.838109 0.033211 -0.516507 -0.855639 +-0.829056 0.541171 0.026883 -0.842450 0.538614 0.013145 +0.579924 0.134609 0.792958 0.593143 0.130426 0.794462 +-0.387237 -0.442184 0.802366 -0.419349 -0.422233 0.803658 +0.978524 -0.173595 -0.005549 0.991910 -0.126940 -0.001331 +0.204767 0.448449 -0.872494 0.168995 0.452497 -0.875607 +-0.611034 0.552984 -0.556212 -0.610702 0.587118 -0.531352 +-0.958776 0.160582 -0.205972 -0.959091 0.185352 -0.213983 +-0.170531 0.134833 -0.972244 -0.204855 0.143103 -0.968275 +-0.759489 0.605982 0.217435 -0.750306 0.619847 0.229850 +-0.193230 -0.680500 0.704151 -0.173504 -0.672375 0.719589 +-0.907298 0.352722 0.172368 -0.918520 0.346902 0.189686 +-0.615833 0.385612 -0.681554 -0.623560 0.361359 -0.693248 +-0.425954 -0.449854 -0.779366 -0.426108 -0.437833 -0.791666 +-0.430297 0.514947 0.729603 -0.435951 0.550605 0.711886 +0.785066 -0.585483 0.177981 0.800620 -0.578424 0.156309 +0.507264 -0.543503 0.651389 0.505028 -0.555127 0.660894 +-0.886369 -0.365415 -0.264309 -0.898788 -0.325187 -0.293996 +0.100032 0.829348 -0.539283 0.073583 0.859017 -0.506632 +0.037701 -0.754406 0.652084 0.052368 -0.763461 0.643728 +0.025518 0.457478 -0.881836 0.006593 0.446986 -0.894517 +0.334362 -0.704832 0.616095 0.345706 -0.684674 0.641645 +-0.718141 -0.315437 -0.606392 -0.726095 -0.254650 -0.638702 +-0.042280 -0.941583 -0.324442 -0.034003 -0.952192 -0.303602 +0.709031 -0.635279 0.306647 0.696477 -0.637877 0.328684 +-0.406363 -0.773935 0.456931 -0.431133 -0.781045 0.451767 +0.922216 -0.364581 0.065457 0.917870 -0.388553 0.080880 +0.528231 -0.639488 -0.554260 0.531984 -0.620458 -0.576215 +-0.766233 0.408903 -0.475066 -0.789486 0.376157 -0.484993 +-0.636811 -0.207150 -0.731647 -0.656864 -0.204877 -0.725641 +0.553052 0.822754 0.065052 0.581170 0.812043 0.053181 +-0.247083 0.801544 0.540975 -0.295670 0.788726 0.538972 +0.643650 -0.708697 0.273188 0.645142 -0.718296 0.260466 +0.248570 0.592519 -0.762718 0.257419 0.595032 -0.761362 +-0.350485 -0.917048 -0.121482 -0.326412 -0.933369 -0.149259 +-0.181221 0.029016 0.970402 -0.171337 0.027638 0.984825 +0.382369 0.919299 0.127807 0.404177 0.902227 0.150423 +-0.656448 -0.461069 0.582012 -0.640583 -0.454826 0.618698 +-0.553915 0.021582 -0.830028 -0.566049 -0.030858 -0.823794 +-0.698650 0.692402 0.167293 -0.717404 0.674983 0.172424 +-0.088873 -0.307650 0.944418 -0.090509 -0.313803 0.945164 +0.643440 -0.357138 0.669508 0.644790 -0.349394 0.679831 +-0.722329 0.584145 -0.349377 -0.712384 0.584634 -0.388216 +0.014538 -0.288084 0.953538 0.033314 -0.305026 0.951761 +0.761155 -0.045213 -0.624958 0.770691 -0.029509 -0.636525 +0.352944 -0.174715 0.911453 0.330797 -0.191387 0.924091 +0.545826 -0.144765 -0.817764 0.589784 -0.139280 -0.795460 +-0.686608 0.144116 0.706616 -0.704999 0.110591 0.700532 +-0.425279 -0.905758 0.004181 -0.413976 -0.909675 -0.033394 +0.215088 0.250355 -0.944411 0.163557 0.220459 -0.961586 +-0.064506 0.200709 -0.972040 -0.100263 0.195174 -0.975630 +0.187048 0.054899 -0.974000 0.171533 0.048178 -0.984000 +-0.055102 -0.988295 0.107247 -0.066729 -0.994039 0.086216 +0.582933 0.775402 -0.195253 0.549282 0.815431 -0.182651 +-0.927172 0.260749 -0.229844 -0.932911 0.283166 -0.222474 diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/data/elephant.off b/Optimal_bounding_box/test/Optimal_bounding_box/data/elephant.off new file mode 100644 index 00000000000..cf7cc2b68ca --- /dev/null +++ b/Optimal_bounding_box/test/Optimal_bounding_box/data/elephant.off @@ -0,0 +1,8337 @@ +OFF +2775 5558 0 + +0.262933 0.102269 0.138247 +0.0843142 0.0418575 -0.0419302 +0.0676609 -0.0308717 0.133371 +0.202895 0.468475 0.0802072 +0.113075 -0.465378 -0.0546734 +0.225577 -0.277149 -0.193776 +-0.146525 -0.22403 -0.169286 +-0.0249865 -0.129931 -0.13238 +-0.160965 -0.480027 -0.0707824 +0.0794063 -0.415277 -0.0839096 +0.0469116 -0.050008 0.252355 +-0.0998372 -0.193745 -0.16268 +-0.111131 -0.104825 -0.14166 +-0.061459 -0.0977343 -0.133353 +-0.247783 -0.131539 0.0722694 +-0.145972 -0.486627 -0.0633275 +0.0916759 0.0333604 -0.133002 +-0.184954 -0.325468 -0.133853 +0.0847778 -0.432659 -0.0978527 +-0.210776 -0.299151 0.0751516 +-0.151539 -0.388715 0.01282 +-0.154564 -0.438244 -0.0249412 +-0.123411 -0.0182656 0.0135824 +0.00773278 -0.053391 -0.0428874 +-0.0774524 -0.292395 -0.106335 +0.0201594 -0.263586 0.119859 +-0.105646 -0.0365155 -0.0770751 +-0.113391 -0.41896 -0.0906771 +-0.128213 -0.46259 -0.0994907 +-0.160526 -0.468057 -0.0393445 +0.197609 -0.127492 -0.0574767 +0.0757306 -0.449539 -0.0614557 +0.147148 -0.412461 -0.0801639 +0.103782 -0.333007 0.0288926 +0.108917 -0.401981 -0.00841926 +0.11392 -0.408931 -0.0973654 +0.129733 -0.31331 -0.0672325 +0.0904388 -0.356531 -0.0803906 +0.0359798 -0.255445 -0.113562 +-0.22312 -0.107007 -0.0611904 +-0.163408 -0.433458 -0.0704785 +-0.0915185 -0.473885 -0.0165533 +-0.141417 -0.474418 -0.0834065 +-0.0944539 -0.479454 -0.0663683 +-0.085985 -0.101282 0.158093 +-0.0225438 -0.0889567 -0.0848587 +0.092707 -0.109496 -0.114561 +-0.159213 -0.159272 -0.138793 +-0.24541 -0.230248 -0.110578 +0.183744 -0.231931 0.0176086 +0.294273 -0.0955008 0.116328 +-0.16477 -0.385872 -0.0413331 +-0.185303 -0.313456 -0.00374653 +-0.297084 -0.262835 -0.00415653 +0.167756 -0.128776 0.197921 +-0.0273811 0.0608812 -0.0989637 +0.208303 0.00452459 -0.0746544 +-0.150831 -0.448909 -0.0901866 +-0.0720206 -0.147118 -0.154796 +-0.0197986 -0.210658 -0.154154 +-0.130593 -0.498558 -0.021161 +0.129662 -0.373473 -0.0794411 +-0.120692 -0.481168 -0.0685411 +-0.108692 -0.494274 -0.0429275 +-0.0970902 -0.252938 -0.14843 +-0.0098054 -0.335319 -0.0147292 +0.0769246 -0.410346 -0.0391239 +-0.132409 -0.464154 -0.0197707 +-0.102806 -0.4217 0.00855496 +-0.0760332 -0.34128 0.100617 +-0.104435 -0.377391 0.0553722 +-0.14788 -0.33188 0.0922673 +-0.151409 -0.218926 0.165812 +-0.111518 -0.286925 0.148566 +-0.0458796 -0.210094 0.18627 +0.0439919 -0.147905 0.137964 +-0.0358575 -0.361749 0.0457868 +0.0284346 -0.311464 0.0537885 +0.0409609 -0.0869988 -0.085353 +0.118462 -0.0465078 -0.0483438 +-0.141108 -0.422593 -0.0846889 +-0.129145 -0.379198 -0.0712284 +-0.149426 -0.329507 -0.0473837 +-0.212723 -0.300322 -0.0706413 +-0.156151 -0.403775 -0.0651516 +-0.077704 -0.400019 -0.0437424 +-0.0783601 -0.342543 -0.0687412 +-0.0202922 -0.309739 -0.0758353 +0.0501325 -0.290557 -0.0430839 +0.0954448 -0.256567 0.0733017 +0.144565 -0.158299 0.0913557 +0.0562207 -0.179498 -0.140905 +0.16863 -0.175124 -0.176771 +0.121523 -0.241503 -0.138152 +0.196749 0.136407 0.00365942 +0.14057 0.277481 0.154966 +0.156168 -0.385879 -0.0324162 +-0.146564 -0.288069 -0.168907 +-0.212533 -0.256019 -0.170893 +0.0775241 -0.353084 -0.0221894 +-0.161054 -0.48311 -0.0516067 +-0.151386 -0.488726 -0.0297486 +-0.167299 -0.464731 -0.058517 +-0.167494 -0.44542 -0.0440266 +-0.166175 -0.416312 -0.0405929 +-0.155665 -0.409399 -0.0112037 +-0.130777 -0.428881 -0.00549876 +-0.162855 -0.460869 -0.0783452 +-0.0949104 -0.0628065 -0.118829 +-0.171364 -0.0681205 -0.104606 +-0.189411 -0.0391257 -0.0301772 +-0.201329 -0.0450332 0.0672375 +-0.0621659 -0.0595357 -0.0819357 +-0.0724451 -0.0386843 -0.0212262 +-0.0317016 -0.00827391 0.0812953 +0.125617 -0.445138 -0.086335 +0.16914 -0.45638 -0.0514974 +-0.188699 -0.102786 0.151505 +-0.127982 -0.406882 0.0143939 +-0.130706 -0.384 0.0373578 +-0.17253 -0.34721 0.0442322 +-0.136499 -0.357829 0.0655808 +-0.101729 -0.398953 0.0314689 +-0.06477 -0.393705 0.00175031 +-0.0683606 -0.382507 0.0422398 +-0.0619729 -0.361557 0.0725343 +-0.0129886 -0.329893 0.099078 +-0.0485077 -0.306718 0.14972 +-0.0586671 -0.359537 -0.0297503 +-0.105132 -0.354471 0.0834642 +-0.111953 -0.324339 0.110194 +-0.146952 -0.298663 0.122985 +-0.147935 -0.259899 0.146585 +-0.224685 -0.230598 0.12386 +-0.194785 -0.274899 0.125615 +-0.1144 -0.250007 0.185149 +-0.10665 -0.185071 0.204627 +-0.155805 -0.154327 0.174517 +-0.215755 -0.165279 0.142947 +-0.0743299 -0.277016 0.17853 +-0.0218198 -0.257755 0.16445 +0.000800113 -0.199671 0.138749 +-0.0254547 -0.133829 0.140633 +0.0635315 -0.20852 0.111271 +-0.0256804 -0.0569419 0.140514 +-0.0948894 -0.0414189 0.110395 +-0.0705488 -0.0374163 0.0415111 +-0.00760713 -0.0195458 0.0164934 +0.0499878 0.0289775 0.0673286 +0.140466 0.0718009 0.144428 +-0.00188983 0.0792593 -0.003093 +0.0559872 -0.0140882 -0.011506 +-0.227407 -0.0888195 0.0117762 +-0.273528 -0.167121 -0.0102922 +-0.0402782 -0.263586 -0.140793 +-0.137564 -0.296782 -0.109847 +-0.166109 -0.381665 -0.0120175 +-0.16983 -0.360755 0.0137933 +-0.16456 -0.354211 -0.0308766 +-0.185156 -0.334386 0.0190529 +-0.207978 -0.298552 0.0310885 +-0.252507 -0.243462 0.0511336 +-0.223388 -0.268692 -0.019703 +-0.193938 -0.322649 0.048456 +-0.175095 -0.332532 0.0736524 +-0.176111 -0.310734 0.103586 +-0.147337 -0.494175 -0.0467278 +-0.129359 -0.490613 -0.0537016 +-0.148829 -0.364106 -0.0543963 +-0.120087 -0.343197 -0.0662243 +-0.130345 -0.305692 -0.0722136 +-0.171529 -0.299424 -0.0833938 +-0.181343 -0.292949 -0.0416997 +0.207831 -0.217496 -0.0966998 +0.180453 0.174523 0.151623 +0.0997558 -0.44202 -0.0211251 +0.141829 -0.427452 -0.0246256 +0.231902 -0.0518172 0.0262484 +0.222165 -0.00765217 0.131632 +0.257605 0.0468554 0.0496674 +0.134457 -0.362329 0.00455646 +0.162364 -0.298449 0.0119315 +0.167632 -0.334853 -0.0258239 +0.166781 -0.258058 -0.0451734 +0.196618 -0.203737 -0.0367216 +0.204966 -0.148702 0.029823 +0.188775 -0.0899398 0.0842549 +0.118735 -0.0897053 0.120666 +0.108518 -0.0623755 0.19827 +0.0943505 -0.134977 0.262277 +0.0987744 0.0186293 0.19077 +0.164162 -0.016078 0.17849 +0.217401 -0.0732307 0.174029 +0.244384 -0.159022 0.158735 +0.0938974 -0.414078 -0.0986619 +0.0882094 -0.386204 -0.0874415 +0.110237 -0.433985 -0.106491 +0.0752909 -0.377302 -0.0545033 +0.136893 -0.424401 -0.103861 +0.101623 -0.446793 -0.0879738 +0.0803589 -0.447974 -0.0828166 +0.0955794 -0.458697 -0.0690652 +0.0852254 -0.472952 -0.043714 +0.0423481 -0.131534 -0.117698 +0.0102534 -0.163639 -0.135844 +-0.0294235 -0.16777 -0.154302 +-0.0581903 -0.19678 -0.162941 +-0.0495263 -0.23206 -0.157295 +0.0213258 -0.204668 -0.142847 +0.0591534 -0.221375 -0.128414 +0.094939 -0.204956 -0.158559 +0.102368 -0.149902 -0.152017 +0.161838 -0.127189 -0.119413 +0.0883157 -0.255475 -0.0965547 +0.00337956 -0.243572 -0.138992 +-0.00441584 -0.28038 -0.109802 +0.139454 -0.244447 -0.0884262 +0.17799 -0.253819 -0.13106 +0.239512 -0.249475 -0.139746 +0.239769 -0.199663 -0.201225 +0.139899 -0.220537 -0.184787 +0.188104 -0.214287 -0.208834 +0.241446 -0.186766 -0.139849 +0.209446 -0.161297 -0.101029 +-0.199048 -0.317265 -0.100601 +-0.293252 -0.31357 -0.122798 +-0.243299 -0.355691 -0.130502 +-0.247594 -0.319033 -0.0988683 +-0.291668 -0.287409 -0.0637038 +-0.248832 -0.272185 -0.0865389 +-0.259174 -0.220646 -0.0469428 +-0.282126 -0.263379 -0.124759 +-0.269731 -0.294935 -0.18724 +-0.247297 -0.165961 -0.0866554 +0.0601914 -0.0464014 -0.0549033 +-0.211085 -0.18579 -0.128927 +-0.200721 -0.132547 -0.108259 +-0.0634953 -0.15489 0.179525 +0.153912 -0.0887253 -0.0733484 +0.185145 -0.0471144 -0.0260532 +0.211443 0.0144377 0.0032337 +0.139575 0.0029693 0.000737671 +0.166751 0.0710484 -0.0323169 +0.107842 0.107181 0.0410238 +0.241648 0.0800111 -0.0150955 +-0.140262 -0.4992 -0.033581 +-0.123763 -0.497978 -0.0364981 +-0.108133 -0.495253 -0.0202341 +-0.1219 -0.481038 -0.0158085 +-0.110456 -0.461331 -0.014079 +-0.087635 -0.441699 -0.0445804 +-0.0916102 -0.451765 -0.0239283 +-0.0811529 -0.421697 -0.020421 +-0.0723115 -0.470105 -0.0423155 +-0.102577 -0.44033 -0.0062072 +-0.139118 -0.480546 -0.0199347 +-0.149266 -0.466768 -0.0254061 +0.222317 -0.0925366 -0.0161067 +-0.0417433 -0.361447 0.00632817 +-0.00965295 -0.347119 0.0218202 +0.0216724 -0.318231 0.010836 +-0.00474667 -0.341486 0.0613973 +0.0698488 -0.285166 0.0205835 +-0.108371 -0.29389 -0.0941984 +-0.11094 -0.279255 -0.127432 +-0.0852691 -0.31423 -0.083395 +-0.0516331 -0.309713 -0.0908278 +-0.0463843 -0.329032 -0.0615785 +-0.13427 -0.295211 -0.140976 +-0.16029 -0.312528 -0.151535 +-0.208046 -0.313472 -0.188061 +-0.177638 -0.29982 -0.178676 +-0.173332 -0.259819 -0.179118 +-0.186949 -0.225139 -0.161631 +-0.121077 -0.271737 -0.158365 +-0.222098 -0.229029 -0.143015 +-0.254895 -0.254361 -0.158387 +-0.119307 -0.241249 -0.168619 +-0.0940058 -0.224454 -0.161034 +-0.119452 -0.213541 -0.164903 +-0.133444 -0.181194 -0.153714 +-0.123212 -0.142937 -0.146434 +-0.154852 -0.114002 -0.127562 +-0.16919 -0.193253 -0.151916 +-0.202578 -0.281459 -0.18846 +-0.238459 -0.276537 -0.185897 +-0.240282 -0.308392 -0.197824 +-0.31592 -0.411023 -0.222975 +-0.28556 -0.354091 -0.210885 +-0.235315 -0.349789 -0.176342 +-0.247249 -0.413591 -0.205119 +-0.313616 -0.39085 -0.145549 +-0.265064 -0.38952 -0.162643 +-0.137308 -0.0765217 -0.126585 +-0.138269 -0.043252 -0.101811 +-0.149787 -0.024537 -0.0569204 +-0.190238 -0.325155 -0.164883 +-0.214126 -0.342005 -0.145019 +-0.11169 -0.0249744 -0.0351987 +-0.154494 -0.0206052 -0.0150451 +-0.170024 -0.0235376 0.033341 +-0.149964 -0.0212297 0.0915499 +-0.146292 -0.0570396 0.143171 +-0.204533 -0.050976 0.0222898 +-0.222839 -0.0748301 0.0497298 +-0.218112 -0.0836084 0.106186 +-0.241131 -0.10804 0.0423425 +-0.253857 -0.126023 0.000914005 +-0.268045 -0.155579 0.0359862 +-0.254096 -0.191499 0.0837602 +-0.284127 -0.206805 0.0257642 +-0.255388 -0.139415 -0.0455141 +-0.266486 -0.179542 -0.0496151 +-0.255448 -0.200689 -0.0776309 +-0.238672 -0.192995 -0.107883 +-0.225097 -0.163824 -0.109937 +-0.22995 -0.135947 -0.0896828 +-0.209528 -0.114818 -0.0862766 +-0.197715 -0.0771741 -0.074156 +-0.18152 -0.102481 -0.104911 +-0.212552 -0.0754645 -0.0336012 +-0.179069 -0.0426745 -0.0757348 +-0.191113 -0.0400122 0.118805 +0.0761558 -0.344791 -0.0536197 +0.0734921 -0.316433 -0.0291825 +0.0865869 -0.298841 -0.0691012 +0.0805876 -0.328744 0.0029047 +0.0952029 -0.361348 0.00820626 +0.11906 -0.273469 -0.0673767 +0.0841053 -0.310717 0.0264162 +0.125408 -0.292597 0.041066 +0.0878905 -0.285295 0.052224 +0.0491288 -0.272854 0.0806291 +0.143869 -0.242882 0.0528378 +0.117789 -0.207199 0.0870858 +0.169353 -0.193132 0.0552639 +0.0969256 -0.166289 0.115505 +0.054006 -0.288058 0.0505697 +0.0199581 -0.301066 0.0971587 +-0.00766116 -0.296894 0.132807 +0.0766599 -0.302889 0.00259846 +0.0459981 -0.299327 0.00649094 +0.0275534 -0.307808 -0.0222832 +0.0149271 -0.300169 -0.0594622 +0.0407712 -0.276916 -0.0798141 +0.0598138 -0.291021 -0.0166231 +0.105499 -0.310063 0.042044 +0.129965 -0.318676 0.0271739 +-0.0843085 -0.494264 -0.0321529 +-0.0752323 -0.238787 0.196776 +-0.295928 -0.43397 -0.176216 +0.0851801 -0.382062 -0.0130588 +0.0187394 -0.0952484 0.145146 +0.0700063 -0.10227 0.135872 +0.0221841 -0.0461712 0.144279 +0.0234739 0.0145751 0.123876 +-0.00955997 -0.0145334 0.135796 +-0.0455413 -0.0274983 0.116817 +-0.0630042 -0.0646849 0.123712 +-0.0996182 -0.0685448 0.139479 +-0.129134 -0.0937854 0.159793 +-0.112763 -0.133107 0.183753 +-0.0586283 -0.0384282 0.0801443 +-0.0976008 -0.0306336 0.0712047 +-0.187313 -0.236737 0.146886 +-0.186919 -0.194456 0.158247 +-0.276732 -0.200888 -0.0224537 +-0.291326 -0.23573 -0.0313163 +-0.262172 -0.26119 -0.0228289 +-0.244304 -0.258186 0.0138536 +-0.238049 -0.253808 -0.053252 +-0.278468 -0.245353 0.0237178 +-0.250374 -0.233381 -0.0762153 +-0.317786 -0.266287 -0.0397057 +-0.29694 -0.227134 0.00135872 +-0.28761 -0.282597 -0.0302299 +-0.0768305 -0.203891 0.202176 +-0.107975 -0.220055 0.202264 +-0.134773 -0.20066 0.190676 +-0.13214 -0.167949 0.192848 +-0.157713 -0.187173 0.17141 +-0.0792541 -0.17391 0.197354 +-0.103166 -0.157466 0.196315 +-0.0861693 -0.139966 0.183699 +-0.0642112 -0.126048 0.16286 +-0.0525585 -0.0978366 0.139755 +0.173523 -0.0454835 0.124705 +0.124762 -0.0100876 0.132612 +0.0801162 0.0231847 0.117816 +0.0903158 0.0691509 0.0824377 +0.111706 0.138719 0.113497 +0.109897 0.0476799 0.0291314 +0.0568194 0.0789592 0.018431 +0.166721 0.186565 0.0672199 +0.252858 0.160254 0.0700128 +0.103948 0.0891733 -0.0142249 +0.151331 0.103958 0.00831307 +0.156258 0.148984 0.0332697 +0.195526 0.176469 0.0301312 +0.246249 0.159404 0.0147221 +0.272985 0.107792 0.0403664 +0.220496 0.208803 0.0718273 +0.172006 0.242405 0.105809 +0.284857 0.213191 0.163319 +0.220004 0.262975 0.168971 +0.243752 0.187223 0.124992 +0.303317 0.156118 0.132187 +0.124557 0.160014 0.070217 +0.145476 0.178627 0.113721 +0.143822 0.145597 0.146983 +0.199699 0.112576 0.148784 +0.221259 0.0552492 0.134196 +0.124553 0.109697 0.139987 +0.100062 0.0751807 0.125633 +0.107686 0.0453443 0.15701 +0.152453 0.0251604 0.154394 +0.160741 0.1045 0.158385 +0.183054 0.0708926 0.1447 +0.188656 0.0314673 0.13741 +0.286002 0.0789154 0.0896861 +0.044874 0.0868553 -0.0397086 +0.0292084 0.0351428 -0.0773123 +-0.00652383 0.0868322 -0.0563984 +0.153395 -0.330946 0.00521793 +0.165687 0.227811 0.159326 +0.176713 -0.253714 -0.180764 +0.276141 0.126578 0.0974557 +-0.0329659 -0.0648403 -0.0508016 +-0.022748 -0.0460692 -0.0136176 +-0.0397109 -0.0394184 0.0195973 +0.00993129 -0.0278328 -0.0155697 +0.0270531 -0.00832198 0.0106523 +0.0103826 0.00500549 0.0538795 +0.0666135 0.0125544 0.0261568 +0.103369 0.00889595 0.155654 +0.11659 -0.0298082 0.170544 +0.153029 -0.0696813 0.168481 +0.113461 -0.0186162 0.216944 +0.10035 -0.0580327 0.251516 +0.150235 -0.084971 0.233939 +0.0675669 -0.0946043 0.253879 +0.0719166 -0.0391569 0.214813 +0.10687 -0.103697 0.22877 +0.136543 -0.144876 0.235107 +0.147147 -0.0351617 0.149371 +0.1197 -0.0491892 0.122959 +0.148505 -0.0696344 0.112799 +0.152678 -0.114026 0.101195 +0.181641 -0.136376 0.0700095 +0.177794 -0.0667748 0.102185 +0.219377 -0.0856118 0.124697 +0.231869 -0.0572983 0.0801841 +0.250938 -0.00881912 0.0578761 +0.198815 -0.0628459 0.124187 +0.177363 -0.0676828 0.147605 +0.177944 -0.101552 0.169756 +0.213844 -0.114113 0.199683 +0.250347 -0.109904 0.165803 +0.259893 -0.130195 0.122038 +0.180633 -0.0723966 0.203599 +0.114076 -0.0955963 0.272717 +0.201886 -0.0333539 0.161782 +0.240288 -0.0485439 0.141813 +0.261312 -0.0227503 0.104643 +0.273982 -0.0593402 0.119899 +0.280362 -0.074792 0.0701015 +0.238595 0.0177583 0.0951404 +0.14643 -0.0478943 0.212489 +-0.227331 -0.265687 0.0979085 +-0.244646 -0.230401 0.0887962 +-0.293688 -0.268968 -0.164669 +-0.297979 -0.308788 -0.162348 +-0.312868 -0.346598 -0.144794 +-0.344082 -0.367401 -0.192127 +-0.317302 -0.337357 -0.184462 +-0.280828 -0.350074 -0.123607 +0.105148 0.105807 0.112878 +0.112708 0.122082 0.0774818 +0.133565 0.128779 0.0503619 +-0.153371 -0.370618 0.0324641 +0.254239 -0.0926281 0.0998171 +-0.0128437 0.0136567 0.10826 +0.0175667 0.0217155 0.0871281 +0.0477136 0.0340255 0.104217 +0.0750182 0.0489044 0.100742 +0.0776037 0.0433948 0.0700673 +0.0973389 0.0603657 0.0539823 +0.0861821 0.0686274 0.0252903 +0.0735784 0.0589072 -0.0094551 +0.0829016 0.102631 0.0164944 +0.0811061 0.0911963 0.0569078 +0.0940457 0.0476479 0.121838 +0.105428 0.0231317 0.131003 +0.0916425 -0.00738665 0.126455 +0.0604145 5.34629e-005 0.128347 +0.10359 0.0595398 0.00049955 +0.144344 0.0457444 0.00327488 +0.122523 0.0419513 -0.0300499 +0.11811 0.0162342 -0.0830375 +0.170091 0.0155571 -0.145681 +0.138389 0.0626357 -0.0743287 +0.165069 0.0235027 -0.0532363 +0.177768 0.0409007 -0.100742 +0.136707 0.0380317 -0.122381 +0.124141 0.00775387 -0.157586 +0.154959 -0.000810753 -0.105169 +0.105591 0.0562623 -0.100272 +0.0594242 0.0548004 -0.106957 +0.201162 -0.0168583 -0.120783 +0.0976411 0.0972697 0.0801317 +0.0943337 0.0848541 0.102457 +0.0890479 0.0650811 0.109825 +0.0389773 0.0745551 -0.0779593 +0.0138551 0.0593589 -0.108474 +0.0773146 0.0765993 -0.0629692 +0.118409 0.00125651 -0.11931 +0.14578 -0.0101392 -0.137264 +0.178622 -0.0192175 -0.148664 +0.15461 0.0388676 -0.0266866 +0.193622 0.0322602 -0.0272748 +0.1942 0.050466 -0.0642106 +0.173634 0.0303747 -0.00069076 +0.179101 -0.0110744 -0.00523936 +0.230507 0.0422098 -0.0173425 +0.202418 0.070871 -0.0135348 +0.22302 0.0184239 -0.0441485 +0.215157 -0.0248187 0.00288885 +0.233855 -0.00344678 0.0259658 +0.238719 0.033163 0.0205233 +0.25481 0.0672767 0.0179763 +0.222129 -0.0581209 -0.00731524 +0.227145 -0.0819987 0.0145053 +0.219253 -0.118982 0.0109807 +0.211654 -0.158762 -0.0192499 +0.210611 -0.101269 0.0490966 +0.200451 -0.190104 0.0116714 +0.203938 -0.0712158 -0.0282028 +0.173774 -0.0735362 -0.0475631 +0.2027 -0.10102 -0.0400541 +0.212795 -0.129107 -0.0298945 +0.206091 -0.151217 -0.0455168 +0.202467 -0.150775 -0.0745887 +0.209378 -0.187531 -0.0743719 +0.181149 -0.126003 -0.0892617 +0.205972 -0.177843 -0.0383337 +0.188301 -0.142819 -0.114464 +0.208779 -0.164491 -0.140437 +0.171227 -0.151151 -0.147387 +0.136617 -0.138704 -0.143839 +0.131975 -0.166643 -0.169617 +0.128263 -0.113939 -0.11894 +0.116875 -0.0858965 -0.091059 +0.0786764 -0.0829677 -0.090746 +0.187859 -0.214057 -0.0686071 +0.175679 -0.237132 -0.0957975 +0.178163 -0.10588 -0.0665832 +0.269129 0.0763722 0.0451229 +0.27889 0.058723 0.0679827 +0.267652 0.0453551 0.105512 +0.2613 0.0363273 0.0775663 +0.250278 0.0199214 0.0566543 +0.250269 0.00638094 0.0769677 +0.262967 -0.0160504 0.0796628 +0.285344 -0.0433845 0.0872574 +0.24971 -0.0386027 0.0640826 +0.229012 -0.0528564 0.0533874 +0.210073 -0.0746435 0.0657137 +0.221889 -0.0775407 0.0410909 +0.302572 -0.0710887 0.0949218 +0.236871 -0.0290995 0.0413907 +0.21774 0.0486965 -0.0445342 +0.224846 0.0339602 -0.0740774 +0.244042 0.0044793 -0.10874 +0.254336 0.102378 0.0100739 +0.220262 0.108437 -0.00385435 +0.184431 0.103867 -0.0063665 +0.227766 0.138272 0.00117268 +0.21603 0.168687 0.00560537 +0.214962 0.252952 4.36931e-005 +0.24674 0.211475 0.00674743 +0.208103 0.206716 0.00898043 +0.198252 0.239152 0.0425261 +0.241235 0.183275 -0.00372162 +0.24846 0.187657 0.0253371 +0.236173 0.217937 0.0406376 +0.208251 0.202717 0.0430183 +0.190765 0.204953 0.0676283 +0.199822 0.228771 0.0907818 +0.212055 0.262964 0.121847 +0.167888 0.20936 0.0941323 +0.230768 0.216285 0.106419 +0.226441 0.220307 0.1523 +0.160904 0.217518 0.126833 +0.151535 0.251202 0.133586 +0.158786 0.306935 0.0984538 +0.193903 0.396086 0.195106 +0.119767 0.364922 0.154966 +0.158434 0.284691 0.125614 +0.188265 0.327264 0.175224 +0.139712 0.323472 0.144742 +0.247398 0.226772 0.208026 +0.162628 0.357991 0.158091 +0.132463 0.334186 0.215838 +0.184892 0.418747 0.128073 +0.148158 0.405567 0.1589 +0.116952 0.392105 0.208798 +0.128904 0.307582 0.18276 +0.173163 0.280669 0.197839 +0.237808 0.190239 0.0542196 +0.242415 0.187695 0.0885314 +0.257589 0.159811 0.105872 +0.25799 0.149475 0.1552 +0.249199 0.167605 0.0439231 +0.270589 0.141138 0.0478035 +0.291007 0.120776 0.0668204 +0.27986 0.0943457 0.0648346 +0.262028 0.128688 0.0220064 +0.283888 0.104244 0.08796 +0.278117 0.09277 0.114653 +0.296211 0.119268 0.134225 +0.25745 0.0686993 0.129638 +0.231499 0.0874258 0.144645 +0.23624 0.121986 0.150481 +0.21822 0.158716 0.152133 +0.276736 0.0681718 0.110294 +0.286087 0.0545245 0.0921962 +0.114064 0.342002 0.184102 +0.184346 0.361594 0.187357 +0.161147 0.378013 0.229421 +0.186402 0.32651 0.232026 +0.224199 0.278314 0.231623 +0.178684 0.387524 0.165454 +0.207571 0.416517 0.162223 +0.115261 0.360345 0.210089 +0.111327 0.375408 0.183082 +0.123148 0.405595 0.17979 +0.161317 0.441861 0.200022 +0.134075 0.42215 0.208124 +0.166581 0.413272 0.221996 +0.184888 0.467555 0.155941 +0.139501 0.435526 0.173911 +0.158717 0.435906 0.144337 +0.167498 0.45215 0.103084 +0.137763 0.359978 0.22921 +0.165611 0.348074 0.227085 +0.15984 0.318857 0.217125 +0.185554 0.304169 0.211919 +0.205103 0.278784 0.204981 +0.244841 0.279219 0.196675 +0.226891 0.25345 0.209087 +0.216714 0.31142 0.225032 +0.18164 0.33693 0.20427 +0.203702 0.303717 0.18726 +0.193627 0.296232 0.146589 +0.191637 0.257284 0.18429 +0.157803 0.257523 0.177293 +0.175634 0.311565 0.125155 +0.161107 0.457828 0.173386 +0.194169 0.447882 0.185268 +0.194408 0.477711 0.118315 +0.219599 0.449898 0.13857 +0.135294 0.387364 0.228733 +0.145147 0.282789 0.187345 +0.143956 0.303159 0.203618 +0.177446 0.366384 0.212315 +0.179329 0.391491 0.217312 +0.18672 0.412483 0.210145 +0.202606 0.421792 0.189409 +0.174085 0.42914 0.210627 +0.153641 0.426813 0.21312 +0.144424 0.408706 0.223131 +0.190464 0.428693 0.201747 +0.178837 0.441581 0.19921 +0.169704 0.452082 0.187978 +0.180705 0.459908 0.173619 +0.202088 0.458198 0.166952 +0.151672 0.449754 0.186725 +0.142475 0.436806 0.198199 +0.127991 0.425256 0.188222 +0.210178 0.437176 0.172385 +0.119636 0.410278 0.199562 +0.206557 0.46857 0.145869 +0.215386 0.468035 0.123827 +0.207969 0.436894 0.106764 +0.212477 0.477963 0.10116 +0.128023 0.4054 0.215288 +0.223073 0.454408 0.0921651 +0.184017 0.321535 0.149004 +0.164058 0.339436 0.133054 +0.141763 0.356765 0.138374 +0.138767 0.331395 0.111494 +0.18387 0.5 0.0894472 +0.178253 0.341112 0.15974 +0.158692 0.397227 0.229447 +0.261987 0.258572 0.22454 +0.209557 0.191204 0.156985 +0.19703 0.220129 0.168363 +0.114158 0.395299 0.191384 +0.237163 0.239354 0.0176536 +0.22873 0.228755 -0.0079498 +0.204237 0.229854 -0.000985107 +0.191898 0.248869 0.0164149 +0.195144 0.299533 0.0501168 +0.211408 0.277777 0.0261684 +0.181525 0.269092 0.042102 +0.232338 -0.0296485 0.018274 +0.220704 0.448894 0.117889 +0.211836 0.430361 0.128709 +0.200007 0.22745 0.0221073 +0.206622 0.221816 0.0395427 +0.223655 0.239447 0.0484776 +0.206846 0.263872 0.061817 +0.192412 0.289403 0.0880222 +0.200823 -0.0669613 0.089238 +0.1998 0.487191 0.0879627 +0.178418 0.478766 0.0726805 +0.171907 0.478 0.098484 +0.179607 0.4432 0.070784 +0.215421 0.44036 0.0572748 +0.206111 0.438517 0.081171 +0.184196 0.432818 0.0953164 +0.172787 0.433405 0.115219 +0.16681 0.454422 0.128591 +0.158037 0.463512 0.080819 +0.300027 -0.106441 0.0798503 +0.301565 -0.138608 0.110073 +0.223785 -0.0676095 0.104371 +0.244386 -0.0720528 0.0937201 +0.25624 -0.0594904 0.0758547 +0.271472 -0.0437947 0.0690266 +0.283677 -0.0568988 0.0744319 +0.294284 -0.0698767 0.0795338 +0.293906 -0.0887216 0.0736412 +0.275743 -0.101071 0.0877101 +0.309738 -0.0894098 0.0874741 +0.287014 -0.123527 0.0945964 +0.311125 -0.118131 0.0991123 +0.298899 -0.117613 0.118193 +0.276193 -0.109289 0.135451 +0.270493 -0.137621 0.153632 +0.286312 -0.136798 0.132025 +0.257826 -0.0797919 0.144654 +0.303792 -0.0864306 0.104131 +0.28817 -0.0747287 0.113826 +0.276632 -0.0878111 0.128274 +0.30695 -0.103289 0.107245 +0.287682 -0.0559229 0.10414 +0.272738 -0.0407993 0.108633 +0.253435 -0.0365139 0.124117 +0.295415 -0.0573592 0.0898843 +0.270105 -0.0629299 0.0693418 +0.263375 -0.0783235 0.0820667 +-0.216962 -0.20051 0.140681 +-0.236047 -0.180496 0.115013 +-0.230292 -0.136771 0.112494 +-0.247625 -0.159292 0.0914591 +-0.209896 -0.129892 0.141237 +0.222682 0.288177 0.190351 +0.233778 0.296853 0.212089 +0.209365 0.287061 0.167624 +0.208618 0.271128 0.146657 +0.223776 0.247151 0.14266 +0.250594 0.280585 0.221005 +0.215525 0.238928 0.164607 +0.248724 0.243405 0.176599 +0.282927 0.23674 0.194658 +0.253819 0.208937 0.178714 +0.265424 0.184312 0.155732 +0.308614 0.169998 0.183237 +0.273365 0.179729 0.192265 +0.265912 0.204786 0.204674 +0.300509 0.203464 0.194384 +0.281969 0.151677 0.177526 +0.279246 0.127373 0.158699 +0.31079 0.143896 0.162421 +0.30954 0.171009 0.155179 +0.288086 0.1804 0.137744 +0.264265 0.175268 0.132545 +0.241184 0.168571 0.143536 +0.282052 0.162312 0.123541 +0.290218 0.138764 0.11928 +0.232003 0.191432 0.146429 +0.237199 0.211128 0.131059 +0.175486 0.13591 0.157401 +0.244193 0.0453066 0.121153 +0.216838 0.0295154 0.115567 +0.0778181 0.0182774 -0.0959304 +0.132697 0.385267 0.165833 +0.155812 0.38306 0.160495 +-0.00373338 0.0386319 -0.0871428 +0.0052284 0.0508015 -0.0521262 +-0.0272532 0.0521944 -0.0650671 +-0.0417118 0.0760468 -0.0274796 +0.0432101 0.0478592 -0.0430105 +0.0360437 0.064037 -0.0095129 +0.0264403 0.0878588 0.0105855 +0.0200841 0.0963175 -0.0204482 +0.0508265 0.0939603 -0.0091335 +0.0753367 0.087282 -0.0290458 +-0.0114666 0.0989277 -0.0268583 +0.189464 0.426182 0.111762 +-0.04038 -0.0265907 0.0536548 +0.188037 0.19051 0.048384 +0.170897 0.170857 0.0404072 +0.180803 0.154042 0.0195245 +0.168583 0.128396 0.0100026 +0.150344 0.161847 0.0580756 +0.146195 0.173828 0.0846654 +0.123104 0.163389 0.100752 +0.131952 0.158423 0.126057 +0.154039 0.169296 0.137953 +0.163282 0.191526 0.127822 +0.170691 0.206066 0.147249 +0.123979 0.136658 0.135 +0.136161 0.125537 0.148878 +0.153818 0.131557 0.161379 +0.111897 0.12133 0.126074 +0.111889 0.144276 0.0890707 +0.11658 0.140768 0.0690434 +0.119959 0.124948 0.0613596 +0.107779 0.107117 0.0626571 +0.122618 0.115267 0.0466942 +0.127454 0.104238 0.0219653 +0.136258 0.119892 0.0320023 +0.129073 0.0915077 -0.00265103 +0.130797 0.0780035 -0.0369633 +0.10768 0.094992 0.00979378 +0.163926 0.154671 0.152149 +0.0894836 0.0909923 0.00058556 +0.0689505 0.0963924 0.00171312 +0.0612997 0.100634 0.0224348 +0.0675451 0.0846698 0.038694 +0.0795109 0.103357 0.0384133 +0.0848094 0.0754581 0.0444653 +0.110567 0.10366 0.130086 +0.12281 0.0864143 0.139975 +0.117855 0.062854 0.143513 +0.13666 0.0472165 0.155281 +0.128164 0.0235742 0.176647 +0.163067 0.0498951 0.143567 +0.143932 0.0949004 0.145284 +0.179917 0.317727 0.0742859 +0.183725 0.275085 0.0676723 +0.16838 0.29297 0.0787056 +0.0930951 0.102542 0.05002 +0.100339 0.0681106 0.0373411 +0.102886 0.0622715 0.0197467 +0.121511 0.0540863 0.0117598 +0.124719 0.0242285 0.0166428 +0.0967861 -0.00310471 -0.0020113 +0.12138 0.0519179 -0.0102922 +0.0990646 0.0492208 -0.022422 +0.0873807 -0.0275369 -0.03209 +0.200694 -0.191636 -0.0546067 +0.206298 -0.170055 -0.0598788 +0.209964 -0.168421 -0.0791806 +0.221182 -0.183261 -0.0963771 +0.222775 -0.172837 -0.120159 +0.235715 -0.195921 -0.115182 +0.253933 -0.218526 -0.134037 +0.311213 -0.253911 -0.191866 +0.279294 -0.244732 -0.16099 +0.266185 -0.201338 -0.169529 +0.285572 -0.216415 -0.213382 +0.273765 -0.285731 -0.187819 +0.259679 -0.265381 -0.248632 +0.24894 -0.227823 -0.231771 +0.232153 -0.25966 -0.225227 +0.254118 -0.290735 -0.220386 +0.336364 -0.328047 -0.241676 +0.281317 -0.319577 -0.26697 +0.295033 -0.317038 -0.218433 +0.327766 -0.263669 -0.27537 +0.320681 -0.238904 -0.235706 +0.333487 -0.28367 -0.222752 +0.25789 -0.299076 -0.25318 +0.280382 -0.278404 -0.287734 +0.262726 -0.334272 -0.234674 +0.315714 -0.303377 -0.28762 +0.358898 -0.298323 -0.270079 +0.292961 -0.250812 -0.263064 +0.260427 0.269097 0.206442 +0.273912 0.251948 0.207483 +0.274266 0.226866 0.218876 +0.254508 0.262332 0.186312 +0.268737 0.247011 0.182676 +0.278883 0.230014 0.174886 +0.292676 0.216891 0.181537 +0.301666 0.196568 0.170643 +0.235991 0.25839 0.179999 +0.216996 0.262302 0.191107 +0.233602 0.240223 0.192553 +0.26623 0.217767 0.166603 +0.291208 0.219735 0.206357 +0.285626 0.200003 0.208179 +0.295054 0.181857 0.198439 +-0.119559 -0.0454446 0.130205 +-0.148541 -0.0288065 0.124554 +-0.122421 -0.0280036 0.104512 +-0.169628 -0.0428483 0.136658 +-0.192691 -0.0700149 0.138018 +-0.165949 -0.0805689 0.151606 +-0.157867 -0.111652 0.162619 +-0.182289 -0.134815 0.160033 +-0.171616 -0.0265274 0.119564 +-0.182821 -0.0294707 0.089096 +-0.207158 -0.0941133 0.130893 +-0.0813687 -0.408143 0.0168626 +-0.0493082 -0.255289 0.183439 +-0.0417823 -0.281988 0.16825 +-0.0232624 -0.242141 -0.150317 +0.237084 0.148575 0.150278 +0.21825 0.135883 0.152701 +0.196547 0.147262 0.152063 +0.248839 0.134889 0.149793 +0.25417 0.116897 0.146677 +0.154738 -0.248351 -0.113516 +0.149894 -0.252291 -0.14374 +0.127807 -0.247316 -0.112579 +0.100037 -0.239188 -0.118127 +0.171952 -0.258325 -0.155783 +0.206243 -0.267544 -0.164319 +0.152779 -0.244265 -0.170212 +0.238869 -0.271194 -0.164355 +0.19948 -0.240785 -0.114164 +0.228533 -0.228656 -0.117975 +0.0806348 -0.448964 -0.0364622 +0.092817 -0.46403 -0.0236687 +0.131465 -0.464547 -0.0186627 +0.111576 -0.45856 -0.0162136 +0.12236 -0.437795 -0.0167687 +0.116113 -0.473014 -0.0333379 +0.141834 -0.466374 -0.0462667 +0.15629 -0.45187 -0.0265272 +0.162053 -0.430562 -0.0436087 +0.170805 -0.433786 -0.074571 +0.150694 -0.440322 -0.089161 +0.142403 -0.453672 -0.0687084 +0.20922 0.0225383 -0.118012 +0.245897 0.00269769 -0.0710137 +-0.0868896 -0.445579 -0.0827631 +-0.0899978 -0.418668 -0.0662628 +-0.0919895 -0.382051 -0.0731611 +-0.286076 -0.18977 0.00251657 +0.166397 -0.235956 -0.0665238 +0.18289 -0.231659 -0.0402536 +0.183601 -0.256036 -0.0114407 +0.19304 -0.222737 -0.0114233 +0.168396 -0.264129 0.0198747 +0.175145 -0.292863 -0.0261367 +0.159612 -0.311932 -0.0502102 +0.151795 -0.349231 -0.058414 +0.168467 0.120276 0.165442 +0.179322 0.109989 0.151163 +0.191745 0.091503 0.1476 +0.207409 0.0731218 0.143583 +0.170472 0.088013 0.148441 +0.198308 0.0526608 0.137187 +-0.288444 -0.322548 -0.196751 +-0.258254 -0.336596 -0.201797 +-0.260706 -0.370334 -0.191889 +-0.262012 -0.38355 -0.234182 +0.169409 0.331718 0.106522 +-0.0883279 -0.427369 -0.00320489 +-0.0757242 -0.410706 -0.00350047 +-0.0694098 -0.396348 -0.0215868 +-0.339105 -0.28249 -0.133907 +0.14338 -0.190029 -0.185968 +0.113197 -0.189729 -0.178573 +0.161752 -0.208101 -0.1989 +0.163143 -0.233988 -0.192556 +0.187542 -0.24244 -0.20457 +0.214342 -0.231174 -0.221761 +0.200695 -0.263551 -0.191549 +0.0888974 -0.174918 -0.165344 +0.0728578 -0.155488 -0.148655 +0.0857975 -0.13271 -0.133069 +0.0496654 -0.153477 -0.133288 +0.208417 -0.252602 -0.211864 +0.214499 -0.20684 -0.209109 +0.212326 -0.182246 -0.176825 +0.196622 -0.193456 -0.194925 +-0.0366034 0.0848157 -0.0747335 +-0.0106036 0.0767347 -0.0825468 +-0.248014 -0.143811 -0.0711582 +0.156176 -0.353723 -0.00967102 +0.161881 -0.35946 -0.0354879 +0.154192 -0.374021 -0.054565 +0.153835 -0.401954 -0.0551512 +0.147106 -0.376782 -0.0111704 +0.141013 -0.401853 -0.0175381 +0.127378 -0.38782 -0.00428773 +0.152558 -0.410563 -0.0345712 +0.144573 -0.387551 -0.0699167 +0.129797 -0.395951 -0.0860393 +0.110844 -0.383365 -0.0877166 +0.111358 -0.362136 -0.0828181 +0.10863 -0.332992 -0.0757964 +0.131091 -0.348484 -0.0736181 +0.114528 -0.372564 0.00601769 +0.116893 -0.350867 0.0177725 +0.143657 -0.369483 -0.0686154 +0.0433039 -0.239647 0.0998892 +-0.318832 -0.357055 -0.211401 +-0.299837 -0.377374 -0.238049 +-0.340344 -0.383626 -0.224893 +-0.356366 -0.419986 -0.188103 +-0.285529 -0.404192 -0.228972 +-0.356375 -0.393121 -0.201407 +-0.349321 -0.392013 -0.165399 +-0.328811 -0.42272 -0.163607 +-0.345548 -0.417553 -0.216974 +-0.322795 -0.427865 -0.195551 +-0.33518 -0.363207 -0.161311 +-0.0812327 -0.396788 0.0342935 +-0.065289 -0.38943 0.0224745 +-0.0508718 -0.371639 0.0298172 +-0.260668 -0.216401 0.0653687 +-0.2704 -0.185201 0.0538295 +0.187032 0.486356 0.0996338 +0.279593 -0.136382 0.110973 +0.26837 -0.117918 0.105466 +0.248285 -0.109463 0.116456 +0.232397 -0.125931 0.141691 +0.210603 -0.141776 0.171116 +0.137574 -0.108705 0.207737 +0.169921 0.29167 0.0522744 +0.00992085 -0.113945 -0.0964453 +0.258261 -0.257702 -0.154872 +0.275321 -0.267702 -0.17038 +0.295633 -0.272896 -0.184932 +0.295815 -0.294739 -0.20199 +0.314713 -0.27743 -0.201437 +0.327332 -0.256197 -0.214678 +0.340385 -0.261017 -0.241446 +0.313356 -0.232789 -0.209684 +0.296344 -0.226073 -0.182212 +0.31592 -0.301772 -0.216769 +0.318635 -0.326842 -0.222796 +0.307178 -0.325937 -0.251416 +0.274745 -0.303144 -0.21295 +0.263287 -0.308346 -0.232527 +0.255382 -0.319889 -0.248754 +0.332002 -0.310475 -0.229091 +0.353636 -0.307458 -0.245121 +0.335859 -0.313851 -0.265914 +0.340499 -0.300896 -0.286697 +0.344989 -0.280039 -0.276203 +0.327449 -0.28026 -0.295194 +0.304942 -0.268737 -0.28762 +0.34983 -0.283684 -0.251927 +0.343136 -0.265469 -0.261534 +0.326713 -0.248963 -0.256716 +0.307917 -0.24034 -0.252462 +0.279159 -0.231625 -0.241522 +0.300353 -0.229376 -0.234338 +0.311358 -0.251222 -0.26759 +0.299024 -0.289572 -0.301481 +0.279907 -0.305571 -0.290358 +0.263002 -0.29286 -0.276914 +0.260616 -0.313748 -0.268771 +0.275922 -0.322371 -0.224156 +0.284975 -0.33259 -0.244221 +0.303023 -0.336946 -0.233483 +0.289605 -0.333838 -0.221905 +0.166435 0.39886 0.154509 +0.189152 0.404825 0.153461 +0.197133 0.400723 0.1737 +0.17424 0.413608 0.143911 +0.169142 0.426834 0.132439 +0.188725 0.386035 0.180698 +0.186219 0.378081 0.198788 +-0.267025 -0.372115 -0.138391 +-0.248022 -0.367522 -0.158602 +0.174505 0.292586 0.0990952 +0.186251 0.309263 0.0928235 +0.181697 0.30513 0.109614 +0.189499 0.279776 0.119317 +0.172647 0.294457 0.120787 +0.158057 0.303956 0.130265 +0.143476 0.291331 0.139139 +0.131312 0.30031 0.159002 +0.186095 0.298863 0.131041 +0.198975 0.28677 0.132576 +0.172236 0.277192 0.117866 +0.184313 0.260452 0.109718 +0.15755 0.265746 0.122578 +0.145983 0.269471 0.137935 +0.151234 0.256355 0.155644 +0.124293 0.323596 0.164277 +0.126678 0.342635 0.150186 +0.129524 0.341544 0.128525 +0.146576 0.349856 0.118779 +0.192269 0.30374 0.0759625 +0.202728 0.285813 0.0690781 +0.210479 0.281567 0.0483558 +0.222196 0.26209 0.0407369 +0.224073 0.261141 0.0186008 +0.162756 0.306191 0.114529 +0.149682 0.318744 0.121136 +0.152677 0.341974 0.100993 +0.164071 0.331208 0.0841361 +0.146523 0.323278 0.093798 +0.15695 0.312461 0.0714443 +0.22266 -0.203518 -0.100877 +0.262076 -0.292278 -0.202356 +0.249754 -0.28212 -0.183581 +0.242451 -0.284733 -0.203885 +0.229725 -0.273053 -0.211906 +0.243386 -0.275428 -0.225419 +0.255999 -0.283472 -0.239546 +-0.261873 -0.405224 -0.222848 +-0.280772 -0.420055 -0.201182 +-0.274389 -0.414773 -0.173401 +-0.298626 -0.411672 -0.158377 +-0.28738 -0.389898 -0.148508 +-0.300008 -0.369107 -0.135836 +-0.257381 -0.39915 -0.185758 +-0.257531 -0.421709 -0.186727 +-0.319983 -0.369357 -0.146016 +-0.25404 -0.39271 -0.206532 +-0.269186 -0.375948 -0.213104 +0.171129 0.312683 0.0555484 +0.186538 0.309469 0.0612947 +0.17697 0.322584 0.0897939 +0.180094 0.317456 0.102692 +0.0389455 -0.294719 0.0707663 +0.19085 0.129482 0.148059 +0.26893 -0.330546 -0.250405 +0.261495 -0.324416 -0.260179 +0.163955 0.0845671 -0.00775852 +0.172992 0.467003 0.114773 +0.17962 0.47069 0.135115 +0.167392 0.460661 0.148013 +0.0927702 -0.0102964 0.178794 +0.0791092 -0.00358862 0.211868 +0.0484002 -0.0727004 0.143042 +0.0857054 -0.0664246 0.132462 +0.170606 0.462905 0.162683 +0.107346 -0.291576 0.0507084 +0.123054 -0.26548 0.0555752 +0.1033 -0.273351 0.0618915 +-0.217347 -0.0684085 0.0793768 +-0.232534 -0.1003 0.0785864 +0.160705 0.203815 0.112095 +0.157448 0.189802 0.0951937 +0.163855 0.222961 0.107992 +0.178039 0.226994 0.0939715 +0.157779 0.236558 0.121407 +0.156862 0.233096 0.141593 +0.254115 0.147478 0.0328869 +0.246739 0.139758 0.0163119 +-0.313249 -0.26088 -0.138114 +-0.319034 -0.272336 -0.0954566 +-0.312031 -0.286413 -0.151154 +-0.318615 -0.301412 -0.127758 +-0.31358 -0.30952 -0.0911544 +-0.342054 -0.297563 -0.104135 +-0.285707 -0.289103 -0.098473 +-0.332554 -0.290038 -0.0650158 +0.224391 0.444149 0.0748945 +0.224127 0.466497 0.0733316 +0.00933378 -0.0890982 -0.073455 +-0.196836 -0.0544369 -0.0547609 +-0.268852 -0.35939 -0.204575 +-0.134821 -0.144762 0.184037 +-0.134018 -0.119846 0.172991 +-0.108849 -0.110436 0.169417 +-0.142893 -0.258813 -0.176858 +0.163435 0.422628 0.144619 +0.149105 0.425301 0.157986 +0.151653 0.445126 0.160854 +0.205634 0.453218 0.0682861 +0.196116 0.437078 0.0613117 +0.305429 0.136514 0.131635 +0.304223 0.128705 0.150462 +0.294739 0.1352 0.16485 +0.29983 0.148475 0.176204 +0.293633 0.16134 0.186506 +0.312816 0.146868 0.144611 +0.290574 0.119539 0.149687 +0.280449 0.10933 0.137413 +0.285959 0.112117 0.117297 +0.154398 0.116961 0.162863 +0.147042 0.108372 0.152274 +0.179394 0.214392 0.162515 +0.185651 0.194518 0.157404 +0.180628 0.232354 0.173507 +0.198969 0.238329 0.174545 +0.207694 0.253512 0.177641 +0.203869 0.264161 0.186147 +0.189501 0.273156 0.193533 +0.17312 0.263127 0.188581 +-0.206119 -0.0619918 0.116346 +-0.201545 -0.0465532 0.095691 +0.256266 0.152102 0.0503785 +0.264034 0.143148 0.0672501 +0.26342 0.152022 0.0867622 +0.269601 0.144159 0.103885 +0.281713 0.137095 0.0629023 +0.296165 0.127981 0.0376256 +0.300117 0.13462 0.0559043 +0.287642 0.140563 0.0456708 +0.278661 0.132147 0.0309413 +0.271646 0.118273 0.028754 +0.262921 0.1025 0.0261376 +0.261118 0.0855637 0.0169037 +0.25422 0.0767023 0.000233527 +0.237362 0.0575218 0.00198963 +0.283388 0.119704 0.0383643 +0.282941 0.112062 0.0540402 +0.249937 0.0937398 -0.00575339 +0.231931 0.0954578 -0.0107377 +0.210437 0.0914748 -0.0140972 +0.239252 0.109782 0.000233887 +0.191402 0.0870306 -0.0134669 +0.184376 0.0704441 -0.0225342 +0.184719 0.0606504 -0.044543 +0.166145 0.0578967 -0.0668264 +0.200251 0.061117 -0.0313226 +0.217304 0.057967 -0.0199728 +0.227686 0.12158 0.00370932 +0.20937 0.123042 0.000300618 +0.244333 0.124524 0.00810813 +0.295429 0.120597 0.0522453 +0.178132 0.0791963 -0.0112798 +0.177197 -0.279627 -0.000252101 +0.173639 -0.299787 -0.00606886 +0.172196 -0.313975 -0.0223573 +0.166117 -0.326159 -0.00858114 +0.168079 -0.321719 -0.0379096 +0.162521 -0.339731 -0.0445028 +0.151373 -0.32895 -0.0576036 +0.312369 -0.105021 0.0899766 +0.306 -0.11652 0.0866674 +0.301418 -0.129182 0.0942967 +0.290875 -0.135236 0.101483 +0.289966 -0.143698 0.1109 +0.295915 -0.13953 0.122573 +0.279108 -0.148197 0.122497 +0.27841 -0.152315 0.142258 +0.265867 -0.157983 0.158785 +0.256687 -0.14661 0.137703 +0.25422 -0.140442 0.172759 +0.232237 -0.161116 0.192798 +0.192807 -0.160413 0.202508 +0.178601 -0.140578 0.237092 +0.154384 -0.117167 0.24831 +0.13004 -0.134226 0.269277 +0.17845 -0.105479 0.223698 +0.247464 -0.158843 0.179106 +0.226891 -0.158442 0.171794 +0.209982 -0.159856 0.187271 +0.217821 -0.141328 0.207646 +0.23745 -0.141109 0.186416 +0.229503 -0.142546 0.156329 +0.214657 -0.125289 0.155947 +0.193847 -0.12199 0.171057 +0.217246 -0.105649 0.140104 +0.198069 -0.0856194 0.142621 +0.193693 -0.14343 0.18682 +0.198045 -0.145975 0.222277 +0.178989 -0.164931 0.225321 +0.158831 -0.146831 0.218292 +0.158889 -0.159611 0.244735 +0.138513 -0.154491 0.257842 +0.156487 -0.13924 0.256434 +-0.290841 -0.208347 -0.00770324 +-0.29533 -0.224009 -0.017137 +-0.30561 -0.24462 -0.0155011 +-0.278365 -0.220452 -0.0277869 +-0.267819 -0.241114 -0.0357093 +-0.286737 -0.259306 -0.0462551 +-0.310093 -0.264404 -0.0203987 +-0.307167 -0.250649 -0.0341839 +-0.307612 -0.281242 -0.0310235 +-0.321036 -0.286281 -0.0471544 +-0.310491 -0.270102 -0.0639157 +-0.311345 -0.301149 -0.0633156 +-0.297683 -0.291436 -0.0450671 +-0.294949 -0.304108 -0.0790095 +-0.285459 -0.27779 -0.0488974 +-0.296472 -0.275126 -0.0168658 +-0.276222 -0.270671 -0.00788631 +-0.246454 -0.248267 -0.0329014 +-0.244456 -0.252303 -0.00937036 +-0.304286 -0.259682 -0.0492577 +-0.294933 -0.27203 -0.0604957 +-0.300998 -0.278796 -0.0743602 +-0.316674 -0.274623 -0.0789273 +-0.337714 -0.280945 -0.0853892 +-0.325825 -0.275251 -0.0655092 +-0.332977 -0.302425 -0.0833069 +-0.293564 -0.290291 -0.0772666 +-0.298024 -0.281309 -0.0905074 +-0.293634 -0.272694 -0.109468 +-0.270428 -0.274072 -0.107657 +-0.256077 -0.253991 -0.120812 +-0.261078 -0.296954 -0.0999473 +-0.2381 -0.297373 -0.0849839 +-0.232752 -0.278906 -0.0645746 +-0.272041 -0.319246 -0.10842 +-0.21032 -0.284441 -0.0448701 +-0.256436 -0.341131 -0.11181 +-0.225098 -0.336223 -0.113241 +-0.200175 -0.288996 -0.0158483 +-0.223009 -0.317757 -0.0905879 +-0.301096 -0.262202 -0.123506 +-0.32405 -0.263071 -0.116908 +-0.292477 -0.257052 -0.14263 +-0.270149 -0.255918 -0.142108 +-0.275486 -0.258003 -0.162669 +-0.259523 -0.2674 -0.178244 +-0.251069 -0.250018 -0.0970302 +-0.24056 -0.260706 -0.172311 +-0.232499 -0.247239 -0.154361 +-0.34182 -0.274562 -0.107339 +-0.294559 -0.307923 -0.0994756 +-0.275844 -0.269552 -0.0355918 +-0.227344 -0.270897 -0.045083 +0.25093 0.170443 0.120028 +0.248384 0.184009 0.106523 +0.235777 0.198062 0.103222 +0.23641 0.211305 0.086191 +0.221152 0.226047 0.0898201 +0.223243 0.24123 0.111495 +0.203883 0.250541 0.105061 +0.226958 0.225862 0.123117 +0.219737 0.240254 0.12789 +0.214138 0.253162 0.132941 +0.232275 0.224561 0.138088 +0.109391 -0.247931 -0.0995264 +0.104952 -0.262437 -0.0820427 +0.080763 -0.274056 -0.0783487 +0.0604155 -0.262392 -0.0950373 +-0.227936 -0.329497 -0.190147 +-0.214125 -0.337031 -0.170051 +0.263325 -0.0528405 0.0685009 +0.251926 -0.0484757 0.0715634 +0.237277 -0.0480579 0.0658708 +0.244491 -0.055646 0.0790843 +0.239659 -0.0616442 0.0888399 +0.226162 -0.0616059 0.0920824 +0.21522 -0.0631162 0.0781895 +0.212545 -0.0629682 0.0966232 +0.196781 -0.0599901 0.105959 +0.210127 -0.0657511 0.11188 +0.250495 -0.0660959 0.0846797 +0.234672 -0.0671026 0.0978575 +0.237261 -0.0846396 0.108485 +0.25989 -0.0423809 0.0666642 +0.259987 -0.0257531 0.0664908 +0.247883 -0.0247631 0.0554477 +0.242689 -0.0135836 0.0440572 +0.246291 0.00496067 0.0457059 +0.245187 0.0234669 0.0372413 +0.250061 0.17416 0.133813 +0.259114 0.167602 0.148828 +0.26511 0.166925 0.171546 +0.238618 0.181672 0.138204 +0.229669 0.176644 0.149535 +0.262049 0.187134 0.176237 +0.261795 0.200868 0.165371 +0.276513 0.199318 0.153854 +0.292677 0.199982 0.157209 +0.302715 0.186361 0.157188 +0.308755 0.181779 0.171774 +0.305926 0.190608 0.185482 +0.312423 0.167782 0.169221 +0.31381 0.157653 0.158921 +0.310783 0.154703 0.171639 +0.301108 0.177938 0.144841 +0.293264 0.189309 0.147256 +0.279322 0.188458 0.145304 +0.262483 0.193127 0.192418 +0.274289 0.192768 0.20161 +0.254841 0.206509 0.193978 +0.245154 0.222549 0.189318 +0.253012 0.22552 0.174345 +0.265429 0.23121 0.17081 +-0.253206 -0.236908 -0.0443888 +0.149428 0.386275 0.232451 +0.147867 0.371017 0.232576 +0.152926 0.356705 0.229375 +0.149032 0.338169 0.225131 +0.166114 0.363727 0.223417 +0.172256 0.353426 0.215568 +0.179541 0.338962 0.221969 +0.181625 0.354174 0.201921 +0.186426 0.343494 0.187951 +0.192075 0.328517 0.215563 +0.192453 0.320313 0.195502 +0.17815 0.351274 0.174302 +0.17655 0.370022 0.172318 +0.165276 0.33179 0.225541 +0.00939661 -0.323412 0.0804555 +0.117561 -0.144032 0.250595 +0.120353 -0.125008 0.233582 +0.111251 -0.145731 0.271784 +0.11093 -0.120815 0.285658 +0.0754192 -0.0921393 0.301481 +0.0769558 -0.124739 0.290267 +0.0748528 -0.117401 0.265004 +0.0426218 -0.103655 0.282975 +0.0504123 -0.0659143 0.287583 +0.0836935 -0.0669285 0.279976 +0.0588543 -0.11803 0.279938 +0.0586609 -0.105277 0.297458 +0.0557269 -0.0839063 0.29826 +0.0381914 -0.083198 0.286361 +0.0371995 -0.0680895 0.266535 +0.047335 -0.0888232 0.265922 +0.05563 -0.0732275 0.247968 +0.0616189 -0.0543441 0.232231 +0.0811821 -0.0784737 0.231059 +0.0764784 -0.0353683 0.254905 +0.0689625 -0.0703705 0.29266 +0.0661415 -0.0548095 0.278244 +0.0608765 -0.028919 0.235586 +0.087271 -0.018263 0.234864 +0.0756435 -0.10953 0.298971 +0.0951645 -0.0988538 0.288259 +0.0930654 -0.116235 0.295574 +0.0947803 -0.133863 0.284699 +0.0966033 -0.0830131 0.273711 +0.113798 -0.076403 0.258582 +0.127442 -0.0600385 0.234949 +0.132794 -0.0953943 0.252522 +0.0489111 -0.0556973 0.272686 +0.0606107 -0.0431898 0.263976 +0.0971312 -0.036293 0.245012 +0.110687 -0.0488392 0.23675 +0.126176 -0.0414728 0.221378 +0.136057 -0.0243951 0.201716 +0.122078 0.00127519 0.196707 +0.142291 0.00027007 0.178375 +0.0664164 -0.0191578 0.217877 +0.0802696 -0.0234954 0.199319 +0.0910082 -0.0454502 0.20083 +0.0798776 -0.132726 0.273919 +0.102454 0.00166634 0.210465 +0.0802091 -0.00534582 0.192641 +0.0863635 0.00814252 0.179895 +0.0946306 0.0282399 0.168655 +0.0981336 0.029523 0.148764 +0.101777 0.0395859 0.135111 +0.102082 0.0581642 0.134881 +0.0956437 0.0321468 0.122829 +0.0938658 0.0161985 0.122282 +0.107901 0.00369122 0.128399 +0.078491 0.00576055 0.124425 +0.0841199 0.0382034 0.11313 +0.0659972 0.0331947 0.109714 +0.0520056 0.0196069 0.12098 +0.108345 -0.0142416 0.126349 +0.0915975 -0.0313276 0.129913 +0.122833 -0.0287943 0.124051 +0.146418 -0.0426624 0.119895 +0.142658 -0.0228961 0.131632 +0.132595 -0.0194368 0.150249 +0.160419 -0.0327892 0.133975 +0.163125 -0.050543 0.147173 +0.060233 0.0422739 0.0970401 +0.0469107 0.0353785 0.0851224 +0.0330985 0.0252247 0.0760721 +0.0344131 0.0145341 0.0525338 +0.0185411 0.0141735 0.0691085 +-0.00651953 0.00766464 0.081092 +0.0314926 0.0314677 0.0951056 +0.0155266 0.0258059 0.107793 +0.11957 0.0050674 0.144577 +0.11348 -0.010764 0.15919 +0.0864989 0.00930931 0.196192 +0.112679 0.0343949 0.172228 +0.110056 0.0172326 0.144505 +-0.231861 -0.256194 -0.0373807 +-0.233847 -0.249852 -0.0220477 +-0.230235 -0.258784 -0.00973726 +-0.217151 -0.280061 0.00814621 +-0.228026 -0.273051 0.0389012 +-0.222798 -0.271648 -0.00409819 +-0.229682 -0.268052 0.0118625 +-0.212876 -0.279385 -0.0140325 +-0.214439 -0.277583 -0.0303969 +-0.199886 -0.285356 -0.0320197 +-0.187179 -0.295224 -0.0255156 +-0.167219 -0.315028 -0.0304058 +-0.156845 -0.302235 -0.0544314 +-0.236758 -0.254924 0.00227314 +0.0884351 -0.404348 -0.0195924 +0.0722252 -0.268984 0.0670772 +0.070147 -0.245252 0.0862941 +0.0966471 -0.229612 0.0882203 +0.0926053 -0.203806 0.103764 +0.0777673 -0.186021 0.118999 +0.0417862 -0.182948 0.126604 +0.0709209 -0.158179 0.128709 +0.095465 -0.128791 0.124296 +0.0102764 -0.16375 0.133447 +-0.0233099 -0.171526 0.153541 +-0.0499934 -0.0465621 -0.00582837 +-0.0749973 -0.0355191 0.0101971 +-0.0645299 -0.324704 -0.077104 +0.221779 0.470802 0.0892895 +0.219761 0.464582 0.1032 +0.246597 0.0246927 0.0795416 +0.253586 0.0320272 0.0977802 +0.252394 0.0305168 0.0670227 +0.261064 0.0424817 0.0637394 +0.267205 0.0556508 0.058182 +0.262106 0.0615289 0.0436471 +0.250683 0.0500973 0.0298185 +0.272972 0.0454164 0.0731281 +0.274554 0.0385023 0.090004 +0.285852 0.0505507 0.0780368 +0.287544 0.066644 0.0791877 +0.280213 0.0764884 0.0661465 +0.226162 0.0537579 -0.00800313 +0.231726 0.0372941 0.00212281 +0.226833 0.070796 -0.0125112 +-0.0228881 0.0822405 -0.0141151 +-0.0164496 0.062439 -0.0353807 +-0.0311204 0.09353 -0.0291259 +-0.0468617 0.0890411 -0.0503417 +-0.0192694 0.0958145 -0.0445491 +-0.0451838 0.0631149 -0.0497516 +-0.0349277 0.0970377 -0.0439657 +-0.0281121 0.0908295 -0.0597278 +-0.0422149 0.0875756 -0.0360098 +-0.0493018 0.0748281 -0.0407497 +-0.0508974 0.0756362 -0.0555946 +-0.045787 0.0616401 -0.0714534 +-0.0463878 0.0860458 -0.0643425 +-0.0469 0.0754389 -0.0734442 +-0.0361876 0.0721397 -0.0877453 +-0.0344753 0.0506229 -0.0835042 +-0.0209274 0.0429352 -0.0951495 +-0.00835098 0.0548898 -0.109767 +-0.0439408 0.0675081 -0.0809412 +-0.0384794 0.0604865 -0.0888934 +-0.0325578 0.0529818 -0.0938199 +-0.0250287 0.0507859 -0.100857 +-0.0171358 0.0586173 -0.103485 +-0.00108771 0.0669554 -0.09638 +0.0141047 0.0764389 -0.0789872 +-0.0166767 0.0687863 -0.0931008 +-0.0154196 0.0443974 -0.106822 +0.00804033 0.0334573 -0.118139 +-0.00353356 0.0420783 -0.115203 +0.00267945 0.0333406 -0.10199 +0.0284162 0.0260832 -0.102463 +0.0140719 0.0342408 -0.0876383 +0.01206 0.042083 -0.0690778 +0.0262722 0.0834922 -0.057317 +0.052314 0.0257381 -0.0888721 +0.0550064 0.0153199 -0.121681 +0.0742668 0.0307726 -0.0684202 +0.0254542 0.0462258 -0.0537161 +0.0192751 0.0579365 -0.0299961 +0.043388 0.0389601 -0.0621497 +0.0632571 0.0407552 -0.0511604 +0.0628168 0.0511918 -0.0295138 +-0.00769957 0.0468719 -0.0674097 +0.0356439 0.036944 -0.129564 +0.00985644 0.0486694 -0.11871 +0.0293481 0.0500299 -0.116265 +0.034304 0.0639803 -0.0982281 +0.0203799 0.0394103 -0.126099 +0.0274107 0.0238815 -0.120304 +-0.00989932 0.038173 -0.0977698 +0.0409915 0.0204434 -0.130582 +0.0603476 0.0361414 -0.135064 +0.0745924 0.0111822 -0.144256 +0.0995383 0.0164619 -0.152082 +0.079494 0.0098491 -0.119596 +0.109969 -0.00178903 -0.14121 +0.128369 -0.00667529 -0.145234 +0.147176 -0.000628591 -0.159936 +0.143478 0.0207956 -0.143584 +0.15945 -0.0140125 -0.151421 +0.167046 -0.013357 -0.130058 +0.175024 -0.000463673 -0.161193 +0.200548 0.00730904 -0.144289 +0.228188 0.00606999 -0.13371 +0.232374 -0.0225206 -0.12062 +0.217352 -0.0205681 -0.149989 +0.196446 -0.0094088 -0.159916 +0.0468892 0.0318746 -0.136603 +0.0588847 0.0194871 -0.141629 +0.0497176 0.0425705 -0.12546 +0.067316 0.0466181 -0.121528 +0.0829023 0.0554408 -0.10632 +0.0702884 0.0671402 -0.0864572 +0.0736048 0.0280122 -0.141966 +-0.0393368 0.0927115 -0.058201 +-0.074253 -0.462729 -0.0674302 +-0.0882268 -0.46748 -0.0836924 +-0.10265 -0.454789 -0.102517 +-0.100302 -0.434985 -0.0953132 +-0.123508 -0.439573 -0.0964816 +0.30376 -0.329009 -0.220778 +-0.34576 -0.287787 -0.1184 +-0.333412 -0.299886 -0.118936 +-0.318278 -0.306436 -0.109371 +-0.342798 -0.273541 -0.122349 +-0.330946 -0.265681 -0.13448 +-0.32759 -0.278136 -0.147142 +-0.313986 -0.269795 -0.152301 +-0.304937 -0.277784 -0.160852 +-0.289134 -0.290053 -0.171285 +-0.300398 -0.29313 -0.159904 +-0.305136 -0.304081 -0.143109 +-0.303823 -0.326091 -0.148763 +-0.297334 -0.338307 -0.131821 +-0.0297344 -0.320795 0.126249 +-0.0440833 -0.337561 0.102751 +-0.0635963 -0.3222 0.124646 +-0.0820192 -0.303394 0.145977 +-0.0280108 -0.346215 0.0792887 +0.190023 -0.166658 -0.160984 +0.187606 0.489479 0.0788413 +0.169798 0.492699 0.0805537 +0.160239 0.479513 0.0724411 +0.160997 0.477019 0.0876359 +0.167909 0.48647 0.0907839 +0.168839 0.465921 0.0685027 +0.185848 0.461592 0.0756332 +0.163713 0.449815 0.0719867 +0.171034 0.442192 0.0868531 +0.172622 0.439121 0.100638 +0.176648 -0.0540189 0.138439 +0.191763 0.435033 0.0761478 +0.150024 0.450095 0.173316 +0.142684 0.444609 0.180888 +0.134925 0.435737 0.185852 +0.0901553 -0.0455623 0.257862 +0.0764097 -0.0467149 0.266788 +0.218445 0.190081 -0.00453558 +0.212983 0.187132 0.0158667 +0.234912 0.203072 -0.0090602 +0.217724 0.208098 -0.00630956 +0.209095 0.231498 0.0538229 +0.223398 0.222537 0.0510417 +0.229495 0.205818 0.051858 +0.241614 0.200114 0.0387668 +0.245196 0.212463 0.0252865 +0.232616 0.199508 0.066443 +0.245867 0.187445 0.0704899 +0.218046 0.211438 0.0580939 +0.206013 0.207163 0.0667587 +0.208167 0.217137 0.0808695 +0.189985 0.216171 0.0819923 +-0.328288 -0.282754 -0.0562593 +-0.321215 -0.270892 -0.0527491 +-0.321885 -0.294532 -0.0580289 +-0.324301 -0.301836 -0.070993 +-0.309665 -0.294095 -0.0515043 +-0.298437 -0.298535 -0.0585809 +-0.293755 -0.297175 -0.0685565 +-0.301865 -0.303693 -0.0670723 +-0.312242 -0.307406 -0.0760424 +0.113855 0.0103494 0.135894 +0.117356 -0.000872108 0.134011 +0.24192 0.231796 0.179613 +0.236568 0.24336 0.180529 +0.226028 0.250706 0.186633 +0.280884 -0.220307 -0.163899 +0.26654 -0.211351 -0.150233 +0.265056 -0.233891 -0.14678 +0.318482 -0.331697 -0.239506 +0.324395 -0.322699 -0.253479 +0.31194 -0.314679 -0.269415 +0.329739 -0.334727 -0.229668 +0.336703 -0.323152 -0.229076 +0.344428 -0.313085 -0.23571 +0.342498 -0.293727 -0.236916 +0.350543 -0.322922 -0.2465 +0.353252 -0.314 -0.261759 +0.347047 -0.326986 -0.235121 +0.0827363 -0.465408 -0.0592863 +0.0757733 -0.45735 -0.0483001 +0.0758332 -0.442944 -0.0486429 +0.0763754 -0.427162 -0.064874 +0.0810297 -0.429275 -0.0354104 +0.0760881 -0.402196 -0.0628009 +0.0803331 -0.462498 -0.0366385 +0.075746 -0.427719 -0.0496393 +0.213629 0.454927 0.154222 +0.216172 0.433851 0.152191 +0.213875 -0.163106 0.208849 +0.228479 0.0837143 -0.0171959 +0.214862 0.0777937 -0.0178642 +0.203914 0.0820668 -0.0169156 +0.213551 0.066976 -0.0133462 +-0.291696 -0.291685 -0.053913 +-0.288445 -0.286967 -0.0453936 +-0.283457 -0.280518 -0.0392925 +0.198493 0.267303 0.113918 +-0.00816198 -0.315253 0.11742 +0.312224 -0.337685 -0.224702 +0.0776115 -0.0114015 0.225043 +0.094616 -0.00802053 0.222738 +0.212523 -0.00317223 -0.153514 +0.228944 -0.0069181 -0.146501 +0.230166 -0.0223035 -0.138067 +0.212902 -0.0238532 -0.132712 +0.194522 -0.0219296 -0.138137 +0.240306 -0.00819778 -0.130311 +0.24497 -0.0122967 -0.113875 +0.221562 -0.0094445 -0.0973672 +0.242491 -0.00970392 -0.0927411 +-0.195428 -0.293105 -0.0588105 +-0.174639 -0.293714 -0.0615636 +-0.159198 -0.295096 -0.0708856 +-0.150745 -0.297027 -0.0916319 +-0.165094 -0.309633 -0.116063 +-0.129532 -0.293794 -0.0901166 +-0.12154 -0.29002 -0.105668 +-0.103655 -0.284754 -0.110478 +-0.083304 -0.273535 -0.126518 +-0.126229 -0.291149 -0.124142 +-0.0551206 -0.282297 -0.123125 +-0.0279253 -0.280704 -0.123568 +-0.0254074 -0.296918 -0.100527 +-0.143636 -0.296672 -0.0765836 +0.228772 0.249576 0.00807469 +0.246793 0.197559 -0.000456927 +0.249351 0.185655 0.00965958 +0.077471 -0.38535 -0.0716786 +0.0780138 -0.366405 -0.0698751 +0.0796117 -0.349597 -0.0694382 +0.0817673 -0.324046 -0.067713 +0.0920794 -0.339278 -0.0766687 +0.0745961 -0.308674 -0.0513846 +0.0686559 -0.285979 -0.0584538 +0.0701691 -0.296007 -0.0346939 +0.0958416 -0.324563 -0.0739969 +0.111686 -0.315208 -0.0712996 +0.118212 -0.295045 -0.0671537 +0.145789 -0.285221 -0.0572786 +0.142444 -0.258951 -0.0651148 +0.125807 -0.256448 -0.0777825 +0.0725557 -0.302564 -0.0188272 +0.0757738 -0.318738 -0.0113816 +0.0755625 -0.334153 -0.022547 +0.0716925 -0.292684 -0.00740334 +0.0574002 -0.292216 -0.00131701 +0.0442788 -0.29974 -0.0118635 +0.0322898 -0.309073 -0.00126775 +0.0158934 -0.319374 -0.00927168 +0.00270388 -0.318254 -0.036966 +0.00321031 -0.33353 0.006095 +0.0101246 -0.330737 0.0331595 +0.0571801 -0.291727 0.0142738 +0.0411549 -0.302632 0.0323113 +0.0568056 -0.290026 0.0325413 +0.0726196 -0.279494 0.0399911 +0.0843075 -0.293947 0.0355701 +0.0802412 -0.296732 0.0208207 +0.0757523 -0.290551 0.00911073 +0.0904109 -0.307387 0.0401159 +0.0937218 -0.321431 0.0333001 +0.0876185 -0.332554 0.0196986 +-0.261918 -0.356193 -0.123562 +-0.274572 -0.363058 -0.128675 +-0.283885 -0.374671 -0.137095 +0.0993425 -0.475253 -0.0345906 +0.105878 -0.470302 -0.022596 +0.161209 0.00758193 -0.157082 +0.162861 -0.00496129 -0.160125 +0.14622 0.0234899 0.00861402 +0.16407 0.00688456 0.00334424 +0.187476 0.0108016 -0.000104135 +0.198618 0.0267239 -0.00776275 +0.213159 0.032032 -0.0211609 +0.229764 0.0271876 -0.0288068 +0.229938 0.0432028 -0.0342052 +0.231973 0.0361819 -0.05417 +0.241585 0.0230077 -0.0674939 +0.235826 0.0200922 -0.0913851 +0.229532 0.00831192 -0.0604593 +0.228417 0.0182383 -0.11087 +0.214387 0.0313739 -0.095916 +0.23826 0.0319925 -0.0407356 +0.240603 0.0153722 -0.0478262 +0.185434 0.0390225 -0.0120783 +0.174046 0.035224 -0.0278333 +0.183039 0.0254835 -0.0435084 +0.185088 0.013208 -0.0664572 +0.184517 -0.00115634 -0.0944301 +0.15883 0.0112792 -0.0789407 +0.166768 0.0454452 -0.0125857 +0.149871 0.0473393 -0.0127261 +0.24097 0.0273212 -0.0523021 +0.244689 0.0183228 -0.0578172 +0.239121 0.00955592 -0.0564169 +0.23067 0.0133196 -0.0511149 +0.217815 0.013095 -0.0555127 +0.202953 0.0215885 -0.0445658 +0.223255 0.0309758 -0.00933388 +0.246338 0.00680161 -0.0920968 +-0.29666 -0.251794 -0.0420083 +-0.282377 -0.246563 -0.0382484 +-0.274248 -0.257163 -0.0411355 +0.121069 0.3764 0.220244 +0.124178 0.361607 0.222425 +0.12316 0.347289 0.21517 +0.120818 0.335014 0.200629 +0.131773 0.318764 0.203442 +0.240354 -0.189104 -0.174254 +0.226426 -0.17846 -0.157236 +0.25469 -0.197929 -0.186668 +0.262527 -0.207499 -0.20859 +0.275709 -0.206748 -0.189755 +0.268196 -0.218714 -0.226562 +0.252109 -0.214264 -0.221034 +0.231966 -0.219863 -0.222417 +0.16439 -0.290409 -0.045741 +0.174232 0.353361 0.161991 +0.167416 0.346038 0.151615 +0.153417 0.351454 0.147309 +0.141711 0.365653 0.160008 +0.174784 0.33351 0.146976 +0.172695 0.32064 0.137876 +0.171538 0.327653 0.122668 +-0.153467 -0.465689 -0.0917447 +-0.142244 -0.458217 -0.0978282 +-0.137315 -0.444624 -0.0945322 +-0.142546 -0.468457 -0.0929801 +-0.130113 -0.470071 -0.0887414 +-0.111868 -0.466578 -0.0912306 +-0.129822 -0.476932 -0.0773011 +-0.116192 -0.47396 -0.0799073 +-0.102072 -0.471199 -0.0816089 +0.0648327 -0.288276 0.006469 +0.290523 -0.14969 0.120852 +0.286341 -0.149084 0.132395 +0.276561 -0.154417 0.131433 +0.266874 -0.144863 0.128327 +0.266123 -0.155511 0.139202 +0.254682 -0.156501 0.14847 +0.243072 -0.144724 0.147014 +0.246658 -0.132891 0.13506 +0.271484 -0.158645 0.148826 +0.262513 -0.161728 0.150556 +0.255383 -0.163883 0.160093 +0.258182 -0.154155 0.170424 +0.247063 -0.165211 0.168804 +0.236375 -0.166699 0.177267 +0.223809 -0.16596 0.182974 +0.219971 -0.167303 0.19665 +0.224247 -0.15536 0.203023 +0.206877 -0.166582 0.198203 +0.201256 -0.167208 0.210293 +0.187949 -0.165778 0.214542 +0.175727 -0.151043 0.207983 +0.205839 -0.156778 0.218275 +0.191606 -0.158183 0.226132 +0.180969 -0.154585 0.235065 +0.170507 -0.150398 0.244702 +0.167678 -0.135398 0.246604 +0.174695 -0.121433 0.234619 +0.192199 -0.123695 0.219574 +0.161002 -0.150315 0.252813 +0.149901 -0.156196 0.25282 +0.145756 -0.15618 0.238445 +0.158231 -0.157867 0.22927 +0.148019 -0.147104 0.261177 +0.14318 -0.132144 0.260892 +0.131504 -0.114456 0.261736 +0.136414 -0.145181 0.266602 +0.124033 -0.152215 0.261533 +0.128756 -0.151616 0.248741 +0.169715 -0.162656 0.235355 +0.125332 -0.145025 0.270918 +0.118124 -0.13431 0.277651 +0.122928 -0.121301 0.271952 +0.113017 -0.148351 0.260498 +0.105868 -0.137752 0.254904 +0.0970603 -0.116879 0.246491 +0.113377 -0.13188 0.244126 +0.102989 -0.14407 0.26402 +0.09993 -0.141861 0.276203 +-0.208269 -0.22401 0.141633 +-0.20692 -0.250284 0.132437 +0.0965268 -0.427234 -0.105996 +0.0991486 -0.439673 -0.0998914 +0.19126 -0.17619 0.0390751 +0.184715 -0.204433 0.0324441 +0.164304 -0.221583 0.0465757 +0.1444 -0.208807 0.0686986 +0.0226172 -0.0147867 0.137076 +-0.142255 -0.49298 -0.0216335 +0.233691 0.0208001 -0.0385404 +-0.192672 -0.315988 0.0839294 +-0.202286 -0.295403 0.104035 +-0.212462 -0.276423 0.111373 +-0.218066 -0.285356 0.0914372 +-0.230517 -0.270625 0.068595 +0.136055 0.0355608 0.0131192 +0.121886 0.0399552 0.0198872 +0.106186 0.0275039 0.0255554 +0.0928691 0.0373146 0.0446539 +0.107832 0.0113031 0.0106037 +0.0853288 0.00897116 0.0135994 +0.0648776 -0.00152148 0.00684991 +0.301901 0.1917 0.196837 +0.304498 0.181718 0.192274 +0.29757 0.171529 0.192207 +0.283611 0.170157 0.190984 +0.17589 0.332048 0.230978 +0.176274 0.318104 0.221305 +0.189786 0.308195 0.22975 +0.199452 0.291101 0.221444 +0.210647 0.278153 0.221165 +0.212403 0.290739 0.232707 +0.229872 0.295702 0.229994 +0.238851 0.283146 0.23072 +0.237981 0.260514 0.227763 +0.248013 0.243086 0.221386 +0.245976 0.271423 0.230129 +0.237201 0.240055 0.208931 +0.239318 0.292509 0.222434 +0.244312 0.28734 0.210021 +0.234086 0.289095 0.199595 +0.221914 0.298769 0.201947 +0.1778 0.322602 0.229777 +0.232474 0.299285 0.221376 +0.223334 0.304746 0.213608 +0.207337 0.311267 0.204764 +0.224642 0.304397 0.226583 +0.214619 0.302742 0.233384 +0.203769 0.313465 0.232857 +0.204968 0.319702 0.218324 +0.201735 0.298965 0.232154 +-0.0492057 -0.0812756 -0.10551 +-0.0710597 -0.075701 -0.12067 +-0.0879497 -0.0905516 -0.13677 +-0.0843511 -0.119489 -0.147588 +-0.0762899 -0.059326 -0.102542 +-0.0985707 -0.0477827 -0.098696 +-0.118275 -0.0536394 -0.113913 +-0.11441 -0.0717159 -0.128365 +0.179503 0.303256 0.0436704 +0.192013 0.290229 0.0290644 +0.17689 0.287515 0.0370015 +0.192038 0.271729 0.0156116 +0.209167 0.267708 0.00969983 +0.200133 0.255704 0.00478026 +-0.247504 -0.392344 -0.224787 +-0.247477 -0.405986 -0.218212 +-0.243099 -0.400741 -0.206484 +-0.246703 -0.405341 -0.193269 +-0.249065 -0.417066 -0.193806 +-0.263856 -0.417281 -0.202583 +-0.253854 -0.410374 -0.185389 +-0.264275 -0.407223 -0.177693 +-0.272044 -0.40206 -0.166216 +-0.284666 -0.409799 -0.163624 +-0.28689 -0.423019 -0.170791 +-0.283285 -0.428723 -0.186577 +-0.301536 -0.424549 -0.197331 +-0.276684 -0.426319 -0.176604 +-0.270204 -0.426002 -0.18843 +-0.267033 -0.421163 -0.178871 +-0.28572 -0.431162 -0.176917 +0.0984334 0.0428629 0.147655 +0.0984512 0.0370662 0.158757 +-0.324734 -0.278381 -0.0492733 +-0.319049 -0.278035 -0.0388895 +-0.314693 -0.271902 -0.0298211 +-0.0814975 -0.486596 -0.0514846 +-0.0716057 -0.47534 -0.0576231 +-0.0807984 -0.475501 -0.0687174 +-0.0782273 -0.46782 -0.0773567 +-0.0794515 -0.454639 -0.076562 +-0.0865219 -0.442019 -0.0638219 +-0.0826697 -0.456554 -0.0896798 +-0.0913604 -0.446861 -0.0969099 +-0.0924184 -0.432044 -0.0753911 +-0.098273 -0.416607 -0.0817744 +-0.111942 -0.395187 -0.0818225 +-0.0923505 -0.401008 -0.0727607 +-0.110463 -0.376831 -0.0757945 +-0.0955645 -0.358515 -0.0727168 +-0.0748788 -0.367775 -0.053732 +-0.099584 -0.336657 -0.0718408 +-0.0617229 -0.346951 -0.0508932 +-0.0372908 -0.340191 -0.0358611 +-0.187209 -0.0514446 0.134371 +-0.172275 -0.062062 0.144345 +-0.181772 -0.0387772 0.12984 +0.27325 0.225257 0.167666 +0.283037 0.221467 0.169903 +0.141164 -0.00931766 -0.150578 +0.223335 -0.262546 -0.149684 +0.199958 -0.258684 -0.141852 +0.218212 -0.249649 -0.131577 +-0.0730224 -0.485274 -0.0383372 +-0.0765985 -0.473674 -0.025717 +-0.0833487 -0.485599 -0.0202509 +-0.0969784 -0.487241 -0.0157338 +-0.106328 -0.475595 -0.0156679 +-0.107519 -0.486132 -0.0147883 +-0.117398 -0.491224 -0.0155421 +-0.11866 -0.497871 -0.0255495 +0.192205 -0.0198585 -0.151725 +0.281772 0.238327 0.210562 +0.269826 0.243309 0.222088 +0.243244 0.207816 -0.00325363 +0.239729 0.221932 -0.000908316 +0.243256 0.225044 0.0142927 +0.235434 0.23543 0.00346349 +0.158954 -0.447934 -0.074517 +0.164 -0.440163 -0.0849532 +0.160645 -0.422992 -0.0839209 +0.160099 -0.41995 -0.0633914 +0.170063 -0.432118 -0.0580684 +0.170775 -0.442201 -0.0470561 +0.167356 -0.452883 -0.036848 +0.157537 -0.464023 -0.0432353 +0.154265 -0.458207 -0.0582632 +0.146921 -0.466798 -0.0291891 +0.17099 -0.445942 -0.0649823 +0.152813 -0.426396 -0.0985179 +0.142833 -0.435406 -0.0989063 +0.126573 -0.436557 -0.100225 +0.120949 -0.42189 -0.103936 +0.130685 -0.411647 -0.0938972 +0.160351 -0.460975 -0.0324222 +0.164884 -0.460693 -0.0398836 +0.167083 -0.430709 -0.0834012 +0.161089 -0.432508 -0.0931652 +0.165433 -0.424956 -0.0749657 +0.155909 -0.417913 -0.0743018 +0.149825 -0.407366 -0.067413 +0.142015 -0.399818 -0.0764637 +0.153043 -0.435416 -0.0966096 +0.148842 -0.431897 -0.101759 +0.145045 -0.424265 -0.10134 +0.147732 -0.418014 -0.0911084 +0.138977 -0.417451 -0.0965307 +0.139635 -0.411036 -0.0878314 +0.14174 -0.430413 -0.104765 +0.134784 -0.434536 -0.101822 +0.135086 -0.440748 -0.0918112 +0.13766 -0.447456 -0.0800542 +0.122938 -0.455334 -0.0698495 +0.127914 -0.428797 -0.106691 +0.135671 -0.430083 -0.106069 +-0.0268041 -0.304928 0.142542 +-0.0182344 -0.281255 0.151927 +0.000262015 -0.258244 0.142866 +0.0151742 -0.229959 0.128466 +-0.00970849 -0.227931 0.154073 +0.0337917 -0.209923 0.115845 +0.0199495 -0.192987 0.125832 +-0.154293 -0.0335699 -0.082135 +-0.129631 -0.0324487 -0.0813475 +-0.120097 -0.027431 -0.0586998 +-0.0956922 -0.0340394 -0.0533561 +-0.0814148 -0.0448428 -0.0722969 +-0.0594432 -0.0515596 -0.0534184 +-0.160793 -0.0482086 -0.0989707 +-0.166155 -0.0307425 -0.0663998 +-0.169924 -0.0270352 -0.0414151 +-0.183311 -0.0375758 -0.0551581 +-0.174206 -0.0274939 -0.0203147 +-0.192353 -0.0397338 -0.00141151 +-0.170447 -0.0249801 0.0063437 +-0.211587 -0.0636911 -0.00501259 +-0.0018753 -0.187141 -0.149775 +0.0183103 -0.182965 -0.142326 +0.0322217 -0.167313 -0.134641 +0.0236675 -0.146992 -0.123167 +-0.00232452 -0.142332 -0.126149 +0.0375806 -0.18533 -0.140019 +0.0530379 -0.201545 -0.137283 +0.0772348 -0.20845 -0.140694 +0.0988175 -0.224384 -0.140468 +0.119251 -0.222512 -0.162731 +0.03788 -0.218276 -0.135529 +0.0772845 -0.19139 -0.155355 +0.080882 -0.225907 -0.127445 +0.0653619 -0.242778 -0.113036 +0.0731805 -0.173068 -0.155239 +0.0897045 -0.191329 -0.166141 +0.102707 -0.199007 -0.171074 +0.119058 -0.208637 -0.176942 +0.127514 -0.196293 -0.185172 +0.13998 -0.205302 -0.190755 +0.149824 -0.215626 -0.194546 +0.161245 -0.221969 -0.199237 +0.175364 -0.230409 -0.20401 +0.173584 -0.215336 -0.204853 +0.178202 -0.198362 -0.197173 +0.188397 -0.22907 -0.211289 +0.202734 -0.22056 -0.215065 +0.199745 -0.239634 -0.214151 +0.0815106 -0.18364 -0.162988 +-0.172104 -0.359269 -0.00938238 +-0.172319 -0.335226 -0.0164663 +-0.16873 -0.368903 -0.0231312 +-0.292266 -0.291505 -0.0889456 +-0.288266 -0.299574 -0.0955502 +-0.280983 -0.308012 -0.105167 +-0.278654 -0.297571 -0.101297 +-0.274336 -0.285615 -0.103446 +-0.260134 -0.28158 -0.0989442 +-0.257005 -0.265144 -0.10215 +-0.26942 -0.305285 -0.10276 +-0.257003 -0.309674 -0.100476 +-0.244993 -0.306014 -0.0938734 +-0.249351 -0.292113 -0.0926885 +-0.25954 -0.322424 -0.104282 +-0.267093 -0.332079 -0.111051 +-0.283312 -0.328944 -0.119574 +-0.249017 -0.331591 -0.10481 +-0.232981 -0.32784 -0.100164 +-0.240291 -0.342062 -0.113719 +-0.229688 -0.345883 -0.126712 +-0.23058 -0.352629 -0.145077 +-0.21352 -0.337371 -0.127344 +-0.269191 -0.344874 -0.117105 +-0.208623 -0.327937 -0.112241 +-0.191793 -0.321843 -0.117022 +-0.180909 -0.311277 -0.104708 +0.11012 0.10505 0.0238496 +0.213679 0.221732 0.163906 +-0.0357839 -0.0025294 0.108473 +-0.0312254 -0.0135193 0.128152 +-0.0238807 -0.033229 0.139313 +-0.00300831 -0.046529 0.144036 +-0.00364169 -0.0760125 0.145155 +-0.0103288 -0.10643 0.141831 +0.015326 -0.129347 0.142131 +-0.041062 -0.0443202 0.130625 +-0.0555252 -0.0465254 0.114753 +-0.0556686 -0.0325657 0.0996413 +-0.0768736 -0.0422105 0.0949058 +-0.0167984 0.000564353 0.123722 +0.00524698 0.0020139 0.129964 +-0.0281137 -0.0861213 0.139333 +-0.0785841 -0.0379469 0.0747431 +-0.0762529 -0.0505618 0.114297 +-0.032521 -0.108383 0.136839 +-0.0633754 -0.0458183 0.101476 +-0.0250298 0.00663901 0.112981 +-0.0219675 0.00393164 0.0935556 +-0.147404 -0.304789 -0.127071 +0.192111 0.473304 0.143665 +0.202701 0.475169 0.131787 +0.206558 0.475874 0.120017 +0.202492 0.480449 0.108775 +0.157654 -0.366957 -0.0205798 +0.26661 -0.307414 -0.281977 +0.270077 -0.295571 -0.288815 +0.283263 -0.291236 -0.297392 +0.290598 -0.279448 -0.297082 +0.304158 -0.276932 -0.29882 +0.315035 -0.2885 -0.301158 +0.307588 -0.298676 -0.297006 +0.297613 -0.307939 -0.283621 +0.293787 -0.301201 -0.295424 +0.318389 -0.297707 -0.296483 +0.328066 -0.301032 -0.289042 +0.324582 -0.309109 -0.276338 +0.33579 -0.291676 -0.2964 +0.346867 -0.288071 -0.287976 +0.353956 -0.299169 -0.28317 +0.345495 -0.307423 -0.274703 +0.352866 -0.288693 -0.277818 +0.351312 -0.284395 -0.265224 +0.355354 -0.294774 -0.257468 +0.360217 -0.304818 -0.260578 +0.35682 -0.308388 -0.269609 +0.359106 -0.312264 -0.252967 +0.356474 -0.316127 -0.245135 +0.351445 -0.319298 -0.237976 +-0.26647 -0.314705 -0.199507 +-0.27426 -0.329739 -0.204261 +-0.290128 -0.337563 -0.206145 +-0.303723 -0.332243 -0.195363 +-0.303858 -0.323407 -0.176279 +-0.302757 -0.349394 -0.210447 +-0.304665 -0.364526 -0.223447 +-0.321319 -0.375627 -0.232938 +-0.285437 -0.371465 -0.224735 +-0.28011 -0.37957 -0.242654 +-0.314609 -0.397575 -0.24523 +-0.31498 -0.344154 -0.199865 +-0.330892 -0.351901 -0.189469 +-0.332902 -0.388937 -0.243068 +-0.348245 -0.402805 -0.233911 +-0.328232 -0.404959 -0.235266 +-0.273541 -0.396265 -0.240028 +-0.293049 -0.39498 -0.245656 +-0.355214 -0.402159 -0.217135 +-0.360108 -0.415844 -0.205721 +-0.346381 -0.42668 -0.201491 +-0.340374 -0.436455 -0.180032 +-0.360217 -0.406031 -0.193698 +-0.356506 -0.391255 -0.182727 +-0.356512 -0.407116 -0.177427 +-0.347384 -0.421732 -0.172779 +-0.348669 -0.37532 -0.17511 +-0.341266 -0.408591 -0.160307 +-0.332592 -0.391247 -0.153464 +-0.323849 -0.407723 -0.153687 +-0.349384 -0.43169 -0.189135 +-0.335815 -0.43119 -0.192046 +-0.324454 -0.435806 -0.181733 +-0.331465 -0.433295 -0.170921 +-0.314528 -0.431132 -0.168412 +-0.260177 -0.397767 -0.235 +-0.252953 -0.401301 -0.227678 +-0.247407 -0.394723 -0.238053 +-0.24372 -0.401046 -0.225417 +-0.243948 -0.396615 -0.216223 +-0.258003 -0.38952 -0.247437 +-0.272162 -0.387844 -0.252537 +-0.287147 -0.384539 -0.255755 +-0.302942 -0.384129 -0.252391 +-0.315505 -0.382766 -0.24459 +-0.323099 -0.390444 -0.249836 +-0.312399 -0.390336 -0.253745 +-0.328503 -0.399215 -0.245058 +-0.340635 -0.398589 -0.24271 +-0.266346 -0.382624 -0.244488 +-0.267321 -0.391914 -0.245578 +-0.0266812 0.0695328 -0.0242573 +-0.00773299 0.0681739 -0.0184911 +0.0122858 0.0669077 -0.0123781 +0.0150035 0.0767227 0.00239352 +0.0141467 0.0954062 -0.00215996 +0.0325338 0.098411 -0.00617133 +0.0450676 0.0983028 0.010086 +0.0314473 0.0730983 0.00401189 +0.0505593 0.0686309 0.00292132 +0.0698817 0.067505 0.00832925 +0.145383 0.180744 0.0984363 +0.132189 0.17376 0.0925198 +0.121241 0.164951 0.0850023 +0.133425 0.169934 0.0774819 +0.11505 0.153676 0.07879 +-0.083942 -0.368893 -0.0674225 +-0.0809876 -0.385027 -0.0581697 +-0.0723248 -0.382058 -0.0416794 +-0.00904893 0.0914446 -0.0120745 +0.00504523 0.0987359 -0.0150796 +0.0060609 0.0932522 -0.034057 +0.0248461 0.0873188 -0.0377031 +0.0363994 0.089055 -0.023789 +0.00213821 0.0914225 -0.00482177 +0.0092558 0.0863088 0.00212053 +0.106375 0.0274106 0.14138 +-0.263884 -0.385451 -0.252252 +0.258755 0.24689 0.225661 +0.259085 0.23306 0.219814 +0.249971 0.25591 0.228242 +-0.322841 -0.345115 -0.164492 +-0.323706 -0.355326 -0.152393 +-0.279169 -0.265328 -0.0439542 +-0.285416 -0.267917 -0.0516616 +-0.294745 -0.263175 -0.0517725 +0.23393 -0.0149701 -0.10397 +0.219738 -0.0165453 -0.112039 +0.204608 -0.00981825 -0.104246 +0.187184 -0.00954937 -0.110855 +0.228145 0.230452 0.102316 +0.214447 0.238029 0.0983297 +0.23229 0.220992 0.0943503 +0.215398 0.247623 0.105271 +0.217938 0.25177 0.117669 +0.210276 0.258003 0.111405 +0.220949 0.241286 0.103103 +0.290344 -0.337843 -0.233955 +0.276226 -0.337233 -0.22831 +0.296573 -0.339782 -0.226215 +0.227663 0.461812 0.0838481 +0.234265 0.455281 0.0718225 +0.229698 0.445794 0.0603386 +0.225781 0.470182 0.0813133 +0.214396 0.4698 0.0788369 +0.208406 0.478123 0.0862021 +0.214031 0.460896 0.0711899 +0.217085 0.451741 0.0628259 +0.219354 0.474333 0.0827819 +0.21619 0.47758 0.0903862 +0.217994 0.472178 0.097233 +0.209525 0.481852 0.0939712 +0.227208 0.456115 0.0633709 +0.234329 0.451682 0.0642008 +0.23166 0.462658 0.0759848 +0.273713 -0.249314 -0.252993 +0.274317 -0.268417 -0.267071 +0.263304 -0.282613 -0.260934 +-0.240326 -0.404033 -0.2139 +-0.241182 -0.408607 -0.207233 +0.243855 0.194683 0.113624 +0.235959 0.206195 0.114609 +-0.329827 -0.30598 -0.098469 +-0.057071 -0.0425853 0.0117122 +-0.0551192 -0.0420888 0.0309046 +-0.0534835 -0.0402863 0.0500454 +-0.0435993 -0.0469165 0.00748095 +-0.0255629 -0.0374196 0.00481763 +-0.00817324 -0.0328811 -0.0061182 +-0.00350439 -0.0437548 -0.0255784 +-0.0349503 -0.0490115 -0.00492533 +-0.0419875 -0.0536475 -0.0293419 +-0.0139014 -0.0607747 -0.0378374 +-0.0105205 -0.0780801 -0.0585195 +-0.0335249 -0.0540562 -0.0180409 +-0.0278411 -0.0595083 -0.0313207 +0.193253 0.49569 0.0858481 +0.189805 0.494474 0.0949255 +0.179559 0.491992 0.0947812 +0.19709 0.487808 0.0978913 +0.174576 0.497081 0.0879734 +0.179584 0.496616 0.0784813 +0.175502 0.48892 0.0725035 +0.169475 0.481635 0.069206 +0.164994 0.474033 0.0669237 +0.155945 0.469227 0.0714265 +0.159639 0.459314 0.0671634 +0.160451 -0.0544036 0.113535 +0.0454737 -0.0938547 0.293886 +0.0481458 -0.104952 0.292926 +0.0550885 -0.114349 0.29062 +0.0654216 -0.120788 0.289843 +0.0691263 -0.126298 0.278339 +0.0372417 -0.0943784 0.286279 +0.0377118 -0.088702 0.274623 +0.179652 -0.262284 0.0054219 +0.186087 -0.244472 0.00347757 +0.246807 -0.00615903 -0.103541 +0.242297 -0.0135206 -0.100916 +0.240802 -0.0172339 -0.108388 +0.232593 -0.0188607 -0.112191 +0.240348 -0.0194541 -0.117278 +0.238974 -0.018297 -0.127651 +-0.164632 -0.397326 -0.024693 +0.0813645 -0.458079 -0.0716845 +0.302397 0.127887 0.0470846 +0.298473 0.138148 0.0455108 +0.292313 0.136477 0.0386335 +0.288054 0.130079 0.0326142 +0.28271 0.137427 0.0379629 +0.271939 0.136706 0.038053 +0.261008 0.14116 0.0404912 +0.28194 0.12422 0.0312108 +0.300876 0.126279 0.0551937 +0.295306 0.129324 0.0632115 +0.286846 0.130603 0.0706512 +0.282604 0.11846 0.0804122 +0.273418 0.134767 0.0747422 +0.296205 0.121995 0.0600976 +0.289869 0.116278 0.0576534 +0.283444 0.108666 0.0679441 +0.208186 0.435058 0.0678801 +0.218992 0.437774 0.0675136 +0.20517 0.444041 0.0615 +0.195457 0.447135 0.0675955 +0.224157 0.438328 0.0597838 +0.221367 0.446069 0.0584788 +0.168291 -0.443724 -0.076199 +-0.239169 -0.248023 -0.0426243 +-0.246509 -0.244281 -0.0523825 +-0.245933 -0.250709 -0.0701381 +-0.252213 -0.23035 -0.0598084 +-0.256922 -0.212794 -0.063622 +-0.26443 -0.20039 -0.048456 +-0.236601 -0.248665 -0.0331221 +-0.248238 -0.244973 -0.04299 +-0.257005 -0.243536 -0.0363368 +-0.264619 -0.253098 -0.0324677 +-0.260909 -0.234911 -0.0387305 +-0.270856 -0.228969 -0.0335016 +-0.268106 -0.214873 -0.0367573 +-0.255525 -0.250409 -0.0291707 +-0.246354 -0.252152 -0.0213798 +-0.25421 -0.258055 -0.0140562 +-0.253371 -0.258976 0.00135493 +-0.263391 -0.256528 0.0180325 +-0.264412 -0.265611 -0.0106557 +-0.268835 -0.263918 0.00476582 +-0.24972 -0.252323 0.0327963 +-0.239732 -0.259608 0.0493553 +-0.242639 -0.251027 0.0706418 +-0.27192 -0.270836 -0.02103 +-0.264888 -0.241199 0.0366373 +-0.279792 -0.22631 0.033251 +-0.274206 -0.207933 0.0474852 +-0.283361 -0.276288 -0.0174295 +-0.267659 -0.226048 0.0482271 +0.202151 0.274483 0.19338 +0.194908 0.283204 0.198963 +-0.157532 -0.273615 -0.179435 +-0.176899 -0.279729 -0.184503 +-0.188947 -0.290942 -0.187096 +-0.192598 -0.3074 -0.18306 +-0.203551 -0.297799 -0.190929 +-0.222085 -0.288246 -0.191352 +-0.217908 -0.303036 -0.194268 +-0.355074 -0.426501 -0.195973 +-0.354866 -0.423993 -0.205337 +-0.355569 -0.419108 -0.214528 +-0.353763 -0.412061 -0.224887 +-0.346029 -0.286085 -0.1062 +-0.341227 -0.288967 -0.0947058 +-0.336277 -0.278132 -0.0971269 +-0.328988 -0.269127 -0.105169 +-0.340297 -0.292656 -0.0831052 +-0.335578 -0.266756 -0.115188 +-0.339311 -0.299368 -0.0917431 +0.212569 0.261061 0.18216 +0.216886 0.255854 0.175009 +0.219484 0.251322 0.162982 +0.212289 0.247584 0.170006 +0.218513 0.26322 0.154269 +0.225667 0.261532 0.178216 +0.218436 0.276817 0.178562 +0.234042 0.273996 0.185236 +0.223426 0.242038 0.154678 +0.21181 0.288948 0.181391 +0.220498 0.257755 0.18435 +0.211254 0.266563 0.187703 +0.211739 0.26954 0.199826 +0.278409 -0.209413 -0.174692 +0.233056 0.457965 0.0658843 +0.227063 0.46182 0.0682472 +0.220168 0.458063 0.0666597 +-0.0481392 -0.0447802 0.0166181 +0.131516 0.0530135 0.000672445 +0.12038 0.0567042 0.000376152 +0.134766 0.046581 0.0097546 +0.0956782 -0.141364 0.26837 +0.0877085 -0.13595 0.269242 +0.0854698 -0.124959 0.261926 +0.0839071 -0.111836 0.253439 +0.0904091 -0.099649 0.239147 +0.0872053 -0.136949 0.279095 +0.085161 -0.130401 0.287023 +0.0763801 -0.13103 0.282851 +-0.00884361 -0.0890856 -0.0728998 +-0.00654069 -0.102279 -0.0895079 +-0.0290648 -0.104665 -0.111248 +-0.0100257 -0.116287 -0.107029 +0.0875054 -0.104584 0.297054 +0.191386 -0.264049 -0.175252 +0.190045 -0.262732 -0.156889 +0.204589 -0.269071 -0.178679 +0.222111 -0.273266 -0.172895 +0.189235 0.0753918 -0.0129238 +0.0782752 -0.467624 -0.0498343 +0.0759673 -0.46177 -0.0555898 +0.0772195 -0.460605 -0.0642783 +0.151932 0.323656 0.079912 +0.153175 0.313215 0.0881136 +0.161272 0.302381 0.0857396 +0.163146 0.324848 0.0718597 +0.151557 0.334415 0.0880604 +0.142886 0.334889 0.0972586 +0.140662 0.34411 0.107021 +0.133598 0.347717 0.117582 +0.131314 0.355467 0.129074 +0.127988 0.361743 0.142546 +0.123763 0.348981 0.138438 +0.119822 0.353337 0.149718 +0.116288 0.351928 0.168204 +0.226419 0.174912 -0.00671405 +0.232006 0.15884 0.00199041 +0.243933 0.169091 0.00253819 +0.237571 0.172786 -0.00612936 +0.183717 0.142245 0.147062 +0.183533 0.157982 0.153224 +0.200684 0.169917 0.154336 +0.175927 0.14817 0.154877 +0.164064 0.143191 0.159694 +0.181391 0.132744 0.149775 +0.177453 0.123521 0.157312 +0.108424 0.0602759 0.0311611 +0.101691 0.0511896 0.042029 +0.297187 0.12858 0.124591 +0.286869 0.125817 0.115842 +0.279264 0.13651 0.11071 +0.277464 0.150893 0.114839 +0.267972 0.163015 0.116989 +0.29066 -0.215317 -0.195858 +-0.0439761 -0.143405 -0.149346 +0.0959309 0.0199379 0.158053 +0.0941358 0.00844127 0.16726 +0.273991 -0.158318 0.138404 +0.280108 -0.155995 0.136908 +0.28311 -0.154668 0.131232 +0.287165 -0.152142 0.126309 +0.291082 -0.145525 0.127381 +0.258354 -0.329753 -0.2515 +0.256649 -0.327468 -0.240856 +0.265642 -0.321399 -0.233195 +0.269005 -0.32965 -0.227653 +0.204877 0.287044 0.0357487 +0.289139 -0.339472 -0.226774 +0.282728 -0.335989 -0.224475 +0.283065 -0.327384 -0.221193 +0.28398 -0.316486 -0.219293 +0.289461 -0.305296 -0.210924 +0.2738 -0.310998 -0.221733 +0.2646 -0.301502 -0.221281 +0.282981 -0.339471 -0.231684 +0.275544 -0.336339 -0.239462 +0.259131 -0.2954 -0.232139 +0.281853 -0.296955 -0.202405 +0.287258 -0.287693 -0.192682 +0.301236 -0.282638 -0.194913 +0.23745 0.0270265 -0.0333549 +0.234865 0.0358956 -0.0292661 +0.240774 0.0243245 -0.0402136 +0.034599 -0.0884904 0.28182 +0.0345637 -0.0787252 0.277243 +0.0422003 -0.0728232 0.283477 +0.048607 -0.0763619 0.292696 +0.0395236 -0.0802562 0.266836 +0.0486856 -0.0788086 0.257578 +0.044992 -0.0647291 0.254151 +0.0587204 -0.0731238 0.296598 +0.068389 -0.0812067 0.300077 +0.0829644 -0.0808872 0.290453 +0.0435251 -0.0559756 0.262078 +0.20354 0.276522 0.016541 +-0.0980428 -0.240155 0.197738 +-0.0924965 -0.26196 0.186819 +-0.109853 -0.270124 0.168775 +-0.253582 -0.386742 -0.238773 +-0.0267016 0.0982672 -0.0374627 +0.214024 0.433945 0.0622105 +0.204736 0.432758 0.058829 +0.201109 0.433103 0.0655996 +0.201809 0.436011 0.073894 +0.193477 0.433855 0.0682907 +0.185218 0.436354 0.0703184 +0.180836 0.436291 0.0819631 +0.191166 0.440882 0.0659291 +0.187348 0.447071 0.070626 +0.179215 0.453739 0.0726364 +0.193028 0.454826 0.0736221 +0.173421 0.440644 0.0776765 +-0.147031 -0.496444 -0.028386 +-0.151597 -0.495421 -0.0374969 +-0.157627 -0.484775 -0.0397619 +-0.140246 -0.499465 -0.0256815 +-0.132401 -0.5 -0.0296698 +-0.132703 -0.497498 -0.0384881 +-0.126331 -0.494492 -0.0452588 +-0.11646 -0.490117 -0.0524448 +-0.101295 -0.487303 -0.0547567 +-0.136101 -0.494007 -0.0471871 +-0.13938 -0.490039 -0.0561432 +-0.133381 -0.483866 -0.0661423 +-0.15577 -0.492035 -0.0446482 +-0.153261 -0.490282 -0.0555144 +0.197755 0.272342 0.0690149 +0.190382 0.263313 0.0560052 +0.0686632 -0.292912 -0.0237205 +0.056243 -0.29127 -0.0303266 +0.0398126 -0.298058 -0.030698 +0.0315681 -0.295788 -0.0489563 +0.043708 -0.285681 -0.061727 +0.0621136 -0.289132 -0.040881 +0.0722108 -0.295077 -0.0484755 +0.0577034 -0.286988 -0.0524253 +0.0569935 -0.281989 -0.0659264 +0.064236 -0.290328 -0.0328163 +-0.0127838 0.0757233 -0.00921143 +0.0935192 0.0772038 0.0642915 +0.169714 0.302879 0.0497006 +0.163659 0.300165 0.0640716 +0.172929 0.295611 0.0434924 +0.049865 0.0913802 0.0221499 +0.0418831 0.0808731 0.013212 +0.0368549 0.0913191 0.0145569 +0.0319565 0.0968433 0.00544037 +0.310435 0.13526 0.142507 +0.026474 0.0305763 -0.129196 +0.017822 0.0292426 -0.122273 +0.0163904 0.0280919 -0.108702 +0.0350495 0.0278097 -0.132911 +0.178361 0.286185 0.0866978 +0.184473 0.288229 0.0959947 +0.0746028 -0.0119842 0.202652 +0.0770488 -0.00198153 0.201878 +0.0861829 0.00359659 0.206228 +0.0964676 0.00912576 0.20305 +0.110414 0.00821695 0.200752 +0.119478 0.0159283 0.18886 +-0.0749585 -0.470198 -0.0703816 +-0.0722579 -0.469101 -0.0627931 +-0.0775597 -0.45771 -0.0519849 +-0.0725204 -0.466379 -0.0530837 +-0.0822617 -0.458336 -0.0360309 +0.11796 -0.00196684 -0.151498 +0.110489 0.008862 -0.155734 +0.119387 0.0273131 -0.141295 +0.100036 0.00317869 -0.149099 +0.0946498 0.00360487 -0.130289 +0.0996271 0.00897841 -0.108462 +0.0876406 0.00969553 -0.149119 +0.0889673 0.0239205 -0.144401 +0.103773 0.0275171 -0.140968 +0.112143 0.0407687 -0.122665 +0.128275 -0.00210722 -0.155193 +0.136944 0.00690927 -0.158099 +0.1315 0.01712 -0.150046 +0.148823 0.0111196 -0.154092 +0.137878 -0.00286061 -0.157253 +0.0812501 0.0180999 -0.148671 +0.0723702 0.0199576 -0.146504 +0.0894465 0.0177562 -0.14994 +-0.244247 -0.411744 -0.197734 +0.0532101 -0.0425986 0.239458 +0.0614299 -0.034607 0.250277 +0.0718515 -0.0264935 0.244569 +0.0612036 -0.0408317 0.227838 +0.211416 0.21985 0.0506815 +0.209629 0.209187 0.0516229 +0.197715 0.200596 0.0531448 +0.210711 0.212673 0.041983 +0.209533 0.205981 0.0261421 +0.207685 0.214484 0.0320655 +0.204793 0.215907 0.019768 +0.207322 0.190012 0.0316877 +0.210424 0.206724 0.0353988 +0.209086 0.197885 0.0355421 +0.19948 0.191764 0.0420701 +0.206287 0.1798 0.0239909 +0.199532 0.162119 0.0159658 +0.0889829 0.0153312 0.187549 +0.0895058 0.0194699 0.175832 +0.0997882 0.0258376 0.180178 +0.0912633 -0.43583 -0.104962 +0.0893849 -0.44209 -0.0966632 +0.0818551 -0.438899 -0.0891003 +0.0775492 -0.435915 -0.0759439 +0.0805228 -0.426773 -0.087989 +0.0848008 -0.421093 -0.0971385 +0.0844397 -0.410175 -0.0930928 +0.0796444 -0.399052 -0.082153 +0.096306 -0.399151 -0.0928503 +0.0992866 -0.434977 -0.10667 +-0.038871 -0.095203 0.134909 +-0.0453136 -0.074362 0.132403 +-0.0642973 -0.0816285 0.135216 +0.128958 0.371237 0.164377 +0.114324 0.368213 0.169385 +0.110394 0.358489 0.182698 +0.119359 0.382173 0.172221 +0.244566 0.0274799 0.091132 +0.236517 0.0321023 0.108593 +0.228129 0.0154777 0.110489 +0.243652 -0.0044318 0.106704 +0.215089 0.0116198 0.126655 +0.193164 -0.00203925 0.149761 +0.295901 -0.145148 0.11649 +0.181002 0.326878 0.162405 +0.192626 0.308402 0.164847 +0.180295 0.335983 0.171005 +0.215019 0.222685 -0.0085752 +0.216226 0.238327 -0.00679645 +0.204842 0.243639 -0.00108745 +0.197086 0.237151 0.00943393 +0.207737 0.21475 -0.00125832 +0.200663 0.225332 0.00994825 +0.227239 0.239308 -0.00361834 +0.210369 0.205349 -0.000451507 +0.212421 0.195338 0.00658041 +0.0965367 0.0723068 0.0490018 +-0.263237 -0.382248 -0.20077 +-0.334935 -0.395374 -0.246716 +0.0666968 0.0983382 0.0352739 +0.0735768 0.104043 0.0256427 +0.0854137 0.105714 0.0280147 +0.0966684 0.103408 0.0197312 +-0.293219 -0.246559 0.00868918 +-0.284829 -0.260543 0.00656712 +0.231694 -0.239358 -0.229883 +0.249173 -0.248287 -0.23972 +-0.313753 -0.278534 -0.156686 +-0.167921 -0.0222432 0.100354 +-0.166557 -0.0217484 0.0804222 +-0.137191 -0.0189498 0.0544508 +-0.183157 -0.0297007 0.0652393 +-0.193717 -0.0386652 0.0428719 +-0.162262 -0.0205653 0.0563587 +-0.148465 -0.0201145 0.071316 +-0.122512 -0.0229086 0.0762312 +-0.112808 -0.0225311 0.0535636 +-0.15755 -0.0225071 0.112728 +-0.13968 -0.0242143 0.109228 +-0.128528 -0.0323847 0.121144 +-0.137944 -0.0426964 0.133983 +0.338353 -0.331842 -0.233 +0.197716 0.0369013 -0.0158252 +0.225598 0.0269623 0.107608 +0.227611 0.0352699 0.116368 +0.216481 0.0416846 0.126455 +0.20366 0.0291575 0.127785 +0.197706 0.0139181 0.138946 +0.177004 0.0154396 0.15063 +0.196436 0.0406475 0.130552 +0.183582 0.0465791 0.137895 +0.171962 0.0340634 0.144092 +0.209838 0.0350513 0.1214 +0.122018 -0.0147207 0.202688 +0.134625 -0.010294 0.190699 +0.150345 -0.0204184 0.190322 +0.171467 -0.0443352 0.191435 +0.124137 -0.0275222 0.21069 +0.115004 -0.0324307 0.220668 +0.103488 -0.0235525 0.230568 +-0.234966 -0.250492 -0.00657503 +0.230136 -0.0629922 0.010065 +0.22781 -0.0439028 0.0052695 +0.226758 -0.0758146 -0.00318988 +0.218119 -0.0755566 -0.0185995 +0.210925 -0.0881128 -0.0299059 +0.195391 -0.0835698 -0.0397083 +0.187049 -0.0970928 -0.0513544 +0.215909 -0.10623 -0.0275177 +0.221663 -0.111792 -0.00835326 +0.21689 -0.135734 -0.006698 +0.187289 -0.0668273 -0.0361071 +0.170089 -0.0549841 -0.0384156 +0.158135 -0.0292105 -0.0224101 +0.144698 -0.0631652 -0.0561794 +0.210349 -0.156804 0.00619425 +0.122465 -0.0210506 -0.020971 +0.25102 0.0827579 -0.00901225 +0.246076 0.0717907 -0.00732438 +0.248146 0.0653429 0.00439784 +0.245544 0.0538898 0.0151974 +0.255748 0.0868229 -0.000826293 +-0.125725 -0.258433 -0.170214 +0.151089 -0.0268375 0.140451 +0.244155 0.0131187 -0.0533056 +0.246127 0.0105937 -0.0612737 +0.239403 0.00492409 -0.0645919 +0.228547 -0.00190445 -0.0800819 +0.236042 0.000460551 -0.073323 +0.244455 -0.00400961 -0.0816292 +0.225173 0.00380285 -0.0703884 +0.247885 -0.00234363 -0.0902777 +0.247838 0.00379159 -0.0839495 +0.243353 0.0148187 -0.0838177 +0.236031 0.0244971 -0.0791546 +0.225616 0.0291453 -0.0875646 +-0.29518 -0.390079 -0.254006 +-0.303646 -0.394416 -0.248506 +-0.302477 -0.403327 -0.233435 +-0.298023 -0.412267 -0.217588 +-0.29425 -0.38151 -0.250683 +-0.302074 -0.390767 -0.254186 +0.191342 0.435898 0.0636941 +-0.0964353 -0.460913 -0.0144457 +0.137532 -0.0116873 0.139128 +0.343547 -0.294973 -0.292923 +0.137424 0.0947211 0.0118894 +0.147115 0.0902563 -0.00271409 +0.147874 0.0802052 -0.0226835 +0.255027 -0.310713 -0.257667 +0.257498 -0.300887 -0.266482 +0.220835 -0.0105204 -0.15317 +0.210403 -0.014095 -0.156518 +0.204562 -0.0228168 -0.148776 +-0.117774 -0.20207 0.202016 +3 575 1215 1225 +3 902 137 1166 +3 2122 17 2125 +3 1333 1332 328 +3 1031 1037 1032 +3 1235 1234 736 +3 986 1231 182 +3 532 534 185 +3 534 448 185 +3 1588 1570 1587 +3 674 675 639 +3 1130 1225 242 +3 279 6 280 +3 6 283 280 +3 621 954 955 +3 235 273 275 +3 2565 1747 2566 +3 2225 2224 2223 +3 11 206 278 +3 922 93 2080 +3 530 2723 2724 +3 2144 2146 2139 +3 1374 1376 766 +3 1361 1374 766 +3 1775 525 1893 +3 2626 1649 2625 +3 2338 2265 2339 +3 992 96 990 +3 103 21 104 +3 1681 1682 31 +3 1686 1682 1681 +3 2064 2065 295 +3 747 748 464 +3 597 1084 1086 +3 1003 2191 2190 +3 2184 1003 2190 +3 214 38 215 +3 2202 2205 473 +3 2725 257 2728 +3 216 554 944 +3 554 553 944 +3 1457 1456 445 +3 986 2154 96 +3 458 1022 1021 +3 961 1949 2534 +3 625 1514 1515 +3 1786 1791 518 +3 1586 2773 2006 +3 52 1485 1486 +3 2101 52 1486 +3 2368 2374 1380 +3 2054 1499 74 +3 329 326 1762 +3 933 934 176 +3 527 569 705 +3 2004 247 2003 +3 414 1966 1967 +3 853 544 184 +3 1136 354 352 +3 1896 1895 134 +3 5 978 1108 +3 1344 1342 726 +3 80 27 1599 +3 1489 1683 175 +3 1952 1953 2619 +3 21 105 104 +3 21 103 29 +3 2180 959 1164 +3 288 2180 1164 +3 294 1940 1941 +3 1263 1865 443 +3 1755 1756 337 +3 696 1187 1185 +3 1186 696 1185 +3 1489 66 1683 +3 68 907 122 +3 260 1748 341 +3 1340 1341 451 +3 806 397 478 +3 1337 750 728 +3 1516 419 1515 +3 279 11 278 +3 277 279 278 +3 226 2120 2119 +3 258 259 76 +3 686 683 719 +3 1232 950 1230 +3 1597 1598 1978 +3 91 2073 977 +3 724 734 1233 +3 724 732 734 +3 47 281 280 +3 85 1982 2246 +3 207 154 64 +3 2000 1998 1999 +3 553 853 184 +3 76 261 1618 +3 259 261 76 +3 682 706 1504 +3 660 706 682 +3 296 17 297 +3 17 2122 297 +3 554 216 916 +3 381 383 382 +3 271 269 296 +3 269 17 296 +3 1082 656 1823 +3 115 199 196 +3 1056 1049 880 +3 1520 2574 2248 +3 212 550 238 +3 1980 1598 27 +3 364 72 365 +3 674 657 673 +3 82 168 158 +3 1133 641 1171 +3 440 1406 1411 +3 804 803 398 +3 178 2662 461 +3 159 2100 157 +3 1657 1659 1658 +3 1659 1280 1658 +3 1499 141 1498 +3 2144 2137 2146 +3 358 2137 2144 +3 567 534 531 +3 64 264 274 +3 137 365 380 +3 379 137 380 +3 117 903 902 +3 377 376 136 +3 88 2566 2567 +3 83 1299 1306 +3 1819 692 1822 +3 1642 584 710 +3 645 602 1808 +3 503 500 502 +3 1855 1263 54 +3 1706 1580 517 +3 1169 1069 1068 +3 42 1825 1828 +3 21 67 106 +3 81 80 84 +3 20 105 118 +3 20 156 105 +3 67 21 256 +3 1015 258 1016 +3 259 258 65 +3 649 890 1665 +3 2021 116 2020 +3 1146 402 1147 +3 126 1615 1618 +3 164 1894 163 +3 120 164 163 +3 2774 378 377 +3 1796 1893 525 +3 510 511 413 +3 1143 754 305 +3 1257 1024 1260 +3 866 1816 1815 +3 2685 1816 866 +3 574 1222 1221 +3 1673 1038 1672 +3 158 168 51 +3 793 1560 1561 +3 750 730 465 +3 729 730 750 +3 996 998 61 +3 280 281 11 +3 919 93 918 +3 590 2300 1322 +3 1305 1478 1482 +3 68 122 118 +3 238 537 555 +3 138 365 903 +3 1536 1562 1535 +3 264 1720 268 +3 2079 2080 93 +3 6 273 283 +3 2554 63 246 +3 236 317 319 +3 40 84 80 +3 84 40 104 +3 778 1357 1356 +3 1359 778 1356 +3 170 263 265 +3 1986 170 265 +3 21 106 105 +3 944 183 1740 +3 944 945 183 +3 1894 164 165 +3 67 249 106 +3 283 235 47 +3 63 2005 246 +3 314 235 275 +3 435 436 188 +3 1746 1747 345 +3 1161 2431 2432 +3 2459 594 1102 +3 1484 1305 1482 +3 2 1136 1137 +3 1062 2510 2511 +3 1811 219 1809 +3 1736 997 1732 +3 264 268 274 +3 439 1427 1247 +3 526 2722 530 +3 2722 2721 530 +3 118 105 106 +3 164 120 121 +3 71 131 165 +3 63 247 2005 +3 1894 165 1895 +3 2054 2052 2053 +3 2285 2432 2286 +3 254 106 249 +3 254 68 106 +3 685 661 670 +3 1498 75 2135 +3 989 180 991 +3 263 24 265 +3 2021 2020 932 +3 1724 170 1487 +3 124 1016 76 +3 277 278 64 +3 431 151 430 +3 2225 2757 2189 +3 818 407 478 +3 1499 237 74 +3 1994 1576 2611 +3 2697 904 897 +3 904 899 897 +3 377 378 135 +3 132 72 364 +3 282 109 293 +3 109 282 319 +3 224 83 1306 +3 74 381 376 +3 2054 2053 141 +3 2226 2678 2224 +3 1134 1438 1437 +3 412 814 813 +3 2624 1641 709 +3 126 1618 261 +3 999 34 991 +3 899 1991 1989 +3 98 1315 275 +3 928 1767 931 +3 144 2131 2136 +3 23 234 78 +3 603 800 707 +3 337 1490 332 +3 1490 1491 332 +3 1348 1341 727 +3 1591 16 1590 +3 547 92 549 +3 2194 2226 2189 +3 2236 2582 2581 +3 378 72 135 +3 1796 1784 1893 +3 278 206 207 +3 170 82 1487 +3 265 24 266 +3 308 153 943 +3 310 308 943 +3 569 565 177 +3 267 1987 1502 +3 236 316 317 +3 1895 165 134 +3 1898 2388 1479 +3 163 159 120 +3 1464 1468 1463 +3 756 903 117 +3 138 903 756 +3 951 1231 986 +3 987 951 986 +3 2670 700 2672 +3 445 187 446 +3 1722 154 910 +3 256 21 29 +3 84 168 81 +3 1283 2386 2684 +3 2736 79 852 +3 146 363 2143 +3 1323 1324 2271 +3 68 118 106 +3 1043 1038 1673 +3 2773 1585 1705 +3 1231 1232 1230 +3 1337 729 750 +3 922 917 93 +3 825 395 824 +3 510 389 511 +3 763 1188 2128 +3 833 831 487 +3 560 1355 179 +3 560 1354 1355 +3 899 904 1991 +3 639 1133 1138 +3 674 639 1138 +3 1250 1243 1254 +3 2715 2714 1433 +3 502 499 503 +3 1690 1213 1212 +3 1342 451 1341 +3 1397 1025 443 +3 929 928 930 +3 1855 1854 1262 +3 1854 1857 1262 +3 2733 2736 241 +3 1001 987 993 +3 2662 2708 191 +3 1470 2764 1459 +3 264 1717 1720 +3 264 1718 1717 +3 346 330 1139 +3 1137 1136 353 +3 1514 557 1515 +3 2045 115 2026 +3 143 1494 1495 +3 1487 1713 1724 +3 211 974 975 +3 319 318 109 +3 319 317 318 +3 2081 2077 209 +3 1015 123 258 +3 207 59 910 +3 1770 241 848 +3 857 222 1810 +3 546 857 1810 +3 87 343 1750 +3 621 915 622 +3 393 803 806 +3 977 976 975 +3 2016 992 934 +3 992 176 934 +3 1794 2744 2745 +3 278 207 64 +3 524 1692 1691 +3 2772 1702 2771 +3 1702 2772 1586 +3 1107 1105 1106 +3 190 2593 2594 +3 802 393 586 +3 1777 1783 1793 +3 476 816 390 +3 2159 1049 1048 +3 516 515 1576 +3 321 2057 2063 +3 476 477 509 +3 1180 773 1181 +3 553 184 945 +3 1227 1228 949 +3 1892 255 101 +3 1919 600 2258 +3 124 1014 1015 +3 273 98 275 +3 225 1612 1613 +3 48 313 314 +3 539 2728 2729 +3 2728 539 538 +3 1897 1896 468 +3 1810 1809 980 +3 794 2238 2237 +3 307 39 311 +3 39 307 320 +3 1531 1533 1538 +3 1583 1702 1582 +3 410 954 621 +3 2519 2333 2332 +3 541 854 855 +3 459 439 1249 +3 529 1511 2740 +3 1259 450 1258 +3 1677 2170 2175 +3 509 389 510 +3 1704 1703 1707 +3 1703 1583 1707 +3 1644 1645 584 +3 463 562 2660 +3 175 929 930 +3 262 1756 1755 +3 1756 262 1757 +3 380 72 378 +3 365 72 380 +3 128 2247 1985 +3 2532 135 2533 +3 128 1985 1987 +3 1121 2187 288 +3 891 1663 1377 +3 135 132 2533 +3 76 1016 258 +3 117 902 901 +3 132 135 72 +3 908 139 909 +3 125 76 1618 +3 76 125 124 +3 737 736 745 +3 30 541 543 +3 30 540 541 +3 395 826 824 +3 260 1751 1749 +3 341 1746 1753 +3 173 553 554 +3 1141 331 1139 +3 1756 1490 337 +3 2668 2667 700 +3 1751 1752 259 +3 230 1380 2377 +3 281 282 12 +3 2137 2138 2146 +3 1689 1852 1850 +3 588 1697 1083 +3 1069 1169 641 +3 1149 424 1088 +3 11 279 280 +3 919 1331 213 +3 1626 715 3 +3 2374 2368 2367 +3 178 2661 2707 +3 2094 2093 2092 +3 320 318 39 +3 318 317 39 +3 754 14 755 +3 6 272 273 +3 2172 1047 1051 +3 1058 2163 2162 +3 237 1499 142 +3 1799 523 1518 +3 591 695 781 +3 696 695 2128 +3 234 23 430 +3 800 720 683 +3 236 282 47 +3 235 236 47 +3 23 1162 2312 +3 2192 2678 2227 +3 2681 2680 832 +3 236 319 282 +3 817 390 808 +3 509 510 476 +3 1661 1474 492 +3 1278 1659 1657 +3 191 2715 2716 +3 1138 1133 1171 +3 835 840 412 +3 840 1184 412 +3 1898 1897 468 +3 138 756 754 +3 22 2069 300 +3 309 755 1018 +3 1651 586 589 +3 1147 1651 589 +3 1771 2733 241 +3 2733 1771 522 +3 379 380 378 +3 1749 1751 65 +3 1729 1728 197 +3 2092 2093 970 +3 300 2069 2068 +3 903 137 902 +3 25 332 1002 +3 236 235 315 +3 1162 78 1027 +3 1163 318 320 +3 147 429 801 +3 360 359 302 +3 2285 1172 3 +3 637 669 677 +3 754 1143 14 +3 2706 2709 418 +3 1213 575 574 +3 1215 575 1213 +3 2186 2223 2192 +3 2364 718 2365 +3 535 184 544 +3 610 1197 394 +3 1401 2331 2444 +3 839 149 837 +3 956 149 839 +3 181 330 347 +3 674 1138 657 +3 340 326 329 +3 1430 1415 1635 +3 2664 1822 692 +3 173 554 924 +3 944 553 945 +3 535 544 533 +3 1740 216 944 +3 334 90 336 +3 2475 783 2480 +3 927 1767 929 +3 1267 310 943 +3 2479 952 783 +3 1144 592 1146 +3 929 175 927 +3 323 1731 1730 +3 2280 2292 2430 +3 1811 1813 1812 +3 1733 1735 2570 +3 222 857 858 +3 346 1139 1760 +3 809 808 390 +3 292 1073 1072 +3 1113 1959 1962 +3 1765 1764 1116 +3 2285 2286 1172 +3 1961 1012 287 +3 1754 77 1752 +3 509 820 844 +3 417 839 2710 +3 1260 1024 1252 +3 1463 1468 483 +3 2734 2732 537 +3 568 742 734 +3 2060 2059 298 +3 187 1137 353 +3 1438 1414 441 +3 469 133 753 +3 901 902 360 +3 902 1166 360 +3 592 1144 811 +3 151 234 430 +3 2321 715 2322 +3 1648 1643 1642 +3 498 786 2606 +3 1501 2696 146 +3 2699 145 898 +3 373 1970 1273 +3 1229 985 182 +3 384 237 142 +3 1025 1263 443 +3 1273 1275 1282 +3 900 1989 1193 +3 381 237 383 +3 839 837 415 +3 755 753 754 +3 138 754 753 +3 2719 437 1701 +3 789 1562 1536 +3 2604 2607 1573 +3 820 509 477 +3 780 2484 2485 +3 1184 840 416 +3 2717 1433 2713 +3 437 2717 2713 +3 1216 1219 1217 +3 394 1195 612 +3 238 550 551 +3 1206 529 1207 +3 1442 1472 2637 +3 1472 190 2637 +3 1778 1794 2745 +3 1082 1078 656 +3 1709 2266 2265 +3 498 497 1 +3 1235 735 1234 +3 526 527 705 +3 624 620 558 +3 393 589 586 +3 2128 1188 696 +3 501 497 498 +3 616 1204 1205 +3 825 514 798 +3 293 2063 294 +3 215 343 87 +3 853 854 544 +3 854 853 542 +3 2769 1060 1129 +3 212 547 548 +3 121 479 119 +3 784 620 411 +3 1320 610 1321 +3 419 618 624 +3 1518 2740 528 +3 410 953 954 +3 957 2709 2705 +3 1662 1470 1661 +3 619 2484 1174 +3 2672 708 2670 +3 893 771 887 +3 1418 2622 1700 +3 2306 2307 428 +3 1348 1342 1341 +3 527 528 1355 +3 455 436 454 +3 1704 1705 1585 +3 1703 1704 1585 +3 1900 848 1901 +3 1259 1257 455 +3 401 1323 1646 +3 422 2250 1553 +3 2250 422 1524 +3 668 666 671 +3 1469 482 481 +3 1449 1662 1661 +3 622 912 410 +3 844 2681 832 +3 454 1630 453 +3 463 748 747 +3 467 1433 2717 +3 735 1021 733 +3 909 2051 140 +3 1216 524 1219 +3 840 956 416 +3 408 811 1144 +3 739 740 738 +3 449 446 447 +3 2731 536 2726 +3 576 1223 1221 +3 461 2716 192 +3 598 2665 2664 +3 1144 1146 589 +3 627 1392 1393 +3 569 177 705 +3 1390 1391 651 +3 1799 1518 240 +3 1089 606 626 +3 1776 1220 523 +3 462 461 192 +3 1505 561 560 +3 192 459 456 +3 701 581 704 +3 673 676 636 +3 1022 1349 480 +3 2722 177 2721 +3 462 178 461 +3 611 1358 1357 +3 625 624 558 +3 2322 1621 2321 +3 1630 1460 386 +3 2727 537 2726 +3 748 178 462 +3 480 733 1021 +3 983 1543 1545 +3 531 534 532 +3 778 611 1357 +3 2607 2604 2605 +3 1463 485 148 +3 567 565 566 +3 748 462 464 +3 412 816 834 +3 743 746 464 +3 566 534 567 +3 606 663 1808 +3 1770 1771 241 +3 834 835 412 +3 420 798 514 +3 1454 1662 1449 +3 2306 428 2309 +3 763 2128 591 +3 625 558 1513 +3 477 476 390 +3 817 477 390 +3 1526 1523 1528 +3 1562 1521 791 +3 551 46 552 +3 700 2670 2669 +3 497 501 518 +3 790 1562 1552 +3 1212 574 1214 +3 1588 1587 1571 +3 2736 849 241 +3 2039 2024 2038 +3 123 128 258 +3 128 123 965 +3 1726 1727 582 +3 550 46 551 +3 274 2742 64 +3 1779 1781 2755 +3 1781 1782 2755 +3 503 506 500 +3 709 1641 581 +3 1563 1589 1587 +3 505 498 515 +3 2238 2239 392 +3 807 2243 2241 +3 818 477 817 +3 1589 1565 507 +3 1736 325 1737 +3 1530 1531 1525 +3 872 1052 1051 +3 1800 2753 2752 +3 534 186 448 +3 603 1069 721 +3 2665 653 687 +3 1513 559 1512 +3 1782 520 571 +3 2473 1727 399 +3 2748 2750 2747 +3 240 1773 1799 +3 1773 1774 1799 +3 753 752 138 +3 1 497 851 +3 1070 627 1393 +3 1071 627 1070 +3 744 743 464 +3 803 397 806 +3 1086 1084 1085 +3 402 1086 1085 +3 1020 458 1021 +3 854 540 544 +3 540 533 544 +3 811 810 174 +3 729 562 563 +3 1351 562 729 +3 731 749 568 +3 749 746 568 +3 1338 564 1350 +3 1337 1338 1350 +3 455 1257 54 +3 1198 2486 426 +3 817 2244 818 +3 239 530 536 +3 242 1225 1216 +3 1582 499 938 +3 50 737 745 +3 735 724 1234 +3 540 539 533 +3 539 540 30 +3 901 1990 900 +3 223 541 855 +3 541 540 854 +3 715 1620 3 +3 212 548 550 +3 545 543 541 +3 223 545 541 +3 2456 2455 1680 +3 545 546 547 +3 223 546 545 +3 1163 110 2066 +3 212 545 547 +3 945 946 183 +3 549 548 547 +3 2748 2747 2749 +3 217 917 920 +3 173 924 925 +3 855 542 856 +3 855 854 542 +3 46 203 552 +3 1081 95 662 +3 173 542 553 +3 149 956 840 +3 1505 560 1507 +3 742 50 745 +3 2749 1710 2751 +3 561 562 452 +3 179 1509 1508 +3 1507 560 179 +3 2574 150 2248 +3 665 638 693 +3 571 1778 2754 +3 727 751 480 +3 705 177 2722 +3 885 882 765 +3 177 565 567 +3 402 1326 587 +3 556 1516 1509 +3 1690 1691 1213 +3 742 745 734 +3 725 1235 736 +3 1374 769 1375 +3 1361 769 1374 +3 1343 566 565 +3 451 1343 565 +3 707 1066 603 +3 707 632 1066 +3 1076 656 1078 +3 584 1643 1644 +3 705 2722 526 +3 1326 402 1085 +3 1148 1086 402 +3 598 652 2665 +3 2636 2635 577 +3 773 611 914 +3 611 773 772 +3 914 622 915 +3 1925 1924 757 +3 680 697 605 +3 663 646 645 +3 732 724 733 +3 833 490 831 +3 677 669 636 +3 618 617 1182 +3 617 618 419 +3 844 490 509 +3 697 680 635 +3 566 713 186 +3 1070 595 1071 +3 1825 107 57 +3 814 409 813 +3 636 672 673 +3 2349 2348 1203 +3 900 117 901 +3 1206 573 1205 +3 658 679 675 +3 2653 1821 596 +3 410 621 622 +3 2738 2737 1207 +3 649 1665 891 +3 620 0 621 +3 680 678 635 +3 674 658 675 +3 598 2664 2666 +3 1807 602 1806 +3 698 710 584 +3 710 698 1096 +3 395 798 828 +3 1365 1372 1364 +3 1371 1372 1365 +3 409 2479 827 +3 1321 610 609 +3 1151 616 1223 +3 2177 2176 1044 +3 0 915 621 +3 2664 2665 687 +3 2672 2671 580 +3 733 724 735 +3 2737 1211 2741 +3 1346 453 1345 +3 2351 1209 1204 +3 845 2676 833 +3 2323 715 1625 +3 1151 1150 616 +3 2352 2344 1201 +3 2273 2274 588 +3 615 1516 556 +3 557 1516 1515 +3 744 50 743 +3 1145 1144 589 +3 1181 1182 619 +3 1182 1181 618 +3 2546 2545 1626 +3 620 621 411 +3 1374 1375 770 +3 405 1356 1320 +3 1359 1356 405 +3 145 2144 2139 +3 1353 452 1352 +3 1469 2141 355 +3 137 379 1165 +3 784 558 620 +3 670 693 638 +3 668 671 672 +3 2753 1779 2754 +3 1069 722 721 +3 654 1187 1188 +3 637 678 680 +3 1687 1688 660 +3 813 390 816 +3 671 667 658 +3 667 679 658 +3 2350 1195 613 +3 607 646 663 +3 665 595 666 +3 638 666 668 +3 711 1096 1095 +3 769 1361 1358 +3 758 1924 1925 +3 597 1086 1087 +3 1989 900 1990 +3 1183 1184 416 +3 708 581 701 +3 1420 1407 2330 +3 637 680 685 +3 672 671 658 +3 669 670 638 +3 636 669 668 +3 669 638 668 +3 637 670 669 +3 1919 1921 600 +3 816 412 813 +3 693 628 665 +3 1082 1077 1078 +3 636 668 672 +3 666 595 667 +3 1641 1642 710 +3 884 648 881 +3 1688 707 660 +3 637 685 670 +3 145 359 2144 +3 1908 1907 895 +3 706 660 707 +3 1861 1247 1860 +3 731 568 734 +3 721 722 642 +3 606 1089 1081 +3 1352 452 1351 +3 2152 682 1504 +3 857 546 223 +3 717 1627 2545 +3 1780 1797 2750 +3 747 746 563 +3 881 694 882 +3 1133 639 1132 +3 489 829 2680 +3 1548 1537 1564 +3 965 964 252 +3 490 844 832 +3 1175 1176 1180 +3 1557 1559 793 +3 2547 2542 1628 +3 1726 1639 2009 +3 992 990 176 +3 859 222 858 +3 1667 222 859 +3 732 465 731 +3 465 730 731 +3 566 186 534 +3 357 2130 2129 +3 465 732 733 +3 1366 768 1368 +3 746 749 563 +3 731 734 732 +3 743 568 746 +3 568 743 742 +3 1579 516 1994 +3 878 2164 2165 +3 773 1176 772 +3 956 839 417 +3 50 742 743 +3 1233 736 1234 +3 751 733 480 +3 903 365 137 +3 465 733 751 +3 751 728 750 +3 465 751 750 +3 752 365 138 +3 1922 1923 758 +3 1389 2666 1392 +3 575 805 94 +3 881 762 694 +3 1442 2492 1134 +3 887 886 765 +3 406 776 1371 +3 954 417 955 +3 590 1322 1323 +3 2661 178 2659 +3 137 1165 1166 +3 773 1180 1176 +3 622 914 911 +3 439 467 1426 +3 782 591 781 +3 765 893 887 +3 413 835 834 +3 809 813 409 +3 805 823 397 +3 1356 777 1320 +3 1020 1236 1237 +3 793 1558 1557 +3 2686 2685 866 +3 965 123 964 +3 703 1096 1097 +3 2317 1019 2316 +3 1557 421 1559 +3 286 2179 232 +3 1676 2176 2177 +3 354 2133 352 +3 393 802 803 +3 407 806 478 +3 954 956 417 +3 777 2488 1320 +3 1212 1211 244 +3 2238 2580 2237 +3 813 809 390 +3 1184 1183 814 +3 835 149 840 +3 478 821 819 +3 392 2579 2580 +3 1127 2481 953 +3 819 821 820 +3 818 819 477 +3 818 478 819 +3 805 396 823 +3 819 820 477 +3 1211 573 2741 +3 397 823 478 +3 395 825 798 +3 2236 829 797 +3 831 392 487 +3 2681 489 2680 +3 798 829 828 +3 956 953 416 +3 953 956 954 +3 2128 695 591 +3 1184 814 412 +3 1943 2576 1122 +3 487 846 845 +3 1904 1903 849 +3 542 853 553 +3 16 2608 1593 +3 1048 2160 2159 +3 1586 2772 2773 +3 856 223 855 +3 978 867 1108 +3 2194 2189 2758 +3 239 536 2731 +3 2295 2296 865 +3 2170 2166 1046 +3 1138 1171 657 +3 873 1055 1035 +3 2046 2045 936 +3 2134 2145 142 +3 1167 44 360 +3 875 2296 2770 +3 2165 2164 2167 +3 1051 1052 1034 +3 914 915 773 +3 306 14 1143 +3 623 913 912 +3 2695 2694 301 +3 2353 2354 614 +3 694 762 1920 +3 1906 1907 1367 +3 1142 304 1143 +3 906 117 900 +3 756 117 906 +3 931 1767 1766 +3 754 756 906 +3 214 910 59 +3 911 912 622 +3 1129 870 1128 +3 77 337 1126 +3 917 217 916 +3 917 916 918 +3 1001 998 951 +3 1392 1818 1393 +3 1739 1740 183 +3 1075 1124 1125 +3 1414 440 1412 +3 964 963 252 +3 1494 1496 1495 +3 2708 2662 2707 +3 1881 1882 2437 +3 396 2766 822 +3 823 396 822 +3 2711 415 2708 +3 417 2710 957 +3 1008 473 1005 +3 289 1073 960 +3 71 130 131 +3 2223 1004 2222 +3 2050 339 2051 +3 1625 715 1626 +3 2520 2333 2519 +3 2407 2197 2408 +3 2197 2407 2198 +3 1226 2334 948 +3 2678 2192 2224 +3 2433 2305 2302 +3 124 1015 1016 +3 248 255 60 +3 473 1003 1005 +3 2191 1003 473 +3 2348 613 1202 +3 2036 993 2035 +3 123 907 964 +3 907 123 1015 +3 1207 2739 2738 +3 1242 1838 1839 +3 926 1681 1680 +3 1109 865 1110 +3 868 1109 1110 +3 2320 1621 2319 +3 1037 1038 1043 +3 2768 2767 1130 +3 1986 265 86 +3 1984 1986 86 +3 2107 1298 2108 +3 2377 2375 1271 +3 1380 2375 2377 +3 2195 2229 2214 +3 1294 1153 1289 +3 995 61 994 +3 1253 1856 1689 +3 2113 1299 229 +3 2423 889 2421 +3 1274 1273 1269 +3 373 1273 1274 +3 1610 1611 1154 +3 1610 471 1611 +3 2120 226 2121 +3 2535 1524 1526 +3 1375 894 770 +3 2072 204 2073 +3 2601 2604 2602 +3 2601 1575 2604 +3 981 980 979 +3 981 979 221 +3 922 425 920 +3 425 922 970 +3 2142 2145 2134 +3 2650 2145 2142 +3 970 922 220 +3 113 2062 2060 +3 2451 921 1996 +3 1996 217 2451 +3 217 920 2451 +3 57 1826 1825 +3 2168 2171 2169 +3 208 2081 214 +3 770 2258 600 +3 2258 770 883 +3 2085 975 974 +3 549 974 211 +3 335 1888 1887 +3 1334 2084 213 +3 976 548 211 +3 2079 2078 210 +3 1755 337 1754 +3 1332 213 1331 +3 869 1672 1669 +3 281 58 11 +3 58 281 1938 +3 1815 1816 219 +3 1816 979 219 +3 1812 1815 219 +3 998 1232 951 +3 1997 1996 1995 +3 2094 2096 2093 +3 2096 2094 221 +3 2098 978 971 +3 978 973 971 +3 2093 2096 971 +3 2096 2098 971 +3 2098 2096 2097 +3 1619 547 546 +3 1996 921 1995 +3 2096 221 2097 +3 1821 601 1820 +3 1769 1577 1768 +3 1581 1769 1768 +3 925 924 1997 +3 984 316 233 +3 303 2692 2068 +3 2692 300 2068 +3 2129 2130 2147 +3 1529 1525 792 +3 1530 1529 1523 +3 729 563 730 +3 2728 257 2729 +3 2673 699 2668 +3 699 2667 2668 +3 1541 1540 55 +3 1536 1540 1541 +3 1533 1531 1530 +3 348 1971 1998 +3 1523 1532 1530 +3 2250 2251 1553 +3 2251 2250 796 +3 676 657 1632 +3 1633 676 1632 +3 1527 422 983 +3 2248 150 2253 +3 2249 2248 2253 +3 2693 2689 2694 +3 2693 2691 2689 +3 22 298 299 +3 2656 697 635 +3 787 2656 635 +3 2599 1972 2597 +3 1972 1973 2597 +3 316 39 317 +3 316 984 39 +3 984 311 39 +3 1393 1818 601 +3 37 195 1729 +3 2052 2054 140 +3 1120 2218 1949 +3 989 990 96 +3 990 989 991 +3 1684 9 1682 +3 998 1001 61 +3 66 1686 1683 +3 990 930 176 +3 930 990 34 +3 930 933 176 +3 298 2059 295 +3 444 1460 1461 +3 444 2743 1460 +3 195 996 995 +3 2158 1049 2159 +3 1677 1676 1045 +3 985 180 989 +3 180 985 423 +3 333 89 1140 +3 333 1492 89 +3 695 1186 2477 +3 1186 174 2477 +3 2062 2061 2060 +3 991 34 990 +3 1699 1063 1669 +3 930 928 933 +3 33 347 346 +3 33 1000 347 +3 1030 1032 860 +3 1030 2515 1032 +3 1886 2640 2649 +3 2640 1885 2649 +3 1161 2432 2285 +3 993 987 988 +3 987 96 988 +3 143 1491 1492 +3 1493 143 1492 +3 1493 334 336 +3 734 745 1233 +3 38 1334 344 +3 927 926 1685 +3 1867 1265 1864 +3 1679 4 202 +3 2050 127 1614 +3 127 1616 1614 +3 922 920 917 +3 195 37 996 +3 1731 1736 1732 +3 1757 329 1760 +3 351 34 999 +3 327 351 999 +3 774 1179 1369 +3 1233 745 736 +3 1491 1002 332 +3 2565 88 2569 +3 323 197 99 +3 996 997 998 +3 999 991 180 +3 1000 999 180 +3 1000 327 999 +3 2140 356 2141 +3 1743 1742 324 +3 1000 180 423 +3 347 1000 423 +3 33 327 1000 +3 987 1001 951 +3 351 99 197 +3 1029 864 1030 +3 2773 1706 2006 +3 2605 2606 1574 +3 960 292 1117 +3 1073 292 960 +3 1959 1958 1114 +3 2272 1326 2274 +3 2002 249 248 +3 249 67 248 +3 2201 1006 2203 +3 2200 2210 2211 +3 1939 1935 1936 +3 1939 112 1935 +3 1533 982 1534 +3 1538 1533 1534 +3 2206 2203 2204 +3 70 124 125 +3 1014 124 70 +3 2028 994 2042 +3 2041 2028 2042 +3 2192 1005 2186 +3 1962 1960 1963 +3 1965 350 1960 +3 2187 961 2188 +3 77 1395 261 +3 41 2000 1999 +3 1014 907 1015 +3 122 907 1014 +3 70 122 1014 +3 350 1114 2213 +3 2209 2200 2204 +3 2209 2204 1006 +3 2668 700 2669 +3 141 2053 2056 +3 2321 2320 1620 +3 2321 1621 2320 +3 1010 2213 2208 +3 2299 1321 1322 +3 405 1321 2299 +3 706 707 683 +3 2301 1157 1602 +3 831 490 2679 +3 490 832 2679 +3 287 1012 1011 +3 1010 2206 2204 +3 1013 2191 473 +3 2205 1013 473 +3 2561 166 2560 +3 2201 2202 1008 +3 2203 2202 2201 +3 2369 2368 2370 +3 1896 1897 1895 +3 102 40 107 +3 2394 1283 53 +3 1283 2394 2390 +3 985 2154 986 +3 2076 2072 2073 +3 2076 208 2072 +3 308 310 1018 +3 755 308 1018 +3 308 755 14 +3 1848 1849 1251 +3 2345 1200 2346 +3 737 740 1238 +3 740 737 738 +3 1020 1021 735 +3 738 737 50 +3 50 744 738 +3 454 1259 455 +3 1337 1350 729 +3 480 1021 1022 +3 738 744 741 +3 457 738 741 +3 1841 1840 193 +3 1840 1841 1242 +3 1693 1691 1519 +3 1025 442 188 +3 1257 1256 1024 +3 453 450 1259 +3 928 931 2022 +3 931 932 2022 +3 2055 2056 2053 +3 2056 2055 1495 +3 336 1497 1496 +3 2701 1678 1673 +3 1672 2701 1673 +3 436 455 1025 +3 188 436 1025 +3 459 467 439 +3 702 1123 1093 +3 1026 842 843 +3 1093 1123 841 +3 1945 2578 1943 +3 2684 2384 371 +3 2384 2684 2386 +3 1526 1524 1527 +3 2537 2538 1173 +3 2252 796 2235 +3 1076 1125 656 +3 691 2316 2315 +3 704 842 1026 +3 342 1747 1748 +3 1747 341 1748 +3 1163 320 110 +3 190 2639 2637 +3 2065 2064 2066 +3 2079 93 919 +3 2078 2077 2082 +3 2077 91 2082 +3 1231 1230 182 +3 1678 2178 1674 +3 1048 2168 2167 +3 1676 2177 2178 +3 2177 1044 2178 +3 2500 2508 1041 +3 190 2594 2595 +3 377 136 2774 +3 874 1033 1032 +3 1710 2265 2337 +3 2336 1710 2337 +3 2158 1057 2157 +3 1057 2163 2157 +3 1236 735 1235 +3 1815 1812 1814 +3 499 1578 503 +3 2315 2316 714 +3 1620 2315 714 +3 382 1165 379 +3 1033 873 1035 +3 1033 1034 873 +3 1238 725 737 +3 861 1030 860 +3 1036 861 860 +3 1035 1036 860 +3 1938 2490 58 +3 861 1029 1030 +3 1285 2720 1488 +3 1801 1286 1274 +3 367 1801 1274 +3 937 2013 2021 +3 1673 1674 1043 +3 1415 1430 2622 +3 1430 1419 2622 +3 2161 1057 2160 +3 1037 871 1038 +3 28 1599 1597 +3 1830 28 1597 +3 2025 2044 2043 +3 2161 2162 2163 +3 2173 2172 1050 +3 2172 2173 879 +3 1095 703 2502 +3 1169 604 1170 +3 1169 1065 604 +3 971 425 970 +3 658 674 673 +3 788 604 1065 +3 631 788 1065 +3 659 2153 1019 +3 2153 2318 1019 +3 425 971 973 +3 1059 2155 2770 +3 868 1105 1107 +3 1109 868 1107 +3 35 2028 2027 +3 2028 198 2027 +3 2132 356 2131 +3 331 1756 1757 +3 2014 2032 2031 +3 2032 2015 2031 +3 1047 2171 2168 +3 1046 2166 2165 +3 1048 1049 872 +3 1834 1759 262 +3 873 1053 1055 +3 1715 155 1714 +3 2509 2508 1040 +3 2731 2726 537 +3 1705 1704 1584 +3 616 2349 1203 +3 238 543 212 +3 1047 872 1051 +3 2171 2172 879 +3 1050 1051 1034 +3 1708 1707 572 +3 2090 2089 967 +3 1681 31 1680 +3 2513 1031 2514 +3 1031 2515 2514 +3 2508 2500 1061 +3 2500 2501 1061 +3 1033 874 1034 +3 1034 1052 873 +3 1052 1053 873 +3 1052 1056 1053 +3 1055 863 1035 +3 1032 1033 860 +3 1033 1035 860 +3 1054 863 1055 +3 1049 2295 880 +3 2295 1049 876 +3 1967 1444 2491 +3 1056 1052 872 +3 1706 508 2268 +3 1580 1706 2268 +3 1814 863 1054 +3 1788 1790 1789 +3 1056 880 1053 +3 2016 2017 2033 +3 1054 1053 880 +3 2194 1011 2193 +3 2095 969 967 +3 2091 2092 970 +3 2091 969 2092 +3 2618 2616 2608 +3 2618 2607 2616 +3 2167 1046 2165 +3 2162 2161 878 +3 2644 2643 9 +3 2025 2038 2037 +3 2008 2257 2258 +3 883 2008 2258 +3 1004 2185 2187 +3 673 672 658 +3 940 1979 1976 +3 199 1886 196 +3 2769 875 2770 +3 1106 864 1029 +3 923 1106 1029 +3 2506 2508 1061 +3 640 1171 1170 +3 1171 641 1170 +3 2224 2192 2223 +3 2770 2155 1060 +3 2155 870 1060 +3 240 528 527 +3 1518 528 240 +3 220 2088 2090 +3 2088 2089 2090 +3 2035 993 988 +3 2099 2085 974 +3 2564 1742 1745 +3 2165 2166 878 +3 2013 2046 936 +3 937 2046 2013 +3 1684 1686 66 +3 631 1065 1066 +3 1067 631 1066 +3 667 1067 632 +3 1067 1066 632 +3 595 1067 667 +3 1091 2468 2466 +3 1170 641 1169 +3 1066 1068 603 +3 1066 1065 1068 +3 1170 635 640 +3 604 635 1170 +3 1934 1932 1912 +3 1928 1927 758 +3 1067 595 1070 +3 1068 1065 1169 +3 471 1612 1611 +3 1612 225 1611 +3 1067 1070 631 +3 2399 271 2400 +3 665 664 1071 +3 664 665 628 +3 2125 2126 224 +3 102 103 40 +3 712 1075 2589 +3 2588 712 2589 +3 612 399 583 +3 399 612 1150 +3 1076 1078 1074 +3 673 657 676 +3 1084 597 1078 +3 1115 1765 1116 +3 291 1115 1116 +3 653 1083 1082 +3 687 653 1082 +3 656 1824 1823 +3 1077 1082 1083 +3 1075 1125 1076 +3 1094 1093 712 +3 711 710 1096 +3 2274 2273 2272 +3 1094 702 1093 +3 584 2011 698 +3 2011 584 1645 +3 1087 1080 597 +3 1080 1087 95 +3 593 1087 1086 +3 593 1088 1087 +3 1078 1077 1084 +3 1179 1174 406 +3 1911 1394 645 +3 1911 1926 1394 +3 690 2463 1102 +3 1076 1074 2589 +3 1822 1823 688 +3 173 1104 542 +3 1091 1090 2468 +3 1099 599 1091 +3 690 1099 1091 +3 1529 1528 1523 +3 594 1098 1099 +3 1077 1085 1084 +3 2570 325 1733 +3 597 1080 1079 +3 1963 1960 1112 +3 424 655 1088 +3 1079 1080 599 +3 1080 1081 599 +3 2423 2422 757 +3 2422 2423 2421 +3 404 2422 2421 +3 760 653 759 +3 760 1083 653 +3 48 314 275 +3 1149 1088 593 +3 2589 1075 1076 +3 2588 2589 1074 +3 1085 1077 1697 +3 1146 1148 402 +3 1146 592 1148 +3 1641 711 581 +3 711 2563 581 +3 591 782 1330 +3 1146 1147 589 +3 1147 402 587 +3 1087 1088 95 +3 1088 655 95 +3 655 662 95 +3 1820 601 1819 +3 2291 2281 2365 +3 2286 2291 2365 +3 1527 982 1594 +3 962 1124 1101 +3 1203 1204 616 +3 1093 841 1075 +3 1091 599 1090 +3 599 1089 1090 +3 2469 1090 2470 +3 1103 2461 1122 +3 2458 2461 1103 +3 399 2472 2473 +3 2472 399 1151 +3 2060 2061 26 +3 794 2237 2232 +3 599 1081 1089 +3 603 721 800 +3 721 720 800 +3 2117 2114 2115 +3 2466 2468 2467 +3 689 2466 2467 +3 2468 1090 2469 +3 2467 2468 2469 +3 626 2470 1089 +3 688 1092 689 +3 1820 689 1821 +3 1099 1079 599 +3 1126 332 338 +3 332 25 338 +3 706 686 1504 +3 683 686 706 +3 702 1094 1095 +3 962 1100 1092 +3 1078 1079 1098 +3 1079 1078 597 +3 2566 1747 342 +3 1074 1098 594 +3 1074 1078 1098 +3 594 1099 1102 +3 2562 2563 711 +3 841 1124 1075 +3 1098 1079 1099 +3 1460 1630 1461 +3 1760 329 1761 +3 249 2002 2763 +3 254 249 2763 +3 1628 1629 642 +3 1628 720 1629 +3 925 1104 173 +3 1823 1824 688 +3 1125 1124 962 +3 677 1633 1634 +3 1183 815 814 +3 1503 2282 2287 +3 2288 1503 2287 +3 2717 2718 1432 +3 856 542 1104 +3 858 856 1104 +3 858 857 856 +3 858 1104 925 +3 858 925 859 +3 594 2459 2460 +3 1102 1099 690 +3 2578 1026 2576 +3 1671 1039 870 +3 1107 1106 5 +3 1108 1107 5 +3 2277 2505 2501 +3 2277 2504 2505 +3 2505 1061 2501 +3 1672 1038 1699 +3 2367 370 1475 +3 2014 936 2032 +3 521 1791 1785 +3 1814 1054 866 +3 1815 1814 866 +3 1608 1607 470 +3 1607 1608 2687 +3 1154 2687 1608 +3 1108 867 1109 +3 1107 1108 1109 +3 1030 2514 2515 +3 1281 2262 1696 +3 2262 1281 2263 +3 1825 8 107 +3 1956 1955 1117 +3 2185 2184 288 +3 1003 2184 2185 +3 2224 2225 2189 +3 2226 2224 2189 +3 88 2565 2566 +3 185 448 1887 +3 1174 780 406 +3 286 232 285 +3 1834 1753 1746 +3 116 2021 2023 +3 2021 2013 2023 +3 1954 1963 1112 +3 1833 1832 1830 +3 620 624 618 +3 2760 1004 2188 +3 799 1524 2535 +3 2210 2200 2209 +3 1116 1119 291 +3 2416 1190 1189 +3 1521 2230 1525 +3 8 102 107 +3 1118 1953 1955 +3 1954 1953 1118 +3 1007 2196 2195 +3 1116 475 1613 +3 1113 1956 1957 +3 1952 1951 1120 +3 1950 290 1111 +3 882 2007 765 +3 1955 1964 1118 +3 1445 1444 1966 +3 1008 2202 473 +3 896 2699 2700 +3 683 707 800 +3 2242 2241 2243 +3 675 1687 681 +3 639 675 681 +3 1525 1529 1530 +3 2546 1626 3 +3 2461 841 1122 +3 912 913 1127 +3 912 1127 410 +3 953 410 1127 +3 810 827 174 +3 827 2476 174 +3 2481 2480 783 +3 2481 1127 2480 +3 845 846 2482 +3 2352 2353 2357 +3 1229 182 1228 +3 182 1230 1228 +3 1069 641 722 +3 641 1133 722 +3 2320 2319 691 +3 722 1132 1131 +3 1132 722 1133 +3 361 383 1167 +3 1902 391 1901 +3 431 147 432 +3 1229 181 423 +3 2316 2318 714 +3 2318 2316 1019 +3 1131 659 1019 +3 1131 1132 659 +3 2716 459 192 +3 1136 2 354 +3 461 2662 191 +3 536 2725 2726 +3 484 485 1462 +3 484 389 485 +3 973 2452 2450 +3 2452 921 2450 +3 2141 1891 355 +3 1440 1701 437 +3 1936 1935 13 +3 1409 2520 2519 +3 355 494 1453 +3 346 1760 1761 +3 329 1758 340 +3 1847 193 1845 +3 1846 1847 1845 +3 1856 1853 1689 +3 1247 1266 1860 +3 1395 1126 338 +3 153 366 943 +3 366 1267 943 +3 1798 525 1774 +3 2696 2690 2695 +3 363 2696 2695 +3 898 2695 301 +3 94 805 804 +3 1194 111 1142 +3 633 1805 1804 +3 1737 997 1736 +3 1517 1208 1518 +3 523 1517 1518 +3 715 2321 1620 +3 582 2474 2471 +3 582 2473 2474 +3 111 304 1142 +3 303 304 2692 +3 111 1194 905 +3 1498 2135 142 +3 2136 357 2137 +3 304 306 1143 +3 152 306 304 +3 408 810 811 +3 2476 2478 2475 +3 913 2476 2475 +3 593 1148 1149 +3 592 1149 1148 +3 808 408 2241 +3 1148 593 1086 +3 594 2460 1074 +3 2459 1103 2460 +3 1558 2231 1521 +3 810 408 809 +3 809 408 808 +3 2275 2270 2272 +3 886 885 765 +3 1149 592 812 +3 592 811 812 +3 2145 385 384 +3 142 2145 384 +3 1197 610 1198 +3 2517 1776 523 +3 2724 2723 257 +3 56 2267 1709 +3 471 2183 1612 +3 227 2112 2111 +3 1608 1609 1610 +3 470 1609 1608 +3 314 313 233 +3 313 312 233 +3 1310 1309 231 +3 276 1310 1297 +3 1292 2413 2415 +3 48 372 313 +3 471 1610 1609 +3 2387 2388 161 +3 2391 2387 161 +3 225 1603 1155 +3 321 2066 2064 +3 1163 2066 321 +3 2261 472 2260 +3 1606 1154 1155 +3 1603 1602 1155 +3 1083 1697 1077 +3 2263 1281 1287 +3 1281 228 1287 +3 1611 225 1155 +3 1310 231 1297 +3 1306 1299 2112 +3 1277 1288 1289 +3 1288 1294 1289 +3 1694 1695 1279 +3 1695 1694 1281 +3 643 661 1804 +3 1382 661 643 +3 1279 1275 1656 +3 1278 1654 1655 +3 1156 1660 1292 +3 1291 1652 1653 +3 1291 1277 1289 +3 228 1288 1287 +3 228 1293 1288 +3 1970 1275 1273 +3 2347 2348 2346 +3 2291 2432 2431 +3 2432 2291 2286 +3 2013 2366 2023 +3 366 153 312 +3 2372 366 312 +3 370 2368 2369 +3 472 2261 1119 +3 1951 2297 2218 +3 2217 2297 1950 +3 2297 2217 2218 +3 1365 1366 775 +3 1166 1167 360 +3 361 1167 1166 +3 2206 2207 1009 +3 277 6 279 +3 277 1168 6 +3 444 1459 2743 +3 268 97 274 +3 821 823 822 +3 1458 1460 2743 +3 1460 1458 1457 +3 1005 2227 2193 +3 2159 1057 2158 +3 1919 2258 2257 +3 2169 1046 2765 +3 720 721 1629 +3 657 1171 1632 +3 1627 2547 1628 +3 2466 2465 1091 +3 2466 1092 2465 +3 1523 1594 1532 +3 426 2485 1182 +3 617 426 1182 +3 1196 2356 1199 +3 2356 1196 1197 +3 1181 0 618 +3 0 620 618 +3 1180 619 1175 +3 741 192 457 +3 1250 1254 1244 +3 1176 774 1177 +3 773 915 1181 +3 1636 1405 1635 +3 619 1180 1181 +3 462 192 741 +3 646 1911 645 +3 1911 646 1912 +3 771 1367 888 +3 629 1387 1910 +3 1926 629 1910 +3 1371 775 406 +3 1179 406 775 +3 1369 1179 775 +3 1440 2592 1701 +3 2590 1437 1436 +3 712 1093 1075 +3 1176 1175 774 +3 2484 619 1182 +3 2485 2484 1182 +3 2486 2487 780 +3 779 780 2487 +3 780 779 406 +3 98 272 284 +3 272 2399 284 +3 424 1187 655 +3 38 2084 1334 +3 494 493 1450 +3 1192 654 1191 +3 799 2535 1522 +3 812 1185 424 +3 1149 812 424 +3 1808 663 645 +3 812 1186 1185 +3 812 174 1186 +3 811 174 812 +3 1404 1428 2521 +3 1666 1668 861 +3 1189 654 1188 +3 2417 1189 2419 +3 884 2423 648 +3 647 1913 2397 +3 655 1187 1192 +3 2426 890 2416 +3 654 1189 1190 +3 270 2402 2401 +3 1193 906 900 +3 271 2398 97 +3 2417 2416 1189 +3 2426 2416 2417 +3 1191 2397 607 +3 654 1190 1191 +3 305 906 1193 +3 906 305 754 +3 654 1192 1187 +3 1936 108 1939 +3 1192 662 655 +3 607 662 1192 +3 662 607 663 +3 2446 1027 2448 +3 1570 2587 1587 +3 2587 1563 1587 +3 647 1914 1913 +3 1142 1143 305 +3 1193 1142 305 +3 2595 2639 190 +3 1473 2639 2595 +3 322 905 1194 +3 1194 1142 1193 +3 1196 394 1197 +3 915 0 1181 +3 2676 486 2575 +3 615 556 400 +3 1206 1205 556 +3 529 1206 556 +3 1205 400 556 +3 2211 350 2213 +3 2211 1961 350 +3 577 2471 2472 +3 576 577 2472 +3 805 397 804 +3 1195 394 1196 +3 2486 2485 426 +3 913 623 2477 +3 2636 577 94 +3 1631 719 720 +3 719 1631 2539 +3 1195 1196 613 +3 1196 1199 613 +3 616 2350 2349 +3 616 1150 2350 +3 528 2740 1511 +3 1209 1224 1210 +3 1224 2358 1210 +3 2242 407 2244 +3 83 1711 1302 +3 1300 83 1302 +3 1727 1726 579 +3 1645 579 2011 +3 1516 557 1509 +3 1221 1222 576 +3 1222 94 576 +3 613 1199 1202 +3 170 1716 263 +3 1355 528 1511 +3 1210 400 1209 +3 2767 2768 824 +3 2221 2196 2756 +3 2196 2221 2220 +3 570 1217 1219 +3 1217 570 520 +3 2739 1207 529 +3 1219 1693 1220 +3 1219 524 1693 +3 207 910 154 +3 1212 1213 574 +3 2358 1224 2357 +3 1204 400 1205 +3 1204 1209 400 +3 613 2349 2350 +3 2351 1203 2347 +3 1203 2348 2347 +3 399 1727 583 +3 501 1788 1787 +3 1971 1973 1972 +3 396 575 1130 +3 575 1225 1130 +3 2352 2357 1224 +3 1639 1726 582 +3 520 1218 1217 +3 497 518 1792 +3 2348 1202 2346 +3 242 1217 1218 +3 1208 2739 2740 +3 2739 529 2740 +3 277 2742 1168 +3 519 1785 1786 +3 1772 522 1771 +3 1218 825 242 +3 825 1218 500 +3 2023 2366 935 +3 242 1216 1217 +3 782 1327 1330 +3 56 1788 1789 +3 2631 2633 2628 +3 2631 2634 2633 +3 233 312 984 +3 1786 1785 1791 +3 1793 1784 1794 +3 570 1220 1776 +3 1223 616 573 +3 616 1205 573 +3 1776 2517 1783 +3 574 1221 1214 +3 1199 2356 2354 +3 1214 1223 573 +3 1223 1214 1221 +3 1211 1214 573 +3 419 624 625 +3 1515 419 625 +3 1150 1195 2350 +3 2455 1685 1680 +3 2286 2362 1172 +3 1695 1696 375 +3 1219 1220 570 +3 2359 615 1210 +3 2358 2359 1210 +3 1509 557 1512 +3 1236 725 1237 +3 949 946 1226 +3 183 946 949 +3 36 1232 998 +3 997 36 998 +3 874 1037 1043 +3 1226 1227 949 +3 1226 181 1227 +3 1123 702 1943 +3 740 739 1240 +3 1836 740 1240 +3 354 2 1891 +3 1229 1227 181 +3 1229 1228 1227 +3 1909 769 1358 +3 772 1909 1358 +3 923 1029 1028 +3 2178 1044 1674 +3 1232 36 950 +3 859 925 218 +3 925 1997 218 +3 924 217 1996 +3 1817 949 1230 +3 945 184 947 +3 2044 2048 2049 +3 2048 2044 2026 +3 2734 537 238 +3 1836 2496 2497 +3 1236 1020 735 +3 18 2642 2644 +3 1844 1839 1843 +3 1839 1844 1840 +3 1235 725 1236 +3 1243 1846 739 +3 1251 193 1847 +3 1366 1365 888 +3 1846 1250 1847 +3 1022 1842 1023 +3 458 1838 1242 +3 1842 1242 1841 +3 739 457 1243 +3 737 725 736 +3 2383 2386 2385 +3 2382 2383 2385 +3 1845 193 1840 +3 1255 193 1251 +3 184 535 947 +3 947 535 49 +3 535 1888 49 +3 1237 1239 1020 +3 1839 1838 1837 +3 1243 1250 1846 +3 192 456 457 +3 458 1242 1842 +3 1251 1252 1024 +3 339 2052 2051 +3 110 2065 2066 +3 1616 1617 130 +3 69 1616 130 +3 448 90 335 +3 1842 1841 1023 +3 2622 1418 2621 +3 1268 1270 367 +3 909 2050 2051 +3 2050 909 127 +3 1255 1841 193 +3 1247 1869 1868 +3 456 1254 457 +3 2552 60 2551 +3 1253 1254 456 +3 456 459 1249 +3 1249 439 1247 +3 1835 2496 1239 +3 2496 1835 2497 +3 1243 457 1254 +3 1496 1494 336 +3 2418 2419 763 +3 1277 1291 1653 +3 1909 1908 895 +3 1497 187 353 +3 2574 2230 2231 +3 1864 1865 1264 +3 1864 1265 1865 +3 440 2524 1412 +3 1254 1851 1244 +3 2308 2307 430 +3 1691 1692 1213 +3 1692 1215 1213 +3 1691 1690 1519 +3 450 1022 1258 +3 1909 1178 1908 +3 1263 1855 1262 +3 1024 1255 1251 +3 454 453 1259 +3 90 448 447 +3 448 186 447 +3 1256 1255 1024 +3 1255 1256 1023 +3 186 449 447 +3 1257 1260 54 +3 1023 1258 1022 +3 1023 1256 1258 +3 1256 1257 1258 +3 1258 1257 1259 +3 1245 1260 1252 +3 1488 2383 1285 +3 2383 1488 369 +3 1253 456 1862 +3 1861 1246 1862 +3 1367 768 1366 +3 1907 768 1367 +3 2764 1458 2743 +3 1459 2764 2743 +3 25 2052 339 +3 1263 1262 1866 +3 1519 1690 244 +3 1690 1212 244 +3 1457 386 1460 +3 1298 2110 2111 +3 1403 2327 2332 +3 2333 1403 2332 +3 2214 2219 2534 +3 2229 2219 2214 +3 2375 2380 2376 +3 140 74 908 +3 74 140 2054 +3 338 25 339 +3 520 570 571 +3 2598 250 2600 +3 1699 1038 1600 +3 1481 1479 369 +3 56 1789 2267 +3 1267 1270 1268 +3 1270 1267 366 +3 374 1267 1268 +3 433 1905 431 +3 1004 2186 2185 +3 351 1489 34 +3 1272 1801 1802 +3 2379 230 2378 +3 230 2377 2378 +3 1282 2394 53 +3 371 2683 2684 +3 1296 2107 2108 +3 1658 1293 228 +3 1314 98 285 +3 375 1282 1275 +3 1279 375 1275 +3 469 468 133 +3 1017 469 309 +3 1018 1017 309 +3 2393 1017 1018 +3 2684 2683 53 +3 2733 2732 2734 +3 551 2734 238 +3 555 537 2727 +3 2107 1296 1295 +3 1158 2107 1295 +3 1159 1291 1290 +3 1291 1289 1290 +3 1273 1282 53 +3 1269 1273 53 +3 1292 1159 2413 +3 312 153 311 +3 2125 17 1715 +3 2119 2120 1304 +3 2401 271 296 +3 1288 1277 1287 +3 2122 2125 2124 +3 375 1279 1695 +3 1656 1657 1279 +3 1656 1278 1657 +3 373 1969 1970 +3 424 1185 1187 +3 716 1623 642 +3 1131 716 642 +3 288 2184 2181 +3 2184 2182 2181 +3 1360 778 1359 +3 369 2384 2383 +3 2028 35 994 +3 370 1300 1319 +3 158 2100 2101 +3 227 2118 1306 +3 828 489 2682 +3 52 160 1478 +3 1305 52 1478 +3 1036 2429 1666 +3 1270 2378 367 +3 2378 1270 2379 +3 2730 2735 533 +3 1271 2375 2376 +3 1802 1271 1803 +3 1271 2376 1803 +3 1152 1307 1309 +3 1307 231 1309 +3 315 314 233 +3 231 1307 1295 +3 2111 2114 227 +3 1802 1803 1272 +3 2560 166 2549 +3 1158 2104 2106 +3 1158 2103 2104 +3 1153 1290 1289 +3 984 312 311 +3 1710 1709 2265 +3 1309 1311 470 +3 1153 1294 1295 +3 289 1336 2121 +3 2384 2386 2383 +3 1336 297 2121 +3 1300 229 1299 +3 83 1300 1299 +3 1607 1309 470 +3 48 1297 1313 +3 2272 1325 2275 +3 1325 2272 2273 +3 1422 1423 1399 +3 1114 1115 291 +3 1603 2301 1602 +3 1605 1308 1152 +3 1012 2211 2210 +3 371 2384 2391 +3 1116 1764 475 +3 1306 2112 227 +3 1280 1293 1658 +3 1603 225 1317 +3 1156 1603 1317 +3 475 1764 1763 +3 162 1476 1475 +3 2685 972 1816 +3 978 972 2685 +3 2114 2111 1301 +3 1315 1314 276 +3 1315 1297 275 +3 275 1297 48 +3 1315 276 1297 +3 2076 91 2077 +3 91 2076 2073 +3 2221 2760 2188 +3 1319 1302 1483 +3 369 1479 2387 +3 2384 369 2387 +3 160 52 159 +3 469 753 309 +3 1989 1991 322 +3 543 555 30 +3 555 2727 30 +3 189 1881 2437 +3 2396 1191 1190 +3 1009 2203 2206 +3 2106 2107 1158 +3 2107 2106 1298 +3 1290 2410 2413 +3 367 1802 1801 +3 1153 1295 1308 +3 1308 1295 1307 +3 1308 1307 1152 +3 47 280 283 +3 372 48 1313 +3 230 2370 1380 +3 1610 1154 1608 +3 1311 1309 1310 +3 235 314 315 +3 283 273 235 +3 2110 1301 2111 +3 98 1314 1315 +3 1311 276 1312 +3 276 1311 1310 +3 1660 1280 1659 +3 1312 1314 285 +3 1314 1312 276 +3 1301 2116 2115 +3 2115 2123 1303 +3 2123 1763 1303 +3 1010 2208 2206 +3 2410 2415 2413 +3 2651 2650 2142 +3 2412 2411 1153 +3 966 1155 1602 +3 1304 2120 2122 +3 1602 1157 1601 +3 2301 1292 2415 +3 1316 2409 2411 +3 2756 2196 2757 +3 647 2397 2396 +3 1357 777 1356 +3 1357 767 777 +3 911 778 623 +3 912 911 623 +3 611 911 914 +3 587 1650 1651 +3 805 575 396 +3 2478 783 2475 +3 952 2479 815 +3 405 1320 1321 +3 782 781 405 +3 2261 1013 1119 +3 1360 623 778 +3 1116 472 1119 +3 1322 1321 609 +3 1042 1129 2498 +3 1042 2769 1129 +3 2372 2379 366 +3 2379 1270 366 +3 2084 919 213 +3 2012 2673 1725 +3 1323 1322 609 +3 782 2299 2300 +3 1064 1600 871 +3 2274 1697 588 +3 2505 2506 1061 +3 1324 587 2270 +3 2400 284 2399 +3 2402 284 2400 +3 2074 977 2073 +3 977 2074 203 +3 2270 2269 1324 +3 404 2417 2418 +3 2417 2419 2418 +3 2563 2562 842 +3 2396 2397 1191 +3 1819 1822 688 +3 1330 1327 1328 +3 761 1330 1328 +3 1801 2264 1286 +3 2373 1475 1476 +3 918 1331 919 +3 1331 918 216 +3 1732 1730 1731 +3 2215 1950 1111 +3 77 1126 1395 +3 1757 1760 331 +3 1760 1139 331 +3 324 323 1744 +3 296 1336 270 +3 297 1336 296 +3 1038 871 1600 +3 1538 1534 1539 +3 728 1338 1337 +3 1340 1338 728 +3 1338 1340 1339 +3 1339 564 1338 +3 1339 569 564 +3 569 1339 565 +3 1346 1344 726 +3 564 1351 1350 +3 1351 564 1352 +3 451 1339 1340 +3 1339 451 565 +3 2168 2169 2765 +3 1349 1348 727 +3 450 1346 726 +3 955 957 411 +3 508 2267 2268 +3 453 1346 450 +3 1341 1347 727 +3 449 186 713 +3 1345 449 713 +3 1347 751 727 +3 451 1342 1343 +3 1349 727 480 +3 1343 713 566 +3 1344 713 1343 +3 713 1344 1345 +3 746 747 464 +3 463 2660 748 +3 2717 1432 467 +3 1344 1343 1342 +3 1347 728 751 +3 2660 178 748 +3 2659 178 2660 +3 1340 728 1347 +3 1340 1347 1341 +3 386 1345 453 +3 1345 1344 1346 +3 726 1342 1348 +3 726 1348 1349 +3 726 1349 450 +3 741 464 462 +3 741 744 464 +3 450 1349 1022 +3 1350 1351 729 +3 452 1353 1354 +3 1353 527 1354 +3 781 1360 1359 +3 411 2705 784 +3 569 1352 564 +3 1006 2201 2198 +3 497 1792 850 +3 887 888 403 +3 419 1516 615 +3 522 1772 526 +3 569 1353 1352 +3 452 1354 560 +3 561 452 560 +3 463 747 563 +3 776 406 779 +3 2443 1423 1422 +3 1379 885 886 +3 1362 1363 767 +3 1394 1910 644 +3 1910 1387 644 +3 1361 766 1362 +3 1576 1994 516 +3 590 1323 2271 +3 1357 1358 767 +3 1358 1361 767 +3 1407 1420 1400 +3 911 611 778 +3 611 772 1358 +3 1927 1922 758 +3 2331 1406 1402 +3 767 1361 1362 +3 888 1365 1364 +3 892 1363 1362 +3 1363 892 403 +3 1364 1363 403 +3 888 1364 403 +3 1177 772 1176 +3 766 892 1362 +3 774 1369 1370 +3 1177 774 1370 +3 1370 1368 768 +3 1178 1370 768 +3 1178 1177 1370 +3 1366 1368 775 +3 772 1177 1178 +3 2174 879 2173 +3 2174 2175 879 +3 2282 1161 2283 +3 2279 2282 1503 +3 1369 775 1368 +3 1370 1369 1368 +3 781 1359 405 +3 767 1363 1373 +3 709 708 2629 +3 1650 587 1324 +3 1646 608 1643 +3 1733 323 324 +3 1363 1364 1372 +3 2299 1322 2300 +3 767 1373 777 +3 1373 776 777 +3 1326 1697 2274 +3 1373 1363 1372 +3 1371 776 1372 +3 776 1373 1372 +3 1360 2477 623 +3 770 600 1376 +3 1374 770 1376 +3 1378 764 1379 +3 764 885 1379 +3 600 1377 1376 +3 1376 1377 766 +3 1234 724 1233 +3 1377 1378 766 +3 696 1186 695 +3 600 891 1377 +3 1028 1668 218 +3 554 217 924 +3 1378 1379 892 +3 766 1378 892 +3 1993 886 887 +3 1381 628 693 +3 670 1381 693 +3 1381 670 661 +3 1914 630 1915 +3 630 1916 1915 +3 1428 1417 1429 +3 1941 293 294 +3 1382 628 1381 +3 661 1382 1381 +3 2508 2509 1041 +3 2509 2512 1041 +3 980 219 979 +3 1809 219 980 +3 664 1388 1071 +3 651 1387 1390 +3 645 1384 602 +3 1072 1765 1115 +3 629 1390 1387 +3 629 1933 1390 +3 1870 1871 1265 +3 1874 1871 1870 +3 643 1804 1805 +3 2524 1410 2525 +3 644 1386 1385 +3 644 1387 1386 +3 628 1385 664 +3 644 1385 1383 +3 1383 1385 1382 +3 1385 628 1382 +3 1383 1382 643 +3 2523 1411 2333 +3 651 1388 1386 +3 1387 651 1386 +3 1934 1931 1932 +3 1931 650 1932 +3 2654 2653 596 +3 2654 2656 2653 +3 1615 1616 69 +3 1761 33 346 +3 644 1383 1384 +3 1929 1928 1925 +3 1391 1929 652 +3 598 1391 652 +3 598 1389 1391 +3 1388 1389 627 +3 1071 1388 627 +3 601 1818 1819 +3 1393 788 631 +3 1393 601 788 +3 290 1950 2298 +3 1388 664 1386 +3 1910 1394 1926 +3 1388 651 1389 +3 1407 2329 2330 +3 629 1926 1912 +3 1926 1911 1912 +3 638 665 666 +3 1389 651 1391 +3 440 1402 1406 +3 1666 862 1667 +3 862 1666 2429 +3 2672 700 2671 +3 92 1619 981 +3 1392 627 1389 +3 1394 644 1384 +3 1923 762 881 +3 1669 1672 1699 +3 200 2641 199 +3 126 261 1395 +3 260 1754 1752 +3 2123 475 1763 +3 475 2123 2116 +3 1263 1866 1865 +3 1496 353 75 +3 1497 353 1496 +3 1916 1922 1927 +3 1432 1431 1426 +3 1476 2720 1285 +3 2720 1476 1477 +3 2141 356 1891 +3 1441 1442 1134 +3 909 139 127 +3 838 837 1473 +3 306 152 307 +3 25 1002 2053 +3 189 1878 1881 +3 2328 2329 1407 +3 1436 441 2623 +3 2130 2131 356 +3 1411 1403 2333 +3 383 384 44 +3 1040 2513 1105 +3 1617 1616 127 +3 2449 1421 2528 +3 1410 2521 1428 +3 2521 1410 2520 +3 1811 862 1813 +3 1411 1406 1403 +3 1918 2259 1920 +3 630 1918 1920 +3 920 425 2450 +3 1439 2331 1402 +3 2331 1439 2444 +3 10 1413 2525 +3 1413 1412 2525 +3 1425 1424 460 +3 381 74 237 +3 1868 1869 1248 +3 2327 1408 2522 +3 1414 1413 441 +3 1418 1436 2623 +3 2701 1672 869 +3 1635 1415 1636 +3 2399 2398 271 +3 1409 2521 2520 +3 1416 1417 1404 +3 2314 2308 2311 +3 2330 1401 1420 +3 147 430 2307 +3 147 431 430 +3 1404 1417 1428 +3 353 1136 352 +3 1165 361 1166 +3 2332 2327 1409 +3 237 384 383 +3 2331 1401 2330 +3 188 442 1414 +3 349 74 376 +3 753 133 752 +3 133 1883 752 +3 1424 438 1405 +3 438 1424 1425 +3 2055 1002 143 +3 2053 1002 2055 +3 1879 2441 442 +3 579 583 1727 +3 2131 2130 2136 +3 1636 1415 1429 +3 1437 1441 1134 +3 1401 2443 1422 +3 439 1426 1427 +3 1426 1425 1427 +3 2260 2191 1013 +3 2443 2444 2442 +3 1807 1808 602 +3 1431 438 1426 +3 1431 1430 438 +3 2717 437 2718 +3 2714 2713 1433 +3 364 365 1883 +3 2525 2529 10 +3 2525 1410 2529 +3 1878 1880 1396 +3 838 2595 1435 +3 1879 189 2439 +3 460 1424 1421 +3 1881 1877 1398 +3 1877 1881 1878 +3 1434 2713 2714 +3 356 2140 2130 +3 1880 443 1396 +3 1397 443 1880 +3 442 1025 1397 +3 467 1432 1426 +3 1399 1423 1875 +3 1867 1870 1265 +3 1870 1867 1868 +3 1427 1425 460 +3 1248 1876 1875 +3 444 1461 436 +3 1426 438 1425 +3 2524 2525 1412 +3 2530 1947 1946 +3 1947 2530 703 +3 1807 633 626 +3 2133 2132 144 +3 2404 286 2403 +3 108 1936 1937 +3 1419 1701 1700 +3 600 1921 891 +3 1700 1701 1135 +3 1417 1636 1429 +3 1406 2331 2330 +3 2620 2623 1413 +3 1913 1914 1915 +3 714 2290 2284 +3 2290 714 2318 +3 1703 2771 1702 +3 1405 1636 1417 +3 1416 1405 1417 +3 1919 1918 649 +3 2259 1918 1919 +3 2716 467 459 +3 66 351 197 +3 351 66 1489 +3 132 73 2533 +3 1438 435 188 +3 1459 435 1471 +3 441 1437 1438 +3 2652 44 385 +3 2444 1439 2442 +3 265 266 1502 +3 266 267 1502 +3 1500 2302 2305 +3 2440 2439 1402 +3 1437 441 1436 +3 1447 491 1451 +3 188 1414 1438 +3 1134 435 1438 +3 2593 1440 2594 +3 2201 1008 2198 +3 2651 2136 358 +3 2652 2651 358 +3 2492 2491 434 +3 1977 1596 1597 +3 2637 2638 1442 +3 434 1474 1470 +3 1450 493 1448 +3 2 493 494 +3 1445 491 1447 +3 492 1445 1447 +3 2595 838 1473 +3 2639 2638 2637 +3 2639 1443 2638 +3 413 491 1446 +3 413 511 491 +3 1446 836 413 +3 413 836 835 +3 414 836 1446 +3 491 1445 1446 +3 1447 1448 492 +3 1448 1449 492 +3 445 1455 1137 +3 485 389 486 +3 926 1680 1685 +3 388 1447 1451 +3 2598 2600 253 +3 1472 2592 2593 +3 190 1472 2593 +3 493 1449 1448 +3 485 486 1902 +3 1448 388 1450 +3 1454 1455 1456 +3 1134 2492 1471 +3 1451 511 484 +3 511 1451 491 +3 511 389 484 +3 1447 388 1448 +3 482 1467 481 +3 1966 1444 1967 +3 1451 484 1452 +3 1454 1449 493 +3 388 1453 1450 +3 388 1452 1453 +3 2485 2486 780 +3 1456 387 1454 +3 1455 2 1137 +3 551 79 2734 +3 552 79 551 +3 1906 1367 771 +3 1456 1455 445 +3 1902 486 2483 +3 780 1174 2484 +3 1458 387 1456 +3 1457 1458 1456 +3 1459 444 435 +3 1452 1462 483 +3 1452 484 1462 +3 1457 445 446 +3 521 1785 1773 +3 1324 2269 2271 +3 2269 590 2271 +3 1471 1470 1459 +3 1134 1471 435 +3 1470 1471 434 +3 2766 826 822 +3 2744 1784 1795 +3 939 2746 2748 +3 1794 1784 2744 +3 1452 483 1453 +3 1462 1463 483 +3 1469 355 1468 +3 482 1469 1468 +3 485 1463 1462 +3 619 2583 1175 +3 1174 2583 619 +3 830 829 2236 +3 2680 829 830 +3 392 2580 2238 +3 1466 1467 482 +3 942 1984 2245 +3 2255 1445 492 +3 1561 2238 794 +3 1465 431 432 +3 433 431 1465 +3 1466 432 1467 +3 60 2552 2005 +3 2552 246 2005 +3 1465 1464 148 +3 1455 493 2 +3 255 1892 60 +3 415 837 838 +3 355 1453 483 +3 1468 355 483 +3 482 1468 1464 +3 2133 2142 2134 +3 476 834 816 +3 476 413 834 +3 476 510 413 +3 1284 2374 2367 +3 2168 2765 2167 +3 2765 1046 2167 +3 2141 481 2140 +3 1469 481 2141 +3 1664 889 764 +3 2689 301 2694 +3 493 1455 1454 +3 2638 2492 1442 +3 2492 2638 2491 +3 2491 2638 1443 +3 836 149 835 +3 414 837 836 +3 414 1473 837 +3 837 149 836 +3 1712 171 1713 +3 2398 1168 97 +3 1168 2398 272 +3 1305 1485 52 +3 2265 2266 2339 +3 1476 162 1477 +3 66 197 1684 +3 2368 1380 2370 +3 370 2367 2368 +3 1302 1484 1483 +3 1319 162 1475 +3 1475 370 1319 +3 1902 2483 391 +3 2395 1017 2393 +3 19 1898 1479 +3 2389 161 2388 +3 1478 1479 1481 +3 1478 160 1479 +3 2723 531 257 +3 2750 1797 56 +3 930 34 175 +3 34 1489 175 +3 2369 2370 372 +3 1482 1483 1484 +3 1482 162 1483 +3 1716 1714 155 +3 1717 1716 155 +3 1305 1484 1485 +3 1484 172 1485 +3 2730 2729 532 +3 2303 1501 146 +3 2303 2302 1501 +3 147 2307 2306 +3 1566 1544 512 +3 1501 1500 113 +3 220 2080 2088 +3 2726 2725 538 +3 2392 2395 2393 +3 1477 1480 1488 +3 172 1486 1485 +3 1486 172 1487 +3 1017 2389 469 +3 161 2389 1017 +3 1712 1487 172 +3 1487 1712 1713 +3 1480 1481 1488 +3 2727 538 30 +3 538 539 30 +3 2727 2726 538 +3 536 2724 2725 +3 2724 257 2725 +3 1493 1492 334 +3 1858 1246 1859 +3 1025 54 1263 +3 1493 336 1494 +3 143 1493 1494 +3 2306 2309 2305 +3 2309 1500 2305 +3 26 2058 2059 +3 140 908 909 +3 1879 1878 189 +3 430 23 2308 +3 1498 1495 75 +3 90 1497 336 +3 234 151 852 +3 447 187 1497 +3 90 447 1497 +3 1025 455 54 +3 1495 1498 2056 +3 1498 141 2056 +3 2136 2130 357 +3 2308 2314 428 +3 2138 114 362 +3 771 888 887 +3 2294 2295 865 +3 2294 880 2295 +3 2322 2323 1622 +3 2686 865 1109 +3 463 563 562 +3 1506 1513 558 +3 1513 1506 559 +3 466 561 1505 +3 559 1505 1507 +3 1355 1511 179 +3 523 1220 1517 +3 2129 2148 114 +3 2704 2703 2658 +3 2705 2704 784 +3 2657 1506 2658 +3 1506 784 2658 +3 1440 2713 1434 +3 2594 1440 1434 +3 2660 466 2659 +3 556 1510 529 +3 1509 1510 556 +3 1509 179 1510 +3 1508 1512 559 +3 1509 1512 1508 +3 2703 466 2658 +3 2703 2659 466 +3 1726 2009 579 +3 579 2009 2010 +3 1222 574 575 +3 2707 418 2708 +3 2705 785 2704 +3 557 1514 1512 +3 2435 2434 847 +3 1786 501 1787 +3 1510 1511 529 +3 179 1511 1510 +3 530 2721 2723 +3 2721 531 2723 +3 536 530 2724 +3 730 749 731 +3 730 563 749 +3 625 1513 1514 +3 1514 1513 1512 +3 2129 2147 2148 +3 452 562 1351 +3 1207 2741 1206 +3 2251 420 1553 +3 295 2058 2057 +3 806 2243 807 +3 393 806 807 +3 269 268 2149 +3 486 389 2575 +3 389 509 2575 +3 1561 488 2238 +3 408 1145 2240 +3 408 1144 1145 +3 144 2132 2131 +3 787 1821 2653 +3 1445 2255 1444 +3 1554 1559 421 +3 792 1520 1522 +3 2708 1435 191 +3 1545 1542 55 +3 1542 1541 55 +3 2222 2756 2761 +3 1546 1541 1542 +3 1536 1541 1546 +3 2231 2230 1521 +3 2691 905 2689 +3 2515 1031 1032 +3 2325 1627 723 +3 1528 792 1522 +3 583 1645 1644 +3 1527 1524 422 +3 303 152 304 +3 2690 2694 2695 +3 2697 301 2688 +3 1164 1121 288 +3 2677 1121 1164 +3 1532 982 1533 +3 1530 1532 1533 +3 434 2491 1474 +3 2057 2058 294 +3 299 298 295 +3 791 1525 1531 +3 2541 1631 2542 +3 1555 1570 1588 +3 1572 1555 1588 +3 1999 253 2600 +3 421 1551 1550 +3 2585 2584 1568 +3 2584 2585 1567 +3 789 1536 1569 +3 704 1026 1945 +3 982 983 1534 +3 2059 2058 295 +3 2541 2540 1631 +3 2064 2057 321 +3 1531 1539 1535 +3 1539 1531 1538 +3 2057 2064 295 +3 1937 1942 108 +3 1406 2329 1403 +3 2329 2328 1403 +3 282 281 47 +3 1723 215 87 +3 1546 1548 1569 +3 1551 789 1549 +3 2670 1948 2669 +3 1562 791 1535 +3 1587 1589 1571 +3 1543 1544 513 +3 1552 1557 790 +3 1097 578 1947 +3 578 1097 1725 +3 1547 1548 1564 +3 1548 1547 1549 +3 1560 793 1559 +3 1622 2324 1623 +3 2324 723 1623 +3 498 1 1556 +3 1546 1537 1548 +3 677 678 637 +3 677 1634 678 +3 513 1537 1543 +3 1942 12 293 +3 293 12 282 +3 1540 1539 55 +3 1543 1542 1545 +3 1543 1537 1542 +3 1545 55 1534 +3 1539 1534 55 +3 798 420 797 +3 422 1544 983 +3 512 1553 420 +3 1557 1558 790 +3 1937 1938 12 +3 421 1552 1551 +3 131 132 134 +3 1544 1543 983 +3 1054 880 2294 +3 1534 983 1545 +3 1540 1535 1539 +3 1536 1535 1540 +3 843 842 2588 +3 1565 1564 513 +3 1537 1546 1542 +3 512 420 514 +3 1567 1565 1563 +3 1565 1567 1564 +3 1591 2610 16 +3 1556 1 1560 +3 498 1556 786 +3 1946 1948 701 +3 2323 2324 1622 +3 321 2063 109 +3 1552 421 1557 +3 1579 1580 516 +3 1569 1536 1546 +3 1162 23 78 +3 2587 2584 1563 +3 2587 1568 2584 +3 1551 1552 789 +3 1171 640 1632 +3 422 1553 1544 +3 1558 1521 790 +3 2254 795 2234 +3 1120 1951 2218 +3 512 1544 1553 +3 1549 789 1569 +3 2609 16 2610 +3 2281 2364 2365 +3 234 552 78 +3 1121 961 2187 +3 1554 1550 1555 +3 2460 2577 843 +3 499 2614 1578 +3 2614 499 1768 +3 494 1450 1453 +3 482 1464 1466 +3 794 2232 1558 +3 796 2252 2251 +3 793 794 1558 +3 504 2601 2602 +3 2613 504 2602 +3 488 2239 2238 +3 1905 151 431 +3 1 1561 1560 +3 1 851 1561 +3 1561 851 488 +3 2063 2057 294 +3 1552 1562 789 +3 790 1521 1562 +3 506 1591 1592 +3 1550 1551 2586 +3 2586 2585 1568 +3 1570 1568 2587 +3 1550 1568 1555 +3 1555 1574 786 +3 1569 1548 1549 +3 2603 2613 2602 +3 1574 2606 786 +3 787 788 1821 +3 1554 421 1550 +3 1565 1566 507 +3 1566 1565 513 +3 1544 1566 513 +3 843 2588 1074 +3 2586 1568 1550 +3 982 1532 1594 +3 281 12 1938 +3 1567 1563 2584 +3 1570 1555 1568 +3 2491 1444 1474 +3 1555 1572 1574 +3 976 211 975 +3 2604 1575 2605 +3 507 1591 1590 +3 46 976 203 +3 516 505 515 +3 1573 2618 2608 +3 1582 1581 499 +3 684 2289 2288 +3 951 1232 1231 +3 1575 515 2605 +3 1790 505 1789 +3 2319 2317 691 +3 2287 2282 2283 +3 1779 2753 1800 +3 572 1779 1800 +3 206 205 59 +3 1577 2612 2614 +3 1768 1577 2614 +3 2611 2601 504 +3 69 129 125 +3 1583 1582 938 +3 2742 277 64 +3 1580 505 516 +3 218 1995 923 +3 1581 1768 499 +3 1708 2341 1707 +3 2659 785 2661 +3 1772 240 526 +3 240 527 526 +3 2170 1045 2166 +3 1064 871 2505 +3 238 555 543 +3 1230 949 1228 +3 876 2158 2157 +3 1809 1810 222 +3 862 1809 222 +3 979 972 2097 +3 972 2098 2097 +3 972 978 2098 +3 1817 1739 183 +3 2287 2283 2284 +3 1050 2172 1051 +3 2164 2160 2167 +3 2160 1048 2167 +3 848 1900 1899 +3 2357 2353 614 +3 2342 2102 51 +3 2342 156 2102 +3 183 949 1817 +3 578 1948 1947 +3 1620 714 3 +3 446 2326 1457 +3 2671 2674 580 +3 1709 2747 56 +3 1121 2677 1120 +3 517 1580 1579 +3 1585 2772 2771 +3 1300 1302 1319 +3 1707 1583 572 +3 1789 505 2268 +3 1781 1583 938 +3 543 545 212 +3 1200 1224 1209 +3 1563 1565 1589 +3 507 1566 1592 +3 1590 1589 507 +3 1571 1589 1590 +3 786 1554 1555 +3 507 1592 1591 +3 1554 786 1556 +3 604 788 787 +3 1554 1556 1559 +3 1556 1560 1559 +3 1588 1571 1593 +3 1590 1593 1571 +3 1590 16 1593 +3 2217 2216 1949 +3 1527 1594 1526 +3 1594 1523 1526 +3 2400 2401 2402 +3 2324 2323 2325 +3 1132 639 2150 +3 1978 1598 940 +3 1598 1979 940 +3 1980 1979 1598 +3 926 1683 1681 +3 1838 458 1020 +3 1156 1292 2301 +3 940 1976 1975 +3 1598 1599 27 +3 869 1669 1670 +3 2597 1595 2599 +3 2643 31 1682 +3 1828 1825 1826 +3 1829 28 1830 +3 1113 1957 1958 +3 1963 1954 1118 +3 2559 42 1831 +3 1599 1598 1597 +3 101 2550 2549 +3 2264 1287 1286 +3 1801 1272 2264 +3 1277 1286 1287 +3 1294 1158 1295 +3 1611 1155 1154 +3 2194 2227 2226 +3 206 58 205 +3 58 2490 205 +3 966 1605 1606 +3 966 1606 1155 +3 2087 2086 968 +3 2086 974 968 +3 2084 2083 919 +3 311 153 307 +3 958 471 1609 +3 232 958 1609 +3 1013 2207 1119 +3 1604 966 1601 +3 966 1602 1601 +3 2227 1005 2192 +3 1607 1152 1309 +3 1152 1607 1605 +3 1606 1605 1607 +3 143 1002 1491 +3 1609 1312 232 +3 470 1312 1609 +3 1311 1312 470 +3 1013 2261 2260 +3 1617 127 139 +3 2008 883 2007 +3 503 2610 506 +3 1614 1616 1615 +3 125 1615 69 +3 1615 125 1618 +3 1764 1072 1763 +3 2774 136 379 +3 694 2008 882 +3 2257 2008 694 +3 2015 2033 2031 +3 73 1617 139 +3 73 132 131 +3 2214 2534 2216 +3 2534 1949 2216 +3 130 73 131 +3 130 1617 73 +3 129 69 130 +3 71 129 130 +3 2002 248 2003 +3 2669 1948 578 +3 2668 2669 578 +3 126 1614 1615 +3 217 554 916 +3 318 321 109 +3 141 1499 2054 +3 2534 2219 2228 +3 961 2534 2228 +3 2284 2283 3 +3 689 1092 2466 +3 2465 690 1091 +3 1634 1633 640 +3 677 676 1633 +3 676 677 636 +3 1632 640 1633 +3 472 1612 2260 +3 2544 2545 2546 +3 2363 2544 2546 +3 723 1628 642 +3 721 642 1629 +3 1630 386 453 +3 1624 1623 716 +3 1102 2463 2462 +3 2458 1102 2462 +3 1173 2543 2363 +3 962 1101 1100 +3 1101 2462 1100 +3 963 68 254 +3 722 1131 642 +3 1623 723 642 +3 1103 2459 2458 +3 2459 1102 2458 +3 1461 1630 454 +3 2579 830 2236 +3 2067 299 2065 +3 2070 2068 110 +3 2068 2070 303 +3 2067 2065 110 +3 2691 300 2692 +3 2446 45 2445 +3 152 2070 320 +3 320 2070 110 +3 111 2691 2692 +3 2362 2363 1172 +3 678 1634 640 +3 1621 1622 1623 +3 2183 2260 1612 +3 2257 2259 1919 +3 2257 694 2259 +3 438 1635 1405 +3 2667 2671 700 +3 1920 2259 694 +3 1413 1414 1412 +3 1635 438 1430 +3 1435 1434 2714 +3 1324 1323 401 +3 1650 1324 401 +3 1145 393 807 +3 711 1641 710 +3 1291 1159 1652 +3 502 938 499 +3 401 1646 1648 +3 1649 401 1648 +3 1647 608 1646 +3 2559 62 167 +3 2634 802 2626 +3 1647 1646 1323 +3 1648 1646 1643 +3 608 612 583 +3 1644 608 583 +3 1642 1643 584 +3 585 2634 2626 +3 2627 2629 2632 +3 585 2627 2632 +3 586 1649 2626 +3 802 586 2626 +3 1647 394 612 +3 612 608 1647 +3 394 1647 609 +3 2489 1036 1035 +3 613 2348 2349 +3 609 1647 1323 +3 401 1649 1650 +3 1654 1656 1276 +3 1649 586 1651 +3 1649 1651 1650 +3 2564 1735 1742 +3 2408 1011 2407 +3 1277 1653 1286 +3 1275 1276 1656 +3 1159 1654 1652 +3 1652 1654 1276 +3 157 479 120 +3 159 157 120 +3 479 121 120 +3 2101 82 158 +3 1293 1294 1288 +3 1660 1659 1278 +3 1899 496 1770 +3 1654 1278 1656 +3 1655 1660 1278 +3 1970 1969 1275 +3 1329 588 760 +3 2100 159 2101 +3 159 52 2101 +3 1486 82 2101 +3 2117 227 2114 +3 1294 2103 1158 +3 1662 1454 387 +3 1474 1661 1470 +3 2124 1304 2122 +3 1660 1655 1292 +3 1470 1662 387 +3 1663 1378 1377 +3 1378 1663 764 +3 2425 2422 759 +3 2425 757 2422 +3 1664 891 1665 +3 891 1664 1663 +3 1664 764 1663 +3 2421 2417 404 +3 889 884 764 +3 2417 2421 2426 +3 1667 1668 1666 +3 1668 1667 859 +3 1814 1812 863 +3 1666 861 1036 +3 2686 1109 867 +3 1029 861 1028 +3 1668 859 218 +3 1371 1365 775 +3 861 1668 1028 +3 1677 2175 2174 +3 2176 1677 2174 +3 1670 1669 1039 +3 1044 1675 1674 +3 1675 1043 1674 +3 958 232 2179 +3 46 550 976 +3 1675 1050 1034 +3 1845 1241 1846 +3 2162 1671 870 +3 872 1049 1056 +3 1671 1670 1039 +3 2295 1059 2296 +3 1059 2295 876 +3 1095 2502 702 +3 1722 1721 154 +3 874 1675 1034 +3 2174 2173 1044 +3 2176 2174 1044 +3 1122 1123 1943 +3 1037 874 1032 +3 1045 1670 1671 +3 874 1043 1675 +3 1834 262 1753 +3 1670 1676 869 +3 1670 1045 1676 +3 2335 946 947 +3 946 945 947 +3 201 4 1679 +3 1673 1678 1674 +3 2018 116 2023 +3 519 1774 2702 +3 662 663 606 +3 2664 692 2666 +3 1890 90 334 +3 1687 660 681 +3 1729 197 323 +3 2568 2567 343 +3 387 1458 2764 +3 2643 1682 9 +3 200 199 201 +3 2343 200 201 +3 119 118 122 +3 250 941 85 +3 250 1976 941 +3 1999 1998 253 +3 681 660 682 +3 2647 195 2648 +3 2008 2007 882 +3 175 1683 926 +3 927 175 926 +3 1686 1684 1682 +3 32 2035 2034 +3 32 2036 2035 +3 1614 1698 2050 +3 1595 2598 2599 +3 1683 1686 1681 +3 1866 1262 1873 +3 1262 1858 1873 +3 2017 2023 935 +3 1848 1250 1244 +3 1400 2527 1408 +3 1923 881 648 +3 679 632 1688 +3 679 667 632 +3 679 1688 1687 +3 675 679 1687 +3 603 1068 1069 +3 1688 632 707 +3 1852 1252 1850 +3 1882 2442 2437 +3 1861 1860 1246 +3 1693 1519 1517 +3 1519 1208 1517 +3 1220 1693 1517 +3 524 1691 1693 +3 1772 1771 521 +3 938 1782 1781 +3 1696 1318 375 +3 1657 1694 1279 +3 1657 228 1694 +3 1658 228 1657 +3 1281 1694 228 +3 1696 1695 1281 +3 1059 876 2156 +3 1326 1085 1697 +3 1096 703 1095 +3 1698 338 339 +3 1698 1395 338 +3 126 1395 1698 +3 126 1698 1614 +3 1706 1705 508 +3 1300 370 2369 +3 1436 1700 1135 +3 1700 1436 1418 +3 1582 1702 1586 +3 1581 1582 1586 +3 2007 893 765 +3 883 893 2007 +3 1418 2623 2620 +3 952 815 1183 +3 1817 950 1739 +3 2269 2275 1325 +3 2275 2269 2270 +3 1679 202 2455 +3 1790 1788 501 +3 1583 1703 1702 +3 379 378 2774 +3 2738 244 2737 +3 1711 172 1484 +3 1302 1711 1484 +3 826 2127 822 +3 2490 7 205 +3 2733 2734 79 +3 2474 2473 2472 +3 2471 2474 2472 +3 833 2575 490 +3 833 2676 2575 +3 1214 1211 1212 +3 849 2736 852 +3 2729 531 532 +3 2341 1584 1704 +3 1707 2341 1704 +3 2266 1584 2339 +3 2341 2340 1584 +3 2280 2430 2293 +3 156 2100 2102 +3 2100 158 2102 +3 171 83 224 +3 171 1711 83 +3 243 822 2127 +3 821 822 243 +3 172 1711 1712 +3 82 1486 1487 +3 1732 997 996 +3 1721 1719 154 +3 1713 171 1714 +3 1719 64 154 +3 171 1712 1711 +3 1476 1285 2381 +3 701 2670 708 +3 82 170 169 +3 272 98 273 +3 17 269 1715 +3 823 821 478 +3 155 1720 1717 +3 2448 1027 2075 +3 2447 2446 2448 +3 1717 263 1716 +3 263 1717 1718 +3 1719 1718 264 +3 1719 24 1718 +3 64 1719 264 +3 24 263 1718 +3 2075 7 2448 +3 2447 2448 7 +3 209 2083 2084 +3 38 209 2084 +3 266 1721 1723 +3 1721 266 24 +3 266 1723 87 +3 2645 2644 9 +3 1722 214 215 +3 1721 1722 1723 +3 1758 1759 340 +3 1714 1724 1713 +3 1724 1714 1716 +3 1716 170 1724 +3 1097 698 1725 +3 2675 1637 1638 +3 1637 1639 582 +3 576 1151 1223 +3 576 2472 1151 +3 994 2036 2042 +3 2010 1639 699 +3 2010 2009 1639 +3 1639 1640 699 +3 1578 2603 503 +3 2170 1677 1045 +3 2172 2171 1047 +3 2038 2024 2037 +3 261 259 1752 +3 820 243 844 +3 1729 1730 37 +3 323 1730 1729 +3 325 1333 328 +3 1333 325 1734 +3 1736 1731 325 +3 1733 1731 323 +3 1744 323 99 +3 2230 2574 1520 +3 792 2230 1520 +3 2564 2565 2573 +3 2565 2564 345 +3 325 1738 1737 +3 1743 326 340 +3 93 917 918 +3 260 341 1754 +3 1743 324 1744 +3 36 1738 1739 +3 1730 1732 37 +3 37 1732 996 +3 38 344 215 +3 325 328 1738 +3 1733 324 1735 +3 1126 337 332 +3 2573 2565 2569 +3 1741 1331 216 +3 1041 2512 875 +3 213 1333 1334 +3 36 997 1737 +3 340 1745 1742 +3 345 1745 1746 +3 1741 1332 1331 +3 2746 2750 2748 +3 2750 2746 1780 +3 1737 1738 36 +3 1070 1393 631 +3 1392 692 1818 +3 1891 2 494 +3 1889 335 1890 +3 355 1891 494 +3 36 1739 950 +3 1741 328 1332 +3 1072 226 1763 +3 1739 1738 328 +3 1740 1739 328 +3 1741 1740 328 +3 916 216 918 +3 216 1740 1741 +3 2142 144 2651 +3 1742 1743 340 +3 326 1743 1744 +3 99 326 1744 +3 327 326 99 +3 1754 337 77 +3 1734 325 2570 +3 2569 88 2571 +3 2570 2569 2571 +3 1750 343 2567 +3 342 1750 2567 +3 460 1421 1399 +3 1751 259 65 +3 260 1749 1748 +3 342 1748 1749 +3 1749 65 1750 +3 1750 342 1749 +3 2431 2430 2291 +3 327 99 351 +3 77 261 1752 +3 260 1752 1751 +3 341 1753 1754 +3 1753 1755 1754 +3 347 330 346 +3 1758 329 1757 +3 331 1141 1490 +3 1756 331 1490 +3 1141 89 1490 +3 1491 1490 89 +3 1492 1491 89 +3 1141 1140 89 +3 1753 262 1755 +3 948 330 181 +3 948 1140 330 +3 1850 1849 1244 +3 1850 1252 1849 +3 2020 2030 2029 +3 2030 2019 2029 +3 2018 2023 2017 +3 262 1759 1758 +3 262 1758 1757 +3 948 333 1140 +3 33 1762 327 +3 1762 326 327 +3 1762 33 1761 +3 329 1762 1761 +3 1613 475 2116 +3 1072 1073 226 +3 472 1116 1613 +3 40 103 104 +3 1115 292 1072 +3 4 931 1766 +3 1765 1072 1764 +3 1612 472 1613 +3 4 1766 202 +3 927 1685 202 +3 1766 927 202 +3 129 70 125 +3 931 4 932 +3 929 1767 928 +3 121 70 129 +3 1777 571 570 +3 549 92 967 +3 517 1769 1581 +3 1586 517 1581 +3 1769 517 1579 +3 1776 1777 570 +3 2658 784 2704 +3 2662 178 2707 +3 242 2768 1130 +3 496 521 1770 +3 1327 590 2269 +3 1353 569 527 +3 1773 1772 521 +3 1772 1773 240 +3 163 1894 19 +3 1774 525 1775 +3 1710 2747 1709 +3 530 239 526 +3 1786 518 501 +3 1208 1519 2738 +3 571 1777 1778 +3 2751 1710 2336 +3 1787 1788 1798 +3 2752 2749 2751 +3 1800 2752 2751 +3 571 2754 2755 +3 610 394 609 +3 502 500 1218 +3 938 502 1782 +3 1327 2269 1325 +3 2657 2658 466 +3 1776 1783 1777 +3 1505 2657 466 +3 1518 1208 2740 +3 1775 2517 523 +3 523 1799 1775 +3 382 383 361 +3 1211 2737 244 +3 1774 1775 1799 +3 1786 1787 519 +3 1789 2268 2267 +3 2336 2337 1708 +3 505 1790 498 +3 1580 2268 505 +3 501 498 1790 +3 502 520 1782 +3 521 496 1791 +3 1705 1706 2773 +3 1791 1792 518 +3 1791 496 1792 +3 2333 2520 2523 +3 2517 1775 2516 +3 2517 2516 1783 +3 2519 2332 1409 +3 2738 1519 244 +3 313 2371 2372 +3 2266 1709 2267 +3 1780 1795 1796 +3 2523 1410 2524 +3 1793 1794 1778 +3 1777 1793 1778 +3 1798 1774 519 +3 1787 1798 519 +3 1795 1784 1796 +3 56 1797 1788 +3 526 239 522 +3 525 1797 1796 +3 1796 1797 1780 +3 2752 2753 939 +3 1788 1797 1798 +3 525 1798 1797 +3 313 372 2371 +3 2262 2263 1272 +3 1272 1803 2262 +3 1274 1269 367 +3 372 2370 2371 +3 661 605 1804 +3 661 685 605 +3 2419 1188 763 +3 2611 1576 2601 +3 1804 605 633 +3 605 634 633 +3 633 1806 1805 +3 643 1805 1806 +3 643 1806 602 +3 1384 643 602 +3 688 962 1092 +3 1824 962 688 +3 1383 643 1384 +3 606 1808 1807 +3 1125 1824 656 +3 1809 862 1811 +3 708 2672 2630 +3 652 759 2665 +3 652 1925 757 +3 699 1640 2667 +3 980 1619 1810 +3 1810 1619 546 +3 104 2342 51 +3 218 923 1028 +3 219 1811 1812 +3 1816 972 979 +3 1054 1055 1053 +3 2327 2328 1407 +3 474 2182 2190 +3 1230 950 1817 +3 2289 1503 2288 +3 1508 559 1507 +3 1082 1823 687 +3 42 8 1825 +3 1080 95 1081 +3 689 1820 688 +3 1819 688 1820 +3 94 577 576 +3 634 605 697 +3 2656 634 697 +3 634 2656 2654 +3 664 1385 1386 +3 601 1821 788 +3 962 1824 1125 +3 1955 1952 1117 +3 1827 80 1599 +3 1979 941 1976 +3 80 57 40 +3 1827 57 80 +3 1831 1829 1832 +3 1831 62 2559 +3 1745 1834 1746 +3 1826 1827 28 +3 1827 1599 28 +3 292 1115 1957 +3 1827 1826 57 +3 1832 62 1831 +3 42 1828 1829 +3 1828 28 1829 +3 1828 1826 28 +3 1415 2621 1429 +3 2622 2621 1415 +3 1759 1745 340 +3 1745 1759 1834 +3 1888 1889 49 +3 1595 1975 1976 +3 57 107 40 +3 42 1829 1831 +3 100 2561 2560 +3 8 2561 100 +3 2550 100 2560 +3 102 29 103 +3 1832 1833 43 +3 78 203 1027 +3 2335 49 948 +3 2334 2335 948 +3 946 2335 2334 +3 1838 1020 1239 +3 1837 1838 1239 +3 535 1887 1888 +3 738 457 739 +3 1839 1840 1242 +3 458 1842 1022 +3 1844 1241 1845 +3 1844 1843 1241 +3 1841 1255 1023 +3 1229 423 985 +3 2494 1240 2493 +3 1240 1843 2493 +3 1836 1240 2494 +3 2494 2493 1837 +3 1849 1848 1244 +3 1847 1848 1251 +3 1245 1855 1260 +3 1247 1427 1869 +3 1844 1845 1840 +3 1843 1240 739 +3 1241 1843 739 +3 739 1846 1241 +3 1245 1252 1852 +3 78 552 203 +3 2020 2022 932 +3 347 423 181 +3 2139 2146 362 +3 2146 2138 362 +3 1849 1252 1251 +3 1851 1850 1244 +3 1851 1689 1850 +3 1254 1253 1851 +3 1253 1689 1851 +3 1847 1250 1848 +3 1260 1855 54 +3 1245 1853 1854 +3 1853 1245 1852 +3 1855 1245 1854 +3 1869 1876 1248 +3 333 334 1492 +3 1139 1140 1141 +3 330 1140 1139 +3 1253 1862 1261 +3 1862 1246 1261 +3 1857 1854 1853 +3 1856 1857 1853 +3 1852 1689 1853 +3 1261 1857 1856 +3 1246 1858 1261 +3 1858 1857 1261 +3 1266 1247 1868 +3 1253 1261 1856 +3 1864 1264 1863 +3 769 1909 895 +3 1858 1859 1873 +3 25 2053 2052 +3 1859 1246 1860 +3 1249 1862 456 +3 1249 1861 1862 +3 895 1907 1906 +3 436 1461 454 +3 1266 1868 1867 +3 1863 1859 1860 +3 1266 1863 1860 +3 1864 1863 1867 +3 1266 1867 1863 +3 1866 1264 1865 +3 1859 1863 1264 +3 349 139 908 +3 1868 1248 1870 +3 2051 2052 140 +3 1872 1396 443 +3 1872 1865 1265 +3 1865 1872 443 +3 1872 1265 1871 +3 1871 1396 1872 +3 1264 1866 1873 +3 1873 1859 1264 +3 1858 1262 1857 +3 1875 1876 1399 +3 1248 1874 1870 +3 1876 460 1399 +3 460 1876 1869 +3 2440 2441 1879 +3 1874 1877 1871 +3 1398 1877 1874 +3 1877 1396 1871 +3 318 1163 321 +3 1495 2055 143 +3 1398 1874 1875 +3 1874 1248 1875 +3 1879 2439 2440 +3 1875 1423 1882 +3 1398 1875 1882 +3 1879 1397 1880 +3 1878 1879 1880 +3 1869 1427 460 +3 442 1397 1879 +3 1878 1396 1877 +3 45 2447 1935 +3 2438 189 2437 +3 1881 1398 1882 +3 1883 365 752 +3 133 1884 1883 +3 1884 364 1883 +3 134 364 1884 +3 198 2043 2049 +3 1698 339 2050 +3 2498 2499 1042 +3 1128 877 2498 +3 877 2499 2498 +3 960 2677 1164 +3 2641 2640 1886 +3 1885 194 35 +3 2027 198 2048 +3 2040 2024 2039 +3 214 1722 910 +3 539 2730 533 +3 857 223 856 +3 1887 448 335 +3 948 49 1889 +3 333 948 1889 +3 335 1889 1888 +3 1890 333 1889 +3 334 333 1890 +3 335 90 1890 +3 1895 1897 19 +3 101 2549 2548 +3 532 2735 2730 +3 1006 2204 2203 +3 164 71 165 +3 121 71 164 +3 119 70 121 +3 121 129 71 +3 479 20 119 +3 134 1884 1896 +3 1884 468 1896 +3 468 1884 133 +3 19 1894 1895 +3 1423 2442 1882 +3 1423 2443 2442 +3 177 531 2721 +3 531 177 567 +3 160 19 1479 +3 134 132 364 +3 1488 1481 369 +3 1770 848 1899 +3 850 495 851 +3 1903 241 849 +3 241 1903 848 +3 1901 848 1903 +3 1900 1901 391 +3 1902 1904 433 +3 1902 1901 1904 +3 86 1985 2245 +3 86 1987 1985 +3 148 485 1902 +3 497 850 851 +3 495 488 851 +3 2648 2646 2647 +3 1903 1904 1901 +3 1904 1905 433 +3 793 1561 794 +3 849 1905 1904 +3 849 151 1905 +3 849 852 151 +3 1137 187 445 +3 883 894 893 +3 893 894 771 +3 894 1906 771 +3 769 895 1375 +3 894 895 1906 +3 1375 895 894 +3 1178 768 1908 +3 1908 768 1907 +3 1249 1247 1861 +3 1909 772 1178 +3 1488 2720 1477 +3 191 2716 461 +3 1929 650 1928 +3 1933 650 1929 +3 1394 1384 645 +3 2424 763 591 +3 2341 1708 2340 +3 649 630 1914 +3 630 649 1918 +3 758 1925 1928 +3 671 666 667 +3 2260 474 2191 +3 649 891 1921 +3 1924 1923 648 +3 630 1920 1917 +3 1921 1919 649 +3 474 2190 2191 +3 2262 1318 1696 +3 764 884 885 +3 884 881 882 +3 885 884 882 +3 762 1917 1920 +3 934 2018 2017 +3 1026 2577 2576 +3 1916 1917 1922 +3 1917 762 1922 +3 630 1917 1916 +3 814 815 409 +3 1188 1187 696 +3 1923 1922 762 +3 2019 116 2018 +3 1700 2622 1419 +3 1923 1924 758 +3 1913 1934 1912 +3 1916 1927 1930 +3 1927 1928 1930 +3 1931 1930 650 +3 1930 1928 650 +3 1390 1933 1391 +3 1916 1930 1931 +3 1915 1916 1931 +3 1407 1400 1408 +3 2528 2527 1400 +3 1933 1929 1391 +3 595 665 1071 +3 1931 1934 1915 +3 1932 1933 629 +3 1932 629 1912 +3 1913 1912 646 +3 112 45 1935 +3 1932 650 1933 +3 2621 1418 2620 +3 1913 1915 1934 +3 1936 13 1937 +3 1937 13 1938 +3 1967 2491 1443 +3 1473 1967 1443 +3 108 1941 1940 +3 1942 293 1941 +3 108 1942 1941 +3 1940 1939 108 +3 2247 2246 1985 +3 2278 1064 2503 +3 1527 983 982 +3 1944 1943 702 +3 1944 1945 1943 +3 2670 701 1948 +3 2503 2276 2278 +3 1335 289 959 +3 959 289 960 +3 2533 139 2532 +3 2222 2761 2225 +3 1625 2325 2323 +3 703 1097 1947 +3 1946 1947 1948 +3 2576 2577 1122 +3 1062 2511 1128 +3 1944 1946 1945 +3 1946 704 1945 +3 1172 2363 2546 +3 635 678 640 +3 701 704 1946 +3 449 2326 446 +3 1955 1953 1952 +3 1164 959 960 +3 1120 1949 1121 +3 1949 961 1121 +3 1117 1952 1120 +3 1115 1114 1958 +3 292 1956 1117 +3 2186 1004 2223 +3 2197 1005 2193 +3 1012 2199 1011 +3 1113 1964 1956 +3 2221 2188 2220 +3 1111 290 1954 +3 1953 1954 290 +3 2144 359 358 +3 359 2652 358 +3 1114 350 1959 +3 1111 1954 1112 +3 1962 1965 1960 +3 1965 1962 1959 +3 1956 292 1957 +3 2226 2227 2678 +3 1964 1113 1962 +3 1964 1962 1963 +3 1956 1964 1955 +3 1965 1959 350 +3 42 15 8 +3 1959 1113 1958 +3 1112 1960 1961 +3 2561 15 2558 +3 1960 350 1961 +3 166 2558 2557 +3 2561 2558 166 +3 8 15 2561 +3 1963 1118 1964 +3 388 1451 1452 +3 414 1446 1966 +3 1445 1966 1446 +3 1652 1276 1968 +3 1653 1652 1968 +3 1201 1199 2353 +3 1201 1202 1199 +3 1969 1276 1275 +3 373 1653 1969 +3 1653 373 1286 +3 1653 1968 1969 +3 1968 1276 1969 +3 2557 2554 2553 +3 1286 373 1274 +3 348 63 2556 +3 1971 348 2556 +3 31 200 2343 +3 2457 31 2343 +3 2596 1595 2597 +3 62 1832 43 +3 681 2150 639 +3 1977 940 1975 +3 1977 1974 1596 +3 1977 1975 1974 +3 1596 43 1833 +3 2640 2641 18 +3 1596 1974 1973 +3 1975 1595 1974 +3 1596 1973 43 +3 1980 941 1979 +3 1982 1981 942 +3 1981 1982 1980 +3 1978 940 1977 +3 1597 1978 1977 +3 1833 1597 1596 +3 1830 1597 1833 +3 2247 85 2246 +3 942 2246 1982 +3 2245 2246 942 +3 2648 195 995 +3 18 1885 2640 +3 1885 18 2645 +3 169 1986 1984 +3 1983 169 1984 +3 420 2251 2252 +3 685 680 605 +3 1991 904 322 +3 1194 1193 322 +3 1193 1989 322 +3 80 81 1981 +3 80 1981 27 +3 1981 1980 27 +3 1982 941 1980 +3 2247 128 965 +3 85 941 1982 +3 1988 65 258 +3 2697 2698 301 +3 897 2698 2697 +3 1988 258 128 +3 1981 1983 942 +3 1981 81 1983 +3 965 85 2247 +3 1984 942 1983 +3 2233 795 2254 +3 169 81 168 +3 81 169 1983 +3 265 1502 86 +3 1502 1987 86 +3 169 170 1986 +3 1988 128 1987 +3 197 1728 1684 +3 1750 65 1988 +3 267 1750 1988 +3 87 1750 267 +3 267 1988 1987 +3 796 2250 2249 +3 799 2249 2250 +3 1992 1379 886 +3 588 1329 2273 +3 2270 587 1326 +3 1573 2608 2609 +3 1328 1327 1325 +3 1992 892 1379 +3 2611 2615 1994 +3 887 403 1993 +3 892 1992 403 +3 1992 1993 403 +3 2298 2619 290 +3 2619 2298 1951 +3 218 1997 1995 +3 1106 2453 5 +3 1996 1997 924 +3 1766 1767 927 +3 2454 1215 1692 +3 2454 1216 1225 +3 1215 2454 1225 +3 524 2454 1692 +3 2454 524 1216 +3 963 251 252 +3 964 907 963 +3 348 1998 2000 +3 247 348 2001 +3 63 348 247 +3 348 2000 2001 +3 2001 2000 41 +3 2001 2003 247 +3 1619 92 547 +3 2006 517 1586 +3 2005 2004 60 +3 247 2004 2005 +3 2004 248 60 +3 122 70 119 +3 248 2004 2003 +3 517 2006 1706 +3 2772 1585 2773 +3 2033 2017 935 +3 1367 1366 888 +3 2528 1416 2527 +3 2019 2018 934 +3 243 820 821 +3 1807 1806 633 +3 2345 2346 1202 +3 2631 2628 1638 +3 2016 2033 2034 +3 877 2500 2499 +3 923 2453 1106 +3 1040 2508 2506 +3 196 2027 2048 +3 1885 2027 196 +3 2048 198 2049 +3 2026 115 196 +3 35 2027 1885 +3 2044 2045 2026 +3 2045 2044 2025 +3 199 2047 201 +3 2016 934 2017 +3 2034 2033 2015 +3 2043 2038 2025 +3 2043 2039 2038 +3 96 987 986 +3 96 992 988 +3 1081 662 606 +3 933 2019 934 +3 2021 932 937 +3 2020 116 2030 +3 116 2019 2030 +3 2041 198 2028 +3 1679 2343 201 +3 1679 2457 2343 +3 2040 2039 2041 +3 61 993 994 +3 2042 2036 32 +3 202 1685 2455 +3 1699 2278 1063 +3 1998 1971 1972 +3 2044 2049 2043 +3 2041 2039 198 +3 1042 2500 1041 +3 2048 2026 196 +3 2029 2022 2020 +3 2022 2029 933 +3 2029 2019 933 +3 1503 1504 686 +3 2279 1503 686 +3 933 928 2022 +3 2014 2031 935 +3 2031 2033 935 +3 2035 2016 2034 +3 2035 988 2016 +3 2513 2507 1031 +3 2161 2160 2164 +3 2013 936 2014 +3 988 992 2016 +3 2511 877 1128 +3 1110 2296 875 +3 2512 1110 875 +3 2040 2042 32 +3 2015 2032 2024 +3 2032 2037 2024 +3 2032 936 2037 +3 2502 1944 702 +3 1946 1944 2530 +3 2451 920 2450 +3 994 993 2036 +3 2015 2040 32 +3 32 2034 2015 +3 2040 2015 2024 +3 993 61 1001 +3 2037 936 2025 +3 2046 115 2045 +3 198 2039 2043 +3 868 1110 2512 +3 2042 2040 2041 +3 936 2045 2025 +3 1039 1063 1062 +3 1039 1062 870 +3 1669 1063 1039 +3 1601 1157 2409 +3 1045 1671 2166 +3 4 201 2047 +3 937 2047 2046 +3 2046 2047 115 +3 287 2758 2759 +3 878 2161 2164 +3 199 115 2047 +3 932 2047 937 +3 4 2047 932 +3 2309 2313 1500 +3 428 2313 2309 +3 2310 1500 2313 +3 26 1940 2058 +3 1940 294 2058 +3 2308 23 2311 +3 791 1531 1535 +3 113 2060 298 +3 2060 26 2059 +3 26 2061 1940 +3 1940 2061 1939 +3 2061 112 1939 +3 2062 112 2061 +3 427 112 2062 +3 112 427 45 +3 113 1500 2310 +3 2310 2062 113 +3 307 152 320 +3 2069 22 299 +3 299 295 2065 +3 2068 2069 2067 +3 2069 299 2067 +3 2068 2067 110 +3 343 215 344 +3 975 91 977 +3 2085 91 975 +3 205 204 2071 +3 479 157 20 +3 59 208 214 +3 208 59 2071 +3 22 1501 298 +3 1501 113 298 +3 152 303 2070 +3 2082 210 2078 +3 210 2082 2086 +3 2083 2079 919 +3 203 2074 1027 +3 204 2074 2073 +3 2075 2074 204 +3 1027 2074 2075 +3 2446 2445 1162 +3 2071 59 205 +3 2075 204 205 +3 7 2075 205 +3 24 1719 1721 +3 1422 1421 2449 +3 1421 1422 1399 +3 2080 2079 210 +3 214 2081 38 +3 549 211 548 +3 2081 209 38 +3 220 922 2080 +3 2078 2079 2083 +3 208 2077 2081 +3 2076 2077 208 +3 220 2091 970 +3 2078 2083 209 +3 2077 2078 209 +3 203 976 977 +3 157 156 20 +3 156 157 2100 +3 204 2072 2071 +3 2085 2082 91 +3 1317 1280 1156 +3 210 2086 2087 +3 2087 2088 2080 +3 2088 2087 968 +3 2087 2080 210 +3 549 967 2089 +3 968 549 2089 +3 968 2089 2088 +3 969 2090 967 +3 969 2091 2090 +3 2091 220 2090 +3 970 2093 971 +3 2072 208 2071 +3 206 59 207 +3 2095 92 981 +3 2097 221 979 +3 967 92 2095 +3 969 2094 2092 +3 11 58 206 +3 2095 981 221 +3 980 981 1619 +3 221 2094 2095 +3 969 2095 2094 +3 2686 2294 865 +3 2085 2099 2082 +3 2086 2099 974 +3 2082 2099 2086 +3 1317 225 2105 +3 1293 2103 1294 +3 2102 158 51 +3 2103 1293 1280 +3 2104 2103 1280 +3 1280 1317 2104 +3 1317 2105 2104 +3 1296 231 1295 +3 1297 2109 1313 +3 2108 229 2109 +3 1296 2108 2109 +3 2113 2112 1299 +3 2124 2125 224 +3 2110 1298 2106 +3 2105 2110 2106 +3 2108 2113 229 +3 1298 2112 2113 +3 2111 2112 1298 +3 1297 1296 2109 +3 231 1296 1297 +3 2106 2104 2105 +3 2105 1301 2110 +3 2123 2115 2116 +3 232 1312 285 +3 1298 2113 2108 +3 2124 2118 1304 +3 2118 2124 1306 +3 84 51 168 +3 227 2117 2118 +3 1301 2115 2114 +3 226 1073 2121 +3 1303 2119 2117 +3 2119 2118 2117 +3 2119 1304 2118 +3 1156 1280 1660 +3 1303 226 2119 +3 1303 1763 226 +3 2105 225 2116 +3 2105 2116 1301 +3 225 1613 2116 +3 1073 289 2121 +3 1336 289 1335 +3 2117 2115 1303 +3 297 2120 2121 +3 297 2122 2120 +3 2126 1715 171 +3 224 1306 2124 +3 82 169 168 +3 2125 1715 2126 +3 1714 171 1715 +3 171 224 2126 +3 2682 489 2681 +3 828 2682 826 +3 395 828 826 +3 826 2682 2127 +3 487 845 833 +3 1467 2148 481 +3 2148 2147 481 +3 2143 2139 362 +3 2135 2134 142 +3 787 2653 2656 +3 2502 2530 1944 +3 2502 703 2530 +3 302 359 896 +3 2700 302 896 +3 2537 1173 2362 +3 1891 2132 354 +3 1891 356 2132 +3 352 2134 2135 +3 354 2132 2133 +3 1508 1507 179 +3 2650 2651 385 +3 2133 2134 352 +3 2524 1411 2523 +3 2320 691 2315 +3 357 2129 2138 +3 1499 1498 142 +3 147 2306 429 +3 353 352 2135 +3 357 2138 2137 +3 2129 114 2138 +3 898 145 363 +3 2147 2130 2140 +3 155 2149 1720 +3 2149 268 1720 +3 300 2691 2693 +3 2149 155 1715 +3 2142 2133 144 +3 385 44 384 +3 2688 904 2697 +3 411 621 955 +3 2143 363 2139 +3 363 145 2139 +3 114 801 362 +3 242 825 2768 +3 2143 2304 146 +3 626 606 1807 +3 2689 905 2688 +3 301 2689 2688 +3 1528 1529 792 +3 2140 481 2147 +3 1715 269 2149 +3 268 269 97 +3 1132 2150 2151 +3 2150 681 2151 +3 659 1132 2151 +3 2152 1504 684 +3 2153 2152 684 +3 691 2317 2316 +3 2151 681 682 +3 2152 2151 682 +3 2283 2285 3 +3 1161 2285 2283 +3 714 2284 3 +3 659 2152 2153 +3 659 2151 2152 +3 1621 1623 1624 +3 1019 716 1131 +3 985 989 2154 +3 96 2154 989 +3 182 985 986 +3 2157 2156 876 +3 1060 870 1129 +3 293 109 2063 +3 1058 870 2155 +3 867 2685 2686 +3 2215 2216 2217 +3 287 1011 2194 +3 1059 2156 2155 +3 878 1671 2162 +3 2158 876 1049 +3 2166 1671 878 +3 872 1047 1048 +3 2160 1057 2159 +3 1110 865 2296 +3 2162 870 1058 +3 2169 2171 879 +3 2168 1048 1047 +3 2175 2169 879 +3 2175 2170 2169 +3 2176 1676 1677 +3 2170 1046 2169 +3 2279 2293 2282 +3 2293 1161 2282 +3 1044 2173 1675 +3 2173 1050 1675 +3 1201 2345 1202 +3 1204 1203 2351 +3 1201 2344 2345 +3 1318 2262 1803 +3 1678 1676 2178 +3 1676 1678 869 +3 2179 286 959 +3 286 1335 959 +3 2181 958 2180 +3 2180 958 2179 +3 959 2180 2179 +3 2222 1004 2760 +3 1898 19 1897 +3 2220 2188 2228 +3 2759 1961 287 +3 2266 2267 508 +3 2181 2182 958 +3 958 2183 471 +3 958 2182 2183 +3 2182 474 2183 +3 2698 898 301 +3 1420 2449 1400 +3 2449 2528 1400 +3 894 883 770 +3 2186 1005 1003 +3 2185 2186 1003 +3 2202 1009 2205 +3 966 1604 1605 +3 1008 1005 2197 +3 2188 1004 2187 +3 2184 2190 2182 +3 711 1094 2562 +3 711 1095 1094 +3 2181 2180 288 +3 2187 2185 288 +3 2195 2220 2229 +3 2198 1008 2197 +3 2230 792 1525 +3 2407 2406 2198 +3 1112 2759 1007 +3 2579 831 2679 +3 830 2579 2679 +3 1009 1013 2205 +3 2208 2207 2206 +3 2211 2213 2212 +3 2213 1114 2208 +3 2550 2560 2549 +3 2200 2212 2204 +3 2200 2211 2212 +3 2548 2549 245 +3 1316 2414 1604 +3 2412 1153 1308 +3 2549 166 245 +3 291 1119 2207 +3 2416 2427 1190 +3 1013 1009 2207 +3 291 2208 1114 +3 2208 291 2207 +3 1655 1159 1292 +3 2002 2003 2001 +3 1654 1159 1655 +3 2210 2209 2199 +3 1012 2210 2199 +3 1010 2204 2212 +3 2213 1010 2212 +3 8 100 102 +3 1012 1961 2211 +3 2298 2297 1951 +3 2298 1950 2297 +3 2215 2217 1950 +3 843 2577 1026 +3 296 270 2401 +3 1111 2195 2214 +3 2194 2193 2227 +3 1111 2214 2215 +3 2183 474 2260 +3 353 2135 75 +3 2757 2758 2189 +3 1111 1112 1007 +3 2195 1111 1007 +3 2214 2216 2215 +3 1336 1335 270 +3 2218 2217 1949 +3 1830 1832 1829 +3 2641 1886 199 +3 2232 2231 1558 +3 2222 2225 2223 +3 97 269 271 +3 18 2641 2642 +3 1335 286 2404 +3 961 2228 2188 +3 1520 799 1522 +3 2583 1179 774 +3 2232 2233 150 +3 795 2582 2234 +3 2581 2582 795 +3 2253 2254 2234 +3 1465 432 1466 +3 1465 1466 1464 +3 2243 806 407 +3 2583 1174 1179 +3 2679 2680 830 +3 148 1902 433 +3 2237 795 2233 +3 2233 2254 150 +3 2234 2235 796 +3 2249 2234 796 +3 1175 2583 774 +3 393 1145 589 +3 2467 2469 596 +3 2579 2581 2580 +3 2579 2236 2581 +3 1473 414 1967 +3 148 433 1465 +3 2581 795 2580 +3 392 2239 487 +3 828 829 489 +3 2239 488 495 +3 487 2239 495 +3 846 487 495 +3 2241 2242 808 +3 817 808 2242 +3 2243 407 2242 +3 2240 807 2241 +3 2241 408 2240 +3 2242 2244 817 +3 807 2240 1145 +3 797 2252 2235 +3 266 87 267 +3 2245 1984 86 +3 1524 799 2250 +3 2648 995 35 +3 194 2648 35 +3 2245 1985 2246 +3 1520 2248 799 +3 118 119 20 +3 2254 2253 150 +3 150 2231 2232 +3 1821 2467 596 +3 2579 392 831 +3 2576 1943 2578 +3 2237 2233 2232 +3 797 420 2252 +3 2249 2253 2234 +3 2255 1474 1444 +3 492 1474 2255 +3 2220 2228 2256 +3 2229 2220 2256 +3 2219 2256 2228 +3 2229 2256 2219 +3 2155 2156 1058 +3 2157 1058 2156 +3 272 6 1168 +3 285 98 2403 +3 2402 2404 2403 +3 2404 2402 270 +3 2198 2406 2405 +3 1006 2198 2405 +3 2535 1526 1522 +3 284 2402 2403 +3 2163 1058 2157 +3 1272 2263 2264 +3 2263 1287 2264 +3 572 1583 1781 +3 2340 2339 1584 +3 2340 2338 2339 +3 1708 2338 2340 +3 1584 2266 1705 +3 2266 508 1705 +3 533 2735 535 +3 2735 1887 535 +3 1993 1992 886 +3 2270 1326 2272 +3 405 2299 782 +3 704 2563 842 +3 2273 1328 1325 +3 1329 1328 2273 +3 761 1328 1329 +3 1063 2276 1062 +3 2507 1040 2506 +3 2507 2513 1040 +3 2500 877 2501 +3 2277 877 2511 +3 2510 2277 2511 +3 2503 1064 2504 +3 2365 718 2286 +3 2278 1600 1064 +3 2278 1699 1600 +3 718 2362 2286 +3 2366 2014 935 +3 2322 715 2323 +3 2284 2288 2287 +3 684 2290 2153 +3 1403 2328 2327 +3 2290 2288 2284 +3 382 361 1165 +3 1504 2289 684 +3 719 1160 686 +3 684 2288 2290 +3 1504 1503 2289 +3 1154 1606 2687 +3 1606 1607 2687 +3 2319 1621 1624 +3 2315 1620 2320 +3 2280 1160 2292 +3 2279 1160 2280 +3 686 1160 2279 +3 2279 2280 2293 +3 2011 579 2010 +3 2012 2011 2010 +3 2671 1640 2674 +3 1725 698 2012 +3 698 2011 2012 +3 698 1097 1096 +3 500 514 825 +3 2291 2292 2281 +3 2292 1160 2281 +3 2430 2431 2293 +3 2431 1161 2293 +3 2300 1327 782 +3 2300 590 1327 +3 2411 2410 1290 +3 2411 2409 2410 +3 1290 2413 1159 +3 1603 1156 2301 +3 1521 1525 791 +3 801 2303 2304 +3 801 429 2303 +3 146 2304 2303 +3 2304 2143 362 +3 801 2304 362 +3 2434 496 2436 +3 2062 2310 427 +3 2314 2310 2313 +3 2314 427 2310 +3 1500 1501 2302 +3 2311 23 2312 +3 427 2311 2312 +3 429 2306 2305 +3 428 2307 2308 +3 428 2314 2313 +3 2311 427 2314 +3 1496 75 1495 +3 45 427 2312 +3 2446 2447 45 +3 1027 2446 1162 +3 2449 1420 1422 +3 1420 1401 1422 +3 2529 1410 1428 +3 870 1062 1128 +3 2317 716 1019 +3 1624 716 2317 +3 2322 1622 1621 +3 2318 2153 2290 +3 2319 1624 2317 +3 1410 2523 2520 +3 1578 2613 2603 +3 513 1564 1537 +3 1173 2363 2362 +3 386 1457 2326 +3 2002 2001 41 +3 2763 2002 41 +3 2366 2013 2014 +3 2541 2542 717 +3 2544 2541 717 +3 2434 1792 496 +3 850 1792 2434 +3 2303 429 2433 +3 626 633 2655 +3 2324 2325 723 +3 1625 1627 2325 +3 2327 1407 1408 +3 386 449 1345 +3 386 2326 449 +3 2329 1406 2330 +3 2445 2312 1162 +3 2312 2445 45 +3 136 382 379 +3 136 381 382 +3 1836 2494 2495 +3 2496 1836 2495 +3 1226 946 2334 +3 2496 2495 1239 +3 136 376 381 +3 572 2336 1708 +3 2335 947 49 +3 506 1592 514 +3 514 500 506 +3 2195 2196 2220 +3 2344 1200 2345 +3 572 1800 2336 +3 287 2194 2758 +3 531 2729 257 +3 2750 56 2747 +3 2337 2338 1708 +3 2337 2265 2338 +3 2725 2728 538 +3 447 446 187 +3 1667 862 222 +3 156 2342 105 +3 51 84 104 +3 2607 2605 1572 +3 2342 104 105 +3 2462 2463 1100 +3 1971 43 1973 +3 2641 200 2642 +3 2752 939 2749 +3 1795 2746 2745 +3 2745 2744 1795 +3 2344 1224 1200 +3 2344 2352 1224 +3 1209 2347 1200 +3 2347 2346 1200 +3 615 400 1210 +3 2347 1209 2351 +3 2745 2746 939 +3 1778 2745 939 +3 2545 1625 1626 +3 2352 1201 2353 +3 617 615 2359 +3 617 419 615 +3 2356 2355 2354 +3 426 2355 2356 +3 2354 2353 1199 +3 777 779 2488 +3 779 777 776 +3 426 617 2355 +3 1197 426 2356 +3 426 1197 1198 +3 2355 617 2359 +3 2359 2358 614 +3 2357 614 2358 +3 2355 2359 614 +3 2354 2355 614 +3 718 2364 2536 +3 2537 718 2536 +3 2360 2539 2538 +3 2360 719 2539 +3 2360 2538 2537 +3 2536 2360 2537 +3 718 2537 2362 +3 717 2545 2544 +3 719 2360 2361 +3 719 2361 1160 +3 2364 2281 1160 +3 2361 2364 1160 +3 1313 2369 372 +3 2109 229 1313 +3 229 2369 1313 +3 1300 2369 229 +3 315 316 236 +3 2370 230 2371 +3 2367 1475 2373 +3 312 313 2372 +3 1284 2367 2373 +3 315 233 316 +3 2381 2373 1476 +3 2382 1285 2383 +3 2374 2375 1380 +3 1284 2375 2374 +3 2378 1802 367 +3 2378 1271 1802 +3 2381 2380 1284 +3 1284 2373 2381 +3 1803 2376 1318 +3 2379 2372 230 +3 2371 230 2372 +3 2375 1284 2380 +3 310 1267 374 +3 2392 310 374 +3 2389 468 469 +3 468 2389 1898 +3 2378 2377 1271 +3 2380 368 2376 +3 1479 2388 2387 +3 2380 2382 368 +3 2381 2382 2380 +3 1283 2385 2386 +3 162 1480 1477 +3 2388 1898 2389 +3 2381 1285 2382 +3 2382 2385 368 +3 2384 2387 2391 +3 19 160 163 +3 163 160 159 +3 1478 1481 1480 +3 2392 2391 2395 +3 310 2392 2393 +3 368 2390 1318 +3 2376 368 1318 +3 2390 368 2385 +3 2385 1283 2390 +3 1480 162 1482 +3 1478 1480 1482 +3 1483 162 1319 +3 1283 2684 53 +3 2397 646 607 +3 646 2397 1913 +3 375 2390 2394 +3 375 1318 2390 +3 371 2391 2392 +3 310 2393 1018 +3 375 2394 1282 +3 2391 161 2395 +3 79 2736 2733 +3 1925 652 1929 +3 1665 890 2426 +3 2399 272 2398 +3 98 284 2403 +3 271 2401 2400 +3 2405 2199 2209 +3 1006 2405 2209 +3 2403 286 285 +3 1011 2406 2407 +3 2406 1011 2199 +3 2406 2199 2405 +3 2193 1011 2408 +3 2408 2197 2193 +3 1153 2411 1290 +3 1308 1605 2414 +3 1308 2414 2412 +3 2412 2414 1316 +3 1605 1604 2414 +3 1009 2202 2203 +3 1316 1601 2409 +3 1604 1601 1316 +3 1157 2410 2409 +3 2411 2412 1316 +3 1157 2415 2410 +3 2415 1157 2301 +3 2427 2396 1190 +3 2426 2421 1665 +3 2421 889 1665 +3 2422 404 759 +3 2424 591 1330 +3 1665 889 1664 +3 761 2420 2424 +3 2420 2418 2424 +3 761 1329 2420 +3 652 2425 759 +3 652 757 2425 +3 1189 1188 2419 +3 2418 2420 404 +3 760 759 2420 +3 759 404 2420 +3 760 588 1083 +3 1329 760 2420 +3 2424 1330 761 +3 1914 2428 649 +3 2423 884 889 +3 2418 763 2424 +3 890 2427 2416 +3 2427 2428 2396 +3 2427 890 2428 +3 2428 647 2396 +3 1914 647 2428 +3 1924 2423 757 +3 890 649 2428 +3 648 2423 1924 +3 862 2429 1813 +3 2291 2430 2292 +3 429 2305 2433 +3 2433 2302 2303 +3 2439 1439 1402 +3 2435 847 495 +3 847 846 495 +3 850 2435 495 +3 2482 2483 845 +3 486 845 2483 +3 2436 1900 847 +3 2434 2436 847 +3 1130 2767 396 +3 2767 2766 396 +3 850 2434 2435 +3 1899 1900 2436 +3 496 1899 2436 +3 391 2483 2482 +3 440 2440 1402 +3 440 2441 2440 +3 440 1414 2441 +3 189 2438 2439 +3 2438 1439 2439 +3 1414 442 2441 +3 1401 2444 2443 +3 1439 2438 2442 +3 2438 2437 2442 +3 2447 7 13 +3 1935 2447 13 +3 2566 342 2567 +3 425 973 2450 +3 996 61 995 +3 921 2451 2450 +3 2453 923 1995 +3 2453 1995 921 +3 2452 2453 921 +3 2452 5 2453 +3 973 5 2452 +3 978 5 973 +3 1103 1122 2577 +3 1972 253 1998 +3 2456 2457 1679 +3 2456 31 2457 +3 2455 2456 1679 +3 250 85 252 +3 907 68 963 +3 1026 2578 1945 +3 843 1074 2460 +3 2542 720 1628 +3 2461 1101 841 +3 1101 1124 841 +3 1100 2463 2464 +3 690 2464 2463 +3 2458 1101 2461 +3 2458 2462 1101 +3 2464 1092 1100 +3 2470 2654 596 +3 2469 2470 596 +3 626 2655 2470 +3 690 2465 2464 +3 2465 1092 2464 +3 1821 689 2467 +3 1222 575 94 +3 2470 1090 1089 +3 799 2248 2249 +3 2361 2536 2364 +3 2471 1637 582 +3 1127 913 2475 +3 952 1183 416 +3 2476 913 2477 +3 1057 2161 2163 +3 952 416 953 +3 2481 952 953 +3 520 502 1218 +3 1637 1640 1639 +3 577 1637 2471 +3 1638 1637 577 +3 1727 2473 582 +3 2477 174 2476 +3 810 409 827 +3 2540 2762 1173 +3 2538 2540 1173 +3 1173 2762 2543 +3 2762 2541 2543 +3 1781 1779 572 +3 952 2481 783 +3 809 409 810 +3 815 2479 409 +3 1360 695 2477 +3 695 1360 781 +3 2478 2476 827 +3 2479 2478 827 +3 2478 2479 783 +3 2767 824 2766 +3 2480 1127 2475 +3 847 391 2482 +3 1900 391 847 +3 2482 846 847 +3 1320 2488 610 +3 2710 418 2709 +3 957 2710 2709 +3 785 2712 2706 +3 2712 2709 2706 +3 2709 2712 2705 +3 610 2488 1198 +3 1813 2429 2489 +3 1035 863 2489 +3 1198 2487 2486 +3 863 1813 2489 +3 1813 863 1812 +3 2488 2487 1198 +3 2488 779 2487 +3 2429 1036 2489 +3 2609 2608 16 +3 7 2490 13 +3 13 2490 1938 +3 2493 1839 1837 +3 1974 1595 2596 +3 252 85 965 +3 2596 1973 1974 +3 2493 1843 1839 +3 2495 2494 1837 +3 1237 1835 1239 +3 948 181 1226 +3 2495 1837 1239 +3 2497 1238 740 +3 2646 2645 9 +3 2497 740 1836 +3 1128 2498 1129 +3 2770 2296 1059 +3 2769 2770 1060 +3 877 2277 2501 +3 2504 1064 2505 +3 868 2512 2509 +3 2499 2500 1042 +3 1105 864 1106 +3 2506 2505 871 +3 2507 871 1037 +3 2506 871 2507 +3 1031 2507 1037 +3 1105 2509 1040 +3 2509 1105 868 +3 2276 1063 2278 +3 2510 2276 2503 +3 2504 2510 2503 +3 2504 2277 2510 +3 875 1042 1041 +3 2276 2510 1062 +3 864 2513 2514 +3 2513 864 1105 +3 864 2514 1030 +3 1775 1893 2516 +3 2738 2739 1208 +3 1778 2753 2754 +3 2518 1893 1784 +3 2518 2516 1893 +3 1793 2518 1784 +3 1793 1783 2518 +3 1783 2516 2518 +3 1167 383 44 +3 1990 302 899 +3 901 302 1990 +3 360 302 901 +3 1409 2522 2521 +3 2521 2522 1404 +3 1989 1990 899 +3 2327 2522 1409 +3 440 1411 2524 +3 1424 1405 2528 +3 2528 1405 1416 +3 1421 1424 2528 +3 2522 1408 2526 +3 2522 2526 1404 +3 2526 1416 1404 +3 2526 2527 1416 +3 2526 1408 2527 +3 1678 2701 869 +3 376 377 349 +3 377 2531 349 +3 165 131 134 +3 377 135 2531 +3 135 2532 2531 +3 2532 349 2531 +3 139 349 2532 +3 73 139 2533 +3 74 349 908 +3 270 1335 2404 +3 2552 2551 245 +3 2360 2536 2361 +3 720 2542 1631 +3 251 254 2763 +3 841 1123 1122 +3 251 2763 41 +3 41 1999 251 +3 1631 2540 2539 +3 2540 2538 2539 +3 963 254 251 +3 2541 2544 2543 +3 2543 2544 2363 +3 2547 1627 717 +3 723 1627 1628 +3 1627 1625 2545 +3 1172 2546 3 +3 719 683 720 +3 2542 2547 717 +3 1892 101 2548 +3 29 100 2550 +3 100 29 102 +3 345 2564 1745 +3 256 2550 101 +3 256 29 2550 +3 60 1892 2551 +3 245 2553 2552 +3 2553 246 2552 +3 245 2551 2548 +3 2551 1892 2548 +3 167 2557 2558 +3 167 2554 2557 +3 67 255 248 +3 2556 63 2555 +3 2554 246 2553 +3 167 62 2555 +3 167 2555 2554 +3 2555 63 2554 +3 255 256 101 +3 67 256 255 +3 2557 2553 245 +3 166 2557 245 +3 2556 62 43 +3 1971 2556 43 +3 1680 31 2456 +3 62 2556 2555 +3 2558 2559 167 +3 2559 2558 15 +3 15 42 2559 +3 2562 1094 712 +3 842 2562 712 +3 2574 2231 150 +3 587 1651 1147 +3 2563 704 581 +3 2565 345 1747 +3 1735 324 1742 +3 2570 2571 1734 +3 2568 2571 88 +3 2571 2568 2572 +3 1735 2564 2573 +3 341 1747 1746 +3 88 2567 2568 +3 343 344 2568 +3 2569 1735 2573 +3 2569 2570 1735 +3 1734 2571 2572 +3 1333 213 1332 +3 432 147 801 +3 1731 1733 325 +3 1333 1734 2572 +3 2572 1334 1333 +3 1334 2572 344 +3 344 2572 2568 +3 432 801 114 +3 432 114 1467 +3 1467 114 2148 +3 2575 509 490 +3 1464 1463 148 +3 2235 2582 2236 +3 1103 2577 2460 +3 243 2682 2681 +3 844 243 2681 +3 2582 2235 2234 +3 2236 797 2235 +3 2237 2580 795 +3 2244 407 818 +3 1942 1937 12 +3 1549 1547 2586 +3 2586 1547 2585 +3 2585 1547 1567 +3 1547 1564 1567 +3 2586 1551 1549 +3 2588 842 712 +3 2590 1436 1135 +3 2590 2591 1441 +3 1472 1441 2591 +3 1472 1442 1441 +3 2593 2592 1440 +3 2590 1135 2591 +3 1701 2592 1135 +3 2591 1135 2592 +3 1437 2590 1441 +3 1472 2591 2592 +3 308 306 307 +3 2595 1434 1435 +3 2492 434 1471 +3 2595 2594 1434 +3 2600 251 1999 +3 2597 1973 2596 +3 2598 1595 1976 +3 251 250 252 +3 2600 250 251 +3 2598 1976 250 +3 1972 2599 253 +3 2599 2598 253 +3 550 548 976 +3 2617 1588 1593 +3 1591 506 2610 +3 2602 2604 1573 +3 974 549 968 +3 1572 2605 1574 +3 2602 1573 2603 +3 2612 2613 2614 +3 2613 1578 2614 +3 79 552 234 +3 852 79 234 +3 2605 515 2606 +3 2609 2603 1573 +3 2609 2610 2603 +3 515 498 2606 +3 2603 2610 503 +3 2616 1593 2608 +3 2612 2611 504 +3 2612 2615 2611 +3 1952 2619 1951 +3 2607 1572 2616 +3 1576 515 1575 +3 1576 1575 2601 +3 2613 2612 504 +3 2612 1577 2615 +3 1577 1994 2615 +3 1577 1579 1994 +3 1769 1579 1577 +3 1573 2607 2618 +3 2619 1953 290 +3 2616 2617 1593 +3 1572 2617 2616 +3 2617 1572 1588 +3 2620 1413 10 +3 2621 2620 10 +3 1429 2621 10 +3 10 2529 1429 +3 2529 1428 1429 +3 441 1413 2623 +3 585 2626 2625 +3 1642 1641 2624 +3 1648 1642 2624 +3 585 2625 2627 +3 608 1644 1643 +3 2625 1649 1648 +3 708 709 581 +3 398 2634 2631 +3 2635 2631 1638 +3 2629 2627 709 +3 2630 2628 2629 +3 2627 2624 709 +3 2627 2625 2624 +3 1648 2624 2625 +3 2629 708 2630 +3 2635 1638 577 +3 2628 2630 580 +3 398 803 802 +3 2633 2634 585 +3 2633 585 2632 +3 398 2631 2635 +3 2632 2629 2628 +3 2633 2632 2628 +3 398 802 2634 +3 1151 399 1150 +3 1195 1150 612 +3 2636 94 804 +3 845 486 2676 +3 2639 1473 1443 +3 215 1723 1722 +3 2643 2644 2642 +3 2145 2650 385 +3 200 31 2643 +3 200 2643 2642 +3 2645 18 2644 +3 1886 2649 196 +3 2647 2646 9 +3 1684 1728 2647 +3 1728 195 2647 +3 2645 194 1885 +3 1684 2647 9 +3 995 994 35 +3 2646 2648 194 +3 2645 2646 194 +3 1728 1729 195 +3 2649 1885 196 +3 2136 2137 358 +3 2651 2652 385 +3 144 2136 2651 +3 359 44 2652 +3 360 44 359 +3 604 787 635 +3 2655 2654 2470 +3 2655 634 2654 +3 2655 633 634 +3 1526 1528 1522 +3 785 2703 2704 +3 785 2659 2703 +3 559 2657 1505 +3 1506 2657 559 +3 2707 2706 418 +3 1433 467 2715 +3 2706 2661 785 +3 466 2660 561 +3 561 2660 562 +3 558 784 1506 +3 1835 1237 2663 +3 2663 1237 725 +3 725 1238 2663 +3 1835 1238 2497 +3 1835 2663 1238 +3 2664 687 1822 +3 687 1823 1822 +3 692 1819 1818 +3 692 1392 2666 +3 1389 598 2666 +3 2630 2672 580 +3 1191 607 1192 +3 653 2665 759 +3 512 1592 1566 +3 797 829 798 +3 1592 512 514 +3 397 803 804 +3 2012 2010 699 +3 2668 578 2673 +3 1640 2671 2667 +3 2012 699 2673 +3 578 1725 2673 +3 2760 2756 2222 +3 1638 2628 2675 +3 2675 2628 580 +3 580 2674 2675 +3 398 2636 804 +3 398 2635 2636 +3 1637 2675 2674 +3 2674 1640 1637 +3 1645 583 579 +3 1120 2677 1117 +3 2756 2760 2221 +3 1957 1115 1958 +3 1117 2677 960 +3 2682 243 2127 +3 832 2680 2679 +3 2392 374 2683 +3 371 2392 2683 +3 53 2683 1269 +3 367 1269 1268 +3 1269 374 1268 +3 374 1269 2683 +3 867 978 2685 +3 1054 2686 866 +3 1054 2294 2686 +3 905 904 2688 +3 905 322 904 +3 146 2696 363 +3 2691 111 905 +3 2690 2693 2694 +3 896 145 2699 +3 2690 300 2693 +3 2690 22 300 +3 363 2695 898 +3 2690 2696 22 +3 2692 304 111 +3 2699 898 2698 +3 2698 897 2699 +3 1501 22 2696 +3 359 145 896 +3 2700 2699 897 +3 899 2700 897 +3 302 2700 899 +3 2702 1774 1773 +3 1785 2702 1773 +3 2702 1785 519 +3 435 444 436 +3 2713 1440 437 +3 521 1771 1770 +3 527 1355 1354 +3 2715 467 2716 +3 2710 839 2711 +3 1800 2751 2336 +3 957 2705 411 +3 2707 2661 2706 +3 417 957 955 +3 2705 2712 785 +3 2708 415 1435 +3 415 838 1435 +3 1795 1780 2746 +3 2711 2708 418 +3 2710 2711 418 +3 492 1449 1661 +3 839 415 2711 +3 191 1435 2715 +3 2715 1435 2714 +3 1431 2719 1430 +3 1430 2719 1419 +3 1431 2718 2719 +3 2718 1431 1432 +3 2718 437 2719 +3 1701 1419 2719 +3 753 755 309 +3 14 306 308 +3 1017 2395 161 +3 308 307 153 +3 539 2729 2730 +3 2732 2731 537 +3 239 2731 2732 +3 2735 185 1887 +3 532 185 2735 +3 2733 522 239 +3 2733 239 2732 +3 97 2742 274 +3 2742 97 1168 +3 2741 573 1206 +3 1207 2737 2741 +3 939 2748 2749 +3 2753 1778 939 +3 2749 2747 1710 +3 1782 571 2755 +3 1779 2755 2754 +3 2541 2762 2540 +3 2196 2758 2757 +3 1007 2758 2196 +3 2758 1007 2759 +3 2759 1112 1961 +3 2225 2761 2757 +3 2756 2757 2761 +3 387 2764 1470 +3 2766 824 826 +3 825 824 2768 +3 1703 1585 2771 +3 1042 875 2769 + From 2571c7719e393f8cf5af89454f560f0cb145469c Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Wed, 9 May 2018 15:26:56 +0200 Subject: [PATCH 023/150] abstract interface for eigen dense matrix --- .../Optimal_bounding_box/bench_custom.cpp | 1 - .../Optimal_bounding_box/bench_obb.cpp | 4 - .../Optimal_bounding_box/bench_perfomance.cpp | 1 - .../Optimal_bounding_box/fitness_function.h | 2 +- .../Optimal_bounding_box/linear_algebra.h | 15 +- .../include/CGAL/Optimal_bounding_box/obb.h | 41 ++- .../optimization_algorithms.h | 4 +- .../CGAL/Optimal_bounding_box/population.h | 6 +- .../test_linear_algebra_functions.cpp | 260 ++++++++++++++++-- .../test_optimization_algorithms.cpp | 158 +++++++++-- .../Plugins/PCA/Create_obb_mesh_plugin.cpp | 2 +- .../CGAL/Eigen_linear_algebra_traits.h | 158 +++++++++++ 12 files changed, 593 insertions(+), 59 deletions(-) create mode 100644 Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp index 38d9413ca8c..aad2ef10026 100644 --- a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp index d4ad8de002a..ae604898449 100644 --- a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp @@ -5,16 +5,12 @@ #include #include #include -#include #include //#define OBB_DEBUG_BENCHMARK -typedef Eigen::MatrixXd MatrixXd; -typedef Eigen::Matrix3d Matrix3d; - typedef CGAL::Exact_predicates_inexact_constructions_kernel K; diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp index 71b8b86be7c..a35fc86bf13 100644 --- a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 96146b6cb58..0c214432083 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -43,7 +43,7 @@ const double compute_fitness(const Vertex& R, const Matrix& data) double xmin, xmax, ymin, ymax, zmin, zmax; for(int i = 0; i < data.rows(); i++){ - Eigen::Vector3d vec = data.row(i); + Matrix vec = data.row(i); vec = R * vec; if(i == 0){ diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h index e10aaa7c24b..5d7e1ffbc75 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h @@ -82,19 +82,26 @@ Matrix mean(const Matrix& m1, const Matrix& m2) CGAL_assertion(m2.cols() == 3); CGAL_assertion(m2.cols() == 3); - Matrix contract = 0.5 * m1 + 0.5 * m2; + Matrix reduction = 0.5 * m1 + 0.5 * m2; Matrix Q; - qr_factorization(contract, Q); + //qr_factorization(contract, Q); + + reduction.qr_factorization(Q); + double det = Q.determinant(); return Q / det; } template -const Matrix centroid(Matrix& S1, Matrix& S2, Matrix& S3) +const Matrix centroid(Matrix& S1, Matrix& S2, Matrix& S3) // const? { Matrix mean = (S1 + S2 + S3) / 3.0; Matrix Q; - qr_factorization(mean, Q); + //qr_factorization(mean, Q); + + mean.qr_factorization(Q); + + double det = Q.determinant(); return Q / det; } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index c58a5c2adfb..870b122f621 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -34,7 +34,8 @@ #include #include -#include +//#include +#include namespace CGAL { @@ -124,7 +125,8 @@ void post_processing(Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) std::vector v_points; // Simplex -> std::vector for(std::size_t i = 0; i < rotated_points.rows(); ++i) { - Point p(rotated_points.coeff(i, 0), rotated_points.coeff(i, 1), rotated_points.coeff(i, 2)); + //Point p(rotated_points.coeff(i, 0), rotated_points.coeff(i, 1), rotated_points.coeff(i, 2)); + Point p(rotated_points(i, 0), rotated_points(i, 1), rotated_points(i, 2)); v_points.push_back(p); } CGAL::Bbox_3 bbox; @@ -138,9 +140,17 @@ void post_processing(Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) for(std::size_t i = 0; i < 8; ++i) { + /* aabb.coeffRef(i, 0) = ic[i].x(); aabb.coeffRef(i, 1) = ic[i].y(); aabb.coeffRef(i, 2) = ic[i].z(); + */ + + aabb.set_coef(i, 0, ic[i].x()); + aabb.set_coef(i, 1, ic[i].y()); + aabb.set_coef(i, 2, ic[i].z()); + + } // 3) apply inverse rotation to rotated AABB @@ -154,9 +164,16 @@ void fill_matrix(std::vector& v_points, Matrix& points_mat) for(std::size_t i = 0; i < v_points.size(); ++i) { Point p = v_points[i]; + /* points_mat.coeffRef(i, 0) = p.x(); points_mat.coeffRef(i, 1) = p.y(); points_mat.coeffRef(i, 2) = p.z(); + */ + + points_mat.set_coef(i, 0, p.x()); + points_mat.set_coef(i, 1, p.y()); + points_mat.set_coef(i, 2, p.z()); + } } @@ -175,8 +192,12 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u CGAL_assertion(obb_points.size() == 8); // using eigen internally - typedef Eigen::MatrixXd MatrixXd; // for point data - typedef Eigen::Matrix3d Matrix3d; // for matrices in simplices + //typedef Eigen::MatrixXd MatrixXd; // for point data + //typedef Eigen::Matrix3d Matrix3d; // for matrices in simplices + + // todo: sort out typedefs + typedef CGAL::Eigen_dense_matrix MatrixXd; // for point data + typedef CGAL::Eigen_dense_matrix Matrix3d; // for matrices in simplices MatrixXd points_mat; @@ -198,17 +219,23 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u fill_matrix(points, points_mat); } - Matrix3d R; + //Matrix3d R; // todo: sort out preallocation + Matrix3d R(3, 3); std::size_t max_generations = 100; CGAL::Optimal_bounding_box::evolution(R, points_mat, max_generations); - Eigen::Matrix obb; + //Eigen::Matrix obb; + + CGAL::Eigen_dense_matrix obb; // compile time preallocation?? + obb.resize(8, 3); + CGAL::Optimal_bounding_box::post_processing(points_mat, R, obb); // matrix -> vector for(std::size_t i = 0; i < 8; ++i) { - Point p(obb.coeff(i, 0), obb.coeff(i, 1), obb.coeff(i, 2)); + //Point p(obb.coeff(i, 0), obb.coeff(i, 1), obb.coeff(i, 2)); + Point p(obb(i, 0), obb(i, 1), obb(i, 2)); obb_points[i] = p; } } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h index 3e7b45ddd11..598d75c6192 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h @@ -259,7 +259,9 @@ void genetic_algorithm(Population& pop, const Matrix& points) } // qr factorization of the offspring - qr_factorization(offspring); + qr_factorization(offspring); + + offspringsB[i] = offspring; } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index ab5e27299c8..b86a5101ab4 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -103,7 +103,8 @@ private: create_vertex(R); Matrix Q; // no allocation - qr_factorization(R, Q); + //qr_factorization(R, Q); + R.qr_factorization(Q); simplex[i] = Q; } CGAL_assertion(simplex.size() == 4); @@ -118,7 +119,8 @@ private: { for(std::size_t j = 0; j < 3; ++j) { - R.coeffRef(i, j) = random_generator.get_double(); + //R.coeffRef(i, j) = random_generator.get_double(); + R.set_coef(i, j, random_generator.get_double()); } } } diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index a36313eacce..7565df7e56f 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -5,6 +5,7 @@ #include #include +#include typedef Eigen::Matrix3d Matrix3d; @@ -15,13 +16,29 @@ bool assert_doubles(double d1, double d2, double epsilon) void test_qr_factorization() { - Matrix3d A(3, 3); + CGAL::Eigen_dense_matrix A(3, 3); + /* A << 0.3011944, 0.9932761, 0.5483701, 0.5149142, 0.5973263, 0.5162336, 0.0039213, 0.0202949, 0.9240308; + */ + + A.set_coef(0, 0, 0.3011944); + A.set_coef(0, 1, 0.9932761); + A.set_coef(0, 2, 0.5483701); + A.set_coef(1, 0, 0.5149142); + A.set_coef(1, 1, 0.5973263); + A.set_coef(1, 2, 0.5162336); + A.set_coef(2, 0, 0.0039213); + A.set_coef(2, 1, 0.0202949); + A.set_coef(2, 2, 0.9240308); + + CGAL::Eigen_dense_matrix Q; + //CGAL::Optimal_bounding_box::qr_factorization(A, Q); + + A.qr_factorization(Q); + - Matrix3d Q; - CGAL::Optimal_bounding_box::qr_factorization(A, Q); double epsilon = 1e-6; CGAL_assertion(assert_doubles(Q(0,0), -0.504895, epsilon)); @@ -37,16 +54,52 @@ void test_qr_factorization() void test_fitness_function() { - Eigen::Matrix data_points(4, 3); + //Eigen::Matrix data_points(4, 3); + CGAL::Eigen_dense_matrix data_points(4, 3); + + /* data_points << 0.866802, 0.740808, 0.895304, 0.912651, 0.761565, 0.160330, 0.093661, 0.892578, 0.737412, 0.166461, 0.149912, 0.364944; + */ - Matrix3d rotation(3, 3); + data_points.set_coef(0, 0, 0.866802); + data_points.set_coef(0, 1, 0.740808); + data_points.set_coef(0, 2, 0.895304); + + data_points.set_coef(1, 0, 0.912651); + data_points.set_coef(1, 1, 0.761565); + data_points.set_coef(1, 2, 0.160330); + + data_points.set_coef(2, 0, 0.093661); + data_points.set_coef(2, 1, 0.892578); + data_points.set_coef(2, 2, 0.737412); + + data_points.set_coef(3, 0, 0.166461); + data_points.set_coef(3, 1, 0.149912); + data_points.set_coef(3, 2, 0.364944); + + + + //Matrix3d rotation(3, 3); + CGAL::Eigen_dense_matrix rotation(3, 3); + /* rotation << -0.809204, 0.124296, 0.574230, -0.574694, 0.035719, -0.817589, -0.122134, -0.991602, 0.042528; + */ + + + rotation.set_coef(0, 0, -0.809204); + rotation.set_coef(0, 1, 0.124296); + rotation.set_coef(0, 2, 0.574230); + rotation.set_coef(1, 0, -0.574694); + rotation.set_coef(1, 1, 0.035719); + rotation.set_coef(1, 2, -0.817589); + rotation.set_coef(2, 0, -0.122134); + rotation.set_coef(2, 1, -0.991602); + rotation.set_coef(2, 2, 0.042528); double fitness = CGAL::Optimal_bounding_box::compute_fitness(rotation, data_points); CGAL_assertion(assert_doubles(fitness, 0.58606, 1e-5)); @@ -55,17 +108,46 @@ void test_fitness_function() void test_simplex_operations() { - Matrix3d Sc(3, 3); + //Matrix3d Sc(3, 3); + CGAL::Eigen_dense_matrix Sc(3, 3); + /* Sc << -0.809204, 0.124296, 0.574230, -0.574694, 0.035719, -0.817589, -0.122134, -0.991602, 0.042528; + */ - Matrix3d S_worst(3, 3); + Sc.set_coef(0, 0, -0.809204); + Sc.set_coef(0, 1, 0.124296); + Sc.set_coef(0, 2, 0.574230); + Sc.set_coef(1, 0, -0.574694); + Sc.set_coef(1, 1, 0.035719); + Sc.set_coef(1, 2, -0.817589); + Sc.set_coef(2, 0, -0.122134); + Sc.set_coef(2, 1, -0.991602); + Sc.set_coef(2, 2, 0.042528); + + + + CGAL::Eigen_dense_matrix S_worst(3, 3); + /* S_worst << -0.45070, -0.32769, -0.83035, -0.13619, -0.89406, 0.42675, -0.88222, 0.30543, 0.35833; + */ - Matrix3d Sr = CGAL::Optimal_bounding_box::reflection(Sc, S_worst); + + S_worst.set_coef(0, 0, -0.45070); + S_worst.set_coef(0, 1, -0.32769); + S_worst.set_coef(0, 2, -0.83035); + S_worst.set_coef(1, 0, -0.13619); + S_worst.set_coef(1, 1, -0.89406); + S_worst.set_coef(1, 2, 0.42675); + S_worst.set_coef(2, 0, -0.88222); + S_worst.set_coef(2, 1, 0.30543); + S_worst.set_coef(2, 2, 0.35833); + + + CGAL::Eigen_dense_matrix Sr = CGAL::Optimal_bounding_box::reflection(Sc, S_worst); double epsilon = 1e-5; CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); @@ -77,7 +159,7 @@ void test_simplex_operations() CGAL_assertion(assert_doubles(Sr(2,1), 0.25411, epsilon)); CGAL_assertion(assert_doubles(Sr(2,2), -0.56300, epsilon)); - Matrix3d Se = CGAL::Optimal_bounding_box::expansion(Sc, S_worst, Sr); + CGAL::Eigen_dense_matrix Se = CGAL::Optimal_bounding_box::expansion(Sc, S_worst, Sr); CGAL_assertion(assert_doubles(Se(0,0), -0.87991, epsilon)); CGAL_assertion(assert_doubles(Se(0,1), 0.36105, epsilon)); CGAL_assertion(assert_doubles(Se(0,2), -0.30888, epsilon)); @@ -88,17 +170,45 @@ void test_simplex_operations() CGAL_assertion(assert_doubles(Se(2,1), -0.48595, epsilon)); CGAL_assertion(assert_doubles(Se(2,2), 0.74300, epsilon)); - Matrix3d S_a(3, 3); + CGAL::Eigen_dense_matrix S_a(3, 3); + /* S_a << -0.277970, 0.953559, 0.116010, -0.567497, -0.065576, -0.820760, -0.775035, -0.293982, 0.559370; + */ - Matrix3d S_b(3, 3); + + S_a.set_coef(0, 0, -0.277970); + S_a.set_coef(0, 1, 0.953559); + S_a.set_coef(0, 2, 0.116010); + S_a.set_coef(1, 0, -0.567497); + S_a.set_coef(1, 1, -0.065576); + S_a.set_coef(1, 2, -0.820760); + S_a.set_coef(2, 0, -0.775035); + S_a.set_coef(2, 1, -0.293982); + S_a.set_coef(2, 2, 0.559370); + + + CGAL::Eigen_dense_matrix S_b(3, 3); + /* S_b << -0.419979, 0.301765, -0.855894, -0.653011, -0.755415, 0.054087, -0.630234, 0.581624, 0.514314; + */ - Matrix3d S_c = CGAL::Optimal_bounding_box::mean(S_a, S_b); + + S_b.set_coef(0, 0, -0.419979); + S_b.set_coef(0, 1, 0.301765); + S_b.set_coef(0, 2, -0.8558940); + S_b.set_coef(1, 0, -0.653011); + S_b.set_coef(1, 1, -0.755415); + S_b.set_coef(1, 2, 0.054087); + S_b.set_coef(2, 0, -0.630234); + S_b.set_coef(2, 1, 0.581624); + S_b.set_coef(2, 2, 0.514314); + + + CGAL::Eigen_dense_matrix S_c = CGAL::Optimal_bounding_box::mean(S_a, S_b); CGAL_assertion(assert_doubles(S_c(0,0), -0.35111, epsilon)); CGAL_assertion(assert_doubles(S_c(0,1), 0.79308, epsilon)); CGAL_assertion(assert_doubles(S_c(0,2), -0.49774, epsilon)); @@ -112,22 +222,61 @@ void test_simplex_operations() void test_centroid() { - Matrix3d S_a(3, 3); + CGAL::Eigen_dense_matrix S_a(3, 3); + /* S_a << -0.588443, 0.807140, -0.047542, -0.786228, -0.584933, -0.199246, -0.188629, -0.079867, 0.978795; + */ - Matrix3d S_b(3, 3); + S_a.set_coef(0, 0, -0.588443); + S_a.set_coef(0, 1, 0.807140); + S_a.set_coef(0, 2, -0.047542); + S_a.set_coef(1, 0, -0.786228); + S_a.set_coef(1, 1, -0.584933); + S_a.set_coef(1, 2, -0.199246); + S_a.set_coef(2, 0, -0.188629); + S_a.set_coef(2, 1, -0.079867); + S_a.set_coef(2, 2, 0.978795); + + CGAL::Eigen_dense_matrix S_b(3, 3); + /* S_b << -0.2192721, 0.2792986, -0.9348326, -0.7772152, -0.6292092, -0.0056861, -0.5897934, 0.7253193, 0.3550431; + */ - Matrix3d S_c(3, 3); + S_b.set_coef(0, 0, -0.2192721); + S_b.set_coef(0, 1, 0.2792986); + S_b.set_coef(0, 2, -0.9348326); + S_b.set_coef(1, 0, -0.7772152); + S_b.set_coef(1, 1, -0.6292092); + S_b.set_coef(1, 2, -0.005686); + S_b.set_coef(2, 0, -0.5897934); + S_b.set_coef(2, 1, 0.7253193); + S_b.set_coef(2, 2, 0.3550431); + + CGAL::Eigen_dense_matrix S_c(3, 3); + /* S_c << -0.32657, -0.60013, -0.73020, -0.20022, -0.71110, 0.67398, -0.92372, 0.36630, 0.11207; + */ - Matrix3d S_centroid = CGAL::Optimal_bounding_box::centroid(S_a, S_b, S_c); + S_c.set_coef(0, 0, -0.32657); + S_c.set_coef(0, 1, -0.60013); + S_c.set_coef(0, 2, -0.730206); + S_c.set_coef(1, 0, -0.20022); + S_c.set_coef(1, 1, -0.71110); + S_c.set_coef(1, 2, 0.67398); + S_c.set_coef(2, 0, -0.92372); + S_c.set_coef(2, 1, 0.36630); + S_c.set_coef(2, 2, 0.11207); + + + + + CGAL::Eigen_dense_matrix S_centroid = CGAL::Optimal_bounding_box::centroid(S_a, S_b, S_c); double epsilon = 1e-5; CGAL_assertion(assert_doubles(S_centroid(0,0), -0.419979, epsilon)); CGAL_assertion(assert_doubles(S_centroid(0,1), 0.301765, epsilon)); @@ -140,12 +289,91 @@ void test_centroid() CGAL_assertion(assert_doubles(S_centroid(2,2), 0.514314, epsilon)); } + +void test_eigen_matrix_interface() +{ + CGAL::Eigen_dense_matrix A(3, 3); + A.set_coef(0, 0, 0.1); + A.set_coef(0, 1, 0.2); + A.set_coef(0, 2, 0.3); + A.set_coef(1, 0, 0.4); + A.set_coef(1, 1, 0.5); + A.set_coef(1, 2, 0.6); + A.set_coef(2, 0, 0.7); + A.set_coef(2, 1, 0.8); + A.set_coef(2, 2, 0.9); + CGAL::Eigen_dense_matrix B = A.transpose(); + + CGAL::Eigen_dense_matrix S = 0.5 * A; + + CGAL::Eigen_dense_matrix C(3,3); + C.set_coef(0, 0, 0.3011944); + C.set_coef(0, 1, 0.9932761); + C.set_coef(0, 2, 0.5483701); + C.set_coef(1, 0, 0.5149142); + C.set_coef(1, 1, 0.5973263); + C.set_coef(1, 2, 0.5162336); + C.set_coef(2, 0, 0.0039213); + C.set_coef(2, 1, 0.0202949); + C.set_coef(2, 2, 0.9240308); + + CGAL::Eigen_dense_matrix Q(3,3); + C.qr_factorization(Q); + + double epsilon = 1e-5; + CGAL_assertion(assert_doubles(Q(0,0), -0.504895, epsilon)); + CGAL_assertion(assert_doubles(Q(0,1), 0.862834, epsilon)); + CGAL_assertion(assert_doubles(Q(0,2), -0.024447, epsilon)); + CGAL_assertion(assert_doubles(Q(1,0), -0.863156, epsilon)); + CGAL_assertion(assert_doubles(Q(1,1), -0.504894, epsilon)); + CGAL_assertion(assert_doubles(Q(1,2), 0.006687, epsilon)); + CGAL_assertion(assert_doubles(Q(2,0), -0.006573, epsilon)); + CGAL_assertion(assert_doubles(Q(2,1), 0.024478, epsilon)); + CGAL_assertion(assert_doubles(Q(2,2), 0.999679, epsilon)); + + CGAL::Eigen_dense_matrix D(3,3); + D.set_coef(0, 0, -0.809204); + D.set_coef(0, 1, 0.124296); + D.set_coef(0, 2, 0.574230); + D.set_coef(1, 0, -0.574694); + D.set_coef(1, 1, 0.035719); + D.set_coef(1, 2, -0.817589); + D.set_coef(2, 0, -0.122134); + D.set_coef(2, 1, -0.991602); + D.set_coef(2, 2, 0.042528); + + CGAL::Eigen_dense_matrix E(3,3); + E.set_coef(0, 0, -0.45070); + E.set_coef(0, 1, -0.32769); + E.set_coef(0, 2, -0.83035); + E.set_coef(1, 0, -0.13619); + E.set_coef(1, 1, -0.89406); + E.set_coef(1, 2, 0.42675); + E.set_coef(2, 0, -0.88222); + E.set_coef(2, 1, 0.30543); + E.set_coef(2, 2, 0.35833); + + CGAL::Eigen_dense_matrix Sr = CGAL::Optimal_bounding_box::reflection(D, E); + CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); + CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); + CGAL_assertion(assert_doubles(Sr(0,2), -0.24664, epsilon)); + CGAL_assertion(assert_doubles(Sr(1,0), -0.60307, epsilon)); + CGAL_assertion(assert_doubles(Sr(1,1), -0.11875, epsilon)); + CGAL_assertion(assert_doubles(Sr(1,2), 0.78880, epsilon)); + CGAL_assertion(assert_doubles(Sr(2,0), -0.78642, epsilon)); + CGAL_assertion(assert_doubles(Sr(2,1), 0.25411, epsilon)); + CGAL_assertion(assert_doubles(Sr(2,2), -0.56300, epsilon)); +} + int main() { test_qr_factorization(); test_fitness_function(); + test_simplex_operations(); + test_centroid(); + test_eigen_matrix_interface(); return 0; } diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index bb72757c76f..8515ee37534 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -5,10 +5,16 @@ #include #include #include -#include -typedef Eigen::MatrixXd MatrixXd; -typedef Eigen::Matrix3d Matrix3d; +#include +#include + +//typedef Eigen::MatrixXd MatrixXd; +//typedef Eigen::Matrix3d Matrix3d; + +// todo: sort this out +typedef CGAL::Eigen_dense_matrix MatrixXd; +typedef CGAL::Eigen_dense_matrix Matrix3d; typedef CGAL::Exact_predicates_inexact_constructions_kernel K; @@ -31,9 +37,16 @@ void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) for(vertex_descriptor v : vertices(sm)) { Point_ref p = get(vpm, v); + /* mat.coeffRef(i, 0) = p.x(); mat.coeffRef(i, 1) = p.y(); mat.coeffRef(i, 2) = p.z(); + */ + + mat.set_coef(i, 0, p.x()); + mat.set_coef(i, 1, p.y()); + mat.set_coef(i, 2, p.z()); + ++i; } } @@ -82,34 +95,109 @@ void test_population() void test_nelder_mead() { - Eigen::Matrix data_points(4, 3); + //Eigen::Matrix data_points(4, 3); + + CGAL::Eigen_dense_matrix data_points(4,3); + + /* data_points << 0.866802, 0.740808, 0.895304, 0.912651, 0.761565, 0.160330, 0.093661, 0.892578, 0.737412, 0.166461, 0.149912, 0.364944; + */ + + data_points(0,0) = 0.866802; + data_points(0,1) = 0.740808, + data_points(0,2) = 0.895304, + data_points(1,0) = 0.912651; + data_points(1,1) = 0.761565; + data_points(1,2) = 0.160330; + data_points(2,0) = 0.093661; + data_points(2,1) = 0.892578; + data_points(2,2) = 0.737412; + data_points(3,0) = 0.166461; + data_points(3,1) = 0.149912, + data_points(3,2) = 0.364944; // one simplex - std::vector simplex(4); + //std::vector simplex(4); + std::vector> simplex(4); - Matrix3d v0; + + + //Matrix3d v0; + CGAL::Eigen_dense_matrix v0(3,3); + + /* v0 << -0.2192721, 0.2792986, -0.9348326, -0.7772152, -0.6292092, -0.0056861, -0.5897934, 0.7253193, 0.3550431; + */ - Matrix3d v1; + v0(0,0) = -0.2192721; + v0(0,1) = 0.2792986, + v0(0,2) = -0.9348326, + v0(1,0) = -0.7772152; + v0(1,1) = -0.6292092; + v0(1,2) = -0.0056861; + v0(2,0) = -0.5897934; + v0(2,1) = 0.7253193; + v0(2,2) = 0.3550431; + + + //Matrix3d v1; + //Matrix3d v2; + //Matrix3d v3; + + CGAL::Eigen_dense_matrix v1(3,3); + CGAL::Eigen_dense_matrix v2(3,3); + CGAL::Eigen_dense_matrix v3(3,3); + + + /* v1 << -0.588443, 0.807140, -0.047542, -0.786228, -0.584933, -0.199246, -0.188629, -0.079867, 0.978795; - Matrix3d v2; v2 << -0.277970, 0.953559, 0.116010, -0.567497, -0.065576, -0.820760, -0.775035, -0.293982, 0.559370; - Matrix3d v3; v3 << -0.32657, -0.60013, -0.73020, -0.20022, -0.71110, 0.67398, -0.92372, 0.36630, 0.11207; + */ + + v1(0,0) = -0.588443; + v1(0,1) = 0.807140; + v1(0,2) = -0.047542; + v1(1,0) = -0.786228; + v1(1,1) = -0.584933; + v1(1,2) = -0.199246; + v1(2,0) = -0.188629; + v1(2,1) = -0.079867; + v1(2,2) = 0.978795; + + v2(0,0) = -0.277970; + v2(0,1) = 0.953559; + v2(0,2) = 0.116010; + v2(1,0) = -0.567497; + v2(1,1) = -0.065576; + v2(1,2) = -0.820760; + v2(2,0) = -0.775035; + v2(2,1) = -0.293982; + v2(2,2) = 0.559370; + + v3(0,0) = -0.32657; + v3(0,1) = -0.60013; + v3(0,2) = -0.73020; + v3(1,0) = -0.20022; + v3(1,1) = -0.71110; + v3(1,2) = 0.67398; + v3(2,0) = -0.92372; + v3(2,1) = 0.36630; + v3(2,2) = 0.11207; + simplex[0] = v0; simplex[1] = v1; @@ -121,7 +209,7 @@ void test_nelder_mead() double epsilon = 1e-5; - Matrix3d v0_new = simplex[0]; + CGAL::Eigen_dense_matrix v0_new = simplex[0]; CGAL_assertion(assert_doubles(v0_new(0,0), -0.288975, epsilon)); CGAL_assertion(assert_doubles(v0_new(0,1), 0.7897657, epsilon)); CGAL_assertion(assert_doubles(v0_new(0,2), -0.541076, epsilon)); @@ -132,7 +220,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v0_new(2,1), 0.5111260, epsilon)); CGAL_assertion(assert_doubles(v0_new(2,2), 0.84094, epsilon)); - Matrix3d v1_new = simplex[1]; + CGAL::Eigen_dense_matrix v1_new = simplex[1]; CGAL_assertion(assert_doubles(v1_new(0,0), -0.458749, epsilon)); CGAL_assertion(assert_doubles(v1_new(0,1), 0.823283, epsilon)); CGAL_assertion(assert_doubles(v1_new(0,2), -0.334296, epsilon)); @@ -143,7 +231,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v1_new(2,1), 0.338040, epsilon)); CGAL_assertion(assert_doubles(v1_new(2,2), 0.937987, epsilon)); - Matrix3d v2_new = simplex[2]; + CGAL::Eigen_dense_matrix v2_new = simplex[2]; CGAL_assertion(assert_doubles(v2_new(0,0), -0.346582, epsilon)); CGAL_assertion(assert_doubles(v2_new(0,1), 0.878534, epsilon)); CGAL_assertion(assert_doubles(v2_new(0,2), -0.328724, epsilon)); @@ -154,7 +242,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v2_new(2,1), 0.334057, epsilon)); CGAL_assertion(assert_doubles(v2_new(2,2), 0.941423, epsilon)); - Matrix3d v3_new = simplex[3]; + CGAL::Eigen_dense_matrix v3_new = simplex[3]; CGAL_assertion(assert_doubles(v3_new(0,0), -0.394713, epsilon)); CGAL_assertion(assert_doubles(v3_new(0,1), 0.791782, epsilon)); CGAL_assertion(assert_doubles(v3_new(0,2), -0.466136, epsilon)); @@ -168,11 +256,27 @@ void test_nelder_mead() void test_genetic_algorithm() { - Eigen::Matrix data_points(4, 3); + //Eigen::Matrix data_points(4, 3); + CGAL::Eigen_dense_matrix data_points(4, 3); + /* data_points << 0.866802, 0.740808, 0.895304, 0.912651, 0.761565, 0.160330, 0.093661, 0.892578, 0.737412, 0.166461, 0.149912, 0.364944; + */ + + data_points(0,0) = 0.866802; + data_points(0,1) = 0.740808, + data_points(0,2) = 0.895304, + data_points(1,0) = 0.912651; + data_points(1,1) = 0.761565; + data_points(1,2) = 0.160330; + data_points(2,0) = 0.093661; + data_points(2,1) = 0.892578; + data_points(2,2) = 0.737412; + data_points(3,0) = 0.166461; + data_points(3,1) = 0.149912, + data_points(3,2) = 0.364944; CGAL::Optimal_bounding_box::Population pop(5); CGAL::Optimal_bounding_box::genetic_algorithm(pop, data_points); @@ -181,11 +285,21 @@ void test_genetic_algorithm() void test_random_unit_tetra() { - Eigen::Matrix data_points(4, 3); // points on their convex hull - data_points << 0.866802, 0.740808, 0.895304, - 0.912651, 0.761565, 0.160330, - 0.093661, 0.892578, 0.737412, - 0.166461, 0.149912, 0.364944; + CGAL::Eigen_dense_matrix data_points(4, 3); // points on their convex hull + + data_points(0,0) = 0.866802; + data_points(0,1) = 0.740808, + data_points(0,2) = 0.895304, + data_points(1,0) = 0.912651; + data_points(1,1) = 0.761565; + data_points(1,2) = 0.160330; + data_points(2,0) = 0.093661; + data_points(2,1) = 0.892578; + data_points(2,2) = 0.737412; + data_points(3,0) = 0.166461; + data_points(3,1) = 0.149912, + data_points(3,2) = 0.364944; + typedef CGAL::Simple_cartesian K; typedef K::Point_3 Point; @@ -205,7 +319,9 @@ void test_random_unit_tetra() out.close(); #endif - Matrix3d R; + //Matrix3d R; // have to sort this out - preallocation + Matrix3d R(3, 3); + std::size_t generations = 10; CGAL::Optimal_bounding_box::evolution(R, data_points, generations); @@ -334,7 +450,7 @@ void test_find_obb(std::string fname) #endif } -void test_find_obb_mesh(std::string fname) +void test_find_obb_mesh(std::string fname) { std::ifstream input(fname); CGAL::Surface_mesh mesh; diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp index 6c158b9e8a8..70b8f765731 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp @@ -136,7 +136,7 @@ void Create_obb_mesh_plugin::gather_mesh_points(std::vector& points) PointPMap pmap = get(CGAL::vertex_point, pmesh); BOOST_FOREACH(vertex_descriptor v, selected_vertices) - points.push_back(get(pmap, v )); + points.push_back(get(pmap, v)); } CGAL_assertion(points.size() >= 3); } diff --git a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h new file mode 100644 index 00000000000..51d776f97ce --- /dev/null +++ b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h @@ -0,0 +1,158 @@ + +//license + +#ifndef CGAL_EIGEN_LINEAR_ALGEBRA_TRAITS_H +#define CGAL_EIGEN_LINEAR_ALGEBRA_TRAITS_H + +#include +#include +#include + + +namespace CGAL { + + +template +class Eigen_dense_matrix +{ + +public: + + typedef Eigen::Matrix EigenType; + typedef Eigen::Vector3d VectorType; + + Eigen_dense_matrix(std::size_t nrows, std::size_t ncols) + : m_matrix(static_cast(nrows), static_cast(ncols)) + { + CGAL_assertion(m_matrix.rows() > 0); + CGAL_assertion(m_matrix.cols() > 0); + } + + Eigen_dense_matrix(int nrows, int ncols) + : m_matrix(nrows, ncols) + { + CGAL_assertion(m_matrix.rows() > 0); + CGAL_assertion(m_matrix.cols() > 0); + } + + Eigen_dense_matrix(const EigenType& eigen_mat) + : m_matrix(eigen_mat) {} + + Eigen_dense_matrix() : m_matrix() {} + + ~Eigen_dense_matrix() {} + + T& operator() (int i_, int j_) + { + return m_matrix(i_, j_); + } + + void set_coef(std::size_t i_, std::size_t j_, T val) + { + int i = static_cast(i_); + int j = static_cast(j_); + CGAL_precondition(i < m_matrix.rows()); + CGAL_precondition(j < m_matrix.cols()); + + m_matrix.coeffRef(i,j) = val; + } + + std::size_t rows() const {return m_matrix.rows();} + std::size_t cols() const {return m_matrix.cols();} + + void resize(int i_, int j_) { m_matrix.resize(i_, j_);} + + const Eigen_dense_matrix row(int i_) const + { + VectorType row = m_matrix.row(i_); + Eigen_dense_matrix r(row); + return r; + } + + const T& coeff(int i_) const + { + return m_matrix.coeff(i_); + } + + const Eigen_dense_matrix transpose() const + { + Eigen_dense_matrix dm(m_matrix.transpose()); + return dm; + //return Eigen_dense_matrix(m_matrix.transpose()); + } + + const double determinant() const + { + return m_matrix.determinant(); + } + + void qr_factorization(Eigen_dense_matrix& Q) + { + Q.resize(m_matrix.rows(), m_matrix.cols()); + Eigen::HouseholderQR qr(m_matrix); + Eigen_dense_matrix qr_mat(qr.householderQ()); + Q = qr_mat; + } + + friend void qr_factorization(std::vector& simplex) + { + for(int i = 0; i < simplex.size(); ++i) + { + Eigen::HouseholderQR qr(simplex[i].m_matrix); + Eigen_dense_matrix Q(qr.householderQ()); + simplex[i] = Q; + } + } + + friend const Eigen_dense_matrix operator* (const Eigen_dense_matrix& A, + const Eigen_dense_matrix& B) + { + const Eigen_dense_matrix product(A.m_matrix * B.m_matrix); + return product; + } + + friend const Eigen_dense_matrix operator* (const T& scalar, + const Eigen_dense_matrix& B) + { + const Eigen_dense_matrix product(scalar * B.m_matrix); + return product; + } + + friend const Eigen_dense_matrix operator+ (const Eigen_dense_matrix& A, + const Eigen_dense_matrix& B) + { + const Eigen_dense_matrix sum_result(A.m_matrix + B.m_matrix); + return sum_result; + } + + friend const Eigen_dense_matrix operator/ (const Eigen_dense_matrix& A, + const double& scalar) + { + const Eigen_dense_matrix product(A.m_matrix / scalar); + return product; + } + + friend const Eigen_dense_matrix operator/ (const double& scalar , + const Eigen_dense_matrix& A) + { + const Eigen_dense_matrix product(scalar / A.m_matrix); + return product; + } + + + +private: + mutable EigenType m_matrix; +}; + + + + + + + +} // end namespace + + + +#endif // CGAL_EIGEN_LINEAR_ALGEBRA_TRAITS_H From 5380ebac1b0414a626321c15bfc318879fcaad5e Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Mon, 14 May 2018 16:06:52 +0200 Subject: [PATCH 024/150] eigen linear algebra traits --- .../CGAL/Optimal_bounding_box/evolution.h | 375 ++++++++++++++++++ .../Optimal_bounding_box/fitness_function.h | 25 +- .../include/CGAL/Optimal_bounding_box/obb.h | 94 ++++- .../optimization_algorithms.h | 22 +- .../test_linear_algebra_functions.cpp | 79 ++-- .../test_optimization_algorithms.cpp | 207 +++++----- .../CGAL/Eigen_linear_algebra_traits.h | 92 ++++- 7 files changed, 701 insertions(+), 193 deletions(-) create mode 100644 Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h new file mode 100644 index 00000000000..fe672b5ffb2 --- /dev/null +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -0,0 +1,375 @@ +// Copyright (c) 2018 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Konstantinos Katrioplas + + +#ifndef CGAL_EVOLUTION_H +#define CGAL_EVOLUTION_H + +#include +#include + + +namespace CGAL { +namespace Optimal_bounding_box { + + +template +class Evolution +{ + + typedef typename Linear_algebra_traits::MatrixXd MatrixXd; + typedef typename Linear_algebra_traits::Matrix3d Matrix3d; + typedef typename Linear_algebra_traits::Vector3d Vector3d; + +public: + Evolution(Population& pop, MatrixXd& points) : + population(pop), + point_data(points) + {} + + // simplex: 4 rotation matrices are its vertices + void nelder_mead(std::vector& simplex, std::size_t nelder_mead_iterations) + { + CGAL_assertion(simplex.size() == 4); // tetrahedron + + std::vector fitness(4); + std::vector indices( boost::counting_iterator( 0 ), + boost::counting_iterator( simplex.size() ) ); + + for(std::size_t t = 0; t < nelder_mead_iterations; ++t) + { + for(std::size_t i = 0; i < 4; ++i) + { + fitness[i] = compute_fitness(simplex[i], point_data); + } + + CGAL_assertion(fitness.size() == 4); + CGAL_assertion(indices.size() == 4); + + // get indices of sorted sequence + Comparator compare_indices(fitness); + std::sort(indices.begin(), indices.end(), compare_indices); + + // new sorted simplex & fitness + std::vector s_simplex(4); + std::vector s_fitness(4); + for(int i = 0; i < 4; ++i) + { + s_simplex[i] = simplex[indices[i]]; + s_fitness[i] = fitness[indices[i]]; + } + + simplex = s_simplex; + fitness = s_fitness; + + // centroid + const Matrix3d v_centroid = centroid(simplex[0], simplex[1], simplex[2]); + + // find worst's vertex reflection + const Matrix3d v_worst = simplex[3]; + const Matrix3d v_refl = reflection(v_centroid, v_worst); + const double f_refl = compute_fitness(v_refl, point_data); + + if(f_refl < fitness[2]) + { + if(f_refl >= fitness[0]) // if reflected point is not better than the best + { + // do reflection + simplex[3] = v_refl; + } + else + { + // expansion + const Matrix3d v_expand = expansion(v_centroid, v_worst, v_refl); + const double f_expand = compute_fitness(v_expand, point_data); + if(f_expand < f_refl) + simplex[3] = v_expand; + else + simplex[3] = v_refl; + } + } + else // if reflected vertex is not better + { + const Matrix3d v_mean = mean(v_centroid, v_worst); + const double f_mean = compute_fitness(v_mean, point_data); + if(f_mean <= fitness[3]) + // contraction of worst + simplex[3] = v_mean; + else + { + // reduction: move all vertices towards the best + for(std::size_t i=1; i < 4; ++i) + { + simplex[i] = mean(simplex[i], simplex[0]); + } + } + } + + CGAL_assertion(simplex.size() == 4); // tetrahedron + + } // iterations + } + + + void genetic_algorithm() + { + // random permutations + std::size_t m = population.size(); + + //groups 1,2 : size m/2 groups 3,4 : size (m - m/2). m/2 is floored + std::size_t size_first_group = m/2; + std::size_t size_second_group = m - m/2; + + std::vector ids1(m/2), ids2(m/2); + std::vector ids3(m - m/2), ids4(m - m/2); + + CGAL::Random rng; + std::generate(ids1.begin(), ids1.end(), + [&rng, &m] () { return rng.get_int(0, m); }); + std::generate(ids2.begin(), ids2.end(), + [&rng, &m] () { return rng.get_int(0, m); }); + std::generate(ids3.begin(), ids3.end(), + [&rng, &m] () { return rng.get_int(0, m); }); + std::generate(ids4.begin(), ids4.end(), + [&rng, &m] () { return rng.get_int(0, m); }); + + Population group1(m/2), group2(m/2); + Population group3(m - m/2), group4(m - m/2); + + for(std::size_t i = 0; i < ids1.size(); ++i) + group1[i] = population[ids1[i]]; + + for(std::size_t i = 0; i < ids2.size(); ++i) + group2[i] = population[ids2[i]]; + + for(std::size_t i = 0; i < ids3.size(); ++i) + group3[i] = population[ids3[i]]; + + for(std::size_t i = 0; i < ids4.size(); ++i) + group4[i] = population[ids4[i]]; + + #ifdef OBB_DEBUG + check_det(group1); + check_det(group2); + check_det(group3); + check_det(group4); + #endif + + // crossover I + Population offspringsA(size_first_group); + double bias = 0.1; + + for(int i = 0; i < size_first_group; ++i) + { + std::vector offspring(4); + for(int j = 0; j < 4; ++j) + { + double r = rng.get_double(); + double fitnessA = compute_fitness(group1[i][j], point_data); + double fitnessB = compute_fitness(group2[i][j], point_data); + double threshold; + if(fitnessA < fitnessB) + threshold = 0.5 + bias; + else + threshold = 0.5 - bias; + if(r < threshold) // choose A + offspring[j] = group1[i][j]; + else // choose B + offspring[j] = group2[i][j]; + } + offspringsA[i] = offspring; + } + + #ifdef OBB_DEBUG + std::cout << "offspringsA: \n" ; + check_det(offspringsA); + std::cin.get(); + #endif + + // crossover II + Population offspringsB(size_second_group); + bias = 0.1; + + for(int i = 0; i < size_second_group; ++i) + { + std::vector offspring(4); + for(int j = 0; j < 4; ++j) + { + double fitnessA = compute_fitness(group3[i][j], point_data); + double fitnessB = compute_fitness(group4[i][j], point_data); + double lambda; + if(fitnessA < fitnessB) + lambda = 0.5 + bias; + else + lambda = 0.5 - bias; + // combine information from A and B + offspring[j] = lambda * group3[i][j] + lambda * group4[i][j]; + + } + + // qr factorization of the offspring + qr_factorization(offspring); + + + offspringsB[i] = offspring; + } + + #ifdef OBB_DEBUG + std::cout << "offspringsB: \n" ; + check_det(offspringsB); + #endif + + CGAL_assertion(offspringsA.size() == size_first_group); + CGAL_assertion(offspringsB.size() == size_second_group); + CGAL_assertion(offspringsA.size() + offspringsB.size() == population.size()); + + // next generatrion + for(std::size_t i = 0; i < size_first_group; ++i) + { + population[i] = offspringsA[i]; + } + + for(std::size_t i = 0; i < size_second_group; ++i) + { + population[size_first_group + i] = offspringsB[i]; + } + } + + + void evolve(std::size_t generations) + { + + // hardcoded nelder_mead_iterations + std::size_t nelder_mead_iterations = 20; + + // stopping criteria prameters + double prev_fit_value = 0; + double new_fit_value = 0; + double tolerance = 1e-2; + int stale = 0; + + // evolve here + for(std::size_t t = 0; t < generations; ++t) + { + + #ifdef OBB_DEBUG + std::cout << "generation= " << t << "\n"; + #endif + + genetic_algorithm(); + + #ifdef OBB_DEBUG + //std::cout << "pop after genetic" << std::endl; + //pop.show_population(); + //std::cout << std::endl; + #endif + + for(std::size_t s = 0; s < population.size(); ++s) + nelder_mead(population[s], nelder_mead_iterations); + + #ifdef OBB_DEBUG + //std::cout << "pop after nelder mead: " << std::endl; + //pop.show_population(); + //std::cout << std::endl; + + // debugging + Fitness_map fitness_map(pop, point_data); + Matrix R_now = fitness_map.get_best(); + std::cout << "det= " << R_now.determinant() << std::endl; + #endif + + // stopping criteria + Fitness_map fitness_map(population, point_data); + new_fit_value = fitness_map.get_best_fitness_value(point_data); + + double difference = new_fit_value - prev_fit_value; + if(abs(difference) < tolerance * new_fit_value) + stale++; + + if(stale == 5) + break; + + prev_fit_value = new_fit_value; + } + } + + const Matrix3d get_best() // reference ?? + { + Fitness_map fitness_map(population, point_data); + return fitness_map.get_best(); + } + + +private: + + // needed in genetic algorithm + struct Comparator + { + Comparator(std::vector in) : fitness(in) {} + + inline bool operator() (std::size_t& i, std::size_t& j) + { + return fitness[i] < fitness[j]; + } + + std::vector fitness; + }; + + + + // data + Population population; + MatrixXd point_data; + + +}; + + +#ifdef OBB_DEBUG +template +void check_det(Population& pop) +{ + for(int i = 0; i < pop.size(); ++i) + { + for(int j = 0; j < 4; ++j) + { + auto A = pop[i][j]; // Simplex + std::cout << A.determinant() << std::endl; + } + } +} +#endif + + + +}} // end namespaces + + + + + + + + + + + +#endif diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 0c214432083..5c75819ad43 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -27,11 +27,14 @@ #include #include +#include + namespace CGAL { namespace Optimal_bounding_box { -template -const double compute_fitness(const Vertex& R, const Matrix& data) +template +const double compute_fitness(const typename Linear_algebra_traits::Matrix3d& R, + typename Linear_algebra_traits::MatrixXd& data) { // R: rotation matrix CGAL_assertion(R.cols() == 3); @@ -40,10 +43,12 @@ const double compute_fitness(const Vertex& R, const Matrix& data) CGAL_assertion(data.cols() == 3); CGAL_assertion(data.rows() >= 3); + typedef typename Linear_algebra_traits::Vector3d Vector3d; + double xmin, xmax, ymin, ymax, zmin, zmax; for(int i = 0; i < data.rows(); i++){ - Matrix vec = data.row(i); + Vector3d vec = data.row(i); vec = R * vec; if(i == 0){ @@ -59,7 +64,7 @@ const double compute_fitness(const Vertex& R, const Matrix& data) if(vec.coeff(2) > zmax) zmax = vec.coeff(2); } } - + CGAL_assertion(xmax > xmin); CGAL_assertion(ymax > ymin); CGAL_assertion(zmax > zmin); @@ -71,6 +76,8 @@ const double compute_fitness(const Vertex& R, const Matrix& data) template struct Fitness_map { + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; // to be added as a parameter + Fitness_map(Population& p, Matrix& points) : pop(p), points(points) {} @@ -83,7 +90,7 @@ struct Fitness_map for(std::size_t j =0; j < 4; ++j) { const Vertex vertex = pop[i][j]; - const double fitness = compute_fitness(vertex, points); + const double fitness = compute_fitness(vertex, points); if (fitness < best_fitness) { simplex_id = i; @@ -96,13 +103,13 @@ struct Fitness_map return pop[simplex_id][vertex_id]; } - const double get_best_fitness_value(const Matrix& data) + const double get_best_fitness_value(Matrix& data) { - Vertex best_mat = get_best(); - return compute_fitness(best_mat, data); + const Vertex best_mat = get_best(); + return compute_fitness(best_mat, data); } - const Matrix& points; + Matrix& points; Population& pop; }; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index 870b122f621..ad12d735b3b 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -34,9 +35,9 @@ #include #include -//#include +#if defined(CGAL_EIGEN3_ENABLED) #include - +#endif namespace CGAL { namespace Optimal_bounding_box { @@ -107,7 +108,7 @@ void evolution(Vertex& R, Matrix& points, std::size_t max_generations) // todo: // works on matrices only template -void post_processing(Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) +void post_processing(const Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) { CGAL_assertion(points.cols() == 3); CGAL_assertion(R.rows() == 3); @@ -157,6 +158,8 @@ void post_processing(Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) obb = aabb * R; } + +// to be moved into a helper template void fill_matrix(std::vector& v_points, Matrix& points_mat) { @@ -177,11 +180,8 @@ void fill_matrix(std::vector& v_points, Matrix& points_mat) } } -/// @param points point coordinates of the input mesh. -/// @param obb_points the 8 points of the obb. -/// @param use convex hull or not. -/// -/// todo named parameters: max iterations, population size, tolerance. + +// with linear algebra traits template void find_obb(std::vector& points, std::vector& obb_points, bool use_ch) { @@ -191,13 +191,73 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u obb_points.resize(8); CGAL_assertion(obb_points.size() == 8); - // using eigen internally - //typedef Eigen::MatrixXd MatrixXd; // for point data - //typedef Eigen::Matrix3d Matrix3d; // for matrices in simplices + // could be used from a t. parameter + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + typedef typename Linear_algebra_traits::MatrixXd MatrixXd; + typedef typename Linear_algebra_traits::Matrix3d Matrix3d; - // todo: sort out typedefs - typedef CGAL::Eigen_dense_matrix MatrixXd; // for point data - typedef CGAL::Eigen_dense_matrix Matrix3d; // for matrices in simplices + MatrixXd points_mat; + + // get the ch3 + if(use_ch) + { + // find the ch - todo: template kernel + typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; + CGAL::Polyhedron_3 poly; + convex_hull_3(points.begin(), points.end(), poly); + std::vector ch_points(poly.points_begin(), poly.points_end()); + + // points: vector -> matrix + fill_matrix(ch_points, points_mat); + } + else + { + // points: vector -> matrix + fill_matrix(points, points_mat); + } + + std::size_t max_generations = 100; + Population pop(50); + CGAL::Optimal_bounding_box::Evolution + search_solution(pop, points_mat); + search_solution.evolve(max_generations); + Matrix3d rotation = search_solution.get_best(); + + MatrixXd obb; // could be preallocated at compile time + obb.resize(8, 3); + + post_processing(points_mat, rotation, obb); + + // matrix -> vector + for(std::size_t i = 0; i < 8; ++i) + { + Point p(obb(i, 0), obb(i, 1), obb(i, 2)); + obb_points[i] = p; + } + +} + + +/* + //USES ::EVOLUTION + +/// @param points point coordinates of the input mesh. +/// @param obb_points the 8 points of the obb. +/// @param use convex hull or not. +/// +/// todo named parameters: max iterations, population size, tolerance. +template +void find_obb(std::vector& points, std::vector& obb_points, bool use_ch, bool use_eigen) +{ + CGAL_assertion(points.size() >= 3); + + if(obb_points.size() != 8) // temp sanity until the API is decided + obb_points.resize(8); + CGAL_assertion(obb_points.size() == 8); + + // using eigen internally + typedef Eigen::MatrixXd MatrixXd; // for point data + typedef Eigen::Matrix3d Matrix3d; // for matrices in simplices MatrixXd points_mat; @@ -226,7 +286,7 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u //Eigen::Matrix obb; - CGAL::Eigen_dense_matrix obb; // compile time preallocation?? + MatrixXd obb; // compile time preallocation?? obb.resize(8, 3); CGAL::Optimal_bounding_box::post_processing(points_mat, R, obb); @@ -240,13 +300,15 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u } } +*/ + /// @param pmesh the input mesh. /// @param obbmesh the obb in a hexahedron pmesh. /// @param use convex hull or not. /// /// todo named parameters: max iterations, population size, tolerance. template -void find_obb(PolygonMesh& pmesh , PolygonMesh& obbmesh, bool use_ch) +void find_obb(PolygonMesh& pmesh, PolygonMesh& obbmesh, bool use_ch) { CGAL_assertion(vertices(pmesh).size() >= 3); diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h index 598d75c6192..2466ebeb657 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h @@ -36,7 +36,7 @@ namespace CGAL { namespace Optimal_bounding_box { - +/* struct Comparator { Comparator(std::vector in) : fitness(in) {} @@ -52,7 +52,7 @@ struct Comparator // points: point coords // simplex: 4 rotation matrices are its vertices template -void nelder_mead(std::vector& simplex, const Matrix& points, std::size_t nb_iterations) +void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_iterations) { CGAL_assertion(simplex.size() == 4); // tetrahedron @@ -65,7 +65,7 @@ void nelder_mead(std::vector& simplex, const Matrix& points, std::size_t { for(std::size_t i = 0; i < 4; ++i) { - fitness[i] = compute_fitness(simplex[i], points); + fitness[i] = compute_fitness_old(simplex[i], points); } CGAL_assertion(fitness.size() == 4); @@ -93,7 +93,7 @@ void nelder_mead(std::vector& simplex, const Matrix& points, std::size_t // find worst's vertex reflection const Vertex v_worst = simplex[3]; const Vertex v_refl = reflection(v_centroid, v_worst); - const double f_refl = compute_fitness(v_refl, points); + const double f_refl = compute_fitness_old(v_refl, points); if(f_refl < fitness[2]) { @@ -106,7 +106,7 @@ void nelder_mead(std::vector& simplex, const Matrix& points, std::size_t { // expansion const Vertex v_expand = expansion(v_centroid, v_worst, v_refl); - const double f_expand = compute_fitness(v_expand, points); + const double f_expand = compute_fitness_old(v_expand, points); if(f_expand < f_refl) simplex[3] = v_expand; else @@ -116,7 +116,7 @@ void nelder_mead(std::vector& simplex, const Matrix& points, std::size_t else // if reflected vertex is not better { const Vertex v_mean = mean(v_centroid, v_worst); - const double f_mean = compute_fitness(v_mean, points); + const double f_mean = compute_fitness_old(v_mean, points); if(f_mean <= fitness[3]) // contraction of worst simplex[3] = v_mean; @@ -216,8 +216,8 @@ void genetic_algorithm(Population& pop, const Matrix& points) for(int j = 0; j < 4; ++j) { double r = rng.get_double(); - double fitnessA = compute_fitness(group1[i][j], points); - double fitnessB = compute_fitness(group2[i][j], points); + double fitnessA = compute_fitness_old(group1[i][j], points); + double fitnessB = compute_fitness_old(group2[i][j], points); double threshold; if(fitnessA < fitnessB) threshold = 0.5 + bias; @@ -246,8 +246,8 @@ void genetic_algorithm(Population& pop, const Matrix& points) std::vector offspring(4); for(int j = 0; j < 4; ++j) { - double fitnessA = compute_fitness(group3[i][j], points); - double fitnessB = compute_fitness(group4[i][j], points); + double fitnessA = compute_fitness_old(group3[i][j], points); + double fitnessB = compute_fitness_old(group4[i][j], points); double lambda; if(fitnessA < fitnessB) lambda = 0.5 + bias; @@ -286,6 +286,7 @@ void genetic_algorithm(Population& pop, const Matrix& points) } } +*/ #ifdef OBB_DEBUG template @@ -302,6 +303,7 @@ void check_det(Population& pop) } #endif + } } // end namespaces diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index 7565df7e56f..291f377ea16 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include @@ -16,7 +15,7 @@ bool assert_doubles(double d1, double d2, double epsilon) void test_qr_factorization() { - CGAL::Eigen_dense_matrix A(3, 3); + CGAL::Eigen_dense_matrix A(3, 3); /* A << 0.3011944, 0.9932761, 0.5483701, 0.5149142, 0.5973263, 0.5162336, @@ -33,9 +32,9 @@ void test_qr_factorization() A.set_coef(2, 1, 0.0202949); A.set_coef(2, 2, 0.9240308); - CGAL::Eigen_dense_matrix Q; - //CGAL::Optimal_bounding_box::qr_factorization(A, Q); + CGAL::Eigen_dense_matrix Q; + //CGAL::Optimal_bounding_box::qr_factorization(A, Q); A.qr_factorization(Q); @@ -54,15 +53,9 @@ void test_qr_factorization() void test_fitness_function() { - //Eigen::Matrix data_points(4, 3); - CGAL::Eigen_dense_matrix data_points(4, 3); - /* - data_points << 0.866802, 0.740808, 0.895304, - 0.912651, 0.761565, 0.160330, - 0.093661, 0.892578, 0.737412, - 0.166461, 0.149912, 0.364944; - */ + typedef typename CGAL::Eigen_linear_algebra_traits::MatrixXd MatrixXd; + MatrixXd data_points(4, 3); data_points.set_coef(0, 0, 0.866802); data_points.set_coef(0, 1, 0.740808); @@ -81,16 +74,8 @@ void test_fitness_function() data_points.set_coef(3, 2, 0.364944); - - //Matrix3d rotation(3, 3); - CGAL::Eigen_dense_matrix rotation(3, 3); - /* - rotation << -0.809204, 0.124296, 0.574230, - -0.574694, 0.035719, -0.817589, - -0.122134, -0.991602, 0.042528; - */ - - + typedef typename CGAL::Eigen_linear_algebra_traits::Matrix3d Matrix3d; + Matrix3d rotation; rotation.set_coef(0, 0, -0.809204); rotation.set_coef(0, 1, 0.124296); rotation.set_coef(0, 2, 0.574230); @@ -101,15 +86,16 @@ void test_fitness_function() rotation.set_coef(2, 1, -0.991602); rotation.set_coef(2, 2, 0.042528); - double fitness = CGAL::Optimal_bounding_box::compute_fitness(rotation, data_points); - CGAL_assertion(assert_doubles(fitness, 0.58606, 1e-5)); + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + double fitness = CGAL::Optimal_bounding_box::compute_fitness (rotation, data_points); + CGAL_assertion(assert_doubles(fitness, 0.58606, 1e-5)); } void test_simplex_operations() { //Matrix3d Sc(3, 3); - CGAL::Eigen_dense_matrix Sc(3, 3); + CGAL::Eigen_dense_matrix Sc(3, 3); /* Sc << -0.809204, 0.124296, 0.574230, -0.574694, 0.035719, -0.817589, @@ -128,7 +114,7 @@ void test_simplex_operations() - CGAL::Eigen_dense_matrix S_worst(3, 3); + CGAL::Eigen_dense_matrix S_worst(3, 3); /* S_worst << -0.45070, -0.32769, -0.83035, -0.13619, -0.89406, 0.42675, @@ -147,7 +133,7 @@ void test_simplex_operations() S_worst.set_coef(2, 2, 0.35833); - CGAL::Eigen_dense_matrix Sr = CGAL::Optimal_bounding_box::reflection(Sc, S_worst); + CGAL::Eigen_dense_matrix Sr = CGAL::Optimal_bounding_box::reflection(Sc, S_worst); double epsilon = 1e-5; CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); @@ -159,7 +145,7 @@ void test_simplex_operations() CGAL_assertion(assert_doubles(Sr(2,1), 0.25411, epsilon)); CGAL_assertion(assert_doubles(Sr(2,2), -0.56300, epsilon)); - CGAL::Eigen_dense_matrix Se = CGAL::Optimal_bounding_box::expansion(Sc, S_worst, Sr); + CGAL::Eigen_dense_matrix Se = CGAL::Optimal_bounding_box::expansion(Sc, S_worst, Sr); CGAL_assertion(assert_doubles(Se(0,0), -0.87991, epsilon)); CGAL_assertion(assert_doubles(Se(0,1), 0.36105, epsilon)); CGAL_assertion(assert_doubles(Se(0,2), -0.30888, epsilon)); @@ -170,7 +156,7 @@ void test_simplex_operations() CGAL_assertion(assert_doubles(Se(2,1), -0.48595, epsilon)); CGAL_assertion(assert_doubles(Se(2,2), 0.74300, epsilon)); - CGAL::Eigen_dense_matrix S_a(3, 3); + CGAL::Eigen_dense_matrix S_a(3, 3); /* S_a << -0.277970, 0.953559, 0.116010, -0.567497, -0.065576, -0.820760, @@ -189,7 +175,7 @@ void test_simplex_operations() S_a.set_coef(2, 2, 0.559370); - CGAL::Eigen_dense_matrix S_b(3, 3); + CGAL::Eigen_dense_matrix S_b(3, 3); /* S_b << -0.419979, 0.301765, -0.855894, -0.653011, -0.755415, 0.054087, @@ -208,7 +194,7 @@ void test_simplex_operations() S_b.set_coef(2, 2, 0.514314); - CGAL::Eigen_dense_matrix S_c = CGAL::Optimal_bounding_box::mean(S_a, S_b); + CGAL::Eigen_dense_matrix S_c = CGAL::Optimal_bounding_box::mean(S_a, S_b); CGAL_assertion(assert_doubles(S_c(0,0), -0.35111, epsilon)); CGAL_assertion(assert_doubles(S_c(0,1), 0.79308, epsilon)); CGAL_assertion(assert_doubles(S_c(0,2), -0.49774, epsilon)); @@ -222,7 +208,7 @@ void test_simplex_operations() void test_centroid() { - CGAL::Eigen_dense_matrix S_a(3, 3); + CGAL::Eigen_dense_matrix S_a; /* S_a << -0.588443, 0.807140, -0.047542, -0.786228, -0.584933, -0.199246, @@ -239,7 +225,7 @@ void test_centroid() S_a.set_coef(2, 1, -0.079867); S_a.set_coef(2, 2, 0.978795); - CGAL::Eigen_dense_matrix S_b(3, 3); + CGAL::Eigen_dense_matrix S_b(3, 3); /* S_b << -0.2192721, 0.2792986, -0.9348326, -0.7772152, -0.6292092, -0.0056861, @@ -256,7 +242,7 @@ void test_centroid() S_b.set_coef(2, 1, 0.7253193); S_b.set_coef(2, 2, 0.3550431); - CGAL::Eigen_dense_matrix S_c(3, 3); + CGAL::Eigen_dense_matrix S_c(3, 3); /* S_c << -0.32657, -0.60013, -0.73020, -0.20022, -0.71110, 0.67398, @@ -273,10 +259,8 @@ void test_centroid() S_c.set_coef(2, 1, 0.36630); S_c.set_coef(2, 2, 0.11207); - - - - CGAL::Eigen_dense_matrix S_centroid = CGAL::Optimal_bounding_box::centroid(S_a, S_b, S_c); + CGAL::Eigen_dense_matrix S_centroid = + CGAL::Optimal_bounding_box::centroid(S_a, S_b, S_c); double epsilon = 1e-5; CGAL_assertion(assert_doubles(S_centroid(0,0), -0.419979, epsilon)); CGAL_assertion(assert_doubles(S_centroid(0,1), 0.301765, epsilon)); @@ -292,7 +276,7 @@ void test_centroid() void test_eigen_matrix_interface() { - CGAL::Eigen_dense_matrix A(3, 3); + CGAL::Eigen_dense_matrix A(3, 3); A.set_coef(0, 0, 0.1); A.set_coef(0, 1, 0.2); A.set_coef(0, 2, 0.3); @@ -302,11 +286,11 @@ void test_eigen_matrix_interface() A.set_coef(2, 0, 0.7); A.set_coef(2, 1, 0.8); A.set_coef(2, 2, 0.9); - CGAL::Eigen_dense_matrix B = A.transpose(); + CGAL::Eigen_dense_matrix B = A.transpose(); - CGAL::Eigen_dense_matrix S = 0.5 * A; + CGAL::Eigen_dense_matrix S = 0.5 * A; - CGAL::Eigen_dense_matrix C(3,3); + CGAL::Eigen_dense_matrix C(3,3); C.set_coef(0, 0, 0.3011944); C.set_coef(0, 1, 0.9932761); C.set_coef(0, 2, 0.5483701); @@ -317,7 +301,7 @@ void test_eigen_matrix_interface() C.set_coef(2, 1, 0.0202949); C.set_coef(2, 2, 0.9240308); - CGAL::Eigen_dense_matrix Q(3,3); + CGAL::Eigen_dense_matrix Q(3,3); C.qr_factorization(Q); double epsilon = 1e-5; @@ -331,7 +315,7 @@ void test_eigen_matrix_interface() CGAL_assertion(assert_doubles(Q(2,1), 0.024478, epsilon)); CGAL_assertion(assert_doubles(Q(2,2), 0.999679, epsilon)); - CGAL::Eigen_dense_matrix D(3,3); + CGAL::Eigen_dense_matrix D(3,3); D.set_coef(0, 0, -0.809204); D.set_coef(0, 1, 0.124296); D.set_coef(0, 2, 0.574230); @@ -342,7 +326,7 @@ void test_eigen_matrix_interface() D.set_coef(2, 1, -0.991602); D.set_coef(2, 2, 0.042528); - CGAL::Eigen_dense_matrix E(3,3); + CGAL::Eigen_dense_matrix E(3,3); E.set_coef(0, 0, -0.45070); E.set_coef(0, 1, -0.32769); E.set_coef(0, 2, -0.83035); @@ -353,7 +337,7 @@ void test_eigen_matrix_interface() E.set_coef(2, 1, 0.30543); E.set_coef(2, 2, 0.35833); - CGAL::Eigen_dense_matrix Sr = CGAL::Optimal_bounding_box::reflection(D, E); + CGAL::Eigen_dense_matrix Sr = CGAL::Optimal_bounding_box::reflection(D, E); CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); CGAL_assertion(assert_doubles(Sr(0,2), -0.24664, epsilon)); @@ -367,11 +351,10 @@ void test_eigen_matrix_interface() int main() { + test_qr_factorization(); test_fitness_function(); - test_simplex_operations(); - test_centroid(); test_eigen_matrix_interface(); diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 8515ee37534..a7ed6864373 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -6,19 +6,11 @@ #include #include -#include #include -//typedef Eigen::MatrixXd MatrixXd; -//typedef Eigen::Matrix3d Matrix3d; - -// todo: sort this out -typedef CGAL::Eigen_dense_matrix MatrixXd; -typedef CGAL::Eigen_dense_matrix Matrix3d; typedef CGAL::Exact_predicates_inexact_constructions_kernel K; - bool assert_doubles(double d1, double d2, double epsilon) { return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; @@ -37,16 +29,9 @@ void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) for(vertex_descriptor v : vertices(sm)) { Point_ref p = get(vpm, v); - /* - mat.coeffRef(i, 0) = p.x(); - mat.coeffRef(i, 1) = p.y(); - mat.coeffRef(i, 2) = p.z(); - */ - mat.set_coef(i, 0, p.x()); mat.set_coef(i, 1, p.y()); mat.set_coef(i, 2, p.z()); - ++i; } } @@ -86,26 +71,14 @@ double calculate_volume(std::vector points) return ic.volume(); } -void test_population() -{ - CGAL::Optimal_bounding_box::Population pop(5); - //pop.show_population(); - CGAL_assertion(pop.size() == 5); -} void test_nelder_mead() { - //Eigen::Matrix data_points(4, 3); - - CGAL::Eigen_dense_matrix data_points(4,3); - - /* - data_points << 0.866802, 0.740808, 0.895304, - 0.912651, 0.761565, 0.160330, - 0.093661, 0.892578, 0.737412, - 0.166461, 0.149912, 0.364944; - */ + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + typedef Linear_algebra_traits::Matrix3d Matrix3d; + typedef Linear_algebra_traits::MatrixXd MatrixXd; + MatrixXd data_points(4,3); data_points(0,0) = 0.866802; data_points(0,1) = 0.740808, data_points(0,2) = 0.895304, @@ -120,20 +93,13 @@ void test_nelder_mead() data_points(3,2) = 0.364944; // one simplex - //std::vector simplex(4); - std::vector> simplex(4); + std::vector simplex(4); + Matrix3d v0(3,3); + Matrix3d v1(3,3); + Matrix3d v2(3,3); + Matrix3d v3(3,3); - - //Matrix3d v0; - CGAL::Eigen_dense_matrix v0(3,3); - - /* - v0 << -0.2192721, 0.2792986, -0.9348326, - -0.7772152, -0.6292092, -0.0056861, - -0.5897934, 0.7253193, 0.3550431; - */ - v0(0,0) = -0.2192721; v0(0,1) = 0.2792986, v0(0,2) = -0.9348326, @@ -144,30 +110,6 @@ void test_nelder_mead() v0(2,1) = 0.7253193; v0(2,2) = 0.3550431; - - //Matrix3d v1; - //Matrix3d v2; - //Matrix3d v3; - - CGAL::Eigen_dense_matrix v1(3,3); - CGAL::Eigen_dense_matrix v2(3,3); - CGAL::Eigen_dense_matrix v3(3,3); - - - /* - v1 << -0.588443, 0.807140, -0.047542, - -0.786228, -0.584933, -0.199246, - -0.188629, -0.079867, 0.978795; - - v2 << -0.277970, 0.953559, 0.116010, - -0.567497, -0.065576, -0.820760, - -0.775035, -0.293982, 0.559370; - - v3 << -0.32657, -0.60013, -0.73020, - -0.20022, -0.71110, 0.67398, - -0.92372, 0.36630, 0.11207; - */ - v1(0,0) = -0.588443; v1(0,1) = 0.807140; v1(0,2) = -0.047542; @@ -198,18 +140,20 @@ void test_nelder_mead() v3(2,1) = 0.36630; v3(2,2) = 0.11207; - simplex[0] = v0; simplex[1] = v1; simplex[2] = v2; simplex[3] = v3; - std::size_t iterations = 19; - CGAL::Optimal_bounding_box::nelder_mead(simplex, data_points, iterations); + CGAL::Optimal_bounding_box::Population pop(1); + std::size_t nm_iterations = 19; + + CGAL::Optimal_bounding_box::Evolution + evolution(pop, data_points); + evolution.nelder_mead(simplex, nm_iterations); double epsilon = 1e-5; - - CGAL::Eigen_dense_matrix v0_new = simplex[0]; + Matrix3d v0_new = simplex[0]; CGAL_assertion(assert_doubles(v0_new(0,0), -0.288975, epsilon)); CGAL_assertion(assert_doubles(v0_new(0,1), 0.7897657, epsilon)); CGAL_assertion(assert_doubles(v0_new(0,2), -0.541076, epsilon)); @@ -220,7 +164,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v0_new(2,1), 0.5111260, epsilon)); CGAL_assertion(assert_doubles(v0_new(2,2), 0.84094, epsilon)); - CGAL::Eigen_dense_matrix v1_new = simplex[1]; + Matrix3d v1_new = simplex[1]; CGAL_assertion(assert_doubles(v1_new(0,0), -0.458749, epsilon)); CGAL_assertion(assert_doubles(v1_new(0,1), 0.823283, epsilon)); CGAL_assertion(assert_doubles(v1_new(0,2), -0.334296, epsilon)); @@ -231,7 +175,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v1_new(2,1), 0.338040, epsilon)); CGAL_assertion(assert_doubles(v1_new(2,2), 0.937987, epsilon)); - CGAL::Eigen_dense_matrix v2_new = simplex[2]; + Matrix3d v2_new = simplex[2]; CGAL_assertion(assert_doubles(v2_new(0,0), -0.346582, epsilon)); CGAL_assertion(assert_doubles(v2_new(0,1), 0.878534, epsilon)); CGAL_assertion(assert_doubles(v2_new(0,2), -0.328724, epsilon)); @@ -242,7 +186,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v2_new(2,1), 0.334057, epsilon)); CGAL_assertion(assert_doubles(v2_new(2,2), 0.941423, epsilon)); - CGAL::Eigen_dense_matrix v3_new = simplex[3]; + Matrix3d v3_new = simplex[3]; CGAL_assertion(assert_doubles(v3_new(0,0), -0.394713, epsilon)); CGAL_assertion(assert_doubles(v3_new(0,1), 0.791782, epsilon)); CGAL_assertion(assert_doubles(v3_new(0,2), -0.466136, epsilon)); @@ -256,15 +200,7 @@ void test_nelder_mead() void test_genetic_algorithm() { - //Eigen::Matrix data_points(4, 3); CGAL::Eigen_dense_matrix data_points(4, 3); - /* - data_points << 0.866802, 0.740808, 0.895304, - 0.912651, 0.761565, 0.160330, - 0.093661, 0.892578, 0.737412, - 0.166461, 0.149912, 0.364944; - */ - data_points(0,0) = 0.866802; data_points(0,1) = 0.740808, data_points(0,2) = 0.895304, @@ -278,13 +214,19 @@ void test_genetic_algorithm() data_points(3,1) = 0.149912, data_points(3,2) = 0.364944; + typedef CGAL::Eigen_dense_matrix Matrix3d; CGAL::Optimal_bounding_box::Population pop(5); - CGAL::Optimal_bounding_box::genetic_algorithm(pop, data_points); + + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + CGAL::Optimal_bounding_box::Evolution evolution(pop, data_points); + evolution.genetic_algorithm(); + CGAL_assertion(pop.size() == 5); } void test_random_unit_tetra() { + // this is dynamic at run times CGAL::Eigen_dense_matrix data_points(4, 3); // points on their convex hull data_points(0,0) = 0.866802; @@ -319,11 +261,18 @@ void test_random_unit_tetra() out.close(); #endif - //Matrix3d R; // have to sort this out - preallocation - Matrix3d R(3, 3); + + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + typedef Linear_algebra_traits::Matrix3d Matrix3d; std::size_t generations = 10; - CGAL::Optimal_bounding_box::evolution(R, data_points, generations); + + CGAL::Optimal_bounding_box::Population pop(50); + CGAL::Optimal_bounding_box::Evolution evolution(pop, data_points); + evolution.evolve(generations); + + Matrix3d R = evolution.get_best(); + double epsilon = 1e-3; CGAL_assertion(assert_doubles(R.determinant(), 1, epsilon)); @@ -339,12 +288,13 @@ void test_random_unit_tetra() #ifdef OBB_DEBUG_TEST // postprocessing - MatrixXd obb(8, 3); + CGAL::Eigen_dense_matrix obb(8, 3); CGAL::Optimal_bounding_box::post_processing(data_points, R, obb); matrix_to_mesh_and_draw(obb, "data/random_unit_tetra_result.off"); #endif } + void test_reference_tetrahedron(const char* fname) { std::ifstream input(fname); @@ -354,13 +304,21 @@ void test_reference_tetrahedron(const char* fname) exit(1); } + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + typedef Linear_algebra_traits::MatrixXd MatrixXd; + typedef Linear_algebra_traits::Matrix3d Matrix3d; + // points in a matrix MatrixXd points; sm_to_matrix(mesh, points); - Matrix3d R(3, 3); std::size_t generations = 10; - CGAL::Optimal_bounding_box::evolution(R, points, generations); + CGAL::Optimal_bounding_box::Population pop(50); + CGAL::Optimal_bounding_box::Evolution experiment(pop, points); + experiment.evolve(generations); + + Matrix3d R = experiment.get_best(); + double epsilon = 1e-5; CGAL_assertion(assert_doubles(R.determinant(), 1, epsilon)); @@ -381,13 +339,21 @@ void test_long_tetrahedron(std::string fname) exit(1); } + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + typedef Linear_algebra_traits::MatrixXd MatrixXd; + typedef Linear_algebra_traits::Matrix3d Matrix3d; + // points in a matrix MatrixXd points; sm_to_matrix(mesh, points); - MatrixXd R(3, 3); // test with dynamic size - std::size_t generations = 10; - CGAL::Optimal_bounding_box::evolution(R, points, generations); + std::size_t max_generations = 10; + CGAL::Optimal_bounding_box::Population pop(50); + CGAL::Optimal_bounding_box::Evolution experiment(pop, points); + experiment.evolve(max_generations); + + Matrix3d R = experiment.get_best(); + double epsilon = 1e-3; CGAL_assertion(assert_doubles(R.determinant(), 1, epsilon)); CGAL_assertion(assert_doubles(R(0,0), -1, epsilon)); @@ -410,6 +376,7 @@ void test_long_tetrahedron(std::string fname) #endif } +/* void test_find_obb(std::string fname) { std::ifstream input(fname); @@ -429,7 +396,7 @@ void test_find_obb(std::string fname) sm_points.push_back(get(pmap, v)); std::vector obb_points; - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true); + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true, true); double epsilon = 1e-3; double vol = calculate_volume(obb_points); @@ -437,9 +404,48 @@ void test_find_obb(std::string fname) #ifdef OBB_DEBUG_TEST for(int i = 0; i < 8; ++i) - { std::cout << obb_points[i].x() << " " << obb_points[i].y() << " " << obb_points[i].z() << "\n" ; + CGAL::Surface_mesh result_mesh; + CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], + obb_points[4], obb_points[5], obb_points[6], obb_points[7], result_mesh); + + std::ofstream out("data/obb_result.off"); + out << result_mesh; + out.close(); + #endif +} +*/ + + +void test_find_obb_evolution(std::string fname) +{ + std::ifstream input(fname); + typedef CGAL::Surface_mesh SMesh; + SMesh mesh; + if (!input || !(input >> mesh) || mesh.is_empty()) { + std::cerr << fname << " is not a valid off file.\n"; + exit(1); } + // get mesh points + std::vector sm_points; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::property_map::const_type PointPMap; + PointPMap pmap = get(boost::vertex_point, mesh); + BOOST_FOREACH(vertex_descriptor v, vertices(mesh)) + sm_points.push_back(get(pmap, v)); + + std::vector obb_points; + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true); // maybe use algebra parameter here + + double epsilon = 1e-3; + double vol = calculate_volume(obb_points); + CGAL_assertion(assert_doubles(vol, 0.883371, epsilon)); + + #ifdef OBB_DEBUG_TEST + /* + for(int i = 0; i < 8; ++i) + std::cout << obb_points[i].x() << " " << obb_points[i].y() << " " << obb_points[i].z() << "\n" ; + */ CGAL::Surface_mesh result_mesh; CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], obb_points[4], obb_points[5], obb_points[6], obb_points[7], result_mesh); @@ -450,7 +456,7 @@ void test_find_obb(std::string fname) #endif } -void test_find_obb_mesh(std::string fname) +void test_find_obb_mesh(std::string fname) { std::ifstream input(fname); CGAL::Surface_mesh mesh; @@ -469,16 +475,21 @@ void test_find_obb_mesh(std::string fname) #endif } + + int main(int argc, char* argv[]) { - test_population(); + // test_population(); test_nelder_mead(); test_genetic_algorithm(); test_random_unit_tetra(); test_reference_tetrahedron("data/reference_tetrahedron.off"); test_long_tetrahedron("data/long_tetrahedron.off"); - test_find_obb("data/random_unit_tetra.off"); + //test_find_obb("data/random_unit_tetra.off"); + + test_find_obb_evolution("data/random_unit_tetra.off"); test_find_obb_mesh("data/elephant.off"); + return 0; } diff --git a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h index 51d776f97ce..dbbbff09db9 100644 --- a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h +++ b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h @@ -13,13 +13,15 @@ namespace CGAL { template +class Eigen_dense_vector; + +template class Eigen_dense_matrix { - public: - - typedef Eigen::Matrix EigenType; - typedef Eigen::Vector3d VectorType; + typedef Eigen::Matrix EigenType; + typedef Eigen::Matrix EigenType3; + typedef Eigen_dense_vector Eigen_dense_vector_type; Eigen_dense_matrix(std::size_t nrows, std::size_t ncols) : m_matrix(static_cast(nrows), static_cast(ncols)) @@ -62,11 +64,11 @@ public: void resize(int i_, int j_) { m_matrix.resize(i_, j_);} - const Eigen_dense_matrix row(int i_) const + Eigen_dense_vector_type row(int i_) { - VectorType row = m_matrix.row(i_); - Eigen_dense_matrix r(row); - return r; + Eigen::Vector3d row = m_matrix.row(i_); + Eigen_dense_vector_type row_vector(row); + return row_vector; } const T& coeff(int i_) const @@ -139,19 +141,85 @@ public: return product; } - - -private: mutable EigenType m_matrix; }; +template // should it be a template of its size? +class Eigen_dense_vector +{ +private: + typedef Eigen::Vector3d EigenType; + typedef Eigen_dense_matrix Eigen_dense_matrix_type; + +public: + Eigen_dense_vector(T& v0, T& v1, T& v2) + { + m_vector[0] = v0; + m_vector[1] = v1; + m_vector[2] = v2; + } + + Eigen_dense_vector(EigenType& vec) : m_vector(vec) {} + + + const T& coeff(std::size_t i) + { + CGAL_assertion(i >= 0); + CGAL_assertion(i < 3); + return m_vector.coeff(i); + } + + friend const Eigen_dense_vector operator* (const Eigen_dense_matrix_type& A, Eigen_dense_vector& V) + { + EigenType eigen_vec = A.m_matrix * V.m_vector; + Eigen_dense_vector product_vec(eigen_vec); + return product_vec; + } + + mutable EigenType m_vector; +}; + + +class Eigen_linear_algebra_traits +{ +public: + typedef double NT; + + typedef CGAL::Eigen_dense_matrix MatrixXd; // dynamic size at run time + typedef CGAL::Eigen_dense_matrix Matrix3d; // fixed at compile time + typedef CGAL::Eigen_dense_vector Vector3d; // fixed at compile time + + + /* + friend inline const MatrixXd operator* (const MatrixXd& A, + const Matrix3d& B) + { + const MatrixXd product(A.m_matrix * B.m_matrix); + return product; + } + */ + +}; + +typedef CGAL::Eigen_dense_matrix MatrixXd; // dynamic size at run time +typedef CGAL::Eigen_dense_matrix Matrix3d; // fixed at compile time +typedef CGAL::Eigen_dense_vector Vector3d; // fixed at compile time + + +const MatrixXd operator* (const MatrixXd& A, + const Matrix3d& B) +{ + const MatrixXd product(A.m_matrix * B.m_matrix); + return product; +} -} // end namespace +} +// end namespace From 63e1a1292458051edc1f146f5e04eb6efae1140a Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Wed, 16 May 2018 12:02:08 +0200 Subject: [PATCH 025/150] clear warnings & clean eigen eigen linear algrebra traits --- .../Optimal_bounding_box/bench_obb.cpp | 7 +- .../Optimal_bounding_box/bench_perfomance.cpp | 2 +- .../CGAL/Optimal_bounding_box/evolution.h | 13 +- .../Optimal_bounding_box/fitness_function.h | 11 +- .../Optimal_bounding_box/linear_algebra.h | 36 +-- .../include/CGAL/Optimal_bounding_box/obb.h | 12 +- .../optimization_algorithms.h | 3 +- .../CGAL/Optimal_bounding_box/population.h | 21 +- .../test_linear_algebra_functions.cpp | 28 +- .../test_optimization_algorithms.cpp | 22 +- .../CGAL/Eigen_linear_algebra_traits.h | 239 +++++++++--------- 11 files changed, 221 insertions(+), 173 deletions(-) diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp index ae604898449..12df347ea8a 100644 --- a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp @@ -98,9 +98,8 @@ void bench_finding_obb(std::string fname) timer.reset(); - double epsilon = 1e-3; - double vol1 = calculate_volume(obb_points1); - double vol2 = calculate_volume(obb_points2); + //double vol1 = calculate_volume(obb_points1); + // double vol2 = calculate_volume(obb_points2); //std::cout << "vol1= " << vol1 << " -- " << "vol2= " << vol2 << std::endl; @@ -126,7 +125,7 @@ void bench_finding_obb(std::string fname) #endif } -int main(int argc, char* argv[]) +int main() { bench_finding_obb("data/elephant.off"); diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp index a35fc86bf13..dddbcf791cb 100644 --- a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp @@ -69,7 +69,7 @@ void bench_finding_obb(std::string fname) #endif } -int main(int argc, char* argv[]) +int main() { bench_finding_obb("data/elephant.off"); diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index fe672b5ffb2..56d0f0db5ea 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -177,7 +177,7 @@ public: Population offspringsA(size_first_group); double bias = 0.1; - for(int i = 0; i < size_first_group; ++i) + for(std::size_t i = 0; i < size_first_group; ++i) { std::vector offspring(4); for(int j = 0; j < 4; ++j) @@ -208,7 +208,7 @@ public: Population offspringsB(size_second_group); bias = 0.1; - for(int i = 0; i < size_second_group; ++i) + for(std::size_t i = 0; i < size_second_group; ++i) { std::vector offspring(4); for(int j = 0; j < 4; ++j) @@ -226,7 +226,8 @@ public: } // qr factorization of the offspring - qr_factorization(offspring); + //qr_factorization(offspring); + Linear_algebra_traits::qr_factorization(offspring); offspringsB[i] = offspring; @@ -293,7 +294,8 @@ public: // debugging Fitness_map fitness_map(pop, point_data); Matrix R_now = fitness_map.get_best(); - std::cout << "det= " << R_now.determinant() << std::endl; + //std::cout << "det= " << R_now.determinant() << std::endl; + std::cout << "det= " << determinant(R_now) << std::endl; #endif // stopping criteria @@ -352,7 +354,8 @@ void check_det(Population& pop) for(int j = 0; j < 4; ++j) { auto A = pop[i][j]; // Simplex - std::cout << A.determinant() << std::endl; + //std::cout << A.determinant() << std::endl; + std::cout << determinant(A) << std::endl; } } } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 5c75819ad43..1632282cb55 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -33,7 +33,7 @@ namespace CGAL { namespace Optimal_bounding_box { template -const double compute_fitness(const typename Linear_algebra_traits::Matrix3d& R, +double compute_fitness(const typename Linear_algebra_traits::Matrix3d& R, typename Linear_algebra_traits::MatrixXd& data) { // R: rotation matrix @@ -46,9 +46,10 @@ const double compute_fitness(const typename Linear_algebra_traits::Matrix3d& R, typedef typename Linear_algebra_traits::Vector3d Vector3d; double xmin, xmax, ymin, ymax, zmin, zmax; - for(int i = 0; i < data.rows(); i++){ + for(std::size_t i = 0; i < data.rows(); i++){ - Vector3d vec = data.row(i); + Vector3d vec = Linear_algebra_traits::row(data, i); + //Vector3d vec = data.row(i); vec = R * vec; if(i == 0){ @@ -103,14 +104,14 @@ struct Fitness_map return pop[simplex_id][vertex_id]; } - const double get_best_fitness_value(Matrix& data) + double get_best_fitness_value(Matrix& data) { const Vertex best_mat = get_best(); return compute_fitness(best_mat, data); } - Matrix& points; Population& pop; + Matrix& points; }; }} // end namespaces diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h index 5d7e1ffbc75..1f9dedff815 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h @@ -23,14 +23,22 @@ #define CGAL_OPTIMAL_BOUNDING_BOX_H #include -#include #include +#if defined(CGAL_EIGEN3_ENABLED) +#include +#endif + + namespace CGAL { namespace Optimal_bounding_box { +#if defined(CGAL_EIGEN3_ENABLED) +typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; +#endif +/* template void qr_factorization(Matrix& A, Matrix& Q) { @@ -48,6 +56,7 @@ void qr_factorization(std::vector& Simplex) Simplex[i] = Q; } } +*/ template const Matrix reflection(const Matrix& S_centroid, const Matrix& S_worst) @@ -57,7 +66,7 @@ const Matrix reflection(const Matrix& S_centroid, const Matrix& S_worst) CGAL_assertion(S_worst.cols() == 3); CGAL_assertion(S_worst.cols() == 3); - return S_centroid * S_worst.transpose() * S_centroid; + return S_centroid * Linear_algebra_traits::transpose(S_worst) * S_centroid; } template @@ -70,7 +79,7 @@ const Matrix expansion(const Matrix& S_centroid, const Matrix& S_worst, const Ma CGAL_assertion(S_reflection.cols() == 3); CGAL_assertion(S_reflection.cols() == 3); - return S_centroid * S_worst.transpose() * S_reflection; + return S_centroid * Linear_algebra_traits::transpose(S_worst) * S_reflection; } template @@ -83,12 +92,10 @@ Matrix mean(const Matrix& m1, const Matrix& m2) CGAL_assertion(m2.cols() == 3); Matrix reduction = 0.5 * m1 + 0.5 * m2; - Matrix Q; - //qr_factorization(contract, Q); - - reduction.qr_factorization(Q); - - double det = Q.determinant(); + //Matrix Q; + //reduction.qr_factorization(Q); + Matrix Q = Linear_algebra_traits::qr_factorization(reduction); + double det = Linear_algebra_traits::determinant(Q); return Q / det; } @@ -96,13 +103,10 @@ template const Matrix centroid(Matrix& S1, Matrix& S2, Matrix& S3) // const? { Matrix mean = (S1 + S2 + S3) / 3.0; - Matrix Q; - //qr_factorization(mean, Q); - - mean.qr_factorization(Q); - - - double det = Q.determinant(); + //Matrix Q; + //mean.qr_factorization(Q); + Matrix Q = Linear_algebra_traits::qr_factorization(mean); + double det = Linear_algebra_traits::determinant(Q); return Q / det; } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index ad12d735b3b..ef9450ddd17 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -31,7 +31,7 @@ #include #include #include -#include // used to get the ch +#include #include #include @@ -43,6 +43,11 @@ namespace CGAL { namespace Optimal_bounding_box { +#if defined(CGAL_EIGEN3_ENABLED) +typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; +#endif + + template void evolution(Vertex& R, Matrix& points, std::size_t max_generations) // todo: points is const { @@ -85,7 +90,8 @@ void evolution(Vertex& R, Matrix& points, std::size_t max_generations) // todo: // debugging Fitness_map fitness_map(pop, points); Matrix R_now = fitness_map.get_best(); - std::cout << "det= " << R_now.determinant() << std::endl; + //std::cout << "det= " << R_now.determinant() << std::endl; + std::cout << "det= " << determinant(R_now) << std::endl; #endif // stopping criteria @@ -118,7 +124,7 @@ void post_processing(const Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) // 1) rotate points with R Matrix_dynamic rotated_points(points.rows(), points.cols()); - rotated_points = points * R.transpose(); + rotated_points = points * Linear_algebra_traits::transpose(R); // 2) get AABB from rotated points typedef CGAL::Simple_cartesian K; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h index 2466ebeb657..f20df496031 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h @@ -297,7 +297,8 @@ void check_det(Population& pop) for(int j = 0; j < 4; ++j) { auto A = pop[i][j]; // Simplex - std::cout << A.determinant() << std::endl; + //std::cout << A.determinant() << std::endl; + std::cout << determinant(A) << std::endl; } } } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index b86a5101ab4..a68d4639b21 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -28,13 +28,26 @@ #include +#if defined(CGAL_EIGEN3_ENABLED) +#include +#endif + + + namespace CGAL { namespace Optimal_bounding_box { + + template class Population { + +#if defined(CGAL_EIGEN3_ENABLED) + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; +#endif + typedef std::vector Simplex; public: @@ -102,9 +115,11 @@ private: R.resize(3, 3); create_vertex(R); - Matrix Q; // no allocation + //Matrix Q; // no allocation //qr_factorization(R, Q); - R.qr_factorization(Q); + //R.qr_factorization(Q); + Matrix Q = Linear_algebra_traits::qr_factorization(R); + simplex[i] = Q; } CGAL_assertion(simplex.size() == 4); @@ -125,8 +140,8 @@ private: } } - CGAL::Random random_generator; std::size_t n; + CGAL::Random random_generator; std::vector pop; }; diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index 291f377ea16..a7834453d2c 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -32,14 +32,16 @@ void test_qr_factorization() A.set_coef(2, 1, 0.0202949); A.set_coef(2, 2, 0.9240308); - CGAL::Eigen_dense_matrix Q; + //CGAL::Eigen_dense_matrix Q; //CGAL::Optimal_bounding_box::qr_factorization(A, Q); - A.qr_factorization(Q); + //A.qr_factorization(Q); + CGAL::Eigen_dense_matrix Q = + CGAL::Eigen_linear_algebra_traits::qr_factorization(A); - double epsilon = 1e-6; + CGAL_assertion_code(double epsilon = 1e-6); CGAL_assertion(assert_doubles(Q(0,0), -0.504895, epsilon)); CGAL_assertion(assert_doubles(Q(0,1), 0.862834, epsilon)); CGAL_assertion(assert_doubles(Q(0,2), -0.024447, epsilon)); @@ -86,8 +88,9 @@ void test_fitness_function() rotation.set_coef(2, 1, -0.991602); rotation.set_coef(2, 2, 0.042528); - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - double fitness = CGAL::Optimal_bounding_box::compute_fitness (rotation, data_points); + CGAL_assertion_code(typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits); + CGAL_assertion_code(double fitness = CGAL::Optimal_bounding_box:: + compute_fitness (rotation, data_points)); CGAL_assertion(assert_doubles(fitness, 0.58606, 1e-5)); } @@ -134,7 +137,7 @@ void test_simplex_operations() CGAL::Eigen_dense_matrix Sr = CGAL::Optimal_bounding_box::reflection(Sc, S_worst); - double epsilon = 1e-5; + CGAL_assertion_code(double epsilon = 1e-5); CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); CGAL_assertion(assert_doubles(Sr(0,2), -0.24664, epsilon)); @@ -261,7 +264,7 @@ void test_centroid() CGAL::Eigen_dense_matrix S_centroid = CGAL::Optimal_bounding_box::centroid(S_a, S_b, S_c); - double epsilon = 1e-5; + CGAL_assertion_code(double epsilon = 1e-5); CGAL_assertion(assert_doubles(S_centroid(0,0), -0.419979, epsilon)); CGAL_assertion(assert_doubles(S_centroid(0,1), 0.301765, epsilon)); CGAL_assertion(assert_doubles(S_centroid(0,2), -0.855894, epsilon)); @@ -286,7 +289,8 @@ void test_eigen_matrix_interface() A.set_coef(2, 0, 0.7); A.set_coef(2, 1, 0.8); A.set_coef(2, 2, 0.9); - CGAL::Eigen_dense_matrix B = A.transpose(); + //CGAL::Eigen_dense_matrix B = A.transpose(); + CGAL::Eigen_dense_matrix B = CGAL::Eigen_linear_algebra_traits::transpose(A); CGAL::Eigen_dense_matrix S = 0.5 * A; @@ -301,10 +305,12 @@ void test_eigen_matrix_interface() C.set_coef(2, 1, 0.0202949); C.set_coef(2, 2, 0.9240308); - CGAL::Eigen_dense_matrix Q(3,3); - C.qr_factorization(Q); + //C.qr_factorization(Q); - double epsilon = 1e-5; + CGAL::Eigen_dense_matrix Q = + CGAL::Eigen_linear_algebra_traits::qr_factorization(C); + + CGAL_assertion_code(double epsilon = 1e-5); CGAL_assertion(assert_doubles(Q(0,0), -0.504895, epsilon)); CGAL_assertion(assert_doubles(Q(0,1), 0.862834, epsilon)); CGAL_assertion(assert_doubles(Q(0,2), -0.024447, epsilon)); diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index a7ed6864373..7094c249154 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -152,7 +152,7 @@ void test_nelder_mead() evolution(pop, data_points); evolution.nelder_mead(simplex, nm_iterations); - double epsilon = 1e-5; + CGAL_assertion_code(double epsilon = 1e-5); Matrix3d v0_new = simplex[0]; CGAL_assertion(assert_doubles(v0_new(0,0), -0.288975, epsilon)); CGAL_assertion(assert_doubles(v0_new(0,1), 0.7897657, epsilon)); @@ -274,8 +274,8 @@ void test_random_unit_tetra() Matrix3d R = evolution.get_best(); - double epsilon = 1e-3; - CGAL_assertion(assert_doubles(R.determinant(), 1, epsilon)); + CGAL_assertion_code(double epsilon = 1e-3); + CGAL_assertion(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); CGAL_assertion(assert_doubles(R(0,0), -0.25791, epsilon)); CGAL_assertion(assert_doubles(R(0,1), 0.796512, epsilon)); CGAL_assertion(assert_doubles(R(0,2), -0.546855, epsilon)); @@ -319,8 +319,8 @@ void test_reference_tetrahedron(const char* fname) Matrix3d R = experiment.get_best(); - double epsilon = 1e-5; - CGAL_assertion(assert_doubles(R.determinant(), 1, epsilon)); + CGAL_assertion_code(double epsilon = 1e-5); + CGAL_assertion(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); #ifdef OBB_DEBUG_TEST // postprocessing @@ -354,8 +354,8 @@ void test_long_tetrahedron(std::string fname) Matrix3d R = experiment.get_best(); - double epsilon = 1e-3; - CGAL_assertion(assert_doubles(R.determinant(), 1, epsilon)); + CGAL_assertion_code(double epsilon = 1e-3); + CGAL_assertion(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); CGAL_assertion(assert_doubles(R(0,0), -1, epsilon)); CGAL_assertion(assert_doubles(R(0,1), 0, epsilon)); CGAL_assertion(assert_doubles(R(0,2), 0, epsilon)); @@ -437,8 +437,8 @@ void test_find_obb_evolution(std::string fname) std::vector obb_points; CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true); // maybe use algebra parameter here - double epsilon = 1e-3; - double vol = calculate_volume(obb_points); + CGAL_assertion_code(double epsilon = 1e-3); + CGAL_assertion_code(double vol = calculate_volume(obb_points)); CGAL_assertion(assert_doubles(vol, 0.883371, epsilon)); #ifdef OBB_DEBUG_TEST @@ -465,7 +465,7 @@ void test_find_obb_mesh(std::string fname) exit(1); } - CGAL::Surface_mesh obbmesh; + CGAL::Surface_mesh< K::Point_3> obbmesh; CGAL::Optimal_bounding_box::find_obb(mesh, obbmesh, true); #ifdef OBB_DEBUG_TEST @@ -477,7 +477,7 @@ void test_find_obb_mesh(std::string fname) -int main(int argc, char* argv[]) +int main() { // test_population(); test_nelder_mead(); diff --git a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h index dbbbff09db9..5da5e294e22 100644 --- a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h +++ b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h @@ -1,5 +1,23 @@ - -//license +// Copyright (c) 2018 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Konstantinos Katrioplas #ifndef CGAL_EIGEN_LINEAR_ALGEBRA_TRAITS_H #define CGAL_EIGEN_LINEAR_ALGEBRA_TRAITS_H @@ -12,7 +30,7 @@ namespace CGAL { -template +template class Eigen_dense_vector; template @@ -21,7 +39,6 @@ class Eigen_dense_matrix public: typedef Eigen::Matrix EigenType; typedef Eigen::Matrix EigenType3; - typedef Eigen_dense_vector Eigen_dense_vector_type; Eigen_dense_matrix(std::size_t nrows, std::size_t ncols) : m_matrix(static_cast(nrows), static_cast(ncols)) @@ -64,119 +81,32 @@ public: void resize(int i_, int j_) { m_matrix.resize(i_, j_);} - Eigen_dense_vector_type row(int i_) - { - Eigen::Vector3d row = m_matrix.row(i_); - Eigen_dense_vector_type row_vector(row); - return row_vector; - } - const T& coeff(int i_) const { return m_matrix.coeff(i_); } - const Eigen_dense_matrix transpose() const - { - Eigen_dense_matrix dm(m_matrix.transpose()); - return dm; - //return Eigen_dense_matrix(m_matrix.transpose()); - } - - const double determinant() const - { - return m_matrix.determinant(); - } - - void qr_factorization(Eigen_dense_matrix& Q) - { - Q.resize(m_matrix.rows(), m_matrix.cols()); - Eigen::HouseholderQR qr(m_matrix); - Eigen_dense_matrix qr_mat(qr.householderQ()); - Q = qr_mat; - } - - friend void qr_factorization(std::vector& simplex) - { - for(int i = 0; i < simplex.size(); ++i) - { - Eigen::HouseholderQR qr(simplex[i].m_matrix); - Eigen_dense_matrix Q(qr.householderQ()); - simplex[i] = Q; - } - } - - friend const Eigen_dense_matrix operator* (const Eigen_dense_matrix& A, - const Eigen_dense_matrix& B) - { - const Eigen_dense_matrix product(A.m_matrix * B.m_matrix); - return product; - } - - friend const Eigen_dense_matrix operator* (const T& scalar, - const Eigen_dense_matrix& B) - { - const Eigen_dense_matrix product(scalar * B.m_matrix); - return product; - } - - friend const Eigen_dense_matrix operator+ (const Eigen_dense_matrix& A, - const Eigen_dense_matrix& B) - { - const Eigen_dense_matrix sum_result(A.m_matrix + B.m_matrix); - return sum_result; - } - - friend const Eigen_dense_matrix operator/ (const Eigen_dense_matrix& A, - const double& scalar) - { - const Eigen_dense_matrix product(A.m_matrix / scalar); - return product; - } - - friend const Eigen_dense_matrix operator/ (const double& scalar , - const Eigen_dense_matrix& A) - { - const Eigen_dense_matrix product(scalar / A.m_matrix); - return product; - } - mutable EigenType m_matrix; }; -template // should it be a template of its size? +template class Eigen_dense_vector { private: - typedef Eigen::Vector3d EigenType; - typedef Eigen_dense_matrix Eigen_dense_matrix_type; + //typedef Eigen::Vector3d EigenType; + typedef Eigen::Matrix EigenType; public: - Eigen_dense_vector(T& v0, T& v1, T& v2) - { - m_vector[0] = v0; - m_vector[1] = v1; - m_vector[2] = v2; - } - - Eigen_dense_vector(EigenType& vec) : m_vector(vec) {} - + Eigen_dense_vector(const EigenType& vec) : m_vector(vec) {} const T& coeff(std::size_t i) { CGAL_assertion(i >= 0); - CGAL_assertion(i < 3); + CGAL_assertion(i < static_cast(D)); return m_vector.coeff(i); } - friend const Eigen_dense_vector operator* (const Eigen_dense_matrix_type& A, Eigen_dense_vector& V) - { - EigenType eigen_vec = A.m_matrix * V.m_vector; - Eigen_dense_vector product_vec(eigen_vec); - return product_vec; - } - mutable EigenType m_vector; }; @@ -186,35 +116,118 @@ class Eigen_linear_algebra_traits public: typedef double NT; - typedef CGAL::Eigen_dense_matrix MatrixXd; // dynamic size at run time - typedef CGAL::Eigen_dense_matrix Matrix3d; // fixed at compile time - typedef CGAL::Eigen_dense_vector Vector3d; // fixed at compile time + // dynamic size at run time + typedef CGAL::Eigen_dense_matrix MatrixXd; + // fixed at compile time + typedef CGAL::Eigen_dense_matrix Matrix3d; - /* - friend inline const MatrixXd operator* (const MatrixXd& A, - const Matrix3d& B) + // fixed at compile time + typedef CGAL::Eigen_dense_vector Vector3d; + + template + static Matrix transpose(const Matrix& mat) { - const MatrixXd product(A.m_matrix * B.m_matrix); - return product; + return Matrix(mat.m_matrix.transpose()); + } + + template + static NT determinant(const Matrix& mat) + { + return mat.m_matrix.determinant(); + } + + template + static CGAL::Eigen_dense_matrix qr_factorization(const CGAL::Eigen_dense_matrix& A) + { + Eigen::HouseholderQR > qr(A.m_matrix); + return CGAL::Eigen_dense_matrix(qr.householderQ()); + } + + template + static void qr_factorization(std::vector& simplex) + { + for(std::size_t i = 0; i < simplex.size(); ++i) + { + Matrix mat = simplex[i].m_matrix; + simplex[i] = qr_factorization(mat); + } + } + + template + static CGAL::Eigen_dense_vector row(CGAL::Eigen_dense_matrix& A, int i_) + { + return CGAL::Eigen_dense_vector(A.m_matrix.row(i_)); } - */ }; -typedef CGAL::Eigen_dense_matrix MatrixXd; // dynamic size at run time -typedef CGAL::Eigen_dense_matrix Matrix3d; // fixed at compile time -typedef CGAL::Eigen_dense_vector Vector3d; // fixed at compile time - -const MatrixXd operator* (const MatrixXd& A, - const Matrix3d& B) +// matrix multiplication +template +const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix& A, + const CGAL::Eigen_dense_matrix& B) { - const MatrixXd product(A.m_matrix * B.m_matrix); - return product; + return CGAL::Eigen_dense_matrix(A.m_matrix * B.m_matrix); } +template +const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix& A, + const CGAL::Eigen_dense_matrix& B) +{ + return CGAL::Eigen_dense_matrix(A.m_matrix * B.m_matrix); +} +template +const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix& A, + const CGAL::Eigen_dense_matrix& B) +{ + return CGAL::Eigen_dense_matrix(A.m_matrix * B.m_matrix); +} + +// scalar - matrix multiplication +template +const CGAL::Eigen_dense_matrix operator* (const NT& scalar, + const CGAL::Eigen_dense_matrix& B) +{ + return CGAL::Eigen_dense_matrix(scalar * B.m_matrix); +} + +template +const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix& A, + const NT& scalar) +{ + return CGAL::Eigen_dense_matrix(A.m_matrix * scalar); +} + +template +const CGAL::Eigen_dense_matrix operator/ (const CGAL::Eigen_dense_matrix& A, + const double& scalar) +{ + return CGAL::Eigen_dense_matrix(A.m_matrix / scalar); +} + +template +const CGAL::Eigen_dense_matrix operator/ (const double& scalar, + const CGAL::Eigen_dense_matrix & A) +{ + return CGAL::Eigen_dense_matrix (scalar / A.m_matrix); +} + +// addition - subtraction +template +const CGAL::Eigen_dense_matrix operator+ (const CGAL::Eigen_dense_matrix & A, + const CGAL::Eigen_dense_matrix & B) +{ + return CGAL::Eigen_dense_matrix (A.m_matrix + B.m_matrix); +} + +// vector - matrix multiplication +template +const Eigen_dense_vector operator* (const CGAL::Eigen_dense_matrix& A, CGAL::Eigen_dense_vector& V) +{ + return Eigen_dense_vector(A.m_matrix * V.m_vector); +} From 62327b28f0f469b692ded0631745e02ad0f7fe4f Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Wed, 16 May 2018 13:12:42 +0200 Subject: [PATCH 026/150] cleaning --- .../Optimal_bounding_box/bench_obb.cpp | 22 -- .../CGAL/Optimal_bounding_box/evolution.h | 38 +-- .../Optimal_bounding_box/fitness_function.h | 3 +- .../CGAL/Optimal_bounding_box/helper.h | 109 ++++++ .../include/CGAL/Optimal_bounding_box/obb.h | 171 +--------- .../optimization_algorithms.h | 316 ------------------ .../CGAL/Optimal_bounding_box/population.h | 56 ++-- .../test_linear_algebra_functions.cpp | 75 ----- .../test_optimization_algorithms.cpp | 126 +------ 9 files changed, 155 insertions(+), 761 deletions(-) create mode 100644 Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h delete mode 100644 Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp index 12df347ea8a..a3daafffb5a 100644 --- a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp @@ -19,28 +19,6 @@ bool assert_doubles(double d1, double d2, double epsilon) return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; } -/* -template -void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) -{ - typedef typename boost::property_map::const_type Vpm; - typedef typename boost::property_traits::reference Point_ref; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - Vpm vpm = get(boost::vertex_point, sm); - - mat.resize(vertices(sm).size(), 3); - std::size_t i = 0; - for(vertex_descriptor v : vertices(sm)) - { - Point_ref p = get(vpm, v); - mat(i, 0) = p.x(); - mat(i, 1) = p.y(); - mat(i, 2) = p.z(); - ++i; - } -} -*/ - template void gather_mesh_points(SurfaceMesh& mesh, std::vector& points) { diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index 56d0f0db5ea..30cd901b912 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -25,7 +25,7 @@ #include #include - +#include namespace CGAL { namespace Optimal_bounding_box { @@ -34,7 +34,6 @@ namespace Optimal_bounding_box { template class Evolution { - typedef typename Linear_algebra_traits::MatrixXd MatrixXd; typedef typename Linear_algebra_traits::Matrix3d Matrix3d; typedef typename Linear_algebra_traits::Vector3d Vector3d; @@ -124,11 +123,9 @@ public: } CGAL_assertion(simplex.size() == 4); // tetrahedron - } // iterations } - void genetic_algorithm() { // random permutations @@ -222,14 +219,10 @@ public: lambda = 0.5 - bias; // combine information from A and B offspring[j] = lambda * group3[i][j] + lambda * group4[i][j]; - } // qr factorization of the offspring - //qr_factorization(offspring); Linear_algebra_traits::qr_factorization(offspring); - - offspringsB[i] = offspring; } @@ -254,10 +247,8 @@ public: } } - void evolve(std::size_t generations) { - // hardcoded nelder_mead_iterations std::size_t nelder_mead_iterations = 20; @@ -267,7 +258,6 @@ public: double tolerance = 1e-2; int stale = 0; - // evolve here for(std::size_t t = 0; t < generations; ++t) { @@ -290,18 +280,14 @@ public: //std::cout << "pop after nelder mead: " << std::endl; //pop.show_population(); //std::cout << std::endl; - - // debugging - Fitness_map fitness_map(pop, point_data); - Matrix R_now = fitness_map.get_best(); - //std::cout << "det= " << R_now.determinant() << std::endl; - std::cout << "det= " << determinant(R_now) << std::endl; + Fitness_map fitness_map_debug(population, point_data); + Matrix3d R_now = fitness_map_debug.get_best(); + std::cout << "det= " << Linear_algebra_traits::determinant(R_now) << std::endl; #endif // stopping criteria Fitness_map fitness_map(population, point_data); new_fit_value = fitness_map.get_best_fitness_value(point_data); - double difference = new_fit_value - prev_fit_value; if(abs(difference) < tolerance * new_fit_value) stale++; @@ -313,15 +299,13 @@ public: } } - const Matrix3d get_best() // reference ?? + const Matrix3d get_best() { Fitness_map fitness_map(population, point_data); return fitness_map.get_best(); } - private: - // needed in genetic algorithm struct Comparator { @@ -331,17 +315,12 @@ private: { return fitness[i] < fitness[j]; } - std::vector fitness; }; - - // data Population population; MatrixXd point_data; - - }; @@ -349,13 +328,12 @@ private: template void check_det(Population& pop) { - for(int i = 0; i < pop.size(); ++i) + for(std::size_t i = 0; i < pop.size(); ++i) { - for(int j = 0; j < 4; ++j) + for(std::size_t j = 0; j < 4; ++j) { auto A = pop[i][j]; // Simplex - //std::cout << A.determinant() << std::endl; - std::cout << determinant(A) << std::endl; + std::cout << Linear_algebra_traits::determinant(A) << std::endl; } } } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 1632282cb55..8f00286f0ed 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -34,7 +34,7 @@ namespace Optimal_bounding_box { template double compute_fitness(const typename Linear_algebra_traits::Matrix3d& R, - typename Linear_algebra_traits::MatrixXd& data) + typename Linear_algebra_traits::MatrixXd& data) { // R: rotation matrix CGAL_assertion(R.cols() == 3); @@ -49,7 +49,6 @@ double compute_fitness(const typename Linear_algebra_traits::Matrix3d& R, for(std::size_t i = 0; i < data.rows(); i++){ Vector3d vec = Linear_algebra_traits::row(data, i); - //Vector3d vec = data.row(i); vec = R * vec; if(i == 0){ diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h new file mode 100644 index 00000000000..5c4de4bac0f --- /dev/null +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h @@ -0,0 +1,109 @@ +// Copyright (c) 2018 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Konstantinos Katrioplas + +#ifndef CGAL_HELPER_H +#define CGAL_HELPER_H + +#include +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + + +namespace CGAL { +namespace Optimal_bounding_box { + + +template +void fill_matrix(std::vector& v_points, Matrix& points_mat) +{ + points_mat.resize(v_points.size(), 3); + for(std::size_t i = 0; i < v_points.size(); ++i) + { + Point p = v_points[i]; + points_mat.set_coef(i, 0, p.x()); + points_mat.set_coef(i, 1, p.y()); + points_mat.set_coef(i, 2, p.z()); + } +} + +template +void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) +{ + typedef typename boost::property_map::const_type Vpm; + typedef typename boost::property_traits::reference Point_ref; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + Vpm vpm = get(boost::vertex_point, sm); + + mat.resize(vertices(sm).size(), 3); + std::size_t i = 0; + for(vertex_descriptor v : vertices(sm)) + { + Point_ref p = get(vpm, v); + mat.set_coef(i, 0, p.x()); + mat.set_coef(i, 1, p.y()); + mat.set_coef(i, 2, p.z()); + ++i; + } +} + +template +double calculate_volume(std::vector points) +{ + CGAL::Bbox_3 bbox; + bbox = bbox_3(points.begin(), points.end()); + K::Iso_cuboid_3 ic(bbox); + return ic.volume(); +} + +// it is called after post processing in debug only +template +void matrix_to_mesh_and_draw(Matrix& data_points, std::string filename) +{ + typedef CGAL::Simple_cartesian K; + typedef K::Point_3 Point; + typedef CGAL::Surface_mesh Mesh; + + // Simplex -> std::vector + std::vector points; + + for(int i = 0; i < data_points.rows(); ++i) + { + Point p(data_points(i, 0), data_points(i, 1), data_points(i, 2)); + points.push_back(p); + } + + Mesh mesh; + CGAL::make_hexahedron(points[0], points[1], points[2], points[3], points[4], points[5], + points[6], points[7], mesh); + + std::ofstream out(filename); + out << mesh; + out.close(); +} + +}} // end namespaces + + + +#endif diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index ef9450ddd17..b050261f710 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -22,9 +22,9 @@ #ifndef CGAL_OBB_H #define CGAL_OBB_H -#include #include #include +#include #include #include #include @@ -48,70 +48,6 @@ typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; #endif -template -void evolution(Vertex& R, Matrix& points, std::size_t max_generations) // todo: points is const -{ - CGAL_assertion(points.rows() >= 3); - CGAL_assertion(points.cols() == 3); - CGAL_assertion(R.rows() == 3); - CGAL_assertion(R.cols() == 3); - - Population pop(50); - std::size_t nelder_mead_iterations = 20; - - double prev_fit_value = 0; - double new_fit_value = 0; - double tolerance = 1e-2; - int stale = 0; - - for(std::size_t t = 0; t < max_generations; ++t) - { - -#ifdef OBB_DEBUG - std::cout << "generation= " << t << "\n"; -#endif - - genetic_algorithm(pop, points); - -#ifdef OBB_DEBUG - //std::cout << "pop after genetic" << std::endl; - //pop.show_population(); - //std::cout << std::endl; -#endif - - for(std::size_t s = 0; s < pop.size(); ++s) - nelder_mead(pop[s], points, nelder_mead_iterations); - -#ifdef OBB_DEBUG - //std::cout << "pop after nelder mead: " << std::endl; - //pop.show_population(); - //std::cout << std::endl; - - // debugging - Fitness_map fitness_map(pop, points); - Matrix R_now = fitness_map.get_best(); - //std::cout << "det= " << R_now.determinant() << std::endl; - std::cout << "det= " << determinant(R_now) << std::endl; -#endif - - // stopping criteria - Fitness_map fitness_map(pop, points); - new_fit_value = fitness_map.get_best_fitness_value(points); - - double difference = new_fit_value - prev_fit_value; - if(abs(difference) < tolerance * new_fit_value) - stale++; - - if(stale == 5) - break; - - prev_fit_value = new_fit_value; - } - - Fitness_map fitness_map(pop, points); - R = fitness_map.get_best(); -} - // works on matrices only template void post_processing(const Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) @@ -132,7 +68,6 @@ void post_processing(const Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) std::vector v_points; // Simplex -> std::vector for(std::size_t i = 0; i < rotated_points.rows(); ++i) { - //Point p(rotated_points.coeff(i, 0), rotated_points.coeff(i, 1), rotated_points.coeff(i, 2)); Point p(rotated_points(i, 0), rotated_points(i, 1), rotated_points(i, 2)); v_points.push_back(p); } @@ -147,46 +82,15 @@ void post_processing(const Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) for(std::size_t i = 0; i < 8; ++i) { - /* - aabb.coeffRef(i, 0) = ic[i].x(); - aabb.coeffRef(i, 1) = ic[i].y(); - aabb.coeffRef(i, 2) = ic[i].z(); - */ - aabb.set_coef(i, 0, ic[i].x()); aabb.set_coef(i, 1, ic[i].y()); aabb.set_coef(i, 2, ic[i].z()); - - } // 3) apply inverse rotation to rotated AABB obb = aabb * R; } - -// to be moved into a helper -template -void fill_matrix(std::vector& v_points, Matrix& points_mat) -{ - points_mat.resize(v_points.size(), 3); - for(std::size_t i = 0; i < v_points.size(); ++i) - { - Point p = v_points[i]; - /* - points_mat.coeffRef(i, 0) = p.x(); - points_mat.coeffRef(i, 1) = p.y(); - points_mat.coeffRef(i, 2) = p.z(); - */ - - points_mat.set_coef(i, 0, p.x()); - points_mat.set_coef(i, 1, p.y()); - points_mat.set_coef(i, 2, p.z()); - - } -} - - // with linear algebra traits template void find_obb(std::vector& points, std::vector& obb_points, bool use_ch) @@ -214,12 +118,12 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u std::vector ch_points(poly.points_begin(), poly.points_end()); // points: vector -> matrix - fill_matrix(ch_points, points_mat); + CGAL::Optimal_bounding_box::fill_matrix(ch_points, points_mat); } else { // points: vector -> matrix - fill_matrix(points, points_mat); + CGAL::Optimal_bounding_box::fill_matrix(points, points_mat); } std::size_t max_generations = 100; @@ -240,74 +144,8 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u Point p(obb(i, 0), obb(i, 1), obb(i, 2)); obb_points[i] = p; } - } - -/* - //USES ::EVOLUTION - -/// @param points point coordinates of the input mesh. -/// @param obb_points the 8 points of the obb. -/// @param use convex hull or not. -/// -/// todo named parameters: max iterations, population size, tolerance. -template -void find_obb(std::vector& points, std::vector& obb_points, bool use_ch, bool use_eigen) -{ - CGAL_assertion(points.size() >= 3); - - if(obb_points.size() != 8) // temp sanity until the API is decided - obb_points.resize(8); - CGAL_assertion(obb_points.size() == 8); - - // using eigen internally - typedef Eigen::MatrixXd MatrixXd; // for point data - typedef Eigen::Matrix3d Matrix3d; // for matrices in simplices - - MatrixXd points_mat; - - // get the ch3 - if(use_ch) - { - // find the ch - todo: template kernel - typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; - CGAL::Polyhedron_3 poly; - convex_hull_3(points.begin(), points.end(), poly); - std::vector ch_points(poly.points_begin(), poly.points_end()); - - // points: vector -> matrix - fill_matrix(ch_points, points_mat); - } - else - { - // points: vector -> matrix - fill_matrix(points, points_mat); - } - - //Matrix3d R; // todo: sort out preallocation - Matrix3d R(3, 3); - std::size_t max_generations = 100; - CGAL::Optimal_bounding_box::evolution(R, points_mat, max_generations); - - //Eigen::Matrix obb; - - MatrixXd obb; // compile time preallocation?? - obb.resize(8, 3); - - CGAL::Optimal_bounding_box::post_processing(points_mat, R, obb); - - // matrix -> vector - for(std::size_t i = 0; i < 8; ++i) - { - //Point p(obb.coeff(i, 0), obb.coeff(i, 1), obb.coeff(i, 2)); - Point p(obb(i, 0), obb(i, 1), obb(i, 2)); - obb_points[i] = p; - } -} - -*/ - /// @param pmesh the input mesh. /// @param obbmesh the obb in a hexahedron pmesh. /// @param use convex hull or not. @@ -347,9 +185,6 @@ void find_obb(PolygonMesh& pmesh, PolygonMesh& obbmesh, bool use_ch) - - - #endif //CGAL_OBB_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h deleted file mode 100644 index f20df496031..00000000000 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimization_algorithms.h +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright (c) 2018 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0+ -// -// -// Author(s) : Konstantinos Katrioplas - -#ifndef CGAL_OPTIMAL_BOUNDING_BOX_OPTIMIZATION_ALGORITHMS_H -#define CGAL_OPTIMAL_BOUNDING_BOX_OPTIMIZATION_ALGORITHMS_H - -#include -#include -#include -#include - -#include -#include -#include - - -namespace CGAL { - -namespace Optimal_bounding_box { - -/* -struct Comparator -{ - Comparator(std::vector in) : fitness(in) {} - - inline bool operator() (std::size_t& i, std::size_t& j) - { - return fitness[i] < fitness[j]; - } - - std::vector fitness; -}; - -// points: point coords -// simplex: 4 rotation matrices are its vertices -template -void nelder_mead(std::vector& simplex, Matrix& points, std::size_t nb_iterations) -{ - - CGAL_assertion(simplex.size() == 4); // tetrahedron - - std::vector fitness(4); - std::vector indices( boost::counting_iterator( 0 ), - boost::counting_iterator( simplex.size() ) ); - - for(std::size_t t = 0; t < nb_iterations; ++t) - { - for(std::size_t i = 0; i < 4; ++i) - { - fitness[i] = compute_fitness_old(simplex[i], points); - } - - CGAL_assertion(fitness.size() == 4); - CGAL_assertion(indices.size() == 4); - - // get indices of sorted sequence - Comparator compare_indices(fitness); - std::sort(indices.begin(), indices.end(), compare_indices); - - // new sorted simplex & fitness - std::vector s_simplex(4); - std::vector s_fitness(4); - for(int i = 0; i < 4; ++i) - { - s_simplex[i] = simplex[indices[i]]; - s_fitness[i] = fitness[indices[i]]; - } - - simplex = s_simplex; - fitness = s_fitness; - - // centroid - const Vertex v_centroid = centroid(simplex[0], simplex[1], simplex[2]); - - // find worst's vertex reflection - const Vertex v_worst = simplex[3]; - const Vertex v_refl = reflection(v_centroid, v_worst); - const double f_refl = compute_fitness_old(v_refl, points); - - if(f_refl < fitness[2]) - { - if(f_refl >= fitness[0]) // if reflected point is not better than the best - { - // do reflection - simplex[3] = v_refl; - } - else - { - // expansion - const Vertex v_expand = expansion(v_centroid, v_worst, v_refl); - const double f_expand = compute_fitness_old(v_expand, points); - if(f_expand < f_refl) - simplex[3] = v_expand; - else - simplex[3] = v_refl; - } - } - else // if reflected vertex is not better - { - const Vertex v_mean = mean(v_centroid, v_worst); - const double f_mean = compute_fitness_old(v_mean, points); - if(f_mean <= fitness[3]) - // contraction of worst - simplex[3] = v_mean; - else - { - // reduction: move all vertices towards the best - for(std::size_t i=1; i < 4; ++i) - { - simplex[i] = mean(simplex[i], simplex[0]); - } - } - } - - CGAL_assertion(simplex.size() == 4); // tetrahedron - - } // iterations -} - -struct Random_int_generator -{ - Random_int_generator(int l, int h) : low(l), high(h) {} - - int operator() () - { - return random_gen.get_int(low, high); - } - - CGAL::Random random_gen; - int low; - int high; -}; - - -template -void genetic_algorithm(Population& pop, const Matrix& points) -{ - // random permutations - std::size_t m = pop.size(); - - //groups 1,2 : size m/2 groups 3,4 : size (m - m/2). m/2 is floored - std::size_t size_first_group = m/2; - std::size_t size_second_group = m - m/2; - - std::vector ids1(m/2), ids2(m/2); - std::vector ids3(m - m/2), ids4(m - m/2); - - CGAL::Random rng; - - //Random_int_generator rgen(0, m); - //std::generate(indices.begin(), indices.end(), rgen); - - std::generate(ids1.begin(), ids1.end(), - [&rng, &m] () - { return rng.get_int(0, m); }); - - std::generate(ids2.begin(), ids2.end(), - [&rng, &m] () - { return rng.get_int(0, m); }); - - std::generate(ids3.begin(), ids3.end(), - [&rng, &m] () - { return rng.get_int(0, m); }); - - std::generate(ids4.begin(), ids4.end(), - [&rng, &m] () - { return rng.get_int(0, m); }); - - Population group1(m/2), group2(m/2); - Population group3(m - m/2), group4(m - m/2); - - for(std::size_t i = 0; i < ids1.size(); ++i) - group1[i] = pop[ids1[i]]; - - for(std::size_t i = 0; i < ids2.size(); ++i) - group2[i] = pop[ids2[i]]; - - for(std::size_t i = 0; i < ids3.size(); ++i) - group3[i] = pop[ids3[i]]; - - for(std::size_t i = 0; i < ids4.size(); ++i) - group4[i] = pop[ids4[i]]; - -#ifdef OBB_DEBUG - check_det(group1); - check_det(group2); - check_det(group3); - check_det(group4); -#endif - - // crossover I - Population offspringsA(size_first_group); - double bias = 0.1; - - for(int i = 0; i < size_first_group; ++i) - { - std::vector offspring(4); - for(int j = 0; j < 4; ++j) - { - double r = rng.get_double(); - double fitnessA = compute_fitness_old(group1[i][j], points); - double fitnessB = compute_fitness_old(group2[i][j], points); - double threshold; - if(fitnessA < fitnessB) - threshold = 0.5 + bias; - else - threshold = 0.5 - bias; - if(r < threshold) // choose A - offspring[j] = group1[i][j]; - else // choose B - offspring[j] = group2[i][j]; - } - offspringsA[i] = offspring; - } - -#ifdef OBB_DEBUG - std::cout << "offspringsA: \n" ; - check_det(offspringsA); - std::cin.get(); -#endif - - // crossover II - Population offspringsB(size_second_group); - bias = 0.1; - - for(int i = 0; i < size_second_group; ++i) - { - std::vector offspring(4); - for(int j = 0; j < 4; ++j) - { - double fitnessA = compute_fitness_old(group3[i][j], points); - double fitnessB = compute_fitness_old(group4[i][j], points); - double lambda; - if(fitnessA < fitnessB) - lambda = 0.5 + bias; - else - lambda = 0.5 - bias; - // combine information from A and B - offspring[j] = lambda * group3[i][j] + lambda * group4[i][j]; - - } - - // qr factorization of the offspring - qr_factorization(offspring); - - - offspringsB[i] = offspring; - } - -#ifdef OBB_DEBUG - std::cout << "offspringsB: \n" ; - check_det(offspringsB); -#endif - - CGAL_assertion(offspringsA.size() == size_first_group); - CGAL_assertion(offspringsB.size() == size_second_group); - CGAL_assertion(offspringsA.size() + offspringsB.size() == pop.size()); - - // next generatrion - for(std::size_t i = 0; i < size_first_group; ++i) - { - pop[i] = offspringsA[i]; - } - - for(std::size_t i = 0; i < size_second_group; ++i) - { - pop[size_first_group + i] = offspringsB[i]; - } - -} -*/ - -#ifdef OBB_DEBUG -template -void check_det(Population& pop) -{ - for(int i = 0; i < pop.size(); ++i) - { - for(int j = 0; j < 4; ++j) - { - auto A = pop[i][j]; // Simplex - //std::cout << A.determinant() << std::endl; - std::cout << determinant(A) << std::endl; - } - } -} -#endif - - -} } // end namespaces - - - - - - - -#endif //CGAL_OPTIMAL_BOUNDING_BOX_OPTIMIZATION_ALGORITHMS_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index a68d4639b21..1c34cd4a230 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -24,22 +24,17 @@ #include #include -#include #include - #if defined(CGAL_EIGEN3_ENABLED) #include #endif - - +//#define OBB_DEBUG namespace CGAL { namespace Optimal_bounding_box { - - template class Population { @@ -66,26 +61,11 @@ public: } } - void show_population() - { - std::size_t id = 0; - for(const Simplex i : pop) - { - CGAL_assertion(i.size() == 4); - std:: cout << "Simplex: "<< id++ << std::endl; - for(const Matrix R : i) - { - std::cout << R; // eigen out - std::cout << "\n\n"; - } - std:: cout << std:: endl; - } - } + #ifdef OBB_DEBUG + void show_population(); + #endif - std::size_t size() - { - return n; - } + std::size_t size(){return n;} // access simplex Simplex& operator[](std::size_t i) @@ -109,15 +89,10 @@ private: for(std::size_t i = 0; i < 4; ++i) { Matrix R; - // R may be preallocated, if Vertex is Matrix3d, - // but Vertex may not, if Vertex is MatrixXd and R is constructed with MatrixXd R(3,3) if(R.cols() == 0 || R.rows() == 0) R.resize(3, 3); create_vertex(R); - //Matrix Q; // no allocation - //qr_factorization(R, Q); - //R.qr_factorization(Q); Matrix Q = Linear_algebra_traits::qr_factorization(R); simplex[i] = Q; @@ -134,7 +109,6 @@ private: { for(std::size_t j = 0; j < 3; ++j) { - //R.coeffRef(i, j) = random_generator.get_double(); R.set_coef(i, j, random_generator.get_double()); } } @@ -146,6 +120,26 @@ private: }; +#ifdef OBB_DEBUG +template +void Population::show_population() +{ + std::size_t id = 0; + for(const Simplex i : pop) + { + CGAL_assertion(i.size() == 4); + std:: cout << "Simplex: "<< id++ << std::endl; + for(const Matrix R : i) + { + std::cout << R; // eigen out + std::cout << "\n\n"; + } + std:: cout << std:: endl; + } +} +#endif + + } } // end namespaces diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index a7834453d2c..d800f537e32 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -6,8 +6,6 @@ #include -typedef Eigen::Matrix3d Matrix3d; - bool assert_doubles(double d1, double d2, double epsilon) { return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; @@ -16,12 +14,6 @@ bool assert_doubles(double d1, double d2, double epsilon) void test_qr_factorization() { CGAL::Eigen_dense_matrix A(3, 3); - /* - A << 0.3011944, 0.9932761, 0.5483701, - 0.5149142, 0.5973263, 0.5162336, - 0.0039213, 0.0202949, 0.9240308; - */ - A.set_coef(0, 0, 0.3011944); A.set_coef(0, 1, 0.9932761); A.set_coef(0, 2, 0.5483701); @@ -32,15 +24,9 @@ void test_qr_factorization() A.set_coef(2, 1, 0.0202949); A.set_coef(2, 2, 0.9240308); - //CGAL::Eigen_dense_matrix Q; - - //CGAL::Optimal_bounding_box::qr_factorization(A, Q); - //A.qr_factorization(Q); CGAL::Eigen_dense_matrix Q = CGAL::Eigen_linear_algebra_traits::qr_factorization(A); - - CGAL_assertion_code(double epsilon = 1e-6); CGAL_assertion(assert_doubles(Q(0,0), -0.504895, epsilon)); CGAL_assertion(assert_doubles(Q(0,1), 0.862834, epsilon)); @@ -55,7 +41,6 @@ void test_qr_factorization() void test_fitness_function() { - typedef typename CGAL::Eigen_linear_algebra_traits::MatrixXd MatrixXd; MatrixXd data_points(4, 3); @@ -75,7 +60,6 @@ void test_fitness_function() data_points.set_coef(3, 1, 0.149912); data_points.set_coef(3, 2, 0.364944); - typedef typename CGAL::Eigen_linear_algebra_traits::Matrix3d Matrix3d; Matrix3d rotation; rotation.set_coef(0, 0, -0.809204); @@ -91,20 +75,12 @@ void test_fitness_function() CGAL_assertion_code(typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits); CGAL_assertion_code(double fitness = CGAL::Optimal_bounding_box:: compute_fitness (rotation, data_points)); - CGAL_assertion(assert_doubles(fitness, 0.58606, 1e-5)); } void test_simplex_operations() { - //Matrix3d Sc(3, 3); CGAL::Eigen_dense_matrix Sc(3, 3); - /* - Sc << -0.809204, 0.124296, 0.574230, - -0.574694, 0.035719, -0.817589, - -0.122134, -0.991602, 0.042528; - */ - Sc.set_coef(0, 0, -0.809204); Sc.set_coef(0, 1, 0.124296); Sc.set_coef(0, 2, 0.574230); @@ -115,16 +91,7 @@ void test_simplex_operations() Sc.set_coef(2, 1, -0.991602); Sc.set_coef(2, 2, 0.042528); - - CGAL::Eigen_dense_matrix S_worst(3, 3); - /* - S_worst << -0.45070, -0.32769, -0.83035, - -0.13619, -0.89406, 0.42675, - -0.88222, 0.30543, 0.35833; - */ - - S_worst.set_coef(0, 0, -0.45070); S_worst.set_coef(0, 1, -0.32769); S_worst.set_coef(0, 2, -0.83035); @@ -135,7 +102,6 @@ void test_simplex_operations() S_worst.set_coef(2, 1, 0.30543); S_worst.set_coef(2, 2, 0.35833); - CGAL::Eigen_dense_matrix Sr = CGAL::Optimal_bounding_box::reflection(Sc, S_worst); CGAL_assertion_code(double epsilon = 1e-5); CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); @@ -160,13 +126,6 @@ void test_simplex_operations() CGAL_assertion(assert_doubles(Se(2,2), 0.74300, epsilon)); CGAL::Eigen_dense_matrix S_a(3, 3); - /* - S_a << -0.277970, 0.953559, 0.116010, - -0.567497, -0.065576, -0.820760, - -0.775035, -0.293982, 0.559370; - */ - - S_a.set_coef(0, 0, -0.277970); S_a.set_coef(0, 1, 0.953559); S_a.set_coef(0, 2, 0.116010); @@ -177,15 +136,7 @@ void test_simplex_operations() S_a.set_coef(2, 1, -0.293982); S_a.set_coef(2, 2, 0.559370); - CGAL::Eigen_dense_matrix S_b(3, 3); - /* - S_b << -0.419979, 0.301765, -0.855894, - -0.653011, -0.755415, 0.054087, - -0.630234, 0.581624, 0.514314; - */ - - S_b.set_coef(0, 0, -0.419979); S_b.set_coef(0, 1, 0.301765); S_b.set_coef(0, 2, -0.8558940); @@ -196,7 +147,6 @@ void test_simplex_operations() S_b.set_coef(2, 1, 0.581624); S_b.set_coef(2, 2, 0.514314); - CGAL::Eigen_dense_matrix S_c = CGAL::Optimal_bounding_box::mean(S_a, S_b); CGAL_assertion(assert_doubles(S_c(0,0), -0.35111, epsilon)); CGAL_assertion(assert_doubles(S_c(0,1), 0.79308, epsilon)); @@ -212,12 +162,6 @@ void test_simplex_operations() void test_centroid() { CGAL::Eigen_dense_matrix S_a; - /* - S_a << -0.588443, 0.807140, -0.047542, - -0.786228, -0.584933, -0.199246, - -0.188629, -0.079867, 0.978795; - */ - S_a.set_coef(0, 0, -0.588443); S_a.set_coef(0, 1, 0.807140); S_a.set_coef(0, 2, -0.047542); @@ -229,12 +173,6 @@ void test_centroid() S_a.set_coef(2, 2, 0.978795); CGAL::Eigen_dense_matrix S_b(3, 3); - /* - S_b << -0.2192721, 0.2792986, -0.9348326, - -0.7772152, -0.6292092, -0.0056861, - -0.5897934, 0.7253193, 0.3550431; - */ - S_b.set_coef(0, 0, -0.2192721); S_b.set_coef(0, 1, 0.2792986); S_b.set_coef(0, 2, -0.9348326); @@ -246,12 +184,6 @@ void test_centroid() S_b.set_coef(2, 2, 0.3550431); CGAL::Eigen_dense_matrix S_c(3, 3); - /* - S_c << -0.32657, -0.60013, -0.73020, - -0.20022, -0.71110, 0.67398, - -0.92372, 0.36630, 0.11207; - */ - S_c.set_coef(0, 0, -0.32657); S_c.set_coef(0, 1, -0.60013); S_c.set_coef(0, 2, -0.730206); @@ -276,7 +208,6 @@ void test_centroid() CGAL_assertion(assert_doubles(S_centroid(2,2), 0.514314, epsilon)); } - void test_eigen_matrix_interface() { CGAL::Eigen_dense_matrix A(3, 3); @@ -289,11 +220,8 @@ void test_eigen_matrix_interface() A.set_coef(2, 0, 0.7); A.set_coef(2, 1, 0.8); A.set_coef(2, 2, 0.9); - //CGAL::Eigen_dense_matrix B = A.transpose(); CGAL::Eigen_dense_matrix B = CGAL::Eigen_linear_algebra_traits::transpose(A); - CGAL::Eigen_dense_matrix S = 0.5 * A; - CGAL::Eigen_dense_matrix C(3,3); C.set_coef(0, 0, 0.3011944); C.set_coef(0, 1, 0.9932761); @@ -305,8 +233,6 @@ void test_eigen_matrix_interface() C.set_coef(2, 1, 0.0202949); C.set_coef(2, 2, 0.9240308); - //C.qr_factorization(Q); - CGAL::Eigen_dense_matrix Q = CGAL::Eigen_linear_algebra_traits::qr_factorization(C); @@ -357,7 +283,6 @@ void test_eigen_matrix_interface() int main() { - test_qr_factorization(); test_fitness_function(); test_simplex_operations(); diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 7094c249154..82ff3d2e17c 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -1,8 +1,8 @@ #include #include -#include #include #include +#include #include #include @@ -16,62 +16,6 @@ bool assert_doubles(double d1, double d2, double epsilon) return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; } -template -void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) -{ - typedef typename boost::property_map::const_type Vpm; - typedef typename boost::property_traits::reference Point_ref; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - Vpm vpm = get(boost::vertex_point, sm); - - mat.resize(vertices(sm).size(), 3); - std::size_t i = 0; - for(vertex_descriptor v : vertices(sm)) - { - Point_ref p = get(vpm, v); - mat.set_coef(i, 0, p.x()); - mat.set_coef(i, 1, p.y()); - mat.set_coef(i, 2, p.z()); - ++i; - } -} - -// it is called after post processing -template -void matrix_to_mesh_and_draw(Matrix& data_points, std::string filename) -{ - typedef CGAL::Simple_cartesian K; - typedef K::Point_3 Point; - typedef CGAL::Surface_mesh Mesh; - - // Simplex -> std::vector - std::vector points; - - for(int i = 0; i < data_points.rows(); ++i) - { - Point p(data_points(i, 0), data_points(i, 1), data_points(i, 2)); - points.push_back(p); - } - - Mesh mesh; - CGAL::make_hexahedron(points[0], points[1], points[2], points[3], points[4], points[5], - points[6], points[7], mesh); - - std::ofstream out(filename); - out << mesh; - out.close(); -} - -template -double calculate_volume(std::vector points) -{ - CGAL::Bbox_3 bbox; - bbox = bbox_3(points.begin(), points.end()); - K::Iso_cuboid_3 ic(bbox); - return ic.volume(); -} - - void test_nelder_mead() { typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; @@ -99,7 +43,6 @@ void test_nelder_mead() Matrix3d v2(3,3); Matrix3d v3(3,3); - v0(0,0) = -0.2192721; v0(0,1) = 0.2792986, v0(0,2) = -0.9348326, @@ -227,8 +170,9 @@ void test_genetic_algorithm() void test_random_unit_tetra() { // this is dynamic at run times - CGAL::Eigen_dense_matrix data_points(4, 3); // points on their convex hull + CGAL::Eigen_dense_matrix data_points(4, 3); + // points are on their convex hull data_points(0,0) = 0.866802; data_points(0,1) = 0.740808, data_points(0,2) = 0.895304, @@ -242,7 +186,6 @@ void test_random_unit_tetra() data_points(3,1) = 0.149912, data_points(3,2) = 0.364944; - typedef CGAL::Simple_cartesian K; typedef K::Point_3 Point; typedef CGAL::Surface_mesh Mesh; @@ -261,19 +204,16 @@ void test_random_unit_tetra() out.close(); #endif - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; typedef Linear_algebra_traits::Matrix3d Matrix3d; std::size_t generations = 10; - CGAL::Optimal_bounding_box::Population pop(50); CGAL::Optimal_bounding_box::Evolution evolution(pop, data_points); evolution.evolve(generations); Matrix3d R = evolution.get_best(); - CGAL_assertion_code(double epsilon = 1e-3); CGAL_assertion(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); CGAL_assertion(assert_doubles(R(0,0), -0.25791, epsilon)); @@ -290,11 +230,10 @@ void test_random_unit_tetra() // postprocessing CGAL::Eigen_dense_matrix obb(8, 3); CGAL::Optimal_bounding_box::post_processing(data_points, R, obb); - matrix_to_mesh_and_draw(obb, "data/random_unit_tetra_result.off"); + CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, "data/random_unit_tetra_result.off"); #endif } - void test_reference_tetrahedron(const char* fname) { std::ifstream input(fname); @@ -310,7 +249,7 @@ void test_reference_tetrahedron(const char* fname) // points in a matrix MatrixXd points; - sm_to_matrix(mesh, points); + CGAL::Optimal_bounding_box::sm_to_matrix(mesh, points); std::size_t generations = 10; CGAL::Optimal_bounding_box::Population pop(50); @@ -326,7 +265,7 @@ void test_reference_tetrahedron(const char* fname) // postprocessing MatrixXd obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points, R, obb); - matrix_to_mesh_and_draw(obb, "data/OBB.off"); + CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, "data/OBB.off"); #endif } @@ -345,7 +284,7 @@ void test_long_tetrahedron(std::string fname) // points in a matrix MatrixXd points; - sm_to_matrix(mesh, points); + CGAL::Optimal_bounding_box::sm_to_matrix(mesh, points); std::size_t max_generations = 10; CGAL::Optimal_bounding_box::Population pop(50); @@ -372,51 +311,10 @@ void test_long_tetrahedron(std::string fname) // postprocessing MatrixXd obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points, R, obb); - matrix_to_mesh_and_draw(obb, fname + "result.off"); + CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, fname + "result.off"); #endif } -/* -void test_find_obb(std::string fname) -{ - std::ifstream input(fname); - typedef CGAL::Surface_mesh SMesh; - SMesh mesh; - if (!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << fname << " is not a valid off file.\n"; - exit(1); - } - - // get mesh points - std::vector sm_points; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::property_map::const_type PointPMap; - PointPMap pmap = get(boost::vertex_point, mesh); - BOOST_FOREACH(vertex_descriptor v, vertices(mesh)) - sm_points.push_back(get(pmap, v)); - - std::vector obb_points; - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true, true); - - double epsilon = 1e-3; - double vol = calculate_volume(obb_points); - CGAL_assertion(assert_doubles(vol, 0.883371, epsilon)); - - #ifdef OBB_DEBUG_TEST - for(int i = 0; i < 8; ++i) - std::cout << obb_points[i].x() << " " << obb_points[i].y() << " " << obb_points[i].z() << "\n" ; - CGAL::Surface_mesh result_mesh; - CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], - obb_points[4], obb_points[5], obb_points[6], obb_points[7], result_mesh); - - std::ofstream out("data/obb_result.off"); - out << result_mesh; - out.close(); - #endif -} -*/ - - void test_find_obb_evolution(std::string fname) { std::ifstream input(fname); @@ -438,7 +336,7 @@ void test_find_obb_evolution(std::string fname) CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true); // maybe use algebra parameter here CGAL_assertion_code(double epsilon = 1e-3); - CGAL_assertion_code(double vol = calculate_volume(obb_points)); + CGAL_assertion_code(double vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points)); CGAL_assertion(assert_doubles(vol, 0.883371, epsilon)); #ifdef OBB_DEBUG_TEST @@ -475,21 +373,15 @@ void test_find_obb_mesh(std::string fname) #endif } - - int main() { - // test_population(); test_nelder_mead(); test_genetic_algorithm(); test_random_unit_tetra(); test_reference_tetrahedron("data/reference_tetrahedron.off"); test_long_tetrahedron("data/long_tetrahedron.off"); - //test_find_obb("data/random_unit_tetra.off"); - test_find_obb_evolution("data/random_unit_tetra.off"); test_find_obb_mesh("data/elephant.off"); - return 0; } From 10c87d33260d58e0b4453d1adcb914eeb7b538d3 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Wed, 16 May 2018 14:18:18 +0200 Subject: [PATCH 027/150] API linear algebra parameter --- .../Optimal_bounding_box/bench_custom.cpp | 5 ++-- .../Optimal_bounding_box/bench_obb.cpp | 7 +++-- .../Optimal_bounding_box/bench_perfomance.cpp | 7 +++-- .../CGAL/Optimal_bounding_box/helper.h | 1 - .../include/CGAL/Optimal_bounding_box/obb.h | 28 ++++++++++--------- .../test_optimization_algorithms.cpp | 7 +++-- .../Plugins/PCA/Create_obb_mesh_plugin.cpp | 4 ++- 7 files changed, 34 insertions(+), 25 deletions(-) diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp index aad2ef10026..fcc2c64deb6 100644 --- a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp @@ -1,8 +1,8 @@ #include #include -#include #include #include +#include #include #include @@ -33,7 +33,8 @@ bench(const char* fname) std::cout << "input data (points + normals)= " << i << std::endl; std::cout << "number of points= " << sm_points.size() << std::endl; - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, false); + CGAL::Eigen_linear_algebra_traits la_traits; + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, la_traits, false); std::cout << "done" << '\n'; diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp index a3daafffb5a..85d3287be9f 100644 --- a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -56,9 +55,11 @@ void bench_finding_obb(std::string fname) CGAL::Timer timer; timer.start(); + CGAL::Eigen_linear_algebra_traits la_traits; + // 1) using convex hull std::vector obb_points1; - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points1, true); + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points1, la_traits, true); timer.stop(); std::cout << "found obb with convex hull: " << timer.time() << " seconds\n"; @@ -68,7 +69,7 @@ void bench_finding_obb(std::string fname) // 2) without convex hull std::vector obb_points2; - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points2, false); + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points2, la_traits, false); timer.stop(); diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp index dddbcf791cb..49778276e7c 100644 --- a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp @@ -1,8 +1,8 @@ #include #include -#include #include #include +#include #include #include @@ -26,6 +26,7 @@ void bench_finding_obb(std::string fname) CGAL::Timer timer; std::size_t measurements = 4; + CGAL::Eigen_linear_algebra_traits la_traits; for (std::size_t t = 0; t < measurements; ++t) { @@ -35,7 +36,7 @@ void bench_finding_obb(std::string fname) // 1) using convex hull CGAL::Surface_mesh obb_mesh1; - CGAL::Optimal_bounding_box::find_obb(mesh, obb_mesh1, true); + CGAL::Optimal_bounding_box::find_obb(mesh, obb_mesh1, la_traits, true); timer.stop(); std::cout << " with ch: " << timer.time() << " s |"; @@ -45,7 +46,7 @@ void bench_finding_obb(std::string fname) // 2) without convex hull CGAL::Surface_mesh obb_mesh2; - CGAL::Optimal_bounding_box::find_obb(mesh, obb_mesh2, false); + CGAL::Optimal_bounding_box::find_obb(mesh, obb_mesh2, la_traits, false); timer.stop(); diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h index 5c4de4bac0f..e9c3a5eadb0 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h @@ -29,7 +29,6 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; - namespace CGAL { namespace Optimal_bounding_box { diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index b050261f710..a5d6ec79354 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -91,9 +91,11 @@ void post_processing(const Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) obb = aabb * R; } -// with linear algebra traits -template -void find_obb(std::vector& points, std::vector& obb_points, bool use_ch) +template +void find_obb(std::vector& points, + std::vector& obb_points, + LinearAlgebraTraits&, + bool use_ch) { CGAL_assertion(points.size() >= 3); @@ -101,10 +103,9 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u obb_points.resize(8); CGAL_assertion(obb_points.size() == 8); - // could be used from a t. parameter - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - typedef typename Linear_algebra_traits::MatrixXd MatrixXd; - typedef typename Linear_algebra_traits::Matrix3d Matrix3d; + // eigen linear algebra traits + typedef typename LinearAlgebraTraits::MatrixXd MatrixXd; + typedef typename LinearAlgebraTraits::Matrix3d Matrix3d; MatrixXd points_mat; @@ -128,7 +129,7 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u std::size_t max_generations = 100; Population pop(50); - CGAL::Optimal_bounding_box::Evolution + CGAL::Optimal_bounding_box::Evolution search_solution(pop, points_mat); search_solution.evolve(max_generations); Matrix3d rotation = search_solution.get_best(); @@ -149,10 +150,11 @@ void find_obb(std::vector& points, std::vector& obb_points, bool u /// @param pmesh the input mesh. /// @param obbmesh the obb in a hexahedron pmesh. /// @param use convex hull or not. -/// -/// todo named parameters: max iterations, population size, tolerance. -template -void find_obb(PolygonMesh& pmesh, PolygonMesh& obbmesh, bool use_ch) +template +void find_obb(PolygonMesh& pmesh, + PolygonMesh& obbmesh, + LinearAlgrebraTraits& la_traits, + bool use_ch) { CGAL_assertion(vertices(pmesh).size() >= 3); @@ -173,7 +175,7 @@ void find_obb(PolygonMesh& pmesh, PolygonMesh& obbmesh, bool use_ch) points.push_back(get(pmap, v)); std::vector obb_points; - find_obb(points, obb_points, use_ch); + find_obb(points, obb_points, la_traits, use_ch); CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], obb_points[4], obb_points[5], diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 82ff3d2e17c..ae8e1879d95 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -332,8 +332,10 @@ void test_find_obb_evolution(std::string fname) BOOST_FOREACH(vertex_descriptor v, vertices(mesh)) sm_points.push_back(get(pmap, v)); + + CGAL::Eigen_linear_algebra_traits la_traits; std::vector obb_points; - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true); // maybe use algebra parameter here + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, la_traits, true); CGAL_assertion_code(double epsilon = 1e-3); CGAL_assertion_code(double vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points)); @@ -363,8 +365,9 @@ void test_find_obb_mesh(std::string fname) exit(1); } + CGAL::Eigen_linear_algebra_traits la_traits; CGAL::Surface_mesh< K::Point_3> obbmesh; - CGAL::Optimal_bounding_box::find_obb(mesh, obbmesh, true); + CGAL::Optimal_bounding_box::find_obb(mesh, obbmesh, la_traits, true); #ifdef OBB_DEBUG_TEST std::ofstream out("/tmp/result_elephant.off"); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp index 70b8f765731..9dbf9da1da7 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp @@ -15,6 +15,7 @@ #include #include +#include //typedef Scene_surface_mesh_item Scene_facegraph_item; //typedef Scene_facegraph_item Scene_facegraph_item; @@ -163,8 +164,9 @@ void Create_obb_mesh_plugin::obb() gather_mesh_points(points); // find obb + CGAL::Eigen_linear_algebra_traits la_traits; std::vector obb_points(8); - CGAL::Optimal_bounding_box::find_obb(points, obb_points, true); + CGAL::Optimal_bounding_box::find_obb(points, obb_points, la_traits, true); Scene_item* item; if(mw->property("is_polyhedorn_mode").toBool()) From 819e38d6a13e58e4f856031330e3fd58d6c1f22d Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Thu, 17 May 2018 11:03:55 +0200 Subject: [PATCH 028/150] making sure that all matrix allocations happen at compile time when possible --- .../Optimal_bounding_box/bench_obb.cpp | 29 ++++++++++++------- .../CGAL/Optimal_bounding_box/evolution.h | 11 ++++--- .../Optimal_bounding_box/fitness_function.h | 17 ++++------- .../Optimal_bounding_box/linear_algebra.h | 26 +---------------- .../include/CGAL/Optimal_bounding_box/obb.h | 14 ++++----- .../test_optimization_algorithms.cpp | 10 +++---- .../CGAL/Eigen_linear_algebra_traits.h | 20 +++++++------ 7 files changed, 52 insertions(+), 75 deletions(-) diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp index 85d3287be9f..fb759595d1f 100644 --- a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp @@ -1,7 +1,10 @@ #include #include +#include +#include #include #include +#include #include #include @@ -41,6 +44,7 @@ void bench_finding_obb(std::string fname) { std::ifstream input(fname); + CGAL::Eigen_linear_algebra_traits la_traits; std::vector sm_points; // import a mesh @@ -53,26 +57,29 @@ void bench_finding_obb(std::string fname) gather_mesh_points(mesh, sm_points); CGAL::Timer timer; + + // 1) measure convex hull calculation timer.start(); - - CGAL::Eigen_linear_algebra_traits la_traits; - - // 1) using convex hull - std::vector obb_points1; - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points1, la_traits, true); - + CGAL::Polyhedron_3 poly; + convex_hull_3(sm_points.begin(), sm_points.end(), poly); + std::vector ch_points(poly.points_begin(), poly.points_end()); timer.stop(); - std::cout << "found obb with convex hull: " << timer.time() << " seconds\n"; + std::cout << "takes : " << timer.time() << " seconds to find the convex hull\n"; + // 2) using convex hull timer.reset(); timer.start(); + std::vector obb_points1; + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points1, la_traits, true); + timer.stop(); + std::cout << "found obb using convex hull: " << timer.time() << " seconds\n"; - // 2) without convex hull + // 3) without convex hull + timer.reset(); + timer.start(); std::vector obb_points2; CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points2, la_traits, false); - timer.stop(); - std::cout << "found obb without convex hull: " << timer.time() << " seconds\n"; timer.reset(); diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index 30cd901b912..dee4d14a48e 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -19,7 +19,6 @@ // // Author(s) : Konstantinos Katrioplas - #ifndef CGAL_EVOLUTION_H #define CGAL_EVOLUTION_H @@ -34,7 +33,7 @@ namespace Optimal_bounding_box { template class Evolution { - typedef typename Linear_algebra_traits::MatrixXd MatrixXd; + typedef typename Linear_algebra_traits::MatrixX3d MatrixXd; typedef typename Linear_algebra_traits::Matrix3d Matrix3d; typedef typename Linear_algebra_traits::Vector3d Vector3d; @@ -280,14 +279,14 @@ public: //std::cout << "pop after nelder mead: " << std::endl; //pop.show_population(); //std::cout << std::endl; - Fitness_map fitness_map_debug(population, point_data); + Fitness_map fitness_map_debug(population, point_data); Matrix3d R_now = fitness_map_debug.get_best(); std::cout << "det= " << Linear_algebra_traits::determinant(R_now) << std::endl; #endif // stopping criteria - Fitness_map fitness_map(population, point_data); - new_fit_value = fitness_map.get_best_fitness_value(point_data); + Fitness_map fitness_map(population, point_data); + new_fit_value = fitness_map.get_best_fitness_value(); double difference = new_fit_value - prev_fit_value; if(abs(difference) < tolerance * new_fit_value) stale++; @@ -301,7 +300,7 @@ public: const Matrix3d get_best() { - Fitness_map fitness_map(population, point_data); + Fitness_map fitness_map(population, point_data); return fitness_map.get_best(); } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 8f00286f0ed..981ab6bdb49 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -27,14 +27,11 @@ #include #include -#include - namespace CGAL { namespace Optimal_bounding_box { -template -double compute_fitness(const typename Linear_algebra_traits::Matrix3d& R, - typename Linear_algebra_traits::MatrixXd& data) +template +double compute_fitness(const Vertex& R, const Matrix& data) { // R: rotation matrix CGAL_assertion(R.cols() == 3); @@ -73,11 +70,9 @@ double compute_fitness(const typename Linear_algebra_traits::Matrix3d& R, return ((xmax - xmin) * (ymax - ymin) * (zmax - zmin)); } -template +template struct Fitness_map { - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; // to be added as a parameter - Fitness_map(Population& p, Matrix& points) : pop(p), points(points) {} @@ -103,14 +98,14 @@ struct Fitness_map return pop[simplex_id][vertex_id]; } - double get_best_fitness_value(Matrix& data) + double get_best_fitness_value() { const Vertex best_mat = get_best(); - return compute_fitness(best_mat, data); + return compute_fitness(best_mat, points); } Population& pop; - Matrix& points; + const Matrix& points; }; }} // end namespaces diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h index 1f9dedff815..e7dbe3fc99c 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h @@ -38,26 +38,6 @@ namespace Optimal_bounding_box { typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; #endif -/* -template -void qr_factorization(Matrix& A, Matrix& Q) -{ - Eigen::HouseholderQR qr(A); - Q = qr.householderQ(); -} - -template -void qr_factorization(std::vector& Simplex) -{ - for(int i = 0; i < Simplex.size(); ++i) - { - Eigen::HouseholderQR qr(Simplex[i]); - Matrix Q = qr.householderQ(); - Simplex[i] = Q; - } -} -*/ - template const Matrix reflection(const Matrix& S_centroid, const Matrix& S_worst) { @@ -92,19 +72,15 @@ Matrix mean(const Matrix& m1, const Matrix& m2) CGAL_assertion(m2.cols() == 3); Matrix reduction = 0.5 * m1 + 0.5 * m2; - //Matrix Q; - //reduction.qr_factorization(Q); Matrix Q = Linear_algebra_traits::qr_factorization(reduction); double det = Linear_algebra_traits::determinant(Q); return Q / det; } template -const Matrix centroid(Matrix& S1, Matrix& S2, Matrix& S3) // const? +const Matrix centroid(const Matrix& S1, const Matrix& S2, const Matrix& S3) { Matrix mean = (S1 + S2 + S3) / 3.0; - //Matrix Q; - //mean.qr_factorization(Q); Matrix Q = Linear_algebra_traits::qr_factorization(mean); double det = Linear_algebra_traits::determinant(Q); return Q / det; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index a5d6ec79354..6b23f6350b3 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -49,8 +49,8 @@ typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; // works on matrices only -template -void post_processing(const Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) +template +void post_processing(const Matrix& points, Vertex& R, Matrix& obb) { CGAL_assertion(points.cols() == 3); CGAL_assertion(R.rows() == 3); @@ -59,7 +59,7 @@ void post_processing(const Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) CGAL_assertion(obb.cols() == 3); // 1) rotate points with R - Matrix_dynamic rotated_points(points.rows(), points.cols()); + Matrix rotated_points(points.rows(), points.cols()); rotated_points = points * Linear_algebra_traits::transpose(R); // 2) get AABB from rotated points @@ -75,10 +75,8 @@ void post_processing(const Matrix_dynamic& points, Vertex& R, Matrix_fixed& obb) bbox = bbox_3(v_points.begin(), v_points.end()); K::Iso_cuboid_3 ic(bbox); - Matrix_fixed aabb; - // preallocate sanity: if Matrix is not preallocated in compile time - if(aabb.cols() != 3 && aabb.rows() != 8) - aabb.resize(8, 3); + // Matrix is [dynamic, 3] at compile time, so it needs allocation of rows at run time. + Matrix aabb(8, 3); for(std::size_t i = 0; i < 8; ++i) { @@ -104,7 +102,7 @@ void find_obb(std::vector& points, CGAL_assertion(obb_points.size() == 8); // eigen linear algebra traits - typedef typename LinearAlgebraTraits::MatrixXd MatrixXd; + typedef typename LinearAlgebraTraits::MatrixX3d MatrixXd; typedef typename LinearAlgebraTraits::Matrix3d Matrix3d; MatrixXd points_mat; diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index ae8e1879d95..763ed60fbd6 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -20,7 +20,7 @@ void test_nelder_mead() { typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; typedef Linear_algebra_traits::Matrix3d Matrix3d; - typedef Linear_algebra_traits::MatrixXd MatrixXd; + typedef Linear_algebra_traits::MatrixX3d MatrixXd; MatrixXd data_points(4,3); data_points(0,0) = 0.866802; @@ -143,7 +143,7 @@ void test_nelder_mead() void test_genetic_algorithm() { - CGAL::Eigen_dense_matrix data_points(4, 3); + CGAL::Eigen_dense_matrix data_points(4, 3); // -1 : dynamic size at run time data_points(0,0) = 0.866802; data_points(0,1) = 0.740808, data_points(0,2) = 0.895304, @@ -170,7 +170,7 @@ void test_genetic_algorithm() void test_random_unit_tetra() { // this is dynamic at run times - CGAL::Eigen_dense_matrix data_points(4, 3); + CGAL::Eigen_dense_matrix data_points(4, 3); // points are on their convex hull data_points(0,0) = 0.866802; @@ -244,7 +244,7 @@ void test_reference_tetrahedron(const char* fname) } typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - typedef Linear_algebra_traits::MatrixXd MatrixXd; + typedef Linear_algebra_traits::MatrixX3d MatrixXd; typedef Linear_algebra_traits::Matrix3d Matrix3d; // points in a matrix @@ -279,7 +279,7 @@ void test_long_tetrahedron(std::string fname) } typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - typedef Linear_algebra_traits::MatrixXd MatrixXd; + typedef Linear_algebra_traits::MatrixX3d MatrixXd; typedef Linear_algebra_traits::Matrix3d Matrix3d; // points in a matrix diff --git a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h index 5da5e294e22..c1d2716c1cd 100644 --- a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h +++ b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h @@ -38,7 +38,6 @@ class Eigen_dense_matrix { public: typedef Eigen::Matrix EigenType; - typedef Eigen::Matrix EigenType3; Eigen_dense_matrix(std::size_t nrows, std::size_t ncols) : m_matrix(static_cast(nrows), static_cast(ncols)) @@ -94,7 +93,6 @@ template class Eigen_dense_vector { private: - //typedef Eigen::Vector3d EigenType; typedef Eigen::Matrix EigenType; public: @@ -119,11 +117,14 @@ public: // dynamic size at run time typedef CGAL::Eigen_dense_matrix MatrixXd; + // dynamic rows in run time, fixed cols in compile time + typedef CGAL::Eigen_dense_matrix MatrixX3d; + // fixed at compile time typedef CGAL::Eigen_dense_matrix Matrix3d; // fixed at compile time - typedef CGAL::Eigen_dense_vector Vector3d; + typedef CGAL::Eigen_dense_vector Vector3d; template static Matrix transpose(const Matrix& mat) @@ -155,11 +156,11 @@ public: } template - static CGAL::Eigen_dense_vector row(CGAL::Eigen_dense_matrix& A, int i_) + static CGAL::Eigen_dense_vector row(const CGAL::Eigen_dense_matrix& A, + int i) { - return CGAL::Eigen_dense_vector(A.m_matrix.row(i_)); + return CGAL::Eigen_dense_vector(A.m_matrix.row(i)); } - }; @@ -214,7 +215,7 @@ const CGAL::Eigen_dense_matrix operator/ (const double& scalar, return CGAL::Eigen_dense_matrix (scalar / A.m_matrix); } -// addition - subtraction +// addition template const CGAL::Eigen_dense_matrix operator+ (const CGAL::Eigen_dense_matrix & A, const CGAL::Eigen_dense_matrix & B) @@ -224,9 +225,10 @@ const CGAL::Eigen_dense_matrix operator+ (const CGAL::Eigen_dense_ma // vector - matrix multiplication template -const Eigen_dense_vector operator* (const CGAL::Eigen_dense_matrix& A, CGAL::Eigen_dense_vector& V) +const Eigen_dense_vector operator* (const CGAL::Eigen_dense_matrix& A, + const CGAL::Eigen_dense_vector& V) { - return Eigen_dense_vector(A.m_matrix * V.m_vector); + return Eigen_dense_vector(A.m_matrix * V.m_vector); } From d1865ac913c49d1b846057279b9aac8280c5bca4 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Thu, 17 May 2018 12:03:45 +0200 Subject: [PATCH 029/150] draw perfomance graph --- .../Optimal_bounding_box/bench_custom.cpp | 5 ++++- .../Optimal_bounding_box/bench_perfomance.cpp | 19 +++++++++++------- .../Optimal_bounding_box/data/linear.png | Bin 0 -> 25356 bytes .../draw_benchmark_graph.py | 18 +++++++++++++++++ 4 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 Optimal_bounding_box/benchmark/Optimal_bounding_box/data/linear.png create mode 100644 Optimal_bounding_box/benchmark/Optimal_bounding_box/draw_benchmark_graph.py diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp index fcc2c64deb6..7209f3a3346 100644 --- a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp @@ -34,7 +34,10 @@ bench(const char* fname) std::cout << "number of points= " << sm_points.size() << std::endl; CGAL::Eigen_linear_algebra_traits la_traits; - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, la_traits, false); + + // use convex hull - > true + // no convex hull - > false + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, la_traits, false); std::cout << "done" << '\n'; diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp index 49778276e7c..128a9f67f24 100644 --- a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp @@ -24,6 +24,10 @@ void bench_finding_obb(std::string fname) exit(1); } + // export some times + std::ofstream outt("data/times.txt"); + outt << "nb_vertices "<< "with_ch " << "without_ch" << std::endl; + CGAL::Timer timer; std::size_t measurements = 4; CGAL::Eigen_linear_algebra_traits la_traits; @@ -32,32 +36,33 @@ void bench_finding_obb(std::string fname) { std::cout << "#vertices= " << vertices(mesh).size() << " |"; - timer.start(); - // 1) using convex hull + timer.start(); CGAL::Surface_mesh obb_mesh1; CGAL::Optimal_bounding_box::find_obb(mesh, obb_mesh1, la_traits, true); - timer.stop(); + double t_ch = timer.time(); std::cout << " with ch: " << timer.time() << " s |"; + // 2) without convex hull timer.reset(); timer.start(); - - // 2) without convex hull CGAL::Surface_mesh obb_mesh2; CGAL::Optimal_bounding_box::find_obb(mesh, obb_mesh2, la_traits, false); - timer.stop(); - + double t_no_ch = timer.time(); std::cout << " without ch: " << timer.time() << " s\n"; timer.reset(); + outt << vertices(mesh).size() << " " << t_ch << " " << t_no_ch << std::endl; + // 3) subdivision CGAL::Subdivision_method_3::CatmullClark_subdivision(mesh, CGAL::parameters::number_of_iterations(1)); } + outt.close(); + #ifdef OBB_DEBUG_BENCHMARK std::ofstream out1("data/obb_result1.off"); diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/linear.png b/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/linear.png new file mode 100644 index 0000000000000000000000000000000000000000..edb4f44fc9887775259a16c1b62852a1e3ddfec1 GIT binary patch literal 25356 zcmeFZWmr~S6fOD!BGSHsgp?rNh?JxViUNulNSA_9lh0)vc6Ps;Mht!*`ba-{KmC#V#XYrFmBnZOlVxq2>Z9K( z?5`N;{le~kRUlNqB1k1TB2gzfzM@CbG;h07nY1^uQfZ#tvomaz7icZMCvlszqwq2s z{)A2$IAAcq9~)CP)O&w_e@6;zDdYpA)Htco1j%cz#czD%~~ z-$=Ezl7`7LP>v)awBirtkI#bT z49oTp4P{|uY(9`!4Io8XN;{WXDk*(HmRyc|roE|5tY}6ZS!eJ6dyw#XigXroDl03? zDJqs!k%pPgt*j^}i8+Zm69oIqS)`+4yu%|R0s;c2I%E0mqZz_)U}9pjsunWV*4Dz0 z3=D&JFnIkwr>CQ@UiB#}6H0#=**G|;!o@T#$l1XlA`)A7dKmcS3oHAJ?7szpU*G%B z-ox`0VT2Egi*HFwOT%``uc8h!TUc8Q4Gkr(J3AF^Z*QONiXU7Jmyux%+~#m0dYa{5 z&VS+>=s)|&1OtiQ!SFadDnTg)f{&cI#1far$L&?-UTiN_jpnNs89qso@-o$0uo8Y* zpx46nrEOVoLCiKeWMeLOB1y#2vj@LT5gi^bRa z2EKK5lBcJq_R;hV46D}#uKE&SbW|RTbYS{nCAkp&DN}K<5>&!Z2~;cfpiCrp=)Qc4 z3TdWG-J0&^97#T@!*)A8SRiFp@`Oo5G2FOeEleFm!Pn^2)%RFZac_0ZD@e1x$goRq zd8lCdPYJ$XlULJ}&Oo+mcb=&Gv2du^<|PaajAz*|!+Io+mcNxSGBIs5;`3a-a^-Du zGTl{<7q7ktQFbp3=4to1?Tz`t@0jGHUd^_Jeg6DeIN7rQ3mWd@%Q zdBtqV%Bf?bg%kf%TGtz!K2ntVhnR$z#hK-UqR$!WH)lKOUuvAHD;-wQXZc#)UbORF z=uVP!89vEH9wFj(cuUk_^@2hhyYlBtOM`h1S|n)no!77b8fcG{n5y^^QhnES7?V{{ zAmHQUvs?M|``~z}K!5R9I)0VITE?5DfpmI`3*ZKwa*S!d|f(|#N%BLHVX_o$j04|%(Yxr z1YYE65lX#$Ns;WfONon%+r3nG_>bcX3CUvrR}xfS^(G#_QTMBV{a=^Is-hQ?J(7~d zU2dO=X}KR5{D|U`uX8^^#R!^Tn{YqkvYqd&__sU+W88olFR&Q9ZP=64m91Jtx+){1 zr&qXlyMp}<#>jOK$5VymEcFcTDa9rp(}SuQpO&dUKQ_q%F^`({=q=ZX(D?j=_4%N| zkXq@d&dhJUy}v%sB7<$$pQ{-U`zFcb)aiQ&O$X$w2MP+auo-Td^#3i)+u7S=@i;x6 zZIAG~!t_vM*L7{YCXvf;=6mprH?f4y(m+nJ$?t!Kro`03_0uhZsx{66U2y_fDKH`3 z3uh;59wb+;G{W5w%+GQ)V$<%2ZcYdCZ2rs2yWOM`d`*Bt-1!y?3C_*g_H50nsQIq= zzCr`}&AE(29zY^pG$gDP>}1^>1#L8FyI|uRWNj`u96)AzK&5p^z+**xRdA zT~iY)>cCxM@>>sL+I77F$8~?oZ`A#0Mdien`(^(12$sj+M@Hg*L~`_HC{hjNYIa0C zmT=0cV?d+#o)^B_)nZXeCzB#4wY_axH}+X=Sd#wpleBw~Uv*T;s07VY+>UmiWxWUv zrV=WIRd`R%^JwlzWZqG&fJwiVdlHYf1SS@ii2d@=)x6-KpyrX0qxW3FsH45LOsyJc zO8Xbay(t(F3e>ed7sW;yxIxH$jrRCn3;TqjO=24t=o~X z!zy)Gybv<^-L0*39-WqTC-c=tu;q~5AIa(N2MQAB=NwACWwDWx6`Pe1BhyCvDQAr$IyH}1_&fzjZv zFHde5cE&V7WUp^-elq#}?VYc0q5FyRqa?9dW7aCNWckx4qSPS@t?inodI1Ki(dJo3 zC;YGXr?&xAfXbn8JuV6Jm!s` zh1Rq5t(_evft`7ErYx1bM`~(nz6E~dS!yNh@q*?*E{6-6|B=zrnKaN{G5I%`_gGHu zQXm*!)|W_f3E2DQ+gxJ11)n6G;mVkvBKzs}B}BZ`Tg{e4@T zTnL@yBW2}Zguj(a%~YLt{4X>Vb^`$lcT+boU-w0FC1E=+`RMiD{|VJ@2oY5x@G+9U3&yek$x*tsrkrv{vI(~ z)vQ#1xm<_o3kr$OQ{{5#{aF&ne{8~bmj-gY54O5mzp(n$nPs56bJm$5bKs2{z98c~3+Z^>WtJWkg5?;F?wKd;GdF%CMahKgr-l~1)U^>a94<9aH6Eu?xr4^@;a219EEaWPQ zMn@Ofvh?Q?VqL74l(#gPTp;uo+r7)gV{UMHFbFYJxp&Jpdv_)nzn!SC zRjL)^)Wj=uB>$RK0tsb(Fd8r^fy~I$T;`%*68$RK`adirMU7D%}x5)@N-B%ddxjt-cpa zI&U;)v-5e2eAE}Zl}fY6eqZ{B2?Zo<+5X>0)$X}G{E^6;uH}u%_)pHi<5lulRacx_ z-O0uKp^ay!Mh>zz*ylhmY?;r2yFbUYabl&cX{f+ng)vqMXVhWbGmFJMZBjYnEO|AxrV z8w$zj+xKGX!-WR1yt<8wV>7?%`VdUFM3&df!%z{_q`SMyrBolZM&oh@> z;3@-yP6Or^pTO_c_X(BuD?hxja1vVW{jjkW(P8Sd)0(g3quyQRP>8mS7u@~LI4FzJ z8_A_^n9(U@K_KoN6Kc>Ax5ZsQF_Em-@_ty;*WZ8i;l{@L-?V(k4IkUR3CrD`NR7J~ zz0ctuvQ9Bq;hBRQ_d5@$FL@<c!opNxK>k3MS>b=loK()0t^XLGo1Y`;2+8>95%vmAOLPkXJJ84_i0 zZ*NC!sp()Y0hM4-)oNv6Obmsdp5EU-C0Sbs1^TT}w#e<*#uWkG;Ns)YGzXBNs6}kv z0SvZXtJy0w9puh{9s}_4{$Sl{hli)~&C>U3r>&bBk{+k7fN<_Z zxi8=hggSMZimHQL+qGeLWu#&u$>sH*Vm6jX3H4J}ye_+Dr50m9K0k;+InKu#v1(P9 z^RF8k9`A4Te|_qgDC%$%O2XmZTF+z2laF(f_t9YrTxze>4vDBeZyHPn@?7WbUHvwD zPnA|@wA`9Zhmi7Sv(xHmh3!Df9q;T$AAEI4YA;4g&2#?#{kv3YsiBd8{SsC?THIlG zS=Dr+)@=al2G5x^$xQC?7xlryft;#CfyGb;*_-2K7GoWG6_55tZ9{h;iK;~zsM6fF z%O7`~A?z3&9DE-dS_ae3S^uZbqs~AzO2BqrfkRk$=%55jR;kHAwv$hE;LZ<@JmFA4 zk(_=_x)8@d3OPHR7t^D&Mc1nP9?HwxYVjNVAmsp<^uomC8+^-~qm?rCwYoER-y^72 zeb>aD?R?jY0FP$X)&ja!hk`dS;c@2HvH+cerTD>Y1ZB54)cY5(+C|6CP<3@hsEL+( zQ}4oXk?(vCg~Ig5M>hCz0GgT{i0>tsAIjPu8i!F`#bk*wr)tLyy^fxqo@)XoAFp1% ztaAeOL&eR!Y{I?jH&SJ-)zspiXTRh#1>uU>^`4V*pd z)7)9mkQu#eQ)nQ*H|nz&$*jn^G{jexRmrB}a<)rqF@d??L@c>J6bV=^q^HLwwy=;d{F66SB;9zHxql)l4meQXbOrph=0^jormPkzu!$$R>FDzCvYvsKW3J_ch3gk=hH7r zsT>k@9%t_76;#9fA|c%3;cKhnBJMEZCKSn`V%YE&+tc`gxcxGPW~Cj5&e84)BO{|y zxs~qbLeHA3jI1ou(1@%Z{Y?w~RiJ;rv8jnt(p@Z){dwj5QdK#(U(=m{D@+M*0{k_~ znq^-9y70?yGKd;i+YMVb5Q^C7t+H`EZhCsJ{CwWit>m*;e;)+}2I@nL3t7bvk`4y1 z!>R^w5ig4j3AxluI~N;odUSW-b6*R!f4;R~Bz8JawV%ncbr0aXKPA6mK5Xjh>gq3m z4O3H7v$gAzpkL4`I1=J;b#=W-ElN#fRF-9+O4+D=Sh2l?f=d$?ekH;-tz25)+pC)w zQ293Z3weDM;Ni|>$>gvb_iw@`Rx34o5XK;j;(wI?svXD=8I9c<9<8@?FiNwDS{gva z?gw+xrUPy{mB@GIv5W;DQ@;1d!M)^ZGuOFm0Y!UdWJELU6-k)|2DPx&b@M;P*1pwt zBW0Eg(3uv${@Li13jhgeO%&q=4V>#fe`cJXnc)|+kgIi#l{`L~YQX8*e=jfX7tw@4 zPv2YZ^nL5}GB2W&O$;jqiSCd>;=>-L&#GE#jQl)(eLbpF$;x!xMg*kXxVsaJQ z@9B8U+KSw3+|Rd@Cx&=VZG(b>s=vCt_opi4 z7s{g07Um=9{a-^2Ff1LqK2Ka9QTt_}DzLh3Rg?j2fBN*vKPYH+e`5w{6@x_=A^@C! z|GvIROxp=*wK+4{{m0**X_U9^z7+lb_8@{82|_|D!F;10TEOW(drWzCX2XR@gF7_z z651-KmbKqd;U9ivz2iqjvk%D;siN}H+;hO4;OI2_qdVgS0-?%oKtr((J#T^8@J(N0 zx}@~M@LY`woBllQWM~q@!^5SI0#9em2C^w(zoy;wBXZsOtwMd<&L4td15#(c`G_Fu zMXpA>$JvoKG}reL3@c*8SmV6&WBZMPEO0&0*64P|@Ii2S!oI!fe!Ndro9thn`tHKt zahgi|n%*?h%c!gDL+a75M9T;~fByVQKzZ{WAl7gp%W+PRvB=6pZb&k$)6>%lp-?22 zS@(Y2wtvSYKbcI%n|afq^B{!Ac3EBM{{h*nnB)HMu)bg9;;P!iXznhg)i{w%|QiIw6(3|nVI1Mx7vlQ7qKrSt<{N^etA8&&}n&p zRcy2E2Bn(6^3$h4l{h*%ZTwcz{+X@H|0qE?EcI$WWHh_KyDZlvTS4=5*5NO_X5^ z?1jg$SN;M~XVjCF4%-2C#ZqAaHgvldS=y5Oho<{~ZxnTXaU>|C#&XOW4d?S@;8u`a z0HklwuvXX9a+IEY8=E}m&Oh8+7kd?rFajaRF?A<+wbJ>il}rw5^Cax$ue11K>JUA} z$~xzxXRp+q;_duv7_BhOsq2ads0r zA;aA{FZo_pkvZ=cSFsnwwm!maHy$4!N0?mw))0)#moHoWmd%j0A?YX-ww)(v4WUVs z^1_T0W14;sOSSzP(2%W0odl%m2==`d21tx|x;z>|l>UJR=laAkM0E!vvTvgQr_ zF(EC%S}lHU?d||0_uV2-OX(Lz==6*Xo73Y1^_Q`7-CG+QPdbwQIYiz5m@)F2#i*`5 zPPm2tlFPH~U0GS#IIFA-qme3EwklRvoL3Wum)Cj|@nrhcsg20VGo?EZd1mk+_jp2yevmQT)I#(%X1>*%9V)zWFTlstH%O<2j z3VHs3`xCbg@`dwWIGqeV1|8CCK>pvT_)qGv;57wu5MGOM^m{~%efE5JkLL(38D77Pv^5%C)CPQdnuA*L_NZh;Cyb?xfn1j z?S1rHJ7el9Y^SFDV7OxbhDiL5K7mp(2e%-b$Ls`uEY}x#pZZRaD*jnf+$m6kF{It$e zdj1~mxC=e;Oj_{xNRFwrP+0Kh2j_D>%q2K*q0X{S02%FL31dq|2J&;|vHj76o6+~Z zmS!oP>zzr2p<;Rt&lxDc;J<|6sp?F?4Zaq;?l7pCZyw*6T+Vp@g3HPkg|VYQbEwS5 z2_o5tHN)DjenqaIHB1o2aoUROS^CYN^zuv-(~pH}HH}b6X4a4TB~s-^@GyRdU=?bTPeB@#vgQ zP%Uxdw_7E+A0k!jx;}9hrztLDLwP=`?3ZOkYNfYCT}Pc*IMpvc&-$Yo*+%%^JHD@c z)3rQqGpEp@t@L5+YQQM(`7NC?_wRmH28!qOG~bYrlr=@QHhjsL3>cQSNY~Q};|-US z9sC76vS<4wWhsbyYg5qwY`^Zz+kWLbcX#n&qNF8E*6>3_vSl2b@VL7)u%71;JJaAj z6>nMJ+B#k-QyBXlnE=n>#vEIt{S${vmpq9j-{tdGWnF1UpTALS$eq`$2_jfm*<+Zr zzNwT|v4>HgE1$~Q6xE09u4m$~EDa67wS=c3k=@KsbNkiqc8*d5b=^AVOEO1e$Lexu z4 zntkB7%=fb57q#TcEro|2tGOYE0ATN*;|M55)l_?Vmk+(gziFaSFJSP;V~eKfhMSplNk+aD&#(mo*xGa zsu{ZZyFh)jsTH$=tSDmMM7<$r}eBC3`C{zm@6KCQIggIeCs zJIlHEMn8_%jg@1s>wW$Dl~beq1IR@{q5zXPBI0o>#-&zlrS~!$W zLZZVJO3HQs;)@e?lCTVVK%m5GS*ntSWD#%^5fif@{0AWN_JBfJ8L|6%4DWmzKF~8C zzgfXkFRf2>_@f!?uWq}9`n$9w57-@{?WU%t`m0rQM(UXHUnGOO! z8(RSI95XXBO)z_jJuS`6NFRgLy2Zhxg9DN1$Oj&f-U!*1FW_B$dxdE--co@hCCU+9 z!8B@5Fe%Sd(|ng$Tn6xC=Hp~T=*<8quFpklUjfVtuS+RtMgdB21~h(%@&M211DsnW zPmZ?MW@9t#Ob!io;?y!@cKOI@48x*rF~^z&rnFr@RQw)DxX{M+L%#_mVmM4A*81tu z8no)Pm3E7bKtve>F$N-eTT^)^&#O2{HXJQPFG3DC`xtdGm?~c2q`G>tOGtO$s%!JA z^?8;KM}8H+GC6tYWpUfPJ7{Z4Bz=V~hsBwEKS+1ke6YXB;v z{X3AX5Vqv7nm{=-m`BIRbZ4YA-<+!di!RJ;I5tu|Y)+Eg$RrNig0@^{2wxUp;*sW8 zv7_4=knCOIo>z?-$6cwJLQTePFh6M{Qs|8gz(e2F0z{7vC zB-i(UH4KRUnWj7U(0q}3+VB>#1UK>Uy$PvO++1Fd{aH1UVZ=eQesiBHnL_-<%*XNi zepnfgRrX1&^^tE$;^ZcR5I8+aeN0DkQMP#nfg#OLSBCYY91rHm*LQr#xBvplSfG&! zd0ec6vAu+2)GZ}<35wRbUg z8O8T#JLA?KUwKbjP{xe@uXIj7_z~sfv~^wJ_wpJC1MLHN=jKFJvg$L5XIb{T;rBsr z7+_>5MHbOoCG+v!iCROW&_*BK2?^F0ovYtunz0ddTb`Eeep9}Bd4kw!vp$ATsrU=j zSpPsoRk0S5j|MdT;R7oDVJunw;SS(P8I5xwSsn<$i4XI(gWwd;t$xl8z<&(U=l76n zX=N;tD_qtny7->F3Pv{gL|9Khf?~ngL;T>e{25;T(1pEIu z0IG&*G{Zgq=o{d8!kGlM`_)jsZn4E!oHq{fO}oEJ@mVBjYmB;M%r{GMG~&>G*6gJi z$U{j)Zv2kACoB7;#N;_Did*vs5Cfg%)-%w;hSQ;X1 zug4i4F*GbB5hwQ$bb_3MrDH zqBvCn06k^Xth|NFdXe)9>Irg_O&~D9Q(L*3idhrya3N-Fo>E6e*4le&0vqWg~J!vl&kj8qje zD2+0U#H}r$k@#$8<(&6c6`@3-_94Z_in|Cxp|Ou-WeDG@-N$Tfoa|>~RU;+ie#fi` z9gWQBhmK$jGswOthdXI5d#jY)J-~tzOCEm!^4SHi3Nx7ga+n#vL+`Y(S+f@o6=Ga!uWjyLfUKm_W~ z@yXraAuy3f@u=cq?jA`=H|DVuBv=r19sF%Hmy51nky`SRP5G zO6Ti%#qQHH=wU_UdqUk40YVwPAy+6UVsyP;`!%IPd8p`F9qauTIXs^8h^DByW2J0F zGt%FYH+l&ZxZo=g_lBV5T)1#yNVEI-S6o$@!sV}-ovjZdu3Kukn4&kVoX_kVP%+?H zaX;R;|09~m(t&O8Gu?G`d;jW~(l=64HocIiPa8%?#^Yoz^d1S7PjXI1aj6#qmsr(t z8C_v*J1;d>iDWwW6v!IfEwBemjr)AjH}2(IPDp%H$qNY$eeAmc<}0J824E+Iwzx-< z`0TVyWOwr|zY$1I(ALOsPuXbJYpJLbHB4E3h&vrA##bUK^cSX)APAMfix-NYQPCD4 zE;$Y;r>^m+(!rlh@2CavQvGHr#Z+Z~iHB9G-VQ_ZI3G!NuYSxy36#sVS*6}yHg44J zip#fS8@2XBKGTToP{hP|S?4Yeh&5f>2M_Vcfht!3G+9;06?BEhcr~vjEtK?lLAK)n zx!g$`3@cE;ZkY}Qd3vIf+;&w#{eK7MK7?QgG-w~q!hq?r*GR6dA#Blq>GVk3YNJG6 zR_0g5DB}nA=ik=*pFZ9I1;|MF44B)E!_^*z|ot#0V$CA_zxlD@kuNTHa`DAzzO15jmp_)!N0 zMNX}13f>t^axOI)my=8mhO$2%r}~ZBB_{c1l+UtXLrG^4>Y8Krnq|Hw!#<61g=8vN zXcA04+7eY+=rFUCJxg+GEJVM`2Tw~!x8-o54=l;BQkcKv$7J`nx=q*JR6e;L=!^;j z4zlLpCP%WXoSoga!9pmtNF&hkMXt%<(pat8(*m~@+ly=p&=V)YyV7l?sH}Viszrue z7{hEwbSSK^_5S))ygMO7xI7n9sqxopa3Yw8p>WBCSXZFRAyA=XN$TjH06XOJNEuJZ zo+`u$?D1E?kpt}+_wggCTJh^UdU~I>;y`l^nd^uyvYL_xi;A4IG$y1rUg$H1H`Qbq zqXFuZYk77j($ix|-|e#D0e|kf392Fnh}403c|2gv>9jJ3-XkD5xMtc7QT9Mh zA^d%vf&1_517T-Ub`?SS>euQ*=#9&;#-Mt1t&Ua23R%)3HV5!gNVpyLf;s|2v-q0? z+M*tqP|ZfmH{u4>qI{aB%BO8X`_uzZQ}+zi$dyNsKgG8{81I<=#Kgo}$-O5t8wD$T z=>sIVBZbW z!gOwQK|@}hbe%h|E%QeXqwY8VUIE+1AZS&==ZS&_bqdT-DImKYLuo`+pPe4L9xi68 z*80JGT)X8D(Y*m$gA(_Nc z0Zajd9tUh|Xwwbgy~MVA?l> z=H>sZt%77=0A2L<@^A#SRiZ}Nf&Nr-iash@d`ElVTkf13^6L8{DRJn>To;;K9Lx!OP|YwZd>y z*kBzvbguRA*Gg01y&QMGWpeE7Ml0Rr%P2ax3u9GCJ@c2hs^FfqnfrmJq;wiS0K9~N zJSuhoeP8X2*SEaiU)Aj(gG>Hwj@s@Cty&A{*o!tZE%@h&(L5#uw&bSj9Ih`|NA>0gR2w(sQ(KYi*9 z=XN`+pKO@d@WDgy`1B_Yiz{u=Y=Sid3It-tY4FB5fZYM|@wbkZo~%2c8MyTjcAQ_- z+W1VIdxgz6Do28^05^d?Y0~v)%9-C-fT*0(Tf76 zjiu)6Jp-Wt5sPl&f}<~I-|=rBP81h^Yp5jA(@be8&zd&@{*ITS6>G~8(0z;RAtAxM z-xZe*`P(M&D>S|qIbk=ZTIqm^C_i&Y#=0Q~%wt%>n^UplqlpjUdLeFZQxT6zVGYd? z>Oq8s`8(&@O{?qG$AzG6__s+SB(I46%)O#?bu-Qj*mr82q4i*3ID@kc{;zmC-Ug7Q zTI-XXu2$l^?_+?!2Rd~0fgjA$tK@SHImx9v=wNA_rqs;qVdQeI0wBLn@StI%HN?@i zIm?&hxix?1za7F5-3ttGyTslEabIRrqJy;eMI<>g#3BzHE&oXBICr&gGkP_E1sSkL z0z73j24s@)8p~=78c}KGaG>zu=nc}v=T6Lb^;Ymxi|Bpdhkgz^10<`w3Ip|naf!2I z`QOj{R9ufp4n*v*LwE&r1rbmJ;R4X!=V=+Lgl;V;;!h6bD5bw2iwy8@djs-FShlq= zG^hsWIVq0QqYA0#!3O@Fn#jVL)C;mh}N9h;dtUK z)^@HV-VgX-6L^kI#Y}7Jed3ojf9y`||6Mp28(?@O!LT|(rRLs$N)-3E_WVR_kvAPh zj(TaV|GaNV9tsb@yV~jOp{tAJ6oz31pba_?-5*O5K9<03Z||+GQJnzN7)U8}7&W3f z7$$(%(mR?whzh48>W&xY`E4RH5mGW@s>;87xJK`Vyo=)M+6U*VwJ8M0hK#ZC`X5uP zvy%@oue+U`02TW?UV>15Y`e)=Y;HQRKT?7(anOuxhgq_xU?*i6uIS5NB)^LNzp(uN zZCn{B)@e4w9$%v*FWZF_4H5pIX)m~t2}4r>WztLnvYXl=G*g1+I!E@9$qumRmgVqfpZ6o1zC@lfw)+v`e>@7>8W#p^Eo5w*(XkgIs&jI9 zPC3cU(!mU`&i1qQjU8=v7|NGLa-4sW#s?6GMq5H9rCUSRm+~f;@SkQ#)w!R~2)7)D zQZr3wJPu5wQBR|JSwlFJ)mqJepMgNbSavjV2AunrQy>{Lfk}0;zrThLW{RA}UhiGz z{V@kRNW93gCDkKl5lKh>10wN%H)3X|#;S2q797s2udgNQfF9ECm8+Jr@1|AC&o zn*(OI?M-i$ubhST;VrR^cd?TgA7U=Cu>l#tU^BMeO&?CRJYflR)FR9JhS%PN9|l(a z)cG!J_W@x-V~iy^CaUh;1y;>J#i)TCgpvYyVN8(X&k-2lrB$P_Z#qh0zYJ0iu!k9B zQfL+M000*TEew_AYveUv;n&3bm&Yl_EA&DpwFS4%?f`5$i~FGanKS$_8c_ z0&xaZ2;@Wy(u4tW0?*M4=)N`M?O1LOx1MS;VbR{XcCp(U;&{a>NG2)MG| zC1mJFjD$z~9SbTH2?+^e3jt20c6tlCc|q`G(!x*kesu0BaBk@q0Aes!PE0>+(N9m0 z#ZG*jET~?!GK4`a@fw+$X$Yk-78dTme$9%UHP~JPl>o@Cp7qNW+(6`)Ta$-?sd!N9DY7W)KW<>@n3-{+ zz`@^RRqMDh-Mx^@C?=LLIjOU71C*5eOQb@2s)lzKaOmDeYy0*{6anXe-q4|?MD>Yq zQ@*xT9WYq<-%L0O+)qXuV)=Wkgtpg+LC>YE3%+)q{v3HjH7;hrG25T7-f`~X7tN7(b$Ts2UDqi1q@mEtm@SlYd4fIh_;4w& zdj=pOoN!}%_T@5S2u7wIL89QFMtXB__@gghmI6<`S+<%@xDvR9&Ko-?#HjnlK?^+7n7M-~EJBu9Q{|h;h(@fioeISM~0u3aI@Q`XH zCaR~jard}E+f5XWe?UtvZ#hSGt8ICCYRP5E6jp-c*HIZ2PQCgaNhw+|hX07_8rpQ= z^J^-;a8K5&Y>$ge5$NSikO*k7Si`x%ha`6FWqdU#L~syBP!82TjOxwy>w(wfs8$>d>?*cDmG2_f1)#QP?^T}&!g=ByCQWLhOSpVhAgI9oWttc7F{(4M z+|^?s<$N77;ZB8#nd0u|cxY_9I(_hLvB9eGf+7k|ZAGV%NrjoJR$Te^+}jI_C!y-Z zK1PHj$@NMUXN7BU-G8PlOYoeAwH&8B*b`47{ z6@ns82&v{G8VR%A ze~K#E6s}u@%i}o!QWz}cF_gsmhKmr@JE|6agIi%61p>6I+e#KpHlrU@azhC%~g zS7GYgue!z8>*qSkk?GZDli=d6|B_cq$K%wt zsB}+uBOAzmvJSIa@$Nh7;cA&4HUage`=N0&hFv<17s{8oK{bJr`@{s}<0y~F@VmOr zIYo-&LsKNxg=GQanUyFg033Vynn?(qTmSO%&yp#!U`j8X<~IXOzhbRpRfvJOBUKoscq-=wIP zH)BpL#b(9>+fVBuV+ z$Jksb`|oL)WK!+!aFS(ZBwjXQZ_SUPhN{Qoe|iCAbq?)@N)?d-G-JaP3I{WjrK7ol z@&q*|8%f1GVQ;_tl;?{`v+(^m0PDm1ge5RT1Ryr4owY} z;MX22pMRq)oN);bK&p6(g{I@4=KjPPx0u6-xuFU%%mX6KL@h;pys%bBY+0>qxQ)5J zN(iEqsVXc<_!~UWaDgc7WDladesQX`I%;Rkipt2#wi}S5m`uS2mznH4^s*?vRo(K= zOA1G0QZG1KZUM%T*uX&Vl$0~ewegux>|2ta9=^JU<)I8VlooF@SRJvdCkeY0t!nO> zP{ggY45*QeY1rI&2tK#D#EDun zx_4v!cx!%XZ#+O6E z?4Dnt16O?e%6ImHwex9pwx+2>lf#PIb>Ww^R9E!0lEZD*Mjpt>yz=?^N@g`yBfDEW zc$B|_H!etV?DJ8G^d(bU?+@bJ&f>*tTt9yNn4FpE>+ix~XZKv}^V+o85^y!$+r^mI zozkr8WO2QK9qZ>dyakg%#Bk&&_)92#ruuYX`6|5xy`%WSo6mM;G2M86N2eB;oG1@$ zKW7XY5zNmSn607l_;qeaorBxZ*qAUEh8pR2vglvG&Z9`m>+m|8rmXbNdnv!eQws)a zOpDcbsBvffzr%eR$Jp>V7u91V9`tTehSjpwJlepKQWJ9Pvm?S0x~#RED#F2q?SAH> zbK<w8a*Zu!P}s7t6t}(R9e4O`ZEmF_H$>_#XuciN+t7b-v-C6y{@@O zIijhGfr2Q{=}kS?jWO~!dR!YPO^5n_vF>7^$a6L8wQWz|ZyjzG!g^k~(7o8Bt1`t+ zV8)+c&}TKFk1?bXt59F>RsS>1Q;iVZSiEn(?aZ7)93)+lu4fG@WN2qpSl`=@)~n?> zAuDp*+6`IpI*0q?c-&B^GgG(KX3T8DLUvwaKi-{mIy z0x#0DrHegop(eE_PVp%#C<`gl%6~USiE~pCJGfGy)>|C3uXBlZ&D*-)I3N`3TcSkO z?@4-uveY^LGR&rLxPH|$QXq1Fz0J>lp|m`Koa;42Sv&_hxlT9rB;6TkqZpNMOpz@m zAWVP3L_y$1;OD4SuAhxL*eKhz{;BXLL6^)=$Dexn%UMt<%l9awmeuu2gm1#4hxes3eXVF1TXw9nSnx4KJhEPZ^4 zxte3MjMfKg%gjn!7~10hkN1u!GJ;ms)BU8gL;pMK#{D=KRDl1#C+6Aro-0OnF?=oZ zF#0+vY%_J~{kE)N;O78M=0^1yLe&1hew867`^>JBZW>{7n&aCjl!W*$+xY%2VZ6Ai zyf0S+i~s|rimghqwMen_7!HQ|9g}!G;C*bTZS@s}^@1p$GJc#xlO2`!T)Sza>}1T) z>|rbESCrk8a-FTc_#E2ki&E^B7CqJ_1%FJkAH=-sxTAIFQlIZ{wh+z^X5F{Sx=HD} zQv0a#ipt*sC8N8~oE{$0^cfSt!eo;fv!~_pj0Pghd$jom~7+o`` z(co{9{RwibZ0%FVaGW~CUgjP(=P#}Prcr6WBtH9Z8m~l|E0GcprDeiXZ25cKkneZu za~!q-^_k!ahoh4mz04P3q;up*6%R9wT1)Q0jJ;=0|E=ur7M<94SYXliR)+v*c`Y&gITk4t;7Y%Lb_^ zURHVS!}z+A6ADEXNiBWq<2rn2uB`R(KfwpLDa7{_xL?qyKF|D6*eo%)CnDCrOOL8A z?HgHN;5joZaxfWBafP%R8l#} zWYn&$hRg4`Nj{H6`aVo3cWpE@gEV0`qO4HCs*z3hKusuzbZPZph(xMeHkmS{r2?;l z!d9o;HQUS5FS)`kBm+>Wams^`-_!DQpTY?zFzUaz3O@AFc3V4&rgg>T5#RqsqtAKI zo`Q{VWFRxqQnYx>+(;!mJ}W-EmvQ04FFx$F+d-&3Aby1qe~gf1c(b$=XQ@Or-{8h-bD?`|lsYs|r86p}C8Mb-Klx+@aFi(ZbEK?{_ z35i-}Q9>HXR3bx$$WS6TS;~FF#^+P7C{?V?VprEpfxrFu_B=^rjgs=wnyx{^snX$=Vz;IJ z>F;KJ;(afEoUyI!xocKOU*FBoa5qI=oQ2`>MWGkd986(eA%|HFJV!g}hOpf;7ja~j zCU|v}pN5FxqP&LSvczk`(80-Ru%jY1I(q7}0yHi8E(6MK<5mqPjDQI&|z%LluiJ7BJ7`zEwfw7Z$!=`?Vqk`*rWKph~y^g))2R@z=<|*rw8&&V8Km`kb=5 zOvMx)+k6#Hi^SWo!gI=O==++H~P>(%VeMsW=>f*RY^__tKU*v06g zfty#23XJ;|od+x^nuk95h*lYx<_;N%cQO26OsPN2`$IC|TY$ywth+w(9ShbS-<=n- zWtqkPnB}+Oa|%R>$ zKH?qP7P79m%1;eDF@2@oWSJq)8Y>=<3m1^Dl}lhcBk+Q0Fun)Mxx812COgo$L?p>JQ)Z-6)|)#K2VczXZLO_ue|;+!Jjh=Ym(ZW8QNw z113=!vp}3*!?Qs_?n9eJuVrXN%^!Z=Sj0=aDX-{s9t_c|!4rx-mRPNiGUU%o=>w0-=WMp2Y zL1dp%{h>r`6LGWe)~zdbY)ME+2q8D?NqK(Ujzi(_$p*|8eVEMbay2kDrRV3*2pFBV zJyZBhKckI4jiyHGCzeY(t)yT7^d$pjD?~Udq1a?G(JoZbVl#YzNg}E_a3hjQi z0n)(8#-`%``|uN4?~OMPw5S;`1YBf)On%~&?u-aNWO7HCAZ^6eZ72qxc!!)qM?zI%Vc@T6T!F8geeQIFtV^D zS1=1E;N@-IO}@Uqkc(`E)i7y#6dUQO2i=7*YsW)G_f{lWNX>SC&Ce&MrZV82w3{~B zgL&j#NSBt9f?XbkW7+L@Aw)5QK44VoJADOsKmgHgP`JIBDQp9fW@&C!JHNEwsW^Cf z*<-nmU9Z!BdU0mJlGDhAcOV8)qi+u8~qzsgOcr>6%!6e-`# zD=fTT55x9Ga3s!qda6K_26>@rZq3`_1HuOmuqy>DgaA9Z`sMk~}qAR>lMolxtd8+LF{026n$v89FG z-``(IMC3Ru3RZpArlul5B&vc2(fIBim$|t)3LH17n1l(w4$`0WJT)CC zW#q|IGku(zWV5Ybu=MMx*@n& z+y=iwQbJyt%;|28$>`|l(3qGQXxWmszO-_9`s7JuR+i8nCph7iv)dy}OZVf0u^Ge$ zb9Cv&^$ERTwwl17*RQ8fo@z#UOh;hnYqMae{g*fB%UON$+g@4`_j7amtG9ewZw*s< zu5<6{Qyvi98WIFm93~@Je!mPnfrzU~hXO!0UJ5%9a1w6bj0PZ#l{gR5OmcE^qeo7= zb3$sW=oeQs8`@&Li+Y2j0}v_aatm{9J3Aq1o>-2gal0LuTZ_iOciR-3u8$9RzL|4E8{jiBc#xD!%`k zwK5}Q6R{2Y%2`@SK;US_VF3X`SXfx6^Wpst>In)-((9@AKLE%`9LfUhsBOy0$uT@U zlT5|SrInQry+yUPwGyxU4omdUaCjbB)#2R}zxXJpl3T$`6kkb7Jcpry-3=R71O#7O zO-xLPH}6aeOtYbrD_!YoRiCzc?pS9+ehrQofluzg9l zl8J?-4u+_2Q(vJ=FXcYHLg=4+^J`Ad{hnf9$MrEWQBej+?+>EW5%Zn}s5^maaBwf5 zH#o#~qR{Hn3!6N-+`_^_=dOn)Wvkl$KoG#26F}lcpb~x`px&IObjE#Gg@>yS_LvbU zr^=gu*3R3|^r&{a%7EICkd(C3G9xMJ3Urs!22@^k^eBkh;sClqDie^D)W1&s_RSRm zTcz0qEr}v%Zu;>jEh)(S)y&P)B%C0+D|Hd7aO>T0TQ>r{5DlsFbrImCDk*Cs{{*}D zRw>u7kARxPz{IqHK>j+GW7u@(Gztm;am89D+OyRStgIyJ0m-1_iKRzgFuYoR>vcne zN{*on^&N*GE!p-{Q*JOG{)RkD#?S-*ilGl=kmjzuut~6{URXbr7U=Pi(cCdDXb2RD zZDcH5Uieo!koUY#rURvwsWKrsxfA3pkYtRof`i2cyT0K*GK4*{C}?bL<%Cqx4ti(P zTnZqeF+F9c;>qXu$I3Fd<;zH)(UAQ~1+DreW@J!G%gVw)xy6B^+BFN&6s;1##N1bx z-0}0Wlgw}0{{EGKd)y_TgaGGWi(Q-f6h(DhhBf>jVPFpF%I~F6xWHb`C$kP5bDUti zaABuh=-@%KMMaSKgrEhkgWsecT(UY)H=Vt;k{~#YfmAsXTK{O6B&kL>f$&h_;NXY^ z{Nlq{vPj%o+F#J2GZvVNdw6;}8eIdgMdQDMJu(l50%ffAwm3%RZrzN-d!cF;MSxdD z-*$X=Wj6Thiw(t5H9xv7g%lO7^157Ew{I6eq|8-rv(yW@u>6Mn|UgZFW&p3*+AJ z5DBhFx&8xVAqfd>?VHk?9GslZiw5TAd(c&& zij&9FT~!za(K2ed;4q5wMc(^IWl&(?28C`Vd!_+n>`wf$mj1MyEK`1^lWg5h)m_F7-@d-miBHv}wa78-U7xv~`M3=l#>fymOEaP&$<#3oc`%>mcS|kj5-YJa6~^=e*So5Vy%Ac3xq&Y^Q5v;5Y}4EtJF~BJW|57!SsU9Yn$)_ z2-o73aC~GQ=OV$D_)1JdLKSpJf&elLWtUl{hp?Eqc&5H+Tb3HL;$n|InH=E%IzQbf z1C1*UDUZJj(AQ|9Iv)*zg^cy1K0dNAibX@TPJoaGnz1qEEkH7ZVM+aSsxIO zPJhttTLZY%esQWdRodm+LJui{f;S`#XMeZ2cq<0>(%W-E8&kBxK-+@2ylj|FQ`MLm zbCyQi%BN4W;EOrvK0+I?Fn$U6oGe@+m~q^aHUw(@ji@;CjK!|*IK&Cp+Xlj_HfRUw zYI^_vJwYHo<6hD81&j;gW@#Sbzc5EbHeRniLjU@R51)b;!$6hqjp*7wlsNIgjyCZH zf)p&eZy!8=bddPOG&gIJmyBOxzH-~mFEuhRvt(03B(JHLmvrkLCFUzHh@>W3G-+pN z=iU4F>CqC9g#!-JKoFoAYG`ZMAu%T=C2hpaYC_^lAQnf=7<<;|;ZWHL9wMHe|;WS5)LhrT66g@CNAa=(xDJkUs>3 zh3QaPa#Hn0Va1KNMJ-R_sUTVRaY@Id44A_xI8~lI?9cqOHVB;-S?kJ;8#lb%?#Lj9 zz5rs+eY{ODG&J;ie}9#3(J&@OQt&KXE2Kkp%$>Cly z;|#!Aq(%1i1L3dOOwABh1#oxBp{PgxxnqIzj0#&0-`D z_LBxL+%|hm9lY&O6_KS(aB%SI;^SI16gOl_M`kCE!em792tI%QOoDXB2dd=AgucxW zY=P$}TiYL>`;)vUB>0-NmyvAjvxdi2jVWPUm8HFRl5_p>LEA0=?~L$o62|{ Date: Thu, 17 May 2018 14:35:00 +0200 Subject: [PATCH 030/150] benchmark code and benchmark on fitness function --- .../Optimal_bounding_box/CMakeLists.txt | 1 + .../bench_fitness_function.cpp | 63 +++++++++++++++++++ .../include/CGAL/Optimal_bounding_box/obb.h | 43 +++++++++++++ .../CGAL/Eigen_linear_algebra_traits.h | 4 +- 4 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_fitness_function.cpp diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/benchmark/Optimal_bounding_box/CMakeLists.txt index dd9fbe32d76..e918b0a6d4c 100644 --- a/Optimal_bounding_box/benchmark/Optimal_bounding_box/CMakeLists.txt +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/CMakeLists.txt @@ -55,6 +55,7 @@ if (EIGEN3_FOUND) create_single_source_cgal_program("bench_obb.cpp") create_single_source_cgal_program("bench_perfomance.cpp") create_single_source_cgal_program("bench_custom.cpp") + create_single_source_cgal_program("bench_fitness_function.cpp") endif(EIGEN3_FOUND) diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_fitness_function.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_fitness_function.cpp new file mode 100644 index 00000000000..bda67e7d9f9 --- /dev/null +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_fitness_function.cpp @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + + +int main() +{ + + const char* fname = "data/elephant.off"; + + // 1) import a lot a mesh and subdivide it to create a big mesh + std::ifstream input(fname); + + CGAL::Surface_mesh mesh; + if (!input || !(input >> mesh) || mesh.is_empty()) { + std::cerr << fname << " is not a valid off file.\n"; + exit(1); + } + + CGAL::Subdivision_method_3::CatmullClark_subdivision(mesh, + CGAL::parameters::number_of_iterations(6)); + + int nb_points = static_cast(vertices(mesh).size()); + std::cout << "number of points= " << nb_points << std::endl; + + + // 2) fill a Matrix with them + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + typedef Linear_algebra_traits::MatrixX3d MatrixX3d; + MatrixX3d points_mat(nb_points, 3); + CGAL::Optimal_bounding_box::sm_to_matrix(mesh, points_mat); + + + // 3) create a population of simplices + typedef Linear_algebra_traits::Matrix3d Matrix3d; + CGAL::Optimal_bounding_box::Population pop(50); + + + CGAL::Timer timer; + timer.start(); + + // 4) compute fitness of population via the Fitness map + CGAL::Optimal_bounding_box::Fitness_map fit_map(pop, points_mat); + double result = fit_map.get_best_fitness_value(); + + timer.stop(); + + std::cout << "took " << timer.time() << " to compute the fitness of all vertices.\n"; + std::cout << "value of fittest vertex= " << result << std::endl; + + + + return 0; +} \ No newline at end of file diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index 6b23f6350b3..5ce781cdb18 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -34,6 +34,9 @@ #include #include #include +#ifdef OBB_BENCHMARKS +#include +#endif #if defined(CGAL_EIGEN3_ENABLED) #include @@ -125,18 +128,58 @@ void find_obb(std::vector& points, CGAL::Optimal_bounding_box::fill_matrix(points, points_mat); } +#ifdef OBB_BENCHMARKS + CGAL::Timer timer; +#endif + std::size_t max_generations = 100; Population pop(50); + +#ifdef OBB_BENCHMARKS + timer.start(); +#endif + CGAL::Optimal_bounding_box::Evolution search_solution(pop, points_mat); + +#ifdef OBB_BENCHMARKS + timer.stop(); + std::cout << "constructor: " << timer.time() << std::endl; + timer.reset(); + timer.start(); +#endif + search_solution.evolve(max_generations); + +#ifdef OBB_BENCHMARKS + timer.stop(); + std::cout << "evolve: " << timer.time() << std::endl; + timer.reset(); + timer.start(); +#endif + Matrix3d rotation = search_solution.get_best(); +#ifdef OBB_BENCHMARKS + timer.stop(); + std::cout << "get best: " << timer.time() << std::endl; +#endif + MatrixXd obb; // could be preallocated at compile time obb.resize(8, 3); +#ifdef OBB_BENCHMARKS + timer.reset(); + timer.start(); +#endif + post_processing(points_mat, rotation, obb); +#ifdef OBB_BENCHMARKS + timer.stop(); + std::cout << "post porcessing: " << timer.time() << std::endl; +#endif + // matrix -> vector for(std::size_t i = 0; i < 8; ++i) { diff --git a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h index c1d2716c1cd..6e0ae1f8af9 100644 --- a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h +++ b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h @@ -156,10 +156,10 @@ public: } template - static CGAL::Eigen_dense_vector row(const CGAL::Eigen_dense_matrix& A, + static CGAL::Eigen_dense_vector row(const CGAL::Eigen_dense_matrix& A, int i) { - return CGAL::Eigen_dense_vector(A.m_matrix.row(i)); + return CGAL::Eigen_dense_vector(A.m_matrix.row(i)); } }; From aac227eed411fcf1706095b1d3a03a907a0c7e90 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Thu, 17 May 2018 15:53:21 +0200 Subject: [PATCH 031/150] small errors --- .../include/CGAL/Eigen_linear_algebra_traits.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h index 6e0ae1f8af9..345dd3357c3 100644 --- a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h +++ b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h @@ -30,7 +30,7 @@ namespace CGAL { -template +template class Eigen_dense_vector; template @@ -58,8 +58,6 @@ public: Eigen_dense_matrix() : m_matrix() {} - ~Eigen_dense_matrix() {} - T& operator() (int i_, int j_) { return m_matrix(i_, j_); @@ -89,7 +87,7 @@ public: }; -template +template class Eigen_dense_vector { private: @@ -165,6 +163,7 @@ public: // matrix multiplication +/* template const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix& A, const CGAL::Eigen_dense_matrix& B) @@ -178,6 +177,7 @@ const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix(A.m_matrix * B.m_matrix); } +*/ template const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix& A, From 1ea3fc26c9c7c4b1da6bf7aec28a40d452032ac8 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Fri, 18 May 2018 15:15:39 +0200 Subject: [PATCH 032/150] I hate c++ --- .../include/CGAL/Optimal_bounding_box/fitness_function.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 981ab6bdb49..9b65b775c30 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -43,7 +43,7 @@ double compute_fitness(const Vertex& R, const Matrix& data) typedef typename Linear_algebra_traits::Vector3d Vector3d; double xmin, xmax, ymin, ymax, zmin, zmax; - for(std::size_t i = 0; i < data.rows(); i++){ + for(int i = 0; i < data.rows(); ++i){ Vector3d vec = Linear_algebra_traits::row(data, i); vec = R * vec; From 820e9c6098966129c5bae432441d8dadd16d9059 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Fri, 18 May 2018 15:45:58 +0200 Subject: [PATCH 033/150] return precompiled 3-column row only & some cleaning --- .../Optimal_bounding_box/fitness_function.h | 2 +- ...near_algebra.h => nelder_mead_functions.h} | 0 .../CGAL/Optimal_bounding_box/population.h | 2 +- .../test_linear_algebra_functions.cpp | 2 +- .../CGAL/Eigen_linear_algebra_traits.h | 24 +++++-------------- 5 files changed, 9 insertions(+), 21 deletions(-) rename Optimal_bounding_box/include/CGAL/Optimal_bounding_box/{linear_algebra.h => nelder_mead_functions.h} (100%) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 9b65b775c30..2707b808968 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -45,7 +45,7 @@ double compute_fitness(const Vertex& R, const Matrix& data) double xmin, xmax, ymin, ymax, zmin, zmax; for(int i = 0; i < data.rows(); ++i){ - Vector3d vec = Linear_algebra_traits::row(data, i); + Vector3d vec = Linear_algebra_traits::row3(data, i); vec = R * vec; if(i == 0){ diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h similarity index 100% rename from Optimal_bounding_box/include/CGAL/Optimal_bounding_box/linear_algebra.h rename to Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index 1c34cd4a230..1d09a0cbdc5 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -24,7 +24,7 @@ #include #include -#include +#include #if defined(CGAL_EIGEN3_ENABLED) #include diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index d800f537e32..ba259ff0710 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff --git a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h index 345dd3357c3..ebe835243ce 100644 --- a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h +++ b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h @@ -153,32 +153,20 @@ public: } } + // CGAL::Eigen_dense_vector : the returned type with D2 may be -1 in compile time, + // and may not be equal to the expected type. + // Eigen manages to return a precompiled row out of a dynamic matrix but I don't know how. template - static CGAL::Eigen_dense_vector row(const CGAL::Eigen_dense_matrix& A, + static CGAL::Eigen_dense_vector row3(const CGAL::Eigen_dense_matrix& A, int i) { - return CGAL::Eigen_dense_vector(A.m_matrix.row(i)); + return CGAL::Eigen_dense_vector(A.m_matrix.row(i)); } + }; // matrix multiplication -/* -template -const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix& A, - const CGAL::Eigen_dense_matrix& B) -{ - return CGAL::Eigen_dense_matrix(A.m_matrix * B.m_matrix); -} - -template -const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix& A, - const CGAL::Eigen_dense_matrix& B) -{ - return CGAL::Eigen_dense_matrix(A.m_matrix * B.m_matrix); -} -*/ - template const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix& A, const CGAL::Eigen_dense_matrix& B) From 0c215dfecbfd891e7873b865f02b572b57b8dfb4 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Fri, 18 May 2018 16:22:01 +0200 Subject: [PATCH 034/150] use a matrix with dynamic rows and columns are run time for points, because it is a little faster than fixed columns --- .../include/CGAL/Optimal_bounding_box/evolution.h | 2 +- .../include/CGAL/Optimal_bounding_box/obb.h | 2 +- .../test_optimization_algorithms.cpp | 10 +++++----- .../include/CGAL/Eigen_linear_algebra_traits.h | 9 +++++++++ 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index dee4d14a48e..b8eab67ea17 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -33,7 +33,7 @@ namespace Optimal_bounding_box { template class Evolution { - typedef typename Linear_algebra_traits::MatrixX3d MatrixXd; + typedef typename Linear_algebra_traits::MatrixXd MatrixXd; typedef typename Linear_algebra_traits::Matrix3d Matrix3d; typedef typename Linear_algebra_traits::Vector3d Vector3d; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index 5ce781cdb18..b9cb0362955 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -105,7 +105,7 @@ void find_obb(std::vector& points, CGAL_assertion(obb_points.size() == 8); // eigen linear algebra traits - typedef typename LinearAlgebraTraits::MatrixX3d MatrixXd; + typedef typename LinearAlgebraTraits::MatrixXd MatrixXd; typedef typename LinearAlgebraTraits::Matrix3d Matrix3d; MatrixXd points_mat; diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 763ed60fbd6..5e6d8268627 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -20,7 +20,7 @@ void test_nelder_mead() { typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; typedef Linear_algebra_traits::Matrix3d Matrix3d; - typedef Linear_algebra_traits::MatrixX3d MatrixXd; + typedef Linear_algebra_traits::MatrixXd MatrixXd; MatrixXd data_points(4,3); data_points(0,0) = 0.866802; @@ -143,7 +143,7 @@ void test_nelder_mead() void test_genetic_algorithm() { - CGAL::Eigen_dense_matrix data_points(4, 3); // -1 : dynamic size at run time + CGAL::Eigen_dense_matrix data_points(4, 3); // -1 : dynamic size at run time data_points(0,0) = 0.866802; data_points(0,1) = 0.740808, data_points(0,2) = 0.895304, @@ -170,7 +170,7 @@ void test_genetic_algorithm() void test_random_unit_tetra() { // this is dynamic at run times - CGAL::Eigen_dense_matrix data_points(4, 3); + CGAL::Eigen_dense_matrix data_points(4, 3); // points are on their convex hull data_points(0,0) = 0.866802; @@ -244,7 +244,7 @@ void test_reference_tetrahedron(const char* fname) } typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - typedef Linear_algebra_traits::MatrixX3d MatrixXd; + typedef Linear_algebra_traits::MatrixXd MatrixXd; typedef Linear_algebra_traits::Matrix3d Matrix3d; // points in a matrix @@ -279,7 +279,7 @@ void test_long_tetrahedron(std::string fname) } typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - typedef Linear_algebra_traits::MatrixX3d MatrixXd; + typedef Linear_algebra_traits::MatrixXd MatrixXd; typedef Linear_algebra_traits::Matrix3d Matrix3d; // points in a matrix diff --git a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h index ebe835243ce..697e49a7ad4 100644 --- a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h +++ b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h @@ -174,6 +174,15 @@ const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_ma return CGAL::Eigen_dense_matrix(A.m_matrix * B.m_matrix); } +// D2 and D3 may not be equal at compile time, but equal at run time! +// This overload returns a dynamic matrix. +template +const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix& A, + const CGAL::Eigen_dense_matrix& B) +{ + return CGAL::Eigen_dense_matrix(A.m_matrix * B.m_matrix); +} + // scalar - matrix multiplication template const CGAL::Eigen_dense_matrix operator* (const NT& scalar, From 00c782b277112a5376d110b6ba9d37a3a2279786 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Fri, 18 May 2018 17:17:05 +0200 Subject: [PATCH 035/150] documentation --- .../include/CGAL/Optimal_bounding_box/obb.h | 24 ++++- .../CGAL/Eigen_linear_algebra_traits.h | 89 ++++++++++++++++++- 2 files changed, 110 insertions(+), 3 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index b9cb0362955..debc54445b3 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -52,6 +52,7 @@ typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; // works on matrices only +/// \cond SKIP_IN_MANUAL template void post_processing(const Matrix& points, Vertex& R, Matrix& obb) { @@ -91,7 +92,18 @@ void post_processing(const Matrix& points, Vertex& R, Matrix& obb) // 3) apply inverse rotation to rotated AABB obb = aabb * R; } +/// \endcond +/// \ingroup OBB_grp +/// calculates the optimal bounding box. +/// +/// @tparam Point the point type +/// @tparam LinearAlgebraTraits a model of `LinearAlgebraTraits` +/// +/// @param points the input points that are included in the optimal bounding box. +/// @param obb_points the eight points of the optimal bounding box to be calculated. +/// @param use_ch a bool flag to indicating whether to use the convex hull of the input points +/// as an optimization step. template void find_obb(std::vector& points, std::vector& obb_points, @@ -188,9 +200,17 @@ void find_obb(std::vector& points, } } +/// \ingroup OBB_grp +/// calculates the optimal bounding box. +/// +/// @tparam PolygonMesh a model of `FaceListGraph` +/// @tparam LinearAlgebraTraits a model of `LinearAlgebraTraits` +/// /// @param pmesh the input mesh. -/// @param obbmesh the obb in a hexahedron pmesh. -/// @param use convex hull or not. +/// @param obbmesh the hexaedron mesh to be built out of the optimal bounding box. +/// @param la_traits an instance of the linear algebra traits. +/// @param use_ch a bool flag to indicating whether to use the convex hull of the input points +/// as an optimization step. template void find_obb(PolygonMesh& pmesh, PolygonMesh& obbmesh, diff --git a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h index 697e49a7ad4..b6415474c73 100644 --- a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h +++ b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h @@ -33,12 +33,28 @@ namespace CGAL { template class Eigen_dense_vector; +/*! +\ingroup PkgSolver + +The class `Eigen_dense_matrix` is a wrapper around \ref thirdpartyEigen "Eigen" matrix type +`Eigen::DenseMatrix`. + +\tparam T Number type. +\tparam D1 Number of rows, or Dynamic. +\tparam D1 Number of cols, or Dynamic. + +\sa `CGAL::Eigen_dense_vector` +\sa `CGAL::Eigen_linear_algebra_traits` +*/ template class Eigen_dense_matrix { public: + + /// The internal matrix type from \ref thirdpartyEigen "Eigen". typedef Eigen::Matrix EigenType; + /// Create a dense matrix Eigen_dense_matrix(std::size_t nrows, std::size_t ncols) : m_matrix(static_cast(nrows), static_cast(ncols)) { @@ -46,6 +62,7 @@ public: CGAL_assertion(m_matrix.cols() > 0); } + /// Create a dense matrix Eigen_dense_matrix(int nrows, int ncols) : m_matrix(nrows, ncols) { @@ -53,16 +70,25 @@ public: CGAL_assertion(m_matrix.cols() > 0); } + /// Create a dense matrix out of a \ref thirdpartyEigen "Eigen" matrix type Eigen_dense_matrix(const EigenType& eigen_mat) : m_matrix(eigen_mat) {} Eigen_dense_matrix() : m_matrix() {} + /// Read access to a matrix coefficient. + /// + /// \pre 0 <= i < row_dimension(). + /// \pre 0 <= j < column_dimension(). T& operator() (int i_, int j_) { return m_matrix(i_, j_); } + /// Write access to a matrix coefficient: a_ij <- val + /// + /// \pre 0 <= i < row_dimension(). + /// \pre 0 <= j < column_dimension(). void set_coef(std::size_t i_, std::size_t j_, T val) { int i = static_cast(i_); @@ -73,9 +99,12 @@ public: m_matrix.coeffRef(i,j) = val; } + /// Return the matrix number of rows std::size_t rows() const {return m_matrix.rows();} + /// Return the matrix number of cols std::size_t cols() const {return m_matrix.cols();} + /// Resize to i rows and j cols void resize(int i_, int j_) { m_matrix.resize(i_, j_);} const T& coeff(int i_) const @@ -86,16 +115,36 @@ public: mutable EigenType m_matrix; }; +/*! +\ingroup PkgSolver +The class `Eigen_vector` is a wrapper around \ref thirdpartyEigen "Eigen" dense vector +type , +which is a simple array of numbers. + +\cgalModels `SvdTraits::Vector` +\cgalModels `SparseLinearAlgebraTraits_d::Vector`. + +\tparam T Number type. +\tparam D Number of colums, or Dynamic. + +\sa `CGAL::Eigen_dense_matrix` +\sa `CGAL::Eigen_linear_algebra_traits` +*/ template class Eigen_dense_vector { private: + + /// The internal vector type from \ref thirdpartyEigen "Eigen". typedef Eigen::Matrix EigenType; public: + + /// Create a dense vector out of a \ref thirdpartyEigen "Eigen" vector type Eigen_dense_vector(const EigenType& vec) : m_vector(vec) {} + /// Read and write and access to a vector coefficient: `a_i` const T& coeff(std::size_t i) { CGAL_assertion(i >= 0); @@ -107,6 +156,35 @@ public: }; +/*! +\ingroup PkgSolver + +The class `Eigen_linear_algebra_traits` provides an interface to linear algebra functionalities of \ref thirdpartyEigen "Eigen". +\ref thirdpartyEigen "Eigen" version 3.1 (or later) must be available on the system. + +\sa `CGAL::Eigen_dense_matrix` +\sa `CGAL::Eigen_dense_vector` +\sa http://eigen.tuxfamily.org + +Example +-------------- + +\code{.cpp} + +typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + +// dynamic matrix at run time to store a large amount of data +typedef Linear_algebra_traits::MatrixXd MatrixXd; + +// preallocated 3x3 matrix at compile time +typedef Linear_algebra_traits::Matrix3d Matrix3d; + +// preallocated 3-cols vector at compile time +typedef Linear_algebra_traits::Vector3d Vector3d; + +\endcode +*/ + class Eigen_linear_algebra_traits { public: @@ -124,18 +202,22 @@ public: // fixed at compile time typedef CGAL::Eigen_dense_vector Vector3d; + /// Get the transpose of a `CGAL::Eigen_dense_matrix` matrix template static Matrix transpose(const Matrix& mat) { return Matrix(mat.m_matrix.transpose()); } + /// Get the determinant of a `CGAL::Eigen_dense_matrix` matrix template static NT determinant(const Matrix& mat) { return mat.m_matrix.determinant(); } + /// Performs QR decomposition of matrix A to a unitary matrix and an upper triagonal + /// and returns the unitary matrix. template static CGAL::Eigen_dense_matrix qr_factorization(const CGAL::Eigen_dense_matrix& A) { @@ -156,6 +238,9 @@ public: // CGAL::Eigen_dense_vector : the returned type with D2 may be -1 in compile time, // and may not be equal to the expected type. // Eigen manages to return a precompiled row out of a dynamic matrix but I don't know how. + + /// Get the row vector out of a `CGAL::Eigen_dense_matrix`. The result is stored in a + /// preallocated at compile time 3-column `CGAL::Eigen_dense_vector` template static CGAL::Eigen_dense_vector row3(const CGAL::Eigen_dense_matrix& A, int i) @@ -166,7 +251,9 @@ public: }; -// matrix multiplication +/// Matrix multiplication. If the columns of A and the rows of B are equal at compile time, +/// the product is stored at a preallocated at compile time `CGAL::Eigen_dense_matrix`. Otherwise, +/// the product is stored in a dynamic at run time matrix. template const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix& A, const CGAL::Eigen_dense_matrix& B) From 284c2d9d337593e973b815745cf56a6f1eb70812 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Tue, 22 May 2018 10:34:32 +0200 Subject: [PATCH 036/150] python script setting up path --- .../benchmark/Optimal_bounding_box/data/times.txt | 5 +++++ .../Optimal_bounding_box/draw_benchmark_graph.py | 9 +++++---- .../benchmark/Optimal_bounding_box/readme.txt | 2 ++ 3 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 Optimal_bounding_box/benchmark/Optimal_bounding_box/data/times.txt create mode 100644 Optimal_bounding_box/benchmark/Optimal_bounding_box/readme.txt diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/times.txt b/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/times.txt new file mode 100644 index 00000000000..2ef3396b31b --- /dev/null +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/times.txt @@ -0,0 +1,5 @@ +nb_vertices with_ch without_ch +2775 0.037331 0.327787 +16670 0.118251 1.96901 +66692 0.362664 7.75459 +266780 1.20984 32.166 diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/draw_benchmark_graph.py b/Optimal_bounding_box/benchmark/Optimal_bounding_box/draw_benchmark_graph.py index 0bbb61d55b5..8fc416ac260 100644 --- a/Optimal_bounding_box/benchmark/Optimal_bounding_box/draw_benchmark_graph.py +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/draw_benchmark_graph.py @@ -1,18 +1,19 @@ import matplotlib.pyplot as plt import numpy as np -data = np.loadtxt("build/data/times.txt", skiprows = 1) +#path-to-benchmarks +benchmarkfile='data/times.txt' + +data = np.loadtxt(benchmarkfile, skiprows = 1) x = data[:, 0] y1 = data[:, 1] y2 = data[:, 2] - - plt.plot(x, y1, 'go--', label='with convex hull') plt.plot(x, y2, 'ro--', label='without convex hull') legend = plt.legend(loc='best') plt.xlabel('#vertices') plt.ylabel('seconds') -plt.show() \ No newline at end of file +plt.show() diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/readme.txt b/Optimal_bounding_box/benchmark/Optimal_bounding_box/readme.txt new file mode 100644 index 00000000000..b8995463fa7 --- /dev/null +++ b/Optimal_bounding_box/benchmark/Optimal_bounding_box/readme.txt @@ -0,0 +1,2 @@ +To draw a graph with the benchmark times set the path-to-the-measurments in draw_benchmark_times.py if necessary, +and run the script with python 3. From ca1d427dc5ee6d69758f1cda4883568210dac5de Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Tue, 22 May 2018 13:25:53 +0200 Subject: [PATCH 037/150] remove mutable and fix small typo --- .../Optimal_bounding_box/CMakeLists.txt | 0 .../Optimal_bounding_box/bench_custom.cpp | 0 .../Optimal_bounding_box/bench_fitness_function.cpp | 0 .../Optimal_bounding_box/bench_obb.cpp | 0 .../Optimal_bounding_box/bench_perfomance.cpp | 0 .../Optimal_bounding_box/data/elephant.off | 0 .../Optimal_bounding_box/data/linear.png | Bin .../Optimal_bounding_box/data/sphere_1k.xyz | 0 .../Optimal_bounding_box/data/times.txt | 0 .../Optimal_bounding_box/draw_benchmark_graph.py | 0 .../Optimal_bounding_box/readme.txt | 0 .../include/CGAL/Eigen_linear_algebra_traits.h | 4 ++-- 12 files changed, 2 insertions(+), 2 deletions(-) rename Optimal_bounding_box/{benchmark => benchmarks}/Optimal_bounding_box/CMakeLists.txt (100%) rename Optimal_bounding_box/{benchmark => benchmarks}/Optimal_bounding_box/bench_custom.cpp (100%) rename Optimal_bounding_box/{benchmark => benchmarks}/Optimal_bounding_box/bench_fitness_function.cpp (100%) rename Optimal_bounding_box/{benchmark => benchmarks}/Optimal_bounding_box/bench_obb.cpp (100%) rename Optimal_bounding_box/{benchmark => benchmarks}/Optimal_bounding_box/bench_perfomance.cpp (100%) rename Optimal_bounding_box/{benchmark => benchmarks}/Optimal_bounding_box/data/elephant.off (100%) rename Optimal_bounding_box/{benchmark => benchmarks}/Optimal_bounding_box/data/linear.png (100%) rename Optimal_bounding_box/{benchmark => benchmarks}/Optimal_bounding_box/data/sphere_1k.xyz (100%) rename Optimal_bounding_box/{benchmark => benchmarks}/Optimal_bounding_box/data/times.txt (100%) rename Optimal_bounding_box/{benchmark => benchmarks}/Optimal_bounding_box/draw_benchmark_graph.py (100%) rename Optimal_bounding_box/{benchmark => benchmarks}/Optimal_bounding_box/readme.txt (100%) diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt similarity index 100% rename from Optimal_bounding_box/benchmark/Optimal_bounding_box/CMakeLists.txt rename to Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp similarity index 100% rename from Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_custom.cpp rename to Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_fitness_function.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_fitness_function.cpp similarity index 100% rename from Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_fitness_function.cpp rename to Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_fitness_function.cpp diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp similarity index 100% rename from Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp rename to Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp similarity index 100% rename from Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_perfomance.cpp rename to Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/elephant.off b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/data/elephant.off similarity index 100% rename from Optimal_bounding_box/benchmark/Optimal_bounding_box/data/elephant.off rename to Optimal_bounding_box/benchmarks/Optimal_bounding_box/data/elephant.off diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/linear.png b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/data/linear.png similarity index 100% rename from Optimal_bounding_box/benchmark/Optimal_bounding_box/data/linear.png rename to Optimal_bounding_box/benchmarks/Optimal_bounding_box/data/linear.png diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/sphere_1k.xyz b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/data/sphere_1k.xyz similarity index 100% rename from Optimal_bounding_box/benchmark/Optimal_bounding_box/data/sphere_1k.xyz rename to Optimal_bounding_box/benchmarks/Optimal_bounding_box/data/sphere_1k.xyz diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/data/times.txt b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/data/times.txt similarity index 100% rename from Optimal_bounding_box/benchmark/Optimal_bounding_box/data/times.txt rename to Optimal_bounding_box/benchmarks/Optimal_bounding_box/data/times.txt diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/draw_benchmark_graph.py b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/draw_benchmark_graph.py similarity index 100% rename from Optimal_bounding_box/benchmark/Optimal_bounding_box/draw_benchmark_graph.py rename to Optimal_bounding_box/benchmarks/Optimal_bounding_box/draw_benchmark_graph.py diff --git a/Optimal_bounding_box/benchmark/Optimal_bounding_box/readme.txt b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/readme.txt similarity index 100% rename from Optimal_bounding_box/benchmark/Optimal_bounding_box/readme.txt rename to Optimal_bounding_box/benchmarks/Optimal_bounding_box/readme.txt diff --git a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h index b6415474c73..c1671586d4b 100644 --- a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h +++ b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h @@ -112,7 +112,7 @@ public: return m_matrix.coeff(i_); } - mutable EigenType m_matrix; + EigenType m_matrix; }; /*! @@ -152,7 +152,7 @@ public: return m_vector.coeff(i); } - mutable EigenType m_vector; + EigenType m_vector; }; From fe2f1b7e9d37b4cf83641ba0a02cb2d4f2c77d90 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 24 May 2018 07:10:28 +0100 Subject: [PATCH 038/150] fix include guards --- .../include/CGAL/Optimal_bounding_box/evolution.h | 14 +++----------- .../CGAL/Optimal_bounding_box/fitness_function.h | 4 ++-- .../include/CGAL/Optimal_bounding_box/helper.h | 4 ++-- .../Optimal_bounding_box/nelder_mead_functions.h | 6 +++--- .../include/CGAL/Optimal_bounding_box/obb.h | 5 ++--- 5 files changed, 12 insertions(+), 21 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index b8eab67ea17..648c1132f8f 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -19,8 +19,8 @@ // // Author(s) : Konstantinos Katrioplas -#ifndef CGAL_EVOLUTION_H -#define CGAL_EVOLUTION_H +#ifndef CGAL_OPTIMAL_BOUNDING_BOX_EVOLUTION_H +#define CGAL_OPTIMAL_BOUNDING_BOX_EVOLUTION_H #include #include @@ -344,12 +344,4 @@ void check_det(Population& pop) - - - - - - - - -#endif +#endif diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 2707b808968..96574801edd 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -19,8 +19,8 @@ // // Author(s) : Konstantinos Katrioplas -#ifndef CGAL_FITNESS_FUNCTION_H -#define CGAL_FITNESS_FUNCTION_H +#ifndef CGAL_OPTIMAL_BOUNDING_FITNESS_FUNCTION_H +#define CGAL_OPTIMAL_BOUNDING_FITNESS_FUNCTION_H #include #include diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h index e9c3a5eadb0..6fe275ca5a2 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h @@ -19,8 +19,8 @@ // // Author(s) : Konstantinos Katrioplas -#ifndef CGAL_HELPER_H -#define CGAL_HELPER_H +#ifndef CGAL_OPTIMAL_BOUNDING_HELPER_H +#define CGAL_OPTIMAL_BOUNDING_HELPER_H #include #include diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h index e7dbe3fc99c..92536efb788 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h @@ -19,8 +19,8 @@ // // Author(s) : Konstantinos Katrioplas -#ifndef CGAL_OPTIMAL_BOUNDING_BOX_H -#define CGAL_OPTIMAL_BOUNDING_BOX_H +#ifndef CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H +#define CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H #include #include @@ -94,6 +94,6 @@ const Matrix centroid(const Matrix& S1, const Matrix& S2, const Matrix& S3) -#endif //CGAL_OPTIMAL_BOUNDING_BOX_H +#endif diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index debc54445b3..6ed178b0df5 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -19,14 +19,13 @@ // // Author(s) : Konstantinos Katrioplas -#ifndef CGAL_OBB_H -#define CGAL_OBB_H +#ifndef CGAL_OPTIMAL_BOUNDING_BOX_OBB_H +#define CGAL_OPTIMAL_BOUNDING_BOX_OBB_H #include #include #include #include -#include #include #include #include From ff07272ef62f4d23d88cfe2f88954fce947481ba Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 24 May 2018 07:19:06 +0100 Subject: [PATCH 039/150] Use CGAL::abs --- .../include/CGAL/Optimal_bounding_box/evolution.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index 648c1132f8f..02345f436f6 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -288,7 +288,7 @@ public: Fitness_map fitness_map(population, point_data); new_fit_value = fitness_map.get_best_fitness_value(); double difference = new_fit_value - prev_fit_value; - if(abs(difference) < tolerance * new_fit_value) + if(CGAL::abs(difference) < tolerance * new_fit_value) stale++; if(stale == 5) From 0640743adccbb64145d7e2c95098c764f9886ce3 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 24 May 2018 07:27:42 +0100 Subject: [PATCH 040/150] Don't copy the vector --- .../include/CGAL/Optimal_bounding_box/evolution.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index 02345f436f6..601ce5cb9cc 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -308,13 +308,13 @@ private: // needed in genetic algorithm struct Comparator { - Comparator(std::vector in) : fitness(in) {} + Comparator(const std::vector& in) : fitness(in) {} inline bool operator() (std::size_t& i, std::size_t& j) { return fitness[i] < fitness[j]; } - std::vector fitness; + const std::vector& fitness; }; // data From 4defa4ebbce560890dea0f81859032aa1a1c39ff Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 24 May 2018 07:37:11 +0100 Subject: [PATCH 041/150] one less size_t/int warning --- .../include/CGAL/Optimal_bounding_box/evolution.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index 601ce5cb9cc..71844078a4d 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -138,14 +138,15 @@ public: std::vector ids3(m - m/2), ids4(m - m/2); CGAL::Random rng; + int im = static_cast(m); std::generate(ids1.begin(), ids1.end(), - [&rng, &m] () { return rng.get_int(0, m); }); + [&rng, &im] () { return rng.get_int(0, im); }); std::generate(ids2.begin(), ids2.end(), - [&rng, &m] () { return rng.get_int(0, m); }); + [&rng, &im] () { return rng.get_int(0, im); }); std::generate(ids3.begin(), ids3.end(), - [&rng, &m] () { return rng.get_int(0, m); }); + [&rng, &im] () { return rng.get_int(0, im); }); std::generate(ids4.begin(), ids4.end(), - [&rng, &m] () { return rng.get_int(0, m); }); + [&rng, &im] () { return rng.get_int(0, im); }); Population group1(m/2), group2(m/2); Population group3(m - m/2), group4(m - m/2); From 8a544b8dad676d448719876844b6e9f8601c5216 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 24 May 2018 08:06:01 +0100 Subject: [PATCH 042/150] Move typedef to the right scope --- .../include/CGAL/Optimal_bounding_box/helper.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h index 6fe275ca5a2..5f6d85f7f8a 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h @@ -27,7 +27,6 @@ #include #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; namespace CGAL { namespace Optimal_bounding_box { @@ -67,10 +66,11 @@ void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) } template -double calculate_volume(std::vector points) +double calculate_volume(const std::vector& points) { - CGAL::Bbox_3 bbox; - bbox = bbox_3(points.begin(), points.end()); + typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + + CGAL::Bbox_3 bbox = bbox_3(points.begin(), points.end()); K::Iso_cuboid_3 ic(bbox); return ic.volume(); } From c5e5ad701578976b01231c5658035da80b03b099 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 24 May 2018 08:20:39 +0100 Subject: [PATCH 043/150] Move #include --- .../include/CGAL/Optimal_bounding_box/evolution.h | 2 ++ .../include/CGAL/Optimal_bounding_box/nelder_mead_functions.h | 2 +- .../include/CGAL/Optimal_bounding_box/population.h | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index 71844078a4d..eeca2ce4e1c 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -23,6 +23,8 @@ #define CGAL_OPTIMAL_BOUNDING_BOX_EVOLUTION_H #include +#include + #include #include diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h index 92536efb788..8c4e396dfd3 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h @@ -23,7 +23,7 @@ #define CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H #include -#include + #if defined(CGAL_EIGEN3_ENABLED) #include diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index 1d09a0cbdc5..a6515b615f7 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -24,7 +24,6 @@ #include #include -#include #if defined(CGAL_EIGEN3_ENABLED) #include From d35b15bf082eca7e7164e4b4db889008c61d3405 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 24 May 2018 08:42:27 +0100 Subject: [PATCH 044/150] typo --- .../include/CGAL/Optimal_bounding_box/obb.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index 6ed178b0df5..9b1abc0f4d0 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -210,10 +210,10 @@ void find_obb(std::vector& points, /// @param la_traits an instance of the linear algebra traits. /// @param use_ch a bool flag to indicating whether to use the convex hull of the input points /// as an optimization step. -template +template void find_obb(PolygonMesh& pmesh, PolygonMesh& obbmesh, - LinearAlgrebraTraits& la_traits, + LinearAlgebraTraits& la_traits, bool use_ch) { CGAL_assertion(vertices(pmesh).size() >= 3); @@ -247,7 +247,7 @@ void find_obb(PolygonMesh& pmesh, -#endif //CGAL_OBB_H +#endif //CGAL_OPTIMAL_BOUNDING_BOX_OBB_H From 7803481af9b9cf48e5551d5e23948a818ec13436 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Fri, 25 May 2018 12:45:15 +0200 Subject: [PATCH 045/150] requested changes: impoving API with default Linear algebra traits, better use of template parameters at free functions, prefer using convex hull overload which does not depend on the kernel. --- .../CGAL/Optimal_bounding_box/evolution.h | 22 +++--- .../Optimal_bounding_box/fitness_function.h | 7 +- .../CGAL/Optimal_bounding_box/helper.h | 12 +-- .../nelder_mead_functions.h | 28 ++----- .../include/CGAL/Optimal_bounding_box/obb.h | 73 ++++++++++++------- .../CGAL/Optimal_bounding_box/population.h | 12 +-- .../test_linear_algebra_functions.cpp | 21 ++++-- .../test_optimization_algorithms.cpp | 50 +++++++++++-- .../CGAL/Eigen_linear_algebra_traits.h | 1 + 9 files changed, 134 insertions(+), 92 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index eeca2ce4e1c..5e0ecced2de 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -40,7 +40,7 @@ class Evolution typedef typename Linear_algebra_traits::Vector3d Vector3d; public: - Evolution(Population& pop, MatrixXd& points) : + Evolution(Population& pop, MatrixXd& points) : population(pop), point_data(points) {} @@ -81,11 +81,11 @@ public: fitness = s_fitness; // centroid - const Matrix3d v_centroid = centroid(simplex[0], simplex[1], simplex[2]); + const Matrix3d v_centroid = nm_centroid(simplex[0], simplex[1], simplex[2]); // find worst's vertex reflection const Matrix3d v_worst = simplex[3]; - const Matrix3d v_refl = reflection(v_centroid, v_worst); + const Matrix3d v_refl = reflection(v_centroid, v_worst); const double f_refl = compute_fitness(v_refl, point_data); if(f_refl < fitness[2]) @@ -98,7 +98,7 @@ public: else { // expansion - const Matrix3d v_expand = expansion(v_centroid, v_worst, v_refl); + const Matrix3d v_expand = expansion(v_centroid, v_worst, v_refl); const double f_expand = compute_fitness(v_expand, point_data); if(f_expand < f_refl) simplex[3] = v_expand; @@ -108,7 +108,7 @@ public: } else // if reflected vertex is not better { - const Matrix3d v_mean = mean(v_centroid, v_worst); + const Matrix3d v_mean = mean(v_centroid, v_worst); const double f_mean = compute_fitness(v_mean, point_data); if(f_mean <= fitness[3]) // contraction of worst @@ -118,7 +118,7 @@ public: // reduction: move all vertices towards the best for(std::size_t i=1; i < 4; ++i) { - simplex[i] = mean(simplex[i], simplex[0]); + simplex[i] = mean(simplex[i], simplex[0]); } } } @@ -150,8 +150,8 @@ public: std::generate(ids4.begin(), ids4.end(), [&rng, &im] () { return rng.get_int(0, im); }); - Population group1(m/2), group2(m/2); - Population group3(m - m/2), group4(m - m/2); + Population group1(m/2), group2(m/2); + Population group3(m - m/2), group4(m - m/2); for(std::size_t i = 0; i < ids1.size(); ++i) group1[i] = population[ids1[i]]; @@ -173,7 +173,7 @@ public: #endif // crossover I - Population offspringsA(size_first_group); + Population offspringsA(size_first_group); double bias = 0.1; for(std::size_t i = 0; i < size_first_group; ++i) @@ -204,7 +204,7 @@ public: #endif // crossover II - Population offspringsB(size_second_group); + Population offspringsB(size_second_group); bias = 0.1; for(std::size_t i = 0; i < size_second_group; ++i) @@ -321,7 +321,7 @@ private: }; // data - Population population; + Population population; MatrixXd point_data; }; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 96574801edd..cf73880e747 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -41,9 +41,10 @@ double compute_fitness(const Vertex& R, const Matrix& data) CGAL_assertion(data.rows() >= 3); typedef typename Linear_algebra_traits::Vector3d Vector3d; + typedef typename Linear_algebra_traits::Index index; double xmin, xmax, ymin, ymax, zmin, zmax; - for(int i = 0; i < data.rows(); ++i){ + for(index i = 0; i < data.rows(); ++i){ Vector3d vec = Linear_algebra_traits::row3(data, i); vec = R * vec; @@ -73,7 +74,7 @@ double compute_fitness(const Vertex& R, const Matrix& data) template struct Fitness_map { - Fitness_map(Population& p, Matrix& points) : pop(p), points(points) + Fitness_map(Population& p, Matrix& points) : pop(p), points(points) {} const Vertex get_best() @@ -104,7 +105,7 @@ struct Fitness_map return compute_fitness(best_mat, points); } - Population& pop; + Population& pop; const Matrix& points; }; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h index 5f6d85f7f8a..f5d695c78c4 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h @@ -39,9 +39,9 @@ void fill_matrix(std::vector& v_points, Matrix& points_mat) for(std::size_t i = 0; i < v_points.size(); ++i) { Point p = v_points[i]; - points_mat.set_coef(i, 0, p.x()); - points_mat.set_coef(i, 1, p.y()); - points_mat.set_coef(i, 2, p.z()); + points_mat.set_coef(i, 0, CGAL::to_double(p.x())); + points_mat.set_coef(i, 1, CGAL::to_double(p.y())); + points_mat.set_coef(i, 2, CGAL::to_double(p.z())); } } @@ -58,9 +58,9 @@ void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) for(vertex_descriptor v : vertices(sm)) { Point_ref p = get(vpm, v); - mat.set_coef(i, 0, p.x()); - mat.set_coef(i, 1, p.y()); - mat.set_coef(i, 2, p.z()); + mat.set_coef(i, 0, CGAL::to_double(p.x())); + mat.set_coef(i, 1, CGAL::to_double(p.y())); + mat.set_coef(i, 2, CGAL::to_double(p.z())); ++i; } } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h index 8c4e396dfd3..b22b75c53e0 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h @@ -22,23 +22,12 @@ #ifndef CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H #define CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H -#include - - -#if defined(CGAL_EIGEN3_ENABLED) -#include -#endif - - namespace CGAL { namespace Optimal_bounding_box { -#if defined(CGAL_EIGEN3_ENABLED) -typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; -#endif -template +template const Matrix reflection(const Matrix& S_centroid, const Matrix& S_worst) { CGAL_assertion(S_centroid.rows() == 3); @@ -49,7 +38,7 @@ const Matrix reflection(const Matrix& S_centroid, const Matrix& S_worst) return S_centroid * Linear_algebra_traits::transpose(S_worst) * S_centroid; } -template +template const Matrix expansion(const Matrix& S_centroid, const Matrix& S_worst, const Matrix& S_reflection) { CGAL_assertion(S_centroid.rows() == 3); @@ -62,7 +51,7 @@ const Matrix expansion(const Matrix& S_centroid, const Matrix& S_worst, const Ma return S_centroid * Linear_algebra_traits::transpose(S_worst) * S_reflection; } -template +template Matrix mean(const Matrix& m1, const Matrix& m2) { // same API for reduction @@ -77,8 +66,8 @@ Matrix mean(const Matrix& m1, const Matrix& m2) return Q / det; } -template -const Matrix centroid(const Matrix& S1, const Matrix& S2, const Matrix& S3) +template +const Matrix nm_centroid(const Matrix& S1, const Matrix& S2, const Matrix& S3) { Matrix mean = (S1 + S2 + S3) / 3.0; Matrix Q = Linear_algebra_traits::qr_factorization(mean); @@ -86,14 +75,7 @@ const Matrix centroid(const Matrix& S1, const Matrix& S2, const Matrix& S3) return Q / det; } - }} // end namespaces - - - - #endif - - diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index 9b1abc0f4d0..8bd6785ce4f 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #ifdef OBB_BENCHMARKS @@ -45,14 +44,9 @@ namespace CGAL { namespace Optimal_bounding_box { -#if defined(CGAL_EIGEN3_ENABLED) -typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; -#endif - - // works on matrices only /// \cond SKIP_IN_MANUAL -template +template void post_processing(const Matrix& points, Vertex& R, Matrix& obb) { CGAL_assertion(points.cols() == 3); @@ -68,8 +62,11 @@ void post_processing(const Matrix& points, Vertex& R, Matrix& obb) // 2) get AABB from rotated points typedef CGAL::Simple_cartesian K; typedef K::Point_3 Point; - std::vector v_points; // Simplex -> std::vector - for(std::size_t i = 0; i < rotated_points.rows(); ++i) + typedef typename Linear_algebra_traits::Index index; + + // Simplex -> std::vector + std::vector v_points; + for(index i = 0; i < rotated_points.rows(); ++i) { Point p(rotated_points(i, 0), rotated_points(i, 1), rotated_points(i, 2)); v_points.push_back(p); @@ -78,9 +75,7 @@ void post_processing(const Matrix& points, Vertex& R, Matrix& obb) bbox = bbox_3(v_points.begin(), v_points.end()); K::Iso_cuboid_3 ic(bbox); - // Matrix is [dynamic, 3] at compile time, so it needs allocation of rows at run time. Matrix aabb(8, 3); - for(std::size_t i = 0; i < 8; ++i) { aabb.set_coef(i, 0, ic[i].x()); @@ -97,7 +92,8 @@ void post_processing(const Matrix& points, Vertex& R, Matrix& obb) /// calculates the optimal bounding box. /// /// @tparam Point the point type -/// @tparam LinearAlgebraTraits a model of `LinearAlgebraTraits` +/// @tparam LinearAlgebraTraits a model of `LinearAlgebraTraits`. If no instance of `LinearAlgebraTraits` +/// is provided, then `CGAL::Eigen_linear_algebra_traits` is used. /// /// @param points the input points that are included in the optimal bounding box. /// @param obb_points the eight points of the optimal bounding box to be calculated. @@ -111,31 +107,23 @@ void find_obb(std::vector& points, { CGAL_assertion(points.size() >= 3); - if(obb_points.size() != 8) // temp sanity until the API is decided + if(obb_points.size() != 8) obb_points.resize(8); CGAL_assertion(obb_points.size() == 8); // eigen linear algebra traits typedef typename LinearAlgebraTraits::MatrixXd MatrixXd; typedef typename LinearAlgebraTraits::Matrix3d Matrix3d; - MatrixXd points_mat; - // get the ch3 - if(use_ch) + if(use_ch) // get the ch3 { - // find the ch - todo: template kernel - typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; - CGAL::Polyhedron_3 poly; - convex_hull_3(points.begin(), points.end(), poly); - std::vector ch_points(poly.points_begin(), poly.points_end()); - - // points: vector -> matrix + std::vector ch_points; + CGAL::extreme_points_3(points, std::back_inserter(ch_points)); CGAL::Optimal_bounding_box::fill_matrix(ch_points, points_mat); } else { - // points: vector -> matrix CGAL::Optimal_bounding_box::fill_matrix(points, points_mat); } @@ -144,7 +132,7 @@ void find_obb(std::vector& points, #endif std::size_t max_generations = 100; - Population pop(50); + Population pop(50); #ifdef OBB_BENCHMARKS timer.start(); @@ -184,7 +172,7 @@ void find_obb(std::vector& points, timer.start(); #endif - post_processing(points_mat, rotation, obb); + post_processing(points_mat, rotation, obb); #ifdef OBB_BENCHMARKS timer.stop(); @@ -199,11 +187,28 @@ void find_obb(std::vector& points, } } +template +void find_obb(std::vector& points, + std::vector& obb_points, + bool use_ch) +{ +#if defined(CGAL_EIGEN3_ENABLED) + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; +#else + Linear_algebra_traits; +#endif + + Linear_algebra_traits la_traits; + find_obb(points, obb_points, la_traits, use_ch); + +} + /// \ingroup OBB_grp /// calculates the optimal bounding box. /// /// @tparam PolygonMesh a model of `FaceListGraph` -/// @tparam LinearAlgebraTraits a model of `LinearAlgebraTraits` +/// @tparam LinearAlgebraTraits a model of `LinearAlgebraTraits`. If no instance of `LinearAlgebraTraits` +/// is provided, then `CGAL::Eigen_linear_algebra_traits` is used. /// /// @param pmesh the input mesh. /// @param obbmesh the hexaedron mesh to be built out of the optimal bounding box. @@ -242,6 +247,20 @@ void find_obb(PolygonMesh& pmesh, obb_points[6], obb_points[7], obbmesh); } +template +void find_obb(PolygonMesh& pmesh, + PolygonMesh& obbmesh, + bool use_ch) +{ +#if defined(CGAL_EIGEN3_ENABLED) + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; +#else + Linear_algebra_traits; +#endif + + Linear_algebra_traits la_traits; + find_obb(pmesh, obbmesh, la_traits, use_ch); +} }} // end namespaces diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index a6515b615f7..eb8ca1aaf4e 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -25,23 +25,15 @@ #include #include -#if defined(CGAL_EIGEN3_ENABLED) -#include -#endif -//#define OBB_DEBUG namespace CGAL { namespace Optimal_bounding_box { -template +template class Population { - -#if defined(CGAL_EIGEN3_ENABLED) - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; -#endif - + typedef typename Linear_algebra_traits::Matrix3d Matrix; typedef std::vector Simplex; public: diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index ba259ff0710..fd2e7a45f5b 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include @@ -80,6 +79,8 @@ void test_fitness_function() void test_simplex_operations() { + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + CGAL::Eigen_dense_matrix Sc(3, 3); Sc.set_coef(0, 0, -0.809204); Sc.set_coef(0, 1, 0.124296); @@ -102,7 +103,8 @@ void test_simplex_operations() S_worst.set_coef(2, 1, 0.30543); S_worst.set_coef(2, 2, 0.35833); - CGAL::Eigen_dense_matrix Sr = CGAL::Optimal_bounding_box::reflection(Sc, S_worst); + CGAL::Eigen_dense_matrix Sr = + CGAL::Optimal_bounding_box::reflection(Sc, S_worst); CGAL_assertion_code(double epsilon = 1e-5); CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); @@ -114,7 +116,8 @@ void test_simplex_operations() CGAL_assertion(assert_doubles(Sr(2,1), 0.25411, epsilon)); CGAL_assertion(assert_doubles(Sr(2,2), -0.56300, epsilon)); - CGAL::Eigen_dense_matrix Se = CGAL::Optimal_bounding_box::expansion(Sc, S_worst, Sr); + CGAL::Eigen_dense_matrix Se = + CGAL::Optimal_bounding_box::expansion(Sc, S_worst, Sr); CGAL_assertion(assert_doubles(Se(0,0), -0.87991, epsilon)); CGAL_assertion(assert_doubles(Se(0,1), 0.36105, epsilon)); CGAL_assertion(assert_doubles(Se(0,2), -0.30888, epsilon)); @@ -147,7 +150,8 @@ void test_simplex_operations() S_b.set_coef(2, 1, 0.581624); S_b.set_coef(2, 2, 0.514314); - CGAL::Eigen_dense_matrix S_c = CGAL::Optimal_bounding_box::mean(S_a, S_b); + CGAL::Eigen_dense_matrix S_c = + CGAL::Optimal_bounding_box::mean(S_a, S_b); CGAL_assertion(assert_doubles(S_c(0,0), -0.35111, epsilon)); CGAL_assertion(assert_doubles(S_c(0,1), 0.79308, epsilon)); CGAL_assertion(assert_doubles(S_c(0,2), -0.49774, epsilon)); @@ -161,6 +165,8 @@ void test_simplex_operations() void test_centroid() { + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + CGAL::Eigen_dense_matrix S_a; S_a.set_coef(0, 0, -0.588443); S_a.set_coef(0, 1, 0.807140); @@ -195,7 +201,7 @@ void test_centroid() S_c.set_coef(2, 2, 0.11207); CGAL::Eigen_dense_matrix S_centroid = - CGAL::Optimal_bounding_box::centroid(S_a, S_b, S_c); + CGAL::Optimal_bounding_box::nm_centroid(S_a, S_b, S_c); CGAL_assertion_code(double epsilon = 1e-5); CGAL_assertion(assert_doubles(S_centroid(0,0), -0.419979, epsilon)); CGAL_assertion(assert_doubles(S_centroid(0,1), 0.301765, epsilon)); @@ -210,6 +216,8 @@ void test_centroid() void test_eigen_matrix_interface() { + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + CGAL::Eigen_dense_matrix A(3, 3); A.set_coef(0, 0, 0.1); A.set_coef(0, 1, 0.2); @@ -269,7 +277,8 @@ void test_eigen_matrix_interface() E.set_coef(2, 1, 0.30543); E.set_coef(2, 2, 0.35833); - CGAL::Eigen_dense_matrix Sr = CGAL::Optimal_bounding_box::reflection(D, E); + CGAL::Eigen_dense_matrix Sr = + CGAL::Optimal_bounding_box::reflection(D, E); CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); CGAL_assertion(assert_doubles(Sr(0,2), -0.24664, epsilon)); diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 5e6d8268627..7af0ba43a6e 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -88,7 +88,7 @@ void test_nelder_mead() simplex[2] = v2; simplex[3] = v3; - CGAL::Optimal_bounding_box::Population pop(1); + CGAL::Optimal_bounding_box::Population pop(1); std::size_t nm_iterations = 19; CGAL::Optimal_bounding_box::Evolution @@ -158,9 +158,9 @@ void test_genetic_algorithm() data_points(3,2) = 0.364944; typedef CGAL::Eigen_dense_matrix Matrix3d; - CGAL::Optimal_bounding_box::Population pop(5); - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + + CGAL::Optimal_bounding_box::Population pop(5); CGAL::Optimal_bounding_box::Evolution evolution(pop, data_points); evolution.genetic_algorithm(); @@ -208,7 +208,7 @@ void test_random_unit_tetra() typedef Linear_algebra_traits::Matrix3d Matrix3d; std::size_t generations = 10; - CGAL::Optimal_bounding_box::Population pop(50); + CGAL::Optimal_bounding_box::Population pop(50); CGAL::Optimal_bounding_box::Evolution evolution(pop, data_points); evolution.evolve(generations); @@ -252,7 +252,7 @@ void test_reference_tetrahedron(const char* fname) CGAL::Optimal_bounding_box::sm_to_matrix(mesh, points); std::size_t generations = 10; - CGAL::Optimal_bounding_box::Population pop(50); + CGAL::Optimal_bounding_box::Population pop(50); CGAL::Optimal_bounding_box::Evolution experiment(pop, points); experiment.evolve(generations); @@ -287,7 +287,7 @@ void test_long_tetrahedron(std::string fname) CGAL::Optimal_bounding_box::sm_to_matrix(mesh, points); std::size_t max_generations = 10; - CGAL::Optimal_bounding_box::Population pop(50); + CGAL::Optimal_bounding_box::Population pop(50); CGAL::Optimal_bounding_box::Evolution experiment(pop, points); experiment.evolve(max_generations); @@ -376,6 +376,43 @@ void test_find_obb_mesh(std::string fname) #endif } +void test_function_defaults_traits(std::string fname1, std::string fname2) +{ + std::ifstream input1(fname1); + CGAL::Surface_mesh mesh1; + if (!input1 || !(input1 >> mesh1) || mesh1.is_empty()) { + std::cerr << fname1 << " is not a valid off file.\n"; + exit(1); + } + + std::ifstream input2(fname2); + CGAL::Surface_mesh mesh2; + if (!input2 || !(input2 >> mesh2) || mesh2.is_empty()) { + std::cerr << fname2 << " is not a valid off file.\n"; + exit(1); + } + + // test one + std::vector sm_points; + typedef CGAL::Surface_mesh SMesh; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::property_map::const_type PointPMap; + PointPMap pmap = get(boost::vertex_point, mesh1); + BOOST_FOREACH(vertex_descriptor v, vertices(mesh1)) + sm_points.push_back(get(pmap, v)); + + std::vector obb_points; + CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true); + + CGAL_assertion_code(double epsilon = 1e-3); + CGAL_assertion_code(double vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points)); + CGAL_assertion(assert_doubles(vol, 0.883371, epsilon)); + + // test two + CGAL::Surface_mesh< K::Point_3> obbmesh; + CGAL::Optimal_bounding_box::find_obb(mesh2, obbmesh, true); +} + int main() { test_nelder_mead(); @@ -385,6 +422,7 @@ int main() test_long_tetrahedron("data/long_tetrahedron.off"); test_find_obb_evolution("data/random_unit_tetra.off"); test_find_obb_mesh("data/elephant.off"); + test_function_defaults_traits("data/random_unit_tetra.off", "data/elephant.off"); return 0; } diff --git a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h index c1671586d4b..e56f1775f53 100644 --- a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h +++ b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h @@ -189,6 +189,7 @@ class Eigen_linear_algebra_traits { public: typedef double NT; + typedef int Index; // dynamic size at run time typedef CGAL::Eigen_dense_matrix MatrixXd; From 6fd928def0cbb1e8de81e178da9a1d0b65447b2f Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Mon, 11 Jun 2018 14:31:38 +0200 Subject: [PATCH 046/150] added forgotten const qualifiers --- .../include/CGAL/Optimal_bounding_box/helper.h | 2 +- .../Optimal_bounding_box/nelder_mead_functions.h | 1 + .../include/CGAL/Optimal_bounding_box/obb.h | 13 ++++++------- .../test_linear_algebra_functions.cpp | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h index f5d695c78c4..febf283f5a3 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h @@ -33,7 +33,7 @@ namespace Optimal_bounding_box { template -void fill_matrix(std::vector& v_points, Matrix& points_mat) +void fill_matrix(const std::vector& v_points, Matrix& points_mat) { points_mat.resize(v_points.size(), 3); for(std::size_t i = 0; i < v_points.size(); ++i) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h index b22b75c53e0..06a050ffa87 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h @@ -22,6 +22,7 @@ #ifndef CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H #define CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H +#include namespace CGAL { namespace Optimal_bounding_box { diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index 8bd6785ce4f..ff84909f594 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -100,7 +100,7 @@ void post_processing(const Matrix& points, Vertex& R, Matrix& obb) /// @param use_ch a bool flag to indicating whether to use the convex hull of the input points /// as an optimization step. template -void find_obb(std::vector& points, +void find_obb(const std::vector& points, std::vector& obb_points, LinearAlgebraTraits&, bool use_ch) @@ -164,7 +164,7 @@ void find_obb(std::vector& points, std::cout << "get best: " << timer.time() << std::endl; #endif - MatrixXd obb; // could be preallocated at compile time + MatrixXd obb; // may be preallocated at compile time obb.resize(8, 3); #ifdef OBB_BENCHMARKS @@ -188,7 +188,7 @@ void find_obb(std::vector& points, } template -void find_obb(std::vector& points, +void find_obb(const std::vector& points, std::vector& obb_points, bool use_ch) { @@ -200,7 +200,6 @@ void find_obb(std::vector& points, Linear_algebra_traits la_traits; find_obb(points, obb_points, la_traits, use_ch); - } /// \ingroup OBB_grp @@ -216,7 +215,7 @@ void find_obb(std::vector& points, /// @param use_ch a bool flag to indicating whether to use the convex hull of the input points /// as an optimization step. template -void find_obb(PolygonMesh& pmesh, +void find_obb(const PolygonMesh& pmesh, PolygonMesh& obbmesh, LinearAlgebraTraits& la_traits, bool use_ch) @@ -232,13 +231,13 @@ void find_obb(PolygonMesh& pmesh, typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::property_map::type Vpm; typedef typename boost::property_traits::value_type Point; - //typedef typename Kernel_traits::Kernel Kernel; std::vector points; Vpm pmap = get(boost::vertex_point, pmesh); BOOST_FOREACH(vertex_descriptor v, vertices(pmesh)) points.push_back(get(pmap, v)); + std::vector obb_points; find_obb(points, obb_points, la_traits, use_ch); @@ -248,7 +247,7 @@ void find_obb(PolygonMesh& pmesh, } template -void find_obb(PolygonMesh& pmesh, +void find_obb(const PolygonMesh& pmesh, PolygonMesh& obbmesh, bool use_ch) { diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index fd2e7a45f5b..673624a81fc 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -1,8 +1,8 @@ #include #include +#include #include #include - #include bool assert_doubles(double d1, double d2, double epsilon) From f60ca1c3f9ef29441831c993646060e4c034e39f Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Mon, 11 Jun 2018 16:16:36 +0200 Subject: [PATCH 047/150] remove warnings --- .../Optimal_bounding_box/bench_custom.cpp | 1 - .../bench_fitness_function.cpp | 7 +- .../Optimal_bounding_box/bench_obb.cpp | 6 -- .../Optimal_bounding_box/bench_perfomance.cpp | 1 - .../Optimal_bounding_box/fitness_function.h | 4 +- .../include/CGAL/Optimal_bounding_box/obb.h | 2 +- .../test_linear_algebra_functions.cpp | 66 +++++++++---------- .../test_optimization_algorithms.cpp | 27 +++----- 8 files changed, 50 insertions(+), 64 deletions(-) diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp index 7209f3a3346..33f42eb27c3 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_fitness_function.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_fitness_function.cpp index bda67e7d9f9..2b70a2610c9 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_fitness_function.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_fitness_function.cpp @@ -35,13 +35,14 @@ int main() // 2) fill a Matrix with them typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; typedef Linear_algebra_traits::MatrixX3d MatrixX3d; + typedef Linear_algebra_traits::Matrix3d Matrix3d; + MatrixX3d points_mat(nb_points, 3); CGAL::Optimal_bounding_box::sm_to_matrix(mesh, points_mat); // 3) create a population of simplices - typedef Linear_algebra_traits::Matrix3d Matrix3d; - CGAL::Optimal_bounding_box::Population pop(50); + CGAL::Optimal_bounding_box::Population pop(50); CGAL::Timer timer; @@ -60,4 +61,4 @@ int main() return 0; -} \ No newline at end of file +} diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp index fb759595d1f..1bf8bddad18 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp @@ -83,12 +83,6 @@ void bench_finding_obb(std::string fname) std::cout << "found obb without convex hull: " << timer.time() << " seconds\n"; timer.reset(); - - //double vol1 = calculate_volume(obb_points1); - // double vol2 = calculate_volume(obb_points2); - //std::cout << "vol1= " << vol1 << " -- " << "vol2= " << vol2 << std::endl; - - #ifdef OBB_DEBUG_BENCHMARK CGAL::Surface_mesh result_mesh1; CGAL::make_hexahedron(obb_points1[0], obb_points1[1], obb_points1[2], obb_points1[3], diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp index 128a9f67f24..855c21e558c 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index cf73880e747..5810bb1a99c 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -41,10 +41,10 @@ double compute_fitness(const Vertex& R, const Matrix& data) CGAL_assertion(data.rows() >= 3); typedef typename Linear_algebra_traits::Vector3d Vector3d; - typedef typename Linear_algebra_traits::Index index; + typedef typename Linear_algebra_traits::Index Index; double xmin, xmax, ymin, ymax, zmin, zmax; - for(index i = 0; i < data.rows(); ++i){ + for(Index i = 0; i < static_cast(data.rows()); ++i){ Vector3d vec = Linear_algebra_traits::row3(data, i); vec = R * vec; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h index ff84909f594..80e294ef5c5 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h @@ -66,7 +66,7 @@ void post_processing(const Matrix& points, Vertex& R, Matrix& obb) // Simplex -> std::vector std::vector v_points; - for(index i = 0; i < rotated_points.rows(); ++i) + for(index i = 0; i < static_cast(rotated_points.rows()); ++i) { Point p(rotated_points(i, 0), rotated_points(i, 1), rotated_points(i, 2)); v_points.push_back(p); diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index 673624a81fc..0278b1cce15 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -12,7 +12,8 @@ bool assert_doubles(double d1, double d2, double epsilon) void test_qr_factorization() { - CGAL::Eigen_dense_matrix A(3, 3); + typedef CGAL::Eigen_dense_matrix Mat; + Mat A(3, 3); A.set_coef(0, 0, 0.3011944); A.set_coef(0, 1, 0.9932761); A.set_coef(0, 2, 0.5483701); @@ -23,9 +24,7 @@ void test_qr_factorization() A.set_coef(2, 1, 0.0202949); A.set_coef(2, 2, 0.9240308); - CGAL::Eigen_dense_matrix Q = - CGAL::Eigen_linear_algebra_traits::qr_factorization(A); - + CGAL_assertion_code(Mat Q = CGAL::Eigen_linear_algebra_traits::qr_factorization(A)); CGAL_assertion_code(double epsilon = 1e-6); CGAL_assertion(assert_doubles(Q(0,0), -0.504895, epsilon)); CGAL_assertion(assert_doubles(Q(0,1), 0.862834, epsilon)); @@ -79,9 +78,10 @@ void test_fitness_function() void test_simplex_operations() { - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + CGAL_assertion_code(typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits); + typedef CGAL::Eigen_dense_matrix Matrix; - CGAL::Eigen_dense_matrix Sc(3, 3); + Matrix Sc(3, 3); Sc.set_coef(0, 0, -0.809204); Sc.set_coef(0, 1, 0.124296); Sc.set_coef(0, 2, 0.574230); @@ -92,7 +92,7 @@ void test_simplex_operations() Sc.set_coef(2, 1, -0.991602); Sc.set_coef(2, 2, 0.042528); - CGAL::Eigen_dense_matrix S_worst(3, 3); + Matrix S_worst(3, 3); S_worst.set_coef(0, 0, -0.45070); S_worst.set_coef(0, 1, -0.32769); S_worst.set_coef(0, 2, -0.83035); @@ -103,8 +103,7 @@ void test_simplex_operations() S_worst.set_coef(2, 1, 0.30543); S_worst.set_coef(2, 2, 0.35833); - CGAL::Eigen_dense_matrix Sr = - CGAL::Optimal_bounding_box::reflection(Sc, S_worst); + CGAL_assertion_code(Matrix Sr = CGAL::Optimal_bounding_box::reflection(Sc, S_worst)); CGAL_assertion_code(double epsilon = 1e-5); CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); @@ -116,8 +115,8 @@ void test_simplex_operations() CGAL_assertion(assert_doubles(Sr(2,1), 0.25411, epsilon)); CGAL_assertion(assert_doubles(Sr(2,2), -0.56300, epsilon)); - CGAL::Eigen_dense_matrix Se = - CGAL::Optimal_bounding_box::expansion(Sc, S_worst, Sr); + CGAL_assertion_code(Matrix Se = + CGAL::Optimal_bounding_box::expansion(Sc, S_worst, Sr)); CGAL_assertion(assert_doubles(Se(0,0), -0.87991, epsilon)); CGAL_assertion(assert_doubles(Se(0,1), 0.36105, epsilon)); CGAL_assertion(assert_doubles(Se(0,2), -0.30888, epsilon)); @@ -128,7 +127,7 @@ void test_simplex_operations() CGAL_assertion(assert_doubles(Se(2,1), -0.48595, epsilon)); CGAL_assertion(assert_doubles(Se(2,2), 0.74300, epsilon)); - CGAL::Eigen_dense_matrix S_a(3, 3); + Matrix S_a(3, 3); S_a.set_coef(0, 0, -0.277970); S_a.set_coef(0, 1, 0.953559); S_a.set_coef(0, 2, 0.116010); @@ -139,7 +138,7 @@ void test_simplex_operations() S_a.set_coef(2, 1, -0.293982); S_a.set_coef(2, 2, 0.559370); - CGAL::Eigen_dense_matrix S_b(3, 3); + Matrix S_b(3, 3); S_b.set_coef(0, 0, -0.419979); S_b.set_coef(0, 1, 0.301765); S_b.set_coef(0, 2, -0.8558940); @@ -150,8 +149,8 @@ void test_simplex_operations() S_b.set_coef(2, 1, 0.581624); S_b.set_coef(2, 2, 0.514314); - CGAL::Eigen_dense_matrix S_c = - CGAL::Optimal_bounding_box::mean(S_a, S_b); + CGAL_assertion_code(Matrix S_c = + CGAL::Optimal_bounding_box::mean(S_a, S_b)); CGAL_assertion(assert_doubles(S_c(0,0), -0.35111, epsilon)); CGAL_assertion(assert_doubles(S_c(0,1), 0.79308, epsilon)); CGAL_assertion(assert_doubles(S_c(0,2), -0.49774, epsilon)); @@ -165,9 +164,10 @@ void test_simplex_operations() void test_centroid() { - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + CGAL_assertion_code(typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits); + typedef CGAL::Eigen_dense_matrix Matrix; - CGAL::Eigen_dense_matrix S_a; + Matrix S_a; S_a.set_coef(0, 0, -0.588443); S_a.set_coef(0, 1, 0.807140); S_a.set_coef(0, 2, -0.047542); @@ -178,7 +178,7 @@ void test_centroid() S_a.set_coef(2, 1, -0.079867); S_a.set_coef(2, 2, 0.978795); - CGAL::Eigen_dense_matrix S_b(3, 3); + Matrix S_b(3, 3); S_b.set_coef(0, 0, -0.2192721); S_b.set_coef(0, 1, 0.2792986); S_b.set_coef(0, 2, -0.9348326); @@ -189,7 +189,7 @@ void test_centroid() S_b.set_coef(2, 1, 0.7253193); S_b.set_coef(2, 2, 0.3550431); - CGAL::Eigen_dense_matrix S_c(3, 3); + Matrix S_c(3, 3); S_c.set_coef(0, 0, -0.32657); S_c.set_coef(0, 1, -0.60013); S_c.set_coef(0, 2, -0.730206); @@ -200,8 +200,8 @@ void test_centroid() S_c.set_coef(2, 1, 0.36630); S_c.set_coef(2, 2, 0.11207); - CGAL::Eigen_dense_matrix S_centroid = - CGAL::Optimal_bounding_box::nm_centroid(S_a, S_b, S_c); + CGAL_assertion_code(Matrix S_centroid = + CGAL::Optimal_bounding_box::nm_centroid(S_a, S_b, S_c)); CGAL_assertion_code(double epsilon = 1e-5); CGAL_assertion(assert_doubles(S_centroid(0,0), -0.419979, epsilon)); CGAL_assertion(assert_doubles(S_centroid(0,1), 0.301765, epsilon)); @@ -216,9 +216,10 @@ void test_centroid() void test_eigen_matrix_interface() { - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + CGAL_assertion_code(typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits); + typedef CGAL::Eigen_dense_matrix Matrix; - CGAL::Eigen_dense_matrix A(3, 3); + Matrix A(3, 3); A.set_coef(0, 0, 0.1); A.set_coef(0, 1, 0.2); A.set_coef(0, 2, 0.3); @@ -228,9 +229,11 @@ void test_eigen_matrix_interface() A.set_coef(2, 0, 0.7); A.set_coef(2, 1, 0.8); A.set_coef(2, 2, 0.9); - CGAL::Eigen_dense_matrix B = CGAL::Eigen_linear_algebra_traits::transpose(A); - CGAL::Eigen_dense_matrix S = 0.5 * A; - CGAL::Eigen_dense_matrix C(3,3); + CGAL_assertion_code(Matrix B); + CGAL_assertion_code(B = CGAL::Eigen_linear_algebra_traits::transpose(A)); + CGAL_assertion_code(Matrix S); + CGAL_assertion_code(S = 0.5 * A); + Matrix C(3,3); C.set_coef(0, 0, 0.3011944); C.set_coef(0, 1, 0.9932761); C.set_coef(0, 2, 0.5483701); @@ -241,9 +244,7 @@ void test_eigen_matrix_interface() C.set_coef(2, 1, 0.0202949); C.set_coef(2, 2, 0.9240308); - CGAL::Eigen_dense_matrix Q = - CGAL::Eigen_linear_algebra_traits::qr_factorization(C); - + CGAL_assertion_code(Matrix Q = CGAL::Eigen_linear_algebra_traits::qr_factorization(C)); CGAL_assertion_code(double epsilon = 1e-5); CGAL_assertion(assert_doubles(Q(0,0), -0.504895, epsilon)); CGAL_assertion(assert_doubles(Q(0,1), 0.862834, epsilon)); @@ -255,7 +256,7 @@ void test_eigen_matrix_interface() CGAL_assertion(assert_doubles(Q(2,1), 0.024478, epsilon)); CGAL_assertion(assert_doubles(Q(2,2), 0.999679, epsilon)); - CGAL::Eigen_dense_matrix D(3,3); + Matrix D(3,3); D.set_coef(0, 0, -0.809204); D.set_coef(0, 1, 0.124296); D.set_coef(0, 2, 0.574230); @@ -266,7 +267,7 @@ void test_eigen_matrix_interface() D.set_coef(2, 1, -0.991602); D.set_coef(2, 2, 0.042528); - CGAL::Eigen_dense_matrix E(3,3); + Matrix E(3,3); E.set_coef(0, 0, -0.45070); E.set_coef(0, 1, -0.32769); E.set_coef(0, 2, -0.83035); @@ -277,8 +278,7 @@ void test_eigen_matrix_interface() E.set_coef(2, 1, 0.30543); E.set_coef(2, 2, 0.35833); - CGAL::Eigen_dense_matrix Sr = - CGAL::Optimal_bounding_box::reflection(D, E); + CGAL_assertion_code(Matrix Sr = CGAL::Optimal_bounding_box::reflection(D, E)); CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); CGAL_assertion(assert_doubles(Sr(0,2), -0.24664, epsilon)); diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 7af0ba43a6e..5b60bd283c9 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -96,7 +96,7 @@ void test_nelder_mead() evolution.nelder_mead(simplex, nm_iterations); CGAL_assertion_code(double epsilon = 1e-5); - Matrix3d v0_new = simplex[0]; + CGAL_assertion_code(Matrix3d v0_new = simplex[0]); CGAL_assertion(assert_doubles(v0_new(0,0), -0.288975, epsilon)); CGAL_assertion(assert_doubles(v0_new(0,1), 0.7897657, epsilon)); CGAL_assertion(assert_doubles(v0_new(0,2), -0.541076, epsilon)); @@ -107,7 +107,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v0_new(2,1), 0.5111260, epsilon)); CGAL_assertion(assert_doubles(v0_new(2,2), 0.84094, epsilon)); - Matrix3d v1_new = simplex[1]; + CGAL_assertion_code(Matrix3d v1_new = simplex[1]); CGAL_assertion(assert_doubles(v1_new(0,0), -0.458749, epsilon)); CGAL_assertion(assert_doubles(v1_new(0,1), 0.823283, epsilon)); CGAL_assertion(assert_doubles(v1_new(0,2), -0.334296, epsilon)); @@ -118,7 +118,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v1_new(2,1), 0.338040, epsilon)); CGAL_assertion(assert_doubles(v1_new(2,2), 0.937987, epsilon)); - Matrix3d v2_new = simplex[2]; + CGAL_assertion_code(Matrix3d v2_new = simplex[2]); CGAL_assertion(assert_doubles(v2_new(0,0), -0.346582, epsilon)); CGAL_assertion(assert_doubles(v2_new(0,1), 0.878534, epsilon)); CGAL_assertion(assert_doubles(v2_new(0,2), -0.328724, epsilon)); @@ -129,7 +129,7 @@ void test_nelder_mead() CGAL_assertion(assert_doubles(v2_new(2,1), 0.334057, epsilon)); CGAL_assertion(assert_doubles(v2_new(2,2), 0.941423, epsilon)); - Matrix3d v3_new = simplex[3]; + CGAL_assertion_code(Matrix3d v3_new = simplex[3]); CGAL_assertion(assert_doubles(v3_new(0,0), -0.394713, epsilon)); CGAL_assertion(assert_doubles(v3_new(0,1), 0.791782, epsilon)); CGAL_assertion(assert_doubles(v3_new(0,2), -0.466136, epsilon)); @@ -157,13 +157,10 @@ void test_genetic_algorithm() data_points(3,1) = 0.149912, data_points(3,2) = 0.364944; - typedef CGAL::Eigen_dense_matrix Matrix3d; typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - CGAL::Optimal_bounding_box::Population pop(5); CGAL::Optimal_bounding_box::Evolution evolution(pop, data_points); evolution.genetic_algorithm(); - CGAL_assertion(pop.size() == 5); } @@ -205,15 +202,13 @@ void test_random_unit_tetra() #endif typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - typedef Linear_algebra_traits::Matrix3d Matrix3d; - + CGAL_assertion_code(typedef Linear_algebra_traits::Matrix3d Matrix3d); std::size_t generations = 10; CGAL::Optimal_bounding_box::Population pop(50); CGAL::Optimal_bounding_box::Evolution evolution(pop, data_points); evolution.evolve(generations); - Matrix3d R = evolution.get_best(); - + CGAL_assertion_code(Matrix3d R = evolution.get_best()); CGAL_assertion_code(double epsilon = 1e-3); CGAL_assertion(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); CGAL_assertion(assert_doubles(R(0,0), -0.25791, epsilon)); @@ -245,7 +240,7 @@ void test_reference_tetrahedron(const char* fname) typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; typedef Linear_algebra_traits::MatrixXd MatrixXd; - typedef Linear_algebra_traits::Matrix3d Matrix3d; + CGAL_assertion_code(typedef Linear_algebra_traits::Matrix3d Matrix3d); // points in a matrix MatrixXd points; @@ -256,8 +251,7 @@ void test_reference_tetrahedron(const char* fname) CGAL::Optimal_bounding_box::Evolution experiment(pop, points); experiment.evolve(generations); - Matrix3d R = experiment.get_best(); - + CGAL_assertion_code(Matrix3d R = experiment.get_best()); CGAL_assertion_code(double epsilon = 1e-5); CGAL_assertion(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); @@ -280,7 +274,7 @@ void test_long_tetrahedron(std::string fname) typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; typedef Linear_algebra_traits::MatrixXd MatrixXd; - typedef Linear_algebra_traits::Matrix3d Matrix3d; + CGAL_assertion_code(typedef Linear_algebra_traits::Matrix3d Matrix3d); // points in a matrix MatrixXd points; @@ -291,8 +285,7 @@ void test_long_tetrahedron(std::string fname) CGAL::Optimal_bounding_box::Evolution experiment(pop, points); experiment.evolve(max_generations); - Matrix3d R = experiment.get_best(); - + CGAL_assertion_code(Matrix3d R = experiment.get_best()); CGAL_assertion_code(double epsilon = 1e-3); CGAL_assertion(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); CGAL_assertion(assert_doubles(R(0,0), -1, epsilon)); From 9d5a83ebf68c46a3b792a10753e2d43b047025a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 11 Jun 2018 16:32:59 +0200 Subject: [PATCH 048/150] Renamed header --- .../benchmarks/Optimal_bounding_box/bench_custom.cpp | 2 +- .../benchmarks/Optimal_bounding_box/bench_obb.cpp | 2 +- .../benchmarks/Optimal_bounding_box/bench_perfomance.cpp | 2 +- .../CGAL/Optimal_bounding_box/{obb.h => optimal_bounding_box.h} | 0 .../test/Optimal_bounding_box/test_optimization_algorithms.cpp | 2 +- .../demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename Optimal_bounding_box/include/CGAL/Optimal_bounding_box/{obb.h => optimal_bounding_box.h} (100%) diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp index 33f42eb27c3..f1bfa006914 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp index 1bf8bddad18..ae20bc16bdb 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp index 855c21e558c..fa1447df22c 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h similarity index 100% rename from Optimal_bounding_box/include/CGAL/Optimal_bounding_box/obb.h rename to Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 5b60bd283c9..f67dd655891 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp index 9dbf9da1da7..58ebc93542d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp @@ -14,7 +14,7 @@ #include "Scene_points_with_normal_item.h" #include -#include +#include #include //typedef Scene_surface_mesh_item Scene_facegraph_item; From f8a3b552d3d8562b192a6c178894b982734e94b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 11 Jun 2018 16:54:37 +0200 Subject: [PATCH 049/150] Cosmetic changes --- .../Optimal_bounding_box/bench_custom.cpp | 34 ++++----- .../bench_fitness_function.cpp | 20 ++--- .../Optimal_bounding_box/bench_obb.cpp | 24 +++--- .../Optimal_bounding_box/bench_perfomance.cpp | 19 +++-- .../Optimal_bounding_box/readme.txt | 3 +- .../CGAL/Optimal_bounding_box/evolution.h | 74 +++++++++---------- .../Optimal_bounding_box/fitness_function.h | 23 +++--- .../CGAL/Optimal_bounding_box/helper.h | 27 ++++--- .../nelder_mead_functions.h | 7 +- .../optimal_bounding_box.h | 52 ++++++------- .../CGAL/Optimal_bounding_box/population.h | 29 +++----- .../test_linear_algebra_functions.cpp | 5 +- .../test_optimization_algorithms.cpp | 41 +++++----- 13 files changed, 178 insertions(+), 180 deletions(-) diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp index f1bfa006914..56cc644fd72 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp @@ -1,31 +1,32 @@ #include -#include -#include -#include -#include -#include +#include + +#include +#include #include #include -//#define OBB_DEBUG_BENCHMARK +#include +#include +#include + +//#define CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_BENCHMARK typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -void -bench(const char* fname) +void bench(const char* fname) { std::vector sm_points, obb_points; std::ifstream in(fname); K::Point_3 p; int i = 0; - while(in >> p){ - + while(in >> p) + { if(i % 2 == 0) // avoid normals - { sm_points.push_back(p); - } + ++i; } @@ -40,22 +41,19 @@ bench(const char* fname) std::cout << "done" << '\n'; -#ifdef OBB_DEBUG_BENCHMARK +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_BENCHMARK std::cout.precision(17); for(int i =0; i < obb_points.size(); i++) - { std::cout << obb_points[i] << std::endl; - } CGAL::Surface_mesh mesh; - CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], obb_points[4], obb_points[5], - obb_points[6], obb_points[7], mesh); + CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], + obb_points[4], obb_points[5], obb_points[6], obb_points[7], mesh); std::ofstream out("/tmp/result_obb.off"); out << mesh; out.close(); #endif - } int main(int argc, char* argv[]) diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_fitness_function.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_fitness_function.cpp index 2b70a2610c9..15414eaee48 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_fitness_function.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_fitness_function.cpp @@ -1,28 +1,32 @@ #include + +#include + +#include #include #include #include -#include + #include -#include #include + #include +#include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; - int main() { - const char* fname = "data/elephant.off"; // 1) import a lot a mesh and subdivide it to create a big mesh std::ifstream input(fname); CGAL::Surface_mesh mesh; - if (!input || !(input >> mesh) || mesh.is_empty()) { + if (!input || !(input >> mesh) || mesh.is_empty()) + { std::cerr << fname << " is not a valid off file.\n"; - exit(1); + std::exit(1); } CGAL::Subdivision_method_3::CatmullClark_subdivision(mesh, @@ -40,11 +44,9 @@ int main() MatrixX3d points_mat(nb_points, 3); CGAL::Optimal_bounding_box::sm_to_matrix(mesh, points_mat); - // 3) create a population of simplices CGAL::Optimal_bounding_box::Population pop(50); - CGAL::Timer timer; timer.start(); @@ -58,7 +60,5 @@ int main() std::cout << "took " << timer.time() << " to compute the fitness of all vertices.\n"; std::cout << "value of fittest vertex= " << result << std::endl; - - return 0; } diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp index ae20bc16bdb..1d12dc9c4df 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp @@ -1,21 +1,22 @@ #include + #include -#include #include + +#include #include #include -#include + +#include +#include + #include #include -#include - -//#define OBB_DEBUG_BENCHMARK - +//#define CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_BENCHMARK typedef CGAL::Exact_predicates_inexact_constructions_kernel K; - bool assert_doubles(double d1, double d2, double epsilon) { return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; @@ -49,10 +50,12 @@ void bench_finding_obb(std::string fname) // import a mesh CGAL::Surface_mesh mesh; - if (!input || !(input >> mesh) || mesh.is_empty()) { + if (!input || !(input >> mesh) || mesh.is_empty()) + { std::cerr << fname << " is not a valid off file.\n"; - exit(1); + std::exit(1); } + // get mesh points gather_mesh_points(mesh, sm_points); @@ -83,13 +86,12 @@ void bench_finding_obb(std::string fname) std::cout << "found obb without convex hull: " << timer.time() << " seconds\n"; timer.reset(); -#ifdef OBB_DEBUG_BENCHMARK +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_BENCHMARK CGAL::Surface_mesh result_mesh1; CGAL::make_hexahedron(obb_points1[0], obb_points1[1], obb_points1[2], obb_points1[3], obb_points1[4], obb_points1[5], obb_points1[6], obb_points1[7], result_mesh1); - CGAL::Surface_mesh result_mesh2; CGAL::make_hexahedron(obb_points2[0], obb_points2[1], obb_points2[2], obb_points2[3], obb_points2[4], obb_points2[5], obb_points2[6], obb_points2[7], diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp index fa1447df22c..3108af27af6 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp @@ -1,14 +1,17 @@ #include + #include -#include + #include -#include -#include +#include #include #include -//#define OBB_DEBUG_BENCHMARK +#include +#include + +//#define CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_BENCHMARK typedef CGAL::Exact_predicates_inexact_constructions_kernel K; @@ -18,9 +21,10 @@ void bench_finding_obb(std::string fname) // import a mesh CGAL::Surface_mesh mesh; - if (!input || !(input >> mesh) || mesh.is_empty()) { + if (!input || !(input >> mesh) || mesh.is_empty()) + { std::cerr << fname << " is not a valid off file.\n"; - exit(1); + std::exit(1); } // export some times @@ -62,8 +66,7 @@ void bench_finding_obb(std::string fname) outt.close(); - -#ifdef OBB_DEBUG_BENCHMARK +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_BENCHMARK std::ofstream out1("data/obb_result1.off"); out1 << obb_points1; out1.close(); diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/readme.txt b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/readme.txt index b8995463fa7..ac22f73a877 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/readme.txt +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/readme.txt @@ -1,2 +1 @@ -To draw a graph with the benchmark times set the path-to-the-measurments in draw_benchmark_times.py if necessary, -and run the script with python 3. +To draw a graph with the benchmark times set the path-to-the-measurments in draw_benchmark_times.py if necessary, and run the script with python 3. diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index 5e0ecced2de..ee334df7e55 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -16,7 +16,6 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0+ // -// // Author(s) : Konstantinos Katrioplas #ifndef CGAL_OPTIMAL_BOUNDING_BOX_EVOLUTION_H @@ -24,13 +23,20 @@ #include #include - #include + +#include +#include + #include -namespace CGAL { -namespace Optimal_bounding_box { +#include +#include +#include +namespace CGAL { + +namespace Optimal_bounding_box { template class Evolution @@ -40,19 +46,19 @@ class Evolution typedef typename Linear_algebra_traits::Vector3d Vector3d; public: - Evolution(Population& pop, MatrixXd& points) : - population(pop), - point_data(points) + Evolution(Population& pop, MatrixXd& points) + : population(pop), point_data(points) {} // simplex: 4 rotation matrices are its vertices - void nelder_mead(std::vector& simplex, std::size_t nelder_mead_iterations) + void nelder_mead(std::vector& simplex, + std::size_t nelder_mead_iterations) { CGAL_assertion(simplex.size() == 4); // tetrahedron std::vector fitness(4); - std::vector indices( boost::counting_iterator( 0 ), - boost::counting_iterator( simplex.size() ) ); + std::vector indices(boost::counting_iterator(0), + boost::counting_iterator(simplex.size())); for(std::size_t t = 0; t < nelder_mead_iterations; ++t) { @@ -165,12 +171,12 @@ public: for(std::size_t i = 0; i < ids4.size(); ++i) group4[i] = population[ids4[i]]; - #ifdef OBB_DEBUG +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG check_det(group1); check_det(group2); check_det(group3); check_det(group4); - #endif +#endif // crossover I Population offspringsA(size_first_group); @@ -185,10 +191,12 @@ public: double fitnessA = compute_fitness(group1[i][j], point_data); double fitnessB = compute_fitness(group2[i][j], point_data); double threshold; + if(fitnessA < fitnessB) threshold = 0.5 + bias; else threshold = 0.5 - bias; + if(r < threshold) // choose A offspring[j] = group1[i][j]; else // choose B @@ -197,11 +205,11 @@ public: offspringsA[i] = offspring; } - #ifdef OBB_DEBUG +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG std::cout << "offspringsA: \n" ; check_det(offspringsA); std::cin.get(); - #endif +#endif // crossover II Population offspringsB(size_second_group); @@ -228,10 +236,10 @@ public: offspringsB[i] = offspring; } - #ifdef OBB_DEBUG +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG std::cout << "offspringsB: \n" ; check_det(offspringsB); - #endif +#endif CGAL_assertion(offspringsA.size() == size_first_group); CGAL_assertion(offspringsB.size() == size_second_group); @@ -239,14 +247,10 @@ public: // next generatrion for(std::size_t i = 0; i < size_first_group; ++i) - { population[i] = offspringsA[i]; - } for(std::size_t i = 0; i < size_second_group; ++i) - { population[size_first_group + i] = offspringsB[i]; - } } void evolve(std::size_t generations) @@ -262,35 +266,35 @@ public: for(std::size_t t = 0; t < generations; ++t) { - - #ifdef OBB_DEBUG +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG std::cout << "generation= " << t << "\n"; - #endif +#endif genetic_algorithm(); - #ifdef OBB_DEBUG +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG //std::cout << "pop after genetic" << std::endl; //pop.show_population(); //std::cout << std::endl; - #endif +#endif for(std::size_t s = 0; s < population.size(); ++s) nelder_mead(population[s], nelder_mead_iterations); - #ifdef OBB_DEBUG +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG //std::cout << "pop after nelder mead: " << std::endl; //pop.show_population(); //std::cout << std::endl; Fitness_map fitness_map_debug(population, point_data); Matrix3d R_now = fitness_map_debug.get_best(); std::cout << "det= " << Linear_algebra_traits::determinant(R_now) << std::endl; - #endif +#endif // stopping criteria Fitness_map fitness_map(population, point_data); new_fit_value = fitness_map.get_best_fitness_value(); double difference = new_fit_value - prev_fit_value; + if(CGAL::abs(difference) < tolerance * new_fit_value) stale++; @@ -313,10 +317,10 @@ private: { Comparator(const std::vector& in) : fitness(in) {} - inline bool operator() (std::size_t& i, std::size_t& j) - { + inline bool operator() (std::size_t& i, std::size_t& j) { return fitness[i] < fitness[j]; } + const std::vector& fitness; }; @@ -325,8 +329,7 @@ private: MatrixXd point_data; }; - -#ifdef OBB_DEBUG +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG template void check_det(Population& pop) { @@ -341,10 +344,7 @@ void check_det(Population& pop) } #endif +} // end namespace Optimal_bounding_box +} // end namespace CGAL - -}} // end namespaces - - - -#endif +#endif // CGAL_OPTIMAL_BOUNDING_BOX_EVOLUTION_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h index 5810bb1a99c..649dacb40d5 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h @@ -16,18 +16,19 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0+ // -// // Author(s) : Konstantinos Katrioplas #ifndef CGAL_OPTIMAL_BOUNDING_FITNESS_FUNCTION_H #define CGAL_OPTIMAL_BOUNDING_FITNESS_FUNCTION_H -#include -#include #include + +#include + #include namespace CGAL { + namespace Optimal_bounding_box { template @@ -74,7 +75,8 @@ double compute_fitness(const Vertex& R, const Matrix& data) template struct Fitness_map { - Fitness_map(Population& p, Matrix& points) : pop(p), points(points) + Fitness_map(Population& p, Matrix& points) + : pop(p), points(points) {} const Vertex get_best() @@ -109,14 +111,7 @@ struct Fitness_map const Matrix& points; }; -}} // end namespaces - - - - - - -#endif //CGAL_FITNESS_FUNCTION_H - - +} // end namespace Optimal_bounding_box +} // end namespace CGAL +#endif // CGAL_OPTIMAL_BOUNDING_FITNESS_FUNCTION_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h index febf283f5a3..d207feb93ea 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h @@ -19,18 +19,24 @@ // // Author(s) : Konstantinos Katrioplas -#ifndef CGAL_OPTIMAL_BOUNDING_HELPER_H -#define CGAL_OPTIMAL_BOUNDING_HELPER_H +#ifndef CGAL_OPTIMAL_BOUNDING_BOX_HELPER_H +#define CGAL_OPTIMAL_BOUNDING_BOX_HELPER_H -#include -#include #include + +#include +#include +#include +#include #include +#include +#include +#include namespace CGAL { -namespace Optimal_bounding_box { +namespace Optimal_bounding_box { template void fill_matrix(const std::vector& v_points, Matrix& points_mat) @@ -93,16 +99,15 @@ void matrix_to_mesh_and_draw(Matrix& data_points, std::string filename) } Mesh mesh; - CGAL::make_hexahedron(points[0], points[1], points[2], points[3], points[4], points[5], - points[6], points[7], mesh); + CGAL::make_hexahedron(points[0], points[1], points[2], points[3], + points[4], points[5], points[6], points[7], mesh); std::ofstream out(filename); out << mesh; out.close(); } -}} // end namespaces +} // end namespace Optimal_bounding_box +} // end namespace CGAL - - -#endif +#endif // CGAL_OPTIMAL_BOUNDING_BOX_HELPER_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h index 06a050ffa87..d8b9763af00 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h @@ -16,7 +16,6 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0+ // -// // Author(s) : Konstantinos Katrioplas #ifndef CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H @@ -25,8 +24,8 @@ #include namespace CGAL { -namespace Optimal_bounding_box { +namespace Optimal_bounding_box { template const Matrix reflection(const Matrix& S_centroid, const Matrix& S_worst) @@ -76,7 +75,7 @@ const Matrix nm_centroid(const Matrix& S1, const Matrix& S2, const Matrix& S3) return Q / det; } -}} // end namespaces - +} // end namespace Optimal_bounding_box +} // end namespace CGAL #endif diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h index 80e294ef5c5..aaffae6d88a 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h @@ -25,24 +25,30 @@ #include #include #include -#include -#include + +#include #include -#include +#include #include -#include #include -#ifdef OBB_BENCHMARKS -#include +#include +#include + +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS + #include #endif #if defined(CGAL_EIGEN3_ENABLED) #include #endif -namespace CGAL { -namespace Optimal_bounding_box { +#include +#include +#include +namespace CGAL { + +namespace Optimal_bounding_box { // works on matrices only /// \cond SKIP_IN_MANUAL @@ -127,21 +133,20 @@ void find_obb(const std::vector& points, CGAL::Optimal_bounding_box::fill_matrix(points, points_mat); } -#ifdef OBB_BENCHMARKS +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS CGAL::Timer timer; #endif std::size_t max_generations = 100; Population pop(50); -#ifdef OBB_BENCHMARKS +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS timer.start(); #endif - CGAL::Optimal_bounding_box::Evolution - search_solution(pop, points_mat); + CGAL::Optimal_bounding_box::Evolution search_solution(pop, points_mat); -#ifdef OBB_BENCHMARKS +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS timer.stop(); std::cout << "constructor: " << timer.time() << std::endl; timer.reset(); @@ -150,7 +155,7 @@ void find_obb(const std::vector& points, search_solution.evolve(max_generations); -#ifdef OBB_BENCHMARKS +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS timer.stop(); std::cout << "evolve: " << timer.time() << std::endl; timer.reset(); @@ -159,7 +164,7 @@ void find_obb(const std::vector& points, Matrix3d rotation = search_solution.get_best(); -#ifdef OBB_BENCHMARKS +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS timer.stop(); std::cout << "get best: " << timer.time() << std::endl; #endif @@ -167,14 +172,14 @@ void find_obb(const std::vector& points, MatrixXd obb; // may be preallocated at compile time obb.resize(8, 3); -#ifdef OBB_BENCHMARKS +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS timer.reset(); timer.start(); #endif post_processing(points_mat, rotation, obb); -#ifdef OBB_BENCHMARKS +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS timer.stop(); std::cout << "post porcessing: " << timer.time() << std::endl; #endif @@ -242,8 +247,7 @@ void find_obb(const PolygonMesh& pmesh, find_obb(points, obb_points, la_traits, use_ch); CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], - obb_points[4], obb_points[5], - obb_points[6], obb_points[7], obbmesh); + obb_points[4], obb_points[5], obb_points[6], obb_points[7], obbmesh); } template @@ -261,11 +265,7 @@ void find_obb(const PolygonMesh& pmesh, find_obb(pmesh, obbmesh, la_traits, use_ch); } -}} // end namespaces - - - -#endif //CGAL_OPTIMAL_BOUNDING_BOX_OBB_H - - +} // end namespace Optimal_bounding_box +} // end namespace CGAL +#endif // CGAL_OPTIMAL_BOUNDING_BOX_OBB_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index eb8ca1aaf4e..4404acdcd3a 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -22,13 +22,14 @@ #ifndef CGAL_OPTIMAL_BOUNDING_BOX_POPULATION_H #define CGAL_OPTIMAL_BOUNDING_BOX_POPULATION_H -#include +#include #include +#include namespace CGAL { -namespace Optimal_bounding_box { +namespace Optimal_bounding_box { template class Population @@ -37,7 +38,8 @@ class Population typedef std::vector Simplex; public: - Population(std::size_t size) : n(size), random_generator(CGAL::Random()) + Population(std::size_t size) + : n(size), random_generator(CGAL::Random()) { // reserve pop space pop.reserve(n); @@ -52,9 +54,9 @@ public: } } - #ifdef OBB_DEBUG +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG void show_population(); - #endif +#endif std::size_t size(){return n;} @@ -72,7 +74,6 @@ public: } private: - // create random population void create_simplex(Simplex& simplex) { @@ -110,8 +111,7 @@ private: std::vector pop; }; - -#ifdef OBB_DEBUG +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG template void Population::show_population() { @@ -130,14 +130,7 @@ void Population::show_population() } #endif +} // end namespace Optimal_bounding_box +} // end namespace CGAL - -} } // end namespaces - - - - - - - -#endif //CGAL_OPTIMAL_BOUNDING_BOX_POPULATION_H +#endif // CGAL_OPTIMAL_BOUNDING_BOX_POPULATION_H diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index 0278b1cce15..5ae7753271f 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -1,9 +1,8 @@ +#include #include #include + #include -#include -#include -#include bool assert_doubles(double d1, double d2, double epsilon) { diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index f67dd655891..257dcd02ac5 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -1,14 +1,15 @@ #include + #include + +#include #include #include #include + #include #include -#include - - typedef CGAL::Exact_predicates_inexact_constructions_kernel K; bool assert_doubles(double d1, double d2, double epsilon) @@ -195,7 +196,7 @@ void test_random_unit_tetra() Point p4(0.166461, 0.149912, 0.364944); CGAL::make_tetrahedron(p1, p2, p3, p4, mesh); -#ifdef OBB_DEBUG_TEST +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST std::ofstream out("data/random_unit_tetra.off"); out << mesh; out.close(); @@ -221,7 +222,7 @@ void test_random_unit_tetra() CGAL_assertion(assert_doubles(R(2,1), 0.512847, epsilon)); CGAL_assertion(assert_doubles(R(2,2), 0.836992, epsilon)); -#ifdef OBB_DEBUG_TEST +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST // postprocessing CGAL::Eigen_dense_matrix obb(8, 3); CGAL::Optimal_bounding_box::post_processing(data_points, R, obb); @@ -235,7 +236,7 @@ void test_reference_tetrahedron(const char* fname) CGAL::Surface_mesh mesh; if (!input || !(input >> mesh) || mesh.is_empty()) { std::cerr << fname << " is not a valid off file.\n"; - exit(1); + std::exit(1); } typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; @@ -255,7 +256,7 @@ void test_reference_tetrahedron(const char* fname) CGAL_assertion_code(double epsilon = 1e-5); CGAL_assertion(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); - #ifdef OBB_DEBUG_TEST + #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST // postprocessing MatrixXd obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points, R, obb); @@ -269,7 +270,7 @@ void test_long_tetrahedron(std::string fname) CGAL::Surface_mesh mesh; if (!input || !(input >> mesh) || mesh.is_empty()) { std::cerr << fname << " is not a valid off file.\n"; - exit(1); + std::exit(1); } typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; @@ -300,7 +301,7 @@ void test_long_tetrahedron(std::string fname) assert_doubles(R(1,2), -0.707106, epsilon)); CGAL_assertion(assert_doubles(R(2,2), 0.707107, epsilon)); - #ifdef OBB_DEBUG_TEST + #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST // postprocessing MatrixXd obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points, R, obb); @@ -315,7 +316,7 @@ void test_find_obb_evolution(std::string fname) SMesh mesh; if (!input || !(input >> mesh) || mesh.is_empty()) { std::cerr << fname << " is not a valid off file.\n"; - exit(1); + std::exit(1); } // get mesh points std::vector sm_points; @@ -334,7 +335,7 @@ void test_find_obb_evolution(std::string fname) CGAL_assertion_code(double vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points)); CGAL_assertion(assert_doubles(vol, 0.883371, epsilon)); - #ifdef OBB_DEBUG_TEST + #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST /* for(int i = 0; i < 8; ++i) std::cout << obb_points[i].x() << " " << obb_points[i].y() << " " << obb_points[i].z() << "\n" ; @@ -353,16 +354,17 @@ void test_find_obb_mesh(std::string fname) { std::ifstream input(fname); CGAL::Surface_mesh mesh; - if (!input || !(input >> mesh) || mesh.is_empty()) { + if (!input || !(input >> mesh) || mesh.is_empty()) + { std::cerr << fname << " is not a valid off file.\n"; - exit(1); + std::exit(1); } CGAL::Eigen_linear_algebra_traits la_traits; CGAL::Surface_mesh< K::Point_3> obbmesh; CGAL::Optimal_bounding_box::find_obb(mesh, obbmesh, la_traits, true); - #ifdef OBB_DEBUG_TEST + #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST std::ofstream out("/tmp/result_elephant.off"); out << obbmesh; out.close(); @@ -373,16 +375,18 @@ void test_function_defaults_traits(std::string fname1, std::string fname2) { std::ifstream input1(fname1); CGAL::Surface_mesh mesh1; - if (!input1 || !(input1 >> mesh1) || mesh1.is_empty()) { + if (!input1 || !(input1 >> mesh1) || mesh1.is_empty()) + { std::cerr << fname1 << " is not a valid off file.\n"; - exit(1); + std::exit(1); } std::ifstream input2(fname2); CGAL::Surface_mesh mesh2; - if (!input2 || !(input2 >> mesh2) || mesh2.is_empty()) { + if (!input2 || !(input2 >> mesh2) || mesh2.is_empty()) + { std::cerr << fname2 << " is not a valid off file.\n"; - exit(1); + std::exit(1); } // test one @@ -391,6 +395,7 @@ void test_function_defaults_traits(std::string fname1, std::string fname2) typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::property_map::const_type PointPMap; PointPMap pmap = get(boost::vertex_point, mesh1); + BOOST_FOREACH(vertex_descriptor v, vertices(mesh1)) sm_points.push_back(get(pmap, v)); From 280568e1dd61b1816c5fa923511e06c9f1f08884 Mon Sep 17 00:00:00 2001 From: Konstantinos Katrioplas Date: Tue, 12 Jun 2018 12:14:22 +0200 Subject: [PATCH 050/150] move nelder-mead function out of evolution class into the nelder_mead_functions.h --- .../CGAL/Optimal_bounding_box/evolution.h | 99 +---------------- .../nelder_mead_functions.h | 103 ++++++++++++++++++ .../test_optimization_algorithms.cpp | 9 +- 3 files changed, 107 insertions(+), 104 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index ee334df7e55..b76d5e4aaaa 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -28,8 +28,6 @@ #include #include -#include - #include #include #include @@ -50,89 +48,6 @@ public: : population(pop), point_data(points) {} - // simplex: 4 rotation matrices are its vertices - void nelder_mead(std::vector& simplex, - std::size_t nelder_mead_iterations) - { - CGAL_assertion(simplex.size() == 4); // tetrahedron - - std::vector fitness(4); - std::vector indices(boost::counting_iterator(0), - boost::counting_iterator(simplex.size())); - - for(std::size_t t = 0; t < nelder_mead_iterations; ++t) - { - for(std::size_t i = 0; i < 4; ++i) - { - fitness[i] = compute_fitness(simplex[i], point_data); - } - - CGAL_assertion(fitness.size() == 4); - CGAL_assertion(indices.size() == 4); - - // get indices of sorted sequence - Comparator compare_indices(fitness); - std::sort(indices.begin(), indices.end(), compare_indices); - - // new sorted simplex & fitness - std::vector s_simplex(4); - std::vector s_fitness(4); - for(int i = 0; i < 4; ++i) - { - s_simplex[i] = simplex[indices[i]]; - s_fitness[i] = fitness[indices[i]]; - } - - simplex = s_simplex; - fitness = s_fitness; - - // centroid - const Matrix3d v_centroid = nm_centroid(simplex[0], simplex[1], simplex[2]); - - // find worst's vertex reflection - const Matrix3d v_worst = simplex[3]; - const Matrix3d v_refl = reflection(v_centroid, v_worst); - const double f_refl = compute_fitness(v_refl, point_data); - - if(f_refl < fitness[2]) - { - if(f_refl >= fitness[0]) // if reflected point is not better than the best - { - // do reflection - simplex[3] = v_refl; - } - else - { - // expansion - const Matrix3d v_expand = expansion(v_centroid, v_worst, v_refl); - const double f_expand = compute_fitness(v_expand, point_data); - if(f_expand < f_refl) - simplex[3] = v_expand; - else - simplex[3] = v_refl; - } - } - else // if reflected vertex is not better - { - const Matrix3d v_mean = mean(v_centroid, v_worst); - const double f_mean = compute_fitness(v_mean, point_data); - if(f_mean <= fitness[3]) - // contraction of worst - simplex[3] = v_mean; - else - { - // reduction: move all vertices towards the best - for(std::size_t i=1; i < 4; ++i) - { - simplex[i] = mean(simplex[i], simplex[0]); - } - } - } - - CGAL_assertion(simplex.size() == 4); // tetrahedron - } // iterations - } - void genetic_algorithm() { // random permutations @@ -279,7 +194,7 @@ public: #endif for(std::size_t s = 0; s < population.size(); ++s) - nelder_mead(population[s], nelder_mead_iterations); + nelder_mead(population[s], point_data, nelder_mead_iterations); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG //std::cout << "pop after nelder mead: " << std::endl; @@ -312,18 +227,6 @@ public: } private: - // needed in genetic algorithm - struct Comparator - { - Comparator(const std::vector& in) : fitness(in) {} - - inline bool operator() (std::size_t& i, std::size_t& j) { - return fitness[i] < fitness[j]; - } - - const std::vector& fitness; - }; - // data Population population; MatrixXd point_data; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h index d8b9763af00..3d7de8c8db3 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h @@ -22,6 +22,9 @@ #define CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H #include +#include +#include +#include namespace CGAL { @@ -75,6 +78,106 @@ const Matrix nm_centroid(const Matrix& S1, const Matrix& S2, const Matrix& S3) return Q / det; } +// needed in nelder mead algorithm +struct Comparator +{ + Comparator(const std::vector& in) : fitness(in) {} + + inline bool operator() (std::size_t& i, std::size_t& j) { + return fitness[i] < fitness[j]; + } + + const std::vector& fitness; +}; + +// simplex: 4 rotation matrices are its vertices +template +void nelder_mead(std::vector& simplex, + const typename Linear_algebra_traits::MatrixXd& point_data, + std::size_t nelder_mead_iterations) +{ + CGAL_assertion(simplex.size() == 4); // tetrahedron + + + typedef typename Linear_algebra_traits::Matrix3d Matrix3d; + + std::vector fitness(4); + std::vector indices(boost::counting_iterator(0), + boost::counting_iterator(simplex.size())); + + for(std::size_t t = 0; t < nelder_mead_iterations; ++t) + { + for(std::size_t i = 0; i < 4; ++i) + { + fitness[i] = compute_fitness(simplex[i], point_data); + } + + CGAL_assertion(fitness.size() == 4); + CGAL_assertion(indices.size() == 4); + + // get indices of sorted sequence + Comparator compare_indices(fitness); + std::sort(indices.begin(), indices.end(), compare_indices); + + // new sorted simplex & fitness + std::vector s_simplex(4); + std::vector s_fitness(4); + for(int i = 0; i < 4; ++i) + { + s_simplex[i] = simplex[indices[i]]; + s_fitness[i] = fitness[indices[i]]; + } + + simplex = s_simplex; + fitness = s_fitness; + + // centroid + const Matrix3d v_centroid = nm_centroid(simplex[0], simplex[1], simplex[2]); + + // find worst's vertex reflection + const Matrix3d v_worst = simplex[3]; + const Matrix3d v_refl = reflection(v_centroid, v_worst); + const double f_refl = compute_fitness(v_refl, point_data); + + if(f_refl < fitness[2]) + { + if(f_refl >= fitness[0]) // if reflected point is not better than the best + { + // do reflection + simplex[3] = v_refl; + } + else + { + // expansion + const Matrix3d v_expand = expansion(v_centroid, v_worst, v_refl); + const double f_expand = compute_fitness(v_expand, point_data); + if(f_expand < f_refl) + simplex[3] = v_expand; + else + simplex[3] = v_refl; + } + } + else // if reflected vertex is not better + { + const Matrix3d v_mean = mean(v_centroid, v_worst); + const double f_mean = compute_fitness(v_mean, point_data); + if(f_mean <= fitness[3]) + // contraction of worst + simplex[3] = v_mean; + else + { + // reduction: move all vertices towards the best + for(std::size_t i=1; i < 4; ++i) + { + simplex[i] = mean(simplex[i], simplex[0]); + } + } + } + + CGAL_assertion(simplex.size() == 4); // tetrahedron + } // iterations +} + } // end namespace Optimal_bounding_box } // end namespace CGAL diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 257dcd02ac5..86c49eda928 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -89,12 +90,8 @@ void test_nelder_mead() simplex[2] = v2; simplex[3] = v3; - CGAL::Optimal_bounding_box::Population pop(1); std::size_t nm_iterations = 19; - - CGAL::Optimal_bounding_box::Evolution - evolution(pop, data_points); - evolution.nelder_mead(simplex, nm_iterations); + CGAL::Optimal_bounding_box::nelder_mead(simplex, data_points, nm_iterations); CGAL_assertion_code(double epsilon = 1e-5); CGAL_assertion_code(Matrix3d v0_new = simplex[0]); @@ -144,7 +141,7 @@ void test_nelder_mead() void test_genetic_algorithm() { - CGAL::Eigen_dense_matrix data_points(4, 3); // -1 : dynamic size at run time + CGAL::Eigen_dense_matrix data_points(4, 3); // -1 = dynamic size at run time data_points(0,0) = 0.866802; data_points(0,1) = 0.740808, data_points(0,2) = 0.895304, From 53eff19e67c28c737acea897ecc599c08160d447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 12 Jun 2018 11:15:20 +0200 Subject: [PATCH 051/150] Renamed functions --- .../Optimal_bounding_box/bench_custom.cpp | 2 +- .../Optimal_bounding_box/bench_obb.cpp | 4 +-- .../Optimal_bounding_box/bench_perfomance.cpp | 4 +-- .../optimal_bounding_box.h | 34 +++++++++---------- .../test_optimization_algorithms.cpp | 16 ++++----- .../Plugins/PCA/Create_obb_mesh_plugin.cpp | 2 +- 6 files changed, 31 insertions(+), 31 deletions(-) diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp index 56cc644fd72..220aabab3b5 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp @@ -37,7 +37,7 @@ void bench(const char* fname) // use convex hull - > true // no convex hull - > false - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, la_traits, false); + CGAL::Optimal_bounding_box::compute_optimal_bounding_box(sm_points, obb_points, la_traits, false); std::cout << "done" << '\n'; diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp index 1d12dc9c4df..44e85c184bf 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp @@ -73,7 +73,7 @@ void bench_finding_obb(std::string fname) timer.reset(); timer.start(); std::vector obb_points1; - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points1, la_traits, true); + CGAL::Optimal_bounding_box::compute_optimal_bounding_box(sm_points, obb_points1, la_traits, true); timer.stop(); std::cout << "found obb using convex hull: " << timer.time() << " seconds\n"; @@ -81,7 +81,7 @@ void bench_finding_obb(std::string fname) timer.reset(); timer.start(); std::vector obb_points2; - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points2, la_traits, false); + CGAL::Optimal_bounding_box::compute_optimal_bounding_box(sm_points, obb_points2, la_traits, false); timer.stop(); std::cout << "found obb without convex hull: " << timer.time() << " seconds\n"; timer.reset(); diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp index 3108af27af6..2cab424a549 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp @@ -42,7 +42,7 @@ void bench_finding_obb(std::string fname) // 1) using convex hull timer.start(); CGAL::Surface_mesh obb_mesh1; - CGAL::Optimal_bounding_box::find_obb(mesh, obb_mesh1, la_traits, true); + CGAL::Optimal_bounding_box::compute_optimal_bounding_box(mesh, obb_mesh1, la_traits, true); timer.stop(); double t_ch = timer.time(); std::cout << " with ch: " << timer.time() << " s |"; @@ -51,7 +51,7 @@ void bench_finding_obb(std::string fname) timer.reset(); timer.start(); CGAL::Surface_mesh obb_mesh2; - CGAL::Optimal_bounding_box::find_obb(mesh, obb_mesh2, la_traits, false); + CGAL::Optimal_bounding_box::compute_optimal_bounding_box(mesh, obb_mesh2, la_traits, false); timer.stop(); double t_no_ch = timer.time(); std::cout << " without ch: " << timer.time() << " s\n"; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h index aaffae6d88a..62017fc84d4 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h @@ -106,10 +106,10 @@ void post_processing(const Matrix& points, Vertex& R, Matrix& obb) /// @param use_ch a bool flag to indicating whether to use the convex hull of the input points /// as an optimization step. template -void find_obb(const std::vector& points, - std::vector& obb_points, - LinearAlgebraTraits&, - bool use_ch) +void compute_optimal_bounding_box(const std::vector& points, + std::vector& obb_points, + LinearAlgebraTraits&, + bool use_ch) { CGAL_assertion(points.size() >= 3); @@ -193,9 +193,9 @@ void find_obb(const std::vector& points, } template -void find_obb(const std::vector& points, - std::vector& obb_points, - bool use_ch) +void compute_optimal_bounding_box(const std::vector& points, + std::vector& obb_points, + bool use_ch) { #if defined(CGAL_EIGEN3_ENABLED) typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; @@ -204,7 +204,7 @@ void find_obb(const std::vector& points, #endif Linear_algebra_traits la_traits; - find_obb(points, obb_points, la_traits, use_ch); + compute_optimal_bounding_box(points, obb_points, la_traits, use_ch); } /// \ingroup OBB_grp @@ -220,10 +220,10 @@ void find_obb(const std::vector& points, /// @param use_ch a bool flag to indicating whether to use the convex hull of the input points /// as an optimization step. template -void find_obb(const PolygonMesh& pmesh, - PolygonMesh& obbmesh, - LinearAlgebraTraits& la_traits, - bool use_ch) +void compute_optimal_bounding_box(const PolygonMesh& pmesh, + PolygonMesh& obbmesh, + LinearAlgebraTraits& la_traits, + bool use_ch) { CGAL_assertion(vertices(pmesh).size() >= 3); @@ -244,16 +244,16 @@ void find_obb(const PolygonMesh& pmesh, std::vector obb_points; - find_obb(points, obb_points, la_traits, use_ch); + compute_optimal_bounding_box(points, obb_points, la_traits, use_ch); CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], obb_points[4], obb_points[5], obb_points[6], obb_points[7], obbmesh); } template -void find_obb(const PolygonMesh& pmesh, - PolygonMesh& obbmesh, - bool use_ch) +void compute_optimal_bounding_box(const PolygonMesh& pmesh, + PolygonMesh& obbmesh, + bool use_ch) { #if defined(CGAL_EIGEN3_ENABLED) typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; @@ -262,7 +262,7 @@ void find_obb(const PolygonMesh& pmesh, #endif Linear_algebra_traits la_traits; - find_obb(pmesh, obbmesh, la_traits, use_ch); + compute_optimal_bounding_box(pmesh, obbmesh, la_traits, use_ch); } } // end namespace Optimal_bounding_box diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 86c49eda928..4f03054dcbd 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -306,7 +306,7 @@ void test_long_tetrahedron(std::string fname) #endif } -void test_find_obb_evolution(std::string fname) +void test_compute_obb_evolution(std::string fname) { std::ifstream input(fname); typedef CGAL::Surface_mesh SMesh; @@ -326,7 +326,7 @@ void test_find_obb_evolution(std::string fname) CGAL::Eigen_linear_algebra_traits la_traits; std::vector obb_points; - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, la_traits, true); + CGAL::Optimal_bounding_box::compute_optimal_bounding_box(sm_points, obb_points, la_traits, true); CGAL_assertion_code(double epsilon = 1e-3); CGAL_assertion_code(double vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points)); @@ -347,7 +347,7 @@ void test_find_obb_evolution(std::string fname) #endif } -void test_find_obb_mesh(std::string fname) +void test_compute_obb_mesh(std::string fname) { std::ifstream input(fname); CGAL::Surface_mesh mesh; @@ -359,7 +359,7 @@ void test_find_obb_mesh(std::string fname) CGAL::Eigen_linear_algebra_traits la_traits; CGAL::Surface_mesh< K::Point_3> obbmesh; - CGAL::Optimal_bounding_box::find_obb(mesh, obbmesh, la_traits, true); + CGAL::Optimal_bounding_box::compute_optimal_bounding_box(mesh, obbmesh, la_traits, true); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST std::ofstream out("/tmp/result_elephant.off"); @@ -397,7 +397,7 @@ void test_function_defaults_traits(std::string fname1, std::string fname2) sm_points.push_back(get(pmap, v)); std::vector obb_points; - CGAL::Optimal_bounding_box::find_obb(sm_points, obb_points, true); + CGAL::Optimal_bounding_box::compute_optimal_bounding_box(sm_points, obb_points, true); CGAL_assertion_code(double epsilon = 1e-3); CGAL_assertion_code(double vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points)); @@ -405,7 +405,7 @@ void test_function_defaults_traits(std::string fname1, std::string fname2) // test two CGAL::Surface_mesh< K::Point_3> obbmesh; - CGAL::Optimal_bounding_box::find_obb(mesh2, obbmesh, true); + CGAL::Optimal_bounding_box::compute_optimal_bounding_box(mesh2, obbmesh, true); } int main() @@ -415,8 +415,8 @@ int main() test_random_unit_tetra(); test_reference_tetrahedron("data/reference_tetrahedron.off"); test_long_tetrahedron("data/long_tetrahedron.off"); - test_find_obb_evolution("data/random_unit_tetra.off"); - test_find_obb_mesh("data/elephant.off"); + test_compute_obb_evolution("data/random_unit_tetra.off"); + test_compute_obb_mesh("data/elephant.off"); test_function_defaults_traits("data/random_unit_tetra.off", "data/elephant.off"); return 0; diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp index 58ebc93542d..444f0b2acc9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp @@ -166,7 +166,7 @@ void Create_obb_mesh_plugin::obb() // find obb CGAL::Eigen_linear_algebra_traits la_traits; std::vector obb_points(8); - CGAL::Optimal_bounding_box::find_obb(points, obb_points, la_traits, true); + CGAL::Optimal_bounding_box::compute_optimal_bounding_box(points, obb_points, la_traits, true); Scene_item* item; if(mw->property("is_polyhedorn_mode").toBool()) From f6f0f98853313ea1bf3d5a1e7efc506ab070373c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 8 Jul 2018 14:17:45 +0200 Subject: [PATCH 052/150] Added an error message when no traits are provided --- .../include/CGAL/Optimal_bounding_box/evolution.h | 1 - .../CGAL/Optimal_bounding_box/optimal_bounding_box.h | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index b76d5e4aaaa..2089beb9a8c 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -123,7 +123,6 @@ public: #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG std::cout << "offspringsA: \n" ; check_det(offspringsA); - std::cin.get(); #endif // crossover II diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h index 62017fc84d4..3cb4fc338a1 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h @@ -200,7 +200,8 @@ void compute_optimal_bounding_box(const std::vector& points, #if defined(CGAL_EIGEN3_ENABLED) typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; #else - Linear_algebra_traits; + #pragma message("Error: You must either provide linear traits or link CGAL with the Eigen library") + Linear_algebra_traits; // no parameter provided, and Eigen is not enabled --> don't compile! #endif Linear_algebra_traits la_traits; @@ -258,7 +259,8 @@ void compute_optimal_bounding_box(const PolygonMesh& pmesh, #if defined(CGAL_EIGEN3_ENABLED) typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; #else - Linear_algebra_traits; + #pragma message("Error: You must either provide linear traits or link CGAL with the Eigen library") + Linear_algebra_traits; // no parameter provided, and Eigen is not enabled --> don't compile! #endif Linear_algebra_traits la_traits; From 06b167d6cc195ea295e5403985afff63e636bc31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 20 Oct 2019 20:45:13 +0200 Subject: [PATCH 053/150] Change maintainer --- .../package_info/Optimal_bounding_box/maintainer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Optimal_bounding_box/package_info/Optimal_bounding_box/maintainer b/Optimal_bounding_box/package_info/Optimal_bounding_box/maintainer index f45b28bc165..2427333ef57 100644 --- a/Optimal_bounding_box/package_info/Optimal_bounding_box/maintainer +++ b/Optimal_bounding_box/package_info/Optimal_bounding_box/maintainer @@ -1 +1 @@ -Konstantinos Katrioplas +GeometryFactory From 1348d433f02939f518ac0d747c40a5e41084e918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 20 Oct 2019 20:54:20 +0200 Subject: [PATCH 054/150] Update CMakeLists --- .../Optimal_bounding_box/CMakeLists.txt | 59 ++++--------------- .../Polygon_mesh_processing/CMakeLists.txt | 24 ++++++++ .../test/Optimal_bounding_box/CMakeLists.txt | 58 ++++-------------- 3 files changed, 49 insertions(+), 92 deletions(-) create mode 100644 Optimal_bounding_box/examples/Polygon_mesh_processing/CMakeLists.txt diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt index e918b0a6d4c..b66879123fe 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt @@ -1,62 +1,29 @@ # Created by the script cgal_create_CMakeLists # This is the CMake script for compiling a set of CGAL applications. +cmake_minimum_required(VERSION 3.1...3.15) project( Optimal_bounding_box_Benchmark ) - -cmake_minimum_required(VERSION 2.6.2) -if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6) - if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3) - cmake_policy(VERSION 2.8.4) - else() - cmake_policy(VERSION 2.6) - endif() -endif() - - # CGAL and its components -find_package( CGAL QUIET COMPONENTS ) +find_package( CGAL QUIET ) if ( NOT CGAL_FOUND ) - message(STATUS "This project requires the CGAL library, and will not be compiled.") - return() - + return() endif() # include helper file include( ${CGAL_USE_FILE} ) - -# Boost and its components -find_package( Boost REQUIRED ) - -if ( NOT Boost_FOUND ) - - message(STATUS "This project requires the Boost library, and will not be compiled.") - - return() - +find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) +if (NOT EIGEN3_FOUND) + message(STATUS "This project requires the Eigen library, and will not be compiled.") + return() +else() + include(${EIGEN3_USE_FILE}) endif() -# include for local directory - -# include for local package -include_directories( BEFORE ../../include ) - -find_package(Eigen3 3.2.0) #(requires 3.2.0 or greater) - -find_package( TBB ) - -include( CGAL_CreateSingleSourceCGALProgram ) -if (EIGEN3_FOUND) - include( ${EIGEN3_USE_FILE} ) - - create_single_source_cgal_program("bench_obb.cpp") - create_single_source_cgal_program("bench_perfomance.cpp") - create_single_source_cgal_program("bench_custom.cpp") - create_single_source_cgal_program("bench_fitness_function.cpp") - -endif(EIGEN3_FOUND) - - +create_single_source_cgal_program("bench_obb.cpp") +create_single_source_cgal_program("bench_perfomance.cpp") +create_single_source_cgal_program("bench_custom.cpp") +create_single_source_cgal_program("bench_fitness_function.cpp") diff --git a/Optimal_bounding_box/examples/Polygon_mesh_processing/CMakeLists.txt b/Optimal_bounding_box/examples/Polygon_mesh_processing/CMakeLists.txt new file mode 100644 index 00000000000..0faa74ffe4e --- /dev/null +++ b/Optimal_bounding_box/examples/Polygon_mesh_processing/CMakeLists.txt @@ -0,0 +1,24 @@ +# Created by the script cgal_create_cmake_script +# This is the CMake script for compiling a CGAL application. + +cmake_minimum_required(VERSION 3.1...3.15) +project( Optimal_bounding_box_Examples ) + +find_package(CGAL QUIET) + +if (NOT CGAL_FOUND) + message(STATUS "This project requires the CGAL library, and will not be compiled.") + return() +endif() + +include( ${CGAL_USE_FILE} ) + +find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) +if (NOT EIGEN3_FOUND) + message(STATUS "This project requires the Eigen library, and will not be compiled.") + return() +else() + include(${EIGEN3_USE_FILE}) +endif() + +create_single_source_cgal_program("example.cpp") diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt index 57c961df417..dc0d5800453 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt +++ b/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt @@ -1,60 +1,26 @@ # Created by the script cgal_create_CMakeLists # This is the CMake script for compiling a set of CGAL applications. +cmake_minimum_required(VERSION 3.1...3.15) project( Optimal_bounding_box_Tests ) +find_package(CGAL QUIET) -cmake_minimum_required(VERSION 2.6.2) -if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6) - if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3) - cmake_policy(VERSION 2.8.4) - else() - cmake_policy(VERSION 2.6) - endif() -endif() - - -# CGAL and its components -find_package( CGAL QUIET COMPONENTS ) - -if ( NOT CGAL_FOUND ) - +if (NOT CGAL_FOUND) message(STATUS "This project requires the CGAL library, and will not be compiled.") - return() - + return() endif() -# include helper file include( ${CGAL_USE_FILE} ) - -# Boost and its components -find_package( Boost REQUIRED ) - -if ( NOT Boost_FOUND ) - - message(STATUS "This project requires the Boost library, and will not be compiled.") - - return() - +find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) +if (NOT EIGEN3_FOUND) + message(STATUS "This project requires the Eigen library, and will not be compiled.") + return() +else() + include(${EIGEN3_USE_FILE}) endif() -# include for local directory - -# include for local package -include_directories( BEFORE ../../include ) - -find_package(Eigen3 3.2.0) #(requires 3.2.0 or greater) - -find_package( TBB ) - -include( CGAL_CreateSingleSourceCGALProgram ) -if (EIGEN3_FOUND) - include( ${EIGEN3_USE_FILE} ) - - create_single_source_cgal_program("test_linear_algebra_functions.cpp") - create_single_source_cgal_program("test_optimization_algorithms.cpp") - -endif(EIGEN3_FOUND) - +create_single_source_cgal_program("test_linear_algebra_functions.cpp") +create_single_source_cgal_program("test_optimization_algorithms.cpp") From 2ef6e31010b5bc0bb0a17b089b2a9df37dd3873b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 20 Oct 2019 21:02:27 +0200 Subject: [PATCH 055/150] Add doc skeleton --- .../doc/Optimal_bounding_box/Doxyfile.in | 6 + .../Optimal_bounding_box/NamedParameters.txt | 315 ++++++++++++++++++ .../Optimal_bounding_box.txt | 9 + .../PackageDescription.txt | 30 ++ .../doc/Optimal_bounding_box/dependencies | 14 + .../doc/Optimal_bounding_box/examples.txt | 4 + 6 files changed, 378 insertions(+) create mode 100644 Optimal_bounding_box/doc/Optimal_bounding_box/Doxyfile.in create mode 100644 Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt create mode 100644 Optimal_bounding_box/doc/Optimal_bounding_box/Optimal_bounding_box.txt create mode 100644 Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt create mode 100644 Optimal_bounding_box/doc/Optimal_bounding_box/dependencies create mode 100644 Optimal_bounding_box/doc/Optimal_bounding_box/examples.txt diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Doxyfile.in b/Optimal_bounding_box/doc/Optimal_bounding_box/Doxyfile.in new file mode 100644 index 00000000000..c01165a4dee --- /dev/null +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Doxyfile.in @@ -0,0 +1,6 @@ +@INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS} + +PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - Optimal Bounding Box" +EXTRACT_ALL = false +HIDE_UNDOC_CLASSES = true +WARN_IF_UNDOCUMENTED = false diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt new file mode 100644 index 00000000000..d9b8e95c9ac --- /dev/null +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt @@ -0,0 +1,315 @@ +/*! +\defgroup pmp_namedparameters Named Parameters for Polygon Mesh Processing +\ingroup PkgPolygonMeshProcessing + +In this package, all functions optional parameters are implemented as BGL optional +named parameters (see \ref BGLNamedParameters for more information on how to use them). +Since the parameters of the various polygon mesh processing functions defined +in this package are redundant, their long descriptions are centralized below. +The sequence of named parameters should start with `CGAL::parameters::`. +`CGAL::parameters::all_default()` can be used to indicate +that default values of optional named parameters must be used. + +In the following, we assume that the following types are provided as template parameters +of polygon mesh processing functions and classes. Note that, for some of these functions, +the type is more specific: +
    +
  • `PolygonMesh` is a model of the concept `FaceGraph`
  • . +
  • `GeomTraits` a geometric traits class in which constructions are performed and + predicates evaluated. Everywhere in this package, a \cgal `Kernel` fulfills the requirements.
  • +
+ +The following named parameters, offered by the package \ref PkgBGLSummary +(see \ref bgl_namedparameters), are used in this package: + +\cgalNPTableBegin +\cgalNPBegin{vertex_point_map} \anchor PMP_vertex_point_map +is the property map with the points associated to the vertices of the polygon mesh `pmesh`.\n +Type: a class model of `ReadablePropertyMap` with +`boost::graph_traits::%vertex_descriptor` as key type and +`GeomTraits::Point_3` as value type. \n +Default: \code boost::get(CGAL::vertex_point, pmesh) \endcode +\cgalNPEnd + +\cgalNPBegin{vertex_index_map} \anchor PMP_vertex_index_map +is the property map containing the index of each vertex of the input polygon mesh.\n +Type: a class model of `ReadablePropertyMap` with +`boost::graph_traits::%vertex_descriptor` as key type and the value type +\code typename boost::property_traits::type>::value_type \endcode +Default: \code boost::get(CGAL::vertex_index, pmesh)\endcode +\cgalNPEnd + +\cgalNPBegin{face_index_map} \anchor PMP_face_index_map +is the property map containing the index of each face of the input polygon mesh.\n +Type: a class model of `ReadablePropertyMap` with +`boost::graph_traits::%face_descriptor` as key type and the value type: +\code typename boost::property_traits::type>::value_type \endcode +Default: \code boost::get(CGAL::face_index, pmesh)\endcode +If this internal property map exists, its values should be initialized. +\cgalNPEnd + +\cgalNPBegin{edge_is_constrained_map} \anchor PMP_edge_is_constrained_map +is the property map containing information about edges of the input polygon mesh +being marked or not. In `isotropic_remeshing()` and `connected_components()`, +the marked edges are constrained.\n +Type: a class model of `ReadWritePropertyMap` with +`boost::graph_traits::%edge_descriptor` as key type and +`bool` as value type. It should be default constructible.\n +Default: a default property map where no edge is constrained +\cgalNPEnd +\cgalNPTableEnd + +In addition to these named parameters, this package offers the following named parameters: + +\cgalNPTableBegin +\cgalNPBegin{geom_traits} \anchor PMP_geom_traits +is the geometric traits instance in which the mesh processing operation should be performed.\n +Type: a Geometric traits class.\n +Default: +\code typename CGAL::Kernel_traits< + typename boost::property_traits< + typename boost::property_map::type>::value_type>::Kernel \endcode +\cgalNPEnd + +\cgalNPBegin{vertex_incident_patches_map} \anchor PMP_vertex_incident_patches_map +is the property map containing the surface patches incident to each vertex of the input polygon mesh.\n +Type: a class model of `LvaluePropertyMap` with +`boost::graph_traits::%vertex_descriptor` as key type. Its value type +must be a container of `boost::property_traits::%value_type` and have a function `insert()`. +A `std::set` or a `boost::unordered_set` are recommended, as a patch index may be +inserted several times.\n +Default: \code boost::get(CGAL::vertex_incident_patches_t, pmesh)\endcode +\cgalNPEnd + +\cgalNPBegin{vertex_feature_degree_map} \anchor PMP_vertex_feature_degree_map +is the property map containing the number of feature edges being incident to the vertices of the polygon mesh `pmesh`.\n +Type: a class model of `ReadWritePropertyMap` with +`boost::graph_traits::%vertex_descriptor` as key type and +`int` as value type. It should be default constructible.\n +Default: \code boost::get(CGAL::vertex_feature_degree_t(), pmesh) \endcode +\cgalNPEnd + +\cgalNPBegin{vertex_is_constrained_map} \anchor PMP_vertex_is_constrained_map +is the property map containing information about vertices of the input polygon mesh being constrained or not. +Constrained vertices may be replaced by new vertices, but the number and location +of vertices remain unchanged.\n +Type: a class model of `ReadWritePropertyMap` with +`boost::graph_traits::%vertex_descriptor` as key type and +`bool` as value type. It should be default constructible.\n +Default: a default property map where no vertex is constrained is provided. +\cgalNPEnd + +\cgalNPBegin{face_patch_map} \anchor PMP_face_patch_map +is a property map containing information about faces. +It is particularly well-suited for preserving surface patch IDs, +or face colors. +The edges at the interface between surface patches are treated similarly +to the ones of `edge_is_constrained_map`.\n +Type: a class model of `ReadWritePropertyMap` with +`boost::graph_traits::%face_descriptor` as key type and +the desired property, model of `CopyConstructible` as value type.\n +Default: a default property map where each face is associated with the ID of +the connected component it belongs to. Connected components are +computed with respect to the constrained edges listed in the property map +`edge_is_constrained_map` +\cgalNPEnd + +\cgalNPBegin{first_index} \anchor PMP_first_index +is the index of the first surface patch.\n +Type: `std::size_t`\n +Default: 1 +\cgalNPEnd + +\cgalNPBegin{density_control_factor} \anchor PMP_density_control_factor +controls the density of the mesh generated by refinement, with larger values causing denser refinements. +The density of vertices in the refined region is this factor times higher than before refinement.\n +Type: floating scalar value\n +Default: `CGAL::sqrt(2)` +\cgalNPEnd + +\cgalNPBegin{fairing_continuity} \anchor PMP_fairing_continuity +controls the tangential continuity of the output surface in `fair()`. +The possible values are 0, 1 and 2, refering to the C0, C1 +and C2 continuity.\n +Type: \c unsigned \c int between 0 and 2\n +Default: `1` +\cgalNPEnd + +\cgalNPBegin{sparse_linear_solver} \anchor PMP_sparse_linear_solver +is the solver used in `fair()`.\n +Type: a class model of `SparseLinearAlgebraWithFactorTraits_d`.\n +Default: if \ref thirdpartyEigen "Eigen" 3.2 (or greater) is available and +`CGAL_EIGEN3_ENABLED` is defined, then the following overload of `Eigen_solver_traits` +is provided as default value:\n +\code CGAL::Eigen_solver_traits::EigenType, Eigen::COLAMDOrdering > > \endcode +\cgalNPEnd + +\cgalNPBegin{number_of_iterations} \anchor PMP_number_of_iterations +is the number of iterations of the sequence of iterations performed in `isotropic_remeshing()`.\n +Type: \c unsigned \c int \n +Default: `1` +\cgalNPEnd + +\cgalNPBegin{protect_constraints} \anchor PMP_protect_constraints +enables the protection of constraints listed by \ref PMP_edge_is_constrained_map +"edge_is_constrained_map" and boundary edges +in `isotropic_remeshing()`. If `true`, constraint edges cannot be modified at all +during the remeshing process.\n +Type: `bool` \n +Default: `false` +\cgalNPEnd + +\cgalNPBegin{relax_constraints} \anchor PMP_relax_constraints +enables the tangential relaxation step in `isotropic_remeshing()` +to be performed on vertices that are endpoints of constraints listed +by \ref PMP_edge_is_constrained_map "edge_is_constrained_map", and boundary edges. +The vertices move along the constrained polylines they belong to. +Corners (i.e. vertices incident to more than 2 constraints, and vertices listed in +\ref PMP_vertex_is_constrained_map "vertex_is_constrained_map") are not allowed +to move at all. +If \ref PMP_protect_constraints "protect_constraints" is +set to `true`, this parameter is ignored.\n +Type: `bool` \n +Default: `true` +\cgalNPEnd + +\cgalNPBegin{number_of_relaxation_steps} \anchor PMP_number_of_relaxation_steps +is the number of iterations of tangential relaxation that are performed at each iteration +of `isotropic_remeshing()`. A larger number of relaxation steps lead to +a more isotropic mesh.\n +Type: \c unsigned \c int \n +Default: `1` +\cgalNPEnd + +\cgalNPBegin{use_delaunay_triangulation} \anchor PMP_use_delaunay_triangulation +enables the use of the Delaunay triangulation facet search space for hole filling functions.\n +Type: `bool` \n +Default: `true` +\cgalNPEnd + +\cgalNPBegin{use_random_uniform_sampling} \anchor PMP_use_random_uniform_sampling +is a parameter used in `sample_triangle_mesh()` to indicate if points should be picked +in a random uniform way.\n +Type: `bool` \n +Default: `true` +\cgalNPEnd + +\cgalNPBegin{use_grid_sampling} \anchor PMP_use_grid_sampling +is a parameter used in `sample_triangle_mesh()` to indicate if points should be picked +in on a grid in each face.\n +Type: `bool` \n +Default: `false` +\cgalNPEnd + +\cgalNPBegin{use_monte_carlo_sampling} \anchor PMP_use_monte_carlo_sampling +is a parameter used in `sample_triangle_mesh()` to indicate if points should be picked +using a Monte-Carlo approach.\n +Type: `bool` \n +Default: `false` +\cgalNPEnd + +\cgalNPBegin{sample_edges} \anchor PMP_sample_edges +is a parameter used in `sample_triangle_mesh()` to indicate if a dedicated sampling +of edges should be done.\n +Type: `bool` \n +Default: `true` +\cgalNPEnd + +\cgalNPBegin{sample_vertices} \anchor PMP_sample_vertices +is a parameter used in `sample_triangle_mesh()` to indicate if triangle vertices should +be copied in the output iterator.\n +Type: `bool` \n +Default: `true` +\cgalNPEnd + +\cgalNPBegin{sample_faces} \anchor PMP_sample_faces +is a parameter used in `sample_triangle_mesh()` to indicate if the interior of faces +should be considered for the sampling.\n +Type: `bool` \n +Default: `true` +\cgalNPEnd + +\cgalNPBegin{number_of_points_on_faces} \anchor PMP_number_of_points_on_faces +is a parameter used in `sample_triangle_mesh()` to set the number of points picked +using the random uniform method on faces.\n +Type: `std::size_t` \n +Default: `0` +\cgalNPEnd + +\cgalNPBegin{number_of_points_on_edges} \anchor PMP_number_of_points_on_edges +is a parameter used in `sample_triangle_mesh()` to set the number of points picked +using the random uniform method on edges.\n +Type: `std::size_t` \n +Default: `0` +\cgalNPEnd + +\cgalNPBegin{number_of_points_per_face} \anchor PMP_number_of_points_per_face +is a parameter used in `sample_triangle_mesh()` to set the number of points picked +per face using the Monte-Carlo method.\n +Type: `std::size_t` \n +Default: `0` +\cgalNPEnd + +\cgalNPBegin{number_of_points_per_edge} \anchor PMP_number_of_points_per_edge +is a parameter used in `sample_triangle_mesh()` to set the number of points picked +per edge using the Monte-Carlo method.\n +Type: `std::size_t` \n +Default: `0` +\cgalNPEnd + +\cgalNPBegin{grid_spacing} \anchor PMP_grid_spacing +is a parameter used in `sample_triangle_mesh()` to set the grid spacing when using +the grid sampling method.\n +Type: `double` \n +Default: `0` +\cgalNPEnd + +\cgalNPBegin{number_of_points_per_area_unit} \anchor PMP_number_of_points_per_area_unit +is a parameter used in `sample_triangle_mesh()` to set the number of points per +area unit to be picked up in faces for the random uniform sampling and +Monte-Carlo methods.\n +Type: `double` \n +Default: `0` +\cgalNPEnd + +\cgalNPBegin{number_of_points_per_distance_unit} \anchor PMP_number_of_points_per_distance_unit +is a parameter used in `sample_triangle_mesh()` to set the number of points per +distance unit to be picked up on edges for the random uniform sampling and +Monte-Carlo methods.\n +Type: `double` \n +Default: `0` +\cgalNPEnd + +\cgalNPBegin{do_project} \anchor PMP_do_project +is a parameter used in `random_perturbation()` to set whether vertices should be re-projected +to the input surface after their geometric perturbation.\n +Type: `bool` \n +Default: `true` +\cgalNPEnd + +\cgalNPBegin{random_seed} \anchor PMP_random_seed +is a parameter used in `random_perturbation()` to choose a seed to initialize +the random number generator `CGAL::Random()`. +If this parameter is not provided, the perturbation is not deterministic +(i.e. not reproducible from one run to the other).\n +Type: `unsigned int` \n +Default: the random number generator is initialized with `CGAL::Random()` +\cgalNPEnd + +\cgalNPBegin{outward_orientation} \anchor PMP_outward_orientation +Parameter used in orientation functions to choose between an outward or inward orientation. +\n +\b Type : `bool` \n +\b Default value is `true` + +\cgalNPBegin{do_overlap_test_of_bounded_sides} \anchor PMP_do_overlap_test_of_bounded_sides +Parameter used in intersection test functions to indicate whether overlapping tests of bounded sides +of close meshes should be done in addition to surface intersection tests. +\n +\b Type : `bool` \n +\b Default value is `false` +\cgalNPEnd + +\cgalNPTableEnd + +*/ diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Optimal_bounding_box.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/Optimal_bounding_box.txt new file mode 100644 index 00000000000..d84814bee40 --- /dev/null +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Optimal_bounding_box.txt @@ -0,0 +1,9 @@ +namespace CGAL { +/*! +\mainpage User Manual +\anchor Chapter_OptimalBoundingBox + +\cgalAutoToc +\authors + +} /* namespace CGAL */ diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt new file mode 100644 index 00000000000..496066da185 --- /dev/null +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt @@ -0,0 +1,30 @@ +/// \defgroup PkgOptimalBoundingBox Optimal Bounding Box Reference +/// \defgroup PkgOptimalBoundingBoxConcepts Concepts +/// \ingroup PkgOptimalBoundingBox + +\cgalPkgDescriptionBegin{Optimal Bounding Box, PkgOptimalBoundingBoxSummary} +\cgalPkgPicture{} + +\cgalPkgSummaryBegin +\cgalPkgAuthor{} +\cgalPkgDesc{This package provides stuff.} +\cgalPkgManuals{Chapter_OptimalBoundingBox,PkgOptimalBoundingBox} +\cgalPkgSummaryEnd + +\cgalPkgShortInfoBegin +\cgalPkgSince{5.2} +\cgalPkgDependsOn{documented for each function;} +\cgalPkgBib{cgal:lty-pmp} +\cgalPkgLicense{\ref licensesGPL "GPL"} +\cgalPkgDemo{Polyhedron demo,polyhedron_3.zip} +\cgalPkgShortInfoEnd + +\cgalPkgDescriptionEnd + +\cgalClassifedRefPages + +## Parameters ## + +## Functions ## + +*/ diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/dependencies b/Optimal_bounding_box/doc/Optimal_bounding_box/dependencies new file mode 100644 index 00000000000..52428e7009d --- /dev/null +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/dependencies @@ -0,0 +1,14 @@ +Manual +Kernel_23 +STL_Extension +Algebraic_foundations +Circulator +Stream_support +Polyhedron +BGL +Solver_interface +Surface_mesh +Surface_mesh_deformation +AABB_tree +Triangulation_2 +Spatial_sorting diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/examples.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/examples.txt new file mode 100644 index 00000000000..76aff917caf --- /dev/null +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/examples.txt @@ -0,0 +1,4 @@ +/*! + +\example Optimal_bounding_box/example_todo.cpp +*/ From 96088397a98ff5105babfa2020f3cff60a7fd537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sun, 20 Oct 2019 21:03:00 +0200 Subject: [PATCH 056/150] Add missing package info --- Optimal_bounding_box/package_info/Optimal_bounding_box/copyright | 1 + .../package_info/Optimal_bounding_box/dependencies | 0 .../package_info/Optimal_bounding_box/license.txt | 1 + 3 files changed, 2 insertions(+) create mode 100644 Optimal_bounding_box/package_info/Optimal_bounding_box/copyright create mode 100644 Optimal_bounding_box/package_info/Optimal_bounding_box/dependencies create mode 100644 Optimal_bounding_box/package_info/Optimal_bounding_box/license.txt diff --git a/Optimal_bounding_box/package_info/Optimal_bounding_box/copyright b/Optimal_bounding_box/package_info/Optimal_bounding_box/copyright new file mode 100644 index 00000000000..d76cdbe60d6 --- /dev/null +++ b/Optimal_bounding_box/package_info/Optimal_bounding_box/copyright @@ -0,0 +1 @@ +GeometryFactory (France) \ No newline at end of file diff --git a/Optimal_bounding_box/package_info/Optimal_bounding_box/dependencies b/Optimal_bounding_box/package_info/Optimal_bounding_box/dependencies new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Optimal_bounding_box/package_info/Optimal_bounding_box/license.txt b/Optimal_bounding_box/package_info/Optimal_bounding_box/license.txt new file mode 100644 index 00000000000..8bb8efcb72b --- /dev/null +++ b/Optimal_bounding_box/package_info/Optimal_bounding_box/license.txt @@ -0,0 +1 @@ +GPL (v3 or later) From cd4123bf2c5c24026518010bd0e519febb66ab21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 3 Dec 2019 19:45:36 +0100 Subject: [PATCH 057/150] Clean code (partial) --- .../Optimal_bounding_box/bench_obb.cpp | 2 +- .../CGAL/Optimal_bounding_box/evolution.h | 71 ++++++++----------- .../Optimal_bounding_box/fitness_function.h | 18 ++--- .../CGAL/Optimal_bounding_box/helper.h | 1 - .../nelder_mead_functions.h | 27 ++++--- .../optimal_bounding_box.h | 50 +++++-------- .../CGAL/Optimal_bounding_box/population.h | 29 ++++---- .../test_optimization_algorithms.cpp | 4 +- .../CGAL/Eigen_linear_algebra_traits.h | 6 +- 9 files changed, 94 insertions(+), 114 deletions(-) diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp index 44e85c184bf..c7a3a32af62 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp @@ -28,7 +28,7 @@ void gather_mesh_points(SurfaceMesh& mesh, std::vector& points) typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::property_map::type PointPMap; PointPMap pmap = get(boost::vertex_point, mesh); - BOOST_FOREACH(vertex_descriptor v, vertices(mesh)) + for(vertex_descriptor v : vertices(mesh)) points.push_back(get(pmap, v)); } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index 2089beb9a8c..f749b093139 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -33,7 +33,6 @@ #include namespace CGAL { - namespace Optimal_bounding_box { template @@ -51,39 +50,35 @@ public: void genetic_algorithm() { // random permutations - std::size_t m = population.size(); + const std::size_t m = population.size(); //groups 1,2 : size m/2 groups 3,4 : size (m - m/2). m/2 is floored - std::size_t size_first_group = m/2; - std::size_t size_second_group = m - m/2; + const std::size_t size_first_group = m/2; + const std::size_t size_second_group = m - size_first_group; - std::vector ids1(m/2), ids2(m/2); - std::vector ids3(m - m/2), ids4(m - m/2); + std::vector ids1(size_first_group), ids2(size_first_group); + std::vector ids3(size_second_group), ids4(size_second_group); CGAL::Random rng; int im = static_cast(m); - std::generate(ids1.begin(), ids1.end(), - [&rng, &im] () { return rng.get_int(0, im); }); - std::generate(ids2.begin(), ids2.end(), - [&rng, &im] () { return rng.get_int(0, im); }); - std::generate(ids3.begin(), ids3.end(), - [&rng, &im] () { return rng.get_int(0, im); }); - std::generate(ids4.begin(), ids4.end(), - [&rng, &im] () { return rng.get_int(0, im); }); + std::generate(ids1.begin(), ids1.end(), [&rng, &im] () { return rng.get_int(0, im); }); + std::generate(ids2.begin(), ids2.end(), [&rng, &im] () { return rng.get_int(0, im); }); + std::generate(ids3.begin(), ids3.end(), [&rng, &im] () { return rng.get_int(0, im); }); + std::generate(ids4.begin(), ids4.end(), [&rng, &im] () { return rng.get_int(0, im); }); - Population group1(m/2), group2(m/2); - Population group3(m - m/2), group4(m - m/2); + Population group1(size_first_group), group2(size_first_group); + Population group3(size_second_group), group4(size_second_group); - for(std::size_t i = 0; i < ids1.size(); ++i) + for(std::size_t i=0; i offspringsA(size_first_group); double bias = 0.1; - for(std::size_t i = 0; i < size_first_group; ++i) + for(std::size_t i=0; i offspring(4); - for(int j = 0; j < 4; ++j) + for(int j=0; j<4; ++j) { double r = rng.get_double(); double fitnessA = compute_fitness(group1[i][j], point_data); @@ -129,10 +124,10 @@ public: Population offspringsB(size_second_group); bias = 0.1; - for(std::size_t i = 0; i < size_second_group; ++i) + for(std::size_t i=0; i offspring(4); - for(int j = 0; j < 4; ++j) + for(int j=0; j<4; ++j) { double fitnessA = compute_fitness(group3[i][j], point_data); double fitnessB = compute_fitness(group4[i][j], point_data); @@ -160,25 +155,25 @@ public: CGAL_assertion(offspringsA.size() + offspringsB.size() == population.size()); // next generatrion - for(std::size_t i = 0; i < size_first_group; ++i) + for(std::size_t i=0; i fitness_map_debug(population, point_data); Matrix3d R_now = fitness_map_debug.get_best(); - std::cout << "det= " << Linear_algebra_traits::determinant(R_now) << std::endl; + std::cout << "det = " << Linear_algebra_traits::determinant(R_now) << std::endl; #endif // stopping criteria @@ -210,7 +205,7 @@ public: double difference = new_fit_value - prev_fit_value; if(CGAL::abs(difference) < tolerance * new_fit_value) - stale++; + ++stale; if(stale == 5) break; @@ -226,7 +221,6 @@ public: } private: - // data Population population; MatrixXd point_data; }; @@ -235,13 +229,10 @@ private: template void check_det(Population& pop) { - for(std::size_t i = 0; i < pop.size(); ++i) + for(std::size_t i=0, ps=pop.size(); i namespace CGAL { - namespace Optimal_bounding_box { template @@ -45,16 +44,19 @@ double compute_fitness(const Vertex& R, const Matrix& data) typedef typename Linear_algebra_traits::Index Index; double xmin, xmax, ymin, ymax, zmin, zmax; - for(Index i = 0; i < static_cast(data.rows()); ++i){ - + for(Index i=0; i < static_cast(data.rows()); ++i) + { Vector3d vec = Linear_algebra_traits::row3(data, i); vec = R * vec; - if(i == 0){ + if(i == 0) + { xmin = xmax = vec.coeff(0); ymin = ymax = vec.coeff(1); zmin = zmax = vec.coeff(2); - }else { + } + else + { if(vec.coeff(0) < xmin) xmin = vec.coeff(0); if(vec.coeff(1) < ymin) ymin = vec.coeff(1); if(vec.coeff(2) < zmin) zmin = vec.coeff(2); @@ -83,13 +85,13 @@ struct Fitness_map { std::size_t simplex_id, vertex_id; double best_fitness = std::numeric_limits::max(); - for(std::size_t i = 0; i < pop.size(); ++i) + for(std::size_t i=0; i(vertex, points); - if (fitness < best_fitness) + if(fitness < best_fitness) { simplex_id = i; vertex_id = j; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h index d207feb93ea..0ec2d1507c2 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h @@ -35,7 +35,6 @@ #include namespace CGAL { - namespace Optimal_bounding_box { template diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h index 3d7de8c8db3..65233767b77 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h @@ -22,16 +22,18 @@ #define CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H #include -#include #include + +#include + #include namespace CGAL { - namespace Optimal_bounding_box { template -const Matrix reflection(const Matrix& S_centroid, const Matrix& S_worst) +const Matrix reflection(const Matrix& S_centroid, + const Matrix& S_worst) { CGAL_assertion(S_centroid.rows() == 3); CGAL_assertion(S_centroid.rows() == 3); @@ -42,7 +44,9 @@ const Matrix reflection(const Matrix& S_centroid, const Matrix& S_worst) } template -const Matrix expansion(const Matrix& S_centroid, const Matrix& S_worst, const Matrix& S_reflection) +const Matrix expansion(const Matrix& S_centroid, + const Matrix& S_worst, + const Matrix& S_reflection) { CGAL_assertion(S_centroid.rows() == 3); CGAL_assertion(S_centroid.rows() == 3); @@ -55,7 +59,8 @@ const Matrix expansion(const Matrix& S_centroid, const Matrix& S_worst, const Ma } template -Matrix mean(const Matrix& m1, const Matrix& m2) +Matrix mean(const Matrix& m1, + const Matrix& m2) { // same API for reduction CGAL_assertion(m1.rows() == 3); @@ -70,7 +75,9 @@ Matrix mean(const Matrix& m1, const Matrix& m2) } template -const Matrix nm_centroid(const Matrix& S1, const Matrix& S2, const Matrix& S3) +const Matrix nm_centroid(const Matrix& S1, + const Matrix& S2, + const Matrix& S3) { Matrix mean = (S1 + S2 + S3) / 3.0; Matrix Q = Linear_algebra_traits::qr_factorization(mean); @@ -81,7 +88,7 @@ const Matrix nm_centroid(const Matrix& S1, const Matrix& S2, const Matrix& S3) // needed in nelder mead algorithm struct Comparator { - Comparator(const std::vector& in) : fitness(in) {} + Comparator(const std::vector& in) : fitness(in) { } inline bool operator() (std::size_t& i, std::size_t& j) { return fitness[i] < fitness[j]; @@ -107,7 +114,7 @@ void nelder_mead(std::vector& simplex, for(std::size_t t = 0; t < nelder_mead_iterations; ++t) { - for(std::size_t i = 0; i < 4; ++i) + for(std::size_t i=0; i<4; ++i) { fitness[i] = compute_fitness(simplex[i], point_data); } @@ -116,7 +123,7 @@ void nelder_mead(std::vector& simplex, CGAL_assertion(indices.size() == 4); // get indices of sorted sequence - Comparator compare_indices(fitness); + Comparator compare_indices(fitness); // @todo lambda this stuff std::sort(indices.begin(), indices.end(), compare_indices); // new sorted simplex & fitness @@ -167,7 +174,7 @@ void nelder_mead(std::vector& simplex, else { // reduction: move all vertices towards the best - for(std::size_t i=1; i < 4; ++i) + for(std::size_t i=1; i<4; ++i) { simplex[i] = mean(simplex[i], simplex[0]); } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h index 3cb4fc338a1..3900ce6cc1b 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h @@ -35,7 +35,7 @@ #include #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS - #include +#include #endif #if defined(CGAL_EIGEN3_ENABLED) @@ -47,13 +47,14 @@ #include namespace CGAL { - namespace Optimal_bounding_box { // works on matrices only /// \cond SKIP_IN_MANUAL template -void post_processing(const Matrix& points, Vertex& R, Matrix& obb) +void post_processing(const Matrix& points, + Vertex& R, + Matrix& obb) { CGAL_assertion(points.cols() == 3); CGAL_assertion(R.rows() == 3); @@ -66,13 +67,13 @@ void post_processing(const Matrix& points, Vertex& R, Matrix& obb) rotated_points = points * Linear_algebra_traits::transpose(R); // 2) get AABB from rotated points - typedef CGAL::Simple_cartesian K; - typedef K::Point_3 Point; + typedef CGAL::Simple_cartesian K; + typedef K::Point_3 Point; typedef typename Linear_algebra_traits::Index index; // Simplex -> std::vector std::vector v_points; - for(index i = 0; i < static_cast(rotated_points.rows()); ++i) + for(index i=0; i(rotated_points.rows()); ++i) { Point p(rotated_points(i, 0), rotated_points(i, 1), rotated_points(i, 2)); v_points.push_back(p); @@ -82,7 +83,7 @@ void post_processing(const Matrix& points, Vertex& R, Matrix& obb) K::Iso_cuboid_3 ic(bbox); Matrix aabb(8, 3); - for(std::size_t i = 0; i < 8; ++i) + for(std::size_t i = 0; i<8; ++i) { aabb.set_coef(i, 0, ic[i].x()); aabb.set_coef(i, 1, ic[i].y()); @@ -115,11 +116,10 @@ void compute_optimal_bounding_box(const std::vector& points, if(obb_points.size() != 8) obb_points.resize(8); - CGAL_assertion(obb_points.size() == 8); // eigen linear algebra traits - typedef typename LinearAlgebraTraits::MatrixXd MatrixXd; - typedef typename LinearAlgebraTraits::Matrix3d Matrix3d; + typedef typename LinearAlgebraTraits::MatrixXd MatrixXd; + typedef typename LinearAlgebraTraits::Matrix3d Matrix3d; MatrixXd points_mat; if(use_ch) // get the ch3 @@ -133,39 +133,31 @@ void compute_optimal_bounding_box(const std::vector& points, CGAL::Optimal_bounding_box::fill_matrix(points, points_mat); } -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS - CGAL::Timer timer; -#endif - std::size_t max_generations = 100; Population pop(50); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS + CGAL::Timer timer; timer.start(); #endif CGAL::Optimal_bounding_box::Evolution search_solution(pop, points_mat); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS - timer.stop(); std::cout << "constructor: " << timer.time() << std::endl; timer.reset(); - timer.start(); #endif search_solution.evolve(max_generations); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS - timer.stop(); std::cout << "evolve: " << timer.time() << std::endl; timer.reset(); - timer.start(); #endif Matrix3d rotation = search_solution.get_best(); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS - timer.stop(); std::cout << "get best: " << timer.time() << std::endl; #endif @@ -174,22 +166,17 @@ void compute_optimal_bounding_box(const std::vector& points, #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS timer.reset(); - timer.start(); #endif post_processing(points_mat, rotation, obb); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS - timer.stop(); std::cout << "post porcessing: " << timer.time() << std::endl; #endif // matrix -> vector - for(std::size_t i = 0; i < 8; ++i) - { - Point p(obb(i, 0), obb(i, 1), obb(i, 2)); - obb_points[i] = p; - } + for(std::size_t i=0; i<8; ++i) + obb_points.emplace(obb_points.begin() + i, obb(i, 0), obb(i, 1), obb(i, 2)); } template @@ -234,16 +221,15 @@ void compute_optimal_bounding_box(const PolygonMesh& pmesh, return; } - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::property_map::type Vpm; - typedef typename boost::property_traits::value_type Point; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::property_map::type Vpm; + typedef typename boost::property_traits::value_type Point; std::vector points; Vpm pmap = get(boost::vertex_point, pmesh); - BOOST_FOREACH(vertex_descriptor v, vertices(pmesh)) + for(vertex_descriptor v : vertices(pmesh)) points.push_back(get(pmap, v)); - std::vector obb_points; compute_optimal_bounding_box(points, obb_points, la_traits, use_ch); @@ -257,7 +243,7 @@ void compute_optimal_bounding_box(const PolygonMesh& pmesh, bool use_ch) { #if defined(CGAL_EIGEN3_ENABLED) - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; #else #pragma message("Error: You must either provide linear traits or link CGAL with the Eigen library") Linear_algebra_traits; // no parameter provided, and Eigen is not enabled --> don't compile! diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index 4404acdcd3a..704c2834d35 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -28,24 +28,25 @@ #include namespace CGAL { - namespace Optimal_bounding_box { template class Population { - typedef typename Linear_algebra_traits::Matrix3d Matrix; - typedef std::vector Simplex; + typedef typename Linear_algebra_traits::Matrix3d Matrix; + typedef std::vector Simplex; public: Population(std::size_t size) - : n(size), random_generator(CGAL::Random()) + : + n(size), + random_generator(CGAL::Random()) { // reserve pop space pop.reserve(n); // create simplices - for(std::size_t i = 0 ; i < n; ++i) + for(std::size_t i=0 ; i void Population::show_population() { std::size_t id = 0; - for(const Simplex i : pop) + for(const Simplex& i : pop) { CGAL_assertion(i.size() == 4); std:: cout << "Simplex: "<< id++ << std::endl; - for(const Matrix R : i) + for(const Matrix& R : i) { std::cout << R; // eigen out std::cout << "\n\n"; diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 4f03054dcbd..28c21b3a784 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -320,7 +320,7 @@ void test_compute_obb_evolution(std::string fname) typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::property_map::const_type PointPMap; PointPMap pmap = get(boost::vertex_point, mesh); - BOOST_FOREACH(vertex_descriptor v, vertices(mesh)) + for(vertex_descriptor v : vertices(mesh)) sm_points.push_back(get(pmap, v)); @@ -393,7 +393,7 @@ void test_function_defaults_traits(std::string fname1, std::string fname2) typedef typename boost::property_map::const_type PointPMap; PointPMap pmap = get(boost::vertex_point, mesh1); - BOOST_FOREACH(vertex_descriptor v, vertices(mesh1)) + for(vertex_descriptor v : vertices(mesh1)) sm_points.push_back(get(pmap, v)); std::vector obb_points; diff --git a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h index e56f1775f53..cc55ed70ef3 100644 --- a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h +++ b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h @@ -316,11 +316,7 @@ const Eigen_dense_vector operator* (const CGAL::Eigen_dense_matrix(A.m_matrix * V.m_vector); } - - -} -// end namespace - +} // end namespace #endif // CGAL_EIGEN_LINEAR_ALGEBRA_TRAITS_H From 51e965e1dc10206ac11035a3fd8009759c6be62b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Dec 2019 12:25:38 +0100 Subject: [PATCH 058/150] Rewrite most of OBB code to fix design issues and bugs --- .../Optimal_bounding_box/bench_obb.cpp | 9 - .../CGAL/Optimal_bounding_box/evolution.h | 228 ++++++------- .../Optimal_bounding_box/fitness_function.h | 114 +++---- .../CGAL/Optimal_bounding_box/helper.h | 118 +++---- .../nelder_mead_functions.h | 186 +++++----- .../optimal_bounding_box.h | 312 +++++++++-------- .../CGAL/Optimal_bounding_box/population.h | 144 ++++---- .../test_optimization_algorithms.cpp | 260 +++++++------- .../Polyhedron/Plugins/PCA/CMakeLists.txt | 2 +- .../Plugins/PCA/Create_obb_mesh_plugin.cpp | 99 ++---- .../CGAL/Eigen_linear_algebra_traits.h | 322 ------------------ 11 files changed, 655 insertions(+), 1139 deletions(-) delete mode 100644 Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp index c7a3a32af62..02eefd76513 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp @@ -32,15 +32,6 @@ void gather_mesh_points(SurfaceMesh& mesh, std::vector& points) points.push_back(get(pmap, v)); } -template -double calculate_volume(std::vector points) -{ - CGAL::Bbox_3 bbox; - bbox = bbox_3(points.begin(), points.end()); - K::Iso_cuboid_3 ic(bbox); - return ic.volume(); -} - void bench_finding_obb(std::string fname) { std::ifstream input(fname); diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h index f749b093139..a28535e8242 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h @@ -1,23 +1,16 @@ -// Copyright (c) 2018 GeometryFactory (France). +// Copyright (c) 2018-2019 GeometryFactory (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// // // Author(s) : Konstantinos Katrioplas - +// Mael Rouxel-Labbé +// #ifndef CGAL_OPTIMAL_BOUNDING_BOX_EVOLUTION_H #define CGAL_OPTIMAL_BOUNDING_BOX_EVOLUTION_H @@ -29,141 +22,124 @@ #include #include +#include #include #include namespace CGAL { namespace Optimal_bounding_box { -template +template class Evolution { - typedef typename Linear_algebra_traits::MatrixXd MatrixXd; - typedef typename Linear_algebra_traits::Matrix3d Matrix3d; - typedef typename Linear_algebra_traits::Vector3d Vector3d; - public: - Evolution(Population& pop, MatrixXd& points) - : population(pop), point_data(points) - {} + typedef typename Traits::FT FT; + typedef typename Traits::Matrix Matrix; - void genetic_algorithm() + typedef Optimal_bounding_box::Population Population; + typedef typename Population::Simplex Simplex; + + typedef Optimal_bounding_box::Fitness_map Fitness_map; + + Evolution(const PointRange& points, + CGAL::Random& rng, + const Traits& traits) + : + m_population(traits), + m_rng(rng), // @todo just a parameter of genetic_algorithm() ? + m_points(points), + m_traits(traits) + { } + + void genetic_algorithm(const std::size_t population_size = 50) { // random permutations - const std::size_t m = population.size(); + m_population.initialize(population_size, m_rng); //groups 1,2 : size m/2 groups 3,4 : size (m - m/2). m/2 is floored - const std::size_t size_first_group = m/2; - const std::size_t size_second_group = m - size_first_group; + const std::size_t m = population_size; + const std::size_t first_group_size = m / 2; + const std::size_t second_group_size = m - first_group_size; - std::vector ids1(size_first_group), ids2(size_first_group); - std::vector ids3(size_second_group), ids4(size_second_group); + std::vector group1(first_group_size), group2(first_group_size); + std::vector group3(second_group_size), group4(second_group_size); - CGAL::Random rng; int im = static_cast(m); - std::generate(ids1.begin(), ids1.end(), [&rng, &im] () { return rng.get_int(0, im); }); - std::generate(ids2.begin(), ids2.end(), [&rng, &im] () { return rng.get_int(0, im); }); - std::generate(ids3.begin(), ids3.end(), [&rng, &im] () { return rng.get_int(0, im); }); - std::generate(ids4.begin(), ids4.end(), [&rng, &im] () { return rng.get_int(0, im); }); - - Population group1(size_first_group), group2(size_first_group); - Population group3(size_second_group), group4(size_second_group); - - for(std::size_t i=0; i offspringsA(size_first_group); double bias = 0.1; - for(std::size_t i=0; i new_simplices(m); + + for(std::size_t i=0; i offspring(4); + std::array offspring; for(int j=0; j<4; ++j) { - double r = rng.get_double(); - double fitnessA = compute_fitness(group1[i][j], point_data); - double fitnessB = compute_fitness(group2[i][j], point_data); - double threshold; + const double r = m_rng.get_double(); + const double fitnessA = compute_fitness(m_population[group1[i]][j], m_points); + const double fitnessB = compute_fitness(m_population[group2[i]][j], m_points); + const double threshold = (fitnessA < fitnessB) ? (0.5 + bias) : (0.5 - bias); - if(fitnessA < fitnessB) - threshold = 0.5 + bias; + if(r < threshold) + offspring[j] = m_population[group1[i]][j]; else - threshold = 0.5 - bias; - - if(r < threshold) // choose A - offspring[j] = group1[i][j]; - else // choose B - offspring[j] = group2[i][j]; + offspring[j] = m_population[group2[i]][j]; } - offspringsA[i] = offspring; - } -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG - std::cout << "offspringsA: \n" ; - check_det(offspringsA); -#endif + new_simplices[i] = std::move(offspring); + } // crossover II - Population offspringsB(size_second_group); - bias = 0.1; + bias = 0.1; // @fixme should the bias change? What should be the initial value? - for(std::size_t i=0; i offspring(4); + std::array offspring; for(int j=0; j<4; ++j) { - double fitnessA = compute_fitness(group3[i][j], point_data); - double fitnessB = compute_fitness(group4[i][j], point_data); - double lambda; - if(fitnessA < fitnessB) - lambda = 0.5 + bias; - else - lambda = 0.5 - bias; + const double fitnessA = compute_fitness(m_population[group3[i]][j], m_points); + const double fitnessB = compute_fitness(m_population[group4[i]][j], m_points); + const double lambda = (fitnessA < fitnessB) ? (0.5 + bias) : (0.5 - bias); + const double rambda = 1 - lambda; // the 'l' in 'lambda' stands for left + // combine information from A and B - offspring[j] = lambda * group3[i][j] + lambda * group4[i][j]; + Matrix new_vertex(3, 3); + + const Matrix& lm = m_population[group3[i]][j]; + const Matrix& rm = m_population[group4[i]][j]; + + // just avoiding having to add matrix sums and scalar multiplications to the concept + new_vertex.set(0, 0, lambda * lm(0, 0) + rambda * rm(0, 0)); + new_vertex.set(0, 1, lambda * lm(0, 1) + rambda * rm(0, 1)); + new_vertex.set(0, 2, lambda * lm(0, 2) + rambda * rm(0, 2)); + + new_vertex.set(1, 0, lambda * lm(1, 0) + rambda * rm(1, 0)); + new_vertex.set(1, 1, lambda * lm(1, 1) + rambda * rm(1, 1)); + new_vertex.set(1, 2, lambda * lm(1, 2) + rambda * rm(1, 2)); + + new_vertex.set(2, 0, lambda * lm(2, 0) + rambda * rm(2, 0)); + new_vertex.set(2, 1, lambda * lm(2, 1) + rambda * rm(2, 1)); + new_vertex.set(2, 2, lambda * lm(2, 2) + rambda * rm(2, 2)); + + offspring[j] = m_traits.qr_factorization(new_vertex); } - // qr factorization of the offspring - Linear_algebra_traits::qr_factorization(offspring); - offspringsB[i] = offspring; + new_simplices[first_group_size + i] = std::move(offspring); } -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG - std::cout << "offspringsB: \n" ; - check_det(offspringsB); -#endif - - CGAL_assertion(offspringsA.size() == size_first_group); - CGAL_assertion(offspringsB.size() == size_second_group); - CGAL_assertion(offspringsA.size() + offspringsB.size() == population.size()); - - // next generatrion - for(std::size_t i=0; i(population[s], point_data, nelder_mead_iterations); + for(std::size_t s=0; s fitness_map_debug(population, point_data); - Matrix3d R_now = fitness_map_debug.get_best(); - std::cout << "det = " << Linear_algebra_traits::determinant(R_now) << std::endl; + const Matrix& R_now = fitness_map.get_best(); + std::cout << "det = " << m_traits.determinant(R_now) << std::endl; #endif - // stopping criteria - Fitness_map fitness_map(population, point_data); new_fit_value = fitness_map.get_best_fitness_value(); - double difference = new_fit_value - prev_fit_value; + const double difference = new_fit_value - prev_fit_value; if(CGAL::abs(difference) < tolerance * new_fit_value) ++stale; @@ -214,29 +190,19 @@ public: } } - const Matrix3d get_best() + const Matrix& get_best() { - Fitness_map fitness_map(population, point_data); + Fitness_map fitness_map(m_population, m_points); return fitness_map.get_best(); } private: - Population population; - MatrixXd point_data; + Population m_population; + CGAL::Random m_rng; + const PointRange& m_points; + const Traits& m_traits; }; -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG -template -void check_det(Population& pop) -{ - for(std::size_t i=0, ps=pop.size(); i - #include +#include #include namespace CGAL { namespace Optimal_bounding_box { -template -double compute_fitness(const Vertex& R, const Matrix& data) +template +typename Traits::FT +compute_fitness(const typename Traits::Matrix& R, // rotation matrix + const PointRange& points) { - // R: rotation matrix - CGAL_assertion(R.cols() == 3); - CGAL_assertion(R.rows() == 3); - // data: points - CGAL_assertion(data.cols() == 3); - CGAL_assertion(data.rows() >= 3); + typedef typename Traits::FT FT; + typedef typename Traits::Point_3 Point; - typedef typename Linear_algebra_traits::Vector3d Vector3d; - typedef typename Linear_algebra_traits::Index Index; + CGAL_assertion(R.number_of_rows() == 3 && R.number_of_columns() == 3); + CGAL_assertion(points.size() >= 3); - double xmin, xmax, ymin, ymax, zmin, zmax; - for(Index i=0; i < static_cast(data.rows()); ++i) + FT xmin, ymin, zmin, xmax, ymax, zmax; + xmin = ymin = zmin = std::numeric_limits::max(); + xmax = ymax = zmax = std::numeric_limits::lowest(); + + for(const Point& pt : points) { - Vector3d vec = Linear_algebra_traits::row3(data, i); - vec = R * vec; + const FT x = pt.x(), y = pt.y(), z = pt.z(); - if(i == 0) - { - xmin = xmax = vec.coeff(0); - ymin = ymax = vec.coeff(1); - zmin = zmax = vec.coeff(2); - } - else - { - if(vec.coeff(0) < xmin) xmin = vec.coeff(0); - if(vec.coeff(1) < ymin) ymin = vec.coeff(1); - if(vec.coeff(2) < zmin) zmin = vec.coeff(2); - if(vec.coeff(0) > xmax) xmax = vec.coeff(0); - if(vec.coeff(1) > ymax) ymax = vec.coeff(1); - if(vec.coeff(2) > zmax) zmax = vec.coeff(2); - } + const FT rx = x*R(0, 0) + y*R(0, 1) + z*R(0, 2); + const FT ry = x*R(1, 0) + y*R(1, 1) + z*R(1, 2); + const FT rz = x*R(2, 0) + y*R(2, 1) + z*R(2, 2); + + xmin = (std::min)(xmin, rx); + ymin = (std::min)(ymin, ry); + zmin = (std::min)(zmin, rz); + xmax = (std::max)(xmax, rx); + ymax = (std::max)(ymax, ry); + zmax = (std::max)(zmax, rz); } - CGAL_assertion(xmax > xmin); - CGAL_assertion(ymax > ymin); - CGAL_assertion(zmax > zmin); - // volume return ((xmax - xmin) * (ymax - ymin) * (zmax - zmin)); } -template +template struct Fitness_map { - Fitness_map(Population& p, Matrix& points) - : pop(p), points(points) - {} + typedef typename Traits::FT FT; + typedef typename Population::Vertex Vertex; - const Vertex get_best() + Fitness_map(const Population& population, + const PointRange& points) + : + m_pop(population), + m_points(points) + { } + + const Vertex& get_best() const // @todo any point caching this? { std::size_t simplex_id, vertex_id; - double best_fitness = std::numeric_limits::max(); - for(std::size_t i=0; i::max(); + for(std::size_t i=0, ps=m_pop.size(); i(vertex, points); + const Vertex& vertex = m_pop[i][j]; + const FT fitness = compute_fitness(vertex, m_points); if(fitness < best_fitness) { simplex_id = i; @@ -100,17 +89,18 @@ struct Fitness_map } } - return pop[simplex_id][vertex_id]; + return m_pop[simplex_id][vertex_id]; } - double get_best_fitness_value() + FT get_best_fitness_value() const { - const Vertex best_mat = get_best(); - return compute_fitness(best_mat, points); + const Vertex& best_mat = get_best(); + return compute_fitness(best_mat, m_points); } - Population& pop; - const Matrix& points; +private: + const Population& m_pop; + const PointRange& m_points; }; } // end namespace Optimal_bounding_box diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h index 0ec2d1507c2..d12de45212e 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h @@ -1,24 +1,16 @@ -// Copyright (c) 2018 GeometryFactory (France). +// Copyright (c) 2018-2019 GeometryFactory (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Konstantinos Katrioplas - +// Mael Rouxel-Labbé +// #ifndef CGAL_OPTIMAL_BOUNDING_BOX_HELPER_H #define CGAL_OPTIMAL_BOUNDING_BOX_HELPER_H @@ -30,6 +22,11 @@ #include #include +#ifdef CGAL_EIGEN3_ENABLED +#include +#include +#endif + #include #include #include @@ -37,74 +34,45 @@ namespace CGAL { namespace Optimal_bounding_box { -template -void fill_matrix(const std::vector& v_points, Matrix& points_mat) +#ifdef CGAL_EIGEN3_ENABLED +// @tmp move the header include too +template +class Optimal_bounding_box_traits + : public K { - points_mat.resize(v_points.size(), 3); - for(std::size_t i = 0; i < v_points.size(); ++i) +public: + typedef typename K::FT FT; + typedef CGAL::Eigen_matrix Matrix; + +private: + typedef typename Matrix::EigenType EigenType; + +public: + explicit Optimal_bounding_box_traits(const K& k = K()) : K(k) { } + + /// Get the transpose of a `Matrix` matrix + Matrix transpose(const Matrix& mat) const { - Point p = v_points[i]; - points_mat.set_coef(i, 0, CGAL::to_double(p.x())); - points_mat.set_coef(i, 1, CGAL::to_double(p.y())); - points_mat.set_coef(i, 2, CGAL::to_double(p.z())); - } -} - -template -void sm_to_matrix(SurfaceMesh& sm, Matrix& mat) -{ - typedef typename boost::property_map::const_type Vpm; - typedef typename boost::property_traits::reference Point_ref; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - Vpm vpm = get(boost::vertex_point, sm); - - mat.resize(vertices(sm).size(), 3); - std::size_t i = 0; - for(vertex_descriptor v : vertices(sm)) - { - Point_ref p = get(vpm, v); - mat.set_coef(i, 0, CGAL::to_double(p.x())); - mat.set_coef(i, 1, CGAL::to_double(p.y())); - mat.set_coef(i, 2, CGAL::to_double(p.z())); - ++i; - } -} - -template -double calculate_volume(const std::vector& points) -{ - typedef CGAL::Exact_predicates_inexact_constructions_kernel K; - - CGAL::Bbox_3 bbox = bbox_3(points.begin(), points.end()); - K::Iso_cuboid_3 ic(bbox); - return ic.volume(); -} - -// it is called after post processing in debug only -template -void matrix_to_mesh_and_draw(Matrix& data_points, std::string filename) -{ - typedef CGAL::Simple_cartesian K; - typedef K::Point_3 Point; - typedef CGAL::Surface_mesh Mesh; - - // Simplex -> std::vector - std::vector points; - - for(int i = 0; i < data_points.rows(); ++i) - { - Point p(data_points(i, 0), data_points(i, 1), data_points(i, 2)); - points.push_back(p); + return Matrix(mat.eigen_object().transpose()); } - Mesh mesh; - CGAL::make_hexahedron(points[0], points[1], points[2], points[3], - points[4], points[5], points[6], points[7], mesh); + /// Get the determinant of a `Matrix` matrix + FT determinant(const Matrix& matrix) const + { + return matrix.eigen_object().determinant(); + } - std::ofstream out(filename); - out << mesh; - out.close(); -} + /// Performs QR decomposition of matrix A to a unitary matrix and an upper triagonal + /// and returns the unitary matrix. + Matrix qr_factorization(const Matrix& A) const + { + Eigen::HouseholderQR qr(A.eigen_object()); + CGAL_assertion(CGAL::abs(determinant(Matrix(EigenType(qr.householderQ()))) - 1.) < 0.000001); + + return Matrix(EigenType(qr.householderQ())); + } +}; +#endif } // end namespace Optimal_bounding_box } // end namespace CGAL diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h index 65233767b77..c3b42b0d671 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h @@ -1,188 +1,160 @@ -// Copyright (c) 2018 GeometryFactory (France). +// Copyright (c) 2018-2019 GeometryFactory (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// // // Author(s) : Konstantinos Katrioplas - +// Mael Rouxel-Labbé +// #ifndef CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H #define CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H -#include #include -#include +#include -#include +#include +#include namespace CGAL { namespace Optimal_bounding_box { -template -const Matrix reflection(const Matrix& S_centroid, - const Matrix& S_worst) +template +Matrix reflection(const Matrix& S_centroid, + const Matrix& S_worst, + const Traits& traits) { - CGAL_assertion(S_centroid.rows() == 3); - CGAL_assertion(S_centroid.rows() == 3); - CGAL_assertion(S_worst.cols() == 3); - CGAL_assertion(S_worst.cols() == 3); + CGAL_assertion(S_centroid.number_of_rows() == 3 && S_centroid.number_of_columns() == 3); + CGAL_assertion(S_worst.number_of_rows() == 3 && S_worst.number_of_columns() == 3); - return S_centroid * Linear_algebra_traits::transpose(S_worst) * S_centroid; + return S_centroid * traits.transpose(S_worst) * S_centroid; } -template -const Matrix expansion(const Matrix& S_centroid, - const Matrix& S_worst, - const Matrix& S_reflection) +template +Matrix expansion(const Matrix& S_centroid, + const Matrix& S_worst, + const Matrix& S_reflection, + const Traits& traits) { - CGAL_assertion(S_centroid.rows() == 3); - CGAL_assertion(S_centroid.rows() == 3); - CGAL_assertion(S_worst.cols() == 3); - CGAL_assertion(S_worst.cols() == 3); - CGAL_assertion(S_reflection.cols() == 3); - CGAL_assertion(S_reflection.cols() == 3); + CGAL_assertion(S_centroid.number_of_rows() == 3 && S_centroid.number_of_columns() == 3); + CGAL_assertion(S_worst.number_of_rows() == 3 && S_worst.number_of_columns() == 3); + CGAL_assertion(S_reflection.number_of_rows() == 3 && S_reflection.number_of_columns() == 3); - return S_centroid * Linear_algebra_traits::transpose(S_worst) * S_reflection; + return S_centroid * traits.transpose(S_worst) * S_reflection; } -template +template Matrix mean(const Matrix& m1, - const Matrix& m2) + const Matrix& m2, + const Traits& traits) { // same API for reduction - CGAL_assertion(m1.rows() == 3); - CGAL_assertion(m1.rows() == 3); - CGAL_assertion(m2.cols() == 3); - CGAL_assertion(m2.cols() == 3); + CGAL_assertion(m1.number_of_rows() == 3 && m1.number_of_columns() == 3); + CGAL_assertion(m2.number_of_rows() == 3 && m2.number_of_columns() == 3); - Matrix reduction = 0.5 * m1 + 0.5 * m2; - Matrix Q = Linear_algebra_traits::qr_factorization(reduction); - double det = Linear_algebra_traits::determinant(Q); - return Q / det; + const Matrix reduction = 0.5 * m1 + 0.5 * m2; + const Matrix Q = traits.qr_factorization(reduction); + const typename Traits::FT det = traits.determinant(Q); + + return (1. / det) * Q; } -template +template const Matrix nm_centroid(const Matrix& S1, const Matrix& S2, - const Matrix& S3) + const Matrix& S3, + const Traits& traits) { - Matrix mean = (S1 + S2 + S3) / 3.0; - Matrix Q = Linear_algebra_traits::qr_factorization(mean); - double det = Linear_algebra_traits::determinant(Q); - return Q / det; + const Matrix mean = (1./3.) * (S1 + S2 + S3); + const Matrix Q = traits.qr_factorization(mean); + const typename Traits::FT det = traits.determinant(Q); + + return (1. / det) * Q; } -// needed in nelder mead algorithm -struct Comparator +// It's a 3D simplex with 4 rotation matrices as vertices +template +void nelder_mead(Simplex& simplex, + const PointRange& points, + const std::size_t nelder_mead_iterations, + const Traits& traits) { - Comparator(const std::vector& in) : fitness(in) { } + typedef typename Traits::FT FT; + typedef typename Traits::Matrix Matrix; - inline bool operator() (std::size_t& i, std::size_t& j) { - return fitness[i] < fitness[j]; - } + std::array fitness; + std::array indices = {{ 0, 1, 2, 3 }}; - const std::vector& fitness; -}; - -// simplex: 4 rotation matrices are its vertices -template -void nelder_mead(std::vector& simplex, - const typename Linear_algebra_traits::MatrixXd& point_data, - std::size_t nelder_mead_iterations) -{ - CGAL_assertion(simplex.size() == 4); // tetrahedron - - - typedef typename Linear_algebra_traits::Matrix3d Matrix3d; - - std::vector fitness(4); - std::vector indices(boost::counting_iterator(0), - boost::counting_iterator(simplex.size())); - - for(std::size_t t = 0; t < nelder_mead_iterations; ++t) + for(std::size_t t=0; t(simplex[i], point_data); - } - - CGAL_assertion(fitness.size() == 4); - CGAL_assertion(indices.size() == 4); + fitness[i] = compute_fitness(simplex[i], points); // get indices of sorted sequence - Comparator compare_indices(fitness); // @todo lambda this stuff - std::sort(indices.begin(), indices.end(), compare_indices); + std::sort(indices.begin(), indices.end(), + [&fitness](const std::size_t i, const std::size_t j) -> bool + { return fitness[i] < fitness[j]; }); // new sorted simplex & fitness - std::vector s_simplex(4); - std::vector s_fitness(4); - for(int i = 0; i < 4; ++i) + Simplex s_simplex; + std::array s_fitness; + for(int i=0; i<4; ++i) { s_simplex[i] = simplex[indices[i]]; s_fitness[i] = fitness[indices[i]]; } - simplex = s_simplex; - fitness = s_fitness; + simplex = std::move(s_simplex); + fitness = std::move(s_fitness); // centroid - const Matrix3d v_centroid = nm_centroid(simplex[0], simplex[1], simplex[2]); + const Matrix v_centroid = nm_centroid(simplex[0], simplex[1], simplex[2], traits); // find worst's vertex reflection - const Matrix3d v_worst = simplex[3]; - const Matrix3d v_refl = reflection(v_centroid, v_worst); - const double f_refl = compute_fitness(v_refl, point_data); + const Matrix& v_worst = simplex[3]; + const Matrix v_refl = reflection(v_centroid, v_worst, traits); + const FT f_refl = compute_fitness(v_refl, points); if(f_refl < fitness[2]) { if(f_refl >= fitness[0]) // if reflected point is not better than the best { - // do reflection - simplex[3] = v_refl; + // reflection + simplex[3] = std::move(v_refl); } else { // expansion - const Matrix3d v_expand = expansion(v_centroid, v_worst, v_refl); - const double f_expand = compute_fitness(v_expand, point_data); + const Matrix v_expand = expansion(v_centroid, v_worst, v_refl, traits); + const FT f_expand = compute_fitness(v_expand, points); if(f_expand < f_refl) - simplex[3] = v_expand; + simplex[3] = std::move(v_expand); else - simplex[3] = v_refl; + simplex[3] = std::move(v_refl); } } else // if reflected vertex is not better { - const Matrix3d v_mean = mean(v_centroid, v_worst); - const double f_mean = compute_fitness(v_mean, point_data); + const Matrix v_mean = mean(v_centroid, v_worst, traits); + const FT f_mean = compute_fitness(v_mean, points); if(f_mean <= fitness[3]) + { // contraction of worst - simplex[3] = v_mean; + simplex[3] = std::move(v_mean); + } else { // reduction: move all vertices towards the best for(std::size_t i=1; i<4; ++i) - { - simplex[i] = mean(simplex[i], simplex[0]); - } + simplex[i] = mean(simplex[i], simplex[0], traits); } } - - CGAL_assertion(simplex.size() == 4); // tetrahedron - } // iterations + } // nelder mead iterations } } // end namespace Optimal_bounding_box diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h index 3900ce6cc1b..ec2202781bc 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h @@ -1,24 +1,16 @@ -// Copyright (c) 2018 GeometryFactory (France). +// Copyright (c) 2018-2019 GeometryFactory (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Konstantinos Katrioplas - +// Mael Rouxel-Labbé +// #ifndef CGAL_OPTIMAL_BOUNDING_BOX_OBB_H #define CGAL_OPTIMAL_BOUNDING_BOX_OBB_H @@ -26,122 +18,88 @@ #include #include +#include // @tmp +#include + #include #include #include #include #include #include +#include #include #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS -#include -#endif - -#if defined(CGAL_EIGEN3_ENABLED) -#include +#include #endif +#include #include #include +#include #include namespace CGAL { namespace Optimal_bounding_box { +namespace internal { // works on matrices only -/// \cond SKIP_IN_MANUAL -template -void post_processing(const Matrix& points, - Vertex& R, - Matrix& obb) +template +void post_processing(const typename Traits::Matrix& R, + std::array& obb, + const PointRange& points, + const Traits& traits) { - CGAL_assertion(points.cols() == 3); - CGAL_assertion(R.rows() == 3); - CGAL_assertion(R.cols() == 3); - CGAL_assertion(obb.rows() == 8); - CGAL_assertion(obb.cols() == 3); + typedef typename Traits::FT FT; + typedef typename Traits::Point_3 Point; + typedef typename Traits::Matrix Matrix; - // 1) rotate points with R - Matrix rotated_points(points.rows(), points.cols()); - rotated_points = points * Linear_algebra_traits::transpose(R); + CGAL_assertion(R.number_of_rows() == 3 && R.number_of_columns() == 3); - // 2) get AABB from rotated points - typedef CGAL::Simple_cartesian K; - typedef K::Point_3 Point; - typedef typename Linear_algebra_traits::Index index; + const Matrix Rt = traits.transpose(R); - // Simplex -> std::vector - std::vector v_points; - for(index i=0; i(rotated_points.rows()); ++i) - { - Point p(rotated_points(i, 0), rotated_points(i, 1), rotated_points(i, 2)); - v_points.push_back(p); - } CGAL::Bbox_3 bbox; - bbox = bbox_3(v_points.begin(), v_points.end()); - K::Iso_cuboid_3 ic(bbox); - - Matrix aabb(8, 3); - for(std::size_t i = 0; i<8; ++i) + for(const Point& pt : points) { - aabb.set_coef(i, 0, ic[i].x()); - aabb.set_coef(i, 1, ic[i].y()); - aabb.set_coef(i, 2, ic[i].z()); + // @fixme should it be R here Rt at the other one... ? + const FT x = pt.x(), y = pt.y(), z = pt.z(); + Point rotated_pt(x*R(0, 0) + y*R(0, 1) + z*R(0, 2), + x*R(1, 0) + y*R(1, 1) + z*R(1, 2), + x*R(2, 0) + y*R(2, 1) + z*R(2, 2)); + + bbox += traits.construct_bbox_3_object()(rotated_pt); } + // @todo could avoid building a cuboid + typename Traits::Iso_cuboid_3 ic(bbox); + // 3) apply inverse rotation to rotated AABB - obb = aabb * R; + for(std::size_t i = 0; i<8; ++i) + { + const FT x = ic[i].x(), y = ic[i].y(), z = ic[i].z(); + obb[i] = Point(x*Rt(0, 0) + y*Rt(0, 1) + z*Rt(0, 2), + x*Rt(1, 0) + y*Rt(1, 1) + z*Rt(1, 2), + x*Rt(2, 0) + y*Rt(2, 1) + z*Rt(2, 2)); + } } -/// \endcond -/// \ingroup OBB_grp -/// calculates the optimal bounding box. -/// -/// @tparam Point the point type -/// @tparam LinearAlgebraTraits a model of `LinearAlgebraTraits`. If no instance of `LinearAlgebraTraits` -/// is provided, then `CGAL::Eigen_linear_algebra_traits` is used. -/// -/// @param points the input points that are included in the optimal bounding box. -/// @param obb_points the eight points of the optimal bounding box to be calculated. -/// @param use_ch a bool flag to indicating whether to use the convex hull of the input points -/// as an optimization step. -template -void compute_optimal_bounding_box(const std::vector& points, - std::vector& obb_points, - LinearAlgebraTraits&, - bool use_ch) +template +void construct_optimal_bounding_box(std::array& obb_points, + const PointRange& points, + CGAL::Random& rng, + const Traits& traits) { - CGAL_assertion(points.size() >= 3); + typedef typename Traits::Matrix Matrix; - if(obb_points.size() != 8) - obb_points.resize(8); - - // eigen linear algebra traits - typedef typename LinearAlgebraTraits::MatrixXd MatrixXd; - typedef typename LinearAlgebraTraits::Matrix3d Matrix3d; - MatrixXd points_mat; - - if(use_ch) // get the ch3 - { - std::vector ch_points; - CGAL::extreme_points_3(points, std::back_inserter(ch_points)); - CGAL::Optimal_bounding_box::fill_matrix(ch_points, points_mat); - } - else - { - CGAL::Optimal_bounding_box::fill_matrix(points, points_mat); - } - - std::size_t max_generations = 100; - Population pop(50); + const std::size_t max_generations = 100; #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS - CGAL::Timer timer; + CGAL::Real_timer timer; timer.start(); #endif - CGAL::Optimal_bounding_box::Evolution search_solution(pop, points_mat); + Evolution search_solution(points, rng, traits); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS std::cout << "constructor: " << timer.time() << std::endl; @@ -155,105 +113,163 @@ void compute_optimal_bounding_box(const std::vector& points, timer.reset(); #endif - Matrix3d rotation = search_solution.get_best(); + const Matrix& rotation = search_solution.get_best(); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS std::cout << "get best: " << timer.time() << std::endl; #endif - MatrixXd obb; // may be preallocated at compile time - obb.resize(8, 3); - #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS timer.reset(); #endif - post_processing(points_mat, rotation, obb); + post_processing(rotation, obb_points, points, traits); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS std::cout << "post porcessing: " << timer.time() << std::endl; #endif - - // matrix -> vector - for(std::size_t i=0; i<8; ++i) - obb_points.emplace(obb_points.begin() + i, obb(i, 0), obb(i, 1), obb(i, 2)); } -template -void compute_optimal_bounding_box(const std::vector& points, - std::vector& obb_points, - bool use_ch) +template +void construct_optimal_bounding_box(std::array& obb_points, + const bool use_ch, + const PointRange& points, + CGAL::Random& rng, + const Traits& traits) { -#if defined(CGAL_EIGEN3_ENABLED) - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; -#else - #pragma message("Error: You must either provide linear traits or link CGAL with the Eigen library") - Linear_algebra_traits; // no parameter provided, and Eigen is not enabled --> don't compile! -#endif + typedef typename Traits::Matrix Matrix; + typedef typename Traits::Point_3 Point; - Linear_algebra_traits la_traits; - compute_optimal_bounding_box(points, obb_points, la_traits, use_ch); + CGAL_static_assertion((std::is_same::type, Point>::value)); + + if(use_ch) // construct the convex hull to reduce the number of points + { + std::vector ch_points; + extreme_points_3(points, std::back_inserter(ch_points)); + return construct_optimal_bounding_box(obb_points, ch_points, rng, traits); + } + else + { + return construct_optimal_bounding_box(obb_points, points, rng, traits); + } } +} // namespace Optimal_bounding_box +} // namespace internal + /// \ingroup OBB_grp /// calculates the optimal bounding box. /// -/// @tparam PolygonMesh a model of `FaceListGraph` -/// @tparam LinearAlgebraTraits a model of `LinearAlgebraTraits`. If no instance of `LinearAlgebraTraits` -/// is provided, then `CGAL::Eigen_linear_algebra_traits` is used. +/// \tparam PointRange a model of `Range` with value type `Point` +/// \tparam NamedParameters /// -/// @param pmesh the input mesh. -/// @param obbmesh the hexaedron mesh to be built out of the optimal bounding box. -/// @param la_traits an instance of the linear algebra traits. -/// @param use_ch a bool flag to indicating whether to use the convex hull of the input points -/// as an optimization step. -template -void compute_optimal_bounding_box(const PolygonMesh& pmesh, - PolygonMesh& obbmesh, - LinearAlgebraTraits& la_traits, - bool use_ch) +/// \param points the input points that are included in the optimal bounding box. +/// \param obb_points the eight points of the optimal bounding box to be calculated. +/// +template +void optimal_bounding_box(const PointRange& points, + std::array& obb_points, + const CGAL_PMP_NP_CLASS& np) { + using CGAL::parameters::choose_parameter; + using CGAL::parameters::get_parameter; + +#if 0 // @fixme + typedef typename GetSvdTraits::type SVD_traits; + CGAL_static_assertion_msg( + !(std::is_same::NoTraits>::value), + "Error: must provide traits or enable Eigen"); + + const SVD_traits traits = choose_parameter(get_parameter(np, svd_traits), SVD_traits()); +#else + typedef typename CGAL::Kernel_traits::type K; + typedef Optimal_bounding_box::Optimal_bounding_box_traits Traits; + Traits traits; +#endif + + // @fixme + const bool use_ch = true; //choose_parameter(get_parameter(np, internal_np::use_convex_hull), false); + unsigned int seed = choose_parameter(get_parameter(np, internal_np::random_seed), 0); + + CGAL::Random rng(seed); + + return Optimal_bounding_box::internal::construct_optimal_bounding_box(obb_points, use_ch, points, rng, traits); +} + +template +void optimal_bounding_box(const PolygonMesh& pmesh, + std::array& obb_mesh) +{ + return optimal_bounding_box(pmesh, obb_mesh, CGAL::parameters::all_default()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// With polygon meshes +///////////////////////////////////////////////////////////////////////////////////////////////// + +/// \ingroup OBB_grp +/// calculates the optimal bounding box. +/// +/// \tparam PolygonMesh a model of `FaceListGraph` +/// \tparam NamedParameters +/// +/// \param pmesh the input mesh. +/// \param obb_mesh the hexaedron mesh to be built out of the optimal bounding box. +/// +template +void optimal_bounding_box(const PolygonMesh& pmesh, + PolygonMesh& obb_mesh, + const CGAL_PMP_NP_CLASS& np) +{ + namespace PMP = CGAL::Polygon_mesh_processing; + + using CGAL::parameters::choose_parameter; + using CGAL::parameters::get_parameter; + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + + typedef typename PMP::GetVertexPointMap::const_type VPM; + typedef typename boost::property_traits::value_type Point; + CGAL_assertion(vertices(pmesh).size() >= 3); if(vertices(pmesh).size() <= 3) { - std::cerr << "Not enough points in the mesh!\n"; + // @fixme is that even true + std::cerr << "The optimal bounding box cannot be computed for a mesh with fewer than 4 vertices!\n"; return; } - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::property_map::type Vpm; - typedef typename boost::property_traits::value_type Point; + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(vertex_point, pmesh)); std::vector points; - Vpm pmap = get(boost::vertex_point, pmesh); - for(vertex_descriptor v : vertices(pmesh)) - points.push_back(get(pmap, v)); + points.reserve(num_vertices(pmesh)); - std::vector obb_points; - compute_optimal_bounding_box(points, obb_points, la_traits, use_ch); + for(vertex_descriptor v : vertices(pmesh)) + points.push_back(get(vpm, v)); + + std::array obb_points; + optimal_bounding_box(points, obb_points, np); CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], - obb_points[4], obb_points[5], obb_points[6], obb_points[7], obbmesh); + obb_points[4], obb_points[5], obb_points[6], obb_points[7], obb_mesh); } +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// Convenience overloads for polygon meshes +///////////////////////////////////////////////////////////////////////////////////////////////// + template -void compute_optimal_bounding_box(const PolygonMesh& pmesh, - PolygonMesh& obbmesh, - bool use_ch) +void optimal_bounding_box(const PolygonMesh& pmesh, + PolygonMesh& obb_mesh) { -#if defined(CGAL_EIGEN3_ENABLED) - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; -#else - #pragma message("Error: You must either provide linear traits or link CGAL with the Eigen library") - Linear_algebra_traits; // no parameter provided, and Eigen is not enabled --> don't compile! -#endif - - Linear_algebra_traits la_traits; - compute_optimal_bounding_box(pmesh, obbmesh, la_traits, use_ch); + return optimal_bounding_box(pmesh, obb_mesh, CGAL::parameters::all_default()); } -} // end namespace Optimal_bounding_box } // end namespace CGAL #endif // CGAL_OPTIMAL_BOUNDING_BOX_OBB_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h index 704c2834d35..cd8acaf702d 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h @@ -1,113 +1,87 @@ -// Copyright (c) 2018 GeometryFactory (France). +// Copyright (c) 2018-2019 GeometryFactory (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Konstantinos Katrioplas - +// Mael Rouxel-Labbé +// #ifndef CGAL_OPTIMAL_BOUNDING_BOX_POPULATION_H #define CGAL_OPTIMAL_BOUNDING_BOX_POPULATION_H #include #include +#include #include namespace CGAL { namespace Optimal_bounding_box { -template +template class Population { - typedef typename Linear_algebra_traits::Matrix3d Matrix; - typedef std::vector Simplex; - public: - Population(std::size_t size) - : - n(size), - random_generator(CGAL::Random()) - { - // reserve pop space - pop.reserve(n); + typedef typename Traits::FT FT; + typedef typename Traits::Matrix Matrix; + typedef Matrix Vertex; - // create simplices - for(std::size_t i=0 ; i Simplex; + typedef std::vector Simplex_container; + +private: + Matrix create_vertex(CGAL::Random& rng) const + { + Matrix R; + + for(std::size_t i=0; i<3; ++i) + for(std::size_t j=0; j<3; ++j) + R.set(i, j, FT(rng.get_double())); + + return R; } + // create random population + Simplex create_simplex(CGAL::Random& rng) const + { + Simplex simplex; + for(std::size_t i=0; i<4; ++i) + simplex[i] = m_traits.qr_factorization(create_vertex(rng)); + + return simplex; + } + +public: + Population(const Traits& traits) : m_traits(traits) { } + + void initialize(std::size_t population_size, + CGAL::Random& rng) + { + m_pop.clear(); + m_pop.reserve(population_size); + for(std::size_t i=0; i pop; + std::vector m_pop; + const Traits& m_traits; }; #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG @@ -115,15 +89,11 @@ template void Population::show_population() { std::size_t id = 0; - for(const Simplex& i : pop) + for(const Simplex& simplex : m_pop) { - CGAL_assertion(i.size() == 4); - std:: cout << "Simplex: "<< id++ << std::endl; - for(const Matrix& R : i) - { - std::cout << R; // eigen out - std::cout << "\n\n"; - } + std::cout << "Simplex: " << id++ << std::endl; + for(const Matrix& R : simplex) + std::cout << R << "\n\n"; std:: cout << std:: endl; } } diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 28c21b3a784..fd8eb60b8f0 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -21,13 +21,12 @@ bool assert_doubles(double d1, double d2, double epsilon) void test_nelder_mead() { typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - typedef Linear_algebra_traits::Matrix3d Matrix3d; - typedef Linear_algebra_traits::MatrixXd MatrixXd; + typedef Linear_algebra_traits::Matrix Matrix; - MatrixXd data_points(4,3); + Matrix data_points(4,3); data_points(0,0) = 0.866802; - data_points(0,1) = 0.740808, - data_points(0,2) = 0.895304, + data_points(0,1) = 0.740808; + data_points(0,2) = 0.895304; data_points(1,0) = 0.912651; data_points(1,1) = 0.761565; data_points(1,2) = 0.160330; @@ -35,19 +34,19 @@ void test_nelder_mead() data_points(2,1) = 0.892578; data_points(2,2) = 0.737412; data_points(3,0) = 0.166461; - data_points(3,1) = 0.149912, + data_points(3,1) = 0.149912; data_points(3,2) = 0.364944; // one simplex - std::vector simplex(4); - Matrix3d v0(3,3); - Matrix3d v1(3,3); - Matrix3d v2(3,3); - Matrix3d v3(3,3); + std::vector simplex(4); + Matrix v0(3,3); + Matrix v1(3,3); + Matrix v2(3,3); + Matrix v3(3,3); v0(0,0) = -0.2192721; - v0(0,1) = 0.2792986, - v0(0,2) = -0.9348326, + v0(0,1) = 0.2792986; + v0(0,2) = -0.9348326; v0(1,0) = -0.7772152; v0(1,1) = -0.6292092; v0(1,2) = -0.0056861; @@ -93,58 +92,58 @@ void test_nelder_mead() std::size_t nm_iterations = 19; CGAL::Optimal_bounding_box::nelder_mead(simplex, data_points, nm_iterations); - CGAL_assertion_code(double epsilon = 1e-5); - CGAL_assertion_code(Matrix3d v0_new = simplex[0]); - CGAL_assertion(assert_doubles(v0_new(0,0), -0.288975, epsilon)); - CGAL_assertion(assert_doubles(v0_new(0,1), 0.7897657, epsilon)); - CGAL_assertion(assert_doubles(v0_new(0,2), -0.541076, epsilon)); - CGAL_assertion(assert_doubles(v0_new(1,0), -0.9407046, epsilon)); - CGAL_assertion(assert_doubles(v0_new(1,1), -0.3391466, epsilon)); - CGAL_assertion(assert_doubles(v0_new(1,2), 0.0073817, epsilon)); - CGAL_assertion(assert_doubles(v0_new(2,0), -0.1776743, epsilon)); - CGAL_assertion(assert_doubles(v0_new(2,1), 0.5111260, epsilon)); - CGAL_assertion(assert_doubles(v0_new(2,2), 0.84094, epsilon)); + double epsilon = 1e-5; + const Matrix& v0_new = simplex[0]; + assert(assert_doubles(v0_new(0,0), -0.288975, epsilon)); + assert(assert_doubles(v0_new(0,1), 0.7897657, epsilon)); + assert(assert_doubles(v0_new(0,2), -0.541076, epsilon)); + assert(assert_doubles(v0_new(1,0), -0.9407046, epsilon)); + assert(assert_doubles(v0_new(1,1), -0.3391466, epsilon)); + assert(assert_doubles(v0_new(1,2), 0.0073817, epsilon)); + assert(assert_doubles(v0_new(2,0), -0.1776743, epsilon)); + assert(assert_doubles(v0_new(2,1), 0.5111260, epsilon)); + assert(assert_doubles(v0_new(2,2), 0.84094, epsilon)); - CGAL_assertion_code(Matrix3d v1_new = simplex[1]); - CGAL_assertion(assert_doubles(v1_new(0,0), -0.458749, epsilon)); - CGAL_assertion(assert_doubles(v1_new(0,1), 0.823283, epsilon)); - CGAL_assertion(assert_doubles(v1_new(0,2), -0.334296, epsilon)); - CGAL_assertion(assert_doubles(v1_new(1,0), -0.885235, epsilon)); - CGAL_assertion(assert_doubles(v1_new(1,1), -0.455997, epsilon)); - CGAL_assertion(assert_doubles(v1_new(1,2), 0.091794, epsilon)); - CGAL_assertion(assert_doubles(v1_new(2,0), -0.076866, epsilon)); - CGAL_assertion(assert_doubles(v1_new(2,1), 0.338040, epsilon)); - CGAL_assertion(assert_doubles(v1_new(2,2), 0.937987, epsilon)); + const Matrix& v1_new = simplex[1]; + assert(assert_doubles(v1_new(0,0), -0.458749, epsilon)); + assert(assert_doubles(v1_new(0,1), 0.823283, epsilon)); + assert(assert_doubles(v1_new(0,2), -0.334296, epsilon)); + assert(assert_doubles(v1_new(1,0), -0.885235, epsilon)); + assert(assert_doubles(v1_new(1,1), -0.455997, epsilon)); + assert(assert_doubles(v1_new(1,2), 0.091794, epsilon)); + assert(assert_doubles(v1_new(2,0), -0.076866, epsilon)); + assert(assert_doubles(v1_new(2,1), 0.338040, epsilon)); + assert(assert_doubles(v1_new(2,2), 0.937987, epsilon)); - CGAL_assertion_code(Matrix3d v2_new = simplex[2]); - CGAL_assertion(assert_doubles(v2_new(0,0), -0.346582, epsilon)); - CGAL_assertion(assert_doubles(v2_new(0,1), 0.878534, epsilon)); - CGAL_assertion(assert_doubles(v2_new(0,2), -0.328724, epsilon)); - CGAL_assertion(assert_doubles(v2_new(1,0), -0.936885, epsilon)); - CGAL_assertion(assert_doubles(v2_new(1,1), -0.341445, epsilon)); - CGAL_assertion(assert_doubles(v2_new(1,2), 0.075251, epsilon)); - CGAL_assertion(assert_doubles(v2_new(2,0), -0.046131, epsilon)); - CGAL_assertion(assert_doubles(v2_new(2,1), 0.334057, epsilon)); - CGAL_assertion(assert_doubles(v2_new(2,2), 0.941423, epsilon)); + const Matrix& v2_new = simplex[2]; + assert(assert_doubles(v2_new(0,0), -0.346582, epsilon)); + assert(assert_doubles(v2_new(0,1), 0.878534, epsilon)); + assert(assert_doubles(v2_new(0,2), -0.328724, epsilon)); + assert(assert_doubles(v2_new(1,0), -0.936885, epsilon)); + assert(assert_doubles(v2_new(1,1), -0.341445, epsilon)); + assert(assert_doubles(v2_new(1,2), 0.075251, epsilon)); + assert(assert_doubles(v2_new(2,0), -0.046131, epsilon)); + assert(assert_doubles(v2_new(2,1), 0.334057, epsilon)); + assert(assert_doubles(v2_new(2,2), 0.941423, epsilon)); - CGAL_assertion_code(Matrix3d v3_new = simplex[3]); - CGAL_assertion(assert_doubles(v3_new(0,0), -0.394713, epsilon)); - CGAL_assertion(assert_doubles(v3_new(0,1), 0.791782, epsilon)); - CGAL_assertion(assert_doubles(v3_new(0,2), -0.466136, epsilon)); - CGAL_assertion(assert_doubles(v3_new(1,0), -0.912112, epsilon)); - CGAL_assertion(assert_doubles(v3_new(1,1), -0.398788, epsilon)); - CGAL_assertion(assert_doubles(v3_new(1,2), 0.094972, epsilon)); - CGAL_assertion(assert_doubles(v3_new(2,0), -0.110692, epsilon)); - CGAL_assertion(assert_doubles(v3_new(2,1), 0.462655, epsilon)); - CGAL_assertion(assert_doubles(v3_new(2,2), 0.879601, epsilon)); + const Matrix& v3_new = simplex[3]; + assert(assert_doubles(v3_new(0,0), -0.394713, epsilon)); + assert(assert_doubles(v3_new(0,1), 0.791782, epsilon)); + assert(assert_doubles(v3_new(0,2), -0.466136, epsilon)); + assert(assert_doubles(v3_new(1,0), -0.912112, epsilon)); + assert(assert_doubles(v3_new(1,1), -0.398788, epsilon)); + assert(assert_doubles(v3_new(1,2), 0.094972, epsilon)); + assert(assert_doubles(v3_new(2,0), -0.110692, epsilon)); + assert(assert_doubles(v3_new(2,1), 0.462655, epsilon)); + assert(assert_doubles(v3_new(2,2), 0.879601, epsilon)); } void test_genetic_algorithm() { CGAL::Eigen_dense_matrix data_points(4, 3); // -1 = dynamic size at run time data_points(0,0) = 0.866802; - data_points(0,1) = 0.740808, - data_points(0,2) = 0.895304, + data_points(0,1) = 0.740808; + data_points(0,2) = 0.895304; data_points(1,0) = 0.912651; data_points(1,1) = 0.761565; data_points(1,2) = 0.160330; @@ -152,14 +151,14 @@ void test_genetic_algorithm() data_points(2,1) = 0.892578; data_points(2,2) = 0.737412; data_points(3,0) = 0.166461; - data_points(3,1) = 0.149912, + data_points(3,1) = 0.149912; data_points(3,2) = 0.364944; typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; CGAL::Optimal_bounding_box::Population pop(5); CGAL::Optimal_bounding_box::Evolution evolution(pop, data_points); evolution.genetic_algorithm(); - CGAL_assertion(pop.size() == 5); + assert(pop.size() == 5); } void test_random_unit_tetra() @@ -169,8 +168,8 @@ void test_random_unit_tetra() // points are on their convex hull data_points(0,0) = 0.866802; - data_points(0,1) = 0.740808, - data_points(0,2) = 0.895304, + data_points(0,1) = 0.740808; + data_points(0,2) = 0.895304; data_points(1,0) = 0.912651; data_points(1,1) = 0.761565; data_points(1,2) = 0.160330; @@ -178,7 +177,7 @@ void test_random_unit_tetra() data_points(2,1) = 0.892578; data_points(2,2) = 0.737412; data_points(3,0) = 0.166461; - data_points(3,1) = 0.149912, + data_points(3,1) = 0.149912; data_points(3,2) = 0.364944; typedef CGAL::Simple_cartesian K; @@ -199,31 +198,31 @@ void test_random_unit_tetra() out.close(); #endif - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - CGAL_assertion_code(typedef Linear_algebra_traits::Matrix3d Matrix3d); + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + typedef Linear_algebra_traits::Matrix Matrix; + std::size_t generations = 10; CGAL::Optimal_bounding_box::Population pop(50); CGAL::Optimal_bounding_box::Evolution evolution(pop, data_points); evolution.evolve(generations); - CGAL_assertion_code(Matrix3d R = evolution.get_best()); - CGAL_assertion_code(double epsilon = 1e-3); - CGAL_assertion(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); - CGAL_assertion(assert_doubles(R(0,0), -0.25791, epsilon)); - CGAL_assertion(assert_doubles(R(0,1), 0.796512, epsilon)); - CGAL_assertion(assert_doubles(R(0,2), -0.546855, epsilon)); - CGAL_assertion(assert_doubles(R(1,0), -0.947128, epsilon)); - CGAL_assertion(assert_doubles(R(1,1), -0.320242, epsilon)); - CGAL_assertion(assert_doubles(R(1,2), -0.0197553, epsilon)); - CGAL_assertion(assert_doubles(R(2,0), -0.190861, epsilon)); - CGAL_assertion(assert_doubles(R(2,1), 0.512847, epsilon)); - CGAL_assertion(assert_doubles(R(2,2), 0.836992, epsilon)); + Matrix R = evolution.get_best(); + const double epsilon = 1e-3; + assert(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); + assert(assert_doubles(R(0,0), -0.25791, epsilon)); + assert(assert_doubles(R(0,1), 0.796512, epsilon)); + assert(assert_doubles(R(0,2), -0.546855, epsilon)); + assert(assert_doubles(R(1,0), -0.947128, epsilon)); + assert(assert_doubles(R(1,1), -0.320242, epsilon)); + assert(assert_doubles(R(1,2), -0.0197553, epsilon)); + assert(assert_doubles(R(2,0), -0.190861, epsilon)); + assert(assert_doubles(R(2,1), 0.512847, epsilon)); + assert(assert_doubles(R(2,2), 0.836992, epsilon)); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST // postprocessing CGAL::Eigen_dense_matrix obb(8, 3); CGAL::Optimal_bounding_box::post_processing(data_points, R, obb); - CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, "data/random_unit_tetra_result.off"); #endif } @@ -236,12 +235,11 @@ void test_reference_tetrahedron(const char* fname) std::exit(1); } - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - typedef Linear_algebra_traits::MatrixXd MatrixXd; - CGAL_assertion_code(typedef Linear_algebra_traits::Matrix3d Matrix3d); + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + typedef Linear_algebra_traits::Matrix Matrix; // points in a matrix - MatrixXd points; + Matrix points; CGAL::Optimal_bounding_box::sm_to_matrix(mesh, points); std::size_t generations = 10; @@ -249,33 +247,32 @@ void test_reference_tetrahedron(const char* fname) CGAL::Optimal_bounding_box::Evolution experiment(pop, points); experiment.evolve(generations); - CGAL_assertion_code(Matrix3d R = experiment.get_best()); - CGAL_assertion_code(double epsilon = 1e-5); - CGAL_assertion(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); + Matrix R = experiment.get_best(); + double epsilon = 1e-5; + assert(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); - #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST // postprocessing - MatrixXd obb(8, 3); + Matrix obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points, R, obb); - CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, "data/OBB.off"); - #endif +#endif } -void test_long_tetrahedron(std::string fname) +void test_long_tetrahedron(const std::string fname) { std::ifstream input(fname); CGAL::Surface_mesh mesh; - if (!input || !(input >> mesh) || mesh.is_empty()) { + if (!input || !(input >> mesh) || mesh.is_empty()) + { std::cerr << fname << " is not a valid off file.\n"; std::exit(1); } - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - typedef Linear_algebra_traits::MatrixXd MatrixXd; - CGAL_assertion_code(typedef Linear_algebra_traits::Matrix3d Matrix3d); + typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; + typedef Linear_algebra_traits::Matrix Matrix; // points in a matrix - MatrixXd points; + Matrix points; CGAL::Optimal_bounding_box::sm_to_matrix(mesh, points); std::size_t max_generations = 10; @@ -283,42 +280,45 @@ void test_long_tetrahedron(std::string fname) CGAL::Optimal_bounding_box::Evolution experiment(pop, points); experiment.evolve(max_generations); - CGAL_assertion_code(Matrix3d R = experiment.get_best()); - CGAL_assertion_code(double epsilon = 1e-3); - CGAL_assertion(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); - CGAL_assertion(assert_doubles(R(0,0), -1, epsilon)); - CGAL_assertion(assert_doubles(R(0,1), 0, epsilon)); - CGAL_assertion(assert_doubles(R(0,2), 0, epsilon)); - CGAL_assertion(assert_doubles(R(1,0), 0, epsilon)); - CGAL_assertion(assert_doubles(R(1,1), -0.707107, epsilon)); - CGAL_assertion(assert_doubles(R(1,2), 0.707106, epsilon) || - assert_doubles(R(1,2), -0.707106, epsilon)); - CGAL_assertion(assert_doubles(R(2,0), 0, epsilon)); - CGAL_assertion(assert_doubles(R(2,1), 0.707106, epsilon) || - assert_doubles(R(1,2), -0.707106, epsilon)); - CGAL_assertion(assert_doubles(R(2,2), 0.707107, epsilon)); + Matrix R = experiment.get_best(); + double epsilon = 1e-3; + assert(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); + assert(assert_doubles(R(0,0), -1, epsilon)); + assert(assert_doubles(R(0,1), 0, epsilon)); + assert(assert_doubles(R(0,2), 0, epsilon)); + assert(assert_doubles(R(1,0), 0, epsilon)); + assert(assert_doubles(R(1,1), -0.707107, epsilon)); + assert(assert_doubles(R(1,2), 0.707106, epsilon) || + assert_doubles(R(1,2), -0.707106, epsilon)); + assert(assert_doubles(R(2,0), 0, epsilon)); + assert(assert_doubles(R(2,1), 0.707106, epsilon) || + assert_doubles(R(1,2), -0.707106, epsilon)); + assert(assert_doubles(R(2,2), 0.707107, epsilon)); - #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST // postprocessing - MatrixXd obb(8, 3); + Matrix obb(8, 3); CGAL::Optimal_bounding_box::post_processing(points, R, obb); - CGAL::Optimal_bounding_box::matrix_to_mesh_and_draw(obb, fname + "result.off"); - #endif +#endif } -void test_compute_obb_evolution(std::string fname) +void test_compute_obb_evolution(const std::string fname) { std::ifstream input(fname); typedef CGAL::Surface_mesh SMesh; SMesh mesh; - if (!input || !(input >> mesh) || mesh.is_empty()) { + if (!input || !(input >> mesh) || mesh.is_empty()) + { std::cerr << fname << " is not a valid off file.\n"; std::exit(1); } + // get mesh points std::vector sm_points; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::property_map::const_type PointPMap; + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::property_map::const_type PointPMap; + PointPMap pmap = get(boost::vertex_point, mesh); for(vertex_descriptor v : vertices(mesh)) sm_points.push_back(get(pmap, v)); @@ -328,26 +328,26 @@ void test_compute_obb_evolution(std::string fname) std::vector obb_points; CGAL::Optimal_bounding_box::compute_optimal_bounding_box(sm_points, obb_points, la_traits, true); - CGAL_assertion_code(double epsilon = 1e-3); - CGAL_assertion_code(double vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points)); - CGAL_assertion(assert_doubles(vol, 0.883371, epsilon)); + double epsilon = 1e-3; + double vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points); + assert(assert_doubles(vol, 0.883371, epsilon)); - #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST /* for(int i = 0; i < 8; ++i) std::cout << obb_points[i].x() << " " << obb_points[i].y() << " " << obb_points[i].z() << "\n" ; */ CGAL::Surface_mesh result_mesh; CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], - obb_points[4], obb_points[5], obb_points[6], obb_points[7], result_mesh); + obb_points[4], obb_points[5], obb_points[6], obb_points[7], result_mesh); std::ofstream out("data/obb_result.off"); out << result_mesh; out.close(); - #endif +#endif } -void test_compute_obb_mesh(std::string fname) +void test_compute_obb_mesh(const std::string fname) { std::ifstream input(fname); CGAL::Surface_mesh mesh; @@ -361,14 +361,15 @@ void test_compute_obb_mesh(std::string fname) CGAL::Surface_mesh< K::Point_3> obbmesh; CGAL::Optimal_bounding_box::compute_optimal_bounding_box(mesh, obbmesh, la_traits, true); - #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST std::ofstream out("/tmp/result_elephant.off"); out << obbmesh; out.close(); - #endif +#endif } -void test_function_defaults_traits(std::string fname1, std::string fname2) +void test_function_defaults_traits(const std::string fname1, + const std::string fname2) { std::ifstream input1(fname1); CGAL::Surface_mesh mesh1; @@ -389,6 +390,7 @@ void test_function_defaults_traits(std::string fname1, std::string fname2) // test one std::vector sm_points; typedef CGAL::Surface_mesh SMesh; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::property_map::const_type PointPMap; PointPMap pmap = get(boost::vertex_point, mesh1); @@ -399,12 +401,12 @@ void test_function_defaults_traits(std::string fname1, std::string fname2) std::vector obb_points; CGAL::Optimal_bounding_box::compute_optimal_bounding_box(sm_points, obb_points, true); - CGAL_assertion_code(double epsilon = 1e-3); - CGAL_assertion_code(double vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points)); - CGAL_assertion(assert_doubles(vol, 0.883371, epsilon)); + const double epsilon = 1e-3; + const double vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points); + assert(assert_doubles(vol, 0.883371, epsilon)); // test two - CGAL::Surface_mesh< K::Point_3> obbmesh; + CGAL::Surface_mesh obbmesh; CGAL::Optimal_bounding_box::compute_optimal_bounding_box(mesh2, obbmesh, true); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt index d8ba5ededb3..5562e6680f8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/CMakeLists.txt @@ -18,7 +18,7 @@ polyhedron_demo_plugin(create_bbox_mesh_plugin Create_bbox_mesh_plugin) target_link_libraries(create_bbox_mesh_plugin PUBLIC scene_surface_mesh_item) polyhedron_demo_plugin(create_obb_mesh_plugin Create_obb_mesh_plugin) -target_link_libraries(create_obb_mesh_plugin PUBLIC scene_surface_mesh_item scene_polyhedron_item scene_polyhedron_selection_item scene_points_with_normal_item) +target_link_libraries(create_obb_mesh_plugin PUBLIC scene_surface_mesh_item scene_selection_item scene_points_with_normal_item) qt5_wrap_ui( volumesUI_FILES Basic_generator_widget.ui) polyhedron_demo_plugin(basic_generator_plugin Basic_generator_plugin ${volumesUI_FILES} KEYWORDS PolygonMesh PointSetProcessing) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp index 444f0b2acc9..41ed97b2727 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp @@ -1,29 +1,25 @@ #include + #include #include #include #include +#include #include #include "Scene_surface_mesh_item.h" -#include "Polyhedron_type.h" -#include "Scene_polyhedron_item.h" -#include #include "Scene_polyhedron_selection_item.h" #include "Scene_points_with_normal_item.h" -#include +#include + #include -#include -//typedef Scene_surface_mesh_item Scene_facegraph_item; -//typedef Scene_facegraph_item Scene_facegraph_item; - -typedef Scene_facegraph_item::Face_graph FaceGraph; -typedef Polyhedron::Point_3 Point_3; using namespace CGAL::Three; +typedef Scene_surface_mesh_item Scene_facegraph_item; + class Create_obb_mesh_plugin : public QObject, public CGAL::Three::Polyhedron_demo_plugin_interface @@ -36,36 +32,21 @@ public: void init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*); QList actions() const; - bool applicable(QAction*) const { - - /* - if (scene->selectionIndices().size() == 1) - { - return qobject_cast(scene->item(scene->mainSelectionIndex())) - || qobject_cast(scene->item(scene->mainSelectionIndex())); - } - - Q_FOREACH(int index, scene->selectionIndices()) - { - if (qobject_cast(scene->item(index))) - return true; - } - return false; - */ - + bool applicable(QAction*) const + { if(scene->mainSelectionIndex() != -1 && scene->item(scene->mainSelectionIndex())->isFinite()) return true; - return false; - -} + return false; + } protected: void gather_mesh_points(std::vector& points); void obb(); public Q_SLOTS: - void createObb() { + void createObb() + { QApplication::setOverrideCursor(Qt::WaitCursor); obb(); QApplication::restoreOverrideCursor(); @@ -75,11 +56,8 @@ private: Scene_interface* scene; QMainWindow* mw; QAction* actionObb; - }; // end Create_obb_mesh_plugin class - - void Create_obb_mesh_plugin::init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*) { scene = scene_interface; @@ -89,17 +67,16 @@ void Create_obb_mesh_plugin::init(QMainWindow* mainWindow, Scene_interface* scen connect(actionObb, SIGNAL(triggered()), this, SLOT(createObb())); } -QList Create_obb_mesh_plugin::actions() const { +QList Create_obb_mesh_plugin::actions() const +{ return QList() << actionObb; } - void Create_obb_mesh_plugin::gather_mesh_points(std::vector& points) { const Scene_interface::Item_id index = scene->mainSelectionIndex(); - Scene_facegraph_item* poly_item = - qobject_cast(scene->item(index)); + Scene_facegraph_item* item = qobject_cast(scene->item(index)); Scene_polyhedron_selection_item* selection_item = qobject_cast(scene->item(index)); @@ -107,7 +84,7 @@ void Create_obb_mesh_plugin::gather_mesh_points(std::vector& points) Scene_points_with_normal_item* point_set_item = qobject_cast(scene->item(index)); - if(poly_item || selection_item) + if(item || selection_item) { typedef typename boost::property_map::type PointPMap; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; @@ -115,30 +92,29 @@ void Create_obb_mesh_plugin::gather_mesh_points(std::vector& points) std::vector selected_vertices; - if(poly_item != NULL) + if(item != NULL) { - FaceGraph& pmesh = *poly_item->polyhedron(); + FaceGraph& pmesh = *item->polyhedron(); selected_vertices.assign(vertices(pmesh).begin(), vertices(pmesh).end()); PointPMap pmap = get(CGAL::vertex_point, pmesh); - BOOST_FOREACH(vertex_descriptor v, selected_vertices) + for(vertex_descriptor v : selected_vertices) points.push_back(get(pmap, v)); } else if(selection_item != NULL) // using selection of faces { FaceGraph& pmesh = *selection_item->polyhedron(); - BOOST_FOREACH(face_descriptor f, selection_item->selected_facets) + for(face_descriptor f : selection_item->selected_facets) { - BOOST_FOREACH(vertex_descriptor v, vertices_around_face(halfedge(f, pmesh), pmesh)) - { + for(vertex_descriptor v : vertices_around_face(halfedge(f, pmesh), pmesh)) selected_vertices.push_back(v); - } } PointPMap pmap = get(CGAL::vertex_point, pmesh); - BOOST_FOREACH(vertex_descriptor v, selected_vertices) + for(vertex_descriptor v : selected_vertices) points.push_back(get(pmap, v)); } + CGAL_assertion(points.size() >= 3); } @@ -149,12 +125,9 @@ void Create_obb_mesh_plugin::gather_mesh_points(std::vector& points) return; std::cout << "points_set->size()= " << points_set->size() << std::endl; - BOOST_FOREACH(Point_3 p, points_set->points()) - { + for(const Point_3& p : points_set->points()) points.push_back(p); - } } - } void Create_obb_mesh_plugin::obb() @@ -164,24 +137,14 @@ void Create_obb_mesh_plugin::obb() gather_mesh_points(points); // find obb - CGAL::Eigen_linear_algebra_traits la_traits; - std::vector obb_points(8); - CGAL::Optimal_bounding_box::compute_optimal_bounding_box(points, obb_points, la_traits, true); + std::array obb_points; + CGAL::optimal_bounding_box(points, obb_points); - Scene_item* item; - if(mw->property("is_polyhedorn_mode").toBool()) - { - Polyhedron* p = new Polyhedron; - CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], - obb_points[4], obb_points[5], obb_points[6], obb_points[7], *p); - item = new Scene_polyhedron_item(p); - } - else { - SMesh* p = new SMesh; - CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], - obb_points[4], obb_points[5], obb_points[6], obb_points[7], *p); - item = new Scene_surface_mesh_item(p); - } + Scene_facegraph_item* item; + SMesh* p = new SMesh; + CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], + obb_points[4], obb_points[5], obb_points[6], obb_points[7], *p); + item = new Scene_facegraph_item(p); item->setName("Optimal bbox mesh"); item->setRenderingMode(Wireframe); diff --git a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h b/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h deleted file mode 100644 index cc55ed70ef3..00000000000 --- a/Solver_interface/include/CGAL/Eigen_linear_algebra_traits.h +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright (c) 2018 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0+ -// -// -// Author(s) : Konstantinos Katrioplas - -#ifndef CGAL_EIGEN_LINEAR_ALGEBRA_TRAITS_H -#define CGAL_EIGEN_LINEAR_ALGEBRA_TRAITS_H - -#include -#include -#include - - -namespace CGAL { - - -template -class Eigen_dense_vector; - -/*! -\ingroup PkgSolver - -The class `Eigen_dense_matrix` is a wrapper around \ref thirdpartyEigen "Eigen" matrix type -`Eigen::DenseMatrix`. - -\tparam T Number type. -\tparam D1 Number of rows, or Dynamic. -\tparam D1 Number of cols, or Dynamic. - -\sa `CGAL::Eigen_dense_vector` -\sa `CGAL::Eigen_linear_algebra_traits` -*/ -template -class Eigen_dense_matrix -{ -public: - - /// The internal matrix type from \ref thirdpartyEigen "Eigen". - typedef Eigen::Matrix EigenType; - - /// Create a dense matrix - Eigen_dense_matrix(std::size_t nrows, std::size_t ncols) - : m_matrix(static_cast(nrows), static_cast(ncols)) - { - CGAL_assertion(m_matrix.rows() > 0); - CGAL_assertion(m_matrix.cols() > 0); - } - - /// Create a dense matrix - Eigen_dense_matrix(int nrows, int ncols) - : m_matrix(nrows, ncols) - { - CGAL_assertion(m_matrix.rows() > 0); - CGAL_assertion(m_matrix.cols() > 0); - } - - /// Create a dense matrix out of a \ref thirdpartyEigen "Eigen" matrix type - Eigen_dense_matrix(const EigenType& eigen_mat) - : m_matrix(eigen_mat) {} - - Eigen_dense_matrix() : m_matrix() {} - - /// Read access to a matrix coefficient. - /// - /// \pre 0 <= i < row_dimension(). - /// \pre 0 <= j < column_dimension(). - T& operator() (int i_, int j_) - { - return m_matrix(i_, j_); - } - - /// Write access to a matrix coefficient: a_ij <- val - /// - /// \pre 0 <= i < row_dimension(). - /// \pre 0 <= j < column_dimension(). - void set_coef(std::size_t i_, std::size_t j_, T val) - { - int i = static_cast(i_); - int j = static_cast(j_); - CGAL_precondition(i < m_matrix.rows()); - CGAL_precondition(j < m_matrix.cols()); - - m_matrix.coeffRef(i,j) = val; - } - - /// Return the matrix number of rows - std::size_t rows() const {return m_matrix.rows();} - /// Return the matrix number of cols - std::size_t cols() const {return m_matrix.cols();} - - /// Resize to i rows and j cols - void resize(int i_, int j_) { m_matrix.resize(i_, j_);} - - const T& coeff(int i_) const - { - return m_matrix.coeff(i_); - } - - EigenType m_matrix; -}; - -/*! -\ingroup PkgSolver - -The class `Eigen_vector` is a wrapper around \ref thirdpartyEigen "Eigen" dense vector -type , -which is a simple array of numbers. - -\cgalModels `SvdTraits::Vector` -\cgalModels `SparseLinearAlgebraTraits_d::Vector`. - -\tparam T Number type. -\tparam D Number of colums, or Dynamic. - -\sa `CGAL::Eigen_dense_matrix` -\sa `CGAL::Eigen_linear_algebra_traits` -*/ -template -class Eigen_dense_vector -{ -private: - - /// The internal vector type from \ref thirdpartyEigen "Eigen". - typedef Eigen::Matrix EigenType; - -public: - - /// Create a dense vector out of a \ref thirdpartyEigen "Eigen" vector type - Eigen_dense_vector(const EigenType& vec) : m_vector(vec) {} - - /// Read and write and access to a vector coefficient: `a_i` - const T& coeff(std::size_t i) - { - CGAL_assertion(i >= 0); - CGAL_assertion(i < static_cast(D)); - return m_vector.coeff(i); - } - - EigenType m_vector; -}; - - -/*! -\ingroup PkgSolver - -The class `Eigen_linear_algebra_traits` provides an interface to linear algebra functionalities of \ref thirdpartyEigen "Eigen". -\ref thirdpartyEigen "Eigen" version 3.1 (or later) must be available on the system. - -\sa `CGAL::Eigen_dense_matrix` -\sa `CGAL::Eigen_dense_vector` -\sa http://eigen.tuxfamily.org - -Example --------------- - -\code{.cpp} - -typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - -// dynamic matrix at run time to store a large amount of data -typedef Linear_algebra_traits::MatrixXd MatrixXd; - -// preallocated 3x3 matrix at compile time -typedef Linear_algebra_traits::Matrix3d Matrix3d; - -// preallocated 3-cols vector at compile time -typedef Linear_algebra_traits::Vector3d Vector3d; - -\endcode -*/ - -class Eigen_linear_algebra_traits -{ -public: - typedef double NT; - typedef int Index; - - // dynamic size at run time - typedef CGAL::Eigen_dense_matrix MatrixXd; - - // dynamic rows in run time, fixed cols in compile time - typedef CGAL::Eigen_dense_matrix MatrixX3d; - - // fixed at compile time - typedef CGAL::Eigen_dense_matrix Matrix3d; - - // fixed at compile time - typedef CGAL::Eigen_dense_vector Vector3d; - - /// Get the transpose of a `CGAL::Eigen_dense_matrix` matrix - template - static Matrix transpose(const Matrix& mat) - { - return Matrix(mat.m_matrix.transpose()); - } - - /// Get the determinant of a `CGAL::Eigen_dense_matrix` matrix - template - static NT determinant(const Matrix& mat) - { - return mat.m_matrix.determinant(); - } - - /// Performs QR decomposition of matrix A to a unitary matrix and an upper triagonal - /// and returns the unitary matrix. - template - static CGAL::Eigen_dense_matrix qr_factorization(const CGAL::Eigen_dense_matrix& A) - { - Eigen::HouseholderQR > qr(A.m_matrix); - return CGAL::Eigen_dense_matrix(qr.householderQ()); - } - - template - static void qr_factorization(std::vector& simplex) - { - for(std::size_t i = 0; i < simplex.size(); ++i) - { - Matrix mat = simplex[i].m_matrix; - simplex[i] = qr_factorization(mat); - } - } - - // CGAL::Eigen_dense_vector : the returned type with D2 may be -1 in compile time, - // and may not be equal to the expected type. - // Eigen manages to return a precompiled row out of a dynamic matrix but I don't know how. - - /// Get the row vector out of a `CGAL::Eigen_dense_matrix`. The result is stored in a - /// preallocated at compile time 3-column `CGAL::Eigen_dense_vector` - template - static CGAL::Eigen_dense_vector row3(const CGAL::Eigen_dense_matrix& A, - int i) - { - return CGAL::Eigen_dense_vector(A.m_matrix.row(i)); - } - -}; - - -/// Matrix multiplication. If the columns of A and the rows of B are equal at compile time, -/// the product is stored at a preallocated at compile time `CGAL::Eigen_dense_matrix`. Otherwise, -/// the product is stored in a dynamic at run time matrix. -template -const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix& A, - const CGAL::Eigen_dense_matrix& B) -{ - return CGAL::Eigen_dense_matrix(A.m_matrix * B.m_matrix); -} - -// D2 and D3 may not be equal at compile time, but equal at run time! -// This overload returns a dynamic matrix. -template -const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix& A, - const CGAL::Eigen_dense_matrix& B) -{ - return CGAL::Eigen_dense_matrix(A.m_matrix * B.m_matrix); -} - -// scalar - matrix multiplication -template -const CGAL::Eigen_dense_matrix operator* (const NT& scalar, - const CGAL::Eigen_dense_matrix& B) -{ - return CGAL::Eigen_dense_matrix(scalar * B.m_matrix); -} - -template -const CGAL::Eigen_dense_matrix operator* (const CGAL::Eigen_dense_matrix& A, - const NT& scalar) -{ - return CGAL::Eigen_dense_matrix(A.m_matrix * scalar); -} - -template -const CGAL::Eigen_dense_matrix operator/ (const CGAL::Eigen_dense_matrix& A, - const double& scalar) -{ - return CGAL::Eigen_dense_matrix(A.m_matrix / scalar); -} - -template -const CGAL::Eigen_dense_matrix operator/ (const double& scalar, - const CGAL::Eigen_dense_matrix & A) -{ - return CGAL::Eigen_dense_matrix (scalar / A.m_matrix); -} - -// addition -template -const CGAL::Eigen_dense_matrix operator+ (const CGAL::Eigen_dense_matrix & A, - const CGAL::Eigen_dense_matrix & B) -{ - return CGAL::Eigen_dense_matrix (A.m_matrix + B.m_matrix); -} - -// vector - matrix multiplication -template -const Eigen_dense_vector operator* (const CGAL::Eigen_dense_matrix& A, - const CGAL::Eigen_dense_vector& V) -{ - return Eigen_dense_vector(A.m_matrix * V.m_vector); -} - -} // end namespace - - -#endif // CGAL_EIGEN_LINEAR_ALGEBRA_TRAITS_H From da726d1c3c83aec9f9e02a2e09801aaa104aa97c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Dec 2019 12:27:27 +0100 Subject: [PATCH 059/150] Add a basic example --- .../CMakeLists.txt | 2 +- .../Optimal_bounding_box/obb_example.cpp | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) rename Optimal_bounding_box/examples/{Polygon_mesh_processing => Optimal_bounding_box}/CMakeLists.txt (91%) create mode 100644 Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp diff --git a/Optimal_bounding_box/examples/Polygon_mesh_processing/CMakeLists.txt b/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt similarity index 91% rename from Optimal_bounding_box/examples/Polygon_mesh_processing/CMakeLists.txt rename to Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt index 0faa74ffe4e..8fc23ac241a 100644 --- a/Optimal_bounding_box/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt @@ -21,4 +21,4 @@ else() include(${EIGEN3_USE_FILE}) endif() -create_single_source_cgal_program("example.cpp") +create_single_source_cgal_program("obb_example.cpp") diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp new file mode 100644 index 00000000000..92bd88df424 --- /dev/null +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp @@ -0,0 +1,29 @@ +#define CGAL_OPTIMAL_BOUNDING_BOX_DEBUG + +#include +#include + +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_3 Point; +typedef CGAL::Surface_mesh Surface_mesh; + +int main(int argc, char** argv) +{ + std::ifstream input(argv[1]); + Surface_mesh sm; + if (!input || !(input >> sm) || sm.is_empty()) + { + std::cerr << argv[1] << " is not a valid off file.\n"; + return EXIT_FAILURE; + } + + // test one + Surface_mesh obb_sm; + CGAL::optimal_bounding_box(sm, obb_sm); + + std::ofstream("obb.off") << obb_sm; + + return EXIT_SUCCESS; +} From 60845f601d6427b6a16d428d856543fddf74823b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Dec 2019 12:38:50 +0100 Subject: [PATCH 060/150] Move files to better locations --- .../examples/Optimal_bounding_box/obb_example.cpp | 2 +- .../{helper.h => Optimal_bounding_box_traits.h} | 6 +++--- .../CGAL/Optimal_bounding_box/{ => internal}/evolution.h | 6 +++--- .../Optimal_bounding_box/{ => internal}/fitness_function.h | 0 .../{ => internal}/nelder_mead_functions.h | 2 +- .../CGAL/Optimal_bounding_box/{ => internal}/population.h | 0 .../CGAL/{Optimal_bounding_box => }/optimal_bounding_box.h | 6 +++--- 7 files changed, 11 insertions(+), 11 deletions(-) rename Optimal_bounding_box/include/CGAL/Optimal_bounding_box/{helper.h => Optimal_bounding_box_traits.h} (91%) rename Optimal_bounding_box/include/CGAL/Optimal_bounding_box/{ => internal}/evolution.h (97%) rename Optimal_bounding_box/include/CGAL/Optimal_bounding_box/{ => internal}/fitness_function.h (100%) rename Optimal_bounding_box/include/CGAL/Optimal_bounding_box/{ => internal}/nelder_mead_functions.h (98%) rename Optimal_bounding_box/include/CGAL/Optimal_bounding_box/{ => internal}/population.h (100%) rename Optimal_bounding_box/include/CGAL/{Optimal_bounding_box => }/optimal_bounding_box.h (98%) diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp index 92bd88df424..60c5ec3626c 100644 --- a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h similarity index 91% rename from Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h rename to Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h index d12de45212e..e7393926ed4 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/helper.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h @@ -11,8 +11,8 @@ // Author(s) : Konstantinos Katrioplas // Mael Rouxel-Labbé // -#ifndef CGAL_OPTIMAL_BOUNDING_BOX_HELPER_H -#define CGAL_OPTIMAL_BOUNDING_BOX_HELPER_H +#ifndef CGAL_OPTIMAL_BOUNDING_BOX_BOUNDING_BOX_TRAITS_H +#define CGAL_OPTIMAL_BOUNDING_BOX_BOUNDING_BOX_TRAITS_H #include @@ -77,4 +77,4 @@ public: } // end namespace Optimal_bounding_box } // end namespace CGAL -#endif // CGAL_OPTIMAL_BOUNDING_BOX_HELPER_H +#endif // CGAL_OPTIMAL_BOUNDING_BOX_BOUNDING_BOX_TRAITS_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h similarity index 97% rename from Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h rename to Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index a28535e8242..e34452a034b 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -14,9 +14,9 @@ #ifndef CGAL_OPTIMAL_BOUNDING_BOX_EVOLUTION_H #define CGAL_OPTIMAL_BOUNDING_BOX_EVOLUTION_H -#include -#include -#include +#include +#include +#include #include #include diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h similarity index 100% rename from Optimal_bounding_box/include/CGAL/Optimal_bounding_box/fitness_function.h rename to Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h similarity index 98% rename from Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h rename to Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h index c3b42b0d671..f902e5c6316 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h @@ -14,7 +14,7 @@ #ifndef CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H #define CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H -#include +#include #include diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h similarity index 100% rename from Optimal_bounding_box/include/CGAL/Optimal_bounding_box/population.h rename to Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h similarity index 98% rename from Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h rename to Optimal_bounding_box/include/CGAL/optimal_bounding_box.h index ec2202781bc..fd125e17015 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/optimal_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h @@ -14,9 +14,9 @@ #ifndef CGAL_OPTIMAL_BOUNDING_BOX_OBB_H #define CGAL_OPTIMAL_BOUNDING_BOX_OBB_H -#include -#include -#include +#include +#include +#include #include // @tmp #include From 844cd55f85633923c50423ac70f85d62035335b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Dec 2019 15:43:30 +0100 Subject: [PATCH 061/150] Add license files --- .../CGAL/license/Optimal_bounding_box.h | 54 +++++++++++++++++++ .../include/CGAL/license/gpl_package_list.txt | 1 + 2 files changed, 55 insertions(+) create mode 100644 Installation/include/CGAL/license/Optimal_bounding_box.h diff --git a/Installation/include/CGAL/license/Optimal_bounding_box.h b/Installation/include/CGAL/license/Optimal_bounding_box.h new file mode 100644 index 00000000000..a1403a158c3 --- /dev/null +++ b/Installation/include/CGAL/license/Optimal_bounding_box.h @@ -0,0 +1,54 @@ +// Copyright (c) 2016 GeometryFactory SARL (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Andreas Fabri +// +// Warning: this file is generated, see include/CGAL/licence/README.md + +#ifndef CGAL_LICENSE_OPTIMAL_BOUNDING_BOX_H +#define CGAL_LICENSE_OPTIMAL_BOUNDING_BOX_H + +#include +#include + +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_COMMERCIAL_LICENSE + +# if CGAL_OPTIMAL_BOUNDING_BOX_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE + +# if defined(CGAL_LICENSE_WARNING) + + CGAL_pragma_warning("Your commercial license for CGAL does not cover " + "this release of the Optimal Bounding Box package.") +# endif + +# ifdef CGAL_LICENSE_ERROR +# error "Your commercial license for CGAL does not cover this release \ + of the Optimal Bounding Box package. \ + You get this error, as you defined CGAL_LICENSE_ERROR." +# endif // CGAL_LICENSE_ERROR + +# endif // CGAL_OPTIMAL_BOUNDING_BOX_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE + +#else // no CGAL_OPTIMAL_BOUNDING_BOX_COMMERCIAL_LICENSE + +# if defined(CGAL_LICENSE_WARNING) + CGAL_pragma_warning("\nThe macro CGAL_OPTIMAL_BOUNDING_BOX_COMMERCIAL_LICENSE is not defined." + "\nYou use the CGAL Optimal Bounding Box package under " + "the terms of the GPLv3+.") +# endif // CGAL_LICENSE_WARNING + +# ifdef CGAL_LICENSE_ERROR +# error "The macro CGAL_OPTIMAL_BOUNDING_BOX_COMMERCIAL_LICENSE is not defined.\ + You use the CGAL Optimal Bounding Box package under the terms of \ + the GPLv3+. You get this error, as you defined CGAL_LICENSE_ERROR." +# endif // CGAL_LICENSE_ERROR + +#endif // no CGAL_OPTIMAL_BOUNDING_BOX_COMMERCIAL_LICENSE + +#endif // CGAL_LICENSE_OPTIMAL_BOUNDING_BOX_H diff --git a/Installation/include/CGAL/license/gpl_package_list.txt b/Installation/include/CGAL/license/gpl_package_list.txt index 9841982de7d..0099e282734 100644 --- a/Installation/include/CGAL/license/gpl_package_list.txt +++ b/Installation/include/CGAL/license/gpl_package_list.txt @@ -32,6 +32,7 @@ Minkowski_sum_3 3D Minkowski Sum of Polyhedra Nef_2 2D Boolean Operations on Nef Polygons Nef_3 3D Boolean Operations on Nef Polyhedra Nef_S2 2D Boolean Operations on Nef Polygons Embedded on the Sphere +Optimal_bounding_box Optimal Bounding Box Optimal_transportation_reconstruction_2 Optimal Transportation Curve Reconstruction Partition_2 2D Polygon Partitioning Periodic_2_triangulation_2 2D Periodic Triangulations From c844a98dd8c5deefabd2a92cfc5d439ab2fda1eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Dec 2019 15:44:56 +0100 Subject: [PATCH 062/150] Add to travis' package list --- .travis/packages.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis/packages.txt b/.travis/packages.txt index 8bcfe911043..3123b8c14e6 100644 --- a/.travis/packages.txt +++ b/.travis/packages.txt @@ -71,6 +71,7 @@ Nef_S2 NewKernel_d Number_types OpenNL +Optimal_bounding_box Optimal_transportation_reconstruction_2 Optimisation_basic Partition_2 From bafb8e2f7e69f824456aa15443d9a47585f6c6e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Dec 2019 15:45:40 +0100 Subject: [PATCH 063/150] Add some documentation --- Documentation/doc/Documentation/packages.txt | 1 + .../doc/Optimal_bounding_box/Doxyfile.in | 22 +- .../Optimal_bounding_box/NamedParameters.txt | 281 +----------------- .../Optimal_bounding_box.txt | 11 +- .../PackageDescription.txt | 48 ++- .../doc/Optimal_bounding_box/dependencies | 4 +- .../doc/Optimal_bounding_box/examples.txt | 2 +- .../Optimal_bounding_box_traits.h | 44 +-- .../Optimal_bounding_box/internal/evolution.h | 12 +- .../internal/fitness_function.h | 8 +- .../internal/nelder_mead_functions.h | 8 +- .../internal/population.h | 8 +- .../include/CGAL/optimal_bounding_box.h | 168 +++++++---- 13 files changed, 241 insertions(+), 376 deletions(-) diff --git a/Documentation/doc/Documentation/packages.txt b/Documentation/doc/Documentation/packages.txt index 8aa49408b96..f2f3f68af3e 100644 --- a/Documentation/doc/Documentation/packages.txt +++ b/Documentation/doc/Documentation/packages.txt @@ -129,6 +129,7 @@ \package_listing{Box_intersection_d} \package_listing{AABB_tree} \package_listing{Spatial_sorting} +\package_listing{Optimal_bounding_box} \cgalPackageSection{PartGeometricOptimization,Geometric Optimization} diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Doxyfile.in b/Optimal_bounding_box/doc/Optimal_bounding_box/Doxyfile.in index c01165a4dee..26ad50050b8 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Doxyfile.in +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Doxyfile.in @@ -3,4 +3,24 @@ PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - Optimal Bounding Box" EXTRACT_ALL = false HIDE_UNDOC_CLASSES = true -WARN_IF_UNDOCUMENTED = false +WARN_IF_UNDOCUMENTED = true + +# macros to be used inside the code +ALIASES += "cgalNamedParamsBegin=
Named Parameters
" +ALIASES += "cgalNamedParamsEnd=
" +ALIASES += "cgalParamBegin{1}=\ref OBB_\1 \"\1\"" +ALIASES += "cgalParamEnd=" + +#macros for NamedParameters.txt +ALIASES += "cgalNPTableBegin=
" +ALIASES += "cgalNPTableEnd=
" +ALIASES += "cgalNPBegin{1}=\1 " +ALIASES += "cgalNPEnd=" + +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +EXPAND_AS_DEFINED = CGAL_OBB_NP_TEMPLATE_PARAMETERS \ + CGAL_OBB_NP_CLASS +EXCLUDE = ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Optimal_bounding_box/internal +EXCLUDE_SYMBOLS += experimental + diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt index d9b8e95c9ac..68fed836345 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt @@ -1,17 +1,17 @@ /*! -\defgroup pmp_namedparameters Named Parameters for Polygon Mesh Processing -\ingroup PkgPolygonMeshProcessing +\defgroup obb_namedparameters Named Parameters for the package Optimal Bounding Box +\ingroup PkgOptimalBoundingBoxRef In this package, all functions optional parameters are implemented as BGL optional named parameters (see \ref BGLNamedParameters for more information on how to use them). -Since the parameters of the various polygon mesh processing functions defined -in this package are redundant, their long descriptions are centralized below. +Since the parameters of the various functions defined in this package are redundant, +their long descriptions are centralized below. The sequence of named parameters should start with `CGAL::parameters::`. `CGAL::parameters::all_default()` can be used to indicate that default values of optional named parameters must be used. In the following, we assume that the following types are provided as template parameters -of polygon mesh processing functions and classes. Note that, for some of these functions, +of functions and classes. Note that, for some of these functions, the type is more specific:
  • `PolygonMesh` is a model of the concept `FaceGraph`
  • . @@ -19,50 +19,23 @@ the type is more specific: predicates evaluated. Everywhere in this package, a \cgal `Kernel` fulfills the requirements.
-The following named parameters, offered by the package \ref PkgBGLSummary +The following named parameters, offered by the package \ref PkgBGL (see \ref bgl_namedparameters), are used in this package: \cgalNPTableBegin -\cgalNPBegin{vertex_point_map} \anchor PMP_vertex_point_map +\cgalNPBegin{vertex_point_map} \anchor OBB_vertex_point_map is the property map with the points associated to the vertices of the polygon mesh `pmesh`.\n Type: a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` as key type and `GeomTraits::Point_3` as value type. \n Default: \code boost::get(CGAL::vertex_point, pmesh) \endcode \cgalNPEnd - -\cgalNPBegin{vertex_index_map} \anchor PMP_vertex_index_map -is the property map containing the index of each vertex of the input polygon mesh.\n -Type: a class model of `ReadablePropertyMap` with -`boost::graph_traits::%vertex_descriptor` as key type and the value type -\code typename boost::property_traits::type>::value_type \endcode -Default: \code boost::get(CGAL::vertex_index, pmesh)\endcode -\cgalNPEnd - -\cgalNPBegin{face_index_map} \anchor PMP_face_index_map -is the property map containing the index of each face of the input polygon mesh.\n -Type: a class model of `ReadablePropertyMap` with -`boost::graph_traits::%face_descriptor` as key type and the value type: -\code typename boost::property_traits::type>::value_type \endcode -Default: \code boost::get(CGAL::face_index, pmesh)\endcode -If this internal property map exists, its values should be initialized. -\cgalNPEnd - -\cgalNPBegin{edge_is_constrained_map} \anchor PMP_edge_is_constrained_map -is the property map containing information about edges of the input polygon mesh -being marked or not. In `isotropic_remeshing()` and `connected_components()`, -the marked edges are constrained.\n -Type: a class model of `ReadWritePropertyMap` with -`boost::graph_traits::%edge_descriptor` as key type and -`bool` as value type. It should be default constructible.\n -Default: a default property map where no edge is constrained -\cgalNPEnd \cgalNPTableEnd In addition to these named parameters, this package offers the following named parameters: \cgalNPTableBegin -\cgalNPBegin{geom_traits} \anchor PMP_geom_traits +\cgalNPBegin{geom_traits} \anchor OBB_geom_traits is the geometric traits instance in which the mesh processing operation should be performed.\n Type: a Geometric traits class.\n Default: @@ -71,243 +44,13 @@ is the geometric traits instance in which the mesh processing operation should b typename boost::property_map::type>::value_type>::Kernel \endcode \cgalNPEnd -\cgalNPBegin{vertex_incident_patches_map} \anchor PMP_vertex_incident_patches_map -is the property map containing the surface patches incident to each vertex of the input polygon mesh.\n -Type: a class model of `LvaluePropertyMap` with -`boost::graph_traits::%vertex_descriptor` as key type. Its value type -must be a container of `boost::property_traits::%value_type` and have a function `insert()`. -A `std::set` or a `boost::unordered_set` are recommended, as a patch index may be -inserted several times.\n -Default: \code boost::get(CGAL::vertex_incident_patches_t, pmesh)\endcode -\cgalNPEnd - -\cgalNPBegin{vertex_feature_degree_map} \anchor PMP_vertex_feature_degree_map -is the property map containing the number of feature edges being incident to the vertices of the polygon mesh `pmesh`.\n -Type: a class model of `ReadWritePropertyMap` with -`boost::graph_traits::%vertex_descriptor` as key type and -`int` as value type. It should be default constructible.\n -Default: \code boost::get(CGAL::vertex_feature_degree_t(), pmesh) \endcode -\cgalNPEnd - -\cgalNPBegin{vertex_is_constrained_map} \anchor PMP_vertex_is_constrained_map -is the property map containing information about vertices of the input polygon mesh being constrained or not. -Constrained vertices may be replaced by new vertices, but the number and location -of vertices remain unchanged.\n -Type: a class model of `ReadWritePropertyMap` with -`boost::graph_traits::%vertex_descriptor` as key type and -`bool` as value type. It should be default constructible.\n -Default: a default property map where no vertex is constrained is provided. -\cgalNPEnd - -\cgalNPBegin{face_patch_map} \anchor PMP_face_patch_map -is a property map containing information about faces. -It is particularly well-suited for preserving surface patch IDs, -or face colors. -The edges at the interface between surface patches are treated similarly -to the ones of `edge_is_constrained_map`.\n -Type: a class model of `ReadWritePropertyMap` with -`boost::graph_traits::%face_descriptor` as key type and -the desired property, model of `CopyConstructible` as value type.\n -Default: a default property map where each face is associated with the ID of -the connected component it belongs to. Connected components are -computed with respect to the constrained edges listed in the property map -`edge_is_constrained_map` -\cgalNPEnd - -\cgalNPBegin{first_index} \anchor PMP_first_index -is the index of the first surface patch.\n -Type: `std::size_t`\n -Default: 1 -\cgalNPEnd - -\cgalNPBegin{density_control_factor} \anchor PMP_density_control_factor -controls the density of the mesh generated by refinement, with larger values causing denser refinements. -The density of vertices in the refined region is this factor times higher than before refinement.\n -Type: floating scalar value\n -Default: `CGAL::sqrt(2)` -\cgalNPEnd - -\cgalNPBegin{fairing_continuity} \anchor PMP_fairing_continuity -controls the tangential continuity of the output surface in `fair()`. -The possible values are 0, 1 and 2, refering to the C0, C1 -and C2 continuity.\n -Type: \c unsigned \c int between 0 and 2\n -Default: `1` -\cgalNPEnd - -\cgalNPBegin{sparse_linear_solver} \anchor PMP_sparse_linear_solver -is the solver used in `fair()`.\n -Type: a class model of `SparseLinearAlgebraWithFactorTraits_d`.\n -Default: if \ref thirdpartyEigen "Eigen" 3.2 (or greater) is available and -`CGAL_EIGEN3_ENABLED` is defined, then the following overload of `Eigen_solver_traits` -is provided as default value:\n -\code CGAL::Eigen_solver_traits::EigenType, Eigen::COLAMDOrdering > > \endcode -\cgalNPEnd - -\cgalNPBegin{number_of_iterations} \anchor PMP_number_of_iterations -is the number of iterations of the sequence of iterations performed in `isotropic_remeshing()`.\n -Type: \c unsigned \c int \n -Default: `1` -\cgalNPEnd - -\cgalNPBegin{protect_constraints} \anchor PMP_protect_constraints -enables the protection of constraints listed by \ref PMP_edge_is_constrained_map -"edge_is_constrained_map" and boundary edges -in `isotropic_remeshing()`. If `true`, constraint edges cannot be modified at all -during the remeshing process.\n -Type: `bool` \n -Default: `false` -\cgalNPEnd - -\cgalNPBegin{relax_constraints} \anchor PMP_relax_constraints -enables the tangential relaxation step in `isotropic_remeshing()` -to be performed on vertices that are endpoints of constraints listed -by \ref PMP_edge_is_constrained_map "edge_is_constrained_map", and boundary edges. -The vertices move along the constrained polylines they belong to. -Corners (i.e. vertices incident to more than 2 constraints, and vertices listed in -\ref PMP_vertex_is_constrained_map "vertex_is_constrained_map") are not allowed -to move at all. -If \ref PMP_protect_constraints "protect_constraints" is -set to `true`, this parameter is ignored.\n -Type: `bool` \n -Default: `true` -\cgalNPEnd - -\cgalNPBegin{number_of_relaxation_steps} \anchor PMP_number_of_relaxation_steps -is the number of iterations of tangential relaxation that are performed at each iteration -of `isotropic_remeshing()`. A larger number of relaxation steps lead to -a more isotropic mesh.\n -Type: \c unsigned \c int \n -Default: `1` -\cgalNPEnd - -\cgalNPBegin{use_delaunay_triangulation} \anchor PMP_use_delaunay_triangulation -enables the use of the Delaunay triangulation facet search space for hole filling functions.\n -Type: `bool` \n -Default: `true` -\cgalNPEnd - -\cgalNPBegin{use_random_uniform_sampling} \anchor PMP_use_random_uniform_sampling -is a parameter used in `sample_triangle_mesh()` to indicate if points should be picked -in a random uniform way.\n -Type: `bool` \n -Default: `true` -\cgalNPEnd - -\cgalNPBegin{use_grid_sampling} \anchor PMP_use_grid_sampling -is a parameter used in `sample_triangle_mesh()` to indicate if points should be picked -in on a grid in each face.\n -Type: `bool` \n -Default: `false` -\cgalNPEnd - -\cgalNPBegin{use_monte_carlo_sampling} \anchor PMP_use_monte_carlo_sampling -is a parameter used in `sample_triangle_mesh()` to indicate if points should be picked -using a Monte-Carlo approach.\n -Type: `bool` \n -Default: `false` -\cgalNPEnd - -\cgalNPBegin{sample_edges} \anchor PMP_sample_edges -is a parameter used in `sample_triangle_mesh()` to indicate if a dedicated sampling -of edges should be done.\n -Type: `bool` \n -Default: `true` -\cgalNPEnd - -\cgalNPBegin{sample_vertices} \anchor PMP_sample_vertices -is a parameter used in `sample_triangle_mesh()` to indicate if triangle vertices should -be copied in the output iterator.\n -Type: `bool` \n -Default: `true` -\cgalNPEnd - -\cgalNPBegin{sample_faces} \anchor PMP_sample_faces -is a parameter used in `sample_triangle_mesh()` to indicate if the interior of faces -should be considered for the sampling.\n -Type: `bool` \n -Default: `true` -\cgalNPEnd - -\cgalNPBegin{number_of_points_on_faces} \anchor PMP_number_of_points_on_faces -is a parameter used in `sample_triangle_mesh()` to set the number of points picked -using the random uniform method on faces.\n -Type: `std::size_t` \n -Default: `0` -\cgalNPEnd - -\cgalNPBegin{number_of_points_on_edges} \anchor PMP_number_of_points_on_edges -is a parameter used in `sample_triangle_mesh()` to set the number of points picked -using the random uniform method on edges.\n -Type: `std::size_t` \n -Default: `0` -\cgalNPEnd - -\cgalNPBegin{number_of_points_per_face} \anchor PMP_number_of_points_per_face -is a parameter used in `sample_triangle_mesh()` to set the number of points picked -per face using the Monte-Carlo method.\n -Type: `std::size_t` \n -Default: `0` -\cgalNPEnd - -\cgalNPBegin{number_of_points_per_edge} \anchor PMP_number_of_points_per_edge -is a parameter used in `sample_triangle_mesh()` to set the number of points picked -per edge using the Monte-Carlo method.\n -Type: `std::size_t` \n -Default: `0` -\cgalNPEnd - -\cgalNPBegin{grid_spacing} \anchor PMP_grid_spacing -is a parameter used in `sample_triangle_mesh()` to set the grid spacing when using -the grid sampling method.\n -Type: `double` \n -Default: `0` -\cgalNPEnd - -\cgalNPBegin{number_of_points_per_area_unit} \anchor PMP_number_of_points_per_area_unit -is a parameter used in `sample_triangle_mesh()` to set the number of points per -area unit to be picked up in faces for the random uniform sampling and -Monte-Carlo methods.\n -Type: `double` \n -Default: `0` -\cgalNPEnd - -\cgalNPBegin{number_of_points_per_distance_unit} \anchor PMP_number_of_points_per_distance_unit -is a parameter used in `sample_triangle_mesh()` to set the number of points per -distance unit to be picked up on edges for the random uniform sampling and -Monte-Carlo methods.\n -Type: `double` \n -Default: `0` -\cgalNPEnd - -\cgalNPBegin{do_project} \anchor PMP_do_project -is a parameter used in `random_perturbation()` to set whether vertices should be re-projected -to the input surface after their geometric perturbation.\n -Type: `bool` \n -Default: `true` -\cgalNPEnd - -\cgalNPBegin{random_seed} \anchor PMP_random_seed -is a parameter used in `random_perturbation()` to choose a seed to initialize -the random number generator `CGAL::Random()`. -If this parameter is not provided, the perturbation is not deterministic -(i.e. not reproducible from one run to the other).\n -Type: `unsigned int` \n -Default: the random number generator is initialized with `CGAL::Random()` -\cgalNPEnd - -\cgalNPBegin{outward_orientation} \anchor PMP_outward_orientation -Parameter used in orientation functions to choose between an outward or inward orientation. +\cgalNPBegin{use_convex_hull} \anchor OBB_use_convex_hull +Parameter used in optimal bounding box construction to indicate whether the algorithm should +first extract the extreme points (points that are on the 3D convex hull) of the input data range +to accelerate the computation of the bounding box. \n \b Type : `bool` \n \b Default value is `true` - -\cgalNPBegin{do_overlap_test_of_bounded_sides} \anchor PMP_do_overlap_test_of_bounded_sides -Parameter used in intersection test functions to indicate whether overlapping tests of bounded sides -of close meshes should be done in addition to surface intersection tests. -\n -\b Type : `bool` \n -\b Default value is `false` \cgalNPEnd \cgalNPTableEnd diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Optimal_bounding_box.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/Optimal_bounding_box.txt index d84814bee40..393a803a971 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Optimal_bounding_box.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Optimal_bounding_box.txt @@ -1,9 +1,16 @@ namespace CGAL { + /*! \mainpage User Manual -\anchor Chapter_OptimalBoundingBox +\anchor Chapter_Building_Optimal_Bounding_Box \cgalAutoToc -\authors +\authors Konstantinos Katrioplas, Mael Rouxel-Labbé + +\section sectionSubIntro Introduction + +AABB and stuff + +\section secOBB Optimal Bounding Box } /* namespace CGAL */ diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt index 496066da185..156f50dc13e 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt @@ -1,30 +1,50 @@ -/// \defgroup PkgOptimalBoundingBox Optimal Bounding Box Reference +/// \defgroup PkgOptimalBoundingBoxRef Optimal Bounding Box Reference + /// \defgroup PkgOptimalBoundingBoxConcepts Concepts -/// \ingroup PkgOptimalBoundingBox +/// \ingroup PkgOptimalBoundingBoxRef -\cgalPkgDescriptionBegin{Optimal Bounding Box, PkgOptimalBoundingBoxSummary} -\cgalPkgPicture{} +/// \defgroup PkgOptimalBoundingBoxClasses Optimal Bounding Box Classes +/// \ingroup PkgOptimalBoundingBoxRef +/// \defgroup PkgOptimalBoundingBoxFunctions Optimal Bounding Box Methods +/// \ingroup PkgOptimalBoundingBoxRef + +/*! +\addtogroup PkgOptimalBoundingBoxRef +\cgalPkgDescriptionBegin{Optimal Bounding Box,PkgOptimalBoundingBox} +\cgalPkgPicture{Envelope_2.png} \cgalPkgSummaryBegin -\cgalPkgAuthor{} -\cgalPkgDesc{This package provides stuff.} -\cgalPkgManuals{Chapter_OptimalBoundingBox,PkgOptimalBoundingBox} +\cgalPkgAuthor{Konstantinos Katrioplas, Mael Rouxel-Labbé} +\cgalPkgDesc{This package provides functions to compute oriented bounding boxes around a point set or a polygon mesh.} +\cgalPkgManuals{Chapter_Building_Optimal_Bounding_Box,PkgOptimalBoundingBoxRef} \cgalPkgSummaryEnd - \cgalPkgShortInfoBegin -\cgalPkgSince{5.2} +\cgalPkgSince{5.1} \cgalPkgDependsOn{documented for each function;} -\cgalPkgBib{cgal:lty-pmp} +\cgalPkgBib{cgal:obb} \cgalPkgLicense{\ref licensesGPL "GPL"} -\cgalPkgDemo{Polyhedron demo,polyhedron_3.zip} +\cgalPkgDemo{Polyhedron demo, polyhedron_3.zip} \cgalPkgShortInfoEnd - \cgalPkgDescriptionEnd \cgalClassifedRefPages -## Parameters ## +\cgalCRPSection{Parameters} -## Functions ## +Optional parameters of the functions of this package are implemented as \ref BGLNamedParameters. +The page \ref obb_namedparameters describes their usage and provides a list of the parameters +that are used in this package. + +\cgalCRPSection{Concepts} + +- `CGAL::OptimalBoundingBoxTraits` + +\cgalCRPSection{Classes} + +- `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits` + +\cgalCRPSection{Methods} + +- `CGAL::optimal_bounding_box()` */ diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/dependencies b/Optimal_bounding_box/doc/Optimal_bounding_box/dependencies index 52428e7009d..0379719e9cf 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/dependencies +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/dependencies @@ -8,7 +8,5 @@ Polyhedron BGL Solver_interface Surface_mesh -Surface_mesh_deformation AABB_tree -Triangulation_2 -Spatial_sorting + diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/examples.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/examples.txt index 76aff917caf..4bd9b08df1b 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/examples.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/examples.txt @@ -1,4 +1,4 @@ /*! -\example Optimal_bounding_box/example_todo.cpp +\example Optimal_bounding_box/obb_example.cpp */ diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h index e7393926ed4..a570cdc2412 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h @@ -8,55 +8,59 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Konstantinos Katrioplas -// Mael Rouxel-Labbé +// Author(s) : Mael Rouxel-Labbé // #ifndef CGAL_OPTIMAL_BOUNDING_BOX_BOUNDING_BOX_TRAITS_H #define CGAL_OPTIMAL_BOUNDING_BOX_BOUNDING_BOX_TRAITS_H -#include - -#include -#include -#include -#include -#include +#include #ifdef CGAL_EIGEN3_ENABLED #include #include #endif -#include -#include -#include - namespace CGAL { namespace Optimal_bounding_box { -#ifdef CGAL_EIGEN3_ENABLED -// @tmp move the header include too +#if defined(CGAL_EIGEN3_ENABLED) || defined(DOXYGEN_RUNNING) + +/// \ingroup PkgOptimalBoundingBoxClasses +/// +/// The class `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits` is a traits type +/// to be used with the functions `CGAL::optimal_bounding_box()`. +/// It uses the third party library \ref thirdpartyEigen "Eigen", which must therefore +/// be available on the system for this class to be used. +/// +/// \tparam K must be a model of `Kernel` +/// +/// \cgalModels `OptimalBoundingBoxTraits` +/// template class Optimal_bounding_box_traits : public K { public: + /// The field number type typedef typename K::FT FT; + + /// The matrix type typedef CGAL::Eigen_matrix Matrix; private: typedef typename Matrix::EigenType EigenType; public: + /// Constructor from the base kernel explicit Optimal_bounding_box_traits(const K& k = K()) : K(k) { } - /// Get the transpose of a `Matrix` matrix + /// Get the transpose of a matrix Matrix transpose(const Matrix& mat) const { return Matrix(mat.eigen_object().transpose()); } - /// Get the determinant of a `Matrix` matrix + /// Get the determinant of a matrix FT determinant(const Matrix& matrix) const { return matrix.eigen_object().determinant(); @@ -72,9 +76,9 @@ public: return Matrix(EigenType(qr.householderQ())); } }; -#endif +#endif // defined(CGAL_EIGEN3_ENABLED) || defined(DOXYGEN_RUNNING) -} // end namespace Optimal_bounding_box -} // end namespace CGAL +} // namespace Optimal_bounding_box +} // namespace CGAL #endif // CGAL_OPTIMAL_BOUNDING_BOX_BOUNDING_BOX_TRAITS_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index e34452a034b..cc1bd28350a 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -14,6 +14,8 @@ #ifndef CGAL_OPTIMAL_BOUNDING_BOX_EVOLUTION_H #define CGAL_OPTIMAL_BOUNDING_BOX_EVOLUTION_H +#include + #include #include #include @@ -28,6 +30,7 @@ namespace CGAL { namespace Optimal_bounding_box { +namespace internal { template class Evolution @@ -36,10 +39,10 @@ public: typedef typename Traits::FT FT; typedef typename Traits::Matrix Matrix; - typedef Optimal_bounding_box::Population Population; + typedef Population Population; typedef typename Population::Simplex Simplex; - typedef Optimal_bounding_box::Fitness_map Fitness_map; + typedef Fitness_map Fitness_map; Evolution(const PointRange& points, CGAL::Random& rng, @@ -203,7 +206,8 @@ private: const Traits& m_traits; }; -} // end namespace Optimal_bounding_box -} // end namespace CGAL +} // namespace internal +} // namespace Optimal_bounding_box +} // namespace CGAL #endif // CGAL_OPTIMAL_BOUNDING_BOX_EVOLUTION_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h index bd917b6c370..1d5cb9aac75 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h @@ -14,6 +14,8 @@ #ifndef CGAL_OPTIMAL_BOUNDING_FITNESS_FUNCTION_H #define CGAL_OPTIMAL_BOUNDING_FITNESS_FUNCTION_H +#include + #include #include @@ -21,6 +23,7 @@ namespace CGAL { namespace Optimal_bounding_box { +namespace internal { template typename Traits::FT @@ -103,7 +106,8 @@ private: const PointRange& m_points; }; -} // end namespace Optimal_bounding_box -} // end namespace CGAL +} // namespace internal +} // namespace Optimal_bounding_box +} // namespace CGAL #endif // CGAL_OPTIMAL_BOUNDING_FITNESS_FUNCTION_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h index f902e5c6316..8f080095320 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h @@ -14,6 +14,8 @@ #ifndef CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H #define CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H +#include + #include #include @@ -23,6 +25,7 @@ namespace CGAL { namespace Optimal_bounding_box { +namespace internal { template Matrix reflection(const Matrix& S_centroid, @@ -157,7 +160,8 @@ void nelder_mead(Simplex& simplex, } // nelder mead iterations } -} // end namespace Optimal_bounding_box -} // end namespace CGAL +} // namespace internal +} // namespace Optimal_bounding_box +} // namespace CGAL #endif diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h index cd8acaf702d..640b4423a71 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h @@ -14,6 +14,8 @@ #ifndef CGAL_OPTIMAL_BOUNDING_BOX_POPULATION_H #define CGAL_OPTIMAL_BOUNDING_BOX_POPULATION_H +#include + #include #include @@ -22,6 +24,7 @@ namespace CGAL { namespace Optimal_bounding_box { +namespace internal { template class Population @@ -99,7 +102,8 @@ void Population::show_population() } #endif -} // end namespace Optimal_bounding_box -} // end namespace CGAL +} // namespace internal +} // namespace Optimal_bounding_box +} // namespace CGAL #endif // CGAL_OPTIMAL_BOUNDING_BOX_POPULATION_H diff --git a/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h index fd125e17015..e6723cb8027 100644 --- a/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h @@ -14,12 +14,14 @@ #ifndef CGAL_OPTIMAL_BOUNDING_BOX_OBB_H #define CGAL_OPTIMAL_BOUNDING_BOX_OBB_H +#include + #include #include #include -#include // @tmp -#include +#include +#include #include #include @@ -27,6 +29,7 @@ #include #include #include +#include #include #include @@ -40,6 +43,11 @@ #include #include +#ifdef DOXYGEN_RUNNING +#define CGAL_BGL_NP_TEMPLATE_PARAMETERS NamedParameters +#define CGAL_BGL_NP_CLASS NamedParameters +#endif + namespace CGAL { namespace Optimal_bounding_box { namespace internal { @@ -100,12 +108,6 @@ void construct_optimal_bounding_box(std::array& obb #endif Evolution search_solution(points, rng, traits); - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS - std::cout << "constructor: " << timer.time() << std::endl; - timer.reset(); -#endif - search_solution.evolve(max_generations); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS @@ -117,16 +119,13 @@ void construct_optimal_bounding_box(std::array& obb #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS std::cout << "get best: " << timer.time() << std::endl; -#endif - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS timer.reset(); #endif post_processing(rotation, obb_points, points, traits); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS - std::cout << "post porcessing: " << timer.time() << std::endl; + std::cout << "post-processing: " << timer.time() << std::endl; #endif } @@ -157,72 +156,134 @@ void construct_optimal_bounding_box(std::array& obb } // namespace Optimal_bounding_box } // namespace internal -/// \ingroup OBB_grp -/// calculates the optimal bounding box. +/// \ingroup PkgOptimalBoundingBoxFunctions +/// +/// constructs a rectangular box that contains all the input points. This bounding box +/// is obtained via an optimization process aiming to get a close approximation to the +/// optimal bounding box. /// /// \tparam PointRange a model of `Range` with value type `Point` -/// \tparam NamedParameters +/// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" /// -/// \param points the input points that are included in the optimal bounding box. -/// \param obb_points the eight points of the optimal bounding box to be calculated. +/// \param points the input points that the optimal bounding box will contain +/// \param obb_points the eight points of the resulting englobing box. +/// The order of points is the same as in the function `CGAL::make_hexahedron()` +/// \param np an optional sequence of \ref obb_namedparameters "Named Parameters" among the ones listed below: +/// +/// \cgalNamedParamsBegin +/// \cgalParamBegin{vertex_point_map} +/// the property map with the points associated to the vertices of `pmesh`. +/// If this parameter is omitted, an internal property map for +/// `CGAL::vertex_point_t` must be available in `PolygonMesh` +/// \cgalParamEnd +/// \cgalParamBegin{geom_traits} +/// a geometric traits class instance, model of the concept `OptimalBoundingBoxTraits`. %Default is +/// `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits` where `K` is deduced +/// from the point type, which must be compatible with `CGAL::Kernel_traits`. +/// \cgalParamEnd +/// \cgalParamBegin{use_convex_hull} +/// a Boolean value to indicate whether the algorithm should first extract the so-called extreme +/// points of the data range (i.e. construct the convex hull) to reduce the input data range +/// and accelerate the algorithm. The optimal value of this parameter will depend on the data +/// as it is a balance between two costs. %Default is `true`. +/// \cgalParamEnd +/// \cgalNamedParamsEnd /// template + typename CGAL_BGL_NP_TEMPLATE_PARAMETERS> void optimal_bounding_box(const PointRange& points, std::array& obb_points, - const CGAL_PMP_NP_CLASS& np) + const CGAL_BGL_NP_CLASS& np) { using CGAL::parameters::choose_parameter; using CGAL::parameters::get_parameter; -#if 0 // @fixme - typedef typename GetSvdTraits::type SVD_traits; - CGAL_static_assertion_msg( - !(std::is_same::NoTraits>::value), - "Error: must provide traits or enable Eigen"); - - const SVD_traits traits = choose_parameter(get_parameter(np, svd_traits), SVD_traits()); +#if defined(CGAL_EIGEN3_ENABLED) + typedef typename CGAL::Kernel_traits::type K; + typedef Optimal_bounding_box::Optimal_bounding_box_traits Default_traits; #else - typedef typename CGAL::Kernel_traits::type K; - typedef Optimal_bounding_box::Optimal_bounding_box_traits Traits; - Traits traits; + typedef void Default_traits; #endif - // @fixme - const bool use_ch = true; //choose_parameter(get_parameter(np, internal_np::use_convex_hull), false); - unsigned int seed = choose_parameter(get_parameter(np, internal_np::random_seed), 0); + typedef typename internal_np::Lookup_named_param_def::type Geom_traits; + + CGAL_static_assertion_msg(!(std::is_same::value), + "You must provide a traits class or have Eigen enabled!"); + + Geom_traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Geom_traits()); + + const bool use_ch = choose_parameter(get_parameter(np, internal_np::use_convex_hull), false); + const unsigned int seed = choose_parameter(get_parameter(np, internal_np::random_seed), 0); // undocumented CGAL::Random rng(seed); + // @todo handle those cases instead + CGAL_assertion(points.size() >= 3); + if(points.size() <= 3) + { + std::cerr << "The optimal bounding box cannot YET be computed for a mesh with fewer than 4 vertices!\n"; + return; + } + return Optimal_bounding_box::internal::construct_optimal_bounding_box(obb_points, use_ch, points, rng, traits); } -template -void optimal_bounding_box(const PolygonMesh& pmesh, - std::array& obb_mesh) -{ - return optimal_bounding_box(pmesh, obb_mesh, CGAL::parameters::all_default()); -} +/// \cond SKIP_IN_MANUAL /////////////////////////////////////////////////////////////////////////////////////////////////// -/// With polygon meshes +/// Convenience overloads for point ranges ///////////////////////////////////////////////////////////////////////////////////////////////// -/// \ingroup OBB_grp -/// calculates the optimal bounding box. +template +void optimal_bounding_box(const PointRange& points, + std::array& obb_points) +{ + return optimal_bounding_box(points, obb_points, CGAL::parameters::all_default()); +} + +/// \endcond + +/// \ingroup PkgOptimalBoundingBoxFunctions +/// +/// constructs a rectangular box that contains the input mesh. This bounding box +/// is obtained via an optimization process aiming to get a close approximation to the +/// optimal bounding box. /// /// \tparam PolygonMesh a model of `FaceListGraph` -/// \tparam NamedParameters +/// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" /// -/// \param pmesh the input mesh. -/// \param obb_mesh the hexaedron mesh to be built out of the optimal bounding box. +/// \param pmesh the input mesh +/// \param obb_mesh the eight points of the resulting englobing box. +/// The order of points is the same as in the function `CGAL::make_hexahedron()` +/// \param np an optional sequence of \ref obb_namedparameters "Named Parameters" among the ones listed below: +/// +/// \cgalNamedParamsBegin +/// \cgalParamBegin{vertex_point_map} +/// the property map with the points associated to the vertices of `pmesh`. +/// If this parameter is omitted, an internal property map for +/// `CGAL::vertex_point_t` must be available in `PolygonMesh` +/// \cgalParamEnd +/// \cgalParamBegin{geom_traits} +/// a geometric traits class instance, model of the concept `OptimalBoundingBoxTraits`. %Default is +/// `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits` where `K` is deduced +/// from the point type, which must be compatible with `CGAL::Kernel_traits`. +/// \cgalParamEnd +/// \cgalParamBegin{use_convex_hull} +/// a Boolean value to indicate whether the algorithm should first extract the so-called extreme +/// points of the data range (i.e. construct the convex hull) to reduce the input data range +/// and accelerate the algorithm. The optimal value of this parameter will depend on the data +/// as it is a balance between two costs. %Default is `true`. +/// \cgalParamEnd +/// \cgalNamedParamsEnd /// template + typename CGAL_BGL_NP_TEMPLATE_PARAMETERS> void optimal_bounding_box(const PolygonMesh& pmesh, PolygonMesh& obb_mesh, - const CGAL_PMP_NP_CLASS& np) + const CGAL_BGL_NP_CLASS& np) { namespace PMP = CGAL::Polygon_mesh_processing; @@ -231,18 +292,9 @@ void optimal_bounding_box(const PolygonMesh& pmesh, typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename PMP::GetVertexPointMap::const_type VPM; + typedef typename PMP::GetVertexPointMap::const_type VPM; typedef typename boost::property_traits::value_type Point; - CGAL_assertion(vertices(pmesh).size() >= 3); - - if(vertices(pmesh).size() <= 3) - { - // @fixme is that even true - std::cerr << "The optimal bounding box cannot be computed for a mesh with fewer than 4 vertices!\n"; - return; - } - VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), get_const_property_map(vertex_point, pmesh)); @@ -259,6 +311,8 @@ void optimal_bounding_box(const PolygonMesh& pmesh, obb_points[4], obb_points[5], obb_points[6], obb_points[7], obb_mesh); } +/// \cond SKIP_IN_MANUAL + /////////////////////////////////////////////////////////////////////////////////////////////////// /// Convenience overloads for polygon meshes ///////////////////////////////////////////////////////////////////////////////////////////////// @@ -270,6 +324,8 @@ void optimal_bounding_box(const PolygonMesh& pmesh, return optimal_bounding_box(pmesh, obb_mesh, CGAL::parameters::all_default()); } +/// \endcond + } // end namespace CGAL #endif // CGAL_OPTIMAL_BOUNDING_BOX_OBB_H From 408635fe84ba4bb2575122edef00bc3516b5d825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Dec 2019 16:34:29 +0100 Subject: [PATCH 064/150] Add new NP --- BGL/include/CGAL/boost/graph/parameters_interface.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index 87db07d59ad..02ddd8018ff 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -127,6 +127,9 @@ CGAL_add_named_parameter(max_number_of_proxies_t, max_number_of_proxies, max_num CGAL_add_named_parameter(min_error_drop_t, min_error_drop, min_error_drop) CGAL_add_named_parameter(number_of_relaxations_t, number_of_relaxations, number_of_relaxations) +// List of named parameters used in Optimal_bounding_box package +CGAL_add_named_parameter(use_convex_hull_t, use_convex_hull, use_convex_hull) + // meshing parameters CGAL_add_named_parameter(subdivision_ratio_t, subdivision_ratio, subdivision_ratio) CGAL_add_named_parameter(relative_to_chord_t, relative_to_chord, relative_to_chord) From 325a95f5f1ecaf446ef39c22d9fb8b83292bd79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Dec 2019 16:38:25 +0100 Subject: [PATCH 065/150] Add missing */ --- .../doc/Optimal_bounding_box/Optimal_bounding_box.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Optimal_bounding_box.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/Optimal_bounding_box.txt index 393a803a971..82a8eb6e391 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Optimal_bounding_box.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Optimal_bounding_box.txt @@ -12,5 +12,5 @@ namespace CGAL { AABB and stuff \section secOBB Optimal Bounding Box - +*/ } /* namespace CGAL */ From 9af73856a715dcb5c8ea4b3696854f2d08306bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Dec 2019 16:38:42 +0100 Subject: [PATCH 066/150] Add missing header includes --- .../examples/Optimal_bounding_box/obb_example.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp index 60c5ec3626c..0f57de2d168 100644 --- a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp @@ -5,6 +5,9 @@ #include +#include +#include + typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point; typedef CGAL::Surface_mesh Surface_mesh; From 127bf54e446486f1d921bd9f3962941c6f2418e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Dec 2019 16:39:19 +0100 Subject: [PATCH 067/150] Give Eigen_sparse_matrix its own file The idea is that it is clearer that Eigen_matrix exists --- Solver_interface/include/CGAL/Eigen_matrix.h | 331 +---------------- .../include/CGAL/Eigen_sparse_matrix.h | 335 ++++++++++++++++++ 2 files changed, 340 insertions(+), 326 deletions(-) create mode 100644 Solver_interface/include/CGAL/Eigen_sparse_matrix.h diff --git a/Solver_interface/include/CGAL/Eigen_matrix.h b/Solver_interface/include/CGAL/Eigen_matrix.h index 3f6431d5a6d..ae661a4a129 100644 --- a/Solver_interface/include/CGAL/Eigen_matrix.h +++ b/Solver_interface/include/CGAL/Eigen_matrix.h @@ -8,341 +8,20 @@ // // Author(s) : Gael Guennebaud -#ifndef CGAL_EIGEN_MATRIX_H -#define CGAL_EIGEN_MATRIX_H +#ifndef CGAL_SOLVER_INTERFACE_EIGEN_MATRIX_H +#define CGAL_SOLVER_INTERFACE_EIGEN_MATRIX_H #include // include basic.h before testing #defines -#include +#include // for backward compatibility + +#include namespace CGAL { /*! \ingroup PkgSolverInterfaceRef -The class `Eigen_sparse_matrix` is a wrapper around `Eigen` matrix type -`Eigen::SparseMatrix` -that represents general matrices, be they symmetric or not. - -\cgalModels `SparseLinearAlgebraTraits_d::Matrix` - -\tparam T Number type. - -\sa `CGAL::Eigen_vector` -\sa `CGAL::Eigen_matrix` -\sa `CGAL::Eigen_sparse_symmetric_matrix` -*/ -template -struct Eigen_sparse_matrix -{ - // Public types -public: - /// \name Types - /// @{ - - /// The internal matrix type from \ref thirdpartyEigen "Eigen". - typedef Eigen::SparseMatrix EigenType; - - typedef T NT; - /// @} - - Eigen_sparse_matrix(const EigenType& et) - : m_is_already_built(true), m_matrix(et), m_is_symmetric(false) - {} - - // Public operations -public: - Eigen_sparse_matrix() : - m_is_already_built(false) - {} - - /// Create a square matrix initialized with zeros. - Eigen_sparse_matrix(std::size_t dim, ///< Matrix dimension. - bool is_symmetric = false) ///< Symmetric/hermitian? - : - m_is_already_built(false), - m_matrix(static_cast(dim), static_cast(dim)) - { - CGAL_precondition(dim > 0); - - m_is_symmetric = is_symmetric; - m_triplets.reserve(dim); // reserve memory for a regular 3D grid - } - - /// Create a square matrix initialized with zeros. - Eigen_sparse_matrix(int dim, ///< Matrix dimension. - bool is_symmetric = false) ///< Symmetric/hermitian? - : m_is_already_built(false), - m_matrix(dim, dim) - { - CGAL_precondition(dim > 0); - - m_is_symmetric = is_symmetric; - // reserve memory for a regular 3D grid - m_triplets.reserve(dim); - } - - /// Create a rectangular matrix initialized with zeros. - /// - /// \pre rows == columns if `is_symmetric` is true. - Eigen_sparse_matrix(std::size_t rows, ///< Number of rows. - std::size_t columns, ///< Number of columns. - bool is_symmetric = false) ///< Symmetric/hermitian? - : m_is_already_built(false), - m_matrix(static_cast(rows), static_cast(columns)) - { - CGAL_precondition(rows > 0); - CGAL_precondition(columns > 0); - if(m_is_symmetric) - { - CGAL_precondition(rows == columns); - } - - m_is_symmetric = is_symmetric; - // reserve memory for a regular 3D grid - m_triplets.reserve(rows); - } - - void swap(Eigen_sparse_matrix& other) - { - std::swap(m_is_already_built, other.m_is_already_built); - std::swap(m_is_symmetric, other.m_is_symmetric); - m_matrix.swap(other.m_matrix); - m_triplets.swap(other.m_triplets); - } - - - /// Delete this object and the wrapped matrix. - ~Eigen_sparse_matrix() { } - - /// Create a rectangular matrix initialized with zeros. - /// - /// \pre rows == columns if `is_symmetric` is true. - Eigen_sparse_matrix(int rows, ///< Number of rows. - int columns, ///< Number of columns. - bool is_symmetric = false) ///< Symmetric/hermitian? - : m_is_already_built(false), - m_matrix(rows,columns) - { - CGAL_precondition(rows > 0); - CGAL_precondition(columns > 0); - if(is_symmetric) - { - CGAL_precondition(rows == columns); - } - - m_is_symmetric = is_symmetric; - // reserve memory for a regular 3D grid - m_triplets.reserve(rows); - } - - /// Return the matrix number of rows - int row_dimension() const { return static_cast(m_matrix.rows()); } - /// Return the matrix number of columns - int column_dimension() const { return static_cast(m_matrix.cols()); } - - /// Write access to a matrix coefficient: a_ij <- val. - /// - /// Users can optimize calls to this function by setting 'new_coef' to `true` - /// if the coefficient does not already exist in the matrix. - /// - /// \warning For symmetric matrices, `Eigen_sparse_matrix` only stores the lower triangle - /// and `set_coef()` does nothing if (i, j) belongs to the upper triangle. - /// - /// \pre 0 <= i < row_dimension(). - /// \pre 0 <= j < column_dimension(). - void set_coef(std::size_t i_, std::size_t j_, T val, bool new_coef = false) - { - int i = static_cast(i_); - int j = static_cast(j_); - CGAL_precondition(i < row_dimension()); - CGAL_precondition(j < column_dimension()); - - if (m_is_symmetric && (j > i)) - return; - - if(m_is_already_built) - { - m_matrix.coeffRef(i,j) = val; - } - else - { - if(new_coef == false) - { - assemble_matrix(); - m_matrix.coeffRef(i,j) = val; - } - else - { - m_triplets.push_back(Triplet(i,j,val)); - } - } - } - - /// Write access to a matrix coefficient: a_ij <- a_ij + val. - /// - /// \warning For symmetric matrices, Eigen_sparse_matrix only stores the lower triangle - /// `add_coef()` does nothing if (i, j) belongs to the upper triangle. - /// - /// \pre 0 <= i < row_dimension(). - /// \pre 0 <= j < column_dimension(). - void add_coef(std::size_t i_, std::size_t j_, T val) - { - int i = static_cast(i_); - int j = static_cast(j_); - if(m_is_symmetric && (j > i)) - return; - - if(m_is_already_built){ - CGAL_precondition(i < row_dimension()); - CGAL_precondition(j < column_dimension()); - m_matrix.coeffRef(i,j) += val; - }else{ - m_triplets.push_back(Triplet(i,j,val)); - } - } - - /// Read access to a matrix coefficient. - /// - /// \warning Complexity: - /// - O(log(n)) if the matrix is already built. - /// - O(n) if the matrix is not built. - /// `n` being the number of entries in the matrix. - /// - /// \pre 0 <= i < row_dimension(). - /// \pre 0 <= j < column_dimension(). - NT get_coef (std::size_t i_, std::size_t j_) const - { - int i = static_cast(i_); - int j = static_cast(j_); - CGAL_precondition(i < row_dimension()); - CGAL_precondition(j < column_dimension()); - - if(m_is_symmetric && j > i) - std::swap(i, j); - - if (m_is_already_built) - return m_matrix.coeffRef(i,j); - else - { - NT val = 0; - for(std::size_t t=0; t release some memory - // -> required for some external solvers - m_matrix.makeCompressed(); - return m_matrix; - } - - /// Return the internal matrix, with type `EigenType`. - EigenType& eigen_object() - { - if(!m_is_already_built) - assemble_matrix(); - - // turns the matrix into compressed mode: - // -> release some memory - // -> required for some external solvers - m_matrix.makeCompressed(); - return m_matrix; - } - - -public: - - /// \cond SKIP_IN_MANUAL - friend Eigen_sparse_matrix - operator*(const T& c, const Eigen_sparse_matrix& M) - { - return Eigen_sparse_matrix(c* M.eigen_object()); - } - - - friend Eigen_sparse_matrix - operator+(const Eigen_sparse_matrix& M0, const Eigen_sparse_matrix& M1) - { - return Eigen_sparse_matrix(M0.eigen_object()+ M1.eigen_object()); - } - /// \endcond - - - // Fields -private: - mutable bool m_is_already_built; - - typedef Eigen::Triplet Triplet; - mutable std::vector m_triplets; - - mutable EigenType m_matrix; - - // Symmetric/hermitian? - bool m_is_symmetric; -}; // Eigen_sparse_matrix - - -/*! -\ingroup PkgSolverInterfaceRef - -The class `Eigen_sparse_symmetric_matrix` is a wrapper around `Eigen` matrix type -`Eigen::SparseMatrix` - -Since the matrix is symmetric, only the lower triangle part is stored. - -\cgalModels `SparseLinearAlgebraTraits_d::Matrix` - -\tparam T Number type. - -\sa `CGAL::Eigen_vector` -\sa `CGAL::Eigen_sparse_matrix` -*/ - -template -struct Eigen_sparse_symmetric_matrix - : public Eigen_sparse_matrix -{ - /// Create a square *symmetric* matrix initialized with zeros. - Eigen_sparse_symmetric_matrix(int dim) ///< Matrix dimension. - : Eigen_sparse_matrix(dim, true /* symmetric */) - { - } - - /// Create a square *symmetric* matrix initialized with zeros. - /// - /// \pre rows == columns. - Eigen_sparse_symmetric_matrix(int rows, ///< Number of rows. - int columns) ///< Number of columns. - : Eigen_sparse_matrix(rows, columns, true /* symmetric */) - { - } -}; - -/*! -\ingroup PkgSolverInterfaceRef - The class `Eigen_matrix` is a wrapper around `Eigen` matrix type `Eigen::Matrix`. diff --git a/Solver_interface/include/CGAL/Eigen_sparse_matrix.h b/Solver_interface/include/CGAL/Eigen_sparse_matrix.h new file mode 100644 index 00000000000..54d8663d5ca --- /dev/null +++ b/Solver_interface/include/CGAL/Eigen_sparse_matrix.h @@ -0,0 +1,335 @@ +// Copyright (c) 2012 INRIA Bordeaux Sud-Ouest (France), All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Gael Guennebaud + +#ifndef CGAL_SOLVER_INTERFACE_EIGEN_SPARSE_MATRIX_H +#define CGAL_SOLVER_INTERFACE_EIGEN_SPARSE_MATRIX_H + +#include // include basic.h before testing #defines + +#include + +namespace CGAL { + +/*! +\ingroup PkgSolverInterfaceRef + +The class `Eigen_sparse_matrix` is a wrapper around `Eigen` matrix type +`Eigen::SparseMatrix` +that represents general matrices, be they symmetric or not. + +\cgalModels `SparseLinearAlgebraTraits_d::Matrix` + +\tparam T Number type. + +\sa `CGAL::Eigen_vector` +\sa `CGAL::Eigen_matrix` +\sa `CGAL::Eigen_sparse_symmetric_matrix` +*/ +template +struct Eigen_sparse_matrix +{ + // Public types +public: + /// \name Types + /// @{ + + /// The internal matrix type from \ref thirdpartyEigen "Eigen". + typedef Eigen::SparseMatrix EigenType; + + typedef T NT; + /// @} + + Eigen_sparse_matrix(const EigenType& et) + : m_is_already_built(true), m_matrix(et), m_is_symmetric(false) + {} + + // Public operations +public: + Eigen_sparse_matrix() : m_is_already_built(false) { } + + /// Create a square matrix initialized with zeros. + Eigen_sparse_matrix(std::size_t dim, ///< Matrix dimension. + bool is_symmetric = false) ///< Symmetric/hermitian? + : + m_is_already_built(false), + m_matrix(static_cast(dim), static_cast(dim)) + { + CGAL_precondition(dim > 0); + + m_is_symmetric = is_symmetric; + m_triplets.reserve(dim); // reserve memory for a regular 3D grid + } + + /// Create a square matrix initialized with zeros. + Eigen_sparse_matrix(int dim, ///< Matrix dimension. + bool is_symmetric = false) ///< Symmetric/hermitian? + : m_is_already_built(false), + m_matrix(dim, dim) + { + CGAL_precondition(dim > 0); + + m_is_symmetric = is_symmetric; + // reserve memory for a regular 3D grid + m_triplets.reserve(dim); + } + + /// Create a rectangular matrix initialized with zeros. + /// + /// \pre rows == columns if `is_symmetric` is true. + Eigen_sparse_matrix(std::size_t rows, ///< Number of rows. + std::size_t columns, ///< Number of columns. + bool is_symmetric = false) ///< Symmetric/hermitian? + : m_is_already_built(false), + m_matrix(static_cast(rows), static_cast(columns)) + { + CGAL_precondition(rows > 0); + CGAL_precondition(columns > 0); + if(m_is_symmetric) + { + CGAL_precondition(rows == columns); + } + + m_is_symmetric = is_symmetric; + // reserve memory for a regular 3D grid + m_triplets.reserve(rows); + } + + void swap(Eigen_sparse_matrix& other) + { + std::swap(m_is_already_built, other.m_is_already_built); + std::swap(m_is_symmetric, other.m_is_symmetric); + m_matrix.swap(other.m_matrix); + m_triplets.swap(other.m_triplets); + } + + /// Delete this object and the wrapped matrix. + ~Eigen_sparse_matrix() { } + + /// Create a rectangular matrix initialized with zeros. + /// + /// \pre rows == columns if `is_symmetric` is true. + Eigen_sparse_matrix(int rows, ///< Number of rows. + int columns, ///< Number of columns. + bool is_symmetric = false) ///< Symmetric/hermitian? + : m_is_already_built(false), + m_matrix(rows,columns) + { + CGAL_precondition(rows > 0); + CGAL_precondition(columns > 0); + if(is_symmetric) + { + CGAL_precondition(rows == columns); + } + + m_is_symmetric = is_symmetric; + // reserve memory for a regular 3D grid + m_triplets.reserve(rows); + } + + /// Return the matrix number of rows + int row_dimension() const { return static_cast(m_matrix.rows()); } + /// Return the matrix number of columns + int column_dimension() const { return static_cast(m_matrix.cols()); } + + /// Write access to a matrix coefficient: a_ij <- val. + /// + /// Users can optimize calls to this function by setting 'new_coef' to `true` + /// if the coefficient does not already exist in the matrix. + /// + /// \warning For symmetric matrices, `Eigen_sparse_matrix` only stores the lower triangle + /// and `set_coef()` does nothing if (i, j) belongs to the upper triangle. + /// + /// \pre 0 <= i < row_dimension(). + /// \pre 0 <= j < column_dimension(). + void set_coef(std::size_t i_, std::size_t j_, T val, bool new_coef = false) + { + int i = static_cast(i_); + int j = static_cast(j_); + CGAL_precondition(i < row_dimension()); + CGAL_precondition(j < column_dimension()); + + if (m_is_symmetric && (j > i)) + return; + + if(m_is_already_built) + { + m_matrix.coeffRef(i,j) = val; + } + else + { + if(new_coef == false) + { + assemble_matrix(); + m_matrix.coeffRef(i,j) = val; + } + else + { + m_triplets.push_back(Triplet(i,j,val)); + } + } + } + + /// Write access to a matrix coefficient: a_ij <- a_ij + val. + /// + /// \warning For symmetric matrices, Eigen_sparse_matrix only stores the lower triangle + /// `add_coef()` does nothing if (i, j) belongs to the upper triangle. + /// + /// \pre 0 <= i < row_dimension(). + /// \pre 0 <= j < column_dimension(). + void add_coef(std::size_t i_, std::size_t j_, T val) + { + int i = static_cast(i_); + int j = static_cast(j_); + if(m_is_symmetric && (j > i)) + return; + + if(m_is_already_built){ + CGAL_precondition(i < row_dimension()); + CGAL_precondition(j < column_dimension()); + m_matrix.coeffRef(i,j) += val; + }else{ + m_triplets.push_back(Triplet(i,j,val)); + } + } + + /// Read access to a matrix coefficient. + /// + /// \warning Complexity: + /// - O(log(n)) if the matrix is already built. + /// - O(n) if the matrix is not built. + /// `n` being the number of entries in the matrix. + /// + /// \pre 0 <= i < row_dimension(). + /// \pre 0 <= j < column_dimension(). + NT get_coef (std::size_t i_, std::size_t j_) const + { + int i = static_cast(i_); + int j = static_cast(j_); + CGAL_precondition(i < row_dimension()); + CGAL_precondition(j < column_dimension()); + + if(m_is_symmetric && j > i) + std::swap(i, j); + + if (m_is_already_built) + return m_matrix.coeffRef(i,j); + else + { + NT val = 0; + for(std::size_t t=0; t release some memory + // -> required for some external solvers + m_matrix.makeCompressed(); + return m_matrix; + } + + /// Return the internal matrix, with type `EigenType`. + EigenType& eigen_object() + { + if(!m_is_already_built) + assemble_matrix(); + + // turns the matrix into compressed mode: + // -> release some memory + // -> required for some external solvers + m_matrix.makeCompressed(); + return m_matrix; + } + +public: + /// \cond SKIP_IN_MANUAL + friend Eigen_sparse_matrix + operator*(const T& c, const Eigen_sparse_matrix& M) + { + return Eigen_sparse_matrix(c* M.eigen_object()); + } + + friend Eigen_sparse_matrix + operator+(const Eigen_sparse_matrix& M0, const Eigen_sparse_matrix& M1) + { + return Eigen_sparse_matrix(M0.eigen_object()+ M1.eigen_object()); + } + /// \endcond + + // Fields +private: + mutable bool m_is_already_built; + + typedef Eigen::Triplet Triplet; + mutable std::vector m_triplets; + + mutable EigenType m_matrix; + + // Symmetric/hermitian? + bool m_is_symmetric; +}; // Eigen_sparse_matrix + + +/*! +\ingroup PkgSolverInterfaceRef + +The class `Eigen_sparse_symmetric_matrix` is a wrapper around `Eigen` matrix type +`Eigen::SparseMatrix` + +Since the matrix is symmetric, only the lower triangle part is stored. + +\cgalModels `SparseLinearAlgebraTraits_d::Matrix` + +\tparam T Number type. + +\sa `CGAL::Eigen_vector` +\sa `CGAL::Eigen_sparse_matrix` +*/ +template +struct Eigen_sparse_symmetric_matrix + : public Eigen_sparse_matrix +{ + /// Create a square *symmetric* matrix initialized with zeros. + Eigen_sparse_symmetric_matrix(int dim) ///< Matrix dimension. + : Eigen_sparse_matrix(dim, true /* symmetric */) + { } + + /// Create a square *symmetric* matrix initialized with zeros. + /// + /// \pre rows == columns. + Eigen_sparse_symmetric_matrix(int rows, ///< Number of rows. + int columns) ///< Number of columns. + : Eigen_sparse_matrix(rows, columns, true /* symmetric */) + { } +}; + +} //namespace CGAL + +#endif // CGAL_SOLVER_INTERFACE_EIGEN_SPARSE_MATRIX_H From 566b6e89fb68644bcd0fdcde35baef461496a860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Dec 2019 18:43:46 +0100 Subject: [PATCH 068/150] Doc changes --- Optimal_bounding_box/doc/Optimal_bounding_box/Doxyfile.in | 4 ++-- Optimal_bounding_box/include/CGAL/optimal_bounding_box.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Doxyfile.in b/Optimal_bounding_box/doc/Optimal_bounding_box/Doxyfile.in index 26ad50050b8..d90bd9a87c0 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Doxyfile.in +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Doxyfile.in @@ -19,8 +19,8 @@ ALIASES += "cgalNPEnd=" MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES -EXPAND_AS_DEFINED = CGAL_OBB_NP_TEMPLATE_PARAMETERS \ - CGAL_OBB_NP_CLASS +EXPAND_AS_DEFINED = CGAL_BGL_NP_TEMPLATE_PARAMETERS \ + CGAL_BGL_NP_CLASS EXCLUDE = ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Optimal_bounding_box/internal EXCLUDE_SYMBOLS += experimental diff --git a/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h index e6723cb8027..72243171163 100644 --- a/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h @@ -159,7 +159,7 @@ void construct_optimal_bounding_box(std::array& obb /// \ingroup PkgOptimalBoundingBoxFunctions /// /// constructs a rectangular box that contains all the input points. This bounding box -/// is obtained via an optimization process aiming to get a close approximation to the +/// is obtained via an optimization process aiming to get a close approximation of the /// optimal bounding box. /// /// \tparam PointRange a model of `Range` with value type `Point` @@ -249,7 +249,7 @@ void optimal_bounding_box(const PointRange& points, /// \ingroup PkgOptimalBoundingBoxFunctions /// /// constructs a rectangular box that contains the input mesh. This bounding box -/// is obtained via an optimization process aiming to get a close approximation to the +/// is obtained via an optimization process aiming to get a close approximation of the /// optimal bounding box. /// /// \tparam PolygonMesh a model of `FaceListGraph` From ba1c21f3bd9138ff6e11262adfbbf4e3553f4f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Dec 2019 18:48:46 +0100 Subject: [PATCH 069/150] Enhance CGAL::Eigen_matrix --- Solver_interface/include/CGAL/Eigen_matrix.h | 48 ++++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/Solver_interface/include/CGAL/Eigen_matrix.h b/Solver_interface/include/CGAL/Eigen_matrix.h index ae661a4a129..c360a056872 100644 --- a/Solver_interface/include/CGAL/Eigen_matrix.h +++ b/Solver_interface/include/CGAL/Eigen_matrix.h @@ -28,36 +28,64 @@ The class `Eigen_matrix` is a wrapper around `Eigen` matrix type \cgalModels `SvdTraits::Matrix` \tparam T Number type. +\tparam D1 Number of rows, or Dynamic +\tparam D2 Number of columns, or Dynamic \sa `CGAL::Eigen_vector` \sa `CGAL::Eigen_sparse_matrix` \sa `CGAL::Eigen_sparse_symmetric_matrix` */ -template +template struct Eigen_matrix - : public ::Eigen::Matrix + : public ::Eigen::Matrix { /// The internal matrix type from \ref thirdpartyEigen "Eigen". - typedef ::Eigen::Matrix EigenType; + typedef ::Eigen::Matrix EigenType; - /// Construct a matrix with `nr` rows and `nc` columns. + /// Constructs a null matrix. + Eigen_matrix() { } + + /// Constructs an uninitialized matrix with `nr` rows and `nc` columns. + /// This is useful for dynamic-size matrices. + /// For fixed-size matrices, it is redundant to pass these parameters. Eigen_matrix(std::size_t nr, std::size_t nc) : EigenType(nr, nc) { } - /// Return the matrix number of rows. + /// Constructs a matrix from an Eigen matrix. + Eigen_matrix(const EigenType& b) : EigenType(b) { } + + /// Returns the matrix number of rows. std::size_t number_of_rows() const { return this->rows(); } - /// Return the matrix number of columns. + /// Returns the matrix number of columns. std::size_t number_of_columns() const { return this->cols(); } - /// Return the value of the matrix at position (i,j). + /// Returns the value of the matrix at position (i,j). FT operator()( std::size_t i , std::size_t j ) const { return EigenType::operator()(i,j); } - /// Write access to a matrix coefficient: `a_ij` <- `val`. + /// Writes access to a matrix coefficient: `a_ij` <- `val`. void set(std::size_t i, std::size_t j, FT value) { this->coeffRef(i,j) = value; } - /// Return the internal matrix, with type `EigenType`. + /// Returns the internal matrix, with type `EigenType`. const EigenType& eigen_object() const { return static_cast(*this); } + +public: + /// \cond SKIP_IN_MANUAL + friend Eigen_matrix operator*(const FT c, const Eigen_matrix& M) + { + return Eigen_matrix(c * M.eigen_object()); + } + + friend Eigen_matrix operator*(const Eigen_matrix& M0, const Eigen_matrix& M1) + { + return Eigen_matrix(M0.eigen_object() * M1.eigen_object()); + } + + friend Eigen_matrix operator+(const Eigen_matrix& M0, const Eigen_matrix& M1) + { + return Eigen_matrix(M0.eigen_object() + M1.eigen_object()); + } + /// \endcond }; } //namespace CGAL -#endif // CGAL_EIGEN_MATRIX_H +#endif // CGAL_SOLVER_INTERFACE_EIGEN_MATRIX_H From 6923b144f8f7e9da7013a1d1905c7772eda74a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Dec 2019 18:49:22 +0100 Subject: [PATCH 070/150] Add optimal bounding box traits concept --- .../Concepts/OptimalBoundingBoxTraits.h | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OptimalBoundingBoxTraits.h diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OptimalBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OptimalBoundingBoxTraits.h new file mode 100644 index 00000000000..8fcb42b3bc2 --- /dev/null +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OptimalBoundingBoxTraits.h @@ -0,0 +1,37 @@ +namespace CGAL { + +/*! +\ingroup PkgOptimalBoundingBoxConcepts +\cgalConcept + +The concept `OptimalBoundingBoxTraits` describes the requirements of the traits class +used in the function `CGAL::optimal_bounding_box()`, and in particular the need for +a 3x3 matrix type with a number of supporting functions (determinant and transposed matrix +computations, etc.). + +\cgalRefines `Kernel` + +\cgalHasModel `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits` + +*/ +class OptimalBoundingBoxTraits +{ +public: + /// The field number type; must be a model of the concept `FieldNumberType`. + typedef unspecified_type FT; + + /// A 3x3 matrix type; must be a model of the concept `SvdTraits::Matrix` and support + /// matrix-matrix and scalar-matrix multiplication, as well as matrix-matrix addition. + typedef unspecified_type Matrix; + + /// Returns the transpose of a matrix. + Matrix transpose(const Matrix& mat) const; + + /// Returns the determinant of a matrix. + FT determinant(const Matrix& matrix) const; + + /// Returns the unary matrix Q obtained in the QR decompoisiton of the matrix `A`. + Matrix qr_factorization(const Matrix& A) const; +}; + +} // namespace CGAL From db943b3b6fe328389bb155fd6ee03e1be47e6811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Dec 2019 18:54:46 +0100 Subject: [PATCH 071/150] Doc changes --- .../Concepts/OptimalBoundingBoxTraits.h | 8 ++++---- .../Optimal_bounding_box/PackageDescription.txt | 2 +- .../Optimal_bounding_box_traits.h | 6 +++--- .../Optimal_bounding_box/internal/evolution.h | 4 ++-- .../internal/nelder_mead_functions.h | 8 ++++---- .../Optimal_bounding_box/internal/population.h | 2 +- .../include/CGAL/optimal_bounding_box.h | 15 +++++++++------ .../test_linear_algebra_functions.cpp | 8 ++++---- .../test_optimization_algorithms.cpp | 6 +++--- 9 files changed, 31 insertions(+), 28 deletions(-) diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OptimalBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OptimalBoundingBoxTraits.h index 8fcb42b3bc2..e41a29d0e4b 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OptimalBoundingBoxTraits.h +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OptimalBoundingBoxTraits.h @@ -18,20 +18,20 @@ class OptimalBoundingBoxTraits { public: /// The field number type; must be a model of the concept `FieldNumberType`. - typedef unspecified_type FT; + typedef unspecified_type FT; /// A 3x3 matrix type; must be a model of the concept `SvdTraits::Matrix` and support /// matrix-matrix and scalar-matrix multiplication, as well as matrix-matrix addition. - typedef unspecified_type Matrix; + typedef unspecified_type Matrix; /// Returns the transpose of a matrix. Matrix transpose(const Matrix& mat) const; /// Returns the determinant of a matrix. - FT determinant(const Matrix& matrix) const; + FT compute_determinant(const Matrix& matrix) const; /// Returns the unary matrix Q obtained in the QR decompoisiton of the matrix `A`. - Matrix qr_factorization(const Matrix& A) const; + Matrix get_Q(const Matrix& A) const; }; } // namespace CGAL diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt index 156f50dc13e..dfa00bd717d 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt @@ -20,7 +20,7 @@ \cgalPkgSummaryEnd \cgalPkgShortInfoBegin \cgalPkgSince{5.1} -\cgalPkgDependsOn{documented for each function;} +\cgalPkgDependsOn{\ref PkgConvexHull3} \cgalPkgBib{cgal:obb} \cgalPkgLicense{\ref licensesGPL "GPL"} \cgalPkgDemo{Polyhedron demo, polyhedron_3.zip} diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h index a570cdc2412..9d06fc69ab6 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h @@ -61,17 +61,17 @@ public: } /// Get the determinant of a matrix - FT determinant(const Matrix& matrix) const + FT compute_determinant(const Matrix& matrix) const { return matrix.eigen_object().determinant(); } /// Performs QR decomposition of matrix A to a unitary matrix and an upper triagonal /// and returns the unitary matrix. - Matrix qr_factorization(const Matrix& A) const + Matrix get_Q(const Matrix& A) const { Eigen::HouseholderQR qr(A.eigen_object()); - CGAL_assertion(CGAL::abs(determinant(Matrix(EigenType(qr.householderQ()))) - 1.) < 0.000001); + CGAL_assertion(CGAL::abs(compute_determinant(Matrix(EigenType(qr.householderQ()))) - 1.) < 0.000001); return Matrix(EigenType(qr.householderQ())); } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index cc1bd28350a..cfd1b4b590e 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -129,7 +129,7 @@ public: new_vertex.set(2, 1, lambda * lm(2, 1) + rambda * rm(2, 1)); new_vertex.set(2, 2, lambda * lm(2, 2) + rambda * rm(2, 2)); - offspring[j] = m_traits.qr_factorization(new_vertex); + offspring[j] = m_traits.get_Q(new_vertex); } new_simplices[first_group_size + i] = std::move(offspring); @@ -177,7 +177,7 @@ public: //pop.show_population(); //std::cout << std::endl; const Matrix& R_now = fitness_map.get_best(); - std::cout << "det = " << m_traits.determinant(R_now) << std::endl; + std::cout << "det = " << m_traits.compute_determinant(R_now) << std::endl; #endif new_fit_value = fitness_map.get_best_fitness_value(); diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h index 8f080095320..b6966b71940 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h @@ -61,8 +61,8 @@ Matrix mean(const Matrix& m1, CGAL_assertion(m2.number_of_rows() == 3 && m2.number_of_columns() == 3); const Matrix reduction = 0.5 * m1 + 0.5 * m2; - const Matrix Q = traits.qr_factorization(reduction); - const typename Traits::FT det = traits.determinant(Q); + const Matrix Q = traits.get_Q(reduction); + const typename Traits::FT det = traits.compute_determinant(Q); return (1. / det) * Q; } @@ -74,8 +74,8 @@ const Matrix nm_centroid(const Matrix& S1, const Traits& traits) { const Matrix mean = (1./3.) * (S1 + S2 + S3); - const Matrix Q = traits.qr_factorization(mean); - const typename Traits::FT det = traits.determinant(Q); + const Matrix Q = traits.get_Q(mean); + const typename Traits::FT det = traits.compute_determinant(Q); return (1. / det) * Q; } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h index 640b4423a71..1244c289230 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h @@ -54,7 +54,7 @@ private: { Simplex simplex; for(std::size_t i=0; i<4; ++i) - simplex[i] = m_traits.qr_factorization(create_vertex(rng)); + simplex[i] = m_traits.get_Q(create_vertex(rng)); return simplex; } diff --git a/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h index 72243171163..63ceaa998a4 100644 --- a/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h @@ -160,12 +160,13 @@ void construct_optimal_bounding_box(std::array& obb /// /// constructs a rectangular box that contains all the input points. This bounding box /// is obtained via an optimization process aiming to get a close approximation of the -/// optimal bounding box. +/// optimal bounding box, which is defined as the smallest (in terms of volume) +/// of all the rectangular boxes containing the input points. /// /// \tparam PointRange a model of `Range` with value type `Point` /// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" /// -/// \param points the input points that the optimal bounding box will contain +/// \param points the input points /// \param obb_points the eight points of the resulting englobing box. /// The order of points is the same as in the function `CGAL::make_hexahedron()` /// \param np an optional sequence of \ref obb_namedparameters "Named Parameters" among the ones listed below: @@ -179,7 +180,7 @@ void construct_optimal_bounding_box(std::array& obb /// \cgalParamBegin{geom_traits} /// a geometric traits class instance, model of the concept `OptimalBoundingBoxTraits`. %Default is /// `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits` where `K` is deduced -/// from the point type, which must be compatible with `CGAL::Kernel_traits`. +/// from the point type, which must then be compatible with `CGAL::Kernel_traits`. /// \cgalParamEnd /// \cgalParamBegin{use_convex_hull} /// a Boolean value to indicate whether the algorithm should first extract the so-called extreme @@ -189,6 +190,8 @@ void construct_optimal_bounding_box(std::array& obb /// \cgalParamEnd /// \cgalNamedParamsEnd /// +/// \pre the value type of `PointRange` is `Point` +/// template @@ -250,14 +253,14 @@ void optimal_bounding_box(const PointRange& points, /// /// constructs a rectangular box that contains the input mesh. This bounding box /// is obtained via an optimization process aiming to get a close approximation of the -/// optimal bounding box. +/// optimal bounding box, which is defined as the smallest (in terms of volume) +/// of all the rectangular boxes containing the input mesh. /// /// \tparam PolygonMesh a model of `FaceListGraph` /// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" /// /// \param pmesh the input mesh -/// \param obb_mesh the eight points of the resulting englobing box. -/// The order of points is the same as in the function `CGAL::make_hexahedron()` +/// \param obb_mesh the resulting enclosing bounding box (an hexahedron) /// \param np an optional sequence of \ref obb_namedparameters "Named Parameters" among the ones listed below: /// /// \cgalNamedParamsBegin diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp index 5ae7753271f..9482f15ff49 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp @@ -9,7 +9,7 @@ bool assert_doubles(double d1, double d2, double epsilon) return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; } -void test_qr_factorization() +void test_get_Q() { typedef CGAL::Eigen_dense_matrix Mat; Mat A(3, 3); @@ -23,7 +23,7 @@ void test_qr_factorization() A.set_coef(2, 1, 0.0202949); A.set_coef(2, 2, 0.9240308); - CGAL_assertion_code(Mat Q = CGAL::Eigen_linear_algebra_traits::qr_factorization(A)); + CGAL_assertion_code(Mat Q = CGAL::Eigen_linear_algebra_traits::get_Q(A)); CGAL_assertion_code(double epsilon = 1e-6); CGAL_assertion(assert_doubles(Q(0,0), -0.504895, epsilon)); CGAL_assertion(assert_doubles(Q(0,1), 0.862834, epsilon)); @@ -243,7 +243,7 @@ void test_eigen_matrix_interface() C.set_coef(2, 1, 0.0202949); C.set_coef(2, 2, 0.9240308); - CGAL_assertion_code(Matrix Q = CGAL::Eigen_linear_algebra_traits::qr_factorization(C)); + CGAL_assertion_code(Matrix Q = CGAL::Eigen_linear_algebra_traits::get_Q(C)); CGAL_assertion_code(double epsilon = 1e-5); CGAL_assertion(assert_doubles(Q(0,0), -0.504895, epsilon)); CGAL_assertion(assert_doubles(Q(0,1), 0.862834, epsilon)); @@ -291,7 +291,7 @@ void test_eigen_matrix_interface() int main() { - test_qr_factorization(); + test_get_Q(); test_fitness_function(); test_simplex_operations(); test_centroid(); diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index fd8eb60b8f0..7284bbc5fe3 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -208,7 +208,7 @@ void test_random_unit_tetra() Matrix R = evolution.get_best(); const double epsilon = 1e-3; - assert(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); + assert(assert_doubles(Linear_algebra_traits::compute_determinant(R), 1, epsilon)); assert(assert_doubles(R(0,0), -0.25791, epsilon)); assert(assert_doubles(R(0,1), 0.796512, epsilon)); assert(assert_doubles(R(0,2), -0.546855, epsilon)); @@ -249,7 +249,7 @@ void test_reference_tetrahedron(const char* fname) Matrix R = experiment.get_best(); double epsilon = 1e-5; - assert(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); + assert(assert_doubles(Linear_algebra_traits::compute_determinant(R), 1, epsilon)); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST // postprocessing @@ -282,7 +282,7 @@ void test_long_tetrahedron(const std::string fname) Matrix R = experiment.get_best(); double epsilon = 1e-3; - assert(assert_doubles(Linear_algebra_traits::determinant(R), 1, epsilon)); + assert(assert_doubles(Linear_algebra_traits::compute_determinant(R), 1, epsilon)); assert(assert_doubles(R(0,0), -1, epsilon)); assert(assert_doubles(R(0,1), 0, epsilon)); assert(assert_doubles(R(0,2), 0, epsilon)); From 4f56fdff8ebe1ef52aacc7671011a70b767b7976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Dec 2019 08:18:53 +0100 Subject: [PATCH 072/150] Minor addition to the SVD::Matrix concept --- Solver_interface/doc/Solver_interface/Concepts/SvdTraits.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Solver_interface/doc/Solver_interface/Concepts/SvdTraits.h b/Solver_interface/doc/Solver_interface/Concepts/SvdTraits.h index d6f9b934330..7811be49788 100644 --- a/Solver_interface/doc/Solver_interface/Concepts/SvdTraits.h +++ b/Solver_interface/doc/Solver_interface/Concepts/SvdTraits.h @@ -86,6 +86,9 @@ public: \cgalConcept Concept of matrix type used by the concept `SvdTraits`. +\cgalRefines `DefaultConstructible` +\cgalRefines `Assignable` + \cgalHasModel `CGAL::Eigen_matrix` */ class SvdTraits::Matrix From 0ae811604ac61d88481ce22ed0b2ff8a4d5bc2ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Dec 2019 13:32:55 +0100 Subject: [PATCH 073/150] Update code/doc after pre-review --- .../Concepts/OptimalBoundingBoxTraits.h | 37 -- .../Concepts/OrientedBoundingBoxTraits.h | 45 +++ .../Optimal_bounding_box/NamedParameters.txt | 2 +- .../PackageDescription.txt | 9 +- .../Optimal_bounding_box/obb_example.cpp | 18 +- ...raits.h => Oriented_bounding_box_traits.h} | 29 +- .../Optimal_bounding_box/internal/evolution.h | 17 +- .../internal/fitness_function.h | 4 +- .../oriented_bounding_box.h | 370 ++++++++++++++++++ .../include/CGAL/optimal_bounding_box.h | 322 +-------------- 10 files changed, 477 insertions(+), 376 deletions(-) delete mode 100644 Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OptimalBoundingBoxTraits.h create mode 100644 Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h rename Optimal_bounding_box/include/CGAL/Optimal_bounding_box/{Optimal_bounding_box_traits.h => Oriented_bounding_box_traits.h} (70%) create mode 100644 Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OptimalBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OptimalBoundingBoxTraits.h deleted file mode 100644 index e41a29d0e4b..00000000000 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OptimalBoundingBoxTraits.h +++ /dev/null @@ -1,37 +0,0 @@ -namespace CGAL { - -/*! -\ingroup PkgOptimalBoundingBoxConcepts -\cgalConcept - -The concept `OptimalBoundingBoxTraits` describes the requirements of the traits class -used in the function `CGAL::optimal_bounding_box()`, and in particular the need for -a 3x3 matrix type with a number of supporting functions (determinant and transposed matrix -computations, etc.). - -\cgalRefines `Kernel` - -\cgalHasModel `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits` - -*/ -class OptimalBoundingBoxTraits -{ -public: - /// The field number type; must be a model of the concept `FieldNumberType`. - typedef unspecified_type FT; - - /// A 3x3 matrix type; must be a model of the concept `SvdTraits::Matrix` and support - /// matrix-matrix and scalar-matrix multiplication, as well as matrix-matrix addition. - typedef unspecified_type Matrix; - - /// Returns the transpose of a matrix. - Matrix transpose(const Matrix& mat) const; - - /// Returns the determinant of a matrix. - FT compute_determinant(const Matrix& matrix) const; - - /// Returns the unary matrix Q obtained in the QR decompoisiton of the matrix `A`. - Matrix get_Q(const Matrix& A) const; -}; - -} // namespace CGAL diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h new file mode 100644 index 00000000000..5c8ed9ecda9 --- /dev/null +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h @@ -0,0 +1,45 @@ +namespace CGAL { + +/*! +\ingroup PkgOrientedBoundingBoxConcepts +\cgalConcept + +The concept `OrientedBoundingBoxTraits` describes the requirements of the traits class +used in the function `CGAL::oriented_bounding_box()`, and in particular the need for +a 3x3 matrix type with a number of supporting functions (determinant and transposed matrix +computations, etc.). + +\cgalRefines `Kernel` + +\cgalHasModel `CGAL::Oriented_bounding_box_traits` + +*/ +class OrientedBoundingBoxTraits +{ +public: + /// The field number type; must be a model of the concept `FieldNumberType`. + typedef unspecified_type FT; + + /// The 3D point type; must be model of `Point_3` + typedef unspecified_type Point_3; + + /// A construction object that must provide the function operator: + /// `CGAL::Bbox_3 operator()(const Point_3&)`, + /// which returns an axis-aligned bounding that contains the point + typedef unspecified_type Construct_bbox_3; + + /// A 3x3 matrix type; model of the concept `SvdTraits::Matrix` and which supports + /// matrix-matrix and scalar-matrix multiplication, as well as matrix-matrix addition. + typedef unspecified_type Matrix; + + /// Returns the transpose of a matrix. + Matrix transpose(const Matrix& mat) const; + + /// Returns the determinant of a matrix. + FT compute_determinant(const Matrix& matrix) const; + + /// Returns the unary matrix Q obtained in the QR decomposition of the matrix `A`. + Matrix get_Q(const Matrix& A) const; +}; + +} // namespace CGAL diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt index 68fed836345..3ef83f1f9ae 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt @@ -45,7 +45,7 @@ is the geometric traits instance in which the mesh processing operation should b \cgalNPEnd \cgalNPBegin{use_convex_hull} \anchor OBB_use_convex_hull -Parameter used in optimal bounding box construction to indicate whether the algorithm should +Parameter used in the construction of oriented bounding box to indicate whether the algorithm should first extract the extreme points (points that are on the 3D convex hull) of the input data range to accelerate the computation of the bounding box. \n diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt index dfa00bd717d..e5b5e9f4b5c 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt @@ -9,6 +9,9 @@ /// \defgroup PkgOptimalBoundingBoxFunctions Optimal Bounding Box Methods /// \ingroup PkgOptimalBoundingBoxRef +/// \defgroup PkgOptimalBoundingBox_Oriented_bounding_box Oriented Bounding Box Methods +/// \ingroup PkgOptimalBoundingBoxFunctions + /*! \addtogroup PkgOptimalBoundingBoxRef \cgalPkgDescriptionBegin{Optimal Bounding Box,PkgOptimalBoundingBox} @@ -37,14 +40,14 @@ that are used in this package. \cgalCRPSection{Concepts} -- `CGAL::OptimalBoundingBoxTraits` +- `CGAL::OrientedBoundingBoxTraits` \cgalCRPSection{Classes} -- `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits` +- `CGAL::Oriented_bounding_box_traits` \cgalCRPSection{Methods} -- `CGAL::optimal_bounding_box()` +- \link PkgOptimalBoundingBox_Oriented_bounding_box `CGAL::oriented_bounding_box()` \endlink */ diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp index 0f57de2d168..9cf1ddfd825 100644 --- a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp @@ -4,12 +4,14 @@ #include #include +#include #include #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point; +typedef K::Aff_transformation_3 Aff_transformation; typedef CGAL::Surface_mesh Surface_mesh; int main(int argc, char** argv) @@ -22,9 +24,21 @@ int main(int argc, char** argv) return EXIT_FAILURE; } - // test one + Aff_transformation aff; + + // API test + CGAL::Real_timer timer; + timer.start(); + + std::array obb_points; + CGAL::oriented_bounding_box(sm, obb_points); + + std::cout << "Elapsed time: " << timer.time() << std::endl; + + // Make a mesh out of the oriented bounding box Surface_mesh obb_sm; - CGAL::optimal_bounding_box(sm, obb_sm); + CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], + obb_points[4], obb_points[5], obb_points[6], obb_points[7], obb_sm); std::ofstream("obb.off") << obb_sm; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h similarity index 70% rename from Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h rename to Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h index 9d06fc69ab6..63e5bae7ec4 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Optimal_bounding_box_traits.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h @@ -21,29 +21,36 @@ #endif namespace CGAL { -namespace Optimal_bounding_box { #if defined(CGAL_EIGEN3_ENABLED) || defined(DOXYGEN_RUNNING) /// \ingroup PkgOptimalBoundingBoxClasses /// -/// The class `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits` is a traits type -/// to be used with the functions `CGAL::optimal_bounding_box()`. +/// The class `CGAL::Oriented_bounding_box_traits` is a traits type +/// to be used with the functions `CGAL::oriented_bounding_box()`. /// It uses the third party library \ref thirdpartyEigen "Eigen", which must therefore /// be available on the system for this class to be used. /// /// \tparam K must be a model of `Kernel` /// -/// \cgalModels `OptimalBoundingBoxTraits` +/// \cgalModels `OrientedBoundingBoxTraits` /// template -class Optimal_bounding_box_traits - : public K +class Oriented_bounding_box_traits { public: /// The field number type typedef typename K::FT FT; + /// The point type + typedef typename K::Point_3 Point_3; + + /// The affine transformation type + typedef typename K::Aff_transformation_3 Aff_transformation_3; + + /// The axis-aligned bounding box construction object + typedef typename K::Construct_bbox_3 Construct_bbox_3; + /// The matrix type typedef CGAL::Eigen_matrix Matrix; @@ -52,15 +59,18 @@ private: public: /// Constructor from the base kernel - explicit Optimal_bounding_box_traits(const K& k = K()) : K(k) { } + explicit Oriented_bounding_box_traits() { } - /// Get the transpose of a matrix + /// Offers `construct_bbox_3_object()(const Point_3&)` + Construct_bbox_3 construct_bbox_3_object() const { return Construct_bbox_3(); } + + /// Returns the transpose of a matrix Matrix transpose(const Matrix& mat) const { return Matrix(mat.eigen_object().transpose()); } - /// Get the determinant of a matrix + /// Returns the determinant of a matrix FT compute_determinant(const Matrix& matrix) const { return matrix.eigen_object().determinant(); @@ -78,7 +88,6 @@ public: }; #endif // defined(CGAL_EIGEN3_ENABLED) || defined(DOXYGEN_RUNNING) -} // namespace Optimal_bounding_box } // namespace CGAL #endif // CGAL_OPTIMAL_BOUNDING_BOX_BOUNDING_BOX_TRAITS_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index cfd1b4b590e..b8c0ecae405 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -49,7 +49,7 @@ public: const Traits& traits) : m_population(traits), - m_rng(rng), // @todo just a parameter of genetic_algorithm() ? + m_rng(rng), m_points(points), m_traits(traits) { } @@ -144,12 +144,12 @@ public: const std::size_t population_size = 50; // hardcoded nelder_mead_iterations - const std::size_t nelder_mead_iterations = 20; + const std::size_t nelder_mead_iterations = 150; // stopping criteria prameters double prev_fit_value = 0.; double new_fit_value = 0.; - const double tolerance = 1e-2; + const double tolerance = 1e-9; int stale = 0; for(std::size_t t=0; t= 3); FT xmin, ymin, zmin, xmax, ymax, zmax; - xmin = ymin = zmin = std::numeric_limits::max(); - xmax = ymax = zmax = std::numeric_limits::lowest(); + xmin = ymin = zmin = FT(std::numeric_limits::max()); + xmax = ymax = zmax = FT(std::numeric_limits::lowest()); for(const Point& pt : points) { diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h new file mode 100644 index 00000000000..2f2771d3a8e --- /dev/null +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -0,0 +1,370 @@ +// Copyright (c) 2018-2019 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Mael Rouxel-Labbé +// +#ifndef CGAL_OPTIMAL_BOUNDING_BOX_ORIENTED_BOUNDING_BOX_H +#define CGAL_OPTIMAL_BOUNDING_BOX_ORIENTED_BOUNDING_BOX_H + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS +#include +#endif + +#include +#include +#include +#include +#include + +#ifdef DOXYGEN_RUNNING +#define CGAL_BGL_NP_TEMPLATE_PARAMETERS NamedParameters +#define CGAL_BGL_NP_CLASS NamedParameters +#endif + +namespace CGAL { +namespace Optimal_bounding_box { +namespace internal { + +template +void construct_oriented_bounding_box(std::array& obb_points, + const typename Traits::Aff_transformation_3& transformation, + const typename Traits::Aff_transformation_3& inverse_transformation, + const PointRange& points, + const Traits& traits) +{ + typedef typename Traits::FT FT; + typedef typename Traits::Point_3 Point; + + // Construct the bbox of the transformed point set + CGAL::Bbox_3 bbox; + for(const Point& pt : points) + { + const Point rotated_pt = transformation.transform(pt); + bbox += traits.construct_bbox_3_object()(rotated_pt); + } + + obb_points[0] = Point(bbox.xmin(), bbox.ymin(), bbox.zmin()); + obb_points[1] = Point(bbox.xmax(), bbox.ymin(), bbox.zmin()); + obb_points[2] = Point(bbox.xmax(), bbox.ymax(), bbox.zmin()); + obb_points[3] = Point(bbox.xmin(), bbox.ymax(), bbox.zmin()); + + obb_points[4] = Point(bbox.xmin(), bbox.ymax(), bbox.zmax()); // see order in make_hexahedron()... + obb_points[5] = Point(bbox.xmin(), bbox.ymin(), bbox.zmax()); + obb_points[6] = Point(bbox.xmax(), bbox.ymin(), bbox.zmax()); + obb_points[7] = Point(bbox.xmax(), bbox.ymax(), bbox.zmax()); + + // Apply the inverse rotation to the rotated axis aligned bounding box + for(std::size_t i=0; i<8; ++i) + obb_points[i] = inverse_transformation.transform(obb_points[i]); +} + +template +void compute_best_transformation(typename Traits::Aff_transformation_3& transformation, + typename Traits::Aff_transformation_3& inverse_transformation, + const PointRange& points, + CGAL::Random& rng, + const Traits& traits) +{ + typedef typename Traits::Matrix Matrix; + typedef typename Traits::Aff_transformation_3 Aff_transformation_3; + + const std::size_t max_generations = 50; // @todo hidden NP + +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS + CGAL::Real_timer timer; + timer.start(); +#endif + + Evolution search_solution(points, rng, traits); + search_solution.evolve(max_generations); + +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS + std::cout << "evolve: " << timer.time() << std::endl; + timer.reset(); +#endif + + const Matrix& rot = search_solution.get_best(); + +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS + std::cout << "get best: " << timer.time() << std::endl; +#endif + + transformation = Aff_transformation_3(rot(0, 0), rot(0, 1), rot(0, 2), + rot(1, 0), rot(1, 1), rot(1, 2), + rot(2, 0), rot(2, 1), rot(2, 2)); + + // inverse transformation is simply the transposed since the matrix is unary + inverse_transformation = Aff_transformation_3(rot(0, 0), rot(1, 0), rot(2, 0), + rot(0, 1), rot(1, 1), rot(2, 1), + rot(0, 2), rot(1, 2), rot(2, 2)); +} + +// Following two functions are overload to dispatch depending on return type +template +void construct_oriented_bounding_box(typename Traits::Aff_transformation_3& transformation, + const PointRange& points, + CGAL::Random& rng, + const Traits& traits) +{ + typename Traits::Aff_transformation_3 inverse_transformation; + compute_best_transformation(transformation, inverse_transformation, points, rng, traits); +} + +template +void construct_oriented_bounding_box(std::array& obb_points, + const PointRange& points, + CGAL::Random& rng, + const Traits& traits) +{ + typename Traits::Aff_transformation_3 transformation, inverse_transformation; + compute_best_transformation(transformation, inverse_transformation, points, rng, traits); + + construct_oriented_bounding_box(obb_points, transformation, inverse_transformation, points, traits); +} + +// Entry point, decide whether to compute the CH_3 or not +template +void construct_oriented_bounding_box(Output& output, + const bool use_ch, + const PointRange& points, + CGAL::Random& rng, + const Traits& traits) +{ + typedef typename Traits::Matrix Matrix; + typedef typename Traits::Point_3 Point; + + CGAL_static_assertion((std::is_same::type, Point>::value)); + + if(use_ch) // construct the convex hull to reduce the number of points + { + std::vector ch_points; + extreme_points_3(points, std::back_inserter(ch_points)); + std::cout << "points on CH: " << ch_points.size() << std::endl; + return construct_oriented_bounding_box(output, ch_points, rng, traits); + } + else + { + return construct_oriented_bounding_box(output, points, rng, traits); + } +} + +} // namespace Optimal_bounding_box +} // namespace internal + +/// \addtogroup PkgOptimalBoundingBox_Oriented_bounding_box +/// +/// The function `oriented_bounding_box` computes an approximation of the optimal bounding box, +/// which is defined as the rectangular box with smallest volume of all the rectangular boxes containing +/// the input points. +/// +/// Internally, the algorithm uses an optimization process to find a transformation (rotation) +/// \f$ {\mathcal R}_b\f$ such that the axis-aligned box of the rotated input point set +/// has a volume that is as small as possible. +/// +/// \cgalHeading{Input} +/// +/// The input can be either a range of points, or a polygon mesh. +/// +/// \cgalHeading{Output} +/// +/// The result of the algorithm can be obtained as either: +/// - the best affine transformation (\f$ {\mathcal R}_b\f$) that the algorithm has found; +/// - an array of eight points, representing the best oriented bounding box (\f$ {\mathcal B}_b\f$) +/// that the algorithm has constructed, which is related to (\f$ {\mathcal R}_b\f$) as it is +/// the inverse transformation of the axis-aligned bounding box of the transformed point set. +/// The order of the points in the array is the same as in the function +/// \link PkgBGLHelperFct `CGAL::make_hexahedron()` \endlink, +/// which is a useful function to construct a mesh from these points. +/// +/// Note that when returning an array of points, these points are constructed from the axis-aligned +/// bounding box and some precision loss should be expected if a kernel not providing exact constructions +/// is used. + +/// \ingroup PkgOptimalBoundingBox_Oriented_bounding_box +/// +/// See above. +/// +/// \tparam PointRange a model of `Range` +/// \tparam Output `std::array` with `Point` being equivalent to the traits' `Point_3` type, +/// or `CGAL::Affine_transformation_3` with `K` being a kernel compatible with the point type. +/// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" +/// +/// \param points the input points +/// \param out the resulting array of points or affine transformation +/// \param np an optional sequence of \ref obb_namedparameters "Named Parameters" among the ones listed below: +/// +/// \cgalNamedParamsBegin +/// \cgalParamBegin{vertex_point_map} +/// the property map with the points associated to the vertices of `pmesh`. +/// If this parameter is omitted, an internal property map for +/// `CGAL::vertex_point_t` must be available in `PolygonMesh` +/// \cgalParamEnd +/// \cgalParamBegin{geom_traits} +/// a geometric traits class instance, model of the concept `OrientedBoundingBoxTraits`. +/// %Default is `CGAL::Oriented_bounding_box_traits` where `K` is deduced from the point type. +/// \cgalParamEnd +/// \cgalParamBegin{use_convex_hull} +/// a Boolean value to indicate whether the algorithm should first extract the so-called extreme +/// points of the data range (i.e. construct the convex hull) to reduce the input data range +/// and accelerate the algorithm. %Default is `true`. +/// \cgalParamEnd +/// \cgalNamedParamsEnd +/// +template +void oriented_bounding_box(const PointRange& points, + Output& out, + const CGAL_BGL_NP_CLASS& np, +#ifndef DOXYGEN_RUNNING + typename boost::enable_if< + typename boost::has_range_iterator + >::type* = 0 +#endif + ) +{ + using CGAL::parameters::choose_parameter; + using CGAL::parameters::get_parameter; + +#if defined(CGAL_EIGEN3_ENABLED) + typedef typename boost::range_value::type Point; + typedef typename CGAL::Kernel_traits::type K; + typedef Oriented_bounding_box_traits Default_traits; +#else + typedef void Default_traits; +#endif + + typedef typename internal_np::Lookup_named_param_def::type Geom_traits; + + CGAL_static_assertion_msg(!(std::is_same::value), + "You must provide a traits class or have Eigen enabled!"); + + Geom_traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Geom_traits()); + + const bool use_ch = choose_parameter(get_parameter(np, internal_np::use_convex_hull), true); + const unsigned int seed = choose_parameter(get_parameter(np, internal_np::random_seed), 0); // undocumented + + CGAL::Random rng(seed); + + // @todo handle those cases instead + CGAL_assertion(points.size() >= 3); + if(points.size() <= 3) + { + std::cerr << "The oriented bounding box cannot YET be computed for a mesh with fewer than 4 vertices!\n"; + return; + } + + return Optimal_bounding_box::internal::construct_oriented_bounding_box(out, use_ch, points, rng, traits); +} + +/// \ingroup PkgOptimalBoundingBox_Oriented_bounding_box +/// +/// Extracts the vertices of the mesh as a point range and calls the other overload. +/// +/// \tparam PolygonMesh a model of `VertexListGraph` +/// \tparam Output `std::array` with `Point` being equivalent to the traits' `Point_3` type, +/// or `CGAL::Affine_transformation_3` with `K` being a kernel compatible with the point type. +/// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" +/// +/// \param pmesh the input mesh +/// \param out the resulting array of points or affine transformation +/// \param np an optional sequence of \ref obb_namedparameters "Named Parameters" among the ones listed below: +/// +/// \cgalNamedParamsBegin +/// \cgalParamBegin{vertex_point_map} +/// the property map with the points associated to the vertices of `pmesh`. +/// If this parameter is omitted, an internal property map for +/// `CGAL::vertex_point_t` must be available in `PolygonMesh` +/// \cgalParamEnd +/// \cgalParamBegin{geom_traits} +/// a geometric traits class instance, model of the concept `OrientedBoundingBoxTraits`. +/// %Default is `CGAL::Oriented_bounding_box_traits` where `K` is deduced from the point type. +/// \cgalParamEnd +/// \cgalParamBegin{use_convex_hull} +/// a Boolean value to indicate whether the algorithm should first extract the so-called extreme +/// points of the data range (i.e. construct the convex hull) to reduce the input data range +/// and accelerate the algorithm. %Default is `true`. +/// \cgalParamEnd +/// \cgalNamedParamsEnd +/// +template +void oriented_bounding_box(const PolygonMesh& pmesh, + Output& out, + const CGAL_BGL_NP_CLASS& np, +#ifndef DOXYGEN_RUNNING + typename boost::disable_if< + typename boost::has_range_iterator + >::type* = 0 +#endif + ) +{ + namespace PMP = CGAL::Polygon_mesh_processing; + + using CGAL::parameters::choose_parameter; + using CGAL::parameters::get_parameter; + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + + typedef typename PMP::GetVertexPointMap::const_type VPM; + typedef typename boost::property_traits::value_type Point; + + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(vertex_point, pmesh)); + + std::vector points; + points.reserve(num_vertices(pmesh)); + + for(vertex_descriptor v : vertices(pmesh)) + points.push_back(get(vpm, v)); + + oriented_bounding_box(points, out, np); +} + +/// \cond SKIP_IN_MANUAL + +/////////////////////////////////////////////////////////////////////////////////////////////////// +/// Convenience overloads +///////////////////////////////////////////////////////////////////////////////////////////////// + +template +void oriented_bounding_box(const InputData& data, + OutputType& out) +{ + return oriented_bounding_box(data, out, CGAL::parameters::all_default()); +} + +/// \endcond + +} // end namespace CGAL + +#endif // CGAL_OPTIMAL_BOUNDING_BOX_ORIENTED_BOUNDING_BOX_H diff --git a/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h index 63ceaa998a4..c4c1a33affe 100644 --- a/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h @@ -14,321 +14,13 @@ #ifndef CGAL_OPTIMAL_BOUNDING_BOX_OBB_H #define CGAL_OPTIMAL_BOUNDING_BOX_OBB_H -#include +/** +* \ingroup PkgOptimalBoundingBoxRef +* \file CGAL/optimal_bounding_box.h +* Convenience header file including the headers for all the free functions of this package. +*/ -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS -#include -#endif - -#include -#include -#include -#include -#include - -#ifdef DOXYGEN_RUNNING -#define CGAL_BGL_NP_TEMPLATE_PARAMETERS NamedParameters -#define CGAL_BGL_NP_CLASS NamedParameters -#endif - -namespace CGAL { -namespace Optimal_bounding_box { -namespace internal { - -// works on matrices only -template -void post_processing(const typename Traits::Matrix& R, - std::array& obb, - const PointRange& points, - const Traits& traits) -{ - typedef typename Traits::FT FT; - typedef typename Traits::Point_3 Point; - typedef typename Traits::Matrix Matrix; - - CGAL_assertion(R.number_of_rows() == 3 && R.number_of_columns() == 3); - - const Matrix Rt = traits.transpose(R); - - CGAL::Bbox_3 bbox; - for(const Point& pt : points) - { - // @fixme should it be R here Rt at the other one... ? - const FT x = pt.x(), y = pt.y(), z = pt.z(); - Point rotated_pt(x*R(0, 0) + y*R(0, 1) + z*R(0, 2), - x*R(1, 0) + y*R(1, 1) + z*R(1, 2), - x*R(2, 0) + y*R(2, 1) + z*R(2, 2)); - - bbox += traits.construct_bbox_3_object()(rotated_pt); - } - - // @todo could avoid building a cuboid - typename Traits::Iso_cuboid_3 ic(bbox); - - // 3) apply inverse rotation to rotated AABB - for(std::size_t i = 0; i<8; ++i) - { - const FT x = ic[i].x(), y = ic[i].y(), z = ic[i].z(); - obb[i] = Point(x*Rt(0, 0) + y*Rt(0, 1) + z*Rt(0, 2), - x*Rt(1, 0) + y*Rt(1, 1) + z*Rt(1, 2), - x*Rt(2, 0) + y*Rt(2, 1) + z*Rt(2, 2)); - } -} - -template -void construct_optimal_bounding_box(std::array& obb_points, - const PointRange& points, - CGAL::Random& rng, - const Traits& traits) -{ - typedef typename Traits::Matrix Matrix; - - const std::size_t max_generations = 100; - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS - CGAL::Real_timer timer; - timer.start(); -#endif - - Evolution search_solution(points, rng, traits); - search_solution.evolve(max_generations); - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS - std::cout << "evolve: " << timer.time() << std::endl; - timer.reset(); -#endif - - const Matrix& rotation = search_solution.get_best(); - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS - std::cout << "get best: " << timer.time() << std::endl; - timer.reset(); -#endif - - post_processing(rotation, obb_points, points, traits); - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS - std::cout << "post-processing: " << timer.time() << std::endl; -#endif -} - -template -void construct_optimal_bounding_box(std::array& obb_points, - const bool use_ch, - const PointRange& points, - CGAL::Random& rng, - const Traits& traits) -{ - typedef typename Traits::Matrix Matrix; - typedef typename Traits::Point_3 Point; - - CGAL_static_assertion((std::is_same::type, Point>::value)); - - if(use_ch) // construct the convex hull to reduce the number of points - { - std::vector ch_points; - extreme_points_3(points, std::back_inserter(ch_points)); - return construct_optimal_bounding_box(obb_points, ch_points, rng, traits); - } - else - { - return construct_optimal_bounding_box(obb_points, points, rng, traits); - } -} - -} // namespace Optimal_bounding_box -} // namespace internal - -/// \ingroup PkgOptimalBoundingBoxFunctions -/// -/// constructs a rectangular box that contains all the input points. This bounding box -/// is obtained via an optimization process aiming to get a close approximation of the -/// optimal bounding box, which is defined as the smallest (in terms of volume) -/// of all the rectangular boxes containing the input points. -/// -/// \tparam PointRange a model of `Range` with value type `Point` -/// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" -/// -/// \param points the input points -/// \param obb_points the eight points of the resulting englobing box. -/// The order of points is the same as in the function `CGAL::make_hexahedron()` -/// \param np an optional sequence of \ref obb_namedparameters "Named Parameters" among the ones listed below: -/// -/// \cgalNamedParamsBegin -/// \cgalParamBegin{vertex_point_map} -/// the property map with the points associated to the vertices of `pmesh`. -/// If this parameter is omitted, an internal property map for -/// `CGAL::vertex_point_t` must be available in `PolygonMesh` -/// \cgalParamEnd -/// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of the concept `OptimalBoundingBoxTraits`. %Default is -/// `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits` where `K` is deduced -/// from the point type, which must then be compatible with `CGAL::Kernel_traits`. -/// \cgalParamEnd -/// \cgalParamBegin{use_convex_hull} -/// a Boolean value to indicate whether the algorithm should first extract the so-called extreme -/// points of the data range (i.e. construct the convex hull) to reduce the input data range -/// and accelerate the algorithm. The optimal value of this parameter will depend on the data -/// as it is a balance between two costs. %Default is `true`. -/// \cgalParamEnd -/// \cgalNamedParamsEnd -/// -/// \pre the value type of `PointRange` is `Point` -/// -template -void optimal_bounding_box(const PointRange& points, - std::array& obb_points, - const CGAL_BGL_NP_CLASS& np) -{ - using CGAL::parameters::choose_parameter; - using CGAL::parameters::get_parameter; - -#if defined(CGAL_EIGEN3_ENABLED) - typedef typename CGAL::Kernel_traits::type K; - typedef Optimal_bounding_box::Optimal_bounding_box_traits Default_traits; -#else - typedef void Default_traits; -#endif - - typedef typename internal_np::Lookup_named_param_def::type Geom_traits; - - CGAL_static_assertion_msg(!(std::is_same::value), - "You must provide a traits class or have Eigen enabled!"); - - Geom_traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Geom_traits()); - - const bool use_ch = choose_parameter(get_parameter(np, internal_np::use_convex_hull), false); - const unsigned int seed = choose_parameter(get_parameter(np, internal_np::random_seed), 0); // undocumented - - CGAL::Random rng(seed); - - // @todo handle those cases instead - CGAL_assertion(points.size() >= 3); - if(points.size() <= 3) - { - std::cerr << "The optimal bounding box cannot YET be computed for a mesh with fewer than 4 vertices!\n"; - return; - } - - return Optimal_bounding_box::internal::construct_optimal_bounding_box(obb_points, use_ch, points, rng, traits); -} - -/// \cond SKIP_IN_MANUAL - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// Convenience overloads for point ranges -///////////////////////////////////////////////////////////////////////////////////////////////// - -template -void optimal_bounding_box(const PointRange& points, - std::array& obb_points) -{ - return optimal_bounding_box(points, obb_points, CGAL::parameters::all_default()); -} - -/// \endcond - -/// \ingroup PkgOptimalBoundingBoxFunctions -/// -/// constructs a rectangular box that contains the input mesh. This bounding box -/// is obtained via an optimization process aiming to get a close approximation of the -/// optimal bounding box, which is defined as the smallest (in terms of volume) -/// of all the rectangular boxes containing the input mesh. -/// -/// \tparam PolygonMesh a model of `FaceListGraph` -/// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" -/// -/// \param pmesh the input mesh -/// \param obb_mesh the resulting enclosing bounding box (an hexahedron) -/// \param np an optional sequence of \ref obb_namedparameters "Named Parameters" among the ones listed below: -/// -/// \cgalNamedParamsBegin -/// \cgalParamBegin{vertex_point_map} -/// the property map with the points associated to the vertices of `pmesh`. -/// If this parameter is omitted, an internal property map for -/// `CGAL::vertex_point_t` must be available in `PolygonMesh` -/// \cgalParamEnd -/// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of the concept `OptimalBoundingBoxTraits`. %Default is -/// `CGAL::Optimal_bounding_box::Optimal_bounding_box_traits` where `K` is deduced -/// from the point type, which must be compatible with `CGAL::Kernel_traits`. -/// \cgalParamEnd -/// \cgalParamBegin{use_convex_hull} -/// a Boolean value to indicate whether the algorithm should first extract the so-called extreme -/// points of the data range (i.e. construct the convex hull) to reduce the input data range -/// and accelerate the algorithm. The optimal value of this parameter will depend on the data -/// as it is a balance between two costs. %Default is `true`. -/// \cgalParamEnd -/// \cgalNamedParamsEnd -/// -template -void optimal_bounding_box(const PolygonMesh& pmesh, - PolygonMesh& obb_mesh, - const CGAL_BGL_NP_CLASS& np) -{ - namespace PMP = CGAL::Polygon_mesh_processing; - - using CGAL::parameters::choose_parameter; - using CGAL::parameters::get_parameter; - - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - typedef typename PMP::GetVertexPointMap::const_type VPM; - typedef typename boost::property_traits::value_type Point; - - VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), - get_const_property_map(vertex_point, pmesh)); - - std::vector points; - points.reserve(num_vertices(pmesh)); - - for(vertex_descriptor v : vertices(pmesh)) - points.push_back(get(vpm, v)); - - std::array obb_points; - optimal_bounding_box(points, obb_points, np); - - CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], - obb_points[4], obb_points[5], obb_points[6], obb_points[7], obb_mesh); -} - -/// \cond SKIP_IN_MANUAL - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/// Convenience overloads for polygon meshes -///////////////////////////////////////////////////////////////////////////////////////////////// - -template -void optimal_bounding_box(const PolygonMesh& pmesh, - PolygonMesh& obb_mesh) -{ - return optimal_bounding_box(pmesh, obb_mesh, CGAL::parameters::all_default()); -} - -/// \endcond - -} // end namespace CGAL +#include +#include #endif // CGAL_OPTIMAL_BOUNDING_BOX_OBB_H From 4020a8fb0d135703f6b744369a4a7ca3fcaff468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Dec 2019 13:41:37 +0100 Subject: [PATCH 074/150] Add biblio for the paper --- Documentation/doc/biblio/cgal_manual.bib | 11 +++++++++++ .../CGAL/Optimal_bounding_box/oriented_bounding_box.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/Documentation/doc/biblio/cgal_manual.bib b/Documentation/doc/biblio/cgal_manual.bib index ec232cbda8e..c78a75ca599 100644 --- a/Documentation/doc/biblio/cgal_manual.bib +++ b/Documentation/doc/biblio/cgal_manual.bib @@ -405,6 +405,17 @@ Boissonnat} ,update = "97.08 kettner" } +@article{ cgal:cgm-fobbo-11, + title={Fast oriented bounding box optimization on the rotation group SO (3, ℝ)}, + author={Chang, Chia-Tche and Gorissen, Bastien and Melchior, Samuel}, + journal={ACM Transactions on Graphics (TOG)}, + volume={30}, + number={5}, + pages={122}, + year={2011}, + publisher={ACM} +} + @article{ cgal:cht-oacov-90 ,author = {M. Chang and N. Huang and C. Tang} ,title = {An optimal algorithm for constructing oriented Voronoi diagrams diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 2f2771d3a8e..152df7a6bd2 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -205,6 +205,8 @@ void construct_oriented_bounding_box(Output& output, /// Note that when returning an array of points, these points are constructed from the axis-aligned /// bounding box and some precision loss should be expected if a kernel not providing exact constructions /// is used. +/// +/// The algorithm is based on a paper by Chang, Gorissen, and Melchior \cgalCite{cgal:cgm-fobbo-11}. /// \ingroup PkgOptimalBoundingBox_Oriented_bounding_box /// From bb7bb9721ba427a4d20db24be14c4a3a99dfd2e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Dec 2019 13:41:59 +0100 Subject: [PATCH 075/150] Traits doesn't need to refine Kernel --- .../Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h index 5c8ed9ecda9..f5ef85a757a 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h @@ -9,8 +9,6 @@ used in the function `CGAL::oriented_bounding_box()`, and in particular the need a 3x3 matrix type with a number of supporting functions (determinant and transposed matrix computations, etc.). -\cgalRefines `Kernel` - \cgalHasModel `CGAL::Oriented_bounding_box_traits` */ From ffc7e9a934feeb9549e657c3a9c43992e7c11ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Dec 2019 14:40:47 +0100 Subject: [PATCH 076/150] Minor doc changes --- .../Concepts/OrientedBoundingBoxTraits.h | 4 ++++ .../PackageDescription.txt | 4 ++-- .../fig/optimal_bounding_box.png | Bin 0 -> 11012 bytes .../Oriented_bounding_box_traits.h | 3 --- .../oriented_bounding_box.h | 18 +++++++++--------- 5 files changed, 15 insertions(+), 14 deletions(-) create mode 100644 Optimal_bounding_box/doc/Optimal_bounding_box/fig/optimal_bounding_box.png diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h index f5ef85a757a..4744f230071 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h @@ -21,6 +21,10 @@ public: /// The 3D point type; must be model of `Point_3` typedef unspecified_type Point_3; + /// The 3D affine transformation type; the template parameter `K` must be a model of `Kernel` + /// and be compatible with the type `Point_3`. + typedef CGAL::Aff_transformation_3 Aff_transformation_3; + /// A construction object that must provide the function operator: /// `CGAL::Bbox_3 operator()(const Point_3&)`, /// which returns an axis-aligned bounding that contains the point diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt index e5b5e9f4b5c..438f248e4c5 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt @@ -15,10 +15,10 @@ /*! \addtogroup PkgOptimalBoundingBoxRef \cgalPkgDescriptionBegin{Optimal Bounding Box,PkgOptimalBoundingBox} -\cgalPkgPicture{Envelope_2.png} +\cgalPkgPicture{optimal_bounding_box.png} \cgalPkgSummaryBegin \cgalPkgAuthor{Konstantinos Katrioplas, Mael Rouxel-Labbé} -\cgalPkgDesc{This package provides functions to compute oriented bounding boxes around a point set or a polygon mesh.} +\cgalPkgDesc{This package provides functions to compute tight oriented bounding boxes around a point set or a polygon mesh.} \cgalPkgManuals{Chapter_Building_Optimal_Bounding_Box,PkgOptimalBoundingBoxRef} \cgalPkgSummaryEnd \cgalPkgShortInfoBegin diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/fig/optimal_bounding_box.png b/Optimal_bounding_box/doc/Optimal_bounding_box/fig/optimal_bounding_box.png new file mode 100644 index 0000000000000000000000000000000000000000..a85355c06ed639add2ac1be40e06f480a91530f2 GIT binary patch literal 11012 zcmV+fEBn-mP)pST zkxRrU#BojsB)%28;_;i{vd3S7c_F_D_(e~t+{H>4vkEter-@^RUSsX^h?|5}b7h(8 zIL!&z$RmR^Wuc&kP3UltplVWPy?x1+ZwXcMF#21lgOj6-3VGwC)~KsWRU=)cPe)zk z{y$G!o1O8xhtt5|tLuJF0>OQt*>K(8Q`c>t0f86b+U)qNl+*k->5YySI|iaVz~xOx zQx1TuU103llDXWH0yO=a27Fuqks>g14}{jetlH~1e*y~I^h9^S;Sn%J`=c9w<;7?I zcrb{M00009a7bBm000XT000XT0n*)m`~UzT07*naRCwC$efgJE$CYM8yfxR#tPK#w zjs$4)neH?0o}PC1={eKK?)jl@cYE5F=YN>~r~Fsg21%A>S(a@mgcbw>3RDYKSzE4e zjp%#hM!fe5kPs4u7V}6TE0=bm-7ipugbp!3Q6_`r3uNckgkG$!Mxzn%wd;EDAz%!;o$il*{Num-G9mpg)(>yLj=>ufP6Uf6({+0J#F-l~#^& z1RDPezP7psFXqCbVNguQadPs+$)Ek~mE*^cKLz@;j^*X$^A~=7Tq(JEDMwn#@sR)hyWjoEzyD-vYU(M_|2ND)WMhQNs&4s1slq zh#r6b%FpNK=KkV<24x0L@A~y?jw6I{wA11hp!uhov*r*>A1Lycmsfz(;RO#gY8Vpu zm~j-(&CUMgC;#`a|LU**Qh)|u_tx)!2S*%7V2K4+2*HZ`4|aol%^CkuK+b%1bxq0~ z-Y%7Rpi$EZrD+E2|4;w)zd&dQLGUdH`ug?jzdrw~m6c_Hn4kr(rT+)y#67(6Kvh?o zGu=4f-rgAu`e4-PDL>VywHH+~PSP{aJ@?8huPiJa`E~*gMEv@1UcY$hB3K`$EGkUR z1qqG&+@NHfS9wGK%q^=}-i9f1cWvGCT^hAdGiv-J6+8~FZ@1e&{?Whv{ojA@TLm=y zmP?D5UVZia_SUu+1OO^8pJJ9b2ur0+v0~2rem7WJIh`CC|C2Qnn-HW->CBTcYCIvH zp6=lwEc$JM;ccxle}^TtEmpk$(q zU62hpoOOM0XTo+IU$WFu{Wi-yI1NJoDMn2r6vgq;g`+?J`Tu+N*=N7OK!d1y>#eum zeCxN9$pnHo4hE^=EbO^r&X48>4N)WYa@p98JD&`a&EaInuM3pclTh9`&ZC-%+@(gB zhF2o+5ZI9U!ztn@fe8LT|NnnJ|NK4%HTx*wKmPb*aC&z>x#L2p=OZI4O|W`OTcDW| zG{KFtBh$5EU-1*s3A|I-XD!NEcWu|dk;fU#mOK&CgRq@Dtw)@ho; z&mdG_Ho+UOUAs0OkM}RR`uKrfyu5hf!g&bQKv!V2Mz}C7uf!fu6(Rs1Rv5wqD5vT=B2QSfRqnvJ4!9 z1AGB7j#hkvi|y^LYuB%R=jHEw1AyMx*Z{8h;Dh%8oZ!Cl9U0^Uc|)0qLg**8_`pU2 z_zQNJgY|(}fH&tXCyxT}@)!DB*{$)G^y`iraEvQC4;y~mpKu#uvc?#IC8B@>Ax=|- z7{hHt<9`!|03#&|peE7mlq&DGGX`V8K{{02OuWG2&C zj$=7Y)fjG4q)OzB=V-tVX%2(~h`u$4ra0cp!HWHwAae$D4{EL$2r4JyKaGiUQ!agY zA0jMsi1j_s(Ii5_J53l&u!41e^wHHQio!7bngV_E*3Do2>X%Emmps=sb!ajc_#at; zc!Mm};EXl~5(^>bNj4c}TVu7Eh#~V59)QJRQqFaBhDnh7($Hv!7B(GtWU!vXkA4lz z87LMDEbvOl6>tGcCHO8lf0!o0Fxzd7^DX7ZVbBa%M;kIDcqN@z4+}6!uh;wd#>X!_ z|H9V}=+S8S+Uu{s^T$7c^bdkyPbFh-T|+xBu9X?y5zGNXnB+SHwL0OODo6mY00MGM zFLBMr+%iDbNh;Szme^fQ!5D!tJZ;Ws(V9BojbYs%jbq0{G=(ch^;_F_rD#U=SuugL zZ$9s-hIWdWzs7M>#;CQ{&KECT`q}|~`SRrpub$u7fWS8Zy3iM2k;kIo2{2yb4W(le z2R_drTi?x>Q-4B3nP$@ULAnX$uy~MXshY}B{E^Bt`9D-fd;4dhd;di#v8vG3yWlOQU#Qc+T9>ZfqhH_=LWQhPmSl zndPH+r|uktUnn)aS_PrRCcy}ILHS+0c=0O+dTHs_FMsvRTQ_flybt_p}ZU{78px%lLO z9*su7`OWKZ|KaT{L;f;!XhJko5#jeF>kvka9JZ6?&HN?{qOj(nLU4>iuvTnY0t8@T z$T|Ql6LFw?12)>s^HhQN3mQ()Kp#jDo1ogxEO?C{diAzf>zKqhi|UdjF#X{45SH#^XA}M4}qlBTXT= zeR4npVw+o=7cN}5{O%%0rx!{_vyGb+k7eL{Wt)oa%!A2J26upwYi-95b$*VLMJ6&a!z~;I^bNl&2>sC{1}~rk988J=+rSGP zFHa_*pWUpvz0tohADlM7iRswW8uf=Cevs!7-8fGIX!uRP_{A@Pmuq!!I!>wHOrefd z8G~D{21bSeZ!@{w7kB(N4{E;SR&*OP)>nottWX*TwZc3p5Tq0|xIusqLKTp7Am$2) zO*NOBkO*TI4=)bX^l)hM{FDZUx5I4E8j+`fwQ!?wZ6|7UgTs>N)~IpR!2>NXf3m#1 zeDvtiCjm5o+iW%gW$+>3uQQe6g93ZBgd+^K8PJu+3Wf3@+3IB<%h~`887$Eug)3|W zkuhFH!J>w^G7N+CGFfW`foB}Ug2of4DN&QMT@1(CsDi2f*ca_YE;t@cB zVLFfxRumP_Viq*q-RxG7HR|3}jzOY{$l>&H9A8?z^mu{()HN*d3uk9%QCC4=4I(29 zzzqT*5Cp`7CD$Kr2m$N|rr86CVx=!vbARmk5+*A|(qP4;;cUaWekYlRPT7OM(xITX zT(Wn;%cQfSwr2%YML;vD({%?tZO(<`RJH`GxWUZeOEC_dCJ2Eh9IDeO&A`Gn!WnPA z###wqx|3w1pG;2$^EoMM&4f`DEiNuTMxZ}y`CGT!^*vuv`IA)>$#A)1Ti)DpuREOx z#8a&qg8vC>E|8<~es*5#Hyif_ZX6YeTd)MHL>xxyNJ2T)KxZsZ6bOb!w+K%-wKGyN zkngG5DicZKQxHiC822K5B&veP!H5du_<+O9K$UN+TSOo>Izkuq?v-~RV?p(^fNr&0 z^?FTb22357S)Z1PaoXHyO!>98hczUhgZ9GD7C5d4SPSEq7&Ex&^0z2Zu6RGj3vvOJ zG2#G-0qZ3@s0mM*-ULNmq*R10!XG_&pn0UUp4LYBr8CeI3+A5} zf}n}F;!mu6;TmWc*yHZqwI=~|7=-QC6qY$`k)lv#X}IY&a+uCw6mYp<9e}dq2?CKC z$h8G2``K6-6IM`G1z||d`x!bwz#8FBRTfJKwZo>)id1AAfU77iNO=`*HH-~`G##;8 z!&kDRXN1YC81Axu7%m=E!yc1&uUvT&K*KMao}Sh%RjlH9FgljCk?UiG zCR}5xy3A1~hOlc9t8$`1*+eVCbljTSfUcNm$BJSMZeYtYt! z*6o;)zSh-eycWAU)zKL#xVIC84ZxG-@(uwCJ2QXFxcM zVn~duRJ=$8mATm>y5yyr)FGm$s6j`Uc1w3E81a~+`5G=Ys5`^72NOzXP|>JCCMKmWJ|OQv1X1(tr5WZamyz(-lU_6J%GDuWWc**&Nxa(+$4GN zgph$E|l97)axTm2nbWon%XQb=SpIP%KWD9SoNc~5k4ruL$9?YS+D>vkoZ zT7n}QNibyW)5=iHQJ)4zJvJy;MMi~)nu}`B0wrE_?;|$tG3u-E0;I)R5+bgfozHCq^r8mVvGx{aPS zMNpN*YOf+g#K?h}?g`yq#|dIZdJCgrkAn}$66FOLPdcb-9bwuBOn7bcuC{z#>E2VS zvZSS?YU57G)Wb#qq$Dc2Lo@BPkcT@~_AtvTI^ zS@4Eg-lqzFps8oCyP6~-rqr%W&uF0!UX^;5A5DS{`vthnRiV#{bYV49XVaRN->s51 zy-n5lTt5$y6nHqB9aN^W#?bL56FJ__qM?MaNVkYMUPF%a9h`y0RZ6qR<;TDt58oIC zGagde21I2(u<>|=HM5DH(hSKKwfU8f$Z;JTp&46Mx+RX;geaT`n40r@`)pJtAIg~( zc;q38P|NVJOnH#j_IyVW?{PCX0OEKo(Mf9U0nP?414{}GQJZpOv7=`&wX0!*>Ejz8 zZ*6To0ifqB3sQDT^MGS|;mnkD%3QuN97bZ6avJok4uu_2rkZn;nFK=yeD!d0pbuaZ(UQp`;7OkXj%X(}zxLHMbRo_;0Q5=cyhEoqC0b1{>Mhhm*m2 znocAP^VC5f%vp!y!fVM%zRStCnzL+|0b1pu!F6YoFIT&Y1VitkO_pQ}6X_J3Bl33v{#DYBU;B zS(*lDGKWn8J?qVL*KuZRn+3_udYZ5nbYpitlm8F&Cpv`#7kbuuVE$Cu14uJXArorl%T%Nj9Xm6qFu9^!xpf zu6?w>Kzp7KYFbZJ+XDw5a?rGZDyua1rgciJm62lxS#sxsf^SOKC1c5T)Sxw%m2xID z$D2h~ku8_jO_r_nf(c5PnAcFWsq-h8s8YV~0XtEJ%(!!>DAwR>xG6_q15{&<_wyAi zCXGjc$YpVE?pQ)J7!Pwt z3q)ml(+Ni80Zd6}C3Yn%NWCgWnaThLL(&+#G>=FcB+Q>=3jJYf&0LwBA|mTy(u$@G z^_GB9H)s5;u{lYH#w9|4?zvY#x(ar^k3g3-t)dqWP#T9S^~yCXI+GwC!V zLRgUzwfQ4$VmumT+On8T$t90Dd%X;h`TgZT?;WQOdFf~rI5Kf zxwdFVunJMB&FgR`0HdDgyV;5f-!*>#M_<2wZJ&Xjo3~qMkQWBw;i-P3vVh7&YNfC! zqQs(!ppxOFPh@7RgLIi=_E`rJV~s^#STWKIVl9oYV}*6&fXO^(gtGON`fU9zd%oSJJgt4GqH~0 z!ZyatgIWN?X&ZpKE@kQVYS(s3+I?=|B7?fyIKXzYWnD~0^8oGf;nfevegTMx`i|t02?~6g|wSm$BuSsuq;4DN=%ZI=ZYm?I&R` z(nbxR7qkb&hc|BC*hipiwHjcpY|IcbQ`VDoURVfS zI)EP=({B49%x*R5=T=N0QaVq~Y+YPhl+jeBR7J1|^dNIp^1E)7Df50n9ia=_!*LlJ zvQLIgRSQvROtr#EVCthj2S)t~HB^xjUA%N@AAzQtmZVyXeFQ<+m{L;gp$=Y=$*dd| zR_*%|c9|t2Zpw^$Sr&F}0bh@IvUrr6ZZ6w>fSyyA1*~J#Z3fl&TNWJ63VmX#INbQX zS~DPOCdROZ3!70Wt{24;OgP@24U(W2Wg{xL1ADyp{`-^3WWRvMQp@y=wB>Nib4vE> zau}M{6&M7n!_Scg71ZWZS@i3b8^aq5QV{9D$L3~lX=!Ocfu5Nu z4czK$l{s>KiraR1R>mbJ8C^-7mMM!e8)7;xbUl=On$~2FEkbgqOmUDLmQ|y+U64pG z($aiX0Qfkut(GJ#J4OR>Jx#GGbYSju7M?P1#ux^g#L)pbcs z(7*TIl{k*}3+Sn-sW1rd$$z6Mj013qm`kGGI$mToRnc+EO$=i?GE@cPqT7+i18H>1 z!M0j$P^!#gFq`F2d4;m2^^iq)!t6RiD#8*Sn}vw9Y^(0)lpW+{!yZ?>LP3faztA;+ z=WNXc6L$lR8rj3y*x0yz`_6s=U9Z<0jmEt|Ymu6-POF@1R*XKR;#H4mdg91-cMybqj#FcaLYjsMsK`4S1zq&DlEO)}gHQgQ+D}_(P>^=%;nwT34aYV|#)cX4_xN z&LZ2SQHrXfU#U>dxe7Komma2$ua#awzz|AB)X|_u)%NNYnHt9051hM8Og2hOk`DrT0v?O2^kClA^ zy47km>UH%1pfyuZf_%M$`%9_&j9yhcxLD!tSv5vbW{Z>}Ji&sKtJ_6zyD#?;|IPvR zayvemjvdf*y0w`X>ybdcfi4W1j$SD)rVjb7IS)d4#9CSvn3Wt7)`Bc8e6^}ng?K65 zaUCw|NQx?PVFm~mmePkwfISv3?+ehr@3-4ixIn1VGslV?6F4f=dBSMC3XT=eZqp>3 zS!Y!-Yoia9$>pbt7CQq}b*IztJ1uu^J~-8tCm}#jCYX4l1#8Si77j$rKr-k#B@3I* z%&`z~PsXxHl1L+0BzBo*cAphhehSmqP_{y_&82wtgURxHqwST6ocO+|Q)7eUxR(|$ zet!0N1fT(-Zg=`#g;&gco%+bPo2CQ0SboK<@+d*K9aqMLZM<9-WD$-Wccf9k%QAB3 z!&7=-a(KAo9quI0jeFoBGpce?X%!fTwv+&-*6YGCE7V=^F-0}ZP3&$>+wmOS&?2X7 zwQP1wusNj)$jU~SvRlsff)(oti9l?yV2UG|%97km+cmGH^k$iQvdE6NFde-(x$7oz zhFze-bcdogXgWaUgudQBNx;ll`!J3WYiZ(1-8767XKId_b zFCW1kyHv{5tl>bQlcF@kr7dRS+hbhSG2Tt$)!Mv!){`y0ACxrZ3!C}{MSbbgrIJe@ zBhcM$_nu9~_pAm7s4^#8>o6an!Py+=YEcaUetYWgVB8*nd z=AqN9@1EMcnT)s5=>a^(y%i7ba0+-H2?q!E=fc|R91QvSgE+HndLOe8*)B$@5!;yc{l)Acc#>+77a7) z0}&}V)a)@r(M`X_3q+QuOZ`6&cVlnm?KayQidC{}M%$D_7oq{6L3c*lM+_{_x)IXGrI5Se<8ugjr0b49u)} zK$cx!Mfs~p+5rR9)!d#$_TG^d!U>%gcg&`)7|!I_$_{)Dfjc&)3f4iX=W{RbrPmwm zK)rWnvdN-x3V;gbPC&qnCEz>R&By(0+)qY3snA>oIN@3fK)KG+9R= zlp7V^V3ie1W;VDogcDF{3V(Hi>zP4BLwpF7qNLlLa~Hz;=Et79y#Rqmiyd(L!S3i* z6b#_$tevyaKJT5p>yh$39!G5a3g?9KSapP1B{@x3{;qtA&xr z0JKgm%{{0qyEHVd^J;Rt;mi!F-l2&>Seq__6x|yJW~&nyj$ahB48P>Lbh3sQhHB6D zkN1qLRgAPgg*Ktd6+|x0Oo6oyHj=H|YP6Gdle5#|5j|#k&7BJ6%jtL$t5JXRdd?DG zgaL25tmg87d&FOM3wGR966y+Hgv zpjCClAH6vx&sS%}%%EIhRCq#VO}i*KNtGnZW2T%^28WsSRa0=W*P`zoU&#`?{WLSl z3UFP5g;NmEVaw=v8&iOdAZ4N5eve@g51~g*w2pNA;b16m4-~y#2|EF0ZjKBq3VBYO z@?!gMt#;_pGiT16dHJQ6Pn|mTP%HjYK*QN_Q(If8wMt;mZkXs2w_469;I$YgTG0(+ zjJqoPbomNw24ae!;h1cPwtetyP2RR&YV)Z;<4!$X6+h5yz(Cx^z8rWAyqveqQ8Ti# z1R?b1G)Wq#S+cXcjlHb7X_BPSjK1-V_Mz!?x+hPZeBp%`&YnAWWZ}pc+t=!mfre=k z24RvWyt^_4qCYRv$4<0;t_RQIrUV7=|$y3wQ)BC&p?f#>ok9a#~mHiHA&&krFwfm5u^A7iz zo0G;cPSJGV+JdVzdrSxicbaj0vwc6PT^0v^vtAOkVhuTQj!YKZ%<}0%a0i%6SoiOW8c57qM5Cb5G48Plj=hSYQ0}pBA z1=#?EaOTWekPTqGPx5=NzX;INGt=B|w(!|A8=FqoX8G(ECT&1|=;b=B(t0Z^eR4`~ z^O~i3z}kn}r%6iyUiZ|`lxgmL@6582saC<4w_cJDtw)W5-{7 z5t#RR0QxKWvgI!VG)y|ZANE6yT8Goan%wNLxy{0sWzpbl8=0By><1s1jMM?=S>FvM zh!9*sZh)@h3v)l3j7LNCZj(ub*>~Hw~XrNc$4_X@d-m|*g|GA1+_Nvd_53^ukI(f5#iYSF zyK_XH7%QHdt*2N)%`C@TuA-phEx<$>XwL>-jtJMoZ|+o-Z2--C^vF?&CctH5Yidqm$TIbA`Po9fQ6A9n3|oP z1<&@P4cNZs#``#d#w~yz>5Fo)#3r5o41^Bx%&nZom?n$U(I6UZk9W5L>2ThykJ$)i z2IqbdPEU6a9z1mX*s)WmPJbO_!&d_|2#+wVMRD{{;bCPNMh?ixJMFl4Xp>zXrdvsl z&Mh8ia;J5`e|Bbic7A>inBnB9Q%4q#%+Jp^8V&YsIlds!pi+$=7CSbe+ zFkY}?-}8Z6pZ%*di0knahYvpk0mWngLWplW(726v`Q5q@3Qr~zu;O~XabW)7-+cFf zoIH8*$dMy6Gc!;4i=n@DK+nvicx0~Qv|8=cr=B};;shXj;J|_X`})Oi?(xOHb9Ou) yU%q@9LIyy#162F;*e9T$9*-s;o` with `Point` being equivalent to the traits' `Point_3` type, -/// or `CGAL::Affine_transformation_3` with `K` being a kernel compatible with the point type. +/// \tparam Output either `std::array` with `Point` being equivalent to the traits' `Point_3` type, +/// or the traits' `Affine_transformation_3` type /// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" /// /// \param points the input points @@ -292,8 +292,8 @@ void oriented_bounding_box(const PointRange& points, /// Extracts the vertices of the mesh as a point range and calls the other overload. /// /// \tparam PolygonMesh a model of `VertexListGraph` -/// \tparam Output `std::array` with `Point` being equivalent to the traits' `Point_3` type, -/// or `CGAL::Affine_transformation_3` with `K` being a kernel compatible with the point type. +/// \tparam Output either `std::array` with `Point` being equivalent to the traits' `Point_3` type, +/// or the traits' `Affine_transformation_3` type /// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" /// /// \param pmesh the input mesh From b33ddb6b434f57d941f9fdb95f30d3621cc9c3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Dec 2019 14:47:11 +0100 Subject: [PATCH 077/150] Run generate_travis.sh --- .travis.yml | 44 ++++++++++++++++++++++---------------------- .travis/packages.txt | 2 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.travis.yml b/.travis.yml index 80677c4c030..a5d9284d182 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,28 +30,28 @@ env: - PACKAGE='Minkowski_sum_2 Minkowski_sum_3 Modifier ' - PACKAGE='Modular_arithmetic Nef_2 Nef_3 ' - PACKAGE='Nef_S2 NewKernel_d Number_types ' - - PACKAGE='OpenNL Optimal_transportation_reconstruction_2 Optimisation_basic ' - - PACKAGE='Partition_2 Periodic_2_triangulation_2 Periodic_3_mesh_3 ' - - PACKAGE='Periodic_3_triangulation_3 Periodic_4_hyperbolic_triangulation_2 Point_set_2 ' - - PACKAGE='Point_set_3 Point_set_processing_3 Poisson_surface_reconstruction_3 ' - - PACKAGE='Polygon Polygon_mesh_processing Polygonal_surface_reconstruction ' - - PACKAGE='Polyhedron Polyhedron_IO Polyline_simplification_2 ' - - PACKAGE='Polynomial Polytope_distance_d Principal_component_analysis ' - - PACKAGE='Principal_component_analysis_LGPL Profiling_tools Property_map ' - - PACKAGE='QP_solver Random_numbers Ridges_3 ' - - PACKAGE='STL_Extension Scale_space_reconstruction_3 Scripts ' - - PACKAGE='SearchStructures Segment_Delaunay_graph_2 Segment_Delaunay_graph_Linf_2 ' - - PACKAGE='Set_movable_separability_2 Shape_detection Skin_surface_3 ' - - PACKAGE='Snap_rounding_2 Solver_interface Spatial_searching ' - - PACKAGE='Spatial_sorting Straight_skeleton_2 Stream_lines_2 ' - - PACKAGE='Stream_support Subdivision_method_3 Surface_mesh ' - - PACKAGE='Surface_mesh_approximation Surface_mesh_deformation Surface_mesh_parameterization ' - - PACKAGE='Surface_mesh_segmentation Surface_mesh_shortest_path Surface_mesh_simplification ' - - PACKAGE='Surface_mesh_skeletonization Surface_mesher Surface_sweep_2 ' - - PACKAGE='TDS_2 TDS_3 Testsuite ' - - PACKAGE='Three Triangulation Triangulation_2 ' - - PACKAGE='Triangulation_3 Union_find Visibility_2 ' - - PACKAGE='Voronoi_diagram_2 wininst ' + - PACKAGE='OpenNL Optimal_bounding_box Optimal_transportation_reconstruction_2 ' + - PACKAGE='Optimisation_basic Partition_2 Periodic_2_triangulation_2 ' + - PACKAGE='Periodic_3_mesh_3 Periodic_3_triangulation_3 Periodic_4_hyperbolic_triangulation_2 ' + - PACKAGE='Point_set_2 Point_set_3 Point_set_processing_3 ' + - PACKAGE='Poisson_surface_reconstruction_3 Polygon Polygon_mesh_processing ' + - PACKAGE='Polygonal_surface_reconstruction Polyhedron Polyhedron_IO ' + - PACKAGE='Polyline_simplification_2 Polynomial Polytope_distance_d ' + - PACKAGE='Principal_component_analysis Principal_component_analysis_LGPL Profiling_tools ' + - PACKAGE='Property_map QP_solver Random_numbers ' + - PACKAGE='Ridges_3 STL_Extension Scale_space_reconstruction_3 ' + - PACKAGE='Scripts SearchStructures Segment_Delaunay_graph_2 ' + - PACKAGE='Segment_Delaunay_graph_Linf_2 Set_movable_separability_2 Shape_detection ' + - PACKAGE='Skin_surface_3 Snap_rounding_2 Solver_interface ' + - PACKAGE='Spatial_searching Spatial_sorting Straight_skeleton_2 ' + - PACKAGE='Stream_lines_2 Stream_support Subdivision_method_3 ' + - PACKAGE='Surface_mesh Surface_mesh_approximation Surface_mesh_deformation ' + - PACKAGE='Surface_mesh_parameterization Surface_mesh_segmentation Surface_mesh_shortest_path ' + - PACKAGE='Surface_mesh_simplification Surface_mesh_skeletonization Surface_mesher ' + - PACKAGE='Surface_sweep_2 TDS_2 TDS_3 ' + - PACKAGE='Testsuite Three Triangulation ' + - PACKAGE='Triangulation_2 Triangulation_3 Union_find ' + - PACKAGE='Visibility_2 Voronoi_diagram_2 wininst ' compiler: clang install: - echo "$PWD" diff --git a/.travis/packages.txt b/.travis/packages.txt index 3123b8c14e6..6f8827fd0fd 100644 --- a/.travis/packages.txt +++ b/.travis/packages.txt @@ -71,7 +71,7 @@ Nef_S2 NewKernel_d Number_types OpenNL -Optimal_bounding_box +Optimal_bounding_box Optimal_transportation_reconstruction_2 Optimisation_basic Partition_2 From feddb97792b5f6db00f7316ed7fd1a790386650b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Dec 2019 15:19:52 +0100 Subject: [PATCH 078/150] Update dependencies --- .../Optimal_bounding_box/dependencies | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Optimal_bounding_box/package_info/Optimal_bounding_box/dependencies b/Optimal_bounding_box/package_info/Optimal_bounding_box/dependencies index e69de29bb2d..12c0af8bdbb 100644 --- a/Optimal_bounding_box/package_info/Optimal_bounding_box/dependencies +++ b/Optimal_bounding_box/package_info/Optimal_bounding_box/dependencies @@ -0,0 +1,29 @@ +Algebraic_foundations +Arithmetic_kernel +BGL +Cartesian_kernel +Circulator +Convex_hull_2 +Convex_hull_3 +Distance_2 +Distance_3 +Filtered_kernel +Hash_map +Homogeneous_kernel +Installation +Intersections_2 +Intersections_3 +Interval_support +Kernel_23 +Kernel_d +Modular_arithmetic +Number_types +Optimal_bounding_box +Profiling_tools +Property_map +Random_numbers +STL_Extension +Solver_interface +Stream_support +TDS_2 +Triangulation_2 From f476132cab7ef837d8ed787e318e4ba40ae90dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Dec 2019 15:50:50 +0100 Subject: [PATCH 079/150] Partial test fixes --- .../test/Optimal_bounding_box/CMakeLists.txt | 4 +- .../Optimal_bounding_box/test_OBB_traits.cpp | 135 ++++++++ .../test_linear_algebra_functions.cpp | 301 ------------------ .../Optimal_bounding_box/test_nelder_mead.cpp | 195 ++++++++++++ .../test_optimization_algorithms.cpp | 122 +------ 5 files changed, 334 insertions(+), 423 deletions(-) create mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/test_OBB_traits.cpp delete mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp create mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt index dc0d5800453..79faf94bfad 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt +++ b/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt @@ -21,6 +21,8 @@ else() include(${EIGEN3_USE_FILE}) endif() -create_single_source_cgal_program("test_linear_algebra_functions.cpp") +create_single_source_cgal_program("test_nelder_mead.cpp") +create_single_source_cgal_program("test_OBB_traits.cpp") create_single_source_cgal_program("test_optimization_algorithms.cpp") + diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_OBB_traits.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_OBB_traits.cpp new file mode 100644 index 00000000000..41b0474ba07 --- /dev/null +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_OBB_traits.cpp @@ -0,0 +1,135 @@ +#include +#include +#include + +#include + +bool assert_doubles(double d1, double d2, double epsilon) +{ + return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; +} + +void test_fitness_function() +{ + typedef typename CGAL::Eigen_linear_algebra_traits::MatrixXd MatrixXd; + MatrixXd data_points(4, 3); + + data_points.set_coef(0, 0, 0.866802); + data_points.set_coef(0, 1, 0.740808); + data_points.set_coef(0, 2, 0.895304); + + data_points.set_coef(1, 0, 0.912651); + data_points.set_coef(1, 1, 0.761565); + data_points.set_coef(1, 2, 0.160330); + + data_points.set_coef(2, 0, 0.093661); + data_points.set_coef(2, 1, 0.892578); + data_points.set_coef(2, 2, 0.737412); + + data_points.set_coef(3, 0, 0.166461); + data_points.set_coef(3, 1, 0.149912); + data_points.set_coef(3, 2, 0.364944); + + typedef typename CGAL::Eigen_linear_algebra_traits::Matrix3d Matrix3d; + Matrix3d rotation; + rotation.set_coef(0, 0, -0.809204); + rotation.set_coef(0, 1, 0.124296); + rotation.set_coef(0, 2, 0.574230); + rotation.set_coef(1, 0, -0.574694); + rotation.set_coef(1, 1, 0.035719); + rotation.set_coef(1, 2, -0.817589); + rotation.set_coef(2, 0, -0.122134); + rotation.set_coef(2, 1, -0.991602); + rotation.set_coef(2, 2, 0.042528); + + CGAL_assertion_code(typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits); + CGAL_assertion_code(double fitness = CGAL::Optimal_bounding_box:: + compute_fitness (rotation, data_points)); + CGAL_assertion(assert_doubles(fitness, 0.58606, 1e-5)); +} + + + +void test_eigen_matrix_interface() +{ + CGAL_assertion_code(typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits); + typedef CGAL::Eigen_dense_matrix Matrix; + + Matrix A(3, 3); + A.set_coef(0, 0, 0.1); + A.set_coef(0, 1, 0.2); + A.set_coef(0, 2, 0.3); + A.set_coef(1, 0, 0.4); + A.set_coef(1, 1, 0.5); + A.set_coef(1, 2, 0.6); + A.set_coef(2, 0, 0.7); + A.set_coef(2, 1, 0.8); + A.set_coef(2, 2, 0.9); + CGAL_assertion_code(Matrix B); + CGAL_assertion_code(B = CGAL::Eigen_linear_algebra_traits::transpose(A)); + CGAL_assertion_code(Matrix S); + CGAL_assertion_code(S = 0.5 * A); + Matrix C(3,3); + C.set_coef(0, 0, 0.3011944); + C.set_coef(0, 1, 0.9932761); + C.set_coef(0, 2, 0.5483701); + C.set_coef(1, 0, 0.5149142); + C.set_coef(1, 1, 0.5973263); + C.set_coef(1, 2, 0.5162336); + C.set_coef(2, 0, 0.0039213); + C.set_coef(2, 1, 0.0202949); + C.set_coef(2, 2, 0.9240308); + + CGAL_assertion_code(Matrix Q = CGAL::Eigen_linear_algebra_traits::get_Q(C)); + CGAL_assertion_code(double epsilon = 1e-5); + CGAL_assertion(assert_doubles(Q(0,0), -0.504895, epsilon)); + CGAL_assertion(assert_doubles(Q(0,1), 0.862834, epsilon)); + CGAL_assertion(assert_doubles(Q(0,2), -0.024447, epsilon)); + CGAL_assertion(assert_doubles(Q(1,0), -0.863156, epsilon)); + CGAL_assertion(assert_doubles(Q(1,1), -0.504894, epsilon)); + CGAL_assertion(assert_doubles(Q(1,2), 0.006687, epsilon)); + CGAL_assertion(assert_doubles(Q(2,0), -0.006573, epsilon)); + CGAL_assertion(assert_doubles(Q(2,1), 0.024478, epsilon)); + CGAL_assertion(assert_doubles(Q(2,2), 0.999679, epsilon)); + + Matrix D(3,3); + D.set_coef(0, 0, -0.809204); + D.set_coef(0, 1, 0.124296); + D.set_coef(0, 2, 0.574230); + D.set_coef(1, 0, -0.574694); + D.set_coef(1, 1, 0.035719); + D.set_coef(1, 2, -0.817589); + D.set_coef(2, 0, -0.122134); + D.set_coef(2, 1, -0.991602); + D.set_coef(2, 2, 0.042528); + + Matrix E(3,3); + E.set_coef(0, 0, -0.45070); + E.set_coef(0, 1, -0.32769); + E.set_coef(0, 2, -0.83035); + E.set_coef(1, 0, -0.13619); + E.set_coef(1, 1, -0.89406); + E.set_coef(1, 2, 0.42675); + E.set_coef(2, 0, -0.88222); + E.set_coef(2, 1, 0.30543); + E.set_coef(2, 2, 0.35833); + + CGAL_assertion_code(Matrix Sr = CGAL::Optimal_bounding_box::reflection(D, E)); + CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); + CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); + CGAL_assertion(assert_doubles(Sr(0,2), -0.24664, epsilon)); + CGAL_assertion(assert_doubles(Sr(1,0), -0.60307, epsilon)); + CGAL_assertion(assert_doubles(Sr(1,1), -0.11875, epsilon)); + CGAL_assertion(assert_doubles(Sr(1,2), 0.78880, epsilon)); + CGAL_assertion(assert_doubles(Sr(2,0), -0.78642, epsilon)); + CGAL_assertion(assert_doubles(Sr(2,1), 0.25411, epsilon)); + CGAL_assertion(assert_doubles(Sr(2,2), -0.56300, epsilon)); +} + +int main() +{ + test_fitness_function(); + test_eigen_matrix_interface(); + + return 0; +} diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp deleted file mode 100644 index 9482f15ff49..00000000000 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_linear_algebra_functions.cpp +++ /dev/null @@ -1,301 +0,0 @@ -#include -#include -#include - -#include - -bool assert_doubles(double d1, double d2, double epsilon) -{ - return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; -} - -void test_get_Q() -{ - typedef CGAL::Eigen_dense_matrix Mat; - Mat A(3, 3); - A.set_coef(0, 0, 0.3011944); - A.set_coef(0, 1, 0.9932761); - A.set_coef(0, 2, 0.5483701); - A.set_coef(1, 0, 0.5149142); - A.set_coef(1, 1, 0.5973263); - A.set_coef(1, 2, 0.5162336); - A.set_coef(2, 0, 0.0039213); - A.set_coef(2, 1, 0.0202949); - A.set_coef(2, 2, 0.9240308); - - CGAL_assertion_code(Mat Q = CGAL::Eigen_linear_algebra_traits::get_Q(A)); - CGAL_assertion_code(double epsilon = 1e-6); - CGAL_assertion(assert_doubles(Q(0,0), -0.504895, epsilon)); - CGAL_assertion(assert_doubles(Q(0,1), 0.862834, epsilon)); - CGAL_assertion(assert_doubles(Q(0,2), -0.024447, epsilon)); - CGAL_assertion(assert_doubles(Q(1,0), -0.863156, epsilon)); - CGAL_assertion(assert_doubles(Q(1,1), -0.504894, epsilon)); - CGAL_assertion(assert_doubles(Q(1,2), 0.006687, epsilon)); - CGAL_assertion(assert_doubles(Q(2,0), -0.006573, epsilon)); - CGAL_assertion(assert_doubles(Q(2,1), 0.024478, epsilon)); - CGAL_assertion(assert_doubles(Q(2,2), 0.999679, epsilon)); -} - -void test_fitness_function() -{ - typedef typename CGAL::Eigen_linear_algebra_traits::MatrixXd MatrixXd; - MatrixXd data_points(4, 3); - - data_points.set_coef(0, 0, 0.866802); - data_points.set_coef(0, 1, 0.740808); - data_points.set_coef(0, 2, 0.895304); - - data_points.set_coef(1, 0, 0.912651); - data_points.set_coef(1, 1, 0.761565); - data_points.set_coef(1, 2, 0.160330); - - data_points.set_coef(2, 0, 0.093661); - data_points.set_coef(2, 1, 0.892578); - data_points.set_coef(2, 2, 0.737412); - - data_points.set_coef(3, 0, 0.166461); - data_points.set_coef(3, 1, 0.149912); - data_points.set_coef(3, 2, 0.364944); - - typedef typename CGAL::Eigen_linear_algebra_traits::Matrix3d Matrix3d; - Matrix3d rotation; - rotation.set_coef(0, 0, -0.809204); - rotation.set_coef(0, 1, 0.124296); - rotation.set_coef(0, 2, 0.574230); - rotation.set_coef(1, 0, -0.574694); - rotation.set_coef(1, 1, 0.035719); - rotation.set_coef(1, 2, -0.817589); - rotation.set_coef(2, 0, -0.122134); - rotation.set_coef(2, 1, -0.991602); - rotation.set_coef(2, 2, 0.042528); - - CGAL_assertion_code(typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits); - CGAL_assertion_code(double fitness = CGAL::Optimal_bounding_box:: - compute_fitness (rotation, data_points)); - CGAL_assertion(assert_doubles(fitness, 0.58606, 1e-5)); -} - -void test_simplex_operations() -{ - CGAL_assertion_code(typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits); - typedef CGAL::Eigen_dense_matrix Matrix; - - Matrix Sc(3, 3); - Sc.set_coef(0, 0, -0.809204); - Sc.set_coef(0, 1, 0.124296); - Sc.set_coef(0, 2, 0.574230); - Sc.set_coef(1, 0, -0.574694); - Sc.set_coef(1, 1, 0.035719); - Sc.set_coef(1, 2, -0.817589); - Sc.set_coef(2, 0, -0.122134); - Sc.set_coef(2, 1, -0.991602); - Sc.set_coef(2, 2, 0.042528); - - Matrix S_worst(3, 3); - S_worst.set_coef(0, 0, -0.45070); - S_worst.set_coef(0, 1, -0.32769); - S_worst.set_coef(0, 2, -0.83035); - S_worst.set_coef(1, 0, -0.13619); - S_worst.set_coef(1, 1, -0.89406); - S_worst.set_coef(1, 2, 0.42675); - S_worst.set_coef(2, 0, -0.88222); - S_worst.set_coef(2, 1, 0.30543); - S_worst.set_coef(2, 2, 0.35833); - - CGAL_assertion_code(Matrix Sr = CGAL::Optimal_bounding_box::reflection(Sc, S_worst)); - CGAL_assertion_code(double epsilon = 1e-5); - CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); - CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); - CGAL_assertion(assert_doubles(Sr(0,2), -0.24664, epsilon)); - CGAL_assertion(assert_doubles(Sr(1,0), -0.60307, epsilon)); - CGAL_assertion(assert_doubles(Sr(1,1), -0.11875, epsilon)); - CGAL_assertion(assert_doubles(Sr(1,2), 0.78880, epsilon)); - CGAL_assertion(assert_doubles(Sr(2,0), -0.78642, epsilon)); - CGAL_assertion(assert_doubles(Sr(2,1), 0.25411, epsilon)); - CGAL_assertion(assert_doubles(Sr(2,2), -0.56300, epsilon)); - - CGAL_assertion_code(Matrix Se = - CGAL::Optimal_bounding_box::expansion(Sc, S_worst, Sr)); - CGAL_assertion(assert_doubles(Se(0,0), -0.87991, epsilon)); - CGAL_assertion(assert_doubles(Se(0,1), 0.36105, epsilon)); - CGAL_assertion(assert_doubles(Se(0,2), -0.30888, epsilon)); - CGAL_assertion(assert_doubles(Se(1,0), -0.11816, epsilon)); - CGAL_assertion(assert_doubles(Se(1,1), -0.79593, epsilon)); - CGAL_assertion(assert_doubles(Se(1,2), -0.59375, epsilon)); - CGAL_assertion(assert_doubles(Se(2,0), -0.460215, epsilon)); - CGAL_assertion(assert_doubles(Se(2,1), -0.48595, epsilon)); - CGAL_assertion(assert_doubles(Se(2,2), 0.74300, epsilon)); - - Matrix S_a(3, 3); - S_a.set_coef(0, 0, -0.277970); - S_a.set_coef(0, 1, 0.953559); - S_a.set_coef(0, 2, 0.116010); - S_a.set_coef(1, 0, -0.567497); - S_a.set_coef(1, 1, -0.065576); - S_a.set_coef(1, 2, -0.820760); - S_a.set_coef(2, 0, -0.775035); - S_a.set_coef(2, 1, -0.293982); - S_a.set_coef(2, 2, 0.559370); - - Matrix S_b(3, 3); - S_b.set_coef(0, 0, -0.419979); - S_b.set_coef(0, 1, 0.301765); - S_b.set_coef(0, 2, -0.8558940); - S_b.set_coef(1, 0, -0.653011); - S_b.set_coef(1, 1, -0.755415); - S_b.set_coef(1, 2, 0.054087); - S_b.set_coef(2, 0, -0.630234); - S_b.set_coef(2, 1, 0.581624); - S_b.set_coef(2, 2, 0.514314); - - CGAL_assertion_code(Matrix S_c = - CGAL::Optimal_bounding_box::mean(S_a, S_b)); - CGAL_assertion(assert_doubles(S_c(0,0), -0.35111, epsilon)); - CGAL_assertion(assert_doubles(S_c(0,1), 0.79308, epsilon)); - CGAL_assertion(assert_doubles(S_c(0,2), -0.49774, epsilon)); - CGAL_assertion(assert_doubles(S_c(1,0), -0.61398, epsilon)); - CGAL_assertion(assert_doubles(S_c(1,1), -0.59635, epsilon)); - CGAL_assertion(assert_doubles(S_c(1,2), -0.51710, epsilon)); - CGAL_assertion(assert_doubles(S_c(2,0), -0.70693, epsilon)); - CGAL_assertion(assert_doubles(S_c(2,1), 0.12405, epsilon)); - CGAL_assertion(assert_doubles(S_c(2,2), 0.69632, epsilon)); -} - -void test_centroid() -{ - CGAL_assertion_code(typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits); - typedef CGAL::Eigen_dense_matrix Matrix; - - Matrix S_a; - S_a.set_coef(0, 0, -0.588443); - S_a.set_coef(0, 1, 0.807140); - S_a.set_coef(0, 2, -0.047542); - S_a.set_coef(1, 0, -0.786228); - S_a.set_coef(1, 1, -0.584933); - S_a.set_coef(1, 2, -0.199246); - S_a.set_coef(2, 0, -0.188629); - S_a.set_coef(2, 1, -0.079867); - S_a.set_coef(2, 2, 0.978795); - - Matrix S_b(3, 3); - S_b.set_coef(0, 0, -0.2192721); - S_b.set_coef(0, 1, 0.2792986); - S_b.set_coef(0, 2, -0.9348326); - S_b.set_coef(1, 0, -0.7772152); - S_b.set_coef(1, 1, -0.6292092); - S_b.set_coef(1, 2, -0.005686); - S_b.set_coef(2, 0, -0.5897934); - S_b.set_coef(2, 1, 0.7253193); - S_b.set_coef(2, 2, 0.3550431); - - Matrix S_c(3, 3); - S_c.set_coef(0, 0, -0.32657); - S_c.set_coef(0, 1, -0.60013); - S_c.set_coef(0, 2, -0.730206); - S_c.set_coef(1, 0, -0.20022); - S_c.set_coef(1, 1, -0.71110); - S_c.set_coef(1, 2, 0.67398); - S_c.set_coef(2, 0, -0.92372); - S_c.set_coef(2, 1, 0.36630); - S_c.set_coef(2, 2, 0.11207); - - CGAL_assertion_code(Matrix S_centroid = - CGAL::Optimal_bounding_box::nm_centroid(S_a, S_b, S_c)); - CGAL_assertion_code(double epsilon = 1e-5); - CGAL_assertion(assert_doubles(S_centroid(0,0), -0.419979, epsilon)); - CGAL_assertion(assert_doubles(S_centroid(0,1), 0.301765, epsilon)); - CGAL_assertion(assert_doubles(S_centroid(0,2), -0.855894, epsilon)); - CGAL_assertion(assert_doubles(S_centroid(1,0), -0.653011, epsilon)); - CGAL_assertion(assert_doubles(S_centroid(1,1), -0.755415, epsilon)); - CGAL_assertion(assert_doubles(S_centroid(1,2), 0.054087, epsilon)); - CGAL_assertion(assert_doubles(S_centroid(2,0), -0.630234, epsilon)); - CGAL_assertion(assert_doubles(S_centroid(2,1), 0.581624, epsilon)); - CGAL_assertion(assert_doubles(S_centroid(2,2), 0.514314, epsilon)); -} - -void test_eigen_matrix_interface() -{ - CGAL_assertion_code(typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits); - typedef CGAL::Eigen_dense_matrix Matrix; - - Matrix A(3, 3); - A.set_coef(0, 0, 0.1); - A.set_coef(0, 1, 0.2); - A.set_coef(0, 2, 0.3); - A.set_coef(1, 0, 0.4); - A.set_coef(1, 1, 0.5); - A.set_coef(1, 2, 0.6); - A.set_coef(2, 0, 0.7); - A.set_coef(2, 1, 0.8); - A.set_coef(2, 2, 0.9); - CGAL_assertion_code(Matrix B); - CGAL_assertion_code(B = CGAL::Eigen_linear_algebra_traits::transpose(A)); - CGAL_assertion_code(Matrix S); - CGAL_assertion_code(S = 0.5 * A); - Matrix C(3,3); - C.set_coef(0, 0, 0.3011944); - C.set_coef(0, 1, 0.9932761); - C.set_coef(0, 2, 0.5483701); - C.set_coef(1, 0, 0.5149142); - C.set_coef(1, 1, 0.5973263); - C.set_coef(1, 2, 0.5162336); - C.set_coef(2, 0, 0.0039213); - C.set_coef(2, 1, 0.0202949); - C.set_coef(2, 2, 0.9240308); - - CGAL_assertion_code(Matrix Q = CGAL::Eigen_linear_algebra_traits::get_Q(C)); - CGAL_assertion_code(double epsilon = 1e-5); - CGAL_assertion(assert_doubles(Q(0,0), -0.504895, epsilon)); - CGAL_assertion(assert_doubles(Q(0,1), 0.862834, epsilon)); - CGAL_assertion(assert_doubles(Q(0,2), -0.024447, epsilon)); - CGAL_assertion(assert_doubles(Q(1,0), -0.863156, epsilon)); - CGAL_assertion(assert_doubles(Q(1,1), -0.504894, epsilon)); - CGAL_assertion(assert_doubles(Q(1,2), 0.006687, epsilon)); - CGAL_assertion(assert_doubles(Q(2,0), -0.006573, epsilon)); - CGAL_assertion(assert_doubles(Q(2,1), 0.024478, epsilon)); - CGAL_assertion(assert_doubles(Q(2,2), 0.999679, epsilon)); - - Matrix D(3,3); - D.set_coef(0, 0, -0.809204); - D.set_coef(0, 1, 0.124296); - D.set_coef(0, 2, 0.574230); - D.set_coef(1, 0, -0.574694); - D.set_coef(1, 1, 0.035719); - D.set_coef(1, 2, -0.817589); - D.set_coef(2, 0, -0.122134); - D.set_coef(2, 1, -0.991602); - D.set_coef(2, 2, 0.042528); - - Matrix E(3,3); - E.set_coef(0, 0, -0.45070); - E.set_coef(0, 1, -0.32769); - E.set_coef(0, 2, -0.83035); - E.set_coef(1, 0, -0.13619); - E.set_coef(1, 1, -0.89406); - E.set_coef(1, 2, 0.42675); - E.set_coef(2, 0, -0.88222); - E.set_coef(2, 1, 0.30543); - E.set_coef(2, 2, 0.35833); - - CGAL_assertion_code(Matrix Sr = CGAL::Optimal_bounding_box::reflection(D, E)); - CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); - CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); - CGAL_assertion(assert_doubles(Sr(0,2), -0.24664, epsilon)); - CGAL_assertion(assert_doubles(Sr(1,0), -0.60307, epsilon)); - CGAL_assertion(assert_doubles(Sr(1,1), -0.11875, epsilon)); - CGAL_assertion(assert_doubles(Sr(1,2), 0.78880, epsilon)); - CGAL_assertion(assert_doubles(Sr(2,0), -0.78642, epsilon)); - CGAL_assertion(assert_doubles(Sr(2,1), 0.25411, epsilon)); - CGAL_assertion(assert_doubles(Sr(2,2), -0.56300, epsilon)); -} - -int main() -{ - test_get_Q(); - test_fitness_function(); - test_simplex_operations(); - test_centroid(); - test_eigen_matrix_interface(); - - return 0; -} diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp new file mode 100644 index 00000000000..ad1751f915c --- /dev/null +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp @@ -0,0 +1,195 @@ +#include +#include + +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_3 Point_3; + +typedef CGAL::Oriented_bounding_box_traits Traits; +typedef Traits::Matrix Matrix; + +bool are_equal(double d1, double d2, double epsilon) +{ + return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; +} + +void test_simplex_operations() +{ + const double epsilon = 1e-5; + + Matrix Sc(3, 3); + Sc.set(0, 0, -0.809204); Sc.set(0, 1, 0.124296); Sc.set(0, 2, 0.574230); + Sc.set(1, 0, -0.574694); Sc.set(1, 1, 0.035719); Sc.set(1, 2, -0.817589); + Sc.set(2, 0, -0.122134); Sc.set(2, 1, -0.991602); Sc.set(2, 2, 0.042528); + + Matrix S_worst(3, 3); + S_worst.set(0, 0, -0.45070); S_worst.set(0, 1, -0.32769); S_worst.set(0, 2, -0.83035); + S_worst.set(1, 0, -0.13619); S_worst.set(1, 1, -0.89406); S_worst.set(1, 2, 0.42675); + S_worst.set(2, 0, -0.88222); S_worst.set(2, 1, 0.30543); S_worst.set(2, 2, 0.35833); + + Matrix Sr = CGAL::Optimal_bounding_box::reflection(Sc, S_worst); + assert(are_equal(Sr(0,0), -0.13359, epsilon)); + assert(are_equal(Sr(0,1), -0.95986, epsilon)); + assert(are_equal(Sr(0,2), -0.24664, epsilon)); + assert(are_equal(Sr(1,0), -0.60307, epsilon)); + assert(are_equal(Sr(1,1), -0.11875, epsilon)); + assert(are_equal(Sr(1,2), 0.78880, epsilon)); + assert(are_equal(Sr(2,0), -0.78642, epsilon)); + assert(are_equal(Sr(2,1), 0.25411, epsilon)); + assert(are_equal(Sr(2,2), -0.56300, epsilon)); + + Matrix Se = CGAL::Optimal_bounding_box::expansion(Sc, S_worst, Sr); + assert(are_equal(Se(0,0), -0.87991, epsilon)); + assert(are_equal(Se(0,1), 0.36105, epsilon)); + assert(are_equal(Se(0,2), -0.30888, epsilon)); + assert(are_equal(Se(1,0), -0.11816, epsilon)); + assert(are_equal(Se(1,1), -0.79593, epsilon)); + assert(are_equal(Se(1,2), -0.59375, epsilon)); + assert(are_equal(Se(2,0), -0.460215, epsilon)); + assert(are_equal(Se(2,1), -0.48595, epsilon)); + assert(are_equal(Se(2,2), 0.74300, epsilon)); + + Matrix S_a(3, 3); + S_a.set(0, 0, -0.277970); S_a.set(0, 1, 0.953559); S_a.set(0, 2, 0.116010); + S_a.set(1, 0, -0.567497); S_a.set(1, 1, -0.065576); S_a.set(1, 2, -0.820760); + S_a.set(2, 0, -0.775035); S_a.set(2, 1, -0.293982); S_a.set(2, 2, 0.559370); + + Matrix S_b(3, 3); + S_b.set(0, 0, -0.419979); S_b.set(0, 1, 0.301765); S_b.set(0, 2, -0.8558940); + S_b.set(1, 0, -0.653011); S_b.set(1, 1, -0.755415); S_b.set(1, 2, 0.054087); + S_b.set(2, 0, -0.630234); S_b.set(2, 1, 0.581624); S_b.set(2, 2, 0.514314); + + Matrix S_c = CGAL::Optimal_bounding_box::mean(S_a, S_b); + assert(are_equal(S_c(0,0), -0.35111, epsilon)); + assert(are_equal(S_c(0,1), 0.79308, epsilon)); + assert(are_equal(S_c(0,2), -0.49774, epsilon)); + assert(are_equal(S_c(1,0), -0.61398, epsilon)); + assert(are_equal(S_c(1,1), -0.59635, epsilon)); + assert(are_equal(S_c(1,2), -0.51710, epsilon)); + assert(are_equal(S_c(2,0), -0.70693, epsilon)); + assert(are_equal(S_c(2,1), 0.12405, epsilon)); + assert(are_equal(S_c(2,2), 0.69632, epsilon)); +} + +void test_centroid() +{ + const double epsilon = 1e-5; + + Matrix S_a; + S_a.set(0, 0, -0.588443); S_a.set(0, 1, 0.807140); S_a.set(0, 2, -0.047542); + S_a.set(1, 0, -0.786228); S_a.set(1, 1, -0.584933); S_a.set(1, 2, -0.199246); + S_a.set(2, 0, -0.188629); S_a.set(2, 1, -0.079867); S_a.set(2, 2, 0.978795); + + Matrix S_b(3, 3); + S_b.set(0, 0, -0.2192721); S_b.set(0, 1, 0.2792986); S_b.set(0, 2, -0.9348326); + S_b.set(1, 0, -0.7772152); S_b.set(1, 1, -0.6292092); S_b.set(1, 2, -0.005686); + S_b.set(2, 0, -0.5897934); S_b.set(2, 1, 0.7253193); S_b.set(2, 2, 0.3550431); + + Matrix S_c(3, 3); + S_c.set(0, 0, -0.32657); S_c.set(0, 1, -0.60013); S_c.set(0, 2, -0.730206); + S_c.set(1, 0, -0.20022); S_c.set(1, 1, -0.71110); S_c.set(1, 2, 0.67398); + S_c.set(2, 0, -0.92372); S_c.set(2, 1, 0.36630); S_c.set(2, 2, 0.11207); + + Matrix S_centroid = CGAL::Optimal_bounding_box::nm_centroid(S_a, S_b, S_c); + assert(are_equal(S_centroid(0,0), -0.419979, epsilon)); + assert(are_equal(S_centroid(0,1), 0.301765, epsilon)); + assert(are_equal(S_centroid(0,2), -0.855894, epsilon)); + assert(are_equal(S_centroid(1,0), -0.653011, epsilon)); + assert(are_equal(S_centroid(1,1), -0.755415, epsilon)); + assert(are_equal(S_centroid(1,2), 0.054087, epsilon)); + assert(are_equal(S_centroid(2,0), -0.630234, epsilon)); + assert(are_equal(S_centroid(2,1), 0.581624, epsilon)); + assert(are_equal(S_centroid(2,2), 0.514314, epsilon)); +} + +void test_nelder_mead() +{ + std::array points; + points[0] = Point_3(0.866802, 0.740808, 0.895304); + points[1] = Point_3(0.912651, 0.761565, 0.160330); + points[2] = Point_3(0.093661, 0.892578, 0.737412); + points[3] = Point_3(0.166461, 0.149912, 0.364944); + + // one simplex + std::array simplex; + + Matrix v0, v1, v2, v3; + v0(0,0) = -0.2192721; v0(0,1) = 0.2792986; v0(0,2) = -0.9348326; + v0(1,0) = -0.7772152; v0(1,1) = -0.6292092; v0(1,2) = -0.0056861; + v0(2,0) = -0.5897934; v0(2,1) = 0.7253193; v0(2,2) = 0.3550431; + + v1(0,0) = -0.588443; v1(0,1) = 0.807140; v1(0,2) = -0.047542; + v1(1,0) = -0.786228; v1(1,1) = -0.584933; v1(1,2) = -0.199246; + v1(2,0) = -0.188629; v1(2,1) = -0.079867; v1(2,2) = 0.978795; + + v2(0,0) = -0.277970; v2(0,1) = 0.953559; v2(0,2) = 0.116010; + v2(1,0) = -0.567497; v2(1,1) = -0.065576; v2(1,2) = -0.820760; + v2(2,0) = -0.775035; v2(2,1) = -0.293982; v2(2,2) = 0.559370; + + v3(0,0) = -0.32657; v3(0,1) = -0.60013; v3(0,2) = -0.73020; + v3(1,0) = -0.20022; v3(1,1) = -0.71110; v3(1,2) = 0.67398; + v3(2,0) = -0.92372; v3(2,1) = 0.36630; v3(2,2) = 0.11207; + + simplex[0] = v0; + simplex[1] = v1; + simplex[2] = v2; + simplex[3] = v3; + + std::size_t nm_iterations = 19; + CGAL::Optimal_bounding_box::internal::nelder_mead(simplex, data_points, nm_iterations); + + double epsilon = 1e-5; + const Matrix& v0_new = simplex[0]; + assert(assert_doubles(v0_new(0,0), -0.288975, epsilon)); + assert(assert_doubles(v0_new(0,1), 0.7897657, epsilon)); + assert(assert_doubles(v0_new(0,2), -0.541076, epsilon)); + assert(assert_doubles(v0_new(1,0), -0.9407046, epsilon)); + assert(assert_doubles(v0_new(1,1), -0.3391466, epsilon)); + assert(assert_doubles(v0_new(1,2), 0.0073817, epsilon)); + assert(assert_doubles(v0_new(2,0), -0.1776743, epsilon)); + assert(assert_doubles(v0_new(2,1), 0.5111260, epsilon)); + assert(assert_doubles(v0_new(2,2), 0.84094, epsilon)); + + const Matrix& v1_new = simplex[1]; + assert(assert_doubles(v1_new(0,0), -0.458749, epsilon)); + assert(assert_doubles(v1_new(0,1), 0.823283, epsilon)); + assert(assert_doubles(v1_new(0,2), -0.334296, epsilon)); + assert(assert_doubles(v1_new(1,0), -0.885235, epsilon)); + assert(assert_doubles(v1_new(1,1), -0.455997, epsilon)); + assert(assert_doubles(v1_new(1,2), 0.091794, epsilon)); + assert(assert_doubles(v1_new(2,0), -0.076866, epsilon)); + assert(assert_doubles(v1_new(2,1), 0.338040, epsilon)); + assert(assert_doubles(v1_new(2,2), 0.937987, epsilon)); + + const Matrix& v2_new = simplex[2]; + assert(assert_doubles(v2_new(0,0), -0.346582, epsilon)); + assert(assert_doubles(v2_new(0,1), 0.878534, epsilon)); + assert(assert_doubles(v2_new(0,2), -0.328724, epsilon)); + assert(assert_doubles(v2_new(1,0), -0.936885, epsilon)); + assert(assert_doubles(v2_new(1,1), -0.341445, epsilon)); + assert(assert_doubles(v2_new(1,2), 0.075251, epsilon)); + assert(assert_doubles(v2_new(2,0), -0.046131, epsilon)); + assert(assert_doubles(v2_new(2,1), 0.334057, epsilon)); + assert(assert_doubles(v2_new(2,2), 0.941423, epsilon)); + + const Matrix& v3_new = simplex[3]; + assert(assert_doubles(v3_new(0,0), -0.394713, epsilon)); + assert(assert_doubles(v3_new(0,1), 0.791782, epsilon)); + assert(assert_doubles(v3_new(0,2), -0.466136, epsilon)); + assert(assert_doubles(v3_new(1,0), -0.912112, epsilon)); + assert(assert_doubles(v3_new(1,1), -0.398788, epsilon)); + assert(assert_doubles(v3_new(1,2), 0.094972, epsilon)); + assert(assert_doubles(v3_new(2,0), -0.110692, epsilon)); + assert(assert_doubles(v3_new(2,1), 0.462655, epsilon)); + assert(assert_doubles(v3_new(2,2), 0.879601, epsilon)); +} + +int main() +{ + test_simplex_operations(); + test_centroid(); + test_nelder_mead(); + + return 0; +} diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 7284bbc5fe3..6dbbec359b0 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -18,126 +18,6 @@ bool assert_doubles(double d1, double d2, double epsilon) return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; } -void test_nelder_mead() -{ - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - typedef Linear_algebra_traits::Matrix Matrix; - - Matrix data_points(4,3); - data_points(0,0) = 0.866802; - data_points(0,1) = 0.740808; - data_points(0,2) = 0.895304; - data_points(1,0) = 0.912651; - data_points(1,1) = 0.761565; - data_points(1,2) = 0.160330; - data_points(2,0) = 0.093661; - data_points(2,1) = 0.892578; - data_points(2,2) = 0.737412; - data_points(3,0) = 0.166461; - data_points(3,1) = 0.149912; - data_points(3,2) = 0.364944; - - // one simplex - std::vector simplex(4); - Matrix v0(3,3); - Matrix v1(3,3); - Matrix v2(3,3); - Matrix v3(3,3); - - v0(0,0) = -0.2192721; - v0(0,1) = 0.2792986; - v0(0,2) = -0.9348326; - v0(1,0) = -0.7772152; - v0(1,1) = -0.6292092; - v0(1,2) = -0.0056861; - v0(2,0) = -0.5897934; - v0(2,1) = 0.7253193; - v0(2,2) = 0.3550431; - - v1(0,0) = -0.588443; - v1(0,1) = 0.807140; - v1(0,2) = -0.047542; - v1(1,0) = -0.786228; - v1(1,1) = -0.584933; - v1(1,2) = -0.199246; - v1(2,0) = -0.188629; - v1(2,1) = -0.079867; - v1(2,2) = 0.978795; - - v2(0,0) = -0.277970; - v2(0,1) = 0.953559; - v2(0,2) = 0.116010; - v2(1,0) = -0.567497; - v2(1,1) = -0.065576; - v2(1,2) = -0.820760; - v2(2,0) = -0.775035; - v2(2,1) = -0.293982; - v2(2,2) = 0.559370; - - v3(0,0) = -0.32657; - v3(0,1) = -0.60013; - v3(0,2) = -0.73020; - v3(1,0) = -0.20022; - v3(1,1) = -0.71110; - v3(1,2) = 0.67398; - v3(2,0) = -0.92372; - v3(2,1) = 0.36630; - v3(2,2) = 0.11207; - - simplex[0] = v0; - simplex[1] = v1; - simplex[2] = v2; - simplex[3] = v3; - - std::size_t nm_iterations = 19; - CGAL::Optimal_bounding_box::nelder_mead(simplex, data_points, nm_iterations); - - double epsilon = 1e-5; - const Matrix& v0_new = simplex[0]; - assert(assert_doubles(v0_new(0,0), -0.288975, epsilon)); - assert(assert_doubles(v0_new(0,1), 0.7897657, epsilon)); - assert(assert_doubles(v0_new(0,2), -0.541076, epsilon)); - assert(assert_doubles(v0_new(1,0), -0.9407046, epsilon)); - assert(assert_doubles(v0_new(1,1), -0.3391466, epsilon)); - assert(assert_doubles(v0_new(1,2), 0.0073817, epsilon)); - assert(assert_doubles(v0_new(2,0), -0.1776743, epsilon)); - assert(assert_doubles(v0_new(2,1), 0.5111260, epsilon)); - assert(assert_doubles(v0_new(2,2), 0.84094, epsilon)); - - const Matrix& v1_new = simplex[1]; - assert(assert_doubles(v1_new(0,0), -0.458749, epsilon)); - assert(assert_doubles(v1_new(0,1), 0.823283, epsilon)); - assert(assert_doubles(v1_new(0,2), -0.334296, epsilon)); - assert(assert_doubles(v1_new(1,0), -0.885235, epsilon)); - assert(assert_doubles(v1_new(1,1), -0.455997, epsilon)); - assert(assert_doubles(v1_new(1,2), 0.091794, epsilon)); - assert(assert_doubles(v1_new(2,0), -0.076866, epsilon)); - assert(assert_doubles(v1_new(2,1), 0.338040, epsilon)); - assert(assert_doubles(v1_new(2,2), 0.937987, epsilon)); - - const Matrix& v2_new = simplex[2]; - assert(assert_doubles(v2_new(0,0), -0.346582, epsilon)); - assert(assert_doubles(v2_new(0,1), 0.878534, epsilon)); - assert(assert_doubles(v2_new(0,2), -0.328724, epsilon)); - assert(assert_doubles(v2_new(1,0), -0.936885, epsilon)); - assert(assert_doubles(v2_new(1,1), -0.341445, epsilon)); - assert(assert_doubles(v2_new(1,2), 0.075251, epsilon)); - assert(assert_doubles(v2_new(2,0), -0.046131, epsilon)); - assert(assert_doubles(v2_new(2,1), 0.334057, epsilon)); - assert(assert_doubles(v2_new(2,2), 0.941423, epsilon)); - - const Matrix& v3_new = simplex[3]; - assert(assert_doubles(v3_new(0,0), -0.394713, epsilon)); - assert(assert_doubles(v3_new(0,1), 0.791782, epsilon)); - assert(assert_doubles(v3_new(0,2), -0.466136, epsilon)); - assert(assert_doubles(v3_new(1,0), -0.912112, epsilon)); - assert(assert_doubles(v3_new(1,1), -0.398788, epsilon)); - assert(assert_doubles(v3_new(1,2), 0.094972, epsilon)); - assert(assert_doubles(v3_new(2,0), -0.110692, epsilon)); - assert(assert_doubles(v3_new(2,1), 0.462655, epsilon)); - assert(assert_doubles(v3_new(2,2), 0.879601, epsilon)); -} - void test_genetic_algorithm() { CGAL::Eigen_dense_matrix data_points(4, 3); // -1 = dynamic size at run time @@ -412,8 +292,8 @@ void test_function_defaults_traits(const std::string fname1, int main() { - test_nelder_mead(); test_genetic_algorithm(); + test_random_unit_tetra(); test_reference_tetrahedron("data/reference_tetrahedron.off"); test_long_tetrahedron("data/long_tetrahedron.off"); From c6f3a429fa94daee466c886d21ea52249bc9459a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Dec 2019 15:51:34 +0100 Subject: [PATCH 080/150] Update demo plugin to new API --- .../demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp index 41ed97b2727..a24db1457e1 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Create_obb_mesh_plugin.cpp @@ -14,7 +14,7 @@ #include -#include +#include using namespace CGAL::Three; @@ -138,7 +138,7 @@ void Create_obb_mesh_plugin::obb() // find obb std::array obb_points; - CGAL::optimal_bounding_box(points, obb_points); + CGAL::oriented_bounding_box(points, obb_points); Scene_facegraph_item* item; SMesh* p = new SMesh; From 47b483a11e454cd92d13c1bac1610449232104e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Dec 2019 15:56:09 +0100 Subject: [PATCH 081/150] Tiny doc fixes --- .../CGAL/Optimal_bounding_box/oriented_bounding_box.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 709ca28a74c..a2f76b829c6 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -214,8 +214,8 @@ void construct_oriented_bounding_box(Output& output, /// /// \tparam PointRange a model of `Range` /// \tparam Output either `std::array` with `Point` being equivalent to the traits' `Point_3` type, -/// or the traits' `Affine_transformation_3` type -/// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" +/// or the traits' `Aff_transformation_3` type +/// \tparam NamedParameters a sequence of \ref obb_namedparameters "Named Parameters" /// /// \param points the input points /// \param out the resulting array of points or affine transformation @@ -293,8 +293,8 @@ void oriented_bounding_box(const PointRange& points, /// /// \tparam PolygonMesh a model of `VertexListGraph` /// \tparam Output either `std::array` with `Point` being equivalent to the traits' `Point_3` type, -/// or the traits' `Affine_transformation_3` type -/// \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" +/// or the traits' `Aff_transformation_3` type +/// \tparam NamedParameters a sequence of \ref obb_namedparameters "Named Parameters" /// /// \param pmesh the input mesh /// \param out the resulting array of points or affine transformation From 1ef4ac905b9c67965ce428fe32525cd3eac54c51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Dec 2019 15:57:58 +0100 Subject: [PATCH 082/150] Clean example --- .../examples/Optimal_bounding_box/obb_example.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp index 9cf1ddfd825..e6efa798e8d 100644 --- a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp @@ -11,7 +11,6 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point; -typedef K::Aff_transformation_3 Aff_transformation; typedef CGAL::Surface_mesh Surface_mesh; int main(int argc, char** argv) @@ -24,9 +23,6 @@ int main(int argc, char** argv) return EXIT_FAILURE; } - Aff_transformation aff; - - // API test CGAL::Real_timer timer; timer.start(); From 121fe1cb708e68b2c7c69d524018031cddbe4928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Dec 2019 16:01:57 +0100 Subject: [PATCH 083/150] Test new NP --- BGL/test/BGL/test_cgal_bgl_named_params.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/BGL/test/BGL/test_cgal_bgl_named_params.cpp b/BGL/test/BGL/test_cgal_bgl_named_params.cpp index 70b757b4af0..36b270a903e 100644 --- a/BGL/test/BGL/test_cgal_bgl_named_params.cpp +++ b/BGL/test/BGL/test_cgal_bgl_named_params.cpp @@ -96,6 +96,9 @@ void test(const NamedParameters& np) assert(get_parameter(np, CGAL::internal_np::get_cost_policy).v == 34); assert(get_parameter(np, CGAL::internal_np::get_placement_policy).v == 35); + // Named parameters that we use in the package 'Optimal_bounding_box' + assert(get_parameter(np, CGAL::internal_np::use_convex_hull).v == 58); + // To-be-documented named parameters assert(get_parameter(np, CGAL::internal_np::face_normal).v == 36); assert(get_parameter(np, CGAL::internal_np::random_seed).v == 37); @@ -180,6 +183,9 @@ void test(const NamedParameters& np) check_same_type<34>(get_parameter(np, CGAL::internal_np::get_cost_policy)); check_same_type<35>(get_parameter(np, CGAL::internal_np::get_placement_policy)); + // Named parameters that we use in the package 'Optimal_bounding_box' + check_same_type<58>(get_parameter(np, CGAL::internal_np::use_convex_hull)); + // To-be-documented named parameters check_same_type<36>(get_parameter(np, CGAL::internal_np::face_normal)); check_same_type<37>(get_parameter(np, CGAL::internal_np::random_seed)); @@ -260,11 +266,12 @@ int main() .use_bool_op_to_clip_surface(A<50>(50)) .use_binary_mode(A<51>(51)) .face_size_map(A<52>(52)) - .snapping_tolerance(A<57>(57)) .use_angle_smoothing(A<53>(53)) .use_area_smoothing(A<54>(54)) .use_Delaunay_flips(A<55>(55)) - .use_safety_constraints(A<56>(56)) + .use_safety_constraints(A<56>(56) + .snapping_tolerance(A<57>(57)) + .use_convex_hull(A<58>(58)) ); return EXIT_SUCCESS; From d2072be6265d2d6d0a1686c512d1d3dc74384278 Mon Sep 17 00:00:00 2001 From: Mael Date: Wed, 11 Dec 2019 09:08:29 +0100 Subject: [PATCH 084/150] Add missing license --- Optimal_bounding_box/include/CGAL/optimal_bounding_box.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h index c4c1a33affe..97619cef85f 100644 --- a/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h @@ -20,6 +20,8 @@ * Convenience header file including the headers for all the free functions of this package. */ +#include + #include #include From b63751295240aee550ab8d2370aff9d89fb51c9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 12 Dec 2019 09:49:59 +0100 Subject: [PATCH 085/150] Tiny concept unification --- .../Concepts/OrientedBoundingBoxTraits.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h index 4744f230071..544b8ef7dd0 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h @@ -34,14 +34,14 @@ public: /// matrix-matrix and scalar-matrix multiplication, as well as matrix-matrix addition. typedef unspecified_type Matrix; - /// Returns the transpose of a matrix. - Matrix transpose(const Matrix& mat) const; + /// Returns the transpose of the matrix `m`. + Matrix transpose(const Matrix& m) const; - /// Returns the determinant of a matrix. - FT compute_determinant(const Matrix& matrix) const; + /// Returns the determinant of the matrix `m`. + FT compute_determinant(const Matrix& m) const; - /// Returns the unary matrix Q obtained in the QR decomposition of the matrix `A`. - Matrix get_Q(const Matrix& A) const; + /// Returns the unary matrix `Q` obtained in the QR-decomposition of the matrix `m`. + Matrix get_Q(const Matrix& m) const; }; } // namespace CGAL From aa8efee5c192119b4479cd7c58af432c3d089fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 12 Dec 2019 11:17:36 +0100 Subject: [PATCH 086/150] Fix concept link --- .../Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h index 544b8ef7dd0..c72e96808a8 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h @@ -1,7 +1,7 @@ namespace CGAL { /*! -\ingroup PkgOrientedBoundingBoxConcepts +\ingroup PkgOptimalBoundingBoxConcepts \cgalConcept The concept `OrientedBoundingBoxTraits` describes the requirements of the traits class From ba99311da567fb7b6ed33bea18584833c897a80a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 12 Dec 2019 11:18:29 +0100 Subject: [PATCH 087/150] Simplify OBB concept, remove useless determinant() need --- .../Concepts/OrientedBoundingBoxTraits.h | 11 +---- .../Oriented_bounding_box_traits.h | 22 ++-------- .../Optimal_bounding_box/internal/evolution.h | 2 +- .../Optimal_bounding_box/internal/helper.h | 39 ++++++++++++++++ .../internal/nelder_mead_functions.h | 44 +++++++------------ .../oriented_bounding_box.h | 2 +- .../include/CGAL/optimal_bounding_box.h | 8 ++-- 7 files changed, 68 insertions(+), 60 deletions(-) create mode 100644 Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/helper.h diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h index c72e96808a8..9ab9366cc19 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h @@ -6,8 +6,7 @@ namespace CGAL { The concept `OrientedBoundingBoxTraits` describes the requirements of the traits class used in the function `CGAL::oriented_bounding_box()`, and in particular the need for -a 3x3 matrix type with a number of supporting functions (determinant and transposed matrix -computations, etc.). +a 3x3 matrix type. \cgalHasModel `CGAL::Oriented_bounding_box_traits` @@ -34,13 +33,7 @@ public: /// matrix-matrix and scalar-matrix multiplication, as well as matrix-matrix addition. typedef unspecified_type Matrix; - /// Returns the transpose of the matrix `m`. - Matrix transpose(const Matrix& m) const; - - /// Returns the determinant of the matrix `m`. - FT compute_determinant(const Matrix& m) const; - - /// Returns the unary matrix `Q` obtained in the QR-decomposition of the matrix `m`. + /// Returns the unitary matrix `Q` obtained in the QR-decomposition of the matrix `m`. Matrix get_Q(const Matrix& m) const; }; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h index b76670cdda0..6ab7c1862b4 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h @@ -46,7 +46,7 @@ public: typedef typename K::Point_3 Point_3; /// The affine transformation type - typedef typename K::Aff_transformation_3 Aff_transformation_3; + typedef typename CGAL::Aff_transformation_3 Aff_transformation_3; /// The axis-aligned bounding box construction object typedef typename K::Construct_bbox_3 Construct_bbox_3; @@ -61,25 +61,11 @@ public: /// Offers `construct_bbox_3_object()(const Point_3&)` Construct_bbox_3 construct_bbox_3_object() const { return Construct_bbox_3(); } - /// Returns the transpose of a matrix - Matrix transpose(const Matrix& mat) const - { - return Matrix(mat.eigen_object().transpose()); - } - - /// Returns the determinant of a matrix - FT compute_determinant(const Matrix& matrix) const - { - return matrix.eigen_object().determinant(); - } - - /// Performs QR decomposition of matrix A to a unitary matrix and an upper triagonal + /// Performs QR-decomposition of matrix `m` to a unitary matrix and an upper triagonal /// and returns the unitary matrix. - Matrix get_Q(const Matrix& A) const + Matrix get_Q(const Matrix& m) const { - Eigen::HouseholderQR qr(A.eigen_object()); - CGAL_assertion(CGAL::abs(compute_determinant(Matrix(EigenType(qr.householderQ()))) - 1.) < 0.000001); - + Eigen::HouseholderQR qr(m.eigen_object()); return Matrix(EigenType(qr.householderQ())); } }; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index b8c0ecae405..cbe47f035a2 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -184,7 +185,6 @@ public: #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG const Matrix& R_now = fitness_map.get_best(); std::cout << "new best: " << R_now << std::endl; - std::cout << "det = " << m_traits.compute_determinant(R_now) << std::endl; std::cout << "value difference with previous: " << difference << std::endl; #endif diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/helper.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/helper.h new file mode 100644 index 00000000000..6e05149f064 --- /dev/null +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/helper.h @@ -0,0 +1,39 @@ +// Copyright (c) 2018-2019 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Konstantinos Katrioplas +// Mael Rouxel-Labbé +// +#ifndef CGAL_OPTIMAL_BOUNDING_BOX_INTERNAL_HELPER_H +#define CGAL_OPTIMAL_BOUNDING_BOX_INTERNAL_HELPER_H + +#include + +namespace CGAL { +namespace Optimal_bounding_box { +namespace internal { + +template +Matrix transpose(const Matrix& m) +{ + Matrix tm; + + tm.set(0, 0, m(0, 0)); tm.set(0, 1, m(1, 0)); tm.set(0, 2, m(2, 0)); + tm.set(1, 0, m(0, 1)); tm.set(1, 1, m(1, 1)); tm.set(1, 2, m(2, 1)); + tm.set(2, 0, m(0, 2)); tm.set(2, 1, m(1, 2)); tm.set(2, 2, m(2, 2)); + + return tm; +} + +} // namespace internal +} // namespace Optimal_bounding_box +} // namespace CGAL + +#endif // CGAL_OPTIMAL_BOUNDING_BOX_INTERNAL_HELPER_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h index b6966b71940..8ea3761a931 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h @@ -17,6 +17,7 @@ #include #include +#include #include @@ -27,28 +28,19 @@ namespace CGAL { namespace Optimal_bounding_box { namespace internal { -template +template Matrix reflection(const Matrix& S_centroid, - const Matrix& S_worst, - const Traits& traits) + const Matrix& S_worst) { - CGAL_assertion(S_centroid.number_of_rows() == 3 && S_centroid.number_of_columns() == 3); - CGAL_assertion(S_worst.number_of_rows() == 3 && S_worst.number_of_columns() == 3); - - return S_centroid * traits.transpose(S_worst) * S_centroid; + return S_centroid * transpose(S_worst) * S_centroid; } -template +template Matrix expansion(const Matrix& S_centroid, const Matrix& S_worst, - const Matrix& S_reflection, - const Traits& traits) + const Matrix& S_reflection) { - CGAL_assertion(S_centroid.number_of_rows() == 3 && S_centroid.number_of_columns() == 3); - CGAL_assertion(S_worst.number_of_rows() == 3 && S_worst.number_of_columns() == 3); - CGAL_assertion(S_reflection.number_of_rows() == 3 && S_reflection.number_of_columns() == 3); - - return S_centroid * traits.transpose(S_worst) * S_reflection; + return S_centroid * transpose(S_worst) * S_reflection; } template @@ -56,15 +48,11 @@ Matrix mean(const Matrix& m1, const Matrix& m2, const Traits& traits) { - // same API for reduction - CGAL_assertion(m1.number_of_rows() == 3 && m1.number_of_columns() == 3); - CGAL_assertion(m2.number_of_rows() == 3 && m2.number_of_columns() == 3); + typedef typename Traits::FT FT; - const Matrix reduction = 0.5 * m1 + 0.5 * m2; - const Matrix Q = traits.get_Q(reduction); - const typename Traits::FT det = traits.compute_determinant(Q); + const Matrix reduction = 0.5 * (m1 + m2); - return (1. / det) * Q; + return traits.get_Q(reduction); } template @@ -73,11 +61,11 @@ const Matrix nm_centroid(const Matrix& S1, const Matrix& S3, const Traits& traits) { - const Matrix mean = (1./3.) * (S1 + S2 + S3); - const Matrix Q = traits.get_Q(mean); - const typename Traits::FT det = traits.compute_determinant(Q); + typedef typename Traits::FT FT; - return (1. / det) * Q; + const Matrix mean = (1./3.) * (S1 + S2 + S3); + + return traits.get_Q(mean); } // It's a 3D simplex with 4 rotation matrices as vertices @@ -120,7 +108,7 @@ void nelder_mead(Simplex& simplex, // find worst's vertex reflection const Matrix& v_worst = simplex[3]; - const Matrix v_refl = reflection(v_centroid, v_worst, traits); + const Matrix v_refl = reflection(v_centroid, v_worst); const FT f_refl = compute_fitness(v_refl, points); if(f_refl < fitness[2]) @@ -133,7 +121,7 @@ void nelder_mead(Simplex& simplex, else { // expansion - const Matrix v_expand = expansion(v_centroid, v_worst, v_refl, traits); + const Matrix v_expand = expansion(v_centroid, v_worst, v_refl); const FT f_expand = compute_fitness(v_expand, points); if(f_expand < f_refl) simplex[3] = std::move(v_expand); diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index a2f76b829c6..7f9cb043429 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -119,7 +119,7 @@ void compute_best_transformation(typename Traits::Aff_transformation_3& transfor rot(1, 0), rot(1, 1), rot(1, 2), rot(2, 0), rot(2, 1), rot(2, 2)); - // inverse transformation is simply the transposed since the matrix is unary + // inverse transformation is simply the transposed since the matrix is unitary inverse_transformation = Aff_transformation_3(rot(0, 0), rot(1, 0), rot(2, 0), rot(0, 1), rot(1, 1), rot(2, 1), rot(0, 2), rot(1, 2), rot(2, 2)); diff --git a/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h index 97619cef85f..6e836de4a54 100644 --- a/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h @@ -14,14 +14,16 @@ #ifndef CGAL_OPTIMAL_BOUNDING_BOX_OBB_H #define CGAL_OPTIMAL_BOUNDING_BOX_OBB_H +#ifndef DOXYGEN_RUNNING +#include +#endif + /** * \ingroup PkgOptimalBoundingBoxRef * \file CGAL/optimal_bounding_box.h -* Convenience header file including the headers for all the free functions of this package. +* Convenience header file including the headers for all the classes and functions of this package. */ -#include - #include #include From 528b9b694923cd394501a5ad65c085096debc958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 12 Dec 2019 12:25:46 +0100 Subject: [PATCH 088/150] Misc tiny changes --- .../include/CGAL/Optimal_bounding_box/oriented_bounding_box.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 7f9cb043429..ae2d064b467 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -15,8 +15,8 @@ #include -#include #include +#include #include #include @@ -165,7 +165,6 @@ void construct_oriented_bounding_box(Output& output, { std::vector ch_points; extreme_points_3(points, std::back_inserter(ch_points)); - std::cout << "points on CH: " << ch_points.size() << std::endl; return construct_oriented_bounding_box(output, ch_points, rng, traits); } else From 03aad10541ada75cfd26235bac9384d36469977e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 12 Dec 2019 12:25:59 +0100 Subject: [PATCH 089/150] Generalize oriented_bounding_box to Range + point_map Doc only, implementation later --- .../Optimal_bounding_box/oriented_bounding_box.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index ae2d064b467..fb26db1efa2 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -211,20 +211,20 @@ void construct_oriented_bounding_box(Output& output, /// /// See above. /// -/// \tparam PointRange a model of `Range` +/// \tparam PointRange a model of `Range`. The value type may not be equal to the traits' `Point_3` type +/// if a point map is provided via named parameters (see below) to access points. /// \tparam Output either `std::array` with `Point` being equivalent to the traits' `Point_3` type, /// or the traits' `Aff_transformation_3` type /// \tparam NamedParameters a sequence of \ref obb_namedparameters "Named Parameters" /// -/// \param points the input points +/// \param points the input range /// \param out the resulting array of points or affine transformation /// \param np an optional sequence of \ref obb_namedparameters "Named Parameters" among the ones listed below: /// /// \cgalNamedParamsBegin -/// \cgalParamBegin{vertex_point_map} -/// the property map with the points associated to the vertices of `pmesh`. -/// If this parameter is omitted, an internal property map for -/// `CGAL::vertex_point_t` must be available in `PolygonMesh` +/// \cgalParamBegin{point_map} +/// a model of `ReadPropertyMap` with value type `geom_traits::Point_3`. If this parameter is omitted, +/// `CGAL::Identity_property_map` is used. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} /// a geometric traits class instance, model of the concept `OrientedBoundingBoxTraits`. @@ -288,7 +288,7 @@ void oriented_bounding_box(const PointRange& points, /// \ingroup PkgOptimalBoundingBox_Oriented_bounding_box /// -/// Extracts the vertices of the mesh as a point range and calls the other overload. +/// Extracts the vertices of the mesh as a point range and calls the overload above. /// /// \tparam PolygonMesh a model of `VertexListGraph` /// \tparam Output either `std::array` with `Point` being equivalent to the traits' `Point_3` type, From 99128f9c2027bd3343dc79eff525dbcac960b8ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 12 Dec 2019 12:30:16 +0100 Subject: [PATCH 090/150] Add point_map to OBB's NP --- .../doc/Optimal_bounding_box/NamedParameters.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt index 3ef83f1f9ae..430ab9e4922 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt @@ -30,6 +30,13 @@ is the property map with the points associated to the vertices of the polygon me `GeomTraits::Point_3` as value type. \n Default: \code boost::get(CGAL::vertex_point, pmesh) \endcode \cgalNPEnd + +\cgalNPBegin{point_map} \anchor OBB_point_map + is the property map containing the points associated to the elements of the point range `points`.\n +\b Type: a class model of `ReadablePropertyMap` with `PointRange::iterator::value_type` as key type + and `geom_traits::Point_3` as value type. \n +Default value: \code CGAL::Identity_property_map\endcode +\cgalNPEnd \cgalNPTableEnd In addition to these named parameters, this package offers the following named parameters: From 011bdc865b1660c64067c52ed8d29033defc3e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 7 Jan 2020 15:52:22 +0100 Subject: [PATCH 091/150] Various minor doc fixes --- .../doc/Optimal_bounding_box/dependencies | 1 + .../oriented_bounding_box.h | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/dependencies b/Optimal_bounding_box/doc/Optimal_bounding_box/dependencies index 0379719e9cf..1c28ee0c9b6 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/dependencies +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/dependencies @@ -9,4 +9,5 @@ BGL Solver_interface Surface_mesh AABB_tree +Property_map diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index fb26db1efa2..d6a2d12ece8 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -193,13 +193,13 @@ void construct_oriented_bounding_box(Output& output, /// \cgalHeading{Output} /// /// The result of the algorithm can be retrieved as either: -/// - the best affine transformation (\f$ {\mathcal R}_b\f$) that the algorithm has found; -/// - an array of eight points, representing the best oriented bounding box (\f$ {\mathcal B}_b\f$) -/// that the algorithm has constructed, which is related to (\f$ {\mathcal R}_b\f$) as it is +/// - the best affine transformation \f${\mathcal R}_b\f$ that the algorithm has found; +/// - an array of eight points, representing the best oriented bounding box (\f${\mathcal B}_b\f$) +/// that the algorithm has constructed, which is related to \f$ {\mathcal R}_b\f$ as it is /// the inverse transformation of the axis-aligned bounding box of the transformed point set. /// The order of the points in the array is the same as in the function /// \link PkgBGLHelperFct `CGAL::make_hexahedron()` \endlink, -/// which is a useful function to construct a mesh from these points. +/// which can be used to construct a mesh from these points. /// /// Note that when returning an array of points, these points are constructed from the axis-aligned /// bounding box and some precision loss should therefore be expected if a kernel not providing @@ -213,8 +213,8 @@ void construct_oriented_bounding_box(Output& output, /// /// \tparam PointRange a model of `Range`. The value type may not be equal to the traits' `Point_3` type /// if a point map is provided via named parameters (see below) to access points. -/// \tparam Output either `std::array` with `Point` being equivalent to the traits' `Point_3` type, -/// or the traits' `Aff_transformation_3` type +/// \tparam Output either the traits' `Aff_transformation_3` type, +/// or `std::array` with `Point` being equivalent to the traits' `Point_3` type /// \tparam NamedParameters a sequence of \ref obb_namedparameters "Named Parameters" /// /// \param points the input range @@ -223,7 +223,7 @@ void construct_oriented_bounding_box(Output& output, /// /// \cgalNamedParamsBegin /// \cgalParamBegin{point_map} -/// a model of `ReadPropertyMap` with value type `geom_traits::Point_3`. If this parameter is omitted, +/// a model of `ReadablePropertyMap` with value type `geom_traits::Point_3`. If this parameter is omitted, /// `CGAL::Identity_property_map` is used. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} @@ -291,8 +291,8 @@ void oriented_bounding_box(const PointRange& points, /// Extracts the vertices of the mesh as a point range and calls the overload above. /// /// \tparam PolygonMesh a model of `VertexListGraph` -/// \tparam Output either `std::array` with `Point` being equivalent to the traits' `Point_3` type, -/// or the traits' `Aff_transformation_3` type +/// \tparam Output either the traits' `Aff_transformation_3` type, +/// or `std::array` with `Point` being equivalent to the traits' `Point_3` type /// \tparam NamedParameters a sequence of \ref obb_namedparameters "Named Parameters" /// /// \param pmesh the input mesh From f883bc9c237ac4da36eba47c36abc64d135c8791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 7 Jan 2020 15:59:21 +0100 Subject: [PATCH 092/150] Fix some header includes --- .../CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h | 2 ++ .../test/Optimal_bounding_box/test_nelder_mead.cpp | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h index 6ab7c1862b4..9b616562569 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h @@ -15,6 +15,8 @@ #include +#include + #ifdef CGAL_EIGEN3_ENABLED #include #include diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp index ad1751f915c..bb41c4a021a 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp @@ -1,5 +1,6 @@ -#include -#include +#include + +#include #include From a9b1701980a7bdd2956ba7571fbe75fef25cbd5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 7 Jan 2020 17:00:45 +0100 Subject: [PATCH 093/150] Move concept out of ::CGAL:: namespace --- .../Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h | 4 ---- .../doc/Optimal_bounding_box/PackageDescription.txt | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h index 9ab9366cc19..c68e63ffec8 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h @@ -1,5 +1,3 @@ -namespace CGAL { - /*! \ingroup PkgOptimalBoundingBoxConcepts \cgalConcept @@ -36,5 +34,3 @@ public: /// Returns the unitary matrix `Q` obtained in the QR-decomposition of the matrix `m`. Matrix get_Q(const Matrix& m) const; }; - -} // namespace CGAL diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt index 438f248e4c5..f75add083e8 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt @@ -40,7 +40,7 @@ that are used in this package. \cgalCRPSection{Concepts} -- `CGAL::OrientedBoundingBoxTraits` +- `OrientedBoundingBoxTraits` \cgalCRPSection{Classes} From ae19de584a8f67d9c539f1f4f1700a78a0d929f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 10 Jan 2020 10:11:00 +0100 Subject: [PATCH 094/150] Change after review 1 https://cgal.geometryfactory.com/CGAL/Members/wiki/Features/Optimal_bounding_box/1st_round/Answer_to_review_1 --- .../Concepts/OrientedBoundingBoxTraits.h | 17 +++++---- .../PackageDescription.txt | 4 +-- ...its.h => Oriented_bounding_box_traits_3.h} | 10 +++--- .../Optimal_bounding_box/internal/evolution.h | 26 +++++++------- .../internal/nelder_mead_functions.h | 4 +-- .../oriented_bounding_box.h | 35 ++++++++++--------- .../include/CGAL/optimal_bounding_box.h | 2 +- .../Optimal_bounding_box/test_nelder_mead.cpp | 2 +- 8 files changed, 53 insertions(+), 47 deletions(-) rename Optimal_bounding_box/include/CGAL/Optimal_bounding_box/{Oriented_bounding_box_traits.h => Oriented_bounding_box_traits_3.h} (87%) diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h index c68e63ffec8..215a5b38fd5 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h @@ -2,24 +2,24 @@ \ingroup PkgOptimalBoundingBoxConcepts \cgalConcept -The concept `OrientedBoundingBoxTraits` describes the requirements of the traits class +The concept `OrientedBoundingBoxTraits_3` describes the requirements of the traits class used in the function `CGAL::oriented_bounding_box()`, and in particular the need for a 3x3 matrix type. -\cgalHasModel `CGAL::Oriented_bounding_box_traits` +\cgalHasModel `CGAL::Oriented_bounding_box_traits_3` */ -class OrientedBoundingBoxTraits +class OrientedBoundingBoxTraits_3 { public: - /// The field number type; must be a model of the concept `FieldNumberType`. + /// The field number type; must be a model of the concept `FieldNumberType` typedef unspecified_type FT; /// The 3D point type; must be model of `Point_3` typedef unspecified_type Point_3; /// The 3D affine transformation type; the template parameter `K` must be a model of `Kernel` - /// and be compatible with the type `Point_3`. + /// and be compatible with the type `Point_3` typedef CGAL::Aff_transformation_3 Aff_transformation_3; /// A construction object that must provide the function operator: @@ -28,9 +28,12 @@ public: typedef unspecified_type Construct_bbox_3; /// A 3x3 matrix type; model of the concept `SvdTraits::Matrix` and which supports - /// matrix-matrix and scalar-matrix multiplication, as well as matrix-matrix addition. + /// matrix-matrix and scalar-matrix multiplication, as well as matrix-matrix addition typedef unspecified_type Matrix; - /// Returns the unitary matrix `Q` obtained in the QR-decomposition of the matrix `m`. + /// Returns the unitary matrix `Q` obtained in the QR-decomposition of the matrix `m` Matrix get_Q(const Matrix& m) const; + + /// Gives access to the `Construct_bbox_3` construction object + Construct_bbox_3 construct_bbox_3_object() const { return Construct_bbox_3(); } }; diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt index f75add083e8..b5d53fd80e3 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt @@ -40,11 +40,11 @@ that are used in this package. \cgalCRPSection{Concepts} -- `OrientedBoundingBoxTraits` +- `OrientedBoundingBoxTraits_3` \cgalCRPSection{Classes} -- `CGAL::Oriented_bounding_box_traits` +- `CGAL::Oriented_bounding_box_traits_3` \cgalCRPSection{Methods} diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h similarity index 87% rename from Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h rename to Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h index 9b616562569..80092165d64 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h @@ -28,17 +28,17 @@ namespace CGAL { /// \ingroup PkgOptimalBoundingBoxClasses /// -/// The class `CGAL::Oriented_bounding_box_traits` is a traits type -/// to be used with the functions `CGAL::oriented_bounding_box()`. +/// The class `CGAL::Oriented_bounding_box_traits_3` is a traits type +/// to be used with the overloads of the function `CGAL::oriented_bounding_box()`. /// It uses the third party library \ref thirdpartyEigen "Eigen", which must therefore /// be available on the system for this class to be used. /// /// \tparam K must be a model of `Kernel` /// -/// \cgalModels `OrientedBoundingBoxTraits` +/// \cgalModels `OrientedBoundingBoxTraits_3` /// template -class Oriented_bounding_box_traits +class Oriented_bounding_box_traits_3 { public: /// The field number type @@ -60,7 +60,7 @@ private: typedef typename Matrix::EigenType EigenType; public: - /// Offers `construct_bbox_3_object()(const Point_3&)` + /// Returns a default-constructed construction object Construct_bbox_3 construct_bbox_3_object() const { return Construct_bbox_3(); } /// Performs QR-decomposition of matrix `m` to a unitary matrix and an upper triagonal diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index cbe47f035a2..f3563f57c79 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -75,7 +75,7 @@ public: std::generate(group4.begin(), group4.end(), [&]{ return m_rng.get_int(0, im); }); // crossover I - double bias = 0.1; + FT bias = FT(0.1); std::vector new_simplices(m); @@ -84,10 +84,10 @@ public: std::array offspring; for(int j=0; j<4; ++j) { - const double r = m_rng.get_double(); - const double fitnessA = compute_fitness(m_population[group1[i]][j], m_points); - const double fitnessB = compute_fitness(m_population[group2[i]][j], m_points); - const double threshold = (fitnessA < fitnessB) ? (0.5 + bias) : (0.5 - bias); + const FT r = FT(m_rng.get_double()); + const FT fitnessA = compute_fitness(m_population[group1[i]][j], m_points); + const FT fitnessB = compute_fitness(m_population[group2[i]][j], m_points); + const FT threshold = (fitnessA < fitnessB) ? (0.5 + bias) : (0.5 - bias); if(r < threshold) offspring[j] = m_population[group1[i]][j]; @@ -106,10 +106,10 @@ public: std::array offspring; for(int j=0; j<4; ++j) { - const double fitnessA = compute_fitness(m_population[group3[i]][j], m_points); - const double fitnessB = compute_fitness(m_population[group4[i]][j], m_points); - const double lambda = (fitnessA < fitnessB) ? (0.5 + bias) : (0.5 - bias); - const double rambda = 1 - lambda; // the 'l' in 'lambda' stands for left + const FT fitnessA = compute_fitness(m_population[group3[i]][j], m_points); + const FT fitnessB = compute_fitness(m_population[group4[i]][j], m_points); + const FT lambda = (fitnessA < fitnessB) ? (0.5 + bias) : (0.5 - bias); + const FT rambda = 1 - lambda; // the 'l' in 'lambda' stands for left // combine information from A and B Matrix new_vertex(3, 3); @@ -148,9 +148,9 @@ public: const std::size_t nelder_mead_iterations = 150; // stopping criteria prameters - double prev_fit_value = 0.; - double new_fit_value = 0.; - const double tolerance = 1e-9; + FT prev_fit_value = 0.; + FT new_fit_value = 0.; + const FT tolerance = 1e-9; int stale = 0; for(std::size_t t=0; t #include -#include +#include #include #include @@ -58,7 +58,6 @@ void construct_oriented_bounding_box(std::array& ob const PointRange& points, const Traits& traits) { - typedef typename Traits::FT FT; typedef typename Traits::Point_3 Point; // Construct the bbox of the transformed point set @@ -209,12 +208,16 @@ void construct_oriented_bounding_box(Output& output, /// \ingroup PkgOptimalBoundingBox_Oriented_bounding_box /// -/// See above. +/// The function `oriented_bounding_box` computes an approximation of the optimal bounding box, +/// which is defined as the rectangular box with smallest volume of all the rectangular boxes containing +/// the input points. /// -/// \tparam PointRange a model of `Range`. The value type may not be equal to the traits' `Point_3` type +/// See \ref PkgOptimalBoundingBox_Oriented_bounding_box for more information. +/// +/// \tparam PointRange a model of `Range`. The value type may not be equal to the type `%Point_3` of the traits class /// if a point map is provided via named parameters (see below) to access points. -/// \tparam Output either the traits' `Aff_transformation_3` type, -/// or `std::array` with `Point` being equivalent to the traits' `Point_3` type +/// \tparam Output either the type `Aff_transformation_3` of the traits class, +/// or `std::array` with `Point` being equivalent to the type `%Point_3` of the traits class /// \tparam NamedParameters a sequence of \ref obb_namedparameters "Named Parameters" /// /// \param points the input range @@ -223,12 +226,12 @@ void construct_oriented_bounding_box(Output& output, /// /// \cgalNamedParamsBegin /// \cgalParamBegin{point_map} -/// a model of `ReadablePropertyMap` with value type `geom_traits::Point_3`. If this parameter is omitted, -/// `CGAL::Identity_property_map` is used. +/// a model of `ReadablePropertyMap` with value type the type`%Point_3` of the traits class. +/// If this parameter is omitted, `CGAL::Identity_property_map<%Point_3>` is used. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of the concept `OrientedBoundingBoxTraits`. -/// %Default is `CGAL::Oriented_bounding_box_traits` where `K` is deduced from the point type. +/// a geometric traits class instance, model of the concept `OrientedBoundingBoxTraits_3`. +/// %Default is `CGAL::Oriented_bounding_box_traits_3` where `K` is deduced from the point type. /// \cgalParamEnd /// \cgalParamBegin{use_convex_hull} /// a Boolean value to indicate whether the algorithm should first extract the so-called extreme @@ -256,7 +259,7 @@ void oriented_bounding_box(const PointRange& points, #if defined(CGAL_EIGEN3_ENABLED) typedef typename boost::range_value::type Point; typedef typename CGAL::Kernel_traits::type K; - typedef Oriented_bounding_box_traits Default_traits; + typedef Oriented_bounding_box_traits_3 Default_traits; #else typedef void Default_traits; #endif @@ -288,11 +291,11 @@ void oriented_bounding_box(const PointRange& points, /// \ingroup PkgOptimalBoundingBox_Oriented_bounding_box /// -/// Extracts the vertices of the mesh as a point range and calls the overload above. +/// Extracts the vertices of the mesh as a point range and calls the overload using points as input. /// /// \tparam PolygonMesh a model of `VertexListGraph` -/// \tparam Output either the traits' `Aff_transformation_3` type, -/// or `std::array` with `Point` being equivalent to the traits' `Point_3` type +/// \tparam Output either the type `Aff_transformation_3` of the traits class, +/// or `std::array` with `Point` being equivalent to the type `%Point_3` of the traits class /// \tparam NamedParameters a sequence of \ref obb_namedparameters "Named Parameters" /// /// \param pmesh the input mesh @@ -306,8 +309,8 @@ void oriented_bounding_box(const PointRange& points, /// `CGAL::vertex_point_t` must be available in `PolygonMesh` /// \cgalParamEnd /// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of the concept `OrientedBoundingBoxTraits`. -/// %Default is `CGAL::Oriented_bounding_box_traits` where `K` is deduced from the point type. +/// a geometric traits class instance, model of the concept `OrientedBoundingBoxTraits_3`. +/// %Default is `CGAL::Oriented_bounding_box_traits_3` where `K` is deduced from the point type. /// \cgalParamEnd /// \cgalParamBegin{use_convex_hull} /// a Boolean value to indicate whether the algorithm should first extract the so-called extreme diff --git a/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h index 6e836de4a54..ba9a4d1d813 100644 --- a/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/optimal_bounding_box.h @@ -24,7 +24,7 @@ * Convenience header file including the headers for all the classes and functions of this package. */ -#include +#include #include #endif // CGAL_OPTIMAL_BOUNDING_BOX_OBB_H diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp index bb41c4a021a..a84cb83b5ea 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp @@ -7,7 +7,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point_3; -typedef CGAL::Oriented_bounding_box_traits Traits; +typedef CGAL::Oriented_bounding_box_traits_3 Traits; typedef Traits::Matrix Matrix; bool are_equal(double d1, double d2, double epsilon) From c483680ad814ca402df0e450ec69db8622641eff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 29 Jan 2020 13:18:42 +0100 Subject: [PATCH 095/150] Fixes after review #2 --- .../Concepts/OrientedBoundingBoxTraits.h | 6 +++--- .../doc/Optimal_bounding_box/NamedParameters.txt | 10 +++++----- .../doc/Optimal_bounding_box/PackageDescription.txt | 4 ++-- .../Oriented_bounding_box_traits_3.h | 6 +++--- .../CGAL/Optimal_bounding_box/oriented_bounding_box.h | 6 ++++-- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h index 215a5b38fd5..b2ebf4ab60b 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h @@ -15,7 +15,7 @@ public: /// The field number type; must be a model of the concept `FieldNumberType` typedef unspecified_type FT; - /// The 3D point type; must be model of `Point_3` + /// The 3D point type; must be model of `Kernel::Point_3` typedef unspecified_type Point_3; /// The 3D affine transformation type; the template parameter `K` must be a model of `Kernel` @@ -24,7 +24,7 @@ public: /// A construction object that must provide the function operator: /// `CGAL::Bbox_3 operator()(const Point_3&)`, - /// which returns an axis-aligned bounding that contains the point + /// which returns an axis-aligned bounding box that contains the point typedef unspecified_type Construct_bbox_3; /// A 3x3 matrix type; model of the concept `SvdTraits::Matrix` and which supports @@ -35,5 +35,5 @@ public: Matrix get_Q(const Matrix& m) const; /// Gives access to the `Construct_bbox_3` construction object - Construct_bbox_3 construct_bbox_3_object() const { return Construct_bbox_3(); } + Construct_bbox_3 construct_bbox_3_object() const; }; diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt index 430ab9e4922..1194850104a 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/NamedParameters.txt @@ -33,9 +33,9 @@ is the property map with the points associated to the vertices of the polygon me \cgalNPBegin{point_map} \anchor OBB_point_map is the property map containing the points associated to the elements of the point range `points`.\n -\b Type: a class model of `ReadablePropertyMap` with `PointRange::iterator::value_type` as key type +Type: a class model of `ReadablePropertyMap` with `PointRange::iterator::value_type` as key type and `geom_traits::Point_3` as value type. \n -Default value: \code CGAL::Identity_property_map\endcode +Default: \code CGAL::Identity_property_map\endcode \cgalNPEnd \cgalNPTableEnd @@ -45,7 +45,7 @@ In addition to these named parameters, this package offers the following named p \cgalNPBegin{geom_traits} \anchor OBB_geom_traits is the geometric traits instance in which the mesh processing operation should be performed.\n Type: a Geometric traits class.\n -Default: +Default: \code typename CGAL::Kernel_traits< typename boost::property_traits< typename boost::property_map::type>::value_type>::Kernel \endcode @@ -56,8 +56,8 @@ Parameter used in the construction of oriented bounding box to indicate whether first extract the extreme points (points that are on the 3D convex hull) of the input data range to accelerate the computation of the bounding box. \n -\b Type : `bool` \n -\b Default value is `true` +Type: `bool` \n +Default: `true` \cgalNPEnd \cgalNPTableEnd diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt index b5d53fd80e3..d06675df4c7 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/PackageDescription.txt @@ -6,10 +6,10 @@ /// \defgroup PkgOptimalBoundingBoxClasses Optimal Bounding Box Classes /// \ingroup PkgOptimalBoundingBoxRef -/// \defgroup PkgOptimalBoundingBoxFunctions Optimal Bounding Box Methods +/// \defgroup PkgOptimalBoundingBoxFunctions Optimal Bounding Box Functions /// \ingroup PkgOptimalBoundingBoxRef -/// \defgroup PkgOptimalBoundingBox_Oriented_bounding_box Oriented Bounding Box Methods +/// \defgroup PkgOptimalBoundingBox_Oriented_bounding_box Oriented Bounding Box Functions /// \ingroup PkgOptimalBoundingBoxFunctions /*! diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h index 80092165d64..06c67bc74d0 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h @@ -30,8 +30,8 @@ namespace CGAL { /// /// The class `CGAL::Oriented_bounding_box_traits_3` is a traits type /// to be used with the overloads of the function `CGAL::oriented_bounding_box()`. -/// It uses the third party library \ref thirdpartyEigen "Eigen", which must therefore -/// be available on the system for this class to be used. +/// +/// \attention This class requires the \ref thirdpartyEigen "Eigen" library. /// /// \tparam K must be a model of `Kernel` /// @@ -63,7 +63,7 @@ public: /// Returns a default-constructed construction object Construct_bbox_3 construct_bbox_3_object() const { return Construct_bbox_3(); } - /// Performs QR-decomposition of matrix `m` to a unitary matrix and an upper triagonal + /// Performs the QR-decomposition of the matrix `m` to a unitary matrix and an upper triagonal /// and returns the unitary matrix. Matrix get_Q(const Matrix& m) const { diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 90cc1c68084..06f07e845e0 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -231,7 +231,8 @@ void construct_oriented_bounding_box(Output& output, /// \cgalParamEnd /// \cgalParamBegin{geom_traits} /// a geometric traits class instance, model of the concept `OrientedBoundingBoxTraits_3`. -/// %Default is `CGAL::Oriented_bounding_box_traits_3` where `K` is deduced from the point type. +/// %Default is a default construction object of type `CGAL::Oriented_bounding_box_traits_3` +/// where `K` is a kernel type deduced from the point type. /// \cgalParamEnd /// \cgalParamBegin{use_convex_hull} /// a Boolean value to indicate whether the algorithm should first extract the so-called extreme @@ -310,7 +311,8 @@ void oriented_bounding_box(const PointRange& points, /// \cgalParamEnd /// \cgalParamBegin{geom_traits} /// a geometric traits class instance, model of the concept `OrientedBoundingBoxTraits_3`. -/// %Default is `CGAL::Oriented_bounding_box_traits_3` where `K` is deduced from the point type. +/// %Default is a default construction object of type `CGAL::Oriented_bounding_box_traits_3` +/// where `K` is a kernel type deduced from the point type. /// \cgalParamEnd /// \cgalParamBegin{use_convex_hull} /// a Boolean value to indicate whether the algorithm should first extract the so-called extreme From 5f1eed50484be21775085e71965fccbd4edcb5f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 31 Jan 2020 12:14:11 +0100 Subject: [PATCH 096/150] Doc fixes --- .../Concepts/OrientedBoundingBoxTraits.h | 2 +- .../Optimal_bounding_box/oriented_bounding_box.h | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h index b2ebf4ab60b..cbd5ab6a5b8 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h @@ -34,6 +34,6 @@ public: /// Returns the unitary matrix `Q` obtained in the QR-decomposition of the matrix `m` Matrix get_Q(const Matrix& m) const; - /// Gives access to the `Construct_bbox_3` construction object + /// Returns the 3D box construction functor Construct_bbox_3 construct_bbox_3_object() const; }; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 06f07e845e0..1b8cacc741d 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -246,11 +246,11 @@ template void oriented_bounding_box(const PointRange& points, Output& out, - const CGAL_BGL_NP_CLASS& np, + const CGAL_BGL_NP_CLASS& np #ifndef DOXYGEN_RUNNING - typename boost::enable_if< - typename boost::has_range_iterator - >::type* = 0 + , typename boost::enable_if< + typename boost::has_range_iterator + >::type* = 0 #endif ) { @@ -326,11 +326,11 @@ template void oriented_bounding_box(const PolygonMesh& pmesh, Output& out, - const CGAL_BGL_NP_CLASS& np, + const CGAL_BGL_NP_CLASS& np #ifndef DOXYGEN_RUNNING - typename boost::disable_if< - typename boost::has_range_iterator - >::type* = 0 + , typename boost::disable_if< + typename boost::has_range_iterator + >::type* = 0 #endif ) { From 24a696d0ae83d6b3efe55971f60e0a0d6da02c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 3 Feb 2020 11:05:53 +0100 Subject: [PATCH 097/150] Remove a dot --- .../CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h index 06c67bc74d0..7de034882a4 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h @@ -64,7 +64,7 @@ public: Construct_bbox_3 construct_bbox_3_object() const { return Construct_bbox_3(); } /// Performs the QR-decomposition of the matrix `m` to a unitary matrix and an upper triagonal - /// and returns the unitary matrix. + /// and returns the unitary matrix Matrix get_Q(const Matrix& m) const { Eigen::HouseholderQR qr(m.eigen_object()); From 384123b3b32fdeb844ef27fb6f2319dd16b54985 Mon Sep 17 00:00:00 2001 From: Mael Date: Mon, 3 Feb 2020 13:19:44 +0100 Subject: [PATCH 098/150] Add missing space --- .../include/CGAL/Optimal_bounding_box/oriented_bounding_box.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 1b8cacc741d..68149f2ad76 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -226,7 +226,7 @@ void construct_oriented_bounding_box(Output& output, /// /// \cgalNamedParamsBegin /// \cgalParamBegin{point_map} -/// a model of `ReadablePropertyMap` with value type the type`%Point_3` of the traits class. +/// a model of `ReadablePropertyMap` with value type the type `%Point_3` of the traits class. /// If this parameter is omitted, `CGAL::Identity_property_map<%Point_3>` is used. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} From 75bd7b3b79c39e562ee6fdcb930ba071d6ee4ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 9 Mar 2020 16:54:39 +0100 Subject: [PATCH 099/150] Regenerate travis.yml --- .travis.yml | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1fbffbcaa3e..67ef61cbf57 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,28 +30,29 @@ env: - PACKAGE='Minkowski_sum_2 Minkowski_sum_3 Modifier ' - PACKAGE='Modular_arithmetic Nef_2 Nef_3 ' - PACKAGE='Nef_S2 NewKernel_d Number_types ' - - PACKAGE='OpenNL Optimal_transportation_reconstruction_2 Optimisation_basic ' - - PACKAGE='Partition_2 Periodic_2_triangulation_2 Periodic_3_mesh_3 ' - - PACKAGE='Periodic_3_triangulation_3 Periodic_4_hyperbolic_triangulation_2 Point_set_2 ' - - PACKAGE='Point_set_3 Point_set_processing_3 Poisson_surface_reconstruction_3 ' - - PACKAGE='Polygon Polygon_mesh_processing Polygonal_surface_reconstruction ' - - PACKAGE='Polyhedron Polyhedron_IO Polyline_simplification_2 ' - - PACKAGE='Polynomial Polytope_distance_d Principal_component_analysis ' - - PACKAGE='Principal_component_analysis_LGPL Profiling_tools Property_map ' - - PACKAGE='QP_solver Random_numbers Ridges_3 ' - - PACKAGE='STL_Extension Scale_space_reconstruction_3 Scripts ' - - PACKAGE='SearchStructures Segment_Delaunay_graph_2 Segment_Delaunay_graph_Linf_2 ' - - PACKAGE='Set_movable_separability_2 Shape_detection Skin_surface_3 ' - - PACKAGE='Snap_rounding_2 Solver_interface Spatial_searching ' - - PACKAGE='Spatial_sorting Straight_skeleton_2 Stream_lines_2 ' - - PACKAGE='Stream_support Subdivision_method_3 Surface_mesh ' - - PACKAGE='Surface_mesh_approximation Surface_mesh_deformation Surface_mesh_parameterization ' - - PACKAGE='Surface_mesh_segmentation Surface_mesh_shortest_path Surface_mesh_simplification ' - - PACKAGE='Surface_mesh_skeletonization Surface_mesh_topology Surface_mesher ' - - PACKAGE='Surface_sweep_2 TDS_2 TDS_3 ' - - PACKAGE='Testsuite Three Triangulation ' - - PACKAGE='Triangulation_2 Triangulation_3 Union_find ' - - PACKAGE='Visibility_2 Voronoi_diagram_2 wininst ' + - PACKAGE='OpenNL Optimal_bounding_box Optimal_transportation_reconstruction_2 ' + - PACKAGE='Optimisation_basic Partition_2 Periodic_2_triangulation_2 ' + - PACKAGE='Periodic_3_mesh_3 Periodic_3_triangulation_3 Periodic_4_hyperbolic_triangulation_2 ' + - PACKAGE='Point_set_2 Point_set_3 Point_set_processing_3 ' + - PACKAGE='Poisson_surface_reconstruction_3 Polygon Polygon_mesh_processing ' + - PACKAGE='Polygonal_surface_reconstruction Polyhedron Polyhedron_IO ' + - PACKAGE='Polyline_simplification_2 Polynomial Polytope_distance_d ' + - PACKAGE='Principal_component_analysis Principal_component_analysis_LGPL Profiling_tools ' + - PACKAGE='Property_map QP_solver Random_numbers ' + - PACKAGE='Ridges_3 STL_Extension Scale_space_reconstruction_3 ' + - PACKAGE='Scripts SearchStructures Segment_Delaunay_graph_2 ' + - PACKAGE='Segment_Delaunay_graph_Linf_2 Set_movable_separability_2 Shape_detection ' + - PACKAGE='Skin_surface_3 Snap_rounding_2 Solver_interface ' + - PACKAGE='Spatial_searching Spatial_sorting Straight_skeleton_2 ' + - PACKAGE='Stream_lines_2 Stream_support Subdivision_method_3 ' + - PACKAGE='Surface_mesh Surface_mesh_approximation Surface_mesh_deformation ' + - PACKAGE='Surface_mesh_parameterization Surface_mesh_segmentation Surface_mesh_shortest_path ' + - PACKAGE='Surface_mesh_simplification Surface_mesh_skeletonization Surface_mesh_topology ' + - PACKAGE='Surface_mesher Surface_sweep_2 TDS_2 ' + - PACKAGE='TDS_3 Testsuite Three ' + - PACKAGE='Triangulation Triangulation_2 Triangulation_3 ' + - PACKAGE='Union_find Visibility_2 Voronoi_diagram_2 ' + - PACKAGE='wininst ' compiler: clang install: - echo "$PWD" From 1db10135a60ce7bdc7f34de12bdc76d1a68b6f06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Mar 2020 13:47:50 +0100 Subject: [PATCH 100/150] Change namespaces from internal::Convex_hull_3 to Convex_hull_3::internal On-going uniformization work --- ...fspace_intersection_with_constructions_3.h | 2 +- .../CGAL/Extreme_points_traits_adapter_3.h | 33 ++++++----- Convex_hull_3/include/CGAL/convex_hull_3.h | 56 ++++++++++--------- .../quick_hull_default_traits.cpp | 2 +- 4 files changed, 50 insertions(+), 43 deletions(-) diff --git a/Convex_hull_3/include/CGAL/Convex_hull_3/dual/halfspace_intersection_with_constructions_3.h b/Convex_hull_3/include/CGAL/Convex_hull_3/dual/halfspace_intersection_with_constructions_3.h index cb994d5d8ea..4b529217f68 100644 --- a/Convex_hull_3/include/CGAL/Convex_hull_3/dual/halfspace_intersection_with_constructions_3.h +++ b/Convex_hull_3/include/CGAL/Convex_hull_3/dual/halfspace_intersection_with_constructions_3.h @@ -142,7 +142,7 @@ namespace CGAL boost::optional::value_type>::Kernel::Point_3> const& origin = boost::none) { typedef typename Kernel_traits::value_type>::Kernel K; typedef typename K::Point_3 Point_3; - typedef typename internal::Convex_hull_3::Default_traits_for_Chull_3::type Traits; + typedef typename Convex_hull_3::internal::Default_traits_for_Chull_3::type Traits; halfspace_intersection_with_constructions_3(pbegin, pend, P, origin, Traits()); } diff --git a/Convex_hull_3/include/CGAL/Extreme_points_traits_adapter_3.h b/Convex_hull_3/include/CGAL/Extreme_points_traits_adapter_3.h index 2bfc28b4384..8934091b740 100644 --- a/Convex_hull_3/include/CGAL/Extreme_points_traits_adapter_3.h +++ b/Convex_hull_3/include/CGAL/Extreme_points_traits_adapter_3.h @@ -24,11 +24,10 @@ #include #include - - namespace CGAL { +namespace Convex_hull_3 { +namespace internal { -namespace Convex_hull_impl{ template struct Forward_functor : public F @@ -67,10 +66,13 @@ struct Forward_functor get(vpm_,s)); } }; -}//end Convex_hull_impl + +} // namespace internal +} // namespace Convex_hull_3 + template< class PointPropertyMap, - class Base_traits=typename internal::Convex_hull_3::Default_traits_for_Chull_3< + class Base_traits = typename Convex_hull_3::internal::Default_traits_for_Chull_3< typename boost::property_traits::value_type>::type > class Extreme_points_traits_adapter_3 @@ -85,10 +87,11 @@ public: {} typedef typename boost::property_traits::key_type Vertex; typedef Vertex Point_3; - typedef Convex_hull_impl::Forward_functor Equal_3; - typedef Convex_hull_impl::Forward_functor Collinear_3; - typedef Convex_hull_impl::Forward_functor Coplanar_3; - typedef Convex_hull_impl::Forward_functor Less_distance_to_point_3; + typedef Convex_hull_3::internal::Forward_functor Equal_3; + typedef Convex_hull_3::internal::Forward_functor Collinear_3; + typedef Convex_hull_3::internal::Forward_functor Coplanar_3; + typedef Convex_hull_3::internal::Forward_functor Less_distance_to_point_3; + class Less_signed_distance_to_plane_3 :public Base_traits::Less_signed_distance_to_plane_3 { @@ -167,11 +170,11 @@ public: Proj_traits_3(const PointPropertyMap& map,const Btt& base): Base_proj_traits(base),vpm_(map){} typedef Point_3 Point_2; - typedef Convex_hull_impl::Forward_functor Equal_2; - typedef Convex_hull_impl::Forward_functor Less_xy_2; - typedef Convex_hull_impl::Forward_functor Less_yx_2; - typedef Convex_hull_impl::Forward_functor Less_signed_distance_to_line_2; - typedef Convex_hull_impl::Forward_functor Left_turn_2; + typedef Convex_hull_3::internal::Forward_functor Equal_2; + typedef Convex_hull_3::internal::Forward_functor Less_xy_2; + typedef Convex_hull_3::internal::Forward_functor Less_yx_2; + typedef Convex_hull_3::internal::Forward_functor Less_signed_distance_to_line_2; + typedef Convex_hull_3::internal::Forward_functor Left_turn_2; class Less_rotate_ccw_2:public Btt::Less_rotate_ccw_2 { @@ -212,7 +215,7 @@ public: Orientation_2 orientation_2_object ()const{return Orientation_2(vpm_,static_cast(this)->orientation_2_object() );} }; - typedef internal::Convex_hull_3::Projection_traits Base_PTraits; + typedef Convex_hull_3::internal::Projection_traits Base_PTraits; typedef Proj_traits_3 Traits_xy_3; typedef Proj_traits_3 Traits_yz_3; typedef Proj_traits_3 Traits_xz_3; diff --git a/Convex_hull_3/include/CGAL/convex_hull_3.h b/Convex_hull_3/include/CGAL/convex_hull_3.h index 15dd55705fd..d1a1be76a2d 100644 --- a/Convex_hull_3/include/CGAL/convex_hull_3.h +++ b/Convex_hull_3/include/CGAL/convex_hull_3.h @@ -67,7 +67,8 @@ namespace CGAL { // Forward declaration template class Extreme_points_traits_adapter_3; -namespace internal{ namespace Convex_hull_3{ +namespace Convex_hull_3 { +namespace internal { // wrapper used as a MutableFaceGraph to extract extreme points template @@ -81,7 +82,7 @@ struct Output_iterator_wrapper template void add_isolated_points(const Point_3& point, - internal::Convex_hull_3::Output_iterator_wrapper& w) + Convex_hull_3::internal::Output_iterator_wrapper& w) { *w.out++ = point; } @@ -94,16 +95,17 @@ void add_isolated_points(const Point_3& point, Polyhedron_3& P) template void copy_ch2_to_face_graph(const std::list& CH_2, - internal::Convex_hull_3::Output_iterator_wrapper& w) + Convex_hull_3::internal::Output_iterator_wrapper& w) { for(const Point_3& p : CH_2) *w.out++ = p; } -} } // internal::Convex_hull_3 +} // namespace internal +} // namespace Convex_hull_3 template -void copy_face_graph(const TDS& tds, internal::Convex_hull_3::Output_iterator_wrapper& wrapper) +void copy_face_graph(const TDS& tds, Convex_hull_3::internal::Output_iterator_wrapper& wrapper) { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typename boost::property_map::const_type vpm = get(boost::vertex_point, tds); @@ -114,12 +116,12 @@ void copy_face_graph(const TDS& tds, internal::Convex_hull_3::Output_iterator_wr } template -void clear(internal::Convex_hull_3::Output_iterator_wrapper&) +void clear(Convex_hull_3::internal::Output_iterator_wrapper&) {} template void make_tetrahedron(const Point& p0, const Point& p1, const Point& p2, const Point& p3, - internal::Convex_hull_3::Output_iterator_wrapper& w) + Convex_hull_3::internal::Output_iterator_wrapper& w) { *w.out++ = p0; *w.out++ = p1; @@ -129,19 +131,20 @@ void make_tetrahedron(const Point& p0, const Point& p1, const Point& p2, const P } // CGAL -namespace boost{ +namespace boost { + // needed so that the regular make_tetrahedron of CGAL does not complain when tried to be instantiated template -struct graph_traits > +struct graph_traits > { typedef void* halfedge_descriptor; }; -} + +} // namespace boost namespace CGAL { - - -namespace internal{ namespace Convex_hull_3{ +namespace Convex_hull_3 { +namespace internal { //struct to select the default traits class for computing convex hull template< class Point_3, @@ -440,7 +443,7 @@ void coplanar_3_hull(InputIterator first, InputIterator beyond, const Point_3& p1, const Point_3& p2, const Point_3& p3, Polyhedron_3& P, const Traits& traits ) { - typedef typename internal::Convex_hull_3::Projection_traits PTraits; + typedef typename Convex_hull_3::internal::Projection_traits PTraits; typedef typename PTraits::Traits_xy_3 Traits_xy_3; typedef typename PTraits::Traits_yz_3 Traits_yz_3; typedef typename PTraits::Traits_xz_3 Traits_xz_3; @@ -848,7 +851,8 @@ ch_quickhull_polyhedron_3(std::list& points, } -} } //namespace internal::Convex_hull_3 +} // namespace internal +} // namespace Convex_hull_3 template void @@ -936,7 +940,7 @@ convex_hull_3(InputIterator first, InputIterator beyond, } // result will be a polyhedron - typedef typename internal::Convex_hull_3::Default_polyhedron_for_Chull_3::type Polyhedron; + typedef typename Convex_hull_3::internal::Default_polyhedron_for_Chull_3::type Polyhedron; Polyhedron P; P3_iterator minx, maxx, miny, it; @@ -948,9 +952,9 @@ convex_hull_3(InputIterator first, InputIterator beyond, if(it->y() < miny->y()) miny = it; } if(! collinear(*minx, *maxx, *miny) ){ - internal::Convex_hull_3::ch_quickhull_polyhedron_3(points, minx, maxx, miny, P, traits); + Convex_hull_3::internal::ch_quickhull_polyhedron_3(points, minx, maxx, miny, P, traits); } else { - internal::Convex_hull_3::ch_quickhull_polyhedron_3(points, point1_it, point2_it, point3_it, P, traits); + Convex_hull_3::internal::ch_quickhull_polyhedron_3(points, point1_it, point2_it, point3_it, P, traits); } CGAL_assertion(num_vertices(P)>=3); typename boost::graph_traits::vertex_iterator b,e; @@ -976,7 +980,7 @@ template void convex_hull_3(InputIterator first, InputIterator beyond, Object& ch_object) { typedef typename std::iterator_traits::value_type Point_3; - typedef typename internal::Convex_hull_3::Default_traits_for_Chull_3::type Traits; + typedef typename Convex_hull_3::internal::Default_traits_for_Chull_3::type Traits; convex_hull_3(first, beyond, ch_object, Traits()); } @@ -1009,7 +1013,7 @@ void convex_hull_3(InputIterator first, InputIterator beyond, // if there is only one point or all points are equal if(point2_it == points.end()) { - internal::Convex_hull_3::add_isolated_points(*point1_it, polyhedron); + Convex_hull_3::internal::add_isolated_points(*point1_it, polyhedron); return; } @@ -1028,12 +1032,12 @@ void convex_hull_3(InputIterator first, InputIterator beyond, min_max_element(points.begin(), points.end(), boost::bind(less_dist, *points.begin(), _1, _2), boost::bind(less_dist, *points.begin(), _1, _2)); - internal::Convex_hull_3::add_isolated_points(*endpoints.first, polyhedron); - internal::Convex_hull_3::add_isolated_points(*endpoints.second, polyhedron); + Convex_hull_3::internal::add_isolated_points(*endpoints.first, polyhedron); + Convex_hull_3::internal::add_isolated_points(*endpoints.second, polyhedron); return; } - internal::Convex_hull_3::ch_quickhull_polyhedron_3(points, point1_it, point2_it, point3_it, + Convex_hull_3::internal::ch_quickhull_polyhedron_3(points, point1_it, point2_it, point3_it, polyhedron, traits); } @@ -1046,7 +1050,7 @@ void convex_hull_3(InputIterator first, InputIterator beyond, >::type* =0) //workaround to avoid ambiguity with next overload. { typedef typename std::iterator_traits::value_type Point_3; - typedef typename internal::Convex_hull_3::Default_traits_for_Chull_3::type Traits; + typedef typename Convex_hull_3::internal::Default_traits_for_Chull_3::type Traits; convex_hull_3(first, beyond, polyhedron, Traits()); } @@ -1080,7 +1084,7 @@ extreme_points_3(const InputRange& range, OutputIterator out, const Traits& traits) { - internal::Convex_hull_3::Output_iterator_wrapper wrapper(out); + Convex_hull_3::internal::Output_iterator_wrapper wrapper(out); convex_hull_3(range.begin(), range.end(), wrapper, traits); return out; } @@ -1091,7 +1095,7 @@ extreme_points_3(const InputRange& range, OutputIterator out) { typedef typename InputRange::const_iterator Iterator_type; typedef typename std::iterator_traits::value_type Point_3; - typedef typename internal::Convex_hull_3::Default_traits_for_Chull_3::type Traits; + typedef typename Convex_hull_3::internal::Default_traits_for_Chull_3::type Traits; return extreme_points_3(range, out, Traits()); } diff --git a/Convex_hull_3/test/Convex_hull_3/quick_hull_default_traits.cpp b/Convex_hull_3/test/Convex_hull_3/quick_hull_default_traits.cpp index 968cbf5a510..1ae001fc693 100644 --- a/Convex_hull_3/test/Convex_hull_3/quick_hull_default_traits.cpp +++ b/Convex_hull_3/test/Convex_hull_3/quick_hull_default_traits.cpp @@ -19,7 +19,7 @@ typedef CGAL::Simple_cartesian SCD; typedef CGAL::Simple_homogeneous SHD; typedef CGAL::Simple_cartesian SCR; -using namespace CGAL::internal::Convex_hull_3; +using namespace CGAL::Convex_hull_3::internal; int main() { From 8446ef107344e055f302cda93db461d9227109c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Mar 2020 13:48:30 +0100 Subject: [PATCH 101/150] Clean #include's --- Convex_hull_3/include/CGAL/convex_hull_3.h | 29 +++++++++++----------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/Convex_hull_3/include/CGAL/convex_hull_3.h b/Convex_hull_3/include/CGAL/convex_hull_3.h index d1a1be76a2d..ec2b1577b18 100644 --- a/Convex_hull_3/include/CGAL/convex_hull_3.h +++ b/Convex_hull_3/include/CGAL/convex_hull_3.h @@ -31,21 +31,10 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + #include #include +#include #include #include #include @@ -54,12 +43,24 @@ #include #include -#include +#include +#include +#include +#include +#include +#include #ifndef CGAL_CH_NO_POSTCONDITIONS #include #endif // CGAL_CH_NO_POSTCONDITIONS +#include +#include +#include +#include +#include +#include +#include // first some internal stuff to avoid using a true Face_graph model for extreme_points_3 namespace CGAL { From a846a1e19c28b6f0d71137fad8142b6b1fcf5231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 10 Mar 2020 14:20:17 +0100 Subject: [PATCH 102/150] Remove long-deprecated convex_hull_3_to_polyhedron_3() Use convex_hull_3_to_face_graph() --- .../compare_different_approach.cpp | 4 +- .../CGAL/convex_hull_3_to_polyhedron_3.h | 29 --------------- .../CGAL/convex_hull_3_to_polyhedron_3.h | 37 ------------------- .../Triangulation_3/CGAL/link_to_face_graph.h | 2 +- 4 files changed, 3 insertions(+), 69 deletions(-) delete mode 100644 Convex_hull_3/doc/Convex_hull_3/CGAL/convex_hull_3_to_polyhedron_3.h delete mode 100644 Convex_hull_3/include/CGAL/convex_hull_3_to_polyhedron_3.h diff --git a/Convex_hull_3/benchmark/Convex_hull_3/compare_different_approach.cpp b/Convex_hull_3/benchmark/Convex_hull_3/compare_different_approach.cpp index 6549c202905..3304eb00c67 100644 --- a/Convex_hull_3/benchmark/Convex_hull_3/compare_different_approach.cpp +++ b/Convex_hull_3/benchmark/Convex_hull_3/compare_different_approach.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -68,7 +68,7 @@ int main(int argc,char** argv) time.stop(); std::cout << "Delaunay " << time.time() << std::endl; time.start(); - CGAL::convex_hull_3_to_polyhedron_3(T,poly); + CGAL::convex_hull_3_to_face_graph(T,poly); time.stop(); std::cout << "Delaunay+to_poly " << time.time() <<" "<< poly.size_of_vertices() << std::endl; poly.clear(); diff --git a/Convex_hull_3/doc/Convex_hull_3/CGAL/convex_hull_3_to_polyhedron_3.h b/Convex_hull_3/doc/Convex_hull_3/CGAL/convex_hull_3_to_polyhedron_3.h deleted file mode 100644 index a73ec6a2b0b..00000000000 --- a/Convex_hull_3/doc/Convex_hull_3/CGAL/convex_hull_3_to_polyhedron_3.h +++ /dev/null @@ -1,29 +0,0 @@ -namespace CGAL { - -/*! -\ingroup PkgConvexHull3Functions - -fills a polyhedron with the convex hull of a set of 3D points contained in a 3D triangulation of \cgal. - -The polyhedron `P` is cleared and the convex hull of the set of 3D points is stored in `P`. - -\deprecated since \cgal 4.10. Use `convex_hull_3_to_face_graph()` instead. - -\attention This function does not compute the plane equations of the faces of `P`. - -\attention This function works only for `CGAL::Polyhedron_3`, and users who want -to generate a `Surface_mesh` or any other model of a `FaceGraph` may use `convex_hull_3_to_face_graph()` instead. - -\pre `T.dimension()`==3. - -\tparam Triangulation is a \cgal 3D triangulation. -\tparam Polyhedron is an instantiation of `CGAL::Polyhedron_3`. - -\sa `convex_hull_3()` -\sa `link_to_face_graph()` - -*/ -template -void convex_hull_3_to_polyhedron_3(const Triangulation& T,Polyhedron& P); - -} /* namespace CGAL */ diff --git a/Convex_hull_3/include/CGAL/convex_hull_3_to_polyhedron_3.h b/Convex_hull_3/include/CGAL/convex_hull_3_to_polyhedron_3.h deleted file mode 100644 index 7a048c904a3..00000000000 --- a/Convex_hull_3/include/CGAL/convex_hull_3_to_polyhedron_3.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2011 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Sebastien Loriot -// - -#ifndef CGAL_CONVEX_HULL_3_TO_POLYHEDRON_3_H -#define CGAL_CONVEX_HULL_3_TO_POLYHEDRON_3_H - -#include - - -#define CGAL_DEPRECATED_HEADER "" -#define CGAL_REPLACEMENT_HEADER "" -#include - - -#include - -namespace CGAL { - -template -CGAL_DEPRECATED void convex_hull_3_to_polyhedron_3(const Triangulation_3& T,Polyhedron_3& P){ - clear(P); - link_to_face_graph(T,T.infinite_vertex(), P); -} - -} //namespace CGAL - -#endif //CGAL_CONVEX_HULL_3_TO_POLYHEDRON_3_H diff --git a/Triangulation_3/doc/Triangulation_3/CGAL/link_to_face_graph.h b/Triangulation_3/doc/Triangulation_3/CGAL/link_to_face_graph.h index 600ec0441e8..836884865e6 100644 --- a/Triangulation_3/doc/Triangulation_3/CGAL/link_to_face_graph.h +++ b/Triangulation_3/doc/Triangulation_3/CGAL/link_to_face_graph.h @@ -22,7 +22,7 @@ fills the face graph `tm` with the #include -#include #include #include #include #include #include +#include #include #include @@ -498,12 +498,12 @@ public: // Spatial sorting can only be applied to bare points, so we need an adaptor typedef typename Geom_traits::Construct_point_3 Construct_point_3; typedef typename boost::result_of::type Ret; - typedef CGAL::internal::boost_::function_property_map fpmap; + typedef boost::function_property_map fpmap; typedef CGAL::Spatial_sort_traits_adapter_3 Search_traits_3; spatial_sort(pbegin, points.end(), Search_traits_3( - CGAL::internal::boost_::make_function_property_map( + boost::make_function_property_map( geom_traits().construct_point_3_object()), geom_traits())); Cell_handle hint; diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/connected_component_surface_mesh.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/connected_component_surface_mesh.cpp index c22d400cda4..83fa6a1bb53 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/connected_component_surface_mesh.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/connected_component_surface_mesh.cpp @@ -4,7 +4,8 @@ #include #include #include -#include + +#include #include #include @@ -167,7 +168,7 @@ void test_CC_with_area_size_map(Mesh sm, std::cout << "We keep the " << 2 << " largest components" << std::endl; std::size_t res = PMP::keep_largest_connected_components(sm, 2, - PMP::parameters::face_size_map(CGAL::internal::boost_::make_function_property_map(f)) + PMP::parameters::face_size_map(boost::make_function_property_map(f)) .dry_run(true) .output_iterator(std::back_inserter(faces_to_remove))); @@ -183,7 +184,7 @@ void test_CC_with_area_size_map(Mesh sm, PMP::keep_largest_connected_components(sm, 2, PMP::parameters::face_size_map( - CGAL::internal::boost_::make_function_property_map(f))); + boost::make_function_property_map(f))); assert(vertices(sm).size() == 1459); { @@ -199,7 +200,7 @@ void test_CC_with_area_size_map(Mesh sm, Face_descriptor_area_functor f(m, k); PMP::keep_large_connected_components(m, 10, CGAL::parameters::face_size_map( - CGAL::internal::boost_::make_function_property_map(f))); + boost::make_function_property_map(f))); assert(vertices(m).size() == 3); PMP::keep_largest_connected_components(m, 1); diff --git a/STL_Extension/include/CGAL/internal/boost/function_property_map.hpp b/STL_Extension/include/CGAL/internal/boost/function_property_map.hpp deleted file mode 100644 index 765c0bfd7ae..00000000000 --- a/STL_Extension/include/CGAL/internal/boost/function_property_map.hpp +++ /dev/null @@ -1,84 +0,0 @@ -// -//======================================================================= -// Author: Philipp Moeller -// -// Copyright 2012, Philipp Moeller -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// https://www.boost.org/LICENSE_1_0.txt) -//======================================================================= -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: BSL-1.0 -// - -// Note: This file was copied from Boost v1.64 because it was introduced -// in a release (~v1.51) that is newer than the oldest release of Boost -// that CGAL supports. -// the property map 'function_property_map' is (currently) used -// in the packages Triangulation_2 and Triangulation_3. - -#ifndef CGAL_INTERNAL_BOOST_PROPERTY_MAP_FUNCTION_PROPERTY_MAP_HPP -#define CGAL_INTERNAL_BOOST_PROPERTY_MAP_FUNCTION_PROPERTY_MAP_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace CGAL { -namespace internal { -namespace boost_ { - -template::type> -class function_property_map - : public boost::put_get_helper > -{ -public: - typedef Key key_type; - typedef Ret reference; - typedef typename boost::remove_cv::type>::type value_type; - - typedef typename boost::mpl::if_< - boost::mpl::and_< - boost::is_reference, - boost::mpl::not_< boost::is_const > - >, - boost::lvalue_property_map_tag, - boost::readable_property_map_tag>::type - category; - - function_property_map(Func f = Func()) : f(f) {} - - reference operator[](const Key& k) const { - return f(k); - } - -private: - Func f; -}; - -template -function_property_map -make_function_property_map(const Func& f) { - return function_property_map(f); -} - -template -function_property_map -make_function_property_map(const Func& f) { - return function_property_map(f); -} - -} // boost_ -} // internal -} // CGAL - -#endif /* CGAL_INTERNAL_BOOST_PROPERTY_MAP_FUNCTION_PROPERTY_MAP_HPP */ diff --git a/Triangulation_2/include/CGAL/Regular_triangulation_2.h b/Triangulation_2/include/CGAL/Regular_triangulation_2.h index 2d1e14c5a13..5d9f94b5f69 100644 --- a/Triangulation_2/include/CGAL/Regular_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Regular_triangulation_2.h @@ -20,7 +20,6 @@ #include #include -#include #include #include @@ -34,6 +33,7 @@ #include #include +#include #endif //CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO @@ -414,12 +414,12 @@ public: // spatial sorting must use bare points, so we need an adapter typedef typename Geom_traits::Construct_point_2 Construct_point_2; typedef typename boost::result_of::type Ret; - typedef CGAL::internal::boost_::function_property_map fpmap; + typedef boost::function_property_map fpmap; typedef CGAL::Spatial_sort_traits_adapter_2 Search_traits_2; spatial_sort(points.begin(), points.end(), Search_traits_2( - CGAL::internal::boost_::make_function_property_map( + boost::make_function_property_map( geom_traits().construct_point_2_object()), geom_traits())); Face_handle hint; @@ -482,13 +482,13 @@ private: typedef Index_to_Bare_point > Access_bare_point; typedef typename boost::result_of::type Ret; - typedef CGAL::internal::boost_::function_property_map fpmap; + typedef boost::function_property_map fpmap; typedef CGAL::Spatial_sort_traits_adapter_2 Search_traits_2; Access_bare_point accessor(points, geom_traits().construct_point_2_object()); spatial_sort(indices.begin(), indices.end(), Search_traits_2( - CGAL::internal::boost_::make_function_property_map< + boost::make_function_property_map< std::size_t, Ret, Access_bare_point>(accessor), geom_traits())); diff --git a/Triangulation_2/include/CGAL/Triangulation_2.h b/Triangulation_2/include/CGAL/Triangulation_2.h index de91b826848..568cf63b8ea 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2.h @@ -37,7 +37,6 @@ #include #include -#include #include #include diff --git a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h index 30fa8deac9b..8d9c6917f1e 100644 --- a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h @@ -25,10 +25,9 @@ #include #include -#include - #include #include +#include #include #include #include @@ -130,12 +129,12 @@ public: // Spatial sort can only be used with Gt::Point_2: we need an adapter typedef typename Geom_traits::Construct_point_2 Construct_point_2; typedef typename boost::result_of::type Ret; - typedef CGAL::internal::boost_::function_property_map fpmap; + typedef boost::function_property_map fpmap; typedef CGAL::Spatial_sort_traits_adapter_2 Search_traits_2; spatial_sort(points.begin(), points.end(), Search_traits_2( - CGAL::internal::boost_::make_function_property_map( + boost::make_function_property_map( geom_traits().construct_point_2_object()), geom_traits())); // hints[i] is the face of the previously inserted point in level i. diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_3.h index 17cabad626a..93c0dbb0165 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_3.h @@ -22,13 +22,6 @@ #include -#include - -#include -#include -#include -#include - #ifdef CGAL_LINKED_WITH_TBB # include # include @@ -41,7 +34,6 @@ #include #include #include -#include #include #include @@ -63,6 +55,20 @@ #include #endif +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + namespace CGAL { /************************************************ @@ -269,12 +275,12 @@ private: // Spatial sorting can only be applied to bare points, so we need an adaptor typedef typename Geom_traits::Construct_point_3 Construct_point_3; typedef typename boost::result_of::type Ret; - typedef CGAL::internal::boost_::function_property_map fpmap; + typedef boost::function_property_map fpmap; typedef CGAL::Spatial_sort_traits_adapter_3 Search_traits_3; spatial_sort(points_on_far_sphere.begin(), points_on_far_sphere.end(), Search_traits_3( - CGAL::internal::boost_::make_function_property_map( + boost::make_function_property_map( geom_traits().construct_point_3_object()), geom_traits())); typename std::vector::const_iterator it_p = @@ -341,12 +347,12 @@ public: // kernel creates temporaries and prevent it. typedef typename Geom_traits::Construct_point_3 Construct_point_3; typedef typename boost::result_of::type Ret; - typedef CGAL::internal::boost_::function_property_map fpmap; + typedef boost::function_property_map fpmap; typedef CGAL::Spatial_sort_traits_adapter_3 Search_traits_3; spatial_sort(points.begin(), points.end(), Search_traits_3( - CGAL::internal::boost_::make_function_property_map( + boost::make_function_property_map( geom_traits().construct_point_3_object()), geom_traits())); // Parallel @@ -466,14 +472,14 @@ private: typedef Index_to_Bare_point > Access_bare_point; typedef typename boost::result_of::type Ret; - typedef CGAL::internal::boost_::function_property_map fpmap; + typedef boost::function_property_map fpmap; typedef CGAL::Spatial_sort_traits_adapter_3 Search_traits_3; Access_bare_point accessor(points, geom_traits().construct_point_3_object()); spatial_sort(indices.begin(), indices.end(), Search_traits_3( - CGAL::internal::boost_::make_function_property_map< - std::size_t, Ret, Access_bare_point>(accessor), + boost::make_function_property_map< + std::size_t, Ret, Access_bare_point>(accessor), geom_traits())); #ifdef CGAL_LINKED_WITH_TBB diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 6941c6c8acf..3ab9192eb37 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -47,7 +47,6 @@ #include #include #include -#include #include #include @@ -57,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -6589,12 +6589,12 @@ _remove_cluster_3D(InputIterator first, InputIterator beyond, VertexRemover& rem // Spatial sorting can only be applied to bare points, so we need an adaptor typedef typename Geom_traits::Construct_point_3 Construct_point_3; typedef typename boost::result_of::type Ret; - typedef CGAL::internal::boost_::function_property_map fpmap; + typedef boost::function_property_map fpmap; typedef CGAL::Spatial_sort_traits_adapter_3 Search_traits_3; spatial_sort(vps.begin(), vps.end(), Search_traits_3( - CGAL::internal::boost_::make_function_property_map( + boost::make_function_property_map( geom_traits().construct_point_3_object()), geom_traits())); std::size_t svps = vps.size(); diff --git a/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h b/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h index 5e554cd14c5..b0dcbb95801 100644 --- a/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h @@ -33,8 +33,7 @@ #include #include -#include - +#include #include #include #include @@ -169,12 +168,12 @@ public: // Spatial sort can only be used with Geom_traits::Point_3: we need an adapter typedef typename Geom_traits::Construct_point_3 Construct_point_3; typedef typename boost::result_of::type Ret; - typedef CGAL::internal::boost_::function_property_map fpmap; + typedef boost::function_property_map fpmap; typedef CGAL::Spatial_sort_traits_adapter_3 Search_traits_3; spatial_sort(points.begin(), points.end(), Search_traits_3( - CGAL::internal::boost_::make_function_property_map( + boost::make_function_property_map( geom_traits().construct_point_3_object()), geom_traits())); // hints[i] is the vertex of the previously inserted point in level i. @@ -246,13 +245,13 @@ private: typedef Index_to_Bare_point > Access_bare_point; typedef typename boost::result_of::type Ret; - typedef CGAL::internal::boost_::function_property_map fpmap; + typedef boost::function_property_map fpmap; typedef CGAL::Spatial_sort_traits_adapter_3 Search_traits_3; Access_bare_point accessor(points, geom_traits().construct_point_3_object()); spatial_sort(indices.begin(), indices.end(), Search_traits_3( - CGAL::internal::boost_::make_function_property_map< + boost::make_function_property_map< std::size_t, Ret, Access_bare_point>(accessor), geom_traits())); From 3864f6da9d43123ba2eb25cce6e1e6bdb1eb99c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 12 Mar 2020 22:20:06 +0100 Subject: [PATCH 104/150] Add an overload of choose_parameter to avoid needless constructions --- .../CGAL/boost/graph/Named_function_parameters.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/BGL/include/CGAL/boost/graph/Named_function_parameters.h b/BGL/include/CGAL/boost/graph/Named_function_parameters.h index 66bc5c18b99..2c5e97367e8 100644 --- a/BGL/include/CGAL/boost/graph/Named_function_parameters.h +++ b/BGL/include/CGAL/boost/graph/Named_function_parameters.h @@ -200,6 +200,19 @@ D choose_parameter(const internal_np::Param_not_found&, const D& d) return d; } +// single parameter so that we can avoid a default construction +template +D choose_parameter(const internal_np::Param_not_found&) +{ + return D(); +} + +template +const T& choose_parameter(const T& t) +{ + return t; +} + template const T& choose_parameter(const T& t, const D&) From 2453e7f0ea6192cfb909f9bd73790f8700613854 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 12 Mar 2020 22:21:11 +0100 Subject: [PATCH 105/150] Add two new examples to OBB/examples --- .../Optimal_bounding_box/CMakeLists.txt | 3 + .../Optimal_bounding_box/obb_example.cpp | 1 + .../obb_with_point_maps_example.cpp | 58 +++++++++++++++++ .../rotated_aabb_tree.cpp | 63 +++++++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 Optimal_bounding_box/examples/Optimal_bounding_box/obb_with_point_maps_example.cpp create mode 100644 Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree.cpp diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt index 8fc23ac241a..9930366dd1c 100644 --- a/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt @@ -22,3 +22,6 @@ else() endif() create_single_source_cgal_program("obb_example.cpp") +create_single_source_cgal_program("obb_with_point_maps_example.cpp") +create_single_source_cgal_program("rotated_aabb_tree.cpp") + diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp index e6efa798e8d..52ddad1b5b7 100644 --- a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp @@ -11,6 +11,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point; + typedef CGAL::Surface_mesh Surface_mesh; int main(int argc, char** argv) diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_with_point_maps_example.cpp b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_with_point_maps_example.cpp new file mode 100644 index 00000000000..672cab6d210 --- /dev/null +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_with_point_maps_example.cpp @@ -0,0 +1,58 @@ +#include +#include + +#include + +#include +#include +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_3 Point; +typedef K::Vector_3 Vector; + +typedef CGAL::Surface_mesh Surface_mesh; +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; + +namespace CP = CGAL::parameters; + +int main(int argc, char** argv) +{ + std::ifstream input(argv[1]); + Surface_mesh sm; + if (!input || !(input >> sm) || sm.is_empty()) + { + std::cerr << argv[1] << " is not a valid off file.\n"; + return EXIT_FAILURE; + } + + // a typical call + std::array obb_points; + CGAL::oriented_bounding_box(sm, obb_points); + + // one can associate positions to the vertices of the mesh without changing the mesh + std::unordered_map translated_positions; + for(const vertex_descriptor v : vertices(sm)) + translated_positions[v] = sm.point(v) + Vector(1, 2, 3); + + CGAL::oriented_bounding_box(sm, obb_points, + CP::vertex_point_map(boost::make_assoc_property_map(translated_positions))); + + // using a range of points + std::vector points; + for(const vertex_descriptor v : vertices(sm)) + points.push_back(sm.point(v)); + CGAL::oriented_bounding_box(points, obb_points); + + // one can associate positions to the range without changing the range + std::map scaled_positions; + for(const Point& p : points) + scaled_positions[p] = p + (p - CGAL::ORIGIN); + + CGAL::oriented_bounding_box(points, obb_points, + CP::point_map(boost::make_assoc_property_map(scaled_positions))); + + return EXIT_SUCCESS; +} diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree.cpp b/Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree.cpp new file mode 100644 index 00000000000..9ffdd0f617f --- /dev/null +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree.cpp @@ -0,0 +1,63 @@ +#define CGAL_OPTIMAL_BOUNDING_BOX_DEBUG + +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_3 Point; +typedef K::Aff_transformation_3 Aff_transformation; + +typedef CGAL::Surface_mesh Surface_mesh; +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; + +struct Aff_tr_fct +{ + Aff_tr_fct(const Aff_transformation& at, const Surface_mesh& sm) : m_at(at), m_sm(sm) { } + + Point operator()(const vertex_descriptor v) const { return m_at.transform(m_sm.point(v)); } + +private: + const Aff_transformation& m_at; + const Surface_mesh& m_sm; +}; + +int main(int argc, char** argv) +{ + std::ifstream input(argv[1]); + Surface_mesh sm; + if (!input || !(input >> sm) || sm.is_empty()) + { + std::cerr << argv[1] << " is not a valid off file.\n"; + return EXIT_FAILURE; + } + + // get the transformation that yields the optimal bounding box + Aff_transformation at; + CGAL::oriented_bounding_box(sm, at); + + // functor to apply the affine transformation to a vertex of the mesh + + // @tmp with a lambda... + // auto aff_tr_fct = [&at, &sm] (const vertex_descriptor v) -> Point { return at.transform(sm.point(v)); }; + // @tmp with a struct... + Aff_tr_fct aff_tr_fct(at, sm); + auto aff_tr_vpm = boost::make_function_property_map(aff_tr_fct); + + // rotated AABB tree + typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; + typedef CGAL::AABB_traits AABB_face_graph_traits; + + CGAL::AABB_tree tree(faces(sm).begin(), faces(sm).end(), sm, aff_tr_vpm); + + return EXIT_SUCCESS; +} From 8e00ffff21d997e5e72a611ec2a997f53e377b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 12 Mar 2020 22:21:45 +0100 Subject: [PATCH 106/150] Enable passing a point_map in complement to the range --- .../oriented_bounding_box.h | 65 ++++++++++--------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 68149f2ad76..9cba883654b 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,10 @@ #include #endif +#include +#include +#include + #include #include #include @@ -52,10 +57,10 @@ namespace Optimal_bounding_box { namespace internal { template -void construct_oriented_bounding_box(std::array& obb_points, +void construct_oriented_bounding_box(const PointRange& points, const typename Traits::Aff_transformation_3& transformation, const typename Traits::Aff_transformation_3& inverse_transformation, - const PointRange& points, + std::array& obb_points, const Traits& traits) { typedef typename Traits::Point_3 Point; @@ -84,9 +89,9 @@ void construct_oriented_bounding_box(std::array& ob } template -void compute_best_transformation(typename Traits::Aff_transformation_3& transformation, +void compute_best_transformation(const PointRange& points, + typename Traits::Aff_transformation_3& transformation, typename Traits::Aff_transformation_3& inverse_transformation, - const PointRange& points, CGAL::Random& rng, const Traits& traits) { @@ -126,32 +131,32 @@ void compute_best_transformation(typename Traits::Aff_transformation_3& transfor // Following two functions are overload to dispatch depending on return type template -void construct_oriented_bounding_box(typename Traits::Aff_transformation_3& transformation, - const PointRange& points, +void construct_oriented_bounding_box(const PointRange& points, + typename Traits::Aff_transformation_3& transformation, CGAL::Random& rng, const Traits& traits) { typename Traits::Aff_transformation_3 inverse_transformation; - compute_best_transformation(transformation, inverse_transformation, points, rng, traits); + compute_best_transformation(points, transformation, inverse_transformation, rng, traits); } template -void construct_oriented_bounding_box(std::array& obb_points, - const PointRange& points, +void construct_oriented_bounding_box(const PointRange& points, + std::array& obb_points, CGAL::Random& rng, const Traits& traits) { typename Traits::Aff_transformation_3 transformation, inverse_transformation; - compute_best_transformation(transformation, inverse_transformation, points, rng, traits); + compute_best_transformation(points, transformation, inverse_transformation, rng, traits); - construct_oriented_bounding_box(obb_points, transformation, inverse_transformation, points, traits); + construct_oriented_bounding_box(points, transformation, inverse_transformation, obb_points, traits); } // Entry point, decide whether to compute the CH_3 or not -template -void construct_oriented_bounding_box(Output& output, +template +void construct_oriented_bounding_box(const PointRange& points, const bool use_ch, - const PointRange& points, + Output& output, CGAL::Random& rng, const Traits& traits) { @@ -164,11 +169,11 @@ void construct_oriented_bounding_box(Output& output, { std::vector ch_points; extreme_points_3(points, std::back_inserter(ch_points)); - return construct_oriented_bounding_box(output, ch_points, rng, traits); + return construct_oriented_bounding_box(ch_points, output, rng, traits); } else { - return construct_oriented_bounding_box(output, points, rng, traits); + return construct_oriented_bounding_box(points, output, rng, traits); } } @@ -257,8 +262,10 @@ void oriented_bounding_box(const PointRange& points, using CGAL::parameters::choose_parameter; using CGAL::parameters::get_parameter; + typedef typename Point_set_processing_3::GetPointMap::type PointMap; + #if defined(CGAL_EIGEN3_ENABLED) - typedef typename boost::range_value::type Point; + typedef typename boost::property_traits::value_type Point; typedef typename CGAL::Kernel_traits::type K; typedef Oriented_bounding_box_traits_3 Default_traits; #else @@ -267,12 +274,13 @@ void oriented_bounding_box(const PointRange& points, typedef typename internal_np::Lookup_named_param_def::type Geom_traits; + Default_traits>::type Geom_traits; CGAL_static_assertion_msg(!(std::is_same::value), "You must provide a traits class or have Eigen enabled!"); - Geom_traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Geom_traits()); + Geom_traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits)); + PointMap point_map = choose_parameter(get_parameter(np, internal_np::point_map)); const bool use_ch = choose_parameter(get_parameter(np, internal_np::use_convex_hull), true); const unsigned int seed = choose_parameter(get_parameter(np, internal_np::random_seed), 0); // undocumented @@ -287,7 +295,11 @@ void oriented_bounding_box(const PointRange& points, return; } - return Optimal_bounding_box::internal::construct_oriented_bounding_box(out, use_ch, points, rng, traits); + return Optimal_bounding_box::internal::construct_oriented_bounding_box( + CGAL::make_range( + boost::make_transform_iterator(points.begin(), CGAL::Property_map_to_unary_function(point_map)), + boost::make_transform_iterator(points.end(), CGAL::Property_map_to_unary_function(point_map))), + use_ch, out, rng, traits); } /// \ingroup PkgOptimalBoundingBox_Oriented_bounding_box @@ -307,7 +319,7 @@ void oriented_bounding_box(const PointRange& points, /// \cgalParamBegin{vertex_point_map} /// the property map with the points associated to the vertices of `pmesh`. /// If this parameter is omitted, an internal property map for -/// `CGAL::vertex_point_t` must be available in `PolygonMesh` +/// `CGAL::vertex_point_t` must be available in `PolygonMesh`. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} /// a geometric traits class instance, model of the concept `OrientedBoundingBoxTraits_3`. @@ -341,19 +353,12 @@ void oriented_bounding_box(const PolygonMesh& pmesh, typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename PMP::GetVertexPointMap::const_type VPM; - typedef typename boost::property_traits::value_type Point; + typedef typename CGAL::GetVertexPointMap::const_type VPM; VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), get_const_property_map(vertex_point, pmesh)); - std::vector points; - points.reserve(num_vertices(pmesh)); - - for(vertex_descriptor v : vertices(pmesh)) - points.push_back(get(vpm, v)); - - oriented_bounding_box(points, out, np); + oriented_bounding_box(vertices(pmesh), out, np.point_map(vpm)); } /// \cond SKIP_IN_MANUAL From d9c7814f724e3aabe8074f4bb7182f230443777b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 13 Mar 2020 10:42:31 +0100 Subject: [PATCH 107/150] Add default constructor to functor to please the AABB tree --- .../Optimal_bounding_box/rotated_aabb_tree.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree.cpp b/Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree.cpp index 9ffdd0f617f..18bc7fdc714 100644 --- a/Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree.cpp +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree.cpp @@ -22,13 +22,14 @@ typedef boost::graph_traits::vertex_descriptor vertex_descriptor struct Aff_tr_fct { - Aff_tr_fct(const Aff_transformation& at, const Surface_mesh& sm) : m_at(at), m_sm(sm) { } + Aff_tr_fct() : m_at(nullptr), m_sm(nullptr) { } + Aff_tr_fct(const Aff_transformation& at, const Surface_mesh& sm) : m_at(&at), m_sm(&sm) { } - Point operator()(const vertex_descriptor v) const { return m_at.transform(m_sm.point(v)); } + Point operator()(const vertex_descriptor v) const { return m_at->transform(m_sm->point(v)); } private: - const Aff_transformation& m_at; - const Surface_mesh& m_sm; + const Aff_transformation* m_at; + const Surface_mesh* m_sm; }; int main(int argc, char** argv) @@ -46,10 +47,6 @@ int main(int argc, char** argv) CGAL::oriented_bounding_box(sm, at); // functor to apply the affine transformation to a vertex of the mesh - - // @tmp with a lambda... - // auto aff_tr_fct = [&at, &sm] (const vertex_descriptor v) -> Point { return at.transform(sm.point(v)); }; - // @tmp with a struct... Aff_tr_fct aff_tr_fct(at, sm); auto aff_tr_vpm = boost::make_function_property_map(aff_tr_fct); From 85fd88ac5ca27fabb84837de5643922b29056db3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 13 Mar 2020 11:02:50 +0100 Subject: [PATCH 108/150] Remove bench that is just a duplicate of an example --- .../Optimal_bounding_box/CMakeLists.txt | 1 - .../Optimal_bounding_box/bench_custom.cpp | 64 ------------------- 2 files changed, 65 deletions(-) delete mode 100644 Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt index b66879123fe..6405145d309 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt @@ -25,5 +25,4 @@ endif() create_single_source_cgal_program("bench_obb.cpp") create_single_source_cgal_program("bench_perfomance.cpp") -create_single_source_cgal_program("bench_custom.cpp") create_single_source_cgal_program("bench_fitness_function.cpp") diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp deleted file mode 100644 index 220aabab3b5..00000000000 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_custom.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include - -//#define CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_BENCHMARK - -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; - -void bench(const char* fname) -{ - std::vector sm_points, obb_points; - std::ifstream in(fname); - - K::Point_3 p; - int i = 0; - while(in >> p) - { - if(i % 2 == 0) // avoid normals - sm_points.push_back(p); - - ++i; - } - - std::cout << "input data (points + normals)= " << i << std::endl; - std::cout << "number of points= " << sm_points.size() << std::endl; - - CGAL::Eigen_linear_algebra_traits la_traits; - - // use convex hull - > true - // no convex hull - > false - CGAL::Optimal_bounding_box::compute_optimal_bounding_box(sm_points, obb_points, la_traits, false); - - std::cout << "done" << '\n'; - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_BENCHMARK - std::cout.precision(17); - for(int i =0; i < obb_points.size(); i++) - std::cout << obb_points[i] << std::endl; - - CGAL::Surface_mesh mesh; - CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], - obb_points[4], obb_points[5], obb_points[6], obb_points[7], mesh); - - std::ofstream out("/tmp/result_obb.off"); - out << mesh; - out.close(); -#endif -} - -int main(int argc, char* argv[]) -{ - bench(argv[1]); - - return 0; -} From 99a0edbe61c3bb8ee523cfc0f9604db28f5a7805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 13 Mar 2020 11:57:56 +0100 Subject: [PATCH 109/150] Uniformize types and internal function names (CH_3) --- Convex_hull_3/include/CGAL/convex_hull_3.h | 72 +++++++++++----------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/Convex_hull_3/include/CGAL/convex_hull_3.h b/Convex_hull_3/include/CGAL/convex_hull_3.h index ec2b1577b18..025f657c357 100644 --- a/Convex_hull_3/include/CGAL/convex_hull_3.h +++ b/Convex_hull_3/include/CGAL/convex_hull_3.h @@ -88,8 +88,8 @@ void add_isolated_points(const Point_3& point, *w.out++ = point; } -template -void add_isolated_points(const Point_3& point, Polyhedron_3& P) +template +void add_isolated_points(const Point_3& point, PolygonMesh& P) { put(get(CGAL::vertex_point, P), add_vertex(P), point); } @@ -411,12 +411,12 @@ struct Projection_traits{ {return traits.construct_traits_xz_3_object();} }; -template -void copy_ch2_to_face_graph(const std::list& CH_2, Polyhedron_3& P) +template +void copy_ch2_to_face_graph(const std::list& CH_2, PolygonMesh& P) { - typename boost::property_map::type vpm + typename boost::property_map::type vpm = get(CGAL::vertex_point, P); - typedef boost::graph_traits Graph_traits; + typedef boost::graph_traits Graph_traits; typedef typename Graph_traits::vertex_descriptor vertex_descriptor; typedef typename Graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename Graph_traits::face_descriptor face_descriptor; @@ -439,10 +439,10 @@ void copy_ch2_to_face_graph(const std::list& CH_2, Polyhedron_3& P) } -template +template void coplanar_3_hull(InputIterator first, InputIterator beyond, const Point_3& p1, const Point_3& p2, const Point_3& p3, - Polyhedron_3& P, const Traits& traits ) + PolygonMesh& P, const Traits& traits ) { typedef typename Convex_hull_3::internal::Projection_traits PTraits; typedef typename PTraits::Traits_xy_3 Traits_xy_3; @@ -762,12 +762,12 @@ void non_coplanar_quickhull_3(std::list& points, // CGAL_ch_postcondition(is_strongly_convex_3(P, traits)); } -template +template void -ch_quickhull_polyhedron_3(std::list& points, - InputIterator point1_it, InputIterator point2_it, - InputIterator point3_it, Polyhedron_3& P, - const Traits& traits) +ch_quickhull_face_graph(std::list& points, + InputIterator point1_it, InputIterator point2_it, InputIterator point3_it, + PolygonMesh& P, + const Traits& traits) { typedef typename Traits::Point_3 Point_3; typedef typename Traits::Plane_3 Plane_3; @@ -858,7 +858,8 @@ ch_quickhull_polyhedron_3(std::list& points, template void convex_hull_3(InputIterator first, InputIterator beyond, - Object& ch_object, const Traits& traits) + Object& ch_object, + const Traits& traits) { typedef typename Traits::Point_3 Point_3; typedef std::list Point_3_list; @@ -953,9 +954,9 @@ convex_hull_3(InputIterator first, InputIterator beyond, if(it->y() < miny->y()) miny = it; } if(! collinear(*minx, *maxx, *miny) ){ - Convex_hull_3::internal::ch_quickhull_polyhedron_3(points, minx, maxx, miny, P, traits); + Convex_hull_3::internal::ch_quickhull_face_graph(points, minx, maxx, miny, P, traits); } else { - Convex_hull_3::internal::ch_quickhull_polyhedron_3(points, point1_it, point2_it, point3_it, P, traits); + Convex_hull_3::internal::ch_quickhull_face_graph(points, point1_it, point2_it, point3_it, P, traits); } CGAL_assertion(num_vertices(P)>=3); typename boost::graph_traits::vertex_iterator b,e; @@ -978,18 +979,18 @@ convex_hull_3(InputIterator first, InputIterator beyond, template -void convex_hull_3(InputIterator first, InputIterator beyond, Object& ch_object) +void convex_hull_3(InputIterator first, InputIterator beyond, + Object& ch_object) { typedef typename std::iterator_traits::value_type Point_3; typedef typename Convex_hull_3::internal::Default_traits_for_Chull_3::type Traits; convex_hull_3(first, beyond, ch_object, Traits()); } - - -template +template void convex_hull_3(InputIterator first, InputIterator beyond, - Polyhedron_3& polyhedron, const Traits& traits) + PolygonMesh& polyhedron, + const Traits& traits) { typedef typename Traits::Point_3 Point_3; typedef std::list Point_3_list; @@ -1038,35 +1039,34 @@ void convex_hull_3(InputIterator first, InputIterator beyond, return; } - Convex_hull_3::internal::ch_quickhull_polyhedron_3(points, point1_it, point2_it, point3_it, + Convex_hull_3::internal::ch_quickhull_face_graph(points, point1_it, point2_it, point3_it, polyhedron, traits); } - -template +template void convex_hull_3(InputIterator first, InputIterator beyond, - Polyhedron_3& polyhedron, - typename std::enable_if< - CGAL::is_iterator::value - >::type* =0) //workaround to avoid ambiguity with next overload. + PolygonMesh& polyhedron, + // workaround to avoid ambiguity with next overload. + typename std::enable_if::value>::type* = 0) { - typedef typename std::iterator_traits::value_type Point_3; - typedef typename Convex_hull_3::internal::Default_traits_for_Chull_3::type Traits; - convex_hull_3(first, beyond, polyhedron, Traits()); + typedef typename std::iterator_traits::value_type Point_3; + typedef typename Convex_hull_3::internal::Default_traits_for_Chull_3::type Traits; + convex_hull_3(first, beyond, polyhedron, Traits()); } - template void convex_hull_3(const VertexListGraph& g, PolygonMesh& pm, const NamedParameters& np) { + using CGAL::parameters::choose_parameter; + using CGAL::parameters::get_parameter; + typedef typename GetVertexPointMap::const_type Vpmap; typedef CGAL::Property_map_to_unary_function Vpmap_fct; - Vpmap vpm = CGAL::parameters::choose_parameter( - CGAL::parameters::get_parameter(np, internal_np::vertex_point), - get_const_property_map(boost::vertex_point, g)); - + Vpmap vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, g)); + Vpmap_fct v2p(vpm); convex_hull_3(boost::make_transform_iterator(vertices(g).begin(), v2p), boost::make_transform_iterator(vertices(g).end(), v2p), pm); From 9020240152317127d96042b80c6ad28f34452bb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 13 Mar 2020 11:58:20 +0100 Subject: [PATCH 110/150] Remove useless typedefs --- .../include/CGAL/Optimal_bounding_box/oriented_bounding_box.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 9cba883654b..76cc308906b 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -160,7 +160,6 @@ void construct_oriented_bounding_box(const PointRange& points, CGAL::Random& rng, const Traits& traits) { - typedef typename Traits::Matrix Matrix; typedef typename Traits::Point_3 Point; CGAL_static_assertion((std::is_same::type, Point>::value)); @@ -351,8 +350,6 @@ void oriented_bounding_box(const PolygonMesh& pmesh, using CGAL::parameters::choose_parameter; using CGAL::parameters::get_parameter; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename CGAL::GetVertexPointMap::const_type VPM; VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), From ff8b27408908f6dea722c76a0513428a5cbc9823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 13 Mar 2020 11:59:16 +0100 Subject: [PATCH 111/150] Keep a single (fixed) benchmark program --- .../bench_fitness_function.cpp | 64 --------- .../Optimal_bounding_box/bench_obb.cpp | 128 +++++++++--------- .../Optimal_bounding_box/bench_perfomance.cpp | 85 ------------ 3 files changed, 62 insertions(+), 215 deletions(-) delete mode 100644 Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_fitness_function.cpp delete mode 100644 Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_fitness_function.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_fitness_function.cpp deleted file mode 100644 index 15414eaee48..00000000000 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_fitness_function.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include - -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include - -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; - -int main() -{ - const char* fname = "data/elephant.off"; - - // 1) import a lot a mesh and subdivide it to create a big mesh - std::ifstream input(fname); - - CGAL::Surface_mesh mesh; - if (!input || !(input >> mesh) || mesh.is_empty()) - { - std::cerr << fname << " is not a valid off file.\n"; - std::exit(1); - } - - CGAL::Subdivision_method_3::CatmullClark_subdivision(mesh, - CGAL::parameters::number_of_iterations(6)); - - int nb_points = static_cast(vertices(mesh).size()); - std::cout << "number of points= " << nb_points << std::endl; - - - // 2) fill a Matrix with them - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - typedef Linear_algebra_traits::MatrixX3d MatrixX3d; - typedef Linear_algebra_traits::Matrix3d Matrix3d; - - MatrixX3d points_mat(nb_points, 3); - CGAL::Optimal_bounding_box::sm_to_matrix(mesh, points_mat); - - // 3) create a population of simplices - CGAL::Optimal_bounding_box::Population pop(50); - - CGAL::Timer timer; - timer.start(); - - // 4) compute fitness of population via the Fitness map - CGAL::Optimal_bounding_box::Fitness_map fit_map(pop, points_mat); - double result = fit_map.get_best_fitness_value(); - - timer.stop(); - - std::cout << "took " << timer.time() << " to compute the fitness of all vertices.\n"; - std::cout << "value of fittest vertex= " << result << std::endl; - - return 0; -} diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp index 02eefd76513..5d843594140 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp @@ -3,104 +3,100 @@ #include #include -#include -#include -#include +#include #include +#include #include #include #include +#include +#include -//#define CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_BENCHMARK +#define CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_BENCHMARK -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_3 Point_3; -bool assert_doubles(double d1, double d2, double epsilon) -{ - return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; -} +typedef CGAL::Surface_mesh Surface_mesh; +typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; -template -void gather_mesh_points(SurfaceMesh& mesh, std::vector& points) -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::property_map::type PointPMap; - PointPMap pmap = get(boost::vertex_point, mesh); - for(vertex_descriptor v : vertices(mesh)) - points.push_back(get(pmap, v)); -} - -void bench_finding_obb(std::string fname) +void bench_finding_obb(const std::string fname) { std::ifstream input(fname); - CGAL::Eigen_linear_algebra_traits la_traits; - std::vector sm_points; - // import a mesh - CGAL::Surface_mesh mesh; + Surface_mesh mesh; if (!input || !(input >> mesh) || mesh.is_empty()) { std::cerr << fname << " is not a valid off file.\n"; std::exit(1); } - // get mesh points - gather_mesh_points(mesh, sm_points); - CGAL::Timer timer; - // 1) measure convex hull calculation - timer.start(); - CGAL::Polyhedron_3 poly; - convex_hull_3(sm_points.begin(), sm_points.end(), poly); - std::vector ch_points(poly.points_begin(), poly.points_end()); - timer.stop(); - std::cout << "takes : " << timer.time() << " seconds to find the convex hull\n"; + std::size_t measurements = 4; + for(std::size_t t=0; t obb_points1; - CGAL::Optimal_bounding_box::compute_optimal_bounding_box(sm_points, obb_points1, la_traits, true); - timer.stop(); - std::cout << "found obb using convex hull: " << timer.time() << " seconds\n"; + // 1) measure convex hull calculation + timer.start(); + CGAL::Polyhedron_3 poly; + convex_hull_3(mesh, poly); + timer.stop(); + std::cout << "takes : " << timer.time() << " seconds to find the convex hull\n"; - // 3) without convex hull - timer.reset(); - timer.start(); - std::vector obb_points2; - CGAL::Optimal_bounding_box::compute_optimal_bounding_box(sm_points, obb_points2, la_traits, false); - timer.stop(); - std::cout << "found obb without convex hull: " << timer.time() << " seconds\n"; - timer.reset(); + // 2) using convex hull + timer.reset(); + timer.start(); + std::array obb_points1; + CGAL::oriented_bounding_box(mesh, obb_points1, CGAL::parameters::use_convex_hull(true)); + timer.stop(); + std::cout << "found obb using convex hull: " << timer.time() << " seconds\n"; + + // 3) without convex hull + timer.reset(); + timer.start(); + std::array obb_points2; + CGAL::oriented_bounding_box(mesh, obb_points2, CGAL::parameters::use_convex_hull(false)); + timer.stop(); + std::cout << "found obb without convex hull: " << timer.time() << " seconds\n"; + timer.reset(); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_BENCHMARK - CGAL::Surface_mesh result_mesh1; - CGAL::make_hexahedron(obb_points1[0], obb_points1[1], obb_points1[2], obb_points1[3], - obb_points1[4], obb_points1[5], obb_points1[6], obb_points1[7], - result_mesh1); + Surface_mesh result_mesh1; + CGAL::make_hexahedron(obb_points1[0], obb_points1[1], obb_points1[2], obb_points1[3], + obb_points1[4], obb_points1[5], obb_points1[6], obb_points1[7], + result_mesh1); - CGAL::Surface_mesh result_mesh2; - CGAL::make_hexahedron(obb_points2[0], obb_points2[1], obb_points2[2], obb_points2[3], - obb_points2[4], obb_points2[5], obb_points2[6], obb_points2[7], - result_mesh2); + Surface_mesh result_mesh2; + CGAL::make_hexahedron(obb_points2[0], obb_points2[1], obb_points2[2], obb_points2[3], + obb_points2[4], obb_points2[5], obb_points2[6], obb_points2[7], + result_mesh2); - std::ofstream out1("data/obb_result1.off"); - out1 << result_mesh1; - out1.close(); + std::stringstream oss1; + oss1 << "data/obb_result1_iter_" << t << std::ends; + std::ofstream out1(oss1.str().c_str()); + out1 << result_mesh1; - std::ofstream out2("data/obb_result2.off"); - out2 << result_mesh2; - out2.close(); + std::stringstream oss2; + oss2 << "data/obb_result2_iter_" << t << std::ends; + std::ofstream out2(oss2.str().c_str()); + out2 << result_mesh2; + + CGAL::Subdivision_method_3::CatmullClark_subdivision(mesh, CGAL::parameters::number_of_iterations(1)); #endif + } } -int main() +int main(int argc, char** argv) { - bench_finding_obb("data/elephant.off"); + bench_finding_obb((argc > 1) ? argv[1] : "data/elephant.off"); - return 0; + std::cout << "Done!" << std::endl; + + return EXIT_SUCCESS; } diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp deleted file mode 100644 index 2cab424a549..00000000000 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_perfomance.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include - -#include - -#include -#include - -#include -#include - -#include -#include - -//#define CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_BENCHMARK - -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; - -void bench_finding_obb(std::string fname) -{ - std::ifstream input(fname); - - // import a mesh - CGAL::Surface_mesh mesh; - if (!input || !(input >> mesh) || mesh.is_empty()) - { - std::cerr << fname << " is not a valid off file.\n"; - std::exit(1); - } - - // export some times - std::ofstream outt("data/times.txt"); - outt << "nb_vertices "<< "with_ch " << "without_ch" << std::endl; - - CGAL::Timer timer; - std::size_t measurements = 4; - CGAL::Eigen_linear_algebra_traits la_traits; - - for (std::size_t t = 0; t < measurements; ++t) - { - std::cout << "#vertices= " << vertices(mesh).size() << " |"; - - // 1) using convex hull - timer.start(); - CGAL::Surface_mesh obb_mesh1; - CGAL::Optimal_bounding_box::compute_optimal_bounding_box(mesh, obb_mesh1, la_traits, true); - timer.stop(); - double t_ch = timer.time(); - std::cout << " with ch: " << timer.time() << " s |"; - - // 2) without convex hull - timer.reset(); - timer.start(); - CGAL::Surface_mesh obb_mesh2; - CGAL::Optimal_bounding_box::compute_optimal_bounding_box(mesh, obb_mesh2, la_traits, false); - timer.stop(); - double t_no_ch = timer.time(); - std::cout << " without ch: " << timer.time() << " s\n"; - timer.reset(); - - outt << vertices(mesh).size() << " " << t_ch << " " << t_no_ch << std::endl; - - // 3) subdivision - CGAL::Subdivision_method_3::CatmullClark_subdivision(mesh, - CGAL::parameters::number_of_iterations(1)); - } - - outt.close(); - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_BENCHMARK - std::ofstream out1("data/obb_result1.off"); - out1 << obb_points1; - out1.close(); - - std::ofstream out2("data/obb_result2.off"); - out2 << obb_points2; - out2.close(); -#endif -} - -int main() -{ - bench_finding_obb("data/elephant.off"); - - return 0; -} From 48a39929ffa72b1193c13a6774ca13b1b86f33db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 13 Mar 2020 12:00:13 +0100 Subject: [PATCH 112/150] Illustrate 'use_convex_hull' named parameter usage in an example --- .../examples/Optimal_bounding_box/obb_example.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp index 52ddad1b5b7..0fb233f26ae 100644 --- a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp @@ -27,8 +27,10 @@ int main(int argc, char** argv) CGAL::Real_timer timer; timer.start(); + // Compute the extreme points of the mesh, and then a tightly fitted oriented bounding box std::array obb_points; - CGAL::oriented_bounding_box(sm, obb_points); + CGAL::oriented_bounding_box(sm, obb_points, + CGAL::parameters::use_convex_hull(true)); std::cout << "Elapsed time: " << timer.time() << std::endl; From c545e5ebb260cb9615a77fe3da67ca89768405ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 13 Mar 2020 12:03:53 +0100 Subject: [PATCH 113/150] Remove python script from benchmarks --- .../draw_benchmark_graph.py | 19 ------------------- .../Optimal_bounding_box/readme.txt | 1 - 2 files changed, 20 deletions(-) delete mode 100644 Optimal_bounding_box/benchmarks/Optimal_bounding_box/draw_benchmark_graph.py delete mode 100644 Optimal_bounding_box/benchmarks/Optimal_bounding_box/readme.txt diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/draw_benchmark_graph.py b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/draw_benchmark_graph.py deleted file mode 100644 index 8fc416ac260..00000000000 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/draw_benchmark_graph.py +++ /dev/null @@ -1,19 +0,0 @@ -import matplotlib.pyplot as plt -import numpy as np - -#path-to-benchmarks -benchmarkfile='data/times.txt' - -data = np.loadtxt(benchmarkfile, skiprows = 1) - -x = data[:, 0] -y1 = data[:, 1] -y2 = data[:, 2] - -plt.plot(x, y1, 'go--', label='with convex hull') -plt.plot(x, y2, 'ro--', label='without convex hull') -legend = plt.legend(loc='best') -plt.xlabel('#vertices') -plt.ylabel('seconds') - -plt.show() diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/readme.txt b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/readme.txt deleted file mode 100644 index ac22f73a877..00000000000 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/readme.txt +++ /dev/null @@ -1 +0,0 @@ -To draw a graph with the benchmark times set the path-to-the-measurments in draw_benchmark_times.py if necessary, and run the script with python 3. From 9df21ba79d84fc0f4992e41ba299c808b0d90dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 13 Mar 2020 12:08:55 +0100 Subject: [PATCH 114/150] Add the new examples to examples.txt --- Optimal_bounding_box/doc/Optimal_bounding_box/examples.txt | 2 ++ .../examples/Optimal_bounding_box/CMakeLists.txt | 2 +- .../{rotated_aabb_tree.cpp => rotated_aabb_tree_example.cpp} | 0 3 files changed, 3 insertions(+), 1 deletion(-) rename Optimal_bounding_box/examples/Optimal_bounding_box/{rotated_aabb_tree.cpp => rotated_aabb_tree_example.cpp} (100%) diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/examples.txt b/Optimal_bounding_box/doc/Optimal_bounding_box/examples.txt index 4bd9b08df1b..135614d2249 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/examples.txt +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/examples.txt @@ -1,4 +1,6 @@ /*! \example Optimal_bounding_box/obb_example.cpp +\example Optimal_bounding_box/obb_with_point_maps_example.cpp +\example Optimal_bounding_box/rotated_aabb_tree_example.cpp */ diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt index 9930366dd1c..050b338544a 100644 --- a/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt @@ -23,5 +23,5 @@ endif() create_single_source_cgal_program("obb_example.cpp") create_single_source_cgal_program("obb_with_point_maps_example.cpp") -create_single_source_cgal_program("rotated_aabb_tree.cpp") +create_single_source_cgal_program("rotated_aabb_tree_example.cpp") diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree.cpp b/Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree_example.cpp similarity index 100% rename from Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree.cpp rename to Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree_example.cpp From a7f0473c5c31ae884faa664f97c97a3f9f6c1616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 13 Mar 2020 13:24:03 +0100 Subject: [PATCH 115/150] Fix most of the tests (at least the compilation...) --- .../Optimal_bounding_box/bench_obb.cpp | 1 + .../Optimal_bounding_box/test_OBB_traits.cpp | 224 ++++++++------- .../Optimal_bounding_box/test_nelder_mead.cpp | 232 +++++++-------- .../test_optimization_algorithms.cpp | 267 ++++++------------ 4 files changed, 329 insertions(+), 395 deletions(-) diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp index 5d843594140..b6d1e3a5d6a 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp @@ -48,6 +48,7 @@ void bench_finding_obb(const std::string fname) convex_hull_3(mesh, poly); timer.stop(); std::cout << "takes : " << timer.time() << " seconds to find the convex hull\n"; + std::cout << num_vertices(poly) << " vertices on the convex hull" << std::endl; // 2) using convex hull timer.reset(); diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_OBB_traits.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_OBB_traits.cpp index 41b0474ba07..c5362beb3cd 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_OBB_traits.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_OBB_traits.cpp @@ -1,135 +1,141 @@ -#include -#include -#include +#include + +#include #include -bool assert_doubles(double d1, double d2, double epsilon) +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::FT FT; +typedef K::Point_3 Point_3; + +typedef CGAL::Oriented_bounding_box_traits_3 Traits; +typedef Traits::Matrix Matrix; + +void check_equality(const FT d1, const FT d2) { - return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; + const FT epsilon = 1e-3; + + bool ok; + if(std::is_floating_point::value) + ok = CGAL::abs(d1 - d2) < epsilon * CGAL::abs(d2); + else + ok = (d1 == d2); + + if(!ok) + { + std::cout << "Error: got " << d1 << " but expected: " << d2 << std::endl; + assert(false); + } } void test_fitness_function() { - typedef typename CGAL::Eigen_linear_algebra_traits::MatrixXd MatrixXd; - MatrixXd data_points(4, 3); + std::array points; + points[0] = Point_3(0.866802, 0.740808, 0.895304); + points[1] = Point_3(0.912651, 0.761565, 0.160330); + points[2] = Point_3(0.093661, 0.892578, 0.737412); + points[3] = Point_3(0.166461, 0.149912, 0.364944); - data_points.set_coef(0, 0, 0.866802); - data_points.set_coef(0, 1, 0.740808); - data_points.set_coef(0, 2, 0.895304); + Matrix rotation; + rotation.set(0, 0, -0.809204); + rotation.set(0, 1, 0.124296); + rotation.set(0, 2, 0.574230); + rotation.set(1, 0, -0.574694); + rotation.set(1, 1, 0.035719); + rotation.set(1, 2, -0.817589); + rotation.set(2, 0, -0.122134); + rotation.set(2, 1, -0.991602); + rotation.set(2, 2, 0.042528); - data_points.set_coef(1, 0, 0.912651); - data_points.set_coef(1, 1, 0.761565); - data_points.set_coef(1, 2, 0.160330); - - data_points.set_coef(2, 0, 0.093661); - data_points.set_coef(2, 1, 0.892578); - data_points.set_coef(2, 2, 0.737412); - - data_points.set_coef(3, 0, 0.166461); - data_points.set_coef(3, 1, 0.149912); - data_points.set_coef(3, 2, 0.364944); - - typedef typename CGAL::Eigen_linear_algebra_traits::Matrix3d Matrix3d; - Matrix3d rotation; - rotation.set_coef(0, 0, -0.809204); - rotation.set_coef(0, 1, 0.124296); - rotation.set_coef(0, 2, 0.574230); - rotation.set_coef(1, 0, -0.574694); - rotation.set_coef(1, 1, 0.035719); - rotation.set_coef(1, 2, -0.817589); - rotation.set_coef(2, 0, -0.122134); - rotation.set_coef(2, 1, -0.991602); - rotation.set_coef(2, 2, 0.042528); - - CGAL_assertion_code(typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits); - CGAL_assertion_code(double fitness = CGAL::Optimal_bounding_box:: - compute_fitness (rotation, data_points)); - CGAL_assertion(assert_doubles(fitness, 0.58606, 1e-5)); + const double fitness = CGAL::Optimal_bounding_box::internal::compute_fitness(rotation, points); + check_equality(fitness, 0.58606); } - - void test_eigen_matrix_interface() { - CGAL_assertion_code(typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits); - typedef CGAL::Eigen_dense_matrix Matrix; + Matrix A; + A.set(0, 0, 0.1); + A.set(0, 1, 0.2); + A.set(0, 2, 0.3); + A.set(1, 0, 0.4); + A.set(1, 1, 0.5); + A.set(1, 2, 0.6); + A.set(2, 0, 0.7); + A.set(2, 1, 0.8); + A.set(2, 2, 0.9); - Matrix A(3, 3); - A.set_coef(0, 0, 0.1); - A.set_coef(0, 1, 0.2); - A.set_coef(0, 2, 0.3); - A.set_coef(1, 0, 0.4); - A.set_coef(1, 1, 0.5); - A.set_coef(1, 2, 0.6); - A.set_coef(2, 0, 0.7); - A.set_coef(2, 1, 0.8); - A.set_coef(2, 2, 0.9); - CGAL_assertion_code(Matrix B); - CGAL_assertion_code(B = CGAL::Eigen_linear_algebra_traits::transpose(A)); - CGAL_assertion_code(Matrix S); - CGAL_assertion_code(S = 0.5 * A); - Matrix C(3,3); - C.set_coef(0, 0, 0.3011944); - C.set_coef(0, 1, 0.9932761); - C.set_coef(0, 2, 0.5483701); - C.set_coef(1, 0, 0.5149142); - C.set_coef(1, 1, 0.5973263); - C.set_coef(1, 2, 0.5162336); - C.set_coef(2, 0, 0.0039213); - C.set_coef(2, 1, 0.0202949); - C.set_coef(2, 2, 0.9240308); + Matrix B; + B = CGAL::Optimal_bounding_box::internal::transpose(A); - CGAL_assertion_code(Matrix Q = CGAL::Eigen_linear_algebra_traits::get_Q(C)); - CGAL_assertion_code(double epsilon = 1e-5); - CGAL_assertion(assert_doubles(Q(0,0), -0.504895, epsilon)); - CGAL_assertion(assert_doubles(Q(0,1), 0.862834, epsilon)); - CGAL_assertion(assert_doubles(Q(0,2), -0.024447, epsilon)); - CGAL_assertion(assert_doubles(Q(1,0), -0.863156, epsilon)); - CGAL_assertion(assert_doubles(Q(1,1), -0.504894, epsilon)); - CGAL_assertion(assert_doubles(Q(1,2), 0.006687, epsilon)); - CGAL_assertion(assert_doubles(Q(2,0), -0.006573, epsilon)); - CGAL_assertion(assert_doubles(Q(2,1), 0.024478, epsilon)); - CGAL_assertion(assert_doubles(Q(2,2), 0.999679, epsilon)); + Matrix S; + S = 0.5 * A; - Matrix D(3,3); - D.set_coef(0, 0, -0.809204); - D.set_coef(0, 1, 0.124296); - D.set_coef(0, 2, 0.574230); - D.set_coef(1, 0, -0.574694); - D.set_coef(1, 1, 0.035719); - D.set_coef(1, 2, -0.817589); - D.set_coef(2, 0, -0.122134); - D.set_coef(2, 1, -0.991602); - D.set_coef(2, 2, 0.042528); + Matrix C; + C.set(0, 0, 0.3011944); + C.set(0, 1, 0.9932761); + C.set(0, 2, 0.5483701); + C.set(1, 0, 0.5149142); + C.set(1, 1, 0.5973263); + C.set(1, 2, 0.5162336); + C.set(2, 0, 0.0039213); + C.set(2, 1, 0.0202949); + C.set(2, 2, 0.9240308); - Matrix E(3,3); - E.set_coef(0, 0, -0.45070); - E.set_coef(0, 1, -0.32769); - E.set_coef(0, 2, -0.83035); - E.set_coef(1, 0, -0.13619); - E.set_coef(1, 1, -0.89406); - E.set_coef(1, 2, 0.42675); - E.set_coef(2, 0, -0.88222); - E.set_coef(2, 1, 0.30543); - E.set_coef(2, 2, 0.35833); + Matrix Q = Traits::get_Q(C); - CGAL_assertion_code(Matrix Sr = CGAL::Optimal_bounding_box::reflection(D, E)); - CGAL_assertion(assert_doubles(Sr(0,0), -0.13359, epsilon)); - CGAL_assertion(assert_doubles(Sr(0,1), -0.95986, epsilon)); - CGAL_assertion(assert_doubles(Sr(0,2), -0.24664, epsilon)); - CGAL_assertion(assert_doubles(Sr(1,0), -0.60307, epsilon)); - CGAL_assertion(assert_doubles(Sr(1,1), -0.11875, epsilon)); - CGAL_assertion(assert_doubles(Sr(1,2), 0.78880, epsilon)); - CGAL_assertion(assert_doubles(Sr(2,0), -0.78642, epsilon)); - CGAL_assertion(assert_doubles(Sr(2,1), 0.25411, epsilon)); - CGAL_assertion(assert_doubles(Sr(2,2), -0.56300, epsilon)); + check_equality(Q(0,0), -0.504895); + check_equality(Q(0,1), 0.862834); + check_equality(Q(0,2), -0.024447); + check_equality(Q(1,0), -0.863156); + check_equality(Q(1,1), -0.504894); + check_equality(Q(1,2), 0.006687); + check_equality(Q(2,0), -0.006573); + check_equality(Q(2,1), 0.024478); + check_equality(Q(2,2), 0.999679); + + Matrix D; + D.set(0, 0, -0.809204); + D.set(0, 1, 0.124296); + D.set(0, 2, 0.574230); + D.set(1, 0, -0.574694); + D.set(1, 1, 0.035719); + D.set(1, 2, -0.817589); + D.set(2, 0, -0.122134); + D.set(2, 1, -0.991602); + D.set(2, 2, 0.042528); + + Matrix E; + E.set(0, 0, -0.45070); + E.set(0, 1, -0.32769); + E.set(0, 2, -0.83035); + E.set(1, 0, -0.13619); + E.set(1, 1, -0.89406); + E.set(1, 2, 0.42675); + E.set(2, 0, -0.88222); + E.set(2, 1, 0.30543); + E.set(2, 2, 0.35833); + + Matrix Sr = CGAL::Optimal_bounding_box::internal::reflection(D, E); + check_equality(Sr(0,0), -0.13359); + check_equality(Sr(0,1), -0.95986); + check_equality(Sr(0,2), -0.24664); + check_equality(Sr(1,0), -0.60307); + check_equality(Sr(1,1), -0.11875); + check_equality(Sr(1,2), 0.78880); + check_equality(Sr(2,0), -0.78642); + check_equality(Sr(2,1), 0.25411); + check_equality(Sr(2,2), -0.56300); } -int main() +int main(int, char**) { test_fitness_function(); test_eigen_matrix_interface(); - return 0; + std::cout << "Done!" << std::endl; + + return EXIT_SUCCESS; } diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp index a84cb83b5ea..b1a4587f3be 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp @@ -5,106 +5,115 @@ #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::FT FT; typedef K::Point_3 Point_3; typedef CGAL::Oriented_bounding_box_traits_3 Traits; typedef Traits::Matrix Matrix; -bool are_equal(double d1, double d2, double epsilon) +void check_equality(const FT d1, const FT d2) { - return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; + const FT epsilon = 1e-3; + + bool ok; + if(std::is_floating_point::value) + ok = CGAL::abs(d1 - d2) < epsilon * CGAL::abs(d2); + else + ok = (d1 == d2); + + if(!ok) + { + std::cout << "Error: got " << d1 << " but expected: " << d2 << std::endl; + assert(false); + } } -void test_simplex_operations() +void test_simplex_operations(const Traits& traits) { - const double epsilon = 1e-5; - - Matrix Sc(3, 3); + Matrix Sc; Sc.set(0, 0, -0.809204); Sc.set(0, 1, 0.124296); Sc.set(0, 2, 0.574230); Sc.set(1, 0, -0.574694); Sc.set(1, 1, 0.035719); Sc.set(1, 2, -0.817589); Sc.set(2, 0, -0.122134); Sc.set(2, 1, -0.991602); Sc.set(2, 2, 0.042528); - Matrix S_worst(3, 3); + Matrix S_worst; S_worst.set(0, 0, -0.45070); S_worst.set(0, 1, -0.32769); S_worst.set(0, 2, -0.83035); S_worst.set(1, 0, -0.13619); S_worst.set(1, 1, -0.89406); S_worst.set(1, 2, 0.42675); S_worst.set(2, 0, -0.88222); S_worst.set(2, 1, 0.30543); S_worst.set(2, 2, 0.35833); - Matrix Sr = CGAL::Optimal_bounding_box::reflection(Sc, S_worst); - assert(are_equal(Sr(0,0), -0.13359, epsilon)); - assert(are_equal(Sr(0,1), -0.95986, epsilon)); - assert(are_equal(Sr(0,2), -0.24664, epsilon)); - assert(are_equal(Sr(1,0), -0.60307, epsilon)); - assert(are_equal(Sr(1,1), -0.11875, epsilon)); - assert(are_equal(Sr(1,2), 0.78880, epsilon)); - assert(are_equal(Sr(2,0), -0.78642, epsilon)); - assert(are_equal(Sr(2,1), 0.25411, epsilon)); - assert(are_equal(Sr(2,2), -0.56300, epsilon)); + Matrix Sr = CGAL::Optimal_bounding_box::internal::reflection(Sc, S_worst); + check_equality(Sr(0,0), -0.13359); + check_equality(Sr(0,1), -0.95986); + check_equality(Sr(0,2), -0.24664); + check_equality(Sr(1,0), -0.60307); + check_equality(Sr(1,1), -0.11875); + check_equality(Sr(1,2), 0.78880); + check_equality(Sr(2,0), -0.78642); + check_equality(Sr(2,1), 0.25411); + check_equality(Sr(2,2), -0.56300); - Matrix Se = CGAL::Optimal_bounding_box::expansion(Sc, S_worst, Sr); - assert(are_equal(Se(0,0), -0.87991, epsilon)); - assert(are_equal(Se(0,1), 0.36105, epsilon)); - assert(are_equal(Se(0,2), -0.30888, epsilon)); - assert(are_equal(Se(1,0), -0.11816, epsilon)); - assert(are_equal(Se(1,1), -0.79593, epsilon)); - assert(are_equal(Se(1,2), -0.59375, epsilon)); - assert(are_equal(Se(2,0), -0.460215, epsilon)); - assert(are_equal(Se(2,1), -0.48595, epsilon)); - assert(are_equal(Se(2,2), 0.74300, epsilon)); + Matrix Se = CGAL::Optimal_bounding_box::internal::expansion(Sc, S_worst, Sr); + check_equality(Se(0,0), -0.87991); + check_equality(Se(0,1), 0.36105); + check_equality(Se(0,2), -0.30888); + check_equality(Se(1,0), -0.11816); + check_equality(Se(1,1), -0.79593); + check_equality(Se(1,2), -0.59375); + check_equality(Se(2,0), -0.460215); + check_equality(Se(2,1), -0.48595); + check_equality(Se(2,2), 0.74300); - Matrix S_a(3, 3); + Matrix S_a; S_a.set(0, 0, -0.277970); S_a.set(0, 1, 0.953559); S_a.set(0, 2, 0.116010); S_a.set(1, 0, -0.567497); S_a.set(1, 1, -0.065576); S_a.set(1, 2, -0.820760); S_a.set(2, 0, -0.775035); S_a.set(2, 1, -0.293982); S_a.set(2, 2, 0.559370); - Matrix S_b(3, 3); + Matrix S_b; S_b.set(0, 0, -0.419979); S_b.set(0, 1, 0.301765); S_b.set(0, 2, -0.8558940); S_b.set(1, 0, -0.653011); S_b.set(1, 1, -0.755415); S_b.set(1, 2, 0.054087); S_b.set(2, 0, -0.630234); S_b.set(2, 1, 0.581624); S_b.set(2, 2, 0.514314); - Matrix S_c = CGAL::Optimal_bounding_box::mean(S_a, S_b); - assert(are_equal(S_c(0,0), -0.35111, epsilon)); - assert(are_equal(S_c(0,1), 0.79308, epsilon)); - assert(are_equal(S_c(0,2), -0.49774, epsilon)); - assert(are_equal(S_c(1,0), -0.61398, epsilon)); - assert(are_equal(S_c(1,1), -0.59635, epsilon)); - assert(are_equal(S_c(1,2), -0.51710, epsilon)); - assert(are_equal(S_c(2,0), -0.70693, epsilon)); - assert(are_equal(S_c(2,1), 0.12405, epsilon)); - assert(are_equal(S_c(2,2), 0.69632, epsilon)); + Matrix S_c = CGAL::Optimal_bounding_box::internal::mean(S_a, S_b, traits); + check_equality(S_c(0,0), -0.35111); + check_equality(S_c(0,1), 0.79308); + check_equality(S_c(0,2), -0.49774); + check_equality(S_c(1,0), -0.61398); + check_equality(S_c(1,1), -0.59635); + check_equality(S_c(1,2), -0.51710); + check_equality(S_c(2,0), -0.70693); + check_equality(S_c(2,1), 0.12405); + check_equality(S_c(2,2), 0.69632); } -void test_centroid() +void test_centroid(const Traits& traits) { - const double epsilon = 1e-5; - Matrix S_a; S_a.set(0, 0, -0.588443); S_a.set(0, 1, 0.807140); S_a.set(0, 2, -0.047542); S_a.set(1, 0, -0.786228); S_a.set(1, 1, -0.584933); S_a.set(1, 2, -0.199246); S_a.set(2, 0, -0.188629); S_a.set(2, 1, -0.079867); S_a.set(2, 2, 0.978795); - Matrix S_b(3, 3); + Matrix S_b; S_b.set(0, 0, -0.2192721); S_b.set(0, 1, 0.2792986); S_b.set(0, 2, -0.9348326); S_b.set(1, 0, -0.7772152); S_b.set(1, 1, -0.6292092); S_b.set(1, 2, -0.005686); S_b.set(2, 0, -0.5897934); S_b.set(2, 1, 0.7253193); S_b.set(2, 2, 0.3550431); - Matrix S_c(3, 3); + Matrix S_c; S_c.set(0, 0, -0.32657); S_c.set(0, 1, -0.60013); S_c.set(0, 2, -0.730206); S_c.set(1, 0, -0.20022); S_c.set(1, 1, -0.71110); S_c.set(1, 2, 0.67398); S_c.set(2, 0, -0.92372); S_c.set(2, 1, 0.36630); S_c.set(2, 2, 0.11207); - Matrix S_centroid = CGAL::Optimal_bounding_box::nm_centroid(S_a, S_b, S_c); - assert(are_equal(S_centroid(0,0), -0.419979, epsilon)); - assert(are_equal(S_centroid(0,1), 0.301765, epsilon)); - assert(are_equal(S_centroid(0,2), -0.855894, epsilon)); - assert(are_equal(S_centroid(1,0), -0.653011, epsilon)); - assert(are_equal(S_centroid(1,1), -0.755415, epsilon)); - assert(are_equal(S_centroid(1,2), 0.054087, epsilon)); - assert(are_equal(S_centroid(2,0), -0.630234, epsilon)); - assert(are_equal(S_centroid(2,1), 0.581624, epsilon)); - assert(are_equal(S_centroid(2,2), 0.514314, epsilon)); + Matrix S_centroid = CGAL::Optimal_bounding_box::internal::nm_centroid(S_a, S_b, S_c, traits); + check_equality(S_centroid(0,0), -0.419979); + check_equality(S_centroid(0,1), 0.301765); + check_equality(S_centroid(0,2), -0.855894); + check_equality(S_centroid(1,0), -0.653011); + check_equality(S_centroid(1,1), -0.755415); + check_equality(S_centroid(1,2), 0.054087); + check_equality(S_centroid(2,0), -0.630234); + check_equality(S_centroid(2,1), 0.581624); + check_equality(S_centroid(2,2), 0.514314); } -void test_nelder_mead() +void test_nelder_mead(const Traits& traits) { std::array points; points[0] = Point_3(0.866802, 0.740808, 0.895304); @@ -116,21 +125,21 @@ void test_nelder_mead() std::array simplex; Matrix v0, v1, v2, v3; - v0(0,0) = -0.2192721; v0(0,1) = 0.2792986; v0(0,2) = -0.9348326; - v0(1,0) = -0.7772152; v0(1,1) = -0.6292092; v0(1,2) = -0.0056861; - v0(2,0) = -0.5897934; v0(2,1) = 0.7253193; v0(2,2) = 0.3550431; + v0.set(0, 0, -0.2192721); v0.set(0, 1, 0.2792986); v0.set(0, 2, -0.9348326); + v0.set(1, 0, -0.7772152); v0.set(1, 1, -0.6292092); v0.set(1, 2, -0.0056861); + v0.set(2, 0, -0.5897934); v0.set(2, 1, 0.7253193); v0.set(2, 2, 0.3550431); - v1(0,0) = -0.588443; v1(0,1) = 0.807140; v1(0,2) = -0.047542; - v1(1,0) = -0.786228; v1(1,1) = -0.584933; v1(1,2) = -0.199246; - v1(2,0) = -0.188629; v1(2,1) = -0.079867; v1(2,2) = 0.978795; + v1.set(0, 0, -0.588443); v1.set(0, 1, 0.807140); v1.set(0, 2, -0.047542); + v1.set(1, 0, -0.786228); v1.set(1, 1, -0.584933); v1.set(1, 2, -0.199246); + v1.set(2, 0, -0.188629); v1.set(2, 1, -0.079867); v1.set(2, 2, 0.978795); - v2(0,0) = -0.277970; v2(0,1) = 0.953559; v2(0,2) = 0.116010; - v2(1,0) = -0.567497; v2(1,1) = -0.065576; v2(1,2) = -0.820760; - v2(2,0) = -0.775035; v2(2,1) = -0.293982; v2(2,2) = 0.559370; + v2.set(0, 0, -0.277970); v2.set(0, 1, 0.953559); v2.set(0, 2, 0.116010); + v2.set(1, 0, -0.567497); v2.set(1, 1, -0.065576); v2.set(1, 2, -0.820760); + v2.set(2, 0, -0.775035); v2.set(2, 1, -0.293982); v2.set(2, 2, 0.559370); - v3(0,0) = -0.32657; v3(0,1) = -0.60013; v3(0,2) = -0.73020; - v3(1,0) = -0.20022; v3(1,1) = -0.71110; v3(1,2) = 0.67398; - v3(2,0) = -0.92372; v3(2,1) = 0.36630; v3(2,2) = 0.11207; + v3.set(0, 0, -0.32657); v3.set(0, 1, -0.60013); v3.set(0, 2, -0.73020); + v3.set(1, 0, -0.20022); v3.set(1, 1, -0.71110); v3.set(1, 2, 0.67398); + v3.set(2, 0, -0.92372); v3.set(2, 1, 0.36630); v3.set(2, 2, 0.11207); simplex[0] = v0; simplex[1] = v1; @@ -138,59 +147,62 @@ void test_nelder_mead() simplex[3] = v3; std::size_t nm_iterations = 19; - CGAL::Optimal_bounding_box::internal::nelder_mead(simplex, data_points, nm_iterations); + CGAL::Optimal_bounding_box::internal::nelder_mead(points, nm_iterations, traits, simplex); - double epsilon = 1e-5; const Matrix& v0_new = simplex[0]; - assert(assert_doubles(v0_new(0,0), -0.288975, epsilon)); - assert(assert_doubles(v0_new(0,1), 0.7897657, epsilon)); - assert(assert_doubles(v0_new(0,2), -0.541076, epsilon)); - assert(assert_doubles(v0_new(1,0), -0.9407046, epsilon)); - assert(assert_doubles(v0_new(1,1), -0.3391466, epsilon)); - assert(assert_doubles(v0_new(1,2), 0.0073817, epsilon)); - assert(assert_doubles(v0_new(2,0), -0.1776743, epsilon)); - assert(assert_doubles(v0_new(2,1), 0.5111260, epsilon)); - assert(assert_doubles(v0_new(2,2), 0.84094, epsilon)); + check_equality(v0_new(0,0), -0.288975); + check_equality(v0_new(0,1), 0.7897657); + check_equality(v0_new(0,2), -0.541076); + check_equality(v0_new(1,0), -0.9407046); + check_equality(v0_new(1,1), -0.3391466); + check_equality(v0_new(1,2), 0.0073817); + check_equality(v0_new(2,0), -0.1776743); + check_equality(v0_new(2,1), 0.5111260); + check_equality(v0_new(2,2), 0.84094); const Matrix& v1_new = simplex[1]; - assert(assert_doubles(v1_new(0,0), -0.458749, epsilon)); - assert(assert_doubles(v1_new(0,1), 0.823283, epsilon)); - assert(assert_doubles(v1_new(0,2), -0.334296, epsilon)); - assert(assert_doubles(v1_new(1,0), -0.885235, epsilon)); - assert(assert_doubles(v1_new(1,1), -0.455997, epsilon)); - assert(assert_doubles(v1_new(1,2), 0.091794, epsilon)); - assert(assert_doubles(v1_new(2,0), -0.076866, epsilon)); - assert(assert_doubles(v1_new(2,1), 0.338040, epsilon)); - assert(assert_doubles(v1_new(2,2), 0.937987, epsilon)); + check_equality(v1_new(0,0), -0.458749); + check_equality(v1_new(0,1), 0.823283); + check_equality(v1_new(0,2), -0.334296); + check_equality(v1_new(1,0), -0.885235); + check_equality(v1_new(1,1), -0.455997); + check_equality(v1_new(1,2), 0.091794); + check_equality(v1_new(2,0), -0.076866); + check_equality(v1_new(2,1), 0.338040); + check_equality(v1_new(2,2), 0.937987); const Matrix& v2_new = simplex[2]; - assert(assert_doubles(v2_new(0,0), -0.346582, epsilon)); - assert(assert_doubles(v2_new(0,1), 0.878534, epsilon)); - assert(assert_doubles(v2_new(0,2), -0.328724, epsilon)); - assert(assert_doubles(v2_new(1,0), -0.936885, epsilon)); - assert(assert_doubles(v2_new(1,1), -0.341445, epsilon)); - assert(assert_doubles(v2_new(1,2), 0.075251, epsilon)); - assert(assert_doubles(v2_new(2,0), -0.046131, epsilon)); - assert(assert_doubles(v2_new(2,1), 0.334057, epsilon)); - assert(assert_doubles(v2_new(2,2), 0.941423, epsilon)); + check_equality(v2_new(0,0), -0.346582); + check_equality(v2_new(0,1), 0.878534); + check_equality(v2_new(0,2), -0.328724); + check_equality(v2_new(1,0), -0.936885); + check_equality(v2_new(1,1), -0.341445); + check_equality(v2_new(1,2), 0.075251); + check_equality(v2_new(2,0), -0.046131); + check_equality(v2_new(2,1), 0.334057); + check_equality(v2_new(2,2), 0.941423); const Matrix& v3_new = simplex[3]; - assert(assert_doubles(v3_new(0,0), -0.394713, epsilon)); - assert(assert_doubles(v3_new(0,1), 0.791782, epsilon)); - assert(assert_doubles(v3_new(0,2), -0.466136, epsilon)); - assert(assert_doubles(v3_new(1,0), -0.912112, epsilon)); - assert(assert_doubles(v3_new(1,1), -0.398788, epsilon)); - assert(assert_doubles(v3_new(1,2), 0.094972, epsilon)); - assert(assert_doubles(v3_new(2,0), -0.110692, epsilon)); - assert(assert_doubles(v3_new(2,1), 0.462655, epsilon)); - assert(assert_doubles(v3_new(2,2), 0.879601, epsilon)); + check_equality(v3_new(0,0), -0.394713); + check_equality(v3_new(0,1), 0.791782); + check_equality(v3_new(0,2), -0.466136); + check_equality(v3_new(1,0), -0.912112); + check_equality(v3_new(1,1), -0.398788); + check_equality(v3_new(1,2), 0.094972); + check_equality(v3_new(2,0), -0.110692); + check_equality(v3_new(2,1), 0.462655); + check_equality(v3_new(2,2), 0.879601); } -int main() +int main(int, char**) { - test_simplex_operations(); - test_centroid(); - test_nelder_mead(); + Traits traits; - return 0; + test_simplex_operations(traits); + test_centroid(traits); + test_nelder_mead(traits); + + std::cout << "Done!" << std::endl; + + return EXIT_SUCCESS; } diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 6dbbec359b0..1dbdc081967 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -2,75 +2,62 @@ #include -#include -#include -#include -#include -#include +#include +#include #include #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::FT FT; +typedef K::Point_3 Point_3; -bool assert_doubles(double d1, double d2, double epsilon) +typedef CGAL::Surface_mesh Mesh; + +typedef CGAL::Oriented_bounding_box_traits_3 Traits; +typedef Traits::Matrix Matrix; + +void check_equality(const FT d1, const FT d2) { - return (d1 < d2 + epsilon && d1 > d2 - epsilon) ? true : false; + const FT epsilon = 1e-3; + + bool ok; + if(std::is_floating_point::value) + ok = CGAL::abs(d1 - d2) < epsilon * CGAL::abs(d2); + else + ok = (d1 == d2); + + if(!ok) + { + std::cout << "Error: got " << d1 << " but expected: " << d2 << std::endl; + assert(false); + } } void test_genetic_algorithm() { - CGAL::Eigen_dense_matrix data_points(4, 3); // -1 = dynamic size at run time - data_points(0,0) = 0.866802; - data_points(0,1) = 0.740808; - data_points(0,2) = 0.895304; - data_points(1,0) = 0.912651; - data_points(1,1) = 0.761565; - data_points(1,2) = 0.160330; - data_points(2,0) = 0.093661; - data_points(2,1) = 0.892578; - data_points(2,2) = 0.737412; - data_points(3,0) = 0.166461; - data_points(3,1) = 0.149912; - data_points(3,2) = 0.364944; + std::array points; + points[0] = Point_3(0.866802, 0.740808, 0.895304); + points[1] = Point_3(0.912651, 0.761565, 0.160330); + points[2] = Point_3(0.093661, 0.892578, 0.737412); + points[3] = Point_3(0.166461, 0.149912, 0.364944); - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - CGAL::Optimal_bounding_box::Population pop(5); - CGAL::Optimal_bounding_box::Evolution evolution(pop, data_points); + CGAL::Optimal_bounding_box::internal::Population pop(5); + CGAL::Optimal_bounding_box::internal::Evolution evolution(pop, data_points); evolution.genetic_algorithm(); assert(pop.size() == 5); } void test_random_unit_tetra() { - // this is dynamic at run times - CGAL::Eigen_dense_matrix data_points(4, 3); + std::array points; + points[0] = Point_3(0.866802, 0.740808, 0.895304); + points[1] = Point_3(0.912651, 0.761565, 0.160330); + points[2] = Point_3(0.093661, 0.892578, 0.737412); + points[3] = Point_3(0.166461, 0.149912, 0.364944); - // points are on their convex hull - data_points(0,0) = 0.866802; - data_points(0,1) = 0.740808; - data_points(0,2) = 0.895304; - data_points(1,0) = 0.912651; - data_points(1,1) = 0.761565; - data_points(1,2) = 0.160330; - data_points(2,0) = 0.093661; - data_points(2,1) = 0.892578; - data_points(2,2) = 0.737412; - data_points(3,0) = 0.166461; - data_points(3,1) = 0.149912; - data_points(3,2) = 0.364944; - - typedef CGAL::Simple_cartesian K; - typedef K::Point_3 Point; - typedef CGAL::Surface_mesh Mesh; - - // make a mesh and export it Mesh mesh; - Point p1(0.866802, 0.740808, 0.895304); - Point p2(0.912651, 0.761565, 0.160330); - Point p3(0.093661, 0.892578, 0.737412); - Point p4(0.166461, 0.149912, 0.364944); - CGAL::make_tetrahedron(p1, p2, p3, p4, mesh); + CGAL::make_tetrahedron(points[0], points[1], points[2], points[3], mesh); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST std::ofstream out("data/random_unit_tetra.off"); @@ -78,148 +65,102 @@ void test_random_unit_tetra() out.close(); #endif - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - typedef Linear_algebra_traits::Matrix Matrix; - std::size_t generations = 10; - CGAL::Optimal_bounding_box::Population pop(50); - CGAL::Optimal_bounding_box::Evolution evolution(pop, data_points); + CGAL::Optimal_bounding_box::internal::Population pop(50); + CGAL::Optimal_bounding_box::internal::Evolution evolution(pop, data_points); evolution.evolve(generations); Matrix R = evolution.get_best(); - const double epsilon = 1e-3; - assert(assert_doubles(Linear_algebra_traits::compute_determinant(R), 1, epsilon)); - assert(assert_doubles(R(0,0), -0.25791, epsilon)); - assert(assert_doubles(R(0,1), 0.796512, epsilon)); - assert(assert_doubles(R(0,2), -0.546855, epsilon)); - assert(assert_doubles(R(1,0), -0.947128, epsilon)); - assert(assert_doubles(R(1,1), -0.320242, epsilon)); - assert(assert_doubles(R(1,2), -0.0197553, epsilon)); - assert(assert_doubles(R(2,0), -0.190861, epsilon)); - assert(assert_doubles(R(2,1), 0.512847, epsilon)); - assert(assert_doubles(R(2,2), 0.836992, epsilon)); - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST - // postprocessing - CGAL::Eigen_dense_matrix obb(8, 3); - CGAL::Optimal_bounding_box::post_processing(data_points, R, obb); -#endif + check_equality(Traits::compute_determinant(R), 1); + check_equality(R(0,0), -0.25791); + check_equality(R(0,1), 0.796512); + check_equality(R(0,2), -0.546855); + check_equality(R(1,0), -0.947128); + check_equality(R(1,1), -0.320242); + check_equality(R(1,2), -0.0197553); + check_equality(R(2,0), -0.190861); + check_equality(R(2,1), 0.512847); + check_equality(R(2,2), 0.836992); } void test_reference_tetrahedron(const char* fname) { std::ifstream input(fname); - CGAL::Surface_mesh mesh; - if (!input || !(input >> mesh) || mesh.is_empty()) { + CGAL::Surface_mesh mesh; + if(!input || !(input >> mesh) || mesh.is_empty()) + { std::cerr << fname << " is not a valid off file.\n"; std::exit(1); } - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - typedef Linear_algebra_traits::Matrix Matrix; - // points in a matrix Matrix points; CGAL::Optimal_bounding_box::sm_to_matrix(mesh, points); std::size_t generations = 10; - CGAL::Optimal_bounding_box::Population pop(50); - CGAL::Optimal_bounding_box::Evolution experiment(pop, points); + CGAL::Optimal_bounding_box::internal::Population pop(50); + CGAL::Optimal_bounding_box::internal::Evolution experiment(pop, points); experiment.evolve(generations); Matrix R = experiment.get_best(); - double epsilon = 1e-5; - assert(assert_doubles(Linear_algebra_traits::compute_determinant(R), 1, epsilon)); - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST - // postprocessing - Matrix obb(8, 3); - CGAL::Optimal_bounding_box::post_processing(points, R, obb); -#endif + check_equality(Traits::compute_determinant(R), 1); } void test_long_tetrahedron(const std::string fname) { std::ifstream input(fname); - CGAL::Surface_mesh mesh; - if (!input || !(input >> mesh) || mesh.is_empty()) + CGAL::Surface_mesh mesh; + if(!input || !(input >> mesh) || mesh.is_empty()) { std::cerr << fname << " is not a valid off file.\n"; std::exit(1); } - typedef CGAL::Eigen_linear_algebra_traits Linear_algebra_traits; - typedef Linear_algebra_traits::Matrix Matrix; - // points in a matrix Matrix points; CGAL::Optimal_bounding_box::sm_to_matrix(mesh, points); std::size_t max_generations = 10; - CGAL::Optimal_bounding_box::Population pop(50); - CGAL::Optimal_bounding_box::Evolution experiment(pop, points); + CGAL::Optimal_bounding_box::internal::Population pop(50); + CGAL::Optimal_bounding_box::internal::Evolution experiment(pop, points); experiment.evolve(max_generations); Matrix R = experiment.get_best(); - double epsilon = 1e-3; - assert(assert_doubles(Linear_algebra_traits::compute_determinant(R), 1, epsilon)); - assert(assert_doubles(R(0,0), -1, epsilon)); - assert(assert_doubles(R(0,1), 0, epsilon)); - assert(assert_doubles(R(0,2), 0, epsilon)); - assert(assert_doubles(R(1,0), 0, epsilon)); - assert(assert_doubles(R(1,1), -0.707107, epsilon)); - assert(assert_doubles(R(1,2), 0.707106, epsilon) || - assert_doubles(R(1,2), -0.707106, epsilon)); - assert(assert_doubles(R(2,0), 0, epsilon)); - assert(assert_doubles(R(2,1), 0.707106, epsilon) || - assert_doubles(R(1,2), -0.707106, epsilon)); - assert(assert_doubles(R(2,2), 0.707107, epsilon)); - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST - // postprocessing - Matrix obb(8, 3); - CGAL::Optimal_bounding_box::post_processing(points, R, obb); -#endif + check_equality(Traits::compute_determinant(R), 1); + check_equality(R(0,0), -1); + check_equality(R(0,1), 0); + check_equality(R(0,2), 0); + check_equality(R(1,0), 0); + check_equality(R(1,1), -0.707107); + check_equality(R(1,2), 0.707106) || assert_doubles(R(1,2), -0.707106); + check_equality(R(2,0), 0); + check_equality(R(2,1), 0.707106) || assert_doubles(R(1,2), -0.707106); + check_equality(R(2,2), 0.707107); } void test_compute_obb_evolution(const std::string fname) { std::ifstream input(fname); - typedef CGAL::Surface_mesh SMesh; + typedef CGAL::Surface_mesh SMesh; SMesh mesh; - if (!input || !(input >> mesh) || mesh.is_empty()) + if(!input || !(input >> mesh) || mesh.is_empty()) { std::cerr << fname << " is not a valid off file.\n"; std::exit(1); } - // get mesh points - std::vector sm_points; + Traits traits; + std::array obb_points; + CGAL::oriented_bounding_box(sm, obb_points, CGAL::parameters::use_convex_hull(true) + .geom_traits(traits)); - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::property_map::const_type PointPMap; - - PointPMap pmap = get(boost::vertex_point, mesh); - for(vertex_descriptor v : vertices(mesh)) - sm_points.push_back(get(pmap, v)); - - - CGAL::Eigen_linear_algebra_traits la_traits; - std::vector obb_points; - CGAL::Optimal_bounding_box::compute_optimal_bounding_box(sm_points, obb_points, la_traits, true); - - double epsilon = 1e-3; - double vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points); - assert(assert_doubles(vol, 0.883371, epsilon)); + FT vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points); + check_equality(vol, 0.883371); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST - /* - for(int i = 0; i < 8; ++i) - std::cout << obb_points[i].x() << " " << obb_points[i].y() << " " << obb_points[i].z() << "\n" ; - */ - CGAL::Surface_mesh result_mesh; + CGAL::Surface_mesh result_mesh; CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], - obb_points[4], obb_points[5], obb_points[6], obb_points[7], result_mesh); + obb_points[4], obb_points[5], obb_points[6], obb_points[7], result_mesh); std::ofstream out("data/obb_result.off"); out << result_mesh; @@ -230,16 +171,15 @@ void test_compute_obb_evolution(const std::string fname) void test_compute_obb_mesh(const std::string fname) { std::ifstream input(fname); - CGAL::Surface_mesh mesh; - if (!input || !(input >> mesh) || mesh.is_empty()) + CGAL::Surface_mesh mesh; + if(!input || !(input >> mesh) || mesh.is_empty()) { std::cerr << fname << " is not a valid off file.\n"; std::exit(1); } - CGAL::Eigen_linear_algebra_traits la_traits; - CGAL::Surface_mesh< K::Point_3> obbmesh; - CGAL::Optimal_bounding_box::compute_optimal_bounding_box(mesh, obbmesh, la_traits, true); + CGAL::Surface_mesh obbmesh; + CGAL::oriented_bounding_box(mesh, obbmesh); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST std::ofstream out("/tmp/result_elephant.off"); @@ -248,46 +188,21 @@ void test_compute_obb_mesh(const std::string fname) #endif } -void test_function_defaults_traits(const std::string fname1, - const std::string fname2) +void test_function_defaults_traits(const std::string fname1) { std::ifstream input1(fname1); - CGAL::Surface_mesh mesh1; - if (!input1 || !(input1 >> mesh1) || mesh1.is_empty()) + CGAL::Surface_mesh mesh1; + if(!input1 || !(input1 >> mesh1) || mesh1.is_empty()) { std::cerr << fname1 << " is not a valid off file.\n"; std::exit(1); } - std::ifstream input2(fname2); - CGAL::Surface_mesh mesh2; - if (!input2 || !(input2 >> mesh2) || mesh2.is_empty()) - { - std::cerr << fname2 << " is not a valid off file.\n"; - std::exit(1); - } + std::array obb_points; + CGAL::oriented_bounding_box(sm_points, obb_points, CGAL::parameters::use_convex_hull(true)); - // test one - std::vector sm_points; - typedef CGAL::Surface_mesh SMesh; - - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::property_map::const_type PointPMap; - PointPMap pmap = get(boost::vertex_point, mesh1); - - for(vertex_descriptor v : vertices(mesh1)) - sm_points.push_back(get(pmap, v)); - - std::vector obb_points; - CGAL::Optimal_bounding_box::compute_optimal_bounding_box(sm_points, obb_points, true); - - const double epsilon = 1e-3; - const double vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points); - assert(assert_doubles(vol, 0.883371, epsilon)); - - // test two - CGAL::Surface_mesh obbmesh; - CGAL::Optimal_bounding_box::compute_optimal_bounding_box(mesh2, obbmesh, true); + const FT vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points); + check_equality(vol, 0.883371); } int main() @@ -299,7 +214,7 @@ int main() test_long_tetrahedron("data/long_tetrahedron.off"); test_compute_obb_evolution("data/random_unit_tetra.off"); test_compute_obb_mesh("data/elephant.off"); - test_function_defaults_traits("data/random_unit_tetra.off", "data/elephant.off"); + test_function_defaults_traits("data/random_unit_tetra.off"); return 0; } From 878354720591c951c52024a0b732148333562167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 13 Mar 2020 13:24:26 +0100 Subject: [PATCH 116/150] Make traits function static --- .../Optimal_bounding_box/Oriented_bounding_box_traits_3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h index 7de034882a4..6cf1f1a126f 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h @@ -61,11 +61,11 @@ private: public: /// Returns a default-constructed construction object - Construct_bbox_3 construct_bbox_3_object() const { return Construct_bbox_3(); } + static Construct_bbox_3 construct_bbox_3_object() { return Construct_bbox_3(); } /// Performs the QR-decomposition of the matrix `m` to a unitary matrix and an upper triagonal /// and returns the unitary matrix - Matrix get_Q(const Matrix& m) const + static Matrix get_Q(const Matrix& m) { Eigen::HouseholderQR qr(m.eigen_object()); return Matrix(EigenType(qr.householderQ())); From dd2adcb581a9c0902f99d30a35d2b7e4b4fc83c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 13 Mar 2020 13:25:48 +0100 Subject: [PATCH 117/150] Tiny internal function API change --- .../include/CGAL/Optimal_bounding_box/internal/evolution.h | 2 +- .../Optimal_bounding_box/internal/nelder_mead_functions.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index f3563f57c79..c24fa898d62 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -168,7 +168,7 @@ public: #endif for(std::size_t s=0; s -void nelder_mead(Simplex& simplex, - const PointRange& points, +void nelder_mead(const PointRange& points, const std::size_t nelder_mead_iterations, - const Traits& traits) + const Traits& traits, + Simplex& simplex) { typedef typename Traits::FT FT; typedef typename Traits::Matrix Matrix; From 3c5df657d4b4175580bd4d43418c31c419b94006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 23 Mar 2020 08:59:56 +0100 Subject: [PATCH 118/150] Fix namespace of GetPointMap --- .../include/CGAL/Optimal_bounding_box/oriented_bounding_box.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 76cc308906b..6745c3c5d72 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -261,7 +261,7 @@ void oriented_bounding_box(const PointRange& points, using CGAL::parameters::choose_parameter; using CGAL::parameters::get_parameter; - typedef typename Point_set_processing_3::GetPointMap::type PointMap; + typedef typename CGAL::GetPointMap::type PointMap; #if defined(CGAL_EIGEN3_ENABLED) typedef typename boost::property_traits::value_type Point; From 8652d9ada39fe9b5fbf67923cc9ba2a67f3b6c24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 23 Mar 2020 18:31:09 +0100 Subject: [PATCH 119/150] General improvements to improve speed (x3 faster with this) --- .../Optimal_bounding_box/internal/evolution.h | 105 +++++++--------- .../internal/fitness_function.h | 56 +++------ .../internal/nelder_mead_functions.h | 79 +++++------- .../internal/population.h | 119 +++++++++++------- .../oriented_bounding_box.h | 2 +- .../Optimal_bounding_box/test_nelder_mead.cpp | 2 +- 6 files changed, 175 insertions(+), 188 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index c24fa898d62..13415729658 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -40,15 +40,15 @@ public: typedef typename Traits::FT FT; typedef typename Traits::Matrix Matrix; - typedef Population Population; + typedef internal::Population Population; typedef typename Population::Simplex Simplex; - - typedef Fitness_map Fitness_map; + typedef typename Population::Vertex Vertex; Evolution(const PointRange& points, CGAL::Random& rng, const Traits& traits) : + m_best_v(nullptr), m_population(traits), m_rng(rng), m_points(points), @@ -58,7 +58,7 @@ public: void genetic_algorithm(const std::size_t population_size = 50) { // random permutations - m_population.initialize(population_size, m_rng); + m_population.initialize(population_size, m_points, m_rng); //groups 1,2 : size m/2 groups 3,4 : size (m - m/2). m/2 is floored const std::size_t m = population_size; @@ -74,19 +74,19 @@ public: std::generate(group3.begin(), group3.end(), [&]{ return m_rng.get_int(0, im); }); std::generate(group4.begin(), group4.end(), [&]{ return m_rng.get_int(0, im); }); - // crossover I + // crossover I, pick A or B FT bias = FT(0.1); std::vector new_simplices(m); for(std::size_t i=0; i offspring; + Simplex offspring; for(int j=0; j<4; ++j) { const FT r = FT(m_rng.get_double()); - const FT fitnessA = compute_fitness(m_population[group1[i]][j], m_points); - const FT fitnessB = compute_fitness(m_population[group2[i]][j], m_points); + const FT fitnessA = m_population[group1[i]][j].fitness_value(); + const FT fitnessB = m_population[group2[i]][j].fitness_value(); const FT threshold = (fitnessA < fitnessB) ? (0.5 + bias) : (0.5 - bias); if(r < threshold) @@ -98,39 +98,23 @@ public: new_simplices[i] = std::move(offspring); } - // crossover II + // crossover II, combine information from A and B bias = 0.1; // @fixme should the bias change? What should be the initial value? for(std::size_t i=0; i offspring; + Simplex offspring; for(int j=0; j<4; ++j) { - const FT fitnessA = compute_fitness(m_population[group3[i]][j], m_points); - const FT fitnessB = compute_fitness(m_population[group4[i]][j], m_points); + const FT fitnessA = m_population[group3[i]][j].fitness_value(); + const FT fitnessB = m_population[group4[i]][j].fitness_value(); const FT lambda = (fitnessA < fitnessB) ? (0.5 + bias) : (0.5 - bias); - const FT rambda = 1 - lambda; // the 'l' in 'lambda' stands for left + const FT rambda = 1 - lambda; // because the 'l' in 'lambda' stands for left - // combine information from A and B - Matrix new_vertex(3, 3); + const Matrix& lm = m_population[group3[i]][j].matrix(); + const Matrix& rm = m_population[group4[i]][j].matrix(); - const Matrix& lm = m_population[group3[i]][j]; - const Matrix& rm = m_population[group4[i]][j]; - - // just avoiding having to add matrix sums and scalar multiplications to the concept - new_vertex.set(0, 0, lambda * lm(0, 0) + rambda * rm(0, 0)); - new_vertex.set(0, 1, lambda * lm(0, 1) + rambda * rm(0, 1)); - new_vertex.set(0, 2, lambda * lm(0, 2) + rambda * rm(0, 2)); - - new_vertex.set(1, 0, lambda * lm(1, 0) + rambda * rm(1, 0)); - new_vertex.set(1, 1, lambda * lm(1, 1) + rambda * rm(1, 1)); - new_vertex.set(1, 2, lambda * lm(1, 2) + rambda * rm(1, 2)); - - new_vertex.set(2, 0, lambda * lm(2, 0) + rambda * rm(2, 0)); - new_vertex.set(2, 1, lambda * lm(2, 1) + rambda * rm(2, 1)); - new_vertex.set(2, 2, lambda * lm(2, 2) + rambda * rm(2, 2)); - - offspring[j] = m_traits.get_Q(new_vertex); + offspring[j] = Vertex(m_traits.get_Q(lambda*lm + rambda*rm), m_points, m_traits); } new_simplices[first_group_size + i] = std::move(offspring); @@ -139,56 +123,51 @@ public: m_population.simplices() = std::move(new_simplices); } - void evolve(const std::size_t generations) + void evolve(const std::size_t generations, + const std::size_t population_size = 50, + const std::size_t nelder_mead_iterations = 150) { - // hardcoded population size - const std::size_t population_size = 50; - - // hardcoded nelder_mead_iterations - const std::size_t nelder_mead_iterations = 150; - // stopping criteria prameters - FT prev_fit_value = 0.; - FT new_fit_value = 0.; + FT prev_fit_value = 0; + FT new_fit_value = 0; const FT tolerance = 1e-9; int stale = 0; for(std::size_t t=0; tfitness_value(); const FT difference = new_fit_value - prev_fit_value; #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG - const Matrix& R_now = fitness_map.get_best(); - std::cout << "new best: " << R_now << std::endl; + const Matrix& best_m = m_best_v->matrix(); + std::cout << "new best matrix: " << best_m << std::endl; std::cout << "value difference with previous: " << difference << std::endl; #endif - if(CGAL::abs(difference) < tolerance * new_fit_value) // @todo should depend on input bbox diag + if(CGAL::abs(difference) < tolerance * new_fit_value) ++stale; if(stale == 5) @@ -198,15 +177,17 @@ public: } } - const Matrix& get_best() + const Vertex& get_best() { - Fitness_map fitness_map(m_population, m_points); - return fitness_map.get_best(); + CGAL_assertion(m_best_v != nullptr); + return *m_best_v; } private: + const Vertex* m_best_v; Population m_population; - CGAL::Random m_rng; + + CGAL::Random& m_rng; const PointRange& m_points; const Traits& m_traits; }; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h index de370dd11e3..9f324a95ced 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h @@ -28,7 +28,8 @@ namespace internal { template typename Traits::FT compute_fitness(const typename Traits::Matrix& R, // rotation matrix - const PointRange& points) + const PointRange& points, + const Traits& /*traits*/) { typedef typename Traits::FT FT; typedef typename Traits::Point_3 Point; @@ -60,51 +61,32 @@ compute_fitness(const typename Traits::Matrix& R, // rotation matrix return ((xmax - xmin) * (ymax - ymin) * (zmax - zmin)); } -template -struct Fitness_map +template +const typename Population::Vertex& get_best_vertex(const Population& population, + const PointRange& points) { - typedef typename Traits::FT FT; - typedef typename Population::Vertex Vertex; + typedef typename Population::FT FT; + typedef typename Population::Vertex Vertex; - Fitness_map(const Population& population, - const PointRange& points) - : - m_pop(population), - m_points(points) - { } - - const Vertex& get_best() const // @todo any point caching this? + std::size_t simplex_id, vertex_id; + FT best_fitness = std::numeric_limits::max(); + for(std::size_t i=0, ps=population.size(); i::max(); - for(std::size_t i=0, ps=m_pop.size(); i(vertex, m_points); - if(fitness < best_fitness) - { - simplex_id = i; - vertex_id = j; - best_fitness = fitness; - } + simplex_id = i; + vertex_id = j; + best_fitness = fitness; } } - - return m_pop[simplex_id][vertex_id]; } - FT get_best_fitness_value() const - { - const Vertex& best_mat = get_best(); - return compute_fitness(best_mat, m_points); - } - -private: - const Population& m_pop; - const PointRange& m_points; -}; + return population[simplex_id][vertex_id]; +} } // namespace internal } // namespace Optimal_bounding_box diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h index d4cfc3cbc2a..06dff8f9ab6 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h @@ -50,7 +50,8 @@ Matrix mean(const Matrix& m1, { typedef typename Traits::FT FT; - const Matrix reduction = FT(0.5) * (m1 + m2); + constexpr half = FT(1) / FT(2); + const Matrix reduction = half * (m1 + m2); return traits.get_Q(reduction); } @@ -63,86 +64,74 @@ const Matrix nm_centroid(const Matrix& S1, { typedef typename Traits::FT FT; - const Matrix mean = (FT(1) / FT(3)) * (S1 + S2 + S3); + constexpr FT third = FT(1) / FT(3); + const Matrix mean = third * (S1 + S2 + S3); return traits.get_Q(mean); } // It's a 3D simplex with 4 rotation matrices as vertices template -void nelder_mead(const PointRange& points, +void nelder_mead(Simplex& simplex, const std::size_t nelder_mead_iterations, - const Traits& traits, - Simplex& simplex) + const PointRange& points, + const Traits& traits) { + typedef typename Simplex::value_type Vertex; typedef typename Traits::FT FT; typedef typename Traits::Matrix Matrix; - std::array fitness; - std::array indices = {{ 0, 1, 2, 3 }}; - for(std::size_t t=0; t(simplex[i], points); - - // get indices of sorted sequence - std::sort(indices.begin(), indices.end(), - [&fitness](const std::size_t i, const std::size_t j) -> bool - { return fitness[i] < fitness[j]; }); - - // new sorted simplex & fitness - Simplex s_simplex; - std::array s_fitness; - for(int i=0; i<4; ++i) - { - s_simplex[i] = simplex[indices[i]]; - s_fitness[i] = fitness[indices[i]]; - } - - simplex = std::move(s_simplex); - fitness = std::move(s_fitness); + std::sort(simplex.begin(), simplex.end(), + [](const Vertex& vi, const Vertex& vj) -> bool + { return vi.fitness_value() < vj.fitness_value(); }); // centroid - const Matrix v_centroid = nm_centroid(simplex[0], simplex[1], simplex[2], traits); + const Matrix centroid_m = nm_centroid(simplex[0].matrix(), + simplex[1].matrix(), + simplex[2].matrix(), traits); // find worst's vertex reflection - const Matrix& v_worst = simplex[3]; - const Matrix v_refl = reflection(v_centroid, v_worst); - const FT f_refl = compute_fitness(v_refl, points); + const Matrix& worst_m = simplex[3].matrix(); + const Matrix refl_m = reflection(centroid_m, worst_m); + const FT refl_f = compute_fitness(refl_m, points, traits); - if(f_refl < fitness[2]) + // if reflected point is better than the second worst + if(refl_f < simplex[2].fitness_value()) { - if(f_refl >= fitness[0]) // if reflected point is not better than the best + // if reflected point is not better than the best + if(refl_f >= simplex[0].fitness_value()) { // reflection - simplex[3] = std::move(v_refl); + simplex[3] = Vertex(refl_m, refl_f); } else { // expansion - const Matrix v_expand = expansion(v_centroid, v_worst, v_refl); - const FT f_expand = compute_fitness(v_expand, points); - if(f_expand < f_refl) - simplex[3] = std::move(v_expand); + const Matrix expand_m = expansion(centroid_m, worst_m, refl_m); + const FT expand_f = compute_fitness(expand_m, points, traits); + if(expand_f < refl_f) + simplex[3] = Vertex(expand_m, expand_f); else - simplex[3] = std::move(v_refl); + simplex[3] = Vertex(refl_m, refl_f); } } - else // if reflected vertex is not better + else // reflected vertex is worse { - const Matrix v_mean = mean(v_centroid, v_worst, traits); - const FT f_mean = compute_fitness(v_mean, points); - if(f_mean <= fitness[3]) + const Matrix mean_m = mean(centroid_m, worst_m, traits); + const FT mean_f = compute_fitness(mean_m, points, traits); + + if(mean_f <= simplex[3].fitness_value()) { // contraction of worst - simplex[3] = std::move(v_mean); + simplex[3] = Vertex(mean_m, mean_f); } else { // reduction: move all vertices towards the best for(std::size_t i=1; i<4; ++i) - simplex[i] = mean(simplex[i], simplex[0], traits); + simplex[i] = Vertex(mean(simplex[i].matrix(), simplex[0].matrix(), traits), points, traits); } } } // nelder mead iterations diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h index 1244c289230..2171816e1b8 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h @@ -16,6 +16,8 @@ #include +#include + #include #include @@ -26,49 +28,86 @@ namespace CGAL { namespace Optimal_bounding_box { namespace internal { +template +struct Vertex_with_fitness_value +{ + typedef typename Traits::FT FT; + typedef typename Traits::Matrix Matrix; + + Vertex_with_fitness_value() { CGAL_assertion_code(m_is_val_initialized = false;) } + Vertex_with_fitness_value(const Matrix m, const FT v) : m_mat(std::move(m)), m_val(v) + { + CGAL_assertion_code(m_is_val_initialized = true;) + } + + template + Vertex_with_fitness_value(const Matrix m, + const PointRange& points, + const Traits& traits) + : + m_mat(std::move(m)) + { + m_val = compute_fitness(m, points, traits); + CGAL_assertion_code(m_is_val_initialized = true;) + } + + const Matrix& matrix() const { return m_mat; } + FT fitness_value() const { CGAL_assertion(m_is_val_initialized); return m_val; } + +private: + Matrix m_mat; + FT m_val; + CGAL_assertion_code(bool m_is_val_initialized;) +}; + template class Population { public: typedef typename Traits::FT FT; typedef typename Traits::Matrix Matrix; - typedef Matrix Vertex; - typedef std::array Simplex; + typedef Vertex_with_fitness_value Vertex; + typedef std::array Simplex; typedef std::vector Simplex_container; -private: - Matrix create_vertex(CGAL::Random& rng) const - { - Matrix R; - - for(std::size_t i=0; i<3; ++i) - for(std::size_t j=0; j<3; ++j) - R.set(i, j, FT(rng.get_double())); - - return R; - } - - // create random population - Simplex create_simplex(CGAL::Random& rng) const - { - Simplex simplex; - for(std::size_t i=0; i<4; ++i) - simplex[i] = m_traits.get_Q(create_vertex(rng)); - - return simplex; - } - public: Population(const Traits& traits) : m_traits(traits) { } - void initialize(std::size_t population_size, +private: + Matrix create_random_matrix(CGAL::Random& rng) const + { + Matrix m; + + for(std::size_t i=0; i<3; ++i) + for(std::size_t j=0; j<3; ++j) + m.set(i, j, FT(rng.get_double())); + + return m; + } + + // create random population + template + Simplex create_simplex(const PointRange& points, + CGAL::Random& rng) const + { + Simplex s; + for(std::size_t i=0; i<4; ++i) + s[i] = Vertex(m_traits.get_Q(create_random_matrix(rng)), points, m_traits); + + return s; + } + +public: + template + void initialize(const std::size_t population_size, + const PointRange& points, CGAL::Random& rng) { m_pop.clear(); m_pop.reserve(population_size); for(std::size_t i=0; i m_pop; + const Traits& m_traits; }; -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG -template -void Population::show_population() -{ - std::size_t id = 0; - for(const Simplex& simplex : m_pop) - { - std::cout << "Simplex: " << id++ << std::endl; - for(const Matrix& R : simplex) - std::cout << R << "\n\n"; - std:: cout << std:: endl; - } -} -#endif - } // namespace internal } // namespace Optimal_bounding_box } // namespace CGAL diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 6745c3c5d72..824b0d3b746 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -113,7 +113,7 @@ void compute_best_transformation(const PointRange& points, timer.reset(); #endif - const Matrix& rot = search_solution.get_best(); + const Matrix& rot = search_solution.get_best().matrix(); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS std::cout << "get best: " << timer.time() << std::endl; diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp index b1a4587f3be..bf4acdb39de 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp @@ -147,7 +147,7 @@ void test_nelder_mead(const Traits& traits) simplex[3] = v3; std::size_t nm_iterations = 19; - CGAL::Optimal_bounding_box::internal::nelder_mead(points, nm_iterations, traits, simplex); + CGAL::Optimal_bounding_box::internal::nelder_mead(simplex, nm_iterations, points, traits); const Matrix& v0_new = simplex[0]; check_equality(v0_new(0,0), -0.288975); From e6229d3cb8e07a2601d52139c5b0c42a6272833e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 09:48:06 +0100 Subject: [PATCH 120/150] Fix including removed header This header was a fork from boost, but now all versions of boost that we support provide this header. --- Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp index 1e9ac373d86..af4c21caacf 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/STL_io_plugin.cpp @@ -11,14 +11,14 @@ #include #include -#include - #include #include #include #include #include +#include + #include #include #include @@ -90,7 +90,7 @@ load(QFileInfo fileinfo, bool& ok, bool add_to_scene){ SMesh* SM = new SMesh(); if (CGAL::Polygon_mesh_processing::is_polygon_soup_a_polygon_mesh(triangles)) { - auto pmap = CGAL::internal::boost_::make_function_property_map, Point_3>( + auto pmap = boost::make_function_property_map, Point_3>( [](const std::array& a) { return Point_3(a[0], a[1], a[2]); }); CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh(points, triangles, *SM, CGAL::parameters::point_map(pmap), From 9cfe4539959a3d8f69bd4a5c603b67cffde448cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 10:25:16 +0100 Subject: [PATCH 121/150] Tiny indentation fix --- BGL/include/CGAL/boost/graph/named_params_helper.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/named_params_helper.h b/BGL/include/CGAL/boost/graph/named_params_helper.h index 54c031a7c61..44dc4fece20 100644 --- a/BGL/include/CGAL/boost/graph/named_params_helper.h +++ b/BGL/include/CGAL/boost/graph/named_params_helper.h @@ -222,7 +222,7 @@ typename BGL::internal::GetInitializedIndexMap, \ Graph, NamedParameters>::const_type \ get_initialized_##DTYPE##_index_map(const Graph& g, \ - const NamedParameters& np) \ + const NamedParameters& np) \ { \ typedef BGL::internal::GetInitializedIndexMap, \ Graph, NamedParameters>::type \ get_initialized_##DTYPE##_index_map(Graph& g, \ - const NamedParameters& np) \ + const NamedParameters& np) \ { \ typedef BGL::internal::GetInitializedIndexMap Date: Tue, 24 Mar 2020 10:25:28 +0100 Subject: [PATCH 122/150] Remove unused variable --- .../include/CGAL/Optimal_bounding_box/internal/evolution.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index 13415729658..406e052a277 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -129,7 +129,6 @@ public: { // stopping criteria prameters FT prev_fit_value = 0; - FT new_fit_value = 0; const FT tolerance = 1e-9; int stale = 0; From f2303df4df82c1fa5421fd423ab088f2e7f11eb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 10:25:56 +0100 Subject: [PATCH 123/150] Misc minor changes --- .../Optimal_bounding_box/internal/evolution.h | 14 +++++++------- .../internal/fitness_function.h | 9 ++++----- .../internal/nelder_mead_functions.h | 12 ++++++------ .../internal/population.h | 2 +- .../oriented_bounding_box.h | 19 ++++++++++++------- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index 406e052a277..937d9dca4ce 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -65,8 +65,8 @@ public: const std::size_t first_group_size = m / 2; const std::size_t second_group_size = m - first_group_size; - std::vector group1(first_group_size), group2(first_group_size); - std::vector group3(second_group_size), group4(second_group_size); + std::vector group1{first_group_size}, group2{first_group_size}; + std::vector group3{second_group_size}, group4{second_group_size}; int im = static_cast(m); std::generate(group1.begin(), group1.end(), [&]{ return m_rng.get_int(0, im); }); @@ -84,7 +84,7 @@ public: Simplex offspring; for(int j=0; j<4; ++j) { - const FT r = FT(m_rng.get_double()); + const FT r{m_rng.get_double()}; const FT fitnessA = m_population[group1[i]][j].fitness_value(); const FT fitnessB = m_population[group2[i]][j].fitness_value(); const FT threshold = (fitnessA < fitnessB) ? (0.5 + bias) : (0.5 - bias); @@ -114,7 +114,7 @@ public: const Matrix& lm = m_population[group3[i]][j].matrix(); const Matrix& rm = m_population[group4[i]][j].matrix(); - offspring[j] = Vertex(m_traits.get_Q(lambda*lm + rambda*rm), m_points, m_traits); + offspring[j] = Vertex{m_traits.get_Q(lambda*lm + rambda*rm), m_points, m_traits}; } new_simplices[first_group_size + i] = std::move(offspring); @@ -135,7 +135,7 @@ public: for(std::size_t t=0; tfitness_value(); const FT difference = new_fit_value - prev_fit_value; #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG const Matrix& best_m = m_best_v->matrix(); - std::cout << "new best matrix: " << best_m << std::endl; + std::cout << "new best matrix: " << std::endl << best_m << std::endl; std::cout << "value difference with previous: " << difference << std::endl; #endif diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h index 9f324a95ced..20c0f8d6a20 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h @@ -38,8 +38,8 @@ compute_fitness(const typename Traits::Matrix& R, // rotation matrix CGAL_assertion(points.size() >= 3); FT xmin, ymin, zmin, xmax, ymax, zmax; - xmin = ymin = zmin = FT(std::numeric_limits::max()); - xmax = ymax = zmax = FT(std::numeric_limits::lowest()); + xmin = ymin = zmin = FT{std::numeric_limits::max()}; + xmax = ymax = zmax = FT{std::numeric_limits::lowest()}; for(const Point& pt : points) { @@ -61,9 +61,8 @@ compute_fitness(const typename Traits::Matrix& R, // rotation matrix return ((xmax - xmin) * (ymax - ymin) * (zmax - zmin)); } -template -const typename Population::Vertex& get_best_vertex(const Population& population, - const PointRange& points) +template +const typename Population::Vertex& get_best_vertex(const Population& population) { typedef typename Population::FT FT; typedef typename Population::Vertex Vertex; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h index 06dff8f9ab6..a672ab61369 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h @@ -50,7 +50,7 @@ Matrix mean(const Matrix& m1, { typedef typename Traits::FT FT; - constexpr half = FT(1) / FT(2); + constexpr FT half = FT(1) / FT(2); const Matrix reduction = half * (m1 + m2); return traits.get_Q(reduction); @@ -104,7 +104,7 @@ void nelder_mead(Simplex& simplex, if(refl_f >= simplex[0].fitness_value()) { // reflection - simplex[3] = Vertex(refl_m, refl_f); + simplex[3] = Vertex{refl_m, refl_f}; } else { @@ -112,9 +112,9 @@ void nelder_mead(Simplex& simplex, const Matrix expand_m = expansion(centroid_m, worst_m, refl_m); const FT expand_f = compute_fitness(expand_m, points, traits); if(expand_f < refl_f) - simplex[3] = Vertex(expand_m, expand_f); + simplex[3] = Vertex{expand_m, expand_f}; else - simplex[3] = Vertex(refl_m, refl_f); + simplex[3] = Vertex{refl_m, refl_f}; } } else // reflected vertex is worse @@ -125,13 +125,13 @@ void nelder_mead(Simplex& simplex, if(mean_f <= simplex[3].fitness_value()) { // contraction of worst - simplex[3] = Vertex(mean_m, mean_f); + simplex[3] = Vertex{mean_m, mean_f}; } else { // reduction: move all vertices towards the best for(std::size_t i=1; i<4; ++i) - simplex[i] = Vertex(mean(simplex[i].matrix(), simplex[0].matrix(), traits), points, traits); + simplex[i] = Vertex{mean(simplex[i].matrix(), simplex[0].matrix(), traits), points, traits}; } } } // nelder mead iterations diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h index 2171816e1b8..1b8a472eb72 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h @@ -93,7 +93,7 @@ private: { Simplex s; for(std::size_t i=0; i<4; ++i) - s[i] = Vertex(m_traits.get_Q(create_random_matrix(rng)), points, m_traits); + s[i] = Vertex{m_traits.get_Q(create_random_matrix(rng)), points, m_traits}; return s; } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 824b0d3b746..55e777543ea 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -98,6 +98,8 @@ void compute_best_transformation(const PointRange& points, typedef typename Traits::Matrix Matrix; typedef typename Traits::Aff_transformation_3 Aff_transformation_3; + CGAL_assertion(points.size() >= 3); + const std::size_t max_generations = 50; // @todo hidden NP #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS @@ -168,6 +170,11 @@ void construct_oriented_bounding_box(const PointRange& points, { std::vector ch_points; extreme_points_3(points, std::back_inserter(ch_points)); + +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG + std::cout << ch_points.size() << " points on the convex hull" << std::endl; +#endif + return construct_oriented_bounding_box(ch_points, output, rng, traits); } else @@ -176,8 +183,8 @@ void construct_oriented_bounding_box(const PointRange& points, } } -} // namespace Optimal_bounding_box } // namespace internal +} // namespace Optimal_bounding_box /// \addtogroup PkgOptimalBoundingBox_Oriented_bounding_box /// @@ -287,10 +294,9 @@ void oriented_bounding_box(const PointRange& points, CGAL::Random rng(seed); // @todo handle those cases instead - CGAL_assertion(points.size() >= 3); if(points.size() <= 3) { - std::cerr << "The oriented bounding box cannot YET be computed for a mesh with fewer than 4 vertices!\n"; + std::cerr << "The oriented bounding box cannot (yet) be computed for a mesh with fewer than 4 vertices!\n"; return; } @@ -364,11 +370,10 @@ void oriented_bounding_box(const PolygonMesh& pmesh, /// Convenience overloads ///////////////////////////////////////////////////////////////////////////////////////////////// -template -void oriented_bounding_box(const InputData& data, - OutputType& out) +template +void oriented_bounding_box(const Input& in, Output& out) { - return oriented_bounding_box(data, out, CGAL::parameters::all_default()); + return oriented_bounding_box(in, out, CGAL::parameters::all_default()); } /// \endcond From 25ac723c65adb86a366e02b93999f797d30e02c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 10:51:10 +0100 Subject: [PATCH 124/150] Don't recompute the weight every time --- .../CGAL/Optimal_bounding_box/internal/evolution.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index 937d9dca4ce..6c28188bbca 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -75,7 +75,7 @@ public: std::generate(group4.begin(), group4.end(), [&]{ return m_rng.get_int(0, im); }); // crossover I, pick A or B - FT bias = FT(0.1); + constexpr FT lweight = 0.4, uweight = 0.6; std::vector new_simplices(m); @@ -87,7 +87,7 @@ public: const FT r{m_rng.get_double()}; const FT fitnessA = m_population[group1[i]][j].fitness_value(); const FT fitnessB = m_population[group2[i]][j].fitness_value(); - const FT threshold = (fitnessA < fitnessB) ? (0.5 + bias) : (0.5 - bias); + const FT threshold = (fitnessA < fitnessB) ? uweight : lweight; if(r < threshold) offspring[j] = m_population[group1[i]][j]; @@ -99,8 +99,6 @@ public: } // crossover II, combine information from A and B - bias = 0.1; // @fixme should the bias change? What should be the initial value? - for(std::size_t i=0; i Date: Tue, 24 Mar 2020 10:51:27 +0100 Subject: [PATCH 125/150] Use a random seed by default (instead of a fixed seed of 0) --- .../include/CGAL/Optimal_bounding_box/oriented_bounding_box.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 55e777543ea..f8a31c5c78f 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -289,9 +289,9 @@ void oriented_bounding_box(const PointRange& points, PointMap point_map = choose_parameter(get_parameter(np, internal_np::point_map)); const bool use_ch = choose_parameter(get_parameter(np, internal_np::use_convex_hull), true); - const unsigned int seed = choose_parameter(get_parameter(np, internal_np::random_seed), 0); // undocumented + const unsigned int seed = choose_parameter(get_parameter(np, internal_np::random_seed), -1); // undocumented - CGAL::Random rng(seed); + CGAL::Random rng = (seed == unsigned(-1)) ? CGAL::get_default_random() : CGAL::Random(seed); // @todo handle those cases instead if(points.size() <= 3) From cdefac08212dabc45f30f59a2bb68673ecf85597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 11:24:28 +0100 Subject: [PATCH 126/150] Update OBB's Benchmarks/Examples/Tests/CMakeLists.txt --- .../benchmarks/Optimal_bounding_box/CMakeLists.txt | 5 +---- .../examples/Optimal_bounding_box/CMakeLists.txt | 8 ++++++-- .../test/Optimal_bounding_box/CMakeLists.txt | 11 +++++++---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt index 6405145d309..84cb0ab7dfc 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt @@ -19,10 +19,7 @@ find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) if (NOT EIGEN3_FOUND) message(STATUS "This project requires the Eigen library, and will not be compiled.") return() -else() - include(${EIGEN3_USE_FILE}) endif() create_single_source_cgal_program("bench_obb.cpp") -create_single_source_cgal_program("bench_perfomance.cpp") -create_single_source_cgal_program("bench_fitness_function.cpp") +CGAL_target_use_Eigen(bench_obb) diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt index 050b338544a..9a67221542e 100644 --- a/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt @@ -17,11 +17,15 @@ find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) if (NOT EIGEN3_FOUND) message(STATUS "This project requires the Eigen library, and will not be compiled.") return() -else() - include(${EIGEN3_USE_FILE}) endif() create_single_source_cgal_program("obb_example.cpp") create_single_source_cgal_program("obb_with_point_maps_example.cpp") create_single_source_cgal_program("rotated_aabb_tree_example.cpp") +foreach(target + obb_example + obb_with_point_maps_example + rotated_aabb_tree_example) + CGAL_target_use_Eigen(${target}) +endforeach() diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt index 79faf94bfad..c0ce4c74b4a 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt +++ b/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt @@ -17,12 +17,15 @@ find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) if (NOT EIGEN3_FOUND) message(STATUS "This project requires the Eigen library, and will not be compiled.") return() -else() - include(${EIGEN3_USE_FILE}) endif() -create_single_source_cgal_program("test_nelder_mead.cpp") create_single_source_cgal_program("test_OBB_traits.cpp") +create_single_source_cgal_program("test_nelder_mead.cpp") create_single_source_cgal_program("test_optimization_algorithms.cpp") - +foreach(target + test_OBB_traits + test_nelder_mead + test_optimization_algorithms) + CGAL_target_use_Eigen(${target}) +endforeach() From dc3c63e2fee81f363a16af59e0dd0e69e53d3b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 11:24:59 +0100 Subject: [PATCH 127/150] Fix bad list initialization --- .../include/CGAL/Optimal_bounding_box/internal/evolution.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index 6c28188bbca..179d7f5e6dd 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -65,8 +65,8 @@ public: const std::size_t first_group_size = m / 2; const std::size_t second_group_size = m - first_group_size; - std::vector group1{first_group_size}, group2{first_group_size}; - std::vector group3{second_group_size}, group4{second_group_size}; + std::vector group1(first_group_size), group2(first_group_size); + std::vector group3(second_group_size), group4(second_group_size); int im = static_cast(m); std::generate(group1.begin(), group1.end(), [&]{ return m_rng.get_int(0, im); }); From 64d23ad89a4c74780ff216e732172bcf4fe21f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 11:30:51 +0100 Subject: [PATCH 128/150] Example improvements --- .../Optimal_bounding_box/data/pig.off | 1361 +++++++++++++++++ .../Optimal_bounding_box/obb_example.cpp | 15 +- .../obb_with_point_maps_example.cpp | 4 +- .../rotated_aabb_tree_example.cpp | 4 +- 4 files changed, 1376 insertions(+), 8 deletions(-) create mode 100644 Optimal_bounding_box/examples/Optimal_bounding_box/data/pig.off diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/data/pig.off b/Optimal_bounding_box/examples/Optimal_bounding_box/data/pig.off new file mode 100644 index 00000000000..a6cd4ef4653 --- /dev/null +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/data/pig.off @@ -0,0 +1,1361 @@ +OFF +468 891 0 +0.063974 0.101970 -0.415827 +0.028523 0.114259 -0.442328 +0.063412 0.118087 -0.415381 +0.077614 0.162174 -0.435627 +0.128990 0.122892 -0.393541 +0.122864 -0.147913 0.401369 +0.178320 -0.063881 0.376630 +0.131227 -0.089511 0.441084 +0.164639 -0.008344 0.415245 +0.103820 -0.043044 -0.278399 +0.091834 -0.084101 -0.204746 +0.079859 -0.055424 -0.310790 +0.118637 -0.026027 -0.235186 +0.099707 0.153598 0.166104 +0.094930 0.196480 0.152483 +0.115864 0.191688 0.136248 +0.171734 0.181103 0.136002 +0.193585 0.183376 0.154622 +0.164526 0.109059 0.214381 +-0.153221 0.150924 -0.394866 +-0.081493 0.167834 -0.436769 +-0.072517 0.124239 -0.414300 +-0.161186 0.176848 -0.378966 +-0.176790 0.132941 -0.334836 +-0.171249 0.164538 -0.303896 +-0.080475 0.201851 -0.109296 +-0.071494 0.183497 -0.140195 +-0.097522 0.199020 -0.144832 +-0.056652 0.190914 -0.054368 +-0.039241 0.197263 -0.153247 +-0.141604 0.199711 -0.154047 +-0.129425 0.157767 -0.137661 +-0.165583 0.197728 -0.148208 +-0.190944 0.201695 -0.114791 +-0.184883 0.199199 -0.132786 +-0.178540 0.131594 -0.070966 +-0.153766 0.018107 -0.272151 +-0.130012 -0.023104 -0.280793 +-0.113295 -0.035252 -0.248969 +-0.199246 0.193683 0.195561 +-0.180750 0.123251 0.255085 +-0.181651 0.208804 0.233547 +-0.193764 0.183287 0.154611 +-0.183901 0.083655 0.279856 +-0.171726 0.068282 0.231479 +0.149160 0.094349 0.371830 +0.173037 0.085349 0.334114 +0.168678 0.151411 0.318997 +-0.168351 0.090355 0.342446 +-0.191982 0.004460 0.346603 +0.010306 -0.068937 0.495666 +-0.054048 -0.045698 0.495964 +-0.036648 -0.113382 0.498431 +0.049415 -0.137244 0.485860 +-0.135590 0.204770 -0.026654 +-0.164959 0.204458 -0.052698 +-0.119997 0.140111 0.025175 +0.172825 0.080263 -0.317843 +0.160628 0.062369 -0.340044 +0.177177 0.143953 -0.350070 +0.118606 0.021487 -0.375861 +0.165354 0.008939 -0.353730 +0.237839 0.022829 -0.306004 +0.212030 0.037710 -0.318516 +0.235958 0.004327 -0.346347 +0.269290 -0.012961 -0.323921 +0.177418 -0.011732 -0.301843 +0.134912 0.006718 -0.402388 +0.237840 -0.015554 -0.414292 +0.177088 -0.010878 -0.417488 +0.234583 -0.001111 -0.396570 +0.165512 -0.038754 -0.394103 +0.274848 -0.015963 -0.391667 +0.284810 -0.026997 -0.376984 +0.281300 -0.029101 -0.338206 +0.217331 -0.034592 -0.352687 +0.196409 -0.028130 -0.326693 +0.146613 0.129225 0.183979 +0.125633 0.114296 0.184366 +0.168417 0.063049 0.228672 +0.131279 0.094069 0.157481 +0.093427 0.144615 0.148946 +0.151538 0.030944 0.165340 +0.040532 0.197143 -0.154026 +0.056681 0.209038 -0.212225 +0.002775 0.206856 -0.166610 +0.117369 0.153354 -0.205966 +0.124488 0.200090 -0.152498 +0.086066 0.183902 -0.142107 +0.091309 0.198441 -0.138090 +0.064272 0.187025 -0.133132 +0.080301 0.201940 -0.109295 +0.087605 0.207177 -0.050256 +0.071100 0.186484 -0.043141 +0.144787 0.163143 -0.404482 +0.163037 0.176611 -0.376916 +0.093064 0.199241 -0.432443 +0.133133 0.208266 -0.382604 +0.143249 0.191538 -0.272444 +0.158095 0.192739 -0.314330 +-0.139488 0.186720 -0.261262 +-0.151500 0.199626 -0.324260 +-0.098372 0.223627 -0.288685 +-0.078536 0.189639 -0.197355 +-0.039805 0.227673 -0.260155 +0.097127 0.229527 -0.341482 +0.062369 0.228756 -0.395152 +0.036595 0.231173 -0.450000 +-0.028016 0.125004 -0.448876 +-0.036461 0.096667 -0.434533 +-0.083077 0.090894 -0.414311 +-0.082268 0.070800 -0.428081 +-0.123341 -0.003528 -0.217671 +-0.111649 -0.041351 -0.203434 +-0.143481 0.129458 -0.120457 +-0.166571 0.125111 -0.100292 +-0.091445 0.155603 -0.139780 +-0.108949 0.126603 -0.132705 +-0.155764 -0.002392 -0.117269 +-0.109909 -0.047484 -0.302472 +-0.091801 -0.053960 -0.282808 +-0.111273 -0.076464 -0.152548 +-0.089774 -0.101654 -0.175408 +-0.131191 -0.018764 -0.145092 +-0.117239 -0.118603 -0.106400 +-0.186719 -0.019496 0.218873 +0.094316 -0.206017 0.232131 +0.055117 -0.224837 0.203521 +0.079552 -0.189464 0.070678 +0.040403 -0.204104 0.063479 +0.071493 -0.170167 -0.083686 +-0.180726 -0.068980 0.362373 +-0.182633 -0.099623 0.308202 +-0.158938 -0.138266 0.334999 +0.085658 0.200413 0.176418 +0.065852 0.170004 0.177725 +-0.001292 0.195544 -0.033434 +-0.285400 -0.031989 -0.344981 +-0.271603 -0.015198 -0.325428 +-0.278372 -0.020235 -0.389284 +-0.206668 0.006555 -0.349794 +-0.225044 -0.007684 -0.420462 +-0.238803 0.004342 -0.347955 +-0.158634 0.013703 -0.350809 +-0.228727 0.004252 -0.318223 +-0.223154 0.035457 -0.308571 +-0.193549 0.057123 -0.317739 +-0.210450 -0.029622 -0.405169 +0.172645 -0.045708 -0.037575 +0.158143 -0.075581 -0.062747 +0.161129 -0.053779 -0.087832 +0.151586 -0.077141 0.017952 +0.172046 0.216581 0.250518 +0.160045 0.220693 0.263343 +0.199056 0.193772 0.195561 +0.181331 0.122923 0.257005 +0.183238 0.081029 0.279971 +0.186394 0.009376 0.360522 +0.200356 -0.009475 0.302375 +0.186432 0.204012 -0.088367 +0.166519 0.185025 -0.035652 +0.178625 0.148640 -0.039831 +0.162273 -0.038823 0.020282 +0.164324 0.000657 0.028308 +0.191989 -0.031903 0.230015 +0.188950 -0.072032 0.237843 +0.159438 -0.018081 0.152399 +0.179961 -0.012368 0.206350 +0.154184 -0.071463 0.150146 +0.157446 -0.054932 0.128257 +0.146606 -0.094660 0.103787 +-0.085574 0.204703 0.235486 +-0.100152 0.207801 0.255866 +-0.059913 0.174502 0.263217 +-0.177675 0.138122 0.302573 +-0.166640 0.138235 0.331535 +-0.160235 0.220604 0.263332 +0.065130 0.176233 0.262848 +0.085351 0.204781 0.235497 +0.062759 0.177657 0.222293 +0.099947 0.207890 0.255911 +0.029319 0.167713 0.235458 +-0.007308 0.176521 0.212726 +0.018184 0.155832 0.282328 +0.016196 0.134242 0.331153 +-0.115478 0.114685 0.373666 +-0.138087 0.098705 0.375545 +-0.107498 0.047438 0.447839 +-0.136533 0.029923 0.438192 +-0.151444 0.150957 0.333934 +-0.128669 0.172997 0.320075 +-0.141960 0.217696 0.269060 +-0.070700 0.154566 0.313918 +-0.089073 0.135316 0.352129 +0.113012 -0.180473 0.171463 +0.103166 -0.168475 0.072737 +0.137034 -0.171125 0.287599 +0.153718 -0.147893 0.232349 +0.149223 0.117836 -0.382727 +0.122958 0.086674 -0.404777 +0.070966 0.060503 -0.432879 +0.046513 0.085855 -0.431266 +0.092912 0.013673 -0.404533 +0.090952 -0.016720 -0.385023 +0.077405 -0.042537 -0.356280 +0.058093 -0.059147 -0.335116 +0.068427 -0.123215 -0.187213 +0.101335 -0.132006 -0.117248 +0.097814 -0.149292 -0.079001 +0.122020 -0.125228 -0.016951 +0.126097 -0.138388 0.097790 +0.126318 -0.145156 0.141802 +0.174282 -0.112276 0.330051 +0.190029 -0.084340 0.294626 +0.058942 -0.222818 0.301995 +0.098418 -0.193164 0.340401 +0.058809 -0.206985 0.375651 +0.021923 -0.222862 0.367343 +0.014505 -0.238117 0.299646 +0.122283 0.121443 0.075831 +0.113763 0.148142 0.020311 +0.140282 0.123337 0.018261 +0.027980 -0.177863 -0.119253 +0.026130 -0.193179 -0.070708 +-0.001321 -0.211350 0.079165 +-0.001523 -0.197311 -0.066313 +0.166925 0.094073 -0.266778 +0.163733 0.142170 -0.259072 +0.127467 0.088406 -0.181953 +0.150376 0.077937 0.039615 +0.190766 0.201784 -0.114791 +0.178517 0.136767 -0.071037 +0.184704 0.199288 -0.132775 +0.166379 0.133552 -0.102642 +0.165222 0.047122 -0.102044 +0.078264 0.226830 -0.278641 +0.019112 0.233265 -0.274429 +-0.039110 -0.233486 0.287357 +-0.021609 -0.223013 0.367699 +0.001943 -0.188166 0.439819 +-0.066652 -0.213379 0.338708 +0.027726 -0.233930 0.210941 +-0.000203 -0.237188 0.219039 +-0.136376 -0.172085 0.288837 +-0.099814 -0.201744 0.258297 +-0.027582 -0.234160 0.217991 +-0.060662 -0.218919 0.186226 +-0.055734 -0.201562 0.080354 +-0.029186 -0.209148 0.081362 +-0.029001 -0.192501 -0.071644 +-0.160342 0.063827 0.024713 +-0.177523 0.015890 -0.001911 +-0.162105 0.020607 0.040724 +-0.180080 0.125890 -0.032858 +-0.185297 0.023823 -0.038772 +-0.175803 -0.030161 -0.021666 +-0.149501 -0.083919 0.026313 +-0.160461 -0.041091 0.033786 +-0.156993 -0.049877 0.148952 +-0.179046 0.029177 -0.073993 +-0.177954 -0.024883 -0.058372 +-0.151976 0.126423 -0.229667 +-0.163106 0.092405 -0.253555 +-0.121432 0.099265 -0.173188 +-0.111794 0.137703 -0.178117 +-0.166077 0.091402 -0.340017 +-0.161312 0.070001 -0.345025 +-0.167665 0.059706 -0.282855 +-0.171035 0.078014 -0.296062 +-0.126978 0.030384 -0.171087 +-0.129126 0.050437 -0.192177 +-0.131368 0.059086 -0.126361 +-0.134950 0.025663 -0.131342 +-0.143437 -0.069595 -0.109286 +-0.148269 -0.039929 -0.120515 +-0.163978 -0.065334 -0.065543 +-0.167235 -0.061629 -0.042774 +0.002745 0.189510 0.110554 +0.036689 0.188942 0.019665 +-0.036527 0.174422 0.177147 +-0.087796 0.207088 -0.050265 +-0.076524 0.172540 0.006138 +-0.087508 0.177933 -0.017043 +-0.108099 0.206330 -0.029115 +-0.072629 0.172458 0.181190 +-0.090040 0.162292 0.168261 +-0.089665 0.198396 0.161152 +-0.063826 0.178856 0.211964 +-0.149794 0.182785 0.130788 +-0.116064 0.191599 0.136236 +-0.150418 0.160583 0.151346 +-0.171912 0.181013 0.135924 +-0.138972 0.123679 0.183787 +-0.105455 0.169777 0.154956 +-0.106937 0.141313 0.167043 +-0.064997 0.162208 0.148704 +-0.089200 0.146757 0.141467 +-0.116460 0.121274 0.141967 +0.130312 0.041995 0.435860 +0.129704 -0.002210 0.453987 +0.119563 0.095019 0.389830 +0.106258 -0.067817 0.474757 +0.072458 -0.092968 0.490348 +0.035744 -0.100524 0.501598 +0.090915 -0.018706 0.481902 +0.063954 -0.018620 0.488394 +0.012687 0.019863 0.473158 +-0.066639 0.014188 0.477250 +-0.001853 -0.014358 0.486138 +-0.073991 0.051995 0.453618 +0.015992 0.056915 0.445325 +-0.072272 0.083609 0.419400 +0.125713 0.148591 0.340006 +0.151075 0.147959 0.335541 +0.120626 0.212102 0.266920 +0.069491 0.149561 0.322080 +0.091434 0.136280 0.349720 +0.076196 0.038920 0.461948 +0.080702 0.078897 0.423801 +0.006477 0.083890 0.414722 +0.003928 0.102802 0.385224 +-0.068084 0.039517 -0.430070 +-0.017676 0.023776 -0.427482 +0.193970 0.042648 -0.293997 +0.172856 0.064667 -0.285834 +0.158578 0.030796 -0.272331 +0.140866 -0.005417 -0.270488 +0.134432 0.029296 -0.214306 +0.126251 0.015555 -0.188439 +0.132124 0.003792 -0.136979 +0.125810 -0.029504 -0.153529 +0.129423 0.061526 -0.128092 +0.108063 0.127431 -0.132395 +0.091794 0.155522 -0.139751 +0.124048 0.145248 -0.131126 +0.184444 0.016147 -0.030529 +0.181489 -0.003989 -0.053023 +0.141425 0.199800 -0.154047 +0.165405 0.197817 -0.148141 +0.144876 0.183940 -0.146208 +0.154368 0.144703 -0.122262 +0.146068 0.119123 -0.117735 +0.154841 -0.033503 -0.111889 +0.143738 -0.032315 -0.128787 +0.113871 -0.078221 -0.157136 +0.112005 -0.054404 -0.183556 +0.010090 -0.146944 0.487883 +0.011570 -0.146473 0.485554 +0.010090 -0.136782 0.493756 +-0.015165 -0.128494 0.494118 +-0.010143 -0.136180 0.492642 +-0.030104 -0.153530 0.480762 +-0.010143 -0.146454 0.487048 +-0.006480 -0.157970 0.476349 +0.045456 -0.167686 0.453108 +0.029848 -0.154023 0.480267 +0.030579 -0.132753 -0.220866 +0.021176 -0.090002 -0.310105 +0.181147 0.115479 -0.036001 +0.175183 0.070269 -0.003253 +0.161619 0.042238 0.028286 +0.156945 0.037056 0.086395 +0.051155 0.182427 -0.491632 +0.031566 0.180896 -0.501667 +0.002176 0.193366 -0.489790 +-0.037122 0.180476 -0.500027 +-0.025020 0.194670 -0.492815 +0.055556 0.214167 -0.473439 +0.066526 0.214610 -0.467774 +-0.082413 0.208049 -0.429210 +-0.065055 0.215687 -0.469354 +-0.062206 0.204472 -0.479930 +-0.036973 0.231911 -0.450571 +-0.036983 0.226530 -0.458574 +-0.125722 0.187261 -0.415111 +-0.091376 0.197028 -0.433439 +-0.109535 0.220672 -0.374442 +-0.132871 0.206436 -0.383456 +-0.068993 0.234380 -0.324450 +-0.054731 0.231939 -0.379365 +-0.015007 0.238836 -0.387236 +0.010198 0.238083 -0.347126 +-0.171832 0.010661 0.394832 +-0.164229 -0.033313 0.411342 +-0.071226 -0.093884 0.490608 +-0.099723 -0.021444 0.479401 +-0.106460 -0.079934 0.470702 +-0.126287 -0.023902 0.459235 +-0.151985 -0.067142 0.420950 +-0.147699 -0.107939 0.402674 +-0.109438 -0.119557 0.446423 +-0.020037 -0.195034 0.426407 +-0.045003 -0.203863 0.398142 +-0.079909 -0.190588 0.383979 +-0.073176 -0.153947 0.447608 +-0.060832 -0.134709 0.479062 +-0.132591 -0.160951 0.350157 +-0.119567 -0.148332 0.402715 +-0.065793 -0.128601 -0.175205 +-0.097272 -0.145676 -0.099799 +-0.002565 -0.181714 -0.122217 +-0.024515 -0.179484 -0.119506 +-0.064586 -0.176266 -0.074826 +-0.059683 -0.167369 -0.114486 +-0.099658 -0.163716 0.022325 +-0.040368 -0.148020 -0.173886 +-0.152092 0.033745 0.173508 +-0.159192 -0.012910 0.157435 +-0.186610 0.203923 -0.088370 +-0.183267 0.184340 -0.063974 +-0.136575 0.103373 0.069442 +-0.143137 0.116556 0.022602 +-0.200449 -0.005081 0.293234 +-0.198541 -0.044298 0.289997 +-0.176233 -0.086749 0.211940 +-0.129605 -0.146690 0.159205 +-0.172832 -0.114168 0.232984 +-0.146311 -0.094428 0.150409 +-0.147372 -0.095199 0.103658 +-0.110455 -0.178169 0.151965 +-0.128236 -0.127687 0.039765 +-0.128792 -0.120162 -0.025065 +0.064160 0.162938 0.145558 +0.035172 0.172321 0.185202 +-0.006127 0.202885 -0.099910 +-0.034296 0.191647 -0.029673 +-0.131196 0.116627 -0.390365 +-0.142598 0.108734 -0.385698 +-0.118388 0.084666 -0.406795 +-0.122705 0.099621 -0.397329 +-0.118280 0.017285 -0.383763 +-0.138200 0.021970 -0.357392 +-0.083219 -0.042897 -0.356408 +-0.171574 -0.015949 -0.418570 +-0.079870 -0.020831 -0.382774 +-0.146033 -0.002291 -0.413268 +-0.099733 0.026973 -0.404345 +-0.098251 0.013991 -0.401317 +0.044369 -0.016396 -0.405838 +0.042389 0.006708 -0.423304 +-0.042891 -0.004873 -0.416215 +-0.012107 -0.020909 -0.408756 +-0.205436 -0.024781 -0.328409 +-0.223220 -0.034022 -0.353666 +-0.149992 -0.036689 -0.391942 +-0.164885 -0.044415 -0.367829 +-0.091425 -0.051851 -0.329759 +-0.067188 -0.061962 -0.316028 +0.032718 -0.045780 -0.374356 +0.001142 -0.045018 -0.382344 +-0.008169 -0.088329 -0.317598 +-0.061474 -0.052657 -0.346404 +-0.036931 -0.052082 -0.363104 +-0.163689 -0.139768 0.263934 +-0.134461 -0.171429 0.220297 +-0.093110 -0.202067 0.185697 +-0.083335 -0.193614 0.109481 +-0.161181 0.096630 0.214117 +-0.169578 0.129140 0.197122 +-0.136316 0.091909 0.186973 +-0.137551 0.081713 0.154719 +0.129236 0.172656 -0.007278 +0.135409 0.204859 -0.026639 +0.107912 0.206419 -0.029102 +0.080873 0.173368 -0.015229 +0.100091 0.179921 -0.016858 +-0.000035 -0.119696 -0.260509 +-0.020383 -0.117167 -0.258779 +3 0 1 2 +3 2 3 4 +3 1 3 2 +3 5 6 7 +3 6 8 7 +3 9 10 11 +3 9 12 10 +3 13 14 15 +3 15 16 13 +3 17 18 16 +3 19 20 21 +3 22 23 24 +3 23 22 19 +3 25 26 27 +3 28 29 26 +3 30 31 32 +3 27 26 30 +3 30 26 31 +3 33 34 35 +3 36 37 38 +3 39 40 41 +3 42 40 39 +3 43 40 44 +3 45 46 47 +3 48 43 49 +3 50 51 52 +3 5 7 53 +3 54 55 56 +3 57 58 59 +3 60 58 61 +3 62 63 57 +3 63 64 61 +3 63 61 58 +3 63 58 57 +3 65 64 63 +3 65 63 62 +3 66 65 62 +3 61 67 60 +3 68 69 70 +3 71 69 68 +3 69 67 70 +3 70 67 61 +3 61 64 70 +3 72 73 68 +3 72 68 70 +3 72 70 64 +3 72 65 73 +3 72 64 65 +3 73 65 74 +3 68 73 71 +3 75 74 76 +3 74 65 76 +3 76 65 66 +3 76 66 9 +3 75 76 11 +3 76 9 11 +3 75 11 71 +3 71 73 75 +3 73 74 75 +3 77 16 18 +3 78 77 18 +3 78 18 79 +3 78 80 81 +3 78 13 77 +3 16 77 13 +3 13 78 81 +3 78 82 80 +3 82 78 79 +3 83 84 85 +3 83 86 84 +3 85 29 28 +3 87 88 89 +3 89 88 90 +3 91 89 90 +3 92 91 93 +3 90 93 91 +3 94 95 59 +3 95 94 96 +3 95 96 97 +3 3 96 94 +3 86 98 84 +3 59 95 99 +3 99 95 97 +3 100 101 24 +3 101 22 24 +3 101 100 102 +3 103 102 100 +3 102 103 104 +3 103 29 104 +3 104 29 85 +3 99 105 98 +3 105 97 106 +3 99 97 105 +3 96 106 97 +3 106 96 107 +3 21 108 109 +3 21 20 108 +3 110 21 109 +3 110 109 111 +3 112 38 113 +3 112 36 38 +3 114 115 32 +3 114 32 31 +3 115 35 34 +3 34 32 115 +3 116 117 114 +3 116 114 31 +3 31 26 116 +3 29 116 26 +3 116 29 103 +3 114 118 115 +3 117 118 114 +3 119 120 37 +3 38 37 120 +3 121 113 122 +3 38 122 113 +3 38 120 122 +3 123 113 121 +3 122 124 121 +3 44 125 43 +3 126 127 128 +3 128 129 130 +3 129 128 127 +3 131 132 133 +3 134 14 135 +3 135 14 13 +3 13 81 135 +3 136 90 83 +3 137 138 139 +3 140 141 142 +3 139 142 141 +3 139 138 142 +3 140 143 141 +3 144 36 145 +3 138 144 145 +3 143 145 146 +3 143 140 145 +3 140 142 145 +3 138 145 142 +3 36 144 37 +3 147 137 139 +3 141 147 139 +3 148 149 150 +3 151 149 148 +3 152 153 47 +3 154 152 47 +3 47 46 154 +3 18 155 156 +3 79 18 156 +3 18 17 155 +3 154 155 17 +3 156 155 46 +3 154 46 155 +3 157 6 158 +3 156 157 158 +3 46 157 156 +3 157 46 45 +3 157 45 8 +3 8 6 157 +3 159 160 161 +3 162 148 163 +3 151 148 162 +3 164 156 158 +3 164 158 165 +3 166 82 167 +3 167 79 164 +3 79 156 164 +3 82 79 167 +3 168 169 166 +3 168 170 169 +3 167 168 166 +3 164 168 167 +3 164 165 168 +3 170 151 169 +3 162 169 151 +3 163 169 162 +3 163 166 169 +3 171 172 173 +3 41 174 175 +3 40 174 41 +3 40 43 174 +3 175 174 48 +3 48 174 43 +3 41 175 176 +3 177 178 179 +3 177 180 178 +3 134 179 178 +3 134 135 179 +3 181 182 183 +3 179 181 183 +3 183 182 173 +3 183 184 177 +3 177 179 183 +3 179 135 181 +3 185 186 187 +3 48 186 175 +3 188 186 48 +3 188 187 186 +3 176 189 190 +3 190 189 185 +3 176 175 189 +3 189 175 186 +3 186 185 189 +3 191 176 190 +3 192 193 184 +3 192 184 183 +3 173 192 183 +3 192 173 172 +3 193 192 191 +3 192 172 191 +3 191 190 193 +3 190 185 193 +3 194 128 195 +3 128 130 195 +3 196 194 197 +3 196 126 194 +3 126 128 194 +3 198 199 0 +3 4 198 0 +3 198 4 3 +3 198 3 94 +3 94 59 198 +3 58 198 59 +3 198 58 199 +3 60 199 58 +3 200 201 199 +3 109 108 201 +3 201 108 1 +3 201 1 0 +3 199 201 0 +3 202 67 203 +3 199 202 200 +3 202 199 60 +3 67 202 60 +3 67 69 203 +3 71 203 69 +3 203 204 202 +3 71 204 203 +3 205 204 11 +3 11 10 205 +3 204 71 11 +3 130 206 207 +3 10 207 206 +3 206 205 10 +3 207 150 149 +3 195 208 209 +3 151 170 209 +3 195 130 208 +3 208 130 207 +3 149 209 208 +3 149 151 209 +3 208 207 149 +3 209 210 195 +3 170 210 209 +3 210 168 211 +3 210 170 168 +3 168 165 211 +3 197 211 165 +3 195 210 211 +3 194 211 197 +3 194 195 211 +3 212 197 213 +3 213 197 165 +3 213 165 158 +3 213 6 212 +3 213 158 6 +3 5 212 6 +3 5 196 212 +3 212 196 197 +3 214 215 216 +3 215 126 196 +3 5 215 196 +3 5 216 215 +3 216 217 214 +3 218 214 217 +3 214 218 127 +3 215 214 126 +3 127 126 214 +3 219 220 81 +3 80 219 81 +3 220 219 221 +3 221 161 160 +3 222 130 223 +3 223 130 129 +3 129 224 223 +3 223 225 222 +3 225 223 224 +3 226 227 228 +3 226 59 227 +3 226 57 59 +3 59 99 227 +3 227 99 98 +3 227 98 86 +3 228 227 86 +3 161 221 229 +3 221 219 229 +3 229 219 80 +3 161 230 159 +3 230 161 231 +3 232 230 233 +3 233 231 234 +3 230 231 233 +3 235 105 236 +3 98 105 235 +3 104 85 236 +3 235 236 84 +3 235 84 98 +3 84 236 85 +3 237 218 238 +3 217 238 218 +3 217 239 238 +3 237 238 240 +3 224 241 242 +3 129 241 224 +3 127 241 129 +3 242 241 218 +3 241 127 218 +3 218 237 242 +3 240 243 244 +3 240 244 237 +3 242 245 224 +3 246 245 237 +3 237 244 246 +3 245 242 237 +3 247 248 246 +3 248 247 249 +3 248 249 225 +3 224 248 225 +3 245 248 224 +3 245 246 248 +3 250 251 252 +3 253 251 250 +3 251 254 255 +3 254 251 253 +3 253 35 254 +3 256 257 255 +3 257 258 252 +3 252 251 257 +3 255 257 251 +3 259 118 260 +3 35 259 254 +3 35 115 259 +3 118 259 115 +3 254 259 260 +3 260 255 254 +3 261 24 262 +3 261 100 24 +3 24 23 262 +3 263 264 261 +3 264 263 117 +3 117 116 264 +3 116 103 264 +3 264 103 100 +3 261 264 100 +3 265 266 146 +3 23 19 265 +3 267 268 146 +3 267 262 268 +3 268 262 23 +3 268 23 265 +3 146 268 265 +3 145 267 146 +3 145 36 267 +3 267 36 112 +3 269 263 270 +3 270 112 269 +3 270 263 261 +3 270 261 262 +3 267 270 262 +3 270 267 112 +3 112 113 269 +3 123 269 113 +3 271 272 118 +3 123 272 269 +3 117 271 118 +3 272 271 263 +3 272 263 269 +3 263 271 117 +3 121 273 274 +3 124 273 121 +3 274 260 118 +3 272 274 118 +3 272 123 274 +3 274 123 121 +3 275 276 260 +3 276 256 255 +3 276 255 260 +3 275 260 274 +3 275 274 273 +3 275 273 124 +3 136 277 278 +3 277 136 279 +3 277 279 182 +3 93 90 278 +3 278 90 136 +3 28 26 280 +3 25 280 26 +3 281 282 56 +3 281 28 282 +3 280 282 28 +3 283 282 280 +3 283 54 282 +3 56 282 54 +3 284 285 286 +3 284 286 287 +3 171 287 286 +3 171 173 287 +3 182 287 173 +3 279 284 287 +3 279 287 182 +3 288 289 290 +3 288 290 291 +3 290 292 291 +3 293 294 290 +3 292 290 294 +3 289 293 290 +3 289 286 293 +3 293 285 294 +3 286 285 293 +3 295 281 296 +3 284 279 295 +3 56 296 281 +3 56 297 296 +3 297 294 296 +3 295 296 285 +3 284 295 285 +3 285 296 294 +3 298 299 8 +3 8 45 298 +3 45 300 298 +3 7 8 301 +3 299 301 8 +3 53 301 302 +3 301 53 7 +3 303 53 302 +3 301 304 302 +3 299 304 301 +3 298 304 299 +3 304 305 303 +3 304 303 302 +3 303 305 50 +3 306 307 308 +3 305 306 308 +3 51 308 307 +3 50 308 51 +3 308 50 305 +3 309 307 306 +3 310 309 306 +3 193 185 311 +3 311 187 309 +3 309 187 307 +3 185 187 311 +3 153 312 313 +3 313 47 153 +3 153 314 312 +3 313 312 45 +3 45 47 313 +3 300 45 312 +3 315 180 177 +3 315 177 184 +3 300 312 316 +3 316 314 315 +3 314 180 315 +3 314 316 312 +3 317 318 310 +3 310 306 317 +3 305 317 306 +3 305 304 317 +3 298 317 304 +3 317 298 318 +3 298 300 318 +3 318 300 316 +3 319 320 311 +3 315 184 320 +3 320 184 193 +3 193 311 320 +3 319 311 309 +3 310 319 309 +3 318 319 310 +3 320 319 316 +3 316 315 320 +3 318 316 319 +3 321 111 322 +3 109 322 111 +3 201 322 109 +3 201 200 322 +3 62 323 66 +3 57 324 323 +3 62 57 323 +3 324 57 226 +3 66 325 326 +3 9 326 12 +3 66 326 9 +3 323 325 66 +3 323 324 325 +3 324 226 325 +3 327 228 328 +3 328 12 327 +3 12 326 327 +3 326 325 327 +3 226 327 325 +3 226 228 327 +3 329 330 328 +3 329 328 228 +3 331 329 228 +3 331 228 332 +3 333 332 86 +3 332 228 86 +3 333 86 83 +3 83 90 333 +3 90 88 333 +3 333 88 334 +3 335 148 336 +3 335 163 148 +3 148 150 336 +3 336 231 335 +3 336 234 231 +3 337 338 339 +3 88 339 334 +3 337 339 87 +3 87 339 88 +3 340 341 334 +3 339 340 334 +3 340 339 338 +3 340 338 232 +3 233 340 232 +3 233 341 340 +3 233 234 341 +3 341 332 333 +3 341 333 334 +3 234 336 342 +3 343 342 150 +3 336 150 342 +3 331 343 329 +3 331 332 343 +3 332 341 343 +3 342 343 234 +3 343 330 329 +3 343 341 234 +3 330 344 345 +3 328 345 12 +3 328 330 345 +3 330 343 344 +3 344 343 150 +3 344 150 207 +3 345 344 10 +3 12 345 10 +3 207 10 344 +3 346 347 348 +3 303 347 53 +3 347 303 348 +3 349 350 303 +3 348 303 350 +3 50 349 303 +3 50 52 349 +3 52 351 349 +3 352 349 353 +3 352 350 349 +3 349 351 353 +3 351 239 353 +3 346 352 353 +3 353 347 346 +3 354 53 355 +3 354 355 239 +3 347 355 53 +3 347 353 355 +3 355 353 239 +3 354 239 217 +3 216 354 217 +3 5 354 216 +3 5 53 354 +3 205 356 357 +3 356 205 206 +3 356 206 130 +3 222 356 130 +3 335 231 358 +3 161 358 231 +3 358 161 359 +3 359 161 229 +3 335 358 359 +3 335 359 163 +3 360 361 163 +3 359 360 163 +3 360 229 361 +3 359 229 360 +3 80 361 229 +3 361 80 82 +3 361 82 166 +3 163 361 166 +3 3 362 96 +3 362 1 363 +3 1 362 3 +3 364 363 365 +3 363 1 365 +3 1 108 365 +3 364 365 366 +3 20 365 108 +3 367 107 368 +3 96 368 107 +3 368 96 362 +3 363 367 368 +3 364 367 363 +3 362 363 368 +3 369 370 371 +3 371 366 365 +3 365 20 371 +3 372 373 370 +3 107 373 372 +3 369 372 370 +3 107 367 373 +3 373 367 364 +3 364 366 373 +3 366 371 373 +3 371 370 373 +3 20 374 375 +3 375 369 371 +3 375 371 20 +3 19 374 20 +3 374 19 22 +3 376 369 377 +3 369 375 377 +3 377 101 376 +3 377 375 374 +3 374 22 377 +3 101 377 22 +3 101 102 376 +3 378 379 376 +3 369 379 372 +3 376 379 369 +3 376 102 378 +3 102 104 378 +3 380 378 381 +3 379 380 372 +3 379 378 380 +3 378 104 381 +3 236 381 104 +3 105 381 236 +3 105 106 381 +3 381 107 380 +3 380 107 372 +3 381 106 107 +3 382 383 188 +3 383 382 131 +3 188 48 382 +3 48 49 382 +3 49 131 382 +3 384 52 51 +3 384 51 385 +3 307 385 51 +3 386 385 387 +3 387 385 188 +3 386 384 385 +3 187 385 307 +3 187 188 385 +3 387 188 383 +3 388 131 389 +3 131 133 389 +3 389 390 388 +3 388 390 386 +3 386 387 388 +3 387 383 388 +3 388 383 131 +3 238 391 392 +3 392 393 240 +3 240 238 392 +3 239 391 238 +3 351 392 391 +3 391 239 351 +3 392 394 393 +3 351 395 394 +3 392 351 394 +3 52 395 351 +3 384 395 52 +3 395 384 386 +3 395 390 394 +3 395 386 390 +3 396 393 397 +3 393 394 397 +3 390 397 394 +3 389 397 390 +3 396 397 133 +3 389 133 397 +3 243 396 133 +3 243 240 396 +3 240 393 396 +3 124 398 399 +3 124 122 398 +3 122 120 398 +3 400 356 222 +3 400 222 225 +3 249 401 400 +3 225 249 400 +3 402 399 403 +3 399 402 404 +3 398 403 399 +3 398 405 403 +3 405 401 403 +3 249 402 403 +3 247 402 249 +3 403 401 249 +3 406 252 407 +3 407 252 258 +3 407 258 125 +3 406 407 44 +3 125 44 407 +3 408 33 409 +3 408 409 55 +3 33 35 409 +3 409 35 253 +3 250 410 411 +3 250 252 410 +3 411 410 56 +3 56 410 297 +3 411 56 55 +3 411 55 409 +3 253 411 409 +3 411 253 250 +3 412 125 413 +3 412 413 49 +3 413 132 131 +3 413 131 49 +3 412 49 43 +3 412 43 125 +3 414 415 416 +3 414 125 258 +3 416 413 414 +3 414 413 125 +3 416 132 413 +3 415 417 418 +3 414 417 415 +3 418 417 258 +3 414 258 417 +3 418 258 257 +3 256 418 257 +3 404 419 420 +3 415 420 419 +3 418 420 415 +3 418 256 420 +3 404 420 421 +3 420 256 421 +3 421 256 276 +3 275 421 276 +3 124 421 275 +3 124 399 421 +3 404 421 399 +3 422 135 81 +3 81 220 422 +3 422 278 423 +3 423 278 277 +3 277 182 423 +3 182 181 423 +3 135 422 423 +3 423 181 135 +3 136 424 425 +3 281 295 425 +3 295 279 425 +3 425 279 136 +3 424 136 83 +3 424 83 85 +3 425 424 28 +3 28 281 425 +3 424 85 28 +3 426 19 21 +3 265 427 266 +3 265 19 427 +3 19 426 427 +3 428 266 427 +3 429 428 427 +3 426 429 427 +3 429 110 428 +3 110 111 428 +3 430 143 431 +3 146 431 143 +3 266 431 146 +3 141 143 430 +3 432 433 434 +3 141 435 433 +3 141 430 435 +3 141 433 147 +3 431 436 430 +3 431 266 436 +3 266 428 436 +3 111 436 428 +3 436 111 321 +3 430 436 437 +3 436 321 437 +3 434 433 437 +3 435 437 433 +3 435 430 437 +3 438 439 202 +3 202 204 438 +3 322 200 439 +3 439 200 202 +3 437 440 434 +3 437 321 440 +3 322 440 321 +3 441 440 439 +3 441 439 438 +3 322 439 440 +3 442 144 443 +3 443 119 442 +3 138 443 144 +3 137 443 138 +3 147 443 137 +3 119 37 442 +3 37 144 442 +3 444 432 445 +3 147 444 445 +3 444 147 433 +3 432 444 433 +3 147 445 443 +3 446 447 119 +3 119 443 446 +3 445 446 443 +3 432 446 445 +3 398 447 405 +3 120 447 398 +3 120 119 447 +3 438 448 449 +3 449 448 357 +3 448 438 204 +3 448 204 205 +3 357 448 205 +3 450 449 357 +3 449 441 438 +3 451 405 447 +3 451 447 446 +3 432 451 446 +3 451 434 452 +3 451 432 434 +3 452 434 440 +3 441 452 440 +3 449 452 441 +3 451 452 450 +3 449 450 452 +3 133 453 243 +3 133 132 453 +3 416 454 453 +3 416 453 132 +3 416 415 454 +3 419 454 415 +3 243 453 454 +3 454 244 243 +3 455 456 247 +3 246 455 247 +3 244 455 246 +3 244 454 455 +3 455 419 456 +3 419 455 454 +3 404 456 419 +3 402 456 404 +3 402 247 456 +3 292 457 458 +3 458 457 40 +3 457 44 40 +3 458 40 42 +3 291 458 42 +3 292 458 291 +3 44 457 459 +3 459 457 292 +3 294 459 292 +3 460 406 459 +3 459 297 460 +3 459 406 44 +3 459 294 297 +3 297 410 460 +3 410 252 460 +3 406 460 252 +3 461 160 462 +3 462 463 461 +3 220 221 461 +3 221 160 461 +3 159 462 160 +3 422 464 278 +3 464 220 465 +3 464 422 220 +3 461 465 220 +3 463 465 461 +3 463 92 465 +3 464 465 93 +3 464 93 278 +3 93 465 92 +3 466 357 356 +3 400 466 356 +3 466 400 467 +3 400 401 467 +3 467 401 405 +3 405 451 467 +3 466 467 450 +3 466 450 357 +3 450 467 451 diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp index 0fb233f26ae..e814d7e9d7c 100644 --- a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_example.cpp @@ -4,11 +4,16 @@ #include #include +#include +#include + #include #include #include +namespace PMP = CGAL::Polygon_mesh_processing; + typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point; @@ -16,11 +21,11 @@ typedef CGAL::Surface_mesh Surface_mesh; int main(int argc, char** argv) { - std::ifstream input(argv[1]); + std::ifstream input((argc > 1) ? argv[1] : "data/pig.off"); Surface_mesh sm; - if (!input || !(input >> sm) || sm.is_empty()) + if(!input || !(input >> sm) || sm.is_empty()) { - std::cerr << argv[1] << " is not a valid off file.\n"; + std::cerr << "Invalid input file." << std::endl; return EXIT_FAILURE; } @@ -38,8 +43,10 @@ int main(int argc, char** argv) Surface_mesh obb_sm; CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], obb_points[4], obb_points[5], obb_points[6], obb_points[7], obb_sm); - std::ofstream("obb.off") << obb_sm; + PMP::triangulate_faces(obb_sm); + std::cout << "Volume: " << PMP::volume(obb_sm) << std::endl; + return EXIT_SUCCESS; } diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_with_point_maps_example.cpp b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_with_point_maps_example.cpp index 672cab6d210..9129aef472d 100644 --- a/Optimal_bounding_box/examples/Optimal_bounding_box/obb_with_point_maps_example.cpp +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/obb_with_point_maps_example.cpp @@ -20,11 +20,11 @@ namespace CP = CGAL::parameters; int main(int argc, char** argv) { - std::ifstream input(argv[1]); + std::ifstream input((argc > 1) ? argv[1] : "data/pig.off"); Surface_mesh sm; if (!input || !(input >> sm) || sm.is_empty()) { - std::cerr << argv[1] << " is not a valid off file.\n"; + std::cerr << "Invalid input file." << std::endl; return EXIT_FAILURE; } diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree_example.cpp b/Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree_example.cpp index 18bc7fdc714..b280efad0c4 100644 --- a/Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree_example.cpp +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/rotated_aabb_tree_example.cpp @@ -34,11 +34,11 @@ private: int main(int argc, char** argv) { - std::ifstream input(argv[1]); + std::ifstream input((argc > 1) ? argv[1] : "data/pig.off"); Surface_mesh sm; if (!input || !(input >> sm) || sm.is_empty()) { - std::cerr << argv[1] << " is not a valid off file.\n"; + std::cerr << "Invalid input file." << std::endl; return EXIT_FAILURE; } From 5a7204decbaa7e3d65a3ca9089bf5f09cfa9cc95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 11:35:09 +0100 Subject: [PATCH 129/150] Use a random seed by default (and not rng(0)) --- .../CGAL/Optimal_bounding_box/oriented_bounding_box.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index f8a31c5c78f..1d31b6012e7 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -291,7 +291,12 @@ void oriented_bounding_box(const PointRange& points, const bool use_ch = choose_parameter(get_parameter(np, internal_np::use_convex_hull), true); const unsigned int seed = choose_parameter(get_parameter(np, internal_np::random_seed), -1); // undocumented - CGAL::Random rng = (seed == unsigned(-1)) ? CGAL::get_default_random() : CGAL::Random(seed); + CGAL::Random fixed_seed_rng(seed); + CGAL::Random& rng = (seed == unsigned(-1)) ? CGAL::get_default_random() : fixed_seed_rng; + +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG + std::cout << "Random seed: " << rng.get_seed() << std::endl; +#endif // @todo handle those cases instead if(points.size() <= 3) From 6f90060e7d00b4487a353d94e45b7c7f5cf3696a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 11:37:55 +0100 Subject: [PATCH 130/150] Flush before std::exit (otherwise nothing is printed) --- .../test/Convex_hull_3/test_extreme_points.cpp | 4 ++-- .../benchmarks/Optimal_bounding_box/bench_obb.cpp | 2 +- .../test_optimization_algorithms.cpp | 10 +++++----- .../manifoldness_repair_example.cpp | 2 +- .../surface_mesh_intersection.cpp | 4 ++-- .../remove_degeneracies_test.cpp | 4 ++-- .../surface_intersection_sm_poly.cpp | 4 ++-- .../Polygon_mesh_processing/test_pmp_manifoldness.cpp | 2 +- .../Polygon_mesh_processing/test_shape_predicates.cpp | 6 +++--- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Convex_hull_3/test/Convex_hull_3/test_extreme_points.cpp b/Convex_hull_3/test/Convex_hull_3/test_extreme_points.cpp index 9b9ee278cbb..29d7e632570 100644 --- a/Convex_hull_3/test/Convex_hull_3/test_extreme_points.cpp +++ b/Convex_hull_3/test/Convex_hull_3/test_extreme_points.cpp @@ -52,7 +52,7 @@ void test_triangulated_cube(const char* fname) std::ifstream input(fname); SurfaceMesh mesh; if (!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << fname << " is not a valid off file.\n"; + std::cerr << fname << " is not a valid off file." << std::endl; exit(1); } @@ -206,7 +206,7 @@ void test_extreme_vertices(const char* fname) std::ifstream input(fname); Polyhedron_3 P; if (!input || !(input >> P) || P.is_empty()) { - std::cerr << fname << " is not a valid off file.\n"; + std::cerr << fname << " is not a valid off file." << std::endl; exit(1); } /*CGAL::Extreme_points_traits_adapter_3< diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp index b6d1e3a5d6a..88a2146467f 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp @@ -30,7 +30,7 @@ void bench_finding_obb(const std::string fname) Surface_mesh mesh; if (!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << fname << " is not a valid off file.\n"; + std::cerr << fname << " is not a valid off file." << std::endl; std::exit(1); } diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 1dbdc081967..488530965ad 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -89,7 +89,7 @@ void test_reference_tetrahedron(const char* fname) CGAL::Surface_mesh mesh; if(!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << fname << " is not a valid off file.\n"; + std::cerr << fname << " is not a valid off file." << std::endl; std::exit(1); } @@ -112,7 +112,7 @@ void test_long_tetrahedron(const std::string fname) CGAL::Surface_mesh mesh; if(!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << fname << " is not a valid off file.\n"; + std::cerr << fname << " is not a valid off file." << std::endl; std::exit(1); } @@ -145,7 +145,7 @@ void test_compute_obb_evolution(const std::string fname) SMesh mesh; if(!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << fname << " is not a valid off file.\n"; + std::cerr << fname << " is not a valid off file." << std::endl; std::exit(1); } @@ -174,7 +174,7 @@ void test_compute_obb_mesh(const std::string fname) CGAL::Surface_mesh mesh; if(!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << fname << " is not a valid off file.\n"; + std::cerr << fname << " is not a valid off file." << std::endl; std::exit(1); } @@ -194,7 +194,7 @@ void test_function_defaults_traits(const std::string fname1) CGAL::Surface_mesh mesh1; if(!input1 || !(input1 >> mesh1) || mesh1.is_empty()) { - std::cerr << fname1 << " is not a valid off file.\n"; + std::cerr << fname1 << " is not a valid off file." << std::endl; std::exit(1); } diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/manifoldness_repair_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/manifoldness_repair_example.cpp index 61d8b46bfe4..876de531c29 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/manifoldness_repair_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/manifoldness_repair_example.cpp @@ -39,7 +39,7 @@ int main(int argc, char* argv[]) Mesh mesh; if(!input || !(input >> mesh) || num_vertices(mesh) == 0) { - std::cerr << filename << " is not a valid off file.\n"; + std::cerr << filename << " is not a valid off file." << std::endl; return EXIT_FAILURE; } diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/surface_mesh_intersection.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/surface_mesh_intersection.cpp index 20ccbf2da0f..01c5a7d65b7 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/surface_mesh_intersection.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/surface_mesh_intersection.cpp @@ -24,7 +24,7 @@ int main(int argc, char* argv[]) Mesh mesh1; if ( !input || !(input >> mesh1) ) { - std::cerr << filename1 << " is not a valid off file.\n"; + std::cerr << filename1 << " is not a valid off file." << std::endl; return 1; } input.close(); @@ -34,7 +34,7 @@ int main(int argc, char* argv[]) Mesh mesh2; if ( !input || !(input >> mesh2) ) { - std::cerr << filename2 << " is not a valid off file.\n"; + std::cerr << filename2 << " is not a valid off file." << std::endl; return 1; } diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/remove_degeneracies_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/remove_degeneracies_test.cpp index f18dda38b1e..ac372682ca6 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/remove_degeneracies_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/remove_degeneracies_test.cpp @@ -137,7 +137,7 @@ void remove_degeneracies(const char* filename, Mesh mesh; if (!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << filename << " is not a valid off file.\n"; + std::cerr << filename << " is not a valid off file." << std::endl; exit(1); } @@ -211,7 +211,7 @@ void remove_negligible_connected_components(const char* filename) Mesh mesh, mesh_cpy; if (!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << filename << " is not a valid off file.\n"; + std::cerr << filename << " is not a valid off file." << std::endl; exit(1); } diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/surface_intersection_sm_poly.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/surface_intersection_sm_poly.cpp index 154b56bd6d4..6dbbcccb152 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/surface_intersection_sm_poly.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/surface_intersection_sm_poly.cpp @@ -28,13 +28,13 @@ void run(const char* filename1, const char* filename2, const char* msg) { TriangleMesh mesh1; if ( !CGAL::read_off(filename1, mesh1) ) { - std::cerr << filename1 << " is not a valid off file.\n"; + std::cerr << filename1 << " is not a valid off file." << std::endl; exit(1); } TriangleMesh mesh2; if ( !CGAL::read_off(filename2, mesh2) ) { - std::cerr << filename2 << " is not a valid off file.\n"; + std::cerr << filename2 << " is not a valid off file." << std::endl; exit(1); } diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_manifoldness.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_manifoldness.cpp index c4b8a98d2fa..6ba9b17e466 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_manifoldness.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_manifoldness.cpp @@ -25,7 +25,7 @@ void read_mesh(const char* fname, std::ifstream input(fname); if (!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << fname << " is not a valid off file.\n"; + std::cerr << fname << " is not a valid off file." << std::endl; std::exit(1); } } diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_shape_predicates.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_shape_predicates.cpp index 2f4c275e29d..d1315704637 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_shape_predicates.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_shape_predicates.cpp @@ -24,7 +24,7 @@ void check_edge_degeneracy(const char* fname) std::ifstream input(fname); Surface_mesh mesh; if (!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << fname << " is not a valid off file.\n"; + std::cerr << fname << " is not a valid off file." << std::endl; std::exit(1); } std::vector all_edges(edges(mesh).begin(), edges(mesh).end()); @@ -44,7 +44,7 @@ void check_triangle_face_degeneracy(const char* fname) std::ifstream input(fname); Surface_mesh mesh; if (!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << fname << " is not a valid off file.\n"; + std::cerr << fname << " is not a valid off file." << std::endl; std::exit(1); } @@ -70,7 +70,7 @@ void test_needles_and_caps(const char* fname) std::ifstream input(fname); Surface_mesh mesh; if (!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << fname << " is not a valid off file.\n"; + std::cerr << fname << " is not a valid off file." << std::endl; std::exit(1); } From 5069bcf8137144146ebf04113ab40573bcd3b61d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 11:54:15 +0100 Subject: [PATCH 131/150] Minor internal API changes --- .../include/CGAL/Optimal_bounding_box/internal/evolution.h | 4 ++-- .../include/CGAL/Optimal_bounding_box/oriented_bounding_box.h | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index 179d7f5e6dd..5298c7123de 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -122,8 +122,8 @@ public: } void evolve(const std::size_t generations, - const std::size_t population_size = 50, - const std::size_t nelder_mead_iterations = 150) + const std::size_t population_size, + const std::size_t nelder_mead_iterations) { // stopping criteria prameters FT prev_fit_value = 0; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 1d31b6012e7..efbc78e7413 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -101,6 +101,8 @@ void compute_best_transformation(const PointRange& points, CGAL_assertion(points.size() >= 3); const std::size_t max_generations = 50; // @todo hidden NP + const std::size_t population_size = 50; + const std::size_t nelder_mead_iterations = 150; #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS CGAL::Real_timer timer; @@ -108,7 +110,7 @@ void compute_best_transformation(const PointRange& points, #endif Evolution search_solution(points, rng, traits); - search_solution.evolve(max_generations); + search_solution.evolve(max_generations, population_size, nelder_mead_iterations); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS std::cout << "evolve: " << timer.time() << std::endl; From 631c87e933e973938135a7d4293df2131a074f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 15:38:02 +0100 Subject: [PATCH 132/150] OBB's concept must refine ConvexHullTraits_3 --- .../Concepts/OrientedBoundingBoxTraits.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h index cbd5ab6a5b8..9eb5aee1daa 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h @@ -6,6 +6,8 @@ The concept `OrientedBoundingBoxTraits_3` describes the requirements of the trai used in the function `CGAL::oriented_bounding_box()`, and in particular the need for a 3x3 matrix type. +\cgalRefines `ConvexHullTraits_3` + \cgalHasModel `CGAL::Oriented_bounding_box_traits_3` */ @@ -15,9 +17,6 @@ public: /// The field number type; must be a model of the concept `FieldNumberType` typedef unspecified_type FT; - /// The 3D point type; must be model of `Kernel::Point_3` - typedef unspecified_type Point_3; - /// The 3D affine transformation type; the template parameter `K` must be a model of `Kernel` /// and be compatible with the type `Point_3` typedef CGAL::Aff_transformation_3 Aff_transformation_3; @@ -25,7 +24,7 @@ public: /// A construction object that must provide the function operator: /// `CGAL::Bbox_3 operator()(const Point_3&)`, /// which returns an axis-aligned bounding box that contains the point - typedef unspecified_type Construct_bbox_3; + typedef unspecified_type Construct_bbox_3; /// A 3x3 matrix type; model of the concept `SvdTraits::Matrix` and which supports /// matrix-matrix and scalar-matrix multiplication, as well as matrix-matrix addition From 2cce770aabb35f9b28a38fc53bdc6090eafd5046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 15:39:22 +0100 Subject: [PATCH 133/150] Add missing random mutations --- .../Optimal_bounding_box/internal/evolution.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index 5298c7123de..3c624fc9dbc 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -123,7 +123,8 @@ public: void evolve(const std::size_t generations, const std::size_t population_size, - const std::size_t nelder_mead_iterations) + const std::size_t nelder_mead_iterations, + const int max_random_mutations = 5) { // stopping criteria prameters FT prev_fit_value = 0; @@ -171,6 +172,18 @@ public: break; prev_fit_value = new_fit_value; + + // random mutations, swap #random_mutations random simplices with a new, random simplex + if(max_random_mutations <= 0) + continue; + + CGAL_warning(max_random_mutations <= population_size); + const int random_mutations = m_rng.get_int(0, max_random_mutations+1); + for(std::size_t i=0; i Date: Tue, 24 Mar 2020 15:50:16 +0100 Subject: [PATCH 134/150] Misc improvements --- .../Optimal_bounding_box/internal/evolution.h | 15 +++--- .../internal/fitness_function.h | 26 ---------- .../internal/population.h | 48 ++++++++++++++----- .../oriented_bounding_box.h | 2 +- .../test_merging_border_vertices.cpp | 2 +- 5 files changed, 46 insertions(+), 47 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index 3c624fc9dbc..a130de75c42 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -107,7 +107,7 @@ public: const FT fitnessA = m_population[group3[i]][j].fitness_value(); const FT fitnessB = m_population[group4[i]][j].fitness_value(); const FT lambda = (fitnessA < fitnessB) ? uweight : lweight; - const FT rambda = 1 - lambda; // because the 'l' in 'lambda' stands for left + const FT rambda = FT(1) - lambda; // because the 'l' in 'lambda' stands for left const Matrix& lm = m_population[group3[i]][j].matrix(); const Matrix& rm = m_population[group4[i]][j].matrix(); @@ -121,7 +121,7 @@ public: m_population.simplices() = std::move(new_simplices); } - void evolve(const std::size_t generations, + void evolve(const std::size_t max_generations, const std::size_t population_size, const std::size_t nelder_mead_iterations, const int max_random_mutations = 5) @@ -131,10 +131,11 @@ public: const FT tolerance = 1e-9; int stale = 0; - for(std::size_t t=0; t max_generations) break; prev_fit_value = new_fit_value; @@ -187,14 +188,14 @@ public: } } - const Vertex& get_best() + const Vertex& get_best_vertex() const { CGAL_assertion(m_best_v != nullptr); return *m_best_v; } private: - const Vertex* m_best_v; + Vertex* m_best_v; Population m_population; CGAL::Random& m_rng; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h index 20c0f8d6a20..9a565992912 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h @@ -61,32 +61,6 @@ compute_fitness(const typename Traits::Matrix& R, // rotation matrix return ((xmax - xmin) * (ymax - ymin) * (zmax - zmin)); } -template -const typename Population::Vertex& get_best_vertex(const Population& population) -{ - typedef typename Population::FT FT; - typedef typename Population::Vertex Vertex; - - std::size_t simplex_id, vertex_id; - FT best_fitness = std::numeric_limits::max(); - for(std::size_t i=0, ps=population.size(); i Simplex create_simplex(const PointRange& points, CGAL::Random& rng) const @@ -98,30 +106,46 @@ private: return s; } -public: + // create random population template void initialize(const std::size_t population_size, const PointRange& points, CGAL::Random& rng) { - m_pop.clear(); - m_pop.reserve(population_size); + m_simplices.clear(); + m_simplices.reserve(population_size); for(std::size_t i=0; i::max()}; + for(std::size_t i=0, ps=m_simplices.size(); i m_pop; + std::vector m_simplices; const Traits& m_traits; }; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index efbc78e7413..54d33108769 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -117,7 +117,7 @@ void compute_best_transformation(const PointRange& points, timer.reset(); #endif - const Matrix& rot = search_solution.get_best().matrix(); + const Matrix& rot = search_solution.get_best_vertex().matrix(); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS std::cout << "get best: " << timer.time() << std::endl; diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_merging_border_vertices.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_merging_border_vertices.cpp index 4ae670175e3..7b80028de1a 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_merging_border_vertices.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_merging_border_vertices.cpp @@ -18,7 +18,7 @@ void test_merge_duplicated_vertices_in_boundary_cycles(const char* fname, Surface_mesh mesh; if (!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << fname << " is not a valid off file.\n"; + std::cerr << fname << " is not a valid off file." << std::endl; exit(1); } From 170e3dd68b2b0f46d0d95f3afd359401c45a60e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 15:54:32 +0100 Subject: [PATCH 135/150] Fix traits model --- .../Oriented_bounding_box_traits_3.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h index 6cf1f1a126f..d31bdd2a333 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/Oriented_bounding_box_traits_3.h @@ -39,20 +39,15 @@ namespace CGAL { /// template class Oriented_bounding_box_traits_3 + : public K { public: /// The field number type typedef typename K::FT FT; - /// The point type - typedef typename K::Point_3 Point_3; - /// The affine transformation type typedef typename CGAL::Aff_transformation_3 Aff_transformation_3; - /// The axis-aligned bounding box construction object - typedef typename K::Construct_bbox_3 Construct_bbox_3; - /// The matrix type typedef CGAL::Eigen_matrix Matrix; @@ -60,9 +55,6 @@ private: typedef typename Matrix::EigenType EigenType; public: - /// Returns a default-constructed construction object - static Construct_bbox_3 construct_bbox_3_object() { return Construct_bbox_3(); } - /// Performs the QR-decomposition of the matrix `m` to a unitary matrix and an upper triagonal /// and returns the unitary matrix static Matrix get_Q(const Matrix& m) From 09c9c3044d58d801751ee1a4cbcad9f1a8cfdf10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 15:54:44 +0100 Subject: [PATCH 136/150] Fix not propagating traits to CH3 code --- .../include/CGAL/Optimal_bounding_box/oriented_bounding_box.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 54d33108769..7dafd269b66 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -171,7 +171,7 @@ void construct_oriented_bounding_box(const PointRange& points, if(use_ch) // construct the convex hull to reduce the number of points { std::vector ch_points; - extreme_points_3(points, std::back_inserter(ch_points)); + extreme_points_3(points, std::back_inserter(ch_points), traits); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG std::cout << ch_points.size() << " points on the convex hull" << std::endl; From afb5abe61a088319aa12018d198de03517703227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 16:01:56 +0100 Subject: [PATCH 137/150] Kernel is not a model of ConvexHullTraits_3 (but Extreme_points_... is) K::Traits_xy/xz/yz_3 does not exist --- Convex_hull_2/doc/Convex_hull_2/Concepts/ConvexHullTraits_2.h | 2 +- Convex_hull_3/doc/Convex_hull_3/Concepts/ConvexHullTraits_3.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Convex_hull_2/doc/Convex_hull_2/Concepts/ConvexHullTraits_2.h b/Convex_hull_2/doc/Convex_hull_2/Concepts/ConvexHullTraits_2.h index 426f8f3f265..bbcc197ddd5 100644 --- a/Convex_hull_2/doc/Convex_hull_2/Concepts/ConvexHullTraits_2.h +++ b/Convex_hull_2/doc/Convex_hull_2/Concepts/ConvexHullTraits_2.h @@ -13,7 +13,7 @@ is specified with each function. \cgalHasModel `CGAL::Convex_hull_traits_2` \cgalHasModel `CGAL::Convex_hull_traits_adapter_2` \cgalHasModel `CGAL::Projection_traits_xy_3` -\cgalHasModel `CGAL::Projection_traits_yz_3 ` +\cgalHasModel `CGAL::Projection_traits_yz_3` \cgalHasModel `CGAL::Projection_traits_xz_3` \sa `IsStronglyConvexTraits_3` diff --git a/Convex_hull_3/doc/Convex_hull_3/Concepts/ConvexHullTraits_3.h b/Convex_hull_3/doc/Convex_hull_3/Concepts/ConvexHullTraits_3.h index 97837cbae05..78952b43bdd 100644 --- a/Convex_hull_3/doc/Convex_hull_3/Concepts/ConvexHullTraits_3.h +++ b/Convex_hull_3/doc/Convex_hull_3/Concepts/ConvexHullTraits_3.h @@ -4,8 +4,8 @@ Requirements of the traits class of the function `CGAL::convex_hull_3()`. -\cgalHasModel `CGAL::Convex_hull_traits_3` -\cgalHasModel All models of `Kernel` +\cgalHasModel `CGAL::Convex_hull_traits_3` +\cgalHasModel `CGAL::Extreme_points_traits_adapter_3` */ class ConvexHullTraits_3 { From b2126afd6d9cf347d741a5719087a5a8be13b3dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 16:19:54 +0100 Subject: [PATCH 138/150] Make indentation deterministic (no real changes) --- .../CGAL/Extreme_points_traits_adapter_3.h | 302 ++++++++++-------- 1 file changed, 167 insertions(+), 135 deletions(-) diff --git a/Convex_hull_3/include/CGAL/Extreme_points_traits_adapter_3.h b/Convex_hull_3/include/CGAL/Extreme_points_traits_adapter_3.h index 8934091b740..68b3bd90755 100644 --- a/Convex_hull_3/include/CGAL/Extreme_points_traits_adapter_3.h +++ b/Convex_hull_3/include/CGAL/Extreme_points_traits_adapter_3.h @@ -33,210 +33,245 @@ struct Forward_functor : public F { PointPropertyMap vpm_; - - Forward_functor(const PointPropertyMap& vpm, - const F& f) : F(f), vpm_(vpm) {} - - + + Forward_functor(const PointPropertyMap& vpm, const F& f) : F(f), vpm_(vpm) {} + template typename cpp11::result_of::type - operator() (const Vertex& p, const Vertex& q) const + operator()(const Vertex& p, const Vertex& q) const { - return static_cast(this)->operator()(get(vpm_,p),get(vpm_,q)); + return static_cast(this)->operator()(get(vpm_, p), get(vpm_, q)); } template typename cpp11::result_of::type - operator() (const Vertex& p, const Vertex& q, const Vertex& r) const + operator()(const Vertex& p, const Vertex& q, const Vertex& r) const { - return static_cast(this)->operator()( - get(vpm_,p), - get(vpm_,q), - get(vpm_,r)); + return static_cast(this)->operator()(get(vpm_, p), + get(vpm_, q), + get(vpm_, r)); } template typename cpp11::result_of::type - operator() (const Vertex& p, const Vertex& q, const Vertex& r, const Vertex& s) const + operator()(const Vertex& p, const Vertex& q, const Vertex& r, const Vertex& s) const { - return static_cast(this)->operator()( - get(vpm_,p), - get(vpm_,q), - get(vpm_,r), - get(vpm_,s)); + return static_cast(this)->operator()(get(vpm_, p), + get(vpm_, q), + get(vpm_, r), + get(vpm_, s)); } }; } // namespace internal } // namespace Convex_hull_3 -template< - class PointPropertyMap, - class Base_traits = typename Convex_hull_3::internal::Default_traits_for_Chull_3< - typename boost::property_traits::value_type>::type +template::value_type>::type > class Extreme_points_traits_adapter_3 - :public Base_traits + : public Base_traits { PointPropertyMap vpm_; - - + public: - Extreme_points_traits_adapter_3(const PointPropertyMap& vpmap, Base_traits base=Base_traits()) - :Base_traits(base), vpm_(vpmap) - {} - typedef typename boost::property_traits::key_type Vertex; - typedef Vertex Point_3; - typedef Convex_hull_3::internal::Forward_functor Equal_3; - typedef Convex_hull_3::internal::Forward_functor Collinear_3; - typedef Convex_hull_3::internal::Forward_functor Coplanar_3; - typedef Convex_hull_3::internal::Forward_functor Less_distance_to_point_3; + Extreme_points_traits_adapter_3(const PointPropertyMap& vpmap, + Base_traits base = Base_traits()) + : + Base_traits(base), vpm_(vpmap) + { } + + typedef typename boost::property_traits::key_type Vertex; + typedef Vertex Point_3; + typedef Convex_hull_3::internal::Forward_functor< + typename Base_traits::Equal_3, PointPropertyMap> Equal_3; + typedef Convex_hull_3::internal::Forward_functor< + typename Base_traits::Collinear_3, PointPropertyMap> Collinear_3; + typedef Convex_hull_3::internal::Forward_functor< + typename Base_traits::Coplanar_3, PointPropertyMap> Coplanar_3; + typedef Convex_hull_3::internal::Forward_functor< + typename Base_traits::Less_distance_to_point_3, PointPropertyMap> Less_distance_to_point_3; class Less_signed_distance_to_plane_3 - :public Base_traits::Less_signed_distance_to_plane_3 - { + : public Base_traits::Less_signed_distance_to_plane_3 + { PointPropertyMap vpm_; const typename Base_traits::Less_signed_distance_to_plane_3& base; + public: - typedef typename Base_traits::Plane_3 Plane_3; - - typedef bool result_type; - - Less_signed_distance_to_plane_3( - const PointPropertyMap& map, - const typename Base_traits::Less_signed_distance_to_plane_3& base): - Base_traits::Less_signed_distance_to_plane_3(base),vpm_(map), base(base){} - - bool - operator()( const Plane_3& h, const Vertex& p, const Vertex& q) const + typedef typename Base_traits::Plane_3 Plane_3; + typedef bool result_type; + + Less_signed_distance_to_plane_3(const PointPropertyMap& map, + const typename Base_traits::Less_signed_distance_to_plane_3& base) + : Base_traits::Less_signed_distance_to_plane_3(base), vpm_(map), base(base) + { } + + bool operator()(const Plane_3& h, const Vertex& p, const Vertex& q) const { - return base(h, get(vpm_,p), get(vpm_,q)); + return base(h, get(vpm_, p), get(vpm_, q)); } }; - - - Equal_3 equal_3_object () const {return Equal_3(vpm_,static_cast(this)->equal_3_object() );} - Collinear_3 collinear_3_object () const {return Collinear_3(vpm_,static_cast(this)->collinear_3_object() );} - Coplanar_3 coplanar_3_object () const {return Coplanar_3(vpm_,static_cast(this)->coplanar_3_object() );} - Less_distance_to_point_3 less_distance_to_point_3_object() const { - return Less_distance_to_point_3(vpm_,static_cast(this)->less_distance_to_point_3_object() );} - Less_signed_distance_to_plane_3 less_signed_distance_to_plane_3_object() const { - return Less_signed_distance_to_plane_3( - vpm_,static_cast(this)->less_signed_distance_to_plane_3_object() ); - } - - class Construct_plane_3:public Base_traits::Construct_plane_3 - { + + Equal_3 equal_3_object() const + { return Equal_3(vpm_, static_cast(this)->equal_3_object()); } + Collinear_3 collinear_3_object() const + { return Collinear_3(vpm_, static_cast(this)->collinear_3_object()); } + Coplanar_3 coplanar_3_object() const + { return Coplanar_3(vpm_, static_cast(this)->coplanar_3_object()); } + Less_distance_to_point_3 less_distance_to_point_3_object() const + { return Less_distance_to_point_3(vpm_, static_cast(this)->less_distance_to_point_3_object()); } + Less_signed_distance_to_plane_3 less_signed_distance_to_plane_3_object() const + { return Less_signed_distance_to_plane_3(vpm_, static_cast(this)->less_signed_distance_to_plane_3_object()); } + + class Construct_plane_3 + : public Base_traits::Construct_plane_3 + { PointPropertyMap vpm_; const typename Base_traits::Construct_plane_3& base; + public: - Construct_plane_3(const PointPropertyMap& map, const typename Base_traits::Construct_plane_3& base): - Base_traits::Construct_plane_3(base),vpm_(map), base(base){} - typename Base_traits::Plane_3 operator()(const Vertex& p, const Vertex& q, const Vertex& r)const + Construct_plane_3(const PointPropertyMap& map, + const typename Base_traits::Construct_plane_3& base) + : Base_traits::Construct_plane_3(base), vpm_(map), base(base) + { } + + typename Base_traits::Plane_3 operator()(const Vertex& p, const Vertex& q, const Vertex& r) const { - return base(get(vpm_,p),get(vpm_,q),get(vpm_,r)); + return base(get(vpm_, p), get(vpm_, q), get(vpm_, r)); } }; + Construct_plane_3 construct_plane_3_object() const - {return Construct_plane_3(vpm_,static_cast(this)->construct_plane_3_object());} - - class Has_on_positive_side_3:public Base_traits::Has_on_positive_side_3 - { + {return Construct_plane_3(vpm_, static_cast(this)->construct_plane_3_object());} + + class Has_on_positive_side_3 + : public Base_traits::Has_on_positive_side_3 + { PointPropertyMap vpm_; const typename Base_traits::Has_on_positive_side_3& base; + public: - Has_on_positive_side_3(const PointPropertyMap& map,const typename Base_traits::Has_on_positive_side_3& base): - Base_traits::Has_on_positive_side_3(base),vpm_(map), base(base){} - - typedef typename Base_traits::Plane_3 Plane_3; + Has_on_positive_side_3(const PointPropertyMap& map, + const typename Base_traits::Has_on_positive_side_3& base) + : Base_traits::Has_on_positive_side_3(base), vpm_(map), base(base) + { } + + typedef typename Base_traits::Plane_3 Plane_3; public: - typedef bool result_type; - - result_type - operator()( const Plane_3& pl, const Vertex& p) const - { + typedef bool result_type; + + result_type operator()( const Plane_3& pl, const Vertex& p) const + { return base(pl, get(vpm_, p)); } }; - Has_on_positive_side_3 has_on_positive_side_3_object() const {return Has_on_positive_side_3( - vpm_,static_cast(this)->has_on_positive_side_3_object() );} - + + Has_on_positive_side_3 has_on_positive_side_3_object() const + { return Has_on_positive_side_3(vpm_, static_cast(this)->has_on_positive_side_3_object()); } + template - class Proj_traits_3:public Base_proj_traits + class Proj_traits_3 + : public Base_proj_traits { PointPropertyMap vpm_; typedef Base_proj_traits Btt; + public: - Proj_traits_3(const PointPropertyMap& map,const Btt& base): - Base_proj_traits(base),vpm_(map){} - typedef Point_3 Point_2; - typedef Convex_hull_3::internal::Forward_functor Equal_2; - typedef Convex_hull_3::internal::Forward_functor Less_xy_2; - typedef Convex_hull_3::internal::Forward_functor Less_yx_2; - typedef Convex_hull_3::internal::Forward_functor Less_signed_distance_to_line_2; - typedef Convex_hull_3::internal::Forward_functor Left_turn_2; - - class Less_rotate_ccw_2:public Btt::Less_rotate_ccw_2 + Proj_traits_3(const PointPropertyMap& map, const Btt& base) + : Base_proj_traits(base), vpm_(map) + { } + + typedef Point_3 Point_2; + typedef Convex_hull_3::internal::Forward_functor< + typename Btt::Equal_2, PointPropertyMap> Equal_2; + typedef Convex_hull_3::internal::Forward_functor< + typename Btt::Less_xy_2, PointPropertyMap> Less_xy_2; + typedef Convex_hull_3::internal::Forward_functor< + typename Btt::Less_yx_2, PointPropertyMap> Less_yx_2; + typedef Convex_hull_3::internal::Forward_functor< + typename Btt::Less_signed_distance_to_line_2, PointPropertyMap> Less_signed_distance_to_line_2; + typedef Convex_hull_3::internal::Forward_functor< + typename Btt::Left_turn_2, PointPropertyMap> Left_turn_2; + + class Less_rotate_ccw_2 + : public Btt::Less_rotate_ccw_2 { PointPropertyMap vpm_; const typename Btt::Less_rotate_ccw_2& base; + + public: + Less_rotate_ccw_2(const PointPropertyMap& map, + const typename Btt::Less_rotate_ccw_2& base) + : Btt::Less_rotate_ccw_2(base), vpm_(map), base(base) + { } + public: - Less_rotate_ccw_2(const PointPropertyMap& map,const typename Btt::Less_rotate_ccw_2& base): - Btt::Less_rotate_ccw_2(base),vpm_(map), base(base){} - public: bool operator()(Point_2 e, Point_2 p,Point_2 q) const - { + { return base(get(vpm_, e), get(vpm_, p), get(vpm_, q)); } }; - - Equal_2 equal_2_object () const {return Equal_2(vpm_,static_cast(this)->equal_2_object() );} - Less_xy_2 less_xy_2_object ()const{return Less_xy_2(vpm_,static_cast(this)->less_xy_2_object() );} - Less_yx_2 less_yx_2_object ()const{return Less_yx_2(vpm_,static_cast(this)->less_yx_2_object() );} - Less_signed_distance_to_line_2 less_signed_distance_to_line_2_object ()const - {return Less_signed_distance_to_line_2(vpm_,static_cast(this)->Less_signed_distance_to_line_2() );} - Less_rotate_ccw_2 less_rotate_ccw_2_object ()const - {return Less_rotate_ccw_2(vpm_,static_cast(this)->less_rotate_ccw_2_object() );} - Left_turn_2 left_turn_2_object ()const{return Left_turn_2(vpm_,static_cast(this)->left_turn_2_object() );} - - class Orientation_2:public Btt::Orientation_2 + + Equal_2 equal_2_object() const + { return Equal_2(vpm_, static_cast(this)->equal_2_object()); } + Less_xy_2 less_xy_2_object() const + { return Less_xy_2(vpm_, static_cast(this)->less_xy_2_object()); } + Less_yx_2 less_yx_2_object() const + { return Less_yx_2(vpm_, static_cast(this)->less_yx_2_object()); } + Less_signed_distance_to_line_2 less_signed_distance_to_line_2_object() const + { return Less_signed_distance_to_line_2(vpm_, static_cast(this)->Less_signed_distance_to_line_2()); } + Less_rotate_ccw_2 less_rotate_ccw_2_object() const + { return Less_rotate_ccw_2(vpm_, static_cast(this)->less_rotate_ccw_2_object()); } + Left_turn_2 left_turn_2_object() const + { return Left_turn_2(vpm_, static_cast(this)->left_turn_2_object()); } + + class Orientation_2 + : public Btt::Orientation_2 { - PointPropertyMap vpm_; - const typename Btt::Orientation_2& base; - public: - Orientation_2(const PointPropertyMap& map,const typename Btt::Orientation_2& base): - Btt::Orientation_2(base),vpm_(map), base(base){} - - typename CGAL::Orientation operator()(Point_2 e,Point_2 p, Point_2 q) const - { - return base(get(vpm_, e), get(vpm_, p), get(vpm_, q)); + PointPropertyMap vpm_; + const typename Btt::Orientation_2& base; + + public: + Orientation_2(const PointPropertyMap& map, + const typename Btt::Orientation_2& base) + : Btt::Orientation_2(base), vpm_(map), base(base) + { } + + typename CGAL::Orientation operator()(Point_2 e, Point_2 p, Point_2 q) const + { + return base(get(vpm_, e), get(vpm_, p), get(vpm_, q)); } }; - Orientation_2 orientation_2_object ()const{return Orientation_2(vpm_,static_cast(this)->orientation_2_object() );} + + Orientation_2 orientation_2_object() const + { return Orientation_2(vpm_, static_cast(this)->orientation_2_object()); } }; - + typedef Convex_hull_3::internal::Projection_traits Base_PTraits; - typedef Proj_traits_3 Traits_xy_3; - typedef Proj_traits_3 Traits_yz_3; - typedef Proj_traits_3 Traits_xz_3; - - Traits_xy_3 construct_traits_xy_3_object()const - {return Traits_xy_3(vpm_, Base_PTraits(static_cast(*this)).construct_traits_xy_3_object());} - Traits_yz_3 construct_traits_yz_3_object()const - {return Traits_yz_3(vpm_, Base_PTraits(static_cast(*this)).construct_traits_yz_3_object());} - Traits_xz_3 construct_traits_xz_3_object()const - {return Traits_xz_3(vpm_, Base_PTraits(static_cast(*this)).construct_traits_xz_3_object());} + typedef Proj_traits_3 Traits_xy_3; + typedef Proj_traits_3 Traits_yz_3; + typedef Proj_traits_3 Traits_xz_3; + + Traits_xy_3 construct_traits_xy_3_object() const + { return Traits_xy_3(vpm_, Base_PTraits(static_cast(*this)).construct_traits_xy_3_object()); } + Traits_yz_3 construct_traits_yz_3_object() const + { return Traits_yz_3(vpm_, Base_PTraits(static_cast(*this)).construct_traits_yz_3_object()); } + Traits_xz_3 construct_traits_xz_3_object() const + { return Traits_xz_3(vpm_, Base_PTraits(static_cast(*this)).construct_traits_xz_3_object()); } typename boost::property_traits::reference get_point(const typename boost::property_traits::key_type& k) const { return get(vpm_, k); } - }; + template Extreme_points_traits_adapter_3 -make_extreme_points_traits_adapter(const PointPropertyMap& pmap, Base_traits traits = Base_traits()) +make_extreme_points_traits_adapter(const PointPropertyMap& pmap, + Base_traits traits = Base_traits()) { return Extreme_points_traits_adapter_3(pmap, traits); } @@ -248,9 +283,6 @@ make_extreme_points_traits_adapter(const PointPropertyMap& pmap) return Extreme_points_traits_adapter_3(pmap); } - -//helper function - -}//end CGAL +} // namespace CGAL #endif // CGAL_EXTREME_POINTS_TRAITS_ADAPTER_3_H From 4e01ec78cffd1988c7d421144bdb25d8400927ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 16:22:06 +0100 Subject: [PATCH 139/150] Fix copying points argument in Extreme_points_traits_adapter --- Convex_hull_3/include/CGAL/Extreme_points_traits_adapter_3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Convex_hull_3/include/CGAL/Extreme_points_traits_adapter_3.h b/Convex_hull_3/include/CGAL/Extreme_points_traits_adapter_3.h index 68b3bd90755..adeb88c6e26 100644 --- a/Convex_hull_3/include/CGAL/Extreme_points_traits_adapter_3.h +++ b/Convex_hull_3/include/CGAL/Extreme_points_traits_adapter_3.h @@ -208,7 +208,7 @@ public: { } public: - bool operator()(Point_2 e, Point_2 p,Point_2 q) const + bool operator()(const Point_2& e, const Point_2& p, const Point_2& q) const { return base(get(vpm_, e), get(vpm_, p), get(vpm_, q)); } @@ -239,7 +239,7 @@ public: : Btt::Orientation_2(base), vpm_(map), base(base) { } - typename CGAL::Orientation operator()(Point_2 e, Point_2 p, Point_2 q) const + typename CGAL::Orientation operator()(const Point_2& e, const Point_2& p, const Point_2& q) const { return base(get(vpm_, e), get(vpm_, p), get(vpm_, q)); } From 3c6e5875d58237a8e58e897c9739bbf82003efb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Mar 2020 18:48:32 +0100 Subject: [PATCH 140/150] Grab return Construct_point_3(Weighted_point_3) by reference --- .../include/CGAL/internal/Projection_traits_3.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Kernel_23/include/CGAL/internal/Projection_traits_3.h b/Kernel_23/include/CGAL/internal/Projection_traits_3.h index c203eb6be7b..6e5aae15f29 100644 --- a/Kernel_23/include/CGAL/internal/Projection_traits_3.h +++ b/Kernel_23/include/CGAL/internal/Projection_traits_3.h @@ -521,7 +521,7 @@ public: Weighted_point_2 project(const Weighted_point_3& wp) const { - Point_3 p = R().construct_point_3_object()(wp); + const Point_3& p = R().construct_point_3_object()(wp); return Weighted_point_2(Point_2(x(p), y(p)), wp.weight()); } @@ -550,7 +550,7 @@ public: Weighted_point_2 project(const Weighted_point_3& wp) const { - Point_3 p = R().construct_point_3_object()(wp); + const Point_3& p = R().construct_point_3_object()(wp); return Weighted_point_2(Point_2(x(p), y(p)), wp.weight()); } @@ -577,7 +577,7 @@ public: Weighted_point_2 project(const Weighted_point_3& wp) const { - Point_3 p = R().construct_point_3_object()(wp); + const Point_3& p = R().construct_point_3_object()(wp); return Weighted_point_2(Point_2(x(p), y(p)), wp.weight()); } @@ -614,7 +614,7 @@ public: Weighted_point_2 project(const Weighted_point_3& wp) const { - Point_3 p = R().construct_point_3_object()(wp); + const Point_3& p = R().construct_point_3_object()(wp); return Weighted_point_2(Point_2(x(p), y(p)), wp.weight()); } @@ -659,7 +659,7 @@ public: Weighted_point_2 project(const Weighted_point_3& wp) const { - Point_3 p = R().construct_point_3_object()(wp); + const Point_3& p = R().construct_point_3_object()(wp); return Weighted_point_2(Point_2(x(p), y(p)), wp.weight()); } @@ -697,7 +697,7 @@ public: Weighted_point_2 project(const Weighted_point_3& wp) const { - Point_3 p = R().construct_point_3_object()(wp); + const Point_3& p = R().construct_point_3_object()(wp); return Weighted_point_2(Point_2(x(p), y(p)), wp.weight()); } @@ -739,7 +739,7 @@ public: Weighted_point_2 project(const Weighted_point_3& wp) const { - Point_3 p = R().construct_point_3_object()(wp); + const Point_3& p = R().construct_point_3_object()(wp); return Weighted_point_2(Point_2(x(p), y(p)), wp.weight()); } From 0c2b32ea4807d1cbde0dc2e913c348ed79a16553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 25 Mar 2020 12:37:45 +0100 Subject: [PATCH 141/150] Don't generate a new population at each generation... Obviously, the algorithm is now much more efficient. --- .../CGAL/Optimal_bounding_box/internal/evolution.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index a130de75c42..72b62959043 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -55,13 +55,13 @@ public: m_traits(traits) { } - void genetic_algorithm(const std::size_t population_size = 50) + void genetic_algorithm() { - // random permutations - m_population.initialize(population_size, m_points, m_rng); + // This evolves an existing population + CGAL_precondition(m_population.empty()); - //groups 1,2 : size m/2 groups 3,4 : size (m - m/2). m/2 is floored - const std::size_t m = population_size; + //groups 1,2 : size = floor(m/2) groups 3,4 : size = ceil(m/2). + const std::size_t m = m_population.size(); const std::size_t first_group_size = m / 2; const std::size_t second_group_size = m - first_group_size; @@ -131,6 +131,8 @@ public: const FT tolerance = 1e-9; int stale = 0; + m_population.initialize(population_size, m_points, m_rng); + std::size_t gen_iter = 0; for(;;) { @@ -138,7 +140,7 @@ public: std::cout << "- - - - generation #" << gen_iter << "\n"; #endif - genetic_algorithm(population_size); + genetic_algorithm(); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_PP std::cout << "population after genetic" << std::endl; From fbfec59341dccb23cfe2cb6ea13adbfebfb716c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 25 Mar 2020 15:25:59 +0100 Subject: [PATCH 142/150] Add post-processing: 2D optimization along OBB axes --- .../Concepts/OrientedBoundingBoxTraits.h | 10 +- .../Optimal_bounding_box/internal/evolution.h | 23 +- .../internal/optimize_2.h | 216 ++++++++++++++++++ .../oriented_bounding_box.h | 4 +- 4 files changed, 238 insertions(+), 15 deletions(-) create mode 100644 Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h diff --git a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h index 9eb5aee1daa..f31d11252ec 100644 --- a/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h +++ b/Optimal_bounding_box/doc/Optimal_bounding_box/Concepts/OrientedBoundingBoxTraits.h @@ -6,7 +6,7 @@ The concept `OrientedBoundingBoxTraits_3` describes the requirements of the trai used in the function `CGAL::oriented_bounding_box()`, and in particular the need for a 3x3 matrix type. -\cgalRefines `ConvexHullTraits_3` +\cgalRefines `Kernel` \cgalHasModel `CGAL::Oriented_bounding_box_traits_3` @@ -21,18 +21,10 @@ public: /// and be compatible with the type `Point_3` typedef CGAL::Aff_transformation_3 Aff_transformation_3; - /// A construction object that must provide the function operator: - /// `CGAL::Bbox_3 operator()(const Point_3&)`, - /// which returns an axis-aligned bounding box that contains the point - typedef unspecified_type Construct_bbox_3; - /// A 3x3 matrix type; model of the concept `SvdTraits::Matrix` and which supports /// matrix-matrix and scalar-matrix multiplication, as well as matrix-matrix addition typedef unspecified_type Matrix; /// Returns the unitary matrix `Q` obtained in the QR-decomposition of the matrix `m` Matrix get_Q(const Matrix& m) const; - - /// Returns the 3D box construction functor - Construct_bbox_3 construct_bbox_3_object() const; }; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index 72b62959043..d6649fbe28a 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -157,15 +158,27 @@ public: std::cout << std::endl; #endif + // optimize the current best rotation by using the exact OBB 2D algorithm + // along the axes of the current best OBB + m_best_v = &(m_population.get_best_vertex()); + Matrix& best_m = m_best_v->matrix(); + +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG + std::cout << "new best matrix: " << std::endl << best_m << std::endl; + std::cout << "fitness: " << m_best_v->fitness() << std::endl; +#endif + + optimize_along_OBB_axes(best_m, m_points, m_traits); + m_best_v->fitness() = compute_fitness(best_m, m_points, m_traits); + // stopping criteria - m_best_v = &(get_best_vertex(m_population)); - const FT new_fit_value = m_best_v->fitness_value(); + const FT new_fit_value = m_best_v->fitness(); const FT difference = new_fit_value - prev_fit_value; #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG - const Matrix& best_m = m_best_v->matrix(); - std::cout << "new best matrix: " << std::endl << best_m << std::endl; - std::cout << "value difference with previous: " << difference << std::endl; + std::cout << "post 2D optimization matrix: " << std::endl << best_m << std::endl; + std::cout << "new fit value: " << new_fit_value << std::endl; + std::cout << "difference: " << difference << std::endl; #endif if(CGAL::abs(difference) < tolerance * new_fit_value) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h new file mode 100644 index 00000000000..74306a03c4d --- /dev/null +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h @@ -0,0 +1,216 @@ +// Copyright (c) 2020 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Mael Rouxel-Labbé +// +#ifndef CGAL_OPTIMAL_BOUNDING_BOX_INTERNAL_OPTIMIZE_2_H +#define CGAL_OPTIMAL_BOUNDING_BOX_INTERNAL_OPTIMIZE_2_H + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace CGAL { +namespace Optimal_bounding_box { +namespace internal { + +enum PROJECTION_DIRECTION +{ + ALONG_X = 0, + ALONG_Y, + ALONG_Z +}; + +// Now, we would like to do all of this with projection traits... Unfortunately, it's missing +// a couple of functors (Has_on_negative_side_2, for example), which are necessary in +// CGAL::Min_quadrilateral_default_traits_2. And while we know we have a generic case here, +// it's a bit tedious to get something well-defined in the generic case: for example, +// what should Has_on_negative_side_2 do if the Line_3 is orthogonal to the projection plane? +// +// So, easier to just bail out to real 2D... +template +std::pair +compute_2D_deviation(const PointRange& points, + const PROJECTION_DIRECTION dir, + const Traits& traits) +{ + typedef typename Traits::FT FT; + typedef typename Traits::Point_2 Point_2; + typedef typename Traits::Vector_2 Vector_2; + typedef typename Traits::Point_3 Point_3; + + std::vector points_2D; + points_2D.reserve(points.size()); + for(const Point_3& pt : points) + { + if(dir == ALONG_X) + points_2D.emplace_back(pt.y(), pt.z()); + else if(dir == ALONG_Y) + points_2D.emplace_back(pt.x(), pt.z()); + else if(dir == ALONG_Z) + points_2D.emplace_back(pt.x(), pt.y()); + } + + std::vector extreme_points; + ch_akl_toussaint(points_2D.begin(), points_2D.end(), std::back_inserter(extreme_points), traits); + + CGAL::Polygon_2 pol; + CGAL::Min_quadrilateral_default_traits_2 mrt; + CGAL::min_rectangle_2(extreme_points.begin(), extreme_points.end(), std::back_inserter(pol), mrt); + + CGAL_assertion(pol.size() == 4); + CGAL_assertion(pol.is_counterclockwise_oriented()); + + // Compute the angle between the angle necessary to rotate the rectangle onto the reference frame + auto bot_pos = pol.bottom_vertex(); + auto next_pos = bot_pos; + ++next_pos; + if(next_pos == pol.vertices_end()) + next_pos = pol.begin(); + + const Point_2& p = *bot_pos; + const Point_2& q = *next_pos; + + const Vector_2 pq = traits.construct_vector_2_object()(p, q); + double n = sqrt(to_double(traits.compute_squared_length_2_object()(pq))); + CGAL_assertion(n != 0.); + + const double dot = pq.x(); // that's the scalar product of PQ with V(1, 0) (Ox) + double cosine = dot / n; + + if(cosine > 1.) + cosine = 1.; + if(cosine < -1.) + cosine = -1.; + + double theta = std::acos(cosine); + if(theta > 0.25 * CGAL_PI) // @todo is there a point to this + theta = 0.5 * CGAL_PI - theta; + + return std::make_pair(pol.area(), theta); +} + +template +void optimize_along_OBB_axes(typename Traits::Matrix& rot, + const PointRange& points, + const Traits& traits) +{ + typedef typename Traits::FT FT; + typedef typename Traits::Point_3 Point; + typedef typename Traits::Matrix Matrix; + + CGAL_static_assertion((std::is_same::type, Point>::value)); + + std::vector rotated_points; + rotated_points.size(); + + FT xmin, ymin, zmin, xmax, ymax, zmax; + xmin = ymin = zmin = FT{std::numeric_limits::max()}; + xmax = ymax = zmax = FT{std::numeric_limits::lowest()}; + + for(const Point& pt : points) + { + const FT rx = rot(0, 0) * pt.x() + rot(0, 1) * pt.y() + rot(0, 2) * pt.z(); + const FT ry = rot(1, 0) * pt.x() + rot(1, 1) * pt.y() + rot(1, 2) * pt.z(); + const FT rz = rot(2, 0) * pt.x() + rot(2, 1) * pt.y() + rot(2, 2) * pt.z(); + + rotated_points.emplace_back(rx, ry, rz); + + xmin = (std::min)(xmin, rx); + ymin = (std::min)(ymin, ry); + zmin = (std::min)(zmin, rz); + xmax = (std::max)(xmax, rx); + ymax = (std::max)(ymax, ry); + zmax = (std::max)(zmax, rz); + } + + const FT lx = xmax - xmin; + const FT ly = ymax - ymin; + const FT lz = zmax - zmin; + + std::array angles; + std::array volumes; + + FT area_xy; + std::tie(area_xy, angles[0]) = compute_2D_deviation(rotated_points, ALONG_Z, traits); + volumes[0] = lz * area_xy; + + FT area_xz; + std::tie(area_xz, angles[1]) = compute_2D_deviation(rotated_points, ALONG_Y, traits); + volumes[1] = ly * area_xz; + + FT area_yz; + std::tie(area_yz, angles[2]) = compute_2D_deviation(rotated_points, ALONG_X, traits); + volumes[2] = lx * area_yz; + + auto it = std::min_element(volumes.begin(), volumes.end()); + typename std::iterator_traits::difference_type d = std::distance(volumes.begin(), it); + +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG + std::cout << "volumes: " << volumes[0] << " " << volumes[1] << " " << volumes[2] << std::endl; + std::cout << "angles: " << angles[0] << " " << angles[1] << " " << angles[2] << std::endl; + std::cout << "min at " << d << std::endl; +#endif + + if(d == 0) // Along_Z + { + const double c = std::cos(angles[0]); + const double s = std::sin(angles[0]); + + Matrix opt; + opt.set(0, 0, c); opt.set(0, 1, s); opt.set(0, 2, 0); + opt.set(1, 0, -s); opt.set(1, 1, c); opt.set(1, 2, 0); + opt.set(2, 0, 0); opt.set(2, 1, 0); opt.set(2, 2, 1); + + rot = opt * rot; + } + else if(d == 1) // Along_Y + { + const double c = std::cos(angles[1]); + const double s = std::sin(angles[1]); + + Matrix opt; + opt.set(0, 0, c); opt.set(0, 1, 0); opt.set(0, 2, -s); + opt.set(1, 0, 0); opt.set(1, 1, 1); opt.set(1, 2, 0); + opt.set(2, 0, s); opt.set(2, 1, 0); opt.set(2, 2, c); + + rot = opt * rot; + } + else if(d == 2) // Along_X + { + const double c = std::cos(angles[2]); + const double s = std::sin(angles[2]); + + Matrix opt; + opt.set(0, 0, 1); opt.set(0, 1, 0); opt.set(0, 2, 0); + opt.set(1, 0, 0); opt.set(1, 1, c); opt.set(1, 2, s); + opt.set(2, 0, 0); opt.set(2, 1, -s); opt.set(2, 2, c); + + rot = opt * rot; + } + else + { + CGAL_assertion(false); + } +} + +} // namespace internal +} // namespace Optimal_bounding_box +} // namespace CGAL + +#endif // CGAL_OPTIMAL_BOUNDING_BOX_INTERNAL_OPTIMIZE_2_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 7dafd269b66..5a4a8819b6f 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -171,7 +172,8 @@ void construct_oriented_bounding_box(const PointRange& points, if(use_ch) // construct the convex hull to reduce the number of points { std::vector ch_points; - extreme_points_3(points, std::back_inserter(ch_points), traits); + CGAL::Convex_hull_traits_3 CH_traits; + extreme_points_3(points, std::back_inserter(ch_points), CH_traits); #ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG std::cout << ch_points.size() << " points on the convex hull" << std::endl; From a2f8dcf03406ce4f98837aec1a2b8e1df4e03002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 25 Mar 2020 15:58:23 +0100 Subject: [PATCH 143/150] Misc minor fixes --- .../Optimal_bounding_box/internal/evolution.h | 28 ++++++++++--------- .../internal/fitness_function.h | 4 +-- .../internal/nelder_mead_functions.h | 12 ++++---- .../internal/optimize_2.h | 2 +- .../internal/population.h | 24 ++++++++-------- .../oriented_bounding_box.h | 4 +-- 6 files changed, 38 insertions(+), 36 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index d6649fbe28a..187415d02ed 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -8,8 +8,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Konstantinos Katrioplas -// Mael Rouxel-Labbé +// Author(s) : Mael Rouxel-Labbé +// Konstantinos Katrioplas // #ifndef CGAL_OPTIMAL_BOUNDING_BOX_EVOLUTION_H #define CGAL_OPTIMAL_BOUNDING_BOX_EVOLUTION_H @@ -59,7 +59,7 @@ public: void genetic_algorithm() { // This evolves an existing population - CGAL_precondition(m_population.empty()); + CGAL_precondition(m_population.size() != 0); //groups 1,2 : size = floor(m/2) groups 3,4 : size = ceil(m/2). const std::size_t m = m_population.size(); @@ -86,8 +86,8 @@ public: for(int j=0; j<4; ++j) { const FT r{m_rng.get_double()}; - const FT fitnessA = m_population[group1[i]][j].fitness_value(); - const FT fitnessB = m_population[group2[i]][j].fitness_value(); + const FT fitnessA = m_population[group1[i]][j].fitness(); + const FT fitnessB = m_population[group2[i]][j].fitness(); const FT threshold = (fitnessA < fitnessB) ? uweight : lweight; if(r < threshold) @@ -105,8 +105,8 @@ public: Simplex offspring; for(int j=0; j<4; ++j) { - const FT fitnessA = m_population[group3[i]][j].fitness_value(); - const FT fitnessB = m_population[group4[i]][j].fitness_value(); + const FT fitnessA = m_population[group3[i]][j].fitness(); + const FT fitnessB = m_population[group4[i]][j].fitness(); const FT lambda = (fitnessA < fitnessB) ? uweight : lweight; const FT rambda = FT(1) - lambda; // because the 'l' in 'lambda' stands for left @@ -122,14 +122,16 @@ public: m_population.simplices() = std::move(new_simplices); } + // @todo re-enable random mutations as it is -on theory- useful, but don't allow them to override + // the best (current) candidates void evolve(const std::size_t max_generations, const std::size_t population_size, const std::size_t nelder_mead_iterations, - const int max_random_mutations = 5) + const std::size_t max_random_mutations = 0) { // stopping criteria prameters FT prev_fit_value = 0; - const FT tolerance = 1e-9; + const FT tolerance = 1e-10; int stale = 0; m_population.initialize(population_size, m_points, m_rng); @@ -184,7 +186,7 @@ public: if(CGAL::abs(difference) < tolerance * new_fit_value) ++stale; - if(stale == 5 || gen_iter++ > max_generations) + if(stale == 5 || gen_iter++ >= max_generations) break; prev_fit_value = new_fit_value; @@ -194,10 +196,10 @@ public: continue; CGAL_warning(max_random_mutations <= population_size); - const int random_mutations = m_rng.get_int(0, max_random_mutations+1); - for(std::size_t i=0; i(max_random_mutations+1)); + for(int i=0; i(population_size)); m_population[random_pos] = m_population.create_simplex(m_points, m_rng); } } diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h index 9a565992912..b19ca993630 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/fitness_function.h @@ -8,8 +8,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Konstantinos Katrioplas -// Mael Rouxel-Labbé +// Author(s) : Mael Rouxel-Labbé +// Konstantinos Katrioplas // #ifndef CGAL_OPTIMAL_BOUNDING_FITNESS_FUNCTION_H #define CGAL_OPTIMAL_BOUNDING_FITNESS_FUNCTION_H diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h index a672ab61369..1d2b0c10666 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/nelder_mead_functions.h @@ -8,8 +8,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Konstantinos Katrioplas -// Mael Rouxel-Labbé +// Author(s) : Mael Rouxel-Labbé +// Konstantinos Katrioplas // #ifndef CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H #define CGAL_OPTIMAL_BOUNDING_BOX_NEALDER_MEAD_FUNCTIONS_H @@ -85,7 +85,7 @@ void nelder_mead(Simplex& simplex, { std::sort(simplex.begin(), simplex.end(), [](const Vertex& vi, const Vertex& vj) -> bool - { return vi.fitness_value() < vj.fitness_value(); }); + { return vi.fitness() < vj.fitness(); }); // centroid const Matrix centroid_m = nm_centroid(simplex[0].matrix(), @@ -98,10 +98,10 @@ void nelder_mead(Simplex& simplex, const FT refl_f = compute_fitness(refl_m, points, traits); // if reflected point is better than the second worst - if(refl_f < simplex[2].fitness_value()) + if(refl_f < simplex[2].fitness()) { // if reflected point is not better than the best - if(refl_f >= simplex[0].fitness_value()) + if(refl_f >= simplex[0].fitness()) { // reflection simplex[3] = Vertex{refl_m, refl_f}; @@ -122,7 +122,7 @@ void nelder_mead(Simplex& simplex, const Matrix mean_m = mean(centroid_m, worst_m, traits); const FT mean_f = compute_fitness(mean_m, points, traits); - if(mean_f <= simplex[3].fitness_value()) + if(mean_f <= simplex[3].fitness()) { // contraction of worst simplex[3] = Vertex{mean_m, mean_f}; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h index 74306a03c4d..57374162746 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h @@ -102,7 +102,7 @@ compute_2D_deviation(const PointRange& points, if(theta > 0.25 * CGAL_PI) // @todo is there a point to this theta = 0.5 * CGAL_PI - theta; - return std::make_pair(pol.area(), theta); + return std::make_pair(pol.area(), FT{theta}); } template diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h index 67893912b51..2fc1ee3e07a 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/population.h @@ -8,8 +8,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Konstantinos Katrioplas -// Mael Rouxel-Labbé +// Author(s) : Mael Rouxel-Labbé +// Konstantinos Katrioplas // #ifndef CGAL_OPTIMAL_BOUNDING_BOX_POPULATION_H #define CGAL_OPTIMAL_BOUNDING_BOX_POPULATION_H @@ -29,21 +29,21 @@ namespace Optimal_bounding_box { namespace internal { template -struct Vertex_with_fitness_value +struct Vertex_with_fitness { typedef typename Traits::FT FT; typedef typename Traits::Matrix Matrix; - Vertex_with_fitness_value() { CGAL_assertion_code(m_is_val_initialized = false;) } - Vertex_with_fitness_value(const Matrix m, const FT v) : m_mat(std::move(m)), m_val(v) + Vertex_with_fitness() { CGAL_assertion_code(m_is_val_initialized = false;) } + Vertex_with_fitness(const Matrix m, const FT v) : m_mat(std::move(m)), m_val(v) { CGAL_assertion_code(m_is_val_initialized = true;) } template - Vertex_with_fitness_value(const Matrix m, - const PointRange& points, - const Traits& traits) + Vertex_with_fitness(const Matrix m, + const PointRange& points, + const Traits& traits) : m_mat(std::move(m)) { @@ -53,8 +53,8 @@ struct Vertex_with_fitness_value Matrix& matrix() { return m_mat; } const Matrix& matrix() const { return m_mat; } - FT& fitness_value() { return m_val; } - FT fitness_value() const { CGAL_assertion(m_is_val_initialized); return m_val; } + FT& fitness() { return m_val; } + FT fitness() const { CGAL_assertion(m_is_val_initialized); return m_val; } private: Matrix m_mat; @@ -69,7 +69,7 @@ public: typedef typename Traits::FT FT; typedef typename Traits::Matrix Matrix; - typedef Vertex_with_fitness_value Vertex; + typedef Vertex_with_fitness Vertex; typedef std::array Simplex; typedef std::vector Simplex_container; @@ -127,7 +127,7 @@ public: for(std::size_t j=0; j<4; ++j) { const Vertex& vertex = m_simplices[i][j]; - const FT fitness = vertex.fitness_value(); + const FT fitness = vertex.fitness(); if(fitness < best_fitness) { simplex_id = i; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 5a4a8819b6f..2eded978f06 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -134,7 +134,7 @@ void compute_best_transformation(const PointRange& points, rot(0, 2), rot(1, 2), rot(2, 2)); } -// Following two functions are overload to dispatch depending on return type +// Following two functions are overloads to dispatch depending on return type template void construct_oriented_bounding_box(const PointRange& points, typename Traits::Aff_transformation_3& transformation, @@ -302,7 +302,7 @@ void oriented_bounding_box(const PointRange& points, std::cout << "Random seed: " << rng.get_seed() << std::endl; #endif - // @todo handle those cases instead + // @todo handle those cases (or call min_rectangle_2 with a projection) if(points.size() <= 3) { std::cerr << "The oriented bounding box cannot (yet) be computed for a mesh with fewer than 4 vertices!\n"; From 6a2c04c3eee8e9bb0901875779115956fa3fc1f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 25 Mar 2020 15:58:37 +0100 Subject: [PATCH 144/150] Update algorithm parameters to sensible values Can now be put to values close to what the paper recommends --- .../CGAL/Optimal_bounding_box/oriented_bounding_box.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 2eded978f06..6157e282c9b 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -101,9 +101,9 @@ void compute_best_transformation(const PointRange& points, CGAL_assertion(points.size() >= 3); - const std::size_t max_generations = 50; // @todo hidden NP - const std::size_t population_size = 50; - const std::size_t nelder_mead_iterations = 150; + const std::size_t max_generations = 100; + const std::size_t population_size = 30; + const std::size_t nelder_mead_iterations = 20; #ifdef CGAL_OPTIMAL_BOUNDING_BOX_BENCHMARKS CGAL::Real_timer timer; From ff10c1594e783c45d61e04937f910f68f5922d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 25 Mar 2020 18:46:33 +0100 Subject: [PATCH 145/150] Remove useless data files --- .../Optimal_bounding_box/data/linear.png | Bin 25356 -> 0 bytes .../Optimal_bounding_box/data/sphere_1k.xyz | 1050 ----------------- .../Optimal_bounding_box/data/times.txt | 5 - .../data/random_unit_tetra.off | 11 - 4 files changed, 1066 deletions(-) delete mode 100644 Optimal_bounding_box/benchmarks/Optimal_bounding_box/data/linear.png delete mode 100644 Optimal_bounding_box/benchmarks/Optimal_bounding_box/data/sphere_1k.xyz delete mode 100644 Optimal_bounding_box/benchmarks/Optimal_bounding_box/data/times.txt delete mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/data/random_unit_tetra.off diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/data/linear.png b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/data/linear.png deleted file mode 100644 index edb4f44fc9887775259a16c1b62852a1e3ddfec1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25356 zcmeFZWmr~S6fOD!BGSHsgp?rNh?JxViUNulNSA_9lh0)vc6Ps;Mht!*`ba-{KmC#V#XYrFmBnZOlVxq2>Z9K( z?5`N;{le~kRUlNqB1k1TB2gzfzM@CbG;h07nY1^uQfZ#tvomaz7icZMCvlszqwq2s z{)A2$IAAcq9~)CP)O&w_e@6;zDdYpA)Htco1j%cz#czD%~~ z-$=Ezl7`7LP>v)awBirtkI#bT z49oTp4P{|uY(9`!4Io8XN;{WXDk*(HmRyc|roE|5tY}6ZS!eJ6dyw#XigXroDl03? zDJqs!k%pPgt*j^}i8+Zm69oIqS)`+4yu%|R0s;c2I%E0mqZz_)U}9pjsunWV*4Dz0 z3=D&JFnIkwr>CQ@UiB#}6H0#=**G|;!o@T#$l1XlA`)A7dKmcS3oHAJ?7szpU*G%B z-ox`0VT2Egi*HFwOT%``uc8h!TUc8Q4Gkr(J3AF^Z*QONiXU7Jmyux%+~#m0dYa{5 z&VS+>=s)|&1OtiQ!SFadDnTg)f{&cI#1far$L&?-UTiN_jpnNs89qso@-o$0uo8Y* zpx46nrEOVoLCiKeWMeLOB1y#2vj@LT5gi^bRa z2EKK5lBcJq_R;hV46D}#uKE&SbW|RTbYS{nCAkp&DN}K<5>&!Z2~;cfpiCrp=)Qc4 z3TdWG-J0&^97#T@!*)A8SRiFp@`Oo5G2FOeEleFm!Pn^2)%RFZac_0ZD@e1x$goRq zd8lCdPYJ$XlULJ}&Oo+mcb=&Gv2du^<|PaajAz*|!+Io+mcNxSGBIs5;`3a-a^-Du zGTl{<7q7ktQFbp3=4to1?Tz`t@0jGHUd^_Jeg6DeIN7rQ3mWd@%Q zdBtqV%Bf?bg%kf%TGtz!K2ntVhnR$z#hK-UqR$!WH)lKOUuvAHD;-wQXZc#)UbORF z=uVP!89vEH9wFj(cuUk_^@2hhyYlBtOM`h1S|n)no!77b8fcG{n5y^^QhnES7?V{{ zAmHQUvs?M|``~z}K!5R9I)0VITE?5DfpmI`3*ZKwa*S!d|f(|#N%BLHVX_o$j04|%(Yxr z1YYE65lX#$Ns;WfONon%+r3nG_>bcX3CUvrR}xfS^(G#_QTMBV{a=^Is-hQ?J(7~d zU2dO=X}KR5{D|U`uX8^^#R!^Tn{YqkvYqd&__sU+W88olFR&Q9ZP=64m91Jtx+){1 zr&qXlyMp}<#>jOK$5VymEcFcTDa9rp(}SuQpO&dUKQ_q%F^`({=q=ZX(D?j=_4%N| zkXq@d&dhJUy}v%sB7<$$pQ{-U`zFcb)aiQ&O$X$w2MP+auo-Td^#3i)+u7S=@i;x6 zZIAG~!t_vM*L7{YCXvf;=6mprH?f4y(m+nJ$?t!Kro`03_0uhZsx{66U2y_fDKH`3 z3uh;59wb+;G{W5w%+GQ)V$<%2ZcYdCZ2rs2yWOM`d`*Bt-1!y?3C_*g_H50nsQIq= zzCr`}&AE(29zY^pG$gDP>}1^>1#L8FyI|uRWNj`u96)AzK&5p^z+**xRdA zT~iY)>cCxM@>>sL+I77F$8~?oZ`A#0Mdien`(^(12$sj+M@Hg*L~`_HC{hjNYIa0C zmT=0cV?d+#o)^B_)nZXeCzB#4wY_axH}+X=Sd#wpleBw~Uv*T;s07VY+>UmiWxWUv zrV=WIRd`R%^JwlzWZqG&fJwiVdlHYf1SS@ii2d@=)x6-KpyrX0qxW3FsH45LOsyJc zO8Xbay(t(F3e>ed7sW;yxIxH$jrRCn3;TqjO=24t=o~X z!zy)Gybv<^-L0*39-WqTC-c=tu;q~5AIa(N2MQAB=NwACWwDWx6`Pe1BhyCvDQAr$IyH}1_&fzjZv zFHde5cE&V7WUp^-elq#}?VYc0q5FyRqa?9dW7aCNWckx4qSPS@t?inodI1Ki(dJo3 zC;YGXr?&xAfXbn8JuV6Jm!s` zh1Rq5t(_evft`7ErYx1bM`~(nz6E~dS!yNh@q*?*E{6-6|B=zrnKaN{G5I%`_gGHu zQXm*!)|W_f3E2DQ+gxJ11)n6G;mVkvBKzs}B}BZ`Tg{e4@T zTnL@yBW2}Zguj(a%~YLt{4X>Vb^`$lcT+boU-w0FC1E=+`RMiD{|VJ@2oY5x@G+9U3&yek$x*tsrkrv{vI(~ z)vQ#1xm<_o3kr$OQ{{5#{aF&ne{8~bmj-gY54O5mzp(n$nPs56bJm$5bKs2{z98c~3+Z^>WtJWkg5?;F?wKd;GdF%CMahKgr-l~1)U^>a94<9aH6Eu?xr4^@;a219EEaWPQ zMn@Ofvh?Q?VqL74l(#gPTp;uo+r7)gV{UMHFbFYJxp&Jpdv_)nzn!SC zRjL)^)Wj=uB>$RK0tsb(Fd8r^fy~I$T;`%*68$RK`adirMU7D%}x5)@N-B%ddxjt-cpa zI&U;)v-5e2eAE}Zl}fY6eqZ{B2?Zo<+5X>0)$X}G{E^6;uH}u%_)pHi<5lulRacx_ z-O0uKp^ay!Mh>zz*ylhmY?;r2yFbUYabl&cX{f+ng)vqMXVhWbGmFJMZBjYnEO|AxrV z8w$zj+xKGX!-WR1yt<8wV>7?%`VdUFM3&df!%z{_q`SMyrBolZM&oh@> z;3@-yP6Or^pTO_c_X(BuD?hxja1vVW{jjkW(P8Sd)0(g3quyQRP>8mS7u@~LI4FzJ z8_A_^n9(U@K_KoN6Kc>Ax5ZsQF_Em-@_ty;*WZ8i;l{@L-?V(k4IkUR3CrD`NR7J~ zz0ctuvQ9Bq;hBRQ_d5@$FL@<c!opNxK>k3MS>b=loK()0t^XLGo1Y`;2+8>95%vmAOLPkXJJ84_i0 zZ*NC!sp()Y0hM4-)oNv6Obmsdp5EU-C0Sbs1^TT}w#e<*#uWkG;Ns)YGzXBNs6}kv z0SvZXtJy0w9puh{9s}_4{$Sl{hli)~&C>U3r>&bBk{+k7fN<_Z zxi8=hggSMZimHQL+qGeLWu#&u$>sH*Vm6jX3H4J}ye_+Dr50m9K0k;+InKu#v1(P9 z^RF8k9`A4Te|_qgDC%$%O2XmZTF+z2laF(f_t9YrTxze>4vDBeZyHPn@?7WbUHvwD zPnA|@wA`9Zhmi7Sv(xHmh3!Df9q;T$AAEI4YA;4g&2#?#{kv3YsiBd8{SsC?THIlG zS=Dr+)@=al2G5x^$xQC?7xlryft;#CfyGb;*_-2K7GoWG6_55tZ9{h;iK;~zsM6fF z%O7`~A?z3&9DE-dS_ae3S^uZbqs~AzO2BqrfkRk$=%55jR;kHAwv$hE;LZ<@JmFA4 zk(_=_x)8@d3OPHR7t^D&Mc1nP9?HwxYVjNVAmsp<^uomC8+^-~qm?rCwYoER-y^72 zeb>aD?R?jY0FP$X)&ja!hk`dS;c@2HvH+cerTD>Y1ZB54)cY5(+C|6CP<3@hsEL+( zQ}4oXk?(vCg~Ig5M>hCz0GgT{i0>tsAIjPu8i!F`#bk*wr)tLyy^fxqo@)XoAFp1% ztaAeOL&eR!Y{I?jH&SJ-)zspiXTRh#1>uU>^`4V*pd z)7)9mkQu#eQ)nQ*H|nz&$*jn^G{jexRmrB}a<)rqF@d??L@c>J6bV=^q^HLwwy=;d{F66SB;9zHxql)l4meQXbOrph=0^jormPkzu!$$R>FDzCvYvsKW3J_ch3gk=hH7r zsT>k@9%t_76;#9fA|c%3;cKhnBJMEZCKSn`V%YE&+tc`gxcxGPW~Cj5&e84)BO{|y zxs~qbLeHA3jI1ou(1@%Z{Y?w~RiJ;rv8jnt(p@Z){dwj5QdK#(U(=m{D@+M*0{k_~ znq^-9y70?yGKd;i+YMVb5Q^C7t+H`EZhCsJ{CwWit>m*;e;)+}2I@nL3t7bvk`4y1 z!>R^w5ig4j3AxluI~N;odUSW-b6*R!f4;R~Bz8JawV%ncbr0aXKPA6mK5Xjh>gq3m z4O3H7v$gAzpkL4`I1=J;b#=W-ElN#fRF-9+O4+D=Sh2l?f=d$?ekH;-tz25)+pC)w zQ293Z3weDM;Ni|>$>gvb_iw@`Rx34o5XK;j;(wI?svXD=8I9c<9<8@?FiNwDS{gva z?gw+xrUPy{mB@GIv5W;DQ@;1d!M)^ZGuOFm0Y!UdWJELU6-k)|2DPx&b@M;P*1pwt zBW0Eg(3uv${@Li13jhgeO%&q=4V>#fe`cJXnc)|+kgIi#l{`L~YQX8*e=jfX7tw@4 zPv2YZ^nL5}GB2W&O$;jqiSCd>;=>-L&#GE#jQl)(eLbpF$;x!xMg*kXxVsaJQ z@9B8U+KSw3+|Rd@Cx&=VZG(b>s=vCt_opi4 z7s{g07Um=9{a-^2Ff1LqK2Ka9QTt_}DzLh3Rg?j2fBN*vKPYH+e`5w{6@x_=A^@C! z|GvIROxp=*wK+4{{m0**X_U9^z7+lb_8@{82|_|D!F;10TEOW(drWzCX2XR@gF7_z z651-KmbKqd;U9ivz2iqjvk%D;siN}H+;hO4;OI2_qdVgS0-?%oKtr((J#T^8@J(N0 zx}@~M@LY`woBllQWM~q@!^5SI0#9em2C^w(zoy;wBXZsOtwMd<&L4td15#(c`G_Fu zMXpA>$JvoKG}reL3@c*8SmV6&WBZMPEO0&0*64P|@Ii2S!oI!fe!Ndro9thn`tHKt zahgi|n%*?h%c!gDL+a75M9T;~fByVQKzZ{WAl7gp%W+PRvB=6pZb&k$)6>%lp-?22 zS@(Y2wtvSYKbcI%n|afq^B{!Ac3EBM{{h*nnB)HMu)bg9;;P!iXznhg)i{w%|QiIw6(3|nVI1Mx7vlQ7qKrSt<{N^etA8&&}n&p zRcy2E2Bn(6^3$h4l{h*%ZTwcz{+X@H|0qE?EcI$WWHh_KyDZlvTS4=5*5NO_X5^ z?1jg$SN;M~XVjCF4%-2C#ZqAaHgvldS=y5Oho<{~ZxnTXaU>|C#&XOW4d?S@;8u`a z0HklwuvXX9a+IEY8=E}m&Oh8+7kd?rFajaRF?A<+wbJ>il}rw5^Cax$ue11K>JUA} z$~xzxXRp+q;_duv7_BhOsq2ads0r zA;aA{FZo_pkvZ=cSFsnwwm!maHy$4!N0?mw))0)#moHoWmd%j0A?YX-ww)(v4WUVs z^1_T0W14;sOSSzP(2%W0odl%m2==`d21tx|x;z>|l>UJR=laAkM0E!vvTvgQr_ zF(EC%S}lHU?d||0_uV2-OX(Lz==6*Xo73Y1^_Q`7-CG+QPdbwQIYiz5m@)F2#i*`5 zPPm2tlFPH~U0GS#IIFA-qme3EwklRvoL3Wum)Cj|@nrhcsg20VGo?EZd1mk+_jp2yevmQT)I#(%X1>*%9V)zWFTlstH%O<2j z3VHs3`xCbg@`dwWIGqeV1|8CCK>pvT_)qGv;57wu5MGOM^m{~%efE5JkLL(38D77Pv^5%C)CPQdnuA*L_NZh;Cyb?xfn1j z?S1rHJ7el9Y^SFDV7OxbhDiL5K7mp(2e%-b$Ls`uEY}x#pZZRaD*jnf+$m6kF{It$e zdj1~mxC=e;Oj_{xNRFwrP+0Kh2j_D>%q2K*q0X{S02%FL31dq|2J&;|vHj76o6+~Z zmS!oP>zzr2p<;Rt&lxDc;J<|6sp?F?4Zaq;?l7pCZyw*6T+Vp@g3HPkg|VYQbEwS5 z2_o5tHN)DjenqaIHB1o2aoUROS^CYN^zuv-(~pH}HH}b6X4a4TB~s-^@GyRdU=?bTPeB@#vgQ zP%Uxdw_7E+A0k!jx;}9hrztLDLwP=`?3ZOkYNfYCT}Pc*IMpvc&-$Yo*+%%^JHD@c z)3rQqGpEp@t@L5+YQQM(`7NC?_wRmH28!qOG~bYrlr=@QHhjsL3>cQSNY~Q};|-US z9sC76vS<4wWhsbyYg5qwY`^Zz+kWLbcX#n&qNF8E*6>3_vSl2b@VL7)u%71;JJaAj z6>nMJ+B#k-QyBXlnE=n>#vEIt{S${vmpq9j-{tdGWnF1UpTALS$eq`$2_jfm*<+Zr zzNwT|v4>HgE1$~Q6xE09u4m$~EDa67wS=c3k=@KsbNkiqc8*d5b=^AVOEO1e$Lexu z4 zntkB7%=fb57q#TcEro|2tGOYE0ATN*;|M55)l_?Vmk+(gziFaSFJSP;V~eKfhMSplNk+aD&#(mo*xGa zsu{ZZyFh)jsTH$=tSDmMM7<$r}eBC3`C{zm@6KCQIggIeCs zJIlHEMn8_%jg@1s>wW$Dl~beq1IR@{q5zXPBI0o>#-&zlrS~!$W zLZZVJO3HQs;)@e?lCTVVK%m5GS*ntSWD#%^5fif@{0AWN_JBfJ8L|6%4DWmzKF~8C zzgfXkFRf2>_@f!?uWq}9`n$9w57-@{?WU%t`m0rQM(UXHUnGOO! z8(RSI95XXBO)z_jJuS`6NFRgLy2Zhxg9DN1$Oj&f-U!*1FW_B$dxdE--co@hCCU+9 z!8B@5Fe%Sd(|ng$Tn6xC=Hp~T=*<8quFpklUjfVtuS+RtMgdB21~h(%@&M211DsnW zPmZ?MW@9t#Ob!io;?y!@cKOI@48x*rF~^z&rnFr@RQw)DxX{M+L%#_mVmM4A*81tu z8no)Pm3E7bKtve>F$N-eTT^)^&#O2{HXJQPFG3DC`xtdGm?~c2q`G>tOGtO$s%!JA z^?8;KM}8H+GC6tYWpUfPJ7{Z4Bz=V~hsBwEKS+1ke6YXB;v z{X3AX5Vqv7nm{=-m`BIRbZ4YA-<+!di!RJ;I5tu|Y)+Eg$RrNig0@^{2wxUp;*sW8 zv7_4=knCOIo>z?-$6cwJLQTePFh6M{Qs|8gz(e2F0z{7vC zB-i(UH4KRUnWj7U(0q}3+VB>#1UK>Uy$PvO++1Fd{aH1UVZ=eQesiBHnL_-<%*XNi zepnfgRrX1&^^tE$;^ZcR5I8+aeN0DkQMP#nfg#OLSBCYY91rHm*LQr#xBvplSfG&! zd0ec6vAu+2)GZ}<35wRbUg z8O8T#JLA?KUwKbjP{xe@uXIj7_z~sfv~^wJ_wpJC1MLHN=jKFJvg$L5XIb{T;rBsr z7+_>5MHbOoCG+v!iCROW&_*BK2?^F0ovYtunz0ddTb`Eeep9}Bd4kw!vp$ATsrU=j zSpPsoRk0S5j|MdT;R7oDVJunw;SS(P8I5xwSsn<$i4XI(gWwd;t$xl8z<&(U=l76n zX=N;tD_qtny7->F3Pv{gL|9Khf?~ngL;T>e{25;T(1pEIu z0IG&*G{Zgq=o{d8!kGlM`_)jsZn4E!oHq{fO}oEJ@mVBjYmB;M%r{GMG~&>G*6gJi z$U{j)Zv2kACoB7;#N;_Did*vs5Cfg%)-%w;hSQ;X1 zug4i4F*GbB5hwQ$bb_3MrDH zqBvCn06k^Xth|NFdXe)9>Irg_O&~D9Q(L*3idhrya3N-Fo>E6e*4le&0vqWg~J!vl&kj8qje zD2+0U#H}r$k@#$8<(&6c6`@3-_94Z_in|Cxp|Ou-WeDG@-N$Tfoa|>~RU;+ie#fi` z9gWQBhmK$jGswOthdXI5d#jY)J-~tzOCEm!^4SHi3Nx7ga+n#vL+`Y(S+f@o6=Ga!uWjyLfUKm_W~ z@yXraAuy3f@u=cq?jA`=H|DVuBv=r19sF%Hmy51nky`SRP5G zO6Ti%#qQHH=wU_UdqUk40YVwPAy+6UVsyP;`!%IPd8p`F9qauTIXs^8h^DByW2J0F zGt%FYH+l&ZxZo=g_lBV5T)1#yNVEI-S6o$@!sV}-ovjZdu3Kukn4&kVoX_kVP%+?H zaX;R;|09~m(t&O8Gu?G`d;jW~(l=64HocIiPa8%?#^Yoz^d1S7PjXI1aj6#qmsr(t z8C_v*J1;d>iDWwW6v!IfEwBemjr)AjH}2(IPDp%H$qNY$eeAmc<}0J824E+Iwzx-< z`0TVyWOwr|zY$1I(ALOsPuXbJYpJLbHB4E3h&vrA##bUK^cSX)APAMfix-NYQPCD4 zE;$Y;r>^m+(!rlh@2CavQvGHr#Z+Z~iHB9G-VQ_ZI3G!NuYSxy36#sVS*6}yHg44J zip#fS8@2XBKGTToP{hP|S?4Yeh&5f>2M_Vcfht!3G+9;06?BEhcr~vjEtK?lLAK)n zx!g$`3@cE;ZkY}Qd3vIf+;&w#{eK7MK7?QgG-w~q!hq?r*GR6dA#Blq>GVk3YNJG6 zR_0g5DB}nA=ik=*pFZ9I1;|MF44B)E!_^*z|ot#0V$CA_zxlD@kuNTHa`DAzzO15jmp_)!N0 zMNX}13f>t^axOI)my=8mhO$2%r}~ZBB_{c1l+UtXLrG^4>Y8Krnq|Hw!#<61g=8vN zXcA04+7eY+=rFUCJxg+GEJVM`2Tw~!x8-o54=l;BQkcKv$7J`nx=q*JR6e;L=!^;j z4zlLpCP%WXoSoga!9pmtNF&hkMXt%<(pat8(*m~@+ly=p&=V)YyV7l?sH}Viszrue z7{hEwbSSK^_5S))ygMO7xI7n9sqxopa3Yw8p>WBCSXZFRAyA=XN$TjH06XOJNEuJZ zo+`u$?D1E?kpt}+_wggCTJh^UdU~I>;y`l^nd^uyvYL_xi;A4IG$y1rUg$H1H`Qbq zqXFuZYk77j($ix|-|e#D0e|kf392Fnh}403c|2gv>9jJ3-XkD5xMtc7QT9Mh zA^d%vf&1_517T-Ub`?SS>euQ*=#9&;#-Mt1t&Ua23R%)3HV5!gNVpyLf;s|2v-q0? z+M*tqP|ZfmH{u4>qI{aB%BO8X`_uzZQ}+zi$dyNsKgG8{81I<=#Kgo}$-O5t8wD$T z=>sIVBZbW z!gOwQK|@}hbe%h|E%QeXqwY8VUIE+1AZS&==ZS&_bqdT-DImKYLuo`+pPe4L9xi68 z*80JGT)X8D(Y*m$gA(_Nc z0Zajd9tUh|Xwwbgy~MVA?l> z=H>sZt%77=0A2L<@^A#SRiZ}Nf&Nr-iash@d`ElVTkf13^6L8{DRJn>To;;K9Lx!OP|YwZd>y z*kBzvbguRA*Gg01y&QMGWpeE7Ml0Rr%P2ax3u9GCJ@c2hs^FfqnfrmJq;wiS0K9~N zJSuhoeP8X2*SEaiU)Aj(gG>Hwj@s@Cty&A{*o!tZE%@h&(L5#uw&bSj9Ih`|NA>0gR2w(sQ(KYi*9 z=XN`+pKO@d@WDgy`1B_Yiz{u=Y=Sid3It-tY4FB5fZYM|@wbkZo~%2c8MyTjcAQ_- z+W1VIdxgz6Do28^05^d?Y0~v)%9-C-fT*0(Tf76 zjiu)6Jp-Wt5sPl&f}<~I-|=rBP81h^Yp5jA(@be8&zd&@{*ITS6>G~8(0z;RAtAxM z-xZe*`P(M&D>S|qIbk=ZTIqm^C_i&Y#=0Q~%wt%>n^UplqlpjUdLeFZQxT6zVGYd? z>Oq8s`8(&@O{?qG$AzG6__s+SB(I46%)O#?bu-Qj*mr82q4i*3ID@kc{;zmC-Ug7Q zTI-XXu2$l^?_+?!2Rd~0fgjA$tK@SHImx9v=wNA_rqs;qVdQeI0wBLn@StI%HN?@i zIm?&hxix?1za7F5-3ttGyTslEabIRrqJy;eMI<>g#3BzHE&oXBICr&gGkP_E1sSkL z0z73j24s@)8p~=78c}KGaG>zu=nc}v=T6Lb^;Ymxi|Bpdhkgz^10<`w3Ip|naf!2I z`QOj{R9ufp4n*v*LwE&r1rbmJ;R4X!=V=+Lgl;V;;!h6bD5bw2iwy8@djs-FShlq= zG^hsWIVq0QqYA0#!3O@Fn#jVL)C;mh}N9h;dtUK z)^@HV-VgX-6L^kI#Y}7Jed3ojf9y`||6Mp28(?@O!LT|(rRLs$N)-3E_WVR_kvAPh zj(TaV|GaNV9tsb@yV~jOp{tAJ6oz31pba_?-5*O5K9<03Z||+GQJnzN7)U8}7&W3f z7$$(%(mR?whzh48>W&xY`E4RH5mGW@s>;87xJK`Vyo=)M+6U*VwJ8M0hK#ZC`X5uP zvy%@oue+U`02TW?UV>15Y`e)=Y;HQRKT?7(anOuxhgq_xU?*i6uIS5NB)^LNzp(uN zZCn{B)@e4w9$%v*FWZF_4H5pIX)m~t2}4r>WztLnvYXl=G*g1+I!E@9$qumRmgVqfpZ6o1zC@lfw)+v`e>@7>8W#p^Eo5w*(XkgIs&jI9 zPC3cU(!mU`&i1qQjU8=v7|NGLa-4sW#s?6GMq5H9rCUSRm+~f;@SkQ#)w!R~2)7)D zQZr3wJPu5wQBR|JSwlFJ)mqJepMgNbSavjV2AunrQy>{Lfk}0;zrThLW{RA}UhiGz z{V@kRNW93gCDkKl5lKh>10wN%H)3X|#;S2q797s2udgNQfF9ECm8+Jr@1|AC&o zn*(OI?M-i$ubhST;VrR^cd?TgA7U=Cu>l#tU^BMeO&?CRJYflR)FR9JhS%PN9|l(a z)cG!J_W@x-V~iy^CaUh;1y;>J#i)TCgpvYyVN8(X&k-2lrB$P_Z#qh0zYJ0iu!k9B zQfL+M000*TEew_AYveUv;n&3bm&Yl_EA&DpwFS4%?f`5$i~FGanKS$_8c_ z0&xaZ2;@Wy(u4tW0?*M4=)N`M?O1LOx1MS;VbR{XcCp(U;&{a>NG2)MG| zC1mJFjD$z~9SbTH2?+^e3jt20c6tlCc|q`G(!x*kesu0BaBk@q0Aes!PE0>+(N9m0 z#ZG*jET~?!GK4`a@fw+$X$Yk-78dTme$9%UHP~JPl>o@Cp7qNW+(6`)Ta$-?sd!N9DY7W)KW<>@n3-{+ zz`@^RRqMDh-Mx^@C?=LLIjOU71C*5eOQb@2s)lzKaOmDeYy0*{6anXe-q4|?MD>Yq zQ@*xT9WYq<-%L0O+)qXuV)=Wkgtpg+LC>YE3%+)q{v3HjH7;hrG25T7-f`~X7tN7(b$Ts2UDqi1q@mEtm@SlYd4fIh_;4w& zdj=pOoN!}%_T@5S2u7wIL89QFMtXB__@gghmI6<`S+<%@xDvR9&Ko-?#HjnlK?^+7n7M-~EJBu9Q{|h;h(@fioeISM~0u3aI@Q`XH zCaR~jard}E+f5XWe?UtvZ#hSGt8ICCYRP5E6jp-c*HIZ2PQCgaNhw+|hX07_8rpQ= z^J^-;a8K5&Y>$ge5$NSikO*k7Si`x%ha`6FWqdU#L~syBP!82TjOxwy>w(wfs8$>d>?*cDmG2_f1)#QP?^T}&!g=ByCQWLhOSpVhAgI9oWttc7F{(4M z+|^?s<$N77;ZB8#nd0u|cxY_9I(_hLvB9eGf+7k|ZAGV%NrjoJR$Te^+}jI_C!y-Z zK1PHj$@NMUXN7BU-G8PlOYoeAwH&8B*b`47{ z6@ns82&v{G8VR%A ze~K#E6s}u@%i}o!QWz}cF_gsmhKmr@JE|6agIi%61p>6I+e#KpHlrU@azhC%~g zS7GYgue!z8>*qSkk?GZDli=d6|B_cq$K%wt zsB}+uBOAzmvJSIa@$Nh7;cA&4HUage`=N0&hFv<17s{8oK{bJr`@{s}<0y~F@VmOr zIYo-&LsKNxg=GQanUyFg033Vynn?(qTmSO%&yp#!U`j8X<~IXOzhbRpRfvJOBUKoscq-=wIP zH)BpL#b(9>+fVBuV+ z$Jksb`|oL)WK!+!aFS(ZBwjXQZ_SUPhN{Qoe|iCAbq?)@N)?d-G-JaP3I{WjrK7ol z@&q*|8%f1GVQ;_tl;?{`v+(^m0PDm1ge5RT1Ryr4owY} z;MX22pMRq)oN);bK&p6(g{I@4=KjPPx0u6-xuFU%%mX6KL@h;pys%bBY+0>qxQ)5J zN(iEqsVXc<_!~UWaDgc7WDladesQX`I%;Rkipt2#wi}S5m`uS2mznH4^s*?vRo(K= zOA1G0QZG1KZUM%T*uX&Vl$0~ewegux>|2ta9=^JU<)I8VlooF@SRJvdCkeY0t!nO> zP{ggY45*QeY1rI&2tK#D#EDun zx_4v!cx!%XZ#+O6E z?4Dnt16O?e%6ImHwex9pwx+2>lf#PIb>Ww^R9E!0lEZD*Mjpt>yz=?^N@g`yBfDEW zc$B|_H!etV?DJ8G^d(bU?+@bJ&f>*tTt9yNn4FpE>+ix~XZKv}^V+o85^y!$+r^mI zozkr8WO2QK9qZ>dyakg%#Bk&&_)92#ruuYX`6|5xy`%WSo6mM;G2M86N2eB;oG1@$ zKW7XY5zNmSn607l_;qeaorBxZ*qAUEh8pR2vglvG&Z9`m>+m|8rmXbNdnv!eQws)a zOpDcbsBvffzr%eR$Jp>V7u91V9`tTehSjpwJlepKQWJ9Pvm?S0x~#RED#F2q?SAH> zbK<w8a*Zu!P}s7t6t}(R9e4O`ZEmF_H$>_#XuciN+t7b-v-C6y{@@O zIijhGfr2Q{=}kS?jWO~!dR!YPO^5n_vF>7^$a6L8wQWz|ZyjzG!g^k~(7o8Bt1`t+ zV8)+c&}TKFk1?bXt59F>RsS>1Q;iVZSiEn(?aZ7)93)+lu4fG@WN2qpSl`=@)~n?> zAuDp*+6`IpI*0q?c-&B^GgG(KX3T8DLUvwaKi-{mIy z0x#0DrHegop(eE_PVp%#C<`gl%6~USiE~pCJGfGy)>|C3uXBlZ&D*-)I3N`3TcSkO z?@4-uveY^LGR&rLxPH|$QXq1Fz0J>lp|m`Koa;42Sv&_hxlT9rB;6TkqZpNMOpz@m zAWVP3L_y$1;OD4SuAhxL*eKhz{;BXLL6^)=$Dexn%UMt<%l9awmeuu2gm1#4hxes3eXVF1TXw9nSnx4KJhEPZ^4 zxte3MjMfKg%gjn!7~10hkN1u!GJ;ms)BU8gL;pMK#{D=KRDl1#C+6Aro-0OnF?=oZ zF#0+vY%_J~{kE)N;O78M=0^1yLe&1hew867`^>JBZW>{7n&aCjl!W*$+xY%2VZ6Ai zyf0S+i~s|rimghqwMen_7!HQ|9g}!G;C*bTZS@s}^@1p$GJc#xlO2`!T)Sza>}1T) z>|rbESCrk8a-FTc_#E2ki&E^B7CqJ_1%FJkAH=-sxTAIFQlIZ{wh+z^X5F{Sx=HD} zQv0a#ipt*sC8N8~oE{$0^cfSt!eo;fv!~_pj0Pghd$jom~7+o`` z(co{9{RwibZ0%FVaGW~CUgjP(=P#}Prcr6WBtH9Z8m~l|E0GcprDeiXZ25cKkneZu za~!q-^_k!ahoh4mz04P3q;up*6%R9wT1)Q0jJ;=0|E=ur7M<94SYXliR)+v*c`Y&gITk4t;7Y%Lb_^ zURHVS!}z+A6ADEXNiBWq<2rn2uB`R(KfwpLDa7{_xL?qyKF|D6*eo%)CnDCrOOL8A z?HgHN;5joZaxfWBafP%R8l#} zWYn&$hRg4`Nj{H6`aVo3cWpE@gEV0`qO4HCs*z3hKusuzbZPZph(xMeHkmS{r2?;l z!d9o;HQUS5FS)`kBm+>Wams^`-_!DQpTY?zFzUaz3O@AFc3V4&rgg>T5#RqsqtAKI zo`Q{VWFRxqQnYx>+(;!mJ}W-EmvQ04FFx$F+d-&3Aby1qe~gf1c(b$=XQ@Or-{8h-bD?`|lsYs|r86p}C8Mb-Klx+@aFi(ZbEK?{_ z35i-}Q9>HXR3bx$$WS6TS;~FF#^+P7C{?V?VprEpfxrFu_B=^rjgs=wnyx{^snX$=Vz;IJ z>F;KJ;(afEoUyI!xocKOU*FBoa5qI=oQ2`>MWGkd986(eA%|HFJV!g}hOpf;7ja~j zCU|v}pN5FxqP&LSvczk`(80-Ru%jY1I(q7}0yHi8E(6MK<5mqPjDQI&|z%LluiJ7BJ7`zEwfw7Z$!=`?Vqk`*rWKph~y^g))2R@z=<|*rw8&&V8Km`kb=5 zOvMx)+k6#Hi^SWo!gI=O==++H~P>(%VeMsW=>f*RY^__tKU*v06g zfty#23XJ;|od+x^nuk95h*lYx<_;N%cQO26OsPN2`$IC|TY$ywth+w(9ShbS-<=n- zWtqkPnB}+Oa|%R>$ zKH?qP7P79m%1;eDF@2@oWSJq)8Y>=<3m1^Dl}lhcBk+Q0Fun)Mxx812COgo$L?p>JQ)Z-6)|)#K2VczXZLO_ue|;+!Jjh=Ym(ZW8QNw z113=!vp}3*!?Qs_?n9eJuVrXN%^!Z=Sj0=aDX-{s9t_c|!4rx-mRPNiGUU%o=>w0-=WMp2Y zL1dp%{h>r`6LGWe)~zdbY)ME+2q8D?NqK(Ujzi(_$p*|8eVEMbay2kDrRV3*2pFBV zJyZBhKckI4jiyHGCzeY(t)yT7^d$pjD?~Udq1a?G(JoZbVl#YzNg}E_a3hjQi z0n)(8#-`%``|uN4?~OMPw5S;`1YBf)On%~&?u-aNWO7HCAZ^6eZ72qxc!!)qM?zI%Vc@T6T!F8geeQIFtV^D zS1=1E;N@-IO}@Uqkc(`E)i7y#6dUQO2i=7*YsW)G_f{lWNX>SC&Ce&MrZV82w3{~B zgL&j#NSBt9f?XbkW7+L@Aw)5QK44VoJADOsKmgHgP`JIBDQp9fW@&C!JHNEwsW^Cf z*<-nmU9Z!BdU0mJlGDhAcOV8)qi+u8~qzsgOcr>6%!6e-`# zD=fTT55x9Ga3s!qda6K_26>@rZq3`_1HuOmuqy>DgaA9Z`sMk~}qAR>lMolxtd8+LF{026n$v89FG z-``(IMC3Ru3RZpArlul5B&vc2(fIBim$|t)3LH17n1l(w4$`0WJT)CC zW#q|IGku(zWV5Ybu=MMx*@n& z+y=iwQbJyt%;|28$>`|l(3qGQXxWmszO-_9`s7JuR+i8nCph7iv)dy}OZVf0u^Ge$ zb9Cv&^$ERTwwl17*RQ8fo@z#UOh;hnYqMae{g*fB%UON$+g@4`_j7amtG9ewZw*s< zu5<6{Qyvi98WIFm93~@Je!mPnfrzU~hXO!0UJ5%9a1w6bj0PZ#l{gR5OmcE^qeo7= zb3$sW=oeQs8`@&Li+Y2j0}v_aatm{9J3Aq1o>-2gal0LuTZ_iOciR-3u8$9RzL|4E8{jiBc#xD!%`k zwK5}Q6R{2Y%2`@SK;US_VF3X`SXfx6^Wpst>In)-((9@AKLE%`9LfUhsBOy0$uT@U zlT5|SrInQry+yUPwGyxU4omdUaCjbB)#2R}zxXJpl3T$`6kkb7Jcpry-3=R71O#7O zO-xLPH}6aeOtYbrD_!YoRiCzc?pS9+ehrQofluzg9l zl8J?-4u+_2Q(vJ=FXcYHLg=4+^J`Ad{hnf9$MrEWQBej+?+>EW5%Zn}s5^maaBwf5 zH#o#~qR{Hn3!6N-+`_^_=dOn)Wvkl$KoG#26F}lcpb~x`px&IObjE#Gg@>yS_LvbU zr^=gu*3R3|^r&{a%7EICkd(C3G9xMJ3Urs!22@^k^eBkh;sClqDie^D)W1&s_RSRm zTcz0qEr}v%Zu;>jEh)(S)y&P)B%C0+D|Hd7aO>T0TQ>r{5DlsFbrImCDk*Cs{{*}D zRw>u7kARxPz{IqHK>j+GW7u@(Gztm;am89D+OyRStgIyJ0m-1_iKRzgFuYoR>vcne zN{*on^&N*GE!p-{Q*JOG{)RkD#?S-*ilGl=kmjzuut~6{URXbr7U=Pi(cCdDXb2RD zZDcH5Uieo!koUY#rURvwsWKrsxfA3pkYtRof`i2cyT0K*GK4*{C}?bL<%Cqx4ti(P zTnZqeF+F9c;>qXu$I3Fd<;zH)(UAQ~1+DreW@J!G%gVw)xy6B^+BFN&6s;1##N1bx z-0}0Wlgw}0{{EGKd)y_TgaGGWi(Q-f6h(DhhBf>jVPFpF%I~F6xWHb`C$kP5bDUti zaABuh=-@%KMMaSKgrEhkgWsecT(UY)H=Vt;k{~#YfmAsXTK{O6B&kL>f$&h_;NXY^ z{Nlq{vPj%o+F#J2GZvVNdw6;}8eIdgMdQDMJu(l50%ffAwm3%RZrzN-d!cF;MSxdD z-*$X=Wj6Thiw(t5H9xv7g%lO7^157Ew{I6eq|8-rv(yW@u>6Mn|UgZFW&p3*+AJ z5DBhFx&8xVAqfd>?VHk?9GslZiw5TAd(c&& zij&9FT~!za(K2ed;4q5wMc(^IWl&(?28C`Vd!_+n>`wf$mj1MyEK`1^lWg5h)m_F7-@d-miBHv}wa78-U7xv~`M3=l#>fymOEaP&$<#3oc`%>mcS|kj5-YJa6~^=e*So5Vy%Ac3xq&Y^Q5v;5Y}4EtJF~BJW|57!SsU9Yn$)_ z2-o73aC~GQ=OV$D_)1JdLKSpJf&elLWtUl{hp?Eqc&5H+Tb3HL;$n|InH=E%IzQbf z1C1*UDUZJj(AQ|9Iv)*zg^cy1K0dNAibX@TPJoaGnz1qEEkH7ZVM+aSsxIO zPJhttTLZY%esQWdRodm+LJui{f;S`#XMeZ2cq<0>(%W-E8&kBxK-+@2ylj|FQ`MLm zbCyQi%BN4W;EOrvK0+I?Fn$U6oGe@+m~q^aHUw(@ji@;CjK!|*IK&Cp+Xlj_HfRUw zYI^_vJwYHo<6hD81&j;gW@#Sbzc5EbHeRniLjU@R51)b;!$6hqjp*7wlsNIgjyCZH zf)p&eZy!8=bddPOG&gIJmyBOxzH-~mFEuhRvt(03B(JHLmvrkLCFUzHh@>W3G-+pN z=iU4F>CqC9g#!-JKoFoAYG`ZMAu%T=C2hpaYC_^lAQnf=7<<;|;ZWHL9wMHe|;WS5)LhrT66g@CNAa=(xDJkUs>3 zh3QaPa#Hn0Va1KNMJ-R_sUTVRaY@Id44A_xI8~lI?9cqOHVB;-S?kJ;8#lb%?#Lj9 zz5rs+eY{ODG&J;ie}9#3(J&@OQt&KXE2Kkp%$>Cly z;|#!Aq(%1i1L3dOOwABh1#oxBp{PgxxnqIzj0#&0-`D z_LBxL+%|hm9lY&O6_KS(aB%SI;^SI16gOl_M`kCE!em792tI%QOoDXB2dd=AgucxW zY=P$}TiYL>`;)vUB>0-NmyvAjvxdi2jVWPUm8HFRl5_p>LEA0=?~L$o62|{ Date: Wed, 25 Mar 2020 18:47:05 +0100 Subject: [PATCH 146/150] Some robustness for degenerate data sets --- .../CGAL/Optimal_bounding_box/internal/optimize_2.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h index 57374162746..3424bae2017 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h @@ -73,8 +73,8 @@ compute_2D_deviation(const PointRange& points, CGAL::Min_quadrilateral_default_traits_2 mrt; CGAL::min_rectangle_2(extreme_points.begin(), extreme_points.end(), std::back_inserter(pol), mrt); - CGAL_assertion(pol.size() == 4); - CGAL_assertion(pol.is_counterclockwise_oriented()); + if(pol.size() == 4 || !pol.is_simple() || pol.is_clockwise_oriented()) + return std::make_pair(0., 0.); // Compute the angle between the angle necessary to rotate the rectangle onto the reference frame auto bot_pos = pol.bottom_vertex(); @@ -88,7 +88,9 @@ compute_2D_deviation(const PointRange& points, const Vector_2 pq = traits.construct_vector_2_object()(p, q); double n = sqrt(to_double(traits.compute_squared_length_2_object()(pq))); - CGAL_assertion(n != 0.); + + if(n == 0.) // degenerate input, maybe? Let's just not do anything + return std::make_pair(pol.area(), 0.); const double dot = pq.x(); // that's the scalar product of PQ with V(1, 0) (Ox) double cosine = dot / n; From 34dd14ced4bb6c39c886b60df7bf7151d752b88a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 25 Mar 2020 18:47:30 +0100 Subject: [PATCH 147/150] Misc verbose changes --- .../include/CGAL/Optimal_bounding_box/internal/evolution.h | 6 +++--- .../include/CGAL/Optimal_bounding_box/internal/optimize_2.h | 2 +- .../CGAL/Optimal_bounding_box/oriented_bounding_box.h | 5 +++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index 187415d02ed..477c1294fa1 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -139,7 +139,7 @@ public: std::size_t gen_iter = 0; for(;;) { -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_PP std::cout << "- - - - generation #" << gen_iter << "\n"; #endif @@ -165,7 +165,7 @@ public: m_best_v = &(m_population.get_best_vertex()); Matrix& best_m = m_best_v->matrix(); -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_PP std::cout << "new best matrix: " << std::endl << best_m << std::endl; std::cout << "fitness: " << m_best_v->fitness() << std::endl; #endif @@ -177,7 +177,7 @@ public: const FT new_fit_value = m_best_v->fitness(); const FT difference = new_fit_value - prev_fit_value; -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_PP std::cout << "post 2D optimization matrix: " << std::endl << best_m << std::endl; std::cout << "new fit value: " << new_fit_value << std::endl; std::cout << "difference: " << difference << std::endl; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h index 3424bae2017..b4f2ba4a7da 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h @@ -163,7 +163,7 @@ void optimize_along_OBB_axes(typename Traits::Matrix& rot, auto it = std::min_element(volumes.begin(), volumes.end()); typename std::iterator_traits::difference_type d = std::distance(volumes.begin(), it); -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_PP std::cout << "volumes: " << volumes[0] << " " << volumes[1] << " " << volumes[2] << std::endl; std::cout << "angles: " << angles[0] << " " << angles[1] << " " << angles[2] << std::endl; std::cout << "min at " << d << std::endl; diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 6157e282c9b..0ebf2b207cb 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -86,7 +86,12 @@ void construct_oriented_bounding_box(const PointRange& points, // Apply the inverse rotation to the rotated axis aligned bounding box for(std::size_t i=0; i<8; ++i) + { obb_points[i] = inverse_transformation.transform(obb_points[i]); +#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG + std::cout << " OBB[" << i << "] = " << obb_points[i] << std::endl; +#endif + } } template From 79aa6a755ae30d64eb2ce64d1059646d57331b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 25 Mar 2020 18:47:46 +0100 Subject: [PATCH 148/150] Enable passing a mesh as output --- .../oriented_bounding_box.h | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 0ebf2b207cb..619412f142f 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -140,9 +140,9 @@ void compute_best_transformation(const PointRange& points, } // Following two functions are overloads to dispatch depending on return type -template +template void construct_oriented_bounding_box(const PointRange& points, - typename Traits::Aff_transformation_3& transformation, + CGAL::Aff_transformation_3& transformation, CGAL::Random& rng, const Traits& traits) { @@ -150,11 +150,14 @@ void construct_oriented_bounding_box(const PointRange& points, compute_best_transformation(points, transformation, inverse_transformation, rng, traits); } -template +template void construct_oriented_bounding_box(const PointRange& points, - std::array& obb_points, + Array& obb_points, CGAL::Random& rng, - const Traits& traits) + const Traits& traits, + typename boost::enable_if< + typename boost::has_range_iterator + >::type* = 0) { typename Traits::Aff_transformation_3 transformation, inverse_transformation; compute_best_transformation(points, transformation, inverse_transformation, rng, traits); @@ -162,6 +165,25 @@ void construct_oriented_bounding_box(const PointRange& points, construct_oriented_bounding_box(points, transformation, inverse_transformation, obb_points, traits); } +template +void construct_oriented_bounding_box(const PointRange& points, + PolygonMesh& pm, + CGAL::Random& rng, + const Traits& traits, + typename boost::disable_if< + typename boost::has_range_iterator + >::type* = 0) +{ + typename Traits::Aff_transformation_3 transformation, inverse_transformation; + compute_best_transformation(points, transformation, inverse_transformation, rng, traits); + + std::array obb_points; + construct_oriented_bounding_box(points, transformation, inverse_transformation, obb_points, traits); + + CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], + obb_points[4], obb_points[5], obb_points[6], obb_points[7], pm); +} + // Entry point, decide whether to compute the CH_3 or not template void construct_oriented_bounding_box(const PointRange& points, @@ -237,7 +259,8 @@ void construct_oriented_bounding_box(const PointRange& points, /// \tparam PointRange a model of `Range`. The value type may not be equal to the type `%Point_3` of the traits class /// if a point map is provided via named parameters (see below) to access points. /// \tparam Output either the type `Aff_transformation_3` of the traits class, -/// or `std::array` with `Point` being equivalent to the type `%Point_3` of the traits class +/// or `std::array` with `Point` being equivalent to the type `%Point_3` of the traits class, +/// or a model of `MutableFaceGraph` /// \tparam NamedParameters a sequence of \ref obb_namedparameters "Named Parameters" /// /// \param points the input range @@ -327,7 +350,8 @@ void oriented_bounding_box(const PointRange& points, /// /// \tparam PolygonMesh a model of `VertexListGraph` /// \tparam Output either the type `Aff_transformation_3` of the traits class, -/// or `std::array` with `Point` being equivalent to the type `%Point_3` of the traits class +/// or `std::array` with `Point` being equivalent to the type `%Point_3` of the traits class, +/// or a model of `MutableFaceGraph` /// \tparam NamedParameters a sequence of \ref obb_namedparameters "Named Parameters" /// /// \param pmesh the input mesh @@ -384,7 +408,7 @@ void oriented_bounding_box(const PolygonMesh& pmesh, /// Convenience overloads ///////////////////////////////////////////////////////////////////////////////////////////////// -template +template void oriented_bounding_box(const Input& in, Output& out) { return oriented_bounding_box(in, out, CGAL::parameters::all_default()); From 546f943c6e98b1243bc7499562b4b8a44e56b988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 25 Mar 2020 18:48:44 +0100 Subject: [PATCH 149/150] Update tests --- .../Optimal_bounding_box/data/flat_mesh.off | 323 ++++++++++++++++++ .../Optimal_bounding_box/data/points_0D.xyz | 8 + .../Optimal_bounding_box/data/points_1D.xyz | 7 + .../Optimal_bounding_box/data/points_2D.xyz | 282 +++++++++++++++ .../Optimal_bounding_box/data/triangles.off | 9 + .../Optimal_bounding_box/test_OBB_traits.cpp | 41 +-- .../Optimal_bounding_box/test_nelder_mead.cpp | 19 +- .../test_optimization_algorithms.cpp | 234 ++++--------- 8 files changed, 719 insertions(+), 204 deletions(-) create mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/data/flat_mesh.off create mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/data/points_0D.xyz create mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/data/points_1D.xyz create mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/data/points_2D.xyz create mode 100644 Optimal_bounding_box/test/Optimal_bounding_box/data/triangles.off diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/data/flat_mesh.off b/Optimal_bounding_box/test/Optimal_bounding_box/data/flat_mesh.off new file mode 100644 index 00000000000..879b6594b95 --- /dev/null +++ b/Optimal_bounding_box/test/Optimal_bounding_box/data/flat_mesh.off @@ -0,0 +1,323 @@ +OFF +121 200 0 +0 0 0 +0.10000000000000001 0 0 +0.20000000000000001 0 0 +0.29999999999999999 0 0 +0.40000000000000002 0 0 +0.5 0 0 +0.59999999999999998 0 0 +0.69999999999999996 0 0 +0.80000000000000004 0 0 +0.90000000000000002 0 0 +1 0 0 +0 0.10000000000000001 0.10000000000000001 +0.10000000000000001 0.10000000000000001 0.10000000000000001 +0.20000000000000001 0.10000000000000001 0.10000000000000001 +0.29999999999999999 0.10000000000000001 0.10000000000000001 +0.40000000000000002 0.10000000000000001 0.10000000000000001 +0.5 0.10000000000000001 0.10000000000000001 +0.59999999999999998 0.10000000000000001 0.10000000000000001 +0.69999999999999996 0.10000000000000001 0.10000000000000001 +0.80000000000000004 0.10000000000000001 0.10000000000000001 +0.90000000000000002 0.10000000000000001 0.10000000000000001 +1 0.10000000000000001 0.10000000000000001 +0 0.20000000000000001 0.20000000000000001 +0.10000000000000001 0.20000000000000001 0.20000000000000001 +0.20000000000000001 0.20000000000000001 0.20000000000000001 +0.29999999999999999 0.20000000000000001 0.20000000000000001 +0.40000000000000002 0.20000000000000001 0.20000000000000001 +0.5 0.20000000000000001 0.20000000000000001 +0.59999999999999998 0.20000000000000001 0.20000000000000001 +0.69999999999999996 0.20000000000000001 0.20000000000000001 +0.80000000000000004 0.20000000000000001 0.20000000000000001 +0.90000000000000002 0.20000000000000001 0.20000000000000001 +1 0.20000000000000001 0.20000000000000001 +0 0.29999999999999999 0.29999999999999999 +0.10000000000000001 0.29999999999999999 0.29999999999999999 +0.20000000000000001 0.29999999999999999 0.29999999999999999 +0.29999999999999999 0.29999999999999999 0.29999999999999999 +0.40000000000000002 0.29999999999999999 0.29999999999999999 +0.5 0.29999999999999999 0.29999999999999999 +0.59999999999999998 0.29999999999999999 0.29999999999999999 +0.69999999999999996 0.29999999999999999 0.29999999999999999 +0.80000000000000004 0.29999999999999999 0.29999999999999999 +0.90000000000000002 0.29999999999999999 0.29999999999999999 +1 0.29999999999999999 0.29999999999999999 +0 0.40000000000000002 0.40000000000000002 +0.10000000000000001 0.40000000000000002 0.40000000000000002 +0.20000000000000001 0.40000000000000002 0.40000000000000002 +0.29999999999999999 0.40000000000000002 0.40000000000000002 +0.40000000000000002 0.40000000000000002 0.40000000000000002 +0.5 0.40000000000000002 0.40000000000000002 +0.59999999999999998 0.40000000000000002 0.40000000000000002 +0.69999999999999996 0.40000000000000002 0.40000000000000002 +0.80000000000000004 0.40000000000000002 0.40000000000000002 +0.90000000000000002 0.40000000000000002 0.40000000000000002 +1 0.40000000000000002 0.40000000000000002 +0 0.5 0.5 +0.10000000000000001 0.5 0.5 +0.20000000000000001 0.5 0.5 +0.29999999999999999 0.5 0.5 +0.40000000000000002 0.5 0.5 +0.5 0.5 0.5 +0.59999999999999998 0.5 0.5 +0.69999999999999996 0.5 0.5 +0.80000000000000004 0.5 0.5 +0.90000000000000002 0.5 0.5 +1 0.5 0.5 +0 0.59999999999999998 0.59999999999999998 +0.10000000000000001 0.59999999999999998 0.59999999999999998 +0.20000000000000001 0.59999999999999998 0.59999999999999998 +0.29999999999999999 0.59999999999999998 0.59999999999999998 +0.40000000000000002 0.59999999999999998 0.59999999999999998 +0.5 0.59999999999999998 0.59999999999999998 +0.59999999999999998 0.59999999999999998 0.59999999999999998 +0.69999999999999996 0.59999999999999998 0.59999999999999998 +0.80000000000000004 0.59999999999999998 0.59999999999999998 +0.90000000000000002 0.59999999999999998 0.59999999999999998 +1 0.59999999999999998 0.59999999999999998 +0 0.69999999999999996 0.69999999999999996 +0.10000000000000001 0.69999999999999996 0.69999999999999996 +0.20000000000000001 0.69999999999999996 0.69999999999999996 +0.29999999999999999 0.69999999999999996 0.69999999999999996 +0.40000000000000002 0.69999999999999996 0.69999999999999996 +0.5 0.69999999999999996 0.69999999999999996 +0.59999999999999998 0.69999999999999996 0.69999999999999996 +0.69999999999999996 0.69999999999999996 0.69999999999999996 +0.80000000000000004 0.69999999999999996 0.69999999999999996 +0.90000000000000002 0.69999999999999996 0.69999999999999996 +1 0.69999999999999996 0.69999999999999996 +0 0.80000000000000004 0.80000000000000004 +0.10000000000000001 0.80000000000000004 0.80000000000000004 +0.20000000000000001 0.80000000000000004 0.80000000000000004 +0.29999999999999999 0.80000000000000004 0.80000000000000004 +0.40000000000000002 0.80000000000000004 0.80000000000000004 +0.5 0.80000000000000004 0.80000000000000004 +0.59999999999999998 0.80000000000000004 0.80000000000000004 +0.69999999999999996 0.80000000000000004 0.80000000000000004 +0.80000000000000004 0.80000000000000004 0.80000000000000004 +0.90000000000000002 0.80000000000000004 0.80000000000000004 +1 0.80000000000000004 0.80000000000000004 +0 0.90000000000000002 0.90000000000000002 +0.10000000000000001 0.90000000000000002 0.90000000000000002 +0.20000000000000001 0.90000000000000002 0.90000000000000002 +0.29999999999999999 0.90000000000000002 0.90000000000000002 +0.40000000000000002 0.90000000000000002 0.90000000000000002 +0.5 0.90000000000000002 0.90000000000000002 +0.59999999999999998 0.90000000000000002 0.90000000000000002 +0.69999999999999996 0.90000000000000002 0.90000000000000002 +0.80000000000000004 0.90000000000000002 0.90000000000000002 +0.90000000000000002 0.90000000000000002 0.90000000000000002 +1 0.90000000000000002 0.90000000000000002 +0 1 1 +0.10000000000000001 1 1 +0.20000000000000001 1 1 +0.29999999999999999 1 1 +0.40000000000000002 1 1 +0.5 1 1 +0.59999999999999998 1 1 +0.69999999999999996 1 1 +0.80000000000000004 1 1 +0.90000000000000002 1 1 +1 1 1 +3 0 1 11 +3 1 12 11 +3 11 12 22 +3 12 23 22 +3 22 23 33 +3 23 34 33 +3 33 34 44 +3 34 45 44 +3 44 45 55 +3 45 56 55 +3 55 56 66 +3 56 67 66 +3 66 67 77 +3 67 78 77 +3 77 78 88 +3 78 89 88 +3 88 89 99 +3 89 100 99 +3 99 100 110 +3 100 111 110 +3 1 2 12 +3 2 13 12 +3 12 13 23 +3 13 24 23 +3 23 24 34 +3 24 35 34 +3 34 35 45 +3 35 46 45 +3 45 46 56 +3 46 57 56 +3 56 57 67 +3 57 68 67 +3 67 68 78 +3 68 79 78 +3 78 79 89 +3 79 90 89 +3 89 90 100 +3 90 101 100 +3 100 101 111 +3 101 112 111 +3 2 3 13 +3 3 14 13 +3 13 14 24 +3 14 25 24 +3 24 25 35 +3 25 36 35 +3 35 36 46 +3 36 47 46 +3 46 47 57 +3 47 58 57 +3 57 58 68 +3 58 69 68 +3 68 69 79 +3 69 80 79 +3 79 80 90 +3 80 91 90 +3 90 91 101 +3 91 102 101 +3 101 102 112 +3 102 113 112 +3 3 4 14 +3 4 15 14 +3 14 15 25 +3 15 26 25 +3 25 26 36 +3 26 37 36 +3 36 37 47 +3 37 48 47 +3 47 48 58 +3 48 59 58 +3 58 59 69 +3 59 70 69 +3 69 70 80 +3 70 81 80 +3 80 81 91 +3 81 92 91 +3 91 92 102 +3 92 103 102 +3 102 103 113 +3 103 114 113 +3 4 5 15 +3 5 16 15 +3 15 16 26 +3 16 27 26 +3 26 27 37 +3 27 38 37 +3 37 38 48 +3 38 49 48 +3 48 49 59 +3 49 60 59 +3 59 60 70 +3 60 71 70 +3 70 71 81 +3 71 82 81 +3 81 82 92 +3 82 93 92 +3 92 93 103 +3 93 104 103 +3 103 104 114 +3 104 115 114 +3 5 6 16 +3 6 17 16 +3 16 17 27 +3 17 28 27 +3 27 28 38 +3 28 39 38 +3 38 39 49 +3 39 50 49 +3 49 50 60 +3 50 61 60 +3 60 61 71 +3 61 72 71 +3 71 72 82 +3 72 83 82 +3 82 83 93 +3 83 94 93 +3 93 94 104 +3 94 105 104 +3 104 105 115 +3 105 116 115 +3 6 7 17 +3 7 18 17 +3 17 18 28 +3 18 29 28 +3 28 29 39 +3 29 40 39 +3 39 40 50 +3 40 51 50 +3 50 51 61 +3 51 62 61 +3 61 62 72 +3 62 73 72 +3 72 73 83 +3 73 84 83 +3 83 84 94 +3 84 95 94 +3 94 95 105 +3 95 106 105 +3 105 106 116 +3 106 117 116 +3 7 8 18 +3 8 19 18 +3 18 19 29 +3 19 30 29 +3 29 30 40 +3 30 41 40 +3 40 41 51 +3 41 52 51 +3 51 52 62 +3 52 63 62 +3 62 63 73 +3 63 74 73 +3 73 74 84 +3 74 85 84 +3 84 85 95 +3 85 96 95 +3 95 96 106 +3 96 107 106 +3 106 107 117 +3 107 118 117 +3 8 9 19 +3 9 20 19 +3 19 20 30 +3 20 31 30 +3 30 31 41 +3 31 42 41 +3 41 42 52 +3 42 53 52 +3 52 53 63 +3 53 64 63 +3 63 64 74 +3 64 75 74 +3 74 75 85 +3 75 86 85 +3 85 86 96 +3 86 97 96 +3 96 97 107 +3 97 108 107 +3 107 108 118 +3 108 119 118 +3 9 10 20 +3 10 21 20 +3 20 21 31 +3 21 32 31 +3 31 32 42 +3 32 43 42 +3 42 43 53 +3 43 54 53 +3 53 54 64 +3 54 65 64 +3 64 65 75 +3 65 76 75 +3 75 76 86 +3 76 87 86 +3 86 87 97 +3 87 98 97 +3 97 98 108 +3 98 109 108 +3 108 109 119 +3 109 120 119 diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/data/points_0D.xyz b/Optimal_bounding_box/test/Optimal_bounding_box/data/points_0D.xyz new file mode 100644 index 00000000000..b83af3886b1 --- /dev/null +++ b/Optimal_bounding_box/test/Optimal_bounding_box/data/points_0D.xyz @@ -0,0 +1,8 @@ +413065776.152494 326396843.840397 326457757.911644 +413065776.152494 326396843.840397 326457757.911644 +413065776.152494 326396843.840397 326457757.911644 +413065776.152494 326396843.840397 326457757.911644 +413065776.152494 326396843.840397 326457757.911644 +413065776.152494 326396843.840397 326457757.911644 +413065776.152494 326396843.840397 326457757.911644 + diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/data/points_1D.xyz b/Optimal_bounding_box/test/Optimal_bounding_box/data/points_1D.xyz new file mode 100644 index 00000000000..3a768cdea92 --- /dev/null +++ b/Optimal_bounding_box/test/Optimal_bounding_box/data/points_1D.xyz @@ -0,0 +1,7 @@ +0 0 0 +0 1 2 +0 2 4 +0 3 6 +0 10 20 +0 0.5 1 + diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/data/points_2D.xyz b/Optimal_bounding_box/test/Optimal_bounding_box/data/points_2D.xyz new file mode 100644 index 00000000000..537b0697885 --- /dev/null +++ b/Optimal_bounding_box/test/Optimal_bounding_box/data/points_2D.xyz @@ -0,0 +1,282 @@ +413065776.152494 326396843.840397 0 +413057847.377906 326403660.329056 0 +413052569.655378 326399341.810968 0 +412964155.996695 326429557.407149 0 +412960887.449993 326443760.793625 0 +412939753.084117 326436727.039421 0 +412939894.318992 326428463.667967 0 +412947664.119328 326419882.748586 0 +412970476.46515 326451966.912356 0 +412968925.050862 326458160.301721 0 +412963543.512664 326454495.012767 0 +412985746.970294 326424302.733302 0 +412983665.865636 326410836.59751 0 +412996088.235308 326419469.954289 0 +412998096.793163 326423084.180324 0 +413003418.285576 326419809.050109 0 +413002038.294065 326427600.699796 0 +412945313.935335 326454359.672656 0 +412943663.154485 326452834.040025 0 +412952251.09554 326452986.901051 0 +412950732.333508 326457757.911644 0 +412943971.574173 326459149.099198 0 +412934361.648126 326445041.605944 0 +412936751.268924 326454822.208572 0 +412964758.701994 326486192.337374 0 +412966490.855253 326478259.235383 0 +412973194.081713 326482046.898235 0 +412950650.516328 326468707.808723 0 +412957725.270744 326476103.847023 0 +412950026.231257 326477412.439015 0 +412988174.944206 326470661.339091 0 +412986909.075808 326462858.270384 0 +413000669.61306 326456348.730054 0 +412966234.090172 326488146.292068 0 +413023232.123734 326461197.560115 0 +413023550.270655 326471002.013297 0 +413016185.260894 326465438.977186 0 +412987141.775588 326489693.339605 0 +412982918.043107 326488237.152808 0 +412985980.280763 326483135.425286 0 +413001196.353514 326479715.175257 0 +413008202.547705 326474962.703983 0 +413003755.131316 326481400.115507 0 +412929683.198695 326465491.420262 0 +412920189.499339 326451860.04878 0 +412931611.507502 326452533.708517 0 +412992581.061321 326477132.127848 0 +412989279.419663 326480089.894799 0 +412935705.096519 326482202.861555 0 +412925307.138482 326466637.344135 0 +413076469.52736 326433412.768228 0 +413075298.398716 326444763.979995 0 +413065834.246237 326440647.027719 0 +413009745.175265 326502212.1638 0 +413001718.895276 326508920.841833 0 +413002418.144751 326497753.488837 0 +413060741.401393 326423820.134531 0 +413060876.676061 326428728.639701 0 +413058999.571918 326423687.390799 0 +413025105.511534 326478606.208507 0 +413037158.816855 326472407.974956 0 +413026100.112628 326483530.179333 0 +413079758.83472 326425207.53598 0 +413076210.923893 326422944.976439 0 +413078151.988242 326416248.664714 0 +413053952.794291 326463144.972745 0 +413055684.722689 326475529.630202 0 +413045099.788495 326474825.69738 0 +413062042.967186 326437063.922844 0 +413066790.302583 326430817.2269 0 +413004709.107113 326490135.418709 0 +413005093.685865 326489983.127837 0 +413098251.972367 326408565.921651 0 +413098367.233587 326415127.45218 0 +413097944.35044 326413442.449707 0 +413070518.763323 326460355.49692 0 +413066193.752266 326467461.946737 0 +413087099.80728 326418237.162439 0 +412932643.127595 326424163.465682 0 +412947239.568275 326415586.45517 0 +412929877.917135 326420120.542778 0 +413010920.918128 326399072.312299 0 +412915060.825449 326423803.643013 0 +412963212.559984 326417484.293606 0 +412974527.414159 326428576.196833 0 +412992373.377627 326455620.014196 0 +413010074.272151 326418465.382469 0 +413011850.753162 326417002.217271 0 +413014406.991439 326420203.661922 0 +412977637.839421 326432544.829395 0 +412986148.487405 326429359.611152 0 +412995280.156846 326431026.989975 0 +412990626.28213 326425374.845568 0 +413032797.62091 326426191.034153 0 +413029970.570148 326419936.329868 0 +413044681.544615 326417464.080029 0 +412999129.25698 326438072.80725 0 +413007734.056563 326423851.649794 0 +413016471.93654 326426364.913717 0 +412968431.452864 326491828.041548 0 +412958675.073533 326494006.076801 0 +413012148.256747 326487804.579704 0 +413016405.832048 326480671.32311 0 +412975768.001435 326448708.020146 0 +412979720.162501 326436886.822391 0 +412982917.886679 326443564.393356 0 +412988678.510158 326449487.248631 0 +412985417.106869 326452678.469145 0 +412971510.871442 326435116.950769 0 +412983109.808175 326457244.32078 0 +412957466.876904 326451325.256978 0 +412959384.40943 326448781.181773 0 +412966768.138142 326473363.04219 0 +412971910.952526 326476870.046921 0 +412963392.569735 326463111.127056 0 +412924771.98365 326432849.602577 0 +412917475.177804 326429370.043518 0 +412911569.816167 326425718.742949 0 +412924489.589924 326449937.575511 0 +412956933.247292 326455774.007997 0 +412955340.545694 326460219.517522 0 +412977018.754996 326466258.738995 0 +412970686.301222 326466481.954067 0 +412978255.629151 326461355.571957 0 +412939153.439846 326465339.238827 0 +412923821.154719 326426918.928828 0 +412975936.409656 326502806.20831 0 +412963303.14509 326498679.785427 0 +412969138.482087 326493922.342246 0 +412956467.21651 326489106.767098 0 +412959578.052441 326480365.162202 0 +412977352.621415 326497109.261795 0 +412941422.08486 326477143.510512 0 +412936831.795868 326467205.375027 0 +412961266.195768 326503954.723704 0 +412958703.392685 326524881.814902 0 +412953249.527674 326518460.235631 0 +412935010.36184 326494112.455851 0 +412931570.65415 326484602.04937 0 +412985374.324569 326513222.867276 0 +412978227.727596 326510871.926542 0 +412984173.754694 326502503.840454 0 +412985688.206537 326494576.776311 0 +412978009.820415 326492658.751496 0 +412993618.008235 326491281.852681 0 +412997947.150272 326492521.079555 0 +412976873.960635 326486185.606476 0 +412981478.037092 326484421.347501 0 +412980418.065914 326478321.690068 0 +412979438.184438 326473334.846215 0 +413010215.690383 326443409.550491 0 +413008228.44707 326458894.052728 0 +413035617.465636 326446767.558378 0 +413027230.055638 326446990.503477 0 +413030854.849802 326440245.461135 0 +412979140.451061 326454242.503581 0 +412985468.6174 326450604.80651 0 +413015771.02389 326453064.045201 0 +413021991.755036 326445142.840934 0 +413008006.052746 326469763.695134 0 +413048901.884808 326422501.5037 0 +413045028.78386 326426372.15428 0 +413005007.536883 326484301.633515 0 +413002785.535959 326490180.214403 0 +413014109.69202 326461894.536067 0 +413017207.888265 326470063.830947 0 +413045293.513014 326449673.312107 0 +413044019.75301 326447988.572283 0 +413047003.614678 326443105.313308 0 +412999003.436139 326487344.001445 0 +412996651.65689 326491134.958733 0 +413012316.245006 326479912.254408 0 +413012587.728747 326484153.816803 0 +413016871.37429 326476971.655283 0 +413019842.625853 326474794.530385 0 +413039469.406178 326437529.843339 0 +413041502.67459 326485107.978727 0 +413036035.620497 326461314.614016 0 +413031490.325583 326456799.67237 0 +413020789.72965 326452093.515847 0 +413020692.119972 326434154.560939 0 +413029690.023638 326438011.408021 0 +413043486.972873 326454746.798277 0 +413033511.062177 326430679.751046 0 +413067488.089213 326425961.293338 0 +413083753.259443 326426175.344791 0 +413067460.916052 326410232.697374 0 +413068622.531383 326416317.705612 0 +413061037.102135 326415163.721378 0 +413071143.181797 326424762.764848 0 +413060387.108431 326414188.28851 0 +413060445.58895 326451275.748613 0 +413036317.30909 326431883.117032 0 +413045873.300553 326435644.793299 0 +413048794.267495 326389319.436376 0 +413030291.769546 326411368.835099 0 +413024488.398109 326415338.686016 0 +413021905.956926 326410737.878939 0 +413027639.836779 326415641.265719 0 +413017857.083999 326417952.301599 0 +413029827.400431 326406821.764259 0 +413001443.929946 326407150.378482 0 +413036041.452869 326405791.758584 0 +413033454.48341 326399656.242176 0 +413018633.129927 326413338.952301 0 +413045368.965357 326402337.610635 0 +413048447.394379 326395169.908511 0 +412986849.902761 326405367.534053 0 +413065081.744554 326401671.778183 0 +413092397.837156 326422086.08121 0 +413095318.341189 326412788.599152 0 +413093695.254875 326400330.203004 0 +413099020.077932 326406314.05352 0 +413093140.218869 326403110.903958 0 +413056121.776141 326406403.684953 0 +413089620.108842 326414007.091517 0 +413089387.417624 326419721.87399 0 +413093404.232693 326395001.998282 0 +413085896.789345 326396361.60811 0 +413085454.676931 326391470.731474 0 +413074508.839395 326394470.397757 0 +413068350.570434 326395560.501438 0 +413070143.96055 326386445.935889 0 +412918858.560132 326434979.970278 0 +412955394.145789 326449536.682215 0 +412971144.038673 326433652.368538 0 +412965073.360409 326439051.77804 0 +412970981.692447 326409503.990341 0 +413014840.087809 326404397.988193 0 +412994018.136075 326445298.914892 0 +412990097.829467 326437133.362141 0 +412965842.792609 326448792.291328 0 +412961763.785867 326445852.010028 0 +412947255.093497 326463668.462422 0 +412939952.26946 326466492.382176 0 +412943709.427436 326472618.681827 0 +412952246.783422 326483371.121473 0 +412944807.921928 326491083.247909 0 +412940579.938471 326495813.432763 0 +412945630.90436 326501939.425427 0 +412938409.182245 326503335.780256 0 +412951371.196888 326498868.583434 0 +412949313.764109 326504296.763374 0 +412945558.683443 326510754.714855 0 +413008766.713556 326484732.391891 0 +412990390.280433 326484843.195428 0 +412995165.502732 326483367.864039 0 +413016256.164946 326494798.780171 0 +413017224.89391 326461129.632116 0 +413029625.683716 326471350.776378 0 +413025019.999494 326476200.095554 0 +413048766.414482 326435871.77665 0 +413051725.256746 326438529.947023 0 +413052007.160945 326422036.946841 0 +413058067.843268 326435775.445353 0 +413083660.953967 326393424.812132 0 +413083336.161107 326400813.355748 0 +413066349.33981 326419281.508749 0 +413068090.500382 326410610.12681 0 +413074241.401196 326404770.242276 0 +413081317.053152 326414171.97812 0 +413073381.651167 326406897.136775 0 +413095766.46998 326387248.540458 0 +413097047.640536 326395426.23288 0 +413098209.521961 326406637.959602 0 +413089554.505615 326388294.334232 0 +413074403.539056 326415367.945363 0 +413040020.425247 326411046.731682 0 +413045679.434506 326406659.04965 0 +413039095.903129 326409071.668118 0 +413031306.230818 326393733.283998 0 +413052303.600823 326400659.626307 0 +413081695.584061 326380509.699198 0 +413077541.674433 326389883.685777 0 +413082416.500748 326382824.511316 0 +413073027.473224 326382906.090405 0 +413088349.695199 326383000.125606 0 +413094911.539918 326387536.877598 0 +413092119.400999 326388985.514422 0 +413093374.909798 326384034.886791 0 +413096500.785907 326395520.129613 0 +413094014.467295 326377700.363085 0 diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/data/triangles.off b/Optimal_bounding_box/test/Optimal_bounding_box/data/triangles.off new file mode 100644 index 00000000000..21806ffd7ff --- /dev/null +++ b/Optimal_bounding_box/test/Optimal_bounding_box/data/triangles.off @@ -0,0 +1,9 @@ +OFF +4 2 0 +0 0 0 +1 0 0 +0 1 0 +1 1 0 +3 0 1 2 +3 2 1 3 + diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_OBB_traits.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_OBB_traits.cpp index c5362beb3cd..5635440e4ca 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_OBB_traits.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_OBB_traits.cpp @@ -31,7 +31,7 @@ void check_equality(const FT d1, const FT d2) } } -void test_fitness_function() +void test_fitness_function(const Traits& traits) { std::array points; points[0] = Point_3(0.866802, 0.740808, 0.895304); @@ -50,7 +50,7 @@ void test_fitness_function() rotation.set(2, 1, -0.991602); rotation.set(2, 2, 0.042528); - const double fitness = CGAL::Optimal_bounding_box::internal::compute_fitness(rotation, points); + const double fitness = CGAL::Optimal_bounding_box::internal::compute_fitness(rotation, points, traits); check_equality(fitness, 0.58606); } @@ -95,44 +95,13 @@ void test_eigen_matrix_interface() check_equality(Q(2,0), -0.006573); check_equality(Q(2,1), 0.024478); check_equality(Q(2,2), 0.999679); - - Matrix D; - D.set(0, 0, -0.809204); - D.set(0, 1, 0.124296); - D.set(0, 2, 0.574230); - D.set(1, 0, -0.574694); - D.set(1, 1, 0.035719); - D.set(1, 2, -0.817589); - D.set(2, 0, -0.122134); - D.set(2, 1, -0.991602); - D.set(2, 2, 0.042528); - - Matrix E; - E.set(0, 0, -0.45070); - E.set(0, 1, -0.32769); - E.set(0, 2, -0.83035); - E.set(1, 0, -0.13619); - E.set(1, 1, -0.89406); - E.set(1, 2, 0.42675); - E.set(2, 0, -0.88222); - E.set(2, 1, 0.30543); - E.set(2, 2, 0.35833); - - Matrix Sr = CGAL::Optimal_bounding_box::internal::reflection(D, E); - check_equality(Sr(0,0), -0.13359); - check_equality(Sr(0,1), -0.95986); - check_equality(Sr(0,2), -0.24664); - check_equality(Sr(1,0), -0.60307); - check_equality(Sr(1,1), -0.11875); - check_equality(Sr(1,2), 0.78880); - check_equality(Sr(2,0), -0.78642); - check_equality(Sr(2,1), 0.25411); - check_equality(Sr(2,2), -0.56300); } int main(int, char**) { - test_fitness_function(); + Traits traits; + + test_fitness_function(traits); test_eigen_matrix_interface(); std::cout << "Done!" << std::endl; diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp index bf4acdb39de..944d47673db 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_nelder_mead.cpp @@ -10,6 +10,7 @@ typedef K::Point_3 Point_3; typedef CGAL::Oriented_bounding_box_traits_3 Traits; typedef Traits::Matrix Matrix; +typedef CGAL::Optimal_bounding_box::internal::Population::Vertex Vertex; void check_equality(const FT d1, const FT d2) { @@ -122,7 +123,7 @@ void test_nelder_mead(const Traits& traits) points[3] = Point_3(0.166461, 0.149912, 0.364944); // one simplex - std::array simplex; + std::array simplex; Matrix v0, v1, v2, v3; v0.set(0, 0, -0.2192721); v0.set(0, 1, 0.2792986); v0.set(0, 2, -0.9348326); @@ -141,15 +142,15 @@ void test_nelder_mead(const Traits& traits) v3.set(1, 0, -0.20022); v3.set(1, 1, -0.71110); v3.set(1, 2, 0.67398); v3.set(2, 0, -0.92372); v3.set(2, 1, 0.36630); v3.set(2, 2, 0.11207); - simplex[0] = v0; - simplex[1] = v1; - simplex[2] = v2; - simplex[3] = v3; + simplex[0] = Vertex{v0, points, traits}; + simplex[1] = Vertex{v1, points, traits}; + simplex[2] = Vertex{v2, points, traits}; + simplex[3] = Vertex{v3, points, traits}; std::size_t nm_iterations = 19; CGAL::Optimal_bounding_box::internal::nelder_mead(simplex, nm_iterations, points, traits); - const Matrix& v0_new = simplex[0]; + const Matrix& v0_new = simplex[0].matrix(); check_equality(v0_new(0,0), -0.288975); check_equality(v0_new(0,1), 0.7897657); check_equality(v0_new(0,2), -0.541076); @@ -160,7 +161,7 @@ void test_nelder_mead(const Traits& traits) check_equality(v0_new(2,1), 0.5111260); check_equality(v0_new(2,2), 0.84094); - const Matrix& v1_new = simplex[1]; + const Matrix& v1_new = simplex[1].matrix(); check_equality(v1_new(0,0), -0.458749); check_equality(v1_new(0,1), 0.823283); check_equality(v1_new(0,2), -0.334296); @@ -171,7 +172,7 @@ void test_nelder_mead(const Traits& traits) check_equality(v1_new(2,1), 0.338040); check_equality(v1_new(2,2), 0.937987); - const Matrix& v2_new = simplex[2]; + const Matrix& v2_new = simplex[2].matrix(); check_equality(v2_new(0,0), -0.346582); check_equality(v2_new(0,1), 0.878534); check_equality(v2_new(0,2), -0.328724); @@ -182,7 +183,7 @@ void test_nelder_mead(const Traits& traits) check_equality(v2_new(2,1), 0.334057); check_equality(v2_new(2,2), 0.941423); - const Matrix& v3_new = simplex[3]; + const Matrix& v3_new = simplex[3].matrix(); check_equality(v3_new(0,0), -0.394713); check_equality(v3_new(0,1), 0.791782); check_equality(v3_new(0,2), -0.466136); diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp index 488530965ad..7433312e300 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp +++ b/Optimal_bounding_box/test/Optimal_bounding_box/test_optimization_algorithms.cpp @@ -1,8 +1,14 @@ +#define CGAL_OPTIMAL_BOUNDING_BOX_DEBUG + #include #include +#include +#include #include +#include +#include #include #include @@ -10,211 +16,121 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::FT FT; -typedef K::Point_3 Point_3; +typedef K::Point_3 Point; -typedef CGAL::Surface_mesh Mesh; +typedef CGAL::Polyhedron_3 Mesh; typedef CGAL::Oriented_bounding_box_traits_3 Traits; typedef Traits::Matrix Matrix; -void check_equality(const FT d1, const FT d2) +bool is_equal(const FT d1, const FT d2) { const FT epsilon = 1e-3; bool ok; if(std::is_floating_point::value) - ok = CGAL::abs(d1 - d2) < epsilon * CGAL::abs(d2); + ok = CGAL::abs(d1 - d2) < std::max(epsilon * d1, epsilon); else ok = (d1 == d2); if(!ok) { std::cout << "Error: got " << d1 << " but expected: " << d2 << std::endl; - assert(false); + return false; } + + return true; } -void test_genetic_algorithm() +template +void test_OBB_data(const PointRange& points, + const double expected_vol, + const bool with_convex_hull = true) { - std::array points; - points[0] = Point_3(0.866802, 0.740808, 0.895304); - points[1] = Point_3(0.912651, 0.761565, 0.160330); - points[2] = Point_3(0.093661, 0.892578, 0.737412); - points[3] = Point_3(0.166461, 0.149912, 0.364944); + namespace PMP = CGAL::Polygon_mesh_processing; - CGAL::Optimal_bounding_box::internal::Population pop(5); - CGAL::Optimal_bounding_box::internal::Evolution evolution(pop, data_points); - evolution.genetic_algorithm(); - assert(pop.size() == 5); + // the algorithm is allowed to fail, but not too often + int failure_count = 0; + for(int i=0; i<100; ++i) + { + CGAL::Surface_mesh obb_mesh; + CGAL::oriented_bounding_box(points, obb_mesh, CGAL::parameters::use_convex_hull(with_convex_hull)); + PMP::triangulate_faces(obb_mesh); + + // the triangulate algorithm might fail if the algorithm manages + // to fit perfectly the box to have a true 0 volume + if(CGAL::is_triangle_mesh(obb_mesh)) + { + double vol = PMP::volume(obb_mesh); + std::cout << " volume is: " << vol << ", expected: " << expected_vol << std::endl; + if(!is_equal(vol, expected_vol)) + { + std::cout << "Failure!" << std::endl; + ++failure_count; + } + } + } + + std::cout << "failures: " << failure_count << std::endl; + assert(failure_count < 5); // 5% failure } -void test_random_unit_tetra() +void test_OBB_of_mesh(const std::string fname, + const double expected_vol) { - std::array points; - points[0] = Point_3(0.866802, 0.740808, 0.895304); - points[1] = Point_3(0.912651, 0.761565, 0.160330); - points[2] = Point_3(0.093661, 0.892578, 0.737412); - points[3] = Point_3(0.166461, 0.149912, 0.364944); + std::cout << "Test: " << fname << std::endl; + std::ifstream input(fname); Mesh mesh; - CGAL::make_tetrahedron(points[0], points[1], points[2], points[3], mesh); - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST - std::ofstream out("data/random_unit_tetra.off"); - out << mesh; - out.close(); -#endif - - std::size_t generations = 10; - CGAL::Optimal_bounding_box::internal::Population pop(50); - CGAL::Optimal_bounding_box::internal::Evolution evolution(pop, data_points); - evolution.evolve(generations); - - Matrix R = evolution.get_best(); - check_equality(Traits::compute_determinant(R), 1); - check_equality(R(0,0), -0.25791); - check_equality(R(0,1), 0.796512); - check_equality(R(0,2), -0.546855); - check_equality(R(1,0), -0.947128); - check_equality(R(1,1), -0.320242); - check_equality(R(1,2), -0.0197553); - check_equality(R(2,0), -0.190861); - check_equality(R(2,1), 0.512847); - check_equality(R(2,2), 0.836992); -} - -void test_reference_tetrahedron(const char* fname) -{ - std::ifstream input(fname); - CGAL::Surface_mesh mesh; if(!input || !(input >> mesh) || mesh.is_empty()) { - std::cerr << fname << " is not a valid off file." << std::endl; + std::cerr << fname << " is not a valid input file." << std::endl; std::exit(1); } - // points in a matrix - Matrix points; - CGAL::Optimal_bounding_box::sm_to_matrix(mesh, points); + std::vector points; + for(const auto v : vertices(mesh)) + points.push_back(v->point()); - std::size_t generations = 10; - CGAL::Optimal_bounding_box::internal::Population pop(50); - CGAL::Optimal_bounding_box::internal::Evolution experiment(pop, points); - experiment.evolve(generations); - - Matrix R = experiment.get_best(); - check_equality(Traits::compute_determinant(R), 1); + test_OBB_data(points, expected_vol); } -void test_long_tetrahedron(const std::string fname) +void test_OBB_of_point_set(const std::string fname, + const double expected_vol) { + std::cout << "Test: " << fname << std::endl; + std::ifstream input(fname); - CGAL::Surface_mesh mesh; - if(!input || !(input >> mesh) || mesh.is_empty()) + if(!input) { - std::cerr << fname << " is not a valid off file." << std::endl; + std::cerr << fname << " is not a valid input file." << std::endl; std::exit(1); } - // points in a matrix - Matrix points; - CGAL::Optimal_bounding_box::sm_to_matrix(mesh, points); + std::deque points; + double x, y, z; + while(input >> x >> y >> z) + points.emplace_back(x, y, z); - std::size_t max_generations = 10; - CGAL::Optimal_bounding_box::internal::Population pop(50); - CGAL::Optimal_bounding_box::internal::Evolution experiment(pop, points); - experiment.evolve(max_generations); - - Matrix R = experiment.get_best(); - check_equality(Traits::compute_determinant(R), 1); - check_equality(R(0,0), -1); - check_equality(R(0,1), 0); - check_equality(R(0,2), 0); - check_equality(R(1,0), 0); - check_equality(R(1,1), -0.707107); - check_equality(R(1,2), 0.707106) || assert_doubles(R(1,2), -0.707106); - check_equality(R(2,0), 0); - check_equality(R(2,1), 0.707106) || assert_doubles(R(1,2), -0.707106); - check_equality(R(2,2), 0.707107); -} - -void test_compute_obb_evolution(const std::string fname) -{ - std::ifstream input(fname); - typedef CGAL::Surface_mesh SMesh; - SMesh mesh; - if(!input || !(input >> mesh) || mesh.is_empty()) - { - std::cerr << fname << " is not a valid off file." << std::endl; - std::exit(1); - } - - Traits traits; - std::array obb_points; - CGAL::oriented_bounding_box(sm, obb_points, CGAL::parameters::use_convex_hull(true) - .geom_traits(traits)); - - FT vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points); - check_equality(vol, 0.883371); - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST - CGAL::Surface_mesh result_mesh; - CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3], - obb_points[4], obb_points[5], obb_points[6], obb_points[7], result_mesh); - - std::ofstream out("data/obb_result.off"); - out << result_mesh; - out.close(); -#endif -} - -void test_compute_obb_mesh(const std::string fname) -{ - std::ifstream input(fname); - CGAL::Surface_mesh mesh; - if(!input || !(input >> mesh) || mesh.is_empty()) - { - std::cerr << fname << " is not a valid off file." << std::endl; - std::exit(1); - } - - CGAL::Surface_mesh obbmesh; - CGAL::oriented_bounding_box(mesh, obbmesh); - -#ifdef CGAL_OPTIMAL_BOUNDING_BOX_DEBUG_TEST - std::ofstream out("/tmp/result_elephant.off"); - out << obbmesh; - out.close(); -#endif -} - -void test_function_defaults_traits(const std::string fname1) -{ - std::ifstream input1(fname1); - CGAL::Surface_mesh mesh1; - if(!input1 || !(input1 >> mesh1) || mesh1.is_empty()) - { - std::cerr << fname1 << " is not a valid off file." << std::endl; - std::exit(1); - } - - std::array obb_points; - CGAL::oriented_bounding_box(sm_points, obb_points, CGAL::parameters::use_convex_hull(true)); - - const FT vol = CGAL::Optimal_bounding_box::calculate_volume(obb_points); - check_equality(vol, 0.883371); + test_OBB_data(points, expected_vol, false /*no convex hull due to degenerate data*/); } int main() { - test_genetic_algorithm(); + std::cout.precision(17); - test_random_unit_tetra(); - test_reference_tetrahedron("data/reference_tetrahedron.off"); - test_long_tetrahedron("data/long_tetrahedron.off"); - test_compute_obb_evolution("data/random_unit_tetra.off"); - test_compute_obb_mesh("data/elephant.off"); - test_function_defaults_traits("data/random_unit_tetra.off"); + test_OBB_of_mesh("data/elephant.off", 0.294296); + test_OBB_of_mesh("data/long_tetrahedron.off", 0.04); + test_OBB_of_mesh("data/reference_tetrahedron.off", 1); + + // degenerate cases + test_OBB_of_mesh("data/triangles.off", 0); // 2D data set + test_OBB_of_mesh("data/flat_mesh.off", 0); // 2D data set + test_OBB_of_point_set("data/points_2D.xyz", 0); // 2D data set + test_OBB_of_point_set("data/points_1D.xyz", 0); // 1D data set + test_OBB_of_point_set("data/points_0D.xyz", 0); // 0D data set + + std::cout << "Done!" << std::endl; return 0; } From 4b04b752e581d64ca85969f4bf74b49fdda733c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 26 Mar 2020 08:59:39 +0100 Subject: [PATCH 150/150] Update dependencies --- .../package_info/Optimal_bounding_box/dependencies | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Optimal_bounding_box/package_info/Optimal_bounding_box/dependencies b/Optimal_bounding_box/package_info/Optimal_bounding_box/dependencies index 12c0af8bdbb..2939f3c62fa 100644 --- a/Optimal_bounding_box/package_info/Optimal_bounding_box/dependencies +++ b/Optimal_bounding_box/package_info/Optimal_bounding_box/dependencies @@ -1,6 +1,7 @@ Algebraic_foundations Arithmetic_kernel BGL +Bounding_volumes Cartesian_kernel Circulator Convex_hull_2 @@ -19,6 +20,8 @@ Kernel_d Modular_arithmetic Number_types Optimal_bounding_box +Optimisation_basic +Polygon Profiling_tools Property_map Random_numbers