1 /**
2  *   SFCGAL
3  *
4  *   Copyright (C) 2012-2013 Oslandia <infos@oslandia.com>
5  *   Copyright (C) 2012-2013 IGN (http://www.ign.fr)
6  *
7  *   This library is free software; you can redistribute it and/or
8  *   modify it under the terms of the GNU Library General Public
9  *   License as published by the Free Software Foundation; either
10  *   version 2 of the License, or (at your option) any later version.
11  *
12  *   This library is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *   Library General Public License for more details.
16 
17  *   You should have received a copy of the GNU Library General Public
18  *   License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #ifndef _SFCGAL_POLYGON_H_
22 #define _SFCGAL_POLYGON_H_
23 
24 #include <vector>
25 #include <boost/assert.hpp>
26 #include <boost/ptr_container/ptr_vector.hpp>
27 #include <boost/serialization/base_object.hpp>
28 #include <boost/ptr_container/serialize_ptr_vector.hpp>
29 
30 #include <CGAL/Polygon_with_holes_2.h>
31 
32 #include <SFCGAL/LineString.h>
33 #include <SFCGAL/Surface.h>
34 #include <SFCGAL/Kernel.h>
35 
36 namespace SFCGAL {
37 
38 /**
39  * A Polygon in SFA with holes
40  * @ingroup public_api
41  */
42 class SFCGAL_API Polygon : public Surface {
43 public:
44     typedef boost::ptr_vector< LineString >::iterator       iterator ;
45     typedef boost::ptr_vector< LineString >::const_iterator const_iterator ;
46 
47     /**
48      * Empty Polygon constructor
49      */
50     Polygon() ;
51     /**
52      * Constructor with an exterior ring
53      */
54     Polygon( const std::vector< LineString >& rings ) ;
55     /**
56      * Constructor with an exterior ring
57      */
58     Polygon( const LineString& exteriorRing ) ;
59     /**
60      * Constructor with an exterior ring (takes ownership)
61      */
62     Polygon( LineString* exteriorRing ) ;
63     /**
64      * Constructor with a Triangle
65      */
66     Polygon( const Triangle& triangle ) ;
67     /**
68      * Copy constructor
69      */
70     Polygon( const Polygon& other ) ;
71 
72     /**
73      * Constructor from CGAL::Polygon_with_holes_2<K>
74      */
75     Polygon( const CGAL::Polygon_2< Kernel >& other );
76     /**
77      * Constructor from CGAL::Polygon_with_holes_2<K>
78      */
79     Polygon( const CGAL::Polygon_with_holes_2< Kernel >& other );
80 
81     /**
82      * assign operator
83      */
84     Polygon& operator = ( Polygon other ) ;
85 
86     /**
87      * destructor
88      */
89     ~Polygon() ;
90 
91     //-- SFCGAL::Geometry
92     virtual Polygon*    clone() const ;
93 
94     //-- SFCGAL::Geometry
95     virtual std::string    geometryType() const ;
96     //-- SFCGAL::Geometry
97     virtual GeometryType   geometryTypeId() const ;
98     //-- SFCGAL::Geometry
99     virtual int            coordinateDimension() const ;
100     //-- SFCGAL::Geometry
101     virtual bool           isEmpty() const ;
102     //-- SFCGAL::Geometry
103     virtual bool           is3D() const ;
104     //-- SFCGAL::Geometry
105     virtual bool           isMeasured() const ;
106 
107     /**
108      * Check whether the 2D polygon is pointing up
109      */
110     bool isCounterClockWiseOriented() const;
111 
112     /**
113      * reverse Polygon orientation
114      */
115     void reverse() ;
116 
117 
118     /**
119      * [OGC/SFA]returns the exterior ring
120      */
exteriorRing()121     inline const LineString&     exteriorRing() const {
122         return _rings.front();
123     }
124     /**
125      * [OGC/SFA]returns the exterior ring
126      */
exteriorRing()127     inline LineString&           exteriorRing() {
128         return _rings.front();
129     }
130     /**
131      * Sets the exterior ring
132      */
setExteriorRing(const LineString & ring)133     inline void  setExteriorRing( const LineString& ring ) {
134         _rings.front() = ring ;
135     }
136     /**
137      * Sets the exterior ring (takes ownership)
138      */
setExteriorRing(LineString * ring)139     inline void  setExteriorRing( LineString* ring ) {
140         _rings.replace( 0, ring );
141     }
142 
143     /**
144      * Test if the polygon has interior rings
145      */
hasInteriorRings()146     inline bool                  hasInteriorRings() const {
147         return _rings.size() > 1 ;
148     }
149 
150     /**
151      * [OGC/SFA]returns the exterior ring
152      */
numInteriorRings()153     inline size_t                numInteriorRings() const {
154         return _rings.size() - 1 ;
155     }
156     /**
157      * [OGC/SFA]returns the exterior ring
158      */
interiorRingN(const size_t & n)159     inline const LineString&     interiorRingN( const size_t& n ) const {
160         return _rings[n+1];
161     }
162     /**
163      * [OGC/SFA]returns the exterior ring
164      */
interiorRingN(const size_t & n)165     inline LineString&           interiorRingN( const size_t& n ) {
166         return _rings[n+1];
167     }
168 
169     /**
170      * Returns the number of rings
171      */
numRings()172     inline size_t  numRings() const {
173         return _rings.size() ;
174     }
175     /**
176      * Returns the n-th ring, 0 is exteriorRing
177      * @warning not standard, avoid conditionnal to access rings
178      */
ringN(const size_t & n)179     inline const LineString&     ringN( const size_t& n ) const {
180         BOOST_ASSERT( n < _rings.size() );
181         return _rings[n];
182     }
183     /**
184      * Returns the n-th ring, 0 is exteriorRing
185      * @warning not standard, avoid conditionnal to access rings
186      */
ringN(const size_t & n)187     inline LineString&           ringN( const size_t& n ) {
188         BOOST_ASSERT( n < _rings.size() );
189         return _rings[n];
190     }
191 
192     /**
193      * append a ring to the Polygon
194      */
addInteriorRing(const LineString & ls)195     inline void            addInteriorRing( const LineString& ls ) {
196         _rings.push_back( ls.clone() ) ;
197     }
198     /**
199      * append a ring to the Polygon (take ownership)
200      */
addInteriorRing(LineString * ls)201     inline void            addInteriorRing( LineString* ls ) {
202         BOOST_ASSERT( ls != NULL );
203         _rings.push_back( ls ) ;
204     }
205 
206     /**
207      * append a ring to the Polygon
208      * @deprecated addInteriorRing
209      */
addRing(const LineString & ls)210     inline void            addRing( const LineString& ls ) {
211         _rings.push_back( ls.clone() ) ;
212     }
213     /**
214      * append a ring to the Polygon (take ownership)
215      * @deprecated addInteriorRing
216      */
addRing(LineString * ls)217     inline void            addRing( LineString* ls ) {
218         BOOST_ASSERT( ls != NULL );
219         _rings.push_back( ls ) ;
220     }
221 
begin()222     inline iterator       begin() {
223         return _rings.begin() ;
224     }
begin()225     inline const_iterator begin() const {
226         return _rings.begin() ;
227     }
228 
end()229     inline iterator       end() {
230         return _rings.end() ;
231     }
end()232     inline const_iterator end() const {
233         return _rings.end() ;
234     }
235 
236 
237     /*
238      * @brief Convert to CGAL::Polygon_2. Does not consider holes, if any
239      * @param forceCounterClocksize force exterior ring orientation to counter clocksize
240      */
241     CGAL::Polygon_2<Kernel> toPolygon_2( bool fixOrientation = true ) const;
242 
243     /*
244      * @brief Convert to CGAL::Polygon_with_holes_2.
245      * @param forceCounterClocksize force exterior ring orientation to counter clocksize and
246      *           interior ring to clocksize.
247      */
248     CGAL::Polygon_with_holes_2<Kernel> toPolygon_with_holes_2( bool fixOrientation = true ) const;
249 
250     //-- visitors
251 
252     //-- SFCGAL::Geometry
253     virtual void accept( GeometryVisitor& visitor ) ;
254     //-- SFCGAL::Geometry
255     virtual void accept( ConstGeometryVisitor& visitor ) const ;
256 
257     /**
258      * Serializer
259      */
260     template <class Archive>
serialize(Archive & ar,const unsigned int)261     void serialize( Archive& ar, const unsigned int /*version*/ ) {
262         ar& boost::serialization::base_object<Geometry>( *this );
263         ar& _rings;
264     }
265 private:
266     /**
267      * rings forming the polygon (size() >= 1)
268      *
269      * _ring[0] is the interior ring
270      *
271      * @warning never empty, empty LineString as exteriorRing for empty Polygon
272      */
273     boost::ptr_vector< LineString > _rings ;
274 
swap(Polygon & other)275     void swap( Polygon& other ) {
276         std::swap( _rings, other._rings );
277     }
278 };
279 
280 
281 }
282 
283 #endif
284