Calculate 3D Plane that Rests on a 3D Surface - python

I have about 300,000 points defining my 3D surface. I would like to know if I dropped a infinitely stiff sheet onto my 3D surface, what the equation of that plane would be. I know I need to find the 3 points the sheet would rest on as that defines a plane, but I'm not sure how to find my 3 points out of the ~300,000. You can assume this 3D surface is very bumpy and that this sheet will most likely lie on 3 "hills".
Edit: Some more background knowledge. This is point cloud data for a scan of a 3D surface which is nearly flat. What I would like to know is how this object would rest if I flipped it over and put it on a completely flat surface. I realize that this surface may be able to rest on the table in various different ways depending on the density and thickness of the object but you can assume the number of ways is finite and I would like to know all of the different ways just in case.
Edit: After looking at some point cloud libraries I'm thinking of doing something like computing the curvature using a kd tree (using SciPy) and only looking at regions that have a negative curvature and then there should be 3+ regions with negative curvature so some combinatorics + iterations should give the correct 3 points for the plane(s).

Related

Determining Best Fit Center of Scattered 3D Points

I am attempting to find the center of several sets of 3D points on a sphere. Each set is comprised of three or more points that fall on the arc of a circle, but not perfectly as they have been supplied by an object detection algorithm, so there is some inherent error in these points. This is for me where the difficulty lies, I cannot simply solve the equations, I need to try and minimize variance in radius to this point across all three-point sets.
Currently, I am calculating a plane of best fit for each set of points. By calculating the radius (perpendicular distance) to this normal for each set and determining the variance I can figure out which plane (normal or center of rotation) fits all three sets the best. I am also doing this for an average of the three planes and for two planes after throwing out the plane that agrees least with the other two. So I am getting a pretty decent approximation currently.
My question is, does anyone know how to implement in Python some sort of function that can help me find a normal vector through these points that minimize the variance in radius for all sets. I suspect this won't be far off my current approximation, but am looking for the most accurate solution to this problem.
The picture below shows the results of what I am currently doing. The pink points represent the points I am using, labeled 0,1,2 for each set of points. The blue dots represent the normal vector projected to the surface of the sphere. The orange is the average of the three blue dots projected to the surface of the sphere. Ignore green they are not relevant to this. To minimize the variance my code is currently telling me that axis (blue dot) 0 results in the least variance in radius for the data set as a whole, but I highly doubt it is the best fitting point.

How to check 3D plots within reference path?

For a drone competition, I have:
A- reference 3D trajectory (around 30 points or less)
B- tolerance from that ideal trajectory (say in cm or less)
C- experimental 3D points read from the drone's GPS (about 5000 points)
A bit like in:
RED: reference (A)
BLUE: experimental (C)
GREEN: "tolerance" (A+B, well not really, but you get the idea...)
I'd like to know the best way to check that the "experimental 3D points" (C) all falls within the "reference 3D trajectory" (A) plus/minus the expected "tolerance" (B).
Closest matches I've found here is:
Finding out if a curve is inside or outside a boundary in python. X axis with different resolutions (python)
Approximating data with a multi segment cubic bezier curve and a distance as well as a curvature contraint
Fit Curve-Spline to 3D Point Cloud
How to compare two 3D curves in Python?
https://stackoverflow.com/questions/8980101/what's-the-best-method-to-compare-original-trajectory-with-two-compressed-trajec
From github I've found something close:
https://pypi.org/project/similaritymeasures/
Yet I'd like to be sure I can compare trajectories with different number of points ("reference" +/- "tolerance" provides a simplified "tunnel"). That difference of dataset is the main drawback, since the drone can stop, perhaps even go backward a little before resuming the race.
Maybe displaying the result using Mathpy and/or Payton as well.
While the timing is a factor, it would be nice to do some stats like the min/max deviation from the "reference 3D trajectory" (A).
Probably out of scope, but:
https://www.researchgate.net/publication/281188521_Model_Predictive_Path-Following_Control_of_an_ARDrone_Quadrotor
https://www.researchgate.net/publication/247935750_UAV_Motion_Estimation_using_Hybrid_Stereoscopic_Vision

