|
続き
!●直線
!2点(x1,y1), (x2,y2)を通る直線Lx+My+N=0
!公式 -(y2-y1)(x-x1)+(x2-x1)(y-y1)=0 より
EXTERNAL SUB gcLINE(x1,y1,x2,y2, L,M,N)
IF (x1=x2 AND y1=y2) THEN !同一点なら
PRINT "異なる2点ではないので、直線が成立しません。"; x1;y1;x2;y2
ELSE
LET L=y1-y2
LET M=x2-x1
LET N=x1*y2-y1*x2
END IF
END SUB
!点(x1,y1)と通り、直線Ax+By+C=0に平行な直線
!公式 直線BCがLx+My+N=0のとき、L(x-x1)+M(y-y1)=0
EXTERNAL SUB gcLINEP(x1,y1,L,M,N, A,B,C)
LET A=L
LET B=M
LET C=-L*x1-M*y1
END SUB
!点(x1,y1)と通り、2点(x2,y2), (x3,y3)を通る直線に平行な直線
!公式 直線BCがLx+My+N=0のとき、L(x-x1)+M(y-y1)=0
EXTERNAL SUB gcLINEP2(x1,y1,x2,y2,x3,y3, L,M,N)
IF (x2=x3 AND y2=y3) THEN
PRINT "2点は同一点なので、直線が成立しません。"; x1;y1;x2;y2;x3;y3
ELSE
CALL gcLINE(x2,y2,x3,y3, L,M,N)
LET N=-L*x1-M*y1
END IF
END SUB
!点(x1,y1)と通り、直線Ax+By+C=0に垂直な直線
!公式 直線BCがLx+My+N=0のとき、L(y-y1)=M(x-x1)
EXTERNAL SUB gcLINEX(x1,y1,L,M,N, A,B,C)
LET A=-M
LET B=L
LET C=-L*y1+M*x1
END SUB
!点(x1,y1)と通り、2点(x2,y2), (x3,y3)を通る直線に垂直な直線
!公式 直線BCがLx+My+N=0のとき、L(y-y1)=M(x-x1)
EXTERNAL SUB gcLINEX2(x1,y1,x2,y2,x3,y3, L,M,N)
IF (x2=x3 AND y2=y3) THEN
PRINT "2点は同一点なので、直線が成立しません。"; x1;y1;x2;y2;x3;y3
ELSE
CALL gcLINE(x2,y2,x3,y3, S,T,U)
LET L=-T
LET M=S
LET N=-S*y1+T*x1
END IF
END SUB
!点A(x1,y1)から点B(x2,y2), C(x3,y3)を結ぶ線分BCの中点を通る直線(中線)
EXTERNAL SUB gcD2LINE(x1,y1,x2,y2,x3,y3, L,M,N)
IF (x1=x2 AND y1=y2) OR (x1=x3 AND y1=y3) THEN
PRINT "2点は同一点なので、線分が成立しません。"; x1;y1;x2;y2;x3;y3
ELSE
CALL gcLINE(x1,y1,(x2+x3)/2,(y2+y3)/2, L,M,N)
END IF
END SUB
!点A(x1,y1), B(x2,y2)を結ぶ線分ABの垂直二等分線
EXTERNAL SUB gcP2LINE(x1,y1,x2,y2, L,M,N)
IF (x1=x2 AND y1=y2) THEN
PRINT "2点は同一点なので、線分が成立しません。"; x1;y1;x2;y2
ELSE
CALL gcLINE(x1,y1,x2,y2, A,B,C) !直線AB
CALL gcLINEX((x1+x2)/2,(y1+y2)/2,A,B,C, L,M,N) !中点を通り直線ABに垂直
END IF
END SUB
!直線Ax+By+C=0を一定間隔p(平行線の間隔)だけ平行移動させる
! 長さで三角形A,B,√(A^2+B^2)と三角形x,y,pを考える。
! x方向 √(A^2+B^2) : A = p : x より、x=Ap/√(A^2+B^2)
! y方向 √(A^2+B^2) : B = p : y より、y=Bp/√(A^2+B^2)
! よって、(x,y)を移動量とする平行移動された直線は、A(X-x)+B(Y-y)+C=0
EXTERNAL SUB gcPARALLELLINE(A,B,C,p, L,M,N,dx,dy)
LET t=SQR(A^2+B^2)
LET L=A
LET M=B
LET N=C-t*p
LET dx=-A*p/t !x軸,y軸成分
LET dy=-B*p/t
END SUB
!2直線Lx+My+N=0、Px+Qy+R=0のなす角を二等分する線
! 求める直線上の点を(x,y)とする。
! この点から2直線への距離は等しいので、|Lx+My+N|/√(L^2+M^2)=|Px+Qy+R|/√(P^2+Q^2)
! ∴√(P^2+Q^2)(Lx+My+N)=±√(L^2+M^2)(Px+Qy+R)
EXTERNAL SUB gcA2LINE(L,M,N,P,Q,R, A,B,C, D,E,F, K)
LET s=SQR(P^2+Q^2)
LET t=SQR(L^2+M^2)
LET A=s*L+t*P !1つ目
LET B=s*M+t*Q
LET C=s*N+t*R
LET K=1
IF L*Q-M*P<>0 THEN !2直線が交わるなら
LET D=s*L-t*P !2つ目
LET E=s*M-t*Q
LET F=s*N-t*R
LET K=2
END IF
END SUB
!円x^2+y^2+Ax+By+C=0上の円周上の点(x0,y0)における接線
!公式 円(x+A/2)^2+(y+B/2)^2=(A/2)^2+(B/2)^2-Cより、(x0+A/2)(x+A/2)+(y0+B/2)(y+B/2)=(A^2+B^2)/4-C
EXTERNAL SUB gcTANGENTLINE1C(x0,y0,A,B,C, L,M,N)
LET RR=(A^2+B^2)/4-C !判別式
IF RR>0 THEN
IF ABS(x0^2+y0^2+A*x0+B*y0+C)>cEPS THEN
PRINT "点は円周上にありません。"; x0;y0;A;B;C
ELSE
LET L=x0+A/2
LET M=y0+B/2
LET N=x0*A/2+y0*B/2 +C
END IF
ELSE
PRINT "半径が負または0なので、円が成立しません。"; A;B;C
END IF
END SUB
!●円
EXTERNAL SUB gcCIRCLE(x1,y1,R, A,B,C) !中心(x1,y1)、半径Rの円
IF R>0 THEN
LET A=-2*x1
LET B=-2*y1
LET C=x1^2+y1^2-R^2
ELSE
PRINT "半径が負または0なので、円が成立しません。"; x1;y1;R
END IF
END SUB
!2点P(x1,y1),Q(x2,y2)を結ぶ線分を直径とする円
! A=-2(x1+x2)/2、B=-2(y1+y2)/2、C=(x1+x2)^2/4+(y1+y2)^2/4 -{(x1-x2)^2+(y1-y2)^2}/4 より
EXTERNAL SUB gcCIRCLE2R(x1,y1,x2,y2, A,B,C)
IF (x1=x2 AND y1=y2) THEN !同一点なら
PRINT "2点は同一点なので、円が成立しません。"; x1;y1;x2;y2
ELSE
LET A=-(x1+x2)
LET B=-(y1+y2)
LET C=x1*x2+y1*y2
END IF
END SUB
!2点P(x1,y1),Q(x2,y2)を通る半径Rの円
! 2点を通る直線(半径∞の円) Lx+My+N=0
! 2点を直径とする円 x^2+y^2+Sx+Ty+U=0
! これより、2点を通る曲線 (x^2+y^2+Sx+Ty+U)+k(Lx+My+N)=0 とおける。
! 半径がRより、(x+(S+kL)/2)^2+(y+(T+kM)/2)^2={(S+kL)^2+(T+kM)^2}/4-(U+kN)=R^2
! ∴(S+kL)^2+(T+kM)^2-4(U+kN)-4R^2=0
! ∴(L^2+M^2)k^2 +2(SL+TM-2N)k +{(S^2+T^2)-4*(R^2+U)}=0
! kについての2次方程式を解く。
EXTERNAL SUB gcCIRCLE2(x1,y1,x2,y2,R, A,B,C, D,E,F, K)
IF (x1=x2 AND y1=y2) THEN !同一点なら
PRINT "2点は同一点なので、円が成立しません。"; x1;y1;x2;y2;R
ELSEIF R<=0 THEN
PRINT "半径は負または0なので、円が成立しません。"; x1;y1;x2;y2;R
ELSE
CALL gcLINE(x1,y1,x2,y2, L,M,N) !直線
CALL gcCIRCLE2R(x1,y1,x2,y2, S,T,U) !円
LET aa=L^2+M^2
LET bb=2*(S*L+T*M-2*N)
LET cc=(S^2+T^2)-4*(R^2+U)
CALL Solve2Equ(aa,bb,cc, k1,k2,K)
IF K>0 THEN
LET A=S+k1*L
LET B=T+k1*M
LET C=U+k1*N
IF K=2 THEN !2点を結ぶ線分が直径となる場合は1つ
LET D=S+k2*L
LET E=T+k2*M
LET F=U+k2*N
END IF
ELSE
PRINT "半径の長さが短いので、円が成立しません。"; x1;y1;x2;y2;R
LET K=0
END IF
END IF
END SUB
!3点P(x1,y1),Q(x2,y2),R(x3,y3)を通る円(3点を頂点とする三角形の外接円)
! 線分PQを直径とする円 (x-x1)*(x-x2)+(y-y1)*(y-y2)=0 ←式1
! 点P,Qを通る直線(半径∞の円と考える) (x-x1)*(y2-y1)-(y-y1)*(x2-x1)=0 ←式2
! これより、点P,Qを通る曲線(円)は、(式1)+k*(式2)=0と表される。
! 点Rを通るので、(x3,y3)を代入して、kを定める。
EXTERNAL SUB gcCIRCLE3(x1,y1,x2,y2,x3,y3, A,B,C)
IF (x1=x3 AND y1=y2) OR (x2=x3 AND y2=y3) OR (x3=x1 AND y3=y1) THEN !同一点なら
PRINT "異なる3点ではないので、円が成立しません。"; x1;y1;x2;y2;x3;y3
ELSEIF (x3-x1)*(y2-y1)=(y3-y1)*(x2-x1) THEN !直線PQと直線PRの傾きが同じなら
PRINT "3点は一直線上にあるので、円が成立しません。"; x1;y1;x2;y2;x3;y3
ELSE
LET p=(x3-x1)*(x3-x2)+(y3-y1)*(y3-y2)
LET q=(x3-x1)*(y2-y1)-(y3-y1)*(x2-x1)
LET k=-p/q
!!!PRINT k !debug
LET ox=((x1+x2)-k*(y2-y1))/2 !中心点o(外心)
LET oy=((y1+y2)+k*(x2-x1))/2
LET R=DIST(ox,oy,x1,y1) !半径oA
CALL gcCIRCLE(ox,oy,R, A,B,C)
END IF
END SUB
!2円x^2+y^2+A1x+B1y+C1=0、x^2+y^2+A2x+B2y+C2=0の共通接線
! 2円の配置
! 外側で交わらない
! 2つの共通外接線、4つの接点
! 2つの共通内接線、4つの接点
! 外接
! 2つの共通外接線、4つの接点
! 1つの内接線、1つの接点
! 交わる
! 2つの共通外接線、4つの接点
! 内接
! 1つの接線、1つの接点
! 内側で交わらない
! 接線、接点なし
!
!※接点(PX(1),PY(1))と接点(PX(2),PY(2))を通る接線は、L(1)x+M(1)y+N(1)=0となる。
EXTERNAL SUB gcTANGENTLINE2C(A1,B1,C1,A2,B2,C2, L(),M(),N(),K, PX(),PY(),K2)
LET RR1=(A1^2+B1^2)/4-C1 !判別式
LET RR2=(A2^2+B2^2)/4-C2
IF (RR1>0 AND RR2>0) THEN !円と円
LET R1=SQR(RR1) !円1の半径
LET R2=SQR(RR2) !円2の半径
LET cx1=-A1/2 !円1の中心
LET cy1=-B1/2
LET cx2=-A2/2 !円2の中心
LET cy2=-B2/2
LET d=DIST(cx1,cy1,cx2,cy2) !線分o1o2の長さ(中心間の距離)
LET t=ABS(R1-R2)
IF t<d THEN !外側で交わらない、外接、交わる
!--- 共通外接線
IF R1=R2 THEN !※半径が同じなので、接線は平行となる
CALL gcLINE(cx1,cy1,cx2,cy2, S,T,U) !直線o1o2
CALL gcPARALLELLINE(S,T,U, R1, L(1),M(1),N(1),dx,dy) !間隔R1の直線
LET PX(1)=cx1+dx !接点
LET PY(1)=cy1+dy
LET PX(2)=cx2+dx !接点
LET PY(2)=cy2+dy
CALL gcPARALLELLINE(S,T,U,-R1, L(2),M(2),N(2),dx,dy) !反対側
LET PX(3)=cx1+dx !接点
LET PY(3)=cy1+dy
LET PX(4)=cx2+dx !接点
LET PY(4)=cy2+dy
ELSE !※直線o1o2を共通な辺として、半径を1辺とする相似な三角形を考える
CALL gcDIVIDE(cx1,cy1,cx2,cy2,R1,-R2, xx,yy) !線分o1o2の外分点
CALL gcTANGENTLINE(xx,yy,A1,B1,C1, PX(1),PY(1),PX(3),PY(3),K) !この点から円1に接線を引く
CALL gcDIVIDE(PX(1),PY(1),xx,yy,R1-R2,R2, PX(2),PY(2)) !接点と外分点から円2の接点を算出する
CALL gcDIVIDE(PX(3),PY(3),xx,yy,R1-R2,R2, PX(4),PY(4))
CALL gcLINE(PX(1),PY(1),PX(2),PY(2), L(1),M(1),N(1)) !接線
CALL gcLINE(PX(3),PY(3),PX(4),PY(4), L(2),M(2),N(2))
END IF
LET K=2
LET K2=4
!--- 共通内接線
LET tt=R1+R2
IF tt<d THEN !離れている(外側で交わらない)
CALL gcDIVIDE(cx1,cy1,cx2,cy2,R1,R2, xx,yy) !線分o1o2の内分点
CALL gcTANGENTLINE(xx,yy,A1,B1,C1, PX(5),PY(5),PX(7),PY(7),K) !この点から円1に接線を引く
CALL gcDIVIDE(PX(5),PY(5),xx,yy,R1+R2,-R2, PX(6),PY(6)) !接点と内分点から円2の接点を算出する
CALL gcDIVIDE(PX(7),PY(7),xx,yy,R1+R2,-R2, PX(8),PY(8))
CALL gcLINE(PX(5),PY(5),PX(6),PY(6), L(3),M(3),N(3)) !接線
CALL gcLINE(PX(7),PY(7),PX(8),PY(8), L(4),M(4),N(4))
LET K=4
LET K2=8
ELSEIF ABS(tt-d)<=cEPS THEN !外接している
CALL gcDIVIDE(cx1,cy1,cx2,cy2,R1,R2, PX(5),PY(5)) !線分o1o2をR1:R2に分ける点
CALL gcLINE(cx1,cy1,cx2,cy2, P,Q,R) !その点を通り、線分o1o2に垂直
CALL gcLINEX(PX(5),PY(5),P,Q,R, L(3),M(3),N(3))
LET K=3
LET K2=5
ELSE !交わる
!nop
END IF
ELSEIF ABS(t-d)<=cEPS THEN !内接している
CALL gcDIVIDE(cx1,cy1,cx2,cy2,R1,-R2, PX(1),PY(1)) !線分o1o2をR1:-R2に分ける点
CALL gcLINE(cx1,cy1,cx2,cy2, P,Q,R) !その点を通り、線分o1o2に垂直
CALL gcLINEX(PX(1),PY(1),P,Q,R, L(1),M(1),N(1))
LET K=1
LET K2=1
ELSE !含まれる(内側で交わらない)
IF d=0 THEN PRINT "同心円で";
PRINT "接線はありません。"
LET K=0
END IF
ELSE
PRINT "半径が負または0なので、円が成立しません。"; A1;B1;C1; A2;B2;C2
LET K=0
LET K2=0
END IF
END SUB
|
|