E 道具箱

「B 応用編」 以降に作った,もしくは使っているユーザ定義関数です。

ここから Initialization スロットにコピーしてそのまま使えます。

目次は,数字,カタカナ,漢字(読みがあいうえお順)の順に並んでいます。

2次曲線と直線の交点

2次曲線 放物線 y=ax², 楕円 x²/a²+y²/b²=1 ,双曲線 x²/a²-y²/b²=±1

と 直線 y=cx+d の交点のx座標を求める。

【引 数】coeflist=[a,b,c,d],type : 1:放物線 2: 楕円(円) 3: 双曲線 右辺1 4: 双曲線 右辺 -1

【戻り値】組み込み関数 roots() の戻り値。x座標のリスト。交点がなければ虚数が戻る。

【使用例】円 x²+y²=25 と 直線 y=x+1 の交点のx座標を求める。

intersectconic([5,5,1,1],2);

intersectconic(coeflist,type):=(

regional(a,b,c,d,cf);

a=coeflist_1;

b=coeflist_2;

c=coeflist_3;

d=coeflist_4;

if(type==1,cf=[-d,-c,a]);

if(type==2,cf=[a^2*d^2-a^2*b^2,2*d*a^2*c,b^2+a^2*c^2]);

if(type==3,cf=[-a^2*d^2-a^2*b^2,-2*d*a^2*c,b^2-a^2*c^2]);

if(type==4,cf=[-a^2*d^2+a^2*b^2,-2*d*a^2*c,b^2-a^2*c^2]);

roots(cf);

);

2点を通る直線の方程式

2点を通る直線の方程式 ax+by+c=0 の係数リストを返す。

【引 数】2点の座標 または 作図した点の識別名

【戻り値】[a,b,c]

【使用例】2点 (-3,0),(0,2) を通る直線 : coef=lineonpoint([-3,0],[0,2]);

2点 (3,0),(3,2) を通る直線 : coef=lineonpoint([-3,0],[0,2]);

lineonpoint(p1,p2):=(

regional(x1,x2,y1,y2);

x1=p1.x;

y1=p1.y;

x2=p2.x;

y2=p2.y;

if(x1==x2,

[1,0,-x1];

,

[y1-y2,x2-x1,x1*y2-x2*y1];

);

);

2直線の交点

2直線が方程式で与えられている場合

2直線 a1x+b1y+c1=0 ,a2x+b2y+c2=0の交点の座標を求める。

【引 数】coef1,coef2 それぞれの係数リスト [a1,b1,c1],[a2,2,c2]

【戻り値】交点の座標。平行な場合は未定義値。

【使用例】2x-3y+6=0 と x+y-7=0 の交点の座標 (3,4) が戻る。

intersectline([2,-3,6],[1,1,-7])

intersectline(coef1,coef2):=(

regional(mat,vec);

mat=[[coef1_1,coef1_2],[coef2_1,coef2_2]];

vec=[-coef1_3,-coef2_3];

linearsolve(mat,vec);

);

2直線が通る点で与えられている場合

2点p1,p2 を通る直線と 2点p3,p4 を通る直線の交点の座標を求める。

【引 数】p1,p2,p3,p4 2直線が通る点

【戻り値】交点の座標。平行な場合は未定義値。

【使用例】2点(1,1) , (5,2)を通る直線と,(4,0),(1,5)を通る直線の交点を求める。

interll([1,1],[5,2],[4,0],[1,5])

interll(p1,p2,p3,p4):=(

regional(mata,matb,x);

mata=[[p2_1-p1_1,p3_1-p4_1],[p2_2-p1_2,p3_2-p4_2]];

matb=[p3_1-p1_1,p3_2-p1_2];

x=linearsolve(mata,matb);

(1-x_1)*p1+x_1*p2;

);

ベジェ曲線

2次または3次のベジェ曲線を描く。

【引 数】2つの端点と制御点1点または2点の座標のリスト

【戻り値】無意味

【使用例】bezier([A.xy,B.xy,C.xy,D.xy]); (点の識別名だけでは認識されない)

