Drawing braces with Pyx

一曲冷凌霜 提交于 2019-12-05 02:07:53

问题


How can I draw a “braced” line between two arbitrary points with Pyx?

It would look something like this:

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


回答1:


You can draw pretty braces using sigmoidals. I don't have Pyx installed so I'll just plot these using matplotlib (pylab here). Here beta controls the sharpness of the curves in the braces.

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()

I plotted this along the x-axis to save screen space, but to get braces along the y-axis just swap x and y. Finally, Pyx has plenty of path drawing functionality built-in which coould also work for your needs.




回答2:


tom10 provides a good solution, but could use some improvement.
The key is creates a brace over the range [0,1],[0,1] and then scale it.
This version also lets you tweak the shape a bit. For bonus points, it uses the second derivative to figure out how densely to space the points.

mid sets the balance between the lower and upper parts.
beta1 and beta2 control how sharp the curves (lower and upper) are.
You can change the height (or just multiply y by a scalar).
Making it vertical instead of horizontal just involves swapping x and y.
initial_divisions and resolution_factor govern how the x values are chosen, but should generally be ignorable.

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)

Usage is simple:

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: Don't forget that you can pass clip_on=False to plot and put it outside of the axis.



来源:https://stackoverflow.com/questions/1289681/drawing-braces-with-pyx

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!