1000分相送!!!谁能写一个在windows中画弧的函数,可能画出任意大小的圆弧,比如R=100000等,速度要快,比如画几千个弧也要快速的Paint.最好用VC++,其它语言也可以

解决方案 »

  1.   

    一千分太多了吧,csdn让你一次给别人这么多吗? 还有就是你有这么多吗? 
    先检查一下你的信用....
    kidding...
      

  2.   

    Arc不够快吗????你可以先Arc到一个MemoryDC里面吗
    不过你总得给定些什么条件吧,和Arc一样得参数?BOOL Arc(
      HDC hdc,         // handle to device context
      int nLeftRect,   // x-coord of rectangle's upper-left corner
      int nTopRect,    // y-coord of rectangle's upper-left corner
      int nRightRect,  // x-coord of rectangle's lower-right corner
      int nBottomRect, // y-coord of rectangle's lower-right corner
      int nXStartArc,  // x-coord of first radial ending point
      int nYStartArc,  // y-coord of first radial ending point
      int nXEndArc,    // x-coord of second radial ending point
      int nYEndArc     // y-coord of second radial ending point
    );
      

  3.   

    反正我有1190分,怎么给我不大清楚,好象“可用分捐赠”可以办到,分几次给应该可以吧,画弧的参数当然是圆心、半径,起终点标或角度。不够不是我小看大家,这个问题应该不大可能办到,属于商业机密吧,目前我看到的只有AutoCad可以办到。
      

  4.   

    你试试用ARC画很大的圆弧看看,应该看不到了,我只的是看其中的一段圆弧,如果中心放在屏幕中间,整个圆弧当然都不见了,有好些人笨啊,我真是没办法
      

  5.   

    仔细说一下吧,写这个函数的目的是要象AutoCad那样画圆,可以放大和缩小,没有学过《计算机图形学》的不要试着拿分吧!
      

  6.   

    你只有5分了
    BOOM...好大的牛皮爆了
      

  7.   

    三个月,太久了一点,不过为了得到,我等,不过你应该给的大概的地方,比如XX省XX市,最好给过EMil吧!最最重要的,要和AutoCad一样效果,重画速度要快,是矢量图形,可不是小画笔画出来的那种.
      

  8.   

    不好意思,是我弄错了,可用分是可以送的,sorry
      

  9.   

    如果半径太大那么屏幕中能看到的应该和直线效果差不多了用两个点或者三个点的折线代替也看不出来,这样效率也没有多少损失嘛!
    const long width=800,height=600;//屏幕窗口的高度和宽度,最好设置的大一些//求出圆和矩形(0,0,widht,height)的交点。两个凸曲线的交点最多只有2个
    int intersect(CPoint center,long r,CPoint pt[2]);void stand(long&x,long&y,long r)
    {
       double t = r/sqrt((double)x*x+(double)y*y);
       x = x*t; y = y*t;
    }void Arc(CPoint center,long r)
    {
       if(r<10000)
        //调用API函数并返回
       CPoint pt[2];
       if(intersect(center,r,pt)!=2)
           return;//看不见
       
       //如果2点直线能满足视觉要求画直线OK   //中间插1个点
       CPoint mid = (pt[0]+pt[1])/2-center;
       stand(mid.x,min.y,r);
       //画三点折线应该够了
       …………
       return;   //不怕速度慢可以多插几个点
       …………
       return;
    }
      

  10.   

    ARC画很大的圆弧看看,应该看不到了???不懂,xy不可以是负的? 你换过坐标没有?
      

  11.   

    To wxyhzzp(小王) ,
    你只要看过图形学的书就应该会了,不要过分看重这个
    DrawArc函数就是你要的需求#include <windows.h>
    #include <math.h>
    #include "resource.h"
    /*
    Ellipse:
    1)-1<dy/dx<0 -> 0<b^2*x/(a^2*y)<1 -> b^2*x<a^2*y
    可以看出y的减少率没有x增长率高,我们应该增加x来看y的增长,于是排除(x,y-1)的可能。
    如果F(x,y)<=0,对于下一个点我们应该尽量向外推,因此
    x(i+1)=x(i)+1,y(i+1)=y(i),dF=2*b^2*x+b^2
    如果F(x,y)>0,对于下一个点我们应该尽量向内推,因此
    x(i+1)=x(i)+1,y(i+1)=y(i)-1,dF=2*b^2*x+b^2-2*a^2*y+a^2
    2)dy/dx>=-1 -> b^2*x>=a^2*y
    可以看出y的减少率比x增长率高,我们应该减少y来看x的增长,于是排除(x+1,y)的可能。
    如果F(x,y)<=0,对于下一个点我们应该尽量向外推,因此
    x(i+1)=x(i)+1,y(i+1)=y(i)-1,dF=2*b^2*x+b^2-2*a^2*y+a^2
    如果F(x,y)>0,对于下一个点我们应该尽量向内推,因此
    x(i+1)=x(i),y(i+1)=y(i)-1,dF=-2*a^2*y+a^2
    */#define G(x,y) b*b*x*x+a*a*y*y-a*a*b*bvoid DrawPixelPart(HDC hdc,int x0,int y0,int x,int y,int part,COLORREF color)
    {
    switch(part)
    {
    case 0:
    SetPixel(hdc,x0-x,y0-y,color);break;
    case 1:
    SetPixel(hdc,x0+x,y0-y,color);break;
    case 2:
    SetPixel(hdc,x0+x,y0+y,color);break;
    case 3:
    SetPixel(hdc,x0-x,y0+y,color);break;
    default:
    break;
    }
    }
    #define PI 3.14159
    void DrawArcPart(HDC hdc,int x0,int y0,int a,int b,int arc_start,int arc_end,int part,COLORREF color)
    {
    int F,x,y,B=b*b,A=a*a,Bx,Ay,xend,yend;
    x=((double)a)*sin(arc_start*PI/180)+0.5;y=((double)b)*cos(arc_start*PI/180)+0.5;
    xend=((double)a)*sin(arc_end*PI/180)+0.5;yend=((double)b)*cos(arc_end*PI/180)+0.5;
    xend=max(xend,x);yend=min(yend,y);
    Bx=B*x;Ay=A*y;
    F=G(x,y);
    while(Bx<Ay&&x<=xend&&y>=yend)
    {
    DrawPixelPart(hdc,x0,y0,x,y,part,color);
    if(F>0)
    {
    x++;y--;F+=2*Bx+B-2*Ay+A;Bx+=B;Ay-=A;
    }
    else
    {
    x++;F+=2*Bx+B;Bx=B*x;Bx+=B;
    }
    }
    if(Bx>=Ay)
    {
    while(x<=xend&&y>=yend)
    {
    DrawPixelPart(hdc,x0,y0,x,y,part,color);
    if(F>0)
    {
    y--;F+=A-2*Ay;Ay-=A; 
    }
    else
    {
    x++;y--;F+=2*Bx+B-2*Ay+A;Bx+=B;Ay-=A;
    }


    }#define DrawPart(arc_start,arc_end,part) DrawArcPart(hdc,x0,y0,a,b,arc_start,arc_end,part,color)//用Bresenham算法生成的椭圆弧线,(x0,y0)为圆心,a为x截距,b为y截距,arc_start和arc_end使用角度表示,从-x旋转分别是角度开始/结束,color是颜色
    void DrawArc(HDC hdc,int x0,int y0,int a,int b,int arc_start,int arc_end,COLORREF color)
    {
    int i,part_start,part_end;
    if(arc_start>arc_end)//保证arc_end>arc_start
    {
    i=arc_start;
    arc_start=arc_end;
    arc_end=i;
    }
    if(arc_end-arc_start>=360)//两个角差别大于360,就是全画
    {
    DrawPart(0,90,0); 
    DrawPart(0,90,1);
    DrawPart(0,90,2);
    DrawPart(0,90,3); 
    return;
    }
    arc_start%=360;arc_end%=360;
    part_start=arc_start/90;part_end=arc_end/90;
    if(arc_start>arc_end)//后接式

    if(part_start%2)//偶数象限
    DrawPart(arc_start%90,90,part_start);
    else
    DrawPart(90-arc_start%90,90,part_start); 
    for(i=part_start+1;i<4;i++)
    DrawPart(0,90,i); if(part_end%2)//偶数象限
    DrawPart(0,arc_end%90,part_end);
    else
    DrawPart(90-arc_end%90,90,part_end);for(i=0;i<part_end;i++)
    DrawPart(0,90,i);
    }
    else//前置
    {
    if(part_end!=part_start)//不在一个象限
    {
    if(part_start%2)//偶数象限
    DrawPart(arc_start%90,90,part_start); 
    else
    DrawPart(0,90-arc_start%90,part_start);
    if(part_end%2)//偶数象限
    DrawPart(0,arc_end%90,part_end);
    else
    DrawPart(90-arc_end%90,90,part_end); for(i=part_start+1;i<part_end;i++)
    DrawPart(0,90,i);
    }
    else
    DrawPart(arc_start%90,arc_end%90,part_start);
    }
    }
    INT_PTR CALLBACK DialogProc(
    HWND hwndDlg, // handle to dialog box
    UINT uMsg, // message
    WPARAM wParam, // first message parameter
    LPARAM lParam // second message parameter
    )
    {
    HANDLE hdc;
    PAINTSTRUCT ps;switch(uMsg)
    {
    case WM_PAINT:
    hdc=BeginPaint(hwndDlg,&ps);
    DrawArc(hdc,100,50,70,40,0,150,RGB(255,0,0));EndPaint(hwndDlg,&ps);
    return TRUE;
    case WM_COMMAND:
    switch( LOWORD(wParam))
    {
    case IDOK:
    case IDCANCEL:
    EndDialog(hwndDlg,0);
    return TRUE;
    }
    break;
    default:
    break;
    }
    return FALSE;
    }int WINAPI WinMain(
    HINSTANCE hInstance, // handle to current instance
    HINSTANCE hPrevInstance, // handle to previous instance
    LPSTR lpCmdLine, // command line
    int nCmdShow // show state
    )
    {
    DialogBox(hInstance,MAKEINTRESOURCE (IDD_DIALOG1),NULL,DialogProc);}
      

  12.   

    一个画圆的程序,你自己改一下吧
    void circleMidpoint(int xCenter,int yCenter,int radius,HDC dc)
    {
    int x = 0;
    int y = radius;
    int p=1-radius;
    while(x<y)
    {
    x++;
    if(p<0)
    {
    p+=2*x+1;
    }
    else
    {
    y--;
    p+=2*(x-y)+1;
    }
    SetPixel(dc,xCenter+x,yCenter+y,RGB(255,0,0));
    SetPixel(dc,xCenter-x,yCenter+y,RGB(255,0,0));
    SetPixel(dc,xCenter+x,yCenter-y,RGB(255,0,0));
    SetPixel(dc,xCenter-x,yCenter-y,RGB(255,0,0)); SetPixel(dc,xCenter+y,yCenter+x,RGB(255,0,0));
    SetPixel(dc,xCenter-y,yCenter+x,RGB(255,0,0));
    SetPixel(dc,xCenter+y,yCenter-x,RGB(255,0,0));
    SetPixel(dc,xCenter-y,yCenter-x,RGB(255,0,0));
    }
    }
      

  13.   

    congling你好,因我有事,很久没有上网了,前几天看过你的答复,回去试了一下,发现有问题,
    用以下参数调用DrawArc,后所画的圆有问题,
    DrawArc(hdc,1000,1000,1800,1800,0,360,RGB(255,0,0));
      

  14.   

    如果r比较大的话r》10000,最好先裁剪,呵呵,否则,如果在项素级别使用gdi函数的话,再快的机器画500次,屏幕也有查不多5秒的等待。如果裁剪恰当的话,获取的性能提高是非常明显的,而损失的性能几乎为0,因为机器做裁剪(主要是乘除法)绝对比gdi画点来的要快的多。在gis系统中,我大量的应用了这样的算法,效果非常的好,支持9x到nt系统。
    当然,在nt机器上,直接使用arc是可以支持到long的大小的半径,而且使用dc的clip,也支持的很好,根本不需要使用所谓的图形学算法。
      

  15.   

    可以把要画的弧的各种参数保存在内存中,然后计算出相应的弧的点的位置,windows窗口中化得最快的是是直线,因此把弧上点的取值取稀一点。然后把相应的点用直线拟合起来就可以达到较快的画图速度了
      

  16.   

    唉,你们光说没有用啊,试一试才知道,以上的回答,我都知道,可你们画一下试一试.zhizhi朋友,你把你的程序给我看看,我来测一下有没有问题,比如只给这一个函数,我不要全部,可能你写的是商用软件
      

  17.   

    既然只需要一个函数,那就以arc为例子了。
    p1,p2为计算的点,r为半径。p为中心。
    ::Arc(hDC,p.x-r,p.y-r,p.x+r,p.y+r,p2.x,p2.y,p1.x,p1.y);
    当r 》 32768在nt下,这个函数是成功的,但9x可能不行。只是说可能,不是觉得,可能的意思是说虽然做错了,但你看不出来;不能是说它可能在屏幕上画了条任意的线。
      

  18.   

    这个函数必须自已写,API是不行的,zhizhi朋友
      

  19.   

    这个问题其实不难,
    当然API是不行的
    自己 构造出 折线进行模拟就可以了。
    我有 程序,但不能给你
    因为是 公司的,保密
      

  20.   

    pampa(pampa)朋友,虽然看不到程序,但我猜想,效果未必很好,因为目前为止,我看到只有AutoCAD做得到,连OpenCASCADE都做不到,下面这断话是一位朋友给我的,你看看吧,我下载了,150MB,可是画圆也不行。北航海尔也做出来了,不过效果差太远了如果要做类似于AutoCAD的程序,从最底层写每一行代码工作量和难度都是很大的。
    编写CAD软件应该采用现成的内核,比如AutoCAD的内核是ACIS,UG和SolidWorks的内核
    是parasolid,还有北航海尔的CAXA的内核也是parasolid。
    所谓内核实际上就是一个类库,里面定义了图形数据的存储格式以及大量的图形算法。
    采用CAD内核,也许只需要一两行代码就能解决你所提到的问题。
    但是ACIS和parasolid都是需要购买的,D版市场上也未曾出现过。
    Marta DATAVISION公司的CAD内核OpenCASCADE是开放源代码的,
    你可以去http://www.opencascade.com看看。
    采用OpenCASCADE,不要说二维绘图软件,做三维CAD软件也是有可能的。
      

  21.   

    pampa(pampa)朋友,你仔细调试一下那断代码吧,或者把它和AutoCAD比较一上,看看是不是很完美
      

  22.   

    我没有 进行过与 AutoCAD的对比测试
    但进行过 与 Microstation的测试。
    精度上 绝对不差于 Microstation。感觉比较麻烦,但并没有什么特别高深的东西
    会计算机图形学 就可以高定
      

  23.   

    你怎么像天龙八部里面神秘老僧A呀,啥也不做就能笑傲江湖.既然是公司要做,要求你们公司向AUTOCAD买技术呀,既然是你自己要做,干做到这也没办法呀,如果为了这个等几年,人生有几个几年呀.
    赶紧去吧,看几页书也比在这闲聊强.别吊死在一棵树上了.没见过一个公司为了一个函数等几年的.
      

  24.   

    想不到这个贴字还没有结,
    to wxyhzzp(小王):
      其实你的问题是截图问题,如果要画如此大的园必须作截图优化,就是算出图在目标矩阵中的弧线(可能分割多弧)的开始和结束位置。然后再画图。其实半径4000以上的弧在各个象限的截图仅仅是1度的大小,但是如果不优化,则需要造成大量运算。
      

  25.   

    我没有测试过Arc函数,不知道是否如楼主所说的速度慢,现在提出另一设想:
    将Arc确定的椭圆转化为Bezier(这方面已有文章介绍),然后根据Bezier细分的方法将其细分到比窗口矩形略大即可(可把不需要的部分舍去只细分与窗口相交的部分),这时可用PolyBezier来画。但实在没想出来Arc函数为何会如此之慢
    因椭圆可分为4段Bezier,故可先省去3/4,剩下的部分水平和垂直长度仅为100000,细分10次后即可使长度在窗口范围内了,原理如下:
    100000第一次细分后长度为50000,舍去无用的一半,进行第二次细分,如此下去细分10次后长度仅为1000000/(2^10)大约为100,这时画起来应该很快。上述方法未经测试,但根据本人做过的更复杂的程序来看,这个速度应该通达到你的要求,除非你不但不优化代码反而将其“劣化”,这就不关我的事了,呵呵。
      

  26.   

    我先抛砖好了:
    高效的画象素函数,可以用汇编直接写。以前是没有DirectDraw的。
    大家都想到了,可以把不可见部分跳掉。而且还可以想办法直接写显存。
      

  27.   

    还有算法方面,象逐点计算可视区圆弧段上圆周点的坐标这部分,可能有好些可以琢磨的地方,如果是用计算点跟圆心的距离等等未免有点太昂贵了点。
    对此,前边朋友说的用线段近似就是一例解决,实际上CAD画的小圆弧确实是有棱角的,说起来其实也不是它高明的地方。
      

  28.   

    正头脑风暴的时候忽然说不能连发贴,快憋死我了,哈哈
    我接着说:
    这里圆弧用直线段近似有特殊的地方,这些线段并不需要是"任意"斜率的,所以有好多东西可以做得效率高一点.
    比方一个圆用N段直线近似,那这些线段的斜率:
        K=tg(2*pi/n),n=0 to n/2-1;
    对于每一条线段,可以从起点开始,按一定的序列给X,Y增量,就不需要逐点比较判断运算了.(图形学里的直线画法就是需要逐点判断,然后决定X,Y增量)
      

  29.   

    to wxyhzzp(小王),
     如果你真的知道,何必在这里卖弄了,我觉得你更加应该写一片论文出来,这样更能体现你的学识?  诚然一个产品性质的软件要比一个测试性质的软件代码量要大很多,我觉得在论坛中没有必要讨论产品性质的软件,那些东西过于细化了,但是论原理大家都懂。
      
     你要是真的能够做出来,应该把你的程序贴出来。然后对重要部分加以说明。
      

  30.   

    1000个圆弧,半径141421,绘制时间0.25s左右,可以吗?
    当然,纯显示时间约为0
    btw:我没用过AutoCAD
      

  31.   

    不错,现在来了个动手的,不象我光动嘴。不过其实每个细节都值得开帖子的。在达到比较好的水平以后,要想比别人突出一点点都需要有点特别的地方的,书上的东西需要灵活变通的。
    tonyzym(tony):
    请说说你的画圆程序里头有什么独到的地方可以使你比别人快。现在是发散思维讨论方法的时候。最后10条想法里头有2,3条被使用就不错了。
      

  32.   

    我还一点都没优化,就觉得速度可以忍受,要提高肯定还可以。不知道AutoCAD中到底有多快。
      

  33.   

    这个楼主真TNND!有话你就说,没话你就悄悄的吧。我看你以后也不要说什么话了,说了大家也不要理了。到底有什么东西拿出来看看嘛。阴阳怪气哼哼唧唧算什么呀?大家说好多你什么都不说,你就只会唧唧歪歪,难道这是交流?你是偷大家的想法的窃贼!