Mesh: add function section() to Mesh class
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user