# Open Import Images
proc OpenImportImages { cn } {

    package require img::jpeg
    package require img::png
    package require img::gif
    package require img::bmp

    global sourcedir
    global Open_image Close_image Shift Magnify Display Surface Axis Off
    global Model_rotation_angle Distance Close Frame Apply_all_frames
    global image_size image_posx image_posy
    global num_frames
    global ii_xangle ii_yangle ii_zangle
    global ydistance model_mag
    global x0  y0  z0
    global x0v y0v z0v

    if {[winfo exists .ii$cn]==0} {

    
    # Initialize display data
    for {set j 0} {$j <= [expr $num_frames -1]} {incr j} {
        set image_size($cn,$j) 1.0
        set image_posx($cn,$j) 0
        set image_posy($cn,$j) 0
        set ydistance($cn,$j) 10.0
        set model_mag($cn,$j) 10.0
        set ii_xangle($cn,$j) 0
        set ii_yangle($cn,$j) 0
        set ii_zangle($cn,$j) 0
    }

    # toplevel window
    toplevel .ii$cn
    wm protocol .ii$cn WM_DELETE_WINDOW "CloseImportImages $cn"
    wm title .ii$cn "Swumsuit: Import Images $cn"

    frame .ii$cn.f1 -width 800 -height 800 -bd 0
    for {set j 0} {$j <= [expr $num_frames -1]} {incr j} {
        frame  .ii$cn.f1.$j -width 800 -height 700 -bd 0
        canvas .ii$cn.f1.$j.c1 -width 800 -height 600 -relief flat -bd 0
        frame  .ii$cn.f1.$j.f2 -relief groove -borderwidth 2
        button .ii$cn.f1.$j.f2.b1 -text $Open_image -command "OpenImage $cn $j"
        label  .ii$cn.f1.$j.f2.l1 -text "  $Shift"
        label  .ii$cn.f1.$j.f2.l2 -text "  $Magnify"
        button .ii$cn.f1.$j.f2.b2 -text "$Close_image" -command "CloseImage $cn $j"
        entry  .ii$cn.f1.$j.f2.e1 -textvariable image_size($cn,$j) -width 7
        bind   .ii$cn.f1.$j.f2.e1 <Key-Return> "ChangeImageSize $cn $j"
        entry  .ii$cn.f1.$j.f2.e2 -textvariable image_posx($cn,$j) -width 7
        bind   .ii$cn.f1.$j.f2.e2 <Key-Return> "ChangeImageLocation $cn $j"
        entry  .ii$cn.f1.$j.f2.e3 -textvariable image_posy($cn,$j) -width 7
        bind   .ii$cn.f1.$j.f2.e3 <Key-Return> "ChangeImageLocation $cn $j"
        button .ii$cn.f1.$j.f2.b3 -text "$Apply_all_frames" \
                           -command "ApplyAllFramesImage $cn $j"

        frame  .ii$cn.f1.$j.f3 -relief flat -borderwidth 2
        label  .ii$cn.f1.$j.f3.l3 -text " $Model_rotation_angle"
        label  .ii$cn.f1.$j.f3.l4 -text "  $Magnify"
        label  .ii$cn.f1.$j.f3.l5 -text "  $Distance"
        entry  .ii$cn.f1.$j.f3.e4 -textvariable ii_xangle($cn,$j) -width 7
        entry  .ii$cn.f1.$j.f3.e5 -textvariable ii_yangle($cn,$j) -width 7
        entry  .ii$cn.f1.$j.f3.e6 -textvariable ii_zangle($cn,$j) -width 7
        entry  .ii$cn.f1.$j.f3.e7 -textvariable model_mag($cn,$j) -width 7
        entry  .ii$cn.f1.$j.f3.e8 -textvariable ydistance($cn,$j) -width 7
        button .ii$cn.f1.$j.f3.b1 -text "$Apply_all_frames" \
                           -command "ApplyAllFramesModel $cn $j"
        #checkbutton .ii$cn.f1.$j.f3.c1 -variable dispornot($cn,$j) -text "$Display" \
        #                   -command "ToggleDisplay $cn $j"
        radiobutton .ii$cn.f1.$j.f3.r1 -variable dispstyle($cn,$j) -value 2 -text "$Surface" \
                            -command "ToggleDisplay $cn $j"
        radiobutton .ii$cn.f1.$j.f3.r2 -variable dispstyle($cn,$j) -value 1 -text "$Axis" \
                            -command "ToggleDisplay $cn $j"
        radiobutton .ii$cn.f1.$j.f3.r3 -variable dispstyle($cn,$j) -value 0 -text "$Off" \
                            -command "ToggleDisplay $cn $j"
        global dispstyle
        set dispstyle($cn,$j) 1
        bind   .ii$cn.f1.$j.c1 <ButtonPress-1> "IIRotStart $cn $j %x %y %W"
        bind   .ii$cn.f1.$j.c1 <B1-Motion>     "IIRotMove  $cn $j %x %y"
        bind   .ii$cn.f1.$j.c1 <ButtonPress-3> "IIRotStartZ $cn $j %y %W"
        bind   .ii$cn.f1.$j.c1 <B3-Motion>     "IIRotMoveZ  $cn $j %y"
        bind   .ii$cn.f1.$j.f3.e4 <Key-Return> "IIRot $cn $j"
        bind   .ii$cn.f1.$j.f3.e5 <Key-Return> "IIRot $cn $j"
        bind   .ii$cn.f1.$j.f3.e6 <Key-Return> "IIRot $cn $j"
        bind   .ii$cn.f1.$j.f3.e7 <Key-Return> "DrawSwimmerOnCanvas $cn $j"
        bind   .ii$cn.f1.$j.f3.e8 <Key-Return> "DrawSwimmerOnCanvas $cn $j"


        pack   .ii$cn.f1.$j.f2.b1 -side left -padx 2 -pady 2
        pack   .ii$cn.f1.$j.f2.l1 \
               .ii$cn.f1.$j.f2.e2 \
               .ii$cn.f1.$j.f2.e3 \
               .ii$cn.f1.$j.f2.l2 \
               .ii$cn.f1.$j.f2.e1 \
                              -side left
        pack   .ii$cn.f1.$j.f2.b3 \
                              -side left -padx 10
        pack   .ii$cn.f1.$j.f2.b2 -side right -padx 2 -pady 2

        pack   .ii$cn.f1.$j.f3.l3 \
               .ii$cn.f1.$j.f3.e4 \
               .ii$cn.f1.$j.f3.e5 \
               .ii$cn.f1.$j.f3.e6 \
               .ii$cn.f1.$j.f3.l4 \
               .ii$cn.f1.$j.f3.e7 \
               .ii$cn.f1.$j.f3.l5 \
               .ii$cn.f1.$j.f3.e8 \
                              -side left -pady 0
        pack   .ii$cn.f1.$j.f3.b1 \
                              -side left -padx 10 -pady 0

        pack   .ii$cn.f1.$j.f3.r3 \
               .ii$cn.f1.$j.f3.r2 \
               .ii$cn.f1.$j.f3.r1 \
                                -side right 

        pack   .ii$cn.f1.$j.c1 -side top -fill x
        pack   .ii$cn.f1.$j.f2 -side top -fill x
        pack   .ii$cn.f1.$j.f3 -side top -fill x
    }

    #place  .ii$cn.f1.0 -x 0 -y 0
    pack   .ii$cn.f1.0 -side top -fill x

    # For scale
    frame  .ii$cn.f2 -relief groove -bd 2
    frame  .ii$cn.f2.time
    scale  .ii$cn.f2.s1 -orient horizontal -from 0 -to $num_frames \
                                    -var ajm_time -showvalue false
    bind .ii$cn.f2.s1 <B1-Motion> \
         { UnHilightSegEntry ; HilightSegEntry ; UpdateFrame }
    bind .ii$cn.f2.s1 <ButtonPress-1> \
         { UnHilightSegEntry ; HilightSegEntry ; UpdateFrame }
    bind .ii$cn.f2.s1 <ButtonRelease-1> \
         { UnHilightSegEntry ; HilightSegEntry ; UpdateFrame }
    label  .ii$cn.f2.time.label -text " $Frame: "
    label  .ii$cn.f2.time.time  -text "0/$num_frames" -width 7 -anchor e
    pack .ii$cn.f2.time.label -side left -anchor w
    pack .ii$cn.f2.time.time  -side right
    pack .ii$cn.f2.s1 -side left -expand 1 -fill x
    pack .ii$cn.f2.time -side right

    # For bottom part
    frame .ii$cn.f3
    global sourcedir
    button .ii$cn.f3.play -bitmap @${sourcedir}/bitmap_play.xbm \
                   -command "AjmPlayPause" -width 45 -height 30
    frame  .ii$cn.f3.speed -relief groove -bd 2
    frame  .ii$cn.f3.speed.updown
    button .ii$cn.f3.exit -text " $Close " \
                   -command "CloseImportImages $cn" -height 2
    button .ii$cn.f3.speed.updown.up -bitmap @${sourcedir}/bitmap_up.xbm \
              -command "incr ajm_speed 1 ; AjmSetTimeIncr"
    button .ii$cn.f3.speed.updown.down -bitmap @${sourcedir}/bitmap_down.xbm \
              -command "incr ajm_speed -1 ; AjmSetTimeIncr"
    global Speed
    label  .ii$cn.f3.speed.label -text "$Speed:"
    label  .ii$cn.f3.speed.ratio -text "x1   " -width 5
    pack   .ii$cn.f3.speed.updown.up .ii$cn.f3.speed.updown.down -side top
    pack   .ii$cn.f3.speed.label \
           .ii$cn.f3.speed.ratio .ii$cn.f3.speed.updown -side left
    pack   .ii$cn.f3.speed.updown -side left
    #pack   .ii$cn.f3.play -side left
    pack   .ii$cn.f3.exit -side right -padx 0
    #pack   .ii$cn.f3.speed -side right

    entry .ii$cn.e1 -textvariable ajm_time -width 7

    # Pack all parts
    pack .ii$cn.f1 -side top -fill x
    pack .ii$cn.f2 -side top -fill x -pady 0
    pack .ii$cn.f3 -side top -fill x 

    # load body_gemetry.dat
    if { [file exists body_geometry.dat]==1 } {
        set f [open body_geometry.dat r]
        for {set i 1} {$i<=21} {incr i} {
            gets $f line
            for {set j 1} {$j<=6} {incr j} {
                global bg_val
                set bg_val(s${i}e$j) [expr [lindex $line [expr $j-1]]]
            }
        }
        for {set i 1} {$i<=9} {incr i} {
            gets $f line
            global bg_bu
            set bg_bu($i) [expr $line]
        }
        close $f
    }

    # load joint motion from the edit window
    StoreJointMotion

    # Initialize swimmer's body geometry and position
    global swimmer_initialized
    if {$swimmer_initialized==0} {
        InitializeSwimmer
    }
    set swimmer_initialized 1

    # load display data
    LoadDisplayData $cn

    # draw swimmer for all frames
    for {set j 0} {$j <= [expr $num_frames -1]} {incr j} {
        RotateSegments $j
        DrawSwimmer $cn $j
        IIRot  $cn $j
    }

    ChangeIcon .ii$cn

    } else {
        wm deiconify .ii$cn
    }

    # animation
    global ajm_time_incr
    set ajm_time_incr 0
    #AnimateJointMotion
}


