← 折り紙と数学 技術ノート
図と数値は同じ幾何関数から計算する。数学の処理は src/core.js にまとめ、ビルド時に HTML に埋め込む。展開図データも HTML 内に埋め込む。図の表示に外部のライブラリや通信は使わない。
座標と線対称 正方形は [0,1]×[0,1]、右向きを x、上向きを y とする。直線は上の点 c と単位方向 u で表す。射影を f として、線対称と回転を計算する。
f = c + u(u·(p−c)) p′ = 2f−p 回転中の点 = (fₓ+vₓ cosβ, fᵧ+vᵧ cosβ, s sinβ)
v=p−f、s は折り目からの符号つき距離。β は回転角で、π で鏡映と一致する。図への斜め投影では、奥行きの値を画面の縦方向へ加える。紙の面の3次元座標は、折り目のまわりの回転で求める。
芳賀の交点 P=(1−a,1)、右下の角 R=(1,0)。折り目を PR の垂直二等分線として計算する。移った下辺と x=0 の交点が Q になる。
Q = (0, (1−a)/(1+a)) 1−Qᵧ = 2a/(1+a)
試験する入力は a=0.25, 0.5, 0.75。結果はそれぞれ 0.4, 2/3, 6/7。分数の式だけでなく、鏡映した辺の交点とも照合する。
基本操作の実根 操作1〜5と7は engine/axioms.js と engine/geom.js の幾何式をもとにする。操作6では、有限の区間を走査する方法を、3次以下の多項式の実根を直接求める方法に置き換えた。
点 p の移動先を q(t)=c+tu とし、v=q−p、D=v·v とする。もう1つの点 b を鏡映すると、b′=b−Wv/D、W=2(b−p)·v−D となる。
cross(w,b−d)D − W cross(w,v) = 0
目標の直線を d+sw とした式。D と W は2次以下、cross(w,v) は1次以下なので、全体は3次以下になる。微分した多項式の実根で区間を分け、符号が変わる各区間を二分する。極値が0になる重根も拾う。最後に、両方の鏡映先が目標の直線に乗るかを再検査する。
詳しく — 数値の扱い 幾何計算の基準は 10⁻⁹。操作6の候補の再検査は距離 10⁻⁷ 未満。多項式は各項を最大の絶対値で割って計算する。最上位の項が 10⁻¹³ 未満なら次数を下げる。二分法は各区間で100回行う。根が存在する範囲は、各項から求める上限を使う。
同じ線の候補は重複を除く。点が最初から目標線上にある場合は、その点を通る折り目も調べる。入力が一致して折り目を一意に指定しない退化した場合は、有限の候補だけを表示する。
阿部の三等分とメッサーの比 阿部の図は h=0.2、O=(0,0)、B=(0,2h)。角 θ は40°から85°まで変えられる。φ=θ/3 として O′=(h cotφ,h) を計算し、OO′ の垂直二等分線を折り目にする。
tanθ = (3u−u³)/(1−3u²), u=tanφ
O の鏡映先が y=h、B の鏡映先が角 θ の辺に乗ることを独立に検査する。O′ の座標から計算した角も θ/3 と照合する。
メッサーの図では O=(0,0)、B=(0,1/3)、O′=(1,u)、u=1/(1+∛2)。O を x=1、B を y=2/3 へ乗せる同時条件を検査する。
3u³−3u²+3u−1=0 ((1−u)/u)³=2
頂点と面の順序 山谷の折り線の方向を角度順に並べ、隣の折り線との差を循環して取る。偶数本で、1つおきの角の和が π なら川崎の条件を満たす。山と谷の本数の差の絶対値が2なら前川の条件を満たす。
指定した山谷の確認では、隣より小さい角の両側が山谷の異なる組になる位置を探す。両側の折り目を消し、隣の角を合成して、同じ検査を繰り返す。図の各扇形は折り目で順に鏡映し、面の重なりを描く。
鶴は data/tsuru_final.json の頂点・辺・山谷・面・重なり順を使う。面の表裏の向きは展開図と折った面の符号つき面積から求める。faceOrders の符号にその向きを掛け、下の面から上の面への順序として描く。
150作品の結果は data/theorem_check.json。外周上の頂点を除き、内部頂点3,654個の川崎・前川の成立数を集計した。鶴の54個は、画面でも同じ元座標から角度を計算する。
詳しく — 検査結果の確かめ tools/check_theorems.py は外周、山谷、折り角を調べて内部頂点を集計する。tools/check_negative.py は山谷を1本変える検査と折り線の方向を約1.7°変える検査を行う。材料に記録された結果は、それぞれ3,654個すべてで対応する条件が不成立。数値試験は、同梱された検査結果の集計と鶴の座標を再計算する。
細長い紙 計算例の区間長は [3,1,2,3]。山・谷・山なら、長さ1の区間の両側でクリンプができる。残った区間長は [4,3]。長さ3の端を折ると折り目がなくなる。山・山・山ではクリンプも端の折りも使えない。
クリンプの合成後の長さは l左+l右−l中。上の帯は元の区間と山谷を示す。下の断面は、折り返して求めた x 座標の範囲に水平な線を描き、層を等間隔に積む。折り目は山を赤、谷を青の半円でつなぐ。各ステップで4区間の全24通りの並びを調べ、山谷の向きが合い、線と半円が交差しない並びを選ぶ。折っていない隣の区間は同じ高さにつなぐ。ステップ0は1本の直線、クリンプ後は3層と平らな残り、端を折った後は4層になる。折れない例の山・山・山は、全折り目を畳む全24通りを調べても、山谷が合い、交差しない並びが0通りとなる。図と判定の例は同じ区間長を使う。
厚さと円の配置 ギャリバンの式には厚さ t を mm で入れ、表示する長さ L は m に直す。薄い紙の初期値は0.02 mm、厚い紙は0.10 mm。両方とも計算用の仮定で、製品の実測値ではない。厚さはつまみでも変えられる。
L = (πt/6)(2ⁿ+4)(2ⁿ−1)
断面図では、半分に折るたびに、移す側の面の上下を逆にして層の順序を計算する。もとの紙で隣り合う部分を半円でつなぐ。表示する線が増えた場合は、大きい折り返しにつながる層を選んで表示する。層の高さと半円の半径は、計算した層の順序から求める。
円の配置は、中心から枝分かれする木を用いる。円 i の半径は枝の長さ rᵢ。中心間距離が rᵢ+rⱼ 以上なら、対応する木の距離条件を満たす。1回の「進める」で、重なった円を離して正方形の内側へ戻す計算を12回行う。評価値は、中心から計算した不足距離の二乗和。最小値を保証する手法ではない。表示では 10⁻⁶ 未満を0と扱い、円が収まって重なりがなくなった旨を表示する。数値は小数3桁で表示し、0.001未満の非ゼロ値は有効数字3桁の指数表記を使う。
5章と9章は、ステップ0の円の直径を図の高さとして固定する。縮尺と中心は全ステップで共通とし、途中の折り返しや切って開いた輪郭でも変えない。
一刀切りの鏡映 角幅 π/5 の扇形を10枚使う。直径で半分に折り、角度 2π/5、4π/5、3π/5 の線で順に折る。10枚が角度幅 π/5 の扇形へ重なる。切り線の単位法線を n=(cosγ,sinγ) とし、切り線は n·p=0.55。扇形内の座標を用いて両辺との交点を計算する。切り線は、折った扇形の位置へ 3π/5 回転して描く。
p(β) = 0.55(cosβ,sinβ)/cos(β−γ) β = 0, π/5
各扇形に適用した折り目を逆順にたどり、切り線を元の紙へ鏡映で戻す。10本の線分がつながることと、線分の長さがすべて等しいことを検査する。γ=π/5 では隣の線分が一直線につながり、正五角形になる。切った後の紙も同じ反射の逆順で開く。
三浦折りの閉じた式 辺 a=b=1、鋭角 α=π/3、縦横とも4面で描く。折りのパラメータ θ の範囲は 0≤θ≤α。以下の式は面ごとの位置合わせを繰り返さずに全頂点を求める。
X=a cosθ, H=a sinθ S=b cosα/cosθ, Y=√(b²−S²) vᵢⱼ=(iX+(j mod 2)S, jY, (i mod 2)H)
横の辺ベクトルは (X,0,±H)、縦の辺ベクトルは (±S,Y,0)。長さはそれぞれ a,b、内積の絶対値は XS=ab cosα で一定。各四角形はこの2つのベクトルが作る平面にあるため、面は平らなまま、辺と対角線の長さも変わらない。
幅は4X+S、奥行きは4Y、高さはH。視点の回転後に、面の奥行きの平均値で奥から描く。谷は青の破線、山は赤の実線とする。内部頂点の山谷は3対1または1対3になる。
ビルドと試験 日本語の本文を src/index.html と src/notes.html に書く。tools/build.py が数式用のコードと JSON を埋め込み、同梱した BudouX の日本語モデルで、本文の区切りに改行候補を加える。ビルドに外部パッケージの追加は要らない。
python3 math/tools/build.py
node math/tests/core.test.mjs
node math/tests/page.test.mjs 数学の試験は、図形の距離、鏡映先の条件、交点、3次方程式の実根、三浦折りの辺長・対角線・平面性を検査する。ページの試験は、外部通信の呼び出しがないこと、埋め込んだデータ、各図の初期表示とボタン操作を検査する。
アトリエファクトリーのほかの作品 トップページ AI解説一覧 大学入試の過去問とAI解答 リヴァイア算(高校数学・物理)