1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
6 
7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
9 
10 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
13 
14 #ifndef BOOST_GEOMETRY_GEOMETRIES_SEGMENT_HPP
15 #define BOOST_GEOMETRY_GEOMETRIES_SEGMENT_HPP
16 
17 #include <cstddef>
18 
19 #include <boost/concept/assert.hpp>
20 #include <boost/mpl/if.hpp>
21 #include <boost/type_traits/is_const.hpp>
22 
23 #include <boost/geometry/geometries/concepts/point_concept.hpp>
24 
25 namespace boost { namespace geometry
26 {
27 
28 namespace model
29 {
30 
31 /*!
32 \brief Class segment: small class containing two points
33 \ingroup geometries
34 \details From Wikipedia: In geometry, a line segment is a part of a line that is bounded
35  by two distinct end points, and contains every point on the line between its end points.
36 \note There is also a point-referring-segment, class referring_segment,
37    containing point references, where points are NOT copied
38 
39 \qbk{[include reference/geometries/segment.qbk]}
40 \qbk{before.synopsis,
41 [heading Model of]
42 [link geometry.reference.concepts.concept_segment Segment Concept]
43 }
44 */
45 template<typename Point>
46 class segment : public std::pair<Point, Point>
47 {
48     BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
49 
50 public :
51 
52 #ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
53     /// \constructor_default_no_init
54     segment() = default;
55 #else
56     /// \constructor_default_no_init
57     inline segment()
58     {}
59 #endif
60 
61     /*!
62         \brief Constructor taking the first and the second point
63     */
segment(Point const & p1,Point const & p2)64     inline segment(Point const& p1, Point const& p2)
65     {
66         this->first = p1;
67         this->second = p2;
68     }
69 };
70 
71 
72 /*!
73 \brief Class segment: small class containing two (templatized) point references
74 \ingroup geometries
75 \details From Wikipedia: In geometry, a line segment is a part of a line that is bounded
76  by two distinct end points, and contains every point on the line between its end points.
77 \note The structure is like std::pair, and can often be used interchangeable.
78 Difference is that it refers to points, does not have points.
79 \note Like std::pair, points are public available.
80 \note type is const or non const, so geometry::segment<P> or geometry::segment<P const>
81 \note We cannot derive from std::pair<P&, P&> because of
82 reference assignments.
83 \tparam ConstOrNonConstPoint point type of the segment, maybe a point or a const point
84 */
85 template<typename ConstOrNonConstPoint>
86 class referring_segment
87 {
88     BOOST_CONCEPT_ASSERT( (
89         typename boost::mpl::if_
90             <
91                 boost::is_const<ConstOrNonConstPoint>,
92                 concepts::Point<ConstOrNonConstPoint>,
93                 concepts::ConstPoint<ConstOrNonConstPoint>
94             >
95     ) );
96 
97     typedef ConstOrNonConstPoint point_type;
98 
99 public:
100 
101     point_type& first;
102     point_type& second;
103 
104     /*!
105         \brief Constructor taking the first and the second point
106     */
referring_segment(point_type & p1,point_type & p2)107     inline referring_segment(point_type& p1, point_type& p2)
108         : first(p1)
109         , second(p2)
110     {}
111 };
112 
113 
114 } // namespace model
115 
116 
117 // Traits specializations for segment above
118 #ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
119 namespace traits
120 {
121 
122 template <typename Point>
123 struct tag<model::segment<Point> >
124 {
125     typedef segment_tag type;
126 };
127 
128 template <typename Point>
129 struct point_type<model::segment<Point> >
130 {
131     typedef Point type;
132 };
133 
134 template <typename Point, std::size_t Dimension>
135 struct indexed_access<model::segment<Point>, 0, Dimension>
136 {
137     typedef model::segment<Point> segment_type;
138     typedef typename geometry::coordinate_type<segment_type>::type coordinate_type;
139 
getboost::geometry::traits::indexed_access140     static inline coordinate_type get(segment_type const& s)
141     {
142         return geometry::get<Dimension>(s.first);
143     }
144 
setboost::geometry::traits::indexed_access145     static inline void set(segment_type& s, coordinate_type const& value)
146     {
147         geometry::set<Dimension>(s.first, value);
148     }
149 };
150 
151 
152 template <typename Point, std::size_t Dimension>
153 struct indexed_access<model::segment<Point>, 1, Dimension>
154 {
155     typedef model::segment<Point> segment_type;
156     typedef typename geometry::coordinate_type<segment_type>::type coordinate_type;
157 
getboost::geometry::traits::indexed_access158     static inline coordinate_type get(segment_type const& s)
159     {
160         return geometry::get<Dimension>(s.second);
161     }
162 
setboost::geometry::traits::indexed_access163     static inline void set(segment_type& s, coordinate_type const& value)
164     {
165         geometry::set<Dimension>(s.second, value);
166     }
167 };
168 
169 
170 template <typename ConstOrNonConstPoint>
171 struct tag<model::referring_segment<ConstOrNonConstPoint> >
172 {
173     typedef segment_tag type;
174 };
175 
176 template <typename ConstOrNonConstPoint>
177 struct point_type<model::referring_segment<ConstOrNonConstPoint> >
178 {
179     typedef ConstOrNonConstPoint type;
180 };
181 
182 template <typename ConstOrNonConstPoint, std::size_t Dimension>
183 struct indexed_access<model::referring_segment<ConstOrNonConstPoint>, 0, Dimension>
184 {
185     typedef model::referring_segment<ConstOrNonConstPoint> segment_type;
186     typedef typename geometry::coordinate_type<segment_type>::type coordinate_type;
187 
getboost::geometry::traits::indexed_access188     static inline coordinate_type get(segment_type const& s)
189     {
190         return geometry::get<Dimension>(s.first);
191     }
192 
setboost::geometry::traits::indexed_access193     static inline void set(segment_type& s, coordinate_type const& value)
194     {
195         geometry::set<Dimension>(s.first, value);
196     }
197 };
198 
199 
200 template <typename ConstOrNonConstPoint, std::size_t Dimension>
201 struct indexed_access<model::referring_segment<ConstOrNonConstPoint>, 1, Dimension>
202 {
203     typedef model::referring_segment<ConstOrNonConstPoint> segment_type;
204     typedef typename geometry::coordinate_type<segment_type>::type coordinate_type;
205 
getboost::geometry::traits::indexed_access206     static inline coordinate_type get(segment_type const& s)
207     {
208         return geometry::get<Dimension>(s.second);
209     }
210 
setboost::geometry::traits::indexed_access211     static inline void set(segment_type& s, coordinate_type const& value)
212     {
213         geometry::set<Dimension>(s.second, value);
214     }
215 };
216 
217 
218 
219 } // namespace traits
220 #endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
221 
222 }} // namespace boost::geometry
223 
224 #endif // BOOST_GEOMETRY_GEOMETRIES_SEGMENT_HPP
225