I cannot get multiple polygons from GetNearestPolygon



  • Hi,
    I have been looking for a solution for this for quite a while now, but have to give in after having tried all I can think of.

    For testing purposes I am reusing the DescriptionToolData provided in this thread
    I know it isn't the best example, but still usable for quick tests to figure out if a prototype works or not.

    Now, instead of using the single result I am looking to get all (visible) polygons under the area of the mouse cursor.

    Bool MyDescriptionTool::GetCursorInfo(BaseDocument* doc, BaseContainer& data, BaseDraw* bd, Float x, Float y, BaseContainer& bc)
    {
    
    ...
    
    	AutoAlloc<ViewportSelect> viewportSelect;
    	if (viewportSelect && viewportSelect->Init(w, h, bd, object, Mpolygons, true, VIEWPORTSELECTFLAGS::NONE))
    	{
    		Int32 vpsX = SAFEINT32(x);
    		Int32 vpsY = SAFEINT32(y);
    		const Int32 radius = 10;
    		const ViewportPixel* vpPixel = viewportSelect->GetNearestPolygon(object, vpsX, vpsY, radius, false, nullptr, 0);
    		while (vpPixel)
    		{
    			iferr(mPolygons.Append(vpPixel->i))
    			{}
    			vpPixel = vpPixel->next;
    		}
    		ApplicationOutput("@", mPolygons);
    	}
    
    

    I have tried differet values for the "radius" variable, still I mainly only get a single polygon as result of the GetNearestPolygon call.
    I am using a default sphere primitive, manually created in an empty scene, and "made editable".

    I must be overlooking something simple ...



  • Hello,

    When you Init your viewportSelect it will create a ViewportPixel buffer filled with the informations (different for poly, edge and points)

    When you use GetNearestPolygon it run trough the buffer and simply calculate the length for that pixel to the coordinates of the mouse (if the pixel is in the radius) and return the ViewportPixel. This ViewportPixel is unchanged, so the "next" will simply point to the next pixel. as you can read on this page : "The information for each pixel is stored in a linked list, which you can traverse with ViewportPixel::next. "

    The comparaison is "rDist < rMinDist" so if another polygon is at exact same distance (for example you are right on an edge of two polygons) it will not replace the first one. (i didn't ran test to be sure)

    If you want every pixel on the radius you need to retrieve the nearest polygon for each pixel with a radius of 0. You already passed true to the init function to pick only visible polygon.

    Cheers,
    Manuel



  • @m_magalhaes
    Thanks, but I have read your explanation about 10 times and I still don't get it.
    I would have assumed from the documentation, and also from what you describe that when performing a GetNearestPolygon I should be able to traverse the resulting ViewportPixel. I would thus assume that when passing a radius of 10, all polygons that are within that radius can be collected with the ViewportPixel::next.

    So, if I position the mouse pointer on a point which is shared by 4 polygons, and perform
    const ViewportPixel* vpPixel = viewportSelect->GetNearestPolygon...

    Then vpPixel->i points to the closest polygon.
    I would then assume vpPixel->next points to a next pixel within that radius, and by doing following I can get the next polygon within that same radius?

    vpPixel = vpPixel->next;
    const Int32 nextpolygon = vpPixel->i
    

    And again for the next one? And so on.

    But then you go on saying that if I want every pixel on the radius, I need to perform nearest polygon for each pixel ???

    The native live selection tool allows to select multiple polygons that lie within a radius. Do I then need to iterate over all pixels that are inside the radius and perform for each pixel an GetNearestPolygon?
    Sounds counter-intuitive!



  • hi,

    GetNearestPolygon return a const pointer, that's because it's not the result of the search, it's pointing to the memory that have been build by the Init function. That part of the memory is an linked list of ViewportPixel of the viewport itself (for each pixel)

    If you modify that memory, the next 'result' will be modified also.
    That's why, with ->next, you will have the next pixel of the viewport (and not the result)

            vs->Init(width, height, bd, mesh , Mpolygons, true, VIEWPORTSELECTFLAGS::NONE);
    		
    	const ViewportPixel* np =  vs->GetNearestPolygon(mesh, halfw, haflh, 20);
    	ApplicationOutput("closest poly is @", np->i);
    
    	ViewportPixel* modifnp = const_cast<ViewportPixel*>(np);
    	modifnp->i = 20;
    
    	const ViewportPixel* np2 = vs->GetNearestPolygon(mesh, halfw, haflh, 20);
    	ApplicationOutput("closest poly is @", np2->i);
    
    
    

    As it is a licked list, next will point to the next pixel and will go out the radius without going to the next line of pixel.

    Cheers,
    Manuel



  • @m_magalhaes

    Sorry for the delay, was too busy to reply.

    I see I misunderstood the whole concept of the return value of GetNearestPolygon.
    So, if I understand correctly, in order to actually get all polygons that are within a given radius I will need to iterate over each pixel inside that area using GetPixelInfoPolygon?



  • hello,

    I've lookied into the live selection tool and internally it's using GetPixelInfoPolygon, or the equivalent for point and edges.

    You also have Get<xxx>PixelBuffer where <xxx> is Point, Edge or Polygon. That return the internal buffer constructed inside the Init function of the ViewportSelect Class.

    pixelBuffer[ width*y + x] will give you the right pixel on that buffer.

    Sorry to have missed those functions.

    Cheers,
    Manuel


Log in to reply