# Update frame
proc UpdateFrame {} {
    global ajm_time num_frames

    for {set k 1} {$k <= 4} {incr k} {
        if {[winfo exists .ii$k]==1} {
            if {$ajm_time==18} { set ajm_time 0 }

            # first all delete
            for {set j 0} {$j <= [expr $num_frames -1]} {incr j} {
                place forget .ii$k.f1.$j
            }
            place .ii$k.f1.$ajm_time -x 0 -y 0

            .ii$k.f2.time.time configure -text "$ajm_time/$num_frames" 
        }
    }
}


# Open image
proc OpenImage { cn j } {
    global idimg1
    global img0w img0h
    global image_size image_posx image_posy
    global imagefile

    if {[info exists imagefile($cn,$j)]==0} {
        set imagefile($cn,$j) [tk_getOpenFile]
    } elseif {$imagefile($cn,$j)==""} { 
        set imagefile($cn,$j) [tk_getOpenFile]
    }
    if {$imagefile($cn,$j)==""} { return }

    image create photo img0$cn$j -file $imagefile($cn,$j)
    set img0w($cn,$j) [image width  img0$cn$j]
    set img0h($cn,$j) [image height img0$cn$j]
    set img1w [expr int($img0w($cn,$j) * $image_size($cn,$j))]
    set img1h [expr int($img0h($cn,$j) * $image_size($cn,$j))]
    catch { .ii$cn.f1.$j.c1 delete $idimg1($cn,$j) }
    image create photo img1$cn$j -width $img1w -height $img1h
    winop resample img0$cn$j img1$cn$j
    set idimg1($cn,$j) \
     [.ii$cn.f1.$j.c1 create image \
         $image_posx($cn,$j) $image_posy($cn,$j) \
                                                   -image img1$cn$j -anchor nw]
    .ii$cn.f1.$j.c1 lower $idimg1($cn,$j)
}


# Close image
proc CloseImage { cn j } {
    global idimg1
    global imagefile
    global Close_image_ok
    set a [tk_messageBox -type okcancel -default cancel -icon question \
            -message $Close_image_ok]
    if {$a=="ok"} {
        catch { .ii$cn.f1.$j.c1 delete $idimg1($cn,$j) }
        set imagefile($cn,$j) ""
    }
}


# Change image sise
proc ChangeImageSize { cn j } {
    global img0w img0h
    global image_size image_posx image_posy
    set img1w [expr int($img0w($cn,$j) * $image_size($cn,$j))]
    set img1h [expr int($img0h($cn,$j) * $image_size($cn,$j))]
    image create photo img1$cn$j -width $img1w -height $img1h
    winop resample img0$cn$j img1$cn$j
}


# Change image location
proc ChangeImageLocation { cn j } {
    global image_size image_posx image_posy
    global idimg1
    .ii$cn.f1.$j.c1 delete $idimg1($cn,$j)
    set idimg1($cn,$j) \
      [.ii$cn.f1.$j.c1 create image \
                $image_posx($cn,$j) $image_posy($cn,$j) \
                                  -image img1$cn$j -anchor nw]
    .ii$cn.f1.$j.c1 lower $idimg1($cn,$j)
}


# Close import images
proc CloseImportImages { cn } {
    wm withdraw .ii$cn
}


