-
Notifications
You must be signed in to change notification settings - Fork 0
/
semicircle.hpp
110 lines (87 loc) · 2.75 KB
/
semicircle.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#ifndef GEOMETRY_HEMISPHERE_HPP
#define GEOMETRY_HEMISPHERE_HPP
#include <boost/geometry/geometries/box.hpp>
namespace boost { namespace geometry {
namespace model {
template <typename Point>
struct semicircle;
}
template <typename Point, typename HemispherePoint>
inline bool intersects(Point const& p, model::semicircle<HemispherePoint> const& hs)
{
return hs.intersects_point(p);
}
template <typename Point, typename HemispherePoint>
inline bool intersects(model::box<Point> const& b, model::semicircle<HemispherePoint> const& hs)
{
return hs.intersects_box(b);
}
}}
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/segment.hpp>
namespace boost { namespace geometry {
namespace model {
template <typename Point>
struct semicircle
{
enum side_t {left, right};
template <typename Segment>
semicircle(Segment const &s, side_t side)
: s(s.first, s.second), side(side == right ? 1 : -1) {}
template <typename OtherPoint>
bool intersects_point(OtherPoint const &p) const
{
return strategy::side::side_by_triangle<>::apply(s.first, s.second, p) == side
&& geometry::distance(return_centroid<Point>(s), p) <= geometry::length(s) / 2;
}
template <typename OtherSegment>
bool intersects_segment(OtherSegment const &os) const
{
return (strategy::side::side_by_triangle<>::apply(s.first, s.second, os.first) == side
|| strategy::side::side_by_triangle<>::apply(s.first, s.second, os.second) == side)
&& geometry::distance(return_centroid<Point>(s), os) <= geometry::length(s) / 2;
}
template <typename Box>
bool intersects_box(Box const &b) const
{
if (geometry::intersects(s, b))
return true;
typedef typename point_type<Box>::type BoxPoint;
typedef segment<BoxPoint> BoxSegment;
BoxSegment bs(b.min_corner(),
BoxPoint(get<min_corner, 0>(b), get<max_corner, 1>(b)));
if (intersects_segment(bs))
return true;
bs.first = b.max_corner();
if (intersects_segment(bs))
return true;
set<0>(bs.second, get<max_corner, 0>(b));
set<1>(bs.second, get<min_corner, 1>(b));
if (intersects_segment(bs))
return true;
bs.first = b.min_corner();
if (intersects_segment(bs))
return true;
return false;
}
private:
model::segment<Point> s;
short side;
};
}
struct semicircle_tag : single_tag, areal_tag {};
namespace traits
{
template <typename Point>
struct tag<model::semicircle<Point> >
{
typedef semicircle_tag type;
};
template <typename Point>
struct point_type<model::semicircle<Point> >
{
typedef Point type;
};
}
}}
#endif