Giter VIP home page Giter VIP logo

Comments (22)

mariuszhermansdorfer avatar mariuszhermansdorfer commented on May 18, 2024 2

@Grantim, @Fedr,

I don't know how you guys do it, but you keep delivering amazing solutions!

Remember when I mentioned that Rhino takes 30s to sample the point cloud? In MeshLib this is down to 10ms for 4x the amount of samples!
I'm speechless.

Again, huge thanks for your help! Please close this issue as resolved.

from meshlib.

mariuszhermansdorfer avatar mariuszhermansdorfer commented on May 18, 2024 1

Thanks @Grantim, I'll give it a shot and will report back.

from meshlib.

Fedr avatar Fedr commented on May 18, 2024 1

In Box3f with have a method bool contains( const Point3f & pt ) const. You can use it to test whether the point is within the box. Then call pc->validPoints.reset( i ) for such points.

from meshlib.

Grantim avatar Grantim commented on May 18, 2024 1

Hope this code will help

Vector3f minPoint = Vector3f{0, 0, 0)};
Vector3f normalVector = Vector3f{0.826724f, -0.0802f, 0.556862f};
float resolution = 1.0f; // this is step size

auto basis = normalVector.perpendicular(); // find basis vectors of the plane
 
auto resMesh = makeRegularGridMesh( 100, 50, [&]( size_t, size_t ) { return true; },  
[&]( size_t x, size_t y) 
{
    // locate each point with x,y steps along basis 
    return 
        minPoint + // start position
        resolution * float( x ) * basis.first + // do `x` steps with size=`resolution` along first basis vector
        resolution* float( y ) * basis.second; // do `y` steps with size=`resolution` along second basis vector
} );

from meshlib.

Grantim avatar Grantim commented on May 18, 2024

Hello!
Now we have two sampling algorithms in MeshLib

/// performs sampling of cloud points;
/// subdivides point cloud bounding box on voxels of approximately given size and returns at most one point per voxel;
/// returns std::nullopt if it was terminated by the callback
MRMESH_API std::optional<VertBitSet> pointGridSampling( const PointCloud& cloud, float voxelSize, const ProgressCallback & cb = {} );

and
/// Sample vertices, removing ones that are too close;
/// returns std::nullopt if it was terminated by the callback
/// \ingroup PointCloudGroup
MRMESH_API std::optional<VertBitSet> pointUniformSampling( const PointCloud& pointCloud, float distance, const ProgressCallback & cb = {} );

it will sampled VertBitSet that can be used to set valid points in PointCloud

from meshlib.

mariuszhermansdorfer avatar mariuszhermansdorfer commented on May 18, 2024

I'd like to specify the exact location of my sampling points. The above methods don't seem to allow this flexibility, do they?

from meshlib.

Grantim avatar Grantim commented on May 18, 2024

Oh, thanks, I think I got it now. Is it correct: you have 10000 sample points and for each of them you need to find closest point from 5M point cloud?

from meshlib.

mariuszhermansdorfer avatar mariuszhermansdorfer commented on May 18, 2024

Yeah, that's correct. I want to be able to define these sample points wherever I want and for each of them find the closest point from the big point cloud.

from meshlib.

Grantim avatar Grantim commented on May 18, 2024

So I can suggest code like this:

std::vector<MR::Vector3f> samplePoints(10000);
std::vector<MR::Vector3f> closestResult(10000);
// fill up with points you need
fillSamplePoints( samplePoints );

// project sample points on bigPointCloud  in parallel
MR::ParallelFor( samplePoints, [&]( size_t i ) 
{
    closestResult[i] = bigPointCloud.points[findProjectionOnPoints( samplePoints[i], bigPointCloud ).vId];
} );

from meshlib.

mariuszhermansdorfer avatar mariuszhermansdorfer commented on May 18, 2024

Hmm, somehow I managed to create a memory leak somewhere and the code breaks without any warnings:

This is how I create the point cloud:

PINVOKE PointCloud* CreatePointCloud( const float coordinates[], const int coordinatesLength )
{
	std::vector<MR::Vector3f> coords( coordinatesLength / 3 );
	for ( int i = 0; i < coordinatesLength; i += 3 )
		coords.emplace_back( Vector3f( coordinates[i], coordinates[i + 1], coordinates[i + 2] ) );

	PointCloud* pc = new PointCloud();
	pc->points.vec_ = coords;

	return pc;
}

And since I am only interested in IDs of points in the point cloud, this is how I modified your suggestion:

PINVOKE int* SamplePointCloud( PointCloud* pc, const float coordinates[], const int coordinatesLength )
{
	std::vector<Vector3f> samplePoints( coordinatesLength / 3 );
	for ( int i = 0; i < coordinatesLength; i += 3 )
		samplePoints.push_back( Vector3f( coordinates[i], coordinates[i + 1], coordinates[i + 2] ) );

	int * pointIds = new int[coordinatesLength / 3];
	MR::ParallelFor( samplePoints, [&] ( size_t i )
	{
		pointIds[i] = ( uint32_t )findProjectionOnPoints( samplePoints[i], *pc ).vId;
	} );

	return pointIds;
}

Any ideas what could be wrong with this code?

from meshlib.

mariuszhermansdorfer avatar mariuszhermansdorfer commented on May 18, 2024

Ah, sorry rookie mistake with how I created the vectors... This code doesn't crash but only returns -1 as pointIds.