# Initialize swimmer's body geometry and position
proc InitializeSwimmer {} {
    global bg_val
    global bg_bu
    global x0 y0 z0
    global x1 y1 z1
    global x2 y2 z2
    global x3 y3 z3
    global x10 y10 z10
    global x20 y20 z20
    global x30 y30 z30

    global xs2ra ys2ra zs2ra xs2ra0 ys2ra0 zs2ra0
    global xs2la ys2la zs2la xs2la0 ys2la0 zs2la0
    global xnb2ha ynb2ha znb2ha xnb2ha0 ynb2ha0 znb2ha0
    global xh2rl yh2rl zh2rl xh2ll yh2ll zh2ll xh2rl0 yh2rl0 zh2rl0 xh2ll0 yh2ll0 zh2ll0
    global xtj2tra ytj2tra ztj2tra xtj2tra0 ytj2tra0 ztj2tra0
    global xtj2tla ytj2tla ztj2tla xtj2tla0 ytj2tla0 ztj2tla0
    global xsh2rf ysh2rf zsh2rf xsh2rf0 ysh2rf0 zsh2rf0
    global xsh2lf ysh2lf zsh2lf xsh2lf0 ysh2lf0 zsh2lf0
    global xfj2ra yfj2ra zfj2ra xfj2ra0 yfj2ra0 zfj2ra0
    global xfj2la yfj2la zfj2la xfj2la0 yfj2la0 zfj2la0
    global xuaj2ra yuaj2ra zuaj2ra xuaj2ra0 yuaj2ra0 zuaj2ra0
    global xuaj2la yuaj2la zuaj2la xuaj2la0 yuaj2la0 zuaj2la0

    # load body_geometry.dat
    if {[file exists joint_motion.dat]==1} {
        set f [open body_geometry.dat r]
        for {set i 1} {$i<=21} {incr i} {
            gets $f line
            for {set j 1} {$j<=6} {incr j} {
                set bg_val(s${i}e$j) [expr [lindex $line [expr $j-1]]]
            }
        }
        for {set i 1} {$i<=9} {incr i} {
            gets $f line
            set bg_bu($i) [expr $line]
        }
        close $f
    }

    # create initial position
    # x0(segment,a(root)/b(tip)) ex. x0(21a)

    # first, set directions of segments
    for {set i 1} {$i<=21} {incr i} {
        if {$i<=7||$i>=16} {
            set x10($i)  1.0
            set y10($i)  0.0
            set z10($i)  0.0

            set x20($i)  0.0
            set y20($i)  1.0
            set z20($i)  0.0

            set x3($i)   0.0
            set y3($i)   0.0
            set z3($i)   1.0
            set x30($i)  0.0
            set y30($i)  0.0
            set z30($i)  1.0

        } else {
            # make lower half of the body downward
            set x10($i) -1.0
            set y10($i)  0.0
            set z10($i)  0.0

            set x20($i)  0.0
            set y20($i)  1.0
            set z20($i)  0.0

            set x3($i)   0.0
            set y3($i)   0.0
            set z3($i)  -1.0
            set x30($i)  0.0
            set y30($i)  0.0
            set z30($i) -1.0
        }
    }

    # rotation of two hip segments
    global xtmp ytmp ztmp rxtmp rytmp rztmp
    set xtmp $x10(8)
    set ytmp $y10(8)
    set ztmp $z10(8)
    set rxtmp 0.0
    set rytmp $bg_bu(7)
    set rztmp 0.0
    VecRot
    set x10(8) $xtmp
    set y10(8) $ytmp
    set z10(8) $ztmp

    set xtmp $x20(8)
    set ytmp $y20(8)
    set ztmp $z20(8)
    set rxtmp 0.0
    set rytmp $bg_bu(7)
    set rztmp 0.0
    VecRot
    set x20(8) $xtmp
    set y20(8) $ytmp
    set z20(8) $ztmp

    set xtmp $x30(8)
    set ytmp $y30(8)
    set ztmp $z30(8)
    set rxtmp 0.0
    set rytmp $bg_bu(7)
    set rztmp 0.0
    VecRot
    set x30(8) $xtmp
    set y30(8) $ytmp
    set z30(8) $ztmp
    set x3(8) $xtmp
    set y3(8) $ytmp
    set z3(8) $ztmp

    set xtmp $x10(9)
    set ytmp $y10(9)
    set ztmp $z10(9)
    set rxtmp 0.0
    set rytmp [expr - $bg_bu(7)]
    set rztmp 0.0
    VecRot
    set x10(9) $xtmp
    set y10(9) $ytmp
    set z10(9) $ztmp

    set xtmp $x20(9)
    set ytmp $y20(9)
    set ztmp $z20(9)
    set rxtmp 0.0
    set rytmp [expr - $bg_bu(7)]
    set rztmp 0.0
    VecRot
    set x20(9) $xtmp
    set y20(9) $ytmp
    set z20(9) $ztmp

    set xtmp $x30(9)
    set ytmp $y30(9)
    set ztmp $z30(9)
    set rxtmp 0.0
    set rytmp [expr - $bg_bu(7)]
    set rztmp 0.0
    VecRot
    set x30(9) $xtmp
    set y30(9) $ytmp
    set z30(9) $ztmp
    set x3(9) $xtmp
    set y3(9) $ytmp
    set z3(9) $ztmp

    #
    # set miscellaneous vectors
    #
    # make vectors from point b of upper breast to shoulder joint
    set xs2ra 0.0
    set ys2ra [expr -$bg_val(s4e4)]
    set zs2ra [expr -$bg_bu(2)]
    set xs2ra0 $xs2ra 
    set ys2ra0 $ys2ra
    set zs2ra0 $zs2ra

    set xs2la 0.0
    set ys2la [expr +$bg_val(s4e4)]
    set zs2la [expr -$bg_bu(2)]
    set xs2la0 $xs2la 
    set ys2la0 $ys2la 
    set zs2la0 $zs2la

    # definite vector from neck-b to head-a 
    set xnb2ha $bg_bu(3)
    set ynb2ha 0.0
    set znb2ha 0.0
    set xnb2ha0 $xnb2ha 
    set ynb2ha0 $ynb2ha
    set znb2ha0 $znb2ha

    # give position of hip joint from lower hip-b
    set xh2rl 0.0
    set yh2rl [expr -$bg_bu(4)]
    set zh2rl [expr +$bg_bu(5)]
    set xh2ll 0.0
    set yh2ll [expr +$bg_bu(4)]
    set zh2ll [expr +$bg_bu(5)]
    set xh2rl0 $xh2rl
    set yh2rl0 $yh2rl 
    set zh2rl0 $zh2rl 
    set xh2ll0 $xh2ll 
    set yh2ll0 $yh2ll 
    set zh2ll0 $zh2ll 

    # definite vector from right hip joint to thigh-a
    set xtj2tra 0.0
    set ytj2tra 0.0
    set ztj2tra [expr -$bg_bu(5)]
    set xtj2tra0 $xtj2tra 
    set ytj2tra0 $ytj2tra 
    set ztj2tra0 $ztj2tra 

    # definite vector from left hip joint to thigh-a
    set xtj2tla 0.0
    set ytj2tla 0.0
    set ztj2tla [expr -$bg_bu(5)]
    set xtj2tla0 $xtj2tla 
    set ytj2tla0 $ytj2tla 
    set ztj2tla0 $ztj2tla 

    # give position of foot joint from right shank-b
    set xsh2rf 0.0
    set ysh2rf 0.0
    set zsh2rf [expr -$bg_bu(6)]
    set xsh2rf0 $xsh2rf 
    set ysh2rf0 $ysh2rf 
    set zsh2rf0 $zsh2rf 

    # give position of foot joint from left shank-b
    set xsh2lf 0.0
    set ysh2lf 0.0
    set zsh2lf [expr -$bg_bu(6)]
    set xsh2lf0 $xsh2lf 
    set ysh2lf0 $ysh2lf 
    set zsh2lf0 $zsh2lf 

    # definite vector from right foot joint to point-a
    set xfj2ra 0.0
    set yfj2ra 0.0
    set zfj2ra [expr +$bg_bu(6)]
    set xfj2ra0 $xfj2ra 
    set yfj2ra0 $yfj2ra 
    set zfj2ra0 $zfj2ra 

    # definite vector from left foot joint to point-a 
    set xfj2la 0.0
    set yfj2la 0.0
    set zfj2la [expr +$bg_bu(6)]
    set xfj2la0 $xfj2la 
    set yfj2la0 $yfj2la 
    set zfj2la0 $zfj2la 

    # definite vector from right upper arm joint to point-a
    set xuaj2ra 0.0
    set yuaj2ra [expr -$bg_bu(1)]
    set zuaj2ra [expr -$bg_bu(2)]
    set xuaj2ra0 $xuaj2ra 
    set yuaj2ra0 $yuaj2ra 
    set zuaj2ra0 $zuaj2ra 

    # definite vector from left upper arm joint to point-a
    set xuaj2la 0.0
    set yuaj2la [expr +$bg_bu(1)]
    set zuaj2la [expr -$bg_bu(2)]
    set xuaj2la0 $xuaj2la 
    set yuaj2la0 $yuaj2la 
    set zuaj2la0 $zuaj2la 
}


