Skip to content

Commit 0195899

Browse files
MeshAlgo::segment : Reimplement using MeshSplitter
1 parent bf2040e commit 0195899

File tree

3 files changed

+58
-34
lines changed

3 files changed

+58
-34
lines changed

include/IECoreScene/MeshAlgo.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ class IECORESCENE_API MeshSplitter
157157
/// If segmentValues isn't supplied then primitive is split into the unique values contained in the primitiveVariable.
158158
/// The primitiveVariable must have 'Uniform' iterpolation and match the base type of the VectorTypedData in the segmentValues.
159159
/// Specifying the two parameters segmentValues & primitiveVariable allows for a subset of meshes to be created, rather than
160-
/// completely segmenting the mesh based on the unique values in a primitive variable.
160+
/// completely segmenting the mesh based on the unique values in a primitive variable. If one of the values specified by
161+
/// segmentValues does not occur in the primitiveVariable, the corresponding mesh will be a nullptr.
161162
IECORESCENE_API std::vector<MeshPrimitivePtr> segment( const MeshPrimitive *mesh, const PrimitiveVariable &primitiveVariable, const IECore::Data *segmentValues = nullptr, const IECore::Canceller *canceller = nullptr );
162163

163164
/// Merge the input meshes into a single mesh.

src/IECoreScene/MeshAlgoSegment.cpp

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,48 +34,67 @@
3434

3535
#include "boost/format.hpp"
3636

37-
#include "IECore/DespatchTypedData.h"
3837
#include "IECore/DataAlgo.h"
3938

40-
4139
#include "IECoreScene/MeshAlgo.h"
4240
#include "IECoreScene/private/PrimitiveAlgoUtils.h"
4341

44-
4542
using namespace Imath;
4643
using namespace IECore;
4744
using namespace IECoreScene;
4845

49-
5046
std::vector<MeshPrimitivePtr> IECoreScene::MeshAlgo::segment( const MeshPrimitive *mesh, const PrimitiveVariable &primitiveVariable, const IECore::Data *segmentValues, const Canceller *canceller )
5147
{
48+
MeshSplitter ms( mesh, primitiveVariable, canceller );
49+
int numMeshes = ms.numMeshes();
50+
std::vector<MeshPrimitivePtr> ret;
51+
ret.reserve( numMeshes );
5252

53-
DataPtr data;
5453
if( !segmentValues )
5554
{
56-
Canceller::check( canceller );
57-
data = IECore::uniqueValues( primitiveVariable.data.get() );
58-
segmentValues = data.get();
59-
}
60-
61-
Canceller::check( canceller );
62-
std::string primitiveVariableName;
63-
for (const auto &pv : mesh->variables )
64-
{
65-
if ( pv.second == primitiveVariable )
55+
for( int i = 0; i < numMeshes; i++ )
6656
{
67-
primitiveVariableName = pv.first;
57+
ret.push_back( ms.mesh( i ) );
6858
}
6959
}
70-
71-
if( primitiveVariableName == "" )
60+
else
7261
{
73-
throw IECore::InvalidArgumentException( "IECoreScene::MeshAlgo::segment : Primitive variable not found on Mesh Primitive " );
74-
}
62+
IECore::dispatch( segmentValues,
63+
[ ms, numMeshes, &ret, canceller ]( auto *typedSegmentValues )
64+
{
65+
using DataType = typename std::remove_pointer_t< decltype( typedSegmentValues ) >;
66+
if constexpr ( TypeTraits::IsVectorTypedData<DataType>::value )
67+
{
68+
using ElementType = typename DataType::ValueType::value_type;
7569

76-
auto f = MeshAlgo::deleteFaces;
70+
std::unordered_map< ElementType, int > idMap;
71+
Canceller::check( canceller );
72+
for( int i = 0; i < numMeshes; i++ )
73+
{
74+
idMap[ ms.value<ElementType>( i ) ] = i;
75+
}
7776

78-
IECoreScene::Detail::TaskSegmenter<IECoreScene::MeshPrimitive, decltype(f) > taskSegmenter( mesh, const_cast<IECore::Data*> (segmentValues), primitiveVariableName, f, canceller );
77+
Canceller::check( canceller );
78+
for( const auto &i : typedSegmentValues->readable() )
79+
{
80+
auto f = idMap.find( i );
81+
if( f == idMap.end() )
82+
{
83+
ret.push_back( nullptr );
84+
}
85+
else
86+
{
87+
ret.push_back( ms.mesh( idMap[i] ) );
88+
}
89+
}
90+
}
91+
else
92+
{
93+
throw IECore::Exception( "Invalid Primitive Variable with non-vector typed data." );
94+
}
95+
}
96+
);
97+
}
7998

80-
return dispatch( primitiveVariable.data.get(), taskSegmenter );
99+
return ret;
81100
}

test/IECoreScene/MeshAlgoSegmentTest.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ def testCanSegmentUsingIntegerPrimvar( self ) :
6666
p12 = imath.V3f( 1, 2, 0 )
6767
p22 = imath.V3f( 2, 2, 0 )
6868

