You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

已知正方形顶点、周长上一点及长度,如何确定周长上目标点?

正方形周长上按长度偏移点的最优解法

问题背景

给定正方形的四个顶点向量v1、v2、v3、v4,周长上任意一点p,以及偏移长度n,需要确定周长上经过偏移后的点r。示例代码如下:

let v1 = CGPoint(x: 0.0, y: 0.0)
let v2 = CGPoint(x: 10.0, y: 0.0)
let v3 = CGPoint(x: 10.0, y: 10.0)
let v4 = CGPoint(x: 0.0, y: 10.0)

let corners = [v1, v2, v3, v4]
let p = CGPoint(x: 5.0, y: 0.0)

func add(length n: CGFloat, to p: CGPoint, constrainedTo corners: [CGPoint]) -> CGPoint {
    // …magic!🪄
    return r
}

var n: CGFloat = 17.0
let r = add(length: n, to: p, constrainedTo: corners) // 结果:CGPoint(x: 8.0, y: 10.0)

n = -17.0
let r = add(length: n, to: p, constrainedTo: corners) // 结果:CGPoint(x: 2.0, y: 10.0)

n = -32.8
let r = add(length: n, to: p, constrainedTo: corners) // 结果:CGPoint(x: 10.0, y: 2.2)

疑问

最有效的方式是循环遍历边,逐步增减长度直到n=0吗?还是存在对应的数学公式可以直接计算?

最优解法:数学公式直接计算

循环遍历边逐步消耗长度的方法虽然直观,但效率远不如直接用数学公式计算——尤其是当偏移长度远大于正方形周长时,循环会重复绕圈遍历多轮边,完全是性能浪费。用数学公式可以一步到位,核心步骤如下:

  1. 计算总周长:正方形四条边等长,算出单条边的长度后乘4得到perimeter。
  2. 压缩偏移量:因为周长是循环的,把n对perimeter取模,得到normalizedN,直接把超大的偏移量压缩到一个周长范围内。注意负数的处理:取模后要保持负方向的一致性,避免方向错乱。
  3. 定位p在周长上的位置:遍历正方形的边(最后一个顶点要和第一个顶点相连形成闭合周长),判断p落在哪条边上,再计算p到这条边起点的距离,累计得到p从周长起始点开始的总长度totalDistanceFromStart。
  4. 计算目标点的总位置:把totalDistanceFromStart加上normalizedN得到targetTotalDistance。如果这个值小于0就加perimeter,大于perimeter就减perimeter,确保它落在0到perimeter的范围内。
  5. 算出目标点坐标:再次遍历边的累计长度,找到targetTotalDistance对应的边,计算该边上的相对位置,最终得到目标点r的坐标。

两种方法对比

循环遍历的思路是从p所在边开始,每次用当前边的剩余长度抵消n,直到n被耗完。这种方法逻辑简单,但当n是周长的几十上百倍时,会重复遍历很多轮边,效率极低。而数学公式的方法通过偏移量归一化,只需要两次遍历边(一次找p的位置,一次找目标点的边),不管n多大,都能在固定时间内完成计算,性能优势很明显。

内容的提问来源于stack exchange,提问作者forgot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 21:35:27