3D线段求交算法不正确
2016-10-25 11:30:50
收藏:0
阅读:139
评论:2
我编写了这段代码用于计算两条3D线段的交点。
但是不幸的是,这段代码的结果不准确,交点并不总是在两条线段上。
我感到困惑,不确定自己做错了什么。
下面是我的代码:
--dir = 方向
--p1,p2 = 表示线段
function GetIntersection(dirStart, dirEnd, p1, p2)
local s1_x, s1_y, s2_x, s2_y = dirEnd.x - dirStart.x, dirEnd.z - dirStart.z, p2.x - p1.x, p2.z - p1.z
local div = (-s2_x * s1_y) + (s1_x * s2_y)
if div == 0 then return nil end
local s = (-s1_y * (dirStart.x - p1.x) + s1_x * (dirStart.z - p1.z)) / div
local t = ( s2_x * (dirStart.z - p1.z) - s2_y * (dirStart.x - p1.x)) / div
if (s >= 0 and s <= 1 and t >= 0 and t <= 1) and (Vector(dirStart.x + (t * s1_x), 0, dirStart.z + (t * s1_y)) or nil) then
local v = Vector(dirStart.x + (t * s1_x),0,dirStart.z + (t * s1_y))
return v
end
end
点赞
用户865481
据我所知,你的代码很好。我已经在 JavaScript 中实现了它(在https://jsfiddle.net/SalixAlba/kkrc9kcf/上),并且似乎对我能想到的所有情况都有效。我所做的唯一更改是将它改成了适用于 JavaScript 而不是 Lua。最终条件被注释掉。
function GetIntersection(dirStart, dirEnd, p1, p2) {
var s1_x = dirEnd.x - dirStart.x;
var s1_y = dirEnd.z - dirStart.z;
var s2_x = p2.x - p1.x;
var s2_y = p2.z - p1.z;
var div = (-s2_x * s1_y) + (s1_x * s2_y);
if (div == 0)
return new Vector(0,0);
var s = (-s1_y * (dirStart.x - p1.x) + s1_x * (dirStart.z - p1.z)) / div;
var t = ( s2_x * (dirStart.z - p1.z) - s2_y * (dirStart.x - p1.x)) / div;
if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {
//and (Vector(dirStart.x + (t * s1_x), 0, dirStart.z + (t * s1_y)) or nil) then
var v = new Vector(
dirStart.x + (t * s1_x),
dirStart.z + (t * s1_y));
return v;
}
return new Vector(0,0);
}
数学上讲,这是有意义的。如果 A、B 和 C、D 是两条线。让 s1=B-A,s2=C-D。线 AB 上的一点由 A+ts1 给出,线 CD 上的一点由 C+ss2 给出。要想交点,我们需要
A + ts1 = C + ss2,
或者
(A-C) + ts1 = ss2。
你的 s、t 公式是通过使用向量 s1 和 s2 的二维叉积得到的。
(A-C)^s1 + ts1^s1 = ss2^s1 (A-C)^s2 + ts1^s2 = ss2^s2
记得 s1^s1=s2^s2=0 以及 s2^s1=-s1^s2,我们得到
(A-C)^s1 = ss2^s1 (A-C)^s2 + ts1^s2 = 0
这可以用来解决 s 和 t,这与你的方程相匹配。
2016-10-25 13:26:36
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

这是一段 Delphi 代码示例,用于计算 3D 空间中两个斜线之间的距离。为了达到您的目的,需要检查结果是否足够小(表示有交点),检查参数 s 和 t 是否在范围 0..1 内,然后使用参数 s 计算点位置。
该方法的数学原理已在 Paul Bourke 页面 的“the shortest line…”章节中进行了描述。
VecDiff 是矢量差函数,Dot 是标量积函数
function LineLineDistance(const L0, L1: TLine3D; var s, t: Double): Double; var u: TPoint3D; a, b, c, d, e, det, invdet:Double; begin u := VecDiff(L1.Base, L0.Base); a := Dot(L0.Direction, L0.Direction); b := Dot(L0.Direction, L1.Direction); c := Dot(L1.Direction, L1.Direction); d := Dot(L0.Direction, u); e := Dot(L1.Direction, u); det := a * c - b * b; if det < eps then Result := -1 else begin invdet := 1 / det; s := invdet * (b * e - c * d); t := invdet * (a * e - b * d); Result := Distance(PointAtParam(L0, s), PointAtParam(L1, t)); end; end;