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

如何在保持线段长度与中心不变的情况下使其平行于另一条线段(C#实现)

问题需求

已知线段Line1的两个端点坐标(X1,Y1)、(X2,Y2),以及线段Line2的端点坐标(X3,Y3)、(X4,Y4)。需要计算Line1旋转后的新端点坐标,满足两个核心要求:

  • 旋转后的Line1与Line2平行
  • Line1的中心点坐标保持不变(仅做旋转操作,不改变线段长度和中心位置)

已能实现线段角度和长度的基础计算,但尝试的方案要么旋转结果错误,要么旋转后线段长度改变;现有代码能实现平行旋转,但无法保留Line1的原始长度。


已实现的基础计算代码

计算线段角度

var line1Angle = Mathf.Atan2(x2 - x1, y2 - y1);
var line2Angle = Mathf.Atan2(x4 - x3, y4 - y3);

计算线段长度

var len1 = Math.Sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
var len2 = Math.Sqrt((x4 - x3) * (x4 - x3) + (y4 - y3) * (y4 - y3));

现有问题代码(旋转平行但丢失长度)

float len1 = (float)Math.Sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
float len2 = (float)Math.Sqrt((x4 - x3) * (x4 - x3) + (y4 - y3) * (y4 - y3));

float offset = 3.0f; // 原计划取Line1中心到Line2最近点的距离,暂时设为固定值
float newX1 = x3 + offset * (y4 - y3) * (len1 / len2);
float newX2 = x4 + offset * (y4 - y3) * (len1 / len2);
float newY1 = y3 + offset * (x3 - x4) * (len1 / len2);
float newY2 = y4 + offset * (x3 - x4) * (len1 / len2); 

正确解决方案与代码实现

核心思路

要实现围绕中心点旋转且保留长度、与Line2平行,需按以下步骤操作:

  1. 计算Line1的中心点坐标(旋转的基准点)
  2. 计算Line1两个端点相对于中心点的偏移向量
  3. 计算旋转角度差:Line2的方向角度减去Line1的原始方向角度
  4. 对偏移向量应用旋转变换,得到旋转后的偏移量
  5. 用中心点坐标加上旋转后的偏移量,得到新的端点坐标

代码实现(C#/Unity)

// 输入参数:Line1的两个端点(x1,y1)(x2,y2),Line2的两个端点(x3,y3)(x4,y4)
public void RotateLine1ToMatchLine2(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, out float newX1, out float newY1, out float newX2, out float newY2)
{
    // 1. 计算Line1的中心点坐标
    float centerX = (x1 + x2) / 2f;
    float centerY = (y1 + y2) / 2f;

    // 2. 计算Line1两个端点相对于中心点的偏移向量
    float offsetX1 = x1 - centerX;
    float offsetY1 = y1 - centerY;
    float offsetX2 = x2 - centerX;
    float offsetY2 = y2 - centerY;

    // 3. 计算两条线段的方向角度(注意Atan2参数顺序:y差在前,x差在后)
    float line1Angle = Mathf.Atan2(y2 - y1, x2 - x1);
    float line2Angle = Mathf.Atan2(y4 - y3, x4 - x3);

    // 4. 计算需要旋转的角度差
    float rotateDelta = line2Angle - line1Angle;

    // 5. 计算旋转所需的余弦和正弦值
    float cosDelta = Mathf.Cos(rotateDelta);
    float sinDelta = Mathf.Sin(rotateDelta);

    // 6. 对偏移向量应用旋转变换
    // 旋转公式:x' = x*cosθ - y*sinθ; y' = x*sinθ + y*cosθ
    float newOffsetX1 = offsetX1 * cosDelta - offsetY1 * sinDelta;
    float newOffsetY1 = offsetX1 * sinDelta + offsetY1 * cosDelta;
    float newOffsetX2 = offsetX2 * cosDelta - offsetY2 * sinDelta;
    float newOffsetY2 = offsetX2 * sinDelta + offsetY2 * cosDelta;

    // 7. 计算新的端点坐标
    newX1 = centerX + newOffsetX1;
    newY1 = centerY + newOffsetY1;
    newX2 = centerX + newOffsetX2;
    newY2 = centerY + newOffsetY2;
}

关键说明

  • 修正了Mathf.Atan2的参数顺序:Unity中Atan2(y差, x差)才是正确的方向角度计算方式,原代码参数顺序错误是旋转结果异常的核心原因之一
  • 基于中心点的偏移向量做旋转变换,确保旋转后中心位置不变,线段长度完全保留
  • 角度差直接取Line2与Line1的角度差值,保证旋转后线段方向与Line2完全平行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 16:09:23