;眺めるだけです。操作はありません。 ;位置と大きさの変わる円Aと、位置の変わる点Bがあります。 ;点Bが円Aの外部にあるとき、点Bを通る円Aへの接線の接点が表示されます。 ;;;;;;;;; 以下、ソース ;;;;;;;;; #module __Draw #define WIN_CTR_X ( 300.0 ) #define WIN_CTR_Y ( 240.0 ) ; 描画 #deffunc DrawLine double x0, double y0, double x1, double y1 line x0 + WIN_CTR_X, - y0 + WIN_CTR_Y, x1 + WIN_CTR_X, - y1 + WIN_CTR_Y return #deffunc DrawPoint double px, double py circle px + WIN_CTR_X - 5.0, - py + WIN_CTR_Y - 5.0, px + WIN_CTR_X + 5.0, - py + WIN_CTR_Y + 5.0 return #deffunc DrawCircle double cx, double cy, double radius left = cx - radius + WIN_CTR_X top = - ( cy + radius ) + WIN_CTR_Y circle left, top, left + 2.0 * radius, top + 2.0 * radius, 0 return #deffunc DrawLineV array p_c, array p0 line p_c(0) + WIN_CTR_X, - p_c(1) + WIN_CTR_Y, p0(0) + WIN_CTR_X, - p0(1) + WIN_CTR_Y return #deffunc DrawPointV array c0 circle c0(0) + WIN_CTR_X - 5.0, - c0(1) + WIN_CTR_Y - 5.0, c0(0) + WIN_CTR_X + 5.0, - c0(1) + WIN_CTR_Y + 5.0 pos WIN_CTR_X + c0(0), WIN_CTR_Y - c0(1) mes "("+strf("%.3f", c0(0))+","+strf("%.3f",c0(1))+")" return #deffunc DrawCircleV array c, double radius, int fill left = c(0) - radius + WIN_CTR_X top = - ( c(1) + radius ) + WIN_CTR_Y circle left, top, left + 2.0 * radius, top + 2.0 * radius, fill return #global ; 入力 p_c(0) = 181.0 p_c(1) = -82.0 p0(0) = 170.0 p0(1) = -82.0 rc = 125.0 ; 出力(適当に初期化) cp_c(0) = 12345.0 cp_c(1) = 67890.0 cp0(0) = -12345.0 cp0(1) = -67890.0 ; d_c(0) = -4 d_c(1) = -2 d0(0) = 3 d0(1) = 2 dr = 3 ; is_zero = 0 while( 1 ) redraw 0 color; 255, 255, 255 boxf gosub *Move gosub *Calc gosub *Draw redraw 1 await 25 wend stop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 移動 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; *Move p_c(0) += d0(0) if( p_c(0) < -300 || p_c(0) > 300 ){ p_c(0) -= d0(0) d0(0) = rnd( 10 ) - 5 if( d0(0) >= 0 ){ d0(0) ++ } } d0(0) |= 1 p_c(1) += d0(1) if( p_c(1) < -240 || p_c(1) > 240 ){ p_c(1) -= d0(1) d0(1) = rnd( 10 ) - 5 if( d0(1) >= 0 ){ d0(1) ++ } } d_c(0) |= 1 p0(0) += d_c(0) if( p0(0) < -300 || p0(0) > 300 ){ p0(0) -= d_c(0) d_c(0) = rnd( 10 ) - 5 if( d_c(0) >= 0 ){ d_c(0) ++ } } d_c(0) |= 1 p0(1) += d_c(1) if( p0(1) < -240 || p0(1) > 240 ){ p0(1) -= d_c(1) d_c(1) = rnd( 10 ) - 5 if( d_c(1) >= 0 ){ d_c(1) ++ } } d_c(1) |= 1 rc += dr if( rc < 5 || rc > 200 ){ dr = - dr } return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 計算 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; *Calc ; 計算用変数 ; 線分p_cp0の長さ LX = p0(0) - p_c(0) LY = p0(1) - p_c(1) L2 = LX * LX + LY * LY L = sqrt( L2 ) ; 線分p_cp0の中間点 p2(0) = ( p0(0) + p_c(0) ) / 2 p2(1) = ( p0(1) + p_c(1) ) / 2 ; 中心p2、p_cとp0に接する円の半径 r2 = L * 0.5 r3 = 2 * r2 * r2 if( r3 < 1 ){ is_zero = 1 return } ;cp_c(or cp0)-p_c-p0の角度を a とすると、余弦定理により cos_a = 1.0 - ( rc * rc ) / r3 if( cos_a < -1.0 || cos_a > 1.0 ){ is_zero = 1 return } is_zero = 0 sin_a = sqrt( 1.0 - cos_a * cos_a ) ;p0を平行移動(-p2)→回転移動(±a)→平行移動(p2) ;要するにp2を中心に角度±a[rad]だけ回転 ;平行移動 -p2 sld(0) = p0(0) - p2(0) sld(1) = p0(1) - p2(1) ;回転移動 +a cp_c(0) = cos_a * sld(0) - sin_a * sld(1) cp_c(1) = sin_a * sld(0) + cos_a * sld(1) ;回転移動 -a cp0(0) = cos_a * sld(0) + sin_a * sld(1) cp0(1) = - sin_a * sld(0) + cos_a * sld(1) ;平行移動 +p2 cp_c(0) = cp_c(0) + p2(0) cp_c(1) = cp_c(1) + p2(1) cp0(0) = cp0(0) + p2(0) cp0(1) = cp0(1) + p2(1) return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 描画 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; *Draw color 255,255,255 DrawLine 0, -1000, 0, 1000 DrawLine -1000, 0, 1000, 0 if( is_zero ){ ;p0 color 127, 127, 255 DrawCircleV p0, rc, 1 color 0, 0, 255 DrawPointV p0 DrawCircleV p0, rc, 0 ;p_c color 255, 0, 0 DrawPointV p_c return } ;p0 color 127, 127, 255 DrawCircleV p0, rc, 1 color 0, 0, 255 DrawPointV p0 DrawCircleV p0, rc, 0 ;p_c color 255, 0, 0 DrawPointV p_c color 255, 0, 255 DrawPointV cp_c DrawPointV cp0 DrawLineV p_c, cp_c DrawLineV p_c, cp0 return