#!/usr/bin/env ruby

# 渦巻きをcurvetoで描くための座標を計算するためのRubyスクリプト
# zmp@s1.xrea.com

option_precise = false  # 詳細描画をしたければtrue
option_precise_partly = true  # 最後の2周だけ詳細描画をしたければtrue

# 度数法に対する sin, cos, tan
def degree_sin(angle); Math::sin(angle.to_f * Math::PI / 180.0); end
def degree_cos(angle); Math::cos(angle.to_f * Math::PI / 180.0); end
def degree_tan(angle); Math::tan(angle.to_f * Math::PI / 180.0); end

def rotatePoints(angle, points)
  # 角度angleに応じて，座標点(2値配列)の配列の各要素を回転して返す．

  points.collect do |point|
    x = point[0]
    y = point[1]
    s = degree_sin(angle)
    c = degree_cos(angle)

    [x * c - y * s, x * s + y * c]
  end
end

def calcDivPoint(p1, p2, n1, n2)
  # 2つの点p1, p2について，n1:n2 の比で内分する点を返す．

  n1 = n1.to_f
  n2 = n2.to_f

  [(p1[0] * n2 + p2[0] * n1) / (n1 + n2), 
    (p1[1] * n2 + p2[1] * n1) / (n1 + n2)]
end

def calcPoints(r1, r2, angle)
  # (r1, 0)〜(r2 * degree_sin(angle), r2 * degree_cos(angle))の弧を
  # curvetoで描くための制御点(2値配列の配列)を返す．

  return []  if r1 <= 0 || r2 <= 0

  r1 = r1.to_f
  r2 = r2.to_f
  angle = angle.to_f

  s = degree_sin(angle)
  c = degree_cos(angle)
  t = degree_tan(angle)

  p0 = [r1, 0.0]
  p1 = [r1, -1 / t * (r1 - r2 * c) + r2 * s]
  p2 = [r2 * c, r2 * s]

  points = []

  # この1.8は試行錯誤によるもの．
  points.push(calcDivPoint(p0, p1, 1.8, 1.0))
  points.push(calcDivPoint(p1, p2, 1.0, 1.8))

  points.push(p2)

  points
end

# ここからメイン
r1 = 160.0  # 最初の半径
distance_per_rotation = 20.0  # 1周で減少する半径
division0 = (ARGV.shift || 30).to_i # 渦の1周を描く際の分割数．360の約数であること．
if division0 <= 0 then division0 = 30 end

# 最初の座標
points = [[r1, 0.0]]

# 周回ごとにループ
(r1 / distance_per_rotation).to_i.downto(1) do |j|
  if option_precise || (option_precise_partly && (j == 1 || j == 2))
    division = division0 * 2
  else
    division = division0
  end
  divangle = 360 / division

  # 渦巻きの1周，座標で言うと(r1, 0)〜(r1 - distance_per_rotation, 0)を，
  # division個に分割してcurvetoで描くための座標を求め，
  # 配列pointに格納していく．
  # ただし最後の1周では，最後のdivision/4個の座標を求めない．
  (j == 1 ? division * 3 / 4 : division).times do |i|
    r2 = r1 - distance_per_rotation / division.to_f
    angle = (i * divangle) % 360
    points += rotatePoints(angle, calcPoints(r1, r2, divangle))
    r1 = r2
  end
end

# 各点を出力
points.each do |point|
  printf "%8.5f, %8.5f\n", point[0], point[1]
end
