+ updated refinement algorithm (tanderson69)
git-svn-id: https://free-cad.svn.sourceforge.net/svnroot/free-cad/trunk@5329 e8eeb9e2-ec13-0410-a4a9-efa5cf37419d
This commit is contained in:
parent
4cb8920c15
commit
81906b86a4
|
@ -283,7 +283,7 @@ The parameter is a list of shapes.</UserDocu>
|
|||
<UserDocu>Checks whether a point is inside or outside a given shape</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="removeSplitter">
|
||||
<Methode Name="removeSplitter" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Removes redundant edges from the B-REP model</UserDocu>
|
||||
</Documentation>
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
#include <gp_Cylinder.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <ShapeAnalysis_Edge.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepLib_MakeWire.hxx>
|
||||
#include <BRepLib_FuseEdges.hxx>
|
||||
|
@ -42,91 +42,17 @@
|
|||
#include <BRepBuilderAPI_MakeSolid.hxx>
|
||||
#include <ShapeBuild_ReShape.hxx>
|
||||
#include <ShapeFix_Face.hxx>
|
||||
#include <BRepClass_FaceClassifier.hxx>
|
||||
#include <TopTools_ListOfShape.hxx>
|
||||
#include <TopTools_MapOfShape.hxx>
|
||||
#include <TopTools_ListIteratorOfListOfShape.hxx>
|
||||
#include <BRepTools.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <BRepBndLib.hxx>
|
||||
#include "modelRefine.h"
|
||||
|
||||
using namespace ModelRefine;
|
||||
|
||||
|
||||
|
||||
//this following struct and function was stole from freecad AppPartPy.cpp
|
||||
namespace ModelRefine {
|
||||
struct EdgePoints {
|
||||
gp_Pnt v1, v2;
|
||||
TopoDS_Edge edge;
|
||||
};
|
||||
static std::list<TopoDS_Edge> sort_Edges(double tol3d, const std::vector<TopoDS_Edge>& edges)
|
||||
{
|
||||
tol3d = tol3d * tol3d;
|
||||
std::list<EdgePoints> edge_points;
|
||||
TopExp_Explorer xp;
|
||||
for (std::vector<TopoDS_Edge>::const_iterator it = edges.begin(); it != edges.end(); ++it) {
|
||||
EdgePoints ep;
|
||||
xp.Init(*it,TopAbs_VERTEX);
|
||||
ep.v1 = BRep_Tool::Pnt(TopoDS::Vertex(xp.Current()));
|
||||
xp.Next();
|
||||
ep.v2 = BRep_Tool::Pnt(TopoDS::Vertex(xp.Current()));
|
||||
ep.edge = *it;
|
||||
edge_points.push_back(ep);
|
||||
}
|
||||
|
||||
if (edge_points.empty())
|
||||
return std::list<TopoDS_Edge>();
|
||||
|
||||
std::list<TopoDS_Edge> sorted;
|
||||
gp_Pnt first, last;
|
||||
first = edge_points.front().v1;
|
||||
last = edge_points.front().v2;
|
||||
|
||||
sorted.push_back(edge_points.front().edge);
|
||||
edge_points.erase(edge_points.begin());
|
||||
|
||||
while (!edge_points.empty()) {
|
||||
// search for adjacent edge
|
||||
std::list<EdgePoints>::iterator pEI;
|
||||
for (pEI = edge_points.begin(); pEI != edge_points.end(); ++pEI) {
|
||||
if (pEI->v1.SquareDistance(last) <= tol3d) {
|
||||
last = pEI->v2;
|
||||
sorted.push_back(pEI->edge);
|
||||
edge_points.erase(pEI);
|
||||
break;
|
||||
}
|
||||
else if (pEI->v2.SquareDistance(first) <= tol3d) {
|
||||
first = pEI->v1;
|
||||
sorted.push_front(pEI->edge);
|
||||
edge_points.erase(pEI);
|
||||
break;
|
||||
}
|
||||
else if (pEI->v2.SquareDistance(last) <= tol3d) {
|
||||
last = pEI->v1;
|
||||
sorted.push_back(pEI->edge);
|
||||
edge_points.erase(pEI);
|
||||
break;
|
||||
}
|
||||
else if (pEI->v1.SquareDistance(first) <= tol3d) {
|
||||
first = pEI->v2;
|
||||
sorted.push_front(pEI->edge);
|
||||
edge_points.erase(pEI);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pEI == edge_points.end()) || (last.SquareDistance(first) <= tol3d)) {
|
||||
// no adjacent edge found or polyline is closed
|
||||
return sorted;
|
||||
}
|
||||
}
|
||||
return sorted;
|
||||
}
|
||||
}
|
||||
//end stolen freecad.
|
||||
|
||||
|
||||
void ModelRefine::getFaceEdges(const TopoDS_Face &face, EdgeVectorType &edges)
|
||||
{
|
||||
TopExp_Explorer it;
|
||||
|
@ -175,79 +101,64 @@ TopoDS_Shell ModelRefine::removeFaces(const TopoDS_Shell &shell, const FaceVecto
|
|||
return TopoDS::Shell(rebuilder.Apply(shell));
|
||||
}
|
||||
|
||||
namespace ModelRefine
|
||||
{
|
||||
class WireSort
|
||||
{
|
||||
public:
|
||||
bool operator() (const TopoDS_Wire& wire1, const TopoDS_Wire& wire2)
|
||||
{
|
||||
Bnd_Box box1, box2;
|
||||
BRepBndLib::Add(wire1, box1);
|
||||
BRepBndLib::Add(wire2, box2);
|
||||
return box2.SquareExtent() < box1.SquareExtent();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void BoundaryEdgeSplitter::split(const EdgeVectorType &edgesIn)
|
||||
{
|
||||
buildMap(edgesIn);
|
||||
EdgeVectorType::const_iterator workIt;
|
||||
for (workIt = edgesIn.begin(); workIt != edgesIn.end(); ++workIt)
|
||||
std::list<TopoDS_Edge> edges;
|
||||
std::copy(edgesIn.begin(), edgesIn.end(), back_inserter(edges));
|
||||
while(!edges.empty())
|
||||
{
|
||||
TopoDS_Edge current = *workIt;
|
||||
|
||||
if (processed.Contains(*workIt))
|
||||
TopoDS_Vertex destination = TopExp::FirstVertex(edges.front(), Standard_True);
|
||||
TopoDS_Vertex lastVertex = TopExp::LastVertex(edges.front(), Standard_True);
|
||||
EdgeVectorType boundary;
|
||||
boundary.push_back(edges.front());
|
||||
edges.pop_front();
|
||||
//single edge closed check.
|
||||
if (destination.IsSame(lastVertex))
|
||||
{
|
||||
groupedEdges.push_back(boundary);
|
||||
continue;
|
||||
}
|
||||
|
||||
EdgeVectorType temp;
|
||||
temp.reserve(edgesIn.size() + 1);
|
||||
temp.push_back(current);
|
||||
//recursive call
|
||||
splitRecursive(temp, edgesIn);
|
||||
groupedEdges.push_back(temp);
|
||||
}
|
||||
}
|
||||
|
||||
void BoundaryEdgeSplitter::splitRecursive(EdgeVectorType &tempEdges, const EdgeVectorType &workEdges)
|
||||
{
|
||||
EdgeVectorType::iterator tempIt;
|
||||
EdgeVectorType::const_iterator workIt;
|
||||
for (tempIt = tempEdges.begin(); tempIt != tempEdges.end(); ++tempIt)
|
||||
{
|
||||
for (workIt = workEdges.begin(); workIt != workEdges.end(); ++workIt)
|
||||
bool closedSignal(false);
|
||||
std::list<TopoDS_Edge>::iterator it;
|
||||
for (it = edges.begin(); it != edges.end();)
|
||||
{
|
||||
if ((*tempIt).IsSame(*workIt))
|
||||
continue;
|
||||
if (processed.Contains(*workIt))
|
||||
continue;
|
||||
if (edgeTest(*tempIt, *workIt))
|
||||
TopoDS_Vertex currentVertex = TopExp::FirstVertex(*it, Standard_True);
|
||||
if (lastVertex.IsSame(currentVertex))
|
||||
{
|
||||
tempEdges.push_back(*workIt);
|
||||
processed.Add(*workIt);
|
||||
splitRecursive(tempEdges, workEdges);
|
||||
boundary.push_back(*it);
|
||||
lastVertex = TopExp::LastVertex(*it, Standard_True);
|
||||
edges.erase(it);
|
||||
it = edges.begin();
|
||||
if (lastVertex.IsSame(destination))
|
||||
{
|
||||
closedSignal = true;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
if (closedSignal)
|
||||
groupedEdges.push_back(boundary);
|
||||
}
|
||||
}
|
||||
|
||||
void BoundaryEdgeSplitter::buildMap(const EdgeVectorType &edgesIn)
|
||||
{
|
||||
EdgeVectorType::const_iterator vit;
|
||||
for (vit = edgesIn.begin(); vit != edgesIn.end(); ++vit)
|
||||
{
|
||||
TopTools_ListOfShape shapeList;
|
||||
TopExp_Explorer it;
|
||||
for (it.Init(*vit, TopAbs_VERTEX); it.More(); it.Next())
|
||||
shapeList.Append(it.Current());
|
||||
edgeVertexMap.Bind((*vit), shapeList);
|
||||
}
|
||||
}
|
||||
|
||||
bool BoundaryEdgeSplitter::edgeTest(const TopoDS_Edge &edgeOne, const TopoDS_Edge &edgeTwo)
|
||||
{
|
||||
const TopTools_ListOfShape &verticesOne = edgeVertexMap.Find(edgeOne);
|
||||
const TopTools_ListOfShape &verticesTwo = edgeVertexMap.Find(edgeTwo);
|
||||
TopTools_ListIteratorOfListOfShape itOne;
|
||||
TopTools_ListIteratorOfListOfShape itTwo;
|
||||
|
||||
for (itOne.Initialize(verticesOne); itOne.More(); itOne.Next())
|
||||
{
|
||||
for (itTwo.Initialize(verticesTwo); itTwo.More(); itTwo.Next())
|
||||
{
|
||||
if (itOne.Value().IsSame(itTwo.Value()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FaceTypeSplitter::addShell(const TopoDS_Shell &shellIn)
|
||||
|
@ -460,65 +371,43 @@ TopoDS_Face FaceTypedPlane::buildFace(const FaceVectorType &faces) const
|
|||
BoundaryEdgeSplitter bSplitter;
|
||||
bSplitter.split(bEdges);
|
||||
|
||||
|
||||
//parallel vectors. Topo* doesn't have less than. map wouldn't work.
|
||||
FaceVectorType facesParallel;
|
||||
std::vector<TopoDS_Wire> wiresParallel;
|
||||
std::vector<TopoDS_Wire> wires;
|
||||
|
||||
std::vector<EdgeVectorType> splitEdges = bSplitter.getGroupedEdges();
|
||||
if (splitEdges.empty())
|
||||
return TopoDS_Face();
|
||||
std::vector<EdgeVectorType>::iterator splitIt;
|
||||
for (splitIt = splitEdges.begin(); splitIt != splitEdges.end(); ++splitIt)
|
||||
{
|
||||
std::list<TopoDS_Edge> sortedEdges;
|
||||
sortedEdges = sort_Edges(Precision::Confusion(), *splitIt);
|
||||
|
||||
BRepLib_MakeWire wireMaker;
|
||||
std::list<TopoDS_Edge>::iterator sortedIt;
|
||||
for (sortedIt = sortedEdges.begin(); sortedIt != sortedEdges.end(); ++sortedIt)
|
||||
wireMaker.Add(*sortedIt);
|
||||
EdgeVectorType::iterator it;
|
||||
for (it = (*splitIt).begin(); it != (*splitIt).end(); ++it)
|
||||
wireMaker.Add(*it);
|
||||
TopoDS_Wire currentWire = wireMaker.Wire();
|
||||
|
||||
TopoDS_Face currentFace = BRepBuilderAPI_MakeFace(currentWire, Standard_True);
|
||||
|
||||
facesParallel.push_back(currentFace);
|
||||
wiresParallel.push_back(currentWire);
|
||||
wires.push_back(currentWire);
|
||||
}
|
||||
if (facesParallel.size() < 1)//shouldn't be here.
|
||||
return BRepBuilderAPI_MakeFace();//will cause exception.
|
||||
if (facesParallel.size() == 1)
|
||||
return (facesParallel.front());
|
||||
|
||||
TopoDS_Face current;
|
||||
current = facesParallel.at(0);
|
||||
//now we have more than one wire.
|
||||
//there has to be a better way to determin which face is inside other
|
||||
//without have to build all the faces.
|
||||
for(size_t index(1); index<facesParallel.size(); ++index)
|
||||
std::sort(wires.begin(), wires.end(), ModelRefine::WireSort());
|
||||
|
||||
TopoDS_Face current = BRepLib_MakeFace(wires.at(0));
|
||||
if (wires.size() > 1)
|
||||
{
|
||||
//this algorithm assumes that the boundaries don't intersect.
|
||||
gp_Pnt point;
|
||||
Handle(Geom_Surface) surface = BRep_Tool::Surface(facesParallel.at(index));
|
||||
surface->D0(0.5, 0.5, point);
|
||||
BRepClass_FaceClassifier faceTest(current, point, Precision::Confusion());
|
||||
if (faceTest.State() == TopAbs_EXTERNAL)
|
||||
current = facesParallel.at(index);
|
||||
ShapeFix_Face faceFix(current);
|
||||
faceFix.SetContext(new ShapeBuild_ReShape());
|
||||
for (size_t index(1); index<wires.size(); ++index)
|
||||
faceFix.Add(wires.at(index));
|
||||
Standard_Boolean signal = faceFix.Perform();
|
||||
if (signal > ShapeExtend_DONE)
|
||||
return TopoDS_Face();
|
||||
faceFix.FixOrientation();
|
||||
signal = faceFix.Perform();
|
||||
if (signal > ShapeExtend_DONE)
|
||||
return TopoDS_Face();
|
||||
current = faceFix.Face();
|
||||
}
|
||||
|
||||
ShapeFix_Face faceFix(current);
|
||||
faceFix.SetContext(new ShapeBuild_ReShape());
|
||||
for (size_t index(0); index<facesParallel.size(); ++index)
|
||||
{
|
||||
if (current.IsSame(facesParallel.at(index)))
|
||||
continue;
|
||||
faceFix.Add(wiresParallel.at(index));
|
||||
}
|
||||
faceFix.FixOrientation();
|
||||
Standard_Boolean signal = faceFix.Perform();
|
||||
|
||||
if (signal > ShapeExtend_DONE)
|
||||
return TopoDS_Face();
|
||||
else
|
||||
return faceFix.Face();
|
||||
BRepLib_FuseEdges edgeFuse(current, Standard_True);
|
||||
return TopoDS::Face(edgeFuse.Shape());
|
||||
}
|
||||
|
||||
FaceTypedPlane& ModelRefine::getPlaneObject()
|
||||
|
@ -655,9 +544,6 @@ bool FaceUniter::process()
|
|||
for(sewIt = facesToSew.begin(); sewIt != facesToSew.end(); ++sewIt)
|
||||
builder.Add(workShell, *sewIt);
|
||||
}
|
||||
|
||||
BRepLib_FuseEdges edgeFuse(workShell, true);
|
||||
workShell = TopoDS::Shell(edgeFuse.Shape());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -141,12 +141,7 @@ namespace ModelRefine
|
|||
const std::vector<EdgeVectorType>& getGroupedEdges(){return groupedEdges;}
|
||||
|
||||
private:
|
||||
void splitRecursive(EdgeVectorType &tempEdges, const EdgeVectorType &workEdges);
|
||||
void buildMap(const EdgeVectorType &edgesIn);
|
||||
bool edgeTest(const TopoDS_Edge &edgeOne, const TopoDS_Edge &edgeTwo);
|
||||
TopTools_MapOfShape processed;
|
||||
std::vector<EdgeVectorType> groupedEdges;
|
||||
TopTools_DataMapOfShapeListOfShape edgeVertexMap;
|
||||
};
|
||||
|
||||
class FaceUniter
|
||||
|
|
|
@ -222,16 +222,21 @@ void CmdPartRefineShape::activated(int iMsg)
|
|||
std::vector<App::DocumentObject*> objs = Gui::Selection().getObjectsOfType(partid);
|
||||
openCommand("Refine shape");
|
||||
for (std::vector<App::DocumentObject*>::iterator it = objs.begin(); it != objs.end(); ++it) {
|
||||
doCommand(Doc,"App.ActiveDocument.addObject('Part::Feature','%s').Shape="
|
||||
"App.ActiveDocument.%s.Shape.removeSplitter()\n"
|
||||
"App.ActiveDocument.ActiveObject.Label="
|
||||
"App.ActiveDocument.%s.Label\n",
|
||||
(*it)->getNameInDocument(),
|
||||
(*it)->getNameInDocument(),
|
||||
(*it)->getNameInDocument());
|
||||
copyVisual("ActiveObject", "ShapeColor", (*it)->getNameInDocument());
|
||||
copyVisual("ActiveObject", "LineColor", (*it)->getNameInDocument());
|
||||
copyVisual("ActiveObject", "PointColor", (*it)->getNameInDocument());
|
||||
try {
|
||||
doCommand(Doc,"App.ActiveDocument.addObject('Part::Feature','%s').Shape="
|
||||
"App.ActiveDocument.%s.Shape.removeSplitter()\n"
|
||||
"App.ActiveDocument.ActiveObject.Label="
|
||||
"App.ActiveDocument.%s.Label\n",
|
||||
(*it)->getNameInDocument(),
|
||||
(*it)->getNameInDocument(),
|
||||
(*it)->getNameInDocument());
|
||||
copyVisual("ActiveObject", "ShapeColor", (*it)->getNameInDocument());
|
||||
copyVisual("ActiveObject", "LineColor", (*it)->getNameInDocument());
|
||||
copyVisual("ActiveObject", "PointColor", (*it)->getNameInDocument());
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
Base::Console().Warning("%s: %s\n", (*it)->Label.getValue(), e.what());
|
||||
}
|
||||
}
|
||||
commitCommand();
|
||||
updateActive();
|
||||
|
|
Loading…
Reference in New Issue
Block a user