在 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
给定以下 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