123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- #ifndef BOOST_POLYGON_VORONOI_BUILDER
- #define BOOST_POLYGON_VORONOI_BUILDER
- #include <algorithm>
- #include <map>
- #include <queue>
- #include <utility>
- #include <vector>
- #include "detail/voronoi_ctypes.hpp"
- #include "detail/voronoi_predicates.hpp"
- #include "detail/voronoi_structures.hpp"
- #include "voronoi_geometry_type.hpp"
- namespace boost {
- namespace polygon {
- template <typename T,
- typename CTT = detail::voronoi_ctype_traits<T>,
- typename VP = detail::voronoi_predicates<CTT> >
- class voronoi_builder {
- public:
- typedef typename CTT::int_type int_type;
- typedef typename CTT::fpt_type fpt_type;
- voronoi_builder() : index_(0) {}
-
- std::size_t insert_point(const int_type& x, const int_type& y) {
- site_events_.push_back(site_event_type(x, y));
- site_events_.back().initial_index(index_);
- site_events_.back().source_category(SOURCE_CATEGORY_SINGLE_POINT);
- return index_++;
- }
-
-
-
-
- std::size_t insert_segment(
- const int_type& x1, const int_type& y1,
- const int_type& x2, const int_type& y2) {
-
- point_type p1(x1, y1);
- site_events_.push_back(site_event_type(p1));
- site_events_.back().initial_index(index_);
- site_events_.back().source_category(SOURCE_CATEGORY_SEGMENT_START_POINT);
-
- point_type p2(x2, y2);
- site_events_.push_back(site_event_type(p2));
- site_events_.back().initial_index(index_);
- site_events_.back().source_category(SOURCE_CATEGORY_SEGMENT_END_POINT);
-
- if (point_comparison_(p1, p2)) {
- site_events_.push_back(site_event_type(p1, p2));
- site_events_.back().source_category(SOURCE_CATEGORY_INITIAL_SEGMENT);
- } else {
- site_events_.push_back(site_event_type(p2, p1));
- site_events_.back().source_category(SOURCE_CATEGORY_REVERSE_SEGMENT);
- }
- site_events_.back().initial_index(index_);
- return index_++;
- }
-
- template <typename OUTPUT>
- void construct(OUTPUT* output) {
-
- output->_reserve(site_events_.size());
- init_sites_queue();
- init_beach_line(output);
-
- event_comparison_predicate event_comparison;
- while (!circle_events_.empty() ||
- !(site_event_iterator_ == site_events_.end())) {
- if (circle_events_.empty()) {
- process_site_event(output);
- } else if (site_event_iterator_ == site_events_.end()) {
- process_circle_event(output);
- } else {
- if (event_comparison(*site_event_iterator_,
- circle_events_.top().first)) {
- process_site_event(output);
- } else {
- process_circle_event(output);
- }
- }
- while (!circle_events_.empty() &&
- !circle_events_.top().first.is_active()) {
- circle_events_.pop();
- }
- }
- beach_line_.clear();
-
- output->_build();
- }
- void clear() {
- index_ = 0;
- site_events_.clear();
- }
- private:
- typedef detail::point_2d<int_type> point_type;
- typedef detail::site_event<int_type> site_event_type;
- typedef typename std::vector<site_event_type>::const_iterator
- site_event_iterator_type;
- typedef detail::circle_event<fpt_type> circle_event_type;
- typedef typename VP::template point_comparison_predicate<point_type>
- point_comparison_predicate;
- typedef typename VP::
- template event_comparison_predicate<site_event_type, circle_event_type>
- event_comparison_predicate;
- typedef typename VP::
- template circle_formation_predicate<site_event_type, circle_event_type>
- circle_formation_predicate_type;
- typedef void edge_type;
- typedef detail::beach_line_node_key<site_event_type> key_type;
- typedef detail::beach_line_node_data<edge_type, circle_event_type>
- value_type;
- typedef typename VP::template node_comparison_predicate<key_type>
- node_comparer_type;
- typedef std::map< key_type, value_type, node_comparer_type > beach_line_type;
- typedef typename beach_line_type::iterator beach_line_iterator;
- typedef std::pair<circle_event_type, beach_line_iterator> event_type;
- struct event_comparison_type {
- bool operator()(const event_type& lhs, const event_type& rhs) const {
- return predicate(rhs.first, lhs.first);
- }
- event_comparison_predicate predicate;
- };
- typedef detail::ordered_queue<event_type, event_comparison_type>
- circle_event_queue_type;
- typedef std::pair<point_type, beach_line_iterator> end_point_type;
- void init_sites_queue() {
-
- std::sort(site_events_.begin(), site_events_.end(),
- event_comparison_predicate());
-
- site_events_.erase(std::unique(
- site_events_.begin(), site_events_.end()), site_events_.end());
-
- for (std::size_t cur = 0; cur < site_events_.size(); ++cur) {
- site_events_[cur].sorted_index(cur);
- }
-
- site_event_iterator_ = site_events_.begin();
- }
- template <typename OUTPUT>
- void init_beach_line(OUTPUT* output) {
- if (site_events_.empty())
- return;
- if (site_events_.size() == 1) {
-
- output->_process_single_site(site_events_[0]);
- ++site_event_iterator_;
- } else {
- int skip = 0;
- while (site_event_iterator_ != site_events_.end() &&
- VP::is_vertical(site_event_iterator_->point0(),
- site_events_.begin()->point0()) &&
- VP::is_vertical(*site_event_iterator_)) {
- ++site_event_iterator_;
- ++skip;
- }
- if (skip == 1) {
-
- init_beach_line_default(output);
- } else {
-
- init_beach_line_collinear_sites(output);
- }
- }
- }
-
-
- template <typename OUTPUT>
- void init_beach_line_default(OUTPUT* output) {
-
- site_event_iterator_type it_first = site_events_.begin();
- site_event_iterator_type it_second = site_events_.begin();
- ++it_second;
- insert_new_arc(
- *it_first, *it_first, *it_second, beach_line_.end(), output);
-
- ++site_event_iterator_;
- }
-
- template <typename OUTPUT>
- void init_beach_line_collinear_sites(OUTPUT* output) {
- site_event_iterator_type it_first = site_events_.begin();
- site_event_iterator_type it_second = site_events_.begin();
- ++it_second;
- while (it_second != site_event_iterator_) {
-
- key_type new_node(*it_first, *it_second);
-
- edge_type* edge = output->_insert_new_edge(*it_first, *it_second).first;
-
- beach_line_.insert(beach_line_.end(),
- std::pair<key_type, value_type>(new_node, value_type(edge)));
-
- ++it_first;
- ++it_second;
- }
- }
- void deactivate_circle_event(value_type* value) {
- if (value->circle_event()) {
- value->circle_event()->deactivate();
- value->circle_event(NULL);
- }
- }
- template <typename OUTPUT>
- void process_site_event(OUTPUT* output) {
-
- site_event_type site_event = *site_event_iterator_;
-
- site_event_iterator_type last = site_event_iterator_ + 1;
-
-
- if (!site_event.is_segment()) {
- while (!end_points_.empty() &&
- end_points_.top().first == site_event.point0()) {
- beach_line_iterator b_it = end_points_.top().second;
- end_points_.pop();
- beach_line_.erase(b_it);
- }
- } else {
- while (last != site_events_.end() &&
- last->is_segment() && last->point0() == site_event.point0())
- ++last;
- }
-
-
- key_type new_key(*site_event_iterator_);
- beach_line_iterator right_it = beach_line_.lower_bound(new_key);
- for (; site_event_iterator_ != last; ++site_event_iterator_) {
- site_event = *site_event_iterator_;
- beach_line_iterator left_it = right_it;
-
-
-
- if (right_it == beach_line_.end()) {
-
-
- --left_it;
-
- const site_event_type& site_arc = left_it->first.right_site();
-
- right_it = insert_new_arc(
- site_arc, site_arc, site_event, right_it, output);
-
-
-
- activate_circle_event(left_it->first.left_site(),
- left_it->first.right_site(),
- site_event, right_it);
- } else if (right_it == beach_line_.begin()) {
-
- const site_event_type& site_arc = right_it->first.left_site();
-
- left_it = insert_new_arc(
- site_arc, site_arc, site_event, right_it, output);
-
- if (site_event.is_segment()) {
- site_event.inverse();
- }
-
-
-
- activate_circle_event(site_event, right_it->first.left_site(),
- right_it->first.right_site(), right_it);
- right_it = left_it;
- } else {
-
-
- const site_event_type& site_arc2 = right_it->first.left_site();
- const site_event_type& site3 = right_it->first.right_site();
-
- deactivate_circle_event(&right_it->second);
- --left_it;
- const site_event_type& site_arc1 = left_it->first.right_site();
- const site_event_type& site1 = left_it->first.left_site();
-
- beach_line_iterator new_node_it =
- insert_new_arc(site_arc1, site_arc2, site_event, right_it, output);
-
-
-
- activate_circle_event(site1, site_arc1, site_event, new_node_it);
-
- if (site_event.is_segment()) {
- site_event.inverse();
- }
- activate_circle_event(site_event, site_arc2, site3, right_it);
- right_it = new_node_it;
- }
- }
- }
-
-
-
-
-
-
-
-
-
- template <typename OUTPUT>
- void process_circle_event(OUTPUT* output) {
-
- const event_type& e = circle_events_.top();
- const circle_event_type& circle_event = e.first;
- beach_line_iterator it_first = e.second;
- beach_line_iterator it_last = it_first;
-
- site_event_type site3 = it_first->first.right_site();
-
- edge_type* bisector2 = it_first->second.edge();
-
- --it_first;
- edge_type* bisector1 = it_first->second.edge();
-
- site_event_type site1 = it_first->first.left_site();
- if (!site1.is_segment() && site3.is_segment() &&
- site3.point1() == site1.point0()) {
- site3.inverse();
- }
-
- const_cast<key_type&>(it_first->first).right_site(site3);
-
- it_first->second.edge(output->_insert_new_edge(
- site1, site3, circle_event, bisector1, bisector2).first);
-
- beach_line_.erase(it_last);
- it_last = it_first;
-
- circle_events_.pop();
-
-
- if (it_first != beach_line_.begin()) {
- deactivate_circle_event(&it_first->second);
- --it_first;
- const site_event_type& site_l1 = it_first->first.left_site();
- activate_circle_event(site_l1, site1, site3, it_last);
- }
-
-
- ++it_last;
- if (it_last != beach_line_.end()) {
- deactivate_circle_event(&it_last->second);
- const site_event_type& site_r1 = it_last->first.right_site();
- activate_circle_event(site1, site3, site_r1, it_last);
- }
- }
-
- template <typename OUTPUT>
- beach_line_iterator insert_new_arc(
- const site_event_type& site_arc1, const site_event_type &site_arc2,
- const site_event_type& site_event, beach_line_iterator position,
- OUTPUT* output) {
-
- key_type new_left_node(site_arc1, site_event);
- key_type new_right_node(site_event, site_arc2);
-
- if (site_event.is_segment()) {
- new_right_node.left_site().inverse();
- }
-
- std::pair<edge_type*, edge_type*> edges =
- output->_insert_new_edge(site_arc2, site_event);
- position = beach_line_.insert(position,
- typename beach_line_type::value_type(
- new_right_node, value_type(edges.second)));
- if (site_event.is_segment()) {
-
-
-
- key_type new_node(site_event, site_event);
- new_node.right_site().inverse();
- position = beach_line_.insert(position,
- typename beach_line_type::value_type(new_node, value_type(NULL)));
-
- end_points_.push(std::make_pair(site_event.point1(), position));
- }
- position = beach_line_.insert(position,
- typename beach_line_type::value_type(
- new_left_node, value_type(edges.first)));
- return position;
- }
-
-
- void activate_circle_event(const site_event_type& site1,
- const site_event_type& site2,
- const site_event_type& site3,
- beach_line_iterator bisector_node) {
- circle_event_type c_event;
-
- if (circle_formation_predicate_(site1, site2, site3, c_event)) {
-
-
-
- event_type& e = circle_events_.push(
- std::pair<circle_event_type, beach_line_iterator>(
- c_event, bisector_node));
- bisector_node->second.circle_event(&e.first);
- }
- }
- private:
- point_comparison_predicate point_comparison_;
- struct end_point_comparison {
- bool operator() (const end_point_type& end1,
- const end_point_type& end2) const {
- return point_comparison(end2.first, end1.first);
- }
- point_comparison_predicate point_comparison;
- };
- std::vector<site_event_type> site_events_;
- site_event_iterator_type site_event_iterator_;
- std::priority_queue< end_point_type, std::vector<end_point_type>,
- end_point_comparison > end_points_;
- circle_event_queue_type circle_events_;
- beach_line_type beach_line_;
- circle_formation_predicate_type circle_formation_predicate_;
- std::size_t index_;
-
- voronoi_builder(const voronoi_builder&);
- void operator=(const voronoi_builder&);
- };
- typedef voronoi_builder<detail::int32> default_voronoi_builder;
- }
- }
- #endif
|