How to get all elements from BaseSelect



  • Hello,
    I'm trying to get the selected points from an object. GetPointS gives a baseselect so I'm trying to retrieve the selected points' indices from the baseselect.

    In the attached example, I selected a few of the points of the cube. I iterate through all the baseselect ranges but only half of them give points. The other half result "None". Any idea why it isn't working and/or how to fetch the point selection without iterating through all the points of the object?

    # Main function
    def main():
        objectSelection = doc.GetActiveObject()
        pointSelection = objectSelection.GetPointS()
        selectedCount = pointSelection.GetCount()
        
        for segment in range(pointSelection.GetSegments()):
            print(pointSelection.GetRange(segment, selectedCount))
    

    baseselect.c4d



  • Hi @orestiskon,

    thank you for reaching out to us. The problem with your code is that you pass the number of selected elements as the second argument to BaseSelect.GetRange(). But the method actually does expect the maximum index there, i.e., the total number of points for a point selection. While this method via .GetRange() is a bit more performant, in Python you can also use .GetAll() and list comprehensions. For details see the attached example.

    Cheers,
    Ferdinand

    """A simple example for how to iterate over point selections.
    
    As discussed in:
        https://plugincafe.maxon.net/topic/13115
    """
    
    import c4d
    
    
    def main():
        """Iterates over the selected objects and accesses their point selection.
        """
        # Iterate over the selected objects.
        for obj in doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_NONE):
            # Step over non-point objects.
            if not isinstance(obj, c4d.PointObject):
                continue
    
            # All the points of the point object.
            points = obj.GetAllPoints()
            # And their count.
            pointCount = obj.GetPointCount()
            # The point selection.
            selection = obj.GetPointS()
    
            # The selection state of all elements in the BaseSelect. This is
            # a list of booleans, e.g., [True, False, False, False] for a polygon
            # object with just one quad and the first point in it being
            # selected.
            state = selection.GetAll(pointCount)
            # We have to manually convert this to indices.
            indices = [eid for eid, value in enumerate(state) if value]
            # I.e., you can get all selected indices like this in one go:
            # [eid for eid, val in enumerate(selection.GetAll(pointCount)) if val]
    
            # Print some stuff out.
            print("Object:", obj.GetName())
            print("Indices of selected points:", indices)
            print("The corresponding points:", [points[i] for i in indices])
            # The number of selected elements in the selection.
            print ("selection.GetCount():", selection.GetCount())
            # The segments in the selection, this has nothing to do with the
            # topology, but is rather the number of consecutive selection index
            # "strips". E.g.: [True, True, False, True, True] would be two
            # segments.
            print ("selection.GetSegments():", selection.GetSegments())
            # You can also access the selected elements like you tried to.
            for segment in range(selection.GetSegments()):
                # But you have to pass in here the point count, i.e., the number
                # of total total possible indices, not the number of selected
                # elements.
                print(selection.GetRange(segment, pointCount))
            print("-"*79)
    
    
    if __name__ == '__main__':
        main()
    


  • Hi @orestiskon,

    thank you for reaching out to us. The problem with your code is that you pass the number of selected elements as the second argument to BaseSelect.GetRange(). But the method actually does expect the maximum index there, i.e., the total number of points for a point selection. While this method via .GetRange() is a bit more performant, in Python you can also use .GetAll() and list comprehensions. For details see the attached example.

    Cheers,
    Ferdinand

    """A simple example for how to iterate over point selections.
    
    As discussed in:
        https://plugincafe.maxon.net/topic/13115
    """
    
    import c4d
    
    
    def main():
        """Iterates over the selected objects and accesses their point selection.
        """
        # Iterate over the selected objects.
        for obj in doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_NONE):
            # Step over non-point objects.
            if not isinstance(obj, c4d.PointObject):
                continue
    
            # All the points of the point object.
            points = obj.GetAllPoints()
            # And their count.
            pointCount = obj.GetPointCount()
            # The point selection.
            selection = obj.GetPointS()
    
            # The selection state of all elements in the BaseSelect. This is
            # a list of booleans, e.g., [True, False, False, False] for a polygon
            # object with just one quad and the first point in it being
            # selected.
            state = selection.GetAll(pointCount)
            # We have to manually convert this to indices.
            indices = [eid for eid, value in enumerate(state) if value]
            # I.e., you can get all selected indices like this in one go:
            # [eid for eid, val in enumerate(selection.GetAll(pointCount)) if val]
    
            # Print some stuff out.
            print("Object:", obj.GetName())
            print("Indices of selected points:", indices)
            print("The corresponding points:", [points[i] for i in indices])
            # The number of selected elements in the selection.
            print ("selection.GetCount():", selection.GetCount())
            # The segments in the selection, this has nothing to do with the
            # topology, but is rather the number of consecutive selection index
            # "strips". E.g.: [True, True, False, True, True] would be two
            # segments.
            print ("selection.GetSegments():", selection.GetSegments())
            # You can also access the selected elements like you tried to.
            for segment in range(selection.GetSegments()):
                # But you have to pass in here the point count, i.e., the number
                # of total total possible indices, not the number of selected
                # elements.
                print(selection.GetRange(segment, pointCount))
            print("-"*79)
    
    
    if __name__ == '__main__':
        main()
    


  • Thanks @ferdinand , I misinterpreted the GetRange argument. That clears it up, and thanks for the example as well, it's very useful!


Log in to reply