// 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 IMPLEMENT_STANDARD_RTTIEXT(ShapeAnalysis_TransferParametersProj,ShapeAnalysis_TransferParameters) //======================================================================= //function : ShapeAnalysis_TransferParametersProj //purpose : //======================================================================= ShapeAnalysis_TransferParametersProj::ShapeAnalysis_TransferParametersProj() : myPrecision(0.0) { myMaxTolerance = 1; //Precision::Infinite(); ?? pdn myForceProj = Standard_False; myInitOK = Standard_False; } //======================================================================= //function : ShapeAnalysis_TransferParametersProj //purpose : //======================================================================= ShapeAnalysis_TransferParametersProj::ShapeAnalysis_TransferParametersProj(const TopoDS_Edge& E, const TopoDS_Face& F) { myMaxTolerance = 1; //Precision::Infinite(); ?? pdn myForceProj = Standard_False; Init(E,F); } //======================================================================= //function : Init //purpose : //======================================================================= void ShapeAnalysis_TransferParametersProj::Init(const TopoDS_Edge& E, const TopoDS_Face& F) { myInitOK = Standard_False; ShapeAnalysis_TransferParameters::Init(E,F); myEdge = E; myPrecision = BRep_Tool::Tolerance(E); // it is better - skl OCC2851 //myPrecision = Precision::Confusion(); myCurve = BRep_Tool::Curve (E, myFirst, myLast); if ( myCurve.IsNull() ) { myFirst = 0.; myLast = 1.; return;} if ( F.IsNull() ) return; Standard_Real f2d, l2d; ShapeAnalysis_Edge sae; if(sae.PCurve (E, F, myCurve2d, f2d, l2d, Standard_False)) { Handle(Geom2dAdaptor_HCurve) AC2d = new Geom2dAdaptor_HCurve(myCurve2d,f2d,l2d); Handle(Geom_Surface) aSurface = BRep_Tool::Surface(F,myLocation); Handle(GeomAdaptor_HSurface) AdS = new GeomAdaptor_HSurface(aSurface); Adaptor3d_CurveOnSurface Ad1(AC2d,AdS); myAC3d = Ad1;//new Adaptor3d_CurveOnSurface(AC2d,AdS); myInitOK = Standard_True; } } //======================================================================= //function : Perform //purpose : //======================================================================= Handle(TColStd_HSequenceOfReal) ShapeAnalysis_TransferParametersProj::Perform (const Handle(TColStd_HSequenceOfReal)& Knots, const Standard_Boolean To2d) { //pdn if( !myInitOK || (! myForceProj && myPrecision < myMaxTolerance && BRep_Tool::SameParameter(myEdge))) return ShapeAnalysis_TransferParameters::Perform(Knots,To2d); Handle(TColStd_HSequenceOfReal) resKnots = new TColStd_HSequenceOfReal; Standard_Integer len = Knots->Length(); Standard_Real preci = 2*Precision::PConfusion(); Standard_Real first = (To2d ? myAC3d.FirstParameter() : myFirst); Standard_Real last = (To2d ? myAC3d.LastParameter() : myLast); Standard_Real maxPar = first; Standard_Real lastPar = last; Standard_Real prevPar = maxPar; Standard_Integer j; // svv Jan 10 2000 : porting on DEC for(j = 1; j <= len; j++) { Standard_Real par = PreformSegment(Knots->Value(j),To2d,prevPar,lastPar); prevPar = par; if(prevPar > lastPar) prevPar -= preci; resKnots->Append(par); if(par > maxPar) maxPar = par; } //pdn correcting on periodic if(myCurve->IsClosed()) { for(j = len; j >=1; j--) if(resKnots->Value(j) < maxPar) resKnots->SetValue(j,(To2d ? myAC3d.LastParameter() : myCurve->LastParameter())-(len-j)*preci); else break; } //pdn correction on range for ( j=1; j <= len; j++ ) { if ( resKnots->Value (j) < first ) resKnots->SetValue ( j, first ); if ( resKnots->Value (j) > last ) resKnots->SetValue ( j, last ); } return resKnots; } //======================================================================= //function : PreformSegment //purpose : //======================================================================= Standard_Real ShapeAnalysis_TransferParametersProj::PreformSegment(const Standard_Real Param, const Standard_Boolean To2d, const Standard_Real First, const Standard_Real Last) { Standard_Real linPar = ShapeAnalysis_TransferParameters::Perform(Param, To2d); if( !myInitOK || (! myForceProj && myPrecision < myMaxTolerance && BRep_Tool::SameParameter(myEdge))) return linPar; Standard_Real linDev, projDev; ShapeAnalysis_Curve sac; gp_Pnt pproj; Standard_Real ppar; if(To2d) { gp_Pnt p1 = myCurve->Value(Param).Transformed(myLocation.Inverted()); Handle(Adaptor3d_HSurface) AdS = myAC3d.GetSurface(); Handle(Geom2dAdaptor_HCurve) AC2d = new Geom2dAdaptor_HCurve(myCurve2d,First,Last); Adaptor3d_CurveOnSurface Ad1(AC2d,AdS); projDev = sac.Project(Ad1,p1,myPrecision,pproj,ppar);//pdn linDev = p1.Distance(Ad1.Value(linPar)); } else { gp_Pnt p1 = myAC3d.Value(Param).Transformed(myLocation); projDev = sac.Project(myCurve,p1,myPrecision,pproj,ppar,First,Last,Standard_False); linDev = p1.Distance(myCurve->Value(linPar)); } if ( linDev <= projDev || (linDev < myPrecision && linDev <= 2 * projDev ) ) ppar = linPar; return ppar; } //======================================================================= //function : Perform //purpose : //======================================================================= Standard_Real ShapeAnalysis_TransferParametersProj::Perform(const Standard_Real Knot, const Standard_Boolean To2d) { if( !myInitOK || (! myForceProj && myPrecision < myMaxTolerance && BRep_Tool::SameParameter(myEdge))) return ShapeAnalysis_TransferParameters::Perform(Knot, To2d); Standard_Real res; if(To2d) res = PreformSegment(Knot,To2d,myAC3d.FirstParameter(),myAC3d.LastParameter()); else res = PreformSegment(Knot,To2d,myFirst,myLast); //pdn correction on range Standard_Real first = (To2d ? myAC3d.FirstParameter() : myFirst); Standard_Real last = (To2d ? myAC3d.LastParameter() : myLast); if ( res < first ) res = first; if ( res > last ) res = last; return res; } //======================================================================= //function : CorrectParameter //purpose : auxilary //======================================================================= static Standard_Real CorrectParameter(const Handle(Geom2d_Curve) crv, const Standard_Real param) { if(crv->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) { Handle(Geom2d_TrimmedCurve) tmp = Handle(Geom2d_TrimmedCurve)::DownCast (crv); return CorrectParameter(tmp->BasisCurve(),param); } else if(crv->IsKind(STANDARD_TYPE(Geom2d_OffsetCurve))) { Handle(Geom2d_OffsetCurve) tmp = Handle(Geom2d_OffsetCurve)::DownCast (crv); return CorrectParameter(tmp->BasisCurve(),param); } else if(crv->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) { Handle(Geom2d_BSplineCurve) bspline = Handle(Geom2d_BSplineCurve)::DownCast (crv); for(Standard_Integer j = bspline->FirstUKnotIndex(); j <= bspline->LastUKnotIndex(); j++) { Standard_Real valknot = bspline->Knot(j); if( Abs(valknot-param) Epsilon(myAC3d.LastParameter()) ) { alpha = ( firstPar - myAC3d.FirstParameter() ) / fact; beta = ( lastPar - myAC3d.FirstParameter() ) / fact; } } else { p1 = myCurve->Value(firstPar); if(Precision::IsInfinite(p1.X()) || Precision::IsInfinite(p1.Y()) || Precision::IsInfinite(p1.Z())) { B.SameRange(newEdge, Standard_False); return; } p2 = myCurve->Value(lastPar); if(Precision::IsInfinite(p2.X()) || Precision::IsInfinite(p2.Y()) || Precision::IsInfinite(p2.Z())) { B.SameRange(newEdge, Standard_False); return; } Standard_Real fact = myLast - myFirst; if( fact > Epsilon(myLast) ) { alpha = ( firstPar - myFirst ) / fact; beta = ( lastPar - myFirst ) / fact; } } const Standard_Boolean useLinearFirst = (alpha < preci); const Standard_Boolean useLinearLast = (1-beta < preci); TopLoc_Location EdgeLoc = myEdge.Location(); ShapeAnalysis_Curve sac; gp_Pnt pproj; Standard_Real ppar1,ppar2; BRep_ListOfCurveRepresentation& tolist = (*((Handle(BRep_TEdge)*)&newEdge.TShape()))->ChangeCurves(); Handle(BRep_GCurve) toGC; for (BRep_ListIteratorOfListOfCurveRepresentation toitcr (tolist); toitcr.More(); toitcr.Next()) { toGC = Handle(BRep_GCurve)::DownCast(toitcr.Value()); if ( toGC.IsNull() ) continue; TopLoc_Location loc = ( EdgeLoc * toGC->Location() ).Inverted(); if ( toGC->IsCurve3D() ) { if (!Is2d) { ppar1 = firstPar; ppar2 = lastPar; } else { Handle(Geom_Curve) C3d = toGC->Curve3D(); if (C3d.IsNull()) continue; Standard_Real first = toGC->First(); Standard_Real last = toGC->Last(); Standard_Real len = last -first; gp_Pnt ploc1 = p1.Transformed(loc); gp_Pnt ploc2 = p2.Transformed(loc); GeomAdaptor_Curve GAC(C3d,first,last); // CATIA bplseitli.model FAC1155 - Copy: protection for degenerated edges(3d case for symmetry) Standard_Real linFirst = first+alpha*len; Standard_Real linLast = first+beta*len; Standard_Real dist1 = sac.NextProject(linFirst,GAC,ploc1,myPrecision,pproj,ppar1); Standard_Real dist2 = sac.NextProject(linLast,GAC,ploc2,myPrecision,pproj,ppar2); Standard_Boolean useLinear = Abs(ppar1-ppar2) < preci; gp_Pnt pos1 = C3d->Value ( linFirst ); gp_Pnt pos2 = C3d->Value ( linLast ); Standard_Real d01 = pos1.Distance ( ploc1 ); Standard_Real d02 = pos2.Distance ( ploc2 ); if ( useLinearFirst || useLinear || d01 <= dist1 || ( d01 < myPrecision && d01 <= 2 * dist1 ) ) ppar1 = linFirst; if ( useLinearLast || useLinear || d02 <= dist2 || ( d02 < myPrecision && d02 <= 2 * dist2 ) ) ppar2 = linLast; } if(ppar1 > ppar2) { Standard_Real tmpP = ppar2; ppar2 = ppar1; ppar1 = tmpP; } if(ppar2-ppar1 < preci) { if(ppar1-toGC->First() < preci) ppar2+=2*preci; else if(toGC->Last()-ppar2 < preci) ppar1-=2*preci; else { ppar1 -= preci; ppar2 += preci; } } toGC->SetRange ( ppar1, ppar2); //if(fabs(ppar1- firstPar) > Precision::PConfusion() || // fabs(ppar2 - lastPar) >Precision::PConfusion()) // by LSS if(ppar1!=firstPar || ppar2!=lastPar) samerange = Standard_False; } else if (toGC->IsCurveOnSurface()) { //continue; || Standard_Boolean localLinearFirst = useLinearFirst; Standard_Boolean localLinearLast = useLinearLast; Handle(Geom2d_Curve) C2d = toGC->PCurve(); Standard_Real first = toGC->First(); Standard_Real last = toGC->Last(); Standard_Real len = last -first; Handle(Geom2dAdaptor_HCurve) AC2d = new Geom2dAdaptor_HCurve(toGC->PCurve(),first,last); Handle(GeomAdaptor_HSurface) AdS = new GeomAdaptor_HSurface( toGC->Surface()); Adaptor3d_CurveOnSurface Ad1(AC2d,AdS); ShapeAnalysis_Curve sac1; //gp_Pnt p1 = Ad1.Value(prevPar); //gp_Pnt p2 = Ad1.Value(currPar); gp_Pnt ploc1 = p1.Transformed(loc); gp_Pnt ploc2 = p2.Transformed(loc); // CATIA bplseitli.model FAC1155 - Copy: protection for degenerated edges Standard_Real linFirst = first+alpha*len; Standard_Real linLast = first+beta*len; Standard_Real dist1 = sac1.NextProject(linFirst, Ad1, ploc1, myPrecision,pproj,ppar1); Standard_Real dist2 = sac1.NextProject(linLast, Ad1, ploc2, myPrecision,pproj,ppar2); Standard_Boolean isFirstOnEnd = (ppar1-first)/len < Precision::PConfusion(); Standard_Boolean isLastOnEnd = (last-ppar2)/len < Precision::PConfusion(); Standard_Boolean useLinear = Abs(ppar1-ppar2) < Precision::PConfusion(); if(isFirstOnEnd && ! localLinearFirst) localLinearFirst = Standard_True; if(isLastOnEnd && ! localLinearLast) localLinearLast = Standard_True; gp_Pnt pos1 = Ad1.Value ( linFirst ); gp_Pnt pos2 = Ad1.Value ( linLast ); Standard_Real d01 = pos1.Distance ( ploc1 ); Standard_Real d02 = pos2.Distance ( ploc2 ); if ( localLinearFirst || useLinear || d01 <= dist1 || ( d01 < myPrecision && d01 <= 2 * dist1 ) ) ppar1 = linFirst; if ( localLinearLast || useLinear || d02 <= dist2 || ( d02 < myPrecision && d02 <= 2 * dist2 ) ) ppar2 = linLast; if(ppar1 > ppar2) { Standard_Real tmpP = ppar2; ppar2 = ppar1; ppar1 = tmpP; } ppar1 = CorrectParameter(C2d,ppar1); ppar2 = CorrectParameter(C2d,ppar2); if(ppar2-ppar1 < preci) { if(ppar1-toGC->First() < preci) ppar2+=2*preci; else if(toGC->Last()-ppar2 < preci) ppar1-=2*preci; else { ppar1 -= preci; ppar2 += preci; } } toGC->SetRange ( ppar1, ppar2); //if(fabs(ppar1 - firstPar) > Precision::PConfusion() || // fabs(ppar2 -lastPar) > Precision::PConfusion())// by LSS if(ppar1 != firstPar || ppar2 != lastPar) samerange = Standard_False; } } B.SameRange(newEdge, samerange); } //======================================================================= //function : IsSameRange //purpose : //======================================================================= Standard_Boolean ShapeAnalysis_TransferParametersProj::IsSameRange() const { if( !myInitOK || (! myForceProj && myPrecision < myMaxTolerance && BRep_Tool::SameParameter(myEdge))) return ShapeAnalysis_TransferParameters::IsSameRange(); else return Standard_False; } //======================================================================= //function : ForceProjection //purpose : //======================================================================= Standard_Boolean& ShapeAnalysis_TransferParametersProj::ForceProjection() { return myForceProj; } //======================================================================= //function : CopyNMVertex //purpose : //======================================================================= TopoDS_Vertex ShapeAnalysis_TransferParametersProj::CopyNMVertex (const TopoDS_Vertex& theV, const TopoDS_Edge& toedge, const TopoDS_Edge& fromedge) { TopoDS_Vertex anewV; if(theV.Orientation() != TopAbs_INTERNAL && theV.Orientation() != TopAbs_EXTERNAL) return anewV; TopLoc_Location fromLoc; Standard_Real f1,l1; const Handle(Geom_Curve)& C1 = BRep_Tool::Curve(fromedge,fromLoc,f1,l1); fromLoc = fromLoc.Predivided(theV.Location()); Standard_Real f2,l2; Handle(Geom_Curve) C2 = BRep_Tool::Curve(toedge,f2,l2); anewV = TopoDS::Vertex(theV.EmptyCopied()); gp_Pnt apv = BRep_Tool::Pnt(anewV); BRep_ListOfPointRepresentation& alistrep = (*((Handle(BRep_TVertex)*)&anewV.TShape()))->ChangePoints(); BRep_ListIteratorOfListOfPointRepresentation itpr ((*((Handle(BRep_TVertex)*) &theV.TShape()))->Points()); Standard_Real aOldPar = RealLast(); Standard_Boolean hasRepr = Standard_False; for ( ;itpr.More(); itpr.Next()) { const Handle(BRep_PointRepresentation)& pr = itpr.Value(); if(pr.IsNull()) continue; if(pr->IsPointOnCurve(C1,fromLoc)) { aOldPar = pr->Parameter(); hasRepr =Standard_True; continue; } else if(pr->IsPointOnSurface()) { Handle(BRep_PointOnSurface) aOld = Handle(BRep_PointOnSurface)::DownCast(pr); Handle(BRep_PointOnSurface) aPS = new BRep_PointOnSurface(aOld->Parameter(), aOld->Parameter2(), aOld->Surface(), aOld->Location()); alistrep.Append(aPS); continue; } else if(pr->IsPointOnCurveOnSurface()) { Standard_Boolean found = Standard_False; BRep_ListIteratorOfListOfCurveRepresentation fromitcr ((*((Handle(BRep_TEdge)*)&fromedge.TShape()))->ChangeCurves()); for( ;fromitcr.More() && !found; fromitcr.Next()) { Handle(BRep_GCurve) fromGC = Handle(BRep_GCurve)::DownCast(fromitcr.Value()); if ( fromGC.IsNull() || !fromGC->IsCurveOnSurface()) continue; TopLoc_Location aL = fromGC->Location().Predivided(theV.Location()); Handle(Geom_Surface) surface1 = fromGC->Surface(); Handle(Geom2d_Curve) ac2d1 = fromGC->PCurve(); if (pr->IsPointOnCurveOnSurface(ac2d1,surface1,aL)) { found = Standard_True; if(!hasRepr) { aOldPar = pr->Parameter(); } } } if(found) continue; } if(pr->IsPointOnCurve()) { Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(pr->Parameter(),pr->Curve(),pr->Location()); alistrep.Append(aPRep); } else if(pr->IsPointOnCurveOnSurface() ) { Handle(BRep_PointOnCurveOnSurface) aPonCS = new BRep_PointOnCurveOnSurface(pr->Parameter(),pr->PCurve(),pr->Surface(),pr->Location()); alistrep.Append(aPonCS); } } Standard_Real apar = aOldPar; Standard_Real aTol = BRep_Tool::Tolerance(theV); if(!hasRepr || (fabs(f1-f2) > Precision::PConfusion() || fabs(l1-l2)> Precision::PConfusion())) { gp_Pnt projP; ShapeAnalysis_Curve sae; Standard_Real adist = sae.Project(C2,apv,Precision::Confusion(),projP,apar); if(aTol < adist) aTol = adist; } BRep_Builder aB; aB.UpdateVertex(anewV,apar,toedge,aTol); //update tolerance Standard_Boolean needUpdate = Standard_False; gp_Pnt aPV = (*((Handle(BRep_TVertex)*)&anewV.TShape()))->Pnt(); TopLoc_Location toLoc = toedge.Location(); BRep_ListIteratorOfListOfCurveRepresentation toitcr ((*((Handle(BRep_TEdge)*)&toedge.TShape()))->ChangeCurves()); for( ;toitcr.More() ; toitcr.Next()) { Handle(BRep_GCurve) toGC = Handle(BRep_GCurve)::DownCast(toitcr.Value()); if ( toGC.IsNull() || !toGC->IsCurveOnSurface()) continue; TopLoc_Location aL = (toLoc*toGC->Location()).Predivided(theV.Location()); //aL.Predivided(theV.Location()); Handle(Geom_Surface) surface1 = toGC->Surface(); Handle(Geom2d_Curve) ac2d1 = toGC->PCurve(); gp_Pnt2d aP2d = ac2d1->Value(apar); gp_Pnt aP3d = surface1->Value(aP2d.X(),aP2d.Y()); aP3d.Transform(aL.Transformation()); Standard_Real adist = aPV.Distance(aP3d); if(adist > aTol) { aTol = adist; needUpdate = Standard_True; } } if(needUpdate) aB.UpdateVertex(anewV,aTol); return anewV; } //======================================================================= //function : CopyNMVertex //purpose : //======================================================================= TopoDS_Vertex ShapeAnalysis_TransferParametersProj::CopyNMVertex (const TopoDS_Vertex& theV, const TopoDS_Face& toFace, const TopoDS_Face& fromFace) { TopoDS_Vertex anewV; if(theV.Orientation() != TopAbs_INTERNAL && theV.Orientation() != TopAbs_EXTERNAL) return anewV; TopLoc_Location fromLoc; TopLoc_Location toLoc; Handle(Geom_Surface) fromSurf = BRep_Tool::Surface(fromFace,fromLoc); Handle(Geom_Surface) toSurf = BRep_Tool::Surface(toFace,toLoc); fromLoc = fromLoc.Predivided(theV.Location()); anewV = TopoDS::Vertex(theV.EmptyCopied()); gp_Pnt apv = BRep_Tool::Pnt(anewV); BRep_ListOfPointRepresentation& alistrep = (*((Handle(BRep_TVertex)*)&anewV.TShape()))->ChangePoints(); BRep_ListIteratorOfListOfPointRepresentation itpr ((*((Handle(BRep_TVertex)*) &theV.TShape()))->Points()); Standard_Boolean hasRepr = Standard_False; Standard_Real apar1=0., apar2=0.; for ( ;itpr.More(); itpr.Next()) { const Handle(BRep_PointRepresentation)& pr = itpr.Value(); if(pr.IsNull()) continue; TopLoc_Location aLoc = pr->Location(); if( pr->IsPointOnCurveOnSurface()) { Handle(BRep_PointOnCurveOnSurface) aPonCS = new BRep_PointOnCurveOnSurface(pr->Parameter(),pr->PCurve(),pr->Surface(),aLoc); alistrep.Append(aPonCS); } else if(pr->IsPointOnCurve()) { Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(pr->Parameter(),pr->Curve(),aLoc); alistrep.Append(aPRep); } else if(pr->IsPointOnSurface()) { Handle(BRep_PointOnSurface) aOld = Handle(BRep_PointOnSurface)::DownCast(pr); if(pr->IsPointOnSurface(fromSurf,fromLoc)) { apar1= aOld->Parameter(); apar2 = aOld->Parameter2(); hasRepr = Standard_True; } else { Handle(BRep_PointOnSurface) aPS = new BRep_PointOnSurface(aOld->Parameter(), aOld->Parameter2(), aOld->Surface(), aOld->Location()); alistrep.Append(aPS); } } } Standard_Real aTol = BRep_Tool::Tolerance(anewV); if(!hasRepr || (fromSurf != toSurf || fromLoc != toLoc)) { Handle(Geom_Surface) aS = BRep_Tool::Surface(toFace); Handle(ShapeAnalysis_Surface) aSurfTool = new ShapeAnalysis_Surface(aS); gp_Pnt2d aP2d = aSurfTool->ValueOfUV(apv,Precision::Confusion()); apar1 = aP2d.X(); apar2 = aP2d.Y(); if(aTol < aSurfTool->Gap()) aTol = aSurfTool->Gap() + 0.1*Precision::Confusion(); //Handle(BRep_PointOnSurface) aPS = new BRep_PointOnSurface(aP2d.X(),aP2d.Y(),toSurf,toLoc); //alistrep.Append(aPS); } BRep_Builder aB; aB.UpdateVertex(anewV,apar1,apar2,toFace,aTol); return anewV; }