# Calculate swimmer's body coordinates and draw it on campus
proc DrawSwimmer { cn j } {
    global bg_val
    global bg_bu
    global x0 y0 z0
    global x0v y0v z0v
    global x1 y1 z1
    global x2 y2 z2
    global x3 y3 z3
    global x10 y10 z10
    global x20 y20 z20
    global x30 y30 z30
    global x1v y1v z1v
    global x2v y2v z2v

    global xs2ra ys2ra zs2ra xs2ra0 ys2ra0 zs2ra0
    global xs2la ys2la zs2la xs2la0 ys2la0 zs2la0
    global xnb2ha ynb2ha znb2ha xnb2ha0 ynb2ha0 znb2ha0
    global xh2rl yh2rl zh2rl xh2ll yh2ll zh2ll xh2rl0 yh2rl0 zh2rl0 xh2ll0 yh2ll0 zh2ll0
    global xtj2tra ytj2tra ztj2tra xtj2tra0 ytj2tra0 ztj2tra0
    global xtj2tla ytj2tla ztj2tla xtj2tla0 ytj2tla0 ztj2tla0
    global xsh2rf ysh2rf zsh2rf xsh2rf0 ysh2rf0 zsh2rf0
    global xsh2lf ysh2lf zsh2lf xsh2lf0 ysh2lf0 zsh2lf0
    global xfj2ra yfj2ra zfj2ra xfj2ra0 yfj2ra0 zfj2ra0
    global xfj2la yfj2la zfj2la xfj2la0 yfj2la0 zfj2la0
    global xuaj2ra yuaj2ra zuaj2ra xuaj2ra0 yuaj2ra0 zuaj2ra0
    global xuaj2la yuaj2la zuaj2la xuaj2la0 yuaj2la0 zuaj2la0

    # calculate x,y,z cooridinates of segment's root and tip
    # 1: lower waist
    set x0($j,1a) 0.0
    set y0($j,1a) 0.0
    set z0($j,1a) 0.0

    set x0($j,1b) [expr $x0($j,1a) + $x3(1) * $bg_val(s1e5)] 
    set y0($j,1b) [expr $y0($j,1a) + $y3(1) * $bg_val(s1e5)] 
    set z0($j,1b) [expr $z0($j,1a) + $z3(1) * $bg_val(s1e5)] 

    # 2: upper waist
    set x0($j,2a) $x0($j,1b)
    set y0($j,2a) $y0($j,1b)
    set z0($j,2a) $z0($j,1b)

    set x0($j,2b) [expr $x0($j,2a) + $x3(2) * $bg_val(s2e5)] 
    set y0($j,2b) [expr $y0($j,2a) + $y3(2) * $bg_val(s2e5)] 
    set z0($j,2b) [expr $z0($j,2a) + $z3(2) * $bg_val(s2e5)] 

    # 3: lower chest
    set x0($j,3a) $x0($j,2b)
    set y0($j,3a) $y0($j,2b)
    set z0($j,3a) $z0($j,2b)

    set x0($j,3b) [expr $x0($j,3a) + $x3(3) * $bg_val(s3e5)] 
    set y0($j,3b) [expr $y0($j,3a) + $y3(3) * $bg_val(s3e5)] 
    set z0($j,3b) [expr $z0($j,3a) + $z3(3) * $bg_val(s3e5)] 

    # 4: upper chest
    set x0($j,4a) $x0($j,3b)
    set y0($j,4a) $y0($j,3b)
    set z0($j,4a) $z0($j,3b)

    set x0($j,4b) [expr $x0($j,4a) + $x3(4) * $bg_val(s4e5)] 
    set y0($j,4b) [expr $y0($j,4a) + $y3(4) * $bg_val(s4e5)] 
    set z0($j,4b) [expr $z0($j,4a) + $z3(4) * $bg_val(s4e5)] 

    # 5: shoulder
    set x0($j,5a) $x0($j,4b)
    set y0($j,5a) $y0($j,4b)
    set z0($j,5a) $z0($j,4b)

    set x0($j,5b) [expr $x0($j,5a) + $x3(5) * $bg_val(s5e5)] 
    set y0($j,5b) [expr $y0($j,5a) + $y3(5) * $bg_val(s5e5)] 
    set z0($j,5b) [expr $z0($j,5a) + $z3(5) * $bg_val(s5e5)] 

    # 6: neck
    set x0($j,6a) $x0($j,5b)
    set y0($j,6a) $y0($j,5b)
    set z0($j,6a) $z0($j,5b)

    set x0($j,6b) [expr $x0($j,6a) + $x3(6) * $bg_val(s6e5)] 
    set y0($j,6b) [expr $y0($j,6a) + $y3(6) * $bg_val(s6e5)] 
    set z0($j,6b) [expr $z0($j,6a) + $z3(6) * $bg_val(s6e5)] 

    # 7: head
    set x0($j,7a) [expr $x0($j,6b) + $xnb2ha]
    set y0($j,7a) [expr $y0($j,6b) + $ynb2ha]
    set z0($j,7a) [expr $z0($j,6b) + $znb2ha]

    set x0($j,7b) [expr $x0($j,7a) + $x3(7) * $bg_val(s7e5)] 
    set y0($j,7b) [expr $y0($j,7a) + $y3(7) * $bg_val(s7e5)] 
    set z0($j,7b) [expr $z0($j,7a) + $z3(7) * $bg_val(s7e5)] 

    # 8: upper hip
    set x0($j,8a) $x0($j,1a)
    set y0($j,8a) $y0($j,1a)
    set z0($j,8a) $z0($j,1a)

    set x0($j,8b) [expr $x0($j,8a) + $x3(8) * $bg_val(s8e5)] 
    set y0($j,8b) [expr $y0($j,8a) + $y3(8) * $bg_val(s8e5)] 
    set z0($j,8b) [expr $z0($j,8a) + $z3(8) * $bg_val(s8e5)] 

    # 9: lower hip
    set x0($j,9a) $x0($j,8b)
    set y0($j,9a) $y0($j,8b)
    set z0($j,9a) $z0($j,8b)

    set x0($j,9b) [expr $x0($j,9a) + $x3(9) * $bg_val(s9e5)] 
    set y0($j,9b) [expr $y0($j,9a) + $y3(9) * $bg_val(s9e5)] 
    set z0($j,9b) [expr $z0($j,9a) + $z3(9) * $bg_val(s9e5)] 

    # 10: right thigh
    set x0($j,10a) [expr $x0($j,9b) + $xh2rl + $xtj2tra]
    set y0($j,10a) [expr $y0($j,9b) + $yh2rl + $ytj2tra]
    set z0($j,10a) [expr $z0($j,9b) + $zh2rl + $ztj2tra]

    set x0($j,10b) [expr $x0($j,10a) + $x3(10) * $bg_val(s10e5)] 
    set y0($j,10b) [expr $y0($j,10a) + $y3(10) * $bg_val(s10e5)] 
    set z0($j,10b) [expr $z0($j,10a) + $z3(10) * $bg_val(s10e5)] 

    # 11: left thigh
    set x0($j,11a) [expr $x0($j,9b) + $xh2ll + $xtj2tla]
    set y0($j,11a) [expr $y0($j,9b) + $yh2ll + $ytj2tla]
    set z0($j,11a) [expr $z0($j,9b) + $zh2ll + $ztj2tla]

    set x0($j,11b) [expr $x0($j,11a) + $x3(11) * $bg_val(s11e5)] 
    set y0($j,11b) [expr $y0($j,11a) + $y3(11) * $bg_val(s11e5)] 
    set z0($j,11b) [expr $z0($j,11a) + $z3(11) * $bg_val(s11e5)] 

    # 12: right shank
    set x0($j,12a) $x0($j,10b)
    set y0($j,12a) $y0($j,10b)
    set z0($j,12a) $z0($j,10b)

    set x0($j,12b) [expr $x0($j,12a) + $x3(12) * $bg_val(s12e5)] 
    set y0($j,12b) [expr $y0($j,12a) + $y3(12) * $bg_val(s12e5)] 
    set z0($j,12b) [expr $z0($j,12a) + $z3(12) * $bg_val(s12e5)] 

    # 13: left shank
    set x0($j,13a) $x0($j,11b)
    set y0($j,13a) $y0($j,11b)
    set z0($j,13a) $z0($j,11b)

    set x0($j,13b) [expr $x0($j,13a) + $x3(13) * $bg_val(s13e5)] 
    set y0($j,13b) [expr $y0($j,13a) + $y3(13) * $bg_val(s13e5)] 
    set z0($j,13b) [expr $z0($j,13a) + $z3(13) * $bg_val(s13e5)] 

    # 14: right foot
    set x0($j,14a) [expr $x0($j,12b) + $xfj2ra + $xsh2rf]
    set y0($j,14a) [expr $y0($j,12b) + $yfj2ra + $ysh2rf]
    set z0($j,14a) [expr $z0($j,12b) + $zfj2ra + $zsh2rf]

    set x0($j,14b) [expr $x0($j,14a) + $x3(14) * $bg_val(s14e5)] 
    set y0($j,14b) [expr $y0($j,14a) + $y3(14) * $bg_val(s14e5)] 
    set z0($j,14b) [expr $z0($j,14a) + $z3(14) * $bg_val(s14e5)] 

    # 15: left foot
    set x0($j,15a) [expr $x0($j,13b) + $xfj2la + $xsh2lf]
    set y0($j,15a) [expr $y0($j,13b) + $yfj2la + $ysh2lf]
    set z0($j,15a) [expr $z0($j,13b) + $zfj2la + $zsh2lf]

    set x0($j,15b) [expr $x0($j,15a) + $x3(15) * $bg_val(s15e5)] 
    set y0($j,15b) [expr $y0($j,15a) + $y3(15) * $bg_val(s15e5)] 
    set z0($j,15b) [expr $z0($j,15a) + $z3(15) * $bg_val(s15e5)] 

    # 16: right upper arm
    set x0($j,16a) [expr $x0($j,4b) + $xs2ra + $xuaj2ra]
    set y0($j,16a) [expr $y0($j,4b) + $ys2ra + $yuaj2ra]
    set z0($j,16a) [expr $z0($j,4b) + $zs2ra + $zuaj2ra]

    set x0($j,16b) [expr $x0($j,16a) + $x3(16) * $bg_val(s16e5)] 
    set y0($j,16b) [expr $y0($j,16a) + $y3(16) * $bg_val(s16e5)] 
    set z0($j,16b) [expr $z0($j,16a) + $z3(16) * $bg_val(s16e5)] 

    # 17: left upper arm
    set x0($j,17a) [expr $x0($j,4b) + $xs2la + $xuaj2la]
    set y0($j,17a) [expr $y0($j,4b) + $ys2la + $yuaj2la]
    set z0($j,17a) [expr $z0($j,4b) + $zs2la + $zuaj2la]

    set x0($j,17b) [expr $x0($j,17a) + $x3(17) * $bg_val(s17e5)] 
    set y0($j,17b) [expr $y0($j,17a) + $y3(17) * $bg_val(s17e5)] 
    set z0($j,17b) [expr $z0($j,17a) + $z3(17) * $bg_val(s17e5)] 

    # 18: right forearm
    set x0($j,18a) $x0($j,16b)
    set y0($j,18a) $y0($j,16b)
    set z0($j,18a) $z0($j,16b)

    set x0($j,18b) [expr $x0($j,18a) + $x3(18) * $bg_val(s18e5)] 
    set y0($j,18b) [expr $y0($j,18a) + $y3(18) * $bg_val(s18e5)] 
    set z0($j,18b) [expr $z0($j,18a) + $z3(18) * $bg_val(s18e5)] 

    # 19: left forearm
    set x0($j,19a) $x0($j,17b)
    set y0($j,19a) $y0($j,17b)
    set z0($j,19a) $z0($j,17b)

    set x0($j,19b) [expr $x0($j,19a) + $x3(19) * $bg_val(s19e5)] 
    set y0($j,19b) [expr $y0($j,19a) + $y3(19) * $bg_val(s19e5)] 
    set z0($j,19b) [expr $z0($j,19a) + $z3(19) * $bg_val(s19e5)] 

    # 20: right hand
    set x0($j,20a) $x0($j,18b)
    set y0($j,20a) $y0($j,18b)
    set z0($j,20a) $z0($j,18b)

    set x0($j,20b) [expr $x0($j,20a) + $x3(20) * $bg_val(s20e5)] 
    set y0($j,20b) [expr $y0($j,20a) + $y3(20) * $bg_val(s20e5)] 
    set z0($j,20b) [expr $z0($j,20a) + $z3(20) * $bg_val(s20e5)] 

    # 21: left hand
    set x0($j,21a) $x0($j,19b)
    set y0($j,21a) $y0($j,19b)
    set z0($j,21a) $z0($j,19b)

    set x0($j,21b) [expr $x0($j,21a) + $x3(21) * $bg_val(s21e5)] 
    set y0($j,21b) [expr $y0($j,21a) + $y3(21) * $bg_val(s21e5)] 
    set z0($j,21b) [expr $z0($j,21a) + $z3(21) * $bg_val(s21e5)] 

    for {set k 1} {$k<=21} {incr k} {
        set x0v($j,${k}a) $x0($j,${k}a) 
        set y0v($j,${k}a) $y0($j,${k}a) 
        set z0v($j,${k}a) $z0($j,${k}a) 
        set x0v($j,${k}b) $x0($j,${k}b) 
        set y0v($j,${k}b) $y0($j,${k}b) 
        set z0v($j,${k}b) $z0($j,${k}b) 

        set x1v($j,$k) $x1($j,$k) 
        set y1v($j,$k) $y1($j,$k) 
        set z1v($j,$k) $z1($j,$k) 
        set x2v($j,$k) $x2($j,$k) 
        set y2v($j,$k) $y2($j,$k) 
        set z2v($j,$k) $z2($j,$k) 
    }

    DrawSwimmerOnCanvas $cn $j
}


