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_COORDINATE_H_
22 #define _SFCGAL_COORDINATE_H_
23 
24 #include <SFCGAL/config.h>
25 
26 #include <boost/assert.hpp>
27 #include <boost/array.hpp>
28 #include <boost/variant.hpp>
29 #include <boost/serialization/split_member.hpp>
30 
31 #include <SFCGAL/numeric.h>
32 
33 #include <SFCGAL/Kernel.h>
34 
35 namespace SFCGAL {
36 
37 /**
38  * @brief Represents the Coordinate of a Point (wraps either an empty structure, or a Kernel::Point_2,
39  * or a Kernel::Point_3)
40  */
41 class SFCGAL_API Coordinate {
42 public:
43     /**
44      * Empty Coordinate constructor
45      */
46     Coordinate() ;
47     /**
48      * XY Constructor with exact coordinates
49      */
50     Coordinate( const Kernel::FT& x, const Kernel::FT& y ) ;
51     /**
52      * XYZ Constructor with exact coordinates
53      */
54     Coordinate( const Kernel::FT& x, const Kernel::FT& y, const Kernel::FT& z ) ;
55     /**
56      * XYZ constructor
57      * @warning x,y,z must not be not be NaN nor inf
58      */
59     Coordinate( const double& x, const double& y, const double& z ) ;
60 
61     /**
62      * XY constructor
63      * @warning x,y must not be not be NaN nor inf
64      */
65     Coordinate( const double& x, const double& y ) ;
66     /**
67      * Constructor from CGAL::Point_2<K>
68      */
69     Coordinate( const Kernel::Point_2& other ) ;
70     /**
71      * Constructor from CGAL::Point_3<K>
72      */
73     Coordinate( const Kernel::Point_3& other ) ;
74 
75     /**
76      * copy constructor
77      */
78     Coordinate( const Coordinate& other ) ;
79     /**
80      * assign operator
81      */
82     Coordinate& operator = ( const Coordinate& other ) ;
83     /**
84      * destructor
85      */
86     ~Coordinate() ;
87 
88     /**
89      * @brief Get the dimension of the coordinates
90      */
91     int          coordinateDimension() const ;
92     /**
93      * @brief Tests if the coordinates are empty
94      */
95     bool         isEmpty() const ;
96     /**
97      * @brief Tests if Z is defined
98      */
99     bool         is3D() const ;
100 
101     //--- accessors
102 
103     /**
104      * @brief Gets the x value
105      * @warning Exact, NaN for empty coordinates
106      */
107     Kernel::FT x() const;
108 
109     /**
110      * @brief Gets the y value
111      * @warning Exact, NaN for empty coordinates
112      */
113     Kernel::FT y() const;
114 
115     /**
116      * @brief Gets the z value
117      * @warning Exact, NaN for empty or 0 for 2D coordinates
118      */
119     Kernel::FT z() const;
120 
121     //-- helper
122 
123     /**
124      * @brief round coordinates with a scale factor
125      * @return *this
126      */
127     Coordinate& round( const long& scaleFactor = 1 ) ;
128 
129 
130     //-- comparator
131 
132     /**
133      * @brief Compares two points (lexicographic order)
134      *
135      * @warning coordinates must have the same dimension
136      */
137     bool operator < ( const Coordinate& other ) const ;
138 
139     /**
140      * @brief Compares with an other point
141      *
142      * @warning coordinates must have the same dimension
143      */
144     bool operator == ( const Coordinate& other ) const ;
145     /**
146      * @brief Compares with an other point
147      *
148      * @warning coordinates must have the same dimension
149      */
150     bool operator != ( const Coordinate& other ) const ;
151 
152     /**
153      * @brief Converts to Kernel::Vector_2
154      */
toVector_2()155     inline Kernel::Vector_2 toVector_2() const {
156         return Kernel::Vector_2( CGAL::ORIGIN, toPoint_2() );
157     }
158 
159     /**
160      * @brief Converts to Kernel::Vector_3
161      */
toVector_3()162     inline Kernel::Vector_3 toVector_3() const {
163         return Kernel::Vector_3( CGAL::ORIGIN, toPoint_3() );
164     }
165 
166     /**
167      * @brief Converts to Kernel::Point_2
168      */
169     Kernel::Point_2 toPoint_2() const;
170 
171     /**
172      * @brief Converts to Kernel::Point_3
173      */
174     Kernel::Point_3 toPoint_3() const;
175 
176     // class for Empty coordinate
177     class Empty {};
178 private:
179     boost::variant< Empty, Kernel::Point_2, Kernel::Point_3 > _storage;
180 
181 public:
182     /**
183      * Serialization
184      */
185     template <class Archive>
save(Archive & ar,const unsigned int)186     void save( Archive& ar, const unsigned int /*version*/ ) const {
187         int dim = coordinateDimension();
188         ar << dim;
189 
190         if ( _storage.which() > 0 ) {
191             const Kernel::FT& x_ = x();
192             const Kernel::FT& y_ = y();
193             ar << x_;
194             ar << y_;
195 
196             if ( _storage.which() == 2 ) {
197                 const Kernel::FT& z_ = z();
198                 ar << z_;
199             }
200         }
201     }
202 
203     template <class Archive>
load(Archive & ar,const unsigned int)204     void load( Archive& ar, const unsigned int /*version*/ ) {
205         int dim;
206         ar >> dim;
207 
208         if ( dim == 0 ) {
209             _storage = Empty();
210         }
211         else if ( dim == 2 ) {
212             Kernel::FT x_, y_;
213             ar >> x_;
214             ar >> y_;
215             _storage = Kernel::Point_2( x_, y_ );
216         }
217         else if ( dim == 3 ) {
218             Kernel::FT x_, y_, z_;
219             ar >> x_;
220             ar >> y_;
221             ar >> z_;
222             _storage = Kernel::Point_3( x_, y_, z_ );
223         }
224     }
225 
226     template<class Archive>
serialize(Archive & ar,const unsigned int version)227     void serialize( Archive& ar, const unsigned int version ) {
228         boost::serialization::split_member( ar, *this, version );
229     }
230 };
231 
232 
233 }//SFCGAL
234 
235 #endif
236