Интересно было бы сделать игрушку, в которой данные точки можно таскать мышкой и смотреть как меняются ГМТ, пары касающихся окружностей и четырёхугольники, соответствующие точкам пересечения ГМТ. Это несложно сделать в Mathematica Попытался реализовать идею в Матлабе. Исходные точки таскаются мышкой, при этом меняются кривые ГМТ. При щелчке мышкой далее, чем 5% от любой исходной точки, выполняется поиск решения в окрестности точки щелчка (лучше целенаправленно щелкать в точки пересечения кривых) и строится это решение. Сделано весьма коряво, это мой первый опыт создания GUI, буду признателен за дельные советы и замечания. Насколько я понял, надо создать файл с именем GUI_test.m, и скопировать в него следующий код: (Оффтоп)
Код: function GUI_test(arg) if nargin == 0; Initialize elseif arg == 0 Action elseif arg == -1 SetWindowSize end end
function Initialize() % set(gcf,'numbertitle','off','menubar','none')
h.ws = [0; 0; 5]; axis([h.ws(1)-h.ws(3)/2, h.ws(1)+h.ws(3)/2, h.ws(2)-h.ws(3)/2, h.ws(2)+h.ws(3)/2]) axis square
uicontrol('style','text', 'units','normalized', 'position',[.86 .65 .12 .03], 'string','центр по X'); uicontrol('style','edit', 'units','normalized', 'position',[.86 .60 .12 .05],.... 'string',h.ws(1), 'value',1, 'callback','GUI_test(-1)'); uicontrol('style','text', 'units','normalized', 'position',[.86 .55 .12 .03], 'string','центр по Y'); uicontrol('style','edit', 'units','normalized', 'position',[.86 .50 .12 .05], ... 'string',h.ws(2), 'value',2, 'callback','GUI_test(-1)'); uicontrol('style','text', 'units','normalized', 'position',[.86 .45 .12 .03], 'string','ширина окна'); uicontrol('style','edit', 'units','normalized', 'position',[.86 .40 .12 .05], ... 'string',h.ws(3), 'value',3, 'callback','GUI_test(-1)');
h.P = [1,1; 1,-1; -1,-1; -1,0]; h.P0.mark = line(0, 0, 'marker','o','erase','xor','color','r','LineWidth',2,'Visible','off'); h.P1.mark = line(h.P(1, 1),h.P(1, 2),'marker','o','erase','xor','color','k'); h.P2.mark = line(h.P(2, 1),h.P(2, 2),'marker','o','erase','xor','color','k'); h.P3.mark = line(h.P(3, 1),h.P(3, 2),'marker','o','erase','xor','color','k'); h.P4.mark = line(h.P(4, 1),h.P(4, 2),'marker','o','erase','xor','color','k');
h.F0.line = line([h.P(:, 1); h.P(1, 1)], [h.P(:, 2); h.P(1, 2)], 'erase','xor','color','k'); h.F1.line = line(0, 0, 'erase','xor','color','b','Visible','off'); h.F2.line = line(0, 0, 'marker','.','erase','xor','color','g','Visible','off'); h.F3.line = line(0, 0, 'marker','.','erase','xor','color','g','Visible','off');
h.C1.line = line(h.P(1, 1),h.P(1, 2),'erase','xor','color','c','LineStyle',':'); h.C2.line = line(h.P(1, 1),h.P(1, 2),'erase','xor','color','m','LineStyle',':');
Curves(h);
set(gcf,'name','Задача о четырёхугольнике') set(gcf,'tag','Задача о четырёхугольнике', ... 'userdata',h, ... 'windowbuttondownfcn', 'GUI_test(0); set(gcf,''windowbuttonmotionfcn'',''GUI_test(0)'')', ... 'windowbuttonupfcn', 'set(gcf,''windowbuttonmotionfcn'','''')') end
function Action h = get(gcf,'userdata'); pt = get(gca,'currentpoint'); x = pt(1,1:2);
d1 = (x(1)-h.P(1,1))^2 + (x(2)-h.P(1,2))^2; d2 = (x(1)-h.P(2,1))^2 + (x(2)-h.P(2,2))^2; d3 = (x(1)-h.P(3,1))^2 + (x(2)-h.P(3,2))^2; d4 = (x(1)-h.P(4,1))^2 + (x(2)-h.P(4,2))^2; d_min = min([d1, d2, d3, d4]);
if d_min < h.ws(3)/20 set(h.P0.mark,'Visible','off'); set(h.F1.line,'Visible','off'); set(h.F2.line,'Visible','off'); set(h.F3.line,'Visible','off');
if d_min == d1 h.P = [x; h.P(2,:); h.P(3,:); h.P(4,:)]; h_P = h.P1; elseif d_min == d2 h.P = [h.P(1,:); x; h.P(3,:); h.P(4,:)]; h_P = h.P2; elseif d_min == d3 h.P = [h.P(1,:); h.P(2,:); x; h.P(4,:)]; h_P = h.P3; elseif d_min == d4 h.P = [h.P(1,:); h.P(2,:); h.P(3,:); x]; h_P = h.P4; else return end
set(h_P.mark,'xdata',x(1),'ydata',x(2)); set(h.F0.line,'xdata',[h.P(:, 1); h.P(1, 1)],'ydata',[h.P(:, 2); h.P(1, 2)]); Curves(h); set(gcf,'userdata',h); else Figures(h, x); end end
function Curves(h) X1 = h.P(1,1); Y1 = h.P(1,2); X2 = h.P(2,1); Y2 = h.P(2,2); X3 = h.P(3,1); Y3 = h.P(3,2); X4 = h.P(4,1); Y4 = h.P(4,2);
ds = h.ws(3)/50; xx = (h.ws(1)-h.ws(3)/2):ds:(h.ws(1)+h.ws(3)/2); yy = (h.ws(2)-h.ws(3)/2):ds:(h.ws(2)+h.ws(3)/2); [x0,y0] = meshgrid(xx, yy);
zz = ((X2 - x0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (X1 - x0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0))).*((Y4 - y0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0)) - (Y3 - y0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))) - ((X4 - x0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0)) - (X3 - x0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))).*((Y2 - y0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (Y1 - y0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0))) - x0.*(((X2 - x0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (X1 - x0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0))).*((X3 - x0).*(Y4 - y0) - (X4 - x0).*(Y3 - y0)) - ((X4 - x0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0)) - (X3 - x0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))).*((X1 - x0).*(Y2 - y0) - (X2 - x0).*(Y1 - y0))) - y0.*(((Y2 - y0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (Y1 - y0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0))).*((X3 - x0).*(Y4 - y0) - (X4 - x0).*(Y3 - y0)) - ((Y4 - y0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0)) - (Y3 - y0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))).*((X1 - x0).*(Y2 - y0) - (X2 - x0).*(Y1 - y0))); C = contourc(xx, yy, zz, [0, 0]); C(:,1) = []; set(h.C1.line,'xdata',C(1,:),'ydata',C(2,:));
zz = ((X4 - x0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (X1 - x0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))).*((Y3 - y0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0)) - (Y2 - y0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0))) - ((X3 - x0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0)) - (X2 - x0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0))).*((Y4 - y0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (Y1 - y0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))) - x0.*(((X4 - x0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (X1 - x0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))).*((X2 - x0).*(Y3 - y0) - (X3 - x0).*(Y2 - y0)) - ((X3 - x0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0)) - (X2 - x0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0))).*((X1 - x0).*(Y4 - y0) - (X4 - x0).*(Y1 - y0))) - y0.*(((Y4 - y0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (Y1 - y0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))).*((X2 - x0).*(Y3 - y0) - (X3 - x0).*(Y2 - y0)) - ((Y3 - y0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0)) - (Y2 - y0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0))).*((X1 - x0).*(Y4 - y0) - (X4 - x0).*(Y1 - y0))); C = contourc(xx, yy, zz, [0, 0]); C(:,1) = []; set(h.C2.line,'xdata',C(1,:),'ydata',C(2,:)); end
function Figures(h, x) X1 = h.P(1,1); Y1 = h.P(1,2); X2 = h.P(2,1); Y2 = h.P(2,2); X3 = h.P(3,1); Y3 = h.P(3,2); X4 = h.P(4,1); Y4 = h.P(4,2);
function r = diagonal_conditions(p0) x0 = p0(1); y0 = p0(2); r = [((X2 - x0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (X1 - x0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0))).*((Y4 - y0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0)) - (Y3 - y0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))) - ((X4 - x0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0)) - (X3 - x0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))).*((Y2 - y0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (Y1 - y0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0))) - x0.*(((X2 - x0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (X1 - x0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0))).*((X3 - x0).*(Y4 - y0) - (X4 - x0).*(Y3 - y0)) - ((X4 - x0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0)) - (X3 - x0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))).*((X1 - x0).*(Y2 - y0) - (X2 - x0).*(Y1 - y0))) - y0.*(((Y2 - y0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (Y1 - y0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0))).*((X3 - x0).*(Y4 - y0) - (X4 - x0).*(Y3 - y0)) - ((Y4 - y0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0)) - (Y3 - y0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))).*((X1 - x0).*(Y2 - y0) - (X2 - x0).*(Y1 - y0))); ((X4 - x0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (X1 - x0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))).*((Y3 - y0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0)) - (Y2 - y0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0))) - ((X3 - x0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0)) - (X2 - x0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0))).*((Y4 - y0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (Y1 - y0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))) - x0.*(((X4 - x0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (X1 - x0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))).*((X2 - x0).*(Y3 - y0) - (X3 - x0).*(Y2 - y0)) - ((X3 - x0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0)) - (X2 - x0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0))).*((X1 - x0).*(Y4 - y0) - (X4 - x0).*(Y1 - y0))) - y0.*(((Y4 - y0).*(X1.*(X1 - x0) + Y1.*(Y1 - y0)) - (Y1 - y0).*(X4.*(X4 - x0) + Y4.*(Y4 - y0))).*((X2 - x0).*(Y3 - y0) - (X3 - x0).*(Y2 - y0)) - ((Y3 - y0).*(X2.*(X2 - x0) + Y2.*(Y2 - y0)) - (Y2 - y0).*(X3.*(X3 - x0) + Y3.*(Y3 - y0))).*((X1 - x0).*(Y4 - y0) - (X4 - x0).*(Y1 - y0)))]; end
options = optimoptions('fsolve','Display','off'); p0 = fsolve(@diagonal_conditions, [x(1), x(2)], options);
a = p0(1) - h.P(:, 1); b = p0(2) - h.P(:, 2); c = a.*h.P(:, 1) + b.*h.P(:, 2); ac = circshift(a, -1); bc = circshift(b, -1); cc = circshift(c, -1); z = a.*bc - ac.*b; xv = (bc.*c - b.*cc)./z; yv = (cc.*a - c.*ac)./z;
set(h.P0.mark,'xdata',p0(1),'ydata',p0(2),'Visible','on'); set(h.F1.line,'xdata',[xv; xv(1)],'ydata',[yv; yv(1)],'Visible','on'); set(h.F2.line,'xdata',[xv(1); xv(3)],'ydata',[yv(1); yv(3)],'Visible','on'); set(h.F3.line,'xdata',[xv(2); xv(4)],'ydata',[yv(2); yv(4)],'Visible','on'); end
function SetWindowSize() h = get(gcf,'userdata'); h.ws(get(gco,'value')) = str2num(get(gco,'string')); axis([h.ws(1)-h.ws(3)/2, h.ws(1)+h.ws(3)/2, h.ws(2)-h.ws(3)/2, h.ws(2)+h.ws(3)/2]) axis square Curves(h); set(gcf,'userdata',h) end
|