Hatena::ブログ(Diary)

Asymptote 問題集

2013-01-26

Asymptote 《関数編》

line bisector() -- 二等分線を作る -- import geometry

line bisector(point , point) :二つの点でできる線分の垂直二等分線を作る

f:id:denpoya:20100323230411j:image

point P=(4,0) , Q=(0,5);
dot("$P$",P,E);
dot("$Q$",Q,W);

line m = bisector(P,Q);
draw(m);

となれば,垂直の記号を図に書き込みたくなります。

f:id:denpoya:20100323233143j:image

line p = line(P,Q);
point M = intersectionpoint(p,m);
markrightangle(p.A , M , m.A , size=5mm);

draw(P--Q , dashed);

のように,markrightangle(point , point , point) 関数を使えば実現できます。生成された直線で直線上の点があらわでなくても,m.A のように指定することができます。

 ついでに,PM=QM を表す記号もつけたくなります。

 上記の draw 関数引数を下記のように変えます。また,点M も表示します。

f:id:denpoya:20100324002342j:image

draw(P--Q,dashed, StickIntervalMarker(2,2));

dot("$M$",M ,2S+.5W);

 P--Q のように線分を表すのは無骨すぎると思うときには, segment(P,Q) のように表すこともできます。

 StickIntervalMarker(int , int) 関数の第1引数は,線分の分割数を指定しています。二等分するときには "2" を指定します。第2引数は,記号の線の本数を指定しています。"3" にすれば3本線の記号が表示されます。


line bisector(line , line) :二つの直線でできる角のうち,指定した2直線で時計回りにできる角の二等分線を作る

f:id:denpoya:20100324131542j:image

point P=(0,4), Q=(5,0);
line p = line(P,Q);
dot("$P$",P,E+.5N);dot("$Q$",Q,E+.5N);draw("$p$",p);
line l = line((0,0),(5,3));
draw(l);

point M = intersectionpoint(p,l);

line m = bisector(p,l);
draw("$m$",m);

dot("$M$",M ,2S);

 もう一方の角の二等分線は,line bisector(line , line , real) 関数の第3引数を "90" にして,90度回転させることで得ることができます。

f:id:denpoya:20100324131839j:image

line m = bisector(p,l,90);
draw("$m$",m);

dot("$M$",M ,2W);

 次に,角が等しい記号を書いてみましょう。

  • 直角を表す関数は,
    markrightangle(point , point , point)
    でした。
  • 弧を描いて等しい角を表す関数は,
    markangle(point , point , point , StickIntervalMarker(i=2,n=1))
    です。

 markangle 関数で,弧を描き,StickIntervalMarker 関数で,短い線分を描きます。

 StickIntervalMarker 関数引数のうち,"i=2" は,指定された角を分割して描く線分の個数です。もう一つの引数 "n=1" は,短い線分の本数を指定します。

f:id:denpoya:20100324134601j:image

markangle(l.A , M , p.B , StickIntervalMarker(i=2,n=1));

 弧の半径が大きいようです。半径を半分に,また,描く弧を2重線にしてみましょう。

f:id:denpoya:20100324142039j:image

markangle(2 , radius=0.5*markangleradius() ,
          l.A , M , p.B , StickIntervalMarker(i=2,n=1));

 弧を描くためだけに,2直線 l と p の交点 M を求めていました。交点を使わず,2直線で角を指定できます。

f:id:denpoya:20100324143029j:image

markangle(2 , radius=0.5*markangleradius() ,
          l , p , StickIntervalMarker(i=2,n=1));

 直線 l の起点が逆のようです。そこで,

markangle(2 , radius=0.5*markangleradius() ,
          reverse(l) , p , StickIntervalMarker(i=2,n=1));

f:id:denpoya:20100324143206j:image

 うまくできました。



line perpendicular() -- 垂線を作る -- import geometry

line perpendicular(point , line) :point を通り,line に垂直な直線を作る

triangle triangle() -- 三角形を作る -- import geometry

triangle t = triangle(point , point , point) :三点を指定して三角形を作る

f:id:denpoya:20100323222932j:image

point P=(4,0) , Q=(0,1) , R=(3.5,3);
triangle t = triangle(P,Q,R);
show(t);

 のように,インスタンス t を作った場合でも,各点の名前は引数の順に点A,点B,点Cとなり,辺を参照する変数もそれぞれ t.BC , t.CA , t.AB となります。また,点に向かい合う辺に小文字の名前 "a","b","c" が与えられます。

