Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Envelope Generation in PoissonRecon Integration with CloudCompare #293

Open
Matozinho opened this issue Mar 28, 2024 · 4 comments
Open

Envelope Generation in PoissonRecon Integration with CloudCompare #293

Matozinho opened this issue Mar 28, 2024 · 4 comments

Comments

@Matozinho
Copy link

Hi @mkazhdan,

I'm currently working on upgrading the integration of your PoissonRecon library with the CloudCompare PoissonRecon plugin. This work is part of my undergraduate research at UNIOESTE (Brazil), where we aim to validate whether updating the library version leads to improved reconstructions for our datasets, which consist of point clouds obtained via drone-based LiDAR technology.

In our use case, users only have access to the point cloud data and not the range scans required for generating the depth hull, as explained in your SGP 2020 presentation. To address this, I've been attempting to create an envelope that is a quadrilateral encompassing the extreme points of the cloud. However, I've encountered the Leaf node is unknown error, which seems to originate from the SetUnknownDesignatorsFromChildren function within _GetGeometryNodeDesignators.

I have a few questions regarding this issue:

Does this approach of using a quadrilateral envelope for point clouds make sense in the absence of range scans?
If this approach is valid, is there a different method I should use to generate the envelope?
Could you provide some insight into what the Leaf node is unknown error signifies and how I might resolve it?
Any guidance or suggestions you can provide would be greatly appreciated, as it would help us advance our research and improve the utility of the PoissonRecon integration in CloudCompare for our specific needs.

Thank you for your time and assistance.

@mkazhdan
Copy link
Owner

When you say "quadrilateral envelope" what do you mean? Is this a bounding box? Is it water-tight?
If the envelope is sufficiently "loose" (i.e. it is not tight and encompasses the entire point-set) it seems like the results should be similar to what you would get reconstructing using Dirichlet boundary conditions (instead of the default Neumann).

@Matozinho
Copy link
Author

Yes, the envelope I referred to is indeed a bounding box. I initially thought that using a bounding box would yield similar results to a standard reconstruction. I intended to use this as a preliminary step in incorporating the envelope feature into the reconstruction process within CloudCompare. However, I encountered this error and uncertainties that have stalled my progress.

@mkazhdan
Copy link
Owner

It might be easier if you could share your point set and envelope.
That way I could try to reproduce the error here.

@Matozinho
Copy link
Author

Matozinho commented Apr 8, 2024

I'm sorry for the delay @mkazhdan.

I generate the envelope bounding box as follows:

The wrapper:

  // define the envelope
  typename Reconstructor::Poisson::EnvelopeMesh<Real, Dim> *envelopeMesh = NULL;
  {
    envelopeMesh =
        new typename Reconstructor::Poisson::EnvelopeMesh<Real, Dim>();

    Confia::generateMesh<PositionFactory<Real, Dim>, Real, Dim>(
        PositionFactory<Real, Dim>(), inCloud, envelopeMesh);

    // print all the vertices of the envelopeMesh
    for (size_t i = 0; i < envelopeMesh->vertices.size(); i++) {
      std::cout << "Vertex[" << i << "]: " << envelopeMesh->vertices[i]
                << std::endl;
    }
    std::cout << "Simplicies[0] " << envelopeMesh->simplices[0][0] << " "
              << envelopeMesh->simplices[0][1] << " "
              << envelopeMesh->simplices[0][2] << std::endl;
  }

Bounding Box Generation:

template <typename Real>
void findBoundingBox(const PoissonReconLib::ICloud<Real> &inCloud,
                     Real bbox[8][3]) {
  // Initialize min and max values to the first point's coordinates
  Real minX, minY, minZ, maxX, maxY, maxZ;
  Real firstPoint[3];
  inCloud.getPoint(0, firstPoint);
  minX = maxX = firstPoint[0];
  minY = maxY = firstPoint[1];
  minZ = maxZ = firstPoint[2];

  // Iterate through all points to find min and max values
  for (size_t i = 1; i < inCloud.size(); ++i) {
    Real coords[3];
    inCloud.getPoint(i, coords);

    if (coords[0] < minX)
      minX = coords[0];
    if (coords[0] > maxX)
      maxX = coords[0];
    if (coords[1] < minY)
      minY = coords[1];
    if (coords[1] > maxY)
      maxY = coords[1];
    if (coords[2] < minZ)
      minZ = coords[2];
    if (coords[2] > maxZ)
      maxZ = coords[2];
  }

  // Assign the 8 bounding box points
  bbox[0][0] = minX;
  bbox[0][1] = minY;
  bbox[0][2] = minZ; // Min corner
  bbox[1][0] = maxX;
  bbox[1][1] = minY;
  bbox[1][2] = minZ;
  bbox[2][0] = minX;
  bbox[2][1] = maxY;
  bbox[2][2] = minZ;
  bbox[3][0] = maxX;
  bbox[3][1] = maxY;
  bbox[3][2] = minZ;
  bbox[4][0] = minX;
  bbox[4][1] = minY;
  bbox[4][2] = maxZ;
  bbox[5][0] = maxX;
  bbox[5][1] = minY;
  bbox[5][2] = maxZ;
  bbox[6][0] = minX;
  bbox[6][1] = maxY;
  bbox[6][2] = maxZ;
  bbox[7][0] = maxX;
  bbox[7][1] = maxY;
  bbox[7][2] = maxZ; // Max corner
}

template <typename VertexFactory, class Real, int Dim>
void generateMesh(
    const VertexFactory &vFactory, const PoissonReconLib::ICloud<Real> &inCloud,
    Reconstructor::Poisson::EnvelopeMesh<Real, Dim> *envelopeMesh) {

  Real bbox[8][3];

  findBoundingBox(inCloud, bbox);

  typename VertexFactory::VertexType vertex = vFactory();

  for (size_t i = 0; i < 8; i++) {
    char *buffer = reinterpret_cast<char *>(&bbox[i]);

    vFactory.fromBuffer(buffer, vertex);
    envelopeMesh->vertices.push_back(vertex);
  }

  std::vector<std::vector<int>> simplices = {
      {0, 1, 2}, {0, 2, 3}, {4, 5, 6}, {4, 6, 7}, {0, 1, 5}, {0, 5, 4},
      {2, 3, 7}, {2, 7, 6}, {1, 2, 6}, {1, 6, 5}, {0, 3, 7}, {0, 7, 4}};

  for (size_t i = 0; i < simplices.size(); i++) {
    envelopeMesh->simplices.resize(simplices.size());
    for (size_t j = 0; j < simplices[i].size(); j++) {
      envelopeMesh->simplices[i][j] = simplices[i][j];
    }
  }
}

After making some changes to the implementation, I started receiving the following error:

[ERROR] /home/operador/Dev/unioeste/CloudCompare/plugins/core/Standard/qPoissonRecon/extern/PoissonRecon/Src_CC_wrap/../Src/Rasterizer.inl (Line 59)
        _RegularGridIndex
        Simplex is not in unit cube: ( 0.355635 , 0.289911 , 0.0454546 ) , ( 0.644365 , 0.289911 , 0.0454546 ) , ( 0.355635 , 0.710089 , 0.0454546 )

This error occurs when I'm testing with the torso.points.ply dataset (the example from your repo).

Thank you for your assistance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants