3-1
3-4
3-5
2-6
2-7
2-8
倚天照海花无数,流水高山心自知。
// 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,"bgi">\\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(); // 释放图形系统占用的内存,返回文本模式
}