📄 cgdraw2.cpp
字号:
#include "stdafx.h"
#include "math.h"
#include "cgdraw.h"
#include "Dib.h"
extern HPEN pen;
void CCgDraw::load(CDC *pDC)
{
extern CString name;
IPicture *pPic;
IStream *pStm;
CFileStatus fstatus;
CFile file;
LONG cb;
extern BOOL bLoad;
bLoad=false;
if (file.Open((LPCSTR)name,CFile::modeRead)&&file.GetStatus((LPCSTR)name,fstatus)&&((cb =fstatus.m_size) != -1))
{
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb);
LPVOID pvData = NULL;
if (hGlobal != NULL)
{
if ((pvData = GlobalLock(hGlobal)) != NULL)
{
file.ReadHuge(pvData, cb);
GlobalUnlock(hGlobal);
CreateStreamOnHGlobal(hGlobal, TRUE, &pStm);
if(SUCCEEDED(OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic)))
{
OLE_XSIZE_HIMETRIC hmWidth;
OLE_YSIZE_HIMETRIC hmHeight;
pPic->get_Width(&hmWidth);
pPic->get_Height(&hmHeight);
double fX,fY;
fX=(double)pDC->GetDeviceCaps(HORZRES)*(double)hmWidth/((double)pDC->GetDeviceCaps(HORZSIZE)*100.0);
fY=(double)pDC->GetDeviceCaps(VERTRES)*(double)hmHeight/((double)pDC->GetDeviceCaps(VERTSIZE)*100.0);
if(FAILED(pPic->Render(*pDC,0,0,(DWORD)fX,(DWORD)fY,0,hmHeight,hmWidth,-hmHeight,NULL)))
AfxMessageBox("Failed To Render The picture!");
pPic->Release();
}
else
AfxMessageBox("Error Loading Picture From Stream!");
}
}
}
else
AfxMessageBox("Can't Open Image File!");
}
void CCgDraw::init(CDC *pDC)
{
pDC->SelectObject(pen);
}
void CCgDraw::deletepen()
{
DeleteObject(pen);
}
void CCgDraw::free(CDC *pDC,CPoint oldMousePoint,CPoint newMousePoint)
{ if ((newMousePoint.x!=-1)||(newMousePoint.y!=-1))
{pDC->MoveTo(oldMousePoint.x,oldMousePoint.y);
pDC->LineTo(newMousePoint.x,newMousePoint.y);
}
}
void CCgDraw::line(CDC *pDC, CPoint *point)
{
pDC->MoveTo(point[0]);
pDC->LineTo(point[1]);
}
// 作业1:用几何变换原理,画矩形绕其左下角旋转图,
// 间隔36度,共画10个.
void CCgDraw::rotate(CDC *pDC)
{
int i;
double x1=0,x2=0,x3=0,y1=0,y2=0,y3=0,g,a=90,b=60,c=300,d=200,q,m;
q=sqrt(a*a+b*b);
g=atan2(b,a);
m=3.14159265453;
for(i=1;i<=10;i++)
{
x1=a*cos(i*m/5-m/5)+c;
y1=a*sin(i*m/5-m/5)+d;
pDC->MoveTo((int)c,(int)d);
pDC->LineTo((int)x1,(int)y1);
x2=q*cos(i*m/5+g-m/5)+c;
y2=q*sin(i*m/5+g-m/5)+d;
pDC->MoveTo((int)x1,(int)y1);
pDC->LineTo((int)x2,(int)y2);
x3=b*cos(m/2+i*m/5-m/5)+c;
y3=b*sin(m/2+i*m/5-m/5)+d;
pDC->MoveTo((int)x2,(int)y2);
pDC->LineTo((int)x3,(int)y3);
pDC->MoveTo((int)x3,(int)y3);
pDC->LineTo((int)c,(int)d);
}
}
// 作业2:编写用几何变换的方法生成直线箭头.
// point[0],point[1]:箭头的两个顶点;
// point[2].x:箭头长;
// point[2].y:箭头宽;
// point[3].x:箭头类型(=1 单向;=2 双向).
/*基本算法如下:
以该直线为X轴,直线的一个端点为原点建立坐标系,然后求出新的坐标系下的箭头顶点的坐标,
再将新坐标系下的坐标通过旋转及平移变换到原坐标系下即可。*/
void CCgDraw::arrow(CDC *pDC, CPoint *point)
{
//计算直线两端点之间距离d
double d=sqrt((double)(point[1].x-point[0].x)*(point[1].x-point[0].x)+(double)(point[1].y-point[0].y)*(point[1].y-point[0].y));
int L=point[2].x;
int W=point[2].y;
int M=point[3].x;
POINT poi[4];
//计算直线倾角的cos,sin值cs,sn
double cs=(point[1].x-point[0].x)/d;
double sn=(point[1].y-point[0].y)/d;
//如果M=1,则绘制单向箭头
if(M==1)
{
if(d<L) return;
pDC->MoveTo(point[0]);
pDC->LineTo(point[1]);
////////////////////////////////////////////////////////////////////////////////
//利用cos及sin进行几何变换,分别求得箭头的除去在直线上的顶点外的其它两个顶点的坐标,
//然后将这三个点用直线一一连接起来
poi[0].x=(long)((d-L)*cs-W*sn+point[0].x);
poi[0].y=(long)((d-L)*sn+W*cs+point[0].y);
pDC->MoveTo(point[1]);
pDC->LineTo(poi[0]);
poi[1].x=(long)((d-L)*cs+W*sn+point[0].x);
poi[1].y=(long)((d-L)*sn-W*cs+point[0].y);
pDC->MoveTo(poi[0]);
pDC->LineTo(poi[1]);
pDC->LineTo(point[1]);
}
//如果M=1,则绘制双向箭头,方法与绘制单向箭头类似
if(M==2)
{
if(d<2*L) return;
pDC->MoveTo(point[0]);
pDC->LineTo(point[1]);
poi[0].x=(long)((d-L)*cs-W*sn+point[0].x);
poi[0].y=(long)((d-L)*sn+W*cs+point[0].y);
pDC->LineTo(poi[0]);
poi[1].x=(long)((d-L)*cs+W*sn+point[0].x);
poi[1].y=(long)((d-L)*sn-W*cs+point[0].y);
pDC->LineTo(poi[1]);
pDC->LineTo(point[1]);
pDC->MoveTo(point[0]);
poi[2].x=(long)(L*cs-W*sn+point[0].x);
poi[2].y=(long)(L*sn+W*cs+point[0].y);
pDC->LineTo(poi[2]);
poi[3].x=(long)(L*cs+W*sn+point[0].x);
poi[3].y=(long)(L*sn-W*cs+point[0].y);
pDC->LineTo(poi[3]);
pDC->LineTo(point[0]);
}
}
// 作业3:画两个已知圆的公切线.
// point[0],point[1]:第一,二个圆的圆心;
// point[2].x:第一个圆的半径;
// point[2].y:第二个圆的半径.
void CCgDraw::publine(CDC *pDC, CPoint *point)
{
//绘制两个圆
pDC->Ellipse(point[0].x-point[2].x,point[0].y-point[2].x,point[0].x+point[2].x,point[0].y+point[2].x);
pDC->Ellipse(point[1].x-point[2].y,point[1].y-point[2].y,point[1].x+point[2].y,point[1].y+point[2].y);
//求圆心间距d
double d=sqrt((double)(point[1].x-point[0].x)*(point[1].x-point[0].x)+(double)(point[1].y-point[0].y)*(point[1].y-point[0].y));
//求两圆半径差dr
double dr;
dr=point[2].x-point[2].y;
if((int)d<abs((int)dr)) return;
//如果两圆不相交,则求内外公切线
if(d>=(point[2].x+point[2].y))
{
//求出圆心连线在原坐标系的倾角的cos,sin值cs,sn
double cs=(point[1].x-point[0].x)/d;
double sn=(point[1].y-point[0].y)/d;
POINT poi[8];
POINT p[8];
/*以圆心连线为x轴,point1为原点建立坐标系,x轴的方向为由point1到point2的方向,
然后进行下面的操作:*/
//求出通过外公切线切点的半径与圆心连线的夹角的cos,sin值cst,snt
double snt=sqrt(d*d-dr*dr)/d;
double cst=dr/d;
///////////////////////////////////////////
//求出在新的坐标系下外公切线与圆的切点的坐标
poi[0].x=(long)(point[2].x*cst);
poi[0].y=(long)(point[2].x*snt);
poi[1].x=(long)(point[2].y*cst+d);
poi[1].y=(long)(point[2].y*snt);
poi[2].x=poi[0].x;
poi[2].y=0-poi[0].y;
poi[3].x=poi[1].x;
poi[3].y=0-poi[1].y;
//求出通过内公切线切点的半径与圆心连线的夹角的cos,sin值cst1,snt1
double snt1=sqrt(d*d-(point[2].x+point[2].y)*(point[2].x+point[2].y))/d;
double cst1=(point[2].x+point[2].y)/d;
///////////////////////////////////////////
//求出在新的坐标系下内公切线与圆的切点的坐标
poi[4].x=(long)(point[2].x*cst1);
poi[4].y=(long)(point[2].x*snt1);
poi[5].x=(long)(d-point[2].y*cst1);
poi[5].y=(long)(0-point[2].y*snt1);
poi[6].x=poi[4].x;
poi[6].y=0-poi[4].y;
poi[7].x=poi[5].x;
poi[7].y=0-poi[5].y;
int i;
//通过几何变换将切点在新的坐标系下的坐标变换到原坐标系
for(i=0;i<8;i++)
{
p[i].x=(long)(poi[i].x*cs-poi[i].y*sn+point[0].x);
p[i].y=(long)(poi[i].x*sn+poi[i].y*cs+point[0].y);
}
//绘制切线
pDC->MoveTo(p[0]);
pDC->LineTo(p[1]);
pDC->MoveTo(p[2]);
pDC->LineTo(p[3]);
pDC->MoveTo(p[4]);
pDC->LineTo(p[5]);
pDC->MoveTo(p[6]);
pDC->LineTo(p[7]);
}
//如果两圆相交,则只求外公切线,方法与前面类似
if(dr<(point[2].x+point[2].y))
{
double cs=(point[1].x-point[0].x)/d;
double sn=(point[1].y-point[0].y)/d;
POINT poi[4];
POINT p[4];
double snt=sqrt(d*d-dr*dr)/d;
double cst=dr/d;
poi[0].x=(long)(point[2].x*cst);
poi[0].y=(long)(point[2].x*snt);
poi[1].x=(long)(point[2].y*cst+d);
poi[1].y=(long)(point[2].y*snt);
poi[2].x=poi[0].x;
poi[2].y=0-poi[0].y;
poi[3].x=poi[1].x;
poi[3].y=0-poi[1].y;
int i;
for(i=0;i<4;i++)
{
p[i].x=(long)(poi[i].x*cs-poi[i].y*sn+point[0].x);
p[i].y=(long)(poi[i].x*sn+poi[i].y*cs+point[0].y);
}
pDC->MoveTo(p[0]);
pDC->LineTo(p[1]);
pDC->MoveTo(p[2]);
pDC->LineTo(p[3]);
}
}
// 作业4:画三次Bezier曲线.
// num:型值点数
// point[0] ~ point[num-1]:型值点坐标.
void CCgDraw::bezier(CDC *pDC, int num, CPoint *point)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -