Inkscape.org
Creating New Extensions Issuess with bounding boxes.
  1. #1
    luke1985 luke1985 @luke1985

    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.

  2. #2
    inklinea inklinea @inklinea⛰️

    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.
     

  3. #3
    inklinea inklinea @inklinea⛰️

    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. 

     

     

  4. #4
    luke1985 luke1985 @luke1985
    inklinea
    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.:)
     
     
    inklinea

    I would alway use.

    my_object.transform = my_object.transform @ new_transform

    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

     

    Have a nice day. ;)