区块链技术博客
www.b2bchain.cn

S02E06:线段与线段最近点坐标求职学习资料

本文介绍了S02E06:线段与线段最近点坐标求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

说明

线段与线段最近点坐标,当然也可以仿照射线那样,分情况讨论处理,只不过线段的情况比射线复杂了一倍而已。从理论上讲写出来也不算太难,但是这里,我们可以试试其它方法,比如万能的矩阵:构造一个局部坐标系,将两根线段转换到一个平面上进行处理,求出最近点。

几何

如下图,线段 AB 和 CD 在空间内的位置。我们要利用它们构建一个坐标系,以点 A 为原点,AB 为 x 轴。
S02E06:线段与线段最近点坐标

构造局部坐标系

那么接下来,用叉乘来构造 z 轴,即同时垂直于 AB 和 CD 的轴。再用 x 轴和 z 轴叉乘来得到 y 轴,这样一来就可以将两根线段的位置关系,从三维空间降级到 xy 平面上进行处理了。如下图,向量 AF 就是我们构造出来的 z 轴,它同时垂直于 AB 和 CD。
S02E06:线段与线段最近点坐标
不过这里有个小问题:如果 AB 和 CD 是平行的,那叉乘就没有意义了。这里应该怎么办?这时,我们可以任选一个向量来当临时向量,比如选以前的原始 x 轴,即(1, 0, 0)方向,利用叉乘得到垂直于 AB 和(1, 0, 0)的向量,把它当做局部坐标系的 z 轴,就可以继续后面的处理。

不过这里又有一个问题:如果 AB 平行于 CD,并且平行于原始的 x 轴,又该怎么办?这样其实更简单,我们直接选取原始的 z 轴(0, 0, 1)作为局部坐标系的 z 轴就可以了。这里显然,z 轴是垂直于 x 轴的,也垂直于 AB 和 CD。

总之,不管什么情况,我们的目标是构造出同时垂直于 AB 和 CD 的局部 z 轴,这样就可以暂时丢掉 z 坐标,专心在 xy 平面处理两个线段的位置关系,这样将三维问题化简为二维平面问题。而且其中线段 AB 还在局部坐标系的 x 轴上,A 点是局部坐标系的原点,这样大大降低了处理的难度。

如下图,我们最后得到的局部坐标系如下:以点 A 为坐标原点,以 AB 为 x 轴,以 AG 为 y 轴,以 AF 为 z 轴。
S02E06:线段与线段最近点坐标
然后,我们可以将点 B、C、D 的坐标转换到这个局部坐标系中,并暂时丢弃 z 轴坐标。得到一个平面的线段关系图。
S02E06:线段与线段最近点坐标

平面关系处理

那么接下来,我们在二维平面上,对线段 AB 和 CD 的关系进行讨论并处理。
首先,我们要考虑,AB 和 CD 平行的问题,当平行时,判断 x 轴坐标是否有重合部分,如果有,就有无穷多个最近点;如果没有重合部分,那端点就是最近点。
S02E06:线段与线段最近点坐标

不平行时,我们先考虑,CD 延长线与 AB (即 x 轴)相交的情况,按与 AB 所在直线相交的位置不同,可以分为三种情况:

  • 交点在点 A 左侧
  • 交点在点 B 右侧
  • 交点在 AB 中间
    S02E06:线段与线段最近点坐标
    S02E06:线段与线段最近点坐标
    S02E06:线段与线段最近点坐标

而上述三种情况下,交点在左右两侧时,又可以根据 CD 的位置分为三种情况(我们以左侧为例,右侧同理):

  • 线段 CD 有部分落在左侧,则最近点是点 A,及 A 到 CD 的最近点;
    S02E06:线段与线段最近点坐标
    S02E06:线段与线段最近点坐标
    S02E06:线段与线段最近点坐标
  • 线段 CD 全都在点 A 右侧,其中一点离点 C 近,则最近点是点 C,及点 C 到线段 AB 的最近点;
    S02E06:线段与线段最近点坐标
  • 线段 CD 全都在点 A 右侧,其中一点离点 D 近,则最近点是点 D,及点 D 到线段 AB 的最近点;
    S02E06:线段与线段最近点坐标

那么当交点在线段 AB 中间时,则 CD 的情况也是分三种处理:

  • 交点在 CD 中间,则最近点可按两条直线最近点处理,但在平面上,交点坐标可以直接求出来;
    S02E06:线段与线段最近点坐标
  • 交点在 CD 延长线,点 C 一侧,故最近点分别是点 C,点 C 到线段 AB 的最近点;
    S02E06:线段与线段最近点坐标
  • 交点在 CD 延长线,点 D 一侧,故最近点分别是点 D,点 D 到线段 AB 的最近点;
    S02E06:线段与线段最近点坐标

