Skip to content

Commit

Permalink
DeletePoints : Add support for id lists.
Browse files Browse the repository at this point in the history
  • Loading branch information
danieldresser-ie committed Oct 23, 2024
1 parent 4c601ac commit 0b26a3a
Show file tree
Hide file tree
Showing 5 changed files with 382 additions and 17 deletions.
19 changes: 19 additions & 0 deletions include/GafferScene/DeletePoints.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,31 @@ class GAFFERSCENE_API DeletePoints : public Deformer

public :

enum class SelectionMode
{
VertexPrimitiveVariable,
IdListPrimitiveVariable,
IdList
};

explicit DeletePoints( const std::string &name = defaultName<DeletePoints>() );
~DeletePoints() override;

Gaffer::IntPlug *selectionModePlug();
const Gaffer::IntPlug *selectionModePlug() const;

Gaffer::StringPlug *pointsPlug();
const Gaffer::StringPlug *pointsPlug() const;

Gaffer::StringPlug *idListVariablePlug();
const Gaffer::StringPlug *idListVariablePlug() const;

Gaffer::Int64VectorDataPlug *idListPlug();
const Gaffer::Int64VectorDataPlug *idListPlug() const;

Gaffer::StringPlug *idPlug();
const Gaffer::StringPlug *idPlug() const;

Gaffer::BoolPlug *invertPlug();
const Gaffer::BoolPlug *invertPlug() const;

Expand Down
94 changes: 94 additions & 0 deletions python/GafferSceneTest/DeletePointsTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,100 @@ def testBoundsUpdate( self ) :

self.assertEqual( actualPointsDeletedBounds, expectedBoundingBox )

def testIdList( self ) :

testObject = IECoreScene.PointsPrimitive(
IECore.V3fVectorData( [ imath.V3f( 0, 0, i ) for i in range( 10 ) ] ),
IECore.FloatVectorData( range( 10, 20 ) )
)

testObject["testA"] = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Constant, IECore.IntVectorData( [ 2, 3, 4, 8, 9 ] ) )
testObject["testB"] = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Constant, IECore.Int64VectorData( [ 0, 1, 5, 6, 7 ] ) )
testObject["shiftIds"] = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Vertex, IECore.Int64VectorData( [ i + 5 for i in range( 10 ) ] ) )
testObject["outOfRangeIds"] = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Vertex, IECore.Int64VectorData( [ i + 8000000000 for i in range( 10 ) ] ) )
testObject["duplicateIds"] = IECoreScene.PrimitiveVariable( IECoreScene.PrimitiveVariable.Interpolation.Vertex, IECore.Int64VectorData( [ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4 ] ) )

self.assertTrue( testObject.arePrimitiveVariablesValid() )

pointsScene = GafferScene.ObjectToScene()
pointsScene["object"].setValue( testObject )

deletePoints = GafferScene.DeletePoints()

deletePoints["in"].setInput( pointsScene["out"] )

pathFilter = GafferScene.PathFilter( "PathFilter" )
pathFilter["paths"].setValue( IECore.StringVectorData( [ '/object' ] ) )
deletePoints["filter"].setInput( pathFilter["out"] )

deletePoints["selectionMode"].setValue( GafferScene.DeletePoints.SelectionMode.IdList )
deletePoints["idList"].setValue( IECore.Int64VectorData( [ 1, 7 ] ) )

self.assertEqual(
deletePoints["out"].object( "/object" )["r"].data,
IECore.FloatVectorData( [ 10, 12, 13, 14, 15, 16, 18, 19 ] )
)

deletePoints["invert"].setValue( True )
self.assertEqual(
deletePoints["out"].object( "/object" )["r"].data,
IECore.FloatVectorData( [ 11, 17 ] )
)

deletePoints["invert"].setValue( False )
deletePoints["selectionMode"].setValue( GafferScene.DeletePoints.SelectionMode.IdListPrimitiveVariable )
deletePoints["idListVariable"].setValue( "testA" )

self.assertEqual(
deletePoints["out"].object( "/object" )["r"].data,
IECore.FloatVectorData( [ 10, 11, 15, 16, 17 ] )
)

deletePoints["idListVariable"].setValue( "testB" )

