用C语言编程画出图形,C语言图形编程(六) -图形程序设计实例:零件图形的绘制...

实例:一个零件图形的绘制

有一个零件图,如下:

ead7439b29180d1309740c4a461f0d9d.png

对图3-1中的零件图形,如何根据它所标注的尺寸,按照适当的顺序有步聚地画出该图形,这首先要分析此零件图形的几何关系,了解构成这个图形各线段的性质,才能顺利地绘出此图形。线段(直线或圆弧)在零件图形中分为三类,即已知线段、中间线段和连接线段。以圆弧为例,按几何原理,已知圆心的两个位置尺寸与半径尺寸便可画出圆。因此图形中,已知这三个尺寸的圆弧称为已知圆弧,画图时应该最先画出。凡已知其中二个尺寸的圆弧称为中间圆弧。凡只已知一个尺寸(一般是圆弧半径)的圆弧称为连接圆弧。中间圆弧和连接圆弧都缺省圆心的位置尺寸,它的几何位置是根据相切的条件来确定的。因此画圆弧的顺序为:先画已知圆弧,再画中间圆弧,最后画连接圆弧。

本零件图形是对称图形,三个小圆均匀分布在圆周中心线上,φ10,φ25,φ50和R10都是已知圆弧,R8为连接圆弧,φ50是已知圆弧的端点和R10已知圆弧的端点与连接圆弧的端点相切,从而构成整个图形。

写出算法:

知道了图形的几何关系后,就是怎样用绘图算式或关系式将图形几何关系表示出来,这也就是所要写出的绘图算法,包括算式或关系式中的变量和参数说明。

现在讨论此零件图形的绘图算法。

1. 建立坐标系

以基准为轴线,原点定在中心。

2. 确定贺半径关系

由于所编程序要绘制一类零件图形(这实际上就是参数化绘图),所以在绘图算法公式中φ25圆(以后称内圆)、φ50圆(外圆)和R10圆(凸圆)的半径设计成参变量,其值由用户输入。

所有圆半径的关系如下:

Ri > 0

R0 > Ri

Rc > 0

Rp = Ri + ( Rc - Ri ) / 5

Rs = Rc / 2

Rj = 4 * Rc / 5

式中Ri为内圆半径,R0为外圆半径,Rc为凸圆半径,Rp为点画圆半径,Rs为三个小圆半径,Rj为连接圆半径。

3. 算出φ10圆圆心

设三个φ10圆圆心位置坐标分别为C1(u1,v1),C2(u2,v2),C3(u3,v3),则由零件图上可得计算它们的值的公式为

右边小圆C1:

u1=[Ri+(R0-Ri)/5]cos(-30o)

v1=[Ri+(Ro-Ri)/5]sin(-30o)

上边小圆C2:

u2=[Ri+(Ro-Ri)/5]cos(90o)

v2=[Ri+(Ro-Ri)/5]sin(90o)

左边小圆C3:

u3=[Ri+(Ro-Ri)/5]cos(210o)

v3=[Ri+(Ro-Ri)/5]sin(210o)

式中Ri,Ro含义同前面。

4. 求连接圆弧圆心

设六个连接圆弧的圆心位置坐标分别为L1(x1,y1),L2(x2,y2),L3(x3,y3),L4(x4,y4),L5(x5,y5),L6(x6,y6),则利用连心线长度与距离公式可列出求这六个连接圆弧圆心坐标的六个方程组,进而分别求解可得到圆心坐标的表达式。

这样,连接圆弧L1的议程组是

(x1)2+(y1)2=(Ro-4/5Rc)2

(x1-u1)2+(y1-v1)2=(9/5Rc)2

记     A=(Ro)2+8Ro*Rc/5+16(Rc)2/25

B=(Ro)2+8Rc*Rc/5-13(Rc)2/5

D1=(u1)2+(v1)2

式中Rc为R10圆的半径,Ro为φ50圆的半径。

则方程组成为

(x1)2+(y1)2=A

2u1*x1+2v1*y1=B+D1

解此方程组,有

D1(y1)2-v1(B+D1)*y1+[(B+D1)/2]2-A(u1)2=0

上式中令

a=D1

b=-v1(B+D1)

c=[(B+D1)/2]2-A(u1)2

便成为

a(y1)2+by1+c=0

再由求根公式即得

b2-4ac=(u1)2[4AD1-(B+D1)2]

方程的根为

v1(B+D1)±(u1)2[4AD1-(B+D1)2]

y1'=  -----------------------------

2D1

将y1'代入原方程组便得另外的根

x1'=±(A-(y1')2)1/2

于是连接圆弧L1的圆心坐标表达式为

v1(B+D1)±(u1)2[4AD1-(B+D1)2]

y1'= -------------------------------

2D1

x1'=±(A-(y1')2)1/2

连接圆弧L2的方程组与上面的一样,因为都是关于同样的条件建立方程组,即利用到右边小圆心的连心距离建立方程组,因此上面的两组解有一组是L2连接圆弧的圆心位置坐标。

