安卓、Qt绘图坐标变换

    引言:

       坐标变换的目的:使数学表达式更简单。从数学上理解坐标线性变换后,计算机编程的变换也就容易理解了。

    许多编程工具提供了坐标变换方法,使绘图更加容易

          假设要在某个窗口画一个旋转了45度的矩形,这个新矩形的边与坐标轴不平行,无法用类似 drawRect 的函数画出来,如果把坐标系也旋转45度,则在新的坐标系下,矩形的边与坐标平行,仍可以用drawRect 画出来。

     本想找安卓系统关于Canvas绘图坐标变换的,看了一片文章,后来发现居然是html5的,联想到以前看的Qt绘图坐标变换,发现三者用法差不多啊。

  自己做了一个简单例子传到CSDN资源,相关安卓代码  http://download.csdn.net/download/cibiren2011/5045772

  原文出处:http://blog.sina.com.cn/s/blog_8fab526c01015tqs.html  原文是html5的,

1.Android Canvas绘图坐标变换

1.translate(x,y):平移,将画布的坐标原点向左右方向移动x,向上下方向移动y.canvas的默认位置是在(0,0).
    例子:画布原点假如落在(1,1),那么translate(10,10)就是在原点(1,1)基础上分别在x轴、y轴移动10,则原点变为(11,11)。

2.scale(x,y):扩大。x为水平方向的放大倍数,y为竖直方向的放大倍数。

3.rotate(angel):旋转.angle指旋转的角度,顺时针旋转。
4.transform():切变。所谓切变,其实就是把图像的顶部或底部推到一边。

第一条很好理解,就是要明确顺序。

canvas的转换不是针对整个canvas的,而是针对调用转换方法之后绘制的shapes 或 paths。如下:

context.rotate(45 * Math.PI/180);
context.fillRect(50, 50, 50, 50);

顺序很重要,反了就没有旋转的效果了。


第二条,转换的时候,需要把转换的中心点移到shape的自身的中心,不然的话,请看下面这个例子(浅蓝色部分表示canvas):

context.fillRect(50, 50, 50, 50);



这是没有转换的效果,接着来看旋转45°的效果:

context.rotate(45 * Math.PI/180);
context.fillRect(50, 50, 50, 50);


可以看出,旋转的中心是canvas的左上角(scale()的中心也是左上角),也就是点(0,0),但是通常我们需要的是围绕自己的中心进行旋转,所以就有了第二条。

==========================================================================================

下面说说怎么移动中心点

假如fillRect(50, 50, 50, 50),那么这个矩形的中心点是(x + width/2, y + height/2),即(75, 75)。

上面刚说了,旋转的中心是canvas的左上角,我们要做的就是把(0, 0)移到(75, 75)的位置。


canvas的translate()方法可以使坐标系统的原点向上下左右移动。这正是我们需要的!

context.translate(x + width/2, y + height/2);


好了,中心点处理完了,还记得上面的第一条不,切记顺序,现在该画矩形了,fillRect()的参数 x 和 y 现在是什么呢?
 

调用translate()之后,整个坐标系统都平移了,所以我们之前的fillRect(50, 50, 50, 50),矩形的左上角不再是(50, 50)了,而是(-0.5 * width, -0.5 * height);

context.fillRect(-0.5 * width, -0.5 * height);

 

 

==========================================================================================

 

再说下scale(),如果我们需要放大1倍,即 scale(2, 2); 刚才也说了,缩放的中心点默认也是canvas的左上角,所以我们还是要进行坐标平移:

context.translate(x + width/2, y + height/2);
context.scale(2, 2);

接着画矩形,这里很容易出现幻觉,好像要画一个放大1倍后的矩形,其实不用的,该怎么画还是怎么画:

context.fillRect(50, 50, 50, 50);



例子:
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title></title>
  <style type="text/css">
  </style>

  <script type="text/javascript">
  function ready(){
  var canvas = document.getElementByIdx_x_x_x_x('canvas');
  var context = canvas.getContext('2d'); 
  context.translate(160,30);//平移
  context.fillStyle='rgba(120,93,222,0.25)';//填充
  context.fillRect(0,0,100,50)
 
  for(var i=0;i<50;i++){
    context.translate(25,25);//平移
    context.scale(0.95,0.95);//扩大。所有的方法包括扩大,他们的对象都是针对后面要画出的图形,而非canvas画布。因此后面的fillRecr函数画的矩形的宽仍然是100,高仍然是50.这里相当于把这个矩形扩大为原来的0.95倍。
    context.rotate(Math.PI/10);//旋转。
    context.fillRect(0,0,100,50);//画矩形 这里仍然是画(0,0,100,50)
 
  };
  </script>
</head>
<body>
  <canvas id="canvas" style="border: 1px solid #C9C9C9;" width="300" height="300">
  </canvas>
<input type="button" onClick="ready()">
</body>

</html>


2.Qt坐标变换 :摘自 C++ GUI Qt4,第二版 8.2章

 The viewport and the window are tightly bound. The viewport is an arbitrary rectangle specified in physical coordinates. The window specifies the same rectangle, but in logical coordinates. When we do the painting, we specify points in logical coordinates, and those coordinates are converted into physical coordinates in a linear algebraic manner, based on the current window–viewport settings.

By default, the viewport and the window are set to the device's rectangle. For example, if the device is a 320 x 200 widget, both the viewport and the window are the same 320 x 200 rectangle with its top-left corner at position (0, 0). In this case, the logical and physical coordinate systems are the same.

The window–viewport mechanism is useful to make the drawing code independent of the size or resolution of the paint device. For example, if we want the logical coordinates to extend from (-50, -50) to (+50, +50), with (0, 0) in the middle, we can set the window as follows:

painter.setWindow(-50, -50, 100, 100);        ZFG: (-50,-50)指定 原坐标系下的原点 在 新坐标系下的坐标

The (-50, -50) pair specifies the origin, and the (100, 100) pair specifies the width and height. This means that the logical coordinates (-50, -50) now correspond to the physical coordinates (0, 0), and the logical coordinates (+50, +50) correspond to the physical coordinates (320, 200). This is illustrated inFigure 8.10. In this example, we didn't change the viewport.

now comes the world transform. The world transform is a transformation matrix that is applied in addition to the window–viewport conversion. It allows us to translate, scale, rotate, or shear the items we are drawing. For example, if we wanted to draw text at a 45° angle, we would use this code:

QTransform transform;
transform.rotate(+45.0);
painter.setWorldTransform(transform);
painter.drawText(pos, tr("Sales"));

The logical coordinates we pass todrawText() are converted by the world transform, then mapped to physical coordinates using the window–viewport settings.

If we specify multiple transformations, they are applied in the order in which they are given. For example, if we want to use the point (50, 50) as the rotation's pivot point, we can do so by translating the window by (+50, +50), performing the rotation, and then translating the window back to its original position:

QTransform transform;
transform.translate(+50.0, +50.0);
transform.rotate(+45.0);
transform.translate(-50.0, -50.0);
painter.setWorldTransform(transform);
painter.drawText(pos, tr("Sales"));

A simpler way to specify transformations is to useQPainter'stranslate(),scale(), rotate(), andshear() convenience functions:

painter.translate(-50.0, -50.0);
painter.rotate(+45.0);
painter.translate(+50.0, +50.0);
painter.drawText(pos, tr("Sales"));


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值