0

以下代码有什么问题?我得到了非常奇怪的结果。我错过了什么吗?

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"
 }

输出:

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

交点落在第一个端点 {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}

平行于平面的线

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

平行于平面的线

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

相交发生在第一个终点之前 {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}

交叉点超出第二个端点 {-10.0 -10.0 -10.0 n=-3 d=-9 s=3.0}

4

2 回答 2

2

这是什么?

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

我猜应该是:

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

(注意“|”和“||”的区别)。

另外,关于上述代码的几点注释:

  • 除非你有理由不这样做(没有很多),否则请始终支持你的表达式 --> [expr {$xb-$xa}]。它们会更安全,也更快
  • 通过执行以下任一操作,您可以大大缩短 [lindex] 代码:
    • foreach {xb yb zb} $refPoint {break}(任何版本的 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.

于 2009-10-08T13:25:56.243 回答
1

线

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

看起来不正确,尽管这不是导致您的结果的原因,因为basePoint它是起源。不应该

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

编辑:

我又看了一遍,我可以看到一些问题。首先,您的定义d不正确。您已经使用线方向而不是平面法线和线的方向而topoint不是refPoint. 我要指出,前者可能已经发生,因为您使用了一种奇怪的命名方案并称为线方向组件norm11norm12并且norm13!那行代码应该是

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

我能看到的第二个问题是s应该是d/n而不是n/ d

编辑2:

好的,现在尝试删除测试,d因为我看不到它的意义。当然,您仍然需要进行测试n,因为现在这是您的分母,如果为零,则表示该线平行于平面。这是唯一没有交叉点的情况(假设线被视为无限长)。

于 2009-10-08T12:59:58.480 回答