同样方法可得连接圆弧L3(L1类同)的方程组为

(x3)2+(y3)2=A

2u2*x3+2v2*y3=B+D2

式中D2=(u2)2+(v2)2     A,B 同上

方程组解即L3(L4类同)连接圆弧的圆心坐标位置为

v2(B+D2)±(u2)2[4AD2-(B+D2)2]

y3'= -------------------------------

2D2

x3'=±(A-(y3')2)1/2

比较一下L1(或L2)与L3(或L4)的方程组就会发现,只需将连接圆弧L3(或L4)的方程组中的小圆圆心坐标换成左边小圆圆心坐标,连接圆弧圆心坐标换成L5(或L6)连接圆弧的圆心位置坐标,常数D2也作相应变化便得到连接圆弧L5(L6类同)的方程组

(x5)2+(y5)2=A

2u3*x3+2v3*y5=B+D3

式中D3=(u3)2+(v3)2     A,B 同上

解该方程组得到L5(L6类同)连接圆弧的圆心坐标为

v3(B+D3)±(u3)2[4AD3-(B+D3)2]

y5'= -------------------------------

2D3

x5'=±(A-(y5')2)1/2

5.计算连接圆弧切点

求连接圆弧切点最简便的方法是用定百分比来求解。由图3-1可知,连接圆民外圆的切点为两圆连心线的定百分比,其定比值为λo=Ri/Ro,连接圆弧与凸圆的切点也是两圆连心线的定百分比,其定比值为λc=Rj/Rc,式中Rj,Ro,Rc是相应的圆半径。这样由定比分点计算公式,便可求得加心线上分点也即连接圆弧切点的坐 。

设连接圆弧L1,L2,L3,L4,L5,L6分别与各凸圆的切点为(cx1,cy1),(cx2,cy2),(cx3,cy3),(cx4,cy4),(cx5,cy5),(cx6,cy6),连接圆弧L1,L2,L3,L4,L5,L6与外圆的切点分别为(ox1,oy1),(ox2,oy2),(ox3,oy3),(ox4,oy4),(ox5,oy5),(ox6,oy6)。

