Part.Area: fixed sortWires3D

This commit is contained in:
Zheng, Lei 2017-02-01 02:02:07 +08:00
parent a6380f64a5
commit 6f862fe4a1
2 changed files with 76 additions and 25 deletions

View File

@ -729,7 +729,10 @@ void Area::build() {
return; return;
} }
#ifdef AREA_TRACE_ENABLE
TIME_INIT(t); TIME_INIT(t);
#endif
getPlane(); getPlane();
try { try {
@ -806,7 +809,7 @@ void Area::build() {
myArea = std::move(area.myArea); myArea = std::move(area.myArea);
} }
TIME_PRINT(t,"prepare"); TIME_TRACE(t,"prepare");
}catch(...) { }catch(...) {
clean(); clean();
@ -1283,7 +1286,7 @@ TopoDS_Shape Area::toShape(const CArea &area, bool fill, const gp_Trsf *trsf) {
} }
struct WireInfo { struct WireInfo {
TopoDS_Shape wire; TopoDS_Wire wire;
gp_Pnt pend; gp_Pnt pend;
gp_Pnt pstart; gp_Pnt pstart;
}; };
@ -1296,15 +1299,14 @@ struct GetWires {
void operator()(const TopoDS_Shape &shape, int type) { void operator()(const TopoDS_Shape &shape, int type) {
WireInfo info; WireInfo info;
if(type == TopAbs_WIRE) if(type == TopAbs_WIRE)
info.wire = shape; info.wire = TopoDS::Wire(shape);
else else
info.wire = BRepBuilderAPI_MakeWire(TopoDS::Edge(shape)).Wire(); info.wire = BRepBuilderAPI_MakeWire(TopoDS::Edge(shape)).Wire();
BRepTools_WireExplorer xp(TopoDS::Wire(shape)); BRepTools_WireExplorer xp(info.wire);
info.pstart = BRep_Tool::Pnt(xp.CurrentVertex()); info.pstart = BRep_Tool::Pnt(xp.CurrentVertex());
for(;xp.More();xp.Next()); for(;xp.More();xp.Next());
info.pend = BRep_Tool::Pnt(xp.CurrentVertex()); info.pend = BRep_Tool::Pnt(xp.CurrentVertex());
info.wire = shape;
wires.push_back(info); wires.push_back(info);
} }
}; };
@ -1349,18 +1351,16 @@ struct ShapeInfo{
BRepExtrema_DistShapeShape extss(v,wire); BRepExtrema_DistShapeShape extss(v,wire);
if(extss.IsDone() && extss.NbSolution()) { if(extss.IsDone() && extss.NbSolution()) {
d = extss.Value(); d = extss.Value();
p = extss.PointOnShape2(0); p = extss.PointOnShape2(1);
support = extss.SupportOnShape2(0); support = extss.SupportOnShape2(1);
support_edge = extss.SupportTypeShape2(0)==BRepExtrema_IsOnEdge; support_edge = extss.SupportTypeShape2(1)==BRepExtrema_IsOnEdge;
done = true; done = true;
}else }else
AREA_WARN("BRepExtrema_DistShapeShape failed"); AREA_WARN("BRepExtrema_DistShapeShape failed");
} }
if(!done){ if(!done){
double d1 = p.Distance(it->pstart); double d1 = pt.Distance(it->pstart);
double d2 = p.Distance(it->pend); double d2 = pt.Distance(it->pend);
AREA_TRACE("start "<<AREA_PT(it->pstart)<<", " << d1 <<
AREA_PT(it->pend)<<", " <<d2);
if(d1<d2) { if(d1<d2) {
d = d1; d = d1;
p = it->pstart; p = it->pstart;
@ -1388,24 +1388,31 @@ struct ShapeInfo{
//Assumes nearest() has been called. Rebased the best wire //Assumes nearest() has been called. Rebased the best wire
//to begin with the best point. Currently only works with closed wire //to begin with the best point. Currently only works with closed wire
TopoDS_Shape rebaseWire(gp_Pnt &pend) { TopoDS_Shape rebaseWire(gp_Pnt &pend, double min_dist) {
AREA_TRACE("rebase wire");
BRepBuilderAPI_MakeWire mkWire; BRepBuilderAPI_MakeWire mkWire;
TopoDS_Shape estart; TopoDS_Shape estart;
TopoDS_Edge eend; TopoDS_Edge eend;
if(min_dist < Precision::Confusion())
min_dist = Precision::Confusion();
for(int state=0;state<3;++state) { for(int state=0;state<3;++state) {
BRepTools_WireExplorer xp(TopoDS::Wire(myBestWire->wire)); BRepTools_WireExplorer xp(TopoDS::Wire(myBestWire->wire));
pend = BRep_Tool::Pnt(xp.CurrentVertex()); pend = BRep_Tool::Pnt(xp.CurrentVertex());
//checking the case of bestpoint == wire start //checking the case of bestpoint == wire start
if(state==0 && !mySupportEdge && pend.Distance(myBestPt)<Precision::Confusion()) { if(state==0 && !mySupportEdge && pend.Distance(myBestPt)<Precision::Confusion()) {
AREA_TRACE("keep start");
pend = myBestWire->pend; pend = myBestWire->pend;
return myBestWire->wire; return myBestWire->wire;
} }
gp_Pnt pt; gp_Pnt pt;
for(;xp.More();xp.Next(),pend=pt) { for(;xp.More();xp.Next(),pend=pt) {
//state==2 means we are in second pass. estart marks the new start of the wire //state==2 means we are in second pass. estart marks the new start of the wire.
if(state==2 && estart.IsSame(xp.Current())) //so seeing estart means we're done
if(state==2 && estart.IsEqual(xp.Current()))
break; break;
BRepAdaptor_Curve curve(xp.Current()); BRepAdaptor_Curve curve(xp.Current());
@ -1421,12 +1428,50 @@ struct ShapeInfo{
if(mySupportEdge) { if(mySupportEdge) {
//if best point is on some edge, break the edge in half //if best point is on some edge, break the edge in half
if(xp.Current().IsEqual(mySupport)) { if(xp.Current().IsEqual(mySupport)) {
estart = mySupport; double d1 = pend.Distance(myBestPt);
state = 1; double d2 = pt.Distance(myBestPt);
eend = BRepBuilderAPI_MakeEdge(curve.Curve().Curve(), pend, myBestPt);
mkWire.Add(BRepBuilderAPI_MakeEdge(curve.Curve().Curve(), myBestPt, pt)); if(d1>min_dist && d2>min_dist) {
BRepBuilderAPI_MakeEdge mkEdge1,mkEdge2;
if(reversed) {
mkEdge1.Init(curve.Curve().Curve(), myBestPt, myBestPt);
mkEdge2.Init(curve.Curve().Curve(), pt, myBestPt);
}else{
mkEdge1.Init(curve.Curve().Curve(), pend, myBestPt);
mkEdge2.Init(curve.Curve().Curve(), myBestPt, pt);
}
if(mkEdge1.IsDone() && mkEdge2.IsDone()) {
if(reversed) {
eend = TopoDS::Edge(mkEdge1.Edge().Reversed());
mkWire.Add(TopoDS::Edge(mkEdge2.Edge().Reversed()));
}else{
eend = mkEdge1.Edge();
mkWire.Add(mkEdge2.Edge());
}
estart = mySupport;
state = 1;
AREA_TRACE("edge broken "<<AREA_PT(pend)<<", " << AREA_PT(myBestPt)
<< ", " << AREA_PT(pt) << ", " << d1 << ", " << d2);
continue;
}
AREA_WARN("edge break failed "<<AREA_PT(pend)<<", " << AREA_PT(myBestPt)
<< ", " << AREA_PT(pt) << ", " << d1 << ", " << d2);
}
if(d1<d2) {
AREA_TRACE("break edge->start");
estart = xp.Current();
state = 1;
mkWire.Add(xp.Current());
}else{
AREA_TRACE("break edge->end");
mySupportEdge = false;
myBestPt = pt;
continue;
}
} }
}else if(myBestPt.Distance(pend)<Precision::Confusion()){ }else if(myBestPt.Distance(pend)<Precision::Confusion()){
AREA_TRACE("break vertex");
//if best point is on some vertex //if best point is on some vertex
estart = xp.Current(); estart = xp.Current();
state = 1; state = 1;
@ -1443,13 +1488,14 @@ struct ShapeInfo{
return myBestWire->wire; return myBestWire->wire;
} }
std::list<TopoDS_Shape> sortWires(gp_Pnt &pend) { std::list<TopoDS_Shape> sortWires3D(gp_Pnt &pend,double min_dist) {
std::list<TopoDS_Shape> wires; std::list<TopoDS_Shape> wires;
while(true) { while(true) {
AREA_TRACE("3D sort pt " << AREA_PT(myBestPt)); AREA_TRACE("3D sort pt " << AREA_PT(myBestPt));
if(myRebase) { if(myRebase) {
AREA_TRACE("3D sort rebase"); AREA_TRACE("3D sort rebase");
wires.push_back(rebaseWire(pend)); pend = myBestPt;
wires.push_back(rebaseWire(pend,min_dist));
}else if(!myStart){ }else if(!myStart){
AREA_TRACE("3D sort reverse"); AREA_TRACE("3D sort reverse");
wires.push_back(myBestWire->wire.Reversed()); wires.push_back(myBestWire->wire.Reversed());
@ -1619,7 +1665,7 @@ std::list<TopoDS_Shape> Area::sortWires(const std::list<TopoDS_Shape> &shapes,
0,-1,&pstart,&pend, PARAM_FIELDS(PARAM_FARG,AREA_PARAMS_SORT))); 0,-1,&pstart,&pend, PARAM_FIELDS(PARAM_FARG,AREA_PARAMS_SORT)));
AREA_TIME_2D5; AREA_TIME_2D5;
}else{ }else{
wires.splice(wires.end(),best_it->sortWires(pend)); wires.splice(wires.end(),best_it->sortWires3D(pend,min_dist));
AREA_TIME_3D; AREA_TIME_3D;
} }
pstart = pend; pstart = pend;

View File

@ -51,7 +51,7 @@
#define AREA_PT(_pt) '('<<(_pt).X()<<", " << (_pt).Y()<<", " << (_pt).Z()<<')' #define AREA_PT(_pt) '('<<(_pt).X()<<", " << (_pt).Y()<<", " << (_pt).Z()<<')'
#define AREA_PT2(_pt) '('<<(_pt).x<<", " << (_pt).y<<')' #define AREA_PT2(_pt) '('<<(_pt).x<<", " << (_pt).y<<')'
#ifdef AREA_TRACE_ENABLE #ifdef AREA_TRACE_ENABLE
# define AREA_TRACE AREA_LOG # define AREA_TRACE(_msg) AREA_LOG('('<<__LINE__<<"): " <<_msg)
#else #else
# define AREA_TRACE(...) do{}while(0) # define AREA_TRACE(...) do{}while(0)
#endif #endif
@ -69,12 +69,17 @@
#define TIME_INIT2(_t1,_t2) TIME_INIT(_t1),_t2=_t1 #define TIME_INIT2(_t1,_t2) TIME_INIT(_t1),_t2=_t1
#define TIME_INIT3(_t1,_t2,_t3) TIME_INIT(_t1),_t2=_t1,_t3=_t1 #define TIME_INIT3(_t1,_t2,_t3) TIME_INIT(_t1),_t2=_t1,_t3=_t1
#define DURATION_PRINT(_d,_msg) \ #define _DURATION_PRINT(_l,_d,_msg) \
AREA_LOG(_msg<< " time: " << _d.count()<<'s'); AREA_##_l(_msg<< " time: " << _d.count()<<'s');
#define DURATION_PRINT(_d,_msg) _DURATION_PRINT(LOG,_d,_msg)
#define TIME_PRINT(_t,_msg) \ #define TIME_PRINT(_t,_msg) \
DURATION_PRINT(Path::getDuration(_t),_msg); DURATION_PRINT(Path::getDuration(_t),_msg);
#define TIME_TRACE(_t,_msg) \
_DURATION_PRINT(TRACE,Path::getDuration(_t),_msg);
#define DURATION_INIT(_d) \ #define DURATION_INIT(_d) \
std::chrono::TIME_UNIT _d(0) std::chrono::TIME_UNIT _d(0)