// Created on: 1997-10-13 // Created by: Roman BORISOV // 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef OCCT_DEBUG_CHRONO #include OSD_Chronometer chr_total, chr_init, chr_approx, chr_booltool; Standard_Real t_total, t_init, t_approx, t_booltool; Standard_IMPORT Standard_Real t_init_point, t_dicho_bound; Standard_IMPORT Standard_Integer init_point_count, dicho_bound_count; void InitChron(OSD_Chronometer& ch) { ch.Reset(); ch.Start(); } void ResultChron( OSD_Chronometer & ch, Standard_Real & time) { Standard_Real tch ; ch.Stop(); ch.Show(tch); time=time +tch; } #endif //======================================================================= //function : BRepAlgo_NormalProjection //purpose : //======================================================================= BRepAlgo_NormalProjection::BRepAlgo_NormalProjection() : myWith3d(Standard_True) { BRep_Builder BB; BB.MakeCompound(TopoDS::Compound(myToProj)); myFaceBounds=Standard_True; SetDefaultParams(); myMaxDist = -1; } //======================================================================= //function : BRepAlgo_NormalProjection //purpose : //======================================================================= BRepAlgo_NormalProjection::BRepAlgo_NormalProjection(const TopoDS_Shape& S) : myWith3d(Standard_True) { BRep_Builder BB; BB.MakeCompound(TopoDS::Compound(myToProj)); SetDefaultParams(); myMaxDist = -1; Init(S); } //======================================================================= //function : Init //purpose : //======================================================================= void BRepAlgo_NormalProjection::Init(const TopoDS_Shape& S) { myShape = S; } //======================================================================= //function : Add //purpose : //======================================================================= void BRepAlgo_NormalProjection::Add(const TopoDS_Shape& ToProj) { BRep_Builder BB; BB.Add(myToProj, ToProj); } //======================================================================= //function : SetParams //purpose : //======================================================================= void BRepAlgo_NormalProjection::SetParams(const Standard_Real Tol3D, const Standard_Real Tol2D, const GeomAbs_Shape InternalContinuity, const Standard_Integer MaxDegree, const Standard_Integer MaxSeg) { myTol3d = Tol3D; myTol2d = Tol2D; myContinuity = InternalContinuity; myMaxDegree = MaxDegree; myMaxSeg = MaxSeg; } //======================================================================= //function : SetDefaultParams //purpose : //======================================================================= void BRepAlgo_NormalProjection::SetDefaultParams() { myTol3d = 1.e-4; myTol2d = Pow(myTol3d, 2./3); myContinuity = GeomAbs_C2; myMaxDegree = 14; myMaxSeg = 16; } //======================================================================= //function : SetLimits //purpose : //======================================================================= void BRepAlgo_NormalProjection::SetLimit(const Standard_Boolean FaceBounds) { myFaceBounds = FaceBounds; } //======================================================================= //function : SetMaxDistance //purpose : //======================================================================= void BRepAlgo_NormalProjection::SetMaxDistance(const Standard_Real MaxDist) { myMaxDist = MaxDist; } //======================================================================= //function : Compute3d //purpose : //======================================================================= void BRepAlgo_NormalProjection::Compute3d(const Standard_Boolean With3d) { myWith3d = With3d; } //======================================================================= //function : Build //purpose : //======================================================================= void BRepAlgo_NormalProjection::Build() { #ifdef OCCT_DEBUG_CHRONO Standard_Integer init_count = 0, approx_count = 0, booltool_count = 0; t_total = 0; t_init = 0; t_approx = 0; t_booltool = 0; t_init_point = 0; init_point_count = 0; t_dicho_bound = 0; dicho_bound_count = 0; InitChron(chr_total); #endif myIsDone = Standard_False; ProjLib_CompProjectedCurve Projector; Handle(TopTools_HSequenceOfShape) Edges = new TopTools_HSequenceOfShape(); Handle(TopTools_HSequenceOfShape) Faces = new TopTools_HSequenceOfShape(); TopTools_ListOfShape DescenList; Standard_Integer NbEdges = 0, NbFaces = 0, i, j, k; TopExp_Explorer ExpOfWire, ExpOfShape; Standard_Real Udeb, Ufin; TopoDS_Shape VertexRes; Standard_Boolean Only3d, Only2d, Elementary; // for isoparametric cases TColgp_Array1OfPnt2d Poles(1, 2); TColStd_Array1OfReal Knots(1, 2); TColStd_Array1OfInteger Mults(1,2); Standard_Integer Deg; Deg = 1; Mults(1) = Deg + 1; Mults(2) = Deg + 1; // for(ExpOfWire.Init(myToProj, TopAbs_EDGE); ExpOfWire.More(); ExpOfWire.Next(), NbEdges++) { Edges->Append(ExpOfWire.Current()); } for(ExpOfShape.Init(myShape, TopAbs_FACE); ExpOfShape.More(); ExpOfShape.Next(), NbFaces++) { Faces->Append(ExpOfShape.Current()); } BRep_Builder BB; BB.MakeCompound(TopoDS::Compound(myRes)); BB.MakeCompound(TopoDS::Compound(VertexRes)); Standard_Boolean YaVertexRes = Standard_False; for(i = 1; i <= NbEdges; i++){ DescenList.Clear(); BRepAdaptor_Curve cur(TopoDS::Edge(Edges->Value(i))); Handle(BRepAdaptor_HCurve) hcur = new BRepAdaptor_HCurve(); hcur->Set(cur); Elementary = IsElementary(cur); for(j = 1; j <= NbFaces; j++){ BRepAdaptor_Surface sur(TopoDS::Face(Faces->Value(j))); Handle(BRepAdaptor_HSurface) hsur = new BRepAdaptor_HSurface(); hsur->Set(sur); // computation of TolU and TolV Standard_Real TolU, TolV; TolU = hsur->UResolution(myTol3d)/20; TolV = hsur->VResolution(myTol3d)/20; // Projection #ifdef OCCT_DEBUG_CHRONO InitChron(chr_init); #endif Projector = ProjLib_CompProjectedCurve(hsur, hcur, TolU, TolV, myMaxDist); #ifdef OCCT_DEBUG_CHRONO ResultChron(chr_init,t_init); init_count++; #endif // Handle(ProjLib_HCompProjectedCurve) HProjector = new ProjLib_HCompProjectedCurve(); HProjector->Set(Projector); TopoDS_Shape prj; Standard_Boolean Degenerated = Standard_False; gp_Pnt2d P2d, Pdeb, Pfin; gp_Pnt P; Standard_Real UIso, VIso; Handle(Adaptor2d_HCurve2d) HPCur; Handle(Geom2d_Curve) PCur2d; // Only for isoparametric projection for(k = 1; k <= Projector.NbCurves(); k++){ if(Projector.IsSinglePnt(k, P2d)){ #ifdef OCCT_DEBUG cout << "Projection of edge "<D0(P2d.X(), P2d.Y(), P); prj = BRepLib_MakeVertex(P).Shape(); DescenList.Append(prj); BB.Add(VertexRes, prj); YaVertexRes = Standard_True; myAncestorMap.Bind(prj, Edges->Value(i)); } else { Only2d = Only3d = Standard_False; Projector.Bounds(k, Udeb, Ufin); /**************************************************************/ if (Projector.IsUIso(k, UIso)) { #ifdef OCCT_DEBUG cout << "Projection of edge "<Curve()), Ufin, Udeb); prj = MKed.Edge(); BB.UpdateEdge(TopoDS::Edge(prj), PCur2d, TopoDS::Face(Faces->Value(j)), myTol3d); BB.UpdateVertex(TopExp::FirstVertex(TopoDS::Edge(prj)),myTol3d); BB.UpdateVertex(TopExp::LastVertex(TopoDS::Edge(prj)),myTol3d); } else { #ifdef OCCT_DEBUG_CHRONO InitChron(chr_approx); #endif Approx_CurveOnSurface appr(HPCur, hsur, Udeb, Ufin, myTol3d, myContinuity, myMaxDegree, myMaxSeg, Only3d, Only2d); #ifdef OCCT_DEBUG_CHRONO ResultChron(chr_approx,t_approx); approx_count++; cout<<"Approximation.IsDone = "<LastParameter()-BS3d->FirstParameter())/(NbPoint-1); for (ii=0;iiFirstParameter()+ii*DPar; PP=BS3d->Value(Par); P1.SetXYZ(P1.XYZ() + PP.XYZ()/NbPoint); } for (ii=0;iiFirstParameter()+ii*DPar; PP=BS3d->Value(Par); Dist=P1.Distance(PP); if(Dist > myTol3d) { Degenerated = Standard_False; break; } } // if the test passes a more exact test with 10 points if (Degenerated) { P1.SetCoord(0.,0.,0.); NbPoint =10; DPar = (BS3d->LastParameter()-BS3d->FirstParameter())/(NbPoint-1); for (ii=0;iiFirstParameter()+ii*DPar; PP=BS3d->Value(Par); P1.SetXYZ(P1.XYZ() + PP.XYZ()/NbPoint); } for (ii=0;iiFirstParameter()+ii*DPar; PP=BS3d->Value(Par); Dist=P1.Distance(PP); if(Dist > myTol3d) { Degenerated = Standard_False; break; } } } if (Degenerated) { #ifdef OCCT_DEBUG cout << "Projection of edge "<Value(j)), appr.MaxError3d()); BB.UpdateVertex(TopExp::FirstVertex(TopoDS::Edge(prj)),appr.MaxError3d()); BB.UpdateVertex(TopExp::LastVertex(TopoDS::Edge(prj)),appr.MaxError3d()); if (Degenerated) { BB.Range(TopoDS::Edge(prj), TopoDS::Face(Faces->Value(j)), Udeb,Ufin); } } if(myFaceBounds) { // Trimming edges by face bounds // if the solution is degenerated, use of BoolTool is avoided #ifdef OCCT_DEBUG_CHRONO InitChron(chr_booltool); #endif if (!Degenerated) { // Perform Boolean COMMON operation to get parts of projected edge // inside the face BRepAlgoAPI_Common aCommon(Faces->Value(j), prj); if (aCommon.IsDone()) { const TopoDS_Shape& aRC = aCommon.Shape(); // TopExp_Explorer aExpE(aRC, TopAbs_EDGE); for (; aExpE.More(); aExpE.Next()) { const TopoDS_Shape& aE = aExpE.Current(); BB.Add(myRes, aE); myAncestorMap.Bind(aE, Edges->Value(i)); myCorresp.Bind(aE, Faces->Value(j)); } } else { // if the common operation has failed, try to classify the part BRepTopAdaptor_FClass2d classifier(TopoDS::Face(Faces->Value(j)), Precision::Confusion()); gp_Pnt2d Puv; Standard_Real f = PCur2d->FirstParameter(); Standard_Real l = PCur2d->LastParameter(); Standard_Real pmil = (f + l )/2; PCur2d->D0(pmil, Puv); TopAbs_State state; state = classifier.Perform(Puv); if(state == TopAbs_IN || state == TopAbs_ON) { BB.Add(myRes, prj); DescenList.Append(prj); myAncestorMap.Bind(prj, Edges->Value(i)); myCorresp.Bind(prj, Faces->Value(j)); } } } else { #ifdef OCCT_DEBUG cout << " BooleanOperations : no solution " << endl; #endif BRepTopAdaptor_FClass2d classifier(TopoDS::Face(Faces->Value(j)), Precision::Confusion()); gp_Pnt2d Puv; Standard_Real f = PCur2d->FirstParameter(); Standard_Real l = PCur2d->LastParameter(); Standard_Real pmil = (f + l )/2; PCur2d->D0(pmil, Puv); TopAbs_State state; state = classifier.Perform(Puv); if(state == TopAbs_IN || state == TopAbs_ON) { BB.Add(myRes, prj); DescenList.Append(prj); myAncestorMap.Bind(prj, Edges->Value(i)); myCorresp.Bind(prj, Faces->Value(j)); } #ifdef OCCT_DEBUG_CHRONO ResultChron(chr_booltool,t_booltool); booltool_count++; #endif } } else { BB.Add(myRes, prj); DescenList.Append(prj); myAncestorMap.Bind(prj, Edges->Value(i)); myCorresp.Bind(prj, Faces->Value(j)); } } } } myDescendants.Bind(Edges->Value(i), DescenList); } // JPI : eventual wire creation is reported in a specific method // BuilWire that can be called by the user. Otherwise, the // relations of map myAncestorMap, myCorresp will be lost. if(YaVertexRes) BB.Add(myRes, VertexRes); myIsDone = Standard_True; #ifdef OCCT_DEBUG_CHRONO ResultChron(chr_total,t_total); cout<<"Build - Total time : "<