Regarding Voronoi diagram - matlab

In MATLAB's function of Voronoi diagram, the vertices of edges at infinity are plotted at some distant point. Have a look at the first diagram on the page here. The first point from the top on Y-axis is (0,0.75). (Though it is extended beyond the bounds of the image). I know if I run the following matlab function:
[vx,vy]=voronoi(x,y)
I can get the coordinates of the vertices, but they will be beyond the bounds of the plot. Is there any way to get the coordinate in bounds of the plot (for example, (0,0.75) as mentioned above).

All you need is to detect which of the vx,vy crosses the axes (using find or logical conditions, find(vx<0) , find(vy>1) etc...) , and then apply the equation of the line y=a*x+b. For the point you wanted (which happens to be the 19th col of vx,vy, the slope a is:
a=diff(vy(:,19))/diff(vx(:,19));
and the intersection with y axis is given by b:
b=vy(1,19)-a*vx(1,19)
b =
0.7546
To calc b I picked the first point [vx(1,19),vy(1,19)] but this of course works also for the second point, i.e. b=vy(2,19)-a*vx(2,19)

Related

Rounded corner rectangle coordinate representation

Simple rounded corner rectangle code in Matlab can be written as follows.
rectangle('Position',[0,-1.37/2,3.75,1.37],...
'Curvature',[1],...
'LineWidth',1,'LineStyle','-')
daspect([1,1,1])
How to get the x and y coordinates arrays of this figure?
To get the axes units boundaries, do:
axisUnits = axis(axesHandle) % axesHandle could be gca
axisUnits will be an four elements array, with the following syntax: [xlowlim xhighlim ylowlim yhighlim], it will also contain the zlow and zhigh for 3-D plots.
But I think that is not what you need to know. Checking the matlab documentation for the rectangle properties, we find:
Position four-element vector [x,y,width,height]
Location and size of rectangle. Specifies the location and size of the
rectangle in the data units of the axes. The point defined by x, y
specifies one corner of the rectangle, and width and height define the
size in units along the x- and y-axes respectively.
It is also documented on the rectangle documentation:
rectangle('Position',[x,y,w,h]) draws the rectangle from the point x,y
and having a width of w and a height of h. Specify values in axes data
units.
See if this illustrate what you want. You have an x axis that goes from −100 to 100 and y axis that goes from 5 to 15. Suppose you want to put a rectangle from −30 to −20 in x and 8 to 10 in y.
rectangle('Position',[-30,8,10,2]);
As explained by the comments there appears to be no direct way to query the figure created by rectangle and extract x/y coordinates. On the other hand, I can think of two simple strategies to arrive at coordinates that will closely reproduce the curve generated with rectangle:
(1) Save the figure as an image (say .png) and process the image to extract points corresponding to the curve. Some degree of massaging is necessary but this is relatively straightforward if blunt and I expect the code to be somewhat slow at execution compared to getting data from an axes object.
(2) Write your own code to draw a rectangle with curved edges. While recreating precisely what matlab draws may not be so simple, you may be satisfied with your own version.
Whether you choose one of these approaches boils down to (a) what speed of execution you consider acceptable (b) how closely you need to replicate what rectangle draws on screen (c) whether you have image processing routines, say for reading an image file.
Edit
If you have the image processing toolbox you can arrive at a set of points representing the rectangle as follows:
h=rectangle('Position',[0,-1.37/2,3.75,1.37],...
'Curvature',[1],...
'LineWidth',1,'LineStyle','-')
daspect([1,1,1])
axis off
saveas(gca,'test.png');
im = imread('test.png');
im = rgb2gray(im);
figure, imshow(im)
Note that you will still need to apply a threshold to pick the relevant points from the image and then transform the coordinate system and rearrange the points in order to display properly as a connected set. You'll probably also want to tinker with resolution of the initial image file or apply image processing functions to get a smooth curve.

defining a minimal bounding circle in matlab

The question is
a.write a function which finds the circle with the minimal area s.t it bounds a given list of points (use fminsearch and give appropriate plot).
b.If you managed do the same for sphere (find one with minimal volume)
What I've tried so far:
%%Main function
function minarea= mincircle(points)
maxx=max(points(1,:));
maxy=max(points(2m:));
radius=max(maxx,maxy);
minarea=fminsearch(#(x) circle(x,r,c),[0,0])
end
%%This function is supposed to give equalation of circle
function eq=circle(x,r,c)
eq=(x(1)-c(1)).^2+(x(2)-c(2)).^2 %=r?
% and here I don't know how to insert r:
end`
For better understanding I'll attach a sketch.
In these terms I want to find the area of the circle whose center is in O
Note: I don't believe that the circle you drew is the smallest possible bounding circle. It should be a little smaller, up and to the right, and should touch at least two points on its perimeter.
Approaching the problem
We have a set of points, and we want to draw a circle that encompasses all of them. The problem is that you need three bits of information to define a circle: the X and Y coordinates of the circle's center, and the circle's radius. So the problem doesn't seem straightforward.
However, there is a related problem that is much easier to solve. Suppose the circle's center is fixed. From that point, we make a circle grow concentrically outwards so that it becomes bigger and bigger. At some point, the circle will encompass one of the points in our set. As it gets bigger, it will encompass a second point, and a third, until all the points in our set fall within our circle. Clearly, as soon as the last point in the set falls within our circle, we have the smallest possible circle that encompasses all the points, given that we started by fixing the center point of the circle.
Moreover, we can determine what the radius of this circle is. It is simply the maximum distance from any point in the set to the center of the circle, since we stop when the last point is touched by the perimeter of our expanding circle.
The next problem is to determine What is the best starting point to place the center of our circle? Clearly if the starting point is far away from all the points in our set, then the radius must be very large to even encompass one point in the set. Intuitively, it must be "in the middle" of our points somewhere. But where, exactly?
Using fminsearch
My suggestion is that you want to find the point P(x, y) that minimises how large you have to grow the circle to encompass all the points in the set. And we're in luck that we can use fminsearch to find P.
According to the fminsearch documentation, the function you pass in must be a function of one parameter (which may be an array), and it must return a scalar. The idea is that you want the output of your function to be as small as possible, and you want to find out what inputs will make that possible.
In our case, we want to write a function that outputs the size of our circle, given the center of the circle as input. That way, fminsearch will find the center of the smallest possible circle that will still encompass all the points. I'm going to write a function that outputs the radius required to encompass all the points given a center point P.
pointsX = [..]; % X-coordinates of points in the set
pointsY = [..]; % Y-coordinates of points in the set
function r = radiusFromPoint(P)
px = P(1);
py = P(2);
distanceSquared = (pointsX - px).^2 + (pointsY - py).^2;
r = sqrt(max(distanceSquared));
end
Then we want to use fminsearch to find the point that gives us the smallest radius. I've just naively used the origin (0, 0) as my starting estimate, but you may have a better idea (like using the first point in the set)
P0 = [0, 0]; % starting estimate
[P, radiusMin] = fminsearch(#radiusFromPoint, P0);
The circle is defined by its center at P and radius of radiusMin.
And I'll leave it to you to plot the output and generalize to the 3D case!
Actually, while you may need it to complete your homework assignment (I assume that is what this is) you don't really need to use an optimizer at all. The minboundcircle code posted with my minimal bounding tools does it without use of an optimizer. (There is also a minboundsphere tool.)
Regardless, you might find a few tricks in there that will be useful. At the very least, learn how to reduce the size of the problem (and so the speed of solution) by use of a convex hull. After all, it is only the points on the convex hull that can determine a minimal bounding circle. All other points are simply a waste of CPU time.

matlab: area under overlapping circles

I have a question to you...
Imagine square with size A x A. Now lets simulate circles with diameter of d, randomly distributed within this square, something like on the image below (in this case d's are the same, but its not the rule, they might be also randomly distributed within some range like d1 to d2).
Lets say that circles are described in matrix as:
circles(1, :) = [x, y, d];
circles(2, :) = [x, y, d];
...and so on
where x, y are coordinates, d is diameter. Now the question is, how to simulate this circles, until given crowding parameter c is reached? c is simply defined as: c = yellow area / square area (in this case A^2).
And the second thing - lets say that everything is simulated and I want to check if some coordinate (x,y) is within or outside yellow area... How to do it? I was doing it by checking if my (x,y) is within area of each circle (but its getting more difficult when instead of circles I use i.e. round shape rectangles), one by one, but there must be some better way of doing it.
Thanks for help : )
Here is an approach that should do the trick:
Start with a large empty matrix (big enough to guarantee that every shape generated is fully inside the matrix). Suppose we do it like this color = zeros(100)
while we have not yet reached the cowding ratio: the midpoint and diameter of one circle, I assume you can manage this
change the color of all points in the circle, for example by setting it to one.
Calculate the crowding ratio (something like c = mean(mean(color))
Note, if you only want to use part of the matrix (enable shapes to fall partially out of the picture) this can for example be achieved by using mean(mean(color(11:end-11)) in step 4, ignoring the 10 pixels near the edge.
Now if you want to know whether point (x,y) is yellow, simply check the value of color(x,y). Or if you want to ignore the edges check color(x+10,y+10)

Find closest point in matlab grid

G'day
I'm trying to program a smart way to find the closest grid points to the points along a contour.
The grid is a 2-dimensional grid, stored in x and y (which contain the x and y kilometre positions of the grid cells).
The contour is a line, made up of x and y locations, not necessarily regularly spaced.
This is shown below - the red dots are the grid, and the blue dots are the points on the contour. How do I find the indices of the red dot closest to each blue dot?
Edit - I should mention that the grid is a latitude/longitude grid, of an area fairly close to the south pole. So, the points (the red dots) are the position in metres from the south pole (using a polar stereographic representation). Since the grid is a geographic grid there is unequal grid spacing - with slightly different shaped cells (where the red dots define the vertices of the cells) due to the distortion at high latitudes.
The result is that I can't just find which row/column of the x and y matrix corresponds closest to the input point coordinates - unlike a regular grid from meshgrid, the values in the rows and columns vary...
Cheers
Dave
The usual method is to go:
for every blue point {
for every red point {
is this the closest so far
}
}
But a better way is to put the red data into a kd tree. This is a tree that splits the data along its mean, then splits the two data sets along their means etc until you have them separated into a tree structure.
This will change your searching effeciancy from O(n*m) to O(log(n)*m)
Here is a library:
http://www.mathworks.com.au/matlabcentral/fileexchange/4586-k-d-tree
This library will provide you the means to easily make a kd tree out of the data and to search for the closest point in it.
Alternatively you can use a quadtree, not as simple but the same idea. (you may have to write your own library for that)
Make sure the largest data set (in this case your red points) go into the tree as this will provide the greatest time reduction.
I think I've found a way to do it using the nearest flag of griddata.
I make a matrix that is the same size as the grid x and y matrices, but is filled with the linear indices of the corresponding matrix element. This is formed by reshaping a vector (which is 1:size(x,1)*size(x,2)) to the same dimensions as x.
I then use griddata and the nearest flag to find the linear index of the point closest to each point on my contour (blue dots). Then, simply converting back to subscript notation with ind2sub leaves me with a 2 row vectors describing the matrix subscripts for the points closest to each point on the blue-dotted contour.
This plot below shows the contour (blue dots), the grid (red dots) and the closest grid points (green dots).
This is the code snippet I used:
index_matrix1 = 1:size(x,1)*size(x,2);
index_matrix1 = reshape(index_matrix1,size(x));
lin_ind = griddata(x,y,index_matrix1,CX,CY,'nearest'); % where CX and CY are the coords of the contour
[sub_ind(1,:),sub_ind(2,:)] = ind2sub(size(x),lin_ind);
I suppose that in the stereographic representation, your points form a neat grid in r-theta coordinates. (I'm not too familiar with this, so correct me if I'm wrong. My suggestion may still apply).
For plotting you convert from the stereographic to latitude-longitude, which distorts the grid. However, for finding the nearest point, consider converting the latitude-longitude of the blue contour points into stereographic coordinates, where it is easy to determine the cell for each point using its r and theta values.
If you can index the cell in the stereographic representation, the index will be the same when you transform to another representation.
The main requirement is that under some transformation, the grid points are defined by two vectors, X and Y, so that for any x in X and y in Y, (x, y) is a grid point. Next transform both the grid and the contour points by that transformation. Then given an arbitrary point (x1, y1), we can find the appropriate grid cell by finding the closest x to x1 and the closest y to y1. Transform back to get the points in the desired coordinate system.
dsearchn: N-D nearest point search.
[k, d] = dsearchn(A,B) : returns the distances, d, to the closest points. d is a column vector of length p.
http://au.mathworks.com/help/matlab/ref/dsearchn.html?s_tid=gn_loc_drop

Why do the delaunay edges from Matlab's delaunayn() connect points with non-adjacent Voronoi regions?

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):