Рисование брекетов с помощью Pyx

Как я могу нарисовать «связанную» линию между двумя произвольными точками с помощью Pyx?

Это будет выглядеть примерно так:

http://tof.canardpc.com/view/d16770a8-0fc6-4e9d-b43c-a11eaa09304d


person Bastien Léonard    schedule 17.08.2009    source источник
comment
Похоже, вы создаете холст, находите точку между двумя конечными точками, рисуете вертикальную линию от точки p1 до середины, рисуете какой-то сосок в средней точке, а затем рисуете вертикальную линию от середины до точки p2. Используйте c.stroke(path.line(p1.x, p2.y, halfway.x, halfway.y))) и c.stroke(path.line(halfway.x, halfway.y, p1.x, p2. у))). Или что-то. Я не устанавливаю этот пакет, чтобы ответить на этот вопрос.   -  person hughdbrown    schedule 17.08.2009
comment
@hughbrown: Почему ты не опубликовал свой ответ как ответ?   -  person S.Lott    schedule 17.08.2009
comment
У меня не установлен этот пакет. Я подумал, что смогу набросать приблизительный ответ, и Бастьен сможет с ним работать.   -  person hughdbrown    schedule 17.08.2009


Ответы (2)


Вы можете нарисовать красивые фигурные скобки, используя сигмоиды. У меня не установлен Pyx, поэтому я просто нарисую их с помощью matplotlib (здесь pylab). Здесь beta управляет резкостью кривых в фигурных скобках.

import numpy as nx
import pylab as px


def half_brace(x, beta):
    x0, x1 = x[0], x[-1]
    y = 1/(1.+nx.exp(-1*beta*(x-x0))) + 1/(1.+nx.exp(-1*beta*(x-x1)))
    return y

xmax, xstep = 20, .01
xaxis = nx.arange(0, xmax/2, xstep)
y0 = half_brace(xaxis, 10.)
y = nx.concatenate((y0, y0[::-1]))

px.plot(nx.arange(0, xmax, xstep), y)
px.show()

введите здесь описание изображения

Я построил это по оси x, чтобы сэкономить место на экране, но чтобы получить фигурные скобки по оси y, просто поменяйте местами x и y. Наконец, Pyx имеет множество встроенных функций рисования путей, которые также могут работать для ваших нужд.

person tom10    schedule 17.08.2009
comment
Эй, мне особенно интересно узнать, как вы написали метод half_brace. Математика, которую вы делаете, является обычным стандартным материалом? Можете ли вы помочь указать мне некоторые ресурсы, чтобы узнать это? - person asyncwait; 28.08.2009
comment
@Vadi - я добавил ссылку на сигмовидные функции в первую строку ответа. Функция half_brace представляет собой сумму двух сигмовидных, и я просто подумал, что проще вычислить сумму, чем разбить ее на четыре части. Сигмоиды сами по себе довольно распространены, но это зависит от вашей точки зрения. Например, в физике (но в темах более продвинутых, чем основной курс бакалавриата) они проявляются непосредственно как функция распределения Ферми-Дирака. - person tom10; 29.08.2009

tom10 предлагает хорошее решение, но его можно было бы улучшить.
Ключ создает фигурную скобку в диапазоне [0,1],[0,1], а затем масштабирует ее.
Эта версия также позволяет настраивать немного придайте форму. Для бонусных баллов он использует вторую производную, чтобы выяснить, насколько плотно разместить точки.

mid задает баланс между нижней и верхней частями.
beta1 и beta2 управляют резкостью кривых (нижней и верхней).
Вы можете изменить height (или просто умножить y на скаляр).
Чтобы сделать его вертикальным, а не горизонтальным, нужно просто поменять местами x и y.
initial_divisions и resolution_factor определяют, как выбираются значения x, но обычно ими можно пренебречь.

import numpy as NP

def range_brace(x_min, x_max, mid=0.75, 
                beta1=50.0, beta2=100.0, height=1, 
                initial_divisions=11, resolution_factor=1.5):
    # determine x0 adaptively values using second derivitive
    # could be replaced with less snazzy:
    #   x0 = NP.arange(0, 0.5, .001)
    x0 = NP.array(())
    tmpx = NP.linspace(0, 0.5, initial_divisions)
    tmp = beta1**2 * (NP.exp(beta1*tmpx)) * (1-NP.exp(beta1*tmpx)) / NP.power((1+NP.exp(beta1*tmpx)),3)
    tmp += beta2**2 * (NP.exp(beta2*(tmpx-0.5))) * (1-NP.exp(beta2*(tmpx-0.5))) / NP.power((1+NP.exp(beta2*(tmpx-0.5))),3)
    for i in range(0, len(tmpx)-1):
        t = int(NP.ceil(resolution_factor*max(NP.abs(tmp[i:i+2]))/float(initial_divisions)))
        x0 = NP.append(x0, NP.linspace(tmpx[i],tmpx[i+1],t))
    x0 = NP.sort(NP.unique(x0)) # sort and remove dups
    # half brace using sum of two logistic functions
    y0 = mid*2*((1/(1.+NP.exp(-1*beta1*x0)))-0.5)
    y0 += (1-mid)*2*(1/(1.+NP.exp(-1*beta2*(x0-0.5))))
    # concat and scale x
    x = NP.concatenate((x0, 1-x0[::-1])) * float((x_max-x_min)) + x_min
    y = NP.concatenate((y0, y0[::-1])) * float(height)
    return (x,y)

Использование простое:

import pylab as plt

fig = plt.figure()
ax = fig.add_subplot(111)

x,y = range_brace(0, 100)
ax.plot(x, y,'-')

plt.show()

Сюжет создан на примере

PS: Не забывайте, что вы можете передать clip_on=False в plot и поместить его вне оси.

person travc    schedule 01.12.2013