self.assertEqual(
deletePoints["out"].object( "/object" )["r"].data,
IECore.FloatVectorData( [ 12, 13, 14, 18, 19 ] )
)

deletePoints["invert"].setValue( True )

self.assertEqual(
deletePoints["out"].object( "/object" )["r"].data,
IECore.FloatVectorData( [ 10, 11, 15, 16, 17 ] )
)

deletePoints["invert"].setValue( False )

deletePoints["id"].setValue( "shiftIds" )

self.assertEqual(
deletePoints["out"].object( "/object" )["r"].data,
IECore.FloatVectorData( [ 13, 14, 15, 16, 17, 18, 19 ] )
)

# Test that we work with ids outside the range of an Int32
deletePoints["id"].setValue( "outOfRangeIds" )

deletePoints["selectionMode"].setValue( GafferScene.DeletePoints.SelectionMode.IdList )
deletePoints["idList"].setValue( IECore.Int64VectorData( [ 8000000001, 8000000002, 8000000007, 8000000008 ] ) )

self.assertEqual(
deletePoints["out"].object( "/object" )["r"].data,
IECore.FloatVectorData( [ 10, 13, 14, 15, 16, 19 ] )
)

# With duplicate ids, we only remove the last instance currently. Do we need to do better than this?
# Duplicate ids shouldn't exist anyway?
deletePoints["id"].setValue( "duplicateIds" )
deletePoints["idList"].setValue( IECore.Int64VectorData( [ 0, 2, 4 ] ) )

self.assertEqual(
deletePoints["out"].object( "/object" )["r"].data,
IECore.FloatVectorData( [ 10, 12, 13, 14, 16, 17, 18 ] )
)


def testIgnoreMissing( self ) :

pointsScene = self.makePoints()
Expand Down
47 changes: 46 additions & 1 deletion python/GafferSceneUI/DeletePointsUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,24 @@

"description",
"""
Deletes points from a points primitive using a primitive variable to choose the points.
Deletes points from a points primitive using a primitive variable or id list to choose the points.
""",

plugs = {
"selectionMode" : [
"description",
"""
Choose how to select points to delete. You can use a vertex primitive variable and delete any
points with a non-zero value, or give a list of specific ids to delete, supplied either as
a primitive variable, or as an explicit list.
""",
"preset:Vertex Primitive Variable", GafferScene.DeletePoints.SelectionMode.VertexPrimitiveVariable,
"preset:Id List Primitive Variable", GafferScene.DeletePoints.SelectionMode.IdListPrimitiveVariable,
"preset:Id List", GafferScene.DeletePoints.SelectionMode.IdList,

"plugValueWidget:type", "GafferUI.PresetsPlugValueWidget",
],


"adjustBounds" : [

Expand All @@ -58,9 +72,40 @@
"description",
"""
Vertex interpolated int, float or bool primitive variable to choose which points to delete. Note a non-zero value indicates the point will be deleted.
""",

"layout:visibilityActivator", lambda plug : plug.node()["selectionMode"].getValue() == GafferScene.DeletePoints.SelectionMode.VertexPrimitiveVariable
],

"idListVariable" : [
"description",
"""
The name of a constant primitive variable holding a list of ids to delete. Must be type IntVectorData or Int64VectorData.
""",

"layout:visibilityActivator", lambda plug : plug.node()["selectionMode"].getValue() == GafferScene.DeletePoints.SelectionMode.IdListPrimitiveVariable
],

"idList" : [
"description",
"""
A list of ids to delete.
""",

"layout:visibilityActivator", lambda plug : plug.node()["selectionMode"].getValue() == GafferScene.DeletePoints.SelectionMode.IdList
],

"id" : [
"description",
"""
When using an id list to delete points, this primitive variable defines the id used for each point.
If this primitive variable is not found, then the index of each point is its id.
""",

"layout:visibilityActivator", lambda plug : plug.node()["selectionMode"].getValue() in [ GafferScene.DeletePoints.SelectionMode.IdList, GafferScene.DeletePoints.SelectionMode.IdListPrimitiveVariable ]
],


"invert" : [
"description",
"""
Expand Down
Loading

0 comments on commit 0b26a3a

Please sign in to comment.