What is the max parameter in BaseSelect.GetRange() really for?



  • As the headline says...BaseSelect.GetRange() returns the min and max values for a segment in a selection. But it has a second parameter (besides the segment), called max.

    Now, max is not needed from a structural point of view. The selection contains a known number of segments, which contain one tuple each. Other than e.g. BaseSelect.SelectAll(), where we actually need to pass a max value because the BaseSelect does not know the total number of elements that may possibly selected, GetRange() does not deal with unknowns.

    The documentation says about this parameter:

    max (int) –
    The maximum value for the returned elements numbers.
    Usually pass PolygonObject.GetPolygonCount() or PointObject.GetPointCount() or the edge count of the object.
    The method makes sure they are < max.
    

    I would interpret that as assurance that any value we get returned is smaller than max. So if there is a segment (1,5) and max = 3, then we'd get (1,3) back. (I can't for the life of me think of a reason why I would want that, but hey.)

    That is, however, not what I really get. If I use a value for max that is smaller than the value GetRange tries to return, I receive TypeError: 'NoneType' object is not iterable. If I use a ridiculous large value for max, no apparent effects happen at all, not even a perceivable increase in runtime.

    So, I have a parameter that at best does nothing, and at worst throws an error. I don't know whether this is a bug (R21) or whether I just don't understand the function.

    The C++ doc says about the same parameter:

    The maximum value for a and b. Makes sure a and b are < maxElements. Pass LIMIT<Int32>::MAX for no additional checks.
    

    That supports my understanding of the parameter, but does not explain why I get a TypeError instead.
    (It also doesn't explain why a limit on the selection is so important that it justifies an additional parameter when the check could easily be done on the returned values. Or: what happens, if both returned limits of the segment are larger than max.)

    btw, it would be nice if the Python docs also contained the additional info from the C++ doc:

    The spans are always sorted (spans with higher index have higher numbers for a/b), also b is always >= a. 
    


  • @Cairyn said in What is the max parameter in BaseSelect.GetRange() really for?:

    I would interpret that as assurance that any value we get returned is smaller than max. So if there is a segment (1,5) and max = 3, then we'd get (1,3) back. (I can't for the life of me think of a reason why I would want that, but hey.)

    Simple: interpret an element number as an index. You don't want that index to be out of range.

    If you have a list of n elements and a BaseSelect object to store which elements of that list are "selected", you want to ensure that an index provided by GetRange() is a valid index of that list.

    Why there is an issue with Python I don't know.



  • Hi,

    I admittedly do not quite understand what @PluginStudent is trying to convey here, so I might be misunderstanding something about your question.

    As your quoted description says, the method will test internally that a and b are smaller than max. If they do not match this criteria, this method fails and returns None. I am not quite sure where you would need that, but the scenario would be that you expect a segment not to surpass a certain index and want to test that. You could of course also just test the returned tuple, so it is not very useful. Probably some weird internal reason.

    About your error, are sure that actually the method is raising the error and not your surrounding code with an unpacking or indexing operation for example? When the return value is None, that would give you exactly that error. E.g. this will fail when the method fails, i.e. returns None:

    a, b = selection.GetRange(*data)
    

    Cheers,
    zipit



  • @PluginStudent But the indices in the segment in the BaseSelect are automatically valid if the BaseSelect was built by a valid source. The only way to get invalid values would be to apply the same BaseSelect to a different object with less polys/points, and in that case the function GetRange() is of lower priority - you'd get out of range errors much earlier.

    If you really have an arbitrary BaseSelect to store indices from a list, and the BaseSelect contains indices that are not in the list at all, then your code is buggy, and limiting the output of GetRange() would be just covering up that bug.

    It's confusing. Maybe it's just a relic from some older code, grandfathered into the current API.



  • @zipit said in What is the max parameter in BaseSelect.GetRange() really for?:

    About your error, are sure that actually the method is raising the error and not your surrounding code with an unpacking or indexing operation for example? When the return value is None, that would give you exactly that error. E.g. this will fail when the method fails, i.e. returns None:

    a, b = selection.GetRange(*data)
    

    Aha, good thinking! Yes, that's exactly the error.

    The doc for the parameter doesn't say that the function completely fails when the max condition is not met - it just states The method makes sure they are < max.
    That of course also answers my question what happens when a and b both are < max. It makes the existence of the parameter even more mysterious, but it explains why I get this error.

    I definitely need to be more careful with return value checking... thanks!



  • hi,

    honestly i didn't found any places that could be useful.

    The fact is that you can use Select with any kind of number even if it is superior to the number of polygon, point or edge your object is composed of.

    BaseSelect is also used to know witch text is selected (on parameter). But even there, i got doubt that this Max parameter is usefull.

    It just save you time to not check if the value aren't superior to what's possible.

    and thanks again @zipit

    Cheers,
    Manuel



  • yupyup, BaseSelect has no connection to the original object it actually selects from, not even in the cases where you get a pointer to the BaseSelect returned and change the selection directly through it.

    That's why we need the max parameter for SelectAll and ToggleAll -- the BaseSelect doesn't know what "all" even is. (Not GetLastElement()!) For GetRange() though, that reasoning does not apply.

    Now let's see whether I can crash C4D with inconsistent edge selections...