# DrawSwimmerOnCanvas
proc DrawSwimmerOnCanvas { cn j } {
    global x0v y0v z0v bg_val
    global x1v y1v z1v 
    global x2v y2v z2v 
    global ydistance model_mag
    global dispstyle
    set pi 3.1415926535897932384626
    # set mag 400.0
    set mag 400.0
    catch { .ii$cn.f1.$j.c1 delete swimmerbody }
    catch { .ii$cn.f1.$j.c1 delete swimmersurface }
    for {set k 1} {$k<=21} {incr k} {

        # draw segment axes
        if {$dispstyle($cn,$j)>=1} {
            .ii$cn.f1.$j.c1 create line \
            [expr -$model_mag($cn,$j)*$mag*$z0v($j,${k}a) \
                             /($ydistance($cn,$j)-$y0v($j,${k}a))+400] \
            [expr  $model_mag($cn,$j)*$mag*$x0v($j,${k}a) \
                             /($ydistance($cn,$j)-$y0v($j,${k}a))+300] \
            [expr -$model_mag($cn,$j)*$mag*$z0v($j,${k}b) \
                             /($ydistance($cn,$j)-$y0v($j,${k}a))+400] \
            [expr  $model_mag($cn,$j)*$mag*$x0v($j,${k}b) \
                             /($ydistance($cn,$j)-$y0v($j,${k}a))+300] \
                            -fill #ffee00 -width 2.0 -tags swimmerbody
            .ii$cn.f1.$j.c1 create oval \
            [expr -$model_mag($cn,$j)*$mag*$z0v($j,${k}a) \
                             /($ydistance($cn,$j)-$y0v($j,${k}a))+400-2.0] \
            [expr  $model_mag($cn,$j)*$mag*$x0v($j,${k}a) \
                             /($ydistance($cn,$j)-$y0v($j,${k}a))+300-2.0] \
            [expr -$model_mag($cn,$j)*$mag*$z0v($j,${k}a) \
                             /($ydistance($cn,$j)-$y0v($j,${k}a))+400+2.0] \
            [expr  $model_mag($cn,$j)*$mag*$x0v($j,${k}a) \
                             /($ydistance($cn,$j)-$y0v($j,${k}a))+300+2.0] \
                                                      -fill red -width 0 -tags swimmerbody
        }
        # draw segment surface
        if {$dispstyle($cn,$j)==2} {
            for {set n 0} {$n<=36} {incr n} {
                set xsa [expr $x0v($j,${k}a) + $x1v($j,$k) * cos($n*10.0*$pi/180.0) * $bg_val(s${k}e1) \
                                             + $x2v($j,$k) * sin($n*10.0*$pi/180.0) * $bg_val(s${k}e2) ]
                set ysa [expr $y0v($j,${k}a) + $y1v($j,$k) * cos($n*10.0*$pi/180.0) * $bg_val(s${k}e1) \
                                             + $y2v($j,$k) * sin($n*10.0*$pi/180.0) * $bg_val(s${k}e2) ]
                set zsa [expr $z0v($j,${k}a) + $z1v($j,$k) * cos($n*10.0*$pi/180.0) * $bg_val(s${k}e1) \
                                             + $z2v($j,$k) * sin($n*10.0*$pi/180.0) * $bg_val(s${k}e2) ]
                set xsb [expr $x0v($j,${k}b) + $x1v($j,$k) * cos($n*10.0*$pi/180.0) * $bg_val(s${k}e3) \
                                             + $x2v($j,$k) * sin($n*10.0*$pi/180.0) * $bg_val(s${k}e4) ]
                set ysb [expr $y0v($j,${k}b) + $y1v($j,$k) * cos($n*10.0*$pi/180.0) * $bg_val(s${k}e3) \
                                             + $y2v($j,$k) * sin($n*10.0*$pi/180.0) * $bg_val(s${k}e4) ]
                set zsb [expr $z0v($j,${k}b) + $z1v($j,$k) * cos($n*10.0*$pi/180.0) * $bg_val(s${k}e3) \
                                             + $z2v($j,$k) * sin($n*10.0*$pi/180.0) * $bg_val(s${k}e4) ]

                .ii$cn.f1.$j.c1 create line \
                [expr -$model_mag($cn,$j)*$mag*$zsa \
                                 /($ydistance($cn,$j)-$ysa)+400] \
                [expr  $model_mag($cn,$j)*$mag*$xsa \
                                 /($ydistance($cn,$j)-$ysa)+300] \
                [expr -$model_mag($cn,$j)*$mag*$zsb \
                                 /($ydistance($cn,$j)-$ysa)+400] \
                [expr  $model_mag($cn,$j)*$mag*$xsb \
                                 /($ydistance($cn,$j)-$ysa)+300] \
                            -fill #ffee00 -width 1.0 -tags swimmersurface
            }
        }
    }
}


