Many questions exist already covering how to detect collisions between a line segment and a circle.
In my code, I am using Matlab's linecirc function, then comparing the intersection points it returns with the ends of my line segments, to check that the points are within the line (linecirc assumes an infinite line, which I don't have/want).
Copying and adding some sprintf calls to the linecirc function shows that it is calculating points as intended. These seem to be being lost by my function.
My code is below:
function cutCount = getCutCountHex(R_g, centre)
clf;
cutCount = 0;
% Generate a hex grid
Dg = R_g*2;
L_b = 62;
range = L_b*8;
dx = Dg*cosd(30);
dy = 3*R_g;
xMax = ceil(range/dx); yMax = ceil(range/dy);
d1 = #(xc, yc) [dx*xc dy*yc];
d2 = #(xc, yc) [dx*(xc+0.5) dy*(yc+0.5)];
centres = zeros((xMax*yMax),2);
count = 1;
for yc = 0:yMax-1
for xc = 0:xMax-1
centres(count,:) = d1(xc, yc);
count = count + 1;
centres(count, :) = d2(xc, yc);
count = count + 1;
end
end
for i=1:size(centres,1)
centres(i,:) = centres(i,:) - [xMax/2 * dx, yMax/2 * dy];
end
hold on
axis equal
% Get counter for intersected lines
[VertexX, VertexY] = voronoi(centres(:,1), centres(:,2));
numLines = size(VertexX, 2);
for lc = 1:numLines
segStartPt = [VertexX(1,lc) VertexY(1,lc)];
segEndPt = [VertexX(2,lc) VertexY(2,lc)];
slope = (segEndPt(2) - segStartPt(2))/(segEndPt(1) - segStartPt(1));
intercept = segEndPt(2) - (slope*segEndPt(1));
testSlope = isinf(slope);
if (testSlope(1)==1)
% Pass the x-axis intercept instead
intercept = segStartPt(1);
end
[xInterceptionPoints, yInterceptionPoints] = ...
linecirc(slope, intercept, centre(1), centre(2), L_b);
testArr = isnan(xInterceptionPoints);
if (testArr(1) == 0) % Line intersects. Line segment may not.
interceptionPoint1 = [xInterceptionPoints(1), yInterceptionPoints(1)];
interceptionPoint2 = [xInterceptionPoints(2), yInterceptionPoints(2)];
% Test if first intersection is on the line segment
p1OnSeg = onSeg(segStartPt, segEndPt, interceptionPoint1);
p2OnSeg = onSeg(segStartPt, segEndPt, interceptionPoint2);
if (p1OnSeg == 1)
cutCount = cutCount + 1;
scatter(interceptionPoint1(1), interceptionPoint1(2), 60, 'MarkerFaceColor', 'r', 'MarkerEdgeColor', 'k');
end
% Test if second intersection point is on the line segment
if (interceptionPoint1(1) ~= interceptionPoint2(1) || interceptionPoint1(2) ~= interceptionPoint2(2)) % Don't double count touching points
if (p2OnSeg == 1)
cutCount = cutCount + 1;
scatter(interceptionPoint2(1), interceptionPoint2(2), 60, 'MarkerFaceColor', 'r', 'MarkerEdgeColor', 'k');
end
end
end
end
% Plot circle
viscircles(centre, L_b, 'EdgeColor', 'b');
H = voronoi(centres(:,1), centres(:,2));
for i = 1:size(H)
set(H(i), 'Color', 'g');
end
end
function boolVal = onSeg(segStart, segEnd, testPoint)
bvX = isBetweenOrEq(segStart(1), segEnd(1), testPoint(1));
bvY = isBetweenOrEq(segStart(2), segEnd(2), testPoint(2));
if (bvX == 1 && bvY == 1)
boolVal = 1;
else
boolVal = 0;
end
end
function boolVal = isBetweenOrEq(end1, end2, test)
if ((test <= end1 && test >= end2) || (test >= end1 && test <= end2))
boolVal = 1;
else
boolVal = 0;
end
end
It creates a hexagonal grid, then calculates the number of crossings between a circle drawn with a fixed radius (62 in this case) and a specified centre.
The scatter calls show the locations that the function counts.
Implementing sprintf calls within the if(p1OnSeg == 1) block indicates that my function has chosen fictitious intersection points (although it then deals with them correctly)
if (interceptionPoint1(1) > -26 && interceptionPoint1(1) < -25)
sprintf('p1 = [%f, %f]. Vx = [%f, %f], Vy = [%f, %f].\nxint = [%f, %f], yint = [%f, %f]',...
interceptionPoint1(1), interceptionPoint1(2), VertexX(1,lc), VertexX(2,lc), VertexY(1,lc), VertexY(2,lc),...
xInterceptionPoints(1), xInterceptionPoints(2), yInterceptionPoints(1), yInterceptionPoints(2))
end
Outputs
p1 = [-25.980762, 0.000000]. Vx = [-25.980762, -25.980762], Vy = [-15.000000, 15.000000].
xint = [-25.980762, -25.980762], yint = [0.000000, 0.000000]
A picture shows the strange points.
Sorry for the very long question but - why are these being detected. They don't lie on the circle (displaying values within a mylinecirc function detects the intersections at around (-25, 55) and (-25, -55) or so (as an infinite line would expect).
Moving the circle can remove these points, but sometimes this leads to other problems with detection. What's the deal?
Edit: Rotating my grid pattern created by [Vx, Vy] = voronoi(...) and then removing points with very large values (ie those going close to infinity etc) appears to have fixed this problem. The removal of 'large' value points seems to be necessary to avoid NaN values appearing in 'slope' and 'intercept'. My guess is this is related to a possible slight inclination due to rotation, coupled with then overflow of the expected intercept.
Example code added is below. I also edited in Jan de Gier's code, but that made no difference to the problem and so is not changed in the question code.
%Rotate slightly
RotAngle = 8;
RotMat = [cosd(RotAngle), -sind(RotAngle); sind(RotAngle), cosd(RotAngle)];
for i=1:size(centres,1)
centres(i,:) = centres(i,:) - [floor(xMax/2) * dx, floor(yMax/2) * dy]; %Translation
centres(i,:) = ( RotMat * centres(i,:)' ); %Rotation
end
% Get counter for intersected lines
[VertexX, VertexY] = voronoi(centres(:,1), centres(:,2));
% Filter vertices
numLines = size(VertexX, 2);
newVx = [];
newVy = [];
for lc = 1:numLines
testVec = [VertexX(:,lc) VertexY(:,lc)];
if ~any(abs(testVec) > range*1.5)
newVx = [newVx; VertexX(:,lc)'];
newVy = [newVy; VertexY(:,lc)'];
end
end
VertexX = newVx';
VertexY = newVy';
numLines = size(VertexX, 2);
Still appreciating answers or suggestions to clear up why this is/was occuring.
Example values that cause this are getCutCountHex(30, [0,0]) and ...(35, [0,0])
I cant reproduce your problem, but the thing I did notice is that your onSeg() function might be wrong: it returns true if the testpoint lies in the rectangle with two of the four corner points being segStart and segEnd.
A function that returns true iff a point is on (or more accurate: close enough to) the line segment (segStart,segEnd) could be:
function boolVal = onSeg(segStart, segEnd, testPoint)
tolerance = .5;
AB = sqrt((segEnd(1)-segStart(1))*(segEnd(1)-segStart(1))+(segEnd(2)-segStart(2))*(segEnd(2)-segStart(2)));
AP = sqrt((testPoint(1)-segEnd(1))*(testPoint(1)-segEnd(1))+(testPoint(2)-segEnd(2))*(testPoint(2)-segEnd(2)));
PB = sqrt((segStart(1)-testPoint(1))*(segStart(1)-testPoint(1))+(segStart(2)-testPoint(2))*(segStart(2)-testPoint(2)));
boolVal = abs(AB - (AP + PB)) < tolerance;
end
an approach that I found in one of the anwers here: Find if point lays on line segment. I hope that solves your problem.
Related
So I'm trying to write a program that simulates the movement of gas particles in a sealed environment for an undergrad project (this is my first project so I'm pretty new to coding as a whole). My issue comes down to particle-particle collisions specifically. I have an if statement within an overarching while statement that reverses either the x components or y components of the colliding particles. When I run the script however, particles that should simply collide and have their velocities reversed end up stuttering back and forth. I think what's happening is the separation distance between collided particles after their velocities have been reversed is still below the initial value for collision so the velocities are reversed again. Kinda don't want this to happen and I've been stuck on it for a while. I just want the velocities to be reversed once until a new collision occurs. Collision handling can be found at the bottom of my script. Any advice on this would be greatly appreciated.
clc; clear; close all;
f = figure;
ax = axes('XLim', [0 10], 'YLim', [0 10]);
numberOfParticles = 30;
[particles, particlePositions, particleVelocities] = initializeNewParticle(numberOfParticles);
particleMotion(particles, particleVelocities, particlePositions);
%instantiates N particles
function [particles, particlePositions, particleVelocities] = initializeNewParticle(numberOfParticles)
speedMultiplier = 0.05;
for i = 1:numberOfParticles
particlePositionX(i) = 10*rand;
particlePositionY(i) = 10*rand;
particleVelocityX(i) = speedMultiplier * (-1 + 2*rand);
particleVelocityY(i) = speedMultiplier * (-1 + 2*rand);
particles(i) = line(particlePositionX(i), particlePositionY(i), 'marker', 'o', 'color', 'k', 'markersize', 15);
end
particlePositions = [particlePositionX; particlePositionY];
particleVelocities = [particleVelocityX; particleVelocityY];
end
%initial velocities & collision handling
function [] = particleMotion(particles, particleVelocities, particlePositions)
tic;
while toc < 10
%checks if particles are within bounds of figure
if any(particlePositions(:) < 0) || any(particlePositions(:) > 10)
%creates array that converts elements to 1 if particles out of bounds
outOfBounds = particlePositions < 0 | particlePositions > 10;
%finds index position of non-zero elements
indexPos = outOfBounds(:) > 0;
%uses index to invert velocities of particles out of bounds
particleVelocities(indexPos) = -particleVelocities(indexPos);
end
particlePositions = particlePositions + particleVelocities;
set(particles, 'XData', particlePositions(1,:),'YData', particlePositions(2,:), "LineStyle", "none");
%determines all separations from i particle to all N particles
for i = 1 : length(particles)
currentParticleXPos = get(particles(i), 'XData');
targetParticlesXPos(i, :) = particlePositions(1,:) - particlePositions(1,i);
currentParticleYPos = get(particles(i), 'YData');
targetParticlesYPos(i,:) = particlePositions(2,:) - particlePositions(2,i);
distanceBetweenParticles(i,:) = sqrt(targetParticlesXPos(i,:).^2 + targetParticlesYPos(i,:).^2);
end
%collision check and handling
if find(distanceBetweenParticles >= 0 & distanceBetweenParticles <= 0.5)
collisionCoordinates = triu((distanceBetweenParticles < 0.5 & distanceBetweenParticles > 0));
linearCollisionIndexValue = find(collisionCoordinates == 1);
[particle1,particle2] = ind2sub(size(collisionCoordinates), linearCollisionIndexValue);
particleVelocityX1 = particleVelocities(1,particle1);
particleVelocityX2 = particleVelocities(1,particle2);
particleVelocityY1 = particleVelocities(2,particle1);
particleVelocityY2 = particleVelocities(2,particle2);
if ~isequal(sign(particleVelocityX1), sign(particleVelocityX2))
particleVelocities(1,particle1) = -particleVelocityX1;
particleVelocities(1,particle2) = -particleVelocityX2;
elseif ~isequal(sign(particleVelocityY1), sign(particleVelocityY2))
particleVelocities(2,particle1) = -particleVelocityY1;
particleVelocities(2,particle2) = -particleVelocityY2;
end
end
pause(0.01);
end
end
I want to find Orientation, MajorAxisLengthand MinorAxisLength of contour which is plotted with below code.
clear
[x1 , x2] = meshgrid(linspace(-10,10,100),linspace(-10,10,100));
mu = [1,3];
sigm = [2,0;0,2];
xx_size = length(mu);
tem_matrix = ones(size(x1));
x_mesh= cell(1,xx_size);
for i = 1 : xx_size
x_mesh{i} = tem_matrix * mu(i);
end
x_mesh= {x1,x2};
temp_mesh = [];
for i = 1 : xx_size
temp_mesh = [temp_mesh x_mesh{i}(:)];
end
Z = mvnpdf(temp_mesh,mu,sigm);
z_plat = reshape(Z,size(x1));
figure;contour(x1, x2, z_plat,3, 'LineWidth', 2,'color','m');
% regionprops(z_plat,'Centroid','Orientation','MajorAxisLength','MinorAxisLength');
In my opinion, I may have to use regionprops command but I don't know how to do this. I want to find direction of axis of contour and plot something like this
How can I do this task? Thanks very much for your help
Rather than trying to process the graphical output of contour, I would instead recommend using contourc to compute the ContourMatrix and then use the x/y points to estimate the major and minor axes lengths as well as the orientation (for this I used this file exchange submission)
That would look something like the following. Note that I have modified the inputs to contourc as the first two inputs should be the vector form and not the output of meshgrid.
% Compute the three contours for your data
contourmatrix = contourc(linspace(-10,10,100), linspace(-10,10,100), z_plat, 3);
% Create a "pointer" to keep track of where we are in the output
start = 1;
count = 1;
% Now loop through each contour
while start < size(contourmatrix, 2)
value = contourmatrix(1, start);
nPoints = contourmatrix(2, start);
contour_points = contourmatrix(:, start + (1:nPoints));
% Now fit an ellipse using the file exchange
ellipsedata(count) = fit_ellipse(contour_points(1,:), contour_points(2,:));
% Increment the start pointer
start = start + nPoints + 1;
count = count + 1;
end
orientations = [ellipsedata.phi];
% 0 0 0
major_length = [ellipsedata.long_axis];
% 4.7175 3.3380 2.1539
minor_length = [ellipsedata.short_axis];
% 4.7172 3.3378 2.1532
As you can see, the contours are actually basically circles and therefore the orientation is zero and the major and minor axis lengths are almost equal. The reason that they look like ellipses in your post is because your x and y axes are scaled differently. To fix this, you can call axis equal
figure;contour(x1, x2, z_plat,3, 'LineWidth', 2,'color','m');
axis equal
Thank you #Suever. It help me to do my idea.
I add some line to code:
clear
[X1 , X2] = meshgrid(linspace(-10,10,100),linspace(-10,10,100));
mu = [-1,0];
a = [3,2;1,4];
a = a * a';
sigm = a;
xx_size = length(mu);
tem_matrix = ones(size(X1));
x_mesh= cell(1,xx_size);
for i = 1 : xx_size
x_mesh{i} = tem_matrix * mu(i);
end
x_mesh= {X1,X2};
temp_mesh = [];
for i = 1 : xx_size
temp_mesh = [temp_mesh x_mesh{i}(:)];
end
Z = mvnpdf(temp_mesh,mu,sigm);
z_plat = reshape(Z,size(X1));
figure;contour(X1, X2, z_plat,3, 'LineWidth', 2,'color','m');
hold on;
% Compute the three contours for your data
contourmatrix = contourc(linspace(-10,10,100), linspace(-10,10,100), z_plat, 3);
% Create a "pointer" to keep track of where we are in the output
start = 1;
count = 1;
% Now loop through each contour
while start < size(contourmatrix, 2)
value = contourmatrix(1, start);
nPoints = contourmatrix(2, start);
contour_points = contourmatrix(:, start + (1:nPoints));
% Now fit an ellipse using the file exchange
ellipsedata(count) = fit_ellipse(contour_points(1,:), contour_points(2,:));
% Increment the start pointer
start = start + nPoints + 1;
count = count + 1;
end
orientations = [ellipsedata.phi];
major_length = [ellipsedata.long_axis];
minor_length = [ellipsedata.short_axis];
tet = orientations(1);
x1 = mu(1);
y1 = mu(2);
a = sin(tet) * sqrt(major_length(1));
b = cos(tet) * sqrt(major_length(1));
x2 = x1 + a;
y2 = y1 + b;
line([x1, x2], [y1, y2],'linewidth',2);
tet = ( pi/2 + orientations(1) );
a = sin(tet) * sqrt(minor_length(1));
b = cos(tet) * sqrt(minor_length(1));
x2 = x1 + a;
y2 = y1 + b;
line([x1, x2], [y1, y2],'linewidth',2);
I have a question about changing the color of lines in a plot in MATLAB. I have written a code where I want to change the color of lines in a plot that is embedded in several for loops (the code is shown below). In the code, a new plot is created (with its own figure) when the "if loop" condition is satisfied. I want each plot to have lines with different colors (from other plots), so I created a variable = "NewColor" to increment and change the line colors. However, the following problem has been occurring:
Suppose I am in debug mode and I have stopped at the plot command. I run the next step and a plot is created with a blue line. I check the value of NewColor and find NewColor = 0.1. Next, I use the "run to cursor" command to step to the next time the plot command is activated. When I do this I am still within the "i for loop", so NewColor has not changed. I check the editor to find that NewColor = 0.1. Therefore, when I run the next step a blue line should show up on the current plot. To the contrary and my disbelief an orange line shows up (in addition to the blue line). I don't understand since in both steps of the debugger NewColor = 0.1, and the code is written so the color of the lines = [0,NewColor,0]. If anyone can find the error of my ways it would be greatly appreciated. Thanks
ThetaPlot = [40,50]; % Put incident angle as input
Count1 = 0;
Count2 = 0;
NewColor = 0;
for m = 1:length(ThetaPlot)
NewColor = 0.1;
Title = sprintf('Angle(%d)',ThetaPlot(m));
figure('name',Title)
Count1 = 0;
for i = 1:length(xrange)-1 % X Coordinate of Start Node
for j = 1:length(yrange)-1 % Y Coordinate of Start Node
Count1 = Count1+1;
for k = 2:length(xrange) % X Coordinate of End Node
for l = 2:length(yrange) % Y Coordinate of End Node
Count2 = Count2+1;
if ReflRayData(Count2,ThetaPlot(m) - ThetaIncident(1) + 1,Count1) == 1
x = [xrange(i),xrange(k)];
y = [yrange(j),yrange(l)];
plot(x,y,['-',[0,NewColor,0],'o']);
hold on;
end
end
Count2 = 0;
end
end
end
NewColor = NewColor + 0.02;
end
Full Code:
%% Calculating Angles of Reflection
run = 1; % Set run = 1 for calculations
if run == 1
xrange = [0:1:14.5]'; % Coordinates to try for Panel Geometry (in)
yrange = [0:1:36]'; % Coordinates to try for Panel Geometry (in)
ThetaIncident = [-90:1:90]'; % Incident Angle of Ray (measured relative to normal direction with clockwise postive)
OvenGlassXrange = [14.5:0.1:36.5]; %Range of X coordinates for Oven Glass
ReflRayData = zeros((length(xrange)-1)*(length(yrange)-1),length(ThetaIncident),(length(xrange)-1)*(length(yrange)-1)); % Matrix containing Reflected Ray Data
Count1 = 0;
Count2 = 0;
for i = 1:length(xrange)-1 % X Coordinate of Start Node
for j = 1:length(yrange)-1 % Y Coordinate of Start Node
Count1 = Count1+1;
for k = 2:length(xrange) % X Coordinate of End Node
for l = 2:length(yrange) % Y Coordinate of End Node
Count2 = Count2+1;
for m = 1:length(ThetaIncident)
xStart = xrange(i);
yStart = yrange(j);
xEnd = xrange(k);
yEnd = yrange(l);
m1 = (yEnd - yStart)/(xEnd - xStart); % Slope between Start and End Nodes
b1 = yStart - m1*xStart;
m2 = 1/m1; % Slope of normal direction
b2 = (yEnd - 0.5*(yEnd - yStart)) - m2*(xEnd - 0.5*(xEnd - xStart));
ArbXCoor = 1; % Arbitary Point X Coordinate on Normal Line
ArbYCoor = m2*ArbXCoor+b2; % Arbitary Point Y Coordinate on Normal Line
ThetaReflected = -ThetaIncident(m); % Reflected Angle
ArbXCoorRot = ArbXCoor*cosd(ThetaReflected) - ArbYCoor*sind(ThetaReflected); % Arbitary Point X Coordinate on Reflected Line
ArbYCoorRot = ArbYCoor*cosd(ThetaReflected) + ArbXCoor*sind(ThetaReflected); % Arbitary Point Y Coordinate on Reflected Line
m3 = (ArbYCoorRot - (yEnd - 0.5*(yEnd - yStart)))/(ArbXCoorRot - (xEnd - 0.5*(xEnd - xStart))); % Slope of Reflected Line
b3 = (yEnd - 0.5*(yEnd - yStart)) - m3*(xEnd - 0.5*(xEnd - xStart));
ElemLength = sqrt((yEnd - yStart)^2 + (xEnd - xStart)^2);
if min(OvenGlassXrange) < -b3/m3 && -b3/m3 < max(OvenGlassXrange) && -1 < m1 && m1 < 0 && m1 ~= -Inf && m1 ~= Inf && ElemLength < 3
ReflRayData(Count2,m,Count1) = 1;
end
end
end
end
Count2 = 0;
end
end
%% Plotting
ThetaPlot = [40,50]; % Put incident angle as input
Count1 = 0;
Count2 = 0;
NewColor = 0;
for m = 1:length(ThetaPlot)
NewColor = 0.1;
Title = sprintf('Angle(%d)',ThetaPlot(m));
figure('name',Title)
Count1 = 0;
for i = 1:length(xrange)-1 % X Coordinate of Start Node
for j = 1:length(yrange)-1 % Y Coordinate of Start Node
Count1 = Count1+1;
for k = 2:length(xrange) % X Coordinate of End Node
hold on;
for l = 2:length(yrange) % Y Coordinate of End Node
Count2 = Count2+1;
if ReflRayData(Count2,ThetaPlot(m) - ThetaIncident(1) + 1,Count1) == 1
x = [xrange(i),xrange(k)];
y = [yrange(j),yrange(l)];
plot(x,y,['-',[0,NewColor,0],'o']);
hold on;
end
end
Count2 = 0;
end
end
end
NewColor = NewColor + 0.02;
end
instead of plot(x,y,['-',[0,NewColor,0],'o']); try:
plot(x,y,'linestyle','-','marker','o','color',[0,NewColor,0])
According to the Matlab documentation, by calling hold on Matlab uses the next color.
hold on retains plots in the current axes so that new plots added to the axes do not delete existing plots. New plots use the next colors and line styles based on the ColorOrder and LineStyleOrder properties of the axes.
Therefore, in your code when you call hold on inside the for, it just uses the next color.
My solution is to put figure; hold on; before for loop and remove that one in you loop
I want to set the Location of my legend to 'Best' (like legend('y1','y2','Location','Best')) so the legend doesn't collide with my lines, but at the same time, I would prefer to have it in a corner if that's possible with no data collision. Is there a way of implementing this?
In case anyone's interested in this, I wrote a function based on #S.. answer that does, what I wanted to achieve. Here's the code:
function setPositionCornerBest( figureHandle )
%Sets the Location of the legend of the figure that is referenced by figureHandle to one of the Corners if there is no data in the Corners. Otherwise it sets it to 'Best'
h = figureHandle;
figObjects = get(h,'Children');
legHandle = findobj(figObjects,'Tag','legend');
axHandle = findobj(figObjects,'Type','axes','-and','Tag','');
lineHandle = findobj(figObjects,'Type','line','-and','Parent',axHandle);
axPos = get(axHandle,'Position');
LimX = get(axHandle,'XLim');
LimY = get(axHandle,'YLim');
xScaling = (LimX(2)-LimX(1))/axPos(3);
yScaling = (LimY(2)-LimY(1))/axPos(4);
locCell = {'NorthWest','NorthEast','SouthEast','SouthWest'};
ii = 1;
interSecFlag = true;
while (interSecFlag) && (ii<=4)
set(legHandle,'Location',locCell{ii});
legPos = get(legHandle,'Position');
x(1) = LimX(1)+(legPos(1)-axPos(1))*xScaling;
x(2) = x(1);
x(3) = LimX(1)+(legPos(1)+legPos(3)-axPos(1))*xScaling;
x(4) = x(3);
x(5) = x(1);
y(1) = LimY(1)+(legPos(2)-axPos(2))*yScaling;
y(2) = LimY(1)+(legPos(2)+legPos(4)-axPos(2))*yScaling;
y(3) = y(2);
y(4) = y(1);
y(5) = y(1);
for jj = 1:numel(lineHandle)
xline = get(lineHandle(jj),'XData');
yline = get(lineHandle(jj),'YData');
[xInter ~] = intersections(x,y,xline,yline);
if numel(xInter) == 0
xInterFlag(jj) = 0;
else
xInterFlag(jj) = 1;
end
end
if all(xInterFlag==0)
interSecFlag = false;
end
ii = ii + 1;
end
if interSecFlag
set(legHandle,'Location','Best');
end
end
I don't have a complete answer, only a sketch. However, you could try to first set the legend in a corner
a=legend('y1', 'y2', 'Location', 'NorthEast')
and then obtain its position
get(a,'Position')
You can convert this position to coordinates and simply test whether your lines cross any border of the legend using
http://www.mathworks.com/matlabcentral/fileexchange/11837-fast-and-robust-curve-intersections
.If this is the case, try another corner, until there is no corner left. In that case, use 'Best'.
I have used the following code from the matlab central website in my project to perform seeded region growing. This works perfectly but I am struggling to understand exactly what the code is doing in some places. I have contacted the author but have had no reply. Would anyone be able to provide me with some explanations ?
function Phi = segCroissRegion(tolerance,Igray,x,y)
if(x == 0 || y == 0)
imshow(Igray,[0 255]);
[x,y] = ginput(1);
end
Phi = false(size(Igray,1),size(Igray,2));
ref = true(size(Igray,1),size(Igray,2));
PhiOld = Phi;
Phi(uint8(x),uint8(y)) = 1;
while(sum(Phi(:)) ~= sum(PhiOld(:)))
PhiOld = Phi;
segm_val = Igray(Phi);
meanSeg = mean(segm_val);
posVoisinsPhi = imdilate(Phi,strel('disk',1,0)) - Phi;
voisins = find(posVoisinsPhi);
valeursVoisins = Igray(voisins);
Phi(voisins(valeursVoisins > meanSeg - tolerance & valeursVoisins < meanSeg + tolerance)) = 1;
end
Thanks
I've added some comments in your code :
function Phi = segCroissRegion(tolerance,Igray,x,y)
% If there's no point, select one from image
if(x == 0 || y == 0)
imshow(Igray,[0 255]);
[x,y] = ginput(1);
end
%Create seed with by adding point in black image
Phi = false(size(Igray,1),size(Igray,2));
ref = true(size(Igray,1),size(Igray,2));
PhiOld = Phi;
Phi(uint8(x),uint8(y)) = 1;
while(sum(Phi(:)) ~= sum(PhiOld(:)))
PhiOld = Phi;
% Evaluate image intensity at seed/line points
segm_val = Igray(Phi);
% Calculate mean intensity at seed/line points
meanSeg = mean(segm_val);
% Grow seed 1 pixel, and remove previous seed (so you'll get only new pixel perimeter)
posVoisinsPhi = imdilate(Phi,strel('disk',1,0)) - Phi;
% Evaluate image intensity over the new perimeter
voisins = find(posVoisinsPhi);
valeursVoisins = Igray(voisins);
% If image intensity over new perimeter is greater than the mean intensity of previous perimeter (minus tolerance), than this perimeter is part of the segmented object
Phi(voisins(valeursVoisins > meanSeg - tolerance & valeursVoisins < meanSeg + tolerance)) = 1;
% Repeat while there's new pixel in seed, stop if no new pixel were added
end