Canvas在绘图中的使用(100分)

  • 主题发起人 主题发起人 myevin
  • 开始时间 开始时间
M

myevin

Unregistered / Unconfirmed
GUEST, unregistred user!
在Delphi中,canvas定位坐标时只能使用Integer,但是需要定位的点是含有十位小数的,
如果用Trunc忽略小数的话,点就都重合在一起了,请问用什么方法才可以精确的定位呢?
请指教。
 
象素点用整数还不够表示?你的眼睛和显示器都是绝对牛了!

你所谓的坐标点可以放大10倍100倍1000倍表示与象素点对应的。
 
那么如何将坐标点放大xx倍和象素点对应呢?
主要是当初测量时,x,y的值小数点后都有10位,现在想要用computer绘图时,如何尽量
在不缩小精度的情况下,绘制出图形呢?
 
实在不行还可以用int64啊。
 
但是如果我将x,y都放大了10倍,那又显示不到指定的image中了,
哎,究竟该如何换算才能使精度高些呢?
各位大虾,请指点
 
用逻辑窗口和viewport吧
让windows自己去缩放
 
to myevin:非也非也,你的概念混了吧?
比如说10个象素的单位你可以定义为1,也可以定义为0.001、0.01、0.1、10、100、100……
这个怎么会和精度高低有关系呢?实际显示的还是10个象素而已。
不过如果你的坐标从 (0.00000000000001,0.00000000000001)到
(100000000000,100000000000)都要精确显示的话必然不能同时显示这么大一块了,
简单解决办法有三个:
1、如果中间有些数据不重要就截去;
2、可以都不截取而分块显示,需要显示哪一块就显示哪一块;
3、杀掉对你提这个要求的人或者自杀。
 
能够告诉我源程序该如何写吗?
感激不尽。
 
myevin:说到这份上还要源代码?算了,我懒得写了,这分数你愿意给谁就给谁吧!
 
wjiachun,你误会了我所说的话。
其实我的程序是由实验室中测出的数据,划出一系列平滑的曲线。
但是当我将每个点都标出后,发现如果用trunc省略小数点,那么点就重合了,而将
他们*100000000的话,又不知道该怎么来显示在屏幕上,所以请教各位
 
我没有误会你的话,我也做过类似的东西。
估计你的横坐标是一个时间,纵坐标是一个采集数据,那么你可以只放大纵坐标。
比如原来是一个 (0,0)到(0,100)的直线,分成100点,每个单位就是1。
现在还是这条直线,表示为(0,0)到(0,0.000001),分成100点,每个单位就是0.00000001。
如果我猜测错误,那么你横坐标也类似变换就可以了。

其实这根本就是数学问题。
 
谢谢wjiachun
那我再问一下,我绘制出来的图形在image上,怎么样才能将他打印出来呢?
 
顺便还想问一下,一个array用什么函数清空呢?(找了很久,没找到)
 
打印用COPYRECT到TPRINT上就可以了。要不存成BMP图再用其它的工具打印也是个不错的
选择。
ARRAY嘛,自己定义清空就好了,其实如果你想重复用这个ARRAY的话你注意点的话不用
清空也可以的。

至于你说的小数点的问题WJA。。。已经说清楚了。主要是你把数学运算和画面显示搞
混了。数学运算当然是要用到小数点。可是画面显示可不用。你可以定义一具大大的
IMAGE罗,而它的1个象素点就表示0.000000000001。然后你计算为100的话你的IMAGE上
就应该显示100/0.000000000001=1000000000000。。。。。(算不清几个零)大概就是
这样算。这是没办法的事。你自己看着办。至于这种图要打印,嘿嘿,看来不用绘图仪
是不行的了。
 
如果是动态数组可以用 setlength(array,0)来清空
 
这个问题应该用映射模式来解决,在 VC++ 中由于 Document/View 框架的原因比较常用,
Delphi 中相对就用得少了,下面是一个典型的 VC++ 设置映射模式的例子,当应用程序每次
绘图的时候,都要调用 OnPrepareDC 函数来定位逻辑坐标,比如:

void CSGEView::OnLButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc(this);
OnPrepareDC(&dc);
dc.DPtoLP(&point); // 设备坐标到逻辑坐标转换
...
}

void CSGEView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
// TODO: Add your specialized code here and/or call the base class

CSGEDoc* pDoc = GetDocument();
CScrollView::OnPrepareDC(pDC, pInfo);

pDC->SetMapMode(MM_ANISOTROPIC);
CSize sizeDoc = pDoc->GetDocSize();
sizeDoc.cy = -sizeDoc.cy;
pDC->SetWindowExt(sizeDoc);

CSize sizeNum, sizeDenom;
pDoc->GetZoomFactor(&sizeNum, &sizeDenom);

int xLogPixPerInch = pDC->GetDeviceCaps(LOGPIXELSX);
int yLogPixPerInch = pDC->GetDeviceCaps(LOGPIXELSY);

long xExt = (long)sizeDoc.cx * xLogPixPerInch * sizeNum.cx;
xExt /= 100 * (long)sizeDenom.cx;
long yExt = (long)sizeDoc.cy * yLogPixPerInch * sizeNum.cy;
yExt /= 100 * (long)sizeDenom.cy;
pDC->SetViewportExt((int)xExt, (int)-yExt);
}

你可以把你的坐标放大,当作逻辑坐标,正确地设置了映射模式之后,对逻辑坐标的 GDI
操作会自动转换到设备坐标。但是在你的要求中,10 位的精度未免太高了。
大致的方法就这些,希望对你能有所帮助。
 
其实你也就是要在屏幕上画图吧,你最好建立以下的概念。
首先你要建立一个坐标系。建立视口和逻辑窗口。视口是设备座标,窗口可任意定
你的画图应当是在你自己建立的逻辑窗口中画图。
实际图形从窗口到视口再到设备的转换是windows自动进行的。设置座标系的几个函数如下:
SetWindowOrgEx
SetWindowextex
setviewportorgex
setviewportextex
还有一个函数是设置窗口的映射模式的,好象是setmapmode.
 
多人接受答案了。
 
后退
顶部