# Take starting x,y coordinates for rotation
proc IIRotStart {cn j x y W} {
    global ii_startx ii_starty ii_xangle0 ii_yangle0 ii_xangle ii_yangle
    set ii_startx($cn,$j) $x
    set ii_starty($cn,$j) $y
    set ii_xangle0($cn,$j) $ii_xangle($cn,$j)
    set ii_yangle0($cn,$j) $ii_yangle($cn,$j)
}


# Take starting z coordinates for rotation
proc IIRotStartZ {cn j y W} {
    global ii_startz ii_zangle0 ii_zangle 
    set ii_startz($cn,$j) $y
    set ii_zangle0($cn,$j) $ii_zangle($cn,$j)
}


# Rotate view using mouse pointer
proc IIRotMove {cn j x y} {
    global ii_startx ii_starty ii_xangle0 ii_yangle0 ii_xangle ii_yangle
    global xtmp ytmp ztmp rxtmp rytmp rztmp 

    set mag 1.0
    set ii_xangle($cn,$j) [expr $ii_xangle0($cn,$j) + ($x - $ii_startx($cn,$j)) * $mag ]
    set ii_yangle($cn,$j) [expr $ii_yangle0($cn,$j) + ($y - $ii_starty($cn,$j)) * $mag ]
        
    IIRot $cn $j 
}


# Rotate view using mouse pointer (for z)
proc IIRotMoveZ {cn j y} {
    global ii_startz ii_zangle0 ii_zangle
    global xtmp ytmp ztmp rxtmp rytmp rztmp 

    set mag 1.0
    set ii_zangle($cn,$j) [expr $ii_zangle0($cn,$j) + ($y - $ii_startz($cn,$j)) * $mag ]
        
    IIRot $cn $j 
}


# Rotate view 
proc IIRot {cn j} {
    global ii_xangle ii_yangle ii_zangle
    global xtmp ytmp ztmp rxtmp rytmp rztmp 
    global x0v y0v z0v
    global x0  y0  z0 
    global x1  y1  z1 
    global x1v y1v z1v
    global x2  y2  z2 
    global x2v y2v z2v
    set pi 3.1415926535897932384626

    for {set k 1} {$k<=21} {incr k} {
        set xtmp $x0($j,${k}a)
        set ytmp $y0($j,${k}a) 
        set ztmp $z0($j,${k}a)
        set rztmp [expr -$ii_yangle($cn,$j)*$pi/180.0]
        set rxtmp [expr -$ii_xangle($cn,$j)*$pi/180.0]
        set rytmp [expr -$ii_zangle($cn,$j)*$pi/180.0]
        VecRot
        set x0v($j,${k}a) $xtmp
        set y0v($j,${k}a) $ytmp
        set z0v($j,${k}a) $ztmp

        set xtmp $x0($j,${k}b)
        set ytmp $y0($j,${k}b) 
        set ztmp $z0($j,${k}b)
        VecRot
        set x0v($j,${k}b) $xtmp
        set y0v($j,${k}b) $ytmp
        set z0v($j,${k}b) $ztmp

        set xtmp $x1($j,$k)
        set ytmp $y1($j,$k) 
        set ztmp $z1($j,$k)
        VecRot
        set x1v($j,$k) $xtmp
        set y1v($j,$k) $ytmp
        set z1v($j,$k) $ztmp

        set xtmp $x2($j,$k)
        set ytmp $y2($j,$k) 
        set ztmp $z2($j,$k)
        VecRot
        set x2v($j,$k) $xtmp
        set y2v($j,$k) $ytmp
        set z2v($j,$k) $ztmp
    }
    DrawSwimmerOnCanvas $cn $j
}


