Browse Source

intersection cpp h 分离

divide_struct_def_imp
郑敬润 1 year ago
parent
commit
a8705e3c76
  1. 5
      CMakeLists.txt
  2. 24
      include/Geometry.h
  3. 243
      include/Intersection.h
  4. 22
      include/Point.h
  5. 2
      lib/CMakeLists.txt
  6. 181
      src/Intersection.cpp
  7. 3
      src/xmlsql.cpp
  8. 8
      stdafx.cpp
  9. 26
      stdafx.h

5
CMakeLists.txt

@ -16,7 +16,7 @@ project(
#------------REQUIRED_4 C++------------# #------------REQUIRED_4 C++------------#
# !!!使!!!使set_target_properties/set_property # !!!使!!!使set_target_properties/set_property
# C++ 11(STRING) CMakeCache.txt # C++ 11(STRING) CMakeCache.txt
set(CMAKE_CXX_STANDARD 11 CACHE STRING "The C++ standard to use") set(CMAKE_CXX_STANDARD 17 CACHE STRING "The C++ standard to use")
# CMake 使 # CMake 使
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 使 -std=c++11 -std=g++11 # 使 -std=c++11 -std=g++11
@ -75,6 +75,9 @@ add_executable(
${SRC_DIR} ${SRC_DIR}
) )
# warning C4530: 使 C++ /EHsc
set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "/EHsc")
# add_custom_command( # add_custom_command(
# TARGET ${PROJECT_NAME} POST_BUILD # TARGET ${PROJECT_NAME} POST_BUILD
# COMMAND ${CMAKE_COMMAND} -E copy_directory # COMMAND ${CMAKE_COMMAND} -E copy_directory

24
include/Geometry.h

