Create normalized coordinate system with Graphics::addTransform


#1

I'm attempting to create a drawing surface with y increasing upwards, the origin at the centre, and scaled so that the unit circle just fits within the window.

float w = getWidth(), h = getHeight();
g.addTransform(AffineTransform::verticalFlip(h));
g.addTransform(AffineTransform::translation(w/2, h/2));
float s = 1.f / std::min(w/2, h/2);
g.addTransform(AffineTransform::scale(s));
g.setColour(Colours::white);

I test it with:

{ 
    Path p; 
    p.addEllipse(-1, -1, 1, 1);
    // unit circle p.closeSubPath();
    g.strokePath(p, PathStrokeType(0.1f)); 
} 
{
    Path p;
    p.addRectangle(0, 0, .5f, .5f);
    p.closeSubPath();
    g.fillPath(p);
}

Everything works up to the scaling.

Now I have tested scaling by 0.5, and setting appropriate values for my circle and square. That works! But for a very small value of s, it fails!

I haven't dug into the framework yet, my guess is at some point it is converting to integer and rounding to 0.

But its unexpected behaviour!

π


#2

Most likely just a value going out-of-range. Maybe rather than calling addTransform multiple times, try building these steps into a single AffineTransform so you can see the numbers it contains as the transformations are applied?


#3

beh. I am the walrus.

float s = std::min(w/2, h/2); // was: 1.f / std::min(w/2, h/2);

The UB is all mine!

π


float w = getWidth(), h = getHeight();
g.addTransform(AffineTransform::verticalFlip(h));
g.addTransform(AffineTransform::translation(w / 2, h / 2));
float s = std::min(w / 2, h / 2);
g.addTransform(AffineTransform::scale(s));

{
    Path p;
    // unit circle yellow
    p.addEllipse(-1, -1, 2, 2);
    g.setColour(Colours::yellow);
    g.fillPath(p);
}
{
    // top right quadrant blue
    Path p;
    p.addRectangle(0, 0, 1, 1);
    g.setColour(Colours::blue);
    g.fillPath(p);
}