Skip to content

Commit

Permalink
Path.Area: improved section tolerance
Browse files Browse the repository at this point in the history
Previously, a small offset in the same direction of section is added to
the section height to avoid tagent plane cut. Now we'll retry by adding
offset in the oppsite direction if the first attemp fails.
  • Loading branch information
realthunder authored and wwmayer committed Mar 23, 2017
1 parent 796a8f3 commit b49a8ec
Showing 1 changed file with 64 additions and 42 deletions.
106 changes: 64 additions & 42 deletions src/Mod/Path/App/Area.cpp
Expand Up @@ -565,6 +565,7 @@ std::vector<shared_ptr<Area> > Area::makeSections(
yMin<<','<<yMax<<"), Z("<<zMin<<','<<zMax<<')');

std::vector<double> heights;
double tolerance = 0.0;
if(_heights.empty()) {
double z;
double d = fabs(myParams.Stepdown);
Expand Down Expand Up @@ -593,7 +594,7 @@ std::vector<shared_ptr<Area> > Area::makeSections(
z = zMax;
else if(z < zMin)
z = zMin;
double dz,tolerance;
double dz;
if(myParams.Stepdown>0.0) {
dz = z - zMin;
tolerance = myParams.SectionTolerance;
Expand Down Expand Up @@ -660,56 +661,77 @@ std::vector<shared_ptr<Area> > Area::makeSections(

std::vector<shared_ptr<Area> > sections;
sections.reserve(heights.size());
tolerance *= 2.0;
bool can_retry = fabs(tolerance)>Precision::Confusion();
for(double z : heights) {
gp_Pln pln(gp_Pnt(0,0,z),gp_Dir(0,0,1));
Standard_Real a,b,c,d;
pln.Coefficients(a,b,c,d);
BRepLib_MakeFace mkFace(pln,xMin,xMax,yMin,yMax);
const TopoDS_Shape &face = mkFace.Face();

shared_ptr<Area> area(new Area(&myParams));
area->setPlane(face);
for(const Shape &s : myShapes) {
BRep_Builder builder;
TopoDS_Compound comp;
builder.MakeCompound(comp);
for(TopExp_Explorer it(s.shape.Moved(loc), TopAbs_SOLID); it.More(); it.Next()) {
Part::CrossSection section(a,b,c,it.Current());
std::list<TopoDS_Wire> wires = section.slice(-d);
if(wires.empty()) {
AREA_LOG("Section returns no wires");
continue;
bool retried = !can_retry;
while(true) {
gp_Pln pln(gp_Pnt(0,0,z),gp_Dir(0,0,1));
Standard_Real a,b,c,d;
pln.Coefficients(a,b,c,d);
BRepLib_MakeFace mkFace(pln,xMin,xMax,yMin,yMax);
const TopoDS_Shape &face = mkFace.Face();

shared_ptr<Area> area(new Area(&myParams));
area->setPlane(face);
for(auto it=myShapes.begin();it!=myShapes.end();++it) {
const auto &s = *it;
BRep_Builder builder;
TopoDS_Compound comp;
builder.MakeCompound(comp);
for(TopExp_Explorer xp(s.shape.Moved(loc), TopAbs_SOLID); xp.More(); xp.Next()) {
Part::CrossSection section(a,b,c,xp.Current());
std::list<TopoDS_Wire> wires = section.slice(-d);
if(wires.empty()) {
AREA_LOG("Section returns no wires");
continue;
}
Part::FaceMakerBullseye mkFace;
mkFace.setPlane(pln);
for(const TopoDS_Wire &wire : wires)
mkFace.addWire(wire);
try {
mkFace.Build();
if (mkFace.Shape().IsNull())
AREA_WARN("FaceMakerBullseye return null shape on section");
else {
builder.Add(comp,mkFace.Shape());
continue;
}
}catch (Base::Exception &e){
AREA_WARN("FaceMakerBullseye failed on section: " << e.what());
}
for(const TopoDS_Wire &wire : wires)
builder.Add(comp,wire);
}

Part::FaceMakerBullseye mkFace;
mkFace.setPlane(pln);
for(const TopoDS_Wire &wire : wires)
mkFace.addWire(wire);
try {
mkFace.Build();
if (mkFace.Shape().IsNull())
AREA_WARN("FaceMakerBullseye return null shape on section");
else {
builder.Add(comp,mkFace.Shape());
continue;
// Make sure the compound has at least one edge
TopExp_Explorer xp(comp,TopAbs_EDGE);
if(xp.More()) {
area->add(comp,s.op);
}else if(area->myShapes.empty()){
auto itNext = it;
if(++itNext != myShapes.end() &&
(itNext->op==OperationIntersection ||
itNext->op==OperationDifference))
{
break;
}
}catch (Base::Exception &e){
AREA_WARN("FaceMakerBullseye failed on section: " << e.what());
}
for(const TopoDS_Wire &wire : wires)
builder.Add(comp,wire);
}

// Make sure the compound has at least one edge
for(TopExp_Explorer it(comp,TopAbs_EDGE);it.More();) {
area->add(comp,s.op);
if(area->myShapes.size()){
sections.push_back(area);
break;
}
if(retried) {
AREA_WARN("Discard empty section");
break;
}else{
AREA_TRACE("retry section " <<z<<"->"<<z+tolerance);
z += tolerance;
retried = true;
}
}
if(area->myShapes.size())
sections.push_back(area);
else
AREA_WARN("Discard empty section");
TIME_PRINT(t1,"makeSection " << z);
}
TIME_PRINT(t,"makeSection count: " << sections.size()<<", total");
Expand Down

0 comments on commit b49a8ec

Please sign in to comment.