Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions source/MRMesh/MRMesh.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@
<ClInclude Include="MRVoxelsVolume.h" />
<ClInclude Include="MRWriter.h" />
<ClInclude Include="MRXfBasedCache.h" />
<ClInclude Include="MRPolylineRelax.h" />
<ClInclude Include="MRRelaxParams.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="MR2DContoursTriangulation.cpp" />
Expand Down Expand Up @@ -459,6 +461,7 @@
<ClCompile Include="MRVDBConversions.cpp" />
<ClCompile Include="MRObjectDistanceMap.cpp" />
<ClCompile Include="MRVoxelsVolume.cpp" />
<ClCompile Include="MRPolylineRelax.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MRPch\MRPch.vcxproj">
Expand Down
13 changes: 11 additions & 2 deletions source/MRMesh/MRMesh.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@
<Filter>Source Files\AABBTree</Filter>
</ClInclude>
<ClInclude Include="MRPointCloudRelax.h">
<Filter>Source Files\PointCloud</Filter>
<Filter>Source Files\Relax</Filter>
</ClInclude>
<ClInclude Include="MRBestFitQuadric.h">
<Filter>Source Files\Math</Filter>
Expand Down Expand Up @@ -733,7 +733,7 @@
<Filter>Source Files\Mesh</Filter>
</ClInclude>
<ClInclude Include="MRMeshRelax.h">
<Filter>Source Files\MeshAlgorithm</Filter>
<Filter>Source Files\Relax</Filter>
</ClInclude>
<ClInclude Include="MRMeshToPointCloud.h">
<Filter>Source Files\MeshAlgorithm</Filter>
Expand Down Expand Up @@ -843,6 +843,12 @@
<ClInclude Include="MRChangePolylineAction.h">
<Filter>Source Files\History</Filter>
</ClInclude>
<ClInclude Include="MRPolylineRelax.h">
<Filter>Source Files\Relax</Filter>
</ClInclude>
<ClInclude Include="MRRelaxParams.h">
<Filter>Source Files\Relax</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="MRId.cpp">
Expand Down Expand Up @@ -1427,6 +1433,9 @@
<ClCompile Include="MRPolylineSubdivide.cpp">
<Filter>Source Files\Polyline</Filter>
</ClCompile>
<ClCompile Include="MRPolylineRelax.cpp">
<Filter>Source Files\Polyline</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\.editorconfig" />
Expand Down
17 changes: 1 addition & 16 deletions source/MRMesh/MRMeshRelax.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#include "MRMeshFwd.h"
#include "MRProgressCallback.h"
#include "MRRelaxParams.h"

