如何以编程方式创建重复图像模式?

2024-06-06 00:40:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我想使用Python创建以下图像模式。 enter image description here 为了清晰起见:这是两个独立的图像序列(一个在上排,一个在下排)。 它们相互关联,因为它们是堆积四面体的投影区域。 在三维环境中,它看起来如下:

enter image description here 请注意,这些三维对象没有缩放,因此对象的总尺寸保持不变。上面显示的投影面积就是这种情况。
四层结构(未显示)顶部将有另外10个单元格。
n级的细胞总数为:

C = (n^3 + 3*n^2 + 2*n)/6 

现在我正在手工创建图案(制作3D对象,渲染出投影区域,重复),但这是非常乏味的,不可行的更多的细分。在

我设法用下面的代码创建了一个多边形,但我不知道如何循环,使总边长度保持不变,但多边形以上面所示的方式细分。在

^{pr2}$

enter image description here
我使用了matplotlib和包含的多边形补丁,但我不确定这是否是最理想的方法。 另外,多边形的方向或颜色也不重要。在


Tags: 对象图像区域环境尺寸模式情况序列
3条回答

我没有使用matplotlib,而是提供了一个使用SVG的解决方案,其中脚本只打印出相应的SVG命令。在

注意:创建的SVG标头缺少相同的定义,这就是为什么某些程序无法处理生成的图像。虽然Inkscape可以毫无问题地打开它并再次保存它。

在SVG

中定义多边形

所描述的解决方案基于您展示的“箭头”示例,即下面的示例。
我将箭头编码为SVG路径,有四个点p0、p1、p2和p3,其中p0是顶部尖端,p1是右下边缘,p3是左下角,p2是尖端下面的点。每个点都有一个x和y坐标(p0x,p0y…)。在

注意:与数学坐标不同,SVG坐标从左到右(x)和自上而下(y)增加,因此原点是左上角。

路径以字符串形式存储,点是可变的。最后一个字符串是使用python的str.format()方法创建的。在

代码

# width of the complete picture
width=600
# height of the complete picture
height=600
# desired recursion depth (>=1)
n=5
# "shape factor" of the arrow (=(p1y-p2y)/(p2y-p0y))
# a=0 would result in a triangle
a=0.3
def create_arrows(n, depth=1, width=600, height=600, refx=None, refy=None):
    global a
    if refx==None or refy==None:
        # the first polygon instances defines it's reference point
        # following instances are given a reference point by the caller
        refx = (width - width/n)/2
        refy = 0
    if depth==1:
        # the first polygon instance defines the size of all instancens
        width=width/n
        height=height/n
    # the SVG definition of the polygon
    polyg = r'<path d="M{p0x} {p0y} L{p1x} {p1y} L{p2x} {p2y} L{p3x} {p3y} Z" />'
    points = {"p0x":refx+width/2, "p0y":refy, "p1x":refx+width, "p1y":refy+height, "p2x":refx+width/2, "p2y":refy+(1-a)*height, "p3x":refx, "p3y":refy+height}
    # create the requested polygon
    polygons = [polyg.format(**points)]
    # if maximum recursion depth not reached call method recursively
    if depth<n:
        polygons.extend(myfunction(n, depth+1, width=width, height=height, refy=refy+(1-a)*height, refx=refx)) # down shifted
        polygons.extend(myfunction(n, depth+1, width=width, height=height, refy=refy+height, refx=refx-width/2)) # bottom left
        polygons.extend(myfunction(n, depth+1, width=width, height=height, refy=refy+height, refx=refx+width/2)) #bottom right
    return(polygons)
print('<svg height="{height}" width="{width}">'.format(width=width, height=height))
# converting the list to a set is necessary since some polygons can be created by multiple recursion paths
print('\n'.join(set(create_arrows(4,width=width,height=height))))
print('</svg>')

说明

箭头是以递归方式创建的,即从顶部箭头开始。箭头的维数是width/nheight/n,其中n是所需的递归级别(n>;=1)。您展示的示例是n=1n=2、和{}。下面解释的递归模式是根据经验推导出来的,并不是直接基于您的3D示例。在

n=1:在级别n=1中,创建了顶部箭头之后就完成了。在

n=2:在级别n=2中,这个上箭头将创建另外三个,分别位于右下方和左下方和右下方。这三个箭头的尖端(p0)分别位于原始箭头的p2、p3和p1处。你完了。在

n=3:对在级别n=2中创建的每个箭头重复上述过程。在

下面请找到n=6级别的示例。 对于三角形,你的上例,这个想法很容易适应。你只需要改变多边形路径和递归模式。 顺便说一句,使用给定的脚本和a=0创建一个循环版本的trianlges。所以,如果你懒的话,只需使用它并在inkscape中转换生成的SVG。在

imgage created using above script at level n=6

帮助程序类:

class Custom_Polygon(object):
    """docstring for Polygon"""
    def __init__(self, verts):
        self.verticies = np.array(verts)
        self.dims = self.verticies.shape[1]

    def scale(self, scaleFactor):
        scaleMatrix = np.zeros((self.dims, self.dims))
        np.fill_diagonal(scaleMatrix, scaleFactor)
        self.verticies = np.dot(self.verticies, scaleMatrix)

    def scale_with_orgin(self, scaleFactor, origin):
        origin = origin.copy()
        self.translate([-i for i in origin])
        self.scale(scaleFactor)
        self.translate([i for i in origin])

    def translate(self, shiftBy):
        self.verticies += shiftBy

    def get_width(self):
        x_min = self.verticies[:,0].min()
        x_max = self.verticies[:,0].max()
        return abs(x_max - x_min)


    def get_height(self):
        y_min = self.verticies[:,1].min()
        y_max = self.verticies[:,1].max()
        return abs(y_max - y_min)

创建了一个辅助类,用于缩放和平移多边形以生成图案。并编写了绘制第一个图案的算法。应该不难做出一个类似的算法来绘制第二个图案。在

^{pr2}$

enter image description here

对于第一种模式,您可以使用以下代码:

from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon

nrows = 5
pat = np.array([[0,0],[0.5,np.sqrt(0.75)],[-0.5,np.sqrt(0.75)]])

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

for base in range(nrows):
    npat = 2*base + 1
    for col in np.linspace(-base/2, base/2, npat):
        pp = Polygon(pat + np.array([col, base*v]), fc='k', ec='none')
        ax.add_patch(pp)

ax.autoscale_view(True,True,True)
ax.set_aspect('equal')

plt.show()

enter image description here

相关问题 更多 >