# GDSII Importer Plugin for Google SketchUp
# Copyright 2007, Akira Tsuchiya

require 'sketchup.rb'
require 'GDSII.rb'

#----------------------------------------------------------------
# 共通クラス
#

#
# XY class
#
class XY
  def initialize
    @x = 0
    @y = 0
  end

  # set (x,y) pair
  def set_xy (x, y)
    @x = x
    @y = y
  end

  #### return values
  def x
    return @x
  end

  def y
    return @y
  end
end
#
# end of common classes
#----------------------------------------------------------------

#----------------------------------------------------------------
# グローバル変数
#

#### 共通
$DEBUG = 0          # 1 にすると ruby console にいくつか情報を表示する

def init_vars
  #### GDS読み込み部分 (read_gds) のグローバル変数
  $strlist = Hash.new # STREAMの要素を格納するハッシュ

  # Sketchup への変換時の倍率
  $userunits = 0      # GDSII の USERUNITS
  $physunits = 0      # GDSII の PHYSUNITS
  $unitscale = 1e7    # Sketchup に変換するときの係数
  $scale = 1          # 倍率 (read_gds で $physunits / $userunits * $unitscale で上書き)
  $hscale = 1.0       # 水平方向のスケーリング (Menu Step 4. で指定，set_units で $scale倍して確定)
  $vscale = 1.0       # 垂直方向のスケーリング (Menu Step 4. で指定，set_units で $scale倍して確定)
  
  #### プロセス情報読み込み部分 (read_process) のグローバル変数
  $layerlist = []     # プロセス情報格納用配列  レイヤー番号を配列の index とする

  #### Sketchup オブジェクト生成用グローバル変数
  $max_cells = 50     # col * row の上限．82 でかなり重い (Menu Step 4. で上書き)
  
  # 基板の大きさ決定用
  $xmin = 9999
  $ymin = 9999
  $xmax = -9999
  $ymax = -9999
  $area_factor = 1.5  # 基板の大きさ (Menu Step 4. で上書き)

  # AREF用ローカル座標
  $local_xy = XY.new
  $local_xy.set_xy(0,0)
end

#
# end of global variables
#----------------------------------------------------------------

#----------------------------------------------------------------
# menu : Sketchup上のメニュー管理
#

#### ファイル指定等のダイアログ表示 -> 変換実行 (convert_gds)
def dialog_create_box

  # 変数初期化
  init_vars

  # Step 1. GDSファイルの指定
  msg = "Step 1/4: GDSII file"
  UI.messagebox msg, MB_OK, "Step 1/3"
  gdsfile = UI.openpanel "GDSII file", "c:\\Program Files\\Google\\Google Sketchup 6\\Plugins\\GDSII\\", "*.gds"
  if(gdsfile) then
    $g = GDS.new(gdsfile)   # GDS読み込み用オブジェクトを生成

  else
    return 1
  end

  # Step 2. プロセス情報ファイルの指定
  gdsfile.sub!(/^.*\\/, "")
  msg = "Step 2/4: Process definition file for " + gdsfile
  UI.messagebox msg, MB_OK, "Step 2/3"
  procfile = UI.openpanel "Process definition file", "c:\\Program Files\\Google\\Google Sketchup 6\\Plugins\\GDSII\\", "*.txt"
  if(procfile) then
    # NOP
  else
    return 1
  end

  # Step 3. トップセル名の指定，デフォルトでは GDS のファイル名を使用
  gdsfile.sub!(/\..*?$/, "")
  results = UI.inputbox ["Top cell name  "], [gdsfile], "Step 3/4"
  topcell = results[0]

  # Step 4. その他調整用パラメータの指定
  results = UI.inputbox ["Area of substrate  ", "Horizontal scaling  ", "Vertical scaling  ", "Max # of array   "], [1.5, 1.0, 1.0, 50], "Step 4/4"
  $area_factor = Float(results[0])
  $hscale = Float(results[1])
  $vscale = Float(results[2])
  $max_cells = Integer(results[3])

  # 変換実行
  convert_gds(procfile, topcell)
end

#### Google SketchUp へのメニュー追加
plugins_menu = UI.menu($exStrings.GetString("Plugins"))
gds_menu = plugins_menu.add_submenu($exStrings.GetString("GDSII Importer"))
gds_menu.add_item($exStrings.GetString("Import")) { dialog_create_box }
#
# end of menu
#----------------------------------------------------------------

