Path.Area: work around for OCCT discretization bug

See code comments for more details.
This commit is contained in:
Zheng, Lei
2018-03-19 11:00:31 +08:00
committed by wmayer
parent e1cb69540e
commit 42294442f5

View File

@@ -308,6 +308,67 @@ int Area::addShape(CArea &area, const TopoDS_Shape &shape, const gp_Trsf *trsf,
return skipped;
}
static std::vector<gp_Pnt> discretize(const TopoDS_Edge &edge, double deflection) {
std::vector<gp_Pnt> ret;
BRepAdaptor_Curve curve(edge);
Standard_Real efirst,elast,first,last;
efirst = curve.FirstParameter();
elast = curve.LastParameter();
bool reversed = (edge.Orientation()==TopAbs_REVERSED);
// push the first point
ret.push_back(curve.Value(reversed?elast:efirst));
Handle(Geom_Curve) c = BRep_Tool::Curve(edge, first, last);
first = c->FirstParameter();
last = c->LastParameter();
if(efirst>elast) {
if(first<last)
std::swap(first,last);
}else if(first>last)
std::swap(first,last);
// NOTE: OCCT QuasiUniformDeflection has a bug cause it to return only
// partial points for some (BSpline) curve if we pass in the edge trimmed
// first and last parameters. Passing the original curve first and last
// paramaters works fine. The following algorithm uses the original curve
// parameters, and skip those out of range. The algorithm shall work the
// same for any other discetization algorithm, althgouth it seems only
// QuasiUniformDeflection has this bug.
GCPnts_QuasiUniformDeflection discretizer(curve, deflection, first, last);
if (!discretizer.IsDone ())
Standard_Failure::Raise("Curve discretization failed");
if(discretizer.NbPoints () > 1) {
int nbPoints = discretizer.NbPoints ();
//strangly OCC discretizer points are one-based, not zero-based, why?
if(reversed) {
for (int i=nbPoints-1; i>=1; --i) {
auto param = discretizer.Parameter(i);
if(first<last) {
if(param<efirst || param>elast)
continue;
}else if(param>efirst || param<elast)
continue;
ret.push_back(discretizer.Value(i));
}
}else{
for (int i=2; i<=nbPoints; i++) {
auto param = discretizer.Parameter(i);
if(first<last) {
if(param<efirst || param>elast)
continue;
}else if(param>efirst || param<elast)
continue;
ret.push_back(discretizer.Value(i));
}
}
}
// push the last point
ret.push_back(curve.Value(reversed?efirst:elast));
return ret;
}
void Area::addWire(CArea &area, const TopoDS_Wire& wire,
const gp_Trsf *trsf, double deflection, bool to_edges)
{
@@ -371,33 +432,15 @@ void Area::addWire(CArea &area, const TopoDS_Wire& wire,
break;
} default: {
// Discretize all other type of curves
GCPnts_QuasiUniformDeflection discretizer(curve, deflection,
curve.FirstParameter(), curve.LastParameter());
if (discretizer.IsDone () && discretizer.NbPoints () > 1) {
int nbPoints = discretizer.NbPoints ();
//strangly OCC discretizer points are one-based, not zero-based, why?
if(reversed) {
for (int i=nbPoints-1; i>=1; --i) {
gp_Pnt pt = discretizer.Value (i);
ccurve.append(CVertex(Point(pt.X(),pt.Y())));
if(to_edges) {
area.append(ccurve);
ccurve.m_vertices.pop_front();
}
}
}else{
for (int i=2; i<=nbPoints; i++) {
gp_Pnt pt = discretizer.Value (i);
ccurve.append(CVertex(Point(pt.X(),pt.Y())));
if(to_edges) {
area.append(ccurve);
ccurve.m_vertices.pop_front();
}
}
const auto &pts = discretize(edge,deflection);
for(size_t i=1;i<pts.size();++i) {
auto &pt = pts[i];
ccurve.append(CVertex(Point(pt.X(),pt.Y())));
if(to_edges) {
area.append(ccurve);
ccurve.m_vertices.pop_front();
}
}else
Standard_Failure::Raise("Curve discretization failed");
}
}}
}
if(!to_edges) {
@@ -3316,26 +3359,12 @@ void Area::toPath(Toolpath &path, const std::list<TopoDS_Shape> &shapes,
}
/* FALLTHRU */
default: {
// Discretize all other type of curves
GCPnts_QuasiUniformDeflection discretizer(curve, deflection,
curve.FirstParameter(), curve.LastParameter());
if (discretizer.IsDone () && discretizer.NbPoints () > 1) {
int nbPoints = discretizer.NbPoints ();
if(reversed) {
for (int i=nbPoints-1; i>=1; --i) {
gp_Pnt pt = discretizer.Value (i);
addG1(verbose,path,plast,pt,nf,cur_f);
plast = pt;
}
}else{
for (int i=2; i<=nbPoints; i++) {
gp_Pnt pt = discretizer.Value (i);
addG1(verbose,path,plast,pt,nf,cur_f);
plast = pt;
}
}
}else
Standard_Failure::Raise("Curve discretization failed");
const auto &pts = discretize(edge,deflection);
for(size_t i=1;i<pts.size();++i) {
auto &pt = pts[i];
addG1(verbose,path,plast,pt,nf,cur_f);
plast = pt;
}
}}
}
}