从两条有趣的线,创建盒子并获得所有 4 个角
From two interesting lines, Create box and get all 4 corners
我有两条线相交,我怎样才能在线上放一个盒子来获得 4 个角坐标。
这张图很好的解释了问题。红色虚线(框)只是虚幻的,目的是得到框的 4(????)个角。
可以按方向或形状绘制线条。
我得到了直线的交点和两条直线的中点。
据我了解,您想要一个 world-XY 对齐的 边界矩形。 不然就不是4个而是8个角了;)
实际上,这些线是否相交并不重要。
简单
- 得到直线的四个给定起点和终点
- 根据这些计算 X 轴和 Y 轴的最小值和最大值
- 根据这些最小和最大排列,您可以得到四个角
例如
// The given line points
Vector2 startA;
Vector2 endA;
Vector2 startB;
Vector2 endB;
// calculate min/max for each axis
var minX = Mathf.Min(startA.x, endA.x, startB.x, endB.x);
var maxX = Mathf.Max(startA.x, endA.x, startB.x, endB.x);
var minY = Mathf.Min(startA.y, endA.y, startB.y, endB.y);
var maxY = Mathf.Max(startA.y, endA.y, startB.y, endB.y);
// permutations of these give you the corners
var topRight = new Vector2(maxX, maxY);
var bottomRight = new Vector2(maxX, minY);
var bottomLeft = new Vector2 (minX, minY);
var topLeft = new Vector2 (minX, maxY);
如果你还需要 Z 轴(为了实际得到一个 box),那么 minZ
和 maxZ
相应地只有四个排列.
// The given line points
Vector3 startA;
Vector3 endA;
Vector3 startB;
Vector3 endB;
// calculate min/max for each axis
var minX = Mathf.Min(startA.x, endA.x, startB.x, endB.x);
var maxX = Mathf.Max(startA.x, endA.x, startB.x, endB.x);
var minY = Mathf.Min(startA.y, endA.y, startB.y, endB.y);
var maxY = Mathf.Max(startA.y, endA.y, startB.y, endB.y);
var minZ = Mathf.Min(startA.z, endA.z, startB.z, endB.z);
var maxZ = Mathf.Max(startA.z, endA.z, startB.z, endB.z);
// permutations of these give you the corners
var topRightFront = new Vector3(maxX, maxY, minZ);
var bottomRightFront = new Vector3(maxX, minY, minZ);
var bottomLeftFront = new Vector3 (minX, minY, minZ);
var topLeftFront = new Vector3 (minX, maxY, minZ);
var topRightBack = new Vector3(maxX, maxY, maxZ);
var bottomRightBack = new Vector3(maxX, minY, maxZ);
var bottomLeftBack = new Vector3 (minX, minY, maxZ);
var topLeftBack = new Vector3 (minX, maxY, maxZ);
所以前面提到的代码假设您希望 rect/box 与世界轴对齐。
如果不是这种情况,您可以使用以下方式
- 有一个空的 GameObject 作为旋转世界的参考(例如通过 QR 码跟踪等对齐)- 我们称它为“WorldAnchor”
- 将线点转换成那个WorldAnchor
的本地space
- 现在在本地space
对所有轴执行相同的min/max计算
- 做同样的排列得到角
- 最终将角落转换回世界space
类似
// The given line points in WORLD Space
Vector3 startA;
Vector3 endA;
Vector3 startB;
Vector3 endB;
// The given oriented world anchor
Transform anchor;
// The line points converted to LOCAL space
var localStartA = anchor.InverseTransformPoint(startA);
var localEndA = anchor.InverseTransformPoint(endA);
var localStartB = anchor.InverseTransformPoint(startB);
var localEndB = anchor.InverseTransformPoint(endB);
// calculate min/max for each axis
var localMinX = Mathf.Min(localStartA.x, localEndA.x, localStartB.x, localEndB.x);
var localMaxX = Mathf.Max(localStartA.x, localEndA.x, localStartB.x, localEndB.x);
var localMinY = Mathf.Min(localStartA.y, localEndA.y, localStartB.y, localEndB.y);
var localMaxY = Mathf.Max(localStartA.y, localEndA.y, localStartB.y, localEndB.y);
var localMinZ = Mathf.Min(localStartA.z, localEndA.z, localStartB.z, localEndB.z);
var localMaxZ = Mathf.Max(localStartA.z, localEndA.z, localStartB.z, localEndB.z);
// permutations of these give you the corners
var localTopRightFront = new Vector3(localMaxX, localMaxY, localMinZ);
var localBottomRightFront = new Vector3(localMaxX, localMinY, localMinZ);
var localBottomLeftFront = new Vector3 (localMinX, localMinY, localMinZ);
var localTopLeftFront = new Vector3 (localMinX, localMaxY, localMinZ);
var localTopRightBack = new Vector3(localMaxX, localMaxY, localMaxZ);
var localBottomRightBack = new Vector3(localMaxX, localMinY, localMaxZ);
var localBottomLeftBack = new Vector3 (localMinX, localMinY, localMaxZ);
var localTopLeftBack = new Vector3 (localMinX, localMaxY, localMaxZ);
现在要么简单地将角可视化器放置在这些位置,但作为 WorldAnchor 对象的子对象。
或者使用
将它们转换回全局世界space
var topRightFront = anchor.TransformPoint(localTopRightFront);
var bottomRightFront = anchor.TransformPoint(localBottomRightFront);
var bottomLeftFront = anchor.TransformPoint(localBottomLeftFront);
var topLeftFront = anchor.TransformPoint(localTopLeftFront);
var topRightBack = anchor.TransformPoint(localTopRightBack);
var bottomRightBack = anchor.TransformPoint(localBottomRightBack);
var bottomLeftBack = anchor.TransformPoint(localBottomLeftBack);
var topLeftBack = anchor.TransformPoint(localTopLeftBack);
我有两条线相交,我怎样才能在线上放一个盒子来获得 4 个角坐标。
这张图很好的解释了问题。红色虚线(框)只是虚幻的,目的是得到框的 4(????)个角。
可以按方向或形状绘制线条。
我得到了直线的交点和两条直线的中点。
据我了解,您想要一个 world-XY 对齐的 边界矩形。 不然就不是4个而是8个角了;)
实际上,这些线是否相交并不重要。
简单
- 得到直线的四个给定起点和终点
- 根据这些计算 X 轴和 Y 轴的最小值和最大值
- 根据这些最小和最大排列,您可以得到四个角
例如
// The given line points
Vector2 startA;
Vector2 endA;
Vector2 startB;
Vector2 endB;
// calculate min/max for each axis
var minX = Mathf.Min(startA.x, endA.x, startB.x, endB.x);
var maxX = Mathf.Max(startA.x, endA.x, startB.x, endB.x);
var minY = Mathf.Min(startA.y, endA.y, startB.y, endB.y);
var maxY = Mathf.Max(startA.y, endA.y, startB.y, endB.y);
// permutations of these give you the corners
var topRight = new Vector2(maxX, maxY);
var bottomRight = new Vector2(maxX, minY);
var bottomLeft = new Vector2 (minX, minY);
var topLeft = new Vector2 (minX, maxY);
如果你还需要 Z 轴(为了实际得到一个 box),那么 minZ
和 maxZ
相应地只有四个排列.
// The given line points
Vector3 startA;
Vector3 endA;
Vector3 startB;
Vector3 endB;
// calculate min/max for each axis
var minX = Mathf.Min(startA.x, endA.x, startB.x, endB.x);
var maxX = Mathf.Max(startA.x, endA.x, startB.x, endB.x);
var minY = Mathf.Min(startA.y, endA.y, startB.y, endB.y);
var maxY = Mathf.Max(startA.y, endA.y, startB.y, endB.y);
var minZ = Mathf.Min(startA.z, endA.z, startB.z, endB.z);
var maxZ = Mathf.Max(startA.z, endA.z, startB.z, endB.z);
// permutations of these give you the corners
var topRightFront = new Vector3(maxX, maxY, minZ);
var bottomRightFront = new Vector3(maxX, minY, minZ);
var bottomLeftFront = new Vector3 (minX, minY, minZ);
var topLeftFront = new Vector3 (minX, maxY, minZ);
var topRightBack = new Vector3(maxX, maxY, maxZ);
var bottomRightBack = new Vector3(maxX, minY, maxZ);
var bottomLeftBack = new Vector3 (minX, minY, maxZ);
var topLeftBack = new Vector3 (minX, maxY, maxZ);
所以前面提到的代码假设您希望 rect/box 与世界轴对齐。
如果不是这种情况,您可以使用以下方式
- 有一个空的 GameObject 作为旋转世界的参考(例如通过 QR 码跟踪等对齐)- 我们称它为“WorldAnchor”
- 将线点转换成那个WorldAnchor 的本地space
- 现在在本地space 对所有轴执行相同的min/max计算
- 做同样的排列得到角
- 最终将角落转换回世界space
类似
// The given line points in WORLD Space
Vector3 startA;
Vector3 endA;
Vector3 startB;
Vector3 endB;
// The given oriented world anchor
Transform anchor;
// The line points converted to LOCAL space
var localStartA = anchor.InverseTransformPoint(startA);
var localEndA = anchor.InverseTransformPoint(endA);
var localStartB = anchor.InverseTransformPoint(startB);
var localEndB = anchor.InverseTransformPoint(endB);
// calculate min/max for each axis
var localMinX = Mathf.Min(localStartA.x, localEndA.x, localStartB.x, localEndB.x);
var localMaxX = Mathf.Max(localStartA.x, localEndA.x, localStartB.x, localEndB.x);
var localMinY = Mathf.Min(localStartA.y, localEndA.y, localStartB.y, localEndB.y);
var localMaxY = Mathf.Max(localStartA.y, localEndA.y, localStartB.y, localEndB.y);
var localMinZ = Mathf.Min(localStartA.z, localEndA.z, localStartB.z, localEndB.z);
var localMaxZ = Mathf.Max(localStartA.z, localEndA.z, localStartB.z, localEndB.z);
// permutations of these give you the corners
var localTopRightFront = new Vector3(localMaxX, localMaxY, localMinZ);
var localBottomRightFront = new Vector3(localMaxX, localMinY, localMinZ);
var localBottomLeftFront = new Vector3 (localMinX, localMinY, localMinZ);
var localTopLeftFront = new Vector3 (localMinX, localMaxY, localMinZ);
var localTopRightBack = new Vector3(localMaxX, localMaxY, localMaxZ);
var localBottomRightBack = new Vector3(localMaxX, localMinY, localMaxZ);
var localBottomLeftBack = new Vector3 (localMinX, localMinY, localMaxZ);
var localTopLeftBack = new Vector3 (localMinX, localMaxY, localMaxZ);
现在要么简单地将角可视化器放置在这些位置,但作为 WorldAnchor 对象的子对象。
或者使用
将它们转换回全局世界spacevar topRightFront = anchor.TransformPoint(localTopRightFront);
var bottomRightFront = anchor.TransformPoint(localBottomRightFront);
var bottomLeftFront = anchor.TransformPoint(localBottomLeftFront);
var topLeftFront = anchor.TransformPoint(localTopLeftFront);
var topRightBack = anchor.TransformPoint(localTopRightBack);
var bottomRightBack = anchor.TransformPoint(localBottomRightBack);
var bottomLeftBack = anchor.TransformPoint(localBottomLeftBack);
var topLeftBack = anchor.TransformPoint(localTopLeftBack);