bezier(list):=(

regional(pa,pb,pc,pd);

pa=list_1;

pb=list_2;

pc=list_3;

if(length(list)==3,

plot((1-#)^2*pa+2*t*(1-#)*pb+t^2*pc,stop->1,steps->100);

);

if(length(list)==4,

pd=list_4;

plot((1-#)^3*pa+3*#*(1-#)^2*pb+3*#^2*(1-#)*pc+#^3*pd,stop->1,steps->100);

);

);

扇形

中心と半径を指定した扇形

点paを中心する半径rの,角th1からth2までの扇形を描く。線の太さ,カラーは別途 linesize() ,linecolor() で設定する。

【引 数】pa:中心の座標または点の識別名 r : 半径 th1,th2 角度

【戻り値】無意味

【必要な関数】drawarc()

【使用例】drawsector(A,2,0,pi/4)

drawsector(pa,r,th1,th2):=(

regional(p1,p2);

p1=pa+r*[cos(th1),sin(th1)];

p2=pa+r*[cos(th2),sin(th2)];

drawarc(pa,r,th1,th2);

connect([p1,pa,p2]);

);

中心と半径を指定して中を塗った扇形

点paを中心する半径rの,角th1からth2までの中を塗った扇形を描く。

【引 数】pa:中心の座標または点の識別名 r : 半径 th1,th2 角度

【戻り値】無意味

【使用例】fillsector(A,2,0,pi/4)

fillsector(pa,r,th1,th2):=(

regional(dt,pd);

dt=(th2-th1)/200;

pd=[pa];

forall(0..200,pd=append(pd,pa+r*[cos(th1+#*dt),sin(th1+#*dt)]));

fillpoly(pd);

);

3点を指定した扇形

点Aを中心するBからCまでの扇形を描く。ABとACが等しくないときは短い方を半径とする。

【引 数】pa,pb,pc:中心の座標または点の識別名 r : 半径 th1,th2 角度

【戻り値】無意味

【必要な関数】drawarc() , drawsector()

【使用例】drawsector2(A,2,0,pi/4)

drawsector2(pa,pb,pc):=(

regional(th1,th2,r);

th1=arctan2(pb-pa);

th2=arctan2(pc-pa);

if(th1>=th2,th2=th2+2*pi);

r=min([|pa,pb|,|pa,pc|]);

drawsector(pa,r,th1,th2);

);

3点を指定して中を塗った扇形

点Aを中心として,BからCまでの中を塗った扇形を描く。ABとACが等しくないときは短い方を半径とする。

【引 数】pa,pb,pc:3点の座標または点の識別名

【戻り値】無意味

【必要な関数】fillsector()

【使用例】fillsector(A,B,C)

fillsector2(pa,pb,pc):=(

regional(th1,th2,r);

th1=arctan2(pb-pa);

th2=arctan2(pc-pa);

if(th1>=th2,th2=th2+2*pi);

r=min([|pa,pb|,|pa,pc|]);

fillsector(pa,r,th1,th2);

);

角度の取得

平面上の点p1,p2,p3 に対し、∠p1p2p3を -π〜π の範囲で返す。

【引 数】3点の座標または識別名。リストにはしない。

【戻り値】角の値

【使用例】angle3pt(C,B,A)

angle3pt([2,0],[0,0],[1,1])

angle3pt(p1,p2,p3):=(

regional(z1,z2,z3,z);

z1=complex(p1);

z2=complex(p2);

z3=complex(p3);

if(z1==z2,

0,

z=(z3-z2)/(z1-z2);

arctan2(gauss(z));

);

);

度数法の角度をn°ごとに変

平面上の点p1,p2,p3 に対し、∠p1p2p3を -π〜π の範囲で返す。

【引 数】度数法の角度と,nの値

【戻り値】角の値(度数法)// 度数法の角度をn°刻みに変換

intdeg(th,n):=(

t=text(th);

ep=indexof(text(t),".");

if(ep==0,ep=length(t));

t=substring(t,0,ep-1);

th=floor(parse(t)/n)*n;

th°;

);



中心と半径を指定した弧

【引 数】center:中心の座標または点の識別名 r : 半径

【戻り値】無意味

【使用例】drawarc(A,2,pi/4,3*pi/4);

drawarc([1,1],pi/4,3*pi/4);

drawarc(center,r,th1,th2):=(

plot(center+r*[cos(#),sin(#)],start->th1,stop->th2,steps->200);

);

3点を指定した弧

点Aを中心するBからCまでの反時計回りの弧を描く。ABとACが等しくないときは短い方を半径とする。

【引 数】3点の座標または識別名 A,B,C

【戻り値】無意味

【必要な関数】drawarc()

【使用例】drawarc2(A,B,C);

drawarc2(pa,pb,pc):=(

regional(th1,th2,r);

th1=arctan2(pb-pa);

th2=arctan2(pc-pa);

if(th1>=th2,th2=th2+2*pi);

r=min([|pa,pb|,|pa,pc|]);

drawarc(pa,r,th1,th2);

);

2点を両端とする弧

2点A,Bを両端とする弧を反時計回りに描く。弧の曲がり具合は一定。ただし,関数の定義で th.を変更すると曲がり具合が変わるので,これを引数とすることもできる。

ABを底辺,thを底角とする二等辺三角形の頂点を中心として弧を描いている。

【引 数】2点の座標または識別名 A,B 曲がり具合 d

【戻り値】無意味

【必要な関数】なし

【使用例】drawarc3(A,B);

drawarc3(p1,p2):=(

regional(th,th1,th2,p,z1,z2,z3,r,ev);

th=4*pi/12;

z1=complex(p1);

z2=complex(p2);

r=|p2-p1|/2/cos(th);

ev=(p2-p1)/|p1,p2|;

z3=z1+r*complex(ev)*(cos(th)+i*sin(th));

p=gauss(z3);

th1=arctan2(p1-p);

th2=arctan2(p2-p);

if(th2<th1,th2=th2+360°);

plot([r*cos(t),r*sin(t)]+p,start->th1,stop->th2,steps->50);

);

座標軸

座標軸を指定した範囲で黒で描く。矢じりの有無と大きさはオプション。

矢じりオプションは [1/0,size] または 0 だけ。

1/0 は矢じりの表示/非表示 size は矢じりの大きさ。size を指定するときは,必ずリストにする。

デフォルトは [1,0.4]

表示色を変えたい場合は,関数の中の linecolor() を変える。

【引 数】x,y の範囲(リスト) head 矢じりオプション。

【戻り値】無意味

【副作用】linecolorをデフォルトの青に戻す

【必要な関数】arrowhead()

【使用例】drawaxis([-6,4],[-4,4]);

drawaxis([-6,4],[-4,4],0); // 矢じりを表示しない

drawaxis(rangex,rangey):=drawaxis(rangex,rangey,[1,0.4]);

drawaxis(rangex,rangey,head):=(

regional(x0,x1,y0,y1);

x0=rangex_1; // 軸の範囲

x1=rangex_2;

y0=rangey_1;

y1=rangey_2;

linecolor([0,0,0]);

if(!islist(head),head=[head,0.4]);

draw([[x0,0],[x1,0]]);

draw([[0,y0],[0,y1]]);

if(head_1==1,

if(length(head)>1,hsize=head_2,hsize=0.4);

arrowhead([x1,0],[1,0],hsize);

arrowhead([0,y1],[0,1],hsize);

);

drawtext([x1,0]+[0.2,-0.1],"x");

drawtext([0,y1]+[-0.1,0.2],"y");

// 原点O

drawtext([-0.4,-0.4],"O",size->fsize);

linecolor([0,0,1]);

);

座標軸の目盛

座標軸に目盛と数字を打つ。

目盛の単位はオプションで,[x軸,y軸]のリストで指定。x軸はπも可。πの指定は pi デフォルトは [1,1]

【引 数】x,y の範囲(リスト)

【戻り値】無意味

【副作用】linecolorをデフォルトの青に戻す

【使用例】axisscale([-6,6],[-4,6]);

axisscale([-4,4],[-4,4],[pi,1]);

axisscale(rangex,rangey):=axisscale(rangex,rangey,[1,1]);

axisscale(rangex,rangey,unit):=(

regional(fsize,pch,x0,x1,y0,y1,ux,uy,st,sn,str);

fsize=14; // フォントサイズ

pch=0.4; // 目盛を書くときのすきま

linecolor([0,0,0]);

x0=rangex_1;

x1=rangex_2;

y0=rangey_1;

y1=rangey_2;

ux=unit_1; // 目盛の単位

uy=unit_2;

if(ux!=pi,

st=-floor(-x0/ux)*ux;

sn=floor(-x0/ux)+floor(x1/ux)+1;

repeat(sn,start->st,step->ux,

if(#!=0,

draw([#,-0.05],[#,0.05]);

drawtext([#,-pch],#,align->"center",size->fsize);

);

);

, // x軸の単位がπのとき 目盛は pi/2 ごとに 数字はπごとに

st=-floor(-x0/ux);

sn=floor(-x0/ux)+floor(x1/ux)+1;

repeat(sn*2-1,start->st,step->0.5,

if(#!=0,draw([#*pi,-0.05],[#*pi,0.05]));

);

repeat(sn,start->st,

if(#!=0,

if(#==-1,str="$-\pi$");

if(#==1,str="$\pi$");

if(|#|!=1,str=#+"$\pi$");

drawtext([#*pi,-pch],str,align->"center",size->fsize);

);

);

);

// y軸

st=-floor(-y0/uy)*uy;

sn=floor(-y0/uy)+floor(y1/uy)+1;

repeat(sn,start->st,step->uy,

if(#!=0,

draw([-0.05,#],[0.05,#]);

drawtext([-pch/2,#-pch/2],#,align->"right",size->fsize);

);

);

linecolor([0,0,1]);

);

垂線の足の座標

2点p1,p2を通る直線へ点p3から下した垂線の足の座標を求める。

【引 数】p1,p2,p3 点の座標または作図した点の識別名

【戻り値】垂線の足の座標

【使用例】draw(footofperp(A,B,C));

footofperp(p1,p2,p3):=(

regional(t,uv,foot);

if(|p2-p1|!=0,

uv=(p2-p1)/|p2-p1|;

t=(p3-p1)*uv;

foot=p1+t*uv;

,

println("Warning:p1 is same to p2");

);

foot;

);

直線 ax+by+c=0 を描く

ax+by+c=0 の係数リスト [a,b,c] を与えて直線を描く。定義域を与えることで線分にもなる。線の太さ,カラーは別途 linesize() ,linecolor() で設定する。

【引 数】係数リスト [a,b,c],オプション:定義域リスト range デフォルト [-100,100]

【戻り値】無意味

【使用例】drawling([1,1,-1]);

lineonpoint(p1,p2) と組み合わせて,2点を通る直線を引ける。

drawline(coeflist):=drawline(coeflist,[-100,100]);

drawline(coeflist,range):=(

regional(a,b,c);

a=coeflist_1;

b=coeflist_2;

c=coeflist_3;

if(b==0,

draw(join([-c/a,0],[-c/a,1]));

,

plot(-a/b*#-c/b,start->range_1,stop->range_2);

);

);

点と直線の距離

点と直線の距離を求める。

直線は,通る2点 もしくは ax+by+c=0 の係数のリストで表す。引数の plist が2つの要素からなるリストのときは2点,3つの要素からなるリストのときは係数リストと判断する。エラー処理はなし。

【引 数】p : 点の座標または識別名 plist:2点のリストまたは係数リスト

【戻り値】距離(実数)

【必要な関数】footofperp()

【使用例】distlp(A,[B,C]);

distlp([2,2],[1,-2,7]);

distlp(p,plist):=(

regional(ret,p1,p2,a,b,c);

if(length(plist)==2,

p1=plist_1;

p2=plist_2;

ret=abs(footofperp(p1,p2,p)-p);

);

if(length(plist)==3,

a=plist_1;

b=plist_2;

c=plist_3;

ret=abs(a*p.x+b*p.y+c)/sqrt(a^2+b^2);

);

ret;

);

閉曲線(多角形)の内部/外部の判定

点Pが plistで囲まれる閉曲線(多角形)の中にあるかどうかの判定。plistは閉じていてもいなくてもよい。点の指定は座標または作図した点の識別名。また,多角形は描画されていなくてもよい。

【引 数】点Pの座標,多角形の頂点リスト

【戻り値】ある 1 ない 0 境界線上 2

【必要な関数】angle3pt()

【使用例】pointindomain(D,[A,B,C])

pointindomain(p,plist):=(

regional(n,s,online,th,ret);

if(plist_1!=plist_(-1),plist=append(plist,plist_1));

n=length(plist);

s=0;

online=false;

repeat(n-1,t,

th=angle3pt(plist_t,p,plist_(t+1));

if(abs(th)==pi % th==0,online=true);

s=s+th;

);

if(online,ret=2,

// 次の判定、== だと誤差の関係か、やるたびに結果が異なる

ret=if(abs(s)~=2*pi,1,0);

);

ret;

);

矢印

太さのある矢印

点pt に szの大きさの矢印をcol色で描く。

大きさは画面のスケールによって変わる

【引 数】pt : 点の座標または識別名 sz:大きさ col :RGB

【戻り値】無意味

【使用例】arrow([1,1],0.1,[1,0,0]);

arrow(pt,sz,col):=(

fillpoly([pt,pt+[3*sz,3*sz],pt+[sz,3*sz],pt+[sz,6*sz],pt+[-sz,6*sz],pt+[-sz,3*sz],pt+[-3*sz,3*sz]],color->col);

);

矢じり

点pt に vec の方向で sz の大きさの矢じりをつける。pt は矢じりの先端になる。

形状は,デフォルトで中を塗った楔形。形状や矢じりの開き具合を変えたい場合は,直接関数の中身を書き換える。

【引 数】pt : 点の座標または識別名 sz:大きさ col :RGB

【戻り値】無意味

【使用例】arrowhead(A,[1,1],0.5);

arrowhead(pt,vec,sz,col):=(

regional(th,z1,z2,z3,z,4,z5,p3,p4,p5);

th=pi*8/9; // 矢じりの開き

vec=vec/|vec|;

z1=complex(pt);

z2=complex(vec);

z3=z1+sz*z2*(cos(th)+i*sin(th));

z4=z1+sz*z2*(cos(-th)+i*sin(-th));

z5=z1-sz*0.7*z2; // へこみ具合

p3=gauss(z3);

p4=gauss(z4);

p5=gauss(z5);

// connect([p3,pt,p4],color->col);

fillpoly([pt,p3,p5,p4])

);

矢線

点p1からp2へ,太さsz,矢じりの大きさhszの矢線をcol色で描く。

大きさは画面のスケールによって変わる

【引 数】p1,p2 : 点の座標または識別名 sz,hsz : サイズ(実数)col:RGB

【戻り値】無意味

【必要な関数】arrowhead()

【使用例】arrowline([1,1],[3,2],1,0.3,[1,0,0]);

arrowline(p1,p2,sz,hsz,col):=(

draw([p1,p2],size->sz,color->col);

arrowhead(p2,p2-p1,hsz,col);

);

領域に斜線を引く

2次曲線の領域に斜線を引く。

2次曲線は 放物線 y=ax², 楕円 x²/a²+y²/b²=1 ,双曲線 x²/a²-y²/b²=±1 のいずれか。

(円は楕円で a=b の場合)

引数は coeflist=[[a,b],[p,q]] [a,b]は2次曲線の係数,[p,q]は平行移動量 および,c: 斜線の傾き , range 引く範囲 , inout : 0/1 中/外

【引 数】coeflist,c,range,type,inout

【戻り値】無意味

【必要な関数】intersectconic()

【使用例】「不等式の表す領域」参照

hatchdomain(coeflist,c,range,type,inout):=(

regional(coef,trans,r1,r2,k,rt,d1,d2);

coef=append(coeflist_1,c);

trans=coeflist_2;

r1=range_1;

r2=range_2;

repeat(100,n,start->-50,

k=n/2;

rt=intersectconic(append(coef,k),type);

if(isreal(rt_1),

d1=min(rt)+trans_1;

d2=max(rt)+trans_1;

,

d1=0;

d2=0;

);

if(type==0, // 直線のとき d1=d2

if(inout==1,

plot(c*(#-trans_1)+k+trans_2,start->r1,stop->d1);

,

plot(c*(#-trans_1)+k+trans_2,start->d1,stop->r2);

);

,

if(inout==1,

plot(c*(#-trans_1)+k+trans_2,start->r1,stop->d1);

plot(c*(#-trans_1)+k+trans_2,start->d2,stop->r2);

,

d1=max([d1,r1]);

d2=min([d2,r2]);

plot(c*(#-trans_1)+k+trans_2,start->d1,stop->d2);

);

);

);

);