Построение графика - разные стили линий для разных ребер - PullRequest
0 голосов
/ 20 мая 2019

У меня есть график узлов и ребер, которые я строю против (x, y, z) координат для каждого узла.

Я хотел бы использовать пунктирную линию для «внутренних» краев и прямую линию для «внешних» краев.

LineStyle может помочь мне, но я думаю, что все мои края будут пунктирными. Я хотел бы указать, какие края пунктирные.

Вот код, который я использую для построения графика: (G - это график)

plot(G, 'XData', A(1,:), 'YData', A(2,:), 'ZData', A(3,:))

Любая помощь очень ценится!

У меня есть функция для создания графика, она выдает следующее:

G =
graph with properties:
    Edges: [11×1 table]
    Nodes: [6×0 table] 

И система координат, подобная этой:

A =
     0     1     0    -1     0     0
     0     1     3     2     1     2
     1     1     1     1     1     1

Используя вышеприведенную функцию сюжета, вы получите следующий вывод:

Output

1 Ответ

1 голос
/ 21 мая 2019

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

Классический приемдля этих случаев, когда подгруппа точек / линий должна быть построена иначе, чем целая группа:

  1. Построить всю группу
  2. Построить подгруппу сверхус различными свойствами линии

В вашем случае это означает, что вы должны найти точки и ребра, которые являются частью границы.Я объясню один метод ниже.Имейте в виду, что этот метод будет работать только для выпуклых границ (см. Разницу с вогнутым набором, где метод не будет работать: вогнутый или выпуклый корпус ).

Сначала мне нужно добраться до состояния вашего вопроса, поэтому давайте рассмотрим:

%% Initial data
A =[ 0  1  0 -1  0  0
     0  1  3  2  1  2
     1  1  1  1  1  1 ];
G = graph ;
G = addedge(G,[1 1 1 1 1 2 2 2 3 4 4],[2 3 4 5 6 3 5 6 4 5 6]) ;
plot(G, 'XData', A(1,:), 'YData', A(2,:) , 'LineStyle','--')
grid on ; hold on
np = size(A,2) ;            % Number of points/nodes

Это позволит получить фигуру, точно такую ​​же, как ваша, только с одним linestyle, чтобыло установлено пунктирными линиями для полного графика.Теперь упражнение заключается в построении контура сплошной линией.

Чтобы найти контур (по крайней мере, в 2D-случаях, подобных вашему), используется следующий метод:

  1. найти одну точкуконтура (начальная точка), наименьший возможный x.
  2. вычисляет угол между единичным вектором ux=[1,0,0] и всеми другими векторами (образованными начальной точкой и всеми другими точками матрицы).
  3. Назначьте следующую точку контура (это та, вектор которой имеет минимальный угол).Теперь у вас есть текущий вектор vec (между точками 1 и 2) и текущая точка pt2.
  4. . Рассчитайте угол между vec и всеми другими векторами (образованными текущей точкой *).1039 * и все остальные точки матрицы) следующая точка контура - это точка, вектор которой имеет минимальный угол.
  5. Повторяйте (3) и (4), пока следующая точка контура не станетначальная точка.

Переведено в код:

%% find a point on the edge
% (I chose to start with the lowest point on Y axis)
[~,idxNext] = min(A(2,:)) ;

%% initialise counters
isOnEdge = false(np,1) ;    % this will hold a logical register of contour points
idxEdge = idxNext ;         % this will hold the points of the contour, in order

%% setup start conditions
isOnEdge(idxNext) = true ;  % initial point
p = A(:,idxNext) ;          % initial point
v = [1;0;0] ;               % initial vector (start with unit vector oriented Ox)

%% search for contour
isRunning = true ;
iter = 0 ;
while isRunning
    iter = iter + 1 ;               % make sure we're not stuck in infinite loop
    angs = find_angles(v,p,A) ;     % find angles between initial vector and all other points
    angs(idxNext) = Inf ;           % Exclude current point
    if numel(idxEdge) > 1           % Exclude last point (if not at first iteration)
        angs(idxEdge(end-1)) = Inf ;      
    end
    [~,idxNext] = min(angs) ;       % find the index of the minimum angle 

    if isOnEdge(idxNext)
        % we've completed the close profile, bail out
        isRunning = false ;
    else
        % move on to next point/vector
        idxEdge = [idxEdge idxNext] ; %#ok<AGROW>
        isOnEdge(idxNext) = true ;
        p = A(:,idxNext) ;
        v = A(:,idxNext) - A(:,idxEdge(end-1)) ;
    end

    if iter > np
        break                       % make sure we're not stuck in infinite loop
    end
end

%% present results
if isRunning
    fprintf('Could''t find a closed profile\n')
else
    fprintf('Found points defining a closed profile:\n')
    disp(idxEdge)
end

%% Plot on top of graph
% create a matrix conataining only the contour points, close the contour by
% replicating the first point in last position
C = [A(:,idxEdge) , A(:,idxEdge(1))] ;
% plot
plot3( C(1,:) , C(2,:) , C(3,:) ,'b', 'LineWidth',2)
view(2)

Что даст:

enter image description here


В приведенном выше сценарии я использую функцию find_angles.m.Код для него:

function angs = find_angles(Uin,p,M)
% find angle between Uin vector and the vectors formed between p and 
% all the points in M
np = size(M,2) ;
angs = zeros(np,1) ;
for iv=1:np
    vec = M(:,iv) - p ;
    c = cross(Uin,vec) ;
    d = dot(Uin,vec) ;
    angs(iv) = rad2deg( atan2( norm(c) , d ) ) * sign( c(3) ) ;

    % take care of an edge case
    if c(3)==0 && d==-1 ; angs(iv) = 180 ; end

    % give [0 360] degree results
    if angs(iv) < 0 ; angs(iv) = 180 + (180+angs(iv) ) ; end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...