MATLAB: find intersection points with "solve" [circle + linear equation] - matlab

I would like to find the two (2) intersection points when a linear line goes through a circle's centrum (x,y).
r = 13 radius
x = 0 x-coordinate
y = 7 y-coordinate
k = 9 slope value(?) y=kx+m y=9x+m
So first I'm drawing a circle with r=13 and a centrum of (0,7).
r=13
x=0
y=7
k=9
hold on
z = 0:pi/50:2*pi;
xunit = r * cos(z) + x;
yunit = r * sin(z) + y;
plot(xunit, yunit);
I'm wondering if it would be possible to plot up a circle in an easier way? Something like
(x−cx)^2 + (y −cy)^2 = r^2
(x-0)^2 + (y-7) = 13^2
I've tried this
plot((x−cx)^2 + (y −cy)^2 = r^2)
It doesn't do anything at all so the code must be incorrect.
Well, then I'm drawing the linear equation by calculating
y=kx+m
k=9
the line goes thorugh (0,7)
7=9*0+m
m=7
y=9x+7
so since I'm new to MatLab it took me a while to actually draw the line. I didn't find any easy function to plot it so I plotted a line like this:
I took some random values for x or y and calculated some coordinates.
(0,7)
(2,25)
(-2,-11)
plot([-2,2],[-11,25])
Result image: http://i.imgur.com/ag6HJlm.jpg
So now I just need to solve the intersection points with "solve" function. So well I would really appreciate some help!
best regards

Here is one approach to it:
%Place your lines and figures on the grid
linexypos = eye(100);
shapexypos = flipud(eye(100)) ;
% Guess where they come together
intersection = filter2(ones(3),linexypos + shapexypos);
[quality, loc] = max(intersection(:))
Note that you have to guess, as two lines with widths of 1 pixel may not have exactly the same location. (consider [1 0; 0 1] and [0 1;1 0], they cross but never exactly overlap).
If you want to visualize the situation, try contour(intersection)

Related

Plotting circles with complex numbers in MATLAB

