在三维空间中,我有一组无序的,比如6分;像这样的东西:
(A)*
(C)*
(E)*
(F)*
(B)*
(D)*
这些点形成三维轮廓,但它们是无序的。对于无序,我的意思是它们存储在
中unorderedList = [A - B - C - D - E - F]
我只想从任意位置开始重新组织此列表(比如说A点)并顺时针或逆时针遍历点。像这样:
orderedList = [A - E - B - D - F - C]
或
orderedList = [A - C - F - D - B - E]
我正在尝试尽可能简单地实现算法,因为提到的点集对应于~420000点的网格上的每个顶点的N环邻域,并且我必须为每个点执行此操作在网格上。
前段时间有关于2-D点数的similar discussion,但目前我不清楚如何从这种方法转向我的3D场景。
答案 0 :(得分:7)
没有轴和方向,“顺时针”或“逆时针”的概念没有明确定义! (证据:例如,如果你从显示器屏幕的另一侧观察这些点,或者将它们翻转,会怎样!)
您必须定义轴和方向,并将其指定为附加输入。指定方法包括:
1x=2y=3z
),使用右手规则(A_x, A_y, A_z)
,使用右手规则;这是这样做的首选方式为了确定方向,您必须更深入地研究您的问题:您必须定义网格的“向上”和“向下”大小。然后,对于每组点,您必须采用质心(或另一个“内部”点)并构造一个指向“向上”的单位向量,该向量与表面垂直。 (这样做的一种方法是找到最小二乘拟合平面,然后通过该点找到两个垂直向量,在“向上”方向上选择一个。)
您需要使用上述任何建议来确定您的轴。这将允许您按如下方式重新表述您的问题:
输入:
设定:
算法:
一旦你有角度,你可以对它们进行排序。
答案 1 :(得分:1)
我无法证明此代码的效率,但它可以工作,你可以根据需要优化它的一部分,我只是不擅长它。
代码在C#中,使用系统集合类和linq
Vector3是一个具有浮点数x,y,z和静态向量数学函数的类
Node是一个名为 pos
//Sort nodes with positions in 3d space.
//Assuming the points form a convex shape.
//Assuming points are on a single plain (or close to it).
public List<Node> sortVerticies( Vector3 normal, List<Node> nodes ) {
Vector3 first = nodes[0].pos;
//Sort by distance from random point to get 2 adjacent points.
List<Node> temp = nodes.OrderBy(n => Vector3.Distance(n.pos, first ) ).ToList();
//Create a vector from the 2 adjacent points,
//this will be used to sort all points, except the first, by the angle to this vector.
//Since the shape is convex, angle will not exceed 180 degrees, resulting in a proper sort.
Vector3 refrenceVec = (temp[1].pos - first);
//Sort by angle to reference, but we are still missing the first one.
List<Node> results = temp.Skip(1).OrderBy(n => Vector3.Angle(refrenceVec,n.pos - first)).ToList();
//insert the first one, at index 0.
results.Insert(0,nodes[0]);
//Now that it is sorted, we check if we got the direction right, if we didn't we reverse the list.
//We compare the given normal and the cross product of the first 3 point.
//If the magnitude of the sum of the normal and cross product is less than Sqrt(2) then then there is more than 90 between them.
if ( (Vector3.Cross( results[1].pos-results[0].pos, results[2].pos - results[0].pos ).normalized + normal.normalized).magnitude < 1.414f ) {
results.Reverse();
}
return results;
}