Python library for rotation and translation on a seesaw-like object

I'd like to do calculations on the 3D positions on both end's of a rigid object (see spot where the children are usually sitting in image below). The geometrical situation of the rigid object corresponds to a seesaw. Rotation has to be possible on three axes and can be represented by a ball bearing, which initially is located at the middle of the rod.
The input to the desired function should consist of three rotations performed at the position of the ball bearing, three translations along the bearing and the initial 3D positions of both ends of the object.
The output needs to be the calculated new 3D positions of both ends.
Does anyone know a python library that does provide functionalities regarding this issue?
I've just found out that Open3D has implemented exactly what I was looking for. As it is working with point clouds, all that needs to be done is to create two points in 3D space, define a rotation matrix and the center (= ball bearing in this case). The function "rotate" then calculates the altered positions of the rotated points. This also works for translation.
# Rotation
pcd.rotate(r, center = (0,0,0))
# Translation
pcd.translate(t)
With r = rotation matrix (3x3) and t = translation matrix (3x1).

Noisy 3D point cloud to interpolated surface mesh in python

My general goal is going from a noisy point cloud describing a surface, to a regular surface mesh, in Python. I have found a few solution to this problem, none of which apply to my case well enough. The best ones I found:
B-spline -> sample it -> get new points. This calculates the z values of a function based on a regular set of x,y coordinates, which won't work well for near-vertical surfaces, of which I have a lot.
Rolling ball / convex hull algorithms. My data is noisy along the normal to the surface, so I would get a surface that's "inflated". I would need first to denoise it, which itself requires the calculation of a spline, or something similar.
I feel like there must be an "easy" way to do this, but I just don't know what to look for. Can someone point me in the right direction?
My best guess is that there should be a way to sample a spline surface "regularly" relatively to itself, but I can't figure out how.
The problem which you describe is named surface reconstruction. There is many algorithms and software (standalone program or libraries) able to reconstruct one surface from a set of sample points. There is important differences depending if you have only the XYZ coordinates of the points, or you have more information as the color or the normal to the surface.
Naming some examples, you can use:
Screened Poisson, by Kazhdan and Bolitho. Which is implemented in meshlab, and many other python libraries. Probably your best option.
PowerCRUST, by Nina Amenta, Sunghee Choi and Ravi Kolluri.
Ball Pivoting, by Bernardini, Mittleman, et al. Quite simple and easy to implement by yourself.

Getting approximate vertices of curved-edge closed shapes (for calculating centroid and other properties)

I'm looking to draw outlines of 2D-closed irregular shapes with curved edges, and then compute both (a) the center of gravity (centroid) of the shape's area, and (b) the center of gravity of the shape's perimeter (i.e. the centroid of, e.g., a wire wrapped tightly around the outside of the shape). I have a late-beginner's level proficiency with Python and Matlab.
(a) and (b) are easy enough given a polygon's vertices: the centroid of a polygon's area is given by the equation here, and the centroid of a polygon's perimeter is just the average of all the line segments' midpoints weighted by the line segments' lengths. I've already written some functions to do this.
The trouble I'm having is getting/approximating those vertices from any of the ways I know how to draw a closed shape with curved edges. The best solution I've come up with so far is to use something like this matplotlib-based script to draw the curvy shape, and then call path.to_polygons(), which converts Path objects to polygons — but does so with surprisingly low resolution, such that the resulting approximation is quite poor (and too poor for my purposes — I'd like to compute those centroids fairly precisely).
So, I'm looking to either (i) find some way to increase the resolution of .to_polygons (about 10-fold), which would be satisfactory for my purposes, or (ii) try some new strategy entirely. One option would be to draw the shapes using something like Adobe Illustrator and then get an approximation of their vertices via some plugin or maybe an image processing toolbox (but I have no clue how to do either of those things). Another would be to draw the shape using some toolbox/library that already has built-in functions for finding the centroids of areas and perimeters (I've seen some having the former, but none with the latter). But I'm sure there are many other options out there that I haven't considered.

Categories