Skip to content

Commit 8124a62

Browse files
author
Grant Karapetyan
authored
update reduce noise (#132)
1 parent 9f0aa87 commit 8124a62

File tree

2 files changed

+52
-39
lines changed

2 files changed

+52
-39
lines changed

source/MRMesh/MRMeshRelax.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -120,43 +120,46 @@ void relaxApprox( Mesh& mesh, const MeshApproxRelaxParams params )
120120
dilateRegion( mesh, neighbors, surfaceRadius );
121121

122122
PointAccumulator accum;
123-
Vector3d centroid;
124123
int count = 0;
125124
for ( auto newV : neighbors )
126125
{
127126
Vector3d ptD = Vector3d( mesh.points[newV] );
128-
centroid += ptD;
129127
accum.addPoint( ptD );
130128
++count;
131129
}
132130
if ( count < 6 )
133131
return;
134132

135133
auto& np = newPoints[v];
136-
centroid /= double( count );
134+
137135
Vector3f target;
138-
auto plane = accum.getBestPlane();
139136
if ( params.type == RelaxApproxType::Planar )
140-
{
141-
target = Plane3f( plane ).project( np );
142-
}
137+
target = accum.getBestPlanef().project( np );
143138
else if ( params.type == RelaxApproxType::Quadric )
144139
{
145-
AffineXf3d basis;
146-
basis.A.z = plane.n.normalized();
147-
auto [x, y] = basis.A.z.perpendicular();
148-
basis.A.x = x;
149-
basis.A.y = y;
140+
AffineXf3d basis = accum.getBasicXf();
141+
basis.A = basis.A.transposed();
142+
std::swap( basis.A.x, basis.A.y );
143+
std::swap( basis.A.y, basis.A.z );
150144
basis.A = basis.A.transposed();
151-
basis.b = Vector3d( np );
152145
auto basisInv = basis.inverse();
146+
153147
QuadricApprox approxAccum;
154148
for ( auto newV : neighbors )
155149
approxAccum.addPoint( basisInv( Vector3d( mesh.points[newV] ) ) );
156-
auto res = QuadricApprox::findZeroProjection( approxAccum.calcBestCoefficients() );
157-
target = Vector3f( basis( res ) );
150+
151+
auto centerPoint = basisInv( Vector3d( mesh.points[v] ) );
152+
const auto coefs = approxAccum.calcBestCoefficients();
153+
centerPoint.z =
154+
coefs[0] * centerPoint.x * centerPoint.x +
155+
coefs[1] * centerPoint.x * centerPoint.y +
156+
coefs[2] * centerPoint.y * centerPoint.y +
157+
coefs[3] * centerPoint.x +
158+
coefs[4] * centerPoint.y +
159+
coefs[5];
160+
target = Vector3f( basis( centerPoint ) );
158161
}
159-
np += ( params.force * ( 0.5f * target + Vector3f( 0.5 * centroid ) - np ) );
162+
np += ( params.force * ( target - np ) );
160163
} );
161164
mesh.points.swap( newPoints );
162165
}

source/MRMesh/MRPointCloudRelax.cpp

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -119,50 +119,60 @@ void relaxApprox( PointCloud& pointCloud, const PointCloudApproxRelaxParams& par
119119
float radius = params.neighborhoodRadius > 0.0f ? params.neighborhoodRadius :
120120
pointCloud.getBoundingBox().diagonal() * 0.1f;
121121

122+
bool hasNormals = pointCloud.normals.size() > size_t( pointCloud.validPoints.find_last() );
123+
122124
for ( int i = 0; i < params.iterations; ++i )
123125
{
124126
newPoints = pointCloud.points;
125127
BitSetParallelFor( zone, [&] ( VertId v )
126128
{
127129
PointAccumulator accum;
128-
std::vector<VertId> neighbors;
129-
Vector3d centroid;
130+
std::vector<std::pair<VertId, double>> weightedNeighbors;
131+
130132
findPointsInBall( pointCloud, pointCloud.points[v], radius,
131133
[&] ( VertId newV, const Vector3f& position )
132134
{
133-
Vector3d ptD = Vector3d( position );
134-
centroid += ptD;
135-
accum.addPoint( ptD );
136-
neighbors.push_back( newV );
135+
double w = 1.0;
136+
if ( hasNormals )
137+
w = dot( pointCloud.normals[v], pointCloud.normals[newV] );
138+
if ( w > 0.0 )
139+
{
140+
weightedNeighbors.push_back( { newV,w } );
141+
accum.addPoint( Vector3d( position ), w );
142+
}
137143
} );
138-
if ( neighbors.size() < 6 )
144+
if ( weightedNeighbors.size() < 6 )
139145
return;
140146

141-
centroid /= double( neighbors.size() );
142147
auto& np = newPoints[v];
143148
Vector3f target;
144-
auto plane = accum.getBestPlane();
145149
if ( params.type == RelaxApproxType::Planar )
146-
{
147-
target = Plane3f( plane ).project( np );
148-
}
150+
target = accum.getBestPlanef().project( np );
149151
else if ( params.type == RelaxApproxType::Quadric )
150152
{
151-
AffineXf3d basis;
152-
basis.A.z = plane.n.normalized();
153-
auto [x, y] = basis.A.z.perpendicular();
154-
basis.A.x = x;
155-
basis.A.y = y;
153+
AffineXf3d basis = accum.getBasicXf();
154+
basis.A = basis.A.transposed();
155+
std::swap( basis.A.x, basis.A.y );
156+
std::swap( basis.A.y, basis.A.z );
156157
basis.A = basis.A.transposed();
157-
basis.b = Vector3d( np );
158158
auto basisInv = basis.inverse();
159+
159160
QuadricApprox approxAccum;
160-
for ( auto newV : neighbors )
161-
approxAccum.addPoint( basisInv( Vector3d( pointCloud.points[newV] ) ) );
162-
auto res = QuadricApprox::findZeroProjection( approxAccum.calcBestCoefficients() );
163-
target = Vector3f( basis( res ) );
161+
for ( auto [newV, w] : weightedNeighbors )
162+
approxAccum.addPoint( basisInv( Vector3d( pointCloud.points[newV] ) ), w );
163+
164+
auto centerPoint = basisInv( Vector3d( pointCloud.points[v] ) );
165+
const auto coefs = approxAccum.calcBestCoefficients();
166+
centerPoint.z =
167+
coefs[0] * centerPoint.x * centerPoint.x +
168+
coefs[1] * centerPoint.x * centerPoint.y +
169+
coefs[2] * centerPoint.y * centerPoint.y +
170+
coefs[3] * centerPoint.x +
171+
coefs[4] * centerPoint.y +
172+
coefs[5];
173+
target = Vector3f( basis( centerPoint ) );
164174
}
165-
np += ( params.force * ( 0.5f * target + Vector3f( 0.5 * centroid ) - np ) );
175+
np += ( params.force * ( target - np ) );
166176
} );
167177
pointCloud.points.swap( newPoints );
168178
pointCloud.invalidateCaches();

0 commit comments

Comments
 (0)