triangle t = triangle(real , real , real) :三辺の長さを指定して三角形を作る

f:id:denpoya:20100323223128j:image

triangle t = triangle(3 , 4 , 5);
show(t);

circle circle();-- 円を作る -- import geometry

  • circle circle(point , real):中心 と 半径 で円を作る
  • circle circle(point , point):直径とする2点で円を作る
  • circle circle(point , point , point):3点を通る円を作る
  • circle incircle(point , point , point): 3点でできる三角形の内接円を作る

全て1度に作ってしまいます。

3点A,B,C,を指定し、点Aを中心とする円がC1、辺ACを直径とする円がC2、三角形の外接円がC3そして、三角形の内接円がC4です。

f:id:denpoya:20130126011619j:image

import geometry;
size(7cm,0);

point A=(4,3), B=(0,0), C=(5,0);

triangle t = triangle(A,B,C);
draw(t, red);
dot("$A$", A,S+.5W);
dot("$B$", B,W);
dot("$C$", C);

circle c1 = circle(A, 1);
draw(c1);
dot("$C_1$",c1.C,N);

circle c2 = circle(A, C);
draw(c2);
dot("$C_2$",c2.C,NE);

circle c3=circle(A,B,C);
draw(c3);
dot("$C_3$",c3.C,2W);

circle c4=incircle(A,B,C);
draw(c4);
dot("$C_4$",c4.C,N);

line tangent();-- 円の接線を作る -- import geometry

円cの中心 c.C と円の中心以外の点Pを結ぶ半直線と円cとの交点Tは、

point T = point(c, P);

で得ることができます。

f:id:denpoya:20130126010828j:image

import geometry;
unitsize(1cm);

circle c = circle((0,0), (3,0));
point P = (2,0);

point T = point(c, P);

draw(c);
dot("$c.C$", c.C, W);
dot("$P$", P);

dot("$T$", T);

2種類の接線を引きます。

円周上の1点に接する接線と、円の外側の1点から引く接線です。

  • line tangent(circle, point) :半直線c.CPと円との交点での接線を作る
  • line[] tangents(circle, point) :外部の点Pを通る接線を作る

f:id:denpoya:20130126011737j:image

import geometry;
unitsize(1cm);

circle c = circle((0,0), 2);
point P = (5,-3);

point T = point(c, P);
// 点Tを接点とする接線を求める。
line l = tangent(c, P);
draw("$l$", l);

// 外部の点Pを通る接線の、接点を求める。
point[] Tm = intersectionpoints(c, circle(c.C, P));

line[] m = tangents(c, P);

draw(m[0]);
dot("$T_1$", Tm[0], S);
draw(m[1]);
dot("$T_2$", Tm[1], NE);

draw(c);
dot("$c.C$", c.C, W);

dot("$T$", T, W);
dot("$P$", P, S+W);

座標軸

座標軸の表示の基本

 まずは座標軸だけを描いて見ましょう。以後は、縦10cm、横10cm の大きさに固定します。

f:id:denpoya:20110810152600j:image

unitsize(x=1cm);
import graph;  

real Xmin = -5, Xmax = 5;
real Ymin = -5, Ymax = 5;

xlimits( Xmin, Xmax);
ylimits( Ymin, Ymax);
xaxis();
yaxis();

labelx("$O$",0,SW);
dot((0,0));

 まず矢印とx、yの表示を加えてみましょう。

f:id:denpoya:20110810154841j:image

xaxis(Label("$x$",align=2E), Arrow(2mm));
yaxis(Label("$y$",align=2N), Arrow(2mm));

 次は、目盛りをつけます。

xaxis(Label("$x$",align=2E), Ticks(modify=NoZero, begin=false, end=true), Arrow(2mm));

f:id:denpoya:20110810155728j:image

 おや?矢印の表示のために5mmほど先端が延びて、目盛りがついてしまうようですね。

では、Xmax の値を少し減らしてみましょう。

xlimits( Xmin, Xmax - .1);

 ついでに、y軸のほうは目盛りだけで、数値なしにしてみます。

yaxis(Label("$y$",align=2N), Ticks("%", begin=false, end=true),Arrow(2mm));

f:id:denpoya:20110810184616j:image

 目盛りの線の長さを調節したいですね。

長いほうは、『Size=‥』

短いほうは、『size=‥』

で指定できます。

xaxis(Label("$x$",align=2E), Ticks(modify=NoZero, begin=false, end=true, Size=1mm, size=.7mm), Arrow(2mm));

