Skip to content

Commit 25dc834

Browse files
author
Grant Karapetyan
authored
Python binding improvements and fixes (#583)
* Python binding improvements and fixes * CR Fix and more decimation settings
1 parent 3644fac commit 25dc834

File tree

4 files changed

+60
-5
lines changed

4 files changed

+60
-5
lines changed

source/mrmeshpy/MRPythonBaseExposing.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,8 @@ MR_ADD_PYTHON_CUSTOM_DEF( mrmeshpy, EdgeId, [] ( pybind11::module_& m )
419419
def( "get", &MR::EdgeId::operator int );
420420
} )
421421

422+
MR_ADD_PYTHON_VEC( mrmeshpy, vectorUndirectedEdges, MR::UndirectedEdgeId )
423+
422424
MR_ADD_PYTHON_VEC( mrmeshpy, vectorEdges, MR::EdgeId )
423425

424426
MR_ADD_PYTHON_VEC( mrmeshpy, vectorVerts, MR::VertId )

source/mrmeshpy/MRPythonDecimate.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,31 @@
44

55
MR_ADD_PYTHON_CUSTOM_DEF( mrmeshpy, Decimate, [] ( pybind11::module_& m )
66
{
7+
pybind11::enum_<MR::DecimateStrategy>( m, "DecimateStrategy", "Defines the order of edge collapses inside Decimate algorithm" ).
8+
value( "MinimizeError", MR::DecimateStrategy::MinimizeError, "the next edge to collapse will be the one that introduced minimal error to the surface" ).
9+
value( "ShortestEdgeFirst", MR::DecimateStrategy::ShortestEdgeFirst, "the next edge to collapse will be the shortest one" );
10+
711
pybind11::class_<MR::DecimateSettings>( m, "DecimateSettings", "Parameters structure for decimateMesh" ).
812
def( pybind11::init<>() ).
9-
def_readwrite( "maxError", &MR::DecimateSettings::maxError, "stop the decimation as soon as the estimated distance deviation from the original mesh is more than this value" ). // only comment about default strategy
13+
def_readwrite( "strategy", &MR::DecimateSettings::strategy ).
14+
def_readwrite( "maxError", &MR::DecimateSettings::maxError,
15+
"for DecimateStrategy::MinimizeError:\n"
16+
"\tstop the decimation as soon as the estimated distance deviation from the original mesh is more than this value\n"
17+
"for DecimateStrategy::ShortestEdgeFirst only:\n"
18+
"\tstop the decimation as soon as the shortest edge in the mesh is greater than this value" ).
19+
def_readwrite( "maxEdgeLen", &MR::DecimateSettings::maxEdgeLen, "Edges longer than this value will not be collapsed (but they can appear after collapsing of shorter ones)" ).
1020
def_readwrite( "maxDeletedFaces", &MR::DecimateSettings::maxDeletedFaces, "Limit on the number of deleted faces" ).
1121
def_readwrite( "maxDeletedVertices", &MR::DecimateSettings::maxDeletedVertices, "Limit on the number of deleted vertices" ).
1222
def_readwrite( "maxTriangleAspectRatio", &MR::DecimateSettings::maxTriangleAspectRatio, "Maximal possible aspect ratio of a triangle introduced during decimation" ).
1323
def_readwrite( "stabilizer", &MR::DecimateSettings::stabilizer,
1424
"Small stabilizer is important to achieve good results on completely planar mesh parts,\n"
1525
"if your mesh is not-planer everywhere, then you can set it to zero" ).
16-
def_readwrite( "region", &MR::DecimateSettings::region, "Region on mesh to be decimated, it is updated during the operation" );
26+
def_readwrite("optimizeVertexPos",&MR::DecimateSettings::optimizeVertexPos,
27+
"if true then after each edge collapse the position of remaining vertex is optimized to\n"
28+
"minimize local shape change, if false then the edge is collapsed in one of its vertices, which keeps its position" ).
29+
def_readwrite( "region", &MR::DecimateSettings::region, "Region on mesh to be decimated, it is updated during the operation" ).
30+
def_readwrite( "touchBdVertices", &MR::DecimateSettings::touchBdVertices, "Whether to allow collapsing edges having at least one vertex on (region) boundary" ).
31+
def_readwrite( "packMesh", &MR::DecimateSettings::packMesh, "whether to pack mesh at the end" );
1732

1833
pybind11::class_<MR::DecimateResult>( m, "DecimateResult", "Results of decimateMesh" ).
1934
def( pybind11::init<>() ).

source/mrmeshpy/MRPythonIO.cpp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,36 @@ class PythonIstreamBuf : public std::streambuf
105105
std::streamsize size_;
106106
};
107107

108+
// Buffer that writes in Python instead of C++
109+
class PythonOstreamBuf : public std::stringbuf
110+
{
111+
public:
112+
PythonOstreamBuf( pybind11::object outFileHandle ) :
113+
pywrite_( outFileHandle.attr( "write" ) ),
114+
pyflush_( outFileHandle.attr( "flush" ) )
115+
{
116+
}
117+
~PythonOstreamBuf()
118+
{
119+
sync_();
120+
}
121+
int sync() override
122+
{
123+
sync_();
124+
return 0;
125+
}
126+
127+
private:
128+
pybind11::object pywrite_;
129+
pybind11::object pyflush_;
130+
void sync_()
131+
{
132+
pybind11::bytes bytes = pybind11::bytes( this->str() );
133+
pywrite_( bytes );
134+
pyflush_();
135+
}
136+
};
137+
108138
}
109139

