Mesh: add function section() to Mesh class

This commit is contained in:
wmayer
2021-09-16 17:31:45 +02:00
parent 666f67f8d9
commit 3ab5dadd82
6 changed files with 350 additions and 1 deletions

View File

@@ -618,3 +618,232 @@ bool SetOperations::CollectFacetVisitor::AllowVisit (const MeshFacet& rclFacet,
return true;
}
// ----------------------------------------------------------------------------
bool MeshIntersection::hasIntersection() const
{
Base::BoundBox3f bbox1 = kernel1.GetBoundBox();
Base::BoundBox3f bbox2 = kernel2.GetBoundBox();
if (!(bbox1 && bbox2))
return false;
if (testIntersection(kernel1, kernel2))
return true;
return false;
}
void MeshIntersection::getIntersection(std::list<MeshIntersection::Tuple>& intsct) const
{
const MeshKernel& k1 = kernel1;
const MeshKernel& k2 = kernel2;
// Contains bounding boxes for every facet of 'k1'
std::vector<Base::BoundBox3f> boxes1;
MeshFacetIterator cMFI1(k1);
for (cMFI1.Begin(); cMFI1.More(); cMFI1.Next()) {
boxes1.push_back((*cMFI1).GetBoundBox());
}
// Contains bounding boxes for every facet of 'k2'
std::vector<Base::BoundBox3f> boxes2;
MeshFacetIterator cMFI2(k2);
for (cMFI2.Begin(); cMFI2.More(); cMFI2.Next()) {
boxes2.push_back((*cMFI2).GetBoundBox());
}
// Splits the mesh using grid for speeding up the calculation
MeshFacetGrid cMeshFacetGrid(k1);
const MeshFacetArray& rFaces2 = k2.GetFacets();
Base::SequencerLauncher seq("Checking for intersections...", rFaces2.size());
int index = 0;
MeshGeomFacet facet1, facet2;
Base::Vector3f pt1, pt2;
// Iterate over the facets of the 2nd mesh and find the grid elements of the 1st mesh
for (MeshFacetArray::_TConstIterator it = rFaces2.begin(); it != rFaces2.end(); ++it, index++) {
seq.next();
std::vector<FacetIndex> elements;
cMeshFacetGrid.Inside(boxes2[index], elements, true);
cMFI2.Set(index);
facet2 = *cMFI2;
for (std::vector<FacetIndex>::iterator jt = elements.begin(); jt != elements.end(); ++jt) {
if (boxes2[index] && boxes1[*jt]) {
cMFI1.Set(*jt);
facet1 = *cMFI1;
int ret = facet1.IntersectWithFacet(facet2, pt1, pt2);
if (ret == 2) {
Tuple d;
d.p1 = pt1;
d.p2 = pt2;
d.f1 = *jt;
d.f2 = index;
intsct.push_back(d);
}
}
}
}
}
bool MeshIntersection::testIntersection(const MeshKernel& k1,
const MeshKernel& k2)
{
// Contains bounding boxes for every facet of 'k1'
std::vector<Base::BoundBox3f> boxes1;
MeshFacetIterator cMFI1(k1);
for (cMFI1.Begin(); cMFI1.More(); cMFI1.Next()) {
boxes1.push_back((*cMFI1).GetBoundBox());
}
// Contains bounding boxes for every facet of 'k2'
std::vector<Base::BoundBox3f> boxes2;
MeshFacetIterator cMFI2(k2);
for (cMFI2.Begin(); cMFI2.More(); cMFI2.Next()) {
boxes2.push_back((*cMFI2).GetBoundBox());
}
// Splits the mesh using grid for speeding up the calculation
MeshFacetGrid cMeshFacetGrid(k1);
const MeshFacetArray& rFaces2 = k2.GetFacets();
Base::SequencerLauncher seq("Checking for intersections...", rFaces2.size());
int index = 0;
MeshGeomFacet facet1, facet2;
Base::Vector3f pt1, pt2;
// Iterate over the facets of the 2nd mesh and find the grid elements of the 1st mesh
for (MeshFacetArray::_TConstIterator it = rFaces2.begin(); it != rFaces2.end(); ++it, index++) {
seq.next();
std::vector<FacetIndex> elements;
cMeshFacetGrid.Inside(boxes2[index], elements, true);
cMFI2.Set(index);
facet2 = *cMFI2;
for (std::vector<FacetIndex>::iterator jt = elements.begin(); jt != elements.end(); ++jt) {
if (boxes2[index] && boxes1[*jt]) {
cMFI1.Set(*jt);
facet1 = *cMFI1;
int ret = facet1.IntersectWithFacet(facet2, pt1, pt2);
if (ret == 2) {
// abort after the first detected self-intersection
return true;
}
}
}
}
return false;
}
void MeshIntersection::connectLines(bool onlyclosed, const std::list<MeshIntersection::Tuple>& rdata,
std::list< std::list<MeshIntersection::Triple> >& lines)
{
float fMinEps = minDistance * minDistance;
std::list<Tuple> data = rdata;
while (!data.empty()) {
std::list<Tuple>::iterator pF;
std::list<Triple> newPoly;
// add first line and delete from the list
Triple front, back;
front.f1 = data.begin()->f1;
front.f2 = data.begin()->f2;
front.p = data.begin()->p1; // current start point of the polyline
back.f1 = data.begin()->f1;
back.f2 = data.begin()->f2;
back.p = data.begin()->p2; // current end point of the polyline
newPoly.push_back(front);
newPoly.push_back(back);
data.erase(data.begin());
// search for the next line on the begin/end of the polyline and add it
std::list<Tuple>::iterator pFront, pEnd;
bool bFoundLine;
do {
float fFrontMin = fMinEps, fEndMin = fMinEps;
bool bFrontFirst=false, bEndFirst=false;
pFront = data.end();
pEnd = data.end();
bFoundLine = false;
for (pF = data.begin(); pF != data.end(); ++pF) {
if (Base::DistanceP2(front.p, pF->p1) < fFrontMin) {
fFrontMin = Base::DistanceP2(front.p, pF->p1);
pFront = pF;
bFrontFirst = true;
}
else if (Base::DistanceP2(back.p, pF->p1) < fEndMin) {
fEndMin = Base::DistanceP2(back.p, pF->p1);
pEnd = pF;
bEndFirst = true;
}
else if (Base::DistanceP2(front.p, pF->p2) < fFrontMin) {
fFrontMin = Base::DistanceP2(front.p, pF->p2);
pFront = pF;
bFrontFirst = false;
}
else if (Base::DistanceP2(back.p, pF->p2) < fEndMin) {
fEndMin = Base::DistanceP2(back.p, pF->p2);
pEnd = pF;
bEndFirst = false;
}
if (fFrontMin == 0.0f || fEndMin == 0.0f) {
break;
}
}
if (pFront != data.end()) {
bFoundLine = true;
if (bFrontFirst) {
front.f1 = pFront->f1;
front.f2 = pFront->f2;
front.p = pFront->p2;
newPoly.push_front(front);
}
else {
front.f1 = pFront->f1;
front.f2 = pFront->f2;
front.p = pFront->p1;
newPoly.push_front(front);
}
data.erase(pFront);
}
if (pEnd != data.end()) {
bFoundLine = true;
if (bEndFirst) {
back.f1 = pEnd->f1;
back.f2 = pEnd->f2;
back.p = pEnd->p2;
newPoly.push_back(back);
}
else {
back.f1 = pEnd->f1;
back.f2 = pEnd->f2;
back.p = pEnd->p1;
newPoly.push_back(back);
}
data.erase(pEnd);
}
}
while (bFoundLine);
if (onlyclosed) {
if (newPoly.size() > 2 && Base::DistanceP2(newPoly.front().p, newPoly.back().p) < fMinEps)
lines.push_back(newPoly);
}
else {
lines.push_back(newPoly);
}
}
}