###############################################################################
#    *任意形状の筒状データを作る                                              #
#     "Phoenics轆轤"                                       by Masamori ENDO   #
###############################################################################
#使用方法:csvファイルに以下のようなデータを用意する.
#   起動すると,「形状横幅」「構成面数」を聞いてくる.
#   z0      r0
#   z1      r1
#   z2      r2
#   .       .
#   .       .
#   z(n-1)  r(n-1)
#   このn組みのデータを(z方向位置,半径)と見なして,半円筒状形状を作成.
#   実際には「構成面数」の多面体が作られる.
#   z, rの大きさは任意に設定可能.ただし半径が形状横幅を超えないこと.
#   穴は(1, 0.5, 1)の直方体の中に,半径(r/Wid),長さはz=0からz=1まで貫通で
#   定義される.

#Ver 1.00 06/12/16 初版.
#Ver 1.01 06/12/17 円形の穴形状を作るよう変更
#Ver 1.02 06/12/28 轆轤として汎用化

#-----------------------------------------------------------------------------
# サブルーチン:shapeinput
#     $mach[][0] r座標
#     $mach[][1] z座標
#     $li        データの個数
#     戻り値:最大の半径
sub shapeinput {
  local ($In_Filename)   = $_[0];  # 入力ファイル名
  open (INFILE, "<$In_Filename");
  $li = 0;
  $Mwid = 0;
  while(1) {
    $cline = ;
    if ($cline eq "") {last;}
    split(',',$cline);
    for ($i = 0; $i < 2; $i++) {
      $mach[$li][$i] = @_[$i];
    }
    if($Mwid<$mach[$li][1]) {$Mwid = $mach[$li][1]}
    $li++;
  }
  close(INFILE);
  return $Mwid;
}


#-----------------------------------------------------------------------------
# サブルーチン:pointoutput
#     pointoutput(x,y,z);
#              x x座標
#              y y座標
#              z z座標
# Phoenicsの形状ファイルに適合した形になおして出力.
# ファイルハンドラはOUFILEで決め打ちとする.
#
sub pointoutput {
  $tmp = sprintf "  %E  %E  %E\n", @_[0]/$Wid ,@_[1]/$Hgt,@_[2]/$Len;
  printf OUFILE "%s",substr($tmp, 0,8);
  printf OUFILE "%s",substr($tmp,10,2);
  printf OUFILE "%s",substr($tmp,13,2);
  printf OUFILE "%s",substr($tmp,15,8);
  printf OUFILE "%s",substr($tmp,25,2);
  printf OUFILE "%s",substr($tmp,28,2);
  printf OUFILE "%s",substr($tmp,30,8);
  printf OUFILE "%s",substr($tmp,40,2);
  printf OUFILE "%s",substr($tmp,43,2);
  printf OUFILE "\n";
}


#-----------------------------------------------------------------------------
# サブルーチン:faceoutput
#     faceoutput(p1, p2, p3, p4, offset, rotation);
#              p1, p2, p3, p4 4つのindex
#              offset         indexに足される数値
#              rotation       回転方向(1: 入力順  0: 逆順)
# Phoenicsの形状ファイルに適合した形になおして出力.
# ファイルハンドラはOUFILEで決め打ちとする.
#
sub faceoutput {
  if(@_[5]>0) {
    printf OUFILE "   %-3d  %-3d  %-3d  %-3d   133\n",
          @_[4]+@_[0], @_[4]+@_[1], @_[4]+@_[2], @_[4]+@_[3];
  }
  else {
        printf OUFILE "   %-3d  %-3d  %-3d  %-3d   133\n",
          @_[4]+@_[3], @_[4]+@_[2], @_[4]+@_[1], @_[4]+@_[0];
  }
}


#-----------------------------------------------------------------------------
# メインルーチン
# グローバル変数一覧
$shape_n        ;  #形状ファイルデータ数
@mach           ;  #ノズル形状データ
$Len            ;  #形状のz方向長さ.読み込みファイルで決定
$Hgt            ;  #Shapeのy方向実長さ
$Wid            ;  #Shapeのx方向実長さ
$cn             ;  #半円を構成するポイント数
$fname          ;  #入力/出力ファイル名
$pi       = 3.14159265;


