Closed p1usign closed 1 year ago
When I use ctx.Rotate
to rotate the canvas, every coordinate is messed up, how can i get the correct coordinate?
also, I found there have difference between rotate path, text and image..
I've pushed a commit that changes how the View
(modified by e.g. Rotate
) and CoordView/CoordSystem
work together. The coordinate is now independent of the view. That is, setting the CoordSystem to CartesianIV
will draw elements at the given coordinates without surprises, even if the canvas has been rotated.
I've not seen any divergence in behaviour over paths/text/images, which differences have you observed? See the following example to show how drawing works:
package main
import (
"bytes"
"fmt"
"io/ioutil"
"time"
"github.com/tdewolff/canvas"
"github.com/tdewolff/canvas/renderers"
)
func main() {
fontLatin := canvas.NewFontFamily("latin")
if err := fontLatin.LoadFontFile("/usr/share/fonts/TTF/DejaVuSerif.ttf", canvas.FontRegular); err != nil {
panic(err)
}
W := 80.0
H := 80.0
c := canvas.New(W, H)
ctx := canvas.NewContext(c)
ctx.SetFillColor(canvas.White)
ctx.DrawPath(0, 0, canvas.Rectangle(W, H))
// Rotate
ctx.SetCoordSystem(canvas.CartesianIV)
ctx.Rotate(90.0)
// Text
face := fontLatin.Face(12.0, canvas.Black, canvas.FontRegular, canvas.FontNormal)
text := canvas.NewTextLine(face, "Hello World!", canvas.Left)
ctx.DrawText(30.0, 40.0, text)
// Path
ctx.SetFillColor(canvas.Black)
ctx.DrawPath(40.0, 40.0, canvas.StarPolygon(5, 5.0, 2.0, true))
// Image
lenna, err := ioutil.ReadFile("../resources/lenna.png")
if err != nil {
panic(err)
}
img, err := canvas.NewPNGImage(bytes.NewReader(lenna))
if err != nil {
panic(err)
}
ctx.DrawImage(50.0, 40.0, img, 40.0)
// Render and save
start := time.Now()
renderers.Write("rotate.png", c, canvas.DPMM(10.0))
fmt.Printf("%s to save PNG\n", time.Since(start))
}
I've pushed a commit that changes how the
View
(modified by e.g.Rotate
) andCoordView/CoordSystem
work together. The coordinate is now independent of the view. That is, setting the CoordSystem toCartesianIV
will draw elements at the given coordinates without surprises, even if the canvas has been rotated.I've not seen any divergence in behaviour over paths/text/images, which differences have you observed? See the following example to show how drawing works:
package main import ( "bytes" "fmt" "io/ioutil" "time" "github.com/tdewolff/canvas" "github.com/tdewolff/canvas/renderers" ) func main() { fontLatin := canvas.NewFontFamily("latin") if err := fontLatin.LoadFontFile("/usr/share/fonts/TTF/DejaVuSerif.ttf", canvas.FontRegular); err != nil { panic(err) } W := 80.0 H := 80.0 c := canvas.New(W, H) ctx := canvas.NewContext(c) ctx.SetFillColor(canvas.White) ctx.DrawPath(0, 0, canvas.Rectangle(W, H)) // Rotate ctx.SetCoordSystem(canvas.CartesianIV) ctx.Rotate(90.0) // Text face := fontLatin.Face(12.0, canvas.Black, canvas.FontRegular, canvas.FontNormal) text := canvas.NewTextLine(face, "Hello World!", canvas.Left) ctx.DrawText(30.0, 40.0, text) // Path ctx.SetFillColor(canvas.Black) ctx.DrawPath(40.0, 40.0, canvas.StarPolygon(5, 5.0, 2.0, true)) // Image lenna, err := ioutil.ReadFile("../resources/lenna.png") if err != nil { panic(err) } img, err := canvas.NewPNGImage(bytes.NewReader(lenna)) if err != nil { panic(err) } ctx.DrawImage(50.0, 40.0, img, 40.0) // Render and save start := time.Now() renderers.Write("rotate.png", c, canvas.DPMM(10.0)) fmt.Printf("%s to save PNG\n", time.Since(start)) }
Thanks for your answer
Now after I pull the latest code, I found that now all the element's original point always at the left bottom, even i set coordsystem IV, is it correct?
package main
import (
"github.com/tdewolff/canvas"
"github.com/tdewolff/canvas/renderers"
)
func main() {
fontLatin := canvas.NewFontFamily("latin")
if err := fontLatin.LoadLocalFont("DejaVuSerif.ttf", canvas.FontRegular); err != nil {
panic(err)
}
W := 80.0
H := 80.0
c := canvas.New(W, H)
ctx := canvas.NewContext(c)
ctx.SetFillColor(canvas.White)
ctx.DrawPath(0, 0, canvas.Rectangle(W, H))
ctx.SetCoordSystem(canvas.CartesianIV)
ctx.SetFillColor(canvas.Black)
ctx.DrawPath(0, 20, canvas.Rectangle(20, 20))
renderers.Write("test.png", c, canvas.DPMM(10.0))
}
Before this, the setting of the coordinate system will affect the origin, this change is huge
Also, the performance of translate is now becoming incomprehensible
Maybe you can explain the relationship between coordsystem/coordview and view, and how translate and rotate work
The origin of the path is where ever the path starts (i.e. its first MoveTo command). The canvas.Rectangle
gives a path that starts at the bottom-left and moves counter-clockwise, this has nothing to do with the coordinate system and hasn't changed. You could use canvas.Rectangle(20, -20)
to start at the top-left and go clockwise.
The coordview and coordsystem affect the way that coordinates (i.e. the x
and y
in DrawText(x,y, ...)
) are transformed. First the coordsystem is applied (one of the four Cartesian quadrants) so that coordinates origin in the bottom-left (the default for all functions in Canvas and in mathematics in general). Then the optional coordview is applied in case needed (not in your case). That defines the coordinate at which an object is drawn. Separately, the object gets transformed by the view before drawing at the previously established coordinate. As you see, the coordview and view are independent of each other after the two commits above!
I understand, thank you for your reply and help, issue has been resolved. Thank you very much!
I would like to rotate an element 90 degrees, some like:
by the way, in this case I set coordsystem to be IV:
now the question is, how can I write the code? could u plz give me more information? thx a lot!