f:id:denpoya:20110827222842j:image

 ここまでのソースを書いておきます。

unitsize(x=1cm);
import graph;  

real Xmin = -5, Xmax = 5;
real Ymin = -5, Ymax = 5;

xlimits( Xmin, Xmax - .1);
ylimits( Ymin, Ymax - .1);
xaxis(Label("$x$",align=2E), Ticks(modify=NoZero, begin=false, end=true, Size=1mm, size=.7mm), Arrow(2mm));
yaxis(Label("$y$",align=2N), Ticks("%", begin=false, end=true),Arrow(2mm));

labelx("$O$",0,SW);
dot((0,0));

関数のグラフ

関数の定義
real f(real x) {return x^2/5;}

のように定義できます。

 グラフを描画するには、

graph(f,Xmin,Xmax)

を、draw()の引き数に与えます。

draw(graph(f,Xmin,Xmax));

f:id:denpoya:20110827235429j:image

 ソース

unitsize(x=1cm);
import graph;  

/************************************************************
 *  座標軸の描画を関数定義しました。
 *         使用する前に定義しておく必要があります。
 ************************************************************/
void myAxis(real Xmin, real Xmax, real Ymin, real Ymax) {
  xlimits( Xmin, Xmax - .1);
  ylimits( Ymin, Ymax - .1);
  xaxis(Label("$x$",align=2E), Ticks(modify=NoZero, begin=false, end=true, Size=1mm, size=.7mm), Arrow(2mm));
  yaxis(Label("$y$",align=2N), Ticks(modify=NoZero, begin=false, end=true, Size=1mm, size=.7mm), Arrow(2mm));
  labelx("$O$",0,SW);
  dot((0,0));
}
/***********************************************************/

real Xmin = -5, Xmax = 5;
real Ymin = -5, Ymax = 5;


real f(real x) {return x^2/5;}
draw(graph(f,Xmin,Xmax),red);

myAxis(Xmin, Xmax, Ymin, Ymax);

Asymptote 《関数編》 目次

 使ったことがある関数について,まとめておくことにします。

 書き順は基本的にランダムですが,引数が異なるオーバーロードされている関数は一つにまとまるように記述していきます。(少しずつ追加編集していきます。)

geometry

line bisector() -- 二等分線を作る

1. line bisector(point , point) :二つの点でできる線分の垂直二等分線を作る

    • markrightangle(point , point , point , size=5mm) :直角記号
    • StickIntervalMarker(int , int) :等しい線分を表す記号

 

2. line bisector(line , line) :二つの直線でできる角のうち,小さい角の内側の二等分線を作る

    • markangle(point , point , point) :角を表す記号
    • markangle(point , point , point , StickIntervalMarker(i=2,n=1)) :角の二等分を表す記号
    • markangle(line , line) :角を表す記号
    • markangle(int , line , line) :角を表す記号(弧の本数を指定)
    • markangle( radius=0.5*markangleradius() , line , line) :角を表す記号(弧の半径を指定)

line perpendicular() -- 垂線を作る

1. line perpendicular(point , line) :point を通り,line に垂直な直線を作る


triangle triangle() -- 三角形を作る

1. triangle t = triangle(point , point , point) :三点を指定して三角形を作る

2. triangle t = triangle(real , real , real) :三辺の長さを指定して三角形を作る

circle circle() -- 円を作る

1. circle c = circle(point , real):中心 と 半径 で円を作る

2. circle c = circle(point , point):直径とする2点で円を作る

3. circle circle(point , point , point):3点を通る円を作る

4. circle incircle(point , point , point): 3点でできる三角形の内接円を作る

line tangent();-- 円の接線を作る

1. point T = point(c, P):円の中心 c.C と点Pを結ぶ半直線と円cとの交点T

2. line tangent(circle, point) :半直線c.CPと円との交点での接線を作る

3. line[] tangents(circle, point) :外部の点Pを通る接線を作る




graph

1. 座標軸

2. グラフを描く

2013-01-25

hatena-mode

 円の接線を引くこと。

これは,だいぶ前に調べて分かっていたのですが,

