BaseSelect - IsSelected and GetRange.. [SOLVED]



  • On 12/05/2015 at 02:05, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   R14+ 
    Platform:   Windows  ;   
    Language(s) :      XPRESSO  ;

    ---------
    Hi folks,

    In the C++ docs, it says that using GetRange() is faster than looping through all polygons with IsSelected() as follows:

    #### Bool GetRange(LONG seg, LONG maxElements, LONG* a, LONG* b) const_<_h4_>_
    #### Bool IsSelected(LONG num) co_<_h4_>_h4>
      
     **Note:**  If you efficiently want to go through selections you can use the following code:  
    `  
    LONG seg=0,a,b,i;  
      
    while (bs->GetRange(seg++,&a,&b))  
    {  
      for (i=a; i<=b; ++i)  
      {  
        // ... do something - i is the selected element  
      }  
    }`  
      
    This is faster than:  
      
    `    
    for (i=0; i<maxelements; i++)  
    {  
      if (bs->IsSelected(i))  
      {  
        // ... do something  
      }  
    }`
    `
    


    I am trying to understand how the above GetRange() code actually works, for example what the hell is a 'segment' as i deal with polygon selections, and how does this method actually work..  The above GetRange example also doesn't use MaxElements and throws an error without it.  And do a, b, and maxelements refer to index's within the entire BaseSelect or array index's of the selected elements array only..  Slightly confused :/
    Specifically what i am currently doing ( just to complicate matters ), is a multithreaded approach.  Each thread loops through a portion of the objects polygons, and does some work with BaseSelect.  So the main question is:  is it possible to use GetRange() as above, but for each function to only operate on a portion of the range - for example, something like:

    `
    `LONG seg=0,a=startIndex,b=endIndex,i;  
      
    while (bs->GetRange(seg++,(endIndex-startIndex),&a,&b))  
    {  
      for (i=a; i<=b; ++i)  
      {  
        // ... do something - i is the selected element  
      }  
    }`
    `
    


    Thanks in advance for any help and advice, it's much appreciated.

    `



  • On 12/05/2015 at 07:28, xxxxxxxx wrote:

    Hi,

    first I'd like to apologize, the code example is wrong. It will be correct in the next released documentation.

    What the hell is a segment?

    As explained on GetSegments() segments are disjunct parts of a selection. For example if the indeces 0 to 3 and 6 to 9 are selected, then the BaseSelect has two segments.

    Parameter maxElements of GetRange() refers to indeces of the BaseSelect. It's basically the maximum, which will be returned in parameters a and b. If you don't need this functionality, simply pass LIMIT<Int32>::MAX.

    Threading:
    In general I think, it should be fine to work with multiple threads on the BaseSelect as long as you are only reading. But of course this may depend on several thing, like who's the owner of the BaseSelect and in which context are you trying to this.

    I hope, I was able to shed some light. If not, feel free to ask.



  • On 12/05/2015 at 10:33, xxxxxxxx wrote:

    Threading is working fine with BaseSelect as long as you are careful, even using bs->Select() etc to alter the BaseSelect works multithreaded..  I've simply passed my 'core' BaseSelect into my control thread, and from there passed it on again into each individual thread, and that works..

    Thanks for the explanation on segments, have no idea why i didn't see the info on GetSegments().

    How would i then iterate between say the middle and the end of the GetRange()?  I'm still a bit unclear as to what a and b exactly are doing and what they refer to specifically..



  • On 12/05/2015 at 10:50, xxxxxxxx wrote:

    a and b are the start index and end index of the currently retrieved segment (using GetRange()).

    As Andreas mentioned, imagine you have a cube with 8 vertices and the vertices 0-2 are selected (and no others), then after calling bs->GetRange(0,&a,&b) :

    a = 0
    b = 2

    bs->GetRange(1,&a,&b) would return FALSE, because no other vertices are selected, so there is only one segment (ranging from vertex index 0 to vertex index 2).



  • On 12/05/2015 at 15:35, xxxxxxxx wrote:

    Ah ok i get it thanks Katachi..

    So i could use GetSegments() to find out the number of contiguous polygons, and instruct each thread to iterate through a portion of segments using GetRange()..

    However - say there was only for example two segments, and say 8 threads, it would not be so simple to distribute them over the threads..  Can the above GetRange() example code be manipulated to operate on a range of selected polygons or points regardless of segments?

    Apologies if i am asking seemingly obvious stuff here, i certainly don't mean to have anybody write my code for me :)  Just struggling a little to get to grips with how the GetRange() example code works exactly and how it can be used..



  • On 13/05/2015 at 00:08, xxxxxxxx wrote:

    You could first use GetSegments() and if the number of segments is lower than your number of threads, simply subdivide segment as needed. There's no need to process from a to b in one go, if you don't want to.



  • On 13/05/2015 at 01:13, xxxxxxxx wrote:

    Damnit i think i got it now.  I was really overthinking what GetRange() was doing..  :/

    I've implemented it like this, where pIndexStart and pLength define the range of poly indexes to look at:

    while (dupeSel->GetRange(seg++,MAXLONGl,&a,&b))
    {
        for (i=a; i<=b; ++i)
        {
            if (i>=pIndexStart && i<LONG(pLength+pIndexStart))
            {
                // Do some stuff with sel..
            }
        }
    }
    

    Ideally i think the above could be faster ( with large numbers of selections ), because at the moment although it's only 'doing some stuff' to the desired range of polys, it's still spending time looping through the entire selection ( whereas it would probably be fractionally quicker if i could limit the start and end indexes that the 'while' and 'for' loops run over..

    Just for reference, this is the older ( slightly slower? ) code:

    for (int i=pIndexStart; i<(pLength+pIndexStart); i++)
    {
        if (sel->IsSelected(i))
        {
            // Do some stuff with sel..
        }
    ]
    

Log in to reply