PINVOKE PointCloud* CreatePointCloud( const float coordinates[], const int coordinatesLength )
{
	std::vector<MR::Vector3f> coords( coordinatesLength / 3 );
	for ( size_t i = 0, j = 0; i < coordinatesLength; i += 3, j++ )
		coords[j] = ( Vector3f( coordinates[i], coordinates[i + 1], coordinates[i + 2] ) );

	PointCloud* pc = new PointCloud();
	pc->points.vec_ = coords;

	return pc;
}
PINVOKE int* SamplePointCloud( PointCloud* pc, const float coordinates[], const int coordinatesLength )
{
	std::vector<Vector3f> samplePoints( coordinatesLength / 3 );
	for ( size_t i = 0, j = 0; i < coordinatesLength; i += 3, j++ )
		samplePoints[j] = Vector3f( coordinates[i], coordinates[i + 1], coordinates[i + 2] );

	int* pointIds = new int[coordinatesLength / 3];
	MR::ParallelFor( samplePoints, [&] ( size_t i )
	{
		pointIds[i] = ( uint32_t )findProjectionOnPoints( samplePoints[i], *pc ).vId.get();
	} );

	return pointIds;
}

from meshlib.

Fedr avatar Fedr commented on May 18, 2024

After these lines

	PointCloud* pc = new PointCloud();
	pc->points.vec_ = coords;

please add

	pc->validPoints.resize( pc->points.size(), true );

(otherwise it is considered that all points in the vector are invalid.)

And as to memory leaks, they are because you use raw owning pointers and probably forget to deallocate objects manually. Please replace PointCloud* with std::unique_ptr<PointCloud> or std::shared_ptr<PointCloud> or just PointCloud, e.g.:

PointCloud CreatePointCloud( const float coordinates[], const int coordinatesLength )
{
	PointCloud pc;
	pc.points.reserve( coordinatesLength / 3 );
	for ( size_t i = 0, j = 0; i < coordinatesLength; i += 3, j++ )
		pc.points.push_back( Vector3f( coordinates[i], coordinates[i + 1], coordinates[i + 2] ) );

	pc.validPoints.resize( pc.points.size(), true );
	return pc;
}

from meshlib.

mariuszhermansdorfer avatar mariuszhermansdorfer commented on May 18, 2024

Thanks @Grantim,

this was the missing piece:

pc->validPoints.resize( pc->points.size(), true );

Now, sampling works but it returns weird results. To make sure we are on the same page, my point cloud is volumetric, this is its side view:
image

The name findProjectionOnPoints implies that it gets flattened somehow. Is that correct? I'm trying to find the closest point in the 3d space, not projected on a plane.

from meshlib.

mariuszhermansdorfer avatar mariuszhermansdorfer commented on May 18, 2024

Sorry, my bad. The mistake was elsewhere. Now, everything works very well!

Another question, can I trim the original point cloud with a box while preserving the original point indexing?

from meshlib.

Fedr avatar Fedr commented on May 18, 2024

You can set the bits in pc->validPoints to false for the points outside the box, and then call pc->invalidateCaches().

from meshlib.

mariuszhermansdorfer avatar mariuszhermansdorfer commented on May 18, 2024

Thanks @Fedr, and how do I identify the inside/outside bits given the point cloud and the box?

from meshlib.

Grantim avatar Grantim commented on May 18, 2024

Thank you!

from meshlib.

mariuszhermansdorfer avatar mariuszhermansdorfer commented on May 18, 2024

Apologies for reopening. I remember there was a function to create a regular grid of points based on a rectangle and desired resolution. Could you please help me find it?

Inputs: MinCoordinate, MaxCoordinate, Resolution
Output: Vector of points

from meshlib.

Grantim avatar Grantim commented on May 18, 2024

I don't think we had anything like this, maybe you mean these functions?

// Creates regular mesh with points in valid grid lattice
MRMESH_API Mesh makeRegularGridMesh( size_t width, size_t height,
const RegularGridLatticeValidator& validator,
const RegularGridLatticePositioner& positioner,
const RegularGridMeshFaceValidator& faceValidator = {} );
// Creates regular mesh from monotone (connects point with closed x, y neighbors) points
MRMESH_API Expected<Mesh, std::string> makeRegularGridMesh( VertCoords pc, ProgressCallback cb = {} );

from meshlib.

mariuszhermansdorfer avatar mariuszhermansdorfer commented on May 18, 2024

Yes, this one!

How can I use this to make a regular grid with a user-defined resolution based on a rectangle oriented in an arbitrary plane?

from meshlib.

Grantim avatar Grantim commented on May 18, 2024

You can call it like this:

// user defined width and height
// RegularGridLatticeValidator - always return true so all points will be present
// RegularGridLatticePositioner - returns position of point with given x and y
auto resMesh = makeRegularGridMesh( width, height, [&]( size_t, size_t ) { return true; },  
[&]( size_t x, size_t y) { return Vector3f(/* defined position of this point based on rectangle orientation*/); } );

this will result as grid mesh with points in positions from RegularGridMeshFaceValidator callback

from meshlib.

mariuszhermansdorfer avatar mariuszhermansdorfer commented on May 18, 2024

Sorry @Grantim, but I think I need more help here.

Given the following inputs:
rectangle width = 100;
rectangle height = 50;
rectangle minPoint = {0, 0, 0)}:
rectangle normalVector = {0.826724, -0.0802, 0.556862}
grid resolution = 1;

How can I get the desired grid of 100 x 50 points aligned with the input rectangle?
image

I only understand the width/height part but am not sure how to set the rest.

auto resMesh = makeRegularGridMesh( 100, 50, [&]( size_t, size_t ) { return true; },  
[&]( size_t x, size_t y) { return Vector3f(/* defined position of this point based on rectangle orientation*/); } );

from meshlib.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.