69-
self.assertEqual( segments[0]["P"].data, IECore.V3fVectorData( [p00, p10, p20, p01, p11, p21], IECore.GeometricData.Interpretation.Point ) )
70-
self.assertEqual( segments[1]["P"].data, IECore.V3fVectorData( [p01, p11, p21, p02, p12, p22], IECore.GeometricData.Interpretation.Point ) )
69+
self.assertEqual( segments[0]["P"].data, IECore.V3fVectorData( [p00, p10, p11, p01, p20, p21], IECore.GeometricData.Interpretation.Point ) )
70+
self.assertEqual( segments[1]["P"].data, IECore.V3fVectorData( [p01, p11, p12, p02, p21, p22], IECore.GeometricData.Interpretation.Point ) )
7171

7272
def testCanSegmentUsingStringPrimvar( self ) :
7373
mesh = IECoreScene.MeshPrimitive.createPlane( imath.Box2f( imath.V2f( 0 ), imath.V2f( 2 ) ), imath.V2i( 2 ) )
@@ -95,8 +95,8 @@ def testCanSegmentUsingStringPrimvar( self ) :
9595
p12 = imath.V3f( 1, 2, 0 )
9696
p22 = imath.V3f( 2, 2, 0 )
9797

98-
self.assertEqual( segments[0]["P"].data, IECore.V3fVectorData( [p00, p10, p01, p11, p21, p12, p22], IECore.GeometricData.Interpretation.Point ) )
99-
self.assertEqual( segments[1]["P"].data, IECore.V3fVectorData( [p10, p20, p01, p11, p21, p02, p12], IECore.GeometricData.Interpretation.Point ) )
98+
self.assertEqual( segments[0]["P"].data, IECore.V3fVectorData( [p00, p10, p11, p01, p21, p22, p12], IECore.GeometricData.Interpretation.Point ) )
99+
self.assertEqual( segments[1]["P"].data, IECore.V3fVectorData( [p10, p20, p21, p11, p01, p12, p02], IECore.GeometricData.Interpretation.Point ) )
100100

101101
def testSegmentsFullyIfNoSegmentValuesGiven( self ) :
102102
mesh = IECoreScene.MeshPrimitive.createPlane( imath.Box2f( imath.V2f( 0 ), imath.V2f( 2 ) ), imath.V2i( 2 ) )
@@ -130,8 +130,8 @@ def testSegmentsFullyIfNoSegmentValuesGiven( self ) :
130130
s0 = segments[1]
131131
s1 = segments[0]
132132

133-
self.assertEqual( s0["P"].data, IECore.V3fVectorData( [p00, p10, p01, p11, p21, p12, p22], IECore.GeometricData.Interpretation.Point ) )
134-
self.assertEqual( s1["P"].data, IECore.V3fVectorData( [p10, p20, p01, p11, p21, p02, p12], IECore.GeometricData.Interpretation.Point ) )
133+
self.assertEqual( s0["P"].data, IECore.V3fVectorData( [p00, p10, p11, p01, p21, p22, p12], IECore.GeometricData.Interpretation.Point ) )
134+
self.assertEqual( s1["P"].data, IECore.V3fVectorData( [p10, p20, p21, p11, p01, p12, p02], IECore.GeometricData.Interpretation.Point ) )
135135

136136

137137
def testRaisesExceptionIfSegmentKeysNotSameTypeAsPrimvar( self ) :
@@ -146,7 +146,11 @@ def t() :
146146

147147
self.assertRaises( RuntimeError, t )
148148

149-
def testEmptyPrimitiveIfNotMatching( self ) :
149+
def testNullPrimitiveIfNotMatching( self ) :
150+
151+
# Now that we've reimplemented on top of MeshSplitter, this has now changed from the old version
152+
# of segment. We now return a null pointer for primitive variable values that don't exist, instead
153+
# of a mesh with zero faces
150154
mesh = IECoreScene.MeshPrimitive.createPlane( imath.Box2f( imath.V2f( 0 ), imath.V2f( 2 ) ), imath.V2i( 2 ) )
151155

152156
mesh["s"] = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Uniform, IECore.StringVectorData( ["a", "b", "a", "b"] ) )
@@ -156,8 +160,8 @@ def testEmptyPrimitiveIfNotMatching( self ) :
156160

157161
self.assertEqual( len( segments ), 2 )
158162

159-
self.assertEqual( segments[0]["P"].data, IECore.V3fVectorData( [], IECore.GeometricData.Interpretation.Point ) )
160-
self.assertEqual( segments[1]["P"].data, IECore.V3fVectorData( [], IECore.GeometricData.Interpretation.Point ) )
163+
self.assertTrue( segments[0] is None )
164+
self.assertTrue( segments[1] is None )
161165

162166
def testSegmentSubset( self ) :
163167
mesh = IECoreScene.MeshPrimitive.createPlane( imath.Box2f( imath.V2f( 0 ), imath.V2f( 2 ) ), imath.V2i( 2 ) )
@@ -180,7 +184,7 @@ def testSegmentSubset( self ) :
180184
p22 = imath.V3f( 2, 2, 0 )
181185

182186
self.assertEqual( len( segments ), 1 )
183-
self.assertEqual( segments[0]["P"].data, IECore.V3fVectorData( [p11, p21, p12, p22], IECore.GeometricData.Interpretation.Point ) )
187+
self.assertEqual( segments[0]["P"].data, IECore.V3fVectorData( [p11, p21, p22, p12], IECore.GeometricData.Interpretation.Point ) )
184188
self.assertEqual( segments[0]["s"].data, IECore.StringVectorData( ["b"] ) )
185189

186190

0 commit comments

Comments
 (0)