在 Inkscape(svg 格式)中给定一个旋转的矩形,在 Python 中找到坐标

Given a rotated rectangle in Inkscape (svg format), find coordinates in Python

给定以下 Inkscape .svg 格式的矩形,我想找到第二个矩形(在 Python 中)所有四个角的绝对坐标。无需编写我自己的矩阵变换或任何非常复杂的东西。

你会认为会有一个图书馆来处理这类事情。事实上,我发现 Python SVG Extensions - simpletransform.py,这听起来像是它。但它在我安装的 Inkscape 的 deprecated 文件夹中,并带有以下通知:

This directory IS NOT a module path, to denote this we are using a dash in the name and there is no 'init.py'

并不能像现在这样真正导入。我可能只是尝试 copy/pasting 代码,但我完全不相信它会起作用。

并且似乎有很多questions/articles关于“删除转换”,但它们似乎都与“意外”添加的转换有关。

只是为了让事情变得更复杂 - 它看起来像第二个矩形的 x/y 坐标 - 指的是边界框的角,不是实际的矩形角。我仍然不太了解 Inkscape 的时髦坐标系统——GUI 似乎与实际对象相反。当我将鼠标悬停在矩形上时,它的坐标与我期望看到的不匹配。

哦,所有单位都设置为像素(我认为)。

这是一个非常有趣的问题。 Inkscape 变换(或计算机图形学中的变换)可能非常复杂。该网页提供了一些关于 Inkscape 扩展中转换如何工作的有用信息。

https://inkscapetutorial.org/transforms.html

对于您的具体示例,直接的答案是 Inkscape 系统扩展(1.0 版之后)有一个 Transform class(在 transforms.py 模块中),它有一个方法 apply_to_point 可以计算出绝对坐标。

更具体地说,以下扩展(inx 和 py 文件,在菜单项扩展 -> 自定义 -> 变换元素 2 下)使用 Rectangle class 绘制示例中的矩形,计算使用 apply_to_point 方法的 4 个角,用这 4 个点绘制路径。结果两个矩形相互重叠,所以我们知道计算是正确的。

transform2.inx 文件中的代码

<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
    <name>Transform Element 2</name>
    <id>user.transform2</id>
    <effect>
        <object-type>all</object-type>
        <effects-menu>
            <submenu name="Custom"/>
        </effects-menu>
    </effect>
    <script>
        <command location="inx" interpreter="python">transform2.py</command>
    </script>
</inkscape-extension>

transform2.py 文件中的代码

import inkex
from inkex import Rectangle, Transform
from inkex import Vector2d

class NewElement(inkex.GenerateExtension):
    container_label = 'transform'
    container_layer = True

    def generate(self):
        self.style = {'fill' : 'none', 'stroke' : '#000000', 
            'stroke-width' : self.svg.unittouu('2px')}
        self.style_red = {'fill' : 'none', 'stroke' : '#FF0000', 
            'stroke-width' : self.svg.unittouu('.5px')}
        rects = self.add_rect()
        for r in rects:
            yield r

    def add_rect(self):

        rect = Rectangle.new(15, 5, 20, 5)
        rect.style = self.style 
        tr = Transform('rotate(45)')
        rect.transform = tr

        el = rect
        pt_top_left = tr.apply_to_point(Vector2d(el.left, el.top))
        pt_top_right = tr.apply_to_point(Vector2d(el.right, el.top))
        pt_right_bottom = tr.apply_to_point(Vector2d(el.right, el.bottom)) 
        pt_left_bottom = tr.apply_to_point(Vector2d(el.left, el.bottom)) 

        path = inkex.PathElement()
        path.update(**{
            'style': self.style_red,
            'inkscape:label': 'redline',
            'd': 'M ' + str(pt_top_left.x) + ',' + str(pt_top_left.y) +
                ' L ' + str(pt_top_right.x) + ',' + str(pt_top_right.y) +
                ' L ' + str(pt_right_bottom.x) + ',' + str(pt_right_bottom.y) + 
                ' L ' + str(pt_left_bottom.x) + ',' + str(pt_left_bottom.y) + 
                ' z'})
        return [rect, path]


if __name__ == '__main__':
    NewElement().run()

这里是扩展的结果运行:

此外,您在 post 中引用的 simpletransform.py 文档是为 1.0 版之前的 Inkscape 系统扩展编写的。代码是用Python2.X版本写的。即使你可以找到 Inkscape 0.92.X 附带的文件副本,你也需要花时间理解代码并将其重写为 Python3 兼容,然后才能使用它在你的程序中。真的不建议任何人这样做。

至于 Inkscape 扩展单元,这个网页也有一些关于这个主题的好信息。

https://inkscapetutorial.org/units-and-coordinate-systems.html