1 : /******************************************************************************
2 : *
3 : * Purpose: PCIDSK Vector Shape interface. Declaration.
4 : *
5 : ******************************************************************************
6 : * Copyright (c) 2009
7 : * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
8 : *
9 : * Permission is hereby granted, free of charge, to any person obtaining a
10 : * copy of this software and associated documentation files (the "Software"),
11 : * to deal in the Software without restriction, including without limitation
12 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 : * and/or sell copies of the Software, and to permit persons to whom the
14 : * Software is furnished to do so, subject to the following conditions:
15 : *
16 : * The above copyright notice and this permission notice shall be included
17 : * in all copies or substantial portions of the Software.
18 : *
19 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 : * DEALINGS IN THE SOFTWARE.
26 : ****************************************************************************/
27 :
28 : #ifndef __INCLUDE_PCIDSK_SHAPE_H
29 : #define __INCLUDE_PCIDSK_SHAPE_H
30 :
31 : #include <string>
32 : #include <vector>
33 : #include <cstdlib>
34 : #include <cstring>
35 :
36 : namespace PCIDSK
37 : {
38 :
39 : //! Type used for shape identifier, use constant NullShapeId as a NULL value
40 : typedef int32 ShapeId;
41 :
42 : static const ShapeId NullShapeId = -1;
43 :
44 : //! Structure for an x,y,z point.
45 : typedef struct
46 : {
47 : double x;
48 : double y;
49 : double z;
50 : } ShapeVertex;
51 :
52 : /************************************************************************/
53 : /* ShapeFieldType */
54 : /************************************************************************/
55 : //! Attribute field types.
56 : typedef enum // These deliberately match GDBFieldType values.
57 : {
58 : FieldTypeNone = 0,
59 : FieldTypeFloat = 1,
60 : FieldTypeDouble = 2,
61 : FieldTypeString = 3,
62 : FieldTypeInteger = 4,
63 : FieldTypeCountedInt = 5
64 : } ShapeFieldType;
65 :
66 : /************************************************************************/
67 : /* ShapeFieldTypeName() */
68 : /************************************************************************/
69 : /**
70 : \brief Translate field type into a textual description.
71 : @param type the type enumeration value to translate.
72 : @return name for field type.
73 : */
74 : inline std::string ShapeFieldTypeName( ShapeFieldType type )
75 : {
76 : switch( type ) {
77 : case FieldTypeNone: return "None";
78 : case FieldTypeFloat: return "Float";
79 : case FieldTypeDouble: return "Double";
80 : case FieldTypeString: return "String";
81 : case FieldTypeInteger: return "Integer";
82 : case FieldTypeCountedInt: return "CountedInt";
83 : }
84 : return "";
85 : }
86 :
87 :
88 : /************************************************************************/
89 : /* ShapeField */
90 : /************************************************************************/
91 : /**
92 : \brief Attribute field value.
93 :
94 : This class encapsulates any of the supported vector attribute field
95 : types in a convenient way that avoids memory leaks or ownership confusion.
96 : The object has a field type (initially FieldTypeNone on construction)
97 : and a value of the specified type. Note that the appropriate value
98 : accessor (ie. GetValueInteger()) must be used that corresponds to the
99 : fields type. No attempt is made to automatically convert (ie. float to
100 : double) if the wrong accessor is used.
101 :
102 : */
103 :
104 : class ShapeField
105 : {
106 : private:
107 : ShapeFieldType type; // use FieldTypeNone for NULL fields.
108 :
109 : union
110 : {
111 : float float_val;
112 : double double_val;
113 : char *string_val;
114 : int32 integer_val;
115 : int32 *integer_list_val;
116 : } v;
117 :
118 : public:
119 : //! Simple constructor.
120 4408 : ShapeField()
121 4408 : { v.string_val = NULL; type = FieldTypeNone; }
122 :
123 : //! Copy constructor.
124 128525 : ShapeField( const ShapeField &src )
125 128525 : { v.string_val = NULL; type = FieldTypeNone; *this = src; }
126 :
127 132933 : ~ShapeField()
128 132933 : { Clear(); }
129 :
130 : //! Assignment operator.
131 128525 : ShapeField &operator=( const ShapeField &src )
132 : {
133 128525 : switch( src.GetType() )
134 : {
135 : case FieldTypeFloat:
136 0 : SetValue( src.GetValueFloat() );
137 0 : break;
138 : case FieldTypeDouble:
139 54 : SetValue( src.GetValueDouble() );
140 54 : break;
141 : case FieldTypeInteger:
142 64 : SetValue( src.GetValueInteger() );
143 64 : break;
144 : case FieldTypeCountedInt:
145 2 : SetValue( src.GetValueCountedInt() );
146 2 : break;
147 : case FieldTypeString:
148 26 : SetValue( src.GetValueString() );
149 26 : break;
150 : case FieldTypeNone:
151 128379 : Clear();
152 : break;
153 : }
154 128525 : return *this;
155 : }
156 :
157 : //! Assignment operator.
158 : bool operator==( const ShapeField &other )
159 : {
160 : if( GetType() != other.GetType() )
161 : return false;
162 :
163 : switch( other.GetType() )
164 : {
165 : case FieldTypeFloat:
166 : return GetValueFloat() == other.GetValueFloat();
167 : case FieldTypeDouble:
168 : return GetValueDouble() == other.GetValueDouble();
169 : case FieldTypeInteger:
170 : return GetValueInteger() == other.GetValueInteger();
171 : case FieldTypeString:
172 : return GetValueString() == other.GetValueString();
173 : case FieldTypeCountedInt:
174 : return GetValueCountedInt() == other.GetValueCountedInt();
175 : case FieldTypeNone:
176 : return false;
177 : default:
178 : return false;
179 : }
180 : }
181 :
182 : //! Clear field value.
183 390295 : void Clear()
184 : {
185 390295 : if( (type == FieldTypeString || type == FieldTypeCountedInt)
186 : && v.string_val != NULL )
187 : {
188 17446 : free( v.string_val );
189 17446 : v.string_val = NULL;
190 : }
191 390295 : type = FieldTypeNone;
192 390295 : }
193 :
194 : //! Fetch field type
195 252708 : ShapeFieldType GetType() const
196 252708 : { return type; }
197 :
198 : //! Set integer value on field.
199 55826 : void SetValue( int32 val )
200 : {
201 55826 : Clear();
202 55826 : type = FieldTypeInteger;
203 55826 : v.integer_val = val;
204 55826 : }
205 :
206 : //! Set integer list value on field.
207 4282 : void SetValue( const std::vector<int32> &val )
208 : {
209 4282 : Clear();
210 4282 : type = FieldTypeCountedInt;
211 : v.integer_list_val = (int32*)
212 4282 : malloc(sizeof(int32) * (val.size()+1) );
213 4282 : v.integer_list_val[0] = val.size();
214 4282 : if( val.size() > 0 )
215 : memcpy( v.integer_list_val+1, &(val[0]),
216 126 : sizeof(int32) * val.size() );
217 4282 : }
218 :
219 : //! Set string value on field.
220 13164 : void SetValue( const std::string &val )
221 : {
222 13164 : Clear();
223 13164 : type = FieldTypeString;
224 13164 : v.string_val = strdup(val.c_str());
225 13164 : }
226 :
227 : //! Set double precision floating point value on field.
228 55711 : void SetValue( double val )
229 : {
230 55711 : Clear();
231 55711 : type = FieldTypeDouble;
232 55711 : v.double_val = val;
233 55711 : }
234 :
235 : //! Set single precision floating point value on field.
236 0 : void SetValue( float val )
237 : {
238 0 : Clear();
239 0 : type = FieldTypeFloat;
240 0 : v.float_val = val;
241 0 : }
242 :
243 : //! Fetch value as integer or zero if field not of appropriate type.
244 55798 : int32 GetValueInteger() const
245 55798 : { if( type == FieldTypeInteger ) return v.integer_val; else return 0; }
246 : //! Fetch value as integer list or empty list if field not of appropriate type.
247 4280 : std::vector<int32> GetValueCountedInt() const
248 : {
249 4280 : std::vector<int32> result;
250 4280 : if( type == FieldTypeCountedInt )
251 : {
252 4280 : result.resize( v.integer_list_val[0] );
253 4280 : if( v.integer_list_val[0] > 0 )
254 : memcpy( &(result[0]), &(v.integer_list_val[1]),
255 126 : (v.integer_list_val[0]) * sizeof(int32) );
256 : }
257 0 : return result;
258 : }
259 : //! Fetch value as string or "" if field not of appropriate type.
260 13156 : std::string GetValueString() const
261 13156 : { if( type == FieldTypeString ) return v.string_val; else return ""; }
262 : //! Fetch value as float or 0.0 if field not of appropriate type.
263 0 : float GetValueFloat() const
264 0 : { if( type == FieldTypeFloat ) return v.float_val; else return 0.0; }
265 : //! Fetch value as double or 0.0 if field not of appropriate type.
266 55682 : double GetValueDouble() const
267 55682 : { if( type == FieldTypeDouble ) return v.double_val; else return 0.0; }
268 : };
269 :
270 : } // end namespace PCIDSK
271 :
272 : #endif // __INCLUDE_PCIDSK_SHAPE_H
|