From fa5107a6c40582b111b0a47fd9ca950f154cde9c Mon Sep 17 00:00:00 2001 From: Fedor Chelnokov Date: Tue, 20 Oct 2026 22:43:41 +0300 Subject: [PATCH 1/4] Remove Vector( std::vector && ) constructor Code that built a std::vector only to convert it now builds the Vector type directly (VertCoords, FaceNormals, VertNormals) with typed-id indexing. Where the input really is a std::vector (delaunayTriangulationXY overload, 3mf palettes, offset volume parts, numpy), it is moved into the vec field. Co-Authored-By: Claude Opus 5.5 --- source/MRMesh/MRCylinder.cpp | 46 +++++++++---------- source/MRMesh/MRDelaunayTriangulationXY.cpp | 4 +- source/MRMesh/MRMakeSphereMesh.cpp | 20 ++++---- source/MRMesh/MRMeshLoad.cpp | 4 +- source/MRMesh/MRMeshNormals.cpp | 6 +-- source/MRMesh/MRMeshSave3mf.cpp | 4 +- source/MRMesh/MRSolidOfRevolution.cpp | 4 +- source/MRMesh/MRTorus.cpp | 48 ++++++++++---------- source/MRMesh/MRVector.h | 3 -- source/MRTest/MRContoursCutTests.cpp | 12 ++--- source/MRTest/MRFillContours2DTests.cpp | 2 +- source/MRTest/MRMeshBooleanTests.cpp | 4 +- source/MRVoxels/MROffset.cpp | 2 +- source/mrmeshnumpy/MRPythonNumpyExposing.cpp | 2 +- 14 files changed, 80 insertions(+), 81 deletions(-) diff --git a/source/MRMesh/MRCylinder.cpp b/source/MRMesh/MRCylinder.cpp index adaef5462e6e..79e47cbc5808 100644 --- a/source/MRMesh/MRCylinder.cpp +++ b/source/MRMesh/MRCylinder.cpp @@ -8,19 +8,19 @@ namespace MR Mesh makeCylinder( float radius, float length, int resolution ) { - std::vector points(2 * resolution + 2); + VertCoords points(2 * resolution + 2); auto step = 2.0f * PI_F / float(resolution); for (int h = 0; h < 2; ++h) { - points[h] = Vector3f(0.0f, 0.0f, float(h)*length); + points[VertId( h )] = Vector3f(0.0f, 0.0f, float(h)*length); for (int anglei = 0; anglei < resolution; ++anglei) { float angle = anglei * step; auto ind = anglei + resolution * h + 2; - points[ind].x = radius * cosf(angle); - points[ind].y = radius * sinf(angle); - points[ind].z = h * length; + points[VertId( ind )].x = radius * cosf(angle); + points[VertId( ind )].y = radius * sinf(angle); + points[VertId( ind )].z = h * length; } } @@ -40,7 +40,7 @@ Mesh makeCylinder( float radius, float length, int resolution ) Mesh makeOpenCylinder( float radius, float z1, float z2, int numCircleSegments ) { - std::vector points( 2 * numCircleSegments ); + VertCoords points( 2 * numCircleSegments ); for ( bool side : { false, true } ) { @@ -50,9 +50,9 @@ Mesh makeOpenCylinder( float radius, float z1, float z2, int numCircleSegments ) { float angle = i * 2 * PI_F / numCircleSegments; int index = i + numCircleSegments * side; - points[index].x = radius * std::cos( angle ); - points[index].y = radius * std::sin( angle ); - points[index].z = z; + points[VertId( index )].x = radius * std::cos( angle ); + points[VertId( index )].y = radius * std::sin( angle ); + points[VertId( index )].z = z; } } @@ -74,16 +74,16 @@ Mesh makeOpenCylinder( float radius, float z1, float z2, int numCircleSegments ) Mesh makeOpenCone( float radius, float zApex, float zBase, int numCircleSegments ) { - std::vector points( numCircleSegments + 1 ); + VertCoords points( numCircleSegments + 1 ); for ( int i = 0; i < numCircleSegments; ++i ) { float angle = i * 2 * PI_F / numCircleSegments; - points[i].x = radius * std::cos( angle ); - points[i].y = radius * std::sin( angle ); - points[i].z = zBase; + points[VertId( i )].x = radius * std::cos( angle ); + points[VertId( i )].y = radius * std::sin( angle ); + points[VertId( i )].z = zBase; } - points[numCircleSegments] = Vector3f( 0, 0, zApex ); + points[VertId( numCircleSegments )] = Vector3f( 0, 0, zApex ); Triangulation t; t.reserve( 2 * numCircleSegments ); @@ -127,28 +127,28 @@ Mesh makeCylinderAdvanced( float radius0, float radius1, float start_angle, slice = true; } - std::vector points(cap0 + cap1 + 2); + VertCoords points(cap0 + cap1 + 2); auto step = arc_size / float(resolution); int ver_id = 0; - points[ver_id++] = Vector3f(0.0f, 0.0f, 0.0f); - points[ver_id++] = Vector3f(0.0f, 0.0f, length); + points[VertId( ver_id++ )] = Vector3f(0.0f, 0.0f, 0.0f); + points[VertId( ver_id++ )] = Vector3f(0.0f, 0.0f, length); for (int anglei = 0; anglei < cap0; ++anglei) { float angle = start_angle + anglei * step; - points[ver_id].x = radius0 * cosf(angle); - points[ver_id].y = radius0 * sinf(angle); - points[ver_id].z = 0; + points[VertId( ver_id )].x = radius0 * cosf(angle); + points[VertId( ver_id )].y = radius0 * sinf(angle); + points[VertId( ver_id )].z = 0; ++ver_id; } for (int anglei = 0; anglei < cap1; ++anglei) { float angle = start_angle + anglei * step; - points[ver_id].x = radius1 * cosf(angle); - points[ver_id].y = radius1 * sinf(angle); - points[ver_id].z = length; + points[VertId( ver_id )].x = radius1 * cosf(angle); + points[VertId( ver_id )].y = radius1 * sinf(angle); + points[VertId( ver_id )].z = length; ++ver_id; } diff --git a/source/MRMesh/MRDelaunayTriangulationXY.cpp b/source/MRMesh/MRDelaunayTriangulationXY.cpp index edd1b9451d05..c88b51831780 100644 --- a/source/MRMesh/MRDelaunayTriangulationXY.cpp +++ b/source/MRMesh/MRDelaunayTriangulationXY.cpp @@ -389,7 +389,9 @@ static Expected delaunayTriangulationXY( VertCoords points, const VertBitS Expected delaunayTriangulationXY( std::vector points, const ProgressCallback& cb ) { - return delaunayTriangulationXY( VertCoords( std::move( points ) ), nullptr, cb ); + VertCoords vertCoords; + vertCoords.vec = std::move( points ); + return delaunayTriangulationXY( std::move( vertCoords ), nullptr, cb ); } Expected delaunayTriangulationXY( const PointCloud& cloud, const ProgressCallback& cb ) diff --git a/source/MRMesh/MRMakeSphereMesh.cpp b/source/MRMesh/MRMakeSphereMesh.cpp index 3d6c821c0bea..d0b3d9612c28 100644 --- a/source/MRMesh/MRMakeSphereMesh.cpp +++ b/source/MRMesh/MRMakeSphereMesh.cpp @@ -41,7 +41,7 @@ Mesh makeUVSphere(float radius, int horisontalResolution, int verticalResolution int vertexCount = horisontalResolution * verticalResolution + 2; - std::vector points(vertexCount); + VertCoords points(vertexCount); k = 0; for (j = 0; j < verticalResolution; ++j) { @@ -49,22 +49,22 @@ Mesh makeUVSphere(float radius, int horisontalResolution, int verticalResolution for (i = 0; i < horisontalResolution; ++i) { b = 2 * i * PI_F / horisontalResolution; - points[k].x = (float)(radius * cos(a) * sin(b)); - points[k].y = (float)(radius * cos(a) * cos(b)); - points[k].z = (float)(radius * sin(a)); + points[VertId( k )].x = (float)(radius * cos(a) * sin(b)); + points[VertId( k )].y = (float)(radius * cos(a) * cos(b)); + points[VertId( k )].z = (float)(radius * sin(a)); ++k; } } - points[k].x = 0; - points[k].y = 0; - points[k].z = -radius; + points[VertId( k )].x = 0; + points[VertId( k )].y = 0; + points[VertId( k )].z = -radius; bottom_cap = k; ++k; - points[k].x = 0; - points[k].y = 0; - points[k].z = radius; + points[VertId( k )].x = 0; + points[VertId( k )].y = 0; + points[VertId( k )].z = radius; top_cap = k; Triangulation t; diff --git a/source/MRMesh/MRMeshLoad.cpp b/source/MRMesh/MRMeshLoad.cpp index e1b9920360da..00b1989be798 100644 --- a/source/MRMesh/MRMeshLoad.cpp +++ b/source/MRMesh/MRMeshLoad.cpp @@ -458,7 +458,7 @@ Expected fromOff( std::istream& in, const MeshLoadSettings& settings /*= { } } - std::vector pointsBlocks( numPoints ); + VertCoords pointsBlocks( numPoints ); std::atomic forseStop = false; bool keepGoing = ParallelFor( pointsBlocks, [&] ( size_t numPoint ) @@ -472,7 +472,7 @@ Expected fromOff( std::istream& in, const MeshLoadSettings& settings /*= { const std::string_view line( &buf[splitLines[numLine]], splitLines[numLine + 1] - splitLines[numLine] ); Vector3d temp; auto result = parseTextCoordinate( line, temp ); - pointsBlocks[numPoint] = Vector3f( temp ); + pointsBlocks[VertId( numPoint )] = Vector3f( temp ); if ( !result.has_value() ) { diff --git a/source/MRMesh/MRMeshNormals.cpp b/source/MRMesh/MRMeshNormals.cpp index 3c55c5fb33b4..87da20393adc 100644 --- a/source/MRMesh/MRMeshNormals.cpp +++ b/source/MRMesh/MRMeshNormals.cpp @@ -19,7 +19,7 @@ FaceNormals computePerFaceNormals( const Mesh & mesh ) FaceNormals computePerFaceNormals( const MeshTopology & topology, const VertCoords & points ) { MR_TIMER; - std::vector res( topology.faceSize() ); + FaceNormals res( topology.faceSize() ); BitSetParallelFor( topology.getValidFaces(), [&]( FaceId f ) { res[f] = normal( topology, points, f ); @@ -43,7 +43,7 @@ void computePerFaceNormals4( const Mesh & mesh, Vector4f* faceNormals, size_t si VertNormals computePerVertNormals( const Mesh & mesh ) { MR_TIMER; - std::vector res( mesh.topology.vertSize() ); + VertNormals res( mesh.topology.vertSize() ); BitSetParallelFor( mesh.topology.getValidVerts(), [&] ( VertId v ) { res[v] = mesh.normal( v ); @@ -54,7 +54,7 @@ VertNormals computePerVertNormals( const Mesh & mesh ) VertNormals computePerVertPseudoNormals( const Mesh & mesh ) { MR_TIMER; - std::vector res( mesh.topology.vertSize() ); + VertNormals res( mesh.topology.vertSize() ); BitSetParallelFor( mesh.topology.getValidVerts(), [&] ( VertId v ) { res[v] = mesh.pseudonormal( v ); diff --git a/source/MRMesh/MRMeshSave3mf.cpp b/source/MRMesh/MRMeshSave3mf.cpp index e97979da7268..6c74b720320e 100644 --- a/source/MRMesh/MRMeshSave3mf.cpp +++ b/source/MRMesh/MRMeshSave3mf.cpp @@ -59,7 +59,7 @@ template Vector makePalette( const Vector& colors, const TypedBitSet& validColors, std::ostream& out ) { Vector res; - res = makePalette( colors.vec, validColors, out ); + res.vec = makePalette( colors.vec, validColors, out ); return res; } @@ -104,7 +104,7 @@ Expected toModel3mf( const Mesh & mesh, std::ostream & out, const SaveSett } else if ( savePrimColors ) { - facePalette = makePalette( *settings.primitiveColors, mesh.topology.getValidFaces(), out ); + facePalette.vec = makePalette( *settings.primitiveColors, mesh.topology.getValidFaces(), out ); out << " \n"; } else if ( settings.solidColor ) diff --git a/source/MRMesh/MRSolidOfRevolution.cpp b/source/MRMesh/MRSolidOfRevolution.cpp index 1902bf7c708e..e0ce6ab65a3f 100644 --- a/source/MRMesh/MRSolidOfRevolution.cpp +++ b/source/MRMesh/MRSolidOfRevolution.cpp @@ -11,14 +11,14 @@ Mesh makeSolidOfRevolution( const Contour2f& profile, int resolution ) const auto isClosed = ( profile.front() == profile.back() ); const auto profileSize = profile.size() - int( isClosed ); - std::vector points( profileSize * resolution ); + VertCoords points( profileSize * resolution ); ParallelFor( points, [&] ( size_t index ) { const auto angle = 2.f * PI_F * (float)( index / profileSize ) / (float)resolution; const auto x = std::cos( angle ), y = std::sin( angle ); const auto& pp = profile[index % profileSize]; - points[index] = { + points[VertId( index )] = { pp.x * x, pp.x * y, pp.y, diff --git a/source/MRMesh/MRTorus.cpp b/source/MRMesh/MRTorus.cpp index d54b6f576ad1..1f7b1a5fa479 100644 --- a/source/MRMesh/MRTorus.cpp +++ b/source/MRMesh/MRTorus.cpp @@ -13,7 +13,7 @@ MR::Mesh makeTorus( float primaryRadius, float secondaryRadius, int primaryResol float a, b; int vertexCount = primaryResolution * secondaryResolution; - std::vector points( vertexCount ); + VertCoords points( vertexCount ); bool pSet = false; if ( pointsOut ) pointsOut->resize( primaryResolution ); @@ -25,9 +25,9 @@ MR::Mesh makeTorus( float primaryRadius, float secondaryRadius, int primaryResol { b = 2 * j * PI_F / primaryResolution; - points[k].x = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::cos( b ); - points[k].y = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::sin( b ); - points[k].z = secondaryRadius * std::sin( a ); + points[VertId( k )].x = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::cos( b ); + points[VertId( k )].y = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::sin( b ); + points[VertId( k )].z = secondaryRadius * std::sin( a ); ++k; if ( pointsOut && !pSet ) ( *pointsOut )[j] = {primaryRadius * std::cos( b ),primaryRadius * std::sin( b ),0.0f}; @@ -65,7 +65,7 @@ MR::Mesh makeOuterHalfTorus( float primaryRadius, float secondaryRadius, int pri float a, b; int vertexCount = primaryResolution * secondaryResolution; - std::vector points( vertexCount ); + VertCoords points( vertexCount ); bool pSet = false; if ( pointsOut ) pointsOut->resize( primaryResolution ); @@ -77,9 +77,9 @@ MR::Mesh makeOuterHalfTorus( float primaryRadius, float secondaryRadius, int pri { b = 2 * j * PI_F / primaryResolution; - points[k].x = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::cos( b ); - points[k].y = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::sin( b ); - points[k].z = secondaryRadius * std::sin( a ); + points[VertId( k )].x = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::cos( b ); + points[VertId( k )].y = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::sin( b ); + points[VertId( k )].z = secondaryRadius * std::sin( a ); ++k; if ( pointsOut && !pSet ) ( *pointsOut )[j] = {primaryRadius * std::cos( b ),primaryRadius * std::sin( b ),0.0f}; @@ -118,7 +118,7 @@ MR::Mesh makeTorusWithUndercut( float primaryRadius, float secondaryRadiusInner, float a, b; int vertexCount = primaryResolution * secondaryResolution; - std::vector points( vertexCount ); + VertCoords points( vertexCount ); bool pSet = false; if ( pointsOut ) pointsOut->resize( primaryResolution ); @@ -132,9 +132,9 @@ MR::Mesh makeTorusWithUndercut( float primaryRadius, float secondaryRadiusInner, { b = 2 * j * PI_F / primaryResolution; - points[k].x = ( primaryRadius - secRadius * std::cos( a ) ) * std::cos( b ); - points[k].y = ( primaryRadius - secRadius * std::cos( a ) ) * std::sin( b ); - points[k].z = ( sina > 0.f ? secRadius : -secRadius ) * sina; + points[VertId( k )].x = ( primaryRadius - secRadius * std::cos( a ) ) * std::cos( b ); + points[VertId( k )].y = ( primaryRadius - secRadius * std::cos( a ) ) * std::sin( b ); + points[VertId( k )].z = ( sina > 0.f ? secRadius : -secRadius ) * sina; ++k; if ( pointsOut && !pSet ) ( *pointsOut )[j] = {primaryRadius * std::cos( b ),primaryRadius * std::sin( b ),0.0f}; @@ -175,7 +175,7 @@ MR::Mesh makeTorusWithSpikes( float primaryRadius, float secondaryRadiusInner, f const int spikeFreq = 23; int vertexCount = primaryResolution * secondaryResolution; - std::vector points( vertexCount ); + VertCoords points( vertexCount ); bool pSet = false; if ( pointsOut ) pointsOut->resize( primaryResolution ); @@ -188,9 +188,9 @@ MR::Mesh makeTorusWithSpikes( float primaryRadius, float secondaryRadiusInner, f bool isSpike = ( ( i * secondaryResolution + j ) % spikeFreq == 0 ); b = 2 * j * PI_F / primaryResolution; - points[k].x = ( primaryRadius - ( isSpike ? secondaryRadiusOuter : secondaryRadiusInner ) * std::cos( a ) ) * std::cos( b ); - points[k].y = ( primaryRadius - ( isSpike ? secondaryRadiusOuter : secondaryRadiusInner ) * std::cos( a ) ) * std::sin( b ); - points[k].z = ( isSpike ? secondaryRadiusOuter : secondaryRadiusInner ) * std::sin( a ); + points[VertId( k )].x = ( primaryRadius - ( isSpike ? secondaryRadiusOuter : secondaryRadiusInner ) * std::cos( a ) ) * std::cos( b ); + points[VertId( k )].y = ( primaryRadius - ( isSpike ? secondaryRadiusOuter : secondaryRadiusInner ) * std::cos( a ) ) * std::sin( b ); + points[VertId( k )].z = ( isSpike ? secondaryRadiusOuter : secondaryRadiusInner ) * std::sin( a ); ++k; if ( pointsOut && !pSet ) ( *pointsOut )[j] = {primaryRadius * std::cos( b ),primaryRadius * std::sin( b ),0.0f}; @@ -229,7 +229,7 @@ MR::Mesh makeTorusWithComponents( float primaryRadius, float secondaryRadius, in float a, b; int vertexCount = primaryResolution * secondaryResolution; - std::vector points( vertexCount ); + VertCoords points( vertexCount ); bool pSet = false; if ( pointsOut ) pointsOut->resize( primaryResolution ); @@ -241,9 +241,9 @@ MR::Mesh makeTorusWithComponents( float primaryRadius, float secondaryRadius, in { b = 2 * j * PI_F / primaryResolution; - points[k].x = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::cos( b ); - points[k].y = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::sin( b ); - points[k].z = secondaryRadius * std::sin( a ); + points[VertId( k )].x = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::cos( b ); + points[VertId( k )].y = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::sin( b ); + points[VertId( k )].z = secondaryRadius * std::sin( a ); ++k; if ( pointsOut && !pSet ) ( *pointsOut )[j] = {primaryRadius * std::cos( b ),primaryRadius * std::sin( b ),0.0f}; @@ -282,7 +282,7 @@ MR::Mesh makeTorusWithSelfIntersections( float primaryRadius, float secondaryRad float a, b; int vertexCount = primaryResolution * secondaryResolution; - std::vector points( vertexCount ); + VertCoords points( vertexCount ); bool pSet = false; if ( pointsOut ) pointsOut->resize( primaryResolution ); @@ -294,9 +294,9 @@ MR::Mesh makeTorusWithSelfIntersections( float primaryRadius, float secondaryRad { b = 2 * j * PI_F / primaryResolution; - points[k].x = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::cos( b ); - points[k].y = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::sin( b ); - points[k].z = secondaryRadius * std::sin( 2.f * a ); + points[VertId( k )].x = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::cos( b ); + points[VertId( k )].y = ( primaryRadius - secondaryRadius * std::cos( a ) ) * std::sin( b ); + points[VertId( k )].z = secondaryRadius * std::sin( 2.f * a ); ++k; if ( pointsOut && !pSet ) ( *pointsOut )[j] = {primaryRadius * std::cos( b ),primaryRadius * std::sin( b ),0.0f}; diff --git a/source/MRMesh/MRVector.h b/source/MRMesh/MRVector.h index cc5d7a859e25..0fddfd6bf0de 100644 --- a/source/MRMesh/MRVector.h +++ b/source/MRMesh/MRVector.h @@ -34,9 +34,6 @@ class Vector /// creates a vector with \p size elements with the given value MR_BIND_OVERLOAD_SUFFIX(fill) explicit Vector( size_t size, const T & val ) : vec( size, val ) { } - /// moves data from the given std::vector - MR_BIND_OVERLOAD_SUFFIX(stdVector) Vector( std::vector && v ) : vec( std::move( v ) ) { } - template< class InputIt > Vector( InputIt first, InputIt last ) : vec( first, last ) { } diff --git a/source/MRTest/MRContoursCutTests.cpp b/source/MRTest/MRContoursCutTests.cpp index 44a02b7c337f..ed26d6275880 100644 --- a/source/MRTest/MRContoursCutTests.cpp +++ b/source/MRTest/MRContoursCutTests.cpp @@ -85,7 +85,7 @@ int checkOffsetContoursAndCut( const Mesh& mesh, const OneMeshContours& contours // the path from the last point back to the first one is empty, and the first path crosses the edge exactly at the last point TEST( MRMesh, ClosedContourWithEmptyWrapAroundPath ) { - std::vector points; + VertCoords points; Triangulation t; for ( int y = 0; y < 6; ++y ) for ( int x = 0; x < 6; ++x ) @@ -141,7 +141,7 @@ TEST( MRMesh, ClosedContourWithEmptyWrapAroundPath ) TEST( MRMesh, BooleanIntersectionsSort ) { Mesh meshA; - meshA.points = std::vector + meshA.points = VertCoords { { 8.95297337f, 14.3548975f,-0.212119192f }, { 8.98828983f, 14.3914976f,-0.198161319f }, @@ -156,7 +156,7 @@ TEST( MRMesh, BooleanIntersectionsSort ) meshA.topology = MeshBuilder::fromTriangles( tA ); Mesh meshB; - meshB.points = std::vector + meshB.points = VertCoords { { 8.91892719f, 14.3419390f, -0.208497435f }, { 8.99423218f, 14.4023476f, -0.208966389f }, @@ -195,7 +195,7 @@ TEST( MRMesh, BooleanIntersectionsSort ) TEST( MRMesh, ClosedContourAlongBoundaryEdge ) { Mesh mesh; - mesh.points = std::vector{ { 0, 0, 0 }, { 1, 0, 0.3f }, { 0, 1, 0 }, { 1, 1, 0.3f } }; + mesh.points = VertCoords{ { 0, 0, 0 }, { 1, 0, 0.3f }, { 0, 1, 0 }, { 1, 1, 0.3f } }; mesh.topology = MeshBuilder::fromTriangles( Triangulation{ { 0_v, 1_v, 2_v }, { 1_v, 3_v, 2_v } } ); std::vector mtps; @@ -592,7 +592,7 @@ TEST( MRMesh, MeshCollidePrecise ) // new vertices of the cut get ids from vertSize(), so invalid trailing vertices must not change the offset TEST( MRMesh, SurfaceOffsetWithInvalidTrailingVerts ) { - std::vector points; + VertCoords points; Triangulation t; for ( int y = 0; y < 6; ++y ) for ( int x = 0; x < 6; ++x ) @@ -668,7 +668,7 @@ TEST( MRMesh, SurfaceOffsetAlongOpenBorder ) { // 20x20 squares on [-10,10]^2 with alternating diagonals; the faces inside a wavy disk are kept const int n = 21; - std::vector points; + VertCoords points; for ( int y = 0; y < n; ++y ) for ( int x = 0; x < n; ++x ) points.emplace_back( float( x - 10 ), float( y - 10 ), 0.0f ); diff --git a/source/MRTest/MRFillContours2DTests.cpp b/source/MRTest/MRFillContours2DTests.cpp index b1aacc1e5196..46f84aaf9e17 100644 --- a/source/MRTest/MRFillContours2DTests.cpp +++ b/source/MRTest/MRFillContours2DTests.cpp @@ -277,7 +277,7 @@ TEST( MRMesh, triangulateDisjointContoursPinchedLoop ) TEST( MRMesh, cutMeshAlongBoundaryFillsSpikedHoles ) { Mesh mesh; - mesh.points = std::vector + mesh.points = VertCoords { { 3.09503722f, -0.014356399f, 0.0114405388f }, { 3.43319631f, 0.0118827643f, -0.0905694813f }, diff --git a/source/MRTest/MRMeshBooleanTests.cpp b/source/MRTest/MRMeshBooleanTests.cpp index 3c855b6b5019..75150604733f 100644 --- a/source/MRTest/MRMeshBooleanTests.cpp +++ b/source/MRTest/MRMeshBooleanTests.cpp @@ -108,7 +108,7 @@ static Mesh makeWedge( float length, float halfWidth, float halfAngle ) { const float h = length * std::tan( halfAngle ); Mesh res; - res.points = std::vector{ + res.points = VertCoords{ { 0.f, -halfWidth, 0.f }, { 0.f, halfWidth, 0.f }, { -length, -halfWidth, h }, { -length, halfWidth, h }, { -length, -halfWidth, -h }, { -length, halfWidth, -h } }; @@ -147,7 +147,7 @@ TEST( MRMesh, BooleanDisjointMeshes ) static Mesh makeMeshWithMultipleEdge() { Mesh res; - res.points = std::vector + res.points = VertCoords { {0.0f,0.0f,0.0f}, {-0.5f,1.0f,0.0f}, diff --git a/source/MRVoxels/MROffset.cpp b/source/MRVoxels/MROffset.cpp index 425cb1b46731..930104bb6c7e 100644 --- a/source/MRVoxels/MROffset.cpp +++ b/source/MRVoxels/MROffset.cpp @@ -207,10 +207,10 @@ Expected mcOffsetMesh( const MeshPart& mp, float offset, assert( data.size() <= (size_t)dims.x * dims.y * dims.z ); assert( zOffset == mesher.nextZ() ); SimpleVolume res { - .data = std::move( data ), .dims = dims, .voxelSize = vol.voxelSize, }; + res.data.vec = std::move( data ); return mesher.addPart( res ); }; return diff --git a/source/mrmeshnumpy/MRPythonNumpyExposing.cpp b/source/mrmeshnumpy/MRPythonNumpyExposing.cpp index 8a67368c8916..747b28f98dbb 100644 --- a/source/mrmeshnumpy/MRPythonNumpyExposing.cpp +++ b/source/mrmeshnumpy/MRPythonNumpyExposing.cpp @@ -100,7 +100,7 @@ MR::Mesh fromFV( const pybind11::buffer& faces, const pybind11::buffer& verts, c // verts to points part MR::VertCoords points; - points = fromNumpyArrayInfo( infoVerts ); + points.vec = fromNumpyArrayInfo( infoVerts ); if ( duplicateNonManifoldVertices ) return MR::Mesh::fromTrianglesDuplicatingNonManifoldVertices( std::move( points ), t, nullptr, settings ); else From 7ccb07f32742d4aa2b8db96b55dfa743799efee1 Mon Sep 17 00:00:00 2001 From: Fedor Chelnokov Date: Tue, 20 Oct 2026 22:55:16 +0300 Subject: [PATCH 2/4] mrmeshnumpy: move numpy points/normals into vec Co-Authored-By: Claude Opus 5.5 --- source/mrmeshnumpy/MRPythonNumpyExposing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/mrmeshnumpy/MRPythonNumpyExposing.cpp b/source/mrmeshnumpy/MRPythonNumpyExposing.cpp index 747b28f98dbb..6f3a3200c1d8 100644 --- a/source/mrmeshnumpy/MRPythonNumpyExposing.cpp +++ b/source/mrmeshnumpy/MRPythonNumpyExposing.cpp @@ -260,9 +260,9 @@ MR::PointCloud pointCloudFromNP( const pybind11::buffer& points, const pybind11: MR::PointCloud res; // verts to points part - res.points = fromNumpyArrayInfo( infoPoints ); + res.points.vec = fromNumpyArrayInfo( infoPoints ); if ( infoNormals.size > 0 ) - res.normals = fromNumpyArrayInfo( infoNormals ); + res.normals.vec = fromNumpyArrayInfo( infoNormals ); res.validPoints = MR::VertBitSet( res.points.size() ); res.validPoints.flip(); From 5d4c45e76e7ecbb4cb549646787d2149b723edc2 Mon Sep 17 00:00:00 2001 From: Fedor Chelnokov Date: Tue, 20 Oct 2026 23:10:13 +0300 Subject: [PATCH 3/4] GlobalRegistration Python example: fill Vector_MeshOrPointsXf_ObjId directly The list-to-Vector conversion went through the removed constructor. Co-Authored-By: Claude Opus 5.5 --- examples/python-examples/GlobalRegistration.dox.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/python-examples/GlobalRegistration.dox.py b/examples/python-examples/GlobalRegistration.dox.py index 27e3e62fcdb7..b5128cd82dc4 100644 --- a/examples/python-examples/GlobalRegistration.dox.py +++ b/examples/python-examples/GlobalRegistration.dox.py @@ -26,7 +26,7 @@ def main(argv): # the global registration can be applied to meshes and point clouds # to simplify the sample app, we will work with point clouds only input_clouds_num = len(file_args) - 1 - inputs = [] + inputs = mrmeshpy.Vector_MeshOrPointsXf_ObjId() # as ICP and MultiwayICP classes accept both meshes and point clouds, # the input data must be converted to special wrapper objects # NB: the wrapper objects hold *references* to the source data, NOT their copies @@ -34,7 +34,7 @@ def main(argv): for i in range(input_clouds_num): points = mrmeshpy.loadPoints(file_args[i]) # you may also set an affine transformation for each input as a second argument - inputs.append(mrmeshpy.MeshOrPointsXf(points, mrmeshpy.AffineXf3f())) + inputs.push_back(mrmeshpy.MeshOrPointsXf(points, mrmeshpy.AffineXf3f())) bbox = points.getBoundingBox() if not max_bbox or bbox.volume() > max_bbox.volume(): @@ -45,7 +45,7 @@ def main(argv): # set sampling voxel size sampling_params.samplingVoxelSize = max_bbox.diagonal() * 0.03 - icp = mrmeshpy.MultiwayICP(mrmeshpy.Vector_MeshOrPointsXf_ObjId(inputs), sampling_params) + icp = mrmeshpy.MultiwayICP(inputs, sampling_params) icp.setParams(mrmeshpy.ICPProperties()) # gather statistics @@ -59,7 +59,7 @@ def main(argv): output = mrmeshpy.PointCloud() for i in range(input_clouds_num): xf = xfs.vec[i] - for point in inputs[i].obj.points(): + for point in inputs.vec[i].obj.points(): output.addPoint(xf(point)) mrmeshpy.PointsSave.toAnySupportedFormat(output, file_args[-1]) From bc13d755a3c429383574f21df68a18f1f0626d47 Mon Sep 17 00:00:00 2001 From: Fedor Chelnokov Date: Tue, 20 Oct 2026 23:45:08 +0300 Subject: [PATCH 4/4] C# ICP test: fill Vector_MRMeshOrPointsXf_MRObjId directly Co-Authored-By: Claude Opus 5.5 --- source/MRDotNet2Test/src/ICPTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/MRDotNet2Test/src/ICPTests.cs b/source/MRDotNet2Test/src/ICPTests.cs index 490e4e0fabb7..e0152e7a27a3 100644 --- a/source/MRDotNet2Test/src/ICPTests.cs +++ b/source/MRDotNet2Test/src/ICPTests.cs @@ -12,23 +12,23 @@ internal class ICPTests [Test] public void TestMultiwayICP() { - var inputs = new Std.Vector_MRMeshOrPointsXf(); + var inputs = new Vector_MRMeshOrPointsXf_MRObjId(); Box3f maxBBox = new Box3f(); inputs.pushBack( new MeshOrPointsXf(makeSphere(new SphereParams(1.0f, 1000)), new AffineXf3f())); - Box3f bbox = inputs[0].obj.getObjBoundingBox(); + Box3f bbox = inputs[new ObjId(0)].obj.getObjBoundingBox(); if (!maxBBox.valid() || bbox.volume() > maxBBox.volume()) maxBBox = bbox; inputs.pushBack(new MeshOrPointsXf(makeSphere(new SphereParams(1.0f, 1000)), AffineXf3f.linear(Matrix3f.rotation(Vector3f.plusZ(), 0.1f)))); - bbox = inputs[1].obj.getObjBoundingBox(); + bbox = inputs[new ObjId(1)].obj.getObjBoundingBox(); if (!maxBBox.valid() || bbox.volume() > maxBBox.volume()) maxBBox = bbox; MultiwayICPSamplingParameters samplingParams = new MultiwayICPSamplingParameters(); samplingParams.samplingVoxelSize = maxBBox.diagonal() * 0.03f; - MultiwayICP icp = new MultiwayICP(new Vector_MRMeshOrPointsXf_MRObjId(Misc.Move(inputs)), samplingParams); + MultiwayICP icp = new MultiwayICP(inputs, samplingParams); ICPProperties iCPProperties = new ICPProperties(); icp.setParams(iCPProperties); icp.updateAllPointPairs();