@ -1,18 +1,10 @@
#pragma once #pragma once
#ifdef MY_LIB_SHARED_BUILD #ifdef _WIN32
#ifdef _WIN32 #define GEOMETRY_API __declspec(dllexport)
#ifdef MY_LIB_EXPORTS
#define LIB_API __declspec(dllexport)
#else
#define LIB_API __declspec(dllimport)
#endif // MY_LIB_EXPORTS
#else
#define LIB_API
#endif // _WIN32
#else #else
#define LIB_API #define GEOMETRY_API
#endif // MY_LIB_SHARED_BUILD #endif
#include <numeric> #include <numeric>
#include <limits> #include <limits>
@ -105,21 +97,21 @@ public:
typedef Vec3<float> Vec3f; typedef Vec3<float> Vec3f;
typedef Vec3<unsigned int> Vec3u; typedef Vec3<unsigned int> Vec3u;
extern "C" class LIB_API Mesh extern "C" class GEOMETRY_API Mesh
{ {
public: public:
std::vector<Vec3f> vertices; std::vector<Vec3f> vertices;
std::vector<Vec3u> indices; std::vector<Vec3u> indices;
}; };
extern "C" class LIB_API AABB extern "C" class GEOMETRY_API AABB
{ {
public: public:
Vec3f min, max; Vec3f min, max;
AABB(); AABB();
}; };
extern "C" class LIB_API LineSegment extern "C" class GEOMETRY_API LineSegment
{ {
public: public:
Vec3f start; Vec3f start;
@ -136,7 +128,7 @@ public:
void calculate(); void calculate();
}; };
extern "C" struct LIB_API FaceCenterComparator extern "C" struct GEOMETRY_API FaceCenterComparator
{ {
const std::vector<Vec3f> &faceCenters; // 替换 YourVectorType 为你的向量类型 const std::vector<Vec3f> &faceCenters; // 替换 YourVectorType 为你的向量类型
int longAxis; int longAxis;

243
include/Intersection.h

@ -1,40 +1,30 @@
#pragma once #pragma once
#ifdef _WIN32
#define INTERSECTION_API __declspec(dllexport)
#else
#define INTERSECTION_API
#endif
#include "Geometry.h"
#include <numeric> #include <numeric>
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <cstddef> #include <cstddef>
#include "Geometry.h" #include <iostream> // std::cerr
#include <stdexcept> // std::length_error
struct TriangleSegmentIntersectRes extern "C" struct INTERSECTION_API TriangleSegmentIntersectRes
{ {
bool hit; bool hit;
float t; float t;
TriangleSegmentIntersectRes(bool h, float tt) : hit(h), t(tt) {} // VS2008 TriangleSegmentIntersectRes(bool h, float tt);
}; };
TriangleSegmentIntersectRes INTERSECTION_API
triangleSegmentIntersection(const LineSegment &segment, const Vec3f &a, const Vec3f &b, const Vec3f &c) TriangleSegmentIntersectRes triangleSegmentIntersection(const LineSegment &segment, const Vec3f &a, const Vec3f &b, const Vec3f &c);
{
Vec3f e1 = b - a;
Vec3f e2 = c - a;
Vec3f s = segment.start - a;
Vec3f s1 = segment.getDir().cross(e2);
Vec3f s2 = s.cross(e1);
float s1_dot_e1 = s1.dot(e1);
float b1 = s1.dot(s) / s1_dot_e1;
float b2 = s2.dot(segment.getDir()) / s1_dot_e1;
if (b1 >= 0. && b2 >= 0. && b1 + b2 <= 1.)
{
// hit
// return {true, s2.dot(e2) / s1_dot_e1};
return TriangleSegmentIntersectRes(true, s2.dot(e2) / s1_dot_e1); // VS2008
}
// return {false, 0.};
return TriangleSegmentIntersectRes(false, 0.f); // VS2008
}
class BVHNode extern "C" class INTERSECTION_API BVHNode
{ {
public: public:
size_t left; size_t left;
@ -42,210 +32,27 @@ public:
size_t parent; size_t parent;
AABB boundingBox; AABB boundingBox;
BVHNode(size_t l, size_t r, size_t p, const AABB &aabb) : left(l), right(r), parent(p), boundingBox(aabb) {} BVHNode(size_t l, size_t r, size_t p, const AABB &aabb);
BVHNode() : left(0), right(0), parent(0), boundingBox() {} BVHNode();
}; };
class BVH_intersection extern "C" class INTERSECTION_API BVH_intersection
{ {
public: public:
const Mesh &mesh; const Mesh &mesh;
std::vector<Vec3f> faceCenters; std::vector<Vec3f> faceCenters;
std::vector<BVHNode> nodes; std::vector<BVHNode> nodes;
BVH_intersection(const Mesh &mesh_) : mesh(mesh_) BVH_intersection(const Mesh &mesh_);
{
// ??????????????????
faceCenters.reserve(mesh.indices.size());
for (std::vector<Vec3u>::const_iterator it = mesh.indices.begin(); it != mesh.indices.end(); ++it)
{
const Vec3u &face = *it;
Vec3f center = (mesh.vertices[face[0]] + mesh.vertices[face[1]] + mesh.vertices[face[2]]) / 3.0f;
faceCenters.push_back(center);
} // VS2008
// indicesList ????0,1,2...?C++11iota??
// std::iota(indicesList.begin(), indicesList.end(), 0);
std::vector<size_t> indicesList(mesh.indices.size());
for (size_t i = 0; i < indicesList.size(); ++i)
{
indicesList[i] = i;
}
// ??BVH????
try
{
nodes.resize(2 * mesh.indices.size() - 1);
}
catch (const std::length_error &e)
{
std::cout << "vector.length:" << nodes.size() << " resize_pa:" << (2 * mesh.indices.size() - 1) << std::endl;
std::cerr << "Caught a length_error: " << e.what() << std::endl;
}
size_t nowIdx = 0; size_t
dfsBuild(indicesList, computeAABB(indicesList), nowIdx); dfsBuild(std::vector<size_t> &indicesList, AABB aabb, size_t &nowIdx);
} bool intersectWithLineSegment(const LineSegment &lineSegment) const;
// BVH???
size_t dfsBuild(std::vector<size_t> &indicesList, AABB aabb, size_t &nowIdx)
{
const size_t nodeIdx = nowIdx;
nowIdx++;
if (indicesList.size() == 1)
{
// leaf
nodes[nodeIdx] = BVHNode(0, indicesList[0], 0, aabb); // VS2008
return nodeIdx;
}
// longest axis
int longAxis = -1;
float longAxisLen = -1;
for (int i = 0; i < 3; ++i)
{
const float axisLen = aabb.max[i] - aabb.min[i];
if (axisLen > longAxisLen)
{
longAxisLen = axisLen;
longAxis = i;
}
}
// split indices list
const size_t k = indicesList.size() / 2;
// std::nth_element(indicesList.begin(), indicesList.begin() + k - 1, indicesList.end(),
// [&](const size_t &a, const size_t &b) {
// return faceCenters[a][longAxis] < faceCenters[b][longAxis];
// });
nth(indicesList, k - 1, longAxis);
std::vector<size_t> leftIndices(indicesList.begin(), indicesList.begin() + k);
std::vector<size_t> rightIndices(indicesList.begin() + k, indicesList.end());
const AABB leftAABB = computeAABB(leftIndices);
const AABB rightAABB = computeAABB(rightIndices);
const size_t leftIdx = dfsBuild(leftIndices, leftAABB, nowIdx);
const size_t rightIdx = dfsBuild(rightIndices, rightAABB, nowIdx);
// nodes[nodeIdx] = {leftIdx, rightIdx, 0, aabb};
nodes[nodeIdx] = BVHNode(leftIdx, rightIdx, 0, aabb); // VS2008
nodes[leftIdx].parent = nodeIdx;
nodes[rightIdx].parent = nodeIdx;
return nodeIdx;
}
bool intersectWithLineSegment(const LineSegment &lineSegment) const
{
return recursiveLineSegIntersection(lineSegment, 0);
}
// private:
// AABB computeAABB(const std::vector<size_t> &indices) {
// AABB aabb;
// for (const size_t &idx: indices) {
// const Vec3u &face = mesh.indices[idx];
// for (int i = 0; i < 3; ++i) {
// const Vec3f &vertex = mesh.vertices[face[i]];
// for (int j = 0; j < 3; ++j) {
// aabb.min[j] = std::min(aabb.min[j], vertex[j]);
// aabb.max[j] = std::max(aabb.max[j], vertex[j]);
// }
// }
// }
// return {aabb.min, aabb.max};
// }
private: private:
// ??????????????AABB??????????AABB AABB computeAABB(const std::vector<size_t> &indices);
AABB computeAABB(const std::vector<size_t> &indices) bool recursiveLineSegIntersection(const LineSegment &lineSegment, size_t nodeIdx) const;
{
AABB aabb;
for (std::vector<size_t>::const_iterator it = indices.begin(); it != indices.end(); ++it)
{
const Vec3u &face = mesh.indices[*it];
for (int i = 0; i < 3; ++i)
{
const Vec3f &vertex = mesh.vertices[face[i]];
for (int j = 0; j < 3; ++j)
{
aabb.min[j] = min(aabb.min[j], vertex[j]);
aabb.max[j] = max(aabb.max[j], vertex[j]);
}
}
}
return aabb;
}
bool recursiveLineSegIntersection(const LineSegment &lineSegment, size_t nodeIdx) const
{
// segment-box intersection test
const AABB &aabb = nodes[nodeIdx].boundingBox;
const Vec3f &dir = lineSegment.getDir();
bool hit = false;
for (int i = 0; !hit && i < 3; ++i)
{
float t_min = (aabb.min[i] - lineSegment.start[i]) / dir[i];
float t_max = (aabb.max[i] - lineSegment.start[i]) / dir[i];
if (t_min > t_max)
{
std::swap(t_min, t_max);
}
if (t_min > lineSegment.getLength() || t_max < 0)
return false;
Vec3f hitPt = lineSegment.start + dir * t_min;
int otherPlane1 = (i + 1) % 3, otherPlane2 = (i + 2) % 3;
if (hitPt[otherPlane1] >= aabb.min[otherPlane1] && hitPt[otherPlane1] <= aabb.max[otherPlane1] &&
hitPt[otherPlane2] >= aabb.min[otherPlane2] && hitPt[otherPlane2] <= aabb.max[otherPlane2])
{
hit = true;
}
}
if (hit)
{
if (nodes[nodeIdx].left == 0)
{
// leaf
Vec3u face = mesh.indices[nodes[nodeIdx].right];
TriangleSegmentIntersectRes res = triangleSegmentIntersection(lineSegment, mesh.vertices[face[0]], mesh.vertices[face[1]],
mesh.vertices[face[2]]);
if (!res.hit || res.t < 0 || res.t > lineSegment.getLength())
return false;
return true;
}
else
{
// check children
return recursiveLineSegIntersection(lineSegment, nodes[nodeIdx].left) ||
recursiveLineSegIntersection(lineSegment, nodes[nodeIdx].right);
}
}
return false;
}
// implement nth, without std::nth_element void nth(std::vector<size_t> &indicesList, size_t kth, int longAxis);
// kth is 0-based void recursiveChoose(std::vector<size_t> &indicesList, size_t begin, size_t end, size_t kth, int longAxis);
void nth(std::vector<size_t> &indicesList, size_t kth, int longAxis)
{
recursiveChoose(indicesList, 0, indicesList.size() - 1, kth, longAxis);
}
void recursiveChoose(std::vector<size_t> &indicesList, size_t begin, size_t end, size_t kth, int longAxis)
{
if (begin >= end)
return;
int i = begin, j = end;
while (i < j)
{
while (i < j && faceCenters[indicesList[j]][longAxis] >= faceCenters[indicesList[begin]][longAxis])
j--;
while (i < j && faceCenters[indicesList[i]][longAxis] <= faceCenters[indicesList[begin]][longAxis])
i++;
std::swap(indicesList[i], indicesList[j]);
}
std::swap(indicesList[begin], indicesList[i]);
if (i == kth)
return;
if (i < kth)
recursiveChoose(indicesList, i + 1, end, kth, longAxis);
else
recursiveChoose(indicesList, begin, i - 1, kth, longAxis);
}
}; };

22
include/Point.h

@ -1,18 +1,10 @@
#pragma once #pragma once
#ifdef MY_LIB_SHARED_BUILD #ifdef _WIN32
#ifdef _WIN32 #define POINT_API __declspec(dllexport)
#ifdef MY_LIB_EXPORTS
#define LIB_API __declspec(dllexport)
#else
#define LIB_API __declspec(dllimport)
#endif // MY_LIB_EXPORTS
#else
#define LIB_API
#endif // _WIN32
#else #else
#define LIB_API #define POINT_API
#endif // MY_LIB_SHARED_BUILD #endif
#include <string> #include <string>
@ -22,11 +14,11 @@
using namespace std; using namespace std;
extern "C" LIB_API const double eps = 1e-6; extern "C" POINT_API const double eps = 1e-6;
extern "C" LIB_API bool Equal(double a, double b); extern "C" POINT_API bool Equal(double a, double b);
extern "C" struct LIB_API P extern "C" struct POINT_API P
{ {
double x, y, z; // 坐标 double x, y, z; // 坐标
double dx, dy, dz; // 方向 double dx, dy, dz; // 方向

2
lib/CMakeLists.txt

@ -10,7 +10,7 @@ INSTALL(TARGETS WireRouting DESTINATION ${CMAKE_SOURCE_DIR}/lib)
SET_TARGET_PROPERTIES( SET_TARGET_PROPERTIES(
WireRouting PROPERTIES LINKER_LANGUAGE C WireRouting PROPERTIES LINKER_LANGUAGE C
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/build
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib
OUTPUT_NAME "WireRouting" OUTPUT_NAME "WireRouting"
PREFIX "" PREFIX ""

181
src/Intersection.cpp

@ -0,0 +1,181 @@
#include "Intersection.h"
using namespace std;
TriangleSegmentIntersectRes::TriangleSegmentIntersectRes(bool h, float tt) : hit(h), t(tt) {} // VS2008
TriangleSegmentIntersectRes
triangleSegmentIntersection(const LineSegment &segment, const Vec3f &a, const Vec3f &b, const Vec3f &c)
{
Vec3f e1 = b - a;
Vec3f e2 = c - a;
Vec3f s = segment.start - a;
Vec3f s1 = segment.getDir().cross(e2);
Vec3f s2 = s.cross(e1);
float s1_dot_e1 = s1.dot(e1);
float b1 = s1.dot(s) / s1_dot_e1;
float b2 = s2.dot(segment.getDir()) / s1_dot_e1;
if (b1 >= 0. && b2 >= 0. && b1 + b2 <= 1.)
{
return TriangleSegmentIntersectRes(true, s2.dot(e2) / s1_dot_e1);
}
return TriangleSegmentIntersectRes(false, 0.f);
}
BVHNode::BVHNode(size_t l, size_t r, size_t p, const AABB &aabb) : left(l), right(r), parent(p), boundingBox(aabb) {}
BVHNode::BVHNode() : left(0), right(0), parent(0), boundingBox() {}
BVH_intersection::BVH_intersection(const Mesh &mesh_) : mesh(mesh_)
{
faceCenters.reserve(mesh.indices.size());
for (vector<Vec3u>::const_iterator it = mesh.indices.begin(); it != mesh.indices.end(); ++it)
{
const Vec3u &face = *it;
Vec3f center = (mesh.vertices[face[0]] + mesh.vertices[face[1]] + mesh.vertices[face[2]]) / 3.0f;
faceCenters.push_back(center);
}
vector<size_t> indicesList(mesh.indices.size());
for (size_t i = 0; i < indicesList.size(); ++i)
{
indicesList[i] = i;
}
try
{
nodes.resize(2 * mesh.indices.size() - 1);
}
catch (const length_error &e)
{
cout << "vector.length:" << nodes.size() << " resize_pa:" << (2 * mesh.indices.size() - 1) << endl;
cerr << "Caught a length_error: " << e.what() << endl;
}
size_t nowIdx = 0;
dfsBuild(indicesList, computeAABB(indicesList), nowIdx);
}
size_t BVH_intersection::dfsBuild(vector<size_t> &indicesList, AABB aabb, size_t &nowIdx)
{
const size_t nodeIdx = nowIdx;
nowIdx++;
if (indicesList.size() == 1)
{
nodes[nodeIdx] = BVHNode(0, indicesList[0], 0, aabb); // VS2008
return nodeIdx;
}
int longAxis = -1;
float longAxisLen = -1;
for (int i = 0; i < 3; ++i)
{
const float axisLen = aabb.max[i] - aabb.min[i];
if (axisLen > longAxisLen)
{
longAxisLen = axisLen;
longAxis = i;
}
}
const size_t k = indicesList.size() / 2;
nth(indicesList, k - 1, longAxis);
vector<size_t> leftIndices(indicesList.begin(), indicesList.begin() + k);
vector<size_t> rightIndices(indicesList.begin() + k, indicesList.end());
const AABB leftAABB = computeAABB(leftIndices);
const AABB rightAABB = computeAABB(rightIndices);
const size_t leftIdx = dfsBuild(leftIndices, leftAABB, nowIdx);
const size_t rightIdx = dfsBuild(rightIndices, rightAABB, nowIdx);
nodes[nodeIdx] = BVHNode(leftIdx, rightIdx, 0, aabb); // VS2008
nodes[leftIdx].parent = nodeIdx;
nodes[rightIdx].parent = nodeIdx;
return nodeIdx;
}
bool BVH_intersection::intersectWithLineSegment(const LineSegment &lineSegment) const
{
return recursiveLineSegIntersection(lineSegment, 0);
}
AABB BVH_intersection::computeAABB(const vector<size_t> &indices)
{
AABB aabb;
for (vector<size_t>::const_iterator it = indices.begin(); it != indices.end(); ++it)
{
const Vec3u &face = mesh.indices[*it];
for (int i = 0; i < 3; ++i)
{
const Vec3f &vertex = mesh.vertices[face[i]];
for (int j = 0; j < 3; ++j)
{
aabb.min[j] = min(aabb.min[j], vertex[j]);
aabb.max[j] = max(aabb.max[j], vertex[j]);
}
}
}
return aabb;
}
bool BVH_intersection::recursiveLineSegIntersection(const LineSegment &lineSegment, size_t nodeIdx) const
{
const AABB &aabb = nodes[nodeIdx].boundingBox;
const Vec3f &dir = lineSegment.getDir();
bool hit = false;
for (int i = 0; !hit && i < 3; ++i)
{
float t_min = (aabb.min[i] - lineSegment.start[i]) / dir[i];
float t_max = (aabb.max[i] - lineSegment.start[i]) / dir[i];
if (t_min > t_max)
{
swap(t_min, t_max);
}
if (t_min > lineSegment.getLength() || t_max < 0)
return false;
Vec3f hitPt = lineSegment.start + dir * t_min;
int otherPlane1 = (i + 1) % 3, otherPlane2 = (i + 2) % 3;
if (hitPt[otherPlane1] >= aabb.min[otherPlane1] && hitPt[otherPlane1] <= aabb.max[otherPlane1] &&
hitPt[otherPlane2] >= aabb.min[otherPlane2] && hitPt[otherPlane2] <= aabb.max[otherPlane2])
{
hit = true;
}
}
if (hit)
{
if (nodes[nodeIdx].left == 0)
{
Vec3u face = mesh.indices[nodes[nodeIdx].right];
TriangleSegmentIntersectRes res = triangleSegmentIntersection(lineSegment, mesh.vertices[face[0]], mesh.vertices[face[1]],
mesh.vertices[face[2]]);
if (!res.hit || res.t < 0 || res.t > lineSegment.getLength())
return false;
return true;
}
else
{
return recursiveLineSegIntersection(lineSegment, nodes[nodeIdx].left) ||
recursiveLineSegIntersection(lineSegment, nodes[nodeIdx].right);
}
}
return false;
}
void BVH_intersection::nth(vector<size_t> &indicesList, size_t kth, int longAxis)
{
recursiveChoose(indicesList, 0, indicesList.size() - 1, kth, longAxis);
}
void BVH_intersection::recursiveChoose(vector<size_t> &indicesList, size_t begin, size_t end, size_t kth, int longAxis)
{
if (begin >= end)
return;
int i = begin, j = end;
while (i < j)
{
while (i < j && faceCenters[indicesList[j]][longAxis] >= faceCenters[indicesList[begin]][longAxis])
j--;
while (i < j && faceCenters[indicesList[i]][longAxis] <= faceCenters[indicesList[begin]][longAxis])
i++;
swap(indicesList[i], indicesList[j]);
}
swap(indicesList[begin], indicesList[i]);
if (i == kth)
return;
if (i < kth)
recursiveChoose(indicesList, i + 1, end, kth, longAxis);
else
recursiveChoose(indicesList, begin, i - 1, kth, longAxis);
}

3
src/xmlsql.cpp

@ -1,6 +1,3 @@
// xmlsql.cpp : 定义控制台应用程序的入口点。
//
#include <iostream> #include <iostream>
#include <tinyxml2.h> #include <tinyxml2.h>
#include "Astar.h" #include "Astar.h"

8
stdafx.cpp

@ -1,8 +0,0 @@
// stdafx.cpp : 只包括标准包含文件的源文件
// xmlsql.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息
#include "stdafx.h"
// TODO: 在 STDAFX.H 中
// 引用任何所需的附加头文件,而不是在此文件中引用

26
stdafx.h

@ -1,26 +0,0 @@
// stdafx.h : ��׼ϵͳ�����ļ��İ����ļ���
// ���Ǿ���ʹ�õ��������ĵ�
// �ض�����Ŀ�İ����ļ�
//
#pragma once
// #pragma comment(lib, "tinyxml.lib")
#define Word Microsoft::Office::Interop::Word
#include "targetver.h"
#include <stdio.h>
#ifdef _WIN32
#include <tchar.h>
#include <windows.h>
#include <atlstr.h>
#endif
#include <ctype.h>
#include <iostream>
#include <tinyxml2.h>
// #include <tinystr.h>
// TODO: �ڴ˴����ó�����Ҫ������ͷ�ļ�
Loading…
Cancel
Save