已知三凸圆弧圆心坐标分别为(u1,v1),(u2,v2),(u3,v3),六连接圆弧圆心坐标分别为(x1',y1'),(x2',y2'),(x3',y3'),(x4',y4'),(x5,y5'),和(x6',y6')。

根据定比分点计算公式,可得连接圆弧L1与右边凸圆的切点坐标为

1f12df60ae486144ee0fa3ee433892cb.png

式中 λo=Rj/Ro

λc=Rj/Rc

Rj,Ro,Rc 是相应的圆弧半径

至此,求得了所有连接圆弧切点的坐标

(四)、编写绘图程序

在编写绘图程序前,最好先画出要编写程序的流程框图,然后按照框图内容所描述的计算,用程序语言来实现。

91b544ae75d1f006c07898e96da740f5.png

第一框 输入数据,用下面一个函数实现:

void Enterdata()

{

clrscr();

gotoxy(1,6);

printf("Enter the radius of the circles./n");

gotoxy(1,8);

printf(Enter in_circle radius(>=12.5):/n");

scanf("%f",&Ri);

printf("Enter out_circle radius(>=25.0):/n");

scanf(%f",&Ro);

printf("Enter convex_circle radius(=10.0):/n");

scanf("%f",&Rc);

}

第二框画基准线与圆心线,可由下面的函数完成:

void Base_Center_Line()

{

flost dash_R;

desh_R=(4*Ro+Ri)/5;         // 三个小圆圆心所在的点划圆半径

u1=((4*Ro+Ri)/5)*cos(-30*0.017453);      // 确定三个小圆圆心坐标

v1=((4*Ro+Ri)/5)*sin(-30*0.017453);

u2=0.0;            // ((4*Ro+Ri)/5)*cos(90*0.017453)

v2=((4*Ro+Ri)/5);  // ((4*Ro+Ri)/5)*sin(90*0.017453)

u3=((4*Ro+Ri)/5)*cos(210*0.017453);

v3=((4*Ro+Ri)/5)*sin(210*0.017453);

line(mmaxx-Ro-Rc,mmaxy,mmaxx-(Ro+Rc)/2,mmaxy;    // 画基准线

line(mmaxx-(Ro+Rc)/2+5,mmaxy,mmaxx-(Ro+Rc)/2+5,mmaxy);

line(mmaxx-(Ro+Rc)/2+10,mmaxy,mmaxx-(Ro+Rc)/2,mmaxy);

line(mmaxx+(Ro+Rc)/2+5,mmaxy,mmaxx-(Ro+Rc)/2+5,mmaxy);

line(mmaxx+(Ro+Rc)/2+10,mmaxy,mmaxx+Ro+Rc,mmaxy);

line(mmaxx,mmaxy+Ro+Rc,mmaxx,mmaxy+(Ro+Rc)/2+10);

line(mmaxx,mmaxy+(Ro+Rc)/2+5,mmaxx,mmaxy+(Ro+Rc)/2+5);

line(mmaxx,mmaxy+(Ro+Rc)/2,mmaxx,mmaxy-(Ro+Rc)/2+10);

line(mmaxx,mmaxy-(Ro+Rc)/2+5,mmaxx,mmaxy-(Ro+Rc)/2+5);

line(mmaxx,mmaxy-(Ro+Rc)/2,mmaxx,mmaxy-Ro-Rc);

arc(mmaxx,mmaxy,0,25,desh_R);            // 画点划圆

arc(mmaxx,mmaxy,28,29,desh_R);           // 画点划圆

arc(mmaxx,mmaxy,32,110,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,113,114,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,117,185,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,187,188,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,191,255,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,258,259,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,262,300,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,303,304,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,307,360,desh_R);         // 画点划圆

}

第三个框 画已知圆的程序

void Known_Circle()

{

circle(mmaxx,mmaxy,Ri);

circle(mmaxx+u1,mmaxy-v1,Rc/2);

circle(mmaxx+u2,mmaxy-v2,Rc/2);

circle(mmaxx+u3,mmaxy-v3,Rc/2);

}

第四个框计算连接圆弧圆心,其程序也可作为一个函数如下:

void Link_Arc_Center()

{

float A,B,D1,D2,D3,B2_4AC1,B2_4AC2,B2_4AC3;

float BD1,BD2,BD3,Root1,Root2,Root3,temp;

A=Ro*Ro+8*Ro*Rc/5+16*Rc*Rc/25;

B=Ro*Ro+8*Ro*Rc/5-13*Rc*Rc/5;

D1=u1*u1+v1*v1;        // D1为计算连接圆弧1与2圆心坐标需要的值,须先算出

D2=u2*u2+v2*v2;        // D2为计算连接圆弧3与4圆心坐标需要的值,须先算出

D3=u3*u3+v3*v3;        // D3为计算连接圆弧5与6圆心坐标需要的值,须先算出

// 下面几行计算都是为计算连接圆弧圆心坐标值做准备

BD1=B+D1

BD2=B+D2;

BD3=B+D3;

B2_4AC1=u1*u1*(4*A*D1)-BD1*BD1);

B2_4AC2=u2*u2*(4*A*D2)-BD2*BD2);

B2_4AC3=u3*u3*(4*A*D3)-BD3*BD3);

Root1=sqrt(B2_4AC1);

Root2=sqrt(B2_4AC2);

Root3=sqrt(B2_4AC3);

y1=(v1*BD1-Root1)/(2*D1);         // 根据圆心坐标所处象限位置,选取正负号

// 连接圆弧1圆心y坐标值

temp=A-y1*y1;

x1=sqrt(temp);                   // 连接圆弧1圆心x坐标值

y2=(v1*BD1+Root1)/(2*D1);        // 连接圆弧2圆心y坐标值

temp=A-y2*y2;

x2=sqrt(temp);                   // 连接圆弧2圆心x坐标值

y3=(v2*BD2+Root2)/(2*D2);        // ±Root2=0

// 连接圆弧3圆心y坐标值

temp=A-y3*y3;

x3=sqrt(temp);                  // 连接圆弧3圆心x坐标值

y4=(v2*BD2+Root2)/(2*D2);        // ±Root2=0

// 连接圆弧4圆心y坐标值

x4=-sqrt(A-y4*y4);               // 连接圆弧4圆心x坐标值

y5=(v3*BD3+Root3)/(2*D3);        // 连接圆弧5圆心y坐标值

x5=-sqrt(A-y5*y5);               // 连接圆弧5圆心x坐标值

y6=(v3*BD3-Root3)/(2*D3);        // 连接圆弧6圆心y坐标值

x6=-sqrt(A-y6*y6);               // 连接圆弧6圆心x坐标值

}

第五个框求连接圆弧切点,其程序作为一个函数:

void Tangent_Point()

{

float Rj,Lc,Lo;

Rj=4*Rc/5;

Lc=4.0/5.0;                     // =Rj/Rc

Lo=Rj/Rc;

cx1=(x1+Lc*u1)/(1+Lc);         // 连接圆弧L1与右边凸圆的切点坐标

cy1=(y1+Lc*v1)/(1+Lc);

cx2=(x2+Lc*u1)/(1+Lc);         // 连接圆弧L2与右边凸圆的切点坐标

cy2=(y2+Lc*v1)/(1+Lc);

cx3=(x3+Lc*u2)/(1+Lc);         // 连接圆弧L3与上边凸圆的切点坐标

cy3=(y3+Lc*v2)/(1+Lc);

cx4=(x4+Lc*u2)/(1+Lc);         // 连接圆弧L4与上边凸圆的切点坐标

cy4=(y4+Lc*v2)/(1+Lc);

cx5=(x5+Lc*u3)/(1+Lc);         // 连接圆弧L5与左边凸圆的切点坐标

cy5=(y5+Lc*v3)/(1+Lc);

cx6=(x6+Lc*u3)/(1+Lc);         // 连接圆弧L6与左边凸圆的切点坐标

cy6=(y6+Lc*v3)/(1+Lc);

ox1=(x1+Lo*0.0)/(1+Lo);        // 连接圆弧L1与外圆的切点坐标

oy1=(y1+Lo*0.0)/(1+Lo);

ox2=(x2+Lo*0.0)/(1+Lo);        // 连接圆弧L2与外圆的切点坐标

oy2=(y2+Lo*0.0)/(1+Lo);

ox3=(x3+Lo*0.0)/(1+Lo);        // 连接圆弧L3与外圆的切点坐标

oy3=(y3+Lo*0.0)/(1+Lo);

ox4=(x4+Lo*0.0)/(1+Lo);        // 连接圆弧L4与外圆的切点坐标

oy4=(y4+Lo*0.0)/(1+Lo);

ox5=(x5+Lo*0.0)/(1+Lo);        // 连接圆弧L5与外圆的切点坐标

oy5=(y5+Lo*0.0)/(1+Lo);

ox6=(x6+Lo*0.0)/(1+Lo);        // 连接圆弧L6与外圆的切点坐标

oy6=(y6+Lo*0.0)/(1+Lo);

}

最后一个框 画外圆弧、凸圆弧与连接圆弧,相应的程序为下面两个函数。

C语言中没有提供直接用圆心与圆弧端点坐标画圆弧的函数,下面函数Myarc()就可以实现这一功能,即直接用圆心、圆弧两端点坐标调用函数Myarc()画圆弧。

void Myarc(float ctx,float cty,float startx,float starty,float endx,float endy,float R)

{

float sx,sy,ex,ey,sangle,eangle;

sx=startx-ctx;

sy=starty-cty;

ex=endx-ctx;

ey=endy-cty;

if(sx!=0.0)

{

// θ=arctg y/x, (x>0.0)

// θ=arctg y/x+π,(x<0.0)

if(sx>0.00)sangle=atan(sy/sx);      // 将起点转化成起始角

if(sx<0.0)sangle=atan(sy/sx)+3.1415926;   // 将起点转化成起始角

}

else

{

if(sy>0.0)sangle=3.1415926/2;         // 将起点转化成起始角

if(sy<0.0)sangle=3*3.1415926/2;       // 将起点转化成起始角

}

if(ex!=0.0)

{

if(ex>0.0)eangle=atan(ey/ex);         // 将终点转化成终止角

if(ex<0.0)eangle=atan(ey/ex)+3.1415926;   // 将终点转化成终止角

}

else

{

if(ey>0.0)eangle=3.1415926/2;         // 将终点转化成终止角

if(ey<0.0)eangle=3*3.1415926/2;       // 将终点转化成终止角

}

sangle=sangle/0.017453;                  // 1=1o/0.017453

eangle=eangle/0.017453;

arc(mmaxx+ctx,mmaxy-cty,sangle,eangle,R);      // 画出圆弧

}

void Out_Link_Arc()

{

float Rj;

Rj=4*Rc/5;

Myarc(u1,v1,cx1,cy1,cx2,cy2,Rc);

// 用凸圆弧1圆心、圆弧两端坐标和半径画出凸圆弧1,其它圆弧的绘制类同。

Myarc(x2,y2,ox2,oy2,cx2,cy2,Rj);

Myarc(0.0,0.0,ox2,oy2,ox3,oy3,Ro);

Myarc(x3,y3,cx3,cy3,ox3,oy3,Rj);

Myarc(u2,v2,cx3,cy3,cx4,cy4,Rc);

Myarc(x4,y4,ox4,oy4,cx4,cy4,Rj);

Myarc(0.0,0.0,ox4,oy4,ox5,oy5,Ro);

Myarc(x5,y5,cx5,cy5,ox5,oy5,Rj);

Myarc(u3,v3,cx5,cy5,cx6,cy6,Rc);

Myarc(x6,y6,ox6,oy6,cx6,cy6,Rj);

Myarc(0.0,0.0,ox6,oy6,ox1,oy1,Ro);

Myarc(x1,y1,cx1,cy1,ox1,oy1,Rj);

}

注意这里画圆弧不能直接用C语言中的画圆弧函数arc(),要把圆弧的两端切点即起点与终点转换成起始角与终止角后才能调用它。将圆弧两端点化成起始角与结束角度可通过直角坐标与极坐标的变换关系式来完成。具本转换过程见上面函数Myarc()中程序内容。

六个框的程序编写完后,再加上头文件、全局变量的说明、图形模式初始化函数和主函数就构成画此零件图的整个程序,见后面的程序。本程序运行时,需要用户按提示输入内圆、外圆和凸圆的半径(程序提示中的参数值相应程序图3-1中的图形)。用户可输入不同的参数值,绘出不同大小的同类图形。

// 1. 源程序 Example.c

#include

#include

#include

#include

#include

float Ri,Ro,Rc,u1,v1,u2,v2,u3,v3,mmaxx,mmaxy;

float x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6;

float cx1,cy1,cx2,cy2,cx3,cy3,cx4,cy4,cx5,cy5,cx6,cy6,ox1,oy1,ox2,oy2,

ox3,oy3,ox4,oy4,ox5,oy5,ox6,oy6;

// 变量说明:Ri为内圆半径,Ro为外圆半径,Rc为凸圆半径,u1,v1,u2,v2,u3,v3分别为三个φ10圆

// 圆心位置坐标,x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6分别为六个连接圆弧的圆心位置坐标。

// cx1,cy1,cx2,cy2,cx3,cy3,cx4,cy4,cx5,cy5,cx6,cy6分另为连接圆弧与凸圆的切点坐标。

// ox1,oy1,ox2,oy2,ox3,oy3,ox4,oy4,ox5,oy5,ox6,oy6分别为连接圆弧与外圆的切点。

void EnterData()      // 输入内圆半径Ri、外圆半径Ro和凸圆半径Rc

{

clrscr();

gotoxy(1,6);

printf("Enter the radius of: he circle. /n");

gotoxy(1,8);

printf("Entere in circle radius(>=12.5):/n");

scanf("%f",&Ri);

printf("Enter out_circle radius(>=25.0): /n");

scanf(%f",&Ro);

printf("Enter convex_radius(>=10.0): /n");

scanf("%f",&Rc);

}

void Initialize()   // 初始化图形系统

{

int graphdriver,grapgmode,errormode;

graphdriver=DETECT;

initgraph(&graphdriver,&graphmode,"//bc>bgi");

errorcode=graphresult();

if(errorcode!=grOk)

{

printf("graphics system error: %s",grapherrormsg(errorcode));

exit(1);

}

mmaxx=getmaxx()/2;      // 获取x方向最大分辨率

mmaxy=getmaxy()/2;      // 获取y方向最大分辨率

}

void Base_Center_Line()    // 画基准线函数

{

flost dash_R;

desh_R=(4*Ro+Ri)/5;         // 三个小圆圆心所在的点划圆半径

u1=((4*Ro+Ri)/5)*cos(-30*0.017453);      // 确定三个小圆圆心坐标

v1=((4*Ro+Ri)/5)*sin(-30*0.017453);

u2=0.0;            // ((4*Ro+Ri)/5)*cos(90*0.017453)

v2=((4*Ro+Ri)/5);  // ((4*Ro+Ri)/5)*sin(90*0.017453)

u3=((4*Ro+Ri)/5)*cos(210*0.017453);

v3=((4*Ro+Ri)/5)*sin(210*0.017453);

line(mmaxx-Ro-Rc,mmaxy,mmaxx-(Ro+Rc)/2,mmaxy;    // 画基准线

line(mmaxx-(Ro+Rc)/2+5,mmaxy,mmaxx-(Ro+Rc)/2+5,mmaxy);

line(mmaxx-(Ro+Rc)/2+10,mmaxy,mmaxx-(Ro+Rc)/2,mmaxy);

line(mmaxx+(Ro+Rc)/2+5,mmaxy,mmaxx-(Ro+Rc)/2+5,mmaxy);

line(mmaxx+(Ro+Rc)/2+10,mmaxy,mmaxx+Ro+Rc,mmaxy);

line(mmaxx,mmaxy+Ro+Rc,mmaxx,mmaxy+(Ro+Rc)/2+10);

line(mmaxx,mmaxy+(Ro+Rc)/2+5,mmaxx,mmaxy+(Ro+Rc)/2+5);

line(mmaxx,mmaxy+(Ro+Rc)/2,mmaxx,mmaxy-(Ro+Rc)/2+10);

line(mmaxx,mmaxy-(Ro+Rc)/2+5,mmaxx,mmaxy-(Ro+Rc)/2+5);

line(mmaxx,mmaxy-(Ro+Rc)/2,mmaxx,mmaxy-Ro-Rc);

arc(mmaxx,mmaxy,0,25,desh_R);            // 画点划圆

arc(mmaxx,mmaxy,28,29,desh_R);           // 画点划圆

arc(mmaxx,mmaxy,32,110,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,113,114,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,117,185,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,187,188,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,191,255,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,258,259,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,262,300,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,303,304,desh_R);         // 画点划圆

arc(mmaxx,mmaxy,307,360,desh_R);         // 画点划圆

}

void Known_Circle()      // 画已知圆

{

circle(mmaxx,mmaxy,Ri);

circle(mmaxx+u1,mmaxy-v1,Rc/2);

circle(mmaxx+u2,mmaxy-v2,Rc/2);

circle(mmaxx+u3,mmaxy-v3,Rc/2);

}

vooid Link_Arc_Center()      // 计算连接圆弧圆心坐标值

{

float A,B,D1,D2,D3,B2_4AC1,B2_4AC2,B2_4AC3;

float BD1,BD2,BD3,Root1,Root2,Root3,temp;

A=Ro*Ro+8*Ro*Rc/5+16*Rc*Rc/25;

B=Ro*Ro+8*Ro*Rc/5-13*Rc*Rc/5;

D1=u1*u1+v1*v1;        // D1为计算连接圆弧1与2圆心坐标需要的值,须先算出

D2=u2*u2+v2*v2;        // D2为计算连接圆弧3与4圆心坐标需要的值,须先算出

D3=u3*u3+v3*v3;        // D3为计算连接圆弧5与6圆心坐标需要的值,须先算出

// 下面几行计算都是为计算连接圆弧圆心坐标值做准备

BD1=B+D1

BD2=B+D2;

BD3=B+D3;

B2_4AC1=u1*u1*(4*A*D1)-BD1*BD1);

B2_4AC2=u2*u2*(4*A*D2)-BD2*BD2);

B2_4AC3=u3*u3*(4*A*D3)-BD3*BD3);

Root1=sqrt(B2_4AC1);

Root2=sqrt(B2_4AC2);

Root3=sqrt(B2_4AC3);

y1=(v1*BD1-Root1)/(2*D1);         // 根据圆心坐标所处象限位置,选取正负号

// 连接圆弧1圆心y坐标值

temp=A-y1*y1;

x1=sqrt(temp);                   // 连接圆弧1圆心x坐标值

y2=(v1*BD1+Root1)/(2*D1);        // 连接圆弧2圆心y坐标值

temp=A-y2*y2;

x2=sqrt(temp);                   // 连接圆弧2圆心x坐标值

y3=(v2*BD2+Root2)/(2*D2);        // ±Root2=0

// 连接圆弧3圆心y坐标值

temp=A-y3*y3;

x3=sqrt(temp);                  // 连接圆弧3圆心x坐标值

y4=(v2*BD2+Root2)/(2*D2);        // ±Root2=0

// 连接圆弧4圆心y坐标值

x4=-sqrt(A-y4*y4);               // 连接圆弧4圆心x坐标值

y5=(v3*BD3+Root3)/(2*D3);        // 连接圆弧5圆心y坐标值

x5=-sqrt(A-y5*y5);               // 连接圆弧5圆心x坐标值

y6=(v3*BD3-Root3)/(2*D3);        // 连接圆弧6圆心y坐标值

x6=-sqrt(A-y6*y6);               // 连接圆弧6圆心x坐标值

}

