1 /***************************************************************************
2 qgspointcloudattribute.cpp
3 -----------------------
4 begin : October 2020
5 copyright : (C) 2020 by Peter Petrik
6 email : zilolv at gmail dot com
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "qgis.h"
19 #include "qgspointcloudattribute.h"
20
21 QgsPointCloudAttribute::QgsPointCloudAttribute() = default;
22
QgsPointCloudAttribute(const QString & name,DataType type)23 QgsPointCloudAttribute::QgsPointCloudAttribute( const QString &name, DataType type )
24 : mName( name )
25 , mType( type )
26 {
27 updateSize();
28 }
29
variantType() const30 QVariant::Type QgsPointCloudAttribute::variantType() const
31 {
32 switch ( mType )
33 {
34 case DataType::Char:
35 case DataType::Short:
36 case DataType::UShort:
37 case DataType::Int32:
38 return QVariant::Int;
39
40 case DataType::Float:
41 case DataType::Double:
42 return QVariant::Double;
43 }
44 return QVariant::Invalid;
45 }
46
displayType() const47 QString QgsPointCloudAttribute::displayType() const
48 {
49 switch ( mType )
50 {
51 case DataType::Char:
52 return QObject::tr( "Character" );
53 case DataType::Short:
54 return QObject::tr( "Short" );
55 case DataType::UShort:
56 return QObject::tr( "Unsigned Short" );
57 case DataType::Float:
58 return QObject::tr( "Float" );
59 case DataType::Int32:
60 return QObject::tr( "Integer" );
61 case DataType::Double:
62 return QObject::tr( "Double" );
63 }
64 return QString();
65 }
66
isNumeric(QgsPointCloudAttribute::DataType type)67 bool QgsPointCloudAttribute::isNumeric( QgsPointCloudAttribute::DataType type )
68 {
69 switch ( type )
70 {
71 case DataType::Char:
72 return false;
73 case DataType::Short:
74 case DataType::UShort:
75 case DataType::Float:
76 case DataType::Int32:
77 case DataType::Double:
78 return true;
79 }
80 return false;
81 }
82
updateSize()83 void QgsPointCloudAttribute::updateSize()
84 {
85 switch ( mType )
86 {
87 case DataType::Char:
88 mSize = 1;
89 break;
90 case DataType::Short:
91 case DataType::UShort:
92 mSize = 2;
93 break;
94 case DataType::Float:
95 mSize = 4;
96 break;
97 case DataType::Int32:
98 mSize = 4;
99 break;
100 case DataType::Double:
101 mSize = 8;
102 break;
103 }
104 }
105
106 // //////////////////
107
108 QgsPointCloudAttributeCollection::QgsPointCloudAttributeCollection() = default;
109
QgsPointCloudAttributeCollection(const QVector<QgsPointCloudAttribute> & attributes)110 QgsPointCloudAttributeCollection::QgsPointCloudAttributeCollection( const QVector<QgsPointCloudAttribute> &attributes )
111 {
112 mAttributes.reserve( attributes.size() );
113 for ( const QgsPointCloudAttribute &attribute : attributes )
114 {
115 push_back( attribute );
116 }
117 }
118
push_back(const QgsPointCloudAttribute & attribute)119 void QgsPointCloudAttributeCollection::push_back( const QgsPointCloudAttribute &attribute )
120 {
121 mCachedAttributes.insert( attribute.name(), CachedAttributeData( mAttributes.size(), mSize ) );
122 mAttributes.push_back( attribute );
123 mSize += attribute.size();
124 }
125
attributes() const126 QVector<QgsPointCloudAttribute> QgsPointCloudAttributeCollection::attributes() const
127 {
128 return mAttributes;
129 }
130
find(const QString & attributeName,int & offset) const131 const QgsPointCloudAttribute *QgsPointCloudAttributeCollection::find( const QString &attributeName, int &offset ) const
132 {
133 const auto it = mCachedAttributes.constFind( attributeName );
134 if ( it != mCachedAttributes.constEnd() )
135 {
136 offset = it->offset;
137 return &mAttributes.at( it->index );
138 }
139
140 // not found
141 return nullptr;
142 }
143
indexOf(const QString & name) const144 int QgsPointCloudAttributeCollection::indexOf( const QString &name ) const
145 {
146 const auto it = mCachedAttributes.constFind( name );
147 if ( it != mCachedAttributes.constEnd() )
148 {
149 return it->index;
150 }
151
152 // not found
153 return -1;
154 }
155
toFields() const156 QgsFields QgsPointCloudAttributeCollection::toFields() const
157 {
158 QgsFields fields;
159 for ( const QgsPointCloudAttribute &attribute : mAttributes )
160 {
161 fields.append( QgsField( attribute.name(), attribute.variantType(), attribute.displayType() ) );
162 }
163 return fields;
164 }
165
166 template <typename T>
_attribute(const char * data,std::size_t offset,QgsPointCloudAttribute::DataType type,T & value)167 void _attribute( const char *data, std::size_t offset, QgsPointCloudAttribute::DataType type, T &value )
168 {
169 switch ( type )
170 {
171 case QgsPointCloudAttribute::Char:
172 value = *( data + offset );
173 break;
174
175 case QgsPointCloudAttribute::Int32:
176 value = *reinterpret_cast< const qint32 * >( data + offset );
177 break;
178
179 case QgsPointCloudAttribute::Short:
180 {
181 value = *reinterpret_cast< const short * >( data + offset );
182 }
183 break;
184
185 case QgsPointCloudAttribute::UShort:
186 value = *reinterpret_cast< const unsigned short * >( data + offset );
187 break;
188
189 case QgsPointCloudAttribute::Float:
190 value = static_cast< T >( *reinterpret_cast< const float * >( data + offset ) );
191 break;
192
193 case QgsPointCloudAttribute::Double:
194 value = *reinterpret_cast< const double * >( data + offset );
195 break;
196 }
197 }
198
getPointXYZ(const char * ptr,int i,std::size_t pointRecordSize,int xOffset,QgsPointCloudAttribute::DataType xType,int yOffset,QgsPointCloudAttribute::DataType yType,int zOffset,QgsPointCloudAttribute::DataType zType,const QgsVector3D & indexScale,const QgsVector3D & indexOffset,double & x,double & y,double & z)199 void QgsPointCloudAttribute::getPointXYZ( const char *ptr, int i, std::size_t pointRecordSize, int xOffset, QgsPointCloudAttribute::DataType xType,
200 int yOffset, QgsPointCloudAttribute::DataType yType,
201 int zOffset, QgsPointCloudAttribute::DataType zType,
202 const QgsVector3D &indexScale, const QgsVector3D &indexOffset, double &x, double &y, double &z )
203 {
204 _attribute( ptr, i * pointRecordSize + xOffset, xType, x );
205 x = indexOffset.x() + indexScale.x() * x;
206
207 _attribute( ptr, i * pointRecordSize + yOffset, yType, y );
208 y = indexOffset.y() + indexScale.y() * y;
209
210 _attribute( ptr, i * pointRecordSize + zOffset, zType, z );
211 z = indexOffset.z() + indexScale.z() * z;
212 }
213
getAttributeMap(const char * data,std::size_t recordOffset,const QgsPointCloudAttributeCollection & attributeCollection)214 QVariantMap QgsPointCloudAttribute::getAttributeMap( const char *data, std::size_t recordOffset, const QgsPointCloudAttributeCollection &attributeCollection )
215 {
216 QVariantMap map;
217 const QVector<QgsPointCloudAttribute> attributes = attributeCollection.attributes();
218 for ( const QgsPointCloudAttribute &attr : attributes )
219 {
220 const QString attributeName = attr.name();
221 int attributeOffset;
222 attributeCollection.find( attributeName, attributeOffset );
223 switch ( attr.type() )
224 {
225 case QgsPointCloudAttribute::Char:
226 {
227 const char value = *( data + recordOffset + attributeOffset );
228 map[ attributeName ] = value;
229 }
230 break;
231
232 case QgsPointCloudAttribute::Int32:
233 {
234 const qint32 value = *reinterpret_cast< const qint32 * >( data + recordOffset + attributeOffset );
235 map[ attributeName ] = value;
236 }
237 break;
238
239 case QgsPointCloudAttribute::Short:
240 {
241 const short value = *reinterpret_cast< const short * >( data + recordOffset + attributeOffset );
242 map[ attributeName ] = value;
243 }
244 break;
245
246 case QgsPointCloudAttribute::UShort:
247 {
248 const unsigned short value = *reinterpret_cast< const unsigned short * >( data + recordOffset + attributeOffset );
249 map[ attributeName ] = value;
250 }
251 break;
252
253 case QgsPointCloudAttribute::Float:
254 {
255 const float value = *reinterpret_cast< const float * >( data + recordOffset + attributeOffset );
256 map[ attributeName ] = value;
257 }
258 break;
259
260 case QgsPointCloudAttribute::Double:
261 {
262 const double value = *reinterpret_cast< const double * >( data + recordOffset + attributeOffset );
263 map[ attributeName ] = value;
264 }
265 break;
266 }
267 }
268 return map;
269 }
270