[Solved] Drawable Rotation Around Center

I’m new to JUCE API, and I’m playing around GUI programming using SVGs.

So far, I’m able to get Drawable object from SVG, replace the rotary knob of a slider and apply transformation to this SVG.

I’m trying now to rotate around the center, with this simple logic :

  1. Translate to origin
  2. Rotate
  3. Translate again to original center

Also, I tried to rotate around center directly:

				knob_img->setTransform(AffineTransform::rotation(angle, knob_img->getBounds().getCentreX(), knob_img->getBounds().getCentreY()).scaled(2.0f, 2.0f
					, knob_img->getBounds().getCentreX(), knob_img->getBounds().getCentreY()));
				knob_img->drawAt(g, centreX - dx, centreY - dy, 1.0f);

I always notice a slight translation, like if it’s moving on a pen tip. I have tried various combinations but no good !

It seems like it’s reading the SVG directly will have additional pixels or whatever ! I tried to debug the centreX, centreY of SVG bounds, it’s changed on rotation.

Anyway, I solved the problem using SVG Path Helper to get the path and rotate it, and it works fine with me.

Hi

to my current experience, the [Drawable] object filled with svg might ignore its viewport attribute and gives no option to enable it (i guess). So your situation might be caused by unregular shape of svg that is rather extracted from its document excluding its context. So for example if your original shape has been drawn with an offest from its boundaries, this is going to be ignored at its final stage.


original


drawable


in order to remain shape’s original position you would have to calculate it yourself. for example:

(...)

svg = XmlDocument::parse(file);

width = svg->getStringAttribute("width").getIntValue();
height = svg->getStringAttribute("height").getIntValue();

image = Drawable::createFromSVG(*svg);

(...)

void resized() override {
	if(image)
		image->setTransform(AffineTransform::scale(getWidth() / double(width), getHeight() / double(height)));
}

(...)

unfortuatelly you wont be able to apply it to knob/slider etc. i believe

I have tried your approach, it gives me the same results ! the problem actually is with rotation, I cannot get it applied around center perfectly, the slight difference is in range 1.0f->2.0f in centers which is kinda weird ! why is the center changes in my calculations any yours if the shape is symmetric

I was drilling down in SVGParser, found out that the change is actually happening due to viewport parsing ! Inkscape is not generating numbers accurately !

viewBox="0 0 99.56667 99.56669" >> replaced by viewBox="0 0 100 100" 

Voila :relieved:, everything is working as expected !

Drawable* img = Drawable::createFromSVG(*svg);
img->setTransform(AffineTransform::rotation(angle, svg_width / 2, svg_height / 2)
		.scaled(rw/svg_width, rw/svg_height, svg_width/2, svg_height/2));
img->drawAt(g, centreX - (svg_width / 2), centreY - (svg_height / 2), 1.0f);
5 Likes

Hello, just a simple question here.
What does rw stand for?

Looking at the docs of AffineTransform::scaled(), the arguments are:

AffineTransform::scaled	(float factorX,
                         float factorY,
                         float pivotX,
                         float pivotY) const;

it contributed to the scale factor, so I would guess, rw is the width of the target rectangle, and since it is supposed to be rectangular (or round to be precise), the height is the same like width…

1 Like