void Tangent_Point()      // 计算切点坐标函数

{

float Rj,Lc,Lo;

Rj=4*Rc/5;

Lc=4.0/5.0;                     // =Rj/Rc

Lo=Rj/Rc;

cx1=(x1+Lc*u1)/(1+Lc);         // 连接圆弧L1与右边凸圆的切点坐标

cy1=(y1+Lc*v1)/(1+Lc);

cx2=(x2+Lc*u1)/(1+Lc);         // 连接圆弧L2与右边凸圆的切点坐标

cy2=(y2+Lc*v1)/(1+Lc);

cx3=(x3+Lc*u2)/(1+Lc);         // 连接圆弧L3与上边凸圆的切点坐标

cy3=(y3+Lc*v2)/(1+Lc);

cx4=(x4+Lc*u2)/(1+Lc);         // 连接圆弧L4与上边凸圆的切点坐标

cy4=(y4+Lc*v2)/(1+Lc);

cx5=(x5+Lc*u3)/(1+Lc);         // 连接圆弧L5与左边凸圆的切点坐标

cy5=(y5+Lc*v3)/(1+Lc);

cx6=(x6+Lc*u3)/(1+Lc);         // 连接圆弧L6与左边凸圆的切点坐标

cy6=(y6+Lc*v3)/(1+Lc);

ox1=(x1+Lo*0.0)/(1+Lo);        // 连接圆弧L1与外圆的切点坐标

oy1=(y1+Lo*0.0)/(1+Lo);

ox2=(x2+Lo*0.0)/(1+Lo);        // 连接圆弧L2与外圆的切点坐标

oy2=(y2+Lo*0.0)/(1+Lo);

ox3=(x3+Lo*0.0)/(1+Lo);        // 连接圆弧L3与外圆的切点坐标

oy3=(y3+Lo*0.0)/(1+Lo);

ox4=(x4+Lo*0.0)/(1+Lo);        // 连接圆弧L4与外圆的切点坐标

oy4=(y4+Lo*0.0)/(1+Lo);

ox5=(x5+Lo*0.0)/(1+Lo);        // 连接圆弧L5与外圆的切点坐标

oy5=(y5+Lo*0.0)/(1+Lo);

ox6=(x6+Lo*0.0)/(1+Lo);        // 连接圆弧L6与外圆的切点坐标

oy6=(y6+Lo*0.0)/(1+Lo);

}

