@@ -354,62 +354,38 @@ QgsMesh3dDataBlock QgsMeshLayer::dataset3dValue( const QgsMeshDatasetIndex &inde
354
354
QgsMeshDatasetValue QgsMeshLayer::dataset1dValue ( const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius ) const
355
355
{
356
356
QgsMeshDatasetValue value;
357
- QgsRectangle searchRectangle ( point.x () - searchRadius, point.y () - searchRadius, point.x () + searchRadius, point.y () + searchRadius );
357
+ QgsPointXY projectedPoint;
358
+ int selectedIndex = closestEdge ( point, searchRadius, projectedPoint );
358
359
const QgsTriangularMesh *mesh = triangularMesh ();
359
- if ( mesh &&
360
- mesh->contains ( QgsMesh::Edge ) &&
361
- mDataProvider ->isValid () &&
362
- index.isValid () )
360
+ if ( selectedIndex >= 0 )
363
361
{
364
- // search for the closest edge in rectangle from point
365
- const QList<int > edgeIndexes = mesh->edgeIndexesForRectangle ( searchRectangle );
366
- int selectedIndex = -1 ;
367
- double sqrMaxDistFromPoint = pow ( searchRadius, 2 );
368
- QgsPointXY projectedPoint;
369
- for ( const int edgeIndex : edgeIndexes )
362
+ const QgsMeshDatasetGroupMetadata::DataType dataType = dataProvider ()->datasetGroupMetadata ( index ).dataType ();
363
+ switch ( dataType )
370
364
{
371
- const QgsMeshEdge &edge = mesh->edges ().at ( edgeIndex );
372
- const QgsMeshVertex &vertex1 = mesh->vertices ()[edge.first ];
373
- const QgsMeshVertex &vertex2 = mesh->vertices ()[edge.second ];
374
- QgsPointXY projPoint;
375
- double sqrDist = point.sqrDistToSegment ( vertex1.x (), vertex1.y (), vertex2.x (), vertex2.y (), projPoint );
376
- if ( sqrDist < sqrMaxDistFromPoint )
365
+ case QgsMeshDatasetGroupMetadata::DataOnEdges:
377
366
{
378
- selectedIndex = edgeIndex;
379
- projectedPoint = projPoint;
380
- sqrMaxDistFromPoint = sqrDist;
367
+ value = dataProvider ()->datasetValue ( index, selectedIndex );
381
368
}
382
- }
369
+ break ;
383
370
384
- if ( selectedIndex >= 0 )
385
- {
386
- const QgsMeshDatasetGroupMetadata::DataType dataType = dataProvider ()->datasetGroupMetadata ( index ).dataType ();
387
- switch ( dataType )
371
+ case QgsMeshDatasetGroupMetadata::DataOnVertices:
388
372
{
389
- case QgsMeshDatasetGroupMetadata::DataOnEdges:
390
- {
391
- value = dataProvider ()->datasetValue ( index, selectedIndex );
392
- }
393
- break ;
394
-
395
- case QgsMeshDatasetGroupMetadata::DataOnVertices:
396
- {
397
- const QgsMeshEdge &edge = mesh->edges ()[selectedIndex];
398
- const int v1 = edge.first , v2 = edge.second ;
399
- const QgsPoint p1 = mesh->vertices ()[v1], p2 = mesh->vertices ()[v2];
400
- const QgsMeshDatasetValue val1 = dataProvider ()->datasetValue ( index, v1 );
401
- const QgsMeshDatasetValue val2 = dataProvider ()->datasetValue ( index, v2 );
402
- double edgeLength = p1.distance ( p2 );
403
- double dist1 = p1.distance ( projectedPoint.x (), projectedPoint.y () );
404
- value = QgsMeshLayerUtils::interpolateFromVerticesData ( dist1 / edgeLength, val1, val2 );
405
- }
406
- break ;
407
- default :
408
- break ;
373
+ const QgsMeshEdge &edge = mesh->edges ()[selectedIndex];
374
+ const int v1 = edge.first , v2 = edge.second ;
375
+ const QgsPoint p1 = mesh->vertices ()[v1], p2 = mesh->vertices ()[v2];
376
+ const QgsMeshDatasetValue val1 = dataProvider ()->datasetValue ( index, v1 );
377
+ const QgsMeshDatasetValue val2 = dataProvider ()->datasetValue ( index, v2 );
378
+ double edgeLength = p1.distance ( p2 );
379
+ double dist1 = p1.distance ( projectedPoint.x (), projectedPoint.y () );
380
+ value = QgsMeshLayerUtils::interpolateFromVerticesData ( dist1 / edgeLength, val1, val2 );
409
381
}
382
+ break ;
383
+ default :
384
+ break ;
410
385
}
411
386
}
412
387
388
+
413
389
return value;
414
390
}
415
391
@@ -471,6 +447,37 @@ void QgsMeshLayer::onDatasetGroupsAdded( int count )
471
447
472
448
}
473
449
450
+ int QgsMeshLayer::closestEdge ( const QgsPointXY &point, double searchRadius, QgsPointXY &projectedPoint ) const
451
+ {
452
+ QgsRectangle searchRectangle ( point.x () - searchRadius, point.y () - searchRadius, point.x () + searchRadius, point.y () + searchRadius );
453
+ const QgsTriangularMesh *mesh = triangularMesh ();
454
+ // search for the closest edge in search area from point
455
+ const QList<int > edgeIndexes = mesh->edgeIndexesForRectangle ( searchRectangle );
456
+ int selectedIndex = -1 ;
457
+ if ( mesh &&
458
+ mesh->contains ( QgsMesh::Edge ) &&
459
+ mDataProvider ->isValid () )
460
+ {
461
+ double sqrMaxDistFromPoint = pow ( searchRadius, 2 );
462
+ for ( const int edgeIndex : edgeIndexes )
463
+ {
464
+ const QgsMeshEdge &edge = mesh->edges ().at ( edgeIndex );
465
+ const QgsMeshVertex &vertex1 = mesh->vertices ()[edge.first ];
466
+ const QgsMeshVertex &vertex2 = mesh->vertices ()[edge.second ];
467
+ QgsPointXY projPoint;
468
+ double sqrDist = point.sqrDistToSegment ( vertex1.x (), vertex1.y (), vertex2.x (), vertex2.y (), projPoint );
469
+ if ( sqrDist < sqrMaxDistFromPoint )
470
+ {
471
+ selectedIndex = edgeIndex;
472
+ projectedPoint = projPoint;
473
+ sqrMaxDistFromPoint = sqrDist;
474
+ }
475
+ }
476
+ }
477
+
478
+ return selectedIndex;
479
+ }
480
+
474
481
QgsMeshDatasetIndex QgsMeshLayer::staticVectorDatasetIndex () const
475
482
{
476
483
return mStaticVectorDatasetIndex ;
@@ -484,6 +491,106 @@ void QgsMeshLayer::setReferenceTime( const QDateTime &referenceTime )
484
491
temporalProperties ()->setReferenceTime ( referenceTime, nullptr );
485
492
}
486
493
494
+ QgsPointXY QgsMeshLayer::snapOnVertex ( const QgsPointXY &point, double searchRadius )
495
+ {
496
+ const QgsTriangularMesh *mesh = triangularMesh ();
497
+ QgsPointXY exactPosition;
498
+ if ( !mesh )
499
+ return exactPosition;
500
+ QgsRectangle rectangle ( point.x () - searchRadius, point.y () - searchRadius, point.x () + searchRadius, point.y () + searchRadius );
501
+ double maxDistance = searchRadius;
502
+ // attempt to snap on edges's vertices
503
+ QList<int > edgeIndexes = mesh->edgeIndexesForRectangle ( rectangle );
504
+ for ( const int edgeIndex : edgeIndexes )
505
+ {
506
+ const QgsMeshEdge &edge = mesh->edges ().at ( edgeIndex );
507
+ const QgsMeshVertex &vertex1 = mesh->vertices ()[edge.first ];
508
+ const QgsMeshVertex &vertex2 = mesh->vertices ()[edge.second ];
509
+ double dist1 = point.distance ( vertex1 );
510
+ double dist2 = point.distance ( vertex2 );
511
+ if ( dist1 < maxDistance )
512
+ {
513
+ maxDistance = dist1;
514
+ exactPosition = vertex1;
515
+ }
516
+ if ( dist2 < maxDistance )
517
+ {
518
+ maxDistance = dist2;
519
+ exactPosition = vertex2;
520
+ }
521
+ }
522
+
523
+ // attempt to snap on face's vertices
524
+ QList<int > faceIndexes = mesh->faceIndexesForRectangle ( rectangle );
525
+ for ( const int faceIndex : faceIndexes )
526
+ {
527
+ const QgsMeshFace &face = mesh->triangles ().at ( faceIndex );
528
+ for ( int i = 0 ; i < 3 ; ++i )
529
+ {
530
+ const QgsMeshVertex &vertex = mesh->vertices ()[face.at ( i )];
531
+ double dist = point.distance ( vertex );
532
+ if ( dist < maxDistance )
533
+ {
534
+ maxDistance = dist;
535
+ exactPosition = vertex;
536
+ }
537
+ }
538
+ }
539
+
540
+ return exactPosition;
541
+ }
542
+
543
+ QgsPointXY QgsMeshLayer::snapOnEdge ( const QgsPointXY &point, double searchRadius )
544
+ {
545
+ QgsPointXY projectedPoint;
546
+ closestEdge ( point, searchRadius, projectedPoint );
547
+
548
+ return projectedPoint;
549
+ }
550
+
551
+ QgsPointXY QgsMeshLayer::snapOnFace ( const QgsPointXY &point, double searchRadius )
552
+ {
553
+ const QgsTriangularMesh *mesh = triangularMesh ();
554
+ QgsPointXY centroidPosition;
555
+ if ( !mesh )
556
+ return centroidPosition;
557
+ QgsRectangle rectangle ( point.x () - searchRadius, point.y () - searchRadius, point.x () + searchRadius, point.y () + searchRadius );
558
+ double maxDistance = std::numeric_limits<double >::max ();
559
+
560
+ QList<int > faceIndexes = mesh->faceIndexesForRectangle ( rectangle );
561
+ for ( const int faceIndex : faceIndexes )
562
+ {
563
+ int nativefaceIndex = mesh->trianglesToNativeFaces ().at ( faceIndex );
564
+ if ( nativefaceIndex < 0 && nativefaceIndex >= mesh->faceCentroids ().count () )
565
+ continue ;
566
+ const QgsPointXY centroid = mesh->faceCentroids ()[nativefaceIndex];
567
+ double dist = point.distance ( centroid );
568
+ if ( dist < maxDistance )
569
+ {
570
+ maxDistance = dist;
571
+ centroidPosition = centroid;
572
+ }
573
+ }
574
+
575
+ return centroidPosition;
576
+ }
577
+
578
+ QgsPointXY QgsMeshLayer::snapOnElement ( QgsMesh::ElementType elementType, const QgsPointXY &point, double searchRadius )
579
+ {
580
+ switch ( elementType )
581
+ {
582
+ case QgsMesh::Vertex:
583
+ return snapOnVertex ( point, searchRadius );
584
+ break ;
585
+ case QgsMesh::Edge:
586
+ return snapOnEdge ( point, searchRadius );
587
+ break ;
588
+ case QgsMesh::Face:
589
+ return snapOnFace ( point, searchRadius );
590
+ break ;
591
+ }
592
+ }
593
+
487
594
QgsMeshDatasetIndex QgsMeshLayer::staticScalarDatasetIndex () const
488
595
{
489
596
return mStaticScalarDatasetIndex ;
0 commit comments