views:

140

answers:

1

I am trying to apply some natural transformations whereby the x axis is remapped to some very small domain, like from 0 to 1, whereas y is remapped to some small, but substantially larger domain, like 0 to 30. This way, drawing code can be nice and clean and only care about the model space. However, if I apply a scale, then lines are also scaled, which means that horizontal lines become extremely fat relative to vertical ones.

Here is some sample code. When natural_width is much less than natural_height the picture doesn't look as intended.

I want the picture to look like this, which is what happens with a scale that preserves aspect ratio: alt text

However, with a non-aspect ratio preserving scale, the results look like this: alt text

<html><head><title>Busted example</title></head>
<body>
   <canvas id=example height=300 width=300>
   <script>
   var canvas = document.getElementById('example');
   var ctx = canvas.getContext('2d');
   var natural_width = 10;
   var natural_height = 50;
   ctx.scale(canvas.width / natural_width, canvas.height / natural_height);

   var numLines = 20;
   ctx.beginPath();
   for (var i = 0; i < numLines; ++i) {
     ctx.moveTo(natural_width / 2, natural_height / 2);
     var angle = 2 * Math.PI * i / numLines;
        // yay for screen size independent draw calls.
     ctx.lineTo(natural_width / 2 + natural_width * Math.cos(angle),
         natural_height / 2 + natural_height * Math.sin(angle));
   }
   ctx.stroke();
   ctx.closePath();
   </script>
   </body>
</html>
A: 

Look into using save and restore. You could do a restore before drawing your lines so they keep the old scale.

https://developer.mozilla.org/en/Canvas_tutorial/Transformations

This gives the picture similar to what you are looking for.

 <html><head><title>Busted example</title></head>
<body>
   <canvas id=example height=300 width=300>
   <script>
   var canvas = document.getElementById('example');
   var ctx = canvas.getContext('2d');
   var natural_width = 10;
   var natural_height = 50;

   ctx.save();

   ctx.scale(canvas.width / natural_width, canvas.height / natural_height);


   var numLines = 20;
   ctx.beginPath();
   for (var i = 0; i < numLines; ++i) {
     ctx.moveTo(natural_width / 2, natural_height / 2);
     var angle = 2 * Math.PI * i / numLines;
        // yay for screen size independent draw calls.
     ctx.lineTo(natural_width / 2 + natural_width * Math.cos(angle),
         natural_height / 2 + natural_height * Math.sin(angle));
 }
   ctx.restore();
   ctx.lineWidth = 4;
   ctx.stroke();
   ctx.closePath();
   </script>
   </body>
</html>
Jason Rowe
I understand save and restore. Indeed, they are necessary for using the technique I am trying to apply in a more complicated setting. However, The problem is not that I cannot make/undo local transformations, it's that I cannot get the local transformation that I desire.
rrenaud