您的位置:首页 > 编程语言 > C语言/C++

[转]C语言图形编程(六) -图形程序设计实例:零件图形的绘制

2007-03-27 16:31 483 查看
实例:一个零件图形的绘制
有一个零件图,如下:



[align=left]
对图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与右边凸圆的切点坐标为[/align]



[align=left]式中 λo=Rj/Ro
λc=Rj/Rc
Rj,Ro,Rc 是相应的圆弧半径
至此,求得了所有连接圆弧切点的坐标

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



[align=left]第一框 输入数据,用下面一个函数实现:
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()[/align]
{
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<stdio.h>
#include<graphics.h>
#include<math.h>
#include<conio.h>
#include<stdlib.h>

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() // 计算切点坐标函数
[align=left]{
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(); // 释放图形系统占用的内存,返回文本模式
}[/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: