如何在 SVG 中绘制这个形状?
Posted
技术标签:
【中文标题】如何在 SVG 中绘制这个形状?【英文标题】:How do I draw this shape in SVG? 【发布时间】:2014-03-20 10:24:13 【问题描述】:我一直试图想出一种优雅的算法来用 SVG 绘制它,但它让我望而却步。
仅绘制线框非常简单。它只是从每个角到其右侧边缘的线,目标点在此处等距分布。但是填充它们比较棘手 - 我需要实际的多边形坐标来绘制填充的形状......不是吗?
一种方法是通过一些数学运算来解决所有线段交叉点。这会给我所有交叉点的坐标,但是我怎么知道如何将四个坐标分组,并跟踪要填充的坐标呢?
【问题讨论】:
【参考方案1】:您的图片可以分成 4 个相等的部分,它们是点对称的,除了交换黑白图块。例如,要计算下象限,您遍历从左下角(x1, y1)
开始的所有行并朝右边缘(x2, y2)
进行遍历,然后遍历可以从左上角@ 开始的所有行987654325@ 朝向底部边缘(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 文件作为练习留给读者:)。
【讨论】:
这不太对,因为角落没有相互连接。它们略微扭曲,图像中心有一个黑色“正方形”。 :) 是的,我只是在完成绘图后更详细地研究问题中的图像时才发现。似乎 OP 没有画出精确连接对角的线,而我却画了。在他的例子中,图像具有精确的点对称性。所以要复制他的图像,拿我的图像,交换黑白(在中心得到黑色),然后复制和旋转。通过这种方式,正方形的中心带似乎具有双倍宽度(我不喜欢美学)。我更喜欢拍摄我的图像,交换颜色,旋转 90 度并粘贴。这会在中心的 4 个图块之间放置一个角。【参考方案2】:可能的解决方案:
我们可以将每个黑色填充的单元格视为两个三角形的交集。三角形从每个角落呈扇形散开。所以如果我们有一个函数来计算两个三角形相交的多边形,我们需要做的就是遍历所有三角形的所有相交(实际上相交)。决定是否将三角形着色为黑色基本上是奇偶校验。因此,如果我们有四个边:A、B、C、D 和 N 三角形从每边扇出,那么如果 j*k 是奇数,Aj 和 Bk 的交点应该是黑色的。
【讨论】:
以上是关于如何在 SVG 中绘制这个形状?的主要内容,如果未能解决你的问题,请参考以下文章