我用VC编了一个在地图上实时绘制曲线的程序,就是算一个数据点画一段线那种。
用的当然是最基本的
moveto();
lineto();
啦~!
绘图程序本身是view类里的成员函数,并且我没有在OnDraw里面调用该函数,而是在一个工作者线程里面调用的,该线程用于计算数据点。
现在的问题是:绘图功能可以实现,但是在绘制了一段时间以后,程序就会报一个错误,然后就只能终止程序,错误我看不懂:(
值得注意的是,这个错误似乎与计算步长有关。我编的是画卫星星下点轨道的程序,当计算步长为2秒时,只能画出1轨就报错了。而当我将步长改为30秒时,则可以画出大约15轨,正好与15:1对应,再改步长,该规律依然存在。这是什么原因?
我尝试着在线程中注释掉绘图程序,只进行计算则不会出错。所以判断是绘图程序出错了。但是如果有错,为什么又可以绘图呢?
我是菜鸟,现学VC现编软件,关于绘图什么都不懂。这个问题,不知道表述得是否清楚,也许光靠这点信息无法对错误进行判断,但求各位大虾本着提携后辈的精神,给我提示一些可能的错误之处:比如是否需要用双缓冲,或者绘图程序中可能漏掉了哪些语句?
最好有高手,能直接指出错误之处,感激不尽!!!!
用的当然是最基本的
moveto();
lineto();
啦~!
绘图程序本身是view类里的成员函数,并且我没有在OnDraw里面调用该函数,而是在一个工作者线程里面调用的,该线程用于计算数据点。
现在的问题是:绘图功能可以实现,但是在绘制了一段时间以后,程序就会报一个错误,然后就只能终止程序,错误我看不懂:(
值得注意的是,这个错误似乎与计算步长有关。我编的是画卫星星下点轨道的程序,当计算步长为2秒时,只能画出1轨就报错了。而当我将步长改为30秒时,则可以画出大约15轨,正好与15:1对应,再改步长,该规律依然存在。这是什么原因?
我尝试着在线程中注释掉绘图程序,只进行计算则不会出错。所以判断是绘图程序出错了。但是如果有错,为什么又可以绘图呢?
我是菜鸟,现学VC现编软件,关于绘图什么都不懂。这个问题,不知道表述得是否清楚,也许光靠这点信息无法对错误进行判断,但求各位大虾本着提携后辈的精神,给我提示一些可能的错误之处:比如是否需要用双缓冲,或者绘图程序中可能漏掉了哪些语句?
最好有高手,能直接指出错误之处,感激不尽!!!!
void CSatelliteView::OnDraw(CDC* pDC)
{
UNUSED_ALWAYS(pDC); CSatelliteDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CDC MemDC;//声明内存设备文本对象
MemDC.CreateCompatibleDC(pDC);//创建兼容内存设备
//将位图选入内存设备文本对象
CBitmap*pbmpOld=MemDC.SelectObject(&m_Bitmap);
//pDC->StretchBlt(0,0,m_Width,m_Height,&MemDC,
// 0,0,m_Width,m_Height,SRCCOPY);//显示位图
CRect rcClientRect;//定义一个矩形对象
GetClientRect(&rcClientRect);//取得窗口客户区尺寸
pDC->StretchBlt(0,0,rcClientRect.right,rcClientRect.bottom,
&MemDC,0,0,m_Width,m_Height,SRCCOPY);//显示改变后的位图
CPoint Pos(0,0);//定位窗口位置
MemDC.SelectObject(pbmpOld);//恢复原状 DrawMapGrid();
}
然后是工作者线程:其中pSatelliteView 是全局变量,在CSatelliteView.cpp中声明的。
UINT CalcuThreadProc(LPVOID pParam)
{
CSatOrbitData* pData = (CSatOrbitData*) pParam;
int i=0;
int k;
double alphaG0 = 0.0;//暂取初始格林威治赤经为0 do
{
double r = pData->m_a0;
pData->a = pData->m_a0;
pData->e = pData->m_e0;
pData->i = pData->m_i0*PI/180;
pData->Omega = pData->m_Omega0*PI/180;
double n = sqrt(niu/(pData->m_a0*pData->m_a0*pData->m_a0));
pData->u = Transform(pData->m_u0*PI/180+n*(pData->m_step*i)); //求位置矢量
pData->Xi = r*(cos(pData->u)*cos(pData->Omega)-sin(pData->u)*cos(pData->i)*sin(pData->Omega));
pData->Yi = r*(cos(pData->u)*sin(pData->Omega)+sin(pData->u)*cos(pData->i)*cos(pData->Omega));
pData->Zi = r*sin(pData->u)*sin(pData->i);
//求速度矢量,暂时不求
//求经纬度
double delta = asin(pData->Zi/r);//赤纬
double alpha = Judge(pData->Xi,pData->Yi);//赤经
double alphaG = alphaG0+we*pData->m_step*i;//格林威治赤经
pData->Latitude = delta;//纬度
pData->Longitude = Transform(alpha-alphaG);//经度
//开始绘图
double xxjd[2],xxwd[2];//星下点地理经度、星下点地理纬度
if(i==0)//需要用一次初始时刻的星下点地理经纬度
{
xxjd[0]=pData->Longitude*180/PI;
xxwd[0]=pData->Latitude*180/PI;
xxjd[1]=0;
xxwd[1]=0;
}
if(i>=1)
{
xxjd[1]=pData->Longitude*180/PI;
xxwd[1]=pData->Latitude*180/PI;
} if(pSatelliteView && i>=1)//判断视图类指针是否为空
pSatelliteView->DrawGroundTrack(xxjd,xxwd);//绘制星下点轨迹
//写数据
CString str[10];
str[0].Format("%e",pData->Latitude*180/PI);
str[1].Format("%e",pData->Longitude*180/PI);
str[2].Format("%e",pData->Xi);
str[3].Format("%e",pData->Yi);
str[4].Format("%e",pData->Zi);
str[5].Format("%e",pData->a);
str[6].Format("%e",pData->e);
str[7].Format("%e",pData->i);
str[8].Format("%e",pData->Omega*180/PI);
str[9].Format("%e",pData->u*180/PI); pBar2->m_wndChild.SetItemText(0,0,"1");
for(k=0;k<10;k++)
{
pBar2->m_wndChild.SetItemText(0,k+1,str[k]);
} i=i+1;
}while( pData->Start && !pData->Pause && !pData->End);
return 0;
}
绘制轨迹的函数:
double CSatelliteView::DrawGroundTrack(double xxjd[2],double xxwd[2])
{
int du=10000;//为了避免象素点化整造成的数据点定位误差(表现为曲线抖动厉害)扩大客户坐标比例
CDC* pDC;
pDC=GetDC();
CRect rcClientRect;//定义一个矩形对象
GetClientRect(&rcClientRect);
pDC->SetMapMode(MM_ANISOTROPIC);//选择映射模式
//以下4句将坐标原点移至客户区中央,实现通常意义上的直角坐标系。
pDC->SetWindowOrg(-180*du,90*du);
pDC->SetWindowExt(360*du,-180*du);//使Y轴向上,所以纵向度量为负
pDC->SetViewportOrg(0,0);
pDC->SetViewportExt(rcClientRect.Width(),rcClientRect.Height());
//pDC->SetViewportOrg(rcClientRect.Width()/2,
// rcClientRect.Height()/2);//本来将坐标系原点移至客户区中央也可使用该语句,
//但是坐标轴方向不合适,仍然是Y向下为正的。
CPen NewPen;//声明画笔对象
CPen *pOldPen;//保存原先画笔的指针
//初始化实线、1象素宽的绿色画笔
NewPen.CreatePen(PS_SOLID,1,RGB(0,255,0));
//将画笔选入设备文本对象
pOldPen=pDC->SelectObject(&NewPen);
//使用画笔 //double xxjd_buff,xxwd_buff;//星下点地理经度、星下点地理纬度
if (fabs(xxjd[1]-xxjd[0])>=350)
{
pDC->MoveTo(int(xxjd[1]*du),int(xxwd[1]*du));
}
else
{
pDC->MoveTo(int(xxjd[0]*du),int(xxwd[0]*du));
pDC->LineTo(int(xxjd[1]*du),int(xxwd[1]*du));
} xxjd[0]=xxjd[1];
xxwd[0]=xxwd[1]; //恢复原先的画笔对象
pDC->SelectObject(pOldPen);
return (xxjd[0],xxwd[0]);
return (xxjd[1],xxwd[1]);
}
在CSatelliteView::DrawGroundTrack中加上
ReleaseDC(pDC); 试试
嗯~!加入ReleaseDC(pDC); 问题解决了。我就知道肯定是犯了一些很低级的错误,没办法,菜鸟嘛。对vc绘图机制完全不清楚。
大侠帮忙帮到底,解释一下为什么要释放指针?是不是因为我每次绘制一条线段都创造了一个新指针,而原来的指针没有释放掉,这样就占用了资源,所以当绘图进行到一定的时候,资源不足时,就会出错了?大体意思应该是这样的吧?
那为什么,我看到很多书上的程序例子都没有ReleaseDC(pDC); 这个语句呢?我写的程序基本上都是看书之后稍做修改得来的。
顺便问一下,如果同时有几个人为我解答了这个问题,我是否需要每人都给50分,那我岂不是穷了?5555~~~
嗯~!加入ReleaseDC(pDC); 问题解决了。我就知道肯定是犯了一些很低级的错误,没办法,菜鸟嘛。对vc绘图机制完全不清楚。
大侠帮忙帮到底,解释一下为什么要释放指针?是不是因为我每次绘制一条线段都创造了一个新指针,而原来的指针没有释放掉,这样就占用了资源,所以当绘图进行到一定的时候,资源不足时,就会出错了?大体意思应该是这样的吧?
那为什么,我看到很多书上的程序例子都没有ReleaseDC(pDC); 这个语句呢?我写的程序基本上都是看书之后稍做修改得来的。
顺便问一下,如果同时有几个人为我解答了这个问题,我是否需要每人都给50分,那我岂不是穷了?5555~~~