[vtkusers] Re: vtkmath in tcl

Mark B Stucky mstucky5 at cox.net
Thu Jul 21 17:43:51 EDT 2005


This may be getting slightly off topic, but with regard to your
"DotProd" and "CrossProd" routines, you can speed them up
quite a bit by simply replacing the lines

     scan $a "%f %f %f" ax ay az
     scan $b "%f %f %f" bx by bz

with

     foreach {ax ay az} $a {break}
     foreach {bx by bz} $b {break}

I ran some timings and got the following :

    Times :

    CrossProd    : 17 microseconds per iteration
    myCrossProd  : 7 microseconds per iteration
    vecCross     : 6 microseconds per iteration

    DotProd      : 15 microseconds per iteration
    myDotProd    : 4 microseconds per iteration
    vecDot       : 5 microseconds per iteration

"myCrossProd" and "myDotProd" are versions of your code
with the "foreach" fix.
"vecCross" and "vecDot" are a couple of routines that I found
on the net.

See the code below, or let me know if you have questions.

--Mark

(The code follows this message)

----- Original Message ----- 
From: "Goodwin Lawlor" <goodwin.lawlor at ucd.ie>
To: <vtkusers at public.kitware.com>
Sent: Thursday, July 21, 2005 8:55 AM
Subject: [vtkusers] Re: vtkmath in tcl


> Hi Alberto,
>
> The only vectors operations in vtkMath that work in tcl are vtkMath::Norm 
> and vtkMath::Norm2D
>
> It would be easy enough to extend vtkMath to wrap Cross and Dot into 
> tcl... you might like to add it as an idea to the bug tracker - 
> http://www.vtk.org/Bug
>
> Here are some tcl procs I use to do Dot and Cross
>
> proc DotProd {a b} {
>
>    if {[llength $a] < 3 || [llength $b] < 3} {
>        return -code error "Vectors must have 3 components!"
>    }
>
>    scan $a "%f %f %f" ax ay az
>    scan $b "%f %f %f" bx by bz
>
>    return [expr {$ax*$bx + $ay*$by + $az*$bz}]
>
> }
>
> proc CrossProd {a b} {
>
>    if {[llength $a] < 3 || [llength $b] < 3} {
>        return -code error "Vectors must have 3 components!"
>    }
>
>    scan $a "%f %f %f" ax ay az
>    scan $b "%f %f %f" bx by bz
>
>    set cx [expr {$ay*$bz - $az*$by}]
>    set cy [expr {$az*$bx - $ax*$bz}]
>    set cz [expr {$ax*$by - $ay*$bx}]
>
>    return [list $cx $cy $cz]
> }
>
> use them like this: CrossProd {1 2 3} {4 5 6}
>
>
> hth
>
> Goodwin






proc DotProd {a b} {

    if {[llength $a] < 3 || [llength $b] < 3} {
        return -code error "Vectors must have 3 components!"
    }

    scan $a "%f %f %f" ax ay az
    scan $b "%f %f %f" bx by bz

    return [expr {$ax*$bx + $ay*$by + $az*$bz}]

}

proc CrossProd {a b} {

    if {[llength $a] < 3 || [llength $b] < 3} {
        return -code error "Vectors must have 3 components!"
    }

    scan $a "%f %f %f" ax ay az
    scan $b "%f %f %f" bx by bz

    set cx [expr {$ay*$bz - $az*$by}]
    set cy [expr {$az*$bx - $ax*$bz}]
    set cz [expr {$ax*$by - $ay*$bx}]

    return [list $cx $cy $cz]
}


proc myDotProd {a b} {

    if {[llength $a] < 3 || [llength $b] < 3} {
        return -code error "Vectors must have 3 components!"
    }

    foreach {ax ay az} $a {break}
    foreach {bx by bz} $b {break}

    return [expr {$ax*$bx + $ay*$by + $az*$bz}]

}

proc myCrossProd {a b} {

    if {[llength $a] < 3 || [llength $b] < 3} {
        return -code error "Vectors must have 3 components!"
    }

    foreach {ax ay az} $a {break}
    foreach {bx by bz} $b {break}

    set cx [expr {$ay*$bz - $az*$by}]
    set cy [expr {$az*$bx - $ax*$bz}]
    set cz [expr {$ax*$by - $ay*$bx}]

    return [list $cx $cy $cz]
}

# vector.tcl - vector math routines
# Jonas Beskow 1999-2000

# http://www.speech.kth.se/~beskow/tcl/vec.tcl.txt

namespace eval vec {
 variable PI
 set PI [expr {4*atan(1.0)}]
}

# dot - calculate scalar dot product of two vectors
proc vec::dot {v1 v2} {
 if {[llength $v1]!=[llength $v2]} {
  error "Vectors must be of equal length"
 }
 set d 0.0
 foreach c1 $v1 c2 $v2 {set d [expr {$d+$c1*$c2}]}
 set d
}

# cross - cross product between two 3d-vectors
proc vec::cross {v1 v2} {
 if {[llength $v1]!=3 || [llength $v2]!=3} {
  error "Vectors must be of length 3"
 }
 set v1x [lindex $v1 0]
 set v1y [lindex $v1 1]
 set v1z [lindex $v1 2]
 set v2x [lindex $v2 0]
 set v2y [lindex $v2 1]
 set v2z [lindex $v2 2]
 list \
   [expr {$v1y*$v2z-$v1z*$v2y}] \
   [expr {$v1z*$v2x-$v1x*$v2z}] \
   [expr {$v1x*$v2y-$v1y*$v2x}]
}



proc run_CrossProd { } {
    CrossProd {1.9 2.5 3.1} {4.1 5.7 6.3}
}

proc run_DotProd { } {
    DotProd {1.9 2.5 3.1} {4.1 5.7 6.3}
}

proc run_myCrossProd { } {
    myCrossProd {1.9 2.5 3.1} {4.1 5.7 6.3}
}

proc run_myDotProd { } {
    myDotProd {1.9 2.5 3.1} {4.1 5.7 6.3}
}

proc run_vecCross { } {
    vec::cross {1.9 2.5 3.1} {4.1 5.7 6.3}
}

proc run_vecDot { } {
    vec::dot {1.9 2.5 3.1} {4.1 5.7 6.3}
}

puts " "
puts "Results : "
puts " "
puts "CrossProd    : [CrossProd {1.9 2.5 3.1} {4.1 5.7 6.3}]"
puts "myCrossProd  : [myCrossProd {1.9 2.5 3.1} {4.1 5.7 6.3}]"
puts "vec::cross   : [vec::cross {1.9 2.5 3.1} {4.1 5.7 6.3}]"
puts " "
puts "DotProd      : [DotProd   {1.9 2.5 3.1} {4.1 5.7 6.3}]"
puts "myDotProd    : [myDotProd   {1.9 2.5 3.1} {4.1 5.7 6.3}]"
puts "vec::dot     : [vec::dot {1.9 2.5 3.1} {4.1 5.7 6.3}]"
puts " "
puts "Times : "
puts " "
puts "CrossProd    : [time run_CrossProd 100000]"
puts "myCrossProd  : [time run_myCrossProd 100000]"
puts "vecCross     : [time run_vecCross 100000]"
puts " "
puts "DotProd      : [time run_DotProd 100000]"
puts "myDotProd    : [time run_myDotProd 100000]"
puts "vecDot       : [time run_vecDot 100000]"








More information about the vtkusers mailing list