Нахождение точки пересечения между плоскостью и линией в tcl? - PullRequest
0 голосов
/ 08 октября 2009

В чем проблема с следующим кодом? Я получаю очень странные результаты. Я что-то упустил?

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 с = -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}

пересечение происходит до 1-й конечной точки {4.0 4.0 4.0 n = -1 d = 3 с = -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 с = 3,0}

Ответы [ 2 ]

2 голосов
/ 08 октября 2009

Что это?

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", я думаю, там тоже могут быть проблемы.

1 голос
/ 08 октября 2009

Линия

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

выглядит неправильно, хотя это не может быть причиной ваших результатов, поскольку basePoint является источником. Разве это не должно быть

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

Edit:

У меня был другой взгляд, и я вижу некоторые проблемы. Во-первых, ваше определение d неверно. Вы использовали направление линии вместо плоскости нормали и topoint линии вместо refPoint. Я хотел бы отметить, что первое, вероятно, произошло, потому что вы использовали причудливую схему именования и назвали компоненты направления линии norm11, norm12 и norm13! Эта строка кода должна быть

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

Вторая проблема, которую я вижу, состоит в том, что s должно быть d / n, а не n / d.

Edit2:

Хорошо, теперь попробуйте удалить тест на d, так как я не вижу смысла в этом. Конечно, вам все равно нужен тест на n, поскольку теперь это ваш знаменатель, и если он равен нулю, это означает, что линия параллельна плоскости. Это единственное обстоятельство, при котором пересечение не будет (при условии, что линия рассматривается как бесконечно длинная).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...