如何获取svg路径的点

Luc*_*fer 8 python svg

我有一个 SVG 文件,例如这个

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <path fill="none" stroke="red"
    d="M 10,30
       A 20,20 0,0,1 50,30
       A 20,20 0,0,1 90,30
       Q 90,60 50,90
       Q 10,60 10,30 z" />
</svg>
Run Code Online (Sandbox Code Playgroud)

如何获取这些路径的点 (x, y) 列表?

我已经看到了这个答案,但它不完整,所以我要求完整的解决方案。

我想要一个选项来选择有多少点或控制点的密度。

Gul*_*lbu 5

您可以在此处更改点的比例、偏移量和密度:

from svg.path import parse_path
from xml.dom import minidom


def get_point_at(path, distance, scale, offset):
    pos = path.point(distance)
    pos += offset
    pos *= scale
    return pos.real, pos.imag


def points_from_path(path, density, scale, offset):
    step = int(path.length() * density)
    last_step = step - 1

    if last_step == 0:
        yield get_point_at(path, 0, scale, offset)
        return

    for distance in range(step):
        yield get_point_at(
            path, distance / last_step, scale, offset)


def points_from_doc(doc, density=5, scale=1, offset=0):
    offset = offset[0] + offset[1] * 1j
    points = []
    for element in doc.getElementsByTagName("path"):
        for path in parse_path(element.getAttribute("d")):
            points.extend(points_from_path(
                path, density, scale, offset))

    return points


string = """<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
    <path fill="none" stroke="red"
        d="M 10,30
            A 20,20 0,0,1 50,30
            A 20,20 0,0,1 90,30
            Q 90,60 50,90
            Q 10,60 10,30 z" />
</svg>"""

doc = minidom.parseString(string)
points = points_from_doc(doc, density=1, scale=5, offset=(0, 5))
doc.unlink()
Run Code Online (Sandbox Code Playgroud)

您还可以将这些点可视化:

import pygame
from svg.path import parse_path
from xml.dom import minidom


...  # other functions and string


def main():
    screen = pygame.display.set_mode([500, 500])
    screen.fill((255, 255, 255))

    doc = minidom.parseString(string)
    points = points_from_doc(doc, 0.05, 5, (0, 5))
    doc.unlink()

    for point in points:
        pygame.draw.circle(screen, (0, 0, 255), point, 1)

    pygame.display.flip()

    while 1:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return


pygame.init()
main()
pygame.quit()
Run Code Online (Sandbox Code Playgroud)

density == 0.05

在此输入图像描述

density == 0.1

在此输入图像描述

density == 0.5

在此输入图像描述

density == 1

在此输入图像描述

density == 5

在此输入图像描述