我的Winforms应用程序从3D摄像机获取具有XYZ坐标的CSV文件。使用这些坐标,我需要以立方分米(dm3)为单位计算对象的体积。
我不知所措,不是数学专家。我本来希望是已经做到这一点的库或算法,但是我发现的唯一东西是在C ++中,例如PCL库,或者它们使用Unity。对于像我这样不懂几何的人,有没有一种简单/干净的方法来获取带有XYZ坐标的对象的体积?
更新
这是到目前为止的代码片段:
public class Volume
{
//These are only part of the coordinates in the CSV file. There are more than 69.000 lines
Vector3[] vectors = new Vector3[8]
{
new Vector3 {X=-139,Y=-109,Z=285},
new Vector3 {X=-138,Y=-109,Z=286},
new Vector3 {X=-136,Y=-109,Z=286},
new Vector3 {X=-135,Y=-109,Z=286},
new Vector3 {X=-133,Y=-109,Z=286},
new Vector3 {X=-132,Y=-109,Z=286},
new Vector3 {X=-130,Y=-109,Z=286},
new Vector3 {X=-129,Y=-109,Z=286}
};
public double VolumeOfMesh()
{
Mesh _mesh = new Mesh();
double volume = 0.0;
_mesh.Vertices = vectors; //Should the vectors be organized by proximity to create the triangles?
_mesh.Triangles = null; //How do I calculate the triangles?
Vector3[] vertices = _mesh.Vertices;
int[] triangles = _mesh.Triangles;
for (int i = 0; i < _mesh.Triangles.Length; i += 3)
{
Vector3 p1 = vertices[triangles[i + 0]];
Vector3 p2 = vertices[triangles[i + 1]];
Vector3 p3 = vertices[triangles[i + 2]];
volume += SignedVolumeOfTriangle(p1, p2, p3);
}
return Math.Abs(volume);
}
private double SignedVolumeOfTriangle(Vector3 p1, Vector3 p2, Vector3 p3)
{
var v321 = p3.X * p2.Y * p1.Z;
var v231 = p2.X * p3.Y * p1.Z;
var v312 = p3.X * p1.Y * p2.Z;
var v132 = p1.X * p3.Y * p2.Z;
var v213 = p2.X * p1.Y * p3.Z;
var v123 = p1.X * p2.Y * p3.Z;
return (1.0 / 6.0) * (-v321 + v231 + v312 - v132 - v213 + v123);
}
}
向量数组应该按接近度排序吗?如何填充Triangles属性?
任何建议或指导都将受到欢迎。
答案 0 :(得分:2)
这就是我使用.STL文件将点排列成三角形面的方式。对于您的情况,您需要以某种方式描述结合哪些点(节点)以定义面,并确保这些面形成闭合的水密实体。
这个想法是形成面孔的每三个点 ABC 与原点一起形成一个体积实体
,其中·是矢量点积,×是矢量叉积。
事实证明,当您将所有体积相加时,一些将为正(背离原点),而某些将为负(面向原点)。最后,总和等于对象的封闭体积。
这里是colname_list = dataframe.columns.tolist()
#find 'int' columns
int_df = dataframe.select_dtypes(include='int64')
int_name_list = int_df.columns.tolist()
# change them into 'int32'
for i in range(len(int_name_list)):
dataframe[int_name_list[i]] =
dataframe[int_name_list[i]].astype('int32')
name_dict = {}
for i in range(dataframe.shape[0]):
node = Node(dataframe[colname_list[0]][0])
for j in range(dataframe.shape[1]):
name_dict[j] = str(dataframe.iloc[i, :][colname_list[j]])
attr = dataframe.iloc[i][colname_list[j]]
node[colname_list[j]] = attr
r = Relationship(node, "Belong to", node_table)
graph.create(node)
graph.create(r)
代码的示例,我正在使用该代码从网格获取实体对象属性。请记住,网格是由顶点中三个点的索引值定义的C#
点集合和称为Nodes
的三角形集合。
Faces
作为测试用例,我只使用了一个定义如下的三角形:
此外,通过将上述计算结果与商业CAD软件包产生的结果进行比较,我以更复杂的形状验证了结果。