Browse Source

add some file

master
forty-twoo 1 year ago
parent
commit
7736c45202
  1. 13
      .gitignore
  2. 45
      include/DomainDiscretization.hpp
  3. 11
      include/DomainDiscretization_fwd.hpp
  4. 110
      include/FillBoundary.hpp
  5. 46
      include/FillInterior.hpp
  6. 24
      include/FillInterior_fwd.hpp
  7. 1
      include/OccHelper.hpp
  8. 14
      include/OccShape.hpp
  9. 128
      include/discretization_helpers.hpp
  10. 23
      src/main.cpp

13
.gitignore

@ -0,0 +1,13 @@
.DS_store
.idea
build
cmake-build-debug
cmake-build-release
input
output
result
tools
test

45
include/DomainDiscretization.hpp

@ -88,9 +88,48 @@ namespace meshless {
boundaryMap_.push_back(-1);
return positions_.size() - 1;
}
//bool DomainDiscretization::contains(const vec& point)const;
template<class vec>
template<typename search_struc>
void DomainDiscretization<vec>::makeDiscreteContainsStructure(search_struc& search) const {
int size = boundary().size();
std::vector<vec> boundary_points(size);
for(int i = 0; i < boundaryMap_.size(); i++) {
if(boundaryMap_[i] == -1)
continue;
boundary_points[boundaryMap_[i]] = positions_[i];
}
search.reset(boundary_points);
}
//bool DomainDiscretization::contains(const vec& point)const;
template<typename vec>
template<typename search_struc>
bool DomainDiscretization<vec>::discreteContains(const Eigen::Vector3d& point, search_struc& search, int num)const {
assert_msg((search.size() != 0), "Search structure should not be empty.");
auto closet = search.query(point, num);
auto closet_indexs = closet.first;
for(int i = 0; i < closet_indexs.size(); i++) {
auto idx = closet_indexs[i];
auto n = normals_[idx];
auto closet_point = search.get(idx);
if(n.dot(point - closet_point) >= 0) {
return false;
}
}
// for (auto idx : closet_indexs)
// {
// auto n = normals_[idx];
// auto closet_point = search.get(idx);
// if (n.dot(point - closet_point) >= 0)
// {
// return false;
// }
// }
return true;
// int closest_index = search.query(point, 1).first[0];
// auto closest_point = search.get(closest_index);
// auto n = normals_[closest_index];
// return n.dot(point - closest_point) < 0;
}
};

11
include/DomainDiscretization_fwd.hpp

