图形编辑点线联动.docx
- 文档编号:29522102
- 上传时间:2023-07-24
- 格式:DOCX
- 页数:14
- 大小:128.98KB
图形编辑点线联动.docx
《图形编辑点线联动.docx》由会员分享,可在线阅读,更多相关《图形编辑点线联动.docx(14页珍藏版)》请在冰豆网上搜索。
图形编辑点线联动
VisualC++图形编辑“点-线”联动
摘要以统筹图绘制程序的编制为例,详细给出了应用VisualC++开发工具及MFC实现图形编辑中的节点-箭线联动方法。
该方法对于实现GIS应用、标图应用和统筹图应用中的类似功能有较好的参考价值。
关键词节点;箭线;编辑联动
1引言
很多的图形应用如统筹图应用、GIS应用、标图应用中都存在着编辑联动的问题。
所谓编辑联动,是指在对一个图元编辑修改包括位置的变动后,其他图元由于与这个图元有某种关系,而能自动同步被修改。
按图元类型,可将图形联动划分为点-点、点-线、点-面、线-线、线-面、面-面等6种。
文中以统筹图为例,讨论节点-箭线联动编辑问题。
节点与箭线图元的实现以VC自带面向对象图形例程DRAWCLI基础,添加自定义类CDrawNode和CDrawArrow来实现。
依据功能设计,程序的主要工作包括:
(1)基本图元的绘制。
包括绘制节点和箭线。
绘制的节点图形表示为圆心标有编号圆圈;箭线的两侧标注有文字说明,且文字行与箭线保持平行,箭线带有起节点和终节点。
(2)处理图元及相互位置关系。
包括删除操作和移动操作。
删除某一节点,与该节点相连的箭线全部删除,且调整编号在其后面的节点编号,删除箭线不影响节点。
移动节点时,与之相连的箭线相应移动,其关键是准确计算箭线的位置。
2基本图元及联动
2.1基本图元实现
设在VC++6.0的环境下已建立了工程Draw.dsp。
节点类和箭线类都是以CDrawObj为基类派生。
在建立这两个类之前,需要添加以下全局变量
enumDrawShape{…,circle,arrow,…};//图元类型以及相应的工具circleTool和arrowTool(arrow)、arrowlineTool
2.1.1节点类CDrawNode的设计
classCDrawNode:
publicCDrawObj
{
public:
CDrawNode(constCRect&position,intRadius);
voidSetCircleIndex(intIndex){m_nIndex=Index};设置节点编号
virtualintGetObjIndex(){returnm_nIndex};//获取编号
public:
intm_Radius;//节点半径
intm_CentreX,m_CentreY;//圆心
//在圆中心写上编号,要考虑编号的位数情况
virtualvoidDraw(CDC*pDC,CDrawView*pView);
protected:
intm_nIndex;//编号
CDrawNode*m_pDrawObj;
friendclassCCircleTool;
};
绘制节点的工具CCircleTool在鼠标左键按下OnLButtonDown的消息处理函数中,实际分配内存,产生一个节点对象。
2.1.2箭线类CDrawArrow的设计
classCDrawArrow:
publicCDrawObj
{
public:
CDrawRect(constCRect&position);
voidSetProjectName(CStringname){m_ProjectName=name;};
voidSetProjectTime(inttime){m_ProjectTime=time;};
CStringGetProjectName(){returnm_ProjectName;}
voidSetProjectTime(inttime){returnm_ProjectTime;}
boolm_bForeConnect;//箭线始节点标志
boolm_bBackConnect;//箭线终节点标志
intm_ForeConnect;//箭线连接的始节点序号
intm_BackConnect;//箭线连接的终节点序号
virtualintGetObjIndex(){returno};
//绘制时,计算平行于箭线的说明文字的角度,位置,项目名称总在线的上方
virtualvoidDraw(CDC*pDC,CDrawView*pView);
enumArrowType{none,pureArrow,openArrow,stealthArrow,diamondArrow,ovalArrow};
enumShape{rectangle,roundRectangle,ellipse,line,arrow};
protected:
CStringm_ProjectName;//项目名称
intm_ProjectTime;//时间
Shapem_nShape;
ArrowTypem_lArrow,m_rArrow;//forarrowonly
intm_lArrowSize,m_rArrowSize;//forarrowonly
private:
voidDrawArrow(ArrowTypearrowType,POINTp1,POINTp2,intarrowSize,CDC*,int,int,int,CBrush*);
friendclassCArrowTool;
};
绘制箭线的工具CArrowTool在OnLButtonDown中实际生成箭线对象,并记录箭线所连的开始节点,箭线的终节点确定在后面说明。
2.2图元联动操作
2.2.1删除节点及箭线
voidCDrawView:
:
OnEditClear()
{
CDrawDoc*pDoc=(CDrawDoc*)GetDocument();
POSITIONpos=m_selection.GetHeadPosition();
while(pos!
=NULL)
{
CDrawObj*pObj=m_selection.GetNext(pos);
GetDocument()->Remove(pObj);//删除节点
CDrawNode*pDrawCircle=(CDrawNode*)pObj;
nIndex=pDrawCircle->GetObjIndex();//获取节点编号,若不是节点对象,返回0
if(nIndex)
{
pDoc->m_nIndex=nIndex;
pos=GetDocument()->m_objects.GetHeadPosition();
inti=0;
intnum=pDoc->m_objects.GetCount();
m_num=pDoc->m_nIndex;
while(i {//序号位于被删除节点之后的所有节点序号减1 CDrawNode*pDrawCircle=(CDrawNode*)pDoc->m_objects.GetNext(pos); if(pDrawCircle->GetObjIndex()>m_num) { pDrawCircle->SetCircleIndex(m_num); m_num++; } i++; } pos=pDoc->m_objects.GetHeadPosition(); if(pos! =NULL) { i=0; num=pDoc->m_objects.GetCount(); while(i {//删除与接点相连的所有箭线 CDrawRect*pDrawRect=(CDrawRect*)pDoc->m_objects.GetNext(pos); if(pDrawRect! =NULL) { if(nIndex==pDrawRect->m_ForeConnect) { pDoc->Remove(pDrawRect); pDrawRect->Remove(); } if(nIndex==pDrawRect->m_BackConnect) { pDoc->Remove(pDrawRect); pDrawRect->Remove(); } if(nIndex { pDrawRect->m_ForeConnect--; } if(nIndex { pDrawRect->m_BackConnect--; } } i++; } } Invalidate(); pDoc->m_nIndex=m_num; } pObj->Remove(); } m_selection.RemoveAll(); UINTnFlags; OnLButtonDown(nFlags,CPoint(0,0)); OnLButtonUp(nFlags,CPoint(0,0)); } 2.2.2用鼠标移动某一节点时,同步移动与其相连接的箭线 voidCSelectTool: : OnMouseMove(CDrawView*pView,UINTnFlags,constCPoint&point) { if(pView->GetCapture()! =pView) { … CPointlocal=point; intBackConnect; pView->ClientToDoc(local); POSITIONpos; if(c_drawShape==arrow) //判断鼠标移动绘制箭线过程中是否与某一节点相连 //此时函数是CRectTool: : OnMouseMove()调用selectTool.OnMouseMove();而跳到这里 { CRectcirclerect; CDrawNode*pForeCircle; CDrawNode*pBackCircle; pos=pView->GetDocument()->m_objects.GetHeadPosition(); if(pos! =NULL) { inti=0; intnum=pView->GetDocument()->m_objects.GetCount(); while(i { CDrawNode*pDrawCircle=(CDrawNode*)pView->GetDocument()->m_objects.GetNext(pos); if(pDrawCircle! =NULL) { intindex=pDrawCircle->GetObjIndex(); if(index) {//判断 circlerect=pDrawCircle->m_position; pView->DocToClient(circlerect); if(circlerect.PtInRect(point)) { local=pDrawCircle->GetHandle(8); BackConnect=pDrawCircle->GetObjIndex(); } }}i++;}}} CPointdelta=(CPoint)(local-lastPoint); pos=pView->m_selection.GetHeadPosition(); while(pos! =NULL) { CDrawObj*pObj=pView->m_selection.GetNext(pos); CRectposition=pObj->m_position; if(c_drawShape==arrow) {//记录终节点 pObj->m_BackConnect=BackConnect; pObj->m_bBackConnect=true; } //以下实现移动节点,使所有的箭线跟随节点同步移动 if(selectMode==move) { if(pView->m_selection.GetCount()==1) { CDrawNode*pDrawCircle=(CDrawNode*)pObj; intIndex=pDrawCircle->GetObjIndex(); if(Index)//移动节点 { POSITIONRectpos=pView->GetDocument()->m_objects.GetHeadPosition(); if(Rectpos! =NULL) { inti=0; intnum=pView->GetDocument()->m_objects.GetCount(); while(i {//所有与之相连箭线同步移动 CDrawRect*pDrawObj=(CDrawRect*)pView->GetDocument()->m_objects.GetNext(Rectpos); if(pDrawObj! =NULL) { if(Index==pDrawObj->m_ForeConnect) {//节点是箭线始节点 CRectdeltarect=pDrawObj->m_position; deltarect.BottomRight()+=delta; intlength=deltarect.top-deltarect.bottom; intwidth=deltarect.left-deltarect.right; //节点移动,箭线与节点的连接点改变,计算连接点位置 if(abs(length) deltarect.BottomRight()=pDrawCircle->GetHandle(8); if(abs(length) deltarect.BottomRight()=pDrawCircle->GetHandle(4); if((abs(length)>abs(width)&&width>0&&length<0)|| (abs(length)>abs(width)&&width<0&&length<0)) deltarect.BottomRight()=pDrawCircle->GetHandle (2); if((abs(length)>abs(width)&&length>0&&width>0)|| (abs(length)>abs(width)&&length>0&&width<0)) deltarect.BottomRight()=pDrawCircle->GetHandle(6); intnIndex=pDrawObj->m_BackConnect; POSITIONcirclepos=pView->GetDocument()->m_objects.GetHeadPosition(); if(circlepos! =NULL) { inti=0; intnum=pView->GetDocument()->m_objects.GetCount(); while(i { CDrawNode*pDrawNode=(CDrawNode*)pView->GetDocument()->m_objects.GetNext(circlepos); if(pDrawNode! =NULL) { if(nIndex==pDrawNode->GetObjIndex()) {//计算箭线的新位置 if(abs(length) deltarect.TopLeft()=pDrawNode->GetHandle(4); if(abs(length) deltarect.TopLeft()=pDrawNode->GetHandle(8); if((abs(length)>abs(width)&&width>0&&length<0)||(abs(length)>abs(width)&&width<0&&length<0)) deltarect.TopLeft()=pDrawNode->GetHandle(6); if((abs(length)>abs(width)&&length>0&&width>0)|| (abs(length)>abs(width)&&length>0&&width<0)) deltarect.TopLeft()=pDrawNode->GetHandle (2);}}i++;}}} pDrawObj->MoveTo(deltarect,pView); } if(Index==pDrawObj->m_BackConnect) {//节点是箭线终节点 CRectdeltarect=pDrawObj->m_position; deltarect.TopLeft()+=delta; intlength=deltarect.top-deltarect.bottom; intwidth=deltarect.left-deltarect.right; if(abs(length) deltarect.TopLeft()=pDrawCircle->GetHandle(4); if(abs(length) deltarect.TopLeft()=pDrawCircle->GetHandle(8); if((abs(length)>abs(width)&&width>0&&length<0)||(abs(length)>abs(width)&&width<0&&length<0)) deltarect.TopLeft()=pDrawCircle->GetHandle(6); if((abs(length)>abs(width)&&length>0&&width>0)|| (abs(length)>abs(width)&&length>0&&width<0)) deltarect.TopLeft()=pDrawCircle->GetHandle (2); intnIndex=pDrawObj->m_ForeConnect; POSITIONcirclepos=pView->GetDocument()->m_objects.GetHeadPosition(); if(pos! =NULL){ inti=0; intnum=pView->GetDocument()->m_objects.GetCount(); while(i {CDrawNode*pDrawNode=(CDrawNode*)pView->GetDocument()->m_objects.GetNext(circlepos); if(pDrawNode! =NULL) { if(nIndex==pDrawNode->GetObjIndex()) { if(abs(length) deltarect.BottomRight()=pDrawNode->GetHandle(8); if(abs(length) deltarect.BottomRight()=pDrawNode->GetHandle(4); if((abs(length)>abs(width)&&width>0&&length<0)|| (abs(length)>abs(width)&&width<0&&length<0)) deltarect.BottomRight()=pDrawNode->GetHandle (2); if((abs(length)>abs(width)&&length>0&&width>0)|| (abs(length)>abs(width)&&length>0&&width<0)) deltarect.BottomRight()=pDrawNode->GetHandle(6);}}i++;}}} pDrawObj->MoveTo(deltarect,pView);}}i++;}}}} position+=delta; pObj->MoveTo(position,pView); } elseif(nDragHandle! =0)pObj->MoveHandleTo(nDragHandle,local,pView); } lastPoint=local; if(selectMode==size&&c_drawShape==selection) { c_last=point; SetCursor(pView->m_selection.GetHead()->GetHandleCursor(nDragHandle)); return;//bypassCDrawTool } c_last=point; if(c_drawShape==selection) CDrawTool: : OnMouseMove(pView,nFlags,point); } 3结语 至此,基本上
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 图形 编辑 点线 联动