Как создать гипертекстовые стрелки в gnuplot?

Как создать гипертекстовые векторы или стрелки, которые появляются только тогда, когда пользователь наводит указатель мыши на начальную/конечную точки или рядом с ними? Для очков это выглядит так:

indices = "first second"

plot for [id in indices] "a_test.dat" index id u 1:2

replot for [i=1:words(indices)] "a_test.dat" index word( indices, i ) u 1:2:(sprintf("point = (%d, %d)", column(1), column(2))) w labels hypertext point pt 7 ps 2 lc rgb '#ff000000' notitle

Файл "a_test.dat":

# first
x1  y1
5   1
6   2
9   8

# second
x2  y2
4   5
8   2
2   7

Я не думаю, что gnuplot может это сделать. Какой тип терминала вы используете? Вы можете сделать так, чтобы опция hypertext отображала изображение из файла, что может предоставить отдельно сгенерированный график с нужной стрелкой.

meuh 20.02.2023 15:46

Я использую gnuplot-qt 5.4. Как отобразить изображение с «гипертекстом»? Означает ли это создание нового графика всего с одной стрелкой? Если это сработает, будет здорово.

magfan 20.02.2023 16:00
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
76
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

Это снимок экрана файла svg с (желтым) курсором, находящимся над точкой (4,5). Программа просмотра svg (в данном случае мой браузер) вывела маленькое изображение с фиолетовой стрелкой из файла /tmp/fig1.png в моей системе. Возможно, это не совсем то, что вам нужно, но это лучшее, что я могу сделать с помощью gnuplot. Вот код:

set term png size 400, 400   linewidth 3
unset key
stats "a_test.dat" nooutput
array xx[STATS_records]
array yy[STATS_records]
set xrange [STATS_min_x:STATS_max_x]
set yrange [STATS_min_y:STATS_max_y]
set offsets graph 0.05, graph 0.05, graph 0.05, graph 0.05
# save all data into two arrays
i = 1
fnset(x,y) = (xx[i]=x, yy[i]=y, i=i+1)
set table $dummy
 plot "" using (fnset($1,$2)) with table
unset table
numi = int((i-1)/2)

#-----create fig*.png files
do for [i=1:numi] {
  set output "/tmp/fig".i.".png"
  plot for [j=i:i] $dummy using (xx[j]):(yy[j]):(xx[numi+j]-xx[j]):(yy[numi+j]-yy[j]) with vectors
  set output
}

#-----2nd part

set term svg  size 400, 400  mouse standalone   linewidth 3
set output "aaa.svg"

indices = "first second"
count=0
fncount(x,y)=(count=(count==numi?1:count+1),count)
plot for [i=1:words(indices)] "a_test.dat" \
 index word( indices, i ) \
 u 1:2:(sprintf("image:/tmp/fig%d.png\nfig",fncount($1,$2) )) \
 w labels hypertext point pt 7 ps 2  notitle

Я не буду объяснять строки из предыдущего ответа, такие как чтение данных в 2 массива xx и yy. Чтобы сохранить тот же масштаб для всех графиков он явно установлен с помощью set xrange ... на минимум и max рассчитывается из команды статистики.

Первая часть кода использует do for для создания файлов fig1.png и так далее. on, каждый из которых показывает только одну стрелку, используя один набор из 4 элементов данных из массивов.

Вторая часть выбирает тип терминала svg с опцией mouse и standalone. Это вставляет JavaScript, необходимый для обработки всплывающего окна мыши, в выходной файл svg. Команда plot основана на вашем примере с 3-м столбцом данных, например, строка "image:/tmp/fig1.png\nfig" для первый набор данных. Функция fncount() просто увеличивается при каждом вызове, от 1 до 3 (если у вас 3 строки данных на блок), затем обратно к 1. Это повторно использует те же 3 файла изображений в начальной и конечной точках данных.

Обратите внимание, что программа просмотра svg должна иметь возможность находить файлы изображений в файловой системе.

Я думаю, что это почти возможно. Но вы бы не использовали гипертекст, вы бы использовали функцию «переключить сюжет». Я покажу полный скрипт ниже, но вот основная идея:

