在tcl中找到平面和直线之间的交点?

发布于 2024-08-06 14:10:11 字数 2042 浏览 6 评论 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}

与平面平行的线plane

%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} 之外

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}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

泛泛之交 2024-08-13 14:10:11

这是什么?

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”的源代码,我想那里也可能存在问题。

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.

翻身的咸鱼 2024-08-13 14:10:11

该线

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

看起来不正确,尽管这不可能是导致结果的原因,因为 basePoint 是原点。不应该

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

编辑吗:

我又看了一遍,发现了一些问题。首先,您对 d 的定义不正确。您使用了直线方向而不是平面法线,并使用了直线的topoint 而不是refPoint。我想指出的是,前者可能会发生,因为您使用了奇怪的命名方案并将线方向组件称为 norm11norm12norm13 >!该行代码应该是

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

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

Edit2:

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

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文