我在一个项目上工作。我们生成网格3D,我需要计算几个体积的3D对象。
我不知道如何计算,我想的数学知识太少了。有没有办法来控制这个
EDTI:我不是在寻找所有代码,而是寻找方向或伪代码
答案 0 :(得分:4)
我相信你会通过一个要求计算胸部音量的标题获得更多回应:)。
首先,为了计算网格的体积,它应该是一个封闭的网格。所以我认为您需要选择不需要的面/顶点并将其从网格中移除。 比找到关闭音量的方法:
完成此操作后,根据this paper即可轻松完成。
诀窍是计算四面体的有符号体积 - 基于您的三角形并在原点处加满。音量的符号来自您的三角形是否指向原点方向。 (三角形的法线本身取决于顶点的顺序,这就是为什么你没有看到它在下面明确引用的原因。)
这一切归结为以下简单功能:
float signedVolumeOfTriangle(pcl::PointXYZ p1, pcl::PointXYZ p2, pcl::PointXYZ p3)
{
float v321 = p3.x*p2.y*p1.z;
float v231 = p2.x*p3.y*p1.z;
float v312 = p3.x*p1.y*p2.z;
float v132 = p1.x*p3.y*p2.z;
float v213 = p2.x*p1.y*p3.z;
float v123 = p1.x*p2.y*p3.z;
return (1.0f/6.0f)*(-v321 + v231 + v312 - v132 - v213 + v123);
}
然后是一个计算网格体积的函数:
float volumeOfMesh(pcl::PolygonMesh mesh)
{
float vols = 0.0;
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromPointCloud2(mesh.cloud,*cloud);
for(int triangle=0;triangle<mesh.polygons.size();triangle++)
{
pcl::PointXYZ pt1 = cloud->points[mesh.polygons[triangle].vertices[0]];
pcl::PointXYZ pt2 = cloud->points[mesh.polygons[triangle].vertices[1]];
pcl::PointXYZ pt3 = cloud->points[mesh.polygons[triangle].vertices[2]];
vols += signedVolumeOfTriangle(pt1, pt2, pt3);
}
return Math.Abs(vols.Sum());
}
我没有测试代码,也不知道你是否可以使用PCL,但这应该可以让你开始。
答案 1 :(得分:0)
我已经用ubuntu-18.04的pcl-1.8.1完成了@Deepfreeze的代码。论文的 url 链接更新,click here. 请注意,代码应为“pcl::fromPCLPointCloud2”
main.cpp
#include <iostream>
#include <pcl/point_types.h>
#include <pcl/io/obj_io.h>
#include <pcl/io/vtk_lib_io.h>
#include <pcl/conversions.h>
#include <cmath>
float signedVolumeOfTriangle (pcl::PointXYZ p1, pcl::PointXYZ p2, pcl::PointXYZ p3)
{
float v321 = p3.x*p2.y*p1.z;
float v231 = p2.x*p3.y*p1.z;
float v312 = p3.x*p1.y*p2.z;
float v132 = p1.x*p3.y*p2.z;
float v213 = p2.x*p1.y*p3.z;
float v123 = p1.x*p2.y*p3.z;
return (1.0f/6.0f)*(-v321 + v231 + v312 - v132 - v213 + v123);
}
float volumeOfMesh(pcl::PolygonMesh mesh)
{
float vols = 0.0;
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromPCLPointCloud2(mesh.cloud, *cloud);
for(int triangle=0;triangle<mesh.polygons.size();triangle++)
{
pcl::PointXYZ pt1 = cloud->points[mesh.polygons[triangle].vertices[0]];
pcl::PointXYZ pt2 = cloud->points[mesh.polygons[triangle].vertices[1]];
pcl::PointXYZ pt3 = cloud->points[mesh.polygons[triangle].vertices[2]];
vols += signedVolumeOfTriangle(pt1, pt2, pt3);
}
return abs(vols);
}
int main(int argc, char **argv) {
pcl::PolygonMesh mesh;
pcl::io::loadOBJFile(argv[1], mesh);
std::cout << volumeOfMesh(mesh) << std::endl;
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(mesh_volume)
find_package(PCL 1.8 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (${PROJECT_NAME} main.cpp)
target_link_libraries (${PROJECT_NAME} ${PCL_LIBRARIES})