Changing colour of plotted shape when the mouse hovers it?

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

You cannot change the color of a single side of a polygon object, so I think your only option is to overlay a line over the side you want to highlight.
I'm not 100% clear on your requirements. Here is a simple script that will highlight the indicated side, regardless of where you've hovered over the polyshape.
x = [1 1 5 5 10 10];
y = [1 10 10 5 5 1];
pgon = polyshape(x,y);
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, [10 10],[1 5],'LineWidth',2,'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)
% Make the line visible
lineObj.Visible = true;
else
% Hide the line
lineObj.Visible = false;
end
end

Plus de réponses (1)

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

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

Connectez-vous pour commenter.

Catégories

En savoir plus sur Graphics Object Properties dans Centre d'aide et File Exchange

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by