散景圈不适合广场?

时间:2017-07-11 05:23:09

标签: python geometry bokeh

我正在使用散景绘制一些几何图形并遇到了这个问题。我正在绘制一个具有相等边(即正方形)的矩形,并在该正方形中绘制一个直径=正方形宽度的圆。圆圈应与边缘处的正方形相切,但不是。

这是代码:

from bokeh.plotting import output_notebook, figure, show
output_notebook()

p = figure(width=500, height=500)

p.rect(0, 0, 300, 300, line_color='black')
p.circle(x=0, y=0, radius=150, line_color='black', 
         fill_color='grey',  radius_units='data')

p.axis.minor_tick_out = 0

show(p)

结果如下:

enter image description here

我做错了什么或者可以改变以使圆圈完全适合广场?

提前致谢, 兰德尔

这是另一种情况 - 只画一个圆圈:

p = figure(width=500, height=500, x_range=(-150, 150), y_range=(-150, 150))
p.circle(x=0, y=0, radius=150, line_color='black', 
         fill_color='grey', radius_units='data')
show(p)

圆的半径在x方向上为150,但不在y方向上。

enter image description here

5 个答案:

答案 0 :(得分:4)

更新:请注意以下@DuCorey的新答案。从Bokeh 0.12.7开始,对于这种情况,方位控制现在可用。

问题实际上是正方形不是正方形,这是因为像素长宽比和“数据”宽高比不匹配。即,每个像素的距离在x方向上不同于在y方向上的距离。

有几个选择:

  • 您可以使用各种属性来控制中心绘图区域的尺寸(例如,绘图边框宽度和轴刻度标签方向)您还可以显式控制数据范围。换句话说,您可以制作宽高比匹配,然后圆圈和矩形将匹配

  • 您可以使用绝对像素单位(例如size表示圆圈,并使用较大的square标记代替rect)而不是“数据”单位。

或者,如果你想要一个在方面不匹配时“变形”的圆圈,那么你最好的办法就是使用ellipsewidth相同的height将起作用,因为在这种情况下,散景有两个尺寸用于测量(而不是单个radius)并且可以独立地匹配每个尺寸的尺度。

(这实际上是解释行为的根本区别:rect有两个维度可以独立衡量。circle ,它只有一个,并且必须任意使用x或y维度来测量每个像素的距离)

答案 1 :(得分:3)

我想报告一下,截至Bokeh 0.12.7,现在可以更简单的方式修复此问题。

如其他帖子所述,主要问题不是圆圈不是圆形,而是方形不是正方形。这是因为Bokeh绘制图形(画布)的实际区域默认情况下通常不是正方形,或者甚至在宽度和高度设置为相同值时也是如此。默认情况下,Bokeh将尝试通过占用画布上的所有空间来绘制图形。这会在数据距离与绘图的像素距离之间产生不匹配。

从0.12.7开始,数字现在可以接受match_aspect属性,当设置为True时,该属性将匹配数据空间的方面与像素情节的空间。

在您的示例中,只需在图中添加match_aspect = True

即可
p = figure(width=500, height=500, match_aspect=True, 
           title="Circle touches all 4 sides of square")
p.rect(0, 0, 300, 300, line_color='black')
p.circle(x=0, y=0, radius=150, line_color='black', 
         fill_color='grey',  radius_units='data')

现在将生成

Circle touches all 4 sides of the square

答案 2 :(得分:0)

不确定,但是bleu矩形不是你的矩形。

替换:

p.rect(0, 0, 300, 300, line_color='black')

人:

p.rect(-150, -150, 150, 150, line_color='black')

答案 3 :(得分:0)

好的,基于这些建议,我尝试了一些方法。

  • 更改了y轴刻度标签的方向 - 仍然 有问题。
  • 改变了各种对峙,甚至改变了方向 图中的标签(带负偏移)。也没用。
  • 将figure()中的x_range和r_range更改为相等的元组。
  • 也没用
  • 更改plot_height(减少它),我最终可以通过里亚尔和错误,使用适合的plot_height得到圆圈以适合广场。情节宽度。

控制情节属性的很多很棒的练习。时间会投入。

然而,我尝试过的最后一次改变效果最好。这是最初的建议之一 - 改变情节边界。

奇怪的是,设置p.min_border=40,其中0.12.6是默认值,瞧,图表中的plot_width = plot_height在图表中也显示为1的图表宽高比。

p = figure(plot_width=500, plot_height=500)

p.rect(0, 0, 300, 300, line_color=None)

p.circle(x=0, y=0, radius=150, line_color=None, 
         fill_color='lightgrey',  radius_units='data')

p.min_border=40

show(p)

显示添加p.min_border=40效果的图像之前和之后。超过~33的任何值似乎足以迫使绘图区域具有相同的屏幕x和y尺寸 - 因此正方形实际上是正方形(并且圆形适合内部)。

enter image description here

enter image description here

答案 4 :(得分:0)

原因是你正在创建一个圆形标记(或圆形字形)并将其放在位置(0,0),而你似乎想要创建一个以0为中心的圆。

我认为rect此处“碰巧”可以正常工作,因为它可以在两个维度中正确缩放并保持“矩形”。

Keyword Args:
    radius (UnitsSpecPropertyDescriptor) : The radius values for circle markers (in "data space" units, by default). (default None)
    radius_dimension (BasicPropertyDescriptor) : What dimension to measure circle radii along. (default 'x')
    radius_units (Enum('screen', 'data')) :  (default 'data')

我想我的观点是在这里你通过尝试使用“字形”作为你的情节并指定单位作为数据单位来采取捷径。

如果您想创建一个实际的圆圈,您可以执行以下操作:

th = np.linspace(0, 2*np.pi)

r = 150

p = figure(width=500, height=500)

p.rect(0, 0, 300, 300, line_color='black')

p.line(r * np.cos(th), r * np.sin(th), line_color='black')
# p.circle(x=0, y=0, radius=150, line_color='black',
#         fill_color='grey', radius_units='data')

p.axis.minor_tick_out = 0

show(p)

注意上面的内容更难填充(我没有打扰),因为我猜你需要定义一些闭合的多边形函数,而我只定义了一个恰好是闭合多边形的线,在本例中是一个圆。