Форум программистов, компьютерный форум, киберфорум
Matlab
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/25: Рейтинг темы: голосов - 25, средняя оценка - 5.00
4820 / 2286 / 287
Регистрация: 01.03.2013
Сообщений: 5,970
Записей в блоге: 29
1

Построить четырехугольник по заданным точкам

23.07.2014, 01:58. Показов 4568. Ответов 34
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Есть задача: даны (четыре) точки пересечения со сторонами четырехугольника перпендикуляров, опущенных на стороны из точки пересечения его диагоналей. Построить четырехугольник.
Математика решения более-менее выяснена и реализована. Для каждой исходной конфигурации точек строятся 2 кривые, точки пересечения которых могут являться точкой пересечения диагоналей искомого четырехугольника, по которой (и исходным четырем точкам) он однозначно строится. Сделал из этого анимашку: исходные точки таскаются мышкой, при этом меняются кривые, пересечение которых дает решения. При щелчке мышкой далее, чем 5% от любой исходной точки, выполняется поиск решения в окрестности точки щелчка (лучше целенаправленно щелкать в точки пересечения кривых) и строится это решение. Сделано весьма коряво, это мой первый опыт создания GUI, буду признателен за любые дельные советы и замечания.
Matlab 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
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
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.07.2014, 01:58
Ответы с готовыми решениями:

Построить график кривой по заданным точкам
Здравствуйте!Подскажите пожалуйста как построить график кривой в MatLab имея только точки этой...

Как нарисовать на Canvas четырехугольник по заданным точкам?
если у мне имеется 4 точки как рисовать четирыехуголник

Как построить сплайн по заданным точкам
Всем добрый день. У меня возникла такая проблема. Имеется одномерный массив состоящий из чисел:...

Построить квадрат по двум заданным точкам
подскажите ,пожалуйста,как построить квадрат по двум заданым смежным вершынам? вот мои попытки ...

34
141 / 111 / 19
Регистрация: 14.04.2014
Сообщений: 224
Записей в блоге: 10
23.07.2014, 16:49 2
_Ivana, вообще говоря, мне все нравится. Вполне себе ниче так получилось
Один только вопрос: это нормально, что при некоторой конфигурации получается пересекающийся четырехугольник?
0
4820 / 2286 / 287
Регистрация: 01.03.2013
Сообщений: 5,970
Записей в блоге: 29
23.07.2014, 17:07  [ТС] 3
letete, пересекающийся четырехугольник это нормально, математическая формализация дает выполнение условий задачи, не накладывая дополнительных ограничений - можете подвинуть исходные точки, чтобы они задавали также пересекающийся четырехугольник - посмотрите на результат.

ЗЫ говорите, вам нравится, а если бы мне по основной работе пришлось встретиться с подобной корявостью (как в коде, так и в интерфейсе), я бы составил вполне определенное мнение о программисте и его квалификации
Сейчас продолжаю шлифовать код, обнаружил много забавного - оказывается в Матлабе в типах полей ввода нет числа, только строки - и в хелпе приведен корявый пример обработки этого имхо безобразия:
Matlab M
1
2
3
4
5
6
7
8
function edittext1_Callback(hObject, eventdata, handles)
user_entry = str2double(get(hObject,'string'));
if isnan(user_entry)
  errordlg('You must enter a numeric value','Bad Input','modal')
  uicontrol(hObject)
    return
end
% Proceed with callback...
Много и моих незнаний - как лучше вызывать коллбэк функцию - в кавычках или через @, при первом методе у меня не находит функции, при втором не знаю как передать параметры - использую параметры самого элемента управления (кнопки или поля). Короче - читаю хелп, смотрю демопримеры и шлифую дальше, если интересно - буду выкладывать код по мере дошлифовывания
0
141 / 111 / 19
Регистрация: 14.04.2014
Сообщений: 224
Записей в блоге: 10
23.07.2014, 18:14 4
_Ivana, от кавычек матлаб отходит, слава богу, - лучше использовать @. Это вполне себе обычные указатели на функции. Как передавать параметры - зависит от контекста. В строке, например,
Matlab M
1
uicontrol('style','edit', 'callback','GUI_test(-1)');
лучше всего это сделать вот так:
Matlab M
1
uicontrol('style','edit', 'callback',{@GUI_test, -1});
а вообще вот здесь написано про анонимные функции - полезная вещь. Хотя и не в случае с Callback'ами в GUI.
Что касается в целом о мысли что все хорошо - то да, по сравнению с тем, что здесь иногда почитываешь, дак да - программа просто идеальна)) На самом же деле программу с GUI лучше всего писать примерно так (я, конечно, не претендую на истину в последней инстанции, но как мне кажется, вложенные функции упрощают код). С точки зрения рекурсивного вызова (а именно так у Вас в программе все работает) - это конечно не очень хорошо, хотя и, должен признать, весьма элегантно))