void Myarc(float ctx,float cty,float startx,float starty,float endx,float endy,float R)

{

float sx,sy,ex,ey,sangle,eangle;

sx=startx-ctx;

sy=starty-cty;

ex=endx-ctx;

ey=endy-cty;

if(sx!=0.0)

{

// θ=arctg y/x, (x>0.0)

// θ=arctg y/x+π,(x<0.0)

if(sx>0.00)sangle=atan(sy/sx);      // 将起点转化成起始角

if(sx<0.0)sangle=atan(sy/sx)+3.1415926;   // 将起点转化成起始角

}

else

{

if(sy>0.0)sangle=3.1415926/2;         // 将起点转化成起始角

if(sy<0.0)sangle=3*3.1415926/2;       // 将起点转化成起始角

}

if(ex!=0.0)

{

if(ex>0.0)eangle=atan(ey/ex);         // 将终点转化成终止角

if(ex<0.0)eangle=atan(ey/ex)+3.1415926;   // 将终点转化成终止角

}

else

{

if(ey>0.0)eangle=3.1415926/2;         // 将终点转化成终止角

if(ey<0.0)eangle=3*3.1415926/2;       // 将终点转化成终止角

}

sangle=sangle/0.017453;                  // 1=1o/0.017453

eangle=eangle/0.017453;

arc(mmaxx+ctx,mmaxy-cty,sangle,eangle,R);      // 画出圆弧

}

