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

3D平面内满足双距离约束且距P3最近的点的JS实现求助

3D平面内满足距离约束的点求解方案

已知三个3D点P₁(x₁,y₁,z₁)、P₂(x₂,y₂,z₂)、P₃(x₃,y₃,z₃)定义了一个平面,需要在该平面上找到点A,满足:

  • A到P₁的距离为L₁
  • A到P₂的距离为L₂
  • A是两个符合条件的点中,距离P₃最近的那个

核心思路

把3D平面问题转换为局部2D坐标系问题,复用2D求解逻辑后再转换回3D坐标:

  1. 构建平面的局部正交坐标系
  2. 将所有点投影到局部坐标系的2D平面
  3. 用2D方法算出两个候选点
  4. 筛选出离P₃最近的点,再转换回3D世界坐标

JS实现代码

// 向量工具函数
function vecSub(a, b) {
    return { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };
}

function vecAdd(a, b) {
    return { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z };
}

function vecScale(v, s) {
    return { x: v.x * s, y: v.y * s, z: v.z * s };
}

function vecDot(a, b) {
    return a.x * b.x + a.y * b.y + a.z * b.z;
}

function vecLength(v) {
    return Math.sqrt(vecDot(v, v));
}

function vecNormalize(v) {
    const len = vecLength(v);
    return { x: v.x / len, y: v.y / len, z: v.z / len };
}

// 计算3D平面内的目标点
function calculate3DPoint(p1, p2, p3, l1, l2) {
    // 1. 构建局部坐标系
    const u = vecSub(p2, p1);
    const uLen = vecLength(u);
    const uNorm = vecNormalize(u);

    // 计算平面法向量n = u × (p3 - p1)
    const p1p3 = vecSub(p3, p1);
    const n = {
        x: u.y * p1p3.z - u.z * p1p3.y,
        y: u.z * p1p3.x - u.x * p1p3.z,
        z: u.x * p1p3.y - u.y * p1p3.x
    };
    const nNorm = vecNormalize(n);

    // 计算v轴:平面内垂直于u的向量,v = n × u
    const v = {
        x: nNorm.y * uNorm.z - nNorm.z * uNorm.y,
        y: nNorm.z * uNorm.x - nNorm.x * uNorm.z,
        z: nNorm.x * uNorm.y - nNorm.y * uNorm.x
    };

    // 2. 将P3转换为局部2D坐标(以P1为原点,u为x轴,v为y轴)
    const p3LocalX = vecDot(p1p3, uNorm);
    const p3LocalY = vecDot(p1p3, v);

    // 3. 用2D逻辑计算两个候选点的局部坐标
    // 修正原2D代码的公式错误:正确余弦值为(l1² + L² - l2²)/(2*l1*L)
    const L = uLen;
    const cosTheta = (l1 * l1 + L * L - l2 * l2) / (2 * l1 * L);
    // 防止数值误差导致cosTheta超出[-1,1]范围
    const clampedCosTheta = Math.max(-1, Math.min(1, cosTheta));
    const theta = Math.acos(clampedCosTheta);

    // 两个候选点的局部坐标
    const point1Local = {
        x: l1 * Math.cos(theta),
        y: l1 * Math.sin(theta)
    };
    const point2Local = {
        x: l1 * Math.cos(-theta),
        y: l1 * Math.sin(-theta)
    };

    // 4. 计算哪个局部点离P3的局部坐标更近
    const dist1 = Math.hypot(point1Local.x - p3LocalX, point1Local.y - p3LocalY);
    const dist2 = Math.hypot(point2Local.x - p3LocalX, point2Local.y - p3LocalY);
    const selectedLocal = dist1 <= dist2 ? point1Local : point2Local;

    // 5. 将局部坐标转换回3D世界坐标
    const worldPoint = vecAdd(
        p1,
        vecAdd(
            vecScale(uNorm, selectedLocal.x),
            vecScale(v, selectedLocal.y)
        )
    );

    return worldPoint;
}

// 示例用法
const p1 = { x: 0, y: 0, z: 0 };
const p2 = { x: 5, y: 0, z: 0 };
const p3 = { x: 2, y: 3, z: 0 };
const l1 = 3;
const l2 = 4;

const result = calculate3DPoint(p1, p2, p3, l1, l2);
console.log("目标点坐标:", result);

代码说明

  • 向量工具函数:实现3D向量的加减、缩放、点积、长度计算等基础操作,是整个计算的核心支撑
  • 局部坐标系构建:通过向量叉乘得到平面的正交坐标轴,确保所有计算都严格限制在目标平面内
  • 2D计算修正:修复了你原2D代码中的公式错误,并添加数值钳位处理,避免因浮点精度问题导致acos函数报错
  • 候选点筛选:在局部2D坐标系下比较两个候选点到P3的距离,选择更近的点
  • 坐标还原:将筛选后的局部2D坐标转换回3D世界坐标,得到最终结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 01:30:47