Добавлено через 13 минут
и еще. по поводу
Цитата Сообщение от _Ivana Посмотреть сообщение
имхо безобразия
... проблема в том, что матлаб объективно не очень ориентирован на пользовательские интерфейсы - ну не его это специализация, прямо скажем; из-за этого (по-видимому) и возникают некоторые трудности и "безобразия". Например, я очень долго боролся с полосой прокрутки, которая по умолчанию ВСЕГДА висит в листбоксах, проверка вводимых значений для едитбоксов и много чего другого... Для edit'а действительно нет нормального обработчика: Callback - это все таки реакция на событие LOSTFOCUS, а хотелось бы сильно чтобы было ONCHANGE...
я как будет время запишу по этому поводу в блоге что-нить, ну а сейчас прямо могу дать несколько ссылок: listbox_scroll_bar, edit_change, и вообще!
1
4820 / 2286 / 287
Регистрация: 01.03.2013
Сообщений: 5,970
Записей в блоге: 29
23.07.2014, 18:22  [ТС] 5
letete, спасибо Вам большое за ссылки и участие в теме. Я их почитаю, сделаю по возможности с учетом их рекомендаций и выложу код. И если Вам опять же будет не трудно, мне очень интересно будет почитать его критику )
0
141 / 111 / 19
Регистрация: 14.04.2014
Сообщений: 224
Записей в блоге: 10
23.07.2014, 18:41 6
чёта я призадумался... мне почему-то кажется, что
Цитата Сообщение от letete Посмотреть сообщение
лучше всего это сделать вот так:
Matlab M
1
uicontrol('style','edit', 'callback',{@GUI_test, -1});
работать не будет... То есть работать будет, но не так, как хотелось бы...
Дело в том, что Callback - это специальная функция, у которой УЖЕ ЕСТЬ параметры. А именно: (handle, event). Т.е. автоматически в функцию (по идее) должен передаваться дескриптор объекта, вызывающего Callback и объект события. В большинстве случаев event не используется (в реализации функции можно заменить ~). Конструкция {@GUI_test, -1} позволяет добавлять дополнительные аргументы, поэтому -1 в данном случае будет третьим параметром. Наверно. Кажется. Наверняка не уверен - надо проверять.

Проверять мне, понятное дело, не хочется - проще переписать функцию с вложенными функциями - тогда все станет на свои места само, не нужно будет изобретать велосипедов.
0
4820 / 2286 / 287
Регистрация: 01.03.2013
Сообщений: 5,970
Записей в блоге: 29
23.07.2014, 18:53  [ТС] 7
Работает, передает третьим параметром:
Matlab M
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    uicontrol('style','pushbutton', 'units','normalized', 'position',[.86 .30 .12 .05], ...
       'string','+', 'value', 1, 'callback', {@ZoomAxis, 1});
    uicontrol('style','pushbutton', 'units','normalized', 'position',[.86 .20 .12 .05], ...
       'string','-', 'value', 2, 'callback', {@ZoomAxis, -1});
 
function ZoomAxis(src,evnt,par)
    XLim = get(gca,'XLim');
    YLim = get(gca,'YLim');
    deltaX = XLim(2)-XLim(1);
    deltaY = YLim(2)-YLim(1);
%     if strcmp(get(src,'string'),'+')
    if par == 1
        deltaX = deltaX/4;
        deltaY = deltaY/4;
    end
    axis([mean(XLim)-deltaX, mean(XLim)+deltaX, mean(YLim)-deltaY, mean(YLim)+deltaY])
    Curves(get(gcf,'userdata'));
end
- раньше использовал в условии значение поля string кнопки - голь на выдумки.... ))

