Point cloud point selection

Thanks Mahdiyar,
but what I am looking for is a fast way to get a point cloud subselection.
I need to know the indices or coordinates of the selected points (within selection rectangle)

Maybe using one of the RTree methods - there seem to be some dedicated specifically to point clouds. If I understand correctly they should be very fast :rocket:

https://developer.rhino3d.com/api/RhinoCommon/html/Methods_T_Rhino_Geometry_RTree.htm

Also thank you Graham. Yes - RTree is a fast way to work on a pointcloud. The disadvantage is, that you first have to initialize all points to an rtree.
But I need a very quick way of selecting points from a pointcloud with a selection window. This can be done in rhino by using the tool for removing points from a pointcloud. I assume there is some openGL stuff behind this. Hopefully this is wrapped in some way in rhino common…

thanks,
Philip

Are you looking for GetObjects with filter = 2?

https://developer.rhino3d.com/api/RhinoScriptSyntax/#collapse-GetObjects

Thanks rgr, but this would select the entire pointcloud. I need a sub-selection as shown in the picture. This picture was taken while using the rhino tool for removing points of a pointcloud (yellow, selected points will be removed from the pointcloud and inserted as points in rhino after confirming the command)

@powerpp, i figured, there could be multiple pointclouds (and points) in the window selection, so getting the selected pointcloud point indices required some stretching…

import Rhino
from collections import defaultdict

def DoSomething():
    # prompt for pointcloud points
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt("Select pointcloud points")
    go.GeometryFilter = Rhino.DocObjects.ObjectType.Point
    go.GetMultiple(1, 0)
    
    if go.CommandResult() != Rhino.Commands.Result.Success: return 
    if not go.Objects(): return 
    
    # dictionary: (key = cloud object guid, value = selected cloud pt indices)
    my_dict = defaultdict(lambda: [])
    
    for obj_ref in go.Objects():
        if isinstance(obj_ref.Object(), Rhino.DocObjects.PointCloudObject):
            my_dict[obj_ref.Object().Id].append(obj_ref.GeometryComponentIndex.Index)
    
    for cloud_id, indices in my_dict.iteritems():
        print "CloudId: {} >>> {} points selected".format(cloud_id, len(indices))

DoSomething()

_
c.

2 Likes

Perfekt! Thanks a lot for this Clement.
It is exactly what i was looking for (even more).
Have a nice week!

Best,
PP

@clement Thank you very much for the script. Very useful!

I wonder if it would be possible to save the selected points in some way and then select them again, even though they still belong to the original point cloud. This is because of the following: I have found that the PointCloud Rhino function, with their Add and Remove options, is much faster than any script done in Python (at least, done by me). For example, to remove a group of points from a point cloud I have to go point by point applying the RemoveAt method, which is not very fast, especially if the cloud is large. So I thought maybe the rs.Command() with PointCloud function and Remove option would be faster, but I don’t know how to tell the rs.Command() to delete the group of points (previously selected by your script). I don’t know if I explain myself…

It sounds like you need a new function on the PointCloud class to remove a set of points instead of one by one. Would that help?

Yeah, you are right @stevebaer!
Something similar to AddRange… For example: RemoveRange?

Ok, I added this request to the wishlist for RhinoCommon
https://mcneel.myjetbrains.com/youtrack/issue/RH-62983

1 Like

@stevebaer ok!

Hi @pau.natividad, an alternative to RemoveAt is to create 2 new point clouds, one with the remaining points and one with the ones you remove.

_
c.

Hi again @clement. Thanks for suggestion.

I tried that option as well and it is slow with very large clouds. From what I have been able to find out, the problem appears when the lists are created point by point. From my ignorance, two possible solutions arise: 1) What I proposed in a previous message (using rs.Command) which is surely a somewhat strange idea. 2) What @stevebaer has suggested, which could really solve this issue, since the point lists could be modified very quickly (I suspect that as much as the AddRange method)… Well, we will wait for news about all of this. Thanks anyway for your attention!

Dale Fugier went ahead and implemented this function in RhinoCommon (PointCloud.RemoveRange). This will be available in 7.5 which we should start making release candidates available for on March 9th

1 Like

PointCloud.RemoveRange that is.

Details details… :slight_smile:

Another asymmetry for pointclouds is that intensity can be added/removed with the C++ SDK (double *intensities = cloudGeo.m_V.Array()) but it does not exist in Rhinocommon unless I overlooked it somehow.

While in the end I push all my performance critical code to C++, this crimps my much more rapid new code development/debugging/optimization in Python. Way less hair pulling to get things working in Python than C++, not that I have much hair left to pull being 8.75 years shy of 80.

Regards,
Terry.

https://mcneel.myjetbrains.com/youtrack/issue/RH-62995

1 Like

Dale,

Thanks for adding this. I plan on using the intensity field to store the slope at each point. Having this available in both Python and C++ will significantly help my code development.

It is wonderful to see Rhino supported so well.

Regards,
Terry.

1 Like