一个不规则图形如何表示?

摩尔信使MThings
企业官方账号
2011-07-05 05:34:26
譬如圆形,多边形,
...全文
488 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
pathuang68 2011-07-06
  • 打赏
  • 举报
回复
多边形存储的应该就是有序的点的坐标就可以了。
至善者善之敌 2011-07-05
  • 打赏
  • 举报
回复
[Quote=引用楼主 zhoutanliang 的回复:]
譬如圆形,多边形,
[/Quote]


多边形是N条直线的集合而已

圆形或椭圆形也可以理解为N条直线的集合
Alexen 2011-07-05
  • 打赏
  • 举报
回复
程序中的序号忘记删掉了 里面单行的数字是页码……
或者还有个更简单的方法 直接用自带的函数 Ellipse(a,b,c,d) 就可以画出一个圆形 界线坐标是(a,b) (c,d)
Alexen 2011-07-05
  • 打赏
  • 举报
回复
在计算机图形学这门课程中有详细的介绍 主要是对于各种图形 先要考虑各种情况确定算法
以下给你介绍一个 bresenham圆的画法 算法
1、理论分析
根据该算法,对于圆心为(0,0),半径为R 的圆,绘图的起点为(0,R),d 3 2R 0 = - ,
递推公式为1 1 = + i+ i x x ,当> 0 i d 时, 1 1 = - i+ i y y , 4( ) 10 1 = + - + i+ i i i d d x y ;当£ 0 i d
时, i i y = y +1 , 4 6 1 = + + i+ i i d d x ;结束条件为i i x > y 。根据对称条件,找到一个圆上
点(x,y),可以同时确定其他7个点(x,-y),(-x,y),(-x,-y),(y, x),(y, -x),(-y, x),(-y,
-x)。对于圆心在任意点(x0,y0)的圆,可以使用上述方法,只是在绘点时,将(x,y)等8
个点绘制成(x+x0,y+y0)。实现程序如下:
x=0;y=r;d=3-2*r;
while(x<y||x==y)
{
SetPixel(x+x0,y+y0,RGB(255,0,0));
SetPixel(-x+x0,y+y0,RGB(255,0,0));
SetPixel(x+x0,-y+y0,RGB(255,0,0));
SetPixel(-x+x0,-y+y0,RGB(255,0,0));
SetPixel(y+x0,x+y0,RGB(255,0,0));
SetPixel(-y+x0,x+y0,RGB(255,0,0));
24
SetPixel(y+x0,-x+y0,RGB(255,0,0));
SetPixel(-y+x0,-x+y0,RGB(255,0,0));
x=x+1;
If(d<0||d==0)
{
d=d+4*x+6;
}
else
{
y=y-1;d=d+4*(x-y)+10;
}
};
2、编程实现
目前,Bresenham 圆还没有菜单响应函数,因此要从它的菜单响应函数起步。
1)菜单响应函数建立
.打开工程项目,依次点击菜单“查看”、“建立类向导”,出现窗口。在Class Name:
栏中选CMy200032590100View;在Object Ids:栏中选ID_DRAW_BCIRCLE;在
Messages:栏中选COMMAND;点击Add Function 按键,出现函数命名窗口,点击该窗
口中的OK 按键,该函数在200032590100View.cpp 中生成。点击该窗口中的Edit Code
按键查看、编辑该函数。在函数中加入语句如下:
void CMy200032590100View::OnDrawBcircle()
{
// TODO: Add your command handler code here
PressNum=0; MenuID=3;
}
至此,菜单响应函数建立完成。
2)鼠标操作
画圆的鼠标操作设计为:先用鼠标确定圆心,再移动鼠标确定半径。在确定半径时,随
着鼠标的移动,一个圆随着鼠标的移动半径发生变化。因此,鼠标左键函数完成两件事:1、
25
第一次按键确定圆心,2、第二次按键确定圆上一点,然后调用Bresanham 算法完成圆的
绘制。在鼠标左键函数中增加如下语句:
void CMy200032590100View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CMy200032590100Doc *pDoc=GetDocument(); //获得文档类指针
CClientDC ht(this); //定义当前绘图设备
if(MenuID==1) { // DDA 直线
if(PressNum==0){
pDoc->group[PressNum]=point;
PressNum++;
mPointOrign=point;
mPointOld=point; //记录第一点
SetCapture();
}
else if(PressNum==1){ //第二次按键保留第二点,用文档类画线
pDoc->group[PressNum]=point;PressNum=0;//程序画图
pDoc->DDALine(&ht);ReleaseCapture();
}
}
if(MenuID==3) { // Bresenham圆
if(PressNum==0){//第一次按键将第一点保留在mPointOrign
pDoc->group[PressNum]=point;
PressNum++;
mPointOrign=point;
mPointOld=point; //记录第一点
SetCapture();
}
else if(PressNum==1){//第二次按键调用文档类画圆程序画图
PressNum=0;
26
pDoc->BCircle(&ht,mPointOrign,point);ReleaseCapture();
}
}
CView::OnLButtonDown(nFlags, point);
}
鼠标移动函数要在圆心确定后、圆上点确定前,随着鼠标的移动,画出一个大小变化的
示意圆,该示意圆用VC 自身的函数完成。在鼠标移动函数中增加下列语句:
void CMy200032590100View::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
int xx,yy,r;
char p1[20];
CClientDC pDC(this);
OnPrepareDC(&pDC);
pDC.DPtoLP(&point);
pDC.SetROP2(R2_NOT); // 设置异或方式
xx=point.x;
yy=point.y;
sprintf(p1,"%4d",xx); //转化为字符串
m_wndStatusBar.SetPaneText(2,p1,TRUE); //在第2个区域显示x坐标
sprintf(p1,"%4d",yy);
m_wndStatusBar.SetPaneText(3,p1,TRUE); //在第3个区域显示y坐标
if(MenuID==1&&PressNum==1){
if(mPointOld!=point){
pDC.MoveTo(mPointOrign); pDC.LineTo(mPointOld);//擦旧线
pDC.MoveTo(mPointOrign); pDC.LineTo(point);//画新线
mPointOld=point;
}
}
27
if(MenuID==3&&PressNum==1){
pDC.SelectStockObject(NULL_BRUSH);//画空心圆
if(mPointOld!=point){
r=(int)sqrt((mPointOrign.x-mPointOld.x)*(mPointOrign.xmPointOld.
x)+(mPointOrign.y-mPointOld.y)*(mPointOrign.y
-mPointOld.y));
pDC.Ellipse(mPointOrign.x-r,mPointOrign.y-r,mPointOrign.x+r,
mPointOrign.y+r);//擦旧圆
r=(int)sqrt((mPointOrign.x-point.x)*(mPointOrign.x-point.x)
+(mPointOrign.y-point.y)*(mPointOrign.y-point.y));
pDC.Ellipse(mPointOrign.x-r,mPointOrign.y-r,mPointOrign.x+r,
mPointOrign.y+r);//画新圆
mPointOld=point;
}
}
CView::OnMouseMove(nFlags, point);
}
由于程序中使用了VC的“开方”函数sqrt( ),因此要事先对该函数说明。该函数的说明信
息放在系统文件math.h中,只要在加入这个说明文件即可。考虑到该函数还将用在文档类
函数中,把这个加入说明函数的工作,放在文档类与视图类的共同说明文件
200032590100.h 中。打开200032590100.h,加入一行语句如下:
#if !defined(AFX_200032590100_H__8BFDCCC4_B7A9_43F4_B53E_78587315C2
07__INCLUDED_)
#define
AFX_200032590100_H__8BFDCCC4_B7A9_43F4_B53E_78587315C207__INCLUDED
_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#ifndef __AFXWIN_H__
28
#error include 'stdafx.h' before including this file for PCH
#endif
#include "resource.h" // main symbols
#include "math.h"
3)Bresenham 圆绘制函数
在文档类中实现该函数,因此在文档头文件200032590100Doc.h 中说明该函数。打开
文档头文件200032590100Doc.h 增加如下语句:
public:
CPoint group[100];
// Operations
public:
void DDALine(CClientDC *DCPoint);
void BCircle(CClientDC *DCPoint,CPoint p1,CPoint p2);
打开文档文件200032590100Doc.CPP,在最后部分增加函数:
void CMy200032590100Doc::BCircle(CClientDC *DCPoint,CPoint p1,CPoint p2)
{
int r,d,x,y,x0,y0;
DCPoint->SetROP2(R2_COPYPEN); //绘图方法为直接画
r=(int)sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
x=0;y=r;d=3-2*r;x0=p1.x;y0=p1.y;
while(x<y||x==y)
{
DCPoint->SetPixel(x+x0,y+y0,RGB(255,0,0));
DCPoint->SetPixel(-x+x0,y+y0,RGB(255,0,0));
DCPoint->SetPixel(x+x0,-y+y0,RGB(255,0,0));
DCPoint->SetPixel(-x+x0,-y+y0,RGB(255,0,0));
DCPoint->SetPixel(y+x0,x+y0,RGB(255,0,0));
DCPoint->SetPixel(-y+x0,x+y0,RGB(255,0,0));
DCPoint->SetPixel(y+x0,-x+y0,RGB(255,0,0));
DCPoint->SetPixel(-y+x0,-x+y0,RGB(255,0,0));
29
x=x+1;
if(d<0||d==0)
{
d=d+4*x+6;
}
else
{
y=y-1;d=d+4*(x-y)+10;
}
};
}
ryfdizuo 2011-07-05
  • 打赏
  • 举报
回复
[Quote=引用楼主 zhoutanliang 的回复:]
譬如圆形,多边形,
[/Quote]
可以使用一个有序的顶点序列表示。一般逆时针。
有了这个序列,绘制的时候就方便了,对于凸多边形 相邻三个作为三角形顶点绘制即可。
对于凹多边形,则需要先分割成凸多边形、
Ace丶双鱼 2011-07-05
  • 打赏
  • 举报
回复
圆形用圆心和半径就行
多边形保存顶点在一个容器里就好。
mibbadman 2011-07-05
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 mibbadman 的回复:]
用三角形表示咯~
[/Quote]
圆不用 直接 圆心 和 r 就行;
其他的图像给出 图心 和 N个三角形 保存在list就行啦
xiaoxiao880919 2011-07-05
  • 打赏
  • 举报
回复
说的详细点呢。
mibbadman 2011-07-05
  • 打赏
  • 举报
回复
用三角形表示咯~

65,203

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