Mesh trimming tool
This commit is contained in:
@@ -71,6 +71,8 @@ SET(Core_SRCS
|
||||
Core/TopoAlgorithm.h
|
||||
Core/Triangulation.cpp
|
||||
Core/Triangulation.h
|
||||
Core/Trim.cpp
|
||||
Core/Trim.h
|
||||
Core/tritritest.h
|
||||
Core/Visitor.cpp
|
||||
Core/Visitor.h
|
||||
|
||||
@@ -1603,40 +1603,36 @@ bool MeshAlgorithm::ConnectPolygons(std::list<std::vector<Base::Vector3f> > &clP
|
||||
void MeshAlgorithm::GetFacetsFromPlane (const MeshFacetGrid &rclGrid, const Base::Vector3f& clNormal, float d, const Base::Vector3f &rclLeft,
|
||||
const Base::Vector3f &rclRight, std::vector<unsigned long> &rclRes) const
|
||||
{
|
||||
std::vector<unsigned long> aulFacets;
|
||||
std::vector<unsigned long> aulFacets;
|
||||
|
||||
Base::Vector3f clBase = d * clNormal;
|
||||
Base::Vector3f clBase = d * clNormal;
|
||||
|
||||
Base::Vector3f clPtNormal(rclLeft - rclRight);
|
||||
clPtNormal.Normalize();
|
||||
Base::Vector3f clPtNormal(rclLeft - rclRight);
|
||||
clPtNormal.Normalize();
|
||||
|
||||
// search grid
|
||||
MeshGridIterator clGridIter(rclGrid);
|
||||
for (clGridIter.Init(); clGridIter.More(); clGridIter.Next())
|
||||
{
|
||||
// add facets from grid if the plane if cut the grid-voxel
|
||||
if (clGridIter.GetBoundBox().IsCutPlane(clBase, clNormal) == true)
|
||||
clGridIter.GetElements(aulFacets);
|
||||
}
|
||||
|
||||
// testing facet against planes
|
||||
for (std::vector<unsigned long>::iterator pI = aulFacets.begin(); pI != aulFacets.end(); pI++)
|
||||
{
|
||||
MeshGeomFacet clSFacet = _rclMesh.GetFacet(*pI);
|
||||
if (clSFacet.IntersectWithPlane(clBase, clNormal) == true)
|
||||
{
|
||||
bool bInner = false;
|
||||
for (int i = 0; (i < 3) && (bInner == false); i++)
|
||||
{
|
||||
Base::Vector3f clPt = clSFacet._aclPoints[i];
|
||||
if ((clPt.DistanceToPlane(rclLeft, clPtNormal) <= 0.0f) && (clPt.DistanceToPlane(rclRight, clPtNormal) >= 0.0f))
|
||||
bInner = true;
|
||||
}
|
||||
|
||||
if (bInner == true)
|
||||
rclRes.push_back(*pI);
|
||||
// search grid
|
||||
MeshGridIterator clGridIter(rclGrid);
|
||||
for (clGridIter.Init(); clGridIter.More(); clGridIter.Next()) {
|
||||
// add facets from grid if the plane if cut the grid-voxel
|
||||
if (clGridIter.GetBoundBox().IsCutPlane(clBase, clNormal) == true)
|
||||
clGridIter.GetElements(aulFacets);
|
||||
}
|
||||
|
||||
// testing facet against planes
|
||||
for (std::vector<unsigned long>::iterator pI = aulFacets.begin(); pI != aulFacets.end(); ++pI) {
|
||||
MeshGeomFacet clSFacet = _rclMesh.GetFacet(*pI);
|
||||
if (clSFacet.IntersectWithPlane(clBase, clNormal) == true) {
|
||||
bool bInner = false;
|
||||
for (int i = 0; (i < 3) && (bInner == false); i++) {
|
||||
Base::Vector3f clPt = clSFacet._aclPoints[i];
|
||||
if ((clPt.DistanceToPlane(rclLeft, clPtNormal) <= 0.0f) && (clPt.DistanceToPlane(rclRight, clPtNormal) >= 0.0f))
|
||||
bInner = true;
|
||||
}
|
||||
|
||||
if (bInner == true)
|
||||
rclRes.push_back(*pI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MeshAlgorithm::PointsFromFacetsIndices (const std::vector<unsigned long> &rvecIndices, std::vector<Base::Vector3f> &rvecPoints) const
|
||||
|
||||
@@ -440,6 +440,7 @@ protected:
|
||||
friend class MeshFixDegeneratedFacets;
|
||||
friend class MeshFixDuplicatePoints;
|
||||
friend class MeshBuilder;
|
||||
friend class MeshTrimming;
|
||||
};
|
||||
|
||||
inline MeshPoint MeshKernel::GetPoint (unsigned long ulIndex) const
|
||||
|
||||
684
src/Mod/Mesh/App/Core/Trim.cpp
Normal file
684
src/Mod/Mesh/App/Core/Trim.cpp
Normal file
@@ -0,0 +1,684 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2012 Imetric 3D GmbH *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include "Trim.h"
|
||||
#include "Grid.h"
|
||||
#include "Iterator.h"
|
||||
#include <Base/Sequencer.h>
|
||||
|
||||
using namespace MeshCore;
|
||||
|
||||
MeshTrimming::MeshTrimming(MeshKernel &rclM, const Base::ViewProjMethod* pclProj,
|
||||
const Base::Polygon2D& rclPoly)
|
||||
: myMesh(rclM), myProj(pclProj), myPoly(rclPoly), myInner(true)
|
||||
{
|
||||
}
|
||||
|
||||
MeshTrimming::~MeshTrimming()
|
||||
{
|
||||
}
|
||||
|
||||
void MeshTrimming::SetInnerOrOuter(TMode tMode)
|
||||
{
|
||||
switch (tMode)
|
||||
{
|
||||
case INNER:
|
||||
myInner = true;
|
||||
break;
|
||||
case OUTER:
|
||||
myInner = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MeshTrimming::CheckFacets(const MeshFacetGrid& rclGrid, std::vector<unsigned long> &raulFacets) const
|
||||
{
|
||||
std::vector<unsigned long>::iterator it;
|
||||
MeshFacetIterator clIter(myMesh, 0);
|
||||
|
||||
// cut inner: use grid to accelerate search
|
||||
if (myInner) {
|
||||
Base::BoundBox3f clBBox3d;
|
||||
Base::BoundBox2D clViewBBox, clPolyBBox;
|
||||
std::vector<unsigned long> aulAllElements;
|
||||
|
||||
// BBox of polygon
|
||||
clPolyBBox = myPoly.CalcBoundBox();
|
||||
MeshGridIterator clGridIter(rclGrid);
|
||||
// traverse all BBoxes
|
||||
for (clGridIter.Init(); clGridIter.More(); clGridIter.Next()) {
|
||||
clBBox3d = clGridIter.GetBoundBox();
|
||||
clViewBBox = clBBox3d.ProjectBox(myProj);
|
||||
if (clViewBBox || clPolyBBox) {
|
||||
// save all elements in AllElements
|
||||
clGridIter.GetElements(aulAllElements);
|
||||
}
|
||||
}
|
||||
|
||||
// remove double elements
|
||||
std::sort(aulAllElements.begin(), aulAllElements.end());
|
||||
aulAllElements.erase(std::unique(aulAllElements.begin(), aulAllElements.end()), aulAllElements.end());
|
||||
|
||||
Base::SequencerLauncher seq("Check facets for intersection...", aulAllElements.size());
|
||||
|
||||
for (it = aulAllElements.begin(); it != aulAllElements.end(); it++) {
|
||||
MeshGeomFacet &rclFacet = myMesh.GetFacet(*it);
|
||||
if (HasIntersection(rclFacet))
|
||||
raulFacets.push_back(*it);
|
||||
seq.next();
|
||||
}
|
||||
}
|
||||
// cut outer
|
||||
else {
|
||||
Base::SequencerLauncher seq("Check facets for intersection...", myMesh.CountFacets());
|
||||
for (clIter.Init(); clIter.More(); clIter.Next()) {
|
||||
if (HasIntersection(*clIter))
|
||||
raulFacets.push_back(clIter.Position());
|
||||
seq.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MeshTrimming::HasIntersection(const MeshGeomFacet& rclFacet) const
|
||||
{
|
||||
int i;
|
||||
unsigned long j;
|
||||
Base::Polygon2D clPoly;
|
||||
Base::Line2D clFacLine, clPolyLine;
|
||||
Base::Vector2D S;
|
||||
// is corner of facet inside the polygon
|
||||
for (i=0; i<3; i++) {
|
||||
Base::Vector3f clPt2d = myProj->operator ()(rclFacet._aclPoints[i]);
|
||||
if (myPoly.Contains(Base::Vector2D(clPt2d.x, clPt2d.y)) == myInner)
|
||||
return true;
|
||||
else
|
||||
clPoly.Add(Base::Vector2D(clPt2d.x, clPt2d.y));
|
||||
}
|
||||
|
||||
// is corner of polygon inside the facet
|
||||
for (j=0; j<myPoly.GetCtVectors(); j++) {
|
||||
if (clPoly.Contains(myPoly[j]))
|
||||
return true;
|
||||
}
|
||||
|
||||
// check for other intersections
|
||||
for (j=0; j<myPoly.GetCtVectors(); j++) {
|
||||
clPolyLine.clV1 = myPoly[j];
|
||||
clPolyLine.clV2 = myPoly[(j+1)%myPoly.GetCtVectors()];
|
||||
|
||||
for (i=0; i<3; i++) {
|
||||
clFacLine.clV1 = clPoly[i];
|
||||
clFacLine.clV2 = clPoly[(i+1)%3];
|
||||
|
||||
if (clPolyLine.IntersectAndContain(clFacLine, S))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// no intersection
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MeshTrimming::PolygonContainsCompleteFacet(bool bInner, unsigned long ulIndex) const
|
||||
{
|
||||
const MeshFacet &rclFacet = myMesh._aclFacetArray[ulIndex];
|
||||
for (int i=0; i<3; i++) {
|
||||
const MeshPoint &rclFacPt = myMesh._aclPointArray[rclFacet._aulPoints[i]];
|
||||
Base::Vector3f clPt = (*myProj)(rclFacPt);
|
||||
if (myPoly.Contains(Base::Vector2D(clPt.x, clPt.y)) != bInner)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MeshTrimming::IsPolygonPointInFacet(unsigned long ulIndex, Base::Vector3f& clPoint)
|
||||
{
|
||||
Base::Vector2D A, B, C, P;
|
||||
float u,v,w, fDetPAC, fDetPBC, fDetPAB, fDetABC;
|
||||
Base::Polygon2D clFacPoly;
|
||||
const MeshGeomFacet &rclFacet = myMesh.GetFacet(ulIndex);
|
||||
|
||||
for (int i=0; i<3; i++) {
|
||||
Base::Vector3f clPt = (*myProj)(rclFacet._aclPoints[i]);
|
||||
clFacPoly.Add(Base::Vector2D(clPt.x, clPt.y));
|
||||
}
|
||||
|
||||
A = clFacPoly[0];
|
||||
B = clFacPoly[1];
|
||||
C = clFacPoly[2];
|
||||
fDetABC = A.fX*B.fY+A.fY*C.fX+B.fX*C.fY-(B.fY*C.fX+A.fY*B.fX+A.fX*C.fY);
|
||||
|
||||
for (unsigned long j=0; j<myPoly.GetCtVectors(); j++) {
|
||||
// facet contains a polygon point -> calculate the corresponding 3d-point
|
||||
if (clFacPoly.Contains(myPoly[j])) {
|
||||
P = myPoly[j];
|
||||
fDetPAC = A.fX*P.fY+A.fY*C.fX+P.fX*C.fY-(P.fY*C.fX+A.fY*P.fX+A.fX*C.fY);
|
||||
fDetPBC = P.fX*B.fY+P.fY*C.fX+B.fX*C.fY-(B.fY*C.fX+P.fY*B.fX+P.fX*C.fY);
|
||||
fDetPAB = A.fX*B.fY+A.fY*P.fX+B.fX*P.fY-(B.fY*P.fX+A.fY*B.fX+A.fX*P.fY);
|
||||
u = fDetPBC / fDetABC;
|
||||
v = fDetPAC / fDetABC;
|
||||
w = fDetPAB / fDetABC;
|
||||
|
||||
// point is on edge or no valid convex combination
|
||||
if (u == 0.0f || v == 0.0f || w == 0.0f || fabs(u+v+w-1.0f) >= 0.001)
|
||||
return false;
|
||||
// 3d point
|
||||
clPoint = u*rclFacet._aclPoints[0]+v*rclFacet._aclPoints[1]+w*rclFacet._aclPoints[2];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MeshTrimming::GetIntersectionPointsOfPolygonAndFacet(unsigned long ulIndex, int& iSide, std::vector<Base::Vector3f>& raclPoints) const
|
||||
{
|
||||
MeshGeomFacet clFac(myMesh.GetFacet(ulIndex));
|
||||
Base::Vector2D S;
|
||||
Base::Line2D clFacLine, clPolyLine;
|
||||
int iIntersections=0;
|
||||
int iIntsctWithEdge0=0, iIntsctWithEdge1=0, iIntsctWithEdge2=0;
|
||||
// Edge with no intersection
|
||||
iSide = -1;
|
||||
|
||||
for (unsigned long i=0; i<myPoly.GetCtVectors(); i++) {
|
||||
// totally only four intersections allowed
|
||||
if (iIntersections == 4)
|
||||
break;
|
||||
|
||||
Base::Vector2D P3(myPoly[i]), P4(myPoly[(i+1)%myPoly.GetCtVectors()]);
|
||||
clPolyLine.clV1 = P3;
|
||||
clPolyLine.clV2 = P4;
|
||||
|
||||
for (int j=0; j<3; j++) {
|
||||
Base::Vector3f clP1((*myProj)(clFac._aclPoints[j]));
|
||||
Base::Vector3f clP2((*myProj)(clFac._aclPoints[(j+1)%3]));
|
||||
Base::Vector2D P1(clP1.x, clP1.y);
|
||||
Base::Vector2D P2(clP2.x, clP2.y);
|
||||
clFacLine.clV1 = P1;
|
||||
clFacLine.clV2 = P2;
|
||||
|
||||
if (clPolyLine.Intersect(clFacLine, S)) {
|
||||
bool bPushBack=true;
|
||||
float fP1P2 = (P2-P1).Length();
|
||||
float fSP1 = (P1-S).Length();
|
||||
float fSP2 = (P2-S).Length();
|
||||
|
||||
float fP3P4 = (P4-P3).Length();
|
||||
float fSP3 = (P3-S).Length();
|
||||
float fSP4 = (P4-S).Length();
|
||||
// compute propotion of length
|
||||
float l = fSP1 / fP1P2;
|
||||
float m = fSP2 / fP1P2;
|
||||
|
||||
float r = fSP3 / fP3P4;
|
||||
float s = fSP4 / fP3P4;
|
||||
|
||||
// is intersection point convex combination?
|
||||
if ((fabs(l+m-1.0f) < 0.001) && (fabs(r+s-1.0f) < 0.001)) {
|
||||
#ifdef _DEBUG
|
||||
Base::Vector3f clIntersection(m*clFac._aclPoints[j]+l*clFac._aclPoints[(j+1)%3]);
|
||||
#endif
|
||||
iIntersections++;
|
||||
|
||||
// only two intersections points per edge allowed
|
||||
if (j == 0) {
|
||||
if (iIntsctWithEdge0 == 2)
|
||||
bPushBack = false;
|
||||
else
|
||||
iIntsctWithEdge0++;
|
||||
}
|
||||
else if (j == 1) {
|
||||
if (iIntsctWithEdge1 == 2)
|
||||
bPushBack = false;
|
||||
else
|
||||
iIntsctWithEdge1++;
|
||||
}
|
||||
else {
|
||||
if (iIntsctWithEdge2 == 2)
|
||||
bPushBack = false;
|
||||
else
|
||||
iIntsctWithEdge2++;
|
||||
}
|
||||
|
||||
if (bPushBack == true)
|
||||
raclPoints.push_back(m*clFac._aclPoints[j]+l*clFac._aclPoints[(j+1)%3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for rotating facet later
|
||||
if (iIntsctWithEdge0 == 0)
|
||||
iSide = 0;
|
||||
else if (iIntsctWithEdge1 == 0)
|
||||
iSide = 1;
|
||||
else if (iIntsctWithEdge2 == 0)
|
||||
iSide = 2;
|
||||
|
||||
// further check (for rotating the facet)
|
||||
if (iIntsctWithEdge0 == 0 && iIntsctWithEdge1 == 0)
|
||||
iSide = 1;
|
||||
else if (iIntsctWithEdge0 == 0 && iIntsctWithEdge2 == 0)
|
||||
iSide = 0;
|
||||
else if (iIntsctWithEdge1 == 0 && iIntsctWithEdge2 == 0)
|
||||
iSide = 2;
|
||||
|
||||
// and last another check
|
||||
if (iIntsctWithEdge0 * iIntsctWithEdge1 * iIntsctWithEdge2 > 0) {
|
||||
if (iIntsctWithEdge0 == 2)
|
||||
iSide = 2;
|
||||
else if (iIntsctWithEdge1 == 2)
|
||||
iSide = 0;
|
||||
else if (iIntsctWithEdge2 == 2)
|
||||
iSide = 1;
|
||||
}
|
||||
|
||||
return iIntersections > 0;
|
||||
}
|
||||
|
||||
void MeshTrimming::AdjustFacet(MeshFacet& facet, int iInd)
|
||||
{
|
||||
unsigned long tmp;
|
||||
|
||||
if (iInd == 1) {
|
||||
tmp = facet._aulPoints[0];
|
||||
facet._aulPoints[0] = facet._aulPoints[1];
|
||||
facet._aulPoints[1] = facet._aulPoints[2];
|
||||
facet._aulPoints[2] = tmp;
|
||||
tmp = facet._aulNeighbours[0];
|
||||
facet._aulNeighbours[0] = facet._aulNeighbours[1];
|
||||
facet._aulNeighbours[1] = facet._aulNeighbours[2];
|
||||
facet._aulNeighbours[2] = tmp;
|
||||
}
|
||||
else if (iInd == 2) {
|
||||
tmp = facet._aulPoints[0];
|
||||
facet._aulPoints[0] = facet._aulPoints[2];
|
||||
facet._aulPoints[2] = facet._aulPoints[1];
|
||||
facet._aulPoints[1] = tmp;
|
||||
tmp = facet._aulNeighbours[0];
|
||||
facet._aulNeighbours[0] = facet._aulNeighbours[2];
|
||||
facet._aulNeighbours[2] = facet._aulNeighbours[1];
|
||||
facet._aulNeighbours[1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
bool MeshTrimming::CreateFacets(unsigned long ulFacetPos, int iSide, const std::vector<Base::Vector3f>& raclPoints, std::vector<MeshGeomFacet>& aclNewFacets)
|
||||
{
|
||||
MeshGeomFacet clFac;
|
||||
|
||||
// no valid triangulation possible
|
||||
if (iSide == -1)
|
||||
return false;
|
||||
|
||||
// two points found
|
||||
if (raclPoints.size() == 2) {
|
||||
MeshFacet& facet = myMesh._aclFacetArray[ulFacetPos];
|
||||
AdjustFacet(facet, iSide);
|
||||
Base::Vector3f clP1(raclPoints[0]), clP2(raclPoints[1]);
|
||||
|
||||
if (iSide == 1) {
|
||||
// swap P1 and P2
|
||||
clP1 = raclPoints[1];
|
||||
clP2 = raclPoints[0];
|
||||
}
|
||||
|
||||
// check which facets can be inserted
|
||||
int iCtPts=0;
|
||||
Base::Vector3f clFacPnt;
|
||||
Base::Vector2D clProjPnt;
|
||||
for (int i=0; i<3; i++) {
|
||||
clFacPnt = (*myProj)(myMesh._aclPointArray[facet._aulPoints[i]]);
|
||||
clProjPnt = Base::Vector2D(clFacPnt.x, clFacPnt.y);
|
||||
if (myPoly.Contains(clProjPnt) == myInner)
|
||||
++iCtPts;
|
||||
}
|
||||
|
||||
if (iCtPts == 2) {
|
||||
// erstes Dreieck
|
||||
clFac._aclPoints[0] = clP1;
|
||||
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[2]];
|
||||
clFac._aclPoints[2] = clP2;
|
||||
aclNewFacets.push_back(clFac);
|
||||
}
|
||||
else if (iCtPts == 1) {
|
||||
// erstes Dreieck
|
||||
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
|
||||
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
|
||||
clFac._aclPoints[2] = clP2;
|
||||
aclNewFacets.push_back(clFac);
|
||||
// zweites Dreieck
|
||||
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[1]];
|
||||
clFac._aclPoints[1] = clP1;
|
||||
clFac._aclPoints[2] = clP2;
|
||||
aclNewFacets.push_back(clFac);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
// four points found
|
||||
else if (raclPoints.size() == 4) {
|
||||
MeshFacet& facet = myMesh._aclFacetArray[ulFacetPos];
|
||||
AdjustFacet(facet, iSide);
|
||||
|
||||
MeshFacet clOrg(myMesh._aclFacetArray[ulFacetPos]);
|
||||
clFac = myMesh.GetFacet(ulFacetPos);
|
||||
// intersection points
|
||||
Base::Vector3f clP1(raclPoints[0]), clP2(raclPoints[1]), clP3(raclPoints[2]), clP4(raclPoints[3]);
|
||||
|
||||
// check which facets can be inserted
|
||||
int iCtPts=0;
|
||||
Base::Vector3f clFacPnt;
|
||||
Base::Vector2D clProjPnt;
|
||||
for (int i=0; i<3; i++) {
|
||||
clFacPnt = (*myProj)(myMesh._aclPointArray[facet._aulPoints[i]]);
|
||||
clProjPnt = Base::Vector2D(clFacPnt.x, clFacPnt.y);
|
||||
if (myPoly.Contains(clProjPnt) == myInner)
|
||||
++iCtPts;
|
||||
}
|
||||
|
||||
// sort the intersection points in a certain order
|
||||
if (iCtPts == 0 || iCtPts == 3) {
|
||||
if (iSide == 1) {
|
||||
// swap the points
|
||||
clP1 = clP2;
|
||||
clP2 = raclPoints[0];
|
||||
clP3 = clP4;
|
||||
clP4 = raclPoints[2];
|
||||
}
|
||||
|
||||
if ((clP1-clFac._aclPoints[1]).Length() > (clP3-clFac._aclPoints[1]).Length()) {
|
||||
// swap P1 and P3
|
||||
Base::Vector3f tmp(clP1);
|
||||
clP1 = clP3;
|
||||
clP3 = tmp;
|
||||
}
|
||||
if ((clP2-clFac._aclPoints[0]).Length() > (clP4-clFac._aclPoints[0]).Length()) {
|
||||
// swap P2 and P4
|
||||
Base::Vector3f tmp(clP2);
|
||||
clP2 = clP4;
|
||||
clP4 = tmp;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (iSide == 0) {
|
||||
Base::Vector3f clNormal(clFac.GetNormal());
|
||||
MeshGeomFacet clTmpFac; clTmpFac._aclPoints[0] = clFac._aclPoints[1];
|
||||
clTmpFac._aclPoints[1] = clP2; clTmpFac._aclPoints[2] = clP1;
|
||||
if (clTmpFac.GetNormal() * clNormal > 0) {
|
||||
Base::Vector3f tmp(clP1);
|
||||
clP1 = clP2;
|
||||
clP2 = tmp;
|
||||
}
|
||||
else {
|
||||
Base::Vector3f tmp(clP1);
|
||||
clP1 = clP4;
|
||||
clP4 = clP2;
|
||||
clP2 = clP3;
|
||||
clP3 = tmp;
|
||||
}
|
||||
}
|
||||
else if (iSide == 1) {
|
||||
if ((clP2-clFac._aclPoints[1]).Length() > (clP4-clFac._aclPoints[1]).Length()) {
|
||||
Base::Vector3f tmp(clP1);
|
||||
clP1 = clP4;
|
||||
clP4 = tmp;
|
||||
tmp = clP2;
|
||||
clP2 = clP3;
|
||||
clP3 = tmp;
|
||||
}
|
||||
else {
|
||||
Base::Vector3f tmp(clP1);
|
||||
clP1 = clP2;
|
||||
clP2 = tmp;
|
||||
tmp = clP3;
|
||||
clP3 = clP4;
|
||||
clP4 = tmp;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((clP1-clFac._aclPoints[1]).Length() > (clP3-clFac._aclPoints[1]).Length()) {
|
||||
Base::Vector3f tmp(clP1);
|
||||
clP1 = clP3;
|
||||
clP3 = tmp;
|
||||
tmp = clP2;
|
||||
clP2 = clP4;
|
||||
clP4 = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now create the new facets
|
||||
if (iCtPts == 0) {
|
||||
// insert first facet
|
||||
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
|
||||
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
|
||||
clFac._aclPoints[2] = clP1;
|
||||
aclNewFacets.push_back(clFac);
|
||||
// insert second facet
|
||||
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
|
||||
clFac._aclPoints[1] = clP1;
|
||||
clFac._aclPoints[2] = clP2;
|
||||
aclNewFacets.push_back(clFac);
|
||||
// finally insert third facet
|
||||
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[2]];
|
||||
clFac._aclPoints[1] = clP4;
|
||||
clFac._aclPoints[2] = clP3;
|
||||
aclNewFacets.push_back(clFac);
|
||||
}
|
||||
else if (iCtPts == 1) {
|
||||
// insert first facet
|
||||
clFac._aclPoints[0] = clP1;
|
||||
clFac._aclPoints[1] = clP2;
|
||||
clFac._aclPoints[2] = myMesh._aclPointArray[facet._aulPoints[1]];
|
||||
aclNewFacets.push_back(clFac);
|
||||
// finally insert second facet
|
||||
clFac._aclPoints[0] = clP4;
|
||||
clFac._aclPoints[1] = clP3;
|
||||
clFac._aclPoints[2] = myMesh._aclPointArray[facet._aulPoints[2]];
|
||||
aclNewFacets.push_back(clFac);
|
||||
}
|
||||
else if (iCtPts == 2) {
|
||||
// insert first facet
|
||||
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
|
||||
clFac._aclPoints[1] = clP2;
|
||||
clFac._aclPoints[2] = clP4;
|
||||
aclNewFacets.push_back(clFac);
|
||||
// insert second facet
|
||||
clFac._aclPoints[0] = clP1;
|
||||
clFac._aclPoints[1] = clP4;
|
||||
clFac._aclPoints[2] = clP2;
|
||||
aclNewFacets.push_back(clFac);
|
||||
// finally insert third facet
|
||||
clFac._aclPoints[0] = clP1;
|
||||
clFac._aclPoints[1] = clP3;
|
||||
clFac._aclPoints[2] = clP4;
|
||||
aclNewFacets.push_back(clFac);
|
||||
}
|
||||
else {
|
||||
// insert first facet
|
||||
clFac._aclPoints[0] = clP1;
|
||||
clFac._aclPoints[1] = clP3;
|
||||
clFac._aclPoints[2] = clP4;
|
||||
aclNewFacets.push_back(clFac);
|
||||
// finally insert second facet
|
||||
clFac._aclPoints[0] = clP1;
|
||||
clFac._aclPoints[1] = clP4;
|
||||
clFac._aclPoints[2] = clP2;
|
||||
aclNewFacets.push_back(clFac);
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MeshTrimming::CreateFacets(unsigned long ulFacetPos, int iSide, const std::vector<Base::Vector3f>& raclPoints, Base::Vector3f& clP3,
|
||||
std::vector<MeshGeomFacet>& aclNewFacets)
|
||||
{
|
||||
// no valid triangulation possible
|
||||
if (iSide == -1 || raclPoints.size() < 2)
|
||||
return false;
|
||||
|
||||
Base::Vector3f clP1(raclPoints[0]);
|
||||
Base::Vector3f clP2(raclPoints[1]);
|
||||
|
||||
MeshFacet& facet = myMesh._aclFacetArray[ulFacetPos];
|
||||
AdjustFacet(facet, iSide);
|
||||
|
||||
MeshGeomFacet clFac;
|
||||
|
||||
Base::Vector3f pnt = myMesh._aclPointArray[facet._aulPoints[1]];
|
||||
Base::Vector3f dir = myMesh._aclPointArray[facet._aulPoints[2]] -
|
||||
myMesh._aclPointArray[facet._aulPoints[1]];
|
||||
|
||||
float fDistEdgeP1 = clP1.DistanceToLineSegment(
|
||||
myMesh._aclPointArray[facet._aulPoints[1]],
|
||||
myMesh._aclPointArray[facet._aulPoints[2]]).Length();
|
||||
float fDistEdgeP2 = clP2.DistanceToLineSegment(
|
||||
myMesh._aclPointArray[facet._aulPoints[1]],
|
||||
myMesh._aclPointArray[facet._aulPoints[2]]).Length();
|
||||
|
||||
// swap P1 and P2
|
||||
if (fDistEdgeP2 < fDistEdgeP1) {
|
||||
Base::Vector3f tmp(clP1);
|
||||
clP1 = clP2;
|
||||
clP2 = tmp;
|
||||
}
|
||||
|
||||
// check which facets should be inserted
|
||||
int iCtPts=0;
|
||||
Base::Vector3f clFacPnt;
|
||||
Base::Vector2D clProjPnt;
|
||||
for (int i=0; i<3; i++) {
|
||||
clFacPnt = (*myProj)(myMesh._aclPointArray[facet._aulPoints[i]]);
|
||||
clProjPnt = Base::Vector2D(clFacPnt.x, clFacPnt.y);
|
||||
if (myPoly.Contains(clProjPnt) == myInner)
|
||||
++iCtPts;
|
||||
}
|
||||
if (iCtPts == 3) {
|
||||
clFac = myMesh.GetFacet(ulFacetPos);
|
||||
if ((clP1-clFac._aclPoints[1]).Length() > (clP2-clFac._aclPoints[1]).Length()) {
|
||||
Base::Vector3f tmp(clP1);
|
||||
clP1 = clP2;
|
||||
clP2 = tmp;
|
||||
}
|
||||
// only one facet
|
||||
clFac._aclPoints[0] = clP1;
|
||||
clFac._aclPoints[1] = clP2;
|
||||
clFac._aclPoints[2] = clP3;
|
||||
aclNewFacets.push_back(clFac);
|
||||
}
|
||||
else if (iCtPts == 2) {
|
||||
// first facet
|
||||
clFac._aclPoints[0] = clP1;
|
||||
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[2]];
|
||||
clFac._aclPoints[2] = clP3;
|
||||
aclNewFacets.push_back(clFac);
|
||||
// second facet
|
||||
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[2]];
|
||||
clFac._aclPoints[1] = clP2;
|
||||
clFac._aclPoints[2] = clP3;
|
||||
aclNewFacets.push_back(clFac);
|
||||
}
|
||||
else if (iCtPts == 1) {
|
||||
// first facet
|
||||
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
|
||||
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
|
||||
clFac._aclPoints[2] = clP3;
|
||||
aclNewFacets.push_back(clFac);
|
||||
// second facet
|
||||
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[1]];
|
||||
clFac._aclPoints[1] = clP1;
|
||||
clFac._aclPoints[2] = clP3;
|
||||
aclNewFacets.push_back(clFac);
|
||||
// third facet
|
||||
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
|
||||
clFac._aclPoints[1] = clP3;
|
||||
clFac._aclPoints[2] = clP2;
|
||||
aclNewFacets.push_back(clFac);
|
||||
}
|
||||
else if (iCtPts == 0) {
|
||||
clFac = myMesh.GetFacet(ulFacetPos);
|
||||
if ((clP1-clFac._aclPoints[1]).Length() > (clP2-clFac._aclPoints[1]).Length()) {
|
||||
Base::Vector3f tmp(clP1);
|
||||
clP1 = clP2;
|
||||
clP2 = tmp;
|
||||
}
|
||||
// first facet
|
||||
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[2]];
|
||||
clFac._aclPoints[1] = clP3;
|
||||
clFac._aclPoints[2] = clP2;
|
||||
aclNewFacets.push_back(clFac);
|
||||
// second facet
|
||||
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[2]];
|
||||
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[0]];
|
||||
clFac._aclPoints[2] = clP3;
|
||||
aclNewFacets.push_back(clFac);
|
||||
// third facet
|
||||
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
|
||||
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
|
||||
clFac._aclPoints[2] = clP3;
|
||||
aclNewFacets.push_back(clFac);
|
||||
// and finally fourth facet
|
||||
clFac._aclPoints[0] = clP3;
|
||||
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
|
||||
clFac._aclPoints[2] = clP1;
|
||||
aclNewFacets.push_back(clFac);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MeshTrimming::TrimFacets(const std::vector<unsigned long>& raulFacets, std::vector<MeshGeomFacet>& aclNewFacets)
|
||||
{
|
||||
Base::Vector3f clP;
|
||||
std::vector<Base::Vector3f> clIntsct;
|
||||
int iSide;
|
||||
|
||||
Base::SequencerLauncher seq("trimming facets...", raulFacets.size());
|
||||
for (std::vector<unsigned long>::const_iterator it=raulFacets.begin(); it!=raulFacets.end(); it++) {
|
||||
clIntsct.clear();
|
||||
if (IsPolygonPointInFacet(*it, clP) == false) {
|
||||
// facet must be trimmed
|
||||
if (PolygonContainsCompleteFacet(myInner, *it) == false) {
|
||||
// generate new facets
|
||||
if (GetIntersectionPointsOfPolygonAndFacet(*it, iSide, clIntsct))
|
||||
CreateFacets(*it, iSide, clIntsct, myTriangles);
|
||||
}
|
||||
}
|
||||
// facet contains a polygon point
|
||||
else {
|
||||
// generate new facets
|
||||
if (GetIntersectionPointsOfPolygonAndFacet(*it, iSide, clIntsct))
|
||||
CreateFacets(*it, iSide, clIntsct, clP, myTriangles);
|
||||
}
|
||||
seq.next();
|
||||
}
|
||||
|
||||
aclNewFacets = myTriangles;
|
||||
}
|
||||
108
src/Mod/Mesh/App/Core/Trim.h
Normal file
108
src/Mod/Mesh/App/Core/Trim.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2012 Imetric 3D GmbH *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MESHTRIM_H
|
||||
#define MESHTRIM_H
|
||||
|
||||
#include <Mod/Mesh/App/Core/Elements.h>
|
||||
#include <Mod/Mesh/App/Core/MeshKernel.h>
|
||||
#include <Base/Tools2D.h>
|
||||
#include <Base/ViewProj.h>
|
||||
|
||||
namespace MeshCore {
|
||||
|
||||
/**
|
||||
* Checks the facets in 2D and then trim them in 3D
|
||||
*/
|
||||
class MeshExport MeshTrimming
|
||||
{
|
||||
public:
|
||||
enum TMode {INNER, OUTER};
|
||||
|
||||
public:
|
||||
MeshTrimming(MeshKernel& mesh, const Base::ViewProjMethod* pclProj, const Base::Polygon2D& rclPoly);
|
||||
~MeshTrimming();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Checks all facets for intersection with the polygon and writes all touched facets into the vector
|
||||
*/
|
||||
void CheckFacets(const MeshFacetGrid& rclGrid, std::vector<unsigned long>& raulFacets) const;
|
||||
|
||||
/**
|
||||
* The facets from raulFacets will be trimmed or deleted and aclNewFacets gives the new generated facets
|
||||
*/
|
||||
void TrimFacets(const std::vector<unsigned long>& raulFacets, std::vector<MeshGeomFacet>& aclNewFacets);
|
||||
|
||||
/**
|
||||
* Setter: Trimm INNER or OUTER
|
||||
*/
|
||||
void SetInnerOrOuter(TMode tMode);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Checks if the polygon cuts the facet
|
||||
*/
|
||||
bool HasIntersection(const MeshGeomFacet& rclFacet) const;
|
||||
|
||||
/**
|
||||
* Checks if a facet lies totally within a polygon
|
||||
*/
|
||||
bool PolygonContainsCompleteFacet(bool bInner, unsigned long ulIndex) const;
|
||||
|
||||
/**
|
||||
* Creates new facets from edge points of the facet
|
||||
*/
|
||||
bool CreateFacets(unsigned long ulFacetPos, int iSide, const std::vector<Base::Vector3f>& raclPoints,
|
||||
std::vector<MeshGeomFacet>& aclNewFacets);
|
||||
|
||||
/**
|
||||
* Creates new facets from edge points of the facet and a point inside the facet
|
||||
*/
|
||||
bool CreateFacets(unsigned long ulFacetPos, int iSide, const std::vector<Base::Vector3f>& raclPoints,
|
||||
Base::Vector3f& clP3, std::vector<MeshGeomFacet>& aclNewFacets);
|
||||
|
||||
/**
|
||||
* Checks if a polygon point lies within a facet
|
||||
*/
|
||||
bool IsPolygonPointInFacet(unsigned long ulIndex, Base::Vector3f& clPoint);
|
||||
|
||||
/**
|
||||
* Calculates the two intersection points between polygonline and facet in 2D
|
||||
* and project the points back into 3D (not very exactly)
|
||||
*/
|
||||
bool GetIntersectionPointsOfPolygonAndFacet(unsigned long ulIndex, int& iSide,
|
||||
std::vector<Base::Vector3f>& raclPoints) const;
|
||||
|
||||
void AdjustFacet(MeshFacet& facet, int iInd);
|
||||
|
||||
private:
|
||||
MeshKernel& myMesh;
|
||||
bool myInner;
|
||||
std::vector<MeshGeomFacet> myTriangles;
|
||||
const Base::ViewProjMethod* myProj;
|
||||
const Base::Polygon2D& myPoly;
|
||||
};
|
||||
|
||||
} //namespace MeshCore
|
||||
|
||||
#endif //MESHTRIM_H
|
||||
@@ -49,6 +49,8 @@ libMesh_la_SOURCES=\
|
||||
Core/tritritest.h \
|
||||
Core/Triangulation.cpp \
|
||||
Core/Triangulation.h \
|
||||
Core/Trim.cpp \
|
||||
Core/Trim.h \
|
||||
Core/Tools.cpp \
|
||||
Core/Tools.h \
|
||||
Core/TopoAlgorithm.cpp \
|
||||
|
||||
@@ -743,6 +743,61 @@ bool CmdMeshPolyCut::isActive(void)
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
DEF_STD_CMD_A(CmdMeshPolyTrim);
|
||||
|
||||
CmdMeshPolyTrim::CmdMeshPolyTrim()
|
||||
: Command("Mesh_PolyTrim")
|
||||
{
|
||||
sAppModule = "Mesh";
|
||||
sGroup = QT_TR_NOOP("Mesh");
|
||||
sMenuText = QT_TR_NOOP("Trim mesh");
|
||||
sToolTipText = QT_TR_NOOP("Trims a mesh with a picked polygon");
|
||||
sWhatsThis = "Mesh_PolyTrim";
|
||||
sStatusTip = QT_TR_NOOP("Trims a mesh with a picked polygon");
|
||||
}
|
||||
|
||||
void CmdMeshPolyTrim::activated(int iMsg)
|
||||
{
|
||||
std::vector<App::DocumentObject*> docObj = Gui::Selection().getObjectsOfType(Mesh::Feature::getClassTypeId());
|
||||
for (std::vector<App::DocumentObject*>::iterator it = docObj.begin(); it != docObj.end(); ++it) {
|
||||
if (it == docObj.begin()) {
|
||||
Gui::Document* doc = getActiveGuiDocument();
|
||||
Gui::MDIView* view = doc->getActiveView();
|
||||
if (view->getTypeId().isDerivedFrom(Gui::View3DInventor::getClassTypeId())) {
|
||||
Gui::View3DInventorViewer* viewer = ((Gui::View3DInventor*)view)->getViewer();
|
||||
viewer->setEditing(true);
|
||||
viewer->startSelection(Gui::View3DInventorViewer::Clip);
|
||||
viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(),
|
||||
MeshGui::ViewProviderMeshFaceSet::trimMeshCallback);
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Gui::ViewProvider* pVP = getActiveGuiDocument()->getViewProvider(*it);
|
||||
if (pVP->isVisible())
|
||||
pVP->startEditing();
|
||||
}
|
||||
}
|
||||
|
||||
bool CmdMeshPolyTrim::isActive(void)
|
||||
{
|
||||
// Check for the selected mesh feature (all Mesh types)
|
||||
if (getSelection().countObjectsOfType(Mesh::Feature::getClassTypeId()) == 0)
|
||||
return false;
|
||||
|
||||
Gui::MDIView* view = Gui::getMainWindow()->activeWindow();
|
||||
if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) {
|
||||
Gui::View3DInventorViewer* viewer = static_cast<Gui::View3DInventor*>(view)->getViewer();
|
||||
return !viewer->isEditing();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
DEF_STD_CMD_A(CmdMeshPolySplit);
|
||||
|
||||
CmdMeshPolySplit::CmdMeshPolySplit()
|
||||
@@ -1328,6 +1383,7 @@ void CreateMeshCommands(void)
|
||||
rcCmdMgr.addCommand(new CmdMeshAddFacet());
|
||||
rcCmdMgr.addCommand(new CmdMeshPolyCut());
|
||||
rcCmdMgr.addCommand(new CmdMeshPolySplit());
|
||||
rcCmdMgr.addCommand(new CmdMeshPolyTrim());
|
||||
rcCmdMgr.addCommand(new CmdMeshToolMesh());
|
||||
rcCmdMgr.addCommand(new CmdMeshTransform());
|
||||
rcCmdMgr.addCommand(new CmdMeshEvaluation());
|
||||
|
||||
@@ -77,6 +77,8 @@
|
||||
#include <Mod/Mesh/App/Core/Iterator.h>
|
||||
#include <Mod/Mesh/App/Core/MeshIO.h>
|
||||
#include <Mod/Mesh/App/Core/Triangulation.h>
|
||||
#include <Mod/Mesh/App/Core/Trim.h>
|
||||
#include <Mod/Mesh/App/Core/TopoAlgorithm.h>
|
||||
#include <Mod/Mesh/App/Core/Visitor.h>
|
||||
#include <Mod/Mesh/App/Mesh.h>
|
||||
#include <Mod/Mesh/App/MeshFeature.h>
|
||||
@@ -616,6 +618,41 @@ void ViewProviderMesh::clipMeshCallback(void * ud, SoEventCallback * n)
|
||||
}
|
||||
}
|
||||
|
||||
void ViewProviderMesh::trimMeshCallback(void * ud, SoEventCallback * n)
|
||||
{
|
||||
// show the wait cursor because this could take quite some time
|
||||
Gui::WaitCursor wc;
|
||||
|
||||
// When this callback function is invoked we must in either case leave the edit mode
|
||||
Gui::View3DInventorViewer* view = reinterpret_cast<Gui::View3DInventorViewer*>(n->getUserData());
|
||||
view->setEditing(false);
|
||||
view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), trimMeshCallback,ud);
|
||||
n->setHandled();
|
||||
|
||||
SbBool clip_inner;
|
||||
std::vector<SbVec2f> clPoly = view->getGLPolygon(&clip_inner);
|
||||
if (clPoly.size() < 3)
|
||||
return;
|
||||
if (clPoly.front() != clPoly.back())
|
||||
clPoly.push_back(clPoly.front());
|
||||
|
||||
std::vector<Gui::ViewProvider*> views = view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId());
|
||||
if (!views.empty()) {
|
||||
Gui::Application::Instance->activeDocument()->openCommand("Cut");
|
||||
for (std::vector<Gui::ViewProvider*>::iterator it = views.begin(); it != views.end(); ++it) {
|
||||
ViewProviderMesh* that = static_cast<ViewProviderMesh*>(*it);
|
||||
if (that->getEditingMode() > -1) {
|
||||
that->finishEditing();
|
||||
that->trimMesh(clPoly, *view, clip_inner);
|
||||
}
|
||||
}
|
||||
|
||||
Gui::Application::Instance->activeDocument()->commitCommand();
|
||||
|
||||
view->render();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewProviderMesh::partMeshCallback(void * ud, SoEventCallback * cb)
|
||||
{
|
||||
// show the wait cursor because this could take quite some time
|
||||
@@ -1017,6 +1054,65 @@ void ViewProviderMesh::cutMesh(const std::vector<SbVec2f>& picked,
|
||||
pcObject->purgeTouched();
|
||||
}
|
||||
|
||||
void ViewProviderMesh::trimMesh(const std::vector<SbVec2f>& polygon,
|
||||
Gui::View3DInventorViewer& viewer, SbBool inner)
|
||||
{
|
||||
// get the drawing plane
|
||||
SbViewVolume vol = viewer.getCamera()->getViewVolume();
|
||||
SbPlane drawPlane = vol.getPlane(viewer.getCamera()->focalDistance.getValue());
|
||||
|
||||
std::vector<unsigned long> indices;
|
||||
Mesh::MeshObject* mesh = static_cast<Mesh::Feature*>(pcObject)->Mesh.startEditing();
|
||||
MeshCore::MeshFacetGrid meshGrid(mesh->getKernel());
|
||||
MeshCore::MeshAlgorithm meshAlg(mesh->getKernel());
|
||||
|
||||
#if 0
|
||||
for (std::vector<SbVec2f>::const_iterator it = polygon.begin(); it != polygon.end(); ++it) {
|
||||
// the following element
|
||||
std::vector<SbVec2f>::const_iterator nt = it + 1;
|
||||
if (nt == polygon.end())
|
||||
break;
|
||||
else if (*it == *nt)
|
||||
continue; // two adjacent vertices are equal
|
||||
|
||||
SbVec3f p1,p2;
|
||||
SbLine l1, l2;
|
||||
vol.projectPointToLine(*it, l1);
|
||||
drawPlane.intersect(l1, p1);
|
||||
vol.projectPointToLine(*nt, l2);
|
||||
drawPlane.intersect(l2, p2);
|
||||
|
||||
SbPlane plane(l1.getPosition(), l2.getPosition(),
|
||||
l1.getPosition()+l1.getDirection());
|
||||
const SbVec3f& n = plane.getNormal();
|
||||
float d = plane.getDistanceFromOrigin();
|
||||
meshAlg.GetFacetsFromPlane(meshGrid,
|
||||
Base::Vector3f(n[0],n[1],n[2]), d,
|
||||
Base::Vector3f(p1[0],p1[1],p1[2]),
|
||||
Base::Vector3f(p2[0],p2[1],p2[2]), indices);
|
||||
}
|
||||
#endif
|
||||
|
||||
Gui::ViewVolumeProjection proj(vol);
|
||||
Base::Polygon2D polygon2d;
|
||||
for (std::vector<SbVec2f>::const_iterator it = polygon.begin(); it != polygon.end(); ++it)
|
||||
polygon2d.Add(Base::Vector2D((*it)[0],(*it)[1]));
|
||||
MeshCore::MeshTrimming trim(mesh->getKernel(), &proj, polygon2d);
|
||||
std::vector<unsigned long> check;
|
||||
std::vector<MeshCore::MeshGeomFacet> triangle;
|
||||
trim.SetInnerOrOuter(inner ? MeshCore::MeshTrimming::INNER : MeshCore::MeshTrimming::OUTER);
|
||||
trim.CheckFacets(meshGrid, check);
|
||||
trim.TrimFacets(check, triangle);
|
||||
mesh->deleteFacets(check);
|
||||
if (!triangle.empty()) {
|
||||
mesh->getKernel().AddFacets(triangle);
|
||||
}
|
||||
//Remove the facets from the mesh and open a transaction object for the undo/redo stuff
|
||||
//mesh->deleteFacets(indices);
|
||||
static_cast<Mesh::Feature*>(pcObject)->Mesh.finishEditing();
|
||||
pcObject->purgeTouched();
|
||||
}
|
||||
|
||||
void ViewProviderMesh::splitMesh(const MeshCore::MeshKernel& toolMesh, const Base::Vector3f& normal, SbBool clip_inner)
|
||||
{
|
||||
// Get the attached mesh property
|
||||
|
||||
@@ -153,6 +153,7 @@ protected:
|
||||
virtual void showOpenEdges(bool);
|
||||
void setOpenEdgeColorFrom(const App::Color& col);
|
||||
virtual void cutMesh(const std::vector<SbVec2f>& picked, Gui::View3DInventorViewer &Viewer, SbBool inner);
|
||||
virtual void trimMesh(const std::vector<SbVec2f>& picked, Gui::View3DInventorViewer &Viewer, SbBool inner);
|
||||
virtual void splitMesh(const MeshCore::MeshKernel& toolMesh, const Base::Vector3f& normal, SbBool inner);
|
||||
virtual void segmentMesh(const MeshCore::MeshKernel& toolMesh, const Base::Vector3f& normal, SbBool inner);
|
||||
virtual void faceInfo(unsigned long facet);
|
||||
@@ -169,6 +170,7 @@ public:
|
||||
static void fillHoleCallback(void * ud, SoEventCallback * n);
|
||||
static void markPartCallback(void * ud, SoEventCallback * n);
|
||||
static void clipMeshCallback(void * ud, SoEventCallback * n);
|
||||
static void trimMeshCallback(void * ud, SoEventCallback * n);
|
||||
static void partMeshCallback(void * ud, SoEventCallback * n);
|
||||
static void segmMeshCallback(void * ud, SoEventCallback * n);
|
||||
static void selectGLCallback(void * ud, SoEventCallback * n);
|
||||
|
||||
@@ -87,7 +87,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
<< "Mesh_FillupHoles" << "Mesh_FillInteractiveHole" << "Mesh_RemoveComponents"
|
||||
<< "Mesh_RemoveCompByHand" << "Mesh_AddFacet" << "Mesh_Smoothing" << "Separator"
|
||||
<< "Mesh_BuildRegularSolid" << boolean << "Separator" << "Mesh_PolySelect" << "Mesh_PolyCut"
|
||||
<< "Mesh_PolySplit" << "Mesh_PolySegm" << /*"Mesh_ToolMesh" <<*/ "Mesh_VertexCurvature";
|
||||
<< "Mesh_PolySplit" << "Mesh_PolySegm" << "Mesh_PolyTrim" << "Mesh_VertexCurvature";
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user