I'm trying to create an element append it to a group and center relatively to the group (so that object appears on the center of the group).
I'm doing something like this:
bbox = group.bounding_box()
center = (bbox.center_x, bbox.center_y)
translation = inkex.Transform(translate=center)
try:
parent_transform = group.composed_transform()
except:
pass
else:
transform = -parent_transform @ translation
group.append(some_object)
some_object.transform = transform
The problem is this not always working. I can't grasp the idea of bounding boxes - are they relative to parent or what? The documentation is very spare and isn't clear about that. Thank you for help in advance.
Geometric ( which just considers paths ) and Visual ( which considers stroke width / filters etc )
You can see this on canvas by setting Edit>Preferences>Tools to geometric or visual.
Inkex ( the extension system ) can only give a geometric bounding box for paths. That does include shape objects such as rect, ellipse, circle.
Inkex is a series of python modules that process XML. It also is a standalone product that works without Inkscape being installed.
You can install Inkex to a python venv for example without Inkscape being installed.
------------------------
Inkex cannot produce a visual bounding box, and it cannot give a bounding box for text natively.
The bounding box inkex returns for text is just the top left x, y
That means, if you have a group which contains text, it will not contribute to the bounding box.
Path stroke will not contribute to the bounding box and filters will not.
------------------------
Generally for a visual bounding box you would have to make a command call to the main inkscape program command line using the --query-all option and parse the output into a dictionary.
Geometric ( which just considers paths ) and Visual ( which considers stroke width / filters etc ) (...)
(...)Inkex ( the extension system ) can only give a geometric bounding box for paths. That does include shape objects such as rect, ellipse, circle.
(...)Inkex cannot produce a visual bounding box, and it cannot give a bounding box for text natively. The bounding box inkex returns for text is just the top left x, y That means, if you have a group which contains text, it will not contribute to the bounding box. Path stroke will not contribute to the bounding box and filters will not.
Good to know that. I guess I will stick now to converting text to paths and avoid using some filters that impact the visual bounding box.
Other than that - I've now solved my problem. I had to pass in the group's parent composed_transform to the bounding_box method, it took me some time because getting to the point by reading the source really takes a lot of time and effort.
I think it would be nice if it was mentioned in the docs.:)
Well the thing is, I don't just want to move the object. I needed to reposition it so that it appears in the center of a group and is part of that group. But, since appending object to a group in the code transforms it by the parent composed_transform i had to do the following:
transform = -group_transform @ translation
Where translation holds the geometric bounding_box returned by a call to the object bounding_box(groups_parent_transform), where groups_parent_transform is the composed transform of the group's parent. The full code now looks like following:
I'm trying to create an element append it to a group and center relatively to the group (so that object appears on the center of the group).
I'm doing something like this:
bbox = group.bounding_box()
center = (bbox.center_x, bbox.center_y)
translation = inkex.Transform(translate=center)
try:
parent_transform = group.composed_transform()
except:
pass
else:
transform = -parent_transform @ translation
group.append(some_object)
some_object.transform = transform
The problem is this not always working. I can't grasp the idea of bounding boxes - are they relative to parent or what? The documentation is very spare and isn't clear about that. Thank you for help in advance.
With svg there are two types of bounding box:
Geometric ( which just considers paths ) and Visual ( which considers stroke width / filters etc )
You can see this on canvas by setting Edit>Preferences>Tools to geometric or visual.
Inkex ( the extension system ) can only give a geometric bounding box for paths. That does include shape objects such as rect, ellipse, circle.
Inkex is a series of python modules that process XML. It also is a standalone product that works without Inkscape being installed.
You can install Inkex to a python venv for example without Inkscape being installed.
------------------------
Inkex cannot produce a visual bounding box, and it cannot give a bounding box for text natively.
The bounding box inkex returns for text is just the top left x, y
That means, if you have a group which contains text, it will not contribute to the bounding box.
Path stroke will not contribute to the bounding box and filters will not.
------------------------
Generally for a visual bounding box you would have to make a command call to the main inkscape program command line using the --query-all option and parse the output into a dictionary.
Also if you are applying a transform to an object.
I would alway use.
my_object.transform = my_object.transform @ new_transform
However, have you given my_object any location on the canvas ?
So generally you would do a subtraction between the two object coordinates in question.
To translate to the correct position.
If you post an example svg I may be able to give an example.
Well the thing is, I don't just want to move the object. I needed to reposition it so that it appears in the center of a group and is part of that group.
But, since appending object to a group in the code transforms it by the parent composed_transform i had to do the following:
transform = -group_transform @ translation
Where translation holds the geometric bounding_box returned by a call to the object bounding_box(groups_parent_transform), where groups_parent_transform is the composed transform of the group's parent.
The full code now looks like following:
parent_transform = inkex.Transform()
parent = group.getparent()
if parent is not None:
parent_transform = parent.composed_transform()
bbox = group.bounding_box(parent_transform)
center = (bbox.center_x, bbox.center_y)
translation = inkex.Transform(translate=center)
try:
group_transform = group.composed_transform()
except:
pass
else:
transform = -group_transform @ translation
group.append(some_object)
some_object.transform = transform