Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Purpose: PCIDSK Vector Shape interface. Declaration. 4 : * 5 : ****************************************************************************** 6 : * Copyright (c) 2009 7 : * PCI Geomatics, 90 Allstate Parkway, Markham, Ontario, Canada. 8 : * 9 : * SPDX-License-Identifier: MIT 10 : ****************************************************************************/ 11 : 12 : #ifndef INCLUDE_PCIDSK_SHAPE_H 13 : #define INCLUDE_PCIDSK_SHAPE_H 14 : 15 : #include <string> 16 : #include <vector> 17 : #include <cstdlib> 18 : #include <cstring> 19 : 20 : namespace PCIDSK 21 : { 22 : 23 : //! Type used for shape identifier, use constant NullShapeId as a NULL value 24 : typedef int32 ShapeId; 25 : 26 : static const ShapeId NullShapeId = -1; 27 : 28 : //! Structure for an x,y,z point. 29 : typedef struct 30 : { 31 : double x; 32 : double y; 33 : double z; 34 : } ShapeVertex; 35 : 36 : /************************************************************************/ 37 : /* ShapeFieldType */ 38 : /************************************************************************/ 39 : //! Attribute field types. 40 : typedef enum // These deliberately match GDBFieldType values. 41 : { 42 : FieldTypeNone = 0, 43 : FieldTypeFloat = 1, 44 : FieldTypeDouble = 2, 45 : FieldTypeString = 3, 46 : FieldTypeInteger = 4, 47 : FieldTypeCountedInt = 5 48 : } ShapeFieldType; 49 : 50 : /************************************************************************/ 51 : /* ShapeFieldTypeName() */ 52 : /************************************************************************/ 53 : /** 54 : \brief Translate field type into a textual description. 55 : @param type the type enumeration value to translate. 56 : @return name for field type. 57 : */ 58 : inline std::string ShapeFieldTypeName( ShapeFieldType type ) 59 : { 60 : switch( type ) { 61 : case FieldTypeNone: return "None"; 62 : case FieldTypeFloat: return "Float"; 63 : case FieldTypeDouble: return "Double"; 64 : case FieldTypeString: return "String"; 65 : case FieldTypeInteger: return "Integer"; 66 : case FieldTypeCountedInt: return "CountedInt"; 67 : } 68 : return ""; 69 : } 70 : 71 : 72 : /************************************************************************/ 73 : /* ShapeField */ 74 : /************************************************************************/ 75 : /** 76 : \brief Attribute field value. 77 : 78 : This class encapsulates any of the supported vector attribute field 79 : types in a convenient way that avoids memory leaks or ownership confusion. 80 : The object has a field type (initially FieldTypeNone on construction) 81 : and a value of the specified type. Note that the appropriate value 82 : accessor (i.e. GetValueInteger()) must be used that corresponds to the 83 : fields type. No attempt is made to automatically convert (i.e. float to 84 : double) if the wrong accessor is used. 85 : 86 : */ 87 : 88 : class ShapeField 89 : { 90 : private: 91 : ShapeFieldType type; // use FieldTypeNone for NULL fields. 92 : 93 : union 94 : { 95 : float float_val; 96 : double double_val; 97 : char *string_val; 98 : int32 integer_val; 99 : int32 *integer_list_val; 100 : } v; 101 : 102 : public: 103 : //! Simple constructor. 104 3010 : ShapeField() 105 3010 : { v.string_val = nullptr; type = FieldTypeNone; } 106 : 107 : //! Copy constructor. 108 544 : ShapeField( const ShapeField &src ) 109 544 : { v.string_val = nullptr; type = FieldTypeNone; *this = src; } 110 : 111 3554 : ~ShapeField() 112 3554 : { Clear(); } 113 : 114 : //! Assignment operator. 115 544 : ShapeField &operator=( const ShapeField &src ) 116 : { 117 544 : switch( src.GetType() ) 118 : { 119 0 : case FieldTypeFloat: 120 0 : SetValue( src.GetValueFloat() ); 121 0 : break; 122 84 : case FieldTypeDouble: 123 84 : SetValue( src.GetValueDouble() ); 124 84 : break; 125 129 : case FieldTypeInteger: 126 129 : SetValue( src.GetValueInteger() ); 127 129 : break; 128 0 : case FieldTypeCountedInt: 129 0 : SetValue( src.GetValueCountedInt() ); 130 0 : break; 131 331 : case FieldTypeString: 132 331 : SetValue( src.GetValueString() ); 133 331 : break; 134 0 : case FieldTypeNone: 135 0 : Clear(); 136 0 : break; 137 : } 138 544 : return *this; 139 : } 140 : 141 : //! Assignment operator. 142 : bool operator==( const ShapeField &other ) 143 : { 144 : if( GetType() != other.GetType() ) 145 : return false; 146 : 147 : switch( other.GetType() ) 148 : { 149 : case FieldTypeFloat: 150 : return GetValueFloat() == other.GetValueFloat(); 151 : case FieldTypeDouble: 152 : return GetValueDouble() == other.GetValueDouble(); 153 : case FieldTypeInteger: 154 : return GetValueInteger() == other.GetValueInteger(); 155 : case FieldTypeString: 156 : return GetValueString() == other.GetValueString(); 157 : case FieldTypeCountedInt: 158 : return GetValueCountedInt() == other.GetValueCountedInt(); 159 : case FieldTypeNone: 160 : return false; 161 : default: 162 : return false; 163 : } 164 : } 165 : 166 : //! Clear field value. 167 9452 : void Clear() 168 : { 169 9452 : if( (type == FieldTypeString || type == FieldTypeCountedInt) 170 3910 : && v.string_val != nullptr ) 171 : { 172 3910 : free( v.string_val ); 173 3910 : v.string_val = nullptr; 174 : } 175 9452 : type = FieldTypeNone; 176 9452 : } 177 : 178 : //! Fetch field type 179 2614 : ShapeFieldType GetType() const 180 2614 : { return type; } 181 : 182 : //! Set integer value on field. 183 1752 : void SetValue( int32 val ) 184 : { 185 1752 : Clear(); 186 1752 : type = FieldTypeInteger; 187 1752 : v.integer_val = val; 188 1752 : } 189 : 190 : //! Set integer list value on field. 191 0 : void SetValue( const std::vector<int32> &val ) 192 : { 193 0 : Clear(); 194 0 : type = FieldTypeCountedInt; 195 0 : v.integer_list_val = (int32*) 196 0 : malloc(sizeof(int32) * (val.size()+1) ); 197 0 : v.integer_list_val[0] = static_cast<int32>(val.size()); 198 0 : if( !val.empty() ) 199 0 : memcpy( v.integer_list_val+1, &(val[0]), 200 0 : sizeof(int32) * val.size() ); 201 0 : } 202 : 203 : //! Set string value on field. 204 3910 : void SetValue( const std::string &val ) 205 : { 206 3910 : Clear(); 207 3910 : type = FieldTypeString; 208 3910 : v.string_val = strdup(val.c_str()); 209 3910 : } 210 : 211 : //! Set double precision floating point value on field. 212 236 : void SetValue( double val ) 213 : { 214 236 : Clear(); 215 236 : type = FieldTypeDouble; 216 236 : v.double_val = val; 217 236 : } 218 : 219 : //! Set single precision floating point value on field. 220 0 : void SetValue( float val ) 221 : { 222 0 : Clear(); 223 0 : type = FieldTypeFloat; 224 0 : v.float_val = val; 225 0 : } 226 : 227 : //! Fetch value as integer or zero if field not of appropriate type. 228 1725 : int32 GetValueInteger() const 229 1725 : { if( type == FieldTypeInteger ) return v.integer_val; else return 0; } 230 : //! Fetch value as integer list or empty list if field not of appropriate type. 231 0 : std::vector<int32> GetValueCountedInt() const 232 : { 233 0 : std::vector<int32> result; 234 0 : if( type == FieldTypeCountedInt ) 235 : { 236 0 : result.resize( v.integer_list_val[0] ); 237 0 : if( v.integer_list_val[0] > 0 ) 238 0 : memcpy( &(result[0]), &(v.integer_list_val[1]), 239 0 : (v.integer_list_val[0]) * sizeof(int32) ); 240 : } 241 0 : return result; 242 : } 243 : //! Fetch value as string or "" if field not of appropriate type. 244 3229 : std::string GetValueString() const 245 3229 : { if( type == FieldTypeString ) return v.string_val; else return ""; } 246 : //! Fetch value as float or 0.0 if field not of appropriate type. 247 0 : float GetValueFloat() const 248 0 : { if( type == FieldTypeFloat ) return v.float_val; else return 0.0; } 249 : //! Fetch value as double or 0.0 if field not of appropriate type. 250 209 : double GetValueDouble() const 251 209 : { if( type == FieldTypeDouble ) return v.double_val; else return 0.0; } 252 : }; 253 : 254 : } // end namespace PCIDSK 255 : 256 : #endif // INCLUDE_PCIDSK_SHAPE_H