ЗЫ сейчас бьюсь над сверхзадачей - сделать какое-то поле (эдит, скорее всего), где будут визуализироваться координаты 4 точек (сделано), рефрешиться при таскании (сделано), и там же будет можно их задавать - не сделано, не побеждается преобразование из многострочной строки в матрицу даблов 4х2...
0
141 / 111 / 19
Регистрация: 14.04.2014
Сообщений: 224
Записей в блоге: 10
23.07.2014, 19:02 8
_Ivana, хорошо. Тогда пойдем дальше)) А зачем вообще третий параметр?
Matlab M
1
2
3
4
5
6
7
8
9
10
11
  uicontrol('style','pushbutton', 'units','normalized', 'position',[.86 .30 .12 .05], ...
       'string','+', 'value', 1, 'callback', @ZoomPlus);
  uicontrol('style','pushbutton', 'units','normalized', 'position',[.86 .20 .12 .05], ...
       'string','-', 'value', 2, 'callback', @ZoomMinus);
 
function ZoomPlus(src, ~)
...
end
function ZoomMinus(src, ~)
...
end
Во всяком случае, с точки зрения чтения кода - понятнее
0
4820 / 2286 / 287
Регистрация: 01.03.2013
Сообщений: 5,970
Записей в блоге: 29
23.07.2014, 19:11  [ТС] 9
) идея понятна, и если на разных кнопках совсем разные функции - то вполне красиво. Но если функция по сути одна и та же, при разбитии на 2 будет дублирование 95% кода - что некрасиво. Хотя его можно вынести в третью функцию - но это имхо также некрасиво. В общем, дело вкуса, но в данном случае имхо лучше одна функция с параметром.