#----------------------------------------------------------------
# read_gds : GDSデータの読み込み
#
#require 'GDSII.rb'

####
#### read_gds用クラスの定義
####

# メソッドに重複多いので整理した方がよさげ

#
# STREAM class
#
class Stream
  def initialize
    @strname = ""
    @elements = []
  end

  # set STRNAME
  def set_strname (strname)
    @strname = strname
  end

  # add object to list @elements
  def add_element (obj)
    @elements.push(obj)
  end

  #### return values
  def type
    return "stream"
  end

  def strname
    return @strname
  end

  def elements
    return @elements
  end
end

#
# BOUNDARY class
#
class Boundary
  def initialize
    @layer = 0
    @datatype = 0
    @xy = []
  end

  # set LAYER
  def set_layer (layer)
    @layer = layer
  end

  # set DATATYPE
  def set_datatype (datatype)
    @datatype = datatype
  end

  # add XY to list @xy
  def add_xy (x, y)
    xyobj = XY.new
    xyobj.set_xy(x, y)

    @xy.push(xyobj)
  end

  #### return values
  def type
    return "boundary"
  end

  def layer
    return @layer
  end

  def datatype
    return @datatype
  end

  def xy
    return @xy
  end
end

#
# PATH class
#
class Path
  def initialize
    @layer = 0
    @width = 1
    @datatype = 0
    @pathtype = 0
    @xy = []
  end

  # set LAYER
  def set_layer (layer)
    @layer = layer
  end

  # set DATATYPE
  def set_datatype (datatype)
    @datatype = datatype
  end

  # set PATHTYPE
  def set_pathtype (pathtype)
    @pathtype = pathtype
  end

  # set WIDTH
  def set_width (width)
    @width = width
  end

  # add XY to list @xy
  def add_xy (x, y)
    xyobj = XY.new
    xyobj.set_xy(x, y)

    @xy.push(xyobj)
  end

  #### return values
  def type
    return "path"
  end

  def layer
    return @layer
  end

  def datatype
    return @datatype
  end

  def pathtype
    return @pathtype
  end

  def width
    return @width
  end

  def xy
    return @xy
  end
end

#
# AREF class
#
class Aref
  def initialize
    @sname = ""
    @strans = [0, 0, 0]
    @angle = 0
    @colrow = [0, 0]
    @xy = []
  end

  # set SNAME
  def set_sname (str)
    @sname = str
  end

  # set STRANS
  def set_strans (a, b, c)
    @strans = [a, b, c]
  end

  # set ANGLE
  def set_angle (angle)
    @angle = angle
  end

  # set COLROW
  def set_colrow (col, row)
    @colrow = [col, row]
  end

  # add XY to list @xy
  def add_xy (x, y)
    xyobj = XY.new
    xyobj.set_xy(x, y)

    @xy.push(xyobj)
  end

  #### return values
  def type
    return "aref"
  end

  def sname
    return @sname
  end

  def strans
    return @strans
  end

  def angle
    return @angle
  end

  def colrow
    return @colrow
  end

  def col
    return @colrow[0]
  end

  def row
    return @colrow[1]
  end

  def xy
    return @xy
  end
end

#
# SREF class
#
class Sref
  def initialize
    @sname = ""
    @strans = [0, 0, 0]
    @angle = 0
    @xy = []
  end

  # set SNAME
  def set_sname (str)
    @sname = str
  end

  # set STRANS
  def set_strans (a, b, c)
    @strans = [a, b, c]
  end

  # set ANGLE
  def set_angle (angle)
    @angle = angle
  end

  # add XY to list @xy
  def add_xy (x, y)
    xyobj = XY.new
    xyobj.set_xy(x, y)

    @xy.push(xyobj)
  end

  #### return values
  def type
    return "sref"
  end

  def sname
    return @sname
  end

  def strans
    return @strans
  end

  def angle
    return @angle
  end

  def xy
    return @xy
  end
end


####
#### read_gds用サブルーチン
####

#### set_units : UNITS を読んで倍率を決める
def set_units
  units = $g.return_str.split("\n");

  tmp = units[1].split(/ +/);
  $userunits = Float(tmp[1]);
  tmp = units[2].split(/ +/);
  $physunits = Float(tmp[1]);

  if ($physunits == 0 || $userunits == 0) then
    $scale = 1
  else 
    $scale = $physunits / $userunits * $unitscale;
  end

  $hscale = $hscale * $scale
  $vscale = $vscale * $scale
