Dukales

C++14 implementation of the Quickhull algorithm

Jan 26th, 2015
348
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 28.51 KB | None | 0 0
  1. /* Quickhull algorithm implementation
  2.  *
  3.  * Copyright (c) 2014-2015, Anatoliy V. Tomilov
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following condition is met:
  8.  * Redistributions of source code must retain the above copyright notice, this condition and the following disclaimer.
  9.  *
  10.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  11.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  12.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  13.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  14.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  15.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  16.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  17.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  18.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  19.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  20.  * POSSIBILITY OF SUCH DAMAGE.
  21.  */
  22. #pragma once
  23.  
  24. #include <valarray>
  25. #include <vector>
  26. #include <deque>
  27. #include <list>
  28. #include <set>
  29. #include <unordered_set>
  30. #include <map>
  31. #include <unordered_map>
  32. #include <iterator>
  33. #include <algorithm>
  34. #include <utility>
  35. #include <numeric>
  36.  
  37. #include <cmath>
  38. #include <cassert>
  39.  
  40. template< typename points_iterator >
  41. struct quick_hull
  42. {
  43.  
  44.     static_assert(std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< points_iterator >::iterator_category >::value);
  45.  
  46.     using size_type = std::size_t;
  47.  
  48.     using point = typename std::iterator_traits< points_iterator >::value_type;
  49.     using value_type = typename point::value_type;
  50.  
  51.     size_type const dimension_;
  52.     value_type const eps;
  53.  
  54.     quick_hull(size_type const _dimension,
  55.                value_type _eps = std::numeric_limits< value_type >::epsilon())
  56.         : dimension_(_dimension)
  57.         , eps(std::move(_eps))
  58.         , matrix_(dimension_)
  59.         , shadow_matrix_(dimension_)
  60.         , minor_(dimension_)
  61.     {
  62.         assert(1 < dimension_);
  63.         assert(!(eps < zero));
  64.         for (size_type r = 0; r < dimension_; ++r) {
  65.             matrix_[r].resize(dimension_);
  66.             shadow_matrix_[r].resize(dimension_);
  67.         }
  68.         size_type const minor_size = dimension_ - 1;
  69.         for (size_type r = 1; r < minor_size; ++r) {
  70.             minor_[r].resize(minor_size);
  71.         }
  72.         minor_.front().resize(dimension_);
  73.         minor_.back().resize(dimension_);
  74.     }
  75.  
  76.     using point_array = std::vector< points_iterator >;
  77.     using point_list = std::list< points_iterator >;
  78.     using facet_array = std::vector< size_type >;
  79.  
  80.     struct facet // (d - 1)-dimensional face
  81.     {
  82.  
  83.         using normal = std::valarray< value_type >;
  84.  
  85.         point_array vertices_; // d points (oriented)
  86.         point_list outside_; // if empty, then is convex hull's facet, else the first point (i.e. outside_.front()) is the furthest point from this facet
  87.         facet_array neighbours_; // neighbouring facets
  88.  
  89.         // hyperplane equation
  90.         normal normal_; // components of normalized normal vector
  91.         value_type D; // distance from the origin to the hyperplane
  92.  
  93.         void
  94.         init(point_array && _vertices,
  95.              size_type const _neighbour)
  96.         {
  97.             vertices_ = std::move(_vertices);
  98. #pragma clang diagnostic push
  99. #pragma clang diagnostic ignored "-Wshadow"
  100.             size_type const dimension_ = vertices_.size();
  101. #pragma clang diagnostic pop
  102.             neighbours_.reserve(dimension_);
  103.             neighbours_.push_back(_neighbour);
  104.             normal_.resize(dimension_);
  105.         }
  106.  
  107.         facet(point_array && _vertices,
  108.               size_type const _neighbour)
  109.         {
  110.             init(std::move(_vertices), _neighbour);
  111.         }
  112.  
  113.         facet(typename point_array::const_iterator _first,
  114.               typename point_array::const_iterator _middle,
  115.               typename point_array::const_iterator _last)
  116.             : vertices_(_first, std::prev(_middle))
  117.         {
  118.             vertices_.insert(std::cend(vertices_), _middle, _last);
  119. #pragma clang diagnostic push
  120. #pragma clang diagnostic ignored "-Wshadow"
  121.             size_type const dimension_ = vertices_.size();
  122. #pragma clang diagnostic pop
  123.             neighbours_.reserve(dimension_);
  124.             normal_.resize(dimension_);
  125.         }
  126.  
  127.         value_type
  128.         distance(point const & _point) const
  129.         {
  130.             return std::inner_product(std::cbegin(normal_), std::cend(normal_), std::cbegin(_point), D);
  131.         }
  132.  
  133.     };
  134.  
  135.     using facets_storage = std::deque< facet >;
  136.  
  137.     facets_storage facets_;
  138.  
  139.     value_type
  140.     cos_of_dihedral_angle(facet const & _this, facet const & _other) const
  141.     {
  142.         return std::inner_product(std::cbegin(_this.normal_), std::cend(_this.normal_), std::cbegin(_other.normal_), zero);
  143.     }
  144.  
  145. private :
  146.  
  147.     // math (simple functions, matrices, etc):
  148.  
  149.     value_type const zero = value_type(0);
  150.     value_type const one = value_type(1);
  151.  
  152.     using row = std::valarray< value_type >;
  153.     using matrix = std::vector< row >;
  154.  
  155.     matrix matrix_;
  156.     matrix shadow_matrix_;
  157.     matrix minor_;
  158.  
  159.     void
  160.     transpose() // transpose to cheaper filling columns with ones
  161.     {
  162.         for (size_type r = 0; r < dimension_; ++r) {
  163.             row & row_ = shadow_matrix_[r];
  164.             for (size_type c = 1 + r; c < dimension_; ++c) {
  165.                 using std::swap;
  166.                 swap(shadow_matrix_[c][r], row_[c]);
  167.             }
  168.         }
  169.     }
  170.  
  171.     void
  172.     restore_matrix() // reload matrix from storage
  173.     {
  174.         matrix_ = shadow_matrix_;
  175.     }
  176.  
  177.     void
  178.     restore_matrix(size_type const _identity) // load matrix from storage and replace _identity column with ones
  179.     {
  180.         for (size_type c = 0; c < dimension_; ++c) {
  181.             row & col_ = matrix_[c];
  182.             if (c == _identity) {
  183.                 col_ = one;
  184.             } else {
  185.                 col_ = shadow_matrix_[c];
  186.             }
  187.         }
  188.     }
  189.  
  190.     void
  191.     square_matrix(size_type const _size) // matrix_ = shadow_matrix_ * transposed shadow_matrix_
  192.     {
  193.         assert(_size < dimension_);
  194.         for (size_type r = 0; r < _size; ++r) {
  195.             row & lhs_ = shadow_matrix_[r];
  196.             row const & row_ = matrix_[r];
  197.             for (size_type c = 0; c < _size; ++c) {
  198.                 lhs_[c] = std::inner_product(std::cbegin(row_), std::cend(row_), std::cbegin(matrix_[c]), zero);
  199.             }
  200.         }
  201.     }
  202.  
  203.     value_type
  204.     det(matrix & _matrix, size_type const _dimension) // based on LUP decomposition (complexity is 2 * n^3 / 3 + O(n^2) vs 4 * n^3 / 3 + O(n^2) for QR decomposition via Householder reflections)
  205.     {
  206.         assert(0 < _dimension);
  207.         value_type det_ = one;
  208.         for (size_type i = 0; i < _dimension; ++i) {
  209.             size_type p = i;
  210.             using std::abs;
  211.             value_type max_ = abs(_matrix[p][i]);
  212.             size_type pivot = p;
  213.             while (++p < _dimension) {
  214.                 value_type y_ = abs(_matrix[p][i]);
  215.                 if (max_ < y_) {
  216.                     max_ = std::move(y_);
  217.                     pivot = p;
  218.                 }
  219.             }
  220.             if (!(eps < max_)) { // regular?
  221.                 return zero; // singular
  222.             }
  223.             row & ri_ = _matrix[i];
  224.             if (pivot != i) {
  225.                 det_ = -det_; // each permutation flips sign of det
  226.                 ri_.swap(_matrix[pivot]);
  227.             }
  228.             value_type & dia_ = ri_[i];
  229.             value_type const inv_ = one / dia_;
  230.             det_ *= std::move(dia_); // det is multiple of diagonal elements
  231.             for (size_type j = 1 + i; j < _dimension; ++j) {
  232.                 _matrix[j][i] *= inv_;
  233.             }
  234.             for (size_type a = 1 + i; a < _dimension; ++a) {
  235.                 row & a_ = minor_[a - 1];
  236.                 value_type const & ai_ = _matrix[a][i];
  237.                 for (size_type b = 1 + i; b < _dimension; ++ b) {
  238.                     a_[b - 1] = ai_ * ri_[b];
  239.                 }
  240.             }
  241.             for (size_type a = 1 + i; a < _dimension; ++a) {
  242.                 row const & a_ = minor_[a - 1];
  243.                 row & ra_ = _matrix[a];
  244.                 for (size_type b = 1 + i; b < _dimension; ++ b) {
  245.                     ra_[b] -= a_[b - 1];
  246.                 }
  247.             }
  248.         }
  249.         return det_;
  250.     }
  251.  
  252.     value_type
  253.     det()
  254.     {
  255.         return det(matrix_, dimension_);
  256.     }
  257.  
  258.     // geometry and basic operations on geometric primitives:
  259.  
  260.     void
  261.     set_hyperplane_equation(facet & _facet)
  262.     {
  263.         for (size_type r = 0; r < dimension_; ++r) {
  264.             std::copy_n(std::cbegin(*_facet.vertices_[r]), dimension_, std::begin(shadow_matrix_[r]));
  265.         }
  266.         transpose();
  267.         value_type N = zero;
  268.         for (size_type i = 0; i < dimension_; ++i) {
  269.             restore_matrix(i);
  270.             value_type & n = _facet.normal_[i];
  271.             n = det();
  272.             N += n * n;
  273.         }
  274.         using std::sqrt;
  275.         N = one / sqrt(std::move(N));
  276.         _facet.normal_ *= N;
  277.         restore_matrix();
  278.         _facet.D = -det() * std::move(N);
  279.     }
  280.  
  281.     bool
  282.     orthonormalize(point_array const & _affine_space, size_type const _rank, row const & _origin)
  283.     {
  284.         assert(!(dimension_ < _rank));
  285.         assert(!(_affine_space.size() < _rank));
  286.         auto vertex = std::begin(_affine_space);
  287.         for (size_type r = 0; r < _rank; ++r) { // affine space -> vector space
  288.             row & row_ = shadow_matrix_[r];
  289.             std::copy_n(std::cbegin(**vertex), dimension_, std::begin(row_));
  290.             row_ -= _origin;
  291.             ++vertex;
  292.         }
  293.         for (size_type i = 0; i < _rank; ++i) { // Householder transformation
  294.             value_type norm_ = zero;
  295.             row & qri_ = shadow_matrix_[i]; // shadow_matrix_ is packed QR after
  296.             for (size_type j = i; j < dimension_; ++j) {
  297.                 value_type const & qrij_ = qri_[j];
  298.                 norm_ += qrij_ * qrij_;
  299.             }
  300.             using std::sqrt;
  301.             norm_ = sqrt(norm_);
  302.             if (!(eps < norm_)) {
  303.                 return false;
  304.             }
  305.             value_type & qrii_ = qri_[i];
  306.             bool const sign_ = (zero < qrii_);
  307.             value_type factor_ = norm_ * (norm_ + (sign_ ? qrii_ : -qrii_));
  308.             if (!(eps < factor_)) {
  309.                 return false;
  310.             }
  311.             factor_ = one / sqrt(std::move(factor_));
  312.             if (sign_) {
  313.                 qrii_ += norm_;
  314.             } else {
  315.                 qrii_ -= norm_;
  316.             }
  317.             for (size_type k = i; k < dimension_; ++k) {
  318.                 qri_[k] *= factor_;
  319.             }
  320.             for (size_type j = i + 1; j < _rank; ++j) {
  321.                 row & qrj_ = shadow_matrix_[j];
  322.                 value_type s_ = zero;
  323.                 for (size_type k = i; k < dimension_; ++k) {
  324.                     s_ += qri_[k] * qrj_[k];
  325.                 }
  326.                 for (size_type k = i; k < dimension_; ++k) {
  327.                     qrj_[k] -= qri_[k] * s_;
  328.                 }
  329.             }
  330.         }
  331.         return true;
  332.     }
  333.  
  334.     void
  335.     forward_transformation(size_type const _rank) // calculation of Q
  336.     {
  337.         assert(!(dimension_ < _rank));
  338.         for (size_type i = 0; i < _rank; ++i) {
  339.             row & qi_ = matrix_[i]; // matrix_ is Q after
  340.             qi_ = zero;
  341.             qi_[i] = one;
  342.             size_type j = _rank;
  343.             while (0 < j) {
  344.                 --j;
  345.                 row & qrj_ = shadow_matrix_[j]; // containing packed QR
  346.                 value_type s_ = zero;
  347.                 for (size_type k = j; k < dimension_; ++k) {
  348.                     s_ += qrj_[k] * qi_[k];
  349.                 }
  350.                 for (size_type k = j; k < dimension_; ++k) {
  351.                     qi_[k] -= qrj_[k] * s_;
  352.                 }
  353.             }
  354.         }
  355.     }
  356.  
  357.     bool
  358.     steal_best(point_list & _from, point_array & _to)
  359.     {
  360.         assert(!_to.empty());
  361.         size_type const rank_ = _to.size() - 1;
  362.         assert(rank_ < dimension_);
  363.         row & origin_ = matrix_[rank_];
  364.         std::copy_n(std::cbegin(*_to.back()), dimension_, std::begin(origin_));
  365.         if (!orthonormalize(_to, rank_, origin_)) {
  366.             return false;
  367.         }
  368.         forward_transformation(rank_);
  369.         row & projection_ = minor_.back();
  370.         row & apex_ = minor_.front();
  371.         value_type distance_ = zero;
  372.         auto furthest = std::cend(_from);
  373.         for (auto it = std::cbegin(_from); it != std::cend(_from); ++it) {
  374.             std::copy_n(std::cbegin(**it), dimension_, std::begin(apex_));
  375.             apex_ -= origin_; // turn translated space into vector space
  376.             projection_ = apex_; // project onto orthogonal subspace
  377.             for (size_type i = 0; i < rank_; ++i) {
  378.                 row const & qi_ = matrix_[i];
  379.                 projection_ -= std::inner_product(std::cbegin(apex_), std::cend(apex_), std::cbegin(qi_), zero) * qi_;
  380.             }
  381.             projection_ *= projection_;
  382.             using std::sqrt;
  383.             value_type d_ = sqrt(projection_.sum()); // distance to subspace
  384.             if (distance_ < d_) {
  385.                 distance_ = std::move(d_);
  386.                 furthest = it;
  387.             }
  388.         }
  389.         if (furthest == std::cend(_from)) {
  390.             return false;
  391.         }
  392.         _to.push_back(std::move(*furthest));
  393.         _from.erase(furthest);
  394.         return true;
  395.     }
  396.  
  397.     std::deque< point_array > ordered_; // ordered, but not oriented vertices of facets
  398.     std::set< size_type, std::greater< size_type > > removed_facets_;
  399.  
  400.     size_type
  401.     add_facet(point_array && _vertices, size_type const _oth_facet)
  402.     {
  403.         assert(ordered_.size() == facets_.size());
  404.         if (removed_facets_.empty()) {
  405.             size_type const f = facets_.size();
  406.             facets_.emplace_back(std::move(_vertices), _oth_facet);
  407.             facet & facet_ = facets_.back();
  408.             set_hyperplane_equation(facet_);
  409.             ordered_.emplace_back();
  410.             point_array & ordered_vertices_ = ordered_.back();
  411.             ordered_vertices_ = facet_.vertices_;
  412.             std::sort(std::begin(ordered_vertices_), std::end(ordered_vertices_));
  413.             return f;
  414.         } else {
  415.             auto const rend = std::prev(std::cend(removed_facets_));
  416.             size_type const f = *rend;
  417.             removed_facets_.erase(rend);
  418.             facet & facet_ = facets_[f];
  419.             facet_.init(std::move(_vertices), _oth_facet);
  420.             set_hyperplane_equation(facet_);
  421.             point_array & ordered_vertices_ = ordered_[f];
  422.             ordered_vertices_ = facet_.vertices_;
  423.             std::sort(std::begin(ordered_vertices_), std::end(ordered_vertices_));
  424.             return f;
  425.         }
  426.     }
  427.  
  428.     // selecting of the best facet:
  429.  
  430.     using ranking = std::multimap< value_type, size_type >;
  431.     using ranking_meta = std::unordered_map< size_type, typename ranking::iterator >;
  432.  
  433.     ranking ranking_;
  434.     ranking_meta ranking_meta_;
  435.  
  436.     void
  437.     rank(value_type && _orientation, size_type const _facet)
  438.     {
  439.         if (eps < _orientation) {
  440.             ranking_meta_.emplace(_facet, ranking_.emplace(std::move(_orientation), _facet));
  441.         }
  442.     }
  443.  
  444.     void
  445.     unrank_and_remove(size_type const _facet)
  446.     {
  447.         auto const r = ranking_meta_.find(_facet);
  448.         if (r != std::end(ranking_meta_)) {
  449.             ranking_.erase(r->second);
  450.             ranking_meta_.erase(r);
  451.         }
  452.         removed_facets_.insert(_facet);
  453.     }
  454.  
  455.     value_type
  456.     partition(facet & _facet, point_list & _points)
  457.     {
  458.         auto it = std::cbegin(_points);
  459.         value_type distance_ = zero;
  460.         while (it != std::cend(_points)) {
  461.             auto const next = std::next(it);
  462.             value_type d_ = _facet.distance(**it);
  463.             if (eps < d_) {
  464.                 if (distance_ < d_) {
  465.                     distance_ = std::move(d_);
  466.                     _facet.outside_.splice(std::cbegin(_facet.outside_), _points, it);
  467.                 } else {
  468.                     _facet.outside_.splice(std::cend(_facet.outside_), _points, it);
  469.                 }
  470.             }
  471.             it = next;
  472.         }
  473.         return distance_;
  474.     }
  475.  
  476.     size_type
  477.     get_best_facet() const // select the facet with furthest (between all facets with non-empty outsides_ set) furthest point
  478.     {
  479.         assert(ranking_meta_.size() == ranking_.size());
  480.         return std::prev(std::cend(ranking_))->second;
  481.     }
  482.  
  483.     // visibility from apex:
  484.  
  485.     using facet_unordered_set = std::unordered_set< size_type >;
  486.  
  487.     facet_unordered_set visited_;
  488.     facet_unordered_set bth_facets_; // before-the-horizon facets
  489.     facet_unordered_set not_bth_facets_; // visible, but not before-the-horizon facets
  490.  
  491.     bool
  492.     is_invisible(size_type const _facet) const // to detect over-the-horizon facets
  493.     {
  494.         return (0 == not_bth_facets_.count(_facet)) && (0 == bth_facets_.count(_facet));
  495.     }
  496.  
  497.     bool
  498.     process_visibles(size_type const _facet, point const & _apex) // traverse the graph of visible facets
  499.     {
  500.         visited_.insert(_facet);
  501.         facet const & facet_ = facets_[_facet];
  502.         if (eps < facet_.distance(_apex)) {
  503.             bool bth_ = false;
  504.             for (size_type const neighbour : facet_.neighbours_) {
  505.                 if (visited_.count(neighbour) == 0) {
  506.                     if (process_visibles(neighbour, _apex)) {
  507.                         bth_ = true;
  508.                     }
  509.                 } else if (!bth_) {
  510.                     if (is_invisible(neighbour)){
  511.                         bth_ = true;
  512.                     }
  513.                 }
  514.             }
  515.             if (bth_) {
  516.                 bth_facets_.insert(_facet);
  517.             } else {
  518.                 not_bth_facets_.insert(_facet);
  519.             }
  520.             return false;
  521.         } else {
  522.             return true;
  523.         }
  524.     }
  525.  
  526.     void
  527.     clear_bth()
  528.     {
  529.         visited_.clear();
  530.         bth_facets_.clear();
  531.         not_bth_facets_.clear();
  532.     }
  533.  
  534.     void
  535.     replace_neighbour(size_type const _facet, size_type const _from, size_type const _to)
  536.     {
  537.         if (_from == _to) {
  538.             return;
  539.         }
  540.         for (size_type & neighbour : facets_[_facet].neighbours_) {
  541.             if (neighbour == _from) {
  542.                 neighbour = _to;
  543.                 return;
  544.             }
  545.         }
  546.     }
  547.  
  548.     // adjacency of new facets via its common ridges:
  549.  
  550.     struct ridge
  551.     {
  552.  
  553.         point_array const & ordered_;
  554.         size_type const facet_;
  555.         size_type const excluded_vertex_;
  556.  
  557.         bool
  558.         operator < (ridge const & _other) const
  559.         {
  560. #pragma clang diagnostic push
  561. #pragma clang diagnostic ignored "-Wshadow"
  562.             size_type const dimension_ = ordered_.size();
  563. #pragma clang diagnostic pop
  564.             size_type i = 0;
  565.             size_type j = 0;
  566.             for (;;) {
  567.                 if (i == excluded_vertex_) {
  568.                     ++i;
  569.                 }
  570.                 if (j == _other.excluded_vertex_) {
  571.                     ++j;
  572.                 }
  573.                 if (i == dimension_) {
  574.                     assert(j == dimension_);
  575.                     break;
  576.                 }
  577.                 if (j == dimension_) {
  578.                     assert(i == dimension_);
  579.                     break;
  580.                 }
  581.                 points_iterator const & lhs_ = ordered_[i];
  582.                 points_iterator const & rhs_ = _other.ordered_[j];
  583.                 if (lhs_ < rhs_) {
  584.                     return true;
  585.                 } else if (rhs_ < lhs_) {
  586.                     break;
  587.                 } else { // equivalent
  588.                     ++i;
  589.                     ++j;
  590.                 }
  591.             }
  592.             return false;
  593.         }
  594.  
  595.     };
  596.  
  597.     std::set< ridge > unique_ridges_;
  598.  
  599.     void
  600.     find_adjacent_facets(size_type const _facet, points_iterator const _apex)
  601.     {
  602.         point_array const & ridge_ = ordered_[_facet];
  603.         for (size_type i = 0; i < dimension_; ++i) {
  604.             if (ridge_[i] != _apex) {
  605.                 auto position = unique_ridges_.insert({ridge_, _facet, i});
  606.                 if (!position.second) {
  607.                     size_type const neighbour = position.first->facet_;
  608.                     facets_[neighbour].neighbours_.push_back(_facet);
  609.                     facets_[_facet].neighbours_.push_back(neighbour);
  610.                     unique_ridges_.erase(position.first);
  611.                 }
  612.             }
  613.         }
  614.     }
  615.  
  616. public : // largest possible simplex heuristic, convex hull algorithm
  617.  
  618.     // http://math.stackexchange.com/questions/822741/
  619.     value_type
  620.     hypervolume(point_array const & _vertices) // hypervolume of parallelotope spanned on vectors from one of _vertices to all the rest
  621.     {
  622.         assert(!_vertices.empty());
  623.         size_type const rank_ = _vertices.size() - 1;
  624.         assert(!(dimension_ < rank_));
  625.         row & origin_ = minor_.back();
  626.         std::copy_n(std::cbegin(*_vertices.back()), dimension_, std::begin(origin_));
  627.         auto vertex = std::cbegin(_vertices);
  628.         for (size_type r = 0; r < rank_; ++r) { // affine space -> vector space
  629.             row & row_ = matrix_[r];
  630.             std::copy_n(std::cbegin(**vertex), dimension_, std::begin(row_));
  631.             row_ -= origin_;
  632.             ++vertex;
  633.         }
  634.         if (rank_ == dimension_) { // oriented hypervolume
  635.             return det();
  636.         } else { // non-oriented _rank-dimensional measure
  637.             square_matrix(rank_);
  638.             using std::sqrt;
  639.             return sqrt(det(shadow_matrix_, rank_));
  640.         }
  641.     }
  642.  
  643.     point_array
  644.     create_initial_simplex(points_iterator const _beg, points_iterator const _end)
  645.     {
  646.         // selection of (dimension_ + 1) affinely independent points
  647.         point_array basis_;
  648.         if (_beg == _end) {
  649.             return basis_;
  650.         }
  651.         basis_.reserve(dimension_ + 1);
  652.         basis_.push_back(_beg);
  653.         point_list internal_set_; // it is possible to track "internal set" during whole the algorithm, but it is non-zero-cost
  654.         {
  655.             auto it = _beg;
  656.             while (++it != _end) {
  657.                 internal_set_.push_back(it);
  658.             }
  659.         }
  660.         if (!steal_best(internal_set_, basis_)) {
  661.             return basis_; // can't find affinely independent second point
  662.         }
  663.         { // rejudge 0-indexed point
  664.             points_iterator & first_ = basis_.front();
  665.             internal_set_.push_back(first_);
  666.             first_ = std::move(basis_.back());
  667.             basis_.pop_back();
  668.         }
  669.         for (size_type i = 0; i < dimension_; ++i) {
  670.             if (!steal_best(internal_set_, basis_)) {
  671.                 return basis_; // can't find (i + 2) affinely independent point
  672.             }
  673.         }
  674.         assert(basis_.size() == dimension_ + 1); // simplex
  675.         // simplex construction
  676.         bool inward_ = (zero < hypervolume(basis_)); // is top oriented?
  677.         auto const vbeg = std::cbegin(basis_);
  678.         auto const vend = std::cend(basis_);
  679.         for (auto exclusive = vend; exclusive != vbeg; --exclusive) {
  680.             size_type const newfacet = facets_.size();
  681.             facets_.emplace_back(vbeg, exclusive, vend);
  682.             facet & facet_ = facets_.back();
  683.             inward_ = !inward_;
  684.             if (inward_) {
  685.                 std::swap(facet_.vertices_.front(), // not works for dimension_ == 1
  686.                           facet_.vertices_.back());
  687.             }
  688.             set_hyperplane_equation(facet_);
  689.             ordered_.emplace_back();
  690.             point_array & ordered_vertices_ = ordered_.back();
  691.             ordered_vertices_ = facet_.vertices_;
  692.             std::sort(std::begin(ordered_vertices_), std::end(ordered_vertices_));
  693.             rank(partition(facet_, internal_set_), newfacet);
  694.         }
  695.         for (size_type i = 0; i <= dimension_; ++i) { // adjacency
  696.             facet_array & neighbours_ = facets_[i].neighbours_;
  697.             for (size_type j = 0; j <= dimension_; ++j) {
  698.                 if (i != j) {
  699.                     neighbours_.push_back(j);
  700.                 }
  701.             }
  702.         }
  703.         return basis_;
  704.     }
  705.  
  706.     void
  707.     create_convex_hull()
  708.     {
  709.         assert(facets_.size() == dimension_ + 1);
  710.         assert(ordered_.size() == dimension_ + 1);
  711.         assert(removed_facets_.empty());
  712.         point_list outside_;
  713.         point_array vertices_;
  714.         facet_array neighbours_;
  715.         point_array ridge_; // horizon ridge + furthest point = new facet
  716.         facet_array newfacets_;
  717.         while (!ranking_.empty()) {
  718.             size_type best_facet = get_best_facet();
  719.             point_list & best_facet_outsides_ = facets_[best_facet].outside_;
  720.             assert(!best_facet_outsides_.empty());
  721.             points_iterator const apex = best_facet_outsides_.front();
  722.             best_facet_outsides_.pop_front();
  723.             process_visibles(best_facet, *apex);
  724.             assert(outside_.empty());
  725.             for (size_type const not_bth_facet : not_bth_facets_) {
  726.                 facet & facet_ = facets_[not_bth_facet];
  727.                 outside_.splice(std::cend(outside_), std::move(facet_.outside_));
  728.                 facet_.vertices_.clear();
  729.                 facet_.neighbours_.clear();
  730.                 unrank_and_remove(not_bth_facet);
  731.             }
  732.             assert(newfacets_.empty());
  733.             for (size_type const bth_facet : bth_facets_) {
  734.                 facet & facet_ = facets_[bth_facet];
  735.                 outside_.splice(std::cend(outside_), std::move(facet_.outside_));
  736.                 vertices_ = std::move(facet_.vertices_);
  737.                 neighbours_ = std::move(facet_.neighbours_);
  738.                 unrank_and_remove(bth_facet);
  739.                 for (size_type const neighbour : neighbours_) {
  740.                     if (is_invisible(neighbour)) { // is over-the-horizon facet?
  741.                         {
  742.                             point_array const & horizon_ = ordered_[neighbour];
  743.                             assert(ridge_.empty());
  744.                             ridge_.reserve(dimension_);
  745.                             for (points_iterator const vertex : vertices_) { // facets intersection with keeping of points order as it is in visible facet
  746.                                 if (std::binary_search(std::cbegin(horizon_), std::cend(horizon_), vertex)) {
  747.                                     ridge_.push_back(vertex);
  748.                                 } else {
  749.                                     ridge_.push_back(apex);
  750.                                 }
  751.                             }
  752.                             assert(ridge_.size() == dimension_); // facet
  753.                         }
  754.                         size_type const newfacet = add_facet(std::move(ridge_), neighbour);
  755.                         newfacets_.push_back(newfacet);
  756.                         replace_neighbour(neighbour, bth_facet, newfacet);
  757.                         find_adjacent_facets(newfacet, apex);
  758.                     }
  759.                 }
  760.             }
  761.             assert(unique_ridges_.empty());
  762.             clear_bth();
  763.             for (size_type const newfacet : newfacets_) {
  764.                 rank(partition(facets_[newfacet], outside_), newfacet);
  765.             }
  766.             newfacets_.clear();
  767.             outside_.clear();
  768.         }
  769.         assert(ranking_meta_.empty());
  770.         assert(outside_.empty());
  771.         { // compactify
  772.             size_type source = facets_.size();
  773.             for (size_type const destination : removed_facets_) {
  774.                 if (destination != --source) {
  775.                     facet & facet_ = facets_[destination];
  776.                     facet_ = std::move(facets_.back());
  777.                     for (size_type const neighbour : facet_.neighbours_) {
  778.                         replace_neighbour(neighbour, source, destination);
  779.                     }
  780.                 }
  781.                 facets_.pop_back();
  782.             }
  783.             facets_.shrink_to_fit();
  784.             removed_facets_.clear();
  785.         }
  786.         ordered_.clear();
  787.         ordered_.shrink_to_fit();
  788.     } // Please check the orientation by yourself (using distance to inner point calculations). Then check Euler–Poincaré characteristic. If not convex, then increase eps properly.
  789.  
  790. };
Advertisement
Add Comment
Please, Sign In to add comment