Why do we need to triangulate a convex polygon in order to sample uniformly from it? - matlab

Suppose I want to uniformly sample points inside a convex polygon.
One of the most common approaches described here and on the internet in general consists in triangulation of the polygon and generate uniformly random points inside each triangles using different schemes.
The one I find most practical is to generate exponential distributions from uniform ones taking -log(U) for instance and normalizing the sum to one.
Within Matlab, we would have this code to sample uniformly inside a triangle:
vertex=[0 0;1 0;0.5 0.5]; %vertex coordinates in the 2D plane
mix_coeff=rand(10000,size(vertex,1)); %uniform generation of random coefficients
x=-log(x); %make the uniform distribution exponential
x=bsxfun(#rdivide,x,sum(x,2)); %normalize such that sum is equal to one
unif_samples=x*vertex; %calculate the 2D coordinates of each sample inside the triangle
And this works just fine:
However, using the exact same scheme for anything other than a triangle just fails. For instance for a quadrilateral, we get the following result:
Clearly, sampling is not uniform anymore and the more vertices you add, the more difficult it is to "reach" the corners.
If I triangulate the polygon first then uniform sampling in each triangle is easy and obviously gets the job done.
But why? Why is it necessary to triangulate first?
Which specific property have triangle (and simplexes in general since this behaviour seems to extend to n-dimensional constructions) that makes it work for them and not for the other polygons?
I would be grateful if someone could give me an intuitive explanation of the phenomena or just point to some reference that could help me understand what is going on.

I should point out that it's not strictly necessary to triangulate a polygon in order to sample uniformly from it. Another way to sample a shape is rejection sampling and proceeds as follows.
Determine a bounding box that covers the entire shape. For a polygon, this is as simple as finding the highest and lowest x and y coordinates of the polygon.
Choose a point uniformly at random in the bounding box.
If the point lies inside the shape, return that point. (For a polygon, algorithms that determine this are collectively called point-in-polygon predicates.) Otherwise, go to step 2.
However, there are two things that affect the running time of this algorithm:
The time complexity depends greatly on the shape in question. In general, the acceptance rate of this algorithm is the volume of the shape divided by the volume of the bounding box. (In particular, the acceptance rate is typically very low for high-dimensional shapes, in part because of the curse of dimensionality: typical shapes cover a much smaller volume than their bounding boxes.)
Also, the algorithm's efficiency depends on how fast it is to determine whether a point lies in the shape in question. Because of this, it's often the case that complex shapes are made up of simpler shapes, such as triangles, circles, and rectangles, for which it's easy to determine whether a point lies in the complex shape or to determine that shape's bounding box.
Note that rejection sampling can be applied, in principle, to sample any shape of any dimension, not just convex 2-dimensional polygons. It thus works for circles, ellipses, and curved shapes, among others.
And indeed, a polygon could, in principle, be decomposed into a myriad of shapes other than triangles, one of those shapes sampled in proportion to its area, and a point in that shape sampled at random via rejection sampling.
Now, to explain a little about the phenomenon you give in your second image:
What you have there is not a 4-sided (2-dimensional) polygon, but rather a 3-dimensional simplex (namely a tetrahedron) that was projected to 2-dimensional space. (See also the previous answer.) This projection explains why points inside the "polygon" appear denser in the interior than in the corners. You can see why if you picture the "polygon" as a tetrahedron with its four corners at different depths. With higher dimensions of simplex, this phenomenon becomes more and more acute, again due partly to the curse of dimensionality.

Well, there are less expensive methods to sample uniform in the triangle. You're sampling Dirichlet distribution in the simplex d+1 and taking projection, computing exponents and such. I would refer you to the code sample and paper reference here, only square roots, a lot simpler algorithm.
Concerning uniform sampling in complex areas (quadrilateral in your case) general approach is quite simple:
Triangulate. You'll get two triangles with vertices (a,b,c)0 and (a,b,c)1
Compute triangle areas A0 and A1 using, f.e. Heron's formula
First step, randomly select one of the triangles based on area.
if (random() < A0/(A0+A1)) select triangle 0 else select triangle 1. random() shall return float in the range [0...1]
Sample point in selected triangle using method mentioned above.
This approach could be easily extended to sample for any complex area with uniform density: N triangles, Categorical distribution sampling with probabilities proportional to areas will get you selected triangle, then sample point in the triangle.
UPDATE
We have to triangulate because we know good (fast, reliable, only 2 RNG calls, ...) algorithm to sample with uniform density in triangle. Then we could build on it, good software is all about reusability, and pick one triangle (at the cost of another rng call) and then back to sample from it, total three RNG calls to get uniform density sampling from ANY area, convex and concave alike. Pretty universal method, I would say. And triangulation is a solved problem, and
basically you do it once (triangulate and build weights array Ai/Atotal) and sample till infinity.
Another part of the answer is that we (me, to be precise, but I've worked with random sampling ~20years) don't know good algorithm to sample precisely with uniform density from arbitrary convex more-than-three-vertices closed polygon. You proposed some algorithm based on hunch and it didn't work out. And it shouldn't work, because what you use is Dirichlet distribution in d+1 simplex and project it back to d hyperplane. It is not extendable even to quadrilateral, not talking to some arbitrary convex polygon. And I would state conjecture, that even such algorithm exist, n-vertices polygon would require n-1 calls to RNG, which means there is no triangulation setup, but each call to get a point would be rather expensive.
Few words on complexity of the sampling. Assuming you did triangulation, then with 3 calls to RNG you'll get one point sampled uniformly inside your polygon.
But complexity of sampling wrt number of triangles N would be O(log(N)) at best. YOu basically would do binary search over partial sums of Ai/Atotal.
You could do a bit better, there is O(1) (constant time) sampling using Alias sampling of the triangle. The cost would be a bit more setup time, but it could be fused with triangulation. Also, it would require one more RNG calls. So for four RNG calls you would have constant point sampling time independent of complexity of your polygon, works for any shape

Related

How to find median trajectory of a spiral movement?

Lets some objects make complex spiral moving in 3D and we have get their trajectories projected on a plane.
How to find a median trajectory of such movements and estimate the amplitudes of spirals?
I assume that this requires averaging the coordinates of the trajectories, then somehow finding the distances from the extreme points of the trajectories to the midline. But I don't know a concrete algorithm for this. Can someone suggest this algorithm?
By median trajectory I mean a line that ges between path waves, something like linew on a picture below.
This is a case for a Kalman filter, but this method is a little complicated.
A simpler one is a moving average, with a number of samples that covers as closes as possible to a full period (which you can estimate visually).
Regarding the distances, you can compute the shortest Euclidean distance of every point to the midline (using a line-to-segment function). This will yield an alternating plot, which you can smoothen with a moving maximum (rather than average) over a period.

How to find distance mid point of bezier curve?

I am making game in Unity engine, where car is moving along the bezier curve by percentage of bezier curve legth.
On this image you can see curve with 8 stop points (yellow spheres). Between each stop point is 20% gap of total distance.
On the image above everything is working correctly, but when I move handles, that the handles have different length problem occurs.
As you can see on image above, distances between stop points are not equal. It is because of my algorithm, because I am finding point of segment by multiplying segment length by interpolation (t). In short problem is that: if t=0.5 it is not in the 50% percent of the segment. As you can see on first image, stop points are in half of segment, but in the second image it is not in half of segment. This problem will be fixed, if there is some mathematical formula, how to find distance middle point.
As you can see on the image above, there are two mid points. T param mid point can be found by setting t to 0.5 (it is what i am doing now), but it is not half of the distance.
How can I find distance mid point (for cubic bezier curve, that have handles in different distance)?
You have correctly observed that the parameter value t=0.5 is generally not the point in the middle of the length. That is a good start but the difficulty lies in the mathematics beneath.
Denoting the components of your parametric curve by x(t) and y(t), the length of the curve
between t=0 (the beginning) and a chosen parameter value t = u is equal to
What you are trying to do is to find u such that l(u) is one half of l(1). This is sometimes possible but often difficult or impossible. So what can you do?
One possibility is to approximate the point you want. A straightforward way is to approximate your Bezier curve by a piecewise linear curve (simply by choosing many parameter values 0 = t_0 < t_1 < ... < t_n = 1 and connecting the values in these parameters by line segments). Now it is easy to compute the entire length (Pythagoras Theorem is your friend) as well as the middle point (walk along the piecewise linear curve the prescribed length). The more points you sample, the more precise you will be and the more time your computation will take, so there is a trade-off. Of course, you can use a more complicated numerical scheme for the approximation but that is beyond the scope of the answer.
The second possibility is to restrict yourself to a subclass of Bezier curves that will let you do what you want. These are called Pythagorean-Hodograph (shortly PH) curves. They have the extremely useful property that there exists a polynomial sigma(t) such that
This means that you can compute the integral above and search for the correct value of u. However, everything comes at a price and the price here is that you will have less freedom, where to put the control points (for me as a mathematician, a cubic Bézier curve has four control points; computer graphics people often speak of "handles" so you might have to translate into your terminology). For the cubic case you can find the conditions on slide 15 of this seminar talk by Vito Vitrih.
Denote:
the control points,
;
then the Bézier curve is a PH curve if and only if
.
It is up to you to figure out, if you can enforce this condition in your situation or if it is too restrictive for your application.

How to find closest points between two convex hull in MATLAB?

In part of an Artificial Neural Network matlab code, I want to find nearest points of two convex polygons.
I saw
dsearchn(X,T,XI)
command's description here, but that finds closest points between two sets of points, and polygons (like convexs) have infinites points.
So can you suggest any way/idea?
Notice: I'm using MATLAB 2014a. I have the coordinate of each convex's vertex point.
If you are not happy with what is provided by dsearchn, then, If I were you, I would do one of two following:
Find Nearest Neighbours on the vertices (for example which vertex of
polygon A is the NN of a given vertex of polygon B).
Pick a random point inside polygon A (you may want to compute the
convex hull of A, but you may skip that and take into account only
the vertices you know already). That random point is the query. Find
an NN of that point from the vertices of polygon B.
You may want to ask in Software recommendations for more.
Edit:
Another approach is this:
Create a representative dataset of polygon A. Set the size of the dataset yourself and fill it with samples of points that lie inside the polygon. Choose them uniformly randomly inside the polygon.
Then take a point of polygon B (either a vertex or a random point inside polygon B) and that's the query point, for which you will seek Nearest Neighbour(s) inside the representative dataset of polygon A.
Of course that's just an approximation, but I can't think of something else now.
Notice that you can of course do the same for polygon B.
With This File in File Exchange, I've find the solution.
With a little code modification, I have drawn a perpendicular bisector which I wanted. Of course, this way is time consuming.

Detecting overlapped elliptical regions in image (MATLAB)

I have a multiple plants in a single binary image. How would I identify each leaf in the image assuming that each leaf is approximately elliptical?
example input: http://i.imgur.com/BwhLVmd.png
I was thinking a good place to start would be finding the tip of each leaf and then getting the center of each plant. Then I could fit the curves starting from the tip and then going to the center. I've been looking online and saw something involving a watershed method, but I do not know where to begin with that idea.
You should be aware that these things are tricky to get working robustly - there will always be a failure case.
This said, I think your idea is not bad.
You could start as follows:
Identify the boundary curve of each plant (i.e. pixels with both foreground and background in their neighbourhood).
Compute the centroid of each plant.
Convert each plant boundary to a polar coordinate system, with the centroid as the origin. This amounts to setting up a coordinate system with the distance of each boundary curve point on the Y axis and the angle on the X axis.
In this representation of the boundary curve, try to identify maxima; these are the tips of the leaves. You will probably need to do some smoothing. Use the parts of the curve before and after the maxima the start fitting your ellipses or some other shape.
Generally, a polar coordinate system is always useful for analysing stuff thats roughly circular.
To fit you ellipses, once you have a rough initial position, I would probably try an EM-style approach.
I would do something like this (I is your binary image)
I=bwmorph(bwmorph(I, 'bridge'), 'clean');
SK=bwmorph(I, 'skel', Inf);
endpts = bwmorph(SK,'endpoints');
props=regionprops(I, 'All');
And then connect every segment from the centroids listed in props.centroid to the elements of endpts that should give you your leaves (petals?).
A bit of filtering is probably necessary, bwmorph is your friend. Have fun!

Computing distance from a point to a triangulation in 3D with Matlab

I have a 3D point cloud that I've transformed into a Delaunay triangulation using Matlab's function DelaunayTri. Now I have a test point in 3D and want to compute, in Matlab, the smallest distance between this point and the triangulation.
So far, I've thought of using the nearestNeighbor(...) member function of the DelaunayTri class in Matlab to find the point in the triangulation closest to my test point and then computing the distance between them. That is something but it is not what I really want.
The closest point on the triangulation to my test point is, in general, not a vertex of the triangulation but somewhere on the face of a triangle. How can I find this point?
Thank you!!!
I've written codes for these things, but they are not on the File Exchange. I can be convinced to give them out by direct mail though.
It is relatively easy to find the distance to a convex hull, but not trivial. A delaunay tessellation is bounded by the convex hull anyway. So you can convert that tessellation into the convex hull easily enough, or just use the convex hull. Note that a convex hull is often a terribly poor approximation for many purposes, especially if you are using this for color mapping, which is perhaps the most common thing I see this used for. In that case, an alpha shape is a far better choice. Alpha shapes also will have a triangulated boundary surface, though in general it will not be convex.
So, to find the nearest point on a convex triangulation:
Convert to the convex boundary surface, i.e., the convex hull. This reduces to finding those triangles which are not shared between pairs of tetrahedra. Internal facets will always appear exactly twice in the list of all facets. This trick also works for non-convex tessellations of course, so for alpha shapes.
Compute a bounding circumcircle for each triangular surface facet. This allows you to know when to stop checking facets.
Get the distances to each point on the surface. Sort each facet by the distance to the nearest point in that facet. Start by looking at the nearest facet in that list.
Compute the distance to the apparently nearest facet found in step 3. A simple solution is found by least distance programming (LDP), which can be converted to a constrained linear least squares. Lawson & Hanson have an algorithm for this.
Repeat step 4 until the current best distance found is less than the distance, comparing it to any of the circumcircles from step 2. This loop will be quite short really, at least for a convex hull. For a more general non-convex hull from an alpha shape, it may take more time.
You can also reduce the search space a bit by excluding the facets from your search that point AWAY from the point in question. Use those facet normals for this test.
I wrote the tool point2trimesh for this problem. It's kind of a "brute force" solution which works also for non-convex surfaces.