I was wondering how I show/plot a voronoi diagram in the below FCM method? Also is there a method where you can watch the programme from the figure as it places and computes each point in matlab? Almost like a running trailer.
[centers, U, objFun] = fcm(data, 6);
plot(data(:,1), data(:,2),'o');
maxU = max(U);
index1 = find(U(1, :) == maxU);
index2 = find(U(2, :) == maxU);
line(data(index1,1),data(index1, 2),'linestyle','none',...
'marker','*','color','g');
line(data(index2,1),data(index2, 2),'linestyle','none',...
'marker', '*','color','r');
This should be the same for k-means and FCM, btw.
To get the Voronoi diagram, you need to compute the Delaunay triangulation, then place a side of the Voronoi diagram orthogonal on the mean of each Delaunay edge.
There are efficient algorithms for Delaunay in at least 2D and 3D. This is quite closely related to computing the convex hull. Plus, as you don't have many cluster centers, the scalability is not that hard.
However, you have one big problem: your data is 6 dimensional. This means that the sides of your Voronoi cells are in fact 5-dimensional, and they will not trivially map to a reasonable 2d projection.
Computing the Voronoi diagram in the 2D projection that you are using however will be inaccurate. You could try to compute the Voronoi cells in 6D, and map all the corners of the voronoi cells into 2D, then connect neighboring corners. But that may yield a big mess of lines, and is not particularly helpful IMHO.
Sorry, as far as I know, Voronoi cell visualization is mostly useful for understanding k-means in 2D and if you have a good 3D visualization engine in 3D.
Don't get me wrong: Voronoi cells is exactly what k-means cluster look like. They're not spheres or blobs or stars. They are Voronoi cells: the cell exactly is the area that would be assigned to a particular mean.
Have a look at this image from Wikipedia:
The black lines are the borders (which in a 2D data set are simple 1d lines) that separate the clusters. In the top center there is a blue object just right of the line. It is blue, because it is on the right of the line - it is in the Voronoi cell of the blue mean.
This is a key drawback of k-means: it does not have the notion of size as in spatial extend for a cluster. They only have a center, and the data is split on the orthogonal hyperplane inbetween of two neighboring centers. For this particular data set, k-means *does not have a chance to split the data correctly! It hasn't converged to a "bad" local minimum, but the correct solution cannot be found by k-means, because the clusters have different size (and there is not enough gap inbetween for k-means to be lucky). To properly cluster this data set, you actually need an EM-like notion of cluster size or a density based method. If k-means were able to detect that the green clusters is about twice as big as the blue ones, it would probably work much better (but then it almost were EM already anyway)
Related
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
I have a surface by the code below and another surface which is created by the exact same code. I want to see the height differences in another figure. How am I able to do that? Already operated with the Minus-operator but this won't work.
Furthermore the matrices have NOT the same size!
Appreciate your help!
x1 = Cx1;
y1 = Cy1;
z1 = Cz1;
tri1 = delaunay(x1,y1);
fig1 = figure%('units','normalized','outerposition',[0 0 1 1]);
trisurf(tri1,x2,y2,z2)
xlabel('x [mm] ','FontSize',30)
ylabel('y [mm] ','FontSize',30)
zlabel('z [mm] ','FontSize',30)
The simplest way to solve this problem is to interpolate from one mesh onto the other one. Such an approach works well when one is more highly resolved than the other, or when you're not as concerned with results at individual nodes, but rather the overall pattern across elements. If that's not the case, then you have a very complicated problem because you need to create a polygonal surface that fully captures all nodes and edges of both triangulations. Consider the following pair of triangular patterns:
A surface that captured all the variations would need to have all the vertices and edges that make up both of them, which is not a purely triangular surface. So, let us instead assume the easier case. To map results from one triangulation to the other, you simply need to formulate functions that define how the values vary along the triangles, which are more broadly called basis functions. It is often assumed that values betweeen the nodes (i.e. vertices) of the triangles vary linearly along the surfaces of the triangles. You can do it differently if you want, it just requires defining new basis functions. If we go for linear functions, then the equations in 2D are pretty simple. Let's say you make an array trimap that has which triangle each of the vertices of the other triangulation is inside of. This can be accomplished using the info here. Then, we set the coordinates of the vertices of the current triangle to (x1,y1), (x2,y2), and (x3,y3), and then do the math:
for cnt1=1,npoints
x1=x(tri1(trimap(cnt1),1));
x2=x(tri1(trimap(cnt1),2));
x3=x(tri1(trimap(cnt1),3));
y1=y(tri1(trimap(cnt1),1));
y2=y(tri1(trimap(cnt1),2));
y3=y(tri1(trimap(cnt1),3));
delta=x2*y3+x1*y2+x3*y1-x2*y1-x1*y3-x3*y2;
delta1=(x2*y3-x3*y2+xstat(cnt1)*(y2-y3)+ystat(cnt1)*(x3-x2));
delta2=(x3*y1-x1*y3+xstat(cnt1)*(y3-y1)+ystat(cnt1)*(x1-x3));
delta3=(x1*y2-x2*y1+xstat(cnt1)*(y1-y2)+ystat(cnt1)*(x2-x1));
weights(cnt1,1)=delta1/delta;
weights(cnt1,2)=delta2/delta;
weights(cnt1,3)=delta3/delta;
z1=z(tri1(trimap(cnt1),1));
z2=z(tri1(trimap(cnt1),2));
z3=z(tri1(trimap(cnt1),3));
valinterp(cnt1)=sum(weights(cnt1,:).*[z1,z2,z3]);
end
valinterp is the interpolated value for each point. Here and here are some nice slides explaining the mathematics behind all this. Note that I've not tested any of this code. Note also that you will need to do something to assign to values outside of the triangulation. Perhaps a null value, or an inverse-distance weighted value.
I have a list of triangles in 3D that form a surface (ie a triangulation). The structure is a deformed triangular lattice. I want to know the change in area of the deformed hexagons of the voronoi tessalation of the lattice with respect to the rest area of the undeformed lattice cells (ie with respect to a regular hexagon). In fact, I really want the sum of the squared change in area of the hexagonal unit cells associated with those triangles.
Background/Math details:
I'm approximating a curved elastic sheet by a triangular lattice. One way to tune the poisson ratio (elastic constant) of the sheet is by adding a 'volumetric' strain energy term to the energy. I'm trying to compute a 'volumetric' strain energy of a deformed, elastic, triangular lattice, defined as: U_volumetric = 1/2 T (e_v)^2, where e_v=deltaV/V is determined by the change in area of a voronoi cell with respect to its reference area, which is a known constant.
Reference: https://www.researchgate.net/publication/265853755_Finite_element_implementation_of_a_non-local_particle_method_for_elasticity_and_fracture_analysis
Want:
Sum[ (DeltaA/ A).^2 ] over all hexagonal cells.
My data is stored in the variables:
xyz = [ x1,y1,z1; x2,y2,z2; etc] %the vertices/particles in 3D
TRI = [ vertex0, vertex1, vertex2; etc] %
where vertex0 is the row of xyz for the particle sitting at vertex 0 of the first triangle.
NeighborList = [ p1n1, p1n2, p1n3, p1n4, p1n5,p1n6 ; p2n1...]
% where p1n1 is particle 1's first nearest neighbor as a row index for xyz. For example, xyz(NL(1,1),:) returns the xyz location of particle 1's first neighbor.
AreaTRI = [ areaTRI1; areaTRI2; etc]
I am writing this in MATLAB.
As of now, I am approximating the amount of area attributed to each vertex as 1/3 of the triangle's area, then summing over the 6 nearest neighbor triangles. But a voronoi cell area will NOT be exactly equal to Sum_(i=0,1,...5) 1/3* areaTRI_i, so this is a bad approximation. See the image in the link above, which I think makes this clearer.
You can do this using the DUALMESH-submission on the file exchange:
DUALMESH is a toolbox of mesh processing routines that allow the construction of "dual" meshes based on underlying simplicial triangulations. Support is provided for various planar and surface triangulation types, including non-Delaunay and non-manifold types.
Simply use the following commands to generate a vector areas of all the dual elements' areas. The ordering will correspond to the nodes xyz.
[cp,ce,pv,ev] = makedual2(xyz, TRI);
[~,areas(cp(:,1))] = geomdual2(cp,ce,pv,ev);
You might want to have a look at the boundary areas using:
trisurf(TRI, xyz(:,1), xyz(:,2), areas);
The dual cells of boundary nodes theoretically are unbounded and thus should have infinite area. This submission handles it differently however: Instead of an unbounded cell it will return the intersection of the unbounded cell with the original mesh.
Also mind that your question is not well defined if the mesh you are working with is not planar, as the dual mesh cells will be planar and won't scale the same way as the triangles. So this solution will probably only work correctly if your mesh is really 2D. (From what I can tell, the paper you mention is also only for the 2D-case.)
UPDATE (1/12/14): Dear all, I have been trying all I can to code the algorithm by Dr Darren below in MATLAB but I am yet to succeed with it. I humbly request that a good Samaritan should kindly help me with the code and share the m-file. Thanks once again.
I intend to obtain Voronoi diagram on RBC using MATLAB/FORTRAN. I need the following specific information.
Voronoi vertex using the normal vector for each Delaunay triangle;
Order of each Voronoi polygon;
Voronoi vertex lists that define the Voronoi polygons;
Component of normals on the Voronoi polygons;
Areas of the Voronoi polygons;
Centroids of the Voronoi polygons;
Finally, plot Voronoi polygons using PATCH;
Please find link to corresponding text files RBC_1 which contain XYZ node coordinates on the RBC and RBC_2 which contain face connectivity data from Delaunay triangulation (RBC_1 and RBC_2 are in Zip file).
https://www.dropbox.com/s/slan053xbr2e864/RBC.zip?dl=0
I have tried to follow the work of John Burkardt for unit sphere: http://people.sc.fsu.edu/~jburkardt/m_src/sphere_voronoi/sphere_voronoi.html but its not working.
Thank you in advance.
N.B Any comment and advice will be highly appreciated.
Looking at your files, you have a set of points P in R^3 and a (2-manifold) surface triangulation T of your geometry:
This can easily be turned into a surface voronoi complex V by noting that the voronoi complex is dual to the underlying triangulation T. This means the following:
for each primary edge Ei in T there is a dual edge Vi in the voronoi complex.
for each primary node Pi in P there is a dual cell Vc in the voronoi complex.
Each dual edge in the voronoi complex spans between the centre of the circumballs of the triangles that are adjacent to the associated primary edge in the triangulation.
This duality implies the following algorithm for the construction of the voronoi complex:
calculate circumcentres CC for all triangles in T
for (all edges Ei in T)
find triangles [Ti,Tj] in T adjacent to edge Ei
push voronoi edge Vi between centres [CC(Ti),CC(Tj)]
associate edge Vi with voronoi cells associated with edge endpoints [Pi,Pj] in Ei
endfor
Putting this into practice gives the following voronoi complex for your mesh:
As others have pointed out, your question is very extensive, and I won't try to answer everything here.
I have made a set of dual mesh construction routines available here. Nonetheless, based on the slew of emails that you've bombarded me with over the weekend, let me make a few remarks: (i) you should invest some effort to understand a bit of computational geometry -- don't just blindly use the code provided, and (ii) if you do use the code provided, ensure that you make an effort to reference it appropriately.
I am trying to find the points with edge-adjacent Voronoi regions in a given dataset. I'm new to computational geometry, but from reading up online, it appeared that using the Delaunay tessellation would be an easy way to do this. This PDF in particular even has a lemma that states
Lemma 2.4 Two points of S are joined by a Delaunay edge iff their Voronoi regions
are edge-adjacent.
So, I found the delaunay tessellation of my dataset as
dt = delaunay(dataset); %using delaunayn() since dataset can be multidimensional
But now, when I plot this along with the voronoi diagram for this dataset, I find that the delaunay edges returned connect points whose regions are not actually edge-adjacent.
Here is the code I used to plot Voronoi and Delaunay together:
voronoi(dataset(:, 1),dataset(:, 2));
hold on;
dt = delaunayn(dataset);
triplot(dt, dataset(:, 1), dataset(:, 2), 'red');
And here is the output:
As an example of the problem, see the point X on the right end of the figure connected to point Y near the lower left corner.
Another example is in this SO question - the point 1 is connected to 2 and 3, even though they're not adjacent, and there doesn't seem to be any way 1 and 2 could share an edge even if extended to infinity. This question is actually what prompted me to test the delaunayn output with the above code.
Why is this happening, and how do I actually get the edge-adjacent neighbour regions that I need?
Note: For seeing the image in full size and clarity, please right click and choose 'View image' or similar.
As far as I can see (the quality of the diagram is not so good), the regions for X and Y should be adjacent below the plotted part. If you zoom out far enough, you should see them.
I.e. the edge where X and Y meet exists, but is just not shown on the plot.
The following diagram does not show the voronoi diagram outside of the plotting area, but how to find the intersection point described above (note, the bisector is not shown here):