Initiating Jarvis' March (gift-wrapping) for convex hulls - convex-hull

I am trying to implement the giftwrapping algorithm on a set of points to find their convex hull.
It says that the next point in the convex hull is the leftmost point (this is from wikipedia) from the point of view of the last point found. However, I'm not sure as to how you are supposed to find the second point because you only have one point so far.
If the last point found is p' and the one before p' is p'', I thought the newest point would be point p that forms the largest angle with vector (p'',p'). However, when finding the second point, we do not have a p''.

As seanmcl says, this is not an OCaml question. Reading Wikipedia it looks to me like you're looking for the biggest angle with most recent point pi as center, relative to a line passing through pi, where all points of the hull are on one side of the line (or on the line). For the second point looks like you can use a vertical line (if you start with the leftmost or rightmost point). After that you can use a line through the most recent two points.

Related

Oriented Bounding Box algorithm, Need some understanding/clarification of a few lines of existing (working) code

I am reviewing some MATLAB code that is publicly available at the following location:
https://github.com/mattools/matGeom/blob/master/matGeom/geom2d/orientedBox.m
This is an implementation of the rotating calipers algorithm on the convex hull of a set of points in order to compute an oriented bounding box. My review was to understand intuitively how the algorithm works however I seek clarification on certain lines within the file which I am confused on.
On line 44: hull = bsxfun(#minus, hull, center);. This appears to translate all the points within the convex hull set so the calculated centroid is at (0,0). Is there any particular reason why this is performed? My only guess would be that it allows straightforward rotational transforms later on in the code, as rotating about the real origin would cause significant problems.
On line 71 and 74: indA2 = mod(indA, nV) + 1; , indB2 = mod(indB, nV) + 1;. Is this a trick in order to prevent the access index going out of bounds? My guess is to prevent out of bounds access, it will roll the index over upon reaching the end.
On line 125: y2 = - x * sit + y * cot;. This is the correct transformation as the code behaves properly, but I am not sure why this is actually used and different from the other rotational transforms done later and also prior (with the calls to rotateVector). My best guess is that I am simply not visualizing what rotation needs to be done in my head correctly.
Side note: The external function calls vectorAngle, rotateVector, createLine, and distancePointLine can all be found under the same repository, in files named after the function name (as per MATLAB standard). They are relatively uninteresting and do what you would expect aside from the fact that there is normalization of vector angles going on.
I'm the author of the above piece of code, so I can give some explanations about it:
First of all, the algorithm is indeed a rotating caliper algorithm. In the current implementation, only the width of the algorithm is tested (I did not check the west and est vertice). Actually, it seems the two results correspond most of the time.
Line 44 -> the goal of translating to origin was to improve numerical accuracy. When a polygon is located far away from the origin, coordinates may be large, and close together. Many computation involve products of coordinates. By translating the polygon around the origin, the coordinates are smaller, and the precision of the resulting products are expected to be improved. Well, to be honest, I did not evidenced this effect directly, this is more a careful way of coding than a fix…
Line 71-74! Yes. The idea is to find the index of the next vertex along the polygon. If the current vertex is the last vertex of the polygon, then the next vertex index should be 1. The use of modulo rescale between 0 and N-1. The two lines ensure correct iteration.
Line 125: There are several transformations involved. Using the rotateVector() function, one simply computes the minimal with for a given edge. On line 125, one rotate the points (of the convex hull) to align with the “best” direction (the one that minimizes the width). The last change of coordinates (lines 132->140) is due to the fact that the center of the oriented box is different from the centroid of the polygon. Then we add a shift, which is corrected by the rotation.
I did not really look at the code, this is an explanation of how the rotating calipers work.
A fundamental property is that the tightest bounding box is such that one of its sides overlaps an edge of the hull. So what you do is essentially
try every edge in turn;
for a given edge, seen as being horizontal, south, find the farthest vertices north, west and east;
evaluate the area or the perimeter of the rectangle that they define;
remember the best area.
It is important to note that when you switch from an edge to the next, the N/W/E vertices can only move forward, and are readily found by finding the next decrease of the relevant coordinate. This is how the total processing time is linear in the number of edges (the search for the initial N/E/W vertices takes 3(N-3) comparisons, then the updates take 3(N-1)+Nn+Nw+Ne comparisons, where Nn, Nw, Ne are the number of moves from a vertex to the next; obviously Nn+Nw+Ne = 3N in total).
The modulos are there to implement the cyclic indexing of the edges and vertices.

How to check if given 3d point is outside convex hull

I'm working on a science project. I have a list of xyz-coordinates of voronoi diagram vertices, and a list of points that create my protein's convex-hull (from triangulation). Now some of the vertices lie quite far from the hull and I'd like to filter them out. How can I do it in c++ ? For now it doesn't have to be super optimised, I'm only focused on removing those points.
visualization
I was also thinking to check if a line from voronoi vertex(red crosses) to center of protein(pink sphere) is intersecting with hull face at any point, but I'm not sure how to achive that.
I've read that you can check if a point is inside a polygon by counting the times an infinite line from the point is crossing the hull, but that was for two dimensions. Can similar approach be implemented to suit my needs ?
https://www.geeksforgeeks.org/how-to-check-if-a-given-point-lies-inside-a-polygon/
Let's start with the two-dimensional case. You can find the solution to that on CS.SX:
Determine whether a point lies in a convex hull of points in O(logn)
The idea is that each two consecutive points on the convex hull define a triangular slice of the plane (to some internal point of the hull); you can find the slice in which your point is located, and check whether it's closer to the internal point than the line segment bounding the slide.
For the three-dimensional case, I'm guessing you should be able to do something similar, but the search for the 3 points forming the relevant triangle might be a little tricky. In particular, it would also depend on how the convex hull is represented - as in the 2-d case the convex hull is just a sequence of consecutive points on a cycle.
I know this doesn't quite solve your problem but it's the best I've got given what you've written...

Indexing along a line of 3 D array

Consider a line joining two point X(a, b, c) and Y(d, e, f)in a 3 dimension array. How to find indices of all points in between them along the line, except Least square?
You should definitely stay away from least squares, which would browse the entire 3D space if I understood you correclty. Instead, have a look at Bresenheim's Line Algorithm.
Basically you start with the starting cube, compute the line's gradient in each XYZ direction, and start marching.
You alternate marching in X (for example) direction until the line is no longer inside the cube, then you switch to whichever other direction (Y, Z) brings the line back into the current cube. And so on an so forth until the current cube is the target.
All usual links are in 2D, but the process in 3D is exactly the same.
The trickier bits resides in choosing which direction to start matching. There's an algo in 3D, which whould be adapted to 2D.
Notes:
A cool optimization is, each time you march in a given direction, you can march Nx, or Ny, or Nz steps straight. these 3 numbers can be computed before hand and will never change.
A cooler optimization, is, you should only have to compute the order of X-Y-Z iteration (which might well be Y,X,Z in some cases) only once, at the beginning. Then the marching is nicely periodic and should stay the same until the target is reached.

Finding the concavness pixel/point in binary map using Matlab

Given an binary mask with an object in Matlab. I am going to find the concavity point of the object boundary. The concavity point I mean here is the deepest concavity point with respect to the Euclidean distance to the convex hull chords K_1, K_2 ,and K_3 in the concavity regions B_1, B_2, B_3, respectively. The red dot indicates the concavity point I want to find, where in concavity region B_1 I draw three lines perpendicular to the chord K_1, the deepest concavity point is the middle one since it has the largest length.
Anyone have efficient way/code to do that? Thanks.
Another figure below gives an example with the convex hull, where the red dot indicates the valid concavity point.
Efficient is relative...
How about computing the convex hull (there are standard algorithms for it) and then shrinking it until it is completely inside the object boundaries. The last point touching is your desired concavity point.
Alternative strategy:
calculate convex hull
find all differences between convex hull and object boundary (have to be straight lines, K1 K2 K3 in your case)
for every line, rotate image such that line is horizontal
take the lowest pixel of the object boundary below the line

Drawing a bezier from multiple points

I have a set with 50 points in x,y. I need to draw the smoothest bezier that passes in all points, or in other words, the bezier that will best fit the points.
How do I do that? thanks
I am undergoing a similar problem in 3D. It is slightly easier in 2D because lines will always intersect if not parallel.
Firstly, read up on quadratic bezier curves. Each curve is represented by three points. The line will not pass through the middle point. Thus, your middle point cannot be one of the points you are trying to fit, or it won't go through it.
Instead, the beginning and end point of your quadratic bezier curve must be two consecutive points you want it to pass through. So what is your middle point going to be?
One way of solving this (never tried it myself HENCE it might not look perfect, but Im thinking off the top of my head) is to calculate the tangents from your -1st data point to your 0th data point, and find the intersection between that and the 1st data point to the 2nd data point. Then draw the line between the 0th data point and the 1st data point using this intersection as the middle bezier curve value.
Obviously you may have trouble at the ends of the curves, that may require some inventive thinking to make them look good. (the first point has no -1st point).
Sorry about the lack of diagrams. I would draw one but I'm on an iPad.
Imagine 3-point bezier curve (start-A, middle-B, end-C)
Imagine a straight line from A to C.
Imagine a straight line that is perpendicular to AC and goes through point B.
Those two lines cross in point D.
Bezier curve will go through EXACTLY half way from D to B. In other words if you want bezier curve that goes through 3 points, you must make the second point 2 times further from start and end than the actual second point.