// File: TopOpeBRepTool_REGUW.cxx // Created: Tue Dec 8 18:07:24 1998 // Author: Xuan PHAM PHU // #include #include #include #include #include #include #include #include #include #include #ifdef DRAW #include #endif #define FORWARD (1) #define REVERSED (2) #define INTERNAL (3) #define EXTERNAL (4) #define CLOSING (5) #define M_FORWARD(ori) (ori == TopAbs_FORWARD) #define M_REVERSED(ori) (ori == TopAbs_REVERSED) #define M_INTERNAL(ori) (ori == TopAbs_INTERNAL) #define M_EXTERNAL(ori) (ori == TopAbs_EXTERNAL) #ifdef DEB Standard_IMPORT Standard_Boolean TopOpeBRepTool_GettraceREGUFA(); static TopTools_IndexedMapOfShape STATIC_mapf, STATIC_mapw, STATIC_mapv; static TopTools_IndexedMapOfOrientedShape STATIC_mapeds; void FUN_tro(const Standard_Integer i) { if (i==1) cout<<"FORWARD"; else if (i==2) cout<<"REVERSED"; else if (i==3) cout<<"INTERNAL"; else if (i==4) cout<<"EXTERNAL"; else if (i==5) cout<<"CLOSING"; } Standard_EXPORT Standard_Integer FUN_adds(const TopoDS_Shape& s) { TopAbs_ShapeEnum typ = s.ShapeType(); TCollection_AsciiString aa; Standard_Integer is = 0; if (typ == TopAbs_VERTEX) {aa = TCollection_AsciiString("v"); is = STATIC_mapv.Add(s);} if (typ == TopAbs_EDGE) {aa = TCollection_AsciiString("e"); is = STATIC_mapeds.Add(s);} if (typ == TopAbs_WIRE) {aa = TCollection_AsciiString("wi"); is = STATIC_mapw.Add(s);} if (typ == TopAbs_FACE) {aa = TCollection_AsciiString("f"); is = STATIC_mapf.Add(s);} #ifdef DRAW Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA(); if (trc) FUN_tool_draw(aa,s,is); #endif return is; } #endif Standard_IMPORT void FUN_tool_tori(const TopAbs_Orientation Or); void FUN_tool_Add(TopTools_DataMapOfShapeListOfShape& map,const TopoDS_Shape& key, const TopoDS_Shape& subitem) { if (map.IsBound(key)) map.ChangeFind(key).Append(subitem); else {TopTools_ListOfShape los; los.Append(subitem); map.Bind(key,los);} } static void FUN_Raise() { #ifdef DEB Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA(); if (trc) cout<<"*** Raise REGUW"< must be // splitted // After splitting such edges, we deal only with FORWARD and // REVERSED vertices. // 1) a vertex belonging to a CLOSING edge is represented by 2 distinct // 2d points in the UV space. // 2) a vertex belonging to a DEGENERATED edge has at least 2 UV rep. // (if the original degenerated edge has been splitted). // the bounds of the degenerated edge share the same TShape. // 3) a CLOSED edge binds the same vertex oriented FORWARD and REVERSED. // For each vertex get non-"singular" edges in which the vertex is oriented // FORWARD and REVERSED. // binds v and ed if : // v is FORWARD in ed FORWARD : oriFF(v,ed) = FORWARD // v is REVERSED in ed REVERSED : oriFF(v,ed) = FORWARD // oriFF(v,ed) = (ori(ed) == FORWARD) ? ori(ed) : ori(ed).Reverse. // A "singular" edge is a closed, a closing or a degenerated edge. // In , we bind with the key : // - the FORWARD and the REVERSED CLOSING ancestor edges of // - the DEGENERATED ancestor edge of // - the CLOSED edge ancestor edge of // A MULTIPLE vertex has its single UV representation's connexity > 2 const TopoDS_Shape& CS = myCORRISO.S(); TopExp_Explorer exe(CS, TopAbs_EDGE); for (; exe.More(); exe.Next()){ const TopoDS_Edge& ed = TopoDS::Edge(exe.Current()); Standard_Boolean isdgE = BRep_Tool::Degenerated(ed); Standard_Boolean iscE = TopOpeBRepTool_TOOL::IsClosingE(ed,myCORRISO.S(),Fref()); iscE = iscE && !isdgE; // closing ed TopoDS_Shape vcl; Standard_Boolean isvcl = TopOpeBRepTool_TOOL::ClosedE(ed,TopoDS::Vertex(vcl)); isvcl = isvcl && !isdgE; TopExp_Explorer exv(ed, TopAbs_VERTEX); for (; exv.More(); exv.Next()){ const TopoDS_Vertex& v = TopoDS::Vertex(exv.Current()); Standard_Boolean isb = mymapvEds.Contains(v); TopOpeBRepTool_connexity theconnexity(v); if (!isb) mymapvEds.Add(v, theconnexity); TopOpeBRepTool_connexity& co = mymapvEds.ChangeFromKey(v); if (isdgE) { // avoid adding it twice co.RemoveItem(CLOSING,ed); co.AddItem(CLOSING,ed); break; } else if (iscE) { // FORWARD and REVERSED edge is added co.AddItem(CLOSING,ed); } else if (isvcl && (v.IsSame(vcl))) { // avoid adding it twice co.RemoveItem(CLOSING,ed); co.AddItem(CLOSING,ed); } else { Standard_Integer iov = TopOpeBRepTool_TOOL::OriinSor(v,ed,Standard_False); //iov != 0 co.AddItem(iov,ed); } }//exv }//exe #ifdef DEB if (trc) { for (Standard_Integer iv = 1; iv <= mymapvEds.Extent(); iv++) { const TopoDS_Vertex& v = TopoDS::Vertex(mymapvEds.FindKey(iv)); cout <<"#v"< v, p2d=pt2d(v,e), tg=tg2d(v,e). { Standard_Integer iv1e1 = (iStep == 1) ? FORWARD : REVERSED; TopoDS_Shape aLocalShape = TopOpeBRepTool_TOOL::Vertex(iv1e1,e); v = TopoDS::Vertex(aLocalShape); // v = TopoDS::Vertex(TopOpeBRepTool_TOOL::Vertex(iv1e1,e)); Standard_Real par1 = TopOpeBRepTool_TOOL::ParE(iv1e1,e); Standard_Boolean line = FUN_tool_line(pc); Standard_Boolean quad = FUN_tool_quad(pc);// mytg2d is reapproximated if PCquad Standard_Boolean approx = quad && (!line); gp_Vec2d tg2d; if (approx) { p2d = pc->Value(par1); Standard_Integer iv0e1 = (iStep == 1) ? REVERSED : FORWARD; Standard_Real par0 = TopOpeBRepTool_TOOL::ParE(iv0e1,e); // Getting a point near point of Standard_Real x = 0.2345; Standard_Real par = (1-x)*par1+x*par0; gp_Pnt2d pmil; pc->D1(par,pmil,tg2d); } else { pc->D1(par1,p2d,tg2d); } tg = gp_Dir2d(tg2d); if (M_REVERSED(e.Orientation())) tg.Reverse(); } //======================================================================= //function : InitBlock //purpose : //======================================================================= Standard_Boolean TopOpeBRepTool_REGUW::InitBlock() { if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); #ifdef DEB Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA(); #endif myv0.Nullify(); myp2d0=gp_Pnt2d(1.e7,1.e7); myed.Nullify(); Standard_Integer iv0e1 = (iStep == 1) ? REVERSED : FORWARD; // updating and myListVmultiple TopTools_ListIteratorOfListOfShape itmu(myListVmultiple); while (itmu.More()) { const TopoDS_Shape& vmu = itmu.Value(); const TopOpeBRepTool_connexity& cmu = mymapvEds.FindFromKey(vmu); Standard_Boolean mult = cmu.IsMultiple(); if (!mult) { myListVmultiple.Remove(itmu); mymapvmultiple.Remove(vmu); } else itmu.Next(); } // myv0 : if (myListVmultiple.IsEmpty()) { Standard_Integer i; for (i = 1; i <= mymapvEds.Extent(); i++) { const TopoDS_Vertex& v = TopoDS::Vertex(mymapvEds.FindKey(i)); const TopOpeBRepTool_connexity& co = mymapvEds(i); TopTools_ListOfShape lea; Standard_Integer nea = co.Item(iv0e1,lea); TopTools_ListOfShape leb; Standard_Integer neb = co.Item(CLOSING,leb); TopTools_ListOfShape le; le.Append(lea); le.Append(leb); Standard_Integer ne = nea+neb; if (ne != 0) {myv0 = v; break;} } } else { myv0 = TopoDS::Vertex(myListVmultiple.First()); } if (myv0.IsNull()) return Standard_False; // myed : const TopOpeBRepTool_connexity& co = mymapvEds.FindFromKey(myv0); TopTools_ListOfShape lea; Standard_Integer nea = co.Item(iv0e1,lea); TopTools_ListOfShape leb; Standard_Integer neb = co.Item(CLOSING,leb); TopTools_ListOfShape le; le.Append(lea); le.Append(leb); Standard_Integer ne = nea+neb; if (ne == 0) return Standard_False; if (nea > 0) myed = TopoDS::Edge(le.First()); else {// CLOSING in TopTools_ListIteratorOfListOfShape itb(le); for (; itb.More(); itb.Next()){ const TopoDS_Edge& eb = TopoDS::Edge(itb.Value()); Standard_Boolean iscE = TopOpeBRepTool_TOOL::IsClosingE(myed,myCORRISO.S(),Fref()); if (!iscE) {myed = eb; break;} Standard_Integer iov0 = TopOpeBRepTool_TOOL::OriinSorclosed(myv0,myed); if (iov0 != iv0e1) continue; }//itb(leb) } if (myed.IsNull()) return Standard_False; TopExp_Explorer exv(myed, TopAbs_VERTEX); for (; exv.More(); exv.Next()){ const TopoDS_Shape& vcur = exv.Current(); TopOpeBRepTool_connexity& cco = mymapvEds.ChangeFromKey(vcur); cco.RemoveItem(myed); } // myp2d0 : TopOpeBRepTool_C2DF c2df;Standard_Boolean bound = myCORRISO.UVRep(myed,c2df); if (!bound) return Standard_False; Standard_Real f,l,tol; const Handle(Geom2d_Curve)& pc = c2df.PC(f,l,tol); Standard_Real par0 = TopOpeBRepTool_TOOL::ParE(iv0e1,myed); pc->D0(par0,myp2d0); // myv, myp2d, mytg2d : ::FUN_nextdata(iStep,myed,pc, myv,myp2d,mytg2d); #ifdef DEB if (trc) { cout< && ori(,e)=iv0e1 TopTools_ListOfShape lea; Standard_Integer nea = co.Item(iv0e1,lea); TopTools_ListOfShape leb; Standard_Integer neb = co.Item(CLOSING,leb); TopTools_ListOfShape le; le.Append(lea); le.Append(leb); Standard_Integer ne = nea + neb; TopTools_ListIteratorOfListOfShape ite(le); while (ite.More()) { const TopoDS_Edge& e = TopoDS::Edge(ite.Value()); #ifdef DEB if (trc) cout<<" e"<D0(par,p2de); // p2d(myv,ed)=p2d(myv,e) Standard_Boolean samep2d = p2de.IsEqual(myp2d,mytol2d); if (!samep2d) le.Remove(ite); else ite.Next(); #ifdef DEB if (trc) {if (samep2d) cout<<" valid"< for regularization //======================================================================= Standard_Boolean TopOpeBRepTool_REGUW::REGU(const Standard_Integer istep, #ifdef DEB const TopoDS_Shape& Scur, #else const TopoDS_Shape& , #endif TopTools_ListOfShape& Splits) { if (!HasInit()) Standard_Failure::Raise("TopOpeBRepTool_REGUW : NO INIT"); iStep = istep; #ifdef DEB Standard_Boolean trc = TopOpeBRepTool_GettraceREGUFA(); if (trc) cout<, we get : // - an edge where is oriented REVERSED(step1)/FORWARD(step2) // - the other vertex of oriented FORWARD(step1)/REVERSED(step2) // - is 's UV representation attached to , // - tg2d = Tgt(p2d1,e1) if FORWARD(step1) // = -Tgt(p2d1,e1) if is REVERSED(step1) in the face with // Tgt(p2d1,e1) = tangent to 's pcurve at point // step1 : // ------- // Given a starting couple (, , tg2d, ) with : // - oriented FORWARD in , // - 's 2d representation falling on an UV bound of 's pcurve (if is // on a closing edge), // We get the edge such that : // - is not already touched, // - is oriented REVERSED(step1) in , // - has an UV bound falling into geometry . // - The oriented angle (-tg2d, tg2d) is the lowest, // ( The angle is computed in the anti-trigonometric sense; // the tangents's orientation are reversed if the edge is oriented REVERSED in the face ) // = Smaller oriented (following trigonometric sense) angle (tg2d, -tg2d) // // step2 : reverse the orientations and the angle describes non-matter. // ------- // tol2d = 1.e-2*(lowest distance (p2df,p2dl) between all non-closed // and non-degenerated pcurves seen during the regularization). // This value is updated in method chkp2dFORinE. // The comparision of p2d points is coupled with comparision of vertices // We should in fact use bounding boxes on pcurves but this is too expensive!!! mytol2d = 1.e-5; isinit0 = Standard_True; TopTools_ListOfShape loEcur, loW; Standard_Integer nite = 0; Standard_Integer nE = myCORRISO.Eds().Extent();// recall myCORRISO.Init(myS); TopTools_ListIteratorOfListOfShape ite(myCORRISO.Eds()); for (; ite.More(); ite.Next()) { TopAbs_Orientation oe = ite.Value().Orientation(); if (M_INTERNAL(oe) || M_EXTERNAL(oe)) nE--; } while (nite <= nE) { Standard_Boolean FINI = (nite == nE); //*** Getting starts elements if not defined // ----------------------------------------- if (isinit0 && !FINI) { Standard_Boolean ok = InitBlock(); if (!ok) { #ifdef DEB if (trc) cout<<"** InitBlock fails"< is the first one and == , the wire is closed Standard_Boolean wireisclosed = myp2d.IsEqual(myp2d0,mytol2d); if (wireisclosed) { //* Adding INTERNAL/EXTERNAL edges to wires // ---------------------------------------- TopTools_ListIteratorOfListOfShape ite1(loEcur); for (; ite1.More(); ite1.Next()){ const TopoDS_Shape& e = ite1.Value(); TopExp_Explorer exv(e, TopAbs_VERTEX); for (; exv.More(); exv.Next()){ const TopoDS_Shape& v = exv.Current(); TopOpeBRepTool_connexity& co = mymapvEds.ChangeFromKey(v); TopTools_ListOfShape& le = co.ChangeItem(INTERNAL); TopTools_ListIteratorOfListOfShape itte(le); while (itte.More()) { const TopoDS_Shape& ee = itte.Value(); TopAbs_Orientation oe = ee.Orientation(); if (M_INTERNAL(oe) || M_EXTERNAL(oe)) {loEcur.Append(ee);le.Remove(itte);} else itte.Next(); }//itte(le) }//exv(e) }//ite(loEcur) FINI = (nite == nE); // if Scur = gives only one new wire, and has no new splitted edges, // is valid and unchanged. Standard_Boolean onewok = FINI && loW.IsEmpty() && !hasnewsplits; if (onewok){ #ifdef DEB if (trc) cout<<"wire "<new wire = wi"< is in , = current UV representation Standard_Boolean gotonext = NextinBlock(); if (!gotonext) { #ifdef DEB if (trc) cout<<"** NextinBlock fails"<