33 #ifdef OGDF_INCLUDE_CGAL
48 # include <CGAL/Polygon_2.h>
55 using namespace tools;
57 template<
typename kernel>
58 class Polygon_t :
public CGAL::Polygon_2<kernel> {
60 using poly = CGAL::Polygon_2<kernel>;
65 Polygon_t(
const poly& p) : poly(p) { }
67 Polygon_t(
const poly&& p) : poly(
std::
move(p)) { }
71 Polygon_t(
const Polygon_t<kernel>& p) : poly(p) { }
73 inline typename poly::Edge_const_iterator
begin()
const {
return poly::edges_begin(); }
75 inline typename poly::Edge_const_iterator
end()
const {
return poly::edges_end(); };
77 void push_back(
const Point_t<kernel>& x) {
78 if (poly::is_empty() || (poly::container().back() != x)) {
83 Polygon_t<kernel> operator=(
const Polygon_t<kernel>& p) {
89 template<
typename kernel,
typename Graph>
90 inline Polygon_t<kernel> get_polygon(
const graph::GeometricDrawing<kernel, Graph>& drawing,
91 const graph::Path& path) {
92 Polygon_t<kernel> polygon;
93 for (
auto& v : path.nodes()) {
94 polygon.push_back(drawing.get_point(v));
99 template<
typename kernel,
typename Graph>
100 inline Polygon_t<kernel> get_polygon(
const graph::PolylineDrawing<kernel, Graph>& drawing,
101 const graph::Path& path) {
102 Polygon_t<kernel> polygon;
104 for (
unsigned int i = 0; i < path.edges().
size(); ++i) {
105 auto e = path.edges()[i];
107 if (!path.is_reversed(i)) {
108 for (
auto& p : drawing.get_polyline(e)) {
109 polygon.push_back(p);
112 auto& p = drawing.get_polyline(e);
113 for (
auto itr = p.rbegin(); itr != p.rend(); ++itr) {
114 polygon.push_back(*itr);
121 template<
typename kernel>
122 inline Polygon_t<kernel> get_polygon(
const Rectangle_t<kernel>& rect) {
124 for (
unsigned int i = 0; i < 4; ++i) {
125 p.push_back(rect[i]);
130 template<
typename kernel>
131 inline Polygon_t<kernel> get_polygon(
const CGAL::Bbox_2& bb) {
132 return get_polygon(Rectangle_t<kernel>(bb));
136 template<
typename kernel>
137 LineSegment_t<kernel> clip(
const Rectangle_t<kernel>& rect,
const Line_t<kernel>& line) {
139 std::vector<Point_t<kernel>> is;
140 Polygon_t<kernel> p = get_polygon(rect);
142 if (geometry::do_intersect_wo_target(line, s)) {
143 is.push_back(geometry::intersect(line, s));
147 return LineSegment_t<kernel>(is[0], is[1]);
150 template<
typename kernel,
typename Graph>
151 inline std::vector<typename Graph::Node> graph_from_polygon(
const Polygon_t<kernel>& polygon,
152 graph::GeometricDrawing<kernel, Graph>& drawing) {
153 std::vector<typename Graph::Node> node_map;
154 for (
unsigned int i = 0; i < polygon.size(); ++i) {
155 typename Graph::Node u = drawing.get_graph().add_node();
156 drawing.set_point(u, polygon[i]);
157 node_map.push_back(u);
160 for (
unsigned int i = 0; i < polygon.size(); ++i) {
161 drawing.get_graph().add_edge(node_map[i], node_map[(i + 1) % polygon.size()]);
167 template<
typename kernel>
168 inline unsigned int next(
const Polygon_t<kernel>& p,
unsigned int i) {
169 return (i + 1) % p.size();
172 template<
typename kernel>
173 inline unsigned int prev(
const Polygon_t<kernel>& p,
unsigned int i) {
174 return std::min((
size_t)i - 1, p.size() - 1);
177 template<
typename kernel>
178 inline Polygon_t<kernel>
reverse(
const Polygon_t<kernel>& polygon) {
179 Polygon_t<kernel> revPolygon(polygon.container().rbegin(), polygon.container().rend());
183 template<
typename kernel>
184 inline bool contains(
const Polygon_t<kernel>& polygon,
const geometry::Point_t<kernel>& p) {
186 if (polygon.size() == 0) {
189 if (polygon.size() == 1) {
190 return polygon[0] == p;
192 if (CGAL::is_zero(CGAL::abs(polygon.area()))) {
194 for (
const auto& s : polygon) {
202 unsigned int segment = -1;
203 geometry::LineSegment_t<kernel> l;
206 l = {p, polygon[segment] + polygon.edge(segment).to_vector() * 0.5};
207 }
while (overlapping(l, polygon.edge(segment)));
211 geometry::Ray_t<kernel>
r(p, l.to_vector());
212 unsigned int nof_intersections = 0;
213 bool is_on_border =
false;
215 for (
unsigned int i = 0; i < polygon.size(); ++i) {
216 auto s = polygon.edge(i);
218 if (geometry::do_intersect_wo_target(s,
r)) {
219 auto is = geometry::intersect(s,
r);
220 if (is == s.source()) {
221 auto prev_seg = polygon.edge(prev(polygon, i));
222 if (!geometry::right_turn(prev_seg, s)) {
229 is_on_border = is_on_border || is_on(s, p);
231 return nof_intersections % 2 == 1 || is_on_border;
235 template<
typename Kernel>
236 typename Kernel::FT squared_distance(
const Polygon_t<Kernel>& polygon,
const Point_t<Kernel>& point) {
237 typename Kernel::FT min_dist = CGAL::squared_distance(*polygon.begin(), point);
238 for (
const auto& e : polygon) {
239 typename Kernel::FT sq = CGAL::squared_distance(e, point);
244 if (min_dist > 1e-12 && !contains(polygon, point)) {
245 min_dist = -min_dist;
252 template<
typename Kernel>
253 Point_t<Kernel> centroid(
const Polygon_t<Kernel>& polygon) {
254 Point_t<Kernel> p(0, 0);
255 for (
const Point_t<Kernel>& q : polygon.container()) {
258 p = p * (1.0 / polygon.size());
262 template<
typename kernel>
263 inline Point_t<kernel> intersect(
const Polygon_t<kernel>& polygon,
const Ray_t<kernel>& ray,
272 template<
typename kernel>
273 inline Point_t<kernel> intersect(
const Polygon_t<kernel>& polygon,
const Ray_t<kernel>& ray) {
276 for (
auto s : polygon) {
277 if (geometry::do_intersect_wo_target(s, ray)) {
278 return geometry::intersect(s, ray);
284 template<
typename kernel>
285 inline bool is_clockwise(
const Polygon_t<kernel>& polygon) {
286 return polygon.area() < 0;
289 template<
typename kernel>
290 std::vector<unsigned int> find_duplicates(
const Polygon_t<kernel>& polygon) {
291 std::vector<unsigned int> segment_ids(polygon.size(), 0);
292 for (
unsigned int i = 0; i < polygon.size(); ++i) {
295 std::sort(segment_ids.begin(), segment_ids.end(), [&](
unsigned int i,
unsigned int j) {
296 return (polygon.edge(i).min() < polygon.edge(j).min())
297 || (polygon.edge(i).min() == polygon.edge(j).min()
298 && polygon.edge(i).max() < polygon.edge(j).max());
301 std::vector<unsigned int> is_duplicate(polygon.size(), -1);
302 for (
unsigned int i = 0; i + 1 < polygon.size(); ++i) {
303 unsigned int a = segment_ids[i];
304 unsigned int b = segment_ids[i + 1];
305 if (polygon.edge(a).min() == polygon.edge(b).min()
306 && polygon.edge(a).max() == polygon.edge(b).max()) {
314 template<
typename kernel>
315 std::string ggb(
const Polygon_t<kernel>& polygon) {
316 std::stringstream os;
318 for (
unsigned int i = 0; i < polygon.size(); ++i) {
320 if (i + 1 < polygon.size()) {
328 template<
typename kernel>
329 std::ostream&
operator<<(std::ostream& os,
const Polygon_t<kernel>& p) {