tags:

views:

144

answers:

2

Hi, What is problem with follwoing code? I am getting very strange results. Do I missing something?

proc Dot {vec1 vec2} {
set ret [expr ([lindex $vec1 0]*[lindex $vec2 0])+([lindex $vec1 1]*[lindex $vec2 1])+([lindex $vec1 2]*[lindex $vec2 2])]
}

proc FindInterSectPoint_LineAndPlane {normalVectorPlane basePoint refPoint topoint} {

foreach {norm1 norm2 norm3} $normalVectorPlane {break}

foreach {xB yB zB} $basePoint {break}

foreach {xb yb zb} $refPoint {break}

foreach {xa ya za} $topoint {break}

set vecL1 [expr $xb-$xa]
set vecL2 [expr $yb-$ya]
set vecL3 [expr $zb-$za]

set direction [expr -($norm1*$xB)+($norm2*$yB)+($norm3*$zB)]
set d [expr -(($vecL1*$xb)+($vecL2*$yb)+($vecL3*$zb)+$direction)]
set n [Dot $normalVectorPlane [list $vecL1 $vecL2 $vecL3] ]

if {$n == 0} {
 return "line on parallel to plane"; # line on plane
} 

set s [expr $d/($n*1.000)]

if {$s > 0 && $s < 1} {
 set ret "intersection occurs between the two end points"
} elseif {$s == 0} {
 set ret "intersection falls on the first end point"
} elseif {$s == 1} {
 set ret "intersection falls on the second end point"
} elseif {$s > 1} {
 set ret "intersection occurs beyond second end Point"
} elseif {$s < 0} {
 set ret "intersection happens before 1st end point"
} else {
 set ret "error"
}


set x [expr [lindex $refPoint 0]+($s*$vecL1)]
set y [expr [lindex $refPoint 1]+($s*$vecL2)]
set z [expr [lindex $refPoint 2]+($s*$vecL3)]
lappend ret "$x $y $z n=$n d=$d s=$s"
 }

Output:

%FindInterSectPoint_LineAndPlane {0 0 1} {0 0 0} {0 0 0} {1 2 3}

intersection falls on the first end point {0.0 0.0 0.0 n=-3 d=0 s=-0.0}

%FindInterSectPoint_LineAndPlane {1 0 0} {0 0 0} {0 0 1} {0 0 0}

line on parallel to plane

%FindInterSectPoint_LineAndPlane {1 0 0} {0 0 0} {0 0 1} {0 0 5}

line on parallel to plane

%FindInterSectPoint_LineAndPlane {0 0 1} {0 0 0} {1 1 1} {2 2 2}

intersection happens before 1st end point {4.0 4.0 4.0 n=-1 d=3 s=-3.0}

%FindInterSectPoint_LineAndPlane {0 0 1} {0 0 0} {-1 -1 -1} {2 2 2}

intersection occurs beyond second end Point {-10.0 -10.0 -10.0 n=-3 d=-9 s=3.0}

+1  A: 

The line

set direction [expr -($norm1*$xB)+($norm2*$yB)+($norm3*$zB)]

doesn't look right although that can't be what's causing your results since basePoint is the origin. Should it not be

set direction [expr -(($norm1*$xB)+($norm2*$yB)+($norm3*$zB))]

Edit:

I've had another look and I can see some problems. Firstly, your definition of d is incorrect. You've used the line direction instead of the plane normal and the topoint of the line instead of the refPoint. I would point out that the former has probably happened because you've used a bizarre naming scheme and called the line direction components norm11, norm12 and norm13! That line of code should be

set d [expr -(($norm1*$xb)+($norm1*$yb)+($norm1*$zb)+$direction)]

The second problem I can see is that s should be d/n and not n/d.

Edit2:

Okay now try removing the test on d as I can't see the point of it. You still need the test on n of course since that's now your denominator and if that's zero then that means the line is parallel to the plane. That is the only circumstance under which there will be no intersection (assuming the line is treated as infinitely long).

Troubadour
oh! sorry but it does not matter, result is same.
OliveOne
That's what I said would happen. See my edit for the next two obvious problems.
Troubadour
I made changes but still it gives wrong output.
OliveOne
Okay, now look at Edit2.
Troubadour
You have really helped me. Now FindInterSectPoint_LineAndPlane proc can give any condition of intersection of plane and line.I am thankfull to you.
OliveOne
No problem. Good luck with what you're using it with.
Troubadour
+2  A: 

What's this?

if {$s < 0 | $s > 1} {
   return 0; # no intersection
}

I'd guess that supposed to be:

if {$s < 0 || $s > 1} {
   return 0
}

(note the difference in "|" and "||).

In addition, a few comments about the above code:

  • Unless you have a reason not to (there aren't many), always brace your expressions --> [expr {$xb-$xa}]. They'll be safer, and much faster.
  • You can greatly shorten your [lindex] code by doing either of these:
    • foreach {xb yb zb} $refPoint {break} (any vesion of tcl)
    • lassign $refPoint xb yb zb (Tcl 8.5 and newer)

Since we don't have the source for "Dot" and "UnitVector", I guess there could be problems there as well.

Jeff Godfrey
I have corrected names. Thanks.
OliveOne