#-------------------------
# フィアル名,ポイント数を入力.
#
print "ファイル名,形状横幅,側面の面数を入力して下さい.\n例:XXXX.csv 1.5 12\n";
$kin =<>;
chomp $kin;
split('\s', $kin);
$fname = $_[0];
$Wid   = $_[1];
$Hgt   = $Wid/2.0;
$cn    = $_[2];


#-------------------------
# 現在の時刻を計算
#
($sec, $min, $hour, $day, $mon, $year, $wdy, $yday, $isdst) = localtime(time);
$year += 1900;
$mon++;


#-------------------------
# 形状ファイル読み込み
#
$Mwid = shapeinput($fname);
$shape_n = @mach;
$Len =$mach[shape_n-1][0];

print "Number of read data = $shape_n\n";
print "Last length         = $Len\n";
print "Max width           = $Mwid";
print "Faces               = $cn\n";
if($Mwid>$Wid) {
  print "データ最大が形状定義範囲をはみ出しています.エラー終了\n";
  exit(-1);
}

#-------------------------
# 出力ファイル名生成
#
$fname=~s/(.*)\.(.*)/$1/;
$fname = $fname.".dat";
print "出力ファイル:$fname";


#-------------------------
# 形状生成:まずはヘッダを書き出す
# ファイル名は"nozzleshape.dat"
#
open (OUFILE, ">$fname");
printf OUFILE "\* Shape file generated by Rokuro.pl\n";
printf OUFILE "\* Date and time:",;
printf OUFILE "%04d/%02d/%02d ",   $year, $mon, $day;
printf OUFILE "%02d:%02d:%02d\n",  $hour, $min, $sec;


#-------------------------
# 出力ファイル生成:Points生成
#
printf OUFILE "\* Number of points:\n";
printf OUFILE "   %3d\n", $cn*$shape_n+2; #ポイント数は側面+中心

for ($zn = 0; $zn < $shape_n; $zn++) {    #側面に点を置いて行く
  $z = $mach[$zn][0];
  for($tn = 0; $tn < $cn; $tn++) {
    $theta = $pi/($cn-1)*$tn;
    $xs = cos($theta)*$mach[$zn][1];
    $ys = sin($theta)*$mach[$zn][1];
    pointoutput($Wid/2.0-$xs, $ys, $z);
  }
}

pointoutput($Wid/2, 0.00, 0.00); #
pointoutput($Wid/2, 0.00, $Len); #


#-------------------------
# 出力ファイル生成:Faces生成
#
printf OUFILE "\* Number of faces:\n";
printf OUFILE "   %3d\n", ($cn-1)*($shape_n-1)+($shape_n-1)+($cn-1)*2;

#------------------------------------------------ 内側
for ($zn = 0; $zn < $shape_n-1; $zn++) {
  for($tn = 1; $tn < $cn; $tn++) {
    faceoutput($zn*$cn+$tn, $zn*$cn+$tn+1, ($zn+1)*$cn+$tn+1, ($zn+1)*$cn+$tn, 0 ,0);
  }
}


#------------------------------------------------ 側面
for ($zn = 0; $zn < $shape_n-1; $zn++) {
  faceoutput($zn*$cn+1, ($zn+1)*$cn+1, ($zn+2)*$cn, ($zn+1)*$cn, 0 ,0);
}


#------------------------------------------------ 下面
$P1  = $cn*$shape_n + 1;
$ofs = 0;
for ($tn = 1; $tn < $cn; $tn++) {
  faceoutput($tn+$ofs, $tn+1+$ofs, $P1, $tn+$ofs, 0, 1);
}


#------------------------------------------------ 上面
$P1  = $cn*$shape_n + 2;
$ofs = $cn*($shape_n-1);
for ($tn = 1; $tn < $cn; $tn++) {
  faceoutput($tn+$ofs, $tn+1+$ofs, $P1, $tn+$ofs, 0, 0);
}

close (OUFILE);