namespace MR
{
Expand All @@ -9,16 +10,6 @@ namespace MR
/// \ingroup MeshAlgorithmGroup
/// \{

struct RelaxParams
{
/// number of iterations
int iterations{ 1 };
/// region to relax
const VertBitSet* region{ nullptr };
/// speed of relaxing, typical values (0.0, 0.5]
float force{ 0.5f };
};

struct MeshRelaxParams : RelaxParams
{
/// smooth tetrahedron verts (with complete three edges ring) to base triangle (based on its edges destinations)
Expand All @@ -34,12 +25,6 @@ MRMESH_API bool relax( Mesh& mesh, const MeshRelaxParams& params = {}, ProgressC
/// \return true if was finished successfully, false if was interrupted by progress callback
MRMESH_API bool relaxKeepVolume( Mesh& mesh, const MeshRelaxParams& params = {}, ProgressCallback cb = {} );

enum class RelaxApproxType
{
Planar,
Quadric
};

struct MeshApproxRelaxParams : MeshRelaxParams
{
/// radius to find neighbors by surface
Expand Down
3 changes: 2 additions & 1 deletion source/MRMesh/MRPointCloudRelax.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#include "MRMeshFwd.h"
#include "MRMeshRelax.h"
#include "MRProgressCallback.h"
#include "MRRelaxParams.h"

namespace MR
{
Expand Down
130 changes: 130 additions & 0 deletions source/MRMesh/MRPolylineRelax.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#include "MRPolylineRelax.h"
#include "MRBitSetParallelFor.h"
#include "MRPolyline.h"
#include "MRTimer.h"
#include "MRVector2.h"
#include "MRWriter.h"

namespace MR
{

template<typename V>
bool relax( Polyline<V> &polyline, const RelaxParams &params, ProgressCallback cb )
{
if ( params.iterations <= 0 )
return true;

MR_TIMER
MR_WRITER(polyline)

Vector<V, VertId> newPoints;
const auto& zone = polyline.topology.getVertIds( params.region );

bool keepGoing = true;
for ( int i = 0; i < params.iterations; ++i )
{
ProgressCallback internalCb;
if ( cb )
{
internalCb = [&]( float p )
{
return cb(( float( i ) + p ) / float( params.iterations ));
};
}

newPoints = polyline.points;
keepGoing = BitSetParallelFor( zone, [&]( VertId v )
{
auto e0 = polyline.topology.edgeWithOrg( v );
assert( !polyline.topology.isLoneEdge( e0 ) );
auto e1 = polyline.topology.next( e0 );
if ( e0 == e1 )
return;

auto mp = ( polyline.destPnt( e0 ) + polyline.destPnt( e1 ) ) / 2.f;

auto& np = newPoints[v];
auto pushForce = params.force * ( mp - np );
np += pushForce;
}, internalCb );
polyline.points.swap( newPoints );
if ( !keepGoing )
break;
}
return keepGoing;
}

template<typename V>
bool relaxKeepArea( Polyline<V> &polyline, const RelaxParams &params, ProgressCallback cb )
{
if ( params.iterations <= 0 )
return true;

MR_TIMER
MR_WRITER(polyline)

Vector<V, VertId> newPoints;
const auto& zone = polyline.topology.getVertIds( params.region );
std::vector<V> vertPushForces( zone.size() );

bool keepGoing = true;
for ( int i = 0; i < params.iterations; ++i )
{
ProgressCallback internalCb1, internalCb2;
if ( cb )
{
internalCb1 = [&] ( float p )
{
return cb( ( float( i ) + p * 0.5f ) / float( params.iterations ) );
};
internalCb2 = [&] ( float p )
{
return cb( ( float( i ) + p * 0.5f + 0.5f ) / float( params.iterations ) );
};
}

keepGoing = BitSetParallelFor( zone, [&]( VertId v )
{
auto e0 = polyline.topology.edgeWithOrg( v );
assert( !polyline.topology.isLoneEdge( e0 ) );
auto e1 = polyline.topology.next( e0 );
if ( e0 == e1 )
return;

auto mp = ( polyline.destPnt( e0 ) + polyline.destPnt( e1 ) ) / 2.f;

vertPushForces[v] = params.force * ( mp - polyline.points[v] );
}, internalCb1 );
if ( !keepGoing )
break;

newPoints = polyline.points;
keepGoing = BitSetParallelFor( zone, [&]( VertId v )
{
auto e0 = polyline.topology.edgeWithOrg( v );
assert( !polyline.topology.isLoneEdge( e0 ) );
auto e1 = polyline.topology.next( e0 );
if ( e0 == e1 )
return;

auto& np = newPoints[v];
np += vertPushForces[v];
auto modifier = 1.0f / 2.0f;
np -= ( vertPushForces[polyline.topology.dest( e0 )] * modifier );
np -= ( vertPushForces[polyline.topology.dest( e1 )] * modifier );
}, internalCb2 );
polyline.points.swap( newPoints );
if ( !keepGoing )
break;
}

return keepGoing;
}

template bool relax<>( Polyline2& polyline, const RelaxParams& params, ProgressCallback cb );
template bool relax<>( Polyline3& polyline, const RelaxParams& params, ProgressCallback cb );

template bool relaxKeepArea<>( Polyline2 &polyline, const RelaxParams &params, ProgressCallback cb );
template bool relaxKeepArea<>( Polyline3 &polyline, const RelaxParams &params, ProgressCallback cb );

} // namespace MR
25 changes: 25 additions & 0 deletions source/MRMesh/MRPolylineRelax.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once
#include "MRMeshFwd.h"
#include "MRProgressCallback.h"
#include "MRRelaxParams.h"

namespace MR
{

/// \addtogroup PolylineGroup
/// \{

/// applies given number of relaxation iterations to the whole polyline ( or some region if it is specified )
/// \return true if was finished successfully, false if was interrupted by progress callback
template<typename V>
MRMESH_API bool relax( Polyline<V>& polyline, const RelaxParams& params = {}, ProgressCallback cb = {} );

/// applies given number of relaxation iterations to the whole polyline ( or some region if it is specified )
/// do not really keeps area but tries hard
/// \return true if was finished successfully, false if was interrupted by progress callback
template<typename V>
MRMESH_API bool relaxKeepArea( Polyline<V>& polyline, const RelaxParams& params = {}, ProgressCallback cb = {} );

/// \}

} // namespace MR
23 changes: 23 additions & 0 deletions source/MRMesh/MRRelaxParams.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once
#include "MRMeshFwd.h"

namespace MR
{

struct RelaxParams
{
/// number of iterations
int iterations{1};
/// region to relax
const VertBitSet *region{nullptr};
/// speed of relaxing, typical values (0.0, 0.5]
float force{0.5f};
};

enum class RelaxApproxType
{
Planar,
Quadric,
};

} // namespace MR