如何在SVG中绘制此形状?

时间:2014-02-19 20:18:19

标签: algorithm svg drawing fractals

我一直试图想出一个优雅的算法来用SVG绘制它,它让我望而却步。

只绘制线框非常简单。它只是从每个角落到右侧边缘的线条,目标点的间距相等。但填充它们比较棘手 - 我需要实际的多边形坐标来绘制填充的形状......不是吗?

一种方法是用一点数学来解决所有的段交叉点。这会给我所有交叉点的坐标,但是我如何知道如何对四个坐标组进行分组,并跟踪要填充哪些?

2 个答案:

答案 0 :(得分:5)

除了交换黑色和白色瓷砖外,您的图片可以分为4个等分,即点对称。例如,要计算底部象限,您将遍历从左下角(x1, y1)开始的所有行并向右边缘(x2, y2)进行迭代,然后遍历可从顶部开始的所有行左下角(x3, y3)朝向下边(x4, y4),计算交点并将其保存在矩阵PxPy中。我懒得做数学,所以我只输入line intersections的公式。最后,如果索引ixiy的总和是奇数,则迭代矩阵并在相邻点之间绘制补丁。

使用Python / matplotlib的示例:

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

def intersect(x1, y1, x2, y2, x3, y3, x4, y4):
    det = (x1-x2)*(y3-y4) - (y1-y2)*(x3-x4)
    px = ((x1*y2-y1*x2)*(x3-x4) - (x1-x2)*(x3*y4-y3*x4)) / det
    py = ((x1*y2-y1*x2)*(y3-y4) - (y1-y2)*(x3*y4-y3*x4)) / det
    return px, py

n = 10
Px = np.zeros((n+1, n+1))
Py = np.zeros((n+1, n+1))

x1, y1 = 0, 0
x2 = 1
x3, y3 = 0, 1
y4 = 0
for ix in range(n+1): # index left to right along bottom
    x4 = ix / n
    for iy in range(n+1): # index bottom to top along right side
        y2 = iy / n
        px, py = intersect(x1, y1, x2, y2, x3, y3, x4, y4)
        plt.plot([x1,x2], [y1,y2], 'k')
        plt.plot([x3,x4], [y3,y4], 'k')
        plt.plot(px, py, '.r', markersize=10, zorder=3)
        Px[ix, iy] = px
        Py[ix, iy] = py

for ix in range(n):
    for iy in range(n):
        if (ix + iy) % 2: # only plot if sum is odd
            xy = [[Px[ix, iy], Py[ix, iy]], # rectangle of neighboring points
                  [Px[ix, iy+1], Py[ix, iy+1]],
                  [Px[ix+1, iy+1], Py[ix+1, iy+1]],
                  [Px[ix+1, iy], Py[ix+1, iy]]]
            poly = plt.Polygon(xy,facecolor='gray',edgecolor='none')
            plt.gca().add_patch(poly)
plt.show()   

这段代码可能会更加优化,但是像这样,它应该相当清楚它的作用。

结果: pattern 将其扩展到所有4个象限并将其写为SVG文件留给读者练习:)。

答案 1 :(得分:0)

可能的解决方案:

我们可以将每个黑色填充的单元格视为两个三角形的交集。三角形从每个角落散开。因此,如果我们有一个函数来计算两个三角形的交集的多边形,我们需要做的就是迭代所有三角形的所有交叉点(实际上相交)。然后,将三角形黑色或黑色着色的决定基本上是奇偶校验。因此,如果我们有四个边:A,B,C,D和N三角形从每一边散开,那么如果j * k是奇数,那么Aj和Bk的交点应该是黑色。