Reputation: 311
As you know P5 coordinate system doesn't start from the middle of the canvas plus the y axis is flipped My question is how to change the coordinates of p5 so it became the same as the Cartesian coordinate system
Upvotes: 12
Views: 5233
Reputation: 2106
In addition to translating the origin and flipping the y axis, I came to this question looking to scale for "world coordinates" (coordinates that are for the scene, independent of the pixel dimensions of the canvas).
A few refinements I'd like to add to address my specific needs:
Set up some word coordinate variables:
let worldWidth = 640
let worldHeight = 400
let worldAspect = (worldHeight/worldWidth);
In setup()
adjust the canvas to the width of the window, but maintain the world aspect ratio:
function setup() {
createCanvas(windowWidth, windowWidth * worldAspect);
}
Begin draw()
by translating origin to the bottom left. To use world coordinates, one can scale by the canvas height
and width
, divided by world coordinates (remembering to also flip vertically by using negative height
):
function draw() {
translate(0, height);
scale(width / worldWidth, -height / worldHeight);
# ...
}
For un-flipping text, if you need to do this often, write a function which wraps text() to temporarily un-flip:
function wText(message, x, y, size) {
push();
scale(1, -1);
textSize(size);
text(message, x, -y);
pop();
}
This maintains the world-coordinates scaling because successive calls to scale() are cumulative. It's also why we want to scale by one.
Now we can think in world coordinates, with origin in the bottom left and vertical y axis going up. For instance, this will always draw "hi" the right way up, in the top-right corner, and a medium sized true circle in the center, no matter the size of the window and canvas:
wText("hi", 580, 350, 50);
circle(320, 200, 80);
Note the use of world coordinates means we no longer have to calculate pixel position based on width
and height
: the scale
takes care of this.
The mouseX
and mouseY
variables always contain the mouse's device pixel position: not scaled or translated. To resolve this, define two more functions:
function wMouseX() {
return mouseX * (worldWidth / width)
}
function wMouseY() {
return worldHeight - (mouseY * (worldHeight / height))
}
You can test this with the following code, to show the mouse coordinates (pixels) and their world coordinates (scaled and translated points):
wText(" x:\t" + round(mouseX), 0, 40);
wText(" y:\t" + round(mouseY), 0, 20);
wText("wX:\t" + wMouseX(), 200, 40);
wText("wY:\t" + wMouseY(), 200, 20);
fill("red");
circle(wMouseX(), wMouseY(), 15);
Upvotes: 1
Reputation: 210889
Use translate()
to translate the origin to the center. Use scale
to flip the y axis:
function draw() {
translate(width/2, height/2);
scale(1, -1);
// [...]
}
Note, width
and height
is the width and height of the canvas.
translate(width/2, height/2)
moves everything by the half width and height. It moves the objects of the scene from the top left to the center of the canvas.
This approach will cause that text to be flipped. To "unflip" the text again, each text must be inserted in a push()
/pop()
block that reverses the flip::
push();
scale(1, -1); // reverse the global flip
text(...);
pop();
Upvotes: 22