Нарисуйте график, который содержит (график 1) хвостовые точки (график 2) верхние точки (графики с 3 по N) отдельный график для каждой стрелки. Поскольку каждая стрелка находится на отдельном графике, ее можно включать и выключать, щелкая ее заголовок. Команды toggle в сценарии отключают стрелки для начала. Теперь мы подошли к сложной части. Вместо того, чтобы позволять заголовку автоматически помещаться в ключевое поле графика, мы явно размещаем каждый заголовок поверх его хвостовой точки. Теперь вы можете нажать на точку и вуаля, появится стрелка.

Вот сценарий

set xrange [0:10]
set yrange [0:10]
set style arrow 1 head nofill lc "black"

# Here is the data
$ARROWS << EOF
x1  y1  x2  y2    
5   1   4   5     
6   2   8   2     
9   8   2   7     
EOF

#
# This is the basic plot, with everything visible.
# In an interactive terminal (qt/wxt/x11/windows/svg) you can toggle
# the arrows on and off by clicking on the corresponding title in the key.
#

set key samplen 0.01

plot $ARROWS using 1:2 with points pt 7 ps 2 title "Click me", \
     $ARROWS using 3:4 with points pt 7 ps 2 notitle, \
     for [i=1:*] $ARROWS every 1::i::i using 1:2:($3-$1):($4-$2) with vectors as 1 title " "

pause -1

#
# Now we get tricky by placing the arrow titles on top of the points
# rather than in the key, and we programmatically toggle off the arrows.
# You should be able to make the arrow appear by clicking on the point
# that corresponds to the arrow tail.
#

array tx[3]
array ty[3]
do for [i=1:3] {
    tx[i] = int(word($ARROWS[i+1],1))
    ty[i] = int(word($ARROWS[i+1],2))
}

plot $ARROWS using 1:2 with points pt 7 ps 2 title "Click me", \
     $ARROWS using 3:4 with points pt 7 ps 2 notitle, \
     for [i=1:3] $ARROWS every 1::i::i using 1:2:($3-$1):($4-$2) with vectors as 1 \
        title " " at first tx[i], first ty[i]

do for [plot=3:5] {toggle plot}

pause -1

Вот скрин сюжета до первого клика

А вот и скрин показа сюжета после нажатия на одну из точек

Я говорю, что это «почти» возможно, потому что мне пришлось использовать очень неуклюжий отдельный шаг для загрузки координат заголовка в массивы. Гораздо чище было бы генерировать их на лету по мере отрисовки сюжета. Я не думаю, что это возможно в настоящее время, хотя, возможно, мне не хватает какого-то хитрого трюка.

Ответ принят как подходящий

Я думаю, вы можете имитировать «гипертекстовую стрелку» с петлей while и pause mouse.

Для векторов лучше иметь начальную/конечную точки в одной строке, но это другая тема. Я подумаю над ответом на другой ваш вопрос. Здесь для простоты предполагается, что у вас есть начальная/конечная точки уже в одной строке.

  • данные отображаются один раз, а затем вы входите в цикл while (отметьте help while), который можно остановить, нажав ESC.

  • при нажатии кнопки 1 мыши данные строится снова, но дополнительно строится линия данных с минимальным расстоянием до положения мыши (т.е. переменные MOUSE_X и MOUSE_Y) with vectors. Однако кажется, что вы не можете использовать MOUSE_X и MOUSE_Y в функции. Итак, тогда вам нужно сначала присвоить его переменным x0 и y0.

  • вы, вероятно, могли бы настроить поведение появления стрелки, т.е. исчезает ли она через некоторое время или если вы двигаетесь дальше и т. д...)

Скрипт: (протестировано с gnuplot 5.4.1 и терминалами wxt и qt)

### show arrow on mouse button press (mimic hypertext arrow)
reset session

$Data <<EOD
# first   # second
x1  y1    x2  y2
5   1     4   5
6   2     8   2
9   8     2   7
EOD

set offsets 1,1,1,1
set key out noautotitle

plot $Data u 1:2 w p pt 7 ps 2 lc "blue" ti "start point", \
        '' u 3:4 w p pt 7 ps 2 lc "red"  ti "end point"

dist(colX,colY) = sqrt((column(colX)-x0)**2 + (column(colY)-y0)**2)