@ -2,6 +2,7 @@
#include <vector>
#include <Eigen/Core>
#include "OccShape.hpp"
#include "KDTreeMutable.hpp"
namespace meshless {
@ -21,7 +22,8 @@ namespace meshless {
public:
DomainDiscretization() {}
DomainDiscretization(const OccShape& shape) {
shape_.max_points = shape.max_points;
shape_.max_points_boundary = shape.max_points_boundary;
shape_.max_points_interior = shape.max_points_interior;
shape_.seed_ = shape.seed_;
shape_.n_samples = shape.n_samples;
shape_.zeta = shape.zeta;
@ -184,6 +186,13 @@ namespace meshless {
int addBoundaryNodeWithT(const vec& point, double t, int type, const vec& normal);
int addInternalNodeWithT(const vec& point, double t, int type);
template<typename search_struc>
bool discreteContains(const Eigen::Vector3d& point, search_struc& search, int num = 1)const;
template<typename search_struc>
void makeDiscreteContainsStructure(search_struc& search) const;
private:
int addNode(const vec& point, int type);
int addNodeWithT(const vec& point, double t, int type);

110
include/FillBoundary.hpp

@ -1,4 +1,5 @@
#pragma once
#include "discretization_helpers.hpp"
#include "FillBoundary_fwd.hpp"
#include "KDTree.hpp"
#include "KDTreeMutable.hpp"
@ -28,6 +29,7 @@ namespace meshless {
std::cout << "该面法线需反向\n";
reverseNormal = true;
}
DomainDiscretization<Eigen::Vector2d> domainParamLocalPatch(shape);
//开始离散化每个wire
auto outerWire = BRepTools::OuterWire(face);
@ -39,10 +41,6 @@ namespace meshless {
if(wire == outerWire) {
std::cout << "此wire为外环\n";
}
DomainDiscretization<Eigen::Vector2d> domainParamLocalPatch(shape);
TopExp_Explorer expEdge(wire, TopAbs_EDGE);
int numEdge = 0;
int genPoints = 0;
@ -113,7 +111,7 @@ namespace meshless {
int curNode = domainParamLocalPatch.size() - 1;
int endNode = domainParamLocalPatch.size();
while(curNode < endNode && endNode < shape.max_points) {
while(curNode < endNode && endNode < shape.max_points_boundary) {
genPoints++;
//std::cout << "curNode / endNode : " << curNode << '/' << endNode << '\n';
auto param = domainParamLocalPatch.pos(curNode);
@ -123,31 +121,33 @@ namespace meshless {
gp_Pnt pt;
gp_Vec der;
geomCurve->D1(t, pt, der);
std::cout << "pt: " << pt.X() << "," << pt.Y() << "," << pt.Z() << '\n';
std::cout << "der: " << der.X() << "," << der.Y() << "," << der.Z() << '\n';
std::cout << "der.Mag:" << der.Magnitude() << '\n';
//std::cout << "pt: " << pt.X() << "," << pt.Y() << "," << pt.Z() << '\n';
//std::cout << "der: " << der.X() << "," << der.Y() << "," << der.Z() << '\n';
//std::cout << "der.Mag:" << der.Magnitude() << '\n';
double alpha = h(transPnt(pt)) / der.Magnitude();
for(const auto& uCan : candidates) {
//参数点必须在规定的参数域内
double tNew = t + alpha * uCan;
if(tNew > pCurveLastParam || tNew < pCurveFirstParam) {
std::cout << "排除\n";
//std::cout << "排除\n";
continue;
}
std::cout << "tNew:" << tNew << "\n";
//std::cout << "tNew:" << tNew << "\n";
gp_Pnt2d tNewSeedInPCurve;
geomPCurve->D0(tNew, tNewSeedInPCurve);
gp_Pnt ptNew;
geomCurve->D0(tNew, ptNew);
gp_Pnt ptNew2;
geomSurface->D0(tNewSeedInPCurve.X(), tNewSeedInPCurve.Y(), ptNew2);
std::cout << "ptNew: " << ptNew.X() << "," << ptNew.Y() << "," << ptNew.Z() << '\n';
std::cout << "ptNew2: " << ptNew2.X() << "," << ptNew2.Y() << "," << ptNew2.Z() << '\n';
//std::cout << "ptNew: " << ptNew.X() << "," << ptNew.Y() << "," << ptNew.Z() << '\n';
//std::cout << "ptNew2: " << ptNew2.X() << "," << ptNew2.Y() << "," << ptNew2.Z() << '\n';
double checkradius = pt.SquareDistance(ptNew);
std::cout << "CheckRadius: " << checkradius << '\n';
//std::cout << "CheckRadius: " << checkradius << '\n';
//距离已有的点不能太近
double d_sq_loc = treeLocal.query(transPnt(ptNew)).second[0];
std::cout << "d_sq_loc: " << d_sq_loc << '\n';
//std::cout << "d_sq_loc: " << d_sq_loc << '\n';
if(d_sq_loc >= (shape.zeta * shape.zeta * checkradius)) {
domainParamLocalPatch.addInternalNodeWithT(transPnt2d(tNewSeedInPCurve), tNew, 1);
treeLocal.insert(transPnt(ptNew));
@ -166,10 +166,10 @@ namespace meshless {
domainGlobal.addBoundaryNode(transPnt(ptNew), type, transVec(tSeedNormalNew));
treeGlobal.insert(transPnt(ptNew));
} else {
std::cout << "全局不添加点\n";
//std::cout << "全局不添加点\n";
}
} else {
std::cout << "局部不添加点\n";
//std::cout << "局部不添加点\n";
}
}
curNode++;
@ -177,17 +177,79 @@ namespace meshless {
std::cout << "该边已经生成:" << genPoints << "个点\n";
}
}
//fill boundary surface!
KDTree paramBoundarySearch;
int curNode = 0, endNode = domainParamLocalPatch.size();
while(curNode < endNode && endNode < shape.max_points_boundary) {
auto paramPoint = domainParamLocalPatch.pos(curNode);
gp_Pnt initPt;
gp_Vec derU, derV;
//geomSurface->D0(paramPoint.x(), paramPoint.y(), initPt);
geomSurface->D1(paramPoint.x(), paramPoint.y(), initPt, derU, derV);
Eigen::MatrixXd jacobMat;
jacobMat.resize(3, 2);
jacobMat(0, 0) = derU.X();
jacobMat(0, 1) = derV.X();
jacobMat(1, 0) = derU.Y();
jacobMat(1, 1) = derV.Y();
jacobMat(2, 0) = derU.Z();
jacobMat(2, 1) = derV.Z();
auto unitCandidates = SphereDiscretization<double, 2>::construct(1, shape.n_samples, gen);
for(auto& uCand : unitCandidates) {
double alpha = h(transPnt(initPt)) / (jacobMat * uCand).norm();
auto node = paramPoint + alpha * uCand;
gp_Pnt2d nodePnt(node.x(), node.y());
//该参数点必须在参数域内
BRepClass_FaceClassifier brepF;
brepF.Perform(face, nodePnt, 1e-6);
if(brepF.State() == TopAbs_State::TopAbs_IN) {
//std::cout << "TopAbs_IN\n";
}
if(brepF.State() == TopAbs_State::TopAbs_ON) {
//std::cout << "TopAbs_ON\n";
continue;
}
if(brepF.State() == TopAbs_State::TopAbs_OUT) {
//std::cout << "TopAbs_OUT\n";
continue;
}
if(brepF.State() == TopAbs_State::TopAbs_UNKNOWN) {
//std::cout << "TopAbs_UNKNOWN\n";
continue;
}
gp_Pnt newPt;
gp_Vec derU, derV;
geomSurface->D1(node.x(), node.y(), newPt, derU, derV);
double d_sq = treeGlobal.query(transPnt(newPt)).second[0];
double checkradius = newPt.SquareDistance(initPt);
if(d_sq < (shape.zeta * shape.zeta * checkradius)) {
continue;
}
domainParamLocalPatch.addInternalNode(node, 1);
treeGlobal.insert(transPnt(newPt));
gp_Dir normal;
auto retStatus = GeomLib::NormEstim(geomSurface, nodePnt, 1e-6, normal);
if(retStatus >= 2) {
std::cout << "calculate wrong!\n";
exit(-1);
}
if(reverseNormal) {
normal = -normal;
}
domainGlobal.addBoundaryNode(transPnt(newPt), type, transVec(normal));
endNode++;
}
curNode++;
}
if(endNode >= shape.max_points_boundary) {
std::cerr << "Maximum number of points reached, fill may be incomplete." << std::endl;
}
}
return domainGlobal;
}
};

46
include/FillInterior.hpp

@ -0,0 +1,46 @@
#pragma once
#include "assert.hpp"
#include "discretization_helpers.hpp"
#include "FillInterior_fwd.hpp"
namespace meshless {
template<typename contains_func>
void fillInteriorWithDensity(const OccShape& shape, DomainDiscretization<Eigen::Vector3d>& domain, const std::function<double(Eigen::Vector3d)>& h, KDTreeMutable& search, contains_func& containsFunc, int type) {
if(type == 0)
type = 1;
std::mt19937 gen(shape.seed_);
std::cout << "Filling the domain interior...\n";
int curNode = 0;
int endNode = domain.size();
search.insert(domain.positions());
while((curNode < endNode) && (endNode < shape.max_points_interior)) {
std::cout << "CurNode/EndNode: " << curNode << "/" << endNode << '\n';
auto p = domain.pos(curNode);
double r = h(p);
assert_msg(r > 0, "Nodal spacing radius should be > 0, got %g.", r);
auto candidates = SphereDiscretization<double, 3>::construct(r, shape.n_samples, gen);
for(const auto& f : candidates) {
auto node = p + f;
if(!containsFunc(node))continue;
if(search.existsPointInSphere(node, r * shape.zeta)) {
continue;
}
domain.addInternalNode(node, type);
search.insert(node);
endNode++;
}
curNode++;
}
if(endNode >= shape.max_points_interior) {
std::cerr << "Maximum number of points reached, fill may be incomplete." << std::endl;
}
std::cout << "Filling the domain interior done!\n";
}
};

24
include/FillInterior_fwd.hpp

@ -0,0 +1,24 @@
#pragma once
#include "OccHelper.hpp"
#include "OccShape.hpp"
#include "DomainDiscretization.hpp"
#include "KDTree.hpp"
#include "KDTreeMutable.hpp"
#include <vector>
#include <Eigen/Core>
namespace meshless {
template<typename contains_func>
void fillInteriorWithDensity(const OccShape& shape, DomainDiscretization<Eigen::Vector3d>& domain, const std::function<double(Eigen::Vector3d)>& h, KDTreeMutable& search, contains_func& containsFunc, int type);
template<typename contains_func>
void fillInteriorWithStep(const OccShape& shape, DomainDiscretization<Eigen::Vector3d>& domain, double step, KDTreeMutable& search, contains_func& containsFunc, int type) {
auto f = [=](Eigen::Vector3d) {return step; };
fillInteriorWithDensity(shape, domain, f, search, containsFunc, type);
}
};

1
include/OccHelper.hpp

@ -2,6 +2,7 @@
// OpenCascade includes
#include <Geom2d_TrimmedCurve.hxx>
#include <BRepClass_FaceExplorer.hxx>
#include <BRepClass_FaceClassifier.hxx>
#include <Interface_Static.hxx>
#include <STEPCAFControl_Writer.hxx>

14
include/OccShape.hpp

@ -5,7 +5,9 @@
namespace meshless {
class OccShape {
public:
int max_points = 500000;
int max_points_boundary = 500000;
int max_points_interior = 500000;
int seed_;
int n_samples = 15;
double zeta = 1 - 1e-10;
@ -14,15 +16,19 @@ namespace meshless {
public:
OccShape() {}
OccShape(const TopoDS_Shape& myShape_) {
max_points = 500000;
max_points_boundary = 500000;
seed_;
n_samples = 15;
zeta = 1 - 1e-10;
epsilon = 0;
myShape = myShape_;
}
OccShape& maxPoints(int max_points) {
this->max_points = max_points;
OccShape& maxPointsBoundary(int max_points_boundary) {
this->max_points_boundary = max_points_boundary;
return *this;
}
OccShape& maxPointsInterior(int max_points_interior) {
this->max_points_interior = max_points_interior;
return *this;
}

128
include/discretization_helpers.hpp

@ -0,0 +1,128 @@
#pragma once
#include <Eigen/Core>
#include <random>
namespace meshless {
template <typename T>
struct Pi {
static constexpr T value = T(3.14159265358979323846264338327950L); ///< Value of @f$\pi@f$.
};
static const double PI = Pi<double>::value; ///< Mathematical constant pi in double precision.
static const double INF = 1.0 / 0.0; ///< Infinite floating point value.
static const double NaN = 0.0 / 0.0; ///< Not-a-number floating point value.
template <typename scalar_t, int dim>
struct SphereDiscretization {
/**
* Construct a randomized discretization.
* @param radius Radius of the sphere.
* @param num_samples Number of points on the equator, implies nodal spacing `dp = 2*pi*r/n`.
* @param generator A random number generator.
* @return A vector of discretization points.
*/
template <typename generator_t>
static std::vector<Eigen::Matrix<scalar_t, dim, 1>,
Eigen::aligned_allocator<Eigen::Matrix<scalar_t, dim, 1>>> construct(
scalar_t radius, int num_samples, generator_t& generator) {
scalar_t dphi = 2 * Pi<scalar_t>::value / num_samples;
std::uniform_real_distribution<scalar_t> distribution(0, Pi<scalar_t>::value);
scalar_t offset = distribution(generator);
std::vector<Eigen::Matrix<scalar_t, dim, 1>,
Eigen::aligned_allocator<Eigen::Matrix<scalar_t, dim, 1>>> result;
for(int i = 0; i < num_samples / 2; ++i) {
scalar_t phi = i * dphi + offset;
if(phi > Pi<scalar_t>::value) phi -= Pi<scalar_t>::value;
int slice_n = static_cast<int>(std::ceil(num_samples * std::sin(phi)));
if(slice_n == 0) continue;
auto slice = SphereDiscretization<scalar_t, dim - 1>::construct(
radius * std::sin(phi), slice_n, generator);
Eigen::Matrix<scalar_t, dim, 1> v;
for(const auto& p : slice) {
v[0] = radius * std::cos(phi);
v.template tail<dim - 1>() = p;
result.push_back(v);
}
}
return result;
}
/// Construct the discretization.
static std::vector<Eigen::Matrix<scalar_t, dim, 1>,
Eigen::aligned_allocator<Eigen::Matrix<scalar_t, dim, 1>>> construct(
scalar_t radius, int num_samples) {
scalar_t dphi = 2 * Pi<scalar_t>::value / num_samples;
std::vector<Eigen::Matrix<scalar_t, dim, 1>,
Eigen::aligned_allocator<Eigen::Matrix<scalar_t, dim, 1>>> result;
for(int i = 0; i < num_samples / 2; ++i) {
scalar_t phi = i * dphi;
if(phi > Pi<scalar_t>::value) phi -= Pi<scalar_t>::value;
int slice_n = static_cast<int>(std::ceil(num_samples * std::sin(phi)));
if(slice_n == 0) continue;
auto slice = SphereDiscretization<scalar_t, dim - 1>::construct(
radius * std::sin(phi), slice_n);
Eigen::Matrix<scalar_t, dim, 1> v;
for(const auto& p : slice) {
v[0] = radius * std::cos(phi);
v.template tail<dim - 1>() = p;
result.push_back(v);
}
}
return result;
}
};
/// Two-dimensional base case of the discretization.
template <typename scalar_t>
struct SphereDiscretization<scalar_t, 2> {
/// Construct a randomized discretization.
template <typename generator_t>
static std::vector<Eigen::Matrix<scalar_t, 2, 1>,
Eigen::aligned_allocator<Eigen::Matrix<scalar_t, 2, 1>>> construct(
scalar_t radius, int num_samples, generator_t& generator) {
scalar_t dphi = 2 * Pi<scalar_t>::value / num_samples;
std::uniform_real_distribution<scalar_t> distribution(0, 2 * Pi<scalar_t>::value);
scalar_t offset = distribution(generator);
std::vector<Eigen::Matrix<scalar_t, 2, 1>,
Eigen::aligned_allocator<Eigen::Matrix<scalar_t, 2, 1>>> result;
for(int i = 0; i < num_samples; ++i) {
scalar_t phi = i * dphi + offset;
result.emplace_back(radius * std::cos(phi), radius * std::sin(phi));
}
return result;
}
/// Construct the discretization.
static std::vector<Eigen::Matrix<scalar_t, 2, 1>,
Eigen::aligned_allocator<Eigen::Matrix<scalar_t, 2, 1>>> construct(
scalar_t radius, int num_samples) {
scalar_t dphi = 2 * Pi<scalar_t>::value / num_samples;
std::vector<Eigen::Matrix<scalar_t, 2, 1>,
Eigen::aligned_allocator<Eigen::Matrix<scalar_t, 2, 1>>> result;
for(int i = 0; i < num_samples; ++i) {
scalar_t phi = i * dphi;
result.emplace_back(radius * std::cos(phi), radius * std::sin(phi));
}
return result;
}
};
/// One-dimensional base case of the discretization.
template <typename scalar_t>
struct SphereDiscretization<scalar_t, 1> {
template <typename generator_t>
/// Construct a randomized discretization.
static std::vector<Eigen::Matrix<scalar_t, 1, 1>,
Eigen::aligned_allocator<Eigen::Matrix<scalar_t, 1, 1>>> construct(
scalar_t radius, int, generator_t&) {
return { Eigen::Matrix<scalar_t, 1, 1>(-radius), Eigen::Matrix<scalar_t, 1, 1>(radius) };
}
/// Construct the discretization.
static std::vector<Eigen::Matrix<scalar_t, 1, 1>,
Eigen::aligned_allocator<Eigen::Matrix<scalar_t, 1, 1>>> construct(
scalar_t radius, int) {
return { Eigen::Matrix<scalar_t, 1, 1>(-radius), Eigen::Matrix<scalar_t, 1, 1>(radius) };
}
};
};

23
src/main.cpp

@ -1,7 +1,9 @@
#include <iostream>
#include <fstream>
#include <Eigen/Core>
#include "KDTree.hpp"
#include "FillBoundary.hpp"
#include "FillInterior.hpp"
#include "writeVTK.hpp"
using namespace std;
@ -12,11 +14,24 @@ int main() {
BRep_Builder brepBuilder;
TopoDS_Shape myShape;
//auto status = BRepTools::Read(myShape, "F:/CADMeshless/StepAndBrepModel/DWE_ADM102_ASSIGN.brep", brepBuilder);
auto status = BRepTools::Read(myShape, "F:/CADMeshless/StepAndBrepModel/Exhaust_Manifold.brep", brepBuilder);
auto status = BRepTools::Read(myShape, "F:/CADMeshless/StepAndBrepModel/DWE_ADM102_ASSIGN.brep", brepBuilder);
OccShape occShape(myShape);
auto domain = discretizeBoundaryWithStep(occShape, 1, -1);
Eigen::MatrixXd quaPoints;
double h1 = 1.0;
double h2 = 4.0;
DomainDiscretization<Eigen::Vector3d> domain = discretizeBoundaryWithStep(occShape, h1, -1);
DomainDiscretization<Eigen::Vector3d> domainOverSampled = discretizeBoundaryWithStep(occShape, 0.2, -1);
KDTree containsTree;
domainOverSampled.makeDiscreteContainsStructure(containsTree);
auto containsFunc = [&](const Eigen::Vector3d p) {
return domainOverSampled.discreteContains(p, containsTree, 15);
};
KDTreeMutable tree;
fillInteriorWithStep(myShape, domain, h2, tree, containsFunc, 1);
Eigen::MatrixXd quaPoints;
quaPoints.resize(domain.positions().size(), 3);
std::vector<double> attri;
for(int i = 0; i < domain.positions().size(); i++) {
@ -29,7 +44,7 @@ int main() {
quaPoints(i, 1) = domain.positions()[i].y();
quaPoints(i, 2) = domain.positions()[i].z();
}
writePntVTK<3>("Exhaust_Manifold.vtk", quaPoints, attri);
writePntVTK<3>("DWE_ADM102_ASSIGN.vtk", quaPoints, attri);

Loading…
Cancel
Save