This repository was archived by the owner on Oct 4, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGraphicalInterface.m
264 lines (246 loc) · 11.8 KB
/
GraphicalInterface.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
% This file is part of Interactive Bezier Curves.
%
% Interactive Bezier Curves is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Interactive Bezier Curves is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Nome-Programma. If not, see <http://www.gnu.org/licenses/>.
classdef GraphicalInterface < handle
%GRAPHICALINTERFACE Manage the interface of the application
properties
application;
controlPointsPlot=[];
controlPolyPlot=[];
bezierPlot = [];
linesPlot = [];
clearButton;
addCurveButton;
tangentButton;
normalButton;
textInstructions;
hideControlsButton;
lengthButton;
end
methods
function this = GraphicalInterface(applicationReference)
this.application=applicationReference;
end
function create(this)
%create a figure with defined title and hide showing figure number in title
figureHandler=figure('Name','Interactive Bezier Curves','NumberTitle','off');
%hide the menu
figureHandler.MenuBar='none';
%get screen dimension
screenSize = get(groot,'ScreenSize');
%set figure position and dimension according to screen dimension
figureHandler.Position=[1 screenSize(4)/2 screenSize(3)/2 screenSize(4)/2];
%use the same length for the data units along each axis
axis equal;
%set axis limits
axis([0 1 0 1]);
%get the current axis handler
currentAxis = gca;
%set the unit of measurement to pixel
%ginput() and plot() still use dimension based on cartesian coordinate
currentAxis.Units = 'pixels';
%set axis left-margin, bottom-margin, width and height
currentAxis.Position = [150 110 400 400];
%define clear button but set to invisible for now
this.clearButton = uicontrol('Style', 'pushbutton', 'String', 'Clear','Position', [20 30 60 30],...
'Callback', @(src,event)this.clearAllPlot,...
'Visible','off');
%define button for adding a curve, but hide it for now
this.addCurveButton = uicontrol('Style', 'pushbutton', 'String', 'Add curve','Position', [20 60 90 30],...
'Callback', @(src,event)this.application.userInteractionAgent.drawNewCurve,...
'Visible','off');
%define button for showing tangent, but hide it for now
this.tangentButton = uicontrol('Style', 'pushbutton', 'String', 'Tangent','Position', [20 90 90 30],...
'Callback',{@(src,event)this.application.userInteractionAgent.enterCurveSelectionMode(0)},...
'Visible','off');
%define button for showing normal, but hide it for now
this.normalButton = uicontrol('Style', 'pushbutton', 'String', 'Normal','Position', [20 120 90 30],...
'Callback',{@(src,event)this.application.userInteractionAgent.enterCurveSelectionMode(1)},...
'Visible','off');
%define button for calculate length of the curve, but hide it for now
this.lengthButton = uicontrol('Style', 'pushbutton', 'String', 'Length','Position', [20 150 90 30],...
'Callback',{@(src,event)this.application.userInteractionAgent.enterCurveSelectionMode(2)},...
'Visible','off');
this.hideControlsButton = uicontrol('Style', 'pushbutton', 'String', 'HideControls','Position', [20 180 90 30],...
'Visible','off','Callback',@(src,event)this.hideControls);
%define text for giving istruction to the user
this.textInstructions = uicontrol('Style','text','Position',[150 0 400 80],'HorizontalAlignment','left');
%set hold state to on so adding new points doesn't delete old points
hold on;
end
function enterDrawingMode(this)
%set istructions for the user
this.setInstruction(3);
%set clear button and add button to invisible during drawing
this.clearButton.Visible = 'off';
this.addCurveButton.Visible = 'off';
this.tangentButton.Visible = 'off';
this.normalButton.Visible = 'off';
this.hideControlsButton.Visible = 'off';
this.lengthButton.Visible = 'off';
end
function plotControlPoint(this,x,y,clickcallback,controlPointNumber,curveNumber)
tag = strcat(int2str(controlPointNumber),'-',int2str(curveNumber));
%plot a blue cicle at the given coordinates
plot(x,y,'bo','MarkerSize',10,'MarkerFaceColor','b','ButtonDownFcn',clickcallback,'Tag',tag);
this.controlPointsPlot{curveNumber,controlPointNumber}=tag;
end
function exitDrawingMode(this)
%after a curve is drawn, set to visible the clear button
this.clearButton.Visible='on';
%display all the button for features related to drawed curves
%and the add curve button
this.addCurveButton.Visible='on';
this.tangentButton.Visible = 'on';
this.normalButton.Visible = 'on';
this.hideControlsButton.Visible = 'on';
this.lengthButton.Visible = 'on';
%modify instructions
this.setInstruction(4);
end
%plot bezier curve with control polygonal given a set of points
function drawBezierCurve(this,curveIndex)
%get bezier curve by given index
bezierCurve = this.application.bezierCurves(curveIndex);
%delete old plots if present
if (length(this.controlPolyPlot)>=curveIndex)
delete(this.controlPolyPlot(curveIndex));
delete(this.bezierPlot(curveIndex));
end
if (~isempty(bezierCurve.controlPoints))
% draw control polygonal
this.controlPolyPlot(curveIndex) = plot(bezierCurve.controlPoints(1,:),bezierCurve.controlPoints(2,:),'g-');
%move the control polygonal to minimum z-index for better
%click detection on control points
uistack(this.controlPolyPlot(curveIndex),'bottom');
%calculate bezier curve
bezierPoints = bezierCurve.calculateBezier();
%draw red solid line bézier curve
this.bezierPlot(curveIndex) = plot(bezierPoints(1,:),bezierPoints(2,:),'r-');
%move the bezier curve plot to minimum z-index for better
%click detection on control points
uistack(this.bezierPlot(curveIndex),'bottom');
end
end
function clearAllPlot(this)
%clear everything except this
this.application.clearCurves();
%delete all the control point graphic object
cellfun(@(tag) this.deleteControlPoint(tag),this.controlPointsPlot);
%empties array
this.controlPointsPlot=[];
delete(this.controlPolyPlot);
this.controlPolyPlot = [];
delete(this.bezierPlot);
this.bezierPlot = [];
delete(this.linesPlot);
this.linesPlot=[];
%enter mode for drawing new curve
this.application.userInteractionAgent.drawNewCurve();
end
function deleteControlPoint(~,tag)
%find object given its tag
obj=findobj('Tag',tag);
%delete graphic object
delete(obj);
end
function hideControls(this)
%iterate through the point and set Visible to off
cellfun(@hideControlPoint,this.controlPointsPlot);
function hideControlPoint(tag)
if (ischar(tag))
obj=findobj('Tag',tag);
obj.Visible='off';
end
end
%iterate through the curves and hide polygonal
arrayfun(@hidePolygonals,this.controlPolyPlot);
function hidePolygonals(polygonal)
set(polygonal,'Visible','off');
end
%change button string
this.hideControlsButton.String='Show';
%set 'show' callback on button click
this.hideControlsButton.Callback=@(src,event)this.showControls;
this.setInstruction(5);
end
function showControls(this)
%iterate through the point and set Visible to on
cellfun(@showControls,this.controlPointsPlot);
function showControls(tag)
if (ischar(tag))
obj=findobj('Tag',tag);
obj.Visible='on';
end
end
%iterate through the curves and show polygonal
arrayfun(@hidePolygonals,this.controlPolyPlot);
function hidePolygonals(polygonal)
set(polygonal,'Visible','on');
end
%change button string
this.hideControlsButton.String='Hide';
%set 'hide' callback on button click
this.hideControlsButton.Callback=@(src,event)this.hideControls;
this.setInstruction(4);
end
function movePlotPoint(~,newPos,object)
%update control point "plot"
object.XData=newPos(1);
object.YData=newPos(2);
end
function plotLine(this,line,curveIndex)
%plot the given point
this.linesPlot(curveIndex,end+1) = plot(line(1,:),line(2,:));
%set to minimum z-index so the user can click in the same point
%for the normal/tangent.
uistack(this.linesPlot(curveIndex,end),'bottom');
end
%called on curve modify
function clearLines(this,curveIndex)
%delete all the tangents and normals
delete(this.linesPlot(curveIndex));
%empties array
this.linesPlot(curveIndex) = [];
end
%display a message box with the given value
function displayValue(~,value)
%if the value is numeric
if (isnumeric(value))
%convert it to string
value = num2str(value);
end
%show the value in a message box
msgbox(value);
end
%change instruction for the use
function setInstruction(this,mode)
switch mode
case 0 %tangent mode
this.textInstructions.String = 'Click on a point of a curve for showing the tangent line to that point';
case 1 %normal mode
this.textInstructions.String = 'Click on a point of a curve for showing the normal line to that point';
case 2 %length mode
this.textInstructions.String = 'Click on curve to get its length';
case 3 %drawing mode
this.textInstructions.String = {'Left mouse click for define a control point',...
'Central mouse button for ending draw a closed curve or right mouse button for open curve'};
case 4 %drag and drop mode
this.textInstructions.String = 'Drag and drop a control point for modify the curve';
case 5 %nothing mode
this.textInstructions.String = '';
end
end
end
end