###############################################################
# VRMLでヘリカルコイルを描画する
# S. Hirota and M. Aizawa
###############################################################

### パラメータ
$filename = 'helical.wrl';			# 出力ファイル名
$PI = 3.141592653589793;			

&main;

###############################################################
# main
###############################################################
sub main {

	open(FH, ">$filename") || die ("Open Error!!");
	
	### VRMLヘッダﾞ出力
	&put_vrml_header;
	
	### VRMLプロトタイプ宣言出力
	&put_vrml_proto;
	
	# ヘリカルコイルデータ出力
	&put_vrml_helical_coil('0.0 0.9 0.0');
	
	# 円形コイルデータ出力
	$color = '0.5 0.5 1.0';
	&put_vrml_circular_coil(2.6, 0.5, $color);
	&put_vrml_circular_coil(1.6, 0.5, $color);
	&put_vrml_circular_coil(2.6, -0.5, $color);
	&put_vrml_circular_coil(1.6, -0.5, $color);
}

###############################################################
# VRMLファイル ヘッダﾞ出力
###############################################################
sub put_vrml_header {

	print FH "#VRML V2.0 utf8\n";
	print FH "#$filename\n\n";

}

###############################################################
# VRMLファイル プロトタイプ宣言出力
###############################################################
sub put_vrml_proto {

	### コイル断面データ(crossSection)作成
	# パラメータ
	$cs_div = 12;
	$r_cs = 0.03;
	my $cross_section = '';
	for(my $i = 0; $i <= $cs_div; $i++) {
		my $a = $i * 2 * $PI / $cs_div;
		my $x = $r_cs * cos($a);
		my $y = $r_cs * sin($a);
		if($a != 0) { $cross_section .= ", \n"; }
		$cross_section .= "$x $y";
	}
	
	print FH <<HD;		#----- <start of Here Document>
### オブジェクト Tube プロトタイプ宣言出力
PROTO Tube [
	field	MFVec3f	spine	[ 0 0 0, 1 1 1 ]
	field	SFColor	color	1.0 0.5 0.5
] {
	Shape {
		appearance Appearance {
			material Material {
				diffuseColor IS color
			}
		}
		geometry Extrusion {
			spine IS spine
			crossSection[
$cross_section
			]
			beginCap FALSE
			endCap FALSE
			solid TRUE
		}
	}
}

HD
						#----- <end of Here Document>

}

###############################################################
# VRMLファイル Tube インスタンス出力
###############################################################
sub put_vrml_tube {
	my $color;
	$color = "	color $_[1]" if($_[1]);

	print FH <<HD;		#----- <start of Here Document>
### Tube インスタンス
Tube {
	spine [
$_[0]
	]
$color
}
HD
						#----- <end of Here Document>
}

###############################################################
# VRMLファイル ヘリカルコイルデータ出力
###############################################################
sub put_vrml_helical_coil {
	# パラメータ
	my $spine_cnt = 200;
	my $N = 17;
	my $R0 = 2.1;
	my $r0 = 0.3;
	my $spine = '';
	for(my $i = 0; $i <= $spine_cnt; $i++) {
		my $a = $i * 2 * $PI / $spine_cnt;
		my $x = ($R0 + $r0 * cos($N * $a)) * cos($a + $PI);
		my $y = ($R0 + $r0 * cos($N * $a)) * sin($a + $PI);
		my $z = $r0 * sin($N * $a);
		if($a != 0) { $spine .= ", \n"; }
		$spine .= "$x $y $z";
	}
	&put_vrml_tube($spine, $_[0]);
}

###############################################################
# VRMLファイル 円形コイルデータ出力
###############################################################
sub put_vrml_circular_coil {
	# パラメータ
	my $spine_cnt = 30;
	my $R0 = $_[0];
	my $z = $_[1];
	my $spine = '';
	for(my $i = 0; $i <= $spine_cnt; $i++) {
		my $a = $i * 2 * $PI / $spine_cnt;
		my $x = $R0 * cos($a);
		my $y = $R0 * sin($a);
		if($a != 0) { $spine .= ", \n"; }
		$spine .= "$x $y $z";
	}
	&put_vrml_tube($spine, $_[2]);
}
