如何从Python列表中绘制可缩放的Cantor集合? [英] How to draw a zoomable Cantor set from a Python list?

查看:372
本文介绍了如何从Python列表中绘制可缩放的Cantor集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


我写了一个Python脚本f(n),它产生一个线段的整体列表,然后是三分之一,然后是第九,然后是第二十七等。如何将其转换为图形 - 理想情况下,我可以放大和缩小导航?

我想绘制第一个line,然后是下面的三分之一,然后是那些下面的九分之一,以及那些下面的二十七分之一等等,就像Cantor设置的熟悉的方式一样。



f标记片段在Cantor集合构造的每个阶段保留的时间间隔(有一些值(假设它是为了参数的缘故而编号),并用零标记所有已删除的段,标记为以下格式:



[row-number,element_number,label]

其中label是每个分段的一些参数,假设现在它的数字被移除部分以1开始,并将所有移除的零件标记为零。



所以它输出:

f(0)= [[0,0,1]]



f(1)= [[0,0,1],[1,0,2],[1,1 (3)= [[0,0,1],[1,0,2],[0,0,1],[1,2,3]]

1,1,0],[1,2,3],[2,0,4],[2,1,0],[2,2,5],[2,3,0] ,[2,4,0],[2,5,0],[2,6,6],[2,7,0],[2,8,7]]

$ p

所以要清楚,为了绘制前n行,我不需要使用f(x小于n)作为f(n)足以列出每一行中的分段。



所有必要的数据都在那里,因为我们可以读取行号l,并从中可以定位其高度以及推断段的长度为1/3 ^ l,并且我们有元素的element_number e,所以我们可以将它放在位置e / 3 ^ l,并且我们有标签放置在它的中心e /(2 * 3 ^ (l-1))

我已经安装了networkx和mathplotlib,并且我也可以导出一个gexf,但我正在努力寻找一种方法(对于noob程序员)绘制这些标记的条或段。任何帮助将不胜感激。

解决方案

我完全不理解标签。但是,通过递归地遍历关卡很容易产生cantor情节。

  import numpy as np 
import matplotlib.pyplot作为plt

line = [0,1]
depth = 5

def divide(line,level = 0):
plt.plot( line,[level,level],color =k,lw = 5,solid_capstyle =butt)
if level <深度:
s = np.linspace(line [0],line [1],4)
divide(s [:2],level + 1)
divide(s [2: ,level + 1)

divide(line)
plt.gca()。invert_yaxis()
plt.show()





在这里标记行在这里并不直接,因为行的递归放置顺序与所需的标记顺序不同。通过为每一行放置标签并稍后对标签进行排序来解决这个问题;然后给每个从排序列表中的数字。

  import numpy as np 
import matplotlib.pyplot as plt

line = [0,1]
depth = 5

labels = []
def divide(line,level = 0):
plt.plot(line,[level,level],color =k,lw = 5,solid_capstyle =butt)
label = plt.annotate(,xy =(np.mean(line) ,level),xytext =(0,5),
textcoords =offset points,ha =center,color =crimson)
labels.append(label)
if级别<深度:
s = np.linspace(line [0],line [1],4)
divide(s [:2],level + 1)
divide(s [2: ,level + 1)

divide(line)

labels.sort(key = lambda x:x.xy [:: - 1])$ ​​b $ b for i ,枚举(标签)中的标签:
label.set_text(i + 1)
plt.gca()。invert_yaxis()
plt.show()

请注意,线越小,文本的可读性就越差。因此,标记较小的小线条只有在放大时才有意义。


I've written a Python script f(n) which produces a list of the whole, then the thirds, then ninths, then 27ths, etc. of a line segment. How do I convert this into a graph - ideally one I can zoom in and out of and navigate?

I want to draw the first line, then the thirds underneath, then the ninths under those, and the 27ths below that and so on like the familiar way the Cantor set is constructed.

f labels the segments of the interval that remain at each stage of the Cantor set construction, with some value (let's say it numbers them for argument's sake) and it labels all the removed segments with a zero, labelled in the following format:

[row-number, element_number, label]

where label is some parameter for each segment, let's say for now it numbers the removed parts beginning with 1 and labels all removed parts zero.

so it outputs:

f(0)=[[0,0,1]]

f(1)=[[0,0,1],[1,0,2],[1,1,0],[1,2,3]]

f(3)=[[0,0,1],[1,0,2],[1,1,0],[1,2,3],[2,0,4],[2,1,0],[2,2,5],[2,3,0],[2,4,0],[2,5,0],[2,6,6],[2,7,0],[2,8,7]]

etc.

So to be clear, to graph the first n rows I need not use f(x less than n) as f(n) is sufficient to list the segments in every row.

All necessary data's there as we can read off the line number l and from that can position its height as well as deduce the length of the segment as 1/3^l, and we have the element_number e of the element so we can place it at position e/3^l, and we have the label to place at its centre e/(2*3^(l-1))

I've installed networkx, mathplotlib, and I could also export a gexf but I'm struggling to find a way (for a noob programmer) to draw these labelled bars or segments. Any help would be greatly appreciated.

解决方案

I do not understand the "labels" at all. But a cantor plot is rather easily produced by recursively walking the levels.

import numpy as np
import matplotlib.pyplot as plt

line = [0,1]
depth = 5

def divide(line, level=0):
    plt.plot(line,[level,level], color="k", lw=5, solid_capstyle="butt")
    if level < depth:
        s = np.linspace(line[0],line[1],4)
        divide(s[:2], level+1)
        divide(s[2:], level+1)

divide(line)
plt.gca().invert_yaxis()
plt.show()


Labeling the lines is in this far not straight forward here because the recursive placement of the lines is in a different order than the desired labeling. One solve this by placing a label for each line and later on sort the labels; then giving each the number from the sorted list.

import numpy as np
import matplotlib.pyplot as plt

line = [0,1]
depth = 5

labels=[]
def divide(line, level=0):
    plt.plot(line,[level,level], color="k", lw=5, solid_capstyle="butt")
    label = plt.annotate("",xy=(np.mean(line),level), xytext=(0,5),
                         textcoords="offset points", ha="center", color="crimson")
    labels.append(label)
    if level < depth:
        s = np.linspace(line[0],line[1],4)
        divide(s[:2], level+1)
        divide(s[2:], level+1)

divide(line)

labels.sort(key=lambda x: x.xy[::-1])
for i, label in enumerate(labels):
    label.set_text(i+1)
plt.gca().invert_yaxis()
plt.show()

Note that the smaller the lines, the less readable the text is. So labeling the lower, small lines makes only sense when zooming in I guess.

这篇关于如何从Python列表中绘制可缩放的Cantor集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