I want to make a figure in MATLAB as described in the following image
What I did is the following:
x = [1 2 3];
y = [2 2 4];
radius = [1 1.2 2.2];
theta = [-pi 0 pi];
figure;
scatter(x,y,radius)
How do I add an angle theta to the plot to represent a complex number z = radius.*exp(1j*theta) at every spacial coordinates?
Technically speaking, those are only circles if x and y axes are scaled equally. That is because scatter always plots circles, independently of the scales (and they remain circles if you zoom in nonuniformly. + you have the problem with the line, which should indicate the angle...
You can solve both issues by drawing the circles:
function plotCirc(x,y,r,theta)
% calculate "points" where you want to draw approximate a circle
ang = 0:0.01:2*pi+.01;
xp = r*cos(ang);
yp = r*sin(ang);
% calculate start and end point to indicate the angle (starting at math=0, i.e. right, horizontal)
xt = x + [0 r*sin(theta)];
yt = y + [0 r*cos(theta)];
% plot with color: b-blue
plot(x+xp,y+yp,'b', xt,yt,'b');
end
having this little function, you can call it to draw as many circles as you want
x = [1 2 3];
y = [2 2 4];
radius = [1 1.2 2.2];
theta = [-pi 0 pi];
figure
hold on
for i = 1:length(x)
plotCirc(x(i),y(i),radius(i),theta(i))
end
I went back over scatter again, and it looks like you can't get that directly from the function. Hopefully there's a clean built-in way to do this, and someone else will chime in with it, but as a backup plan, you can just add the lines yourself.
You'd want a number of lines that's the same as the length of your coordinate set, from the center point to the edge at the target angle, and fortunately 'line' does multiple lines if you feed it a matrix.
You could just tack this on to the end of your code to get the angled line:
x_lines = [x; x + radius.*cos(theta)];
y_lines = [y; y + radius.*sin(theta)];
line(x_lines, y_lines, 'Color', 'b')
I had to assign the color specifically, since otherwise 'line' makes each new line cycle through the default colors, but that also means you could easily change the line color to stand out more. There's also no center dot, but that'd just be a second scatter plot with tiny radius. Should plot most of what you're looking for, at least.
(My version of Matlab is old enough that scatter behaves differently, so I can only check the line part, but they have the right length and location.)
Edit: Other answer makes a good point on whether scatter is appropriate here. Probably better to draw the circle too.

How to create random points alongside a complex polyline?

I would like to populate random points on a 2D plot, in such a way that the points fall in proximity of a "C" shaped polyline.
I managed to accomplish this for a rather simple square shaped "C":
This is how I did it:
% Marker color
c = 'k'; % Black
% Red "C" polyline
xl = [8,2,2,8];
yl = [8,8,2,2];
plot(xl,yl,'r','LineWidth',2);
hold on;
% Axis settings
axis equal;
axis([0,10,0,10]);
set(gca,'xtick',[],'ytick',[]);
step = 0.05; % Affects point quantity
coeff = 0.9; % Affects point density
% Top Horizontal segment
x = 2:step:9.5;
y = 8 + coeff*randn(size(x));
scatter(x,y,'filled','MarkerFaceColor',c);
% Vertical segment
y = 1.5:step:8.5;
x = 2 + coeff*randn(size(y));
scatter(x,y,'filled','MarkerFaceColor',c);
% Bottom Horizontal segment
x = 2:step:9.5;
y = 2 + coeff*randn(size(x));
scatter(x,y,'filled','MarkerFaceColor',c);
hold off;
As you can see in the code, for each segment of the polyline I generate the scatter point coordinates artificially using randn.
For the previous example, splitting the polyline into segments and generating the points manually is fine. However, what if I wanted to experiment with a more sophisticated "C" shape like this one:
Note that with my current approach, when the geometric complexity of the polyline increases so does the coding effort.
Before going any further, is there a better approach for this problem?
A simpler approach, which generalizes to any polyline, is to run a loop over the segments. For each segment, r is its length, and m is the number of points to be placed along that segment (it closely corresponds to the prescribed step size, with slight deviation in case the step size does not evenly divide the length). Note that both x and y are subject to random perturbation.
for n = 1:numel(xl)-1
r = norm([xl(n)-xl(n+1), yl(n)-yl(n+1)]);
m = round(r/step) + 1;
x = linspace(xl(n), xl(n+1), m) + coeff*randn(1,m);
y = linspace(yl(n), yl(n+1), m) + coeff*randn(1,m);
scatter(x,y,'filled','MarkerFaceColor',c);
end
Output:
A more complex example, using coeff = 0.4; and xl = [8,4,2,2,6,8];
yl = [8,6,8,2,4,2];
If you think this point cloud is too thin near the endpoints, you can artifically lengthen the first and last segments before running the loop. But I don't see the need: it makes sense that the fuzzied curve is thinning out at the extremities.
With your original approach, two places with the same distance to a line can sampled with a different probability, especially at the corners where two lines meet. I tried to fix this rephrasing the random experiment. The random experiment my code does is: "Pick a random point. Accept it with a probability of normpdf(d)<rand where d is the distance to the next line". This is a rejection sampling strategy.
xl = [8,4,2,2,6,8];
yl = [8,6,8,2,4,2];
resolution=50;
points_to_sample=200;
step=.5;
sigma=.4; %lower value to get points closer to the line.
xmax=(max(xl)+2);
ymax=(max(yl)+2);
dist=zeros(xmax*resolution+1,ymax*resolution+1);
x=[];
y=[];
for n = 1:numel(xl)-1
r = norm([xl(n)-xl(n+1), yl(n)-yl(n+1)]);
m = round(r/step) + 1;
x = [x,round(linspace(xl(n)*resolution+1, xl(n+1)*resolution+1, m*resolution))];
y = [y,round(linspace(yl(n)*resolution+1, yl(n+1)*resolution+1, m*resolution))];
end
%dist contains the lines:
dist(sub2ind(size(dist),x,y))=1;
%dist contains the normalized distance of each rastered pixel to the line.
dist=bwdist(dist)/resolution;
pseudo_pdf=normpdf(dist,0,sigma);
%scale up to have acceptance rate of 1 for most likely pixels.
pseudo_pdf=pseudo_pdf/max(pseudo_pdf(:));
sampled_points=zeros(0,2);
while size(sampled_points,1)<points_to_sample
%sample a random point
sx=rand*xmax;
sy=rand*ymax;
%accept it if criteria based on normal distribution matches.
if pseudo_pdf(round(sx*resolution)+1,round(sy*resolution)+1)>rand
sampled_points(end+1,:)=[sx,sy];
end
end
plot(xl,yl,'r','LineWidth',2);
hold on
scatter(sampled_points(:,1),sampled_points(:,2),'filled');

How would I plot the for loop from my code below?

I have 3D flow data of the velocity of a fluid through a tube. I know the diameter of the tube and have looked at the velocity field and found the centre of the field for an xy plane at both ends of the tube. So I essentially have a line through the centre axis of the tube. I want to NaN all data points that are outside of the diameter. For this I am using an equation that gives the distance to a point from a line in 3D which I found here mathworld.wolfram.com/Point-LineDistance3-Dimensional.html. I then created an if statement which states points smaller than diameter will be NaN.
I am new to matlab so I don't know how I would now plot this.
%%
diff_axis = end_axis-start_axis;
diff_axis_mag = (diff_axis(1)^2 + diff_axis(2)^2 + diff_axis(3)^2)^0.5;
[rw col pl] = size(X);
for j = 1:col
for i = 1:rw
for k = 1:pl
x_curr = X(i,j,k);
y_curr = Y(i,j,k);
z_curr= Z(i,j,k);
x0 = [x_curr y_curr z_curr]
t = - dot((start_axis-x0),(diff_axis))./(diff_axis_mag)^2;
d = sqrt(((start_axis(1) - x0(1)) + (end_axis(1) - start_end(1))*t)^2 + ((start_axis(2)-x0(2))+(end_axis(2)-start_end(2))*t)^2+((start_axis(3)-x0(3))+(end_axis(3)-start_end(3))*t)^2);
if (d > D)
x_curr=NaN
y_curr=NaN
z_curr=NaN
end
end
end
end
It were nice to have explanatory names for your X, Y, and Z. I am guessing they are flow components, and diff_axis are axis coordinates? It is a very cumbersome notation.
what you do in your loops is you take point values (X,Y,Z), copy them to temporary constants and then set them to NaN if they fall out. But the problem is that usually you do not plot point-by-point in MATLAB. So these temorary guys like x_curr will be lost.
Also, the most optimal way to do things in MATLAB is to avoid loops whenever possible.
What you can do is to create first a mask
%// remember to put a dot like in `.^` for entrywise array operations
diff_axis_mag = sqrt(diff_axis(1).^2 + diff_axis(2).^2 + diff_axis(3).^2);
%// are you sure you need to include the third axis?
%// then it is a ball, not a tube
%// create a binary mask
mask = diff_axis_mag < tube_radius
X(~mask) = NaN;
Y(~mask) = NaN;
Z(~mask) = NaN;
Then you can plot your data with quiver3 or
stream3

Plot points and polygon matlab

I am trying to plot a point, a circle surrounding a point with a given radius and polygons from array of coods as input. I have the following code implemented
plot(start(1),start(2))
axis([0,256,0,256]);
hold on;
%pdecirc(endp(1),endp(2),10);
for i = 1:size(X,1)
patch(X(i),Y(i),'r');
end
However, pdecirc is not working. it opens a new editor and thus I have commented it. X and Y are 2d arrays of dimensions (no.of points X 4). Thus X(i) has 4 X values and Y(i) has 4 X values. This code is not drawing the polygons as expected. Can you please tell me the best way of achieving what am trying to do? A code would be really helpful. Thanks in advance.
It appears that pdecirc is part of a matlab pde toolkit, not for generic circle drawing, here's something quick
r = 10;
theta = linspace(0, 2 * pi, 100);
x = r * cos(theta);
y = r * sin(theta);
plot(x, y);
does your patch command work?

How do you draw a line between points in matlab?

I'm looking to create a "web" between a set of points where the data tells whether there is a link between any two points.
The way I thought of would be by plotting every couple points, and overlaying each couple on top of eachother.
However, if there is a way to just simple draw a line between two points that would be much easier.
Any help would be appreciated!
If you can organize the x and y coordinates of your line segments into 2-by-N arrays, you can use the function PLOT to plot each column of the matrices as a line. Here's a simple example to draw the four lines of a unit square:
x = [0 1 1 0; ...
1 1 0 0];
y = [0 0 1 1; ...
0 1 1 0];
plot(x,y);
This will plot each line in a different color. To plot all of the lines as black, do this:
plot(x,y,'k');
Use plot. Suppose your two points are a = [x1 y1] and b = [x2 y2], then:
plot([x1 x2],[y1 y2]);
If you meant by I'm looking to create a "web" between a set of points where the data tells whether there is a link between any two points actually some kind of graph represented by its adjacency matrix (opposite to other answers simple means to connect points), then:
this gplot function may indeed be the proper tool for you. It's the basic visualization tool to plot nodes and links of a graph represented as a adjacency matrix.
use this function:
function [] = drawline(p1, p2 ,color)
%enter code here
theta = atan2( p2(2) - p1(2), p2(1) - p1(1));
r = sqrt( (p2(1) - p1(1))^2 + (p2(2) - p1(2))^2);
line = 0:0.01: r;
x = p1(1) + line*cos(theta);
y = p1(2) + line*sin(theta);
plot(x, y , color)
call it like:
drawline([fx(i) fy(i)] ,[y(i,1) y(i,2)],'red')
Credit: http://www.mathworks.com/matlabcentral/answers/108652-draw-lines-between-points#answer_139175
Lets say you want a line with coordinates (x1,y1) and (x2,y2). Then you make a vector with the x and y coordinates: x = [x1 x2] and y=[y1 y2].
Matlab has a function called 'Line', this is used in this way:
line(x,y)
If you want to see the effect of drawing lines, you can use plot inside for loop note that data is a n*2 matrix containing the 'x,y' of 'n' points
clf(figure(3))
for i = 1 : length(data)-1
plot([data(i,1),data(i+1,1)], [data(i,2),data(i+1,2)], '-*');
hold on
end
hold off
Or can use this statement to draw it in one step
plot(data(:,1), data(:,2), '-*');