(私のホームページ http://www.denpoya.org では公開していました。)

はてな」の編集がめんどくさくて,サボっていました。

 Emacs の 素晴らしい「はてなの編集モード」を見つけることができました。

http://d.hatena.ne.jp/tarao/20130110/1357821338

 WindowsのEmacs24にインストールするのに手間どってしまいましたが,(flimのmakeでした。makeの環境を整理する必要がありました。)使えるようになり,たいへん楽になりました。

 たいへん感謝しております。これからは,バリバリ(たぶん,ウソ)更新していけるかな,と思います。

2012-01-02

アポロニウス【問題5】の解答

問題5の解答

【問題5】1つの円と2本の直線に接する円

幾何的に作図をしようと思ったのですが,うまい方法が見つからず,解析的に作図をすることにしました。その結果,ソースがかなりプログラムになってしまいました。わかりにくいかとは思いますが,ご容赦ください。

(1) 2本の直線が平行になる場合

f:id:denpoya:20120103010310j:image

(2) 2本の直線が平行にならない場合

f:id:denpoya:20120103010511j:image

f:id:denpoya:20120103010510j:imagef:id:denpoya:20120103010509j:imagef:id:denpoya:20120103010508j:imagef:id:denpoya:20120103010507j:image


(1) 2本の直線が平行になる場合

ソース

import geometry;
unitsize(1cm);

/**
 * 2直線が平行な場合
 *    この2直線の距離が求める接円の直径となる。
 *  そこで,接円の中心をx軸上とし,与えられる円の中心をy軸上とした。
 */

// 2直線と円を与える
real r = 3, R = 2, Y = 2.5;

circle cG = circle((0,Y), R);
line l1 = line((-R,r),(R,r));  // y=r
line l2 = line((-R,-r),(R,-r));// y=-r

// 接円の中心を求める
real x = sqrt((R+r)^2-Y^2);
circle c1 = circle((x,0),r);
circle c2 = circle((-x,0),r);

draw(l1);draw(l2);draw(cG);
draw(c1, red);
dot("$C_1$",c1.C);
draw(c2, red);
dot("$C_2$",c2.C);

(2) 2本の直線が平行にならない場合

ソース

import geometry;
size(0,10cm);

/**
 * 2直線が平行でない場合
 *    この2直線の交点を原点とする。
 *  接円の中心は、2等分線上にある。これをx軸とする。
 *  与えられる2直線は、y=mx , y=-mx で表される。
 *
 *    接円があまり大きくならないように注意しましょう。
 */

// 2直線と円を与える
/**
 *  円が2直線の上側にある
 *real m = 1, R = .5, X = 1, Y = 2;
 */
/**
 *  円が直線のひとつと接している
 *real m = 1, R = sqrt(2)/2, X = 2, Y = 1;
 */
/**
 *  円が直線のひとつと2点で交わる
 *real m = 1, R = 1, X = 2, Y = 1;
 */
/**
 *  円が2直線の右側にある
 *real m = 1, R = .5, X = 1, Y = 0;
 */
/**
 *  円が2直線でできる4つの領域にまたがる
 *real m = 1, R = 1, X = 0, Y =0;
 */

real m = 1, R = 1, X = 0, Y =0;

real sin = m/sqrt(1+m^2);
real cos = 1/sqrt(1+m^2);
// 2直線と円を描く
circle cG = circle((X,Y), R);
line l1 = line((0,0),(1,m));  // y=mx
line l2 = line((0,0),(1,-m)); // y=-mx
draw(l1);draw(l2);draw(cG);

// 判別式
real discriminant(real R, real X, real Y, real sin, real cos){
  real D = (X+R*sin)^2 - cos^2*(X^2+Y^2-R^2);

  return D;
}

/**
 *  接円の中心を求める
 */
real [] zcal(real X, real Y, real sin, real cos){
  real[] x={0,0,0,0};
  if(Y==0){
    x[0] = (X-R)/(1-sin);
    x[1] = (X+R)/(1-sin);
    x[2] = (X-R)/(1+sin);
    x[3] = (X+R)/(1+sin);
  }else{
    real D = discriminant(R, X, Y, sin, cos);
    if(D>=0){
      x[0] = (X+R*sin - sqrt(D))/(cos^2);
      x[1] = (X+R*sin + sqrt(D))/(cos^2);
    }
    real D = discriminant(-R, X, Y, sin, cos);
    if(D>=0){
      x[2] = (X-R*sin - sqrt(D))/(cos^2);
      x[3] = (X-R*sin + sqrt(D))/(cos^2);
    }
  }
  return x;
}
/**
 *  接円を描画する
 */
void drawC(real R, real X, real Y, real sin, real cos, int i=0){
  circle c1,c2;
  real[] z = zcal(X,Y,sin,cos);
  if(i==0){
    if(z[0]!=0){
      c1 = circle((z[0],0),z[0]*sin);
      draw(c1, red);
      dot(format("$C_{%i1}$",i),c1.C);
      if(z[1]!=z[0]){
	c2 = circle((z[1],0),z[1]*sin);
	draw(c2, red);
	dot(format("$C_{%i2}$",i),c2.C);
      }
    }
    if(z[2]!=0){
      c1 = circle((z[2],0),z[2]*sin);
      draw(c1, red);
      dot(format("$C_{%i3}$",i),c1.C);
      if(z[3]!=z[2]){
	c2 = circle((z[3],0),z[3]*sin);
	draw(c2, red);
	dot(format("$C_{%i4}$",i),c2.C);
      }
    }
  }
  z = zcal(Y,X,cos,sin);
  if(z[0]!=0){
    i=1;
    c1 = circle((0,z[0]),z[0]*cos);
    draw(c1, blue);
    dot(format("$C_{%i1}$",i),c1.C);
    if(z[1]!=z[0]){
      c2 = circle((0,z[1]),z[1]*cos);
      draw(c2, blue);
      dot(format("$C_{%i2}$",i),c2.C);
    }
  }
  if(z[2]!=0){
    i=1;
    c1 = circle((0,z[2]),z[2]*cos);
    draw(c1, blue);
    dot(format("$C_{%i3}$",i),c1.C);
    if(z[3]!=z[2]){
      c2 = circle((0,z[3]),z[3]*cos);
      draw(c2, blue);
      dot(format("$C_{%i4}$",i),c2.C);
    }
  }
  
}

real D = discriminant(R, X, Y, sin, cos);
if(D >= 0){
  drawC(R, X, Y, sin, cos);
}else if(D < 0){
  drawC(R, X, Y, sin, cos, 1);
}

2011-08-10

Asymptote 《関数編》 目次

 使ったことがある関数について,まとめておくことにします。

 書き順は基本的にランダムですが,引数が異なるオーバーロードされている関数は一つにまとまるように記述していきます。(少しずつ追加編集していきます。)

geometry

line bisector() -- 二等分線を作る

1. line bisector(point , point) :二つの点でできる線分の垂直二等分線を作る

    • markrightangle(point , point , point , size=5mm) :直角記号
    • StickIntervalMarker(int , int) :等しい線分を表す記号

 

2. line bisector(line , line) :二つの直線でできる角のうち,小さい角の内側の二等分線を作る

    • markangle(point , point , point) :角を表す記号
    • markangle(point , point , point , StickIntervalMarker(i=2,n=1)) :角の二等分を表す記号
    • markangle(line , line) :角を表す記号
    • markangle(int , line , line) :角を表す記号(弧の本数を指定)
    • markangle( radius=0.5*markangleradius() , line , line) :角を表す記号(弧の半径を指定)

line perpendicular() -- 垂線を作る

1. line perpendicular(point , line) :point を通り,line に垂直な直線を作る


triangle triangle() -- 三角形を作る

1. triangle t = triangle(point , point , point) :三点を指定して三角形を作る

2. triangle t = triangle(real , real , real) :三辺の長さを指定して三角形を作る

circle circle() -- 円を作る

1. circle c = circle(point , real):中心 と 半径 で円を作る

2. circle c = circle(point , point):直径とする2点で円を作る

3. circle circle(point , point , point):3点を通る円を作る

4. circle incircle(point , point , point): 3点でできる三角形の内接円を作る

line tangent();-- 円の接線を作る

1. point T = point(c, P):円の中心 c.C と点Pを結ぶ半直線と円cとの交点T

2. line tangent(circle, point) :半直線c.CPと円との交点での接線を作る

3. line[] tangents(circle, point) :外部の点Pを通る接線を作る




graph

  1. 座標軸
  2. グラフを描く

2011-03-11

アポロニウスの【問題3】の作図ができるわけ

 アポロニウスの【問題3】『2点を通り一つの直線に接する円』の作図方法は,

f:id:denpoya:20110312003728j:image

● 直線ABと直線lとの交点をKとし,点Kについて点Bと対称な点をB1とする。

● 直線lについて点Bと対称な点をB2とする。

● このとき,3点A,B1,B2を通る円と直線l との交点T1,T2が,求める円が直線l と接する接点となる。

 なぜ,これで作図ができるのか「?」でしたが,やっと証明することができました。

証明に興味がある方はぜひご覧ください。

証明

f:id:denpoya:20110312005235j:image

f:id:denpoya:20110312005234j:image

f:id:denpoya:20110312005233j:image

f:id:denpoya:20110312005232j:image

f:id:denpoya:20110312005231j:image