情况总结

所以总共有 3×3 种情况,而交点 F 的计算也并不复杂,因为 F 可以用点 C 和点 D 来表示,而 F 的 y 坐标等于 0。由此不仅能计算出 F 点坐标,还能知道 F 点在 CD 的位置情况:在 CD 中间,在 C 的外侧,在 D 的外侧。

最后,如果是在局部坐标系得到的交点,还需要再转换到世界坐标系中。

代码

“`swift
///线段与线段最近点坐标
static func nearestPoints(segment1:Segment, segment2:Segment) -> (simd_float3, simd_float3)? {
//构造局部坐标系,segment1 为 x 轴,point1 为坐标原点;z 轴垂直于线段构成的平面;
let direction1 = segment1.point2 – segment1.point1
let direction2 = segment2.point2 – segment2.point1
let p = direction1.almostParallelRelative(to: direction2)

var zValue = p.crossValue if p.isParallel {     // 平行时,构造特殊的矩阵     let xDirection = simd_float3(1, 0, 0)     let px = direction1.almostParallelRelative(to: xDirection)     if px.isParallel {         zValue = simd_float3(0, 0, 1)     } else {         zValue = cross(xDirection,direction1)     } } let xAxis = normalize(direction1) let zAxis = normalize(zValue) let yAxis = normalize(cross(zAxis, xAxis)) let localMatrix = matrix_float4x4(

说明

线段与线段最近点坐标,当然也可以仿照射线那样,分情况讨论处理,只不过线段的情况比射线复杂了一倍而已。从理论上讲写出来也不算太难,但是这里,我们可以试试其它方法,比如万能的矩阵:构造一个局部坐标系,将两根线段转换到一个平面上进行处理,求出最近点。

几何

如下图,线段 AB 和 CD 在空间内的位置。我们要利用它们构建一个坐标系,以点 A 为原点,AB 为 x 轴。
S02E06:线段与线段最近点坐标

构造局部坐标系

那么接下来,用叉乘来构造 z 轴,即同时垂直于 AB 和 CD 的轴。再用 x 轴和 z 轴叉乘来得到 y 轴,这样一来就可以将两根线段的位置关系,从三维空间降级到 xy 平面上进行处理了。如下图,向量 AF 就是我们构造出来的 z 轴,它同时垂直于 AB 和 CD。
S02E06:线段与线段最近点坐标
不过这里有个小问题:如果 AB 和 CD 是平行的,那叉乘就没有意义了。这里应该怎么办?这时,我们可以任选一个向量来当临时向量,比如选以前的原始 x 轴,即(1, 0, 0)方向,利用叉乘得到垂直于 AB 和(1, 0, 0)的向量,把它当做局部坐标系的 z 轴,就可以继续后面的处理。

不过这里又有一个问题:如果 AB 平行于 CD,并且平行于原始的 x 轴,又该怎么办?这样其实更简单,我们直接选取原始的 z 轴(0, 0, 1)作为局部坐标系的 z 轴就可以了。这里显然,z 轴是垂直于 x 轴的,也垂直于 AB 和 CD。

总之,不管什么情况,我们的目标是构造出同时垂直于 AB 和 CD 的局部 z 轴,这样就可以暂时丢掉 z 坐标,专心在 xy 平面处理两个线段的位置关系,这样将三维问题化简为二维平面问题。而且其中线段 AB 还在局部坐标系的 x 轴上,A 点是局部坐标系的原点,这样大大降低了处理的难度。

如下图,我们最后得到的局部坐标系如下:以点 A 为坐标原点,以 AB 为 x 轴,以 AG 为 y 轴,以 AF 为 z 轴。
S02E06:线段与线段最近点坐标
然后,我们可以将点 B、C、D 的坐标转换到这个局部坐标系中,并暂时丢弃 z 轴坐标。得到一个平面的线段关系图。
S02E06:线段与线段最近点坐标

平面关系处理

那么接下来,我们在二维平面上,对线段 AB 和 CD 的关系进行讨论并处理。
首先,我们要考虑,AB 和 CD 平行的问题,当平行时,判断 x 轴坐标是否有重合部分,如果有,就有无穷多个最近点;如果没有重合部分,那端点就是最近点。
S02E06:线段与线段最近点坐标

不平行时,我们先考虑,CD 延长线与 AB (即 x 轴)相交的情况,按与 AB 所在直线相交的位置不同,可以分为三种情况:

  • 交点在点 A 左侧
  • 交点在点 B 右侧
  • 交点在 AB 中间
    S02E06:线段与线段最近点坐标
    S02E06:线段与线段最近点坐标
    S02E06:线段与线段最近点坐标

而上述三种情况下,交点在左右两侧时,又可以根据 CD 的位置分为三种情况(我们以左侧为例,右侧同理):

  • 线段 CD 有部分落在左侧,则最近点是点 A,及 A 到 CD 的最近点;
    S02E06:线段与线段最近点坐标
    S02E06:线段与线段最近点坐标
    S02E06:线段与线段最近点坐标
  • 线段 CD 全都在点 A 右侧,其中一点离点 C 近,则最近点是点 C,及点 C 到线段 AB 的最近点;
    S02E06:线段与线段最近点坐标
  • 线段 CD 全都在点 A 右侧,其中一点离点 D 近,则最近点是点 D,及点 D 到线段 AB 的最近点;
    S02E06:线段与线段最近点坐标

那么当交点在线段 AB 中间时,则 CD 的情况也是分三种处理:

  • 交点在 CD 中间,则最近点可按两条直线最近点处理,但在平面上,交点坐标可以直接求出来;
    S02E06:线段与线段最近点坐标
  • 交点在 CD 延长线,点 C 一侧,故最近点分别是点 C,点 C 到线段 AB 的最近点;
    S02E06:线段与线段最近点坐标
  • 交点在 CD 延长线,点 D 一侧,故最近点分别是点 D,点 D 到线段 AB 的最近点;
    S02E06:线段与线段最近点坐标

情况总结

所以总共有 3×3 种情况,而交点 F 的计算也并不复杂,因为 F 可以用点 C 和点 D 来表示,而 F 的 y 坐标等于 0。由此不仅能计算出 F 点坐标,还能知道 F 点在 CD 的位置情况:在 CD 中间,在 C 的外侧,在 D 的外侧。

最后,如果是在局部坐标系得到的交点,还需要再转换到世界坐标系中。

代码

“`swift
///线段与线段最近点坐标
static func nearestPoints(segment1:Segment, segment2:Segment) -> (simd_float3, simd_float3)? {
//构造局部坐标系,segment1 为 x 轴,point1 为坐标原点;z 轴垂直于线段构成的平面;
let direction1 = segment1.point2 – segment1.point1
let direction2 = segment2.point2 – segment2.point1
let p = direction1.almostParallelRelative(to: direction2)

var zValue = p.crossValue if p.isParallel {     // 平行时,构造特殊的矩阵     let xDirection = simd_float3(1, 0, 0)     let px = direction1.almostParallelRelative(to: xDirection)     if px.isParallel {         zValue = simd_float3(0, 0, 1)     } else {         zValue = cross(xDirection,direction1)     } } let xAxis = normalize(direction1) let zAxis = normalize(zValue) let yAxis = normalize(cross(zAxis, xAxis)) let localMatrix = matrix_float4x4(

说明

线段与线段最近点坐标,当然也可以仿照射线那样,分情况讨论处理,只不过线段的情况比射线复杂了一倍而已。从理论上讲写出来也不算太难,但是这里,我们可以试试其它方法,比如万能的矩阵:构造一个局部坐标系,将两根线段转换到一个平面上进行处理,求出最近点。

几何

如下图,线段 AB 和 CD 在空间内的位置。我们要利用它们构建一个坐标系,以点 A 为原点,AB 为 x 轴。
S02E06:线段与线段最近点坐标

构造局部坐标系

那么接下来,用叉乘来构造 z 轴,即同时垂直于 AB 和 CD 的轴。再用 x 轴和 z 轴叉乘来得到 y 轴,这样一来就可以将两根线段的位置关系,从三维空间降级到 xy 平面上进行处理了。如下图,向量 AF 就是我们构造出来的 z 轴,它同时垂直于 AB 和 CD。
S02E06:线段与线段最近点坐标
不过这里有个小问题:如果 AB 和 CD 是平行的,那叉乘就没有意义了。这里应该怎么办?这时,我们可以任选一个向量来当临时向量,比如选以前的原始 x 轴,即(1, 0, 0)方向,利用叉乘得到垂直于 AB 和(1, 0, 0)的向量,把它当做局部坐标系的 z 轴,就可以继续后面的处理。

不过这里又有一个问题:如果 AB 平行于 CD,并且平行于原始的 x 轴,又该怎么办?这样其实更简单,我们直接选取原始的 z 轴(0, 0, 1)作为局部坐标系的 z 轴就可以了。这里显然,z 轴是垂直于 x 轴的,也垂直于 AB 和 CD。

总之,不管什么情况,我们的目标是构造出同时垂直于 AB 和 CD 的局部 z 轴,这样就可以暂时丢掉 z 坐标,专心在 xy 平面处理两个线段的位置关系,这样将三维问题化简为二维平面问题。而且其中线段 AB 还在局部坐标系的 x 轴上,A 点是局部坐标系的原点,这样大大降低了处理的难度。

如下图,我们最后得到的局部坐标系如下:以点 A 为坐标原点,以 AB 为 x 轴,以 AG 为 y 轴,以 AF 为 z 轴。
S02E06:线段与线段最近点坐标
然后,我们可以将点 B、C、D 的坐标转换到这个局部坐标系中,并暂时丢弃 z 轴坐标。得到一个平面的线段关系图。
S02E06:线段与线段最近点坐标

平面关系处理

那么接下来,我们在二维平面上,对线段 AB 和 CD 的关系进行讨论并处理。
首先,我们要考虑,AB 和 CD 平行的问题,当平行时,判断 x 轴坐标是否有重合部分,如果有,就有无穷多个最近点;如果没有重合部分,那端点就是最近点。
S02E06:线段与线段最近点坐标

不平行时,我们先考虑,CD 延长线与 AB (即 x 轴)相交的情况,按与 AB 所在直线相交的位置不同,可以分为三种情况:

  • 交点在点 A 左侧
  • 交点在点 B 右侧
  • 交点在 AB 中间
    S02E06:线段与线段最近点坐标
    S02E06:线段与线段最近点坐标
    S02E06:线段与线段最近点坐标

而上述三种情况下,交点在左右两侧时,又可以根据 CD 的位置分为三种情况(我们以左侧为例,右侧同理):

  • 线段 CD 有部分落在左侧,则最近点是点 A,及 A 到 CD 的最近点;
    S02E06:线段与线段最近点坐标
    S02E06:线段与线段最近点坐标
    S02E06:线段与线段最近点坐标
  • 线段 CD 全都在点 A 右侧,其中一点离点 C 近,则最近点是点 C,及点 C 到线段 AB 的最近点;
    S02E06:线段与线段最近点坐标
  • 线段 CD 全都在点 A 右侧,其中一点离点 D 近,则最近点是点 D,及点 D 到线段 AB 的最近点;
    S02E06:线段与线段最近点坐标

那么当交点在线段 AB 中间时,则 CD 的情况也是分三种处理:

  • 交点在 CD 中间,则最近点可按两条直线最近点处理,但在平面上,交点坐标可以直接求出来;
    S02E06:线段与线段最近点坐标
  • 交点在 CD 延长线,点 C 一侧,故最近点分别是点 C,点 C 到线段 AB 的最近点;
    S02E06:线段与线段最近点坐标
  • 交点在 CD 延长线,点 D 一侧,故最近点分别是点 D,点 D 到线段 AB 的最近点;
    S02E06:线段与线段最近点坐标

情况总结

所以总共有 3×3 种情况,而交点 F 的计算也并不复杂,因为 F 可以用点 C 和点 D 来表示,而 F 的 y 坐标等于 0。由此不仅能计算出 F 点坐标,还能知道 F 点在 CD 的位置情况:在 CD 中间,在 C 的外侧,在 D 的外侧。

最后,如果是在局部坐标系得到的交点,还需要再转换到世界坐标系中。

代码

“`swift
///线段与线段最近点坐标
static func nearestPoints(segment1:Segment, segment2:Segment) -> (simd_float3, simd_float3)? {
//构造局部坐标系,segment1 为 x 轴,point1 为坐标原点;z 轴垂直于线段构成的平面;
let direction1 = segment1.point2 – segment1.point1
let direction2 = segment2.point2 – segment2.point1
let p = direction1.almostParallelRelative(to: direction2)

var zValue = p.crossValue if p.isParallel {     // 平行时,构造特殊的矩阵     let xDirection = simd_float3(1, 0, 0)     let px = direction1.almostParallelRelative(to: xDirection)     if px.isParallel {         zValue = simd_float3(0, 0, 1)     } else {         zValue = cross(xDirection,direction1)     } } let xAxis = normalize(direction1) let zAxis = normalize(zValue) let yAxis = normalize(cross(zAxis, xAxis)) let localMatrix = matrix_float4x4(

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » S02E06:线段与线段最近点坐标求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们