I used to sleep a lot in math class... For this question https://groups.google.com/forum/m/#!topic/comp.lang.tcl/iOedyEIUC4E%|%Calculating Distance from a Point to a Plane %|% I can answer... Maybe there’s a faster way to calculate... ====== namespace eval Vector3D { namespace export * proc sub_v3v3 {v0 v1} { lassign $v0 v0x v0y v0z lassign $v1 v1x v1y v1z return [list [expr {$v0x - $v1x}] \ [expr {$v0y - $v1y}] \ [expr {$v0z - $v1z}]] } proc dot_v3v3 {v0 v1} { lassign $v0 v0x v0y v0z lassign $v1 v1x v1y v1z return [expr {($v0x * $v1x) + ($v0y * $v1y) + ($v0z * $v1z)}] } proc cross_v3v3 {v0 v1} { lassign $v0 vx0 vy0 vz0 lassign $v1 vx1 vy1 vz1 return [list [expr {($vy0 * $vz1) - ($vy1 * $vz0)}] \ [expr {($vz0 * $vx1) - ($vx0 * $vz1)}] \ [expr {($vx0 * $vy1) - ($vy0 * $vx1)}]] } proc norm {v} { lassign $v vx vy vz return [expr {sqrt($vx**2 + $vy**2 + $vz**2)}] } proc unit {v} { set n [norm $v] if {$n == 0} { error "Must be greatest than 0..." } lassign $v x y z return [list [expr {$x / double($n)}] \ [expr {$y / double($n)}] \ [expr {$z / double($n)}]] } } ====== * Utilisation : ====== namespace import Vector3D::* set plan {{-10 -10 10} {10 -10 10} {0 10 10}} ; # 3 points on plan (3d) set point {0 0 12} ; # point (3d) lassign $plan v0 v1 v2 set u [sub_v3v3 $v1 $v0] set v [sub_v3v3 $v2 $v0] set normal [unit [cross_v3v3 $u $v]] ; # normal to plane set sub [sub_v3v3 $point $v0] set dist [dot_v3v3 $normal $sub] puts "Distance 3D = $dist" # Distance 3D = 2.0 ====== Here is my pure Tcl implementation of the task to compute the distance of a point to a plane in 3D. The procedures are optimized for maximum performance. I did not compare to above implementation. ====== ## Get the distance of a point p to a plane given by origin point a and normal vector u. proc DistPoint2Plane {p a u {abskey 1}} { # Normalize vector u to the length of one set u [VectorNormalize $u] # Get vector from a to p set ap [VectorsDifference $p $a] # Return the distance as scalar product of u and ap if {$abskey} { return [expr {abs([VectorsDotProduct $u $ap])}] } else { return [expr {[VectorsDotProduct $u $ap]}] } } ## Normalize vector a to length 1 proc VectorNormalize {a} { set norm [VectorNorm $a] if {$norm!=0} { return [list [expr {[lindex $a 0]/double($norm)}] [expr {[lindex $a 1]/double($norm)}] [expr {[lindex $a 2]/double($norm)}]] } else { return $a } } ## Compute the length of vector a proc VectorNorm {a} { lassign $a a1 a2 a3 return [expr {sqrt(pow($a1,2)+pow($a2,2)+pow($a3,2))}] } ## compute the difference of vector a and b (a-b) proc VectorsDifference {a b} { if {[lindex $a 3]=="" || [lindex $b 3]==""} { return [list [expr {[lindex $a 0]-[lindex $b 0]}] [expr {[lindex $a 1]-[lindex $b 1]}] [expr {[lindex $a 2]-[lindex $b 2]}]] } else { return [list [expr {[lindex $a 0]-[lindex $b 0]}] [expr {[lindex $a 1]-[lindex $b 1]}] [expr {[lindex $a 2]-[lindex $b 2]}] [expr {[lindex $a 3]-[lindex $b 3]}] [expr {[lindex $a 4]-[lindex $b 4]}] [expr {[lindex $a 5]-[lindex $b 5]}]] } } ## Compute the dot product of vectors a and b proc VectorsDotProduct {a b} { lassign $a a1 a2 a3 lassign $b b1 b2 b3 return [expr {$a1*$b1+$a2*$b2+$a3*$b3}] } ====== Usage: ====== DistPoint2Plane {0 0 10} {0 0 0} {0 0 1} ====== kch - An alternate approach: ====== # # This code presumes all parameters are pre-validated. # proc defPoint {x y z} { return [list $x $y $z] }; # defPoint {} proc defVector {Pa Pb} { set dx [expr {[lindex $Pb 0] - [lindex $Pa 0]}] set dy [expr {[lindex $Pb 1] - [lindex $Pa 1]}] set dz [expr {[lindex $Pb 2] - [lindex $Pa 2]}] return [list $dx $dy $dz] }; # defVector {} proc crossProduct {Va Vb} { set A [expr { [lindex $Va 1] * [lindex $Vb 2] - [lindex $Va 2] * [lindex $Vb 1] }] set B [expr { [lindex $Va 2] * [lindex $Vb 0] - [lindex $Va 0] * [lindex $Vb 2] }] set C [expr { [lindex $Va 0] * [lindex $Vb 1] - [lindex $Va 1] * [lindex $Vb 0] }] return [list $A $B $C] }; # crossProduct {} proc vecLen {V} { set accum 0 foreach element $V { incr accum [expr {$element * $element}] } return [expr {sqrt($accum)}] }; # vecLen {} proc normalize {V} { set len [vecLen $V] set normVec {} foreach element $V { lappend normVec [expr {$element / $len}] } return $normVec }; # normalize {} proc defPlane {NormVec P0} { set D 0 foreach vElement $NormVec pElement $P0 { set D [expr {$D - $vElement * $pElement}] } return [list {*}$NormVec $D] }; # defPlane {} proc distToPlane {plane point} { set D [lindex $plane 3] foreach vElement [lrange $plane 0 2] pElement $point { set D [expr {$D + $vElement * $pElement}] } return $D }; # distToPlane {} ====== Usage: ====== % set P0 [defPoint 1 0 0] 1 0 0 % set P1 [defPoint 0 1 0] 0 1 0 % set P2 [defPoint 0 0 1] 0 0 1 % set Va [defVector $P0 $P1] -1 1 0 % set Vb [defVector $P0 $P2] -1 0 1 % set NormalA [crossProduct $Va $Vb] 1 1 1 % set nVecA [normalize $NormalA] 0.5773502691896258 0.5773502691896258 0.5773502691896258 % set planeA [defPlane $nVecA $P0] 0.5773502691896258 0.5773502691896258 0.5773502691896258 -0.5773502691896258 % distToPlane $PA $P0 0.0 % distToPlane $PA {1 1 1} 1.1547005383792517 % distToPlane $PA {0 0 0} -0.5773502691896258 ======