Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsmeshtriangulation.cpp
3 : : -----------------
4 : : begin : August 9th, 2020
5 : : copyright : (C) 2020 by Vincent Cloarec
6 : : email : vcloarec 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 "qgsmeshtriangulation.h"
19 : : #include "qgsdualedgetriangulation.h"
20 : : #include "qgsvectorlayer.h"
21 : : #include "qgscoordinatetransformcontext.h"
22 : : #include "qgscurve.h"
23 : : #include "qgscurvepolygon.h"
24 : : #include "qgsmultisurface.h"
25 : : #include "qgsmulticurve.h"
26 : : #include "qgsfeedback.h"
27 : : #include "qgslogger.h"
28 : :
29 : 0 : QgsMeshTriangulation::QgsMeshTriangulation(): QObject()
30 : 0 : {
31 : 0 : mTriangulation.reset( new QgsDualEdgeTriangulation() );
32 : 0 : }
33 : :
34 : :
35 : 0 : QgsMeshTriangulation::~QgsMeshTriangulation() = default;
36 : :
37 : 0 : bool QgsMeshTriangulation::addVertices( QgsFeatureIterator &vertexFeatureIterator, int valueAttribute, const QgsCoordinateTransform &transform, QgsFeedback *feedback, long featureCount )
38 : : {
39 : 0 : if ( feedback )
40 : 0 : feedback->setProgress( 0 );
41 : :
42 : 0 : QgsFeature feat;
43 : 0 : long i = 0;
44 : 0 : while ( vertexFeatureIterator.nextFeature( feat ) )
45 : : {
46 : 0 : if ( feedback )
47 : : {
48 : 0 : if ( feedback->isCanceled() )
49 : 0 : break;
50 : :
51 : 0 : feedback->setProgress( 100 * i / featureCount );
52 : 0 : i++;
53 : 0 : }
54 : :
55 : 0 : addVerticesFromFeature( feat, valueAttribute, transform, feedback );
56 : : }
57 : :
58 : : return true;
59 : 0 : }
60 : :
61 : 0 : bool QgsMeshTriangulation::addBreakLines( QgsFeatureIterator &lineFeatureIterator, int valueAttribute, const QgsCoordinateTransform &transform, QgsFeedback *feedback, long featureCount )
62 : : {
63 : 0 : if ( feedback )
64 : 0 : feedback->setProgress( 0 );
65 : :
66 : 0 : QgsFeature feat;
67 : 0 : long i = 0;
68 : 0 : while ( lineFeatureIterator.nextFeature( feat ) )
69 : : {
70 : 0 : if ( feedback )
71 : : {
72 : 0 : if ( feedback->isCanceled() )
73 : 0 : break;
74 : :
75 : 0 : feedback->setProgress( 100 * i / featureCount );
76 : 0 : i++;
77 : 0 : }
78 : :
79 : 0 : QgsWkbTypes::GeometryType geomType = feat.geometry().type();
80 : 0 : switch ( geomType )
81 : : {
82 : : case QgsWkbTypes::PointGeometry:
83 : 0 : addVerticesFromFeature( feat, valueAttribute, transform, feedback );
84 : 0 : break;
85 : : case QgsWkbTypes::LineGeometry:
86 : : case QgsWkbTypes::PolygonGeometry:
87 : 0 : addBreakLinesFromFeature( feat, valueAttribute, transform, feedback );
88 : 0 : break;
89 : : default:
90 : 0 : break;
91 : : }
92 : : }
93 : :
94 : : return true;
95 : 0 : }
96 : :
97 : 0 : QgsMesh QgsMeshTriangulation::triangulatedMesh( QgsFeedback *feedback ) const
98 : : {
99 : 0 : return mTriangulation->triangulationToMesh( feedback );
100 : : }
101 : :
102 : 0 : void QgsMeshTriangulation::setCrs( const QgsCoordinateReferenceSystem &crs )
103 : : {
104 : 0 : mCrs = crs;
105 : 0 : }
106 : :
107 : 0 : void QgsMeshTriangulation::addVerticesFromFeature( const QgsFeature &feature, int valueAttribute, const QgsCoordinateTransform &transform, QgsFeedback *feedback )
108 : : {
109 : 0 : QgsGeometry geom = feature.geometry();
110 : : try
111 : : {
112 : 0 : geom.transform( transform, QgsCoordinateTransform::ForwardTransform, true );
113 : 0 : }
114 : : catch ( QgsCsException &cse )
115 : : {
116 : 0 : Q_UNUSED( cse )
117 : 0 : QgsDebugMsgLevel( QStringLiteral( "Caught CRS exception %1" ).arg( cse.what() ), 4 );
118 : : return;
119 : 0 : }
120 : 0 :
121 : 0 : QgsAbstractGeometry::vertex_iterator vit = geom.vertices_begin();
122 : :
123 : 0 : double value = 0;
124 : 0 : if ( valueAttribute >= 0 )
125 : 0 : value = feature.attribute( valueAttribute ).toDouble();
126 : :
127 : 0 : while ( vit != geom.vertices_end() )
128 : : {
129 : 0 : if ( feedback && feedback->isCanceled() )
130 : 0 : break;
131 : 0 : if ( valueAttribute < 0 )
132 : 0 : mTriangulation->addPoint( *vit );
133 : : else
134 : : {
135 : 0 : mTriangulation->addPoint( QgsPoint( QgsWkbTypes::PointZ, ( *vit ).x(), ( *vit ).y(), value ) );
136 : : }
137 : 0 : ++vit;
138 : : }
139 : 0 : }
140 : :
141 : 0 : void QgsMeshTriangulation::addBreakLinesFromFeature( const QgsFeature &feature, int valueAttribute, const QgsCoordinateTransform &transform, QgsFeedback *feedback )
142 : : {
143 : 0 : double valueOnVertex = 0;
144 : 0 : if ( valueAttribute >= 0 )
145 : 0 : valueOnVertex = feature.attribute( valueAttribute ).toDouble();
146 : :
147 : : //from QgsTinInterpolator::insertData()
148 : 0 : std::vector<const QgsCurve *> curves;
149 : 0 : QgsGeometry geom = feature.geometry();
150 : : try
151 : : {
152 : 0 : geom.transform( transform, QgsCoordinateTransform::ForwardTransform, true );
153 : 0 : }
154 : : catch ( QgsCsException &cse )
155 : : {
156 : 0 : Q_UNUSED( cse )
157 : 0 : QgsDebugMsgLevel( QStringLiteral( "Caught CRS exception %1" ).arg( cse.what() ), 4 );
158 : : return;
159 : 0 : }
160 : :
161 : 0 : if ( QgsWkbTypes::geometryType( geom.wkbType() ) == QgsWkbTypes::PolygonGeometry )
162 : : {
163 : 0 : std::vector< const QgsCurvePolygon * > polygons;
164 : 0 : if ( geom.isMultipart() )
165 : : {
166 : 0 : const QgsMultiSurface *ms = qgsgeometry_cast< const QgsMultiSurface * >( geom.constGet() );
167 : 0 : for ( int i = 0; i < ms->numGeometries(); ++i )
168 : : {
169 : 0 : polygons.emplace_back( qgsgeometry_cast< const QgsCurvePolygon * >( ms->geometryN( i ) ) );
170 : 0 : }
171 : 0 : }
172 : : else
173 : : {
174 : 0 : polygons.emplace_back( qgsgeometry_cast< const QgsCurvePolygon * >( geom.constGet() ) );
175 : : }
176 : :
177 : 0 : for ( const QgsCurvePolygon *polygon : polygons )
178 : : {
179 : 0 : if ( feedback && feedback->isCanceled() )
180 : 0 : break;
181 : 0 : if ( !polygon )
182 : 0 : continue;
183 : :
184 : 0 : if ( polygon->exteriorRing() )
185 : 0 : curves.emplace_back( polygon->exteriorRing() );
186 : :
187 : 0 : for ( int i = 0; i < polygon->numInteriorRings(); ++i )
188 : : {
189 : 0 : if ( feedback && feedback->isCanceled() )
190 : 0 : break;
191 : 0 : curves.emplace_back( polygon->interiorRing( i ) );
192 : 0 : }
193 : : }
194 : 0 : }
195 : : else
196 : : {
197 : 0 : if ( geom.isMultipart() )
198 : : {
199 : 0 : const QgsMultiCurve *mc = qgsgeometry_cast< const QgsMultiCurve * >( geom.constGet() );
200 : 0 : for ( int i = 0; i < mc->numGeometries(); ++i )
201 : : {
202 : 0 : if ( feedback && feedback->isCanceled() )
203 : 0 : break;
204 : 0 : curves.emplace_back( qgsgeometry_cast< const QgsCurve * >( mc->geometryN( i ) ) );
205 : 0 : }
206 : 0 : }
207 : : else
208 : : {
209 : 0 : curves.emplace_back( qgsgeometry_cast< const QgsCurve * >( geom.constGet() ) );
210 : : }
211 : : }
212 : :
213 : 0 : for ( const QgsCurve *curve : curves )
214 : : {
215 : 0 : if ( !curve )
216 : 0 : continue;
217 : :
218 : 0 : if ( feedback && feedback->isCanceled() )
219 : 0 : break;
220 : :
221 : 0 : QgsPointSequence linePoints;
222 : 0 : curve->points( linePoints );
223 : 0 : bool hasZ = curve->is3D();
224 : 0 : if ( valueAttribute >= 0 )
225 : 0 : for ( int i = 0; i < linePoints.count(); ++i )
226 : : {
227 : 0 : if ( feedback && feedback->isCanceled() )
228 : 0 : break;
229 : 0 : if ( hasZ )
230 : 0 : linePoints[i].setZ( valueOnVertex );
231 : : else
232 : : {
233 : 0 : const QgsPoint &point = linePoints.at( i );
234 : 0 : linePoints[i] = QgsPoint( point.x(), point.y(), valueOnVertex );
235 : : }
236 : 0 : }
237 : :
238 : 0 : mTriangulation->addLine( linePoints, QgsInterpolator::SourceBreakLines );
239 : 0 : }
240 : 0 : }
241 : :
242 : 0 : QgsMeshZValueDatasetGroup::QgsMeshZValueDatasetGroup( const QString &datasetGroupName, const QgsMesh &mesh ):
243 : 0 : QgsMeshDatasetGroup( datasetGroupName, QgsMeshDatasetGroupMetadata::DataOnVertices )
244 : 0 : {
245 : 0 : mDataset = std::make_unique< QgsMeshZValueDataset >( mesh );
246 : 0 : }
247 : :
248 : 0 : void QgsMeshZValueDatasetGroup::initialize()
249 : : {
250 : 0 : calculateStatistic();
251 : 0 : }
252 : :
253 : 0 : QgsMeshDatasetMetadata QgsMeshZValueDatasetGroup::datasetMetadata( int datasetIndex ) const
254 : : {
255 : 0 : if ( datasetIndex != 0 )
256 : 0 : return QgsMeshDatasetMetadata();
257 : :
258 : 0 : return mDataset->metadata();
259 : 0 : }
260 : :
261 : 0 : int QgsMeshZValueDatasetGroup::datasetCount() const {return 1;}
262 : :
263 : 0 : QgsMeshDataset *QgsMeshZValueDatasetGroup::dataset( int index ) const
264 : : {
265 : 0 : if ( index != 0 )
266 : 0 : return nullptr;
267 : :
268 : 0 : return mDataset.get();
269 : 0 : }
270 : :
271 : 0 : QDomElement QgsMeshZValueDatasetGroup::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
272 : : {
273 : 0 : Q_UNUSED( doc );
274 : 0 : Q_UNUSED( context );
275 : 0 : return QDomElement();
276 : : }
277 : :
278 : 0 : QgsMeshZValueDataset::QgsMeshZValueDataset( const QgsMesh &mesh ): mMesh( mesh )
279 : 0 : {
280 : 0 : for ( const QgsMeshVertex &vertex : mesh.vertices )
281 : : {
282 : 0 : if ( vertex.z() < mZMinimum )
283 : 0 : mZMinimum = vertex.z();
284 : 0 : if ( vertex.z() > mZMaximum )
285 : 0 : mZMaximum = vertex.z();
286 : : }
287 : 0 : }
288 : :
289 : 0 : QgsMeshDatasetValue QgsMeshZValueDataset::datasetValue( int valueIndex ) const
290 : : {
291 : 0 : if ( valueIndex < 0 || valueIndex >= mMesh.vertexCount() )
292 : 0 : return QgsMeshDatasetValue();
293 : :
294 : 0 : return QgsMeshDatasetValue( mMesh.vertex( valueIndex ).z() );
295 : 0 : }
296 : :
297 : 0 : QgsMeshDataBlock QgsMeshZValueDataset::datasetValues( bool isScalar, int valueIndex, int count ) const
298 : : {
299 : : Q_UNUSED( isScalar )
300 : 0 : QgsMeshDataBlock ret( QgsMeshDataBlock::ScalarDouble, count );
301 : 0 : QVector<double> zValues( count );
302 : 0 : for ( int i = valueIndex; i < valueIndex + count; ++i )
303 : 0 : zValues[i - valueIndex] = mMesh.vertex( i ).z();
304 : 0 : ret.setValues( zValues );
305 : 0 : return ret;
306 : 0 : }
307 : :
308 : 0 : QgsMeshDataBlock QgsMeshZValueDataset::areFacesActive( int faceIndex, int count ) const
309 : : {
310 : : Q_UNUSED( faceIndex );
311 : : Q_UNUSED( count );
312 : 0 : QgsMeshDataBlock ret( QgsMeshDataBlock::ActiveFlagInteger, count );
313 : 0 : ret.setValid( true );
314 : 0 : return ret;
315 : 0 : }
316 : :
317 : 0 : bool QgsMeshZValueDataset::isActive( int faceIndex ) const
318 : : {
319 : 0 : return ( faceIndex > 0 && faceIndex < mMesh.faceCount() );
320 : : }
321 : :
322 : 0 : QgsMeshDatasetMetadata QgsMeshZValueDataset::metadata() const
323 : : {
324 : 0 : return QgsMeshDatasetMetadata( 0, true, mZMinimum, mZMaximum, 0 );
325 : : }
326 : :
327 : 0 : int QgsMeshZValueDataset::valuesCount() const
328 : : {
329 : 0 : return mMesh.vertexCount();
330 : : }
|