void Out_Link_Arc()

{

float Rj;

Rj=4*Rc/5;

Myarc(u1,v1,cx1,cy1,cx2,cy2,Rc);

// 用凸圆弧1圆心、圆弧两端坐标和半径画出凸圆弧1,其它圆弧的绘制类同。

Myarc(x2,y2,ox2,oy2,cx2,cy2,Rj);

Myarc(0.0,0.0,ox2,oy2,ox3,oy3,Ro);

Myarc(x3,y3,cx3,cy3,ox3,oy3,Rj);

Myarc(u2,v2,cx3,cy3,cx4,cy4,Rc);

Myarc(x4,y4,ox4,oy4,cx4,cy4,Rj);

Myarc(0.0,0.0,ox4,oy4,ox5,oy5,Ro);

Myarc(x5,y5,cx5,cy5,ox5,oy5,Rj);

Myarc(u3,v3,cx5,cy5,cx6,cy6,Rc);

Myarc(x6,y6,ox6,oy6,cx6,cy6,Rj);

Myarc(0.0,0.0,ox6,oy6,ox1,oy1,Ro);

Myarc(x1,y1,cx1,cy1,ox1,oy1,Rj);

}

void main()

{

Enter_Data();            // 输入数据值

Initialize();            // 图形初始化

Base_Center_Line();      // 画基准线

Known_Circle();          // 画已知圆

Link_Arc_Center();       // 求连接圆弧圆心

Tangent_Point();         // 求切点

Out_Link_Arc();          // 画出外圆弧、凸圆弧和连接圆弧

getche();                // 使图形暂留在屏幕上

closegraph();            // 释放图形系统占用的内存,返回文本模式

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/334239.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mfc怎么获取进程的线程数_Python多线程获取小米应用商店App,看看我是怎么做到的

一、【项目背景】小米应用商店给用户发现最好的安卓应用和游戏,安全可靠&#xff0c;可是要下载东西要一个一个的搜索太麻烦了。而且速度并不是很快。今天小编就教大家利用多线程爬取小米应用商店的游戏模块&#xff0c;快速获取我们想要的软件安装包。二、【项目目标】目标 &a…

Linux Distribution Timeline for 2010(Linux 2010 年发行版时间线/族谱/发展图)

此图来自维基百科&#xff08;wikimedia&#xff09;&#xff0c;具体地址为&#xff1a;https://commons.wikimedia.org/wiki/File:Linux_Distribution_Timeline.svg?uselangzh-hans#filehistory

git强制推送_Git 常用命令

Git 常用命令总结1. GIT 工作区add commitworking directory ------- index(stage) ---------- HEAD | | | | | | 工作目录 暂存区 …

golang 泛型_Golang 1.x版本泛型编程

本文介绍了Golang 1.x版本的泛型编程。往期回顾&#xff1a;浅谈动态追踪技术Go是一门天生为服务器程序设计的简洁的语言&#xff0c;因此Go的设计原则聚焦在可扩展性、可读性和并发性&#xff0c;而多态性并不是这门语言的设计初衷&#xff0c;因此就被放在了一边。虽然在2.0版…

jwt令牌_JWT令牌的秘密轮换

jwt令牌当您使用JSON Web令牌 &#xff08; JWT &#xff09;或需要对有效载荷信息进行签名或加密的任何其他令牌技术时&#xff0c;设置令牌的到期日期很重要&#xff0c;因此&#xff0c;如果令牌到期&#xff0c;则可以假定这可能被视为安全漏洞&#xff0c;您拒绝使用此令牌…

jasperreports_JasperReports:棘手的部分

jasperreports如果您使用Java进行编程的时间足够长&#xff0c;则有可能需要为业务用户生成报告。 就我而言&#xff0c;我已经看到几个项目使用JasperReportsLibrary来生成PDF和其他文件格式的报告。 最近&#xff0c;我荣幸地观察了Mike和他的团队使用上述报告库以及他们所面…

电脑运行adb闪退_adb+python进阶使用

之前文章有提到过使用python加adb刷视频&#xff0c;今天带来进阶版——无线多台手机。首先要使用adb连接多台手机&#xff0c;手机和电脑肯定要在统一局域网内。1.打开手机开发者模式&#xff0c;并通过USB接口链接电脑。2.打开cmd&#xff1a;输入adb tcpip 5555, 会得到相关…

java office在线编辑_国外10个最受欢迎的 Java 开发的 CMS 系统

CMS是Content Management System的缩写&#xff0c;意为"内容管理系统"&#xff0c;它具有许多基于模板的优秀设计&#xff0c;可以加快网站开发的速度和减少开发的成本。CMS的功能并不只限于文本处理&#xff0c;它也可以处理图片、Flash动画、声像流、图像甚至电子…

apache kafka_Apache Kafka简介

apache kafka什么是Apache Kafka&#xff1f; Apache Kafka是一个分布式流系统&#xff0c;具有发布和订阅记录流的功能。 在另一方面&#xff0c;它是企业消息传递系统。 它是一个快速&#xff0c;水平可扩展和容错的系统。 Kafka有四个核心API&#xff0c; 生产者API&#x…

人脸特征值能存放在sql server中吗_SQL运行内幕:从执行原理看调优的本质

原文链接&#xff1a;https://www.cnblogs.com/arthinking/p/13205303.html相信大家看过无数的MySQL调优经验贴了&#xff0c;会告诉你各种调优手段&#xff0c;如&#xff1a;避免 select *&#xff1b;join字段走索引&#xff1b;慎用in和not in&#xff0c;用exists取代in&a…

rest资源设计_REST资源何时应获得其自己的地址?

rest资源设计在纯粹的REST方法中&#xff0c;所有端点&#xff08;起始端点除外&#xff09;都是不透明的&#xff0c;因此不需要发布其各种详细信息。 即使使用这种方法&#xff0c;本文中的要点也很重要&#xff0c;因为服务器逻辑将必须确定何时需要结束点。 介绍 在REST体…

ckeditor回显带标签_Spring Boot中带有CKEditor的AJAX

ckeditor回显带标签1.概述 在本文中&#xff0c;我们将介绍如何在Spring Boot中使用CKEditor 。 在本教程中&#xff0c;我们将导入一个包含大量数据的XML文档&#xff0c;对使用GET请求将一组数据加载到CKEditor实例的能力进行编程&#xff0c;并执行POST请求以保存CKEditor的…

android 可行性分析,可行性研究项目分析程序与步骤

项目分析程序项目分析分析工作步骤分析程序框架分段实施方法第一阶段初期工作1、收集资料。包括业主的要求&#xff0c;业主已经完成的研究成果&#xff0c;市场、厂址、原料、能源、运输、维修、共用设施、环境、劳动力来源、资金来源、税务、设备材料价格、物价上涨率等有关资…

原码一位乘法器设计_十分钟带你彻底搞懂原码、反码、补码

点击上方“程序员大白”&#xff0c;选择“星标”公众号重磅干货&#xff0c;第一时间送达编辑 | 程序员大白公众号来源丨https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html仅作学术交流&#xff0c;如有侵权&#xff0c;请联系删文本篇文章讲解了计算…

Linux 目录之 /etc/init.d/ 介绍

文章目录一、关于目录 /etc/init.d/二、关于目录 /etc/rc.d/init.d/三、关于文件 /etc/rc.local四、/etc/init.d/ 和 service 文件五、关于命令 service六、关于文件 /etc/inittab七、关于目录 /etc/init/注意&#xff1a;以 System V init 或者 Upstart 为初始化系统的 Linux …

java 异常处理发生异常_处理Java中的异常

java 异常处理发生异常每个程序员都希望编写一个完美的程序。 也就是说&#xff0c;程序运行时没有任何障碍。 好吧&#xff0c;如果希望是马&#xff0c;乞g就会骑。 除了程序员的所有愿望之外&#xff0c;有时还会发生无法预料的情况。 在Java中&#xff0c;这些无法预料的…

android提交项目到svn,Android Studio 配置SVN,通过Share project提交项目和实现忽略文件...

1&#xff1a;首先电脑本身装的SVN必须在bin目录下包含svn.exe文件&#xff0c;如下图。这个文件是在安装SVN时选择安装command line client tools才会出现。如果没有&#xff0c;需要重新安装SVN。2&#xff1a;将SVN关联到Android Studio中声明&#xff1a;在这里我使用的And…

数独游戏技巧从入门到精通_如何引导孩子入门九宫格数独?掌握4个技巧口诀,孩子思维提升快...

九宫格数独对孩子的思维训练有着非常不错的效果&#xff0c;我们完全可以用其培养孩子对数字的兴趣&#xff0c;并培养孩子严谨的逻辑推理态度。那九宫格数独有没有技巧口诀呢&#xff1f;对于孩子来说&#xff0c;过于复杂的技巧他们也掌握不了。所以&#xff0c;我们培养孩子…