I have 2 sets of points in 3D have the same count, I want to know if the have the same pattern, I thought I may project them on XZ,XY and YZ planes then compare the projections in each plane but I am not sure how to do this, I thought the convex hull may help but it won't be accurate.
Is there an easy algorithm to do that? the complexity is not a big issue so far as the points count will be tiny, I implement in Java.
Can I solve this in 3D direct with the same algorithm ?
The attached image shows an example of what I mean.
Edit:
No guarantee for order.
No scale, there are rotation and translation only.
I would gather some information about each point: information that only depends on "shape", not on the actual translation/rotation. For instance, it could be the sum of all the distances between the point and any other point of the shape. Or it could be the largest angle between any two points, as seen from the point under consideration. Choose whatever metric brings the most diversity.
Then sort the points by that metric.
Do the above for both groups of points.
As a first step you can compare both groups by their sorted list of metrics. Allow for a little error margin, since you will be dealing with floating point precision limitations. If they cannot be mapped to each other, abort the algorithm: they are different shapes.
Now translate the point set so that the first point in the ordered list is mapped to the origin (0, 0, 0), i.e. subtract the first point from all points in the group.
Now rotate the point set around the Y axis, so that the second point in the ordered list coincides with XY plane. The rotate the point set around the Z axis, so that that point coincides with the X-axis: it should map to (d, 0, 0), where d is the distance between the first and second point in the sorted list.
Finally, rotate the point set around the X axis, so that the third point in the ordered list coincides with the XY plane. If that point is colinear with the previous points, you need to continue doing this with the next point(s) until you have rotated a non-colinear point.
Do this with both groups of points. Then compare the so-transformed coordinates of both lists.
This is the main algorithm, but I have omitted the cases where the metric value is the same for two points, and thus the sorted list could have permutations without breaking the sort order:
In that case you need to perform the above transformations with the different permutations of those equally valued points at the start of the sorted list, for as long as there is no fit.
Also, while checking the fit, you should take into account that the matching point may not be in the exact same order as in the other group's sorted list, and you should verify the next points that have the same metric as well.
If you have a fixed object with different shapes and movements, pair-wise- or multi-matching can be a helpful solution for you. For example see this paper. This method can be extended for higher-dimensions as well.
If you have two different sets of points that come from different objects and you find the similarity between them, one solution can be computing discrete Frechet distance in both sets of points and then compare their value.
The other related concept is Shape Reconstruction. You can mix the result of a proper shape reconstruction algorithm with two previous methods to compute the similarity:
Related
Multiple points on a 2D plane are given. They represent a window frame of mostly rectangular form with some possible variations. The points which are part of each side are not guaranteed to form a perfect line. Each side of the window should be measured.
A rotating electronic device attached to a window measures the distance in all directions providing a 360 degree measurements. By using the rotation angle and the distance, a set of points are plotted on a 2D coordinate system. So far so good.
Now comes the harder part. The measured window frame could have some variations. The points should be converted to straight lines and the length of each line should be measured.
I imagine that the following steps are required:
Group the different points into straights lines. This means approximating each line “between” the points that form it.
Drawing those lines, getting rid of the separate points used to construct the lines.
Find the points where each two lines intersect.
Measure the distance between those points. However not all distances between all points are interesting. For example diagonals within a frame are irrelevant.
Any Java libraries dealing with geometry that could solve the problem are acceptable. I will write the solution in Kotlin/Java, but any algorithmic insights or code examples and ideas in any other languages or pseudo code are welcome.
Thank you in advance!
New Image
I would solve this in 2 stages:
Data cleaning: round the location (X, Y) of each point to its nearest multiple of N (vary N for varying degrees of precision)
Apply the gift-wrapping algorithm (also known as Jarvis March)
You now have only those points that are not co-linear, and the lines between them, and the order in which they need to be traversed to form the perimeter.
Iterate over the points in order, take point Px and P(x+1), and calculate the distance between them.
I'm trying to design a data-structure to hold/express a piecewise circular trajectory in the Euclidian plane. The trajectory is constrained to be continuous and have finite curvature everywhere, and therefore the circular arcs meet tangentially.
Storing all the circle centers, radii, and touching points would allow for inspecting the geometry anywhere in O(1) but would require explicit enforcement of the continuity and curvature constraints due to data redundancy. In my view, this would make the code messy.
Storing only the circle touching points (which are waypoints along the curve) along with the curve's initial direction would be sufficient in principle, and avoid data redundancy, but then it would be necessary to do an O(n) calculation to inspect the geometry of arc n, since that arc depends on all the arcs preceding it in the trajectory.
I would like to avoid data redundancy, but I also don't want to make the cost of geometric inspection prohibitive.
Does anyone have any high-level idea/advice to share?
For the most efficient traversal of the trajectory, if I am right you need
the ending curvilinear abscissas of every arc (cumulative),
the radii,
the starting angles,
the coordinates of the centers,
so that for a given s you find the index of the arc, then the azimuth and the coordinates of the point. (Either incrementally for a sequence of points, or by dichotomy for a single point.) That takes five parameters per arc.
Only the cumulative abscissas are global, but you can't do without them for single-point accesses. You can drop the radii and starting angles and retrieve them for any arc from the difference of curvilinear abscissas and the limit angles (see below). This reduces to three parameters.
On the other hand, knowing just the coordinates of the centers and those of the starting and ending points is enough to recover the whole geometry, and this takes two parameters per arc.
The meeting point of two arcs is found on the line through the centers, and if you know one radius, the other follows. And the limit angle is given by the direction of the line. So for an incremental traversal, this non-redundant description can do.
For convenient computation, knowing s and the arc index, consider the vectors from the center to the centers of the adjoining arcs. Rotate them so that the first becomes horizontal. The components of the other will give you the amplitude angle. The fraction (s - Si-1) / (Si - Si-1) of the amplitude gives you the azimuth of the point, to which you apply the counter-rotation.
I'd store items with the data required to get info for any point of that element. For example, an arc needs x, y, initial direction, radius, lenght (or end point, or angle difference or whatever you find easiest).
Because you need continuity (same x,y, same bearing, perhaps same curvature) between two ending points then a node with this properties is needed. Notice these properties are common to arcs and straights (a special arc identified by radius = 0). So you can treat a node the same as an item.
The trajectory should be calculated before any request. So you have all items-data in advance.
The container depends on how you request info.
If the trajectory can be somehow represented in a grid, then you better use a quad-tree.
I guess you must find the item from a x,y or accumulated length input. You will have to iterate through the container to find the element closest to the input data. Sorted data may help.
My choice is a simple vector with the consecutive elements, which happens to be sorted on accumulated trajectory length.
Finding by x,y on a x-sorted container (or a tree) is not so simple, due to some x,y may have perpendiculars to several items, consecutive or not, near or not, and you need to select the nearest one.
I have a set of 3d points that lie in a plane. Somewhere on the plane, there will be a hole (which is represented by the lack of points), as in this picture:
I am trying to find the contour of this hole. Other solutions out there involve finding convex/concave hulls but those apply to the outer boundaries, rather than an inner one.
Is there an algorithm that does this?
If you know the plane (which you could determine by PCA), you can project all points into this plane and continue with the 2D coordinates. Thus, your problem reduces to finding boundary points in a 2D data set.
Your data looks as if it might be uniformly sampled (independently per axis). Then, a very simple check might be sufficient: Calculate the centroid of the - let's say 30 - nearest neighbors of a point. If the centroid is very far away from the original point, you are very likely on a boundary.
A second approach might be recording the directions in which you have neighbors. I.e. keep something like a bit field for the discretized directions (e.g. angles in 10° steps, which will give you 36 entries). Then, for every neighbor, calculate its direction and mark that direction, including a few of the adjacent directions, as occupied. E.g. if your neighbor is in the direction of 27.4°, you could mark the direction bits 1, 2, and 3 as occupied. This additional surrounding space will influence how fine-grained the result will be. You might also want to make it depend on the distance of the neighbor (i.e. treat the neighbors as circles and find the angular range that is spanned by the circle). Finally, check if all directions are occupied. If not, you are on a boundary.
Alpha shapes can give you both the inner and outer boundaries.
convert to 2D by projecting the points onto your plane
see related QA dealing with this:
C++ plane interpolation from a set of points
find holes in 2D point set
simply apply this related QA:
Finding holes in 2d point sets?
project found holes back to 3D
again see the link in #1
Sorry for almost link only answer but booth links are here on SO/SE and deals exactly with your issue when combined. I was struggling first to flag your question as duplicate and leave this in a comment but this is more readable.
I've got question about algorithms to compare if two sets of points are in a similar place on the image.
They don't create similar shapes likes circles, rectangles etc, but they are something like irregular clouds.
For example:
The first cloud of points is learning set of desired area on image and we are checking if second cloud is in similar position.
I was thinking of drawing simple shapes to form points (like rectangles which will accumulate all points) and checking if one is in another or distance between centers of figures, but this method doesn't seem to be very accurate.
Are there better algorithms to solve this problem?
Image Moments
Don't worry about the fancy name, it's just a standard method in image processing to do exactly what you require.
Image moment of power n w.r.t. x and m w.r.t. y is actually the
integration of (pixel value * xPosition^n * xPosition^m) over the
entire image.
So (0, 0)th order moment i.e moment(0, 0) is actually area of the cloud.
Similarly, moment(1, 0)/moment(0, 0) is X coordinate of centroid of the cloud.
And, moment(0, 1)/moment(0, 0) is Y coordinate of centroid of the cloud.
Higher order moments give additional features/information peculiar to shape of the clouds.
Now you can easily compare the arbitrary shapes.
These functions are available in opencv and matlab.
Hope this helps.
Good luck.
Sets will have quite similar shapes (it will be set of points of human skeleton from kinect > sensor) and I want to check if person is sitting in the same place as it was learned in the > first place
Then you will probably be able to derive a correspondence between two points (i.e. you will know that a given point is SHOULDER_RIGHT or ELBOW_LEFT or...). If that is the case you can simply calculate the SUM(SQRT((Xi1-Xi2)^2+(Yi1-Yi2)^2) for each i-th pair of points (X1,Y1) and (X2,Y2) (same goes if you can obtain the third dimension Z).
The value thus obtained will have a minimum of zero when the two sets of points are perfectly coinciding.
I have lists of points in 3d (x,y,z)
For each list I want to divide that list into to two lists, one containing points from upper part of profile and second the lower half, just like that:
My question here is how to determine which point should go to upper-part and which one should go to lower part just from having those points with their coordinates (x,y,z).
Since points can be split in 'halves' in a lot of ways, it is good to have more criteria how to split them.
In this case it seems like you are looking for a curve, that splits point cloud, which has a shape similar to that cloud. Fitting curve of type that can cover your shapes can help. Probably polynomial of second or third order are good for these shapes.
Second idea is to create something that goes through 'middle of geometry'. In 2D case you could use medial axis approach. It can be computed for point cloud by Delaunay triangulation. If points are near some plane, you can project them on the plane and use this approach.
First, create "lines" between each adjacent point. Assuming the points are given in order around the loop, this should be easy.
Then, cast a line from 0,0(upper left) to each point. If it intersects another line to get there, it's not on the upper side. If it doesn't, it is.
It's O(n^2), so I'm sure there is a better solution, but for small sets of points, it should be fine. Note that it won't work on extremely concave shapes, but will for all of those shown.
Join adjacent edges to get lines.. Taking anticlockwise angles as positive..
In the upper part of the cloud, successive lines have increasing angles..
while in the lower part the successive lines have decreasing angles..
A lil trial and error should lead you to an appropriate hueristic..