#  printf "Scale is set to %d\n", $scale if( $DEBUG == 1)
end

#### STREAM の読み込み
def read_str
  # read STRNAME
  $g.read_record
  tmp = $g.return_str.split(/\s+/)
  strname = tmp[1]

  # create Stream object
  $strlist[strname] = Stream.new

  # set strname
  $strlist[strname].set_strname(strname)

  # read GDS untill ENDSTR
  while ( $g.read_record ) do
    read_boundary(strname) if ( $g.return_str =~ /^BOUNDARY/ )
    read_path(strname)     if ( $g.return_str =~ /^PATH/ )
    read_aref(strname)     if ( $g.return_str =~ /^AREF/ )
    read_sref(strname)     if ( $g.return_str =~ /^SREF/ )
    break                  if ( $g.return_str =~ /^ENDSTR/ )
  end

end

#### BOUNDARY の読み込み
def read_boundary (strname)
  bndry = Boundary.new

  # LAYER
  $g.read_record
  tmp = $g.return_str.split(/\s+/)
  bndry.set_layer(Integer(tmp[1]))

  # DATATYPE
  $g.read_record
  tmp = $g.return_str.split(/\s+/)
  bndry.set_datatype(Integer(tmp[1]))

  # XY
  $g.read_record
  xy = $g.return_str.split("\n")
  tmp = xy[0].split(/[\s;]+/)
  num = Integer(tmp[1])

  for i in 1..num do
    tmp = xy[i].split(/[\s;]+/)
    bndry.add_xy(Float(tmp[2]), Float(tmp[4]))
  end

  # add to element list in Stream object
  $strlist[strname].add_element(bndry)
end

#### PATH の読み込み
def read_path (strname)
  path = Path.new

  # LAYER
  $g.read_record
  tmp = $g.return_str.split(/\s+/)
  path.set_layer(Integer(tmp[1]))

  # DATATYPE
  $g.read_record
  tmp = $g.return_str.split(/\s+/)
  path.set_datatype(Integer(tmp[1]))

  # PATHTYPE
  $g.read_record
  tmp = $g.return_str.split(/\s+/)
  path.set_pathtype(Integer(tmp[1]))

  # WIDTH
  $g.read_record
  tmp = $g.return_str.split(/\s+/)
  path.set_width(Float(tmp[1]))

  # XY
  $g.read_record
  xy = $g.return_str.split("\n")
  tmp = xy[0].split(/[\s;]+/)
  num = Integer(tmp[1])

  for i in 1..num do
    tmp = xy[i].split(/[\s;]+/)
    path.add_xy(Float(tmp[2]), Float(tmp[4]))
  end

  # add to element list in Stream object
  $strlist[strname].add_element(path)
end

#### AREF の読み込み
def read_aref (strname)
  aref = Aref.new

  while($g.read_record) do
    if( $g.return_str =~ /^SNAME/) then
      # SNAME
      tmp = $g.return_str.split(/\s+/)
      aref.set_sname(tmp[1])
    elsif( $g.return_str =~ /^STRANS/) then
      # STRANS
      tmp = $g.return_str.split(/[\s,]+/)
      aref.set_strans(Integer(tmp[1]), Integer(tmp[2]), Integer(tmp[3]))
    elsif( $g.return_str =~ /^ANGLE/) then
      # ANGLE
      tmp = $g.return_str.split(/[\s,]+/)
      aref.set_angle(Float(tmp[1]))
    elsif( $g.return_str =~ /^COLROW/) then
      # COLROW
      tmp = $g.return_str.split(/\s+/)
      aref.set_colrow(Integer(tmp[1]), Integer(tmp[2]))
    elsif( $g.return_str =~ /^XY/) then
      # XY
      xy = $g.return_str.split("\n")
      tmp = xy[0].split(/[\s;]+/)
      num = Integer(tmp[1])
      
      for i in 1..num do
        tmp = xy[i].split(/[\s;]+/)
        aref.add_xy(Float(tmp[2]), Float(tmp[4]))
      end
    elsif( $g.return_str =~ /^ENDEL/) then
      break
    end
  end

  # add to element list in Stream object
  $strlist[strname].add_element(aref)
end