# Rotate segments
proc RotateSegments { j } {
    global num_line
    global segm_num_a
    global axis_num_a
    global joint_angle_a
    global xtmp ytmp ztmp rxtmp rytmp rztmp
    global x1 y1 z1
    global x2 y2 z2
    global x3 y3 z3
    global x10 y10 z10
    global x20 y20 z20
    global x30 y30 z30
    global xs2ra0 ys2ra0 zs2ra0
    global xs2ra  ys2ra  zs2ra 
    global xs2la0 ys2la0 zs2la0
    global xs2la  ys2la  zs2la 
    global xnb2ha0 ynb2ha0 znb2ha0 
    global xnb2ha  ynb2ha  znb2ha
    global xh2rl0 yh2rl0 zh2rl0 
    global xh2rl  yh2rl  zh2rl 
    global xh2ll0 yh2ll0 zh2ll0 
    global xh2ll  yh2ll  zh2ll 
    global xtj2tra0 ytj2tra0 ztj2tra0
    global xtj2tra  ytj2tra  ztj2tra 
    global xtj2tla0 ytj2tla0 ztj2tla0
    global xtj2tla  ytj2tla  ztj2tla 
    global xsh2rf0 ysh2rf0 zsh2rf0 
    global xsh2rf  ysh2rf  zsh2rf 
    global xsh2lf0 ysh2lf0 zsh2lf0 
    global xsh2lf  ysh2lf  zsh2lf 
    global xfj2ra0 yfj2ra0 zfj2ra0
    global xfj2ra  yfj2ra  zfj2ra 
    global xfj2la0 yfj2la0 zfj2la0
    global xfj2la  yfj2la  zfj2la 
    global xuaj2ra0 yuaj2ra0 zuaj2ra0
    global xuaj2ra  yuaj2ra  zuaj2ra 
    global xuaj2la0 yuaj2la0 zuaj2la0
    global xuaj2la  yuaj2la  zuaj2la 
    set pi 3.1415926535897932384626

    # initialize segments' direction
    for {set k 1} {$k<=21} {incr k} {
        set x1($j,$k) $x10($k)
        set y1($j,$k) $y10($k)
        set z1($j,$k) $z10($k)
        set x2($j,$k) $x20($k)
        set y2($j,$k) $y20($k)
        set z2($j,$k) $z20($k)
        set x3($k) $x30($k)
        set y3($k) $y30($k)
        set z3($k) $z30($k)
        set xs2ra $xs2ra0
        set ys2ra $ys2ra0
        set zs2ra $zs2ra0
        set xs2la $xs2la0
        set ys2la $ys2la0
        set zs2la $zs2la0
        set xnb2ha $xnb2ha0 
        set ynb2ha $ynb2ha0 
        set znb2ha $znb2ha0 
        set xh2rl $xh2rl0
        set yh2rl $yh2rl0
        set zh2rl $zh2rl0
        set xh2ll $xh2ll0
        set yh2ll $yh2ll0
        set zh2ll $zh2ll0
        set xtj2tra $xtj2tra0
        set ytj2tra $ytj2tra0
        set ztj2tra $ztj2tra0
        set xtj2tla $xtj2tla0
        set ytj2tla $ytj2tla0
        set ztj2tla $ztj2tla0
        set xsh2rf $xsh2rf0
        set ysh2rf $ysh2rf0
        set zsh2rf $zsh2rf0
        set xsh2lf $xsh2lf0
        set ysh2lf $ysh2lf0
        set zsh2lf $zsh2lf0
        set xfj2ra $xfj2ra0
        set yfj2ra $yfj2ra0
        set zfj2ra $zfj2ra0
        set xfj2la $xfj2la0
        set yfj2la $yfj2la0
        set zfj2la $zfj2la0
        set xuaj2ra $xuaj2ra0
        set yuaj2ra $yuaj2ra0
        set zuaj2ra $zuaj2ra0
        set xuaj2la $xuaj2la0
        set yuaj2la $yuaj2la0
        set zuaj2la $zuaj2la0
    }

    for {set i 0} {$i<=[expr $num_line -1]} {incr i} {

        # rotate normal segments
        set xtmp $x3($segm_num_a($i))
        set ytmp $y3($segm_num_a($i))
        set ztmp $z3($segm_num_a($i))
        set rxtmp 0.0
        set rytmp 0.0
        set rztmp 0.0
        if {$axis_num_a($i)==1} {
            set rxtmp [expr $joint_angle_a($i,$j) *$pi/180.0]
        } elseif {$axis_num_a($i)==2} {
            set rytmp [expr $joint_angle_a($i,$j) *$pi/180.0]
        } elseif {$axis_num_a($i)==3} {
            set rztmp [expr $joint_angle_a($i,$j) *$pi/180.0]
        }
        VecRot
        set x3($segm_num_a($i)) $xtmp
        set y3($segm_num_a($i)) $ytmp
        set z3($segm_num_a($i)) $ztmp

        set xtmp $x1($j,$segm_num_a($i))
        set ytmp $y1($j,$segm_num_a($i))
        set ztmp $z1($j,$segm_num_a($i))
        VecRot
        set x1($j,$segm_num_a($i)) $xtmp
        set y1($j,$segm_num_a($i)) $ytmp
        set z1($j,$segm_num_a($i)) $ztmp

        set xtmp $x2($j,$segm_num_a($i))
        set ytmp $y2($j,$segm_num_a($i))
        set ztmp $z2($j,$segm_num_a($i))
        VecRot
        set x2($j,$segm_num_a($i)) $xtmp
        set y2($j,$segm_num_a($i)) $ytmp
        set z2($j,$segm_num_a($i)) $ztmp

        # rotate some additional vectors
        if {$segm_num_a($i)==4} { 
            set xtmp $xs2ra
            set ytmp $ys2ra
            set ztmp $zs2ra
            VecRot
            set xs2ra $xtmp
            set ys2ra $ytmp
            set zs2ra $ztmp

            set xtmp $xs2la
            set ytmp $ys2la
            set ztmp $zs2la
            VecRot
            set xs2la $xtmp
            set ys2la $ytmp
            set zs2la $ztmp

            # for shoulder elevation
            if       {$axis_num_a($i)==4} {
                set xtmp $xs2ra
                set ytmp $ys2ra
                set ztmp $zs2ra
                set rxtmp [expr $joint_angle_a($i,$j) *$pi/180.0]
                VecRot
                set xs2ra $xtmp
                set ys2ra $ytmp
                set zs2ra $ztmp
            } elseif {$axis_num_a($i)==5} {
                set xtmp $xs2ra
                set ytmp $ys2ra
                set ztmp $zs2ra
                set rytmp [expr $joint_angle_a($i,$j) *$pi/180.0]
                VecRot
                set xs2ra $xtmp
                set ys2ra $ytmp
                set zs2ra $ztmp
            } elseif {$axis_num_a($i)==6} {
                set xtmp $xs2ra
                set ytmp $ys2ra
                set ztmp $zs2ra
                set rztmp [expr $joint_angle_a($i,$j) *$pi/180.0]
                VecRot
                set xs2ra $xtmp
                set ys2ra $ytmp
                set zs2ra $ztmp
            } elseif {$axis_num_a($i)==7} {
                set xtmp $xs2la
                set ytmp $ys2la
                set ztmp $zs2la
                set rxtmp [expr $joint_angle_a($i,$j) *$pi/180.0]
                VecRot
                set xs2la $xtmp
                set ys2la $ytmp
                set zs2la $ztmp
            } elseif {$axis_num_a($i)==8} {
                set xtmp $xs2la
                set ytmp $ys2la
                set ztmp $zs2la
                set rytmp [expr $joint_angle_a($i,$j) *$pi/180.0]
                VecRot
                set xs2la $xtmp
                set ys2la $ytmp
                set zs2la $ztmp
            } elseif {$axis_num_a($i)==9} {
                set xtmp $xs2la
                set ytmp $ys2la
                set ztmp $zs2la
                set rztmp [expr $joint_angle_a($i,$j) *$pi/180.0]
                VecRot
                set xs2la $xtmp
                set ys2la $ytmp
                set zs2la $ztmp
            }

        } elseif {$segm_num_a($i)==6} { 
            set xtmp $xnb2ha
            set ytmp $ynb2ha
            set ztmp $znb2ha
            VecRot
            set xnb2ha $xtmp
            set ynb2ha $ytmp
            set znb2ha $ztmp
        } elseif {$segm_num_a($i)==9} { 
            set xtmp $xh2rl
            set ytmp $yh2rl
            set ztmp $zh2rl
            VecRot
            set xh2rl $xtmp
            set yh2rl $ytmp
            set zh2rl $ztmp
            set xtmp $xh2ll
            set ytmp $yh2ll
            set ztmp $zh2ll
            VecRot
            set xh2ll $xtmp
            set yh2ll $ytmp
            set zh2ll $ztmp
        } elseif {$segm_num_a($i)==10} { 
            set xtmp $xtj2tra
            set ytmp $ytj2tra
            set ztmp $ztj2tra
            VecRot
            set xtj2tra $xtmp
            set ytj2tra $ytmp
            set ztj2tra $ztmp
        } elseif {$segm_num_a($i)==11} { 
            set xtmp $xtj2tla
            set ytmp $ytj2tla
            set ztmp $ztj2tla
            VecRot
            set xtj2tla $xtmp
            set ytj2tla $ytmp
            set ztj2tla $ztmp
        } elseif {$segm_num_a($i)==12} { 
            set xtmp $xsh2rf
            set ytmp $ysh2rf
            set ztmp $zsh2rf
            VecRot
            set xsh2rf $xtmp
            set ysh2rf $ytmp
            set zsh2rf $ztmp
        } elseif {$segm_num_a($i)==13} { 
            set xtmp $xsh2lf
            set ytmp $ysh2lf
            set ztmp $zsh2lf
            VecRot
            set xsh2lf $xtmp
            set ysh2lf $ytmp
            set zsh2lf $ztmp
        } elseif {$segm_num_a($i)==14} { 
            set xtmp $xfj2ra
            set ytmp $yfj2ra
            set ztmp $zfj2ra
            VecRot
            set xfj2ra $xtmp
            set yfj2ra $ytmp
            set zfj2ra $ztmp
        } elseif {$segm_num_a($i)==15} { 
            set xtmp $xfj2la
            set ytmp $yfj2la
            set ztmp $zfj2la
            VecRot
            set xfj2la $xtmp
            set yfj2la $ytmp
            set zfj2la $ztmp
        } elseif {$segm_num_a($i)==16} { 
            set xtmp $xuaj2ra
            set ytmp $yuaj2ra
            set ztmp $zuaj2ra
            VecRot
            set xuaj2ra $xtmp
            set yuaj2ra $ytmp
            set zuaj2ra $ztmp
        } elseif {$segm_num_a($i)==17} { 
            set xtmp $xuaj2la
            set ytmp $yuaj2la
            set ztmp $zuaj2la
            VecRot
            set xuaj2la $xtmp
            set yuaj2la $ytmp
            set zuaj2la $ztmp
        } 
    }
}


