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);
);
);
);
);