110140
tl::expected<MR::Mesh, std::string> pythonLoadMeshFromAnyFormat( pybind11::object fileHandle, const std::string& extension )
@@ -120,7 +150,7 @@ tl::expected<void, std::string> pythonSaveMeshToAnyFormat( const Mesh& mesh, con
120150
{
121151
if ( !( pybind11::hasattr( fileHandle, "write" ) && pybind11::hasattr( fileHandle, "flush" ) ) )
122152
return tl::make_unexpected( "Argument is not file handle" );
123-
pybind11::detail::pythonbuf pybuf( fileHandle );
153+
PythonOstreamBuf pybuf( fileHandle );
124154
std::ostream outfs( &pybuf );
125155
return MR::MeshSave::toAnySupportedFormat( mesh, outfs, extension );
126156
}
@@ -129,7 +159,7 @@ tl::expected<void, std::string> pythonSaveLinesToAnyFormat( const MR::Polyline3&
129159
{
130160
if ( !( pybind11::hasattr( fileHandle, "write" ) && pybind11::hasattr( fileHandle, "flush" ) ) )
131161
return tl::make_unexpected( "Argument is not file handle" );
132-
pybind11::detail::pythonbuf pybuf( fileHandle );
162+
PythonOstreamBuf pybuf( fileHandle );
133163
std::ostream outfs( &pybuf );
134164
return MR::LinesSave::toAnySupportedFormat( lines, outfs, extension );
135165
}
@@ -147,7 +177,7 @@ tl::expected<void, std::string> pythonSavePointCloudToAnyFormat( const PointClou
147177
{
148178
if ( !( pybind11::hasattr( fileHandle, "write" ) && pybind11::hasattr( fileHandle, "flush" ) ) )
149179
return tl::make_unexpected( "Argument is not file handle" );
150-
pybind11::detail::pythonbuf pybuf( fileHandle );
180+
PythonOstreamBuf pybuf( fileHandle );
151181
std::ostream outfs( &pybuf );
152182
return MR::PointsSave::toAnySupportedFormat( points, outfs, extension );
153183
}

source/mrmeshpy/MRPythonMeshExposing.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ MR_ADD_PYTHON_CUSTOM_DEF( mrmeshpy, Vector, [] ( pybind11::module_& m )
8888
def( pybind11::init<>() ).
8989
def_readwrite( "vec", &MR::VertMap::vec_ );
9090

91+
pybind11::class_<MR::WholeEdgeMap>( m, "WholeEdgeMap" ).
92+
def( pybind11::init<>() ).
93+
def_readwrite( "vec", &MR::WholeEdgeMap::vec_ );
94+
95+
pybind11::class_<MR::UndirectedEdgeMap>( m, "UndirectedEdgeMap" ).
96+
def( pybind11::init<>() ).
97+
def_readwrite( "vec", &MR::UndirectedEdgeMap::vec_ );
98+
9199
pybind11::class_<MR::EdgeMap>( m, "EdgeMap" ).
92100
def( pybind11::init<>() ).
93101
def_readwrite( "vec", &MR::EdgeMap::vec_ );

0 commit comments

Comments
 (0)