# Rotate three-dimensional vectors
proc VecRot { } {
    global xtmp ytmp ztmp rxtmp rytmp rztmp

    # rotate about x
    set x1 $xtmp
    set y1 [expr $ytmp * cos($rxtmp) - $ztmp * sin($rxtmp)]
    set z1 [expr $ytmp * sin($rxtmp) + $ztmp * cos($rxtmp)]

    # rotate about y
    set x2 [expr  $x1 * cos($rytmp) + $z1 * sin($rytmp)]
    set y2 $y1
    set z2 [expr -$x1 * sin($rytmp) + $z1 * cos($rytmp)]

    # rotate about z
    set xtmp [expr $x2 * cos($rztmp) - $y2 * sin($rztmp)]
    set ytmp [expr $x2 * sin($rztmp) + $y2 * cos($rztmp)]
    set ztmp $z2
}


# Save display data
proc SaveDisplayData { } {
    global num_frames 
    global imagefile image_size image_posx image_posy
    global ydistance model_mag
    global ii_xangle ii_yangle ii_zangle

    set f [open import_images.dat w]
    puts $f $num_frames
    for {set cn 1} {$cn<=4} {incr cn} {
        for {set  j 0} {$j<$num_frames} {incr j} {
            if {[info exists image_posx($cn,$j)]==1} {
                puts $f "$image_posx($cn,$j) \
                        $image_posy($cn,$j) \
                        $image_size($cn,$j) \
                        $ii_xangle($cn,$j) \
                        $ii_yangle($cn,$j) \
                        $ii_zangle($cn,$j) \
                        $model_mag($cn,$j) \
                        $ydistance($cn,$j)"
            } else {
                puts $f ""
            }

            if {[info exists imagefile($cn,$j)]==1} {
                puts $f $imagefile($cn,$j)
            } else {
                puts $f ""
            }
 
        }
    }
    close $f
}


# Load display data
proc LoadDisplayData { cn } {
    global num_frames
    global imagefile image_size image_posx image_posy
    global ydistance model_mag
    global ii_xangle ii_yangle ii_zangle

    if {[file exists import_images.dat]==1} {
        set f [open import_images.dat r]
        gets $f line
        for {set i 1} {$i<=4} {incr i} {
            for {set j 0} {$j<=[expr $num_frames -1]} {incr j} {

                gets $f line
                gets $f line2

                if {$i==$cn} {
                    # display parameter line
                    if {$line!=""} {
                        set image_posx($i,$j) [lindex $line 0]
                        set image_posy($i,$j) [lindex $line 1]
                        set image_size($i,$j) [lindex $line 2]
                        set  ii_xangle($i,$j) [lindex $line 3]
                        set  ii_yangle($i,$j) [lindex $line 4]
                        set  ii_zangle($i,$j) [lindex $line 5]
                        set  model_mag($i,$j) [lindex $line 6]
                        set  ydistance($i,$j) [lindex $line 7]
                    }

                    # file line
                    if {$line2!=""} {
                        set imagefile($i,$j) $line2
                        OpenImage $i $j
                    }
                }
            }
        }
        close $f
    }
}


# Toggle display on/off
proc ToggleDisplay { cn j } {
    global dispstyle
    if {$dispstyle($cn,$j)==2} {
        # surface on
            DrawSwimmerOnCanvas $cn $j

    } elseif {$dispstyle($cn,$j)==1} {
        # axis on
        .ii$cn.f1.$j.c1 delete swimmersurface
        .ii$cn.f1.$j.c1 delete swimmerbody
            DrawSwimmerOnCanvas $cn $j
    } else {
        # off
#        .ii$cn.f1.$j.c1 move swimmerbody -1000 -1000
#        .ii$cn.f1.$j.c1 move swimmersurface -1000 -1000
        .ii$cn.f1.$j.c1 delete swimmersurface
        .ii$cn.f1.$j.c1 delete swimmerbody
    }
}


# Update swimmer's posture
proc IISwimmerUpdate { } {
    global num_frames

    global segm_num_a
    global axis_num_a
    global joint_angle_a

    for {set k 1} {$k<=4} {incr k} {
        if {[winfo exists .ii$k]==1} {
            for {set j 0} {$j<=[expr $num_frames -1]} {incr j} {
                RotateSegments $j
                DrawSwimmer $k $j
                IIRot  $k $j
            }
        }
    }
}


# ApplySet display parameters to all frames 
proc ApplyAllFramesModel { cn j } {
    global ii_xangle ii_yangle ii_zangle model_mag ydistance
    global num_frames

    # save current values
    set ii_xangle_all $ii_xangle($cn,$j)
    set ii_yangle_all $ii_yangle($cn,$j)
    set ii_zangle_all $ii_zangle($cn,$j)
    set model_mag_all $model_mag($cn,$j)
    set ydistance_all $ydistance($cn,$j)
   
    for {set k 0} {$k <= [expr $num_frames -1]} {incr k} {
        # change all values
        set ii_xangle($cn,$k) $ii_xangle_all
        set ii_yangle($cn,$k) $ii_yangle_all
        set ii_zangle($cn,$k) $ii_zangle_all
        set model_mag($cn,$k) $model_mag_all
        set ydistance($cn,$k) $ydistance_all

        # redraw swimmer
        IIRot $cn $k
    }
}


proc ApplyAllFramesImage { cn j } {
    global image_posx image_posy image_size
    global num_frames

    # save current values
    set image_posx_all $image_posx($cn,$j)
    set image_posy_all $image_posy($cn,$j) 
    set image_size_all $image_size($cn,$j)

    for {set k 0} {$k <= [expr $num_frames -1]} {incr k} {
        # change all values
        set image_posx($cn,$k) $image_posx_all
        set image_posy($cn,$k) $image_posy_all 
        set image_size($cn,$k) $image_size_all

        # redisplay image
        catch { ChangeImageSize $cn $k}
        catch { ChangeImageLocation $cn $k}
    }
}


# Initialization
set swimmer_initialized 0