#### SREF
def read_sref (strname)
  sref = Sref.new

  while($g.read_record) do
    if( $g.return_str =~ /^SNAME/) then
      # SNAME
      tmp = $g.return_str.split(/\s+/)
      sref.set_sname(tmp[1])
    elsif( $g.return_str =~ /^STRANS/) then
      # STRANS
      tmp = $g.return_str.split(/[\s,]+/)
      sref.set_strans(Integer(tmp[1]), Integer(tmp[2]), Integer(tmp[3]))
    elsif( $g.return_str =~ /^ANGLE/) then
      # ANGLE
      tmp = $g.return_str.split(/[\s,]+/)
      sref.set_angle(Float(tmp[1]))
    elsif( $g.return_str =~ /^XY/) then
      # XY
      xy = $g.return_str.split("\n")
      tmp = xy[0].split(/[\s;]+/)
      num = Integer(tmp[1])

      for i in 1..num do
        tmp = xy[i].split(/[\s;]+/)
        sref.add_xy(Float(tmp[2]), Float(tmp[4]))
      end
    elsif( $g.return_str =~ /^ENDEL/) then
      break
    end
  end

  # add to element list in Stream object
  $strlist[strname].add_element(sref)
end

#### read_gds 本体
def read_gds
  while ($g.read_record) do
    set_units     if( $g.return_str =~ /^UNITS/ )
    read_str      if( $g.return_str =~ /^BGNSTR/ )
    break         if( $g.return_str =~ /^ENDLIB/ )

    puts $g.return_str, "\n" if( $DEBUG == 1 )
  end
end
#
# end of read_gds
#----------------------------------------------------------------

#----------------------------------------------------------------
# read_process : ファイルからレイヤー情報を読み込む
#

####
#### read_process 用クラス定義
####

#
# Layer class
#
class ProcessLayer
  def initialize
    @layer = 0
    @name  = ""
    @abbrv = ""
    @height = 0
    @thick = 0
    @color = "#ffffff".hex
    @alpha = 1
  end

  # set layer#
  def set_layer(int)
    @layer = int
  end

  # set layer name
  def set_name(str)
    @name = str
  end

  # set layer name abbreviation
  def set_abbrv(str)
    @abbrv = str
  end

  # set height from substrate
  def set_height(float)
    @height = float
  end

  # set thickness
  def set_thick(float)
    @thick = float
  end

  # set color
  def set_color(str)
    @color = color_hex(str).hex
  end

  # set alpha
  def set_alpha(float)
    @alpha = float
  end

  #### return values
  def layer
    return @layer
  end

  def name
    return @name
  end

  def abbrv
    return @abbrv
  end

  def height
    return @height
  end

  def thick
    return @thick
  end

  def color
    return @color
  end

  def alpha
    return @alpha
  end
end

