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}

交差点は 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 以降)

「Dot」と「UnitVector」のソースがないので、そこにも問題があるのではないかと思います。

于 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は正しくありません。平面法線の代わりに線の方向を使用し、 の代わりに線の を使用しましtopointrefPointnorm11前者はおそらく奇妙な命名スキームを使用し、行方向コンポーネントを呼び出したために発生した可能性があることを指摘しnorm12ますnorm13。そのコード行は

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

私が見ることができる2番目の問題は、/ではなく/であるsべきだということです。dnnd

編集2:

さて、テストdの要点がわからないので、テストを削除してみてください。もちろん、それが分母であるため、まだテストが必要ですn。それがゼロの場合、線が平面に平行であることを意味します。これが交差しない唯一の状況です (線が無限に長いものとして扱われると仮定して)。

于 2009-10-08T12:59:58.480 に答える