#!/usr/local/bin/perl
#
# usage: prel Involute_Gear.pl

use strict;
use diagnostics;
use Math::Trig;#三角関数を使うモジュール



#--パラメータ
my $Radius = 100;#歯車の内側の円の半径
my $RadiusLarge = 135;#歯車の外側の円の半径
my $CogNum = 12;#歯数
my $CogAngle = 1/8 * pi();#歯の厚さ(歯の底面が占める角度)
my $Interval = 360;#描画の細かさ
my $PlotWidth = 140;#軸を表示する範囲
my $InvoluteLineWidth = 1;#Involuteの線の太さ
my $OtherLineWidth = 1;#その他の線の太さ
my $OriginX = 150;#描画の原点を取る位置(X座標)
my $OriginY = 150;#描画の原点を取る位置(Y座標)



my $Theta = 0;#媒介変数
my @X = ($OriginX + $Radius);
my @Y = ($OriginY);
my @ContactX = ($OriginX + $Radius);
my @ContactY = ($OriginY);
my $i;
my $j;
my $k;
my $TempX;
my $TempY;


open(PS,">Involute_Gear.ps");#PostScriptによるファイル出力
open(SVG,">Involute_Gear.svg");#SVGによるファイル出力

print PS "%!PS-Adobe-3.0
%%BoundingBox: 0 0 ", $OriginX * 2 ," ", $OriginY * 2 ,"
	newpath %x軸
	$OtherLineWidth setlinewidth
	", $OriginX - $PlotWidth ," $OriginY moveto
	", $OriginX + $PlotWidth ," $OriginY lineto
	0.5 0.5 0.5 setrgbcolor
	stroke
	newpath %y軸
	$OtherLineWidth setlinewidth
	$OriginX ", $OriginY - $PlotWidth ," moveto
	$OriginX ", $OriginY + $PlotWidth ," lineto
	0.5 0.5 0.5 setrgbcolor
	stroke
	newpath %内円
	0.5 0.5 0.5 setrgbcolor
	$OtherLineWidth setlinewidth
	$OriginX $OriginY $Radius 0 360 arc
	stroke
	newpath %外円
	0.5 0.5 0.5 setrgbcolor
	$OtherLineWidth setlinewidth
	$OriginX $OriginY $RadiusLarge 0 360 arc
	stroke
	newpath %軸
	0.5 0.5 0.5 setrgbcolor
	$OtherLineWidth setlinewidth
	$OriginX $OriginY ", $Radius*0.01 ," 0 360 arc
	stroke
";
print SVG "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>
	<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">
	<svg width=\"", $OriginX * 2 ,"\" height=\"", $OriginY * 2 ,"\" xmlns=\"http://www.w3.org/2000/svg\">
	<line x1=\"", $OriginX - $PlotWidth ,"\" y1=\"$OriginY\" x2=\"", $OriginX + $PlotWidth ,"\" y2=\"$OriginY\" style=\"stroke:#cccccc; stroke-width:$OtherLineWidth\"/>
	<line x1=\"$OriginX\" y1=\"", $OriginY - $PlotWidth ,"\" x2=\"$OriginX\" y2=\"", $OriginY + $PlotWidth ,"\" style=\"stroke:#cccccc; stroke-width:$OtherLineWidth\"/>
	stroke
	<circle cx=\"$OriginX\" cy=\"$OriginY\" r=\"$Radius\" style=\"stroke:#000000; stroke-width:$OtherLineWidth; fill: none\" >
	</circle>
	<circle cx=\"$OriginX\" cy=\"$OriginY\" r=\"$RadiusLarge\" style=\"stroke:#000000; stroke-width:$OtherLineWidth; fill: none\" >
	</circle>
	<circle cx=\"$OriginX\" cy=\"$OriginY\" r=\"", $Radius*0.01 ,"\" style=\"stroke:#000000; stroke-width:$OtherLineWidth; fill: #000000\" >
	</circle>
";



#--奇跡の計算
$Theta = 0;
while(($X[$#X]-$OriginX)**2+($Y[$#Y]-$OriginY)**2 < $RadiusLarge**2){
	push (@ContactX, $OriginX + $Radius * cos($Theta));
	push (@ContactY, $OriginY + $Radius * sin($Theta));
	push (@X, $OriginX + $Radius * (cos($Theta) + $Theta * sin($Theta)));
	push (@Y, $OriginY + $Radius * (sin($Theta) - $Theta * cos($Theta)));
	$Theta+=2*pi()/$Interval
}
push (@ContactX, $OriginX + $Radius * cos($Theta));
push (@ContactY, $OriginY + $Radius * sin($Theta));
push (@X, $OriginX + $Radius * (cos($Theta) + $Theta * sin($Theta)));
push (@Y, $OriginY + $Radius * (sin($Theta) - $Theta * cos($Theta)));



#--インボリュートの描画
for($k=0 ; $k<2 ; $k++){
	for($j=0 ; $j<$CogNum ; $j++){
		#描画
		print PS "
			newpath
			1 0 0 setrgbcolor
			$InvoluteLineWidth setlinewidth
			$X[0] $Y[0] moveto
		";
		print SVG "<polyline points=\"$X[0] ", $OriginX * 2 - $Y[0];
		$TempX = ($X[0] - $OriginX) * cos(2/$CogNum * pi()) - ($Y[0] - $OriginY) * sin(2/$CogNum * pi()) + $OriginX;
		$TempY = ($X[0] - $OriginX) * sin(2/$CogNum * pi()) + ($Y[0] - $OriginY) * cos(2/$CogNum * pi()) + $OriginY;
		$X[0] = $TempX;
		$Y[0] = $TempY;
		for($i=1 ; $i<$#X ; $i++){
			print PS "$X[$i] $Y[$i] lineto\n";
			print SVG ", $X[$i] ", $OriginX * 2 - $Y[$i];
			
			#回転処理
			$TempX = ($X[$i] - $OriginX) * cos(2/$CogNum * pi()) - ($Y[$i] - $OriginY) * sin(2/$CogNum * pi()) + $OriginX;
			$TempY = ($X[$i] - $OriginX) * sin(2/$CogNum * pi()) + ($Y[$i] - $OriginY) * cos(2/$CogNum * pi()) + $OriginY;
			$X[$i] = $TempX;
			$Y[$i] = $TempY;
		}
		print PS "stroke\n";
		print SVG "\" style=\"stroke:#000000; stroke-width:$InvoluteLineWidth; fill: none\"/>\n";
	}
	
	#歯の反対側のインボリュート曲線の描画のための処理
	for($i=0 ; $i<$#X ; $i++){
		$TempX = ($X[$i] - $OriginX) * cos($CogAngle) + ($Y[$i] - $OriginY) * sin($CogAngle) + $OriginX;
		$TempY = ($X[$i] - $OriginX) * sin($CogAngle) - ($Y[$i] - $OriginY) * cos($CogAngle) + $OriginY;
		$X[$i] = $TempX;
		$Y[$i] = $TempY;
	}
}




print PS "
	showpage
";
print SVG "
	</svg>
";

close(SVG);
close(PS);