#### read_process 本体
def read_process(procfile)
  f = open(procfile)
  while(line = f.gets) do
    next if( line =~ /^\#/ )
    tmp = line.split(/\s+/)

    tmp_obj = ProcessLayer.new
    tmp_obj.set_name(tmp[0])
    tmp_obj.set_layer(Integer(tmp[1]))
    tmp_obj.set_abbrv(tmp[2])
    tmp_obj.set_height(Float(tmp[3]))
    tmp_obj.set_thick(Float(tmp[4]))

    # Material の登録
    m = $materials.add tmp[0]
    m.color = color_hex(tmp[5]).hex
    m.alpha = Float(tmp[6])

    $layerlist[tmp_obj.layer] = tmp_obj
  end
end

#### 16進文字列をいじる
# もうちょっとスマートにできそうな気が
def color_hex(str)
  s = str.sub(/^#/, "")
  rgb = "0x" + s.slice(4,2) + s.slice(2,2) + s.slice(0,2)

  return rgb
end
#
# end of read_process
#----------------------------------------------------------------

#----------------------------------------------------------------
# sketchup オブジェクト生成ルーチン群
#

#### トップセルから全ての要素を生成
def convert_gds(procfile, topcell)
  # sketchup モデルの初期化
  model = Sketchup.active_model
  model.start_operation $exStrings.GetString("GDSII import")

  # Materials の初期化
  $materials = model.materials

  # root entity の作成
  root_entities = model.active_entities

  # プロセス情報読み込み
  read_process(procfile)

  # GDSデータ読み込み
  read_gds

  # top cell から再帰的に生成開始
  box_stream($strlist[topcell], root_entities)

  # substrate, ILD, passivation を生成
  additional_objs(root_entities) if($area_factor > 0)

  # undo用
  model.commit_operation
end

#### オブジェクトを作る
def create_polygon(xy, z, h, entities, mname)
  pts = []
  pt = 0
  for pos in xy do
    pts[pt] = [(pos.x + $local_xy.x) * $hscale, (pos.y + $local_xy.y) * $hscale, z * $vscale]
    pt += 1

    $xmin = pos.x + $local_xy.x if(pos.x + $local_xy.x < $xmin)
    $ymin = pos.y + $local_xy.y if(pos.y + $local_xy.y < $ymin)
    $xmax = pos.x + $local_xy.x if(pos.x + $local_xy.x > $xmax)
    $ymax = pos.y + $local_xy.y if(pos.y + $local_xy.y > $ymax)
  end
  base = entities.add_face pts
  base.material = mname
    
  h = -h if( base.normal.dot(Z_AXIS) < 0 )
    
  base.pushpull(h * $vscale, true)
end

# 対角線指定バージョン
def create_polygon2(x1, y1, x2, y2, z, h, entities, mname)
  pts = []
  pts[0] = [(x1 + $local_xy.x) * $hscale, (y1 + $local_xy.y) * $hscale, z * $vscale]
  pts[1] = [(x2 + $local_xy.x) * $hscale, (y1 + $local_xy.y) * $hscale, z * $vscale]
  pts[2] = [(x2 + $local_xy.x) * $hscale, (y2 + $local_xy.y) * $hscale, z * $vscale]
  pts[3] = [(x1 + $local_xy.x) * $hscale, (y2 + $local_xy.y) * $hscale, z * $vscale]

  $xmin = x1 + $local_xy.x if(x1 + $local_xy.x < $xmin)
  $xmax = x1 + $local_xy.x if(x1 + $local_xy.x > $xmax)
  $xmin = x2 + $local_xy.x if(x2 + $local_xy.x < $xmin)
  $xmax = x2 + $local_xy.x if(x2 + $local_xy.x > $xmax)
  $ymin = y1 + $local_xy.y if(y1 + $local_xy.y < $ymin)
  $ymax = y1 + $local_xy.y if(y1 + $local_xy.y > $ymax)
  $ymin = y2 + $local_xy.y if(y2 + $local_xy.y < $ymin)
  $ymax = y2 + $local_xy.y if(y2 + $local_xy.y > $ymax)

  base = entities.add_face pts
  base.material = mname
  base.back_material = mname
    
  h = -h if( base.normal.dot(Z_AXIS) < 0 )
    
  base.pushpull(h * $vscale, true)
end

# Boundary 用
def create_boundary(xy, z, h, entities, mname)
  # component にするために1つのグループにする
  grp = entities.add_group
  ent = grp.entities

  create_polygon(xy, z, h, ent, mname)
end

# Path 用
# 45度折り曲げには非対応
def create_path(xy, w, z, h, entities, mname)
  # component にするために1つのグループにする
  grp = entities.add_group
  ent = grp.entities

  num = xy.length - 1

  for i in 1..num do
    if( (xy[i-1].x == xy[i].x && xy[i-1].y < xy[i].y) || (xy[i-1].y == xy[i].y && xy[i-1].x < xy[i].x)) then # 上 or 右向き
      x1 = xy[i-1].x - w/2
      y1 = xy[i-1].y - w/2
      x2 = xy[i].x + w/2
      y2 = xy[i].y + w/2
    else # 下 or 左向き
      x1 = xy[i-1].x + w/2
      y1 = xy[i-1].y + w/2
      x2 = xy[i].x - w/2
      y2 = xy[i].y - w/2
    end

    create_polygon2(x1, y1, x2, y2, z, h, ent, mname)
  end

end

#### STREAM の処理
# obj: object, entities: 親entities
def box_stream (obj, parent_entities)
  # セルに対応する group を作る
  group = parent_entities.add_group
  entities = group.entities

  # 要素に応じて分岐
  for obj in obj.elements do
    case obj.type
    when "stream"
      box_stream(obj, parent_entities)
    when "boundary"
      box_boundary(obj, parent_entities)
    when "path"
      box_path(obj, parent_entities)
    when "aref"
      box_aref(obj, parent_entities)
    when "sref"
      box_sref(obj, parent_entities)
    else
      puts "ERROR while reading object list $strlist"
    end
  end
end

#### BOUNDARY の処理 
def box_boundary(obj, parent_entities)
  if( defined? $layerlist[obj.layer].name ) then # 未定義のレイヤーは無視
    z = $layerlist[obj.layer].height
    h = $layerlist[obj.layer].thick

    create_boundary(obj.xy, z, h, parent_entities, $layerlist[obj.layer].name)
  end
end

#### PATH の処理 
def box_path(obj, parent_entities)
  if( defined? $layerlist[obj.layer].name ) then # 未定義のレイヤーは無視
    z = $layerlist[obj.layer].height
    h = $layerlist[obj.layer].thick

    create_path(obj.xy, obj.width, z, h, parent_entities, $layerlist[obj.layer].name)
  end
end

#### AREF の処理
def box_aref (obj, parent_entities)
  # AREFに対応する group を作る
  group = parent_entities.add_group
  entities = group.entities

#  printf "AREF  SNAME: %s, COL: %d, ROW: %d\n", obj.sname, obj.col, obj.row
  current_xy = XY.new
  current_xy.set_xy( $local_xy.x, $local_xy.y )

  col = obj.col
  row = obj.row

  dx = (obj.xy[1].x - obj.xy[0].x) / col
  dy = (obj.xy[2].y - obj.xy[0].y) / row;

  # array
  if(col * row < $max_cells) then
    1.upto(col) { |x|
      1.upto(row) { |y|
        $local_xy.set_xy( current_xy.x + obj.xy[0].x + dx * (x-1), current_xy.y + obj.xy[0].y + dy * (y-1) )
        box_stream($strlist[obj.sname], entities)
      }
    }
  end

  # 座標変換
  transform(obj, group, current_xy)

  $local_xy.set_xy( current_xy.x, current_xy.y )
end

#### SREF の処理
def box_sref (obj, parent_entities)
  current_xy = XY.new
  current_xy.set_xy( $local_xy.x, $local_xy.y )

  group = parent_entities.add_group
  entities = group.entities

  $local_xy.set_xy( current_xy.x + obj.xy[0].x, current_xy.y + obj.xy[0].y )
  box_stream($strlist[obj.sname], entities)

  # 座標変換
  transform(obj, group, current_xy)

  $local_xy.set_xy( current_xy.x, current_xy.y )

end

#### 座標変換
def transform(obj, group, current_xy)
  # ANGLE deg : z軸を中心に回転
  if( obj.angle != 0 ) then
    p_rot = Geom::Point3d.new (current_xy.x + obj.xy[0].x) * $hscale, (current_xy.y + obj.xy[0].y) * $hscale, 0
    v_rot = Geom::Vector3d.new 0,0,1
    angle = 2 * 3.1415926535 * ( obj.angle / 360 )
    t_rot = Geom::Transformation.rotation( p_rot, v_rot, angle )
    group.transform! t_rot
  end

  # STRANS a,b,c : a が 1 だったら x軸について対称，b, c は不明
  if( obj.strans[0] == 1 ) then
    p_tran = Geom::Point3d.new (current_xy.x + obj.xy[0].x) * $hscale, (current_xy.y + obj.xy[0].y) * $hscale, 0
    t_tran = Geom::Transformation.scaling p_tran, 1, -1, 1
    group.transform! t_tran
  end
end

#### substrate, ILD, passivation を作る
def additional_objs(entities)
  puts "BoundingBox: ($xmin, $ymin) - ($xmax, $ymax)" if( $DEBUG == 1 )

  x1 = $xmin - ($xmax - $xmin) * ($area_factor - 1.0) / 2
  y1 = $ymin - ($ymax - $ymin) * ($area_factor - 1.0) / 2
  x2 = $xmax + ($xmax - $xmin) * ($area_factor - 1.0) / 2
  y2 = $ymax + ($ymax - $ymin) * ($area_factor - 1.0) / 2

  # 256: substrate, 257: ILD, 258: passivation
  for i in 256..258 do
    grp = entities.add_group
    ent = grp.entities
    z = $layerlist[i].height
    h = $layerlist[i].thick

    create_polygon2(x1, y1, x2, y2, z, h, ent, $layerlist[i].name)
  end

end
#
# end of sketchup processing routines
#----------------------------------------------------------------

#EOF