continue = 1
while (continue) {
    pause mouse button1,keypress
    if (MOUSE_KEY == 27) { continue=0 }   # press ESC to stop loop
    else {
        x0 = MOUSE_X
        y0 = MOUSE_Y
        plot dMin=NaN \
            $Data u (d=dist(1,2), (dMin!=dMin || d<dMin)?(dMin=d,idxMin=$0):0,$1):2 skip 1 \
                w p pt 7 ps 2 lc "blue" ti "start point", \
            '' u (d=dist(3,4), d<dMin?(dMin=d,idxMin=$0):0,$3):4 w p pt 7 ps 2 lc "red"  ti "end point", \
            '' u 1:2:($3-$1):($4-$2) every ::idxMin::idxMin skip 1 w vec lw 2 lc black
    }
}
### end of script

Снимок экрана: (из терминала wxt)

Дополнение: (оставить и убрать стрелки)

Вот версия, в которой вы оставляете несколько стрелок и можете удалить их, снова щелкнув рядом с их начальной/конечной точкой. Вы можете удалить все стрелки сразу, если щелкнете правой кнопкой мыши (в моей системе это MOUSE_BUTTON==3).

  • определить строку arrowIdxs, содержащую выбранные стрелки, то есть индексы строк
  • определить функцию inList(), которая проверяет, есть ли индекс в списке
  • определить функцию updateList(), которая либо добавляет новый индекс, либо удаляет индекс, если он уже был в списке.

Надеюсь, вы сможете сами разобраться, как работает скрипт в деталях. Проверьте help <keyword> следующие используемые ключевые слова: sprintf, sum, strstrt, strlen.

Скрипт:

### show/hide arrows on mouse button click
reset session

$Data <<EOD
# first   # second
x1  y1    x2  y2
5   1     4   5
6   2     8   2
9   8     2   7
EOD

set offsets 1,1,1,1
set key out noautotitle

plot $Data u 1:2 w p pt 7 ps 2 lc "blue" ti "start point", \
        '' u 3:4 w p pt 7 ps 2 lc "red"  ti "end point"

dist(colX,colY) = sqrt((column(colX)-x0)**2 + (column(colY)-y0)**2)

arrowIdxs = ''
inList(list,n)     = (_s=sprintf("%d",n), int(sum[_i=1:words(list)] word(list,_i) eq _s))
updateList(list,n) = (_s=sprintf("%d",n), inList(list,n) ? \
      list[1:strstrt(list,_s)-2].list[strstrt(list,_s)+strlen(_s):] : list.' '.sprintf("%d",n))

continue = 1
while (continue) {
    pause mouse button1,button3,keypress
    if (MOUSE_KEY == 27) { continue=0 }   # press ESC to stop loop
    else {
        mb=MOUSE_BUTTON
        if (mb==1) {
            x0 = MOUSE_X
            y0 = MOUSE_Y
            plot dMin=NaN \
                $Data u (d=dist(1,2), (dMin!=dMin || d<dMin)?(dMin=d,idxMin=$0):0,$1):2 skip 1 \
                    w p pt 7 ps 2 lc "blue" ti "start point", \
                '' u (d=dist(3,4), d<dMin?(dMin=d,idxMin=$0):0,$3):4 w p pt 7 ps 2 lc "red"  ti "end point", \
                arrowIdxs = updateList(arrowIdxs,idxMin) \
                '' u (inList(arrowIdxs,$0)? $1:NaN):2:($3-$1):($4-$2) skip 1 w vec lw 2 lc black
        }
        if (mb==3) {
            arrowIdxs = ''
            plot $Data u 1:2 w p pt 7 ps 2 lc "blue" ti "start point", \
                    '' u 3:4 w p pt 7 ps 2 lc "red"  ti "end point"
        }
    }
}
### end of script

Снимок экрана: (из терминала wxt)

Как убрать все стрелки при нажатии правой кнопки мыши?

magfan 21.02.2023 14:09

@magfan что значит «все стрелки»? Скрипт рисует только одну стрелку. Возможно, вы хотите сохранить все выбранные стрелки? И очистить их все правой кнопкой мыши?

theozh 21.02.2023 14:16

Я всегда предполагал одну стрелку, потому что думал о гипертексте и зависании. А вот маркировка нескольких стрелок — действительно очень интересный вариант.

magfan 21.02.2023 14:36

@magfan см. измененный ответ, который, я думаю, теперь довольно универсален.

theozh 21.02.2023 16:11

Другие вопросы по теме