Как создать гипертекстовые стрелки в 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
Конечные и Readonly классы в PHP
Конечные и Readonly классы в PHP
В прошлом, когда вы не хотели, чтобы другие классы расширяли определенный класс, вы могли пометить его как final.
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
От React к React Native: Руководство для начинающих по разработке мобильных приложений с использованием React
Если вы уже умеете работать с React, создание мобильных приложений для iOS и Android - это новое приключение, в котором вы сможете применить свои...
БЭМ: Конвенция об именовании CSS
БЭМ: Конвенция об именовании CSS
Я часто вижу беспорядочный код CSS, особенно если проект большой. Кроме того, я совершал эту ошибку в профессиональных или личных проектах и...
Революционная веб-разработка ServiceNow
Революционная веб-разработка ServiceNow
В быстро развивающемся мире веб-разработки ServiceNow для достижения успеха крайне важно оставаться на вершине последних тенденций и технологий. По...
Как добавить SEO(Search Engine Optimization) в наше веб-приложение и как это работает?
Как добавить SEO(Search Engine Optimization) в наше веб-приложение и как это работает?
Заголовок веб-страницы играет наиболее важную роль в SEO, он помогает поисковой системе понять, о чем ваш сайт.
Конфигурация Jest в angular
Конфигурация Jest в angular
В этой статье я рассказываю обо всех необходимых шагах, которые нужно выполнить при настройке jest в angular.
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

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