如何在保持线段长度与中心不变的情况下使其平行于另一条线段(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平行,需按以下步骤操作:
- 计算Line1的中心点坐标(旋转的基准点)
- 计算Line1两个端点相对于中心点的偏移向量
- 计算旋转角度差:Line2的方向角度减去Line1的原始方向角度
- 对偏移向量应用旋转变换,得到旋转后的偏移量
- 用中心点坐标加上旋转后的偏移量,得到新的端点坐标
代码实现(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
相关产品推荐
相关产品推荐

