Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgspointcloudindex.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 "qgspointcloudindex.h"
19 : : #include <QFile>
20 : : #include <QFileInfo>
21 : : #include <QDir>
22 : : #include <QJsonArray>
23 : : #include <QJsonDocument>
24 : : #include <QJsonObject>
25 : : #include <QTime>
26 : : #include <QtDebug>
27 : :
28 : 0 : IndexedPointCloudNode::IndexedPointCloudNode():
29 : 0 : mD( -1 ),
30 : 0 : mX( 0 ),
31 : 0 : mY( 0 ),
32 : 0 : mZ( 0 )
33 : 0 : {}
34 : :
35 : 0 : IndexedPointCloudNode::IndexedPointCloudNode( int _d, int _x, int _y, int _z ):
36 : 0 : mD( _d ),
37 : 0 : mX( _x ),
38 : 0 : mY( _y ),
39 : 0 : mZ( _z )
40 : 0 : {}
41 : :
42 : 0 : IndexedPointCloudNode IndexedPointCloudNode::fromString( const QString &str )
43 : : {
44 : 0 : QStringList lst = str.split( '-' );
45 : 0 : if ( lst.count() != 4 )
46 : 0 : return IndexedPointCloudNode();
47 : 0 : return IndexedPointCloudNode( lst[0].toInt(), lst[1].toInt(), lst[2].toInt(), lst[3].toInt() );
48 : 0 : }
49 : :
50 : 0 : QString IndexedPointCloudNode::toString() const
51 : : {
52 : 0 : return QStringLiteral( "%1-%2-%3-%4" ).arg( mD ).arg( mX ).arg( mY ).arg( mZ );
53 : 0 : }
54 : :
55 : 0 : int IndexedPointCloudNode::d() const
56 : : {
57 : 0 : return mD;
58 : : }
59 : :
60 : 0 : int IndexedPointCloudNode::x() const
61 : : {
62 : 0 : return mX;
63 : : }
64 : :
65 : 0 : int IndexedPointCloudNode::y() const
66 : : {
67 : 0 : return mY;
68 : : }
69 : :
70 : 0 : int IndexedPointCloudNode::z() const
71 : : {
72 : 0 : return mZ;
73 : : }
74 : :
75 : 0 : uint qHash( IndexedPointCloudNode id )
76 : : {
77 : 0 : return id.d() + id.x() + id.y() + id.z();
78 : : }
79 : :
80 : : ///@cond PRIVATE
81 : :
82 : : //
83 : : // QgsPointCloudDataBounds
84 : : //
85 : :
86 : 0 : QgsPointCloudDataBounds::QgsPointCloudDataBounds() = default;
87 : :
88 : 0 : QgsPointCloudDataBounds::QgsPointCloudDataBounds( qint32 xmin, qint32 ymin, qint32 zmin, qint32 xmax, qint32 ymax, qint32 zmax )
89 : 0 : : mXMin( xmin )
90 : 0 : , mYMin( ymin )
91 : 0 : , mZMin( zmin )
92 : 0 : , mXMax( xmax )
93 : 0 : , mYMax( ymax )
94 : 0 : , mZMax( zmax )
95 : : {
96 : :
97 : 0 : }
98 : :
99 : 0 : qint32 QgsPointCloudDataBounds::xMin() const
100 : : {
101 : 0 : return mXMin;
102 : : }
103 : :
104 : 0 : qint32 QgsPointCloudDataBounds::yMin() const
105 : : {
106 : 0 : return mYMin;
107 : : }
108 : :
109 : 0 : qint32 QgsPointCloudDataBounds::xMax() const
110 : : {
111 : 0 : return mXMax;
112 : : }
113 : :
114 : 0 : qint32 QgsPointCloudDataBounds::yMax() const
115 : : {
116 : 0 : return mYMax;
117 : : }
118 : :
119 : 0 : qint32 QgsPointCloudDataBounds::zMin() const
120 : : {
121 : 0 : return mZMin;
122 : : }
123 : :
124 : 0 : qint32 QgsPointCloudDataBounds::zMax() const
125 : : {
126 : 0 : return mZMax;
127 : : }
128 : :
129 : 0 : QgsRectangle QgsPointCloudDataBounds::mapExtent( const QgsVector3D &offset, const QgsVector3D &scale ) const
130 : : {
131 : 0 : return QgsRectangle(
132 : 0 : mXMin * scale.x() + offset.x(), mYMin * scale.y() + offset.y(),
133 : 0 : mXMax * scale.x() + offset.x(), mYMax * scale.y() + offset.y()
134 : : );
135 : : }
136 : :
137 : 0 : QgsDoubleRange QgsPointCloudDataBounds::zRange( const QgsVector3D &offset, const QgsVector3D &scale ) const
138 : : {
139 : 0 : return QgsDoubleRange( mZMin * scale.z() + offset.z(), mZMax * scale.z() + offset.z() );
140 : : }
141 : :
142 : : ///@endcond
143 : :
144 : :
145 : : //
146 : : // QgsPointCloudIndex
147 : : //
148 : :
149 : 0 : QgsPointCloudIndex::QgsPointCloudIndex() = default;
150 : :
151 : 0 : QgsPointCloudIndex::~QgsPointCloudIndex() = default;
152 : :
153 : 0 : QList<IndexedPointCloudNode> QgsPointCloudIndex::nodeChildren( const IndexedPointCloudNode &n ) const
154 : : {
155 : : Q_ASSERT( mHierarchy.contains( n ) );
156 : 0 : QList<IndexedPointCloudNode> lst;
157 : 0 : int d = n.d() + 1;
158 : 0 : int x = n.x() * 2;
159 : 0 : int y = n.y() * 2;
160 : 0 : int z = n.z() * 2;
161 : :
162 : 0 : for ( int i = 0; i < 8; ++i )
163 : : {
164 : 0 : int dx = i & 1, dy = !!( i & 2 ), dz = !!( i & 4 );
165 : 0 : IndexedPointCloudNode n2( d, x + dx, y + dy, z + dz );
166 : 0 : if ( mHierarchy.contains( n2 ) )
167 : 0 : lst.append( n2 );
168 : 0 : }
169 : 0 : return lst;
170 : 0 : }
171 : :
172 : 0 : QgsPointCloudAttributeCollection QgsPointCloudIndex::attributes() const
173 : : {
174 : 0 : return mAttributes;
175 : : }
176 : :
177 : 0 : QgsPointCloudDataBounds QgsPointCloudIndex::nodeBounds( const IndexedPointCloudNode &n ) const
178 : : {
179 : 0 : qint32 xMin = -999999999, yMin = -999999999, zMin = -999999999;
180 : 0 : qint32 xMax = 999999999, yMax = 999999999, zMax = 999999999;
181 : :
182 : 0 : int d = mRootBounds.xMax() - mRootBounds.xMin();
183 : 0 : double dLevel = ( double )d / pow( 2, n.d() );
184 : :
185 : 0 : xMin = round( mRootBounds.xMin() + dLevel * n.x() );
186 : 0 : xMax = round( mRootBounds.xMin() + dLevel * ( n.x() + 1 ) );
187 : 0 : yMin = round( mRootBounds.yMin() + dLevel * n.y() );
188 : 0 : yMax = round( mRootBounds.yMin() + dLevel * ( n.y() + 1 ) );
189 : 0 : zMin = round( mRootBounds.zMin() + dLevel * n.z() );
190 : 0 : zMax = round( mRootBounds.zMin() + dLevel * ( n.z() + 1 ) );
191 : :
192 : 0 : QgsPointCloudDataBounds db( xMin, yMin, zMin, xMax, yMax, zMax );
193 : 0 : return db;
194 : : }
195 : :
196 : 0 : QgsRectangle QgsPointCloudIndex::nodeMapExtent( const IndexedPointCloudNode &node ) const
197 : : {
198 : 0 : return nodeBounds( node ).mapExtent( mOffset, mScale );
199 : : }
200 : :
201 : 0 : QgsDoubleRange QgsPointCloudIndex::nodeZRange( const IndexedPointCloudNode &node ) const
202 : : {
203 : 0 : return nodeBounds( node ).zRange( mOffset, mScale );
204 : : }
205 : :
206 : 0 : float QgsPointCloudIndex::nodeError( const IndexedPointCloudNode &n ) const
207 : : {
208 : 0 : double w = nodeMapExtent( n ).width();
209 : 0 : return w / mSpan;
210 : : }
211 : :
212 : 0 : QgsVector3D QgsPointCloudIndex::scale() const
213 : : {
214 : 0 : return mScale;
215 : : }
216 : :
217 : 0 : QgsVector3D QgsPointCloudIndex::offset() const
218 : : {
219 : 0 : return mOffset;
220 : : }
221 : :
222 : 0 : void QgsPointCloudIndex::setAttributes( const QgsPointCloudAttributeCollection &attributes )
223 : : {
224 : 0 : mAttributes = attributes;
225 : 0 : }
226 : :
227 : 0 : int QgsPointCloudIndex::span() const
228 : : {
229 : 0 : return mSpan;
230 : : }
231 : :
232 : 0 : int QgsPointCloudIndex::nodePointCount( const IndexedPointCloudNode &n )
233 : : {
234 : 0 : if ( !mHierarchy.contains( n ) )
235 : 0 : return -1;
236 : 0 : return mHierarchy[n];
237 : 0 : }
|