// Created on: 1997-11-13 // Created by: Xuan PHAM PHU // Copyright (c) 1997-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef OCCT_DEBUG //Standard_EXPORT Standard_Integer STATIC_PURGE_iwi = 0; //Standard_EXPORT TopTools_IndexedMapOfShape STATIC_PURGE_mapw, STATIC_PURGE_mapv; //Standard_EXPORT TopTools_IndexedMapOfOrientedShape STATIC_PURGE_mapeds, STATIC_CORR_mapeds; Standard_EXPORT void debcorrUV(){}; extern Standard_Boolean TopOpeBRepTool_GettracePURGE(); extern Standard_Boolean TopOpeBRepTool_GettraceCORRISO(); #endif // DEB #define SPLITEDGE (0) #define INCREASE (1) #define DECREASE (-1) #define M_FORWARD(sta) (sta == TopAbs_FORWARD) #define M_REVERSED(sta) (sta == TopAbs_REVERSED) #define M_INTERNAL(sta) (sta == TopAbs_INTERNAL) #define M_EXTERNAL(sta) (sta == TopAbs_EXTERNAL) static void FUN_addtomap(TopTools_DataMapOfShapeListOfShape& map, const TopoDS_Shape& key, const TopoDS_Shape& item) { if (map.IsBound(key)) map.ChangeFind(key).Append(item); else {TopTools_ListOfShape los; los.Append(item); map.Bind(key,los);} } static Standard_Boolean FUN_getv(const TopAbs_Orientation& orivine, const TopoDS_Shape& e, TopoDS_Shape& v) { v.Nullify(); // gets oriented in TopAbs_Orientation oe = e.Orientation(); Standard_Boolean isnonO = M_INTERNAL(oe) || M_EXTERNAL(oe); TopoDS_Shape eO; if (isnonO) { eO = e.Oriented(TopAbs_FORWARD); } else { eO = e; } TopExp_Explorer exv(eO, TopAbs_VERTEX); for (; exv.More(); exv.Next()) { const TopoDS_Shape& vcur = exv.Current(); if (vcur.Orientation() == orivine) {v = vcur; return Standard_True;} } // exv return Standard_False; } Standard_EXPORT Standard_Boolean FUN_tool_ClosedW(const TopoDS_Wire& W) { // !! an edge oriented INTERNAL/EXTERNAL has all its vertices // oriented INTERNAL/EXTERNAL. // = {(v,loe)} / e is oriented : // = {(v,loe)} / e is not oriented (INTERNAL/EXTERNAL) : TopTools_DataMapOfShapeListOfShape mapvFine,mapvRine, mapvIine; TopExp_Explorer exe(W, TopAbs_EDGE); for (; exe.More(); exe.Next()){ const TopoDS_Shape& e = exe.Current(); TopAbs_Orientation oe = e.Orientation(); Standard_Boolean isnonO = M_INTERNAL(oe) || M_EXTERNAL(oe); TopoDS_Shape eO; if (isnonO) { eO = e.Oriented(TopAbs_FORWARD); } else { eO = e; } TopExp_Explorer exv(eO, TopAbs_VERTEX); for (; exv.More(); exv.Next()) { const TopoDS_Shape& v = exv.Current(); TopAbs_Orientation oriv = v.Orientation(); if (M_FORWARD(oriv)) FUN_addtomap(mapvFine,v,e); if (M_REVERSED(oriv)) FUN_addtomap(mapvRine,v,e); if (M_INTERNAL(oriv)) FUN_addtomap(mapvIine,v,e); } } if (mapvFine.Extent() == 0) return Standard_False; // empty wire TopTools_MapOfShape mapvok; // a vertex is found valid if is - an internal vertex // - found FORWARD and REVERSED. TopTools_MapOfShape mapvonlyFine; // {(v,e)} v F in e, v belongs to only one e TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itvFine(mapvFine); for (; itvFine.More(); itvFine.Next()){ const TopoDS_Shape& vFine = itvFine.Key(); Standard_Boolean vIine = mapvIine.IsBound(vFine); if (vIine) {mapvok.Add(vFine); continue;} Standard_Boolean vRine = mapvRine.IsBound(vFine); if (vRine) {mapvok.Add(vFine); continue;} mapvonlyFine.Add(vFine); } // = {(v,e)} v R in e, v belongs to only one e TopTools_MapOfShape mapvonlyRine; TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itvRine(mapvRine); for (; itvRine.More(); itvRine.Next()){ const TopoDS_Shape& vRine = itvRine.Key(); Standard_Boolean vok = mapvok.Contains(vRine); if (vok) continue; Standard_Boolean vIine = mapvIine.IsBound(vRine); if (vIine) {mapvok.Add(vRine); continue;} mapvonlyRine.Add(vRine); } // checking vertices and TopTools_MapIteratorOfMapOfShape itvonlyFRine; Standard_Integer nmap = 0; while (nmap <= 2) { nmap++; Standard_Boolean vFine = (nmap == 1); if (vFine) itvonlyFRine.Initialize(mapvonlyFine); else itvonlyFRine.Initialize(mapvonlyRine); for (; itvonlyFRine.More(); itvonlyFRine.Next()){ const TopoDS_Shape& vtocheck = itvonlyFRine.Key(); TopTools_ListOfShape edsvFRine; if (vFine) edsvFRine = mapvFine.Find(vtocheck); else edsvFRine = mapvRine.Find(vtocheck); if (edsvFRine.Extent() > 1) return Standard_False; // faulty wire const TopoDS_Shape& e = edsvFRine.First(); TopAbs_Orientation ovori = vFine? TopAbs_REVERSED: TopAbs_FORWARD; TopoDS_Shape ov; Standard_Boolean ovfound = FUN_getv(ovori,e,ov); if (!ovfound) return Standard_False; // faulty edge // is on only one edge , // is FORWARD/REVERSED in , // is REVERSED/FORWARD in . // is ok if : - is INTERNAL in another edge // - is FORWARD and REVERSED in // one or two other edges. // and e is not oriented TopAbs_Orientation oe = e.Orientation(); if (M_FORWARD(oe) || M_REVERSED(oe)) return Standard_False; if (!mapvok.Contains(ov)) return Standard_False; Standard_Boolean ovIine = mapvIine.IsBound(ov); if (ovIine) continue; Standard_Boolean ovFine = mapvRine.IsBound(ov); if (!ovFine) return Standard_False; Standard_Boolean ovRine = mapvRine.IsBound(ov); if (!ovRine) return Standard_False; const TopTools_ListOfShape& edsovFine = mapvFine.Find(ov); const TopTools_ListOfShape& edsovRine = mapvRine.Find(ov); if (edsovFine.Extent() > 1) continue; if (edsovRine.Extent() > 1) continue; if (edsovFine.First().IsEqual(e)) return Standard_False; if (edsovRine.First().IsEqual(e)) return Standard_False; } } // nmap return Standard_True; } //======================================================================= //function : PurgeClosingEdges //purpose : //======================================================================= Standard_Boolean TopOpeBRepTool::PurgeClosingEdges(const TopoDS_Face& Fin, const TopoDS_Face& FF, // const TopTools_DataMapOfShapeInteger& MWisOld, const TopTools_DataMapOfShapeInteger& , TopTools_IndexedMapOfOrientedShape& MshNOK) { // Fin is the original face // FF is the splitted face // prequesitory : splitted edges, of edge ancestor a closing edge // keep in memory the geometry of the ancestor edge, // they answer True to BRep_Tool::IsClosed. // elsewhere : we have to get this information using geometric // criteriums (TopOpeBRepTool_TOOL::IsonCLO) #ifdef OCCT_DEBUG Standard_Boolean trc = TopOpeBRepTool_GettracePURGE(); if (trc) cout<<"\n* PurgeClosingEdges:\n\n"; #endif TopOpeBRepTool_CORRISO CORRISO(Fin); Standard_Real tolF = BRep_Tool::Tolerance(Fin); Standard_Real uperiod; Standard_Boolean uclosed = CORRISO.Refclosed(1,uperiod); Standard_Real vperiod; Standard_Boolean vclosed = CORRISO.Refclosed(2,vperiod); if (!uclosed && !vclosed) return Standard_False; Standard_Boolean inU = uclosed ? Standard_True : Standard_False; Standard_Real xmin = inU ? (CORRISO.GASref().FirstUParameter()) : (CORRISO.GASref().FirstVParameter()); Standard_Real xper = inU ? uperiod : vperiod; Standard_Real tolx = inU ? (CORRISO.Tol(1,tolF)) : (CORRISO.Tol(2,tolF)); TopExp_Explorer exw(FF, TopAbs_WIRE); for (; exw.More(); exw.Next()){ const TopoDS_Shape& W = exw.Current(); CORRISO.Init(W); Standard_Boolean ok = CORRISO.UVClosed(); if (ok) continue; TopTools_ListOfShape cEds; TopTools_ListIteratorOfListOfShape ite(CORRISO.Eds()); for (; ite.More(); ite.Next()){ const TopoDS_Edge& E = TopoDS::Edge(ite.Value()); Standard_Boolean closing = BRep_Tool::IsClosed(E,Fin); if (!closing) {// xpu231198 : pcurve modified, the information is lost TopOpeBRepTool_C2DF C2DF; Standard_Boolean isb = CORRISO.UVRep(E,C2DF); if (!isb) return Standard_False;//NYIRAISE Standard_Boolean onclo = TopOpeBRepTool_TOOL::IsonCLO(C2DF,inU,xmin,xper,tolx); if (onclo) closing=Standard_True; } if (closing) cEds.Append(E); } Standard_Integer ncE = cEds.Extent(); Standard_Boolean nopurge = (ncE <= 1); if (nopurge) return Standard_True; // Checking TopTools_ListOfShape fyEds; Standard_Boolean topurge = CORRISO.PurgeFyClosingE(cEds,fyEds); if (topurge) { TopTools_ListIteratorOfListOfShape it(fyEds); for (; it.More(); it.Next()) MshNOK.Add(it.Value()); MshNOK.Add(W); MshNOK.Add(FF); } #ifdef OCCT_DEBUG if (trc && topurge) cout<<"found FAULTY edge = ed"<D0(parv1,pv1); gp_Pnt2d pv2; PCEin->D0(parv2,pv2); Standard_Real par1 = BRep_Tool::Parameter(vfe1,e1,Fsp); Standard_Real par2 = BRep_Tool::Parameter(vfe2,e2,Fsp); gp_Pnt2d p1; PC1->D0(par1,p1); gp_Pnt2d p2; PC2->D0(par2,p2); Standard_Real cv1 = (isuiso) ? pv1.Y() : pv1.X(); Standard_Real cv2 = (isuiso) ? pv2.Y() : pv2.X(); Standard_Real c1 = (isuiso) ? p1.Y() : p1.X(); Standard_Real c2 = (isuiso) ? p2.Y() : p2.X(); Standard_Real d1 = (c1 - cv1); Standard_Real d2 = (c2 - cv2); Standard_Real adc = Abs(c1 - c2); Standard_Real adcv = Abs(cv1 - cv2); Standard_Real tol2d = 1.e-6; Standard_Boolean mmd = (Abs(adc-adcv) < tol2d); if (mmd) { // correction de CTS20973 gp_Vec2d transl(0.,1.); if (isviso) transl = gp_Vec2d(1.,0.); transl.Multiply(d1); // ou d2 ok = FUN_tool_translate(transl,Fsp,Ein); } else { // redefinition des parametres de v1,v2 de Ein tels que des parametres de #ifdef OCCT_DEBUG if (TopOpeBRepTool_GettraceCORRISO()) { cout<<"FUN_correctDegeneratedE : !mmd NYI"<={(fye,recadre)}, recadre = INCREASE,DECREASE // fye has its 2 bounds faulty { fyEds.Clear(); Standard_Real tolF = BRep_Tool::Tolerance(CORRISO.Fref()); Standard_Integer Index = onU ? 1 : 2; Standard_Real xperiod; Standard_Boolean xclosed = CORRISO.Refclosed(Index,xperiod); if (!xclosed) return Standard_False; Standard_Real xtol = CORRISO.Tol(Index,tolF); // fy has its 2 uvbounds non-connexed //nyixpu300998 : iterative (while ko) + map of "static" edges TopoDS_Shape fy; Standard_Integer Ify=0; Standard_Boolean hasfy = CORRISO.EdgeWithFaultyUV(EdstoCheck,2,fy,Ify); if (!hasfy) return Standard_False; TopOpeBRepTool_C2DF C2DF; Standard_Boolean isb = CORRISO.UVRep(TopoDS::Edge(fy),C2DF); if (!isb) return Standard_False; // NYIRAISE TopTools_Array1OfShape vfy(1,2); TopOpeBRepTool_TOOL::Vertices(TopoDS::Edge(fy),vfy); for (Standard_Integer ii = 1; ii <=2; ii++) { // vff = vertex[ii] of fy const TopoDS_Vertex& vff = TopoDS::Vertex(vfy(ii)); Standard_Real parvff = TopOpeBRepTool_TOOL::ParE(ii,TopoDS::Edge(fy));gp_Pnt2d uvff = TopOpeBRepTool_TOOL::UVF(parvff,C2DF); // loe list of edges connexed to faultE TopTools_ListOfShape loe; isb = CORRISO.Connexity(vff,loe); if (!isb) return Standard_False; // FUNRAISE TopTools_ListIteratorOfListOfShape ite(loe); // iteration on connex edges of vff for (; ite.More(); ite.Next()){ const TopoDS_Edge& ee = TopoDS::Edge(ite.Value()); TopTools_Array1OfShape vee(1,2); TopOpeBRepTool_TOOL::Vertices(ee,vee); for (Standard_Integer ive = 1; ive <=2; ive++) { // ve = vertex[ive] of ee const TopoDS_Vertex& ve = TopoDS::Vertex(vee(ive)); Standard_Boolean samev = ve.IsSame(vff); if (!samev) continue; if (ive == ii) continue; TopOpeBRepTool_C2DF C2DFe; isb = CORRISO.UVRep(ee,C2DFe); if (!isb) return Standard_False; // FUNRAISE Standard_Real paree = TopOpeBRepTool_TOOL::ParE(ive,ee); gp_Pnt2d uve = TopOpeBRepTool_TOOL::UVF(paree,C2DFe); // xxtrsl : Standard_Real dxx = onU ? uve.X()-uvff.X() : uve.Y()-uvff.Y(); Standard_Boolean isper =( Abs(xperiod-Abs(dxx)) < xtol); if (!isper) continue; Standard_Integer recadre = (dxx > 0) ? INCREASE : DECREASE; fyEds.Bind(fy,recadre); } //ive=1..2 }//ite(loe) }//ii=1..2 return !fyEds.IsEmpty(); } // FUN_connexX //======================================================================= //function : CorrectONUVISO //purpose : //======================================================================= Standard_Boolean TopOpeBRepTool::CorrectONUVISO(const TopoDS_Face& Fin, TopoDS_Face& Fsp) // is x-periodic { #ifdef OCCT_DEBUG Standard_Boolean trc = TopOpeBRepTool_GettraceCORRISO(); if (trc) cout<<"\n#### CorrectONUVISO ####\n\n"; debcorrUV(); #endif Standard_Real tolF = BRep_Tool::Tolerance(Fin); TopOpeBRepTool_CORRISO CORRISO(Fin); Standard_Real uperiod,vperiod; Standard_Boolean uclosed = CORRISO.Refclosed(1,uperiod); Standard_Boolean vclosed = CORRISO.Refclosed(2,vperiod); if (!uclosed && !vclosed) return Standard_False; CORRISO.Init(Fsp); Standard_Boolean ok = CORRISO.UVClosed(); if (ok) return Standard_True; // Fsp is valid // 1. We check connexity among all edges of // if we find on edge with 2 faulty UVbounds, we try to UVconnect it. // for (Standard_Integer i=1; i<=2; i++) { Standard_Integer i ; for ( i=1; i<=2; i++) { Standard_Boolean onU = (i==1) ? Standard_True : Standard_False; const TopTools_ListOfShape& Tocheck = CORRISO.Eds(); TopTools_DataMapOfOrientedShapeInteger fyEds; ok =::FUN_connexX(onU,CORRISO,Tocheck,fyEds); if (!ok) continue; ok = CORRISO.TrslUV(onU,fyEds); if (!ok) continue; ok = CORRISO.UVClosed(); if (!ok) continue; ok = CORRISO.GetnewS(Fsp); if (!ok) return Standard_False; //NYIRAISE return Standard_True; } // 2. x-2drep(edges) are in [xfirst,xfirst+xperiod] for (i = 1; i <=2; i++) { Standard_Boolean onU = (i==1); Standard_Real xper=0.; Standard_Boolean xclosed = CORRISO.Refclosed(i,xper); if (!xclosed) continue; Standard_Real tolx = CORRISO.Tol(i,tolF); tolx *= 1.e2; // BUC60380 TopTools_DataMapOfOrientedShapeInteger FyEds; Standard_Boolean hasfy = CORRISO.EdgesOUTofBoundsUV(CORRISO.Eds(),onU,tolx,FyEds); if (!hasfy) continue; ok = CORRISO.TrslUV(onU,FyEds); if (!ok) return Standard_False; ok = CORRISO.UVClosed(); if (!ok) continue; ok = CORRISO.GetnewS(Fsp); if (!ok) return Standard_False; //NYIRAISE return Standard_True; } return Standard_False; /*// xpu310898 : eC closing ff, ff sdm F(reference face), proj(eC,F) gives ee with // !closing(ee,Fsp) -> 2drep(Fsp) is not closed. // purpose : translate pceCFOR or pceCREV // cto902B7 (ff=f7,eC=e9,F=f14) ok = ::FUN_tool_reguUV(Fin,Fsp);*/ /*// JYL 980909 : reecriture complete // 1/ traitement de TOUTES les aretes // isou et isov fautives (et non la premiere trouvee); // 2/ traitement des aretes degenerees fautives : CTS20973 TopTools_ListOfShape lisoe,ldege; TopExp_Explorer exe(Fsp, TopAbs_EDGE); for (; exe.More(); exe.Next()){ const TopoDS_Edge& E = TopoDS::Edge(exe.Current()); Standard_Boolean degen = BRep_Tool::Degenerated(E); if ( degen ) { ldege.Append(E); } else { Standard_Real f,l; Handle(Geom2d_Curve) PC = BRep_Tool::CurveOnSurface(E,Fin,f,l); Standard_Boolean uiso,viso; gp_Dir2d d2d; gp_Pnt2d O2d; Standard_Boolean uviso = FUN_tool_IsUViso(PC,uiso,viso,d2d,O2d); Standard_Boolean onclosing = (uiso && uclosed) || (viso && vclosed); if ( onclosing) { lisoe.Append(E); } } } Standard_Integer nisoe = lisoe.Extent(); Standard_Integer ndege = ldege.Extent(); if (nisoe ==0 && ndege == 0) return Standard_False; Standard_Integer tmpisoe; Standard_Integer tmpdege; TopTools_ListOfShape lfyisoe; Standard_Boolean tocorrectisoe = Standard_False; tocorrectisoe = FUN_DetectEdgeswithfaultyUV(Fsp,Fsp,lisoe,Standard_True,lfyisoe,tmpisoe); TopTools_ListOfShape lfydege; Standard_Boolean tocorrectdege = Standard_False; tocorrectdege = FUN_DetectEdgeswithfaultyUV(Fsp,Fsp,ldege,Standard_True,lfydege,tmpdege); tocorrect = (tocorrectisoe || tocorrectdege); if (!tocorrect) { return Standard_True; } #ifdef OCCT_DEBUG if (trc) { cout<<"CorrectONUVISO "; cout<<"iso faulty "<, NOTHING is done! // -> see processing ::PurgeClosingEdges later called in WESMakeFaces Standard_Integer nfoundisoe = 0; for (exe.Init(Fsp, TopAbs_EDGE); exe.More(); exe.Next()) { if (exe.Current().IsSame(fyisoe)) { nfoundisoe++; } } if (nfoundisoe > 1) { continue; } #ifdef DRAW if (trc) { cout<<"TopOpeBRepTool correctONUVISO : faulty iso edge"< is on periodic surface, translates edge // 's uorviso to have its uorvpar bounded in [0.,2PI]. { Handle(Geom2d_TrimmedCurve) C2d = ::FUN_translate(tvector,fF,fyE); Standard_Real tole = BRep_Tool::Tolerance(fyE); //xpu040598 : CTS20280 f37 modified when its split is modified! TopoDS_Face newf; Standard_Boolean ok = FUN_tool_pcurveonF(fF,fyE,C2d,newf); if (ok) fF = newf; return ok; //xpu040598 } */