The PathElement class represents a path element on a drawing. The class is defined in
the inkex/elements/_polygons.py module. It is derived from PathElementBase class.
Both classes only include a few methods and properties. The Python interpreter session
below shows how to get hold of a path element and invoke its methods and properties.
The same drawing drawing-21.svg discussed in Chapter 9 is used here as an example.
The path element is a typical Bezier curve with two end points and two control points.
george@Inspiron-5515:~$ /usr/bin/python3
Python 3.9.5 (default, May 11 2021, 08:20:37)
[GCC 10.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import sys
>>> sys.path.append('/usr/share/inkscape/extensions')
>>>
>>> from inkex import load_svg
>>> et = load_svg('/home/george/Desktop/drawing-21.svg')
>>> svg = et.getroot()
>>>
>>> for el in svg:
... print(el)
...
namedview
defs
g
>>>
>>> gel = svg[-1]
>>> gel
<Element {http://www.w3.org/2000/svg}g at 0x7fc6ecd069a0>
>>>
>>> for el in gel:
... print(el)
...
rect
ellipse
path
path
>>>
>>> pel = gel[-1]
>>>
>>> pel
<Element {http://www.w3.org/2000/svg}path at 0x7fc6ecd06b30>
>>>
>>> pel.original_path
[Move(80.3412, 87.9089), Curve(99.575, 67.2665,
103.398, 73.9063, 113.129, 83.6942)]
>>>
>>> pel.path # defined in ShapeElement
[Move(80.3412, 87.9089), Curve(99.575, 67.2665,
103.398, 73.9063, 113.129, 83.6942)]
>>>
>>> pel.__class__
<class 'inkex.elements._polygons.PathElement'>
>>>
>>> pel.get_path()
'M 80.341223,87.908862 C 99.574968,67.266473
103.39751,73.906308 113.12895,83.694219'
>>>
>>> pel.get('d')
'M 80.341223,87.908862 C 99.574968,67.266473
103.39751,73.906308 113.12895,83.694219'
>>>
>>>
The path property defined in ShapeElement class returns a Path object.
Other classes derived from ShapeElement also have this path property.
The Path class is defined in inkex/paths.py module. The Path object is
interesting, and it is a list of other class objects. The inkex/paths.py module
defines many other classes such as Move, move, Horz, horz, Curve,
curve, etc.
>>> p = pel.path
>>> p
[Move(80.3412, 87.9089), Curve(99.575, 67.2665,
103.398, 73.9063, 113.129, 83.6942)]
>>> p.bounding_box()
BoundingBox((80.341223, 113.12895),(74.37224453581157, 87.908862))
>>>
>>> for pt in p.control_points:
... print(pt)
...
80.3412, 87.9089
99.575, 67.2665
103.398, 73.9063
113.129, 83.6942
>>>
>>> for pt in p.end_points:
... print(pt)
...
80.3412, 87.9089
113.129, 83.6942
>>>
>>>
>>> p.reverse()
[Move(113.129, 83.6942), Curve(103.398, 73.9063,
99.575, 67.2665, 80.3412, 87.9089)]
>>>
>>> from inkex import Transform
>>> p.transform(Transform('translate(10,10)')) # return changed value
[Move(90.3412, 97.9089), Curve(109.575, 77.2665,
113.398, 83.9063, 123.129, 93.6942)]
>>>
>>> p.to_absolute()
[Move(80.3412, 87.9089), Curve(99.575, 67.2665,
103.398, 73.9063, 113.129, 83.6942)]
>>>
>>> str(p)
'M 80.3412 87.9089 C 99.575 67.2665 103.398 73.9063 113.129 83.6942'
>>>
>>> p_str = str(p)
>>> from inkex import Path
>>> p_new = Path(p_str)
>>> p_new
[Move(80.3412, 87.9089), Curve(99.575, 67.2665,
103.398, 73.9063, 113.129, 83.6942)]
>>> p_new.__str__()
'M 80.3412 87.9089 C 99.575 67.2665 103.398 73.9063 113.129 83.6942'
>>>
>>> m = p_new[0]
>>> m
Move(80.3412, 87.9089)
>>> m.args
(80.3412, 87.9089)
>>>
>>> m.x = 80
>>> m.y = 88
>>> m
Move(80, 88)
It is easy to create a Path element from composing class objects.
Here is an example to create a similar Bezier curve as shown above and
add it to a drawing in memory.
>>> from inkex.paths import Move, Curve
>>> p2 = Path()
>>> m = Move(90, 90)
>>> p2.append(m)
>>> c = Curve(99, 67, 104, 74, 114, 84)
>>> p2.append(c)
>>> p2
[Move(90, 90), Curve(99, 67, 104, 74, 114, 84)]
>>>
>>> from inkex import PathElement
>>> pel = PathElement.new(p2)
>>> pel
<Element {http://www.w3.org/2000/svg}path at 0x7fc6ecd06e50>
>>> gel
<Element {http://www.w3.org/2000/svg}g at 0x7fc6ecd069a0>
>>> gel.append(pel)
>>> for el in gel:
... print(el)
...
rect
ellipse
path
path
path # new path element
Inkscape comes with many path related system extensions. They are listed under Modify Path,
Generate From Path, and Visualize Path submenus under Extensions menu.
Let’s examine one of them and discuss its code.
When we work on engineering drawings, the dimension tool is indispensable. The Dimensions
menu under Visualize Path is such a tool. We can select several path elements or a single
element and apply the extension. The extension will draw the auxiliary lines and two
dimension lines with arrow heads. However, the tool does not automatically add dimension
texts along the lines. The figure below shows an example.
The Dimensions extension code is in the dimension.inx and dimension.py files under
system extension directory. The Dimension class is derived from PathModifier class
in pathmodifier.py module, which is in turn derived from EffectExtension class.
The Dimension class doesn’t use any methods in PathModifier class, so it is the
same as subclassing EffectExtension class directly.
The Dimension class defines 5 methods. We have discussed add_arguments and effect
methods in previous chapters. The other three methods add_marker, horz_line,
vert_line are easy to understand.
14. Paths