使用DELPHI的Canvas绘制复杂的图形(形同电脑主板与主板上的芯片),即在画布上画出约二千个大小不等的矩形或直线,现在速度基本上是没有问题,但算法上不知如何解决:1、如何从这组数据中找出图形中坐标原点所在屏幕上的坐标位置;
2、因为所给的原始数据都是以X轴向右,Y轴向上的坐标(即原点在左下角),但屏幕画图是从右上角向右和向下画,所以所有的坐标都要以X轴做个镜向,不知道有什么具体的算法;
3、放大、缩小、旋转以后又如何控制。 有这方面经验的朋友请给点意见或相关的算法,不甚感激,如果你很忙,那就请你给个思路也行。多谢了各位!!对了,我的邮箱是[email protected],如果有源码,可直接发给我!

解决方案 »

  1.   

    首先同意一楼的看法。然后在补充一点。关于矢量图形的变换算法已经非常成熟。你可以参考一些关于计算机图形学的书籍。具体说来也无非是几个矩阵运算而已。关于你的问题的提示如下:1、对于坐标原点的优化,你可以统计出所有矩形的外边界(取最大最小值)。然后把原点设在这个矩形的正中心,同时采取适当的缩放比例就行了。2、如果不涉及文本的显示,你可以使用Get-/SetWindowExtEx和Get-/SetViewportExtEx来设置原点位置、坐标映射和缩放比例。3、关于围绕某一点旋转,其实可以按照先平移,再旋转,最后再平移的顺序分步骤进行。缩放也与此类似。同时还有一些技巧。比如建立矢量的缓存(一次变换,多次使用)等,这样一来你就能够将数据与显示分离开来(比如作为数据的矩形往往只有两个点坐标,而旋转后你则需要四个点坐标来进行绘制)。往后会很有好处的。
      

  2.   

    下面是在显示全部矩形的时候统计坐标原点的方法:
    var
      minx, miny, maxx, maxy : Integer;
      org : TPoint; //原点在屏幕上的位置
      hz, vz, z : Double; //缩放比例
      i : Integer;
    begin
      minx := 0;
      miny := 0;
      maxx := 0;
      maxy := 0;
      for i := 0 to RectCount - 1 do
      begin
        minx := min(Rect[i].Left, minx);
        miny := min(Rect[i].Top, miny);
        maxx := max(Rect[i].Right, maxx);
        maxy := max(Rect[i].Bottom, maxy);
      end;  hz := ClientWidth / (maxx - minx); //横向的缩放
      vz := ClientHeight / (maxy - miny); //纵向的缩放
      z := min(hz, vz); //统一缩放比例
      org.x := Round(ClientWidth * ((0 - minx) / (maxx - minx)));
      org.y := Round(ClientHeight * ((maxx - 0) / (maxy - miny)));
    end;此时你在屏幕上画矩形的时候就应该用换算过的坐标:
    ScreenRect := Rect(org.x + MyRect.Left * z, org.y - MyRect.Top * z, org.x + MyRect.Right * z, org.y - MyRect.Bottom * z);假如你在屏幕上的p点按了一下放大(或缩小),相对当前的放大/缩小倍率为rz:
    z1 := z * rz;
    org1.x := Round(p.x - (p.x - org.x) * rz);
    org1.y := Round(p.y - (p.y - org.y) * rz);上面的代码都没有测试过,只是作个提示吧。