| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| |
|
| | #include <algorithm>
|
| | #include <limits>
|
| |
|
| | #include <Base/Console.h>
|
| | #include <Base/Sequencer.h>
|
| |
|
| | #include "Algorithm.h"
|
| | #include "Approximation.h"
|
| | #include "Elements.h"
|
| | #include "Grid.h"
|
| | #include "Iterator.h"
|
| | #include "Triangulation.h"
|
| |
|
| |
|
| | using namespace MeshCore;
|
| | using Base::BoundBox2d;
|
| | using Base::BoundBox3f;
|
| | using Base::Polygon2d;
|
| |
|
| |
|
| | bool MeshAlgorithm::IsVertexVisible(
|
| | const Base::Vector3f& rcVertex,
|
| | const Base::Vector3f& rcView,
|
| | const MeshFacetGrid& rclGrid
|
| | ) const
|
| | {
|
| | const float fMaxDistance = 0.001F;
|
| | Base::Vector3f cDirection = rcVertex - rcView;
|
| | float fDistance = cDirection.Length();
|
| | Base::Vector3f cIntsct;
|
| | FacetIndex uInd {};
|
| |
|
| |
|
| | if (NearestFacetOnRay(rcView, cDirection, rclGrid, cIntsct, uInd)) {
|
| |
|
| | float fLen = Base::Distance(rcView, cIntsct);
|
| | if (fLen < fDistance) {
|
| |
|
| | if (Base::Distance(rcVertex, cIntsct) > fMaxDistance) {
|
| |
|
| | return false;
|
| | }
|
| | }
|
| | }
|
| |
|
| | return true;
|
| | }
|
| |
|
| | bool MeshAlgorithm::NearestFacetOnRay(
|
| | const Base::Vector3f& rclPt,
|
| | const Base::Vector3f& rclDir,
|
| | Base::Vector3f& rclRes,
|
| | FacetIndex& rulFacet
|
| | ) const
|
| | {
|
| | return NearestFacetOnRay(rclPt, rclDir, Mathf::PI, rclRes, rulFacet);
|
| | }
|
| |
|
| | bool MeshAlgorithm::NearestFacetOnRay(
|
| | const Base::Vector3f& rclPt,
|
| | const Base::Vector3f& rclDir,
|
| | float fMaxAngle,
|
| | Base::Vector3f& rclRes,
|
| | FacetIndex& rulFacet
|
| | ) const
|
| | {
|
| | Base::Vector3f clProj;
|
| | Base::Vector3f clRes;
|
| | bool bSol = false;
|
| | FacetIndex ulInd = 0;
|
| |
|
| |
|
| | MeshFacetIterator clFIter(_rclMesh);
|
| | for (clFIter.Init(); clFIter.More(); clFIter.Next()) {
|
| | if (clFIter->Foraminate(rclPt, rclDir, clRes, fMaxAngle)) {
|
| | if (!bSol) {
|
| |
|
| | bSol = true;
|
| | clProj = clRes;
|
| | ulInd = clFIter.Position();
|
| | }
|
| | else {
|
| |
|
| | if ((clRes - rclPt).Length() < (clProj - rclPt).Length()) {
|
| | clProj = clRes;
|
| | ulInd = clFIter.Position();
|
| | }
|
| | }
|
| | }
|
| | }
|
| |
|
| | if (bSol) {
|
| | rclRes = clProj;
|
| | rulFacet = ulInd;
|
| | }
|
| |
|
| | return bSol;
|
| | }
|
| |
|
| | bool MeshAlgorithm::NearestFacetOnRay(
|
| | const Base::Vector3f& rclPt,
|
| | const Base::Vector3f& rclDir,
|
| | const MeshFacetGrid& rclGrid,
|
| | Base::Vector3f& rclRes,
|
| | FacetIndex& rulFacet
|
| | ) const
|
| | {
|
| | std::vector<FacetIndex> aulFacets;
|
| | MeshGridIterator clGridIter(rclGrid);
|
| |
|
| | if (clGridIter.InitOnRay(rclPt, rclDir, aulFacets)) {
|
| | if (!RayNearestField(rclPt, rclDir, aulFacets, rclRes, rulFacet)) {
|
| | aulFacets.clear();
|
| | while (clGridIter.NextOnRay(aulFacets)) {
|
| | if (RayNearestField(rclPt, rclDir, aulFacets, rclRes, rulFacet)) {
|
| | return true;
|
| | }
|
| | }
|
| | }
|
| | else {
|
| | return true;
|
| | }
|
| | }
|
| |
|
| | return false;
|
| | }
|
| |
|
| | bool MeshAlgorithm::NearestFacetOnRay(
|
| | const Base::Vector3f& rclPt,
|
| | const Base::Vector3f& rclDir,
|
| | float fMaxSearchArea,
|
| | const MeshFacetGrid& rclGrid,
|
| | Base::Vector3f& rclRes,
|
| | FacetIndex& rulFacet
|
| | ) const
|
| | {
|
| | const float fMaxAngle = 1.75F;
|
| | std::vector<FacetIndex> aulFacets;
|
| | MeshGridIterator clGridIter(rclGrid);
|
| |
|
| | if (clGridIter.InitOnRay(rclPt, rclDir, fMaxSearchArea, aulFacets)) {
|
| | if (!RayNearestField(rclPt, rclDir, aulFacets, rclRes, rulFacet, fMaxAngle)) {
|
| | aulFacets.clear();
|
| | while (clGridIter.NextOnRay(aulFacets)) {
|
| | if (RayNearestField(rclPt, rclDir, aulFacets, rclRes, rulFacet, fMaxAngle)) {
|
| | return true;
|
| | }
|
| | }
|
| | }
|
| | else {
|
| | return true;
|
| | }
|
| | }
|
| |
|
| | return false;
|
| | }
|
| |
|
| | bool MeshAlgorithm::NearestFacetOnRay(
|
| | const Base::Vector3f& rclPt,
|
| | const Base::Vector3f& rclDir,
|
| | const std::vector<FacetIndex>& raulFacets,
|
| | Base::Vector3f& rclRes,
|
| | FacetIndex& rulFacet
|
| | ) const
|
| | {
|
| | Base::Vector3f clProj;
|
| | Base::Vector3f clRes;
|
| | bool bSol = false;
|
| | FacetIndex ulInd = 0;
|
| |
|
| | for (FacetIndex index : raulFacets) {
|
| | MeshGeomFacet rclSFacet = _rclMesh.GetFacet(index);
|
| | if (rclSFacet.Foraminate(rclPt, rclDir, clRes)) {
|
| | if (!bSol) {
|
| | bSol = true;
|
| | clProj = clRes;
|
| | ulInd = index;
|
| | }
|
| | else {
|
| | if ((clRes - rclPt).Length() < (clProj - rclPt).Length()) {
|
| | clProj = clRes;
|
| | ulInd = index;
|
| | }
|
| | }
|
| | }
|
| | }
|
| |
|
| | if (bSol) {
|
| | rclRes = clProj;
|
| | rulFacet = ulInd;
|
| | }
|
| |
|
| | return bSol;
|
| | }
|
| |
|
| | bool MeshAlgorithm::RayNearestField(
|
| | const Base::Vector3f& rclPt,
|
| | const Base::Vector3f& rclDir,
|
| | const std::vector<FacetIndex>& raulFacets,
|
| | Base::Vector3f& rclRes,
|
| | FacetIndex& rulFacet,
|
| | float
|
| | ) const
|
| | {
|
| | Base::Vector3f clProj, clRes;
|
| | bool bSol = false;
|
| | FacetIndex ulInd = 0;
|
| |
|
| | for (FacetIndex index : raulFacets) {
|
| | if (_rclMesh.GetFacet(index).Foraminate(rclPt, rclDir, clRes )) {
|
| | if (!bSol) {
|
| | bSol = true;
|
| | clProj = clRes;
|
| | ulInd = index;
|
| | }
|
| | else {
|
| | if ((clRes - rclPt).Length() < (clProj - rclPt).Length()) {
|
| | clProj = clRes;
|
| | ulInd = index;
|
| | }
|
| | }
|
| | }
|
| | }
|
| |
|
| | if (bSol) {
|
| | rclRes = clProj;
|
| | rulFacet = ulInd;
|
| | }
|
| |
|
| | return bSol;
|
| | }
|
| |
|
| | bool MeshAlgorithm::FirstFacetToVertex(
|
| | const Base::Vector3f& rPt,
|
| | float fMaxDistance,
|
| | const MeshFacetGrid& rGrid,
|
| | FacetIndex& uIndex
|
| | ) const
|
| | {
|
| | const float fEps = 0.001F;
|
| |
|
| | bool found = false;
|
| | std::vector<FacetIndex> facets;
|
| |
|
| |
|
| | rGrid.GetElements(rPt, facets);
|
| |
|
| |
|
| | for (FacetIndex facet : facets) {
|
| | MeshGeomFacet cFacet = this->_rclMesh.GetFacet(facet);
|
| | if (cFacet.IsPointOfFace(rPt, fMaxDistance)) {
|
| | found = true;
|
| | uIndex = facet;
|
| | break;
|
| | }
|
| |
|
| |
|
| | Base::Vector3f res;
|
| | float fDist {};
|
| | unsigned short uSide {};
|
| | cFacet.ProjectPointToPlane(rPt, res);
|
| | cFacet.NearestEdgeToPoint(res, fDist, uSide);
|
| | if (fDist < fEps) {
|
| | found = true;
|
| | uIndex = facet;
|
| | break;
|
| | }
|
| | }
|
| |
|
| | return found;
|
| | }
|
| |
|
| | float MeshAlgorithm::GetAverageEdgeLength() const
|
| | {
|
| | float fLen = 0.0F;
|
| | MeshFacetIterator cF(_rclMesh);
|
| | for (cF.Init(); cF.More(); cF.Next()) {
|
| | for (int i = 0; i < 3; i++) {
|
| | fLen += Base::Distance(cF->_aclPoints[i], cF->_aclPoints[(i + 1) % 3]);
|
| | }
|
| | }
|
| |
|
| | fLen = fLen / (3.0F * _rclMesh.CountFacets());
|
| | return fLen;
|
| | }
|
| |
|
| | float MeshAlgorithm::GetMinimumEdgeLength() const
|
| | {
|
| | float fLen = std::numeric_limits<float>::max();
|
| | MeshFacetIterator cF(_rclMesh);
|
| | for (cF.Init(); cF.More(); cF.Next()) {
|
| | for (int i = 0; i < 3; i++) {
|
| | fLen = std::min(fLen, Base::Distance(cF->_aclPoints[i], cF->_aclPoints[(i + 1) % 3]));
|
| | }
|
| | }
|
| |
|
| | return fLen;
|
| | }
|
| |
|
| | float MeshAlgorithm::GetMaximumEdgeLength() const
|
| | {
|
| | float fLen = 0.0F;
|
| | MeshFacetIterator cF(_rclMesh);
|
| | for (cF.Init(); cF.More(); cF.Next()) {
|
| | for (int i = 0; i < 3; i++) {
|
| | fLen = std::max(fLen, Base::Distance(cF->_aclPoints[i], cF->_aclPoints[(i + 1) % 3]));
|
| | }
|
| | }
|
| |
|
| | return fLen;
|
| | }
|
| |
|
| | Base::Vector3f MeshAlgorithm::GetGravityPoint() const
|
| | {
|
| | Base::Vector3f center;
|
| | MeshPointIterator cP(_rclMesh);
|
| | for (cP.Init(); cP.More(); cP.Next()) {
|
| | center += *cP;
|
| | }
|
| |
|
| | return center / static_cast<float>(_rclMesh.CountPoints());
|
| | }
|
| |
|
| | void MeshAlgorithm::GetMeshBorders(std::list<std::vector<Base::Vector3f>>& rclBorders) const
|
| | {
|
| | std::vector<FacetIndex> aulAllFacets(_rclMesh.CountFacets());
|
| | FacetIndex k = 0;
|
| | for (FacetIndex& index : aulAllFacets) {
|
| | index = k++;
|
| | }
|
| |
|
| | GetFacetBorders(aulAllFacets, rclBorders);
|
| | }
|
| |
|
| | void MeshAlgorithm::GetMeshBorders(std::list<std::vector<PointIndex>>& rclBorders) const
|
| | {
|
| | std::vector<FacetIndex> aulAllFacets(_rclMesh.CountFacets());
|
| | FacetIndex k = 0;
|
| | for (FacetIndex& index : aulAllFacets) {
|
| | index = k++;
|
| | }
|
| |
|
| | GetFacetBorders(aulAllFacets, rclBorders, true);
|
| | }
|
| |
|
| | void MeshAlgorithm::GetFacetBorders(
|
| | const std::vector<FacetIndex>& raulInd,
|
| | std::list<std::vector<Base::Vector3f>>& rclBorders
|
| | ) const
|
| | {
|
| | const MeshPointArray& rclPAry = _rclMesh._aclPointArray;
|
| | std::list<std::vector<PointIndex>> aulBorders;
|
| |
|
| | GetFacetBorders(raulInd, aulBorders, true);
|
| | for (const auto& border : aulBorders) {
|
| | std::vector<Base::Vector3f> boundary;
|
| | boundary.reserve(border.size());
|
| |
|
| | for (PointIndex jt : border) {
|
| | boundary.push_back(rclPAry[jt]);
|
| | }
|
| |
|
| | rclBorders.push_back(boundary);
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::GetFacetBorders(
|
| | const std::vector<FacetIndex>& raulInd,
|
| | std::list<std::vector<PointIndex>>& rclBorders,
|
| | bool ignoreOrientation
|
| | ) const
|
| | {
|
| | const MeshFacetArray& rclFAry = _rclMesh._aclFacetArray;
|
| |
|
| |
|
| | ResetFacetFlag(MeshFacet::VISIT);
|
| | for (FacetIndex it : raulInd) {
|
| | rclFAry[it].SetFlag(MeshFacet::VISIT);
|
| | }
|
| |
|
| |
|
| | std::list<std::pair<PointIndex, PointIndex>> aclEdges;
|
| | for (FacetIndex it : raulInd) {
|
| | const MeshFacet& rclFacet = rclFAry[it];
|
| | for (unsigned short i = 0; i < 3; i++) {
|
| | FacetIndex ulNB = rclFacet._aulNeighbours[i];
|
| | if (ulNB != FACET_INDEX_MAX) {
|
| | if (rclFAry[ulNB].IsFlag(MeshFacet::VISIT)) {
|
| | continue;
|
| | }
|
| | }
|
| |
|
| | aclEdges.push_back(rclFacet.GetEdge(i));
|
| | }
|
| | }
|
| |
|
| | if (aclEdges.empty()) {
|
| | return;
|
| | }
|
| |
|
| |
|
| | PointIndex ulFirst {}, ulLast {};
|
| | std::list<PointIndex> clBorder;
|
| | ulFirst = aclEdges.begin()->first;
|
| | ulLast = aclEdges.begin()->second;
|
| |
|
| | aclEdges.erase(aclEdges.begin());
|
| | clBorder.push_back(ulFirst);
|
| | clBorder.push_back(ulLast);
|
| |
|
| | while (!aclEdges.empty()) {
|
| |
|
| | std::list<std::pair<PointIndex, PointIndex>>::iterator pEI;
|
| | for (pEI = aclEdges.begin(); pEI != aclEdges.end(); ++pEI) {
|
| | if (pEI->first == ulLast) {
|
| | ulLast = pEI->second;
|
| | clBorder.push_back(ulLast);
|
| | aclEdges.erase(pEI);
|
| | pEI = aclEdges.begin();
|
| | break;
|
| | }
|
| | if (pEI->second == ulFirst) {
|
| | ulFirst = pEI->first;
|
| | clBorder.push_front(ulFirst);
|
| | aclEdges.erase(pEI);
|
| | pEI = aclEdges.begin();
|
| | break;
|
| | }
|
| |
|
| |
|
| |
|
| | if (pEI->second == ulLast && ignoreOrientation) {
|
| | ulLast = pEI->first;
|
| | clBorder.push_back(ulLast);
|
| | aclEdges.erase(pEI);
|
| | pEI = aclEdges.begin();
|
| | break;
|
| | }
|
| | if (pEI->first == ulFirst && ignoreOrientation) {
|
| | ulFirst = pEI->second;
|
| | clBorder.push_front(ulFirst);
|
| | aclEdges.erase(pEI);
|
| | pEI = aclEdges.begin();
|
| | break;
|
| | }
|
| | }
|
| |
|
| |
|
| |
|
| | if ((pEI == aclEdges.end()) || aclEdges.empty() || (ulLast == ulFirst)) {
|
| |
|
| | rclBorders.emplace_back(clBorder.begin(), clBorder.end());
|
| | clBorder.clear();
|
| |
|
| | if (!aclEdges.empty()) {
|
| |
|
| | ulFirst = aclEdges.begin()->first;
|
| | ulLast = aclEdges.begin()->second;
|
| | aclEdges.erase(aclEdges.begin());
|
| | clBorder.push_back(ulFirst);
|
| | clBorder.push_back(ulLast);
|
| | }
|
| | }
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::GetFacetBorder(FacetIndex uFacet, std::list<PointIndex>& rBorder) const
|
| | {
|
| | const MeshFacetArray& rFAry = _rclMesh._aclFacetArray;
|
| | std::list<std::pair<PointIndex, PointIndex>> openEdges;
|
| | if (uFacet >= rFAry.size()) {
|
| | return;
|
| | }
|
| |
|
| | auto face = rFAry.begin() + uFacet;
|
| | for (unsigned short i = 0; i < 3; i++) {
|
| | if (face->_aulNeighbours[i] == FACET_INDEX_MAX) {
|
| | openEdges.push_back(face->GetEdge(i));
|
| | }
|
| | }
|
| |
|
| | if (openEdges.empty()) {
|
| | return;
|
| | }
|
| |
|
| | for (auto it = rFAry.begin(); it != rFAry.end(); ++it) {
|
| | if (it == face) {
|
| | continue;
|
| | }
|
| | for (unsigned short i = 0; i < 3; i++) {
|
| | if (it->_aulNeighbours[i] == FACET_INDEX_MAX) {
|
| | openEdges.push_back(it->GetEdge(i));
|
| | }
|
| | }
|
| | }
|
| |
|
| | SplitBoundaryFromOpenEdges(openEdges, rBorder);
|
| | }
|
| |
|
| | void MeshAlgorithm::GetFacetsBorders(
|
| | const std::vector<FacetIndex>& uFacets,
|
| | std::list<std::vector<PointIndex>>& rBorders
|
| | ) const
|
| | {
|
| | ResetFacetFlag(MeshFacet::TMP0);
|
| | SetFacetsFlag(uFacets, MeshFacet::TMP0);
|
| | ResetPointFlag(MeshPoint::TMP0);
|
| |
|
| | const MeshFacetArray& rFAry = _rclMesh._aclFacetArray;
|
| | const MeshPointArray& rPAry = _rclMesh._aclPointArray;
|
| | std::list<std::pair<PointIndex, PointIndex>> openEdges;
|
| |
|
| |
|
| | for (auto it : uFacets) {
|
| | const MeshFacet& face = rFAry[it];
|
| | for (int i = 0; i < 3; i++) {
|
| | if (face._aulNeighbours[i] == FACET_INDEX_MAX) {
|
| | std::pair<PointIndex, PointIndex> openEdge = face.GetEdge(i);
|
| | openEdges.push_back(openEdge);
|
| |
|
| | rPAry[openEdge.first].SetFlag(MeshPoint::TMP0);
|
| | rPAry[openEdge.second].SetFlag(MeshPoint::TMP0);
|
| | }
|
| | }
|
| | }
|
| |
|
| | if (openEdges.empty()) {
|
| | return;
|
| | }
|
| |
|
| | for (const auto& it : rFAry) {
|
| | if (it.IsFlag(MeshFacet::TMP0)) {
|
| | continue;
|
| | }
|
| | for (int i = 0; i < 3; i++) {
|
| | if (it._aulNeighbours[i] == FACET_INDEX_MAX) {
|
| | openEdges.push_back(it.GetEdge(i));
|
| | }
|
| | }
|
| | }
|
| |
|
| |
|
| | while (!openEdges.empty()) {
|
| | PointIndex first = openEdges.begin()->first;
|
| | PointIndex second = openEdges.begin()->second;
|
| | if (!rPAry[first].IsFlag(MeshPoint::TMP0)) {
|
| | break;
|
| | }
|
| | if (!rPAry[second].IsFlag(MeshPoint::TMP0)) {
|
| | break;
|
| | }
|
| |
|
| | std::list<PointIndex> boundary;
|
| | SplitBoundaryFromOpenEdges(openEdges, boundary);
|
| | rBorders.emplace_back(boundary.begin(), boundary.end());
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::SplitBoundaryFromOpenEdges(
|
| | std::list<std::pair<PointIndex, PointIndex>>& openEdges,
|
| | std::list<PointIndex>& boundary
|
| | ) const
|
| | {
|
| |
|
| | if (openEdges.empty()) {
|
| | return;
|
| | }
|
| |
|
| | PointIndex ulFirst = openEdges.begin()->first;
|
| | PointIndex ulLast = openEdges.begin()->second;
|
| |
|
| | openEdges.erase(openEdges.begin());
|
| | boundary.push_back(ulFirst);
|
| | boundary.push_back(ulLast);
|
| |
|
| | while (ulLast != ulFirst) {
|
| |
|
| | std::list<std::pair<PointIndex, PointIndex>>::iterator pEI;
|
| | for (pEI = openEdges.begin(); pEI != openEdges.end(); ++pEI) {
|
| | if (pEI->first == ulLast) {
|
| | ulLast = pEI->second;
|
| | boundary.push_back(ulLast);
|
| | openEdges.erase(pEI);
|
| | pEI = openEdges.begin();
|
| | break;
|
| | }
|
| | if (pEI->second == ulFirst) {
|
| | ulFirst = pEI->first;
|
| | boundary.push_front(ulFirst);
|
| | openEdges.erase(pEI);
|
| | pEI = openEdges.begin();
|
| | break;
|
| | }
|
| | }
|
| |
|
| |
|
| | if (pEI == openEdges.end()) {
|
| | break;
|
| | }
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::SplitBoundaryLoops(std::list<std::vector<PointIndex>>& aBorders)
|
| | {
|
| |
|
| | std::map<PointIndex, int> openPointDegree;
|
| | for (const auto& jt : _rclMesh._aclFacetArray) {
|
| | for (int i = 0; i < 3; i++) {
|
| | if (jt._aulNeighbours[i] == FACET_INDEX_MAX) {
|
| | openPointDegree[jt._aulPoints[i]]++;
|
| | openPointDegree[jt._aulPoints[(i + 1) % 3]]++;
|
| | }
|
| | }
|
| | }
|
| |
|
| |
|
| | std::list<std::vector<PointIndex>> aSplitBorders;
|
| | for (const auto& aBorder : aBorders) {
|
| | bool split = false;
|
| | for (auto jt : aBorder) {
|
| |
|
| | if (openPointDegree[jt] > 2) {
|
| | split = true;
|
| | break;
|
| | }
|
| | }
|
| |
|
| | if (!split) {
|
| | aSplitBorders.push_back(aBorder);
|
| | }
|
| | else {
|
| | SplitBoundaryLoops(aBorder, aSplitBorders);
|
| | }
|
| | }
|
| |
|
| | aBorders = aSplitBorders;
|
| | }
|
| |
|
| | void MeshAlgorithm::SplitBoundaryLoops(
|
| | const std::vector<PointIndex>& rBound,
|
| | std::list<std::vector<PointIndex>>& aBorders
|
| | )
|
| | {
|
| | std::map<PointIndex, int> aPtDegree;
|
| | std::vector<PointIndex> cBound;
|
| | for (PointIndex it : rBound) {
|
| | int deg = (aPtDegree[it]++);
|
| | if (deg > 0) {
|
| | for (auto jt = cBound.begin(); jt != cBound.end(); ++jt) {
|
| | if (*jt == it) {
|
| | std::vector<PointIndex> cBoundLoop;
|
| | cBoundLoop.insert(cBoundLoop.end(), jt, cBound.end());
|
| | cBoundLoop.push_back(it);
|
| | cBound.erase(jt, cBound.end());
|
| | aBorders.push_back(cBoundLoop);
|
| | (aPtDegree[it]--);
|
| | break;
|
| | }
|
| | }
|
| | }
|
| |
|
| | cBound.push_back(it);
|
| | }
|
| | }
|
| |
|
| | bool MeshAlgorithm::FillupHole(
|
| | const std::vector<PointIndex>& boundary,
|
| | AbstractPolygonTriangulator& cTria,
|
| | MeshFacetArray& rFaces,
|
| | MeshPointArray& rPoints,
|
| | int level,
|
| | const MeshRefPointToFacets* pP2FStructure
|
| | ) const
|
| | {
|
| | if (boundary.front() == boundary.back()) {
|
| |
|
| | if (boundary.size() < 4) {
|
| | return false;
|
| | }
|
| | }
|
| | else if (boundary.size() < 3) {
|
| | return false;
|
| | }
|
| |
|
| |
|
| | MeshGeomFacet rTriangle;
|
| | MeshFacet rFace;
|
| | PointIndex refPoint0 = *(boundary.begin());
|
| | PointIndex refPoint1 = *(boundary.begin() + 1);
|
| | if (pP2FStructure) {
|
| | const std::set<FacetIndex>& ring1 = (*pP2FStructure)[refPoint0];
|
| | const std::set<FacetIndex>& ring2 = (*pP2FStructure)[refPoint1];
|
| | std::vector<FacetIndex> f_int;
|
| | std::set_intersection(
|
| | ring1.begin(),
|
| | ring1.end(),
|
| | ring2.begin(),
|
| | ring2.end(),
|
| | std::back_insert_iterator<std::vector<FacetIndex>>(f_int)
|
| | );
|
| | if (f_int.size() != 1) {
|
| | return false;
|
| | }
|
| |
|
| | rFace = _rclMesh._aclFacetArray[f_int.front()];
|
| | rTriangle = _rclMesh.GetFacet(rFace);
|
| | }
|
| | else {
|
| | bool ready = false;
|
| | for (auto it = _rclMesh._aclFacetArray.begin(); it != _rclMesh._aclFacetArray.end(); ++it) {
|
| | for (int i = 0; i < 3; i++) {
|
| | if (((it->_aulPoints[i] == refPoint0) && (it->_aulPoints[(i + 1) % 3] == refPoint1))
|
| | || ((it->_aulPoints[i] == refPoint1)
|
| | && (it->_aulPoints[(i + 1) % 3] == refPoint0))) {
|
| | rFace = *it;
|
| | rTriangle = _rclMesh.GetFacet(*it);
|
| | ready = true;
|
| | break;
|
| | }
|
| | }
|
| |
|
| | if (ready) {
|
| | break;
|
| | }
|
| | }
|
| | }
|
| |
|
| |
|
| | std::vector<Base::Vector3f> polygon;
|
| | for (PointIndex jt : boundary) {
|
| | polygon.push_back(_rclMesh._aclPointArray[jt]);
|
| | rPoints.push_back(_rclMesh._aclPointArray[jt]);
|
| | }
|
| |
|
| |
|
| | std::vector<PointIndex> bounds = boundary;
|
| | if (boundary.front() == boundary.back()) {
|
| | bounds.pop_back();
|
| | polygon.pop_back();
|
| | rPoints.pop_back();
|
| | }
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | cTria.SetPolygon(polygon);
|
| | cTria.SetIndices(bounds);
|
| |
|
| | std::vector<Base::Vector3f> surf_pts = cTria.GetPolygon();
|
| | if (pP2FStructure && level > 0) {
|
| | std::set<PointIndex> index = pP2FStructure->NeighbourPoints(boundary, level);
|
| | for (PointIndex it : index) {
|
| | Base::Vector3f pt(_rclMesh._aclPointArray[it]);
|
| | surf_pts.push_back(pt);
|
| | }
|
| | }
|
| |
|
| | if (cTria.TriangulatePolygon()) {
|
| |
|
| |
|
| | cTria.PostProcessing(surf_pts);
|
| |
|
| | rFaces.insert(rFaces.end(), cTria.GetFacets().begin(), cTria.GetFacets().end());
|
| | std::vector<Base::Vector3f> newVertices = cTria.AddedPoints();
|
| | for (const auto& vertex : newVertices) {
|
| | rPoints.push_back(vertex);
|
| | }
|
| |
|
| |
|
| |
|
| |
|
| | std::vector<MeshFacet> faces = cTria.GetFacets();
|
| |
|
| |
|
| |
|
| | if (faces.size() == 1) {
|
| | MeshFacet first = faces.front();
|
| | if (cTria.NeedsReindexing()) {
|
| | first._aulPoints[0] = boundary[first._aulPoints[0]];
|
| | first._aulPoints[1] = boundary[first._aulPoints[1]];
|
| | first._aulPoints[2] = boundary[first._aulPoints[2]];
|
| | }
|
| | if (first.IsEqual(rFace)) {
|
| | rFaces.clear();
|
| | rPoints.clear();
|
| | cTria.Discard();
|
| | return false;
|
| | }
|
| | }
|
| |
|
| | constexpr auto max = std::numeric_limits<unsigned short>::max();
|
| |
|
| | MeshFacet facet;
|
| | unsigned short ref_side = rFace.Side(refPoint0, refPoint1);
|
| | unsigned short tri_side = max;
|
| | if (cTria.NeedsReindexing()) {
|
| |
|
| | refPoint0 = 0;
|
| | refPoint1 = 1;
|
| | }
|
| | if (ref_side < max) {
|
| | for (const auto& face : faces) {
|
| | tri_side = face.Side(refPoint0, refPoint1);
|
| | if (tri_side < max) {
|
| | facet = face;
|
| | break;
|
| | }
|
| | }
|
| | }
|
| |
|
| |
|
| | if (ref_side == max || tri_side == max) {
|
| | Base::Console().log(
|
| | "MeshAlgorithm::FillupHole: Expected open edge for facet <%d, %d, %d>\n",
|
| | rFace._aulPoints[0],
|
| | rFace._aulPoints[1],
|
| | rFace._aulPoints[2]
|
| | );
|
| | rFaces.clear();
|
| | rPoints.clear();
|
| | cTria.Discard();
|
| | return false;
|
| | }
|
| |
|
| | #if 1
|
| | MeshGeomFacet triangle;
|
| | triangle = cTria.GetTriangle(rPoints, facet);
|
| |
|
| | TriangulationVerifier* verifier = cTria.GetVerifier();
|
| | if (!verifier) {
|
| | return true;
|
| | }
|
| |
|
| |
|
| |
|
| |
|
| | Base::Vector3f planeNormal = rTriangle.GetNormal()
|
| | % (rTriangle._aclPoints[(ref_side + 1) % 3] - rTriangle._aclPoints[ref_side]);
|
| | Base::Vector3f planeBase = rTriangle._aclPoints[ref_side % 3];
|
| | Base::Vector3f ref_point = rTriangle._aclPoints[(ref_side + 2) % 3];
|
| | Base::Vector3f tri_point = triangle._aclPoints[(tri_side + 2) % 3];
|
| |
|
| | if (!verifier->Accept(planeNormal, planeBase, ref_point, tri_point)) {
|
| | rFaces.clear();
|
| | rPoints.clear();
|
| | cTria.Discard();
|
| | return false;
|
| | }
|
| |
|
| |
|
| | if (verifier->MustFlip(triangle.GetNormal(), rTriangle.GetNormal())) {
|
| | for (auto& rFace : rFaces) {
|
| | rFace.FlipNormal();
|
| | }
|
| | }
|
| | #endif
|
| |
|
| | return true;
|
| | }
|
| |
|
| | return false;
|
| | }
|
| |
|
| | void MeshAlgorithm::SetFacetsProperty(
|
| | const std::vector<FacetIndex>& raulInds,
|
| | const std::vector<unsigned long>& raulProps
|
| | ) const
|
| | {
|
| | if (raulInds.size() != raulProps.size()) {
|
| | return;
|
| | }
|
| |
|
| | auto iP = raulProps.begin();
|
| | for (auto i = raulInds.begin(); i != raulInds.end(); ++i, ++iP) {
|
| | _rclMesh._aclFacetArray[*i].SetProperty(*iP);
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::SetFacetsFlag(const std::vector<FacetIndex>& raulInds, MeshFacet::TFlagType tF) const
|
| | {
|
| | for (FacetIndex it : raulInds) {
|
| | _rclMesh._aclFacetArray[it].SetFlag(tF);
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::SetPointsFlag(const std::vector<FacetIndex>& raulInds, MeshPoint::TFlagType tF) const
|
| | {
|
| | for (PointIndex it : raulInds) {
|
| | _rclMesh._aclPointArray[it].SetFlag(tF);
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::GetFacetsFlag(std::vector<FacetIndex>& raulInds, MeshFacet::TFlagType tF) const
|
| | {
|
| | raulInds.reserve(raulInds.size() + CountFacetFlag(tF));
|
| | MeshFacetArray::_TConstIterator beg = _rclMesh._aclFacetArray.begin();
|
| | MeshFacetArray::_TConstIterator end = _rclMesh._aclFacetArray.end();
|
| | for (auto it = beg; it != end; ++it) {
|
| | if (it->IsFlag(tF)) {
|
| | raulInds.push_back(it - beg);
|
| | }
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::GetPointsFlag(std::vector<PointIndex>& raulInds, MeshPoint::TFlagType tF) const
|
| | {
|
| | raulInds.reserve(raulInds.size() + CountPointFlag(tF));
|
| | MeshPointArray::_TConstIterator beg = _rclMesh._aclPointArray.begin();
|
| | MeshPointArray::_TConstIterator end = _rclMesh._aclPointArray.end();
|
| | for (auto it = beg; it != end; ++it) {
|
| | if (it->IsFlag(tF)) {
|
| | raulInds.push_back(it - beg);
|
| | }
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::ResetFacetsFlag(const std::vector<FacetIndex>& raulInds, MeshFacet::TFlagType tF) const
|
| | {
|
| | for (FacetIndex it : raulInds) {
|
| | _rclMesh._aclFacetArray[it].ResetFlag(tF);
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::ResetPointsFlag(const std::vector<FacetIndex>& raulInds, MeshPoint::TFlagType tF) const
|
| | {
|
| | for (PointIndex it : raulInds) {
|
| | _rclMesh._aclPointArray[it].ResetFlag(tF);
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::SetFacetFlag(MeshFacet::TFlagType tF) const
|
| | {
|
| | _rclMesh._aclFacetArray.SetFlag(tF);
|
| | }
|
| |
|
| | void MeshAlgorithm::SetPointFlag(MeshPoint::TFlagType tF) const
|
| | {
|
| | _rclMesh._aclPointArray.SetFlag(tF);
|
| | }
|
| |
|
| | void MeshAlgorithm::ResetFacetFlag(MeshFacet::TFlagType tF) const
|
| | {
|
| | _rclMesh._aclFacetArray.ResetFlag(tF);
|
| | }
|
| |
|
| | void MeshAlgorithm::ResetPointFlag(MeshPoint::TFlagType tF) const
|
| | {
|
| | _rclMesh._aclPointArray.ResetFlag(tF);
|
| | }
|
| |
|
| | unsigned long MeshAlgorithm::CountFacetFlag(MeshFacet::TFlagType tF) const
|
| | {
|
| | MeshIsFlag<MeshFacet> flag;
|
| | return std::count_if(
|
| | _rclMesh._aclFacetArray.begin(),
|
| | _rclMesh._aclFacetArray.end(),
|
| | [flag, tF](const MeshFacet& f) { return flag(f, tF); }
|
| | );
|
| | }
|
| |
|
| | unsigned long MeshAlgorithm::CountPointFlag(MeshPoint::TFlagType tF) const
|
| | {
|
| | MeshIsFlag<MeshPoint> flag;
|
| | return std::count_if(
|
| | _rclMesh._aclPointArray.begin(),
|
| | _rclMesh._aclPointArray.end(),
|
| | [flag, tF](const MeshPoint& f) { return flag(f, tF); }
|
| | );
|
| | }
|
| |
|
| | void MeshAlgorithm::GetFacetsFromToolMesh(
|
| | const MeshKernel& rToolMesh,
|
| | const Base::Vector3f& rcDir,
|
| | std::vector<FacetIndex>& raclCutted
|
| | ) const
|
| | {
|
| | MeshFacetIterator cFIt(_rclMesh);
|
| | MeshFacetIterator cTIt(rToolMesh);
|
| |
|
| | BoundBox3f cBB = rToolMesh.GetBoundBox();
|
| |
|
| | Base::SequencerLauncher seq("Check facets...", _rclMesh.CountFacets());
|
| |
|
| |
|
| | Base::Vector3f tmp;
|
| | for (cFIt.Init(); cFIt.More(); cFIt.Next()) {
|
| |
|
| | for (const auto& pnt : cFIt->_aclPoints) {
|
| |
|
| | if (cBB.IsInBox(pnt)) {
|
| |
|
| |
|
| | int ct = 0;
|
| | for (cTIt.Init(); cTIt.More(); cTIt.Next()) {
|
| | if (cTIt->IsPointOfFace(pnt, MeshPoint::epsilon())) {
|
| | ct = 1;
|
| | break;
|
| | }
|
| | if (cTIt->Foraminate(pnt, rcDir, tmp)) {
|
| |
|
| |
|
| | if ((tmp - pnt) * rcDir > 0) {
|
| | ct++;
|
| | }
|
| | }
|
| | }
|
| |
|
| |
|
| | if (ct % 2 == 1) {
|
| | raclCutted.push_back(cFIt.Position());
|
| | break;
|
| | }
|
| | }
|
| | }
|
| |
|
| | seq.next();
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::GetFacetsFromToolMesh(
|
| | const MeshKernel& rToolMesh,
|
| | const Base::Vector3f& rcDir,
|
| | const MeshFacetGrid& rGrid,
|
| | std::vector<FacetIndex>& raclCutted
|
| | ) const
|
| | {
|
| |
|
| | MeshGridIterator clGridIter(rGrid);
|
| | BoundBox3f cBB = rToolMesh.GetBoundBox();
|
| | Base::Vector3f tmp;
|
| |
|
| | MeshFacetIterator cFIt(_rclMesh);
|
| | MeshFacetIterator cTIt(rToolMesh);
|
| | MeshAlgorithm cToolAlg(rToolMesh);
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | std::vector<FacetIndex> aulInds;
|
| | for (clGridIter.Init(); clGridIter.More(); clGridIter.Next()) {
|
| | int ret = cToolAlg.Surround(clGridIter.GetBoundBox(), rcDir);
|
| |
|
| |
|
| | if (ret == 1) {
|
| |
|
| | clGridIter.GetElements(raclCutted);
|
| | }
|
| |
|
| | else if (ret == 0) {
|
| |
|
| | clGridIter.GetElements(aulInds);
|
| | }
|
| |
|
| |
|
| | else if (ret == -1) {
|
| |
|
| | clGridIter.GetElements(aulInds);
|
| | }
|
| | }
|
| |
|
| |
|
| | std::sort(aulInds.begin(), aulInds.end());
|
| | aulInds.erase(std::unique(aulInds.begin(), aulInds.end()), aulInds.end());
|
| | std::sort(raclCutted.begin(), raclCutted.end());
|
| | raclCutted.erase(std::unique(raclCutted.begin(), raclCutted.end()), raclCutted.end());
|
| |
|
| | Base::SequencerLauncher seq("Check facets...", aulInds.size());
|
| |
|
| |
|
| | for (FacetIndex it : aulInds) {
|
| | cFIt.Set(it);
|
| |
|
| |
|
| | for (auto point : cFIt->_aclPoints) {
|
| |
|
| | if (cBB.IsInBox(point)) {
|
| |
|
| |
|
| | int ct = 0;
|
| | for (cTIt.Init(); cTIt.More(); cTIt.Next()) {
|
| | if (cTIt->IsPointOfFace(point, MeshPoint::epsilon())) {
|
| | ct = 1;
|
| | break;
|
| | }
|
| | if (cTIt->Foraminate(point, rcDir, tmp)) {
|
| |
|
| |
|
| | if ((tmp - point) * rcDir > 0) {
|
| | ct++;
|
| | }
|
| | }
|
| | }
|
| |
|
| |
|
| | if (ct % 2 == 1) {
|
| | raclCutted.push_back(cFIt.Position());
|
| | break;
|
| | }
|
| | }
|
| | }
|
| |
|
| | seq.next();
|
| | }
|
| |
|
| |
|
| | std::sort(raclCutted.begin(), raclCutted.end());
|
| | raclCutted.erase(std::unique(raclCutted.begin(), raclCutted.end()), raclCutted.end());
|
| | }
|
| |
|
| | int MeshAlgorithm::Surround(const Base::BoundBox3f& rBox, const Base::Vector3f& rcDir)
|
| | {
|
| | Base::Vector3f pt1, pt2, tmp;
|
| | const BoundBox3f& cBB = _rclMesh.GetBoundBox();
|
| |
|
| |
|
| | if (cBB && rBox) {
|
| |
|
| | Base::Vector3f cCorner[8] = {
|
| | Base::Vector3f(rBox.MinX, rBox.MinY, rBox.MinZ),
|
| | Base::Vector3f(rBox.MaxX, rBox.MinY, rBox.MinZ),
|
| | Base::Vector3f(rBox.MaxX, rBox.MaxY, rBox.MinZ),
|
| | Base::Vector3f(rBox.MinX, rBox.MaxY, rBox.MinZ),
|
| | Base::Vector3f(rBox.MinX, rBox.MinY, rBox.MaxZ),
|
| | Base::Vector3f(rBox.MaxX, rBox.MinY, rBox.MaxZ),
|
| | Base::Vector3f(rBox.MaxX, rBox.MaxY, rBox.MaxZ),
|
| | Base::Vector3f(rBox.MinX, rBox.MaxY, rBox.MaxZ)
|
| | };
|
| |
|
| | MeshFacetIterator cTIt(_rclMesh);
|
| |
|
| |
|
| | int triangles[36] = {0, 1, 2, 0, 2, 3, 0, 1, 5, 0, 5, 4, 0, 4, 7, 0, 7, 3,
|
| | 6, 7, 4, 6, 4, 5, 6, 2, 3, 6, 3, 7, 6, 1, 2, 6, 5, 1};
|
| |
|
| | std::vector<MeshGeomFacet> cFacet(12);
|
| | int id = 0;
|
| | for (size_t ii = 0; ii < 12; ii++) {
|
| | cFacet[ii]._aclPoints[0] = cCorner[triangles[id++]];
|
| | cFacet[ii]._aclPoints[1] = cCorner[triangles[id++]];
|
| | cFacet[ii]._aclPoints[2] = cCorner[triangles[id++]];
|
| | }
|
| |
|
| |
|
| | for (const auto& it : cFacet) {
|
| | for (cTIt.Init(); cTIt.More(); cTIt.Next()) {
|
| | int ret = cTIt->IntersectWithFacet(it, pt1, pt2);
|
| |
|
| |
|
| | if (ret != 0) {
|
| | return 0;
|
| | }
|
| | }
|
| | }
|
| |
|
| |
|
| |
|
| |
|
| | int ct = 0;
|
| | for (cTIt.Init(); cTIt.More(); cTIt.Next()) {
|
| | if (cTIt->IsPointOfFace(cCorner[0], MeshPoint::epsilon())) {
|
| | ct = 1;
|
| | break;
|
| | }
|
| | if (cTIt->Foraminate(cCorner[0], rcDir, tmp)) {
|
| |
|
| | if ((tmp - cCorner[0]) * rcDir > 0) {
|
| | ct++;
|
| | }
|
| | }
|
| | }
|
| |
|
| |
|
| |
|
| | return (ct % 2 == 1) ? 1 : -1;
|
| | }
|
| |
|
| |
|
| | return -1;
|
| | }
|
| |
|
| | void MeshAlgorithm::CheckFacets(
|
| | const MeshFacetGrid& rclGrid,
|
| | const Base::ViewProjMethod* pclProj,
|
| | const Base::Polygon2d& rclPoly,
|
| | bool bInner,
|
| | std::vector<FacetIndex>& raulFacets
|
| | ) const
|
| | {
|
| | std::vector<FacetIndex>::iterator it;
|
| | MeshFacetIterator clIter(_rclMesh, 0);
|
| | Base::Vector3f clPt2d;
|
| | Base::Vector3f clGravityOfFacet;
|
| | bool bNoPointInside {};
|
| |
|
| | Base::ViewProjMatrix fixedProj(pclProj->getComposedProjectionMatrix());
|
| |
|
| | Base::BoundBox2d clPolyBBox = rclPoly.CalcBoundBox();
|
| |
|
| |
|
| | if (bInner) {
|
| | BoundBox3f clBBox3d;
|
| | BoundBox2d clViewBBox;
|
| | std::vector<FacetIndex> aulAllElements;
|
| |
|
| | MeshGridIterator clGridIter(rclGrid);
|
| | for (clGridIter.Init(); clGridIter.More(); clGridIter.Next()) {
|
| | clBBox3d = clGridIter.GetBoundBox();
|
| | clViewBBox = clBBox3d.ProjectBox(&fixedProj);
|
| | if (clViewBBox.Intersect(clPolyBBox)) {
|
| |
|
| | clGridIter.GetElements(aulAllElements);
|
| | }
|
| | }
|
| |
|
| |
|
| | std::sort(aulAllElements.begin(), aulAllElements.end());
|
| | aulAllElements.erase(
|
| | std::unique(aulAllElements.begin(), aulAllElements.end()),
|
| | aulAllElements.end()
|
| | );
|
| |
|
| | Base::SequencerLauncher seq("Check facets", aulAllElements.size());
|
| |
|
| | for (it = aulAllElements.begin(); it != aulAllElements.end(); ++it) {
|
| | bNoPointInside = true;
|
| | clGravityOfFacet.Set(0.0F, 0.0F, 0.0F);
|
| | MeshGeomFacet rclFacet = _rclMesh.GetFacet(*it);
|
| | for (const auto& pnt : rclFacet._aclPoints) {
|
| | clPt2d = fixedProj(pnt);
|
| | clGravityOfFacet += clPt2d;
|
| | if (clPolyBBox.Contains(Base::Vector2d(clPt2d.x, clPt2d.y))
|
| | && rclPoly.Contains(Base::Vector2d(clPt2d.x, clPt2d.y))) {
|
| | raulFacets.push_back(*it);
|
| | bNoPointInside = false;
|
| | break;
|
| | }
|
| | }
|
| |
|
| |
|
| | if (bNoPointInside) {
|
| | clGravityOfFacet *= 1.0F / 3.0F;
|
| |
|
| | if (clPolyBBox.Contains(Base::Vector2d(clGravityOfFacet.x, clGravityOfFacet.y))
|
| | && rclPoly.Contains(Base::Vector2d(clGravityOfFacet.x, clGravityOfFacet.y))) {
|
| | raulFacets.push_back(*it);
|
| | }
|
| | }
|
| |
|
| | seq.next();
|
| | }
|
| | }
|
| |
|
| | else {
|
| | Base::SequencerLauncher seq("Check facets", _rclMesh.CountFacets());
|
| | for (clIter.Init(); clIter.More(); clIter.Next()) {
|
| | for (const auto& pnt : clIter->_aclPoints) {
|
| | clPt2d = fixedProj(pnt);
|
| | if ((clPolyBBox.Contains(Base::Vector2d(clPt2d.x, clPt2d.y))
|
| | && !rclPoly.Contains(Base::Vector2d(clPt2d.x, clPt2d.y)))) {
|
| | raulFacets.push_back(clIter.Position());
|
| | break;
|
| | }
|
| | }
|
| | seq.next();
|
| | }
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::CheckFacets(
|
| | const Base::ViewProjMethod* pclProj,
|
| | const Base::Polygon2d& rclPoly,
|
| | bool bInner,
|
| | std::vector<FacetIndex>& raulFacets
|
| | ) const
|
| | {
|
| | const MeshPointArray& p = _rclMesh.GetPoints();
|
| | const MeshFacetArray& f = _rclMesh.GetFacets();
|
| | Base::Vector3f pt2d;
|
| |
|
| | Base::BoundBox2d bb = rclPoly.CalcBoundBox();
|
| |
|
| | Base::ViewProjMatrix fixedProj(pclProj->getComposedProjectionMatrix());
|
| |
|
| | FacetIndex index = 0;
|
| | for (auto it = f.begin(); it != f.end(); ++it, ++index) {
|
| | for (PointIndex ptIndex : it->_aulPoints) {
|
| | pt2d = fixedProj(p[ptIndex]);
|
| |
|
| |
|
| | if ((bb.Contains(Base::Vector2d(pt2d.x, pt2d.y))
|
| | && rclPoly.Contains(Base::Vector2d(pt2d.x, pt2d.y)))
|
| | ^ !bInner) {
|
| | raulFacets.push_back(index);
|
| | break;
|
| | }
|
| | }
|
| | }
|
| | }
|
| |
|
| | float MeshAlgorithm::Surface() const
|
| | {
|
| | float fTotal = 0.0F;
|
| | MeshFacetIterator clFIter(_rclMesh);
|
| |
|
| | for (clFIter.Init(); clFIter.More(); clFIter.Next()) {
|
| | fTotal += clFIter->Area();
|
| | }
|
| |
|
| | return fTotal;
|
| | }
|
| |
|
| | void MeshAlgorithm::SubSampleByDist(float fDist, std::vector<Base::Vector3f>& rclPoints) const
|
| | {
|
| | rclPoints.clear();
|
| | MeshFacetIterator clFIter(_rclMesh);
|
| | for (clFIter.Init(); clFIter.More(); clFIter.Next()) {
|
| | size_t k = rclPoints.size();
|
| | clFIter->SubSample(fDist, rclPoints);
|
| | if (rclPoints.size() == k) {
|
| | rclPoints.push_back(clFIter->GetGravityPoint());
|
| | }
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::SubSampleAllPoints(std::vector<Base::Vector3f>& rclPoints) const
|
| | {
|
| | rclPoints.clear();
|
| |
|
| |
|
| |
|
| | MeshPointIterator clPIter(_rclMesh);
|
| | for (clPIter.Init(); clPIter.More(); clPIter.Next()) {
|
| | rclPoints.push_back(*clPIter);
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::SubSampleByCount(unsigned long ulCtPoints, std::vector<Base::Vector3f>& rclPoints) const
|
| | {
|
| | float fDist = float(std::sqrt(Surface() / float(ulCtPoints)));
|
| | SubSampleByDist(fDist, rclPoints);
|
| | }
|
| |
|
| | void MeshAlgorithm::SearchFacetsFromPolyline(
|
| | const std::vector<Base::Vector3f>& rclPolyline,
|
| | float fRadius,
|
| | const MeshFacetGrid& rclGrid,
|
| | std::vector<FacetIndex>& rclResultFacetsIndices
|
| | ) const
|
| | {
|
| | rclResultFacetsIndices.clear();
|
| | if (rclPolyline.size() < 3) {
|
| | return;
|
| | }
|
| |
|
| | std::set<FacetIndex> aclFacets;
|
| | for (auto pV = rclPolyline.begin(); pV < (rclPolyline.end() - 1); ++pV) {
|
| | const Base::Vector3f &rclP0 = *pV, &rclP1 = *(pV + 1);
|
| |
|
| |
|
| | BoundBox3f clSegmBB(rclP0.x, rclP0.y, rclP0.z, rclP0.x, rclP0.y, rclP0.z);
|
| | clSegmBB.Add(rclP1);
|
| | clSegmBB.Enlarge(fRadius);
|
| |
|
| | std::vector<FacetIndex> aclBBFacets;
|
| | unsigned long k = rclGrid.Inside(clSegmBB, aclBBFacets, false);
|
| | for (unsigned long i = 0; i < k; i++) {
|
| | if (_rclMesh.GetFacet(aclBBFacets[i]).DistanceToLineSegment(rclP0, rclP1) < fRadius) {
|
| | aclFacets.insert(aclBBFacets[i]);
|
| | }
|
| | }
|
| | }
|
| |
|
| | rclResultFacetsIndices.insert(rclResultFacetsIndices.begin(), aclFacets.begin(), aclFacets.end());
|
| | }
|
| |
|
| | void MeshAlgorithm::CutBorderFacets(std::vector<FacetIndex>& raclFacetIndices, unsigned short usLevel) const
|
| | {
|
| | std::vector<FacetIndex> aclToDelete;
|
| |
|
| | CheckBorderFacets(raclFacetIndices, aclToDelete, usLevel);
|
| |
|
| |
|
| | std::vector<FacetIndex> aclResult;
|
| | std::set<FacetIndex> aclTmp(aclToDelete.begin(), aclToDelete.end());
|
| |
|
| | for (FacetIndex facetIndex : raclFacetIndices) {
|
| | if (aclTmp.find(facetIndex) == aclTmp.end()) {
|
| | aclResult.push_back(facetIndex);
|
| | }
|
| | }
|
| |
|
| | raclFacetIndices = aclResult;
|
| | }
|
| |
|
| | unsigned long MeshAlgorithm::CountBorderEdges() const
|
| | {
|
| | unsigned long cnt = 0;
|
| | const MeshFacetArray& rclFAry = _rclMesh._aclFacetArray;
|
| | auto end = rclFAry.end();
|
| | for (auto it = rclFAry.begin(); it != end; ++it) {
|
| | for (FacetIndex facetIndex : it->_aulNeighbours) {
|
| | if (facetIndex == FACET_INDEX_MAX) {
|
| | cnt++;
|
| | }
|
| | }
|
| | }
|
| |
|
| | return cnt;
|
| | }
|
| |
|
| | void MeshAlgorithm::CheckBorderFacets(
|
| | const std::vector<FacetIndex>& raclFacetIndices,
|
| | std::vector<FacetIndex>& raclResultIndices,
|
| | unsigned short usLevel
|
| | ) const
|
| | {
|
| | ResetFacetFlag(MeshFacet::TMP0);
|
| | SetFacetsFlag(raclFacetIndices, MeshFacet::TMP0);
|
| |
|
| | const MeshFacetArray& rclFAry = _rclMesh._aclFacetArray;
|
| |
|
| | for (unsigned short usL = 0; usL < usLevel; usL++) {
|
| | for (FacetIndex facetIndex : raclFacetIndices) {
|
| | for (FacetIndex ulNB : rclFAry[facetIndex]._aulNeighbours) {
|
| | if (ulNB == FACET_INDEX_MAX) {
|
| | raclResultIndices.push_back(facetIndex);
|
| | rclFAry[facetIndex].ResetFlag(MeshFacet::TMP0);
|
| | continue;
|
| | }
|
| | if (!rclFAry[ulNB].IsFlag(MeshFacet::TMP0)) {
|
| | raclResultIndices.push_back(facetIndex);
|
| | rclFAry[facetIndex].ResetFlag(MeshFacet::TMP0);
|
| | continue;
|
| | }
|
| | }
|
| | }
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::GetBorderPoints(
|
| | const std::vector<FacetIndex>& raclFacetIndices,
|
| | std::set<PointIndex>& raclResultPointsIndices
|
| | ) const
|
| | {
|
| | ResetFacetFlag(MeshFacet::TMP0);
|
| | SetFacetsFlag(raclFacetIndices, MeshFacet::TMP0);
|
| |
|
| | const MeshFacetArray& rclFAry = _rclMesh._aclFacetArray;
|
| |
|
| | for (FacetIndex facetIndex : raclFacetIndices) {
|
| | for (int i = 0; i < 3; i++) {
|
| | const MeshFacet& rclFacet = rclFAry[facetIndex];
|
| | FacetIndex ulNB = rclFacet._aulNeighbours[i];
|
| | if (ulNB == FACET_INDEX_MAX) {
|
| | raclResultPointsIndices.insert(rclFacet._aulPoints[i]);
|
| | raclResultPointsIndices.insert(rclFacet._aulPoints[(i + 1) % 3]);
|
| | continue;
|
| | }
|
| | if (!rclFAry[ulNB].IsFlag(MeshFacet::TMP0)) {
|
| | raclResultPointsIndices.insert(rclFacet._aulPoints[i]);
|
| | raclResultPointsIndices.insert(rclFacet._aulPoints[(i + 1) % 3]);
|
| | continue;
|
| | }
|
| | }
|
| | }
|
| | }
|
| |
|
| | bool MeshAlgorithm::NearestPointFromPoint(
|
| | const Base::Vector3f& rclPt,
|
| | FacetIndex& rclResFacetIndex,
|
| | Base::Vector3f& rclResPoint
|
| | ) const
|
| | {
|
| | if (_rclMesh.CountFacets() == 0) {
|
| | return false;
|
| | }
|
| |
|
| |
|
| | float fMinDist = std::numeric_limits<float>::max();
|
| | FacetIndex ulInd = FACET_INDEX_MAX;
|
| | MeshFacetIterator pF(_rclMesh);
|
| | for (pF.Init(); pF.More(); pF.Next()) {
|
| | float fDist = pF->DistanceToPoint(rclPt);
|
| | if (fDist < fMinDist) {
|
| | fMinDist = fDist;
|
| | ulInd = pF.Position();
|
| | }
|
| | }
|
| |
|
| | MeshGeomFacet rclSFacet = _rclMesh.GetFacet(ulInd);
|
| | rclSFacet.DistanceToPoint(rclPt, rclResPoint);
|
| | rclResFacetIndex = ulInd;
|
| |
|
| | return true;
|
| | }
|
| |
|
| | bool MeshAlgorithm::NearestPointFromPoint(
|
| | const Base::Vector3f& rclPt,
|
| | const MeshFacetGrid& rclGrid,
|
| | FacetIndex& rclResFacetIndex,
|
| | Base::Vector3f& rclResPoint
|
| | ) const
|
| | {
|
| | FacetIndex ulInd = rclGrid.SearchNearestFromPoint(rclPt);
|
| |
|
| | if (ulInd == FACET_INDEX_MAX) {
|
| | return false;
|
| | }
|
| |
|
| | MeshGeomFacet rclSFacet = _rclMesh.GetFacet(ulInd);
|
| | rclSFacet.DistanceToPoint(rclPt, rclResPoint);
|
| | rclResFacetIndex = ulInd;
|
| |
|
| | return true;
|
| | }
|
| |
|
| | bool MeshAlgorithm::NearestPointFromPoint(
|
| | const Base::Vector3f& rclPt,
|
| | const MeshFacetGrid& rclGrid,
|
| | float fMaxSearchArea,
|
| | FacetIndex& rclResFacetIndex,
|
| | Base::Vector3f& rclResPoint
|
| | ) const
|
| | {
|
| | FacetIndex ulInd = rclGrid.SearchNearestFromPoint(rclPt, fMaxSearchArea);
|
| |
|
| | if (ulInd == FACET_INDEX_MAX) {
|
| | return false;
|
| | }
|
| |
|
| | MeshGeomFacet rclSFacet = _rclMesh.GetFacet(ulInd);
|
| | rclSFacet.DistanceToPoint(rclPt, rclResPoint);
|
| | rclResFacetIndex = ulInd;
|
| |
|
| | return true;
|
| | }
|
| |
|
| | bool MeshAlgorithm::CutWithPlane(
|
| | const Base::Vector3f& clBase,
|
| | const Base::Vector3f& clNormal,
|
| | const MeshFacetGrid& rclGrid,
|
| | std::list<std::vector<Base::Vector3f>>& rclResult,
|
| | float fMinEps,
|
| | bool bConnectPolygons
|
| | ) const
|
| | {
|
| | std::vector<FacetIndex> aulFacets;
|
| |
|
| |
|
| | MeshGridIterator clGridIter(rclGrid);
|
| | for (clGridIter.Init(); clGridIter.More(); clGridIter.Next()) {
|
| |
|
| | if (clGridIter.GetBoundBox().IsCutPlane(clBase, clNormal)) {
|
| | clGridIter.GetElements(aulFacets);
|
| | }
|
| | }
|
| |
|
| |
|
| | std::sort(aulFacets.begin(), aulFacets.end());
|
| | aulFacets.erase(std::unique(aulFacets.begin(), aulFacets.end()), aulFacets.end());
|
| |
|
| |
|
| | std::list<std::pair<Base::Vector3f, Base::Vector3f>> clTempPoly;
|
| |
|
| |
|
| | for (FacetIndex facetIndex : aulFacets) {
|
| | Base::Vector3f clE1, clE2;
|
| | const MeshGeomFacet clF(_rclMesh.GetFacet(facetIndex));
|
| |
|
| |
|
| | if (clF.IntersectWithPlane(clBase, clNormal, clE1, clE2)) {
|
| | clTempPoly.emplace_back(clE1, clE2);
|
| | }
|
| | }
|
| |
|
| | if (bConnectPolygons) {
|
| |
|
| | std::list<std::pair<Base::Vector3f, Base::Vector3f>> rclResultLines(
|
| | clTempPoly.begin(),
|
| | clTempPoly.end()
|
| | );
|
| | std::list<std::vector<Base::Vector3f>> tempList;
|
| | ConnectLines(clTempPoly, tempList, fMinEps);
|
| | ConnectPolygons(tempList, clTempPoly);
|
| |
|
| | for (auto& iter : clTempPoly) {
|
| | rclResultLines.push_front(iter);
|
| | }
|
| |
|
| | return ConnectLines(rclResultLines, rclResult, fMinEps);
|
| | }
|
| |
|
| | return ConnectLines(clTempPoly, rclResult, fMinEps);
|
| | }
|
| |
|
| | bool MeshAlgorithm::ConnectLines(
|
| | std::list<std::pair<Base::Vector3f, Base::Vector3f>>& rclLines,
|
| | std::list<std::vector<Base::Vector3f>>& rclPolylines,
|
| | float fMinEps
|
| | ) const
|
| | {
|
| | using TCIter = std::list<std::pair<Base::Vector3f, Base::Vector3f>>::iterator;
|
| |
|
| |
|
| |
|
| | fMinEps = fMinEps * fMinEps;
|
| |
|
| |
|
| | std::list<TCIter> _clToDelete;
|
| | float fToDelDist = fMinEps / 10.0F;
|
| | for (TCIter pF = rclLines.begin(); pF != rclLines.end(); ++pF) {
|
| | if (Base::DistanceP2(pF->first, pF->second) < fToDelDist) {
|
| | _clToDelete.push_back(pF);
|
| | }
|
| | }
|
| |
|
| | for (auto& pI : _clToDelete) {
|
| | rclLines.erase(pI);
|
| | }
|
| |
|
| | while (!rclLines.empty()) {
|
| | TCIter pF;
|
| |
|
| |
|
| | std::list<Base::Vector3f> clPoly;
|
| |
|
| |
|
| | Base::Vector3f clFront = rclLines.begin()->first;
|
| | Base::Vector3f clEnd = rclLines.begin()->second;
|
| | clPoly.push_back(clFront);
|
| | clPoly.push_back(clEnd);
|
| | rclLines.erase(rclLines.begin());
|
| |
|
| |
|
| | TCIter pFront, pEnd;
|
| | bool bFoundLine {};
|
| | do {
|
| | float fFrontMin = fMinEps, fEndMin = fMinEps;
|
| | bool bFrontFirst = false, bEndFirst = false;
|
| |
|
| | pFront = rclLines.end();
|
| | pEnd = rclLines.end();
|
| | bFoundLine = false;
|
| |
|
| | for (pF = rclLines.begin(); pF != rclLines.end(); ++pF) {
|
| | if (Base::DistanceP2(clFront, pF->first) < fFrontMin) {
|
| | fFrontMin = Base::DistanceP2(clFront, pF->first);
|
| | pFront = pF;
|
| | bFrontFirst = true;
|
| | }
|
| | else if (Base::DistanceP2(clEnd, pF->first) < fEndMin) {
|
| | fEndMin = Base::DistanceP2(clEnd, pF->first);
|
| | pEnd = pF;
|
| | bEndFirst = true;
|
| | }
|
| | else if (Base::DistanceP2(clFront, pF->second) < fFrontMin) {
|
| | fFrontMin = Base::DistanceP2(clFront, pF->second);
|
| | pFront = pF;
|
| | bFrontFirst = false;
|
| | }
|
| | else if (Base::DistanceP2(clEnd, pF->second) < fEndMin) {
|
| | fEndMin = Base::DistanceP2(clEnd, pF->second);
|
| | pEnd = pF;
|
| | bEndFirst = false;
|
| | }
|
| | }
|
| |
|
| | if (pFront != rclLines.end()) {
|
| | bFoundLine = true;
|
| | if (bFrontFirst) {
|
| | clPoly.push_front(pFront->second);
|
| | clFront = pFront->second;
|
| | }
|
| | else {
|
| | clPoly.push_front(pFront->first);
|
| | clFront = pFront->first;
|
| | }
|
| |
|
| | rclLines.erase(pFront);
|
| | }
|
| |
|
| | if (pEnd != rclLines.end()) {
|
| | bFoundLine = true;
|
| | if (bEndFirst) {
|
| | clPoly.push_back(pEnd->second);
|
| | clEnd = pEnd->second;
|
| | }
|
| | else {
|
| | clPoly.push_back(pEnd->first);
|
| | clEnd = pEnd->first;
|
| | }
|
| |
|
| | rclLines.erase(pEnd);
|
| | }
|
| | } while (bFoundLine);
|
| |
|
| | rclPolylines.emplace_back(clPoly.begin(), clPoly.end());
|
| | }
|
| |
|
| |
|
| | using TPIter = std::list<std::vector<Base::Vector3f>>::iterator;
|
| | std::list<TPIter> _clPolyToDelete;
|
| | for (TPIter pJ = rclPolylines.begin(); pJ != rclPolylines.end(); ++pJ) {
|
| | if (pJ->size() == 2) {
|
| | if (Base::DistanceP2(*pJ->begin(), *(pJ->begin() + 1)) <= fMinEps) {
|
| | _clPolyToDelete.push_back(pJ);
|
| | }
|
| | }
|
| | }
|
| |
|
| | for (auto& pK : _clPolyToDelete) {
|
| | rclPolylines.erase(pK);
|
| | }
|
| |
|
| | return true;
|
| | }
|
| |
|
| | bool MeshAlgorithm::ConnectPolygons(
|
| | std::list<std::vector<Base::Vector3f>>& clPolyList,
|
| | std::list<std::pair<Base::Vector3f, Base::Vector3f>>& rclLines
|
| | ) const
|
| | {
|
| |
|
| | for (auto OutIter = clPolyList.begin(); OutIter != clPolyList.end(); ++OutIter) {
|
| | if (OutIter->empty()) {
|
| | continue;
|
| | }
|
| | std::pair<Base::Vector3f, Base::Vector3f> currentSort;
|
| | float fDist = Base::Distance(OutIter->front(), OutIter->back());
|
| | currentSort.first = OutIter->front();
|
| | currentSort.second = OutIter->back();
|
| |
|
| | for (auto InnerIter = clPolyList.begin(); InnerIter != clPolyList.end(); ++InnerIter) {
|
| | if (OutIter == InnerIter) {
|
| | continue;
|
| | }
|
| |
|
| | if (Base::Distance(OutIter->front(), InnerIter->front()) < fDist) {
|
| | currentSort.second = InnerIter->front();
|
| | fDist = Base::Distance(OutIter->front(), InnerIter->front());
|
| | }
|
| |
|
| | if (Base::Distance(OutIter->front(), InnerIter->back()) < fDist) {
|
| | currentSort.second = InnerIter->back();
|
| | fDist = Base::Distance(OutIter->front(), InnerIter->back());
|
| | }
|
| | }
|
| |
|
| | rclLines.push_front(currentSort);
|
| | }
|
| |
|
| | return true;
|
| | }
|
| |
|
| | void MeshAlgorithm::GetFacetsFromPlane(
|
| | const MeshFacetGrid& rclGrid,
|
| | const Base::Vector3f& clNormal,
|
| | float d,
|
| | const Base::Vector3f& rclLeft,
|
| | const Base::Vector3f& rclRight,
|
| | std::vector<FacetIndex>& rclRes
|
| | ) const
|
| | {
|
| | std::vector<FacetIndex> aulFacets;
|
| |
|
| | Base::Vector3f clBase = d * clNormal;
|
| |
|
| | Base::Vector3f clPtNormal(rclLeft - rclRight);
|
| | clPtNormal.Normalize();
|
| |
|
| |
|
| | MeshGridIterator clGridIter(rclGrid);
|
| | for (clGridIter.Init(); clGridIter.More(); clGridIter.Next()) {
|
| |
|
| | if (clGridIter.GetBoundBox().IsCutPlane(clBase, clNormal)) {
|
| | clGridIter.GetElements(aulFacets);
|
| | }
|
| | }
|
| |
|
| |
|
| | for (FacetIndex facetIndex : aulFacets) {
|
| | MeshGeomFacet clSFacet = _rclMesh.GetFacet(facetIndex);
|
| | if (clSFacet.IntersectWithPlane(clBase, clNormal)) {
|
| | bool bInner = false;
|
| | for (int i = 0; (i < 3) && !bInner; i++) {
|
| | Base::Vector3f clPt = clSFacet._aclPoints[i];
|
| | if ((clPt.DistanceToPlane(rclLeft, clPtNormal) <= 0.0F)
|
| | && (clPt.DistanceToPlane(rclRight, clPtNormal) >= 0.0F)) {
|
| | bInner = true;
|
| | }
|
| | }
|
| |
|
| | if (bInner) {
|
| | rclRes.push_back(facetIndex);
|
| | }
|
| | }
|
| | }
|
| | }
|
| |
|
| | void MeshAlgorithm::PointsFromFacetsIndices(
|
| | const std::vector<FacetIndex>& rvecIndices,
|
| | std::vector<Base::Vector3f>& rvecPoints
|
| | ) const
|
| | {
|
| | const MeshFacetArray& rclFAry = _rclMesh._aclFacetArray;
|
| | const MeshPointArray& rclPAry = _rclMesh._aclPointArray;
|
| |
|
| | std::set<PointIndex> setPoints;
|
| |
|
| | for (FacetIndex facetIndex : rvecIndices) {
|
| | for (PointIndex pointIndex : rclFAry[facetIndex]._aulPoints) {
|
| | setPoints.insert(pointIndex);
|
| | }
|
| | }
|
| |
|
| | rvecPoints.clear();
|
| | for (PointIndex pointIndex : setPoints) {
|
| | rvecPoints.push_back(rclPAry[pointIndex]);
|
| | }
|
| | }
|
| |
|
| | bool MeshAlgorithm::Distance(
|
| | const Base::Vector3f& rclPt,
|
| | FacetIndex ulFacetIdx,
|
| | float fMaxDistance,
|
| | float& rfDistance
|
| | ) const
|
| | {
|
| | const MeshFacetArray& rclFAry = _rclMesh._aclFacetArray;
|
| | const MeshPointArray& rclPAry = _rclMesh._aclPointArray;
|
| | const PointIndex* pulIdx = rclFAry[ulFacetIdx]._aulPoints;
|
| |
|
| | BoundBox3f clBB;
|
| | clBB.Add(rclPAry[*(pulIdx++)]);
|
| | clBB.Add(rclPAry[*(pulIdx++)]);
|
| | clBB.Add(rclPAry[*pulIdx]);
|
| | clBB.Enlarge(fMaxDistance);
|
| |
|
| | if (!clBB.IsInBox(rclPt)) {
|
| | return false;
|
| | }
|
| |
|
| | rfDistance = _rclMesh.GetFacet(ulFacetIdx).DistanceToPoint(rclPt);
|
| |
|
| | return rfDistance < fMaxDistance;
|
| | }
|
| |
|
| | float MeshAlgorithm::CalculateMinimumGridLength(
|
| | float fLength,
|
| | const Base::BoundBox3f& rBBox,
|
| | unsigned long maxElements
|
| | ) const
|
| | {
|
| |
|
| | float fMaxGridElements = static_cast<float>(maxElements);
|
| |
|
| |
|
| | float fMinGridLen = static_cast<float>(
|
| | std::pow((rBBox.LengthX() * rBBox.LengthY() * rBBox.LengthZ() / fMaxGridElements), 0.3333F)
|
| | );
|
| | return std::max<float>(fMinGridLen, fLength);
|
| | }
|
| |
|
| |
|
| |
|
| | void MeshRefPointToFacets::Rebuild()
|
| | {
|
| | _map.clear();
|
| |
|
| | const MeshPointArray& rPoints = _rclMesh.GetPoints();
|
| | const MeshFacetArray& rFacets = _rclMesh.GetFacets();
|
| | _map.resize(rPoints.size());
|
| |
|
| | auto pFBegin = rFacets.begin();
|
| | for (auto pFIter = rFacets.begin(); pFIter != rFacets.end(); ++pFIter) {
|
| | _map[pFIter->_aulPoints[0]].insert(pFIter - pFBegin);
|
| | _map[pFIter->_aulPoints[1]].insert(pFIter - pFBegin);
|
| | _map[pFIter->_aulPoints[2]].insert(pFIter - pFBegin);
|
| | }
|
| | }
|
| |
|
| | Base::Vector3f MeshRefPointToFacets::GetNormal(PointIndex pos) const
|
| | {
|
| | const std::set<FacetIndex>& n = _map[pos];
|
| | Base::Vector3f normal;
|
| | MeshGeomFacet f;
|
| | for (FacetIndex it : n) {
|
| | f = _rclMesh.GetFacet(it);
|
| | normal += f.Area() * f.GetNormal();
|
| | }
|
| |
|
| | normal.Normalize();
|
| | return normal;
|
| | }
|
| |
|
| | std::set<PointIndex> MeshRefPointToFacets::NeighbourPoints(
|
| | const std::vector<PointIndex>& pt,
|
| | int level
|
| | ) const
|
| | {
|
| | std::set<PointIndex> cp, nb, lp;
|
| | cp.insert(pt.begin(), pt.end());
|
| | lp.insert(pt.begin(), pt.end());
|
| | auto f_it = _rclMesh.GetFacets().begin();
|
| | for (int i = 0; i < level; i++) {
|
| | std::set<PointIndex> cur;
|
| | for (PointIndex it : lp) {
|
| | const std::set<FacetIndex>& ft = (*this)[it];
|
| | for (FacetIndex jt : ft) {
|
| | for (PointIndex index : f_it[jt]._aulPoints) {
|
| | if (cp.find(index) == cp.end() && nb.find(index) == nb.end()) {
|
| | nb.insert(index);
|
| | cur.insert(index);
|
| | }
|
| | }
|
| | }
|
| | }
|
| |
|
| | lp = cur;
|
| | if (lp.empty()) {
|
| | break;
|
| | }
|
| | }
|
| | return nb;
|
| | }
|
| |
|
| | std::set<PointIndex> MeshRefPointToFacets::NeighbourPoints(PointIndex pos) const
|
| | {
|
| | std::set<PointIndex> p;
|
| | const std::set<FacetIndex>& vf = _map[pos];
|
| | for (FacetIndex it : vf) {
|
| | PointIndex p1 {}, p2 {}, p3 {};
|
| | _rclMesh.GetFacetPoints(it, p1, p2, p3);
|
| | if (p1 != pos) {
|
| | p.insert(p1);
|
| | }
|
| | if (p2 != pos) {
|
| | p.insert(p2);
|
| | }
|
| | if (p3 != pos) {
|
| | p.insert(p3);
|
| | }
|
| | }
|
| |
|
| | return p;
|
| | }
|
| |
|
| | void MeshRefPointToFacets::Neighbours(FacetIndex ulFacetInd, float fMaxDist, MeshCollector& collect) const
|
| | {
|
| | std::set<FacetIndex> visited;
|
| | Base::Vector3f clCenter = _rclMesh.GetFacet(ulFacetInd).GetGravityPoint();
|
| |
|
| | const MeshFacetArray& rFacets = _rclMesh.GetFacets();
|
| | SearchNeighbours(rFacets, ulFacetInd, clCenter, fMaxDist * fMaxDist, visited, collect);
|
| | }
|
| |
|
| | void MeshRefPointToFacets::SearchNeighbours(
|
| | const MeshFacetArray& rFacets,
|
| | FacetIndex index,
|
| | const Base::Vector3f& rclCenter,
|
| | float fMaxDist2,
|
| | std::set<FacetIndex>& visited,
|
| | MeshCollector& collect
|
| | ) const
|
| | {
|
| | if (visited.find(index) != visited.end()) {
|
| | return;
|
| | }
|
| |
|
| | const MeshFacet& face = rFacets[index];
|
| | if (Base::DistanceP2(rclCenter, _rclMesh.GetFacet(face).GetGravityPoint()) > fMaxDist2) {
|
| | return;
|
| | }
|
| |
|
| | visited.insert(index);
|
| | collect.Append(_rclMesh, index);
|
| | for (PointIndex ptIndex : face._aulPoints) {
|
| | const std::set<FacetIndex>& f = (*this)[ptIndex];
|
| |
|
| | for (FacetIndex j : f) {
|
| | SearchNeighbours(rFacets, j, rclCenter, fMaxDist2, visited, collect);
|
| | }
|
| | }
|
| | }
|
| |
|
| | MeshFacetArray::_TConstIterator MeshRefPointToFacets::GetFacet(FacetIndex index) const
|
| | {
|
| | return _rclMesh.GetFacets().begin() + index;
|
| | }
|
| |
|
| | const std::set<FacetIndex>& MeshRefPointToFacets::operator[](PointIndex pos) const
|
| | {
|
| | return _map[pos];
|
| | }
|
| |
|
| | std::vector<FacetIndex> MeshRefPointToFacets::GetIndices(PointIndex pos1, PointIndex pos2) const
|
| | {
|
| | std::vector<FacetIndex> intersection;
|
| | std::back_insert_iterator<std::vector<FacetIndex>> result(intersection);
|
| | const std::set<FacetIndex>& set1 = _map[pos1];
|
| | const std::set<FacetIndex>& set2 = _map[pos2];
|
| | std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), result);
|
| | return intersection;
|
| | }
|
| |
|
| | std::vector<FacetIndex> MeshRefPointToFacets::GetIndices(
|
| | PointIndex pos1,
|
| | PointIndex pos2,
|
| | PointIndex pos3
|
| | ) const
|
| | {
|
| | std::vector<FacetIndex> intersection;
|
| | std::back_insert_iterator<std::vector<FacetIndex>> result(intersection);
|
| | std::vector<FacetIndex> set1 = GetIndices(pos1, pos2);
|
| | const std::set<FacetIndex>& set2 = _map[pos3];
|
| | std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), result);
|
| | return intersection;
|
| | }
|
| |
|
| | void MeshRefPointToFacets::AddNeighbour(PointIndex pos, FacetIndex facet)
|
| | {
|
| | _map[pos].insert(facet);
|
| | }
|
| |
|
| | void MeshRefPointToFacets::RemoveNeighbour(PointIndex pos, FacetIndex facet)
|
| | {
|
| | _map[pos].erase(facet);
|
| | }
|
| |
|
| | void MeshRefPointToFacets::RemoveFacet(FacetIndex facetIndex)
|
| | {
|
| | PointIndex p0 {}, p1 {}, p2 {};
|
| | _rclMesh.GetFacetPoints(facetIndex, p0, p1, p2);
|
| |
|
| | _map[p0].erase(facetIndex);
|
| | _map[p1].erase(facetIndex);
|
| | _map[p2].erase(facetIndex);
|
| | }
|
| |
|
| |
|
| |
|
| | void MeshRefFacetToFacets::Rebuild()
|
| | {
|
| | _map.clear();
|
| |
|
| | const MeshFacetArray& rFacets = _rclMesh.GetFacets();
|
| | _map.resize(rFacets.size());
|
| |
|
| | MeshRefPointToFacets vertexFace(_rclMesh);
|
| | auto pFBegin = rFacets.begin();
|
| | for (auto pFIter = pFBegin; pFIter != rFacets.end(); ++pFIter) {
|
| | for (PointIndex ptIndex : pFIter->_aulPoints) {
|
| | const std::set<FacetIndex>& faces = vertexFace[ptIndex];
|
| | for (FacetIndex face : faces) {
|
| | _map[pFIter - pFBegin].insert(face);
|
| | }
|
| | }
|
| | }
|
| | }
|
| |
|
| | const std::set<FacetIndex>& MeshRefFacetToFacets::operator[](FacetIndex pos) const
|
| | {
|
| | return _map[pos];
|
| | }
|
| |
|
| | std::vector<FacetIndex> MeshRefFacetToFacets::GetIndices(FacetIndex pos1, FacetIndex pos2) const
|
| | {
|
| | std::vector<FacetIndex> intersection;
|
| | std::back_insert_iterator<std::vector<FacetIndex>> result(intersection);
|
| | const std::set<FacetIndex>& set1 = _map[pos1];
|
| | const std::set<FacetIndex>& set2 = _map[pos2];
|
| | std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), result);
|
| | return intersection;
|
| | }
|
| |
|
| |
|
| |
|
| | void MeshRefPointToPoints::Rebuild()
|
| | {
|
| | _map.clear();
|
| |
|
| | const MeshPointArray& rPoints = _rclMesh.GetPoints();
|
| | _map.resize(rPoints.size());
|
| |
|
| | const MeshFacetArray& rFacets = _rclMesh.GetFacets();
|
| | for (const auto& rFacet : rFacets) {
|
| | PointIndex ulP0 = rFacet._aulPoints[0];
|
| | PointIndex ulP1 = rFacet._aulPoints[1];
|
| | PointIndex ulP2 = rFacet._aulPoints[2];
|
| |
|
| | _map[ulP0].insert(ulP1);
|
| | _map[ulP0].insert(ulP2);
|
| | _map[ulP1].insert(ulP0);
|
| | _map[ulP1].insert(ulP2);
|
| | _map[ulP2].insert(ulP0);
|
| | _map[ulP2].insert(ulP1);
|
| | }
|
| | }
|
| |
|
| | Base::Vector3f MeshRefPointToPoints::GetNormal(PointIndex pos) const
|
| | {
|
| | const MeshPointArray& rPoints = _rclMesh.GetPoints();
|
| | MeshCore::PlaneFit pf;
|
| | pf.AddPoint(rPoints[pos]);
|
| | MeshCore::MeshPoint center = rPoints[pos];
|
| | const std::set<PointIndex>& cv = _map[pos];
|
| | for (PointIndex cv_it : cv) {
|
| | pf.AddPoint(rPoints[cv_it]);
|
| | center += rPoints[cv_it];
|
| | }
|
| |
|
| | pf.Fit();
|
| |
|
| | Base::Vector3f normal = pf.GetNormal();
|
| | normal.Normalize();
|
| | return normal;
|
| | }
|
| |
|
| | float MeshRefPointToPoints::GetAverageEdgeLength(PointIndex index) const
|
| | {
|
| | const MeshPointArray& rPoints = _rclMesh.GetPoints();
|
| | float len = 0.0F;
|
| | const std::set<PointIndex>& n = (*this)[index];
|
| | const Base::Vector3f& p = rPoints[index];
|
| | for (PointIndex it : n) {
|
| | len += Base::Distance(p, rPoints[it]);
|
| | }
|
| | return (len / n.size());
|
| | }
|
| |
|
| | const std::set<PointIndex>& MeshRefPointToPoints::operator[](PointIndex pos) const
|
| | {
|
| | return _map[pos];
|
| | }
|
| |
|
| | void MeshRefPointToPoints::AddNeighbour(PointIndex pos, PointIndex facet)
|
| | {
|
| | _map[pos].insert(facet);
|
| | }
|
| |
|
| | void MeshRefPointToPoints::RemoveNeighbour(PointIndex pos, PointIndex facet)
|
| | {
|
| | _map[pos].erase(facet);
|
| | }
|
| |
|
| |
|
| |
|
| | void MeshRefEdgeToFacets::Rebuild()
|
| | {
|
| | _map.clear();
|
| |
|
| | const MeshFacetArray& rFacets = _rclMesh.GetFacets();
|
| | FacetIndex index = 0;
|
| | for (auto it = rFacets.begin(); it != rFacets.end(); ++it, ++index) {
|
| | for (int i = 0; i < 3; i++) {
|
| | MeshEdge e;
|
| | e.first = it->_aulPoints[i];
|
| | e.second = it->_aulPoints[(i + 1) % 3];
|
| | auto jt = _map.find(e);
|
| | if (jt == _map.end()) {
|
| | _map[e].first = index;
|
| | _map[e].second = FACET_INDEX_MAX;
|
| | }
|
| | else {
|
| | _map[e].second = index;
|
| | }
|
| | }
|
| | }
|
| | }
|
| |
|
| | const std::pair<FacetIndex, FacetIndex>& MeshRefEdgeToFacets::operator[](const MeshEdge& edge) const
|
| | {
|
| | return _map.find(edge)->second;
|
| | }
|
| |
|
| |
|
| |
|
| | void MeshRefNormalToPoints::Rebuild()
|
| | {
|
| | _norm.clear();
|
| |
|
| | const MeshPointArray& rPoints = _rclMesh.GetPoints();
|
| | _norm.resize(rPoints.size());
|
| |
|
| | const MeshFacetArray& rFacets = _rclMesh.GetFacets();
|
| | for (const auto& rFacet : rFacets) {
|
| | const MeshPoint& p0 = rPoints[rFacet._aulPoints[0]];
|
| | const MeshPoint& p1 = rPoints[rFacet._aulPoints[1]];
|
| | const MeshPoint& p2 = rPoints[rFacet._aulPoints[2]];
|
| | float l2p01 = Base::DistanceP2(p0, p1);
|
| | float l2p12 = Base::DistanceP2(p1, p2);
|
| | float l2p20 = Base::DistanceP2(p2, p0);
|
| |
|
| | Base::Vector3f facenormal = _rclMesh.GetFacet(rFacet).GetNormal();
|
| | _norm[rFacet._aulPoints[0]] += facenormal * (1.0F / (l2p01 * l2p20));
|
| | _norm[rFacet._aulPoints[1]] += facenormal * (1.0F / (l2p12 * l2p01));
|
| | _norm[rFacet._aulPoints[2]] += facenormal * (1.0F / (l2p20 * l2p12));
|
| | }
|
| | for (auto& it : _norm) {
|
| | it.Normalize();
|
| | }
|
| | }
|
| |
|
| | const Base::Vector3f& MeshRefNormalToPoints::operator[](PointIndex pos) const
|
| | {
|
| | return _norm[pos];
|
| | }
|
| |
|