Changing colour of plotted shape when the mouse hovers it?
Afficher commentaires plus anciens
I am trying to change the color of the side of a shape when the mouse hovers over any of the sides of the shape.
So e.g if I have the shape below and hover my mouse over the right side I want that side to change to a different color.
x = [1 1 5 5 10 10];
y = [1 10 10 5 5 1];
pgon = polyshape(x,y);
plot(pgon)
Réponse acceptée
Plus de réponses (1)
Benjamin Kraus
le 17 Nov 2021
Here is a much more complicated version that I think does what you wanted (although I'm not sure).
This version figures out which edge of the polygon is closest to the mouse and highlights that edge.
I adapted this code heavily from the example provided in this MATLAB Answer: Distance Between Points and a Line Segment in 3D
x = [1 1 5 5 10 10];
y = [1 10 10 5 5 1];
pgon = polyshape(x,y);
% Draw the polyshape
f = figure;
ax = axes(f);
polygonObj = plot(ax, pgon);
% Create a line to use as an overlay, but leave it invisible for now.
lineObj = line(ax, NaN, NaN,'LineWidth',3,'Color','red');
lineObj.Visible = false;
% Add a callback to be called when the mouse moves.
f.WindowButtonMotionFcn = @(~,~) hover(polygonObj, lineObj);
function hover(polygonObj, lineObj)
% Find out where the mouse is pointing.
ax = polygonObj.Parent;
x = ax.CurrentPoint(1,1);
y = ax.CurrentPoint(1,2);
% Determine whether the mouse is inside the shape.
pgon = polygonObj.Shape;
if isinterior(pgon, x, y)
% Append the first vertex to the end.
vertices = pgon.Vertices;
vertices = [vertices; vertices(1,:)];
% Find the closest edge.
ind = closestEdge([x y], vertices);
% Draw the line along the closest edge.
lineObj.XData = vertices(ind+[0 1],1);
lineObj.YData = vertices(ind+[0 1],2);
lineObj.Visible = true;
else
% Outside the polygon, hide the line.
lineObj.Visible = false;
end
end
function ind = closestEdge(pt, vertices)
% Pad both vertices and point with 0.
vertices(:,3) = 0;
pt(3) = 0;
% Find the length of each edge:
lengthEdges = vecnorm(diff(vertices, [], 1), 2, 2);
% Find the distance from the point to each individual vertex.
distPointToVertices = vecnorm(pt - vertices, 2, 2);
distPointToStart = distPointToVertices(1:end-1);
distPointToEnd = distPointToVertices(2:end);
% Find the distance from each point to an infinite line along each edge.
a = diff(vertices, [], 1);
b = pt - vertices(2:end,:);
distPointToLine = vecnorm(cross(a,b,2),2,2) ./ vecnorm(a,2,2);
% Determine which edges have the point past the "end" of the edge.
pastTheEnd = vecnorm([lengthEdges distPointToEnd], 2, 2) <= distPointToStart;
% Determine which edges have the point past the "start" of the edge.
pastTheStart = vecnorm([lengthEdges distPointToStart], 2, 2) <= distPointToEnd;
% Find the distance to the edge.
distToEdge = distPointToLine;
distToEdge(pastTheEnd) = distPointToEnd(pastTheEnd);
distToEdge(pastTheStart) = distPointToStart(pastTheStart);
% Find the closest edge.
[~,ind] = min(distToEdge);
end
1 commentaire
Benjamin Kraus
le 17 Nov 2021
And, one more version. This one highlights the closest edge, but only if you are within a short distance from the edge.
x = [1 1 5 5 10 10];
y = [1 10 10 5 5 1];
pgon = polyshape(x,y);
% Draw the polyshape
f = figure;
ax = axes(f);
polygonObj = plot(ax, pgon);
% Create a line to use as an overlay, but leave it invisible for now.
lineObj = line(ax, NaN, NaN,'LineWidth',3,'Color','red');
lineObj.Visible = false;
% Add a callback to be called when the mouse moves.
f.WindowButtonMotionFcn = @(~,~) hover(polygonObj, lineObj);
function hover(polygonObj, lineObj)
% Find out where the mouse is pointing.
ax = polygonObj.Parent;
x = ax.CurrentPoint(1,1);
y = ax.CurrentPoint(1,2);
% Append the first vertex to the end.
vertices = polygonObj.Shape.Vertices;
vertices = [vertices; vertices(1,:)];
% Find the distance to the closest edge.
[d, ind] = closestEdge([x y], vertices);
% If the distance is within a tolerance of 0.1, highlight the edge.
if d < 0.1
% Draw the line along the closest edge.
lineObj.XData = vertices(ind+[0 1],1);
lineObj.YData = vertices(ind+[0 1],2);
lineObj.Visible = true;
else
% Hide the line.
lineObj.Visible = false;
end
end
function [d,ind] = closestEdge(pt, vertices)
% Pad both vertices and point with 0.
vertices(:,3) = 0;
pt(3) = 0;
% Find the length of each edge:
lengthEdges = vecnorm(diff(vertices, [], 1), 2, 2);
% Find the distance from the point to each individual vertex.
distPointToVertices = vecnorm(pt - vertices, 2, 2);
distPointToStart = distPointToVertices(1:end-1);
distPointToEnd = distPointToVertices(2:end);
% Find the distance from each point to an infinite line along each edge.
a = diff(vertices, [], 1);
b = pt - vertices(2:end,:);
distPointToLine = vecnorm(cross(a,b,2),2,2) ./ vecnorm(a,2,2);
% Determine which edges have the point past the "end" of the edge.
pastTheEnd = vecnorm([lengthEdges distPointToEnd], 2, 2) <= distPointToStart;
% Determine which edges have the point past the "start" of the edge.
pastTheStart = vecnorm([lengthEdges distPointToStart], 2, 2) <= distPointToEnd;
% Find the distance to the edge.
distToEdge = distPointToLine;
distToEdge(pastTheEnd) = distPointToEnd(pastTheEnd);
distToEdge(pastTheStart) = distPointToStart(pastTheStart);
% Find the closest edge.
[d,ind] = min(distToEdge);
end
Catégories
En savoir plus sur Graphics Object Properties dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!