ЗЫ но по сравнению с этим вопросом у меня несколько других более насущных проблем стоит, хотя бы изложенная в предыдущем посте
0
141 / 111 / 19
Регистрация: 14.04.2014
Сообщений: 224
Записей в блоге: 10
23.07.2014, 19:15 10
про это?
Цитата Сообщение от _Ivana Посмотреть сообщение
не побеждается преобразование из многострочной строки в матрицу даблов 4х2...
я не очень понял что именно имеется ввиду. увидеть было бы понятнее. может, посмотреть функции
str2double,
str2num?
Они, кстати, разные...
0
4820 / 2286 / 287
Регистрация: 01.03.2013
Сообщений: 5,970
Записей в блоге: 29
23.07.2014, 19:21  [ТС] 11
Сейчас мой код выглядит так:
Matlab 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
function GUI_test()
    h.P = [1,1; 1,-1; -1,-1; -1,0];
    axis([-2, 2, -2, 2])
    axis square
    
    uicontrol('Tag','InitPoints', 'style','edit', 'units','normalized', 'position',[.00 0.80 .20 .15], ...
       'string',num2str(h.P), 'value',3, 'max',3, 'callback', @SetInitialPoints);
    uicontrol('Tag','FigurePoints', 'style','edit', 'units','normalized', 'position',[.00 0.50 .20 .15], ...
       'string','', 'max',3);
   
    uicontrol('style','pushbutton', 'units','normalized', 'position',[.86 .30 .12 .05], ...
       'string','+', 'callback', {@ZoomAxis, 1});
    uicontrol('style','pushbutton', 'units','normalized', 'position',[.86 .20 .12 .05], ...
       'string','-', 'callback', {@ZoomAxis, -1});
    uicontrol('style','pushbutton', 'units','normalized', 'position',[.86 .10 .12 .05], ...
       'string','><', 'callback', @Center_Figure);
    
    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', @wdButtonDownFcn, ...
        'windowbuttonupfcn', 'set(gcf,''windowbuttonmotionfcn'','''')')
 
    function wdButtonDownFcn(gcf,evnt)
        h = get(gcf,'userdata');
        pt = get(gca,'currentpoint');
        x = pt(1,1:2);
        XLim = get(gca,'XLim');
        YLim = get(gca,'YLim');
        wide = max([XLim(2)-XLim(1), YLim(2)-YLim(1)]);
 
        if strcmp(get(gcf,'SelectionType'),'normal')
            set(gcf,'windowbuttonmotionfcn', @wdButtonDownFcn)
 
            set(h.P0.mark,'Visible','off');
            set(h.F1.line,'Visible','off');
            set(h.F2.line,'Visible','off');
            set(h.F3.line,'Visible','off');
 
            d = (x(1)-h.P(:,1)).^2 + (x(2)-h.P(:,2)).^2;
            if min(d) > wide/20
                return
            end
            ind = find(d == min(d));
            ind = ind(1);
            h.P(ind, :) = x;
 
            if ind == 1
                h_P = h.P1;
            elseif ind == 2
                h_P = h.P2;
            elseif ind == 3
                h_P = h.P3;
            elseif ind == 4
                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);
            set(findobj(gcf, 'Tag', 'InitPoints'), 'string', num2str(h.P));%, '%0.3g'));
        else
            Figures(h, x);
        end
    end
 
    function SetInitialPoints(src,evnt)
 
    %     s = '2.2632     0.57895....
    %      1          -1
    %     -1          -1
    %     -1           0
 
        s = get(src,'string')
    %     numel(s)
        numel(s)
 
        s(1)
        s(2)
 
        P = str2double(get(src,'string'))
    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);
 
        XLim = get(gca,'XLim');
        YLim = get(gca,'YLim');
        xx = XLim(1):(XLim(2)-XLim(1))/50:XLim(2);
        yy = YLim(1):(YLim(2)-YLim(1))/50:YLim(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]);
        if numel(C) > 2
            C(:,1) = [];
            set(h.C1.line,'xdata',C(1,:),'ydata',C(2,:),'Visible','on');
        else
            set(h.C1.line,'Visible','off');
        end
 
        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]);
        if numel(C) > 2
            C(:,1) = [];
            set(h.C2.line,'xdata',C(1,:),'ydata',C(2,:),'Visible','on');
        else
            set(h.C2.line,'Visible','off');
        end
    end
 
    function Figures(h, x)
        function r = diagonal_conditions(p0)
            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;
            r = [p0(2)*(xv(3) - xv(1)) - p0(1)*(yv(3) - yv(1)) - yv(1)*xv(3) + xv(1)*yv(3);
                p0(2)*(xv(4) - xv(2)) - p0(1)*(yv(4) - yv(2)) - yv(2)*xv(4) + xv(2)*yv(4)];
        end
        xv = zeros(4, 1); yv = zeros(4, 1);
        options = optimoptions('fsolve','Display','off');
        p0 = fsolve(@diagonal_conditions, [x(1), x(2)], options);
        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');
 
        set(findobj(gcf, 'Tag', 'FigurePoints'), 'string', num2str([xv, yv]));%, '%0.3g'));
    end
 
    function ZoomAxis(src,evnt,par)
        XLim = get(gca,'XLim');
        YLim = get(gca,'YLim');
        deltaX = XLim(2)-XLim(1);
        deltaY = YLim(2)-YLim(1);
    %     if strcmp(get(src,'string'),'+')
        if par == 1
            deltaX = deltaX/4;
            deltaY = deltaY/4;
        end
        axis([mean(XLim)-deltaX, mean(XLim)+deltaX, mean(YLim)-deltaY, mean(YLim)+deltaY])
        Curves(get(gcf,'userdata'));
    end
 
    function Center_Figure(src,evnt)
        h = get(gcf,'userdata');
        x = get(h.F0.line,'xdata');
        if iscolumn(x) x = x'; end
        y = get(h.F0.line,'ydata');
        if iscolumn(y) y = y'; end
        if strcmp(get(h.P0.mark,'Visible'),'on')
            x = [x, get(h.P0.mark,'xdata')];
            y = [y, get(h.P0.mark,'ydata')];
        end
        if strcmp(get(h.F1.line,'Visible'),'on')
            x = [x, get(h.F1.line,'xdata')];
            y = [y, get(h.F1.line,'ydata')];
        end
        xc = (max(x)+min(x))/2;
        yc = (max(y)+min(y))/2;
        delta = 1.1*(max([max(x)-min(x), max(y)-min(y)])/2);
        axis([xc-delta, xc+delta, yc-delta, yc+delta])
        Curves(h);
    end
 
end
Смущает много моментов, но о котором говорю - чтобы в левом верхнем эдите можно было задавать вручную координаты точек - и график брал бы их. Все понятно, кроме того, как их разупаковать из строки с переводами строк...

Да, теперь для построения решения надо правой кнопкой мыши жать
1
141 / 111 / 19
Регистрация: 14.04.2014
Сообщений: 224
Записей в блоге: 10
23.07.2014, 19:29 12
так это и есть str2num.
Matlab M
1
2
3
4
    function SetInitialPoints(src,evnt)
        s = get(src,'string')
        str2num(s)
    end
прекрасно отработает: на выходе даст 4х2 double
Название: Снимок.PNG
Просмотров: 87

Размер: 7.6 Кб
Но естественно, что надо будет сначала потерять фокус (чтобы Callback сработал)
1
4820 / 2286 / 287
Регистрация: 01.03.2013
Сообщений: 5,970
Записей в блоге: 29
23.07.2014, 19:49  [ТС] 13
Сейчас попробую. Возможно, меня смутило то, что есть уже str2double...
А по остальному что скажете, если без поблажек?

Добавлено через 14 минут
Отработало. Стыдно, что сам не попробовал так просто и напрямую, думал только целые значения возвратит... Хотя еще надо защиту от некорректных введенных данных туда лепить.

ЗЫ теперь хочется избавиться от хранения отдельно координат исходных точек, а брать их из xdata ydata точек вывода (это просто), и как-то может покрасивее определять какую точку мы двигаем мышью, да и вообще задавать каждую точку не отдельно, а все одним массивом...
0
141 / 111 / 19
Регистрация: 14.04.2014
Сообщений: 224
Записей в блоге: 10
23.07.2014, 20:03 14
а что сказать в остальном? красиво, богато... структуру (h.*) достаточно сложную Вы используете (это не критика - это намек, что рядышком весьма так недурственно было бы комментарий написать как именно ею пользоваться и из чего она состоит - иначе не то что посторонний, сами же через недельку без поллитра не разберетесь как она сформирована).
второе - употребляете gcf. это, конечно, хорошо, но это GetCurrentFigure. т.е. было бы лучше сделать первой строчкой
Matlab M
1
hWnd = figure(...);
, ибо мало ли как там звезды распорядятся и планеты выстроятся так, что в момент выполнения gcf активным (совершенно случайно!) станет другое окно. Окно - это же главный инструмент Ваш, не лишним, мне кажется, было бы его хэндл хранить. Тэг в матлаб - это что-то типа имени, не хорошо делать его русскоязычным
Matlab M
1
 set(gcf,'tag','Задача о четырёхугольнике', ...)
третье, на случай
Matlab M
1
2
3
4
5
6
7
8
9
10
11
            if ind == 1
                h_P = h.P1;
            elseif ind == 2
                h_P = h.P2;
            elseif ind == 3
                h_P = h.P3;
            elseif ind == 4
                h_P = h.P4;
            else
                return
            end
существует switch...

Вообще говоря, на вкус и цвет, как говорится, все люди разные! ))

Добавлено через 10 минут
Цитата Сообщение от _Ivana Посмотреть сообщение
думал только целые значения возвратит...
с целыми значениями в матлаб очень туго. их почти нет. все значения по умолчанию - double. чтобы использовать чисто целые значения надо сильно постараться. целочисленные типы:
int8, int16, int32, int64,
uint8, uint16, uint32, uint64

но их использование крайне не желательно. дело в том, что не все функции умеют с ними работать (конечно, список этих функций расширяется с каждой версией, но все же...)
есть еще тип single (аналог - float, 4Б, одинарная точность), так вот даже он не всегда адекватен

по поводу проверки. str2num вернет массив чисел, и только лишь в тех местах, где не получилось конвертировать, там будут NaN (NotANumber). так что не так уж и сложна будет проверка. функция isnan() скажет, если что-то не так.
1
4820 / 2286 / 287
Регистрация: 01.03.2013
Сообщений: 5,970
Записей в блоге: 29
23.07.2014, 20:12  [ТС] 15
letete, очередное спасибо Вам за дельные советы и рекомендации. Я понимаю, что совершенствовать код и интерфейс можно бесконечно, и надо остановиться на каком-то компромиссе, но сейчас я не чувствую что достиг его Ну, например, пока еще имхо рано этот код давать как демо пример графического GUI. Буду пытаться шлифовать дальше. Многие моменты мне еще не нравятся, часть я озвучил выше. Если у вас появятся какие-либо мысли или идеи - буду рад почитать.

ЗЫ isnan() это хорошо, это и в хелпе так проверяется. Только еще размерность надо проверить, а то все будет хорошо с числами, но юзер или удалит часть или лишних влепит
0
141 / 111 / 19
Регистрация: 14.04.2014
Сообщений: 224
Записей в блоге: 10
23.07.2014, 23:10 16
Цитата Сообщение от _Ivana Посмотреть сообщение
Только еще размерность надо проверить, а то все будет хорошо с числами, но юзер или удалит часть или лишних влепит
согласен. это фол. а для такого случая (чтобы с размерностями все было чикипуки) можно использовать uitable... ))))
0
4820 / 2286 / 287
Регистрация: 01.03.2013
Сообщений: 5,970
Записей в блоге: 29
25.07.2014, 00:56  [ТС] 17
Финальный вариант на сегодня: удалены лишние поля структуры, немного пошлифован интерфейс... Uitable попробовал, до конца не довел, оставил текстовое поле, но коллбэк по кнопке. Не знаю что еще придумать.
Matlab 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
function GUI_test()
    fh = figure('name','Задача о четырёхугольнике','tag','FourEdgesTask');
%     set(fh,'numbertitle','off','menubar','none')
    ah = axes('DrawMode','fast','units','normalized', 'position',[.00 .00 .73 1.00]);
 
    initP = [1,1; 1,-1; -1,-1; -1,0];
    axis([-2, 2, -2, 2])
    axis square
   
        % четырехугольник из 4 исходных точек:
    h.F0.line = line([initP(:, 1); initP(1, 1)], [initP(:, 2); initP(1, 2)], 'marker','*','erase','xor','color','k');
        % кривые ГМТ условий:
    h.C1.line = line(0, 0, 'erase','xor','color','c','LineStyle',':');
    h.C2.line = line(0, 0, 'erase','xor','color','m','LineStyle',':');
        % точка пересечения диагоналей решения:
    h.P0.mark = line(0, 0, 'marker','o','erase','xor','color','r','LineWidth',2,'Visible','off');
        % четырехугольник решения:
    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');
    
    uicontrol('style','pushbutton', 'units','normalized', 'position',[.74 0.95 .25 .05], ...
       'string','Задать исходные точки', 'callback', @SetInitialPoints);
    uicontrol('Tag','InitPoints', 'style','edit', 'units','normalized', 'position',[.74 0.80 .25 .15], ...
       'string',num2str(initP), 'max',3);
    uicontrol('style','edit', 'units','normalized', 'position',[.74 0.75 .25 .05], ...
       'string','Вершины четырехугольника');
    uicontrol('Tag','FigurePoints', 'style','edit', 'units','normalized', 'position',[.74 0.60 .25 .15], ...
       'string','', 'max',3);
    uicontrol('style','edit', 'units','normalized', 'position',[.74 0.55 .25 .05], ...
       'string','Пересечение диагоналей');
    uicontrol('Tag','DiagCross', 'style','edit', 'units','normalized', 'position',[.74 0.50 .25 .05], ...
       'string','');
    uicontrol('style','pushbutton', 'units','normalized', 'position',[.74 .36 .25 .05], ...
       'string','><', 'callback', @Center_Figure);
    uicontrol('style','pushbutton', 'units','normalized', 'position',[.74 .30 .12 .05], ...
       'string','+', 'callback', {@ZoomAxis, 1});
    uicontrol('style','pushbutton', 'units','normalized', 'position',[.87 .30 .12 .05], ...
       'string','-', 'callback', {@ZoomAxis, -1});
   
    Curves(h);
    set(fh,'userdata',h, 'windowbuttondownfcn', @wdButtonDownFcn, 'windowbuttonupfcn', @wdButtonUpFcn)
 
    function wdButtonDownFcn(src,evnt)
        h = get(fh,'userdata');
        pt = get(ah,'currentpoint');
        x = pt(1,1:2)';
        xlim = get(ah,'xlim');
        ylim = get(ah,'ylim');
        point_array_size = max([xlim(2)-xlim(1), ylim(2)-ylim(1)])/5;
 
        if strcmp(get(fh,'SelectionType'),'normal')
            set(fh,'windowbuttonmotionfcn', @wdButtonDownFcn)
 
            setFigureVisibleOff(h);
            P = [get(h.F0.line,'xdata'); get(h.F0.line,'ydata')];
            P = P(:, 1:4);
            d = ((x(1)-P(1,:)).^2 + (x(2)-P(2,:)).^2).^0.5;
            if min(d) > point_array_size
                return
            end
            ind = find(d == min(d));
            ind = ind(1);
            P(:, ind) = x;
            set(h.F0.line,'xdata',[P(1, :), P(1, 1)],'ydata',[P(2, :), P(2, 1)]);
            Curves(h);
            set(findobj(fh, 'Tag', 'InitPoints'), 'string', num2str(P'));
        else
            Figures(h, x);
        end
    end
 
    function wdButtonUpFcn(src,evnt)
        set(fh,'windowbuttonmotionfcn','')
    end
 
    function SetInitialPoints(src,evnt)
        P = str2num(get(findobj(fh, 'Tag', 'InitPoints'),'string'));
        if size(P) ~= [4, 2]
            errordlg('Данные должны содержать 4 строки по 2 числовых значения','Bad Input','modal')
            return
        end
%         if any(isnan(P))
%             errordlg('Данные должны быть числовыми','Bad Input','modal')
%             return
%         end
        P = [P; P(1,:)];
        h = get(fh,'userdata');
        set(h.F0.line,'xdata',P(:, 1),'ydata',P(:, 2));
        setFigureVisibleOff(h);
        Center_Figure();
    end
 
    function Curves(h)
        x = get(h.F0.line,'xdata');
        y = get(h.F0.line,'ydata');
        X1 = x(1); Y1 = y(1);
        X2 = x(2); Y2 = y(2);
        X3 = x(3); Y3 = y(3);
        X4 = x(4); Y4 = y(4);
 
        xlim = get(ah,'xlim');
        ylim = get(ah,'ylim');
        x = xlim(1):(xlim(2)-xlim(1))/50:xlim(2);
        y = ylim(1):(ylim(2)-ylim(1))/50:ylim(2);
        [x0,y0] = meshgrid(x, y);
 
        z = ((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(x, y, z, [0, 0]);
        n_p = numel(C(1,:));
        if n_p > 1
            set(h.C1.line,'xdata',C(1,2:n_p),'ydata',C(2,2:n_p),'Visible','on');
        else
            set(h.C1.line,'Visible','off');
        end
 
        z = ((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(x, y, z, [0, 0]);
        n_p = numel(C(1,:));
        if n_p > 1
            set(h.C2.line,'xdata',C(1,2:n_p),'ydata',C(2,2:n_p),'Visible','on');
        else
            set(h.C2.line,'Visible','off');
        end
    end
 
    function setFigureVisibleOff(h)
        set(h.P0.mark,'Visible','off');
        set(h.F1.line,'Visible','off');
        set(h.F2.line,'Visible','off');
        set(h.F3.line,'Visible','off');
        set(findobj(fh, 'Tag', 'FigurePoints'), 'string', '');
        set(findobj(fh, 'Tag', 'DiagCross'), 'string', '');
    end
 
    function Figures(h, x)
        P = [get(h.F0.line,'xdata'); get(h.F0.line,'ydata')];
        P = P(:, 1:4)';
        
        function r = diagonal_conditions(p0)
            a = p0(1) - P(:, 1);
            b = p0(2) - P(:, 2);
            c = a.*P(:, 1) + b.*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;
            r = [p0(2)*(xv(3) - xv(1)) - p0(1)*(yv(3) - yv(1)) - yv(1)*xv(3) + xv(1)*yv(3);
                p0(2)*(xv(4) - xv(2)) - p0(1)*(yv(4) - yv(2)) - yv(2)*xv(4) + xv(2)*yv(4)];
        end
        
        xv = zeros(4, 1); yv = zeros(4, 1);
        options = optimoptions('fsolve','Display','off');
        p0 = fsolve(@diagonal_conditions, [x(1), x(2)], options);
        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');
        set(findobj(fh, 'Tag', 'FigurePoints'), 'string', num2str([xv, yv]));
        set(findobj(fh, 'Tag', 'DiagCross'), 'string', num2str(p0));
    end
 
    function ZoomAxis(src,evnt,par)
        xlim = get(ah,'xlim');
        ylim = get(ah,'ylim');
        deltaX = xlim(2)-xlim(1);
        deltaY = ylim(2)-ylim(1);
        if par == 1
            deltaX = deltaX/4;
            deltaY = deltaY/4;
        end
        axis([mean(xlim)-deltaX, mean(xlim)+deltaX, mean(ylim)-deltaY, mean(ylim)+deltaY])
        Curves(get(fh,'userdata'));
    end
 
    function Center_Figure(src,evnt)
        h = get(fh,'userdata');
        x = get(h.F0.line,'xdata');
        y = get(h.F0.line,'ydata');
        if strcmp(get(h.P0.mark,'Visible'),'on')
            x = [x, get(h.P0.mark,'xdata')];
            y = [y, get(h.P0.mark,'ydata')];
        end
        if strcmp(get(h.F1.line,'Visible'),'on')
            x = [x, get(h.F1.line,'xdata')];
            y = [y, get(h.F1.line,'ydata')];
        end
        xc = (max(x)+min(x))/2;
        yc = (max(y)+min(y))/2;
        delta = 1.1*(max([max(x)-min(x), max(y)-min(y)])/2);
        axis([xc-delta, xc+delta, yc-delta, yc+delta])
        Curves(h);
    end
 
end
ЗЫ жаль, что contourc иногда дает лишние ошибочные выбросы, портящие картинку кривых. Причем, это было у меня не только с такой громоздкой функцией, но и с банальной описанной около треугольника окружностью, когда я ее кривую считал через contourc.

Добавлено через 23 часа 23 минуты
Вести с полей - доработал вариант с uitable: отличная вещь! Столько свойств и полей, коллбэк по выбору и редактированию каждой ячейки с возможностью взять предыдущее и новое значения, задания типов ячеек с автоматическим контролем при вводе, жесткое но динамически изменяемое ограничение количества строк/столбцов и еще море всего вкусного
Жаль только, что не удаляются заголовки строк/столбцов (или не нашел как) и в тексте было одно преимущество - было возможно копировать содержимое из поля и вставлять в поле штатными средствами Windows. Это важный момент, облегчает таскание координат точек из кода в поле и обратно. Но у таблицы есть возможность запрограммировать UIContextMenu и там задать команды копирования/вставки через текст, если получится.
1
141 / 111 / 19
Регистрация: 14.04.2014
Сообщений: 224
Записей в блоге: 10
25.07.2014, 13:54 18
_Ivana, насколько я помню колбэки у таблиц позволяют анализировать содержимое при потере фокуса от ячейки - это значит можно сразу же обрабатывать содержимое ячеек, а еще каждая ячейка допускает HTML-форматирование... вобщем на коленках примерчик собрал:
Matlab 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
function exmpl
tbl = uitable(gcf, 'RowName', '', ...  % чтобы не было имен строк
            'ColumnName', '', ...      % чтобы не было имен столбцов
            'ColumnEditable', true, 'RowStriping', 'on', ...
            'Units', 'Normalized', 'Position', [0.01 0.1 0.68 0.9], ...
            'Data', num2cell(eye(5, 5)), ...
            'CellSelectionCallback', @tblSelect, ...
            'CellEditCallback', @tblEdit);
    
    % реакция на выделение (мультистрочное через shift/ctrl в том числе)
    function tblSelect(~, evnt)
        selected = unique(evnt.Indices(:,1));
        disp(['Выделены строки: ' num2str(selected')])
    end 
    % реакция на изменения
    function tblEdit(~, evnt)
        dat = get(tbl, 'Data');
        disp(evnt)
        if isnan(evnt.NewData)
            highlighted = ['<HTML><font color="red"><b>' evnt.EditData '</b></font></HTML>'];
            dat{evnt.Indices(1), evnt.Indices(2)} = highlighted;
            set(tbl, 'Data', dat)
        end
    end 
 
end
Добавлено через 5 минут
Важное замечание: лучше, чтобы содержимым таблицы были ячейки. Иначе не получится совместить текст и числа
1
4820 / 2286 / 287
Регистрация: 01.03.2013
Сообщений: 5,970
Записей в блоге: 29
25.07.2014, 13:56  [ТС] 19
Спасибо, я все более проникаюсь впечатлением от возможностей таблиц по сравнению с более простыми элементами.

ЗЫ если уж на то пошло, то вместо всех этих эдитов и слайдеров можно нарисовать еще одно управляющую графическую область, задать для нее коллбэки нажатия кнопок мыши и таскания, нарисовать ВСЕ ЧТО УГОДНО и по текущим координатам делать изменения нужных параметров
0
141 / 111 / 19
Регистрация: 14.04.2014
Сообщений: 224
Записей в блоге: 10
25.07.2014, 14:06 20
_Ivana, пожалуйста!

Всегда приятно помогать адекватным людям, а не ковыряться в элементарных ошибках студентов, которым надо сдать "срочна! вчира! памагите..."

Матлаб достаточно богат и развит, но не все его возможности лежат на поверхности. Я им занимаюсь всего полгода и, откровенно говоря, не знаю о нем вообще ничего. Для Вас, возможно, будет полезна (кроме прочих) еще вот эта книга - ее достаточно трудно найти и она, к сожалению, немножко англоязычна.
2
25.07.2014, 14:06
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.07.2014, 14:06
Помогаю со студенческими работами здесь

Построить прямоугольник по двум заданным точкам
Построить прямоугольник по двум заданным точкам: левому верхнему и правому нижнему углам. Обе точки...

Построить прямоугольник по двум заданным точкам
Помогите сделать до конца задачу на СИ.! 1)Построить прямоугольник по двум заданным точкам:...

Определить, можно ли по заданным точкам построить прямоугольник
Похожая тема была, но там ничего не ответили. Проблема еще в том, что если глупый пользователь...

Построить кривую параболического типа по 4 точкам, заданным с помощью локатора
Построить график кривой параболического типа по 4 точкам, заданным с помощью локатора. Я написал...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru