|
2 | 2 | #include "MRBitSetParallelFor.h"
|
3 | 3 | #include "MREdgePaths.h"
|
4 | 4 | #include "MRExtractIsolines.h"
|
5 |
| -#include "MRGTest.h" |
6 | 5 | #include "MRLaplacian.h"
|
7 | 6 | #include "MRMesh.h"
|
8 |
| -#include "MRMeshBuilder.h" |
9 | 7 | #include "MRMeshComponents.h"
|
10 | 8 | #include "MRMeshPart.h"
|
11 | 9 | #include "MRGeodesicPath.h"
|
12 | 10 | #include "MRRegionBoundary.h"
|
13 | 11 | #include "MRRingIterator.h"
|
14 | 12 | #include "MRSurfaceDistance.h"
|
15 | 13 | #include "MRTimer.h"
|
| 14 | +#include "MRTriMath.h" |
16 | 15 |
|
17 | 16 | namespace MR
|
18 | 17 | {
|
19 | 18 |
|
20 |
| -// consider triangle 0bc, where a linear scalar field is defined in all vertices: v(0) = 0, v(b) = vb, v(c) = vc; |
21 |
| -// computes field gradient in the triangle |
22 |
| -static Vector3d computeGradient( const Vector3d & b, const Vector3d & c, double vb, double vc ) |
23 |
| -{ |
24 |
| - const auto bb = dot( b, b ); |
25 |
| - const auto bc = dot( b, c ); |
26 |
| - const auto cc = dot( c, c ); |
27 |
| - const auto det = bb * cc - bc * bc; |
28 |
| - if ( det <= 0 ) |
29 |
| - { |
30 |
| - // degenerate triangle |
31 |
| - return {}; |
32 |
| - } |
33 |
| - const auto kb = ( 1 / det ) * ( cc * vb - bc * vc ); |
34 |
| - const auto kc = ( 1 / det ) * (-bc * vb + bb * vc ); |
35 |
| - return kb * b + kc * c; |
36 |
| -} |
37 |
| - |
38 | 19 | static Vector3f computeGradient( const Vector3f & b, const Vector3f & c, float vb, float vc )
|
39 | 20 | {
|
40 |
| - return Vector3f{ computeGradient( Vector3d( b ), Vector3d( c ), double( vb ), double( vc ) ) }; |
| 21 | + return Vector3f{ gradientInTri( Vector3d( b ), Vector3d( c ), double( vb ), double( vc ) ) }; |
41 | 22 | }
|
42 | 23 |
|
43 | 24 | /// given triangle with scalar field increasing in the direction \param dir;
|
@@ -78,30 +59,6 @@ static bool computeEnter01Cross( const Triangle3f & t, const Vector3f & unitDir,
|
78 | 59 | return computeLineLineCross( t[0] - p, t[1] - p, unitDir, a );
|
79 | 60 | }
|
80 | 61 |
|
81 |
| -// consider triangle 0bc, where gradient is given; |
82 |
| -// computes the intersection of the ray (org=0, dir=-grad) with the open segment (b,c) |
83 |
| -static std::optional<float> computeExitPos( const Vector3f & b, const Vector3f & c, const Vector3f & grad ) |
84 |
| -{ |
85 |
| - const auto gradSq = grad.lengthSq(); |
86 |
| - if ( gradSq <= 0 ) |
87 |
| - return {}; |
88 |
| - const auto d = c - b; |
89 |
| - // gort is a vector in the triangle plane orthogonal to grad |
90 |
| - const auto gort = d - ( dot( d, grad ) / gradSq ) * grad; |
91 |
| - const auto god = dot( gort, d ); |
92 |
| - if ( god <= 0 ) |
93 |
| - return {}; |
94 |
| - const auto gob = -dot( gort, b ); |
95 |
| - if ( gob <= 0 || gob >= god ) |
96 |
| - return {}; |
97 |
| - const auto a = gob / god; |
98 |
| - assert( a < FLT_MAX ); |
99 |
| - const auto ip = a * c + ( 1 - a ) * b; |
100 |
| - if ( dot( grad, ip ) >= 0 ) |
101 |
| - return {}; // (b,c) is intersected in the direction +grad |
102 |
| - return a; |
103 |
| -} |
104 |
| - |
105 | 62 | MeshEdgePoint findSteepestDescentPoint( const MeshPart & mp, const VertScalars & field, VertId v )
|
106 | 63 | {
|
107 | 64 | assert( mp.mesh.topology.isInnerOrBdVertex( v, mp.region ) );
|
@@ -146,7 +103,7 @@ MeshEdgePoint findSteepestDescentPoint( const MeshPart & mp, const VertScalars &
|
146 | 103 | const auto triGradSq = triGrad.lengthSq();
|
147 | 104 | if ( triGradSq > maxGradSq )
|
148 | 105 | {
|
149 |
| - if ( auto a = computeExitPos( pd, px, triGrad ) ) |
| 106 | + if ( auto a = findTriExitPos( pd, px, triGrad ) ) |
150 | 107 | {
|
151 | 108 | maxGradSq = triGradSq;
|
152 | 109 | res = MeshEdgePoint{ eBd, *a };
|
@@ -694,78 +651,4 @@ Contours3f surfacePathsToContours3f( const Mesh & mesh, const SurfacePaths & lin
|
694 | 651 | return res;
|
695 | 652 | }
|
696 | 653 |
|
697 |
| -TEST(MRMesh, SurfacePath) |
698 |
| -{ |
699 |
| - Vector3f g; |
700 |
| - |
701 |
| - g = computeGradient( Vector3f{ 1, 0, 0 }, Vector3f{ 0.5f, 1, 0 }, 0, 1 ); |
702 |
| - EXPECT_NEAR( ( g - Vector3f{ 0, 1, 0 } ).length(), 0, 1e-5f ); |
703 |
| - |
704 |
| - g = computeGradient( Vector3f{ 1, 0, 0 }, Vector3f{ 0.1f, 1, 0 }, 0, 1 ); |
705 |
| - EXPECT_NEAR( ( g - Vector3f{ 0, 1, 0 } ).length(), 0, 1e-5f ); |
706 |
| - |
707 |
| - g = computeGradient( Vector3f{ 1, 0, 0 }, Vector3f{ 0.9f, 1, 0 }, 0, 1 ); |
708 |
| - EXPECT_NEAR( ( g - Vector3f{ 0, 1, 0 } ).length(), 0, 1e-5f ); |
709 |
| - |
710 |
| - std::optional<float> e; |
711 |
| - g = computeGradient( Vector3f{ 1, 0, 0 }, Vector3f{ 0, 1, 0 }, 1, 1 ); |
712 |
| - EXPECT_NEAR( ( g - Vector3f{ 1, 1, 0 } ).length(), 0, 1e-5f ); |
713 |
| - e = computeExitPos ( Vector3f{ 1, 0, 0 }, Vector3f{ 0, 1, 0 }, g ); |
714 |
| - EXPECT_FALSE( e.has_value() ); |
715 |
| - e = computeExitPos ( Vector3f{ 1, 0, 0 }, Vector3f{ 0, 1, 0 }, -g ); |
716 |
| - EXPECT_NEAR( *e, 0.5f, 1e-5f ); |
717 |
| - |
718 |
| - g = computeGradient( Vector3f{ 1, -1, 0 }, Vector3f{ 1, 1, 0 }, -1, -1 ); |
719 |
| - EXPECT_NEAR( ( g - Vector3f{ -1, 0, 0 } ).length(), 0, 1e-5f ); |
720 |
| - e = computeExitPos ( Vector3f{ 1, -1, 0 }, Vector3f{ 1, 1, 0 }, g ); |
721 |
| - EXPECT_NEAR( *e, 0.5f, 1e-5f ); |
722 |
| - e = computeExitPos ( Vector3f{ 1, -1, 0 }, Vector3f{ 1, 1, 0 }, -g ); |
723 |
| - EXPECT_FALSE( e.has_value() ); |
724 |
| - |
725 |
| - g = computeGradient( Vector3f{ 1, -0.1f, 0 }, Vector3f{ 1, 0.9f, 0 }, -1, -1 ); |
726 |
| - EXPECT_NEAR( ( g - Vector3f{ -1, 0, 0 } ).length(), 0, 1e-5f ); |
727 |
| - e = computeExitPos ( Vector3f{ 1, -0.1f, 0 }, Vector3f{ 1, 0.9f, 0 }, g ); |
728 |
| - EXPECT_NEAR( *e, 0.1f, 1e-5f ); |
729 |
| - |
730 |
| - g = computeGradient( Vector3f{ 1, -0.9f, 0 }, Vector3f{ 1, 0.1f, 0 }, -1, -1 ); |
731 |
| - EXPECT_NEAR( ( g - Vector3f{ -1, 0, 0 } ).length(), 0, 1e-5f ); |
732 |
| - e = computeExitPos ( Vector3f{ 1, -0.9f, 0 }, Vector3f{ 1, 0.1f, 0 }, g ); |
733 |
| - EXPECT_NEAR( *e, 0.9f, 1e-5f ); |
734 |
| - |
735 |
| - g = computeGradient( Vector3f{ 1, 0.1f, 0 }, Vector3f{ 1, 0.9f, 0 }, -1, -1 ); |
736 |
| - EXPECT_NEAR( ( g - Vector3f{ -1, 0, 0 } ).length(), 0, 1e-5f ); |
737 |
| - e = computeExitPos ( Vector3f{ 1, 0.1f, 0 }, Vector3f{ 1, 0.9f, 0 }, g ); |
738 |
| - EXPECT_FALSE( e.has_value() ); |
739 |
| - e = computeExitPos ( Vector3f{ 1, 0.1f, 0 }, Vector3f{ 1, 0.9f, 0 }, -g ); |
740 |
| - EXPECT_FALSE( e.has_value() ); |
741 |
| -} |
742 |
| - |
743 |
| -TEST( MRMesh, SurfacePathTargets ) |
744 |
| -{ |
745 |
| - Triangulation t{ |
746 |
| - { 0_v, 1_v, 2_v } |
747 |
| - }; |
748 |
| - Mesh mesh; |
749 |
| - mesh.topology = MeshBuilder::fromTriangles( t ); |
750 |
| - |
751 |
| - mesh.points.emplace_back( 0.f, 0.f, 0.f ); // 0_v |
752 |
| - mesh.points.emplace_back( 1.f, 0.f, 0.f ); // 1_v |
753 |
| - mesh.points.emplace_back( 0.f, 1.f, 0.f ); // 2_v |
754 |
| - |
755 |
| - VertBitSet starts(3); |
756 |
| - starts.set( 1_v ); |
757 |
| - starts.set( 2_v ); |
758 |
| - |
759 |
| - VertBitSet ends(3); |
760 |
| - ends.set( 0_v ); |
761 |
| - |
762 |
| - const auto map = computeClosestSurfacePathTargets( mesh, starts, ends ); |
763 |
| - EXPECT_EQ( map.size(), starts.count() ); |
764 |
| - for ( const auto & [start, end] : map ) |
765 |
| - { |
766 |
| - EXPECT_TRUE( starts.test( start ) ); |
767 |
| - EXPECT_TRUE( ends.test( end ) ); |
768 |
| - } |
769 |
| -} |
770 |
| - |
771 | 654 | } //namespace MR
|
0 commit comments