我一直试图想出一个优雅的算法来用SVG绘制它,它让我望而却步。
只绘制线框非常简单。它只是从每个角落到右侧边缘的线条,目标点的间距相等。但填充它们比较棘手 - 我需要实际的多边形坐标来绘制填充的形状......不是吗?
一种方法是用一点数学来解决所有的段交叉点。这会给我所有交叉点的坐标,但是我如何知道如何对四个坐标组进行分组,并跟踪要填充哪些?
答案 0 :(得分:5)
除了交换黑色和白色瓷砖外,您的图片可以分为4个等分,即点对称。例如,要计算底部象限,您将遍历从左下角(x1, y1)
开始的所有行并向右边缘(x2, y2)
进行迭代,然后遍历可从顶部开始的所有行左下角(x3, y3)
朝向下边(x4, y4)
,计算交点并将其保存在矩阵Px
和Py
中。我懒得做数学,所以我只输入line intersections的公式。最后,如果索引ix
和iy
的总和是奇数,则迭代矩阵并在相邻点之间绘制补丁。
使用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()
这段代码可能会更加优化,但是像这样,它应该相当清楚它的作用。
结果: 将其扩展到所有4个象限并将其写为SVG文件留给读者练习:)。
答案 1 :(得分:0)
可能的解决方案:
我们可以将每个黑色填充的单元格视为两个三角形的交集。三角形从每个角落散开。因此,如果我们有一个函数来计算两个三角形的交集的多边形,我们需要做的就是迭代所有三角形的所有交叉点(实际上相交)。然后,将三角形黑色或黑色着色的决定基本上是奇偶校验。因此,如果我们有四个边:A,B,C,D和N三角形从每一边散开,那么如果j * k是奇数,那么Aj和Bk的交点应该是黑色。