annotate DEPENDENCIES/generic/include/boost/graph/is_straight_line_drawing.hpp @ 118:770eb830ec19 emscripten

Typo fix
author Chris Cannam
date Wed, 18 May 2016 16:14:08 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 //=======================================================================
Chris@16 2 // Copyright 2007 Aaron Windsor
Chris@16 3 //
Chris@16 4 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 5 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 7 //=======================================================================
Chris@16 8 #ifndef __IS_STRAIGHT_LINE_DRAWING_HPP__
Chris@16 9 #define __IS_STRAIGHT_LINE_DRAWING_HPP__
Chris@16 10
Chris@16 11 #include <boost/config.hpp>
Chris@16 12 #include <boost/next_prior.hpp>
Chris@16 13 #include <boost/tuple/tuple.hpp>
Chris@16 14 #include <boost/tuple/tuple_comparison.hpp>
Chris@16 15 #include <boost/property_map/property_map.hpp>
Chris@16 16 #include <boost/graph/properties.hpp>
Chris@16 17 #include <boost/graph/planar_detail/bucket_sort.hpp>
Chris@16 18
Chris@16 19 #include <algorithm>
Chris@16 20 #include <vector>
Chris@16 21 #include <set>
Chris@16 22 #include <map>
Chris@16 23
Chris@16 24
Chris@16 25
Chris@16 26 namespace boost
Chris@16 27 {
Chris@16 28
Chris@16 29 // Return true exactly when the line segments s1 = ((x1,y1), (x2,y2)) and
Chris@16 30 // s2 = ((a1,b1), (a2,b2)) intersect in a point other than the endpoints of
Chris@16 31 // the line segments. The one exception to this rule is when s1 = s2, in
Chris@16 32 // which case false is returned - this is to accomodate multiple edges
Chris@16 33 // between the same pair of vertices, which shouldn't invalidate the straight
Chris@16 34 // line embedding. A tolerance variable epsilon can also be used, which
Chris@16 35 // defines how far away from the endpoints of s1 and s2 we want to consider
Chris@16 36 // an intersection.
Chris@16 37
Chris@16 38 inline bool intersects(double x1, double y1,
Chris@16 39 double x2, double y2,
Chris@16 40 double a1, double b1,
Chris@16 41 double a2, double b2,
Chris@16 42 double epsilon = 0.000001
Chris@16 43 )
Chris@16 44 {
Chris@16 45
Chris@16 46 if (x1 - x2 == 0)
Chris@16 47 {
Chris@16 48 std::swap(x1,a1);
Chris@16 49 std::swap(y1,b1);
Chris@16 50 std::swap(x2,a2);
Chris@16 51 std::swap(y2,b2);
Chris@16 52 }
Chris@16 53
Chris@16 54 if (x1 - x2 == 0)
Chris@16 55 {
Chris@16 56 BOOST_USING_STD_MAX();
Chris@16 57 BOOST_USING_STD_MIN();
Chris@16 58
Chris@16 59 //two vertical line segments
Chris@16 60 double min_y = min BOOST_PREVENT_MACRO_SUBSTITUTION(y1,y2);
Chris@16 61 double max_y = max BOOST_PREVENT_MACRO_SUBSTITUTION(y1,y2);
Chris@16 62 double min_b = min BOOST_PREVENT_MACRO_SUBSTITUTION(b1,b2);
Chris@16 63 double max_b = max BOOST_PREVENT_MACRO_SUBSTITUTION(b1,b2);
Chris@16 64 if ((max_y > max_b && max_b > min_y) ||
Chris@16 65 (max_b > max_y && max_y > min_b)
Chris@16 66 )
Chris@16 67 return true;
Chris@16 68 else
Chris@16 69 return false;
Chris@16 70 }
Chris@16 71
Chris@16 72 double x_diff = x1 - x2;
Chris@16 73 double y_diff = y1 - y2;
Chris@16 74 double a_diff = a2 - a1;
Chris@16 75 double b_diff = b2 - b1;
Chris@16 76
Chris@16 77 double beta_denominator = b_diff - (y_diff/((double)x_diff)) * a_diff;
Chris@16 78
Chris@16 79 if (beta_denominator == 0)
Chris@16 80 {
Chris@16 81 //parallel lines
Chris@16 82 return false;
Chris@16 83 }
Chris@16 84
Chris@16 85 double beta = (b2 - y2 - (y_diff/((double)x_diff)) * (a2 - x2)) /
Chris@16 86 beta_denominator;
Chris@16 87 double alpha = (a2 - x2 - beta*(a_diff))/x_diff;
Chris@16 88
Chris@16 89 double upper_bound = 1 - epsilon;
Chris@16 90 double lower_bound = 0 + epsilon;
Chris@16 91
Chris@16 92 return (beta < upper_bound && beta > lower_bound &&
Chris@16 93 alpha < upper_bound && alpha > lower_bound);
Chris@16 94
Chris@16 95 }
Chris@16 96
Chris@16 97
Chris@16 98 template <typename Graph,
Chris@16 99 typename GridPositionMap,
Chris@16 100 typename VertexIndexMap
Chris@16 101 >
Chris@16 102 bool is_straight_line_drawing(const Graph& g,
Chris@16 103 GridPositionMap drawing,
Chris@16 104 VertexIndexMap
Chris@16 105 )
Chris@16 106 {
Chris@16 107
Chris@16 108 typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
Chris@16 109 typedef typename graph_traits<Graph>::edge_descriptor edge_t;
Chris@16 110 typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
Chris@16 111
Chris@16 112 typedef std::size_t x_coord_t;
Chris@16 113 typedef std::size_t y_coord_t;
Chris@16 114 typedef boost::tuple<edge_t, x_coord_t, y_coord_t> edge_event_t;
Chris@16 115 typedef typename std::vector< edge_event_t > edge_event_queue_t;
Chris@16 116
Chris@16 117 typedef tuple<y_coord_t, y_coord_t, x_coord_t, x_coord_t> active_map_key_t;
Chris@16 118 typedef edge_t active_map_value_t;
Chris@16 119 typedef std::map< active_map_key_t, active_map_value_t > active_map_t;
Chris@16 120 typedef typename active_map_t::iterator active_map_iterator_t;
Chris@16 121
Chris@16 122
Chris@16 123 edge_event_queue_t edge_event_queue;
Chris@16 124 active_map_t active_edges;
Chris@16 125
Chris@16 126 edge_iterator_t ei, ei_end;
Chris@16 127 for(boost::tie(ei,ei_end) = edges(g); ei != ei_end; ++ei)
Chris@16 128 {
Chris@16 129 edge_t e(*ei);
Chris@16 130 vertex_t s(source(e,g));
Chris@16 131 vertex_t t(target(e,g));
Chris@16 132 edge_event_queue.push_back
Chris@16 133 (make_tuple(e,
Chris@16 134 static_cast<std::size_t>(drawing[s].x),
Chris@16 135 static_cast<std::size_t>(drawing[s].y)
Chris@16 136 )
Chris@16 137 );
Chris@16 138 edge_event_queue.push_back
Chris@16 139 (make_tuple(e,
Chris@16 140 static_cast<std::size_t>(drawing[t].x),
Chris@16 141 static_cast<std::size_t>(drawing[t].y)
Chris@16 142 )
Chris@16 143 );
Chris@16 144 }
Chris@16 145
Chris@16 146 // Order by edge_event_queue by first, then second coordinate
Chris@16 147 // (bucket_sort is a stable sort.)
Chris@16 148 bucket_sort(edge_event_queue.begin(), edge_event_queue.end(),
Chris@16 149 property_map_tuple_adaptor<edge_event_t, 2>()
Chris@16 150 );
Chris@16 151
Chris@16 152 bucket_sort(edge_event_queue.begin(), edge_event_queue.end(),
Chris@16 153 property_map_tuple_adaptor<edge_event_t, 1>()
Chris@16 154 );
Chris@16 155
Chris@16 156 typedef typename edge_event_queue_t::iterator event_queue_iterator_t;
Chris@16 157 event_queue_iterator_t itr_end = edge_event_queue.end();
Chris@16 158 for(event_queue_iterator_t itr = edge_event_queue.begin();
Chris@16 159 itr != itr_end; ++itr
Chris@16 160 )
Chris@16 161 {
Chris@16 162 edge_t e(get<0>(*itr));
Chris@16 163 vertex_t source_v(source(e,g));
Chris@16 164 vertex_t target_v(target(e,g));
Chris@16 165 if (drawing[source_v].y > drawing[target_v].y)
Chris@16 166 std::swap(source_v, target_v);
Chris@16 167
Chris@16 168 active_map_key_t key(get(drawing, source_v).y,
Chris@16 169 get(drawing, target_v).y,
Chris@16 170 get(drawing, source_v).x,
Chris@16 171 get(drawing, target_v).x
Chris@16 172 );
Chris@16 173
Chris@16 174 active_map_iterator_t a_itr = active_edges.find(key);
Chris@16 175 if (a_itr == active_edges.end())
Chris@16 176 {
Chris@16 177 active_edges[key] = e;
Chris@16 178 }
Chris@16 179 else
Chris@16 180 {
Chris@16 181 active_map_iterator_t before, after;
Chris@16 182 if (a_itr == active_edges.begin())
Chris@16 183 before = active_edges.end();
Chris@16 184 else
Chris@16 185 before = prior(a_itr);
Chris@16 186 after = boost::next(a_itr);
Chris@16 187
Chris@16 188 if (before != active_edges.end())
Chris@16 189 {
Chris@16 190
Chris@16 191 edge_t f = before->second;
Chris@16 192 vertex_t e_source(source(e,g));
Chris@16 193 vertex_t e_target(target(e,g));
Chris@16 194 vertex_t f_source(source(f,g));
Chris@16 195 vertex_t f_target(target(f,g));
Chris@16 196
Chris@16 197 if (intersects(drawing[e_source].x,
Chris@16 198 drawing[e_source].y,
Chris@16 199 drawing[e_target].x,
Chris@16 200 drawing[e_target].y,
Chris@16 201 drawing[f_source].x,
Chris@16 202 drawing[f_source].y,
Chris@16 203 drawing[f_target].x,
Chris@16 204 drawing[f_target].y
Chris@16 205 )
Chris@16 206 )
Chris@16 207 return false;
Chris@16 208 }
Chris@16 209
Chris@16 210 if (after != active_edges.end())
Chris@16 211 {
Chris@16 212
Chris@16 213 edge_t f = after->second;
Chris@16 214 vertex_t e_source(source(e,g));
Chris@16 215 vertex_t e_target(target(e,g));
Chris@16 216 vertex_t f_source(source(f,g));
Chris@16 217 vertex_t f_target(target(f,g));
Chris@16 218
Chris@16 219 if (intersects(drawing[e_source].x,
Chris@16 220 drawing[e_source].y,
Chris@16 221 drawing[e_target].x,
Chris@16 222 drawing[e_target].y,
Chris@16 223 drawing[f_source].x,
Chris@16 224 drawing[f_source].y,
Chris@16 225 drawing[f_target].x,
Chris@16 226 drawing[f_target].y
Chris@16 227 )
Chris@16 228 )
Chris@16 229 return false;
Chris@16 230 }
Chris@16 231
Chris@16 232 active_edges.erase(a_itr);
Chris@16 233
Chris@16 234 }
Chris@16 235 }
Chris@16 236
Chris@16 237 return true;
Chris@16 238
Chris@16 239 }
Chris@16 240
Chris@16 241
Chris@16 242 template <typename Graph, typename GridPositionMap>
Chris@16 243 bool is_straight_line_drawing(const Graph& g, GridPositionMap drawing)
Chris@16 244 {
Chris@16 245 return is_straight_line_drawing(g, drawing, get(vertex_index,g));
Chris@16 246 }
Chris@16 247
Chris@16 248 }
Chris@16 249
Chris@16 250 #endif // __IS_STRAIGHT_LINE_DRAWING_HPP__