diff --git a/src/Base/Builder3D.cpp b/src/Base/Builder3D.cpp index 94a61c121..3c4956cff 100644 --- a/src/Base/Builder3D.cpp +++ b/src/Base/Builder3D.cpp @@ -440,6 +440,18 @@ void InventorBuilder::addPointSet(void) result << Base::blanks(indent) << "PointSet { } " << std::endl; } +/** + * Adds an SoLineSet node after creating an SoCordinate3 node with + * beginPoints() and endPoints(). + * @see startPoints() + * @see beginPoints() + * @see endPoints() + */ +void InventorBuilder::addLineSet(void) +{ + result << Base::blanks(indent) << "LineSet { } " << std::endl; +} + //************************************************************************** // text handling @@ -591,9 +603,9 @@ void InventorBuilder::addIndexedFaceSet(const std::vector& points, con if (points.empty() || indices.size() < 4) return; result << " Separator { " << std::endl - << " ShapeHints {" << std::endl - << " creaseAngle " << crease << std::endl - << " }" << std::endl + << " ShapeHints {" << std::endl + << " creaseAngle " << crease << std::endl + << " }" << std::endl << " Coordinate3 { " << std::endl << " point [ "; std::vector::const_iterator it_last_p = points.end()-1; @@ -731,11 +743,11 @@ void InventorBuilder::addNurbsSurface(const std::vector& control } void InventorBuilder::addCylinder(float radius, float height) -{ - result << Base::blanks(indent) << "Cylinder {\n" - << Base::blanks(indent) << " radius " << radius << "\n" - << Base::blanks(indent) << " height " << height << "\n" - << Base::blanks(indent) << " parts (SIDES | TOP | BOTTOM)\n" +{ + result << Base::blanks(indent) << "Cylinder {\n" + << Base::blanks(indent) << " radius " << radius << "\n" + << Base::blanks(indent) << " height " << height << "\n" + << Base::blanks(indent) << " parts (SIDES | TOP | BOTTOM)\n" << Base::blanks(indent) << "}\n"; } @@ -796,4 +808,4 @@ void InventorBuilder::addTransformation(const Vector3f& translation, const Vecto << rotationaxis.x << " " << rotationaxis.y << " " << rotationaxis.z << " " << fAngle << std::endl; result << Base::blanks(indent) << "}" << std::endl; -} +} diff --git a/src/Base/Builder3D.h b/src/Base/Builder3D.h index 0181790cf..be4f932f3 100644 --- a/src/Base/Builder3D.h +++ b/src/Base/Builder3D.h @@ -166,6 +166,8 @@ public: void endPoints(void); /// add an SoPointSet node void addPointSet(void); + /// add an SoLineSet node + void addLineSet(void); //@} /** @name Line/Direction handling */ diff --git a/src/Mod/Mesh/App/Core/Projection.cpp b/src/Mod/Mesh/App/Core/Projection.cpp index d52e0e503..ef7c7b681 100644 --- a/src/Mod/Mesh/App/Core/Projection.cpp +++ b/src/Mod/Mesh/App/Core/Projection.cpp @@ -39,6 +39,7 @@ # include # include # include +#endif #include "Projection.h" #include "MeshKernel.h" @@ -54,6 +55,7 @@ using namespace MeshCore; +#ifdef FC_USE_OCC MeshProjection::MeshProjection(const MeshKernel& rMesh) : _rcMesh(rMesh) { @@ -262,3 +264,175 @@ void MeshProjection::projectEdgeToEdge( const TopoDS_Edge &aEdge, float fMaxDist } #endif + +// ------------------------------------------------------------------------ + +MeshProjection::MeshProjection(const MeshKernel& mesh) + : kernel(mesh) +{ +} + +MeshProjection::~MeshProjection() +{ +} + +bool MeshProjection::bboxInsideRectangle(const Base::BoundBox3f& bbox, + const Base::Vector3f& p1, + const Base::Vector3f& p2, + const Base::Vector3f& view) const +{ + Base::Vector3f dir(p2 - p1); + Base::Vector3f base(p1), normal(view % dir); + normal.Normalize(); + + if (bbox.IsCutPlane(base, normal)) { + dir.Normalize(); + Base::Vector3f cnt(bbox.CalcCenter()); + + return (fabs(cnt.DistanceToPlane(p1, dir)) + fabs(cnt.DistanceToPlane(p2, dir))) <= + (bbox.CalcDiagonalLength() + (p2 - p1).Length()); + } + + return false; +} + +bool MeshProjection::isPointInsideDistance (const Base::Vector3f& p1, + const Base::Vector3f& p2, + const Base::Vector3f& pt) const +{ + // project point on line + Base::Vector3f proj, dir(p2 - p1); + Base::Vector3f move(pt - p1); + proj.ProjToLine(move, dir); + proj = pt + proj; + return (((p1 - proj) * (p2 - proj)) < 0.0f); +} + +bool MeshProjection::connectLines(std::list< std::pair >& cutLines, + const Base::Vector3f& startPoint, const Base::Vector3f& endPoint, + std::vector& polyline) const +{ + const float fMaxDist = float(sqrt(FLOAT_MAX)); // max. length of a gap + const float fMinEps = 1.0e-4f; + + polyline.clear(); + polyline.push_back(startPoint); + + Base::Vector3f curr(startPoint); + while ((curr != endPoint) && (!cutLines.empty())) { + std::list< std::pair >::iterator it, pCurr = cutLines.end(); + + // get nearest line + float fMin = fMaxDist * fMaxDist; + + bool bPos; + for (it = cutLines.begin(); it != cutLines.end(); ++it) { + float fD1 = Base::DistanceP2(curr, it->first); + float fD2 = Base::DistanceP2(curr, it->second); + if (std::min(fD1, fD2) < fMin) { + pCurr = it; + bPos = fD1 < fD2; + fMin = std::min(fD1, fD2); + if (fMin < fMinEps) // abort because next line already found + break; + } + } + + if (pCurr != cutLines.end()) { + if (bPos) { + if (fMin > fMinEps) // gap, insert point + polyline.push_back(pCurr->first); + polyline.push_back(pCurr->second); + curr = pCurr->second; + } + else { + if (fMin > fMinEps) // gap, insert point + polyline.push_back(pCurr->second); + polyline.push_back(pCurr->first); + curr = pCurr->first; + } + } + else { + return false; // abort because no line was found + } + + cutLines.erase(pCurr); + } + + return true; +} + +bool MeshProjection::projectLineOnMesh(const MeshFacetGrid& grid, + const Base::Vector3f& v1, unsigned long f1, + const Base::Vector3f& v2, unsigned long f2, + const Base::Vector3f& vd, + std::vector& polyline) +{ + Base::Vector3f dir(v2 - v1); + Base::Vector3f base(v1), normal(vd % dir); + normal.Normalize(); + dir.Normalize(); + + + std::vector facets; + + // special case: start and endpoint inside same facet + if (f1 == f2) { + polyline.push_back(v1); + polyline.push_back(v2); + return true; + } + + // cut all facets between the two endpoints + MeshGridIterator gridIter(grid); + for (gridIter.Init(); gridIter.More(); gridIter.Next()) { + // bbox cuts plane + if (bboxInsideRectangle(gridIter.GetBoundBox(), v1, v2, vd)) + gridIter.GetElements(facets); + } + + std::sort(facets.begin(), facets.end()); + facets.erase(std::unique(facets.begin(), facets.end()), facets.end()); + + // cut all facets with plane + std::list< std::pair > cutLine; + unsigned long start = 0, end = 0; + for (std::vector::iterator it = facets.begin(); it != facets.end(); ++it) { + Base::Vector3f e1, e2; + MeshGeomFacet tria = kernel.GetFacet(*it); + if (bboxInsideRectangle(tria.GetBoundBox(), v1, v2, vd)) { + if (tria.IntersectWithPlane(base, normal, e1, e2)) { + if ((*it != f1) && (*it != f2)) { + // inside cut line + if ((isPointInsideDistance(v1, v2, e1) == false) || + (isPointInsideDistance(v1, v2, e2) == false)) { + continue; + } + + cutLine.push_back(std::pair(e1, e2)); + } + else { + if (*it == f1) { // start facet + if (((e2 - v1) * dir) > 0.0f) + cutLine.push_back(std::pair(v1, e2)); + else + cutLine.push_back(std::pair(v1, e1)); + + start = it - facets.begin(); + } + + if (*it == f2) { // end facet + if (((e2 - v2) * -dir) > 0.0f) + cutLine.push_back(std::pair(v2, e2)); + else + cutLine.push_back(std::pair(v2, e1)); + + end = it - facets.begin(); + } + } + } + } + } + + return connectLines(cutLine, v1, v2, polyline); +} diff --git a/src/Mod/Mesh/App/Core/Projection.h b/src/Mod/Mesh/App/Core/Projection.h index 18421a500..8600117f4 100644 --- a/src/Mod/Mesh/App/Core/Projection.h +++ b/src/Mod/Mesh/App/Core/Projection.h @@ -25,13 +25,15 @@ #define MESH_PROJECTION_H #include - +#include #include -#ifdef FC_USE_OCC + using Base::Vector3f; +#ifdef FC_USE_OCC class TopoDS_Edge; class TopoDS_Shape; +#endif namespace MeshCore { @@ -40,6 +42,26 @@ class MeshFacetGrid; class MeshKernel; class MeshGeomFacet; +class MeshExport MeshProjection +{ +public: + MeshProjection(const MeshKernel&); + ~MeshProjection(); + + bool projectLineOnMesh(const MeshFacetGrid& grid, const Base::Vector3f& p1, unsigned long f1, + const Base::Vector3f& p2, unsigned long f2, const Base::Vector3f& view, + std::vector& polyline); +protected: + bool bboxInsideRectangle (const Base::BoundBox3f& bbox, const Base::Vector3f& p1, const Base::Vector3f& p2, const Base::Vector3f& view) const; + bool isPointInsideDistance (const Base::Vector3f& p1, const Base::Vector3f& p2, const Base::Vector3f& pt) const; + bool connectLines(std::list< std::pair >& cutLines, const Base::Vector3f& startPoint, + const Base::Vector3f& endPoint, std::vector& polyline) const; + +private: + const MeshKernel& kernel; +}; + +#ifdef FC_USE_OCC /// Helper class struct SplitEdge { @@ -78,8 +100,8 @@ protected: private: const MeshKernel& _rcMesh; }; - -} // namespace MeshCore #endif +} // namespace MeshCore + #endif // MESH_PROJECTION_H