Make Vector2D inherit from complex and switch internal path operations to complex
What does the merge request do?
First commit: Vector2d inherits from Complex
This is the minimal changeset required to make paths work nicer with numpy (which then enables faster computation through numpy).
We use the builtin complex
as a means to store x and y coordinate, which naturally translates to a numpy datatype.
The change comes with a small performance benefit (although the real benefits will come from vectorizing operations):
master | this | |
---|---|---|
a = inkex.Vector2d(1, 2) + inkex.Vector2d(2,3) |
2.13us | 1.78 us |
a = abs(inkex.Vector2d(1, 2)) |
1.44 us | 463 ns |
Second commit: switch internal path operations to complex
Only two functions of the path commands were used by extensions: control_points
and end_point
. In those cases, I've added a ccontrol_points
and cend_point
function to use in internal computations such as reversing a path.
Also, I've removed the instance checks for PathCommands because that's ridiculously slow compared to a string comparison.
The entire change makes typical path operations about 2-3 times faster (it's better for absolute-only paths and worse for relative-only paths, but doesn't really seem to be affected by path size):
p = inkex.Path('m 58,88 c -10,2 3,13 10,4 z M 32,67 c 14,-5 23,-3 35,7 m 2,-21 c '*20)"
header | master | this |
---|---|---|
p.reverse() | 950us | 364us |
p.to_absolute() | 291us | 146us |
I doesn't really help for to_superpath()
since at least for me, about 60% of time is spent in copy.deepcopy
. That'll be part of a future MR.
Note: additional speedup of path operations would very likely involve
- duplicating tiny amounts of code (say properly implement the end_point, to_curve, ... methods for relative path commands to save the creation of the corresponding Absolute command)
- avoiding duplicate evaluation of end_point, etc
Implementation notes
I had to remove the assign
method, but this is not required by any of the stock extensions - actually no extensions unit test was touched.
Implementation detail: Vector2d(1)
is now legal, since 1
is a legal complex number (1+0j
).
Summary for release notes
Vector2d
now derives from complex
, simplifying the vectorisation of path operations in Numpy. The assign
method has been removed as complex is immutable. Path operations have been sped up by basing their internal computation on complex proper.
Checklist
-
Add unit tests (if applicable) -
Changes to inkex/
are well documented -
Clean merge request history