1
votes

I'm using the PCL library to do a registration using two point clouds. The two point clouds are displayed in two different windows using the viewports v1 and v2. A third window is displayed beneath the two windows to display the registered cloud, using the viewport v3. All of the viewports are used by a single PCLVisualizer named m_viewer. The workflow is to select point correspondences in v1 and v2 to do the registration which will be shown in v3. Following a picture of the program:

Main display of the program

Now I'm trying to implement a feature that highlights points the user clicks on. So if the user clicks on a point in viewport v1 or v2, it will be highlighted in a function markSelectedPoint using a white color. I want to store the highlighted points in two different point clouds markedPointsCloudLeft and markedPointsCloudRight.

To update the visualization of the point cloud, in PCL I have to call updatePointCloud. As far as I know, in PCL it would look like this:

m_viewer->updatePointCloud(markedPointsCloudLeft, white, "marked cloud left");

or

m_viewer->updatePointCloud(markedPointsCloudRight, white, "marked cloud right");

So if I click on the left viewport v1, markedPointsCloudLeft should be updated, the same thing goes for the right one. And here is my problem:

If I click on any of the point clouds, I have to tell markSelectedPoints which one I clicked at. To do that, I need either the id of the viewport where the cloud is or which point cloud the selected point belongs to. So, for example, if I'm clicking on the left point cloud, I have to tell markSelectedPoints I'm referring to v1 or that the point belongs to markedPointsCloudLeft. Until now, I haven't found any function or method in PCL to this data.

Do you have an idea how I could achieve this? Or is there another workaround to get this data? Thanks in advance!

2

2 Answers

0
votes

So guys, I found a solution... although it's not a real solution but more a rather dirty workaround.

First, I applied an offset to m_rightCloud. This offset is calculated based on a distance between the point of m_leftCloud with the maximum x and the point of m_rightCloud with the minimum x.

Next, I transferred the left and right point cloud to a kd tree. See this link for further details.

Now, apply the function nearestKSearch to both trees. This will fill two vectors containing the squared distances. For this case, both vectors contain only one value because only one of the points is needed.

Now compare the values of both vectors. The one vector containing the smaller value will tell you which cloud the point belongs to.

The code for the main function:

if (kdtreeLeft.nearestKSearch(inputPoint, 1, pointSearchValsLeft, pointSqDLeft) > 0 &&
    kdtreeRight.nearestKSearch(inputPoint, 1, pointSearchValsRight, pointSqDRight) > 0) {
    // Call index 0 because only one value is in the vectors
    if (pointSqDLeft.at(0) < pointSqDRight.at(0)) {
        return "left cloud!";
    } else {
        return "right cloud!";
    }
}

This is imo still a bad solution, because the determination of the offset is really cheesy. Also note that this only works for this case. If you are using two or more overlapping point clouds, this solution will hardly work.

If someone finds a better solution, feel free to post it!