// Created on: 1993-02-05 // Created by: Jacques GOUSSARD // Copyright (c) 1993-1999 Matra Datavision // Copyright (c) 1999-2012 OPEN CASCADE SAS // // The content of this file is subject to the Open CASCADE Technology Public // License Version 6.5 (the "License"). You may not use the content of this file // except in compliance with the License. Please obtain a copy of the License // at http://www.opencascade.org and read it completely before using this file. // // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. // // The Original Code and all software distributed under the License is // distributed on an "AS IS" basis, without warranty of any kind, and the // Initial Developer hereby disclaims all such warranties, including without // limitation, any warranties of merchantability, fitness for a particular // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define tole 5.e-6 static IntSurf_TypeTrans ComputeTransitionOnLine (Contap_TheSurfFunction&, const Standard_Real, const Standard_Real, const gp_Vec&); static IntSurf_TypeTrans ComputeTransitionOngpCircle (Contap_TheSurfFunction&, const gp_Circ&); static IntSurf_TypeTrans ComputeTransitionOngpLine (Contap_TheSurfFunction&, const gp_Lin&); static void ComputeInternalPoints (Contap_TheLine& Line, Contap_TheSurfFunction&, const Standard_Real ureso, const Standard_Real vreso); static void ComputeInternalPointsOnRstr (Contap_TheLine&, const Standard_Real, const Standard_Real, Contap_TheSurfFunction&); static void ProcessSegments (const Contap_TheSearch&, Contap_TheSequenceOfLine&, const Standard_Real, Contap_TheSurfFunction&, const Handle(TheTopolTool)&); //-- -------------------------------------------------------------------------------- //-- Recherche des portions utiles sur les lignes static void Recadre(const TheSurface& myHS1, Standard_Real& u1, Standard_Real& v1) { Standard_Real f,l,lmf; GeomAbs_SurfaceType typs1 = myHS1->GetType(); Standard_Boolean myHS1IsUPeriodic,myHS1IsVPeriodic; switch (typs1) { case GeomAbs_Cylinder: case GeomAbs_Cone: case GeomAbs_Sphere: { myHS1IsUPeriodic = Standard_True; myHS1IsVPeriodic = Standard_False; break; } case GeomAbs_Torus: { myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_True; break; } default: { myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_False; break; } } if(myHS1IsUPeriodic) { lmf = M_PI+M_PI; //-- myHS1->UPeriod(); f = myHS1->FirstUParameter(); l = myHS1->LastUParameter(); while(u1 < f) { u1+=lmf; } while(u1 > l) { u1-=lmf; } } if(myHS1IsVPeriodic) { lmf = M_PI+M_PI; //-- myHS1->VPeriod(); f = myHS1->FirstVParameter(); l = myHS1->LastVParameter(); while(v1 < f) { v1+=lmf; } while(v1 > l) { v1-=lmf; } } } static void LineConstructor(Contap_TheSequenceOfLine& slin, const Handle(TheTopolTool)& Domain, Contap_TheLine& L, const TheSurface& Surf) { //-- ------------------------------------------------------------ //-- on decoupe la ligne en portions entre 2 vertex Standard_Real Tol = Precision::PConfusion(); Contap_IType typl = L.TypeContour(); //-- cout<<"\n ----------- Ligne Constructor "< "<Classify(gp_Pnt2d(u2,v2),Tol); if(in2 == TopAbs_OUT) { } else { //-- cout<<"ContapWLine : firtsp="<Add(L.Point(j)); } Line.SetLineOn2S(LineOn2S); Contap_ThePoint pvtx = L.Vertex(i); pvtx.SetParameter(1); Line.Add(pvtx); pvtx = L.Vertex(i+1); pvtx.SetParameter(lastp-firstp+1); Line.Add(pvtx); Line.SetTransitionOnS(L.TransitionOnS()); slin.Append(Line); } } } } else if(typl==Contap_Lin) { Standard_Real u2,v2;// u1,v1; Standard_Integer nbvtx = L.NbVertex(); //-- cout<<" Lin -> "<Classify(gp_Pnt2d(u2,v2),Tol); if(in2 == TopAbs_OUT) { } else { //-- cout<<"Contap Lin : firtsp="< "<0.000000001) { Standard_Real pmid = (firstp+lastp)*0.5; gp_Pnt Pmid = ElCLib::Value(pmid,L.Circle()); if(TheSurfaceTool::GetType(Surf)==GeomAbs_Cylinder) { ElSLib::Parameters(TheSurfaceTool::Cylinder(Surf),Pmid,u2,v2); } else if(TheSurfaceTool::GetType(Surf)==GeomAbs_Cone) { ElSLib::Parameters(TheSurfaceTool::Cone(Surf),Pmid,u2,v2); } else if(TheSurfaceTool::GetType(Surf)==GeomAbs_Sphere) { ElSLib::Parameters(TheSurfaceTool::Sphere(Surf),Pmid,u2,v2); } else { //-- cout<<" Pb ds Contap_ContourGen_2.gxx (typep)"<Classify(gp_Pnt2d(u2,v2),Tol); if(in2 == TopAbs_OUT) { } else { //-- cout<<"Contap Circle : firtsp="<0.0000000001) { Standard_Real pmid = (firstp+lastp)*0.5; gp_Pnt Pmid = ElCLib::Value(pmid,L.Circle()); if(TheSurfaceTool::GetType(Surf)==GeomAbs_Cylinder) { ElSLib::Parameters(TheSurfaceTool::Cylinder(Surf),Pmid,u2,v2); } else if(TheSurfaceTool::GetType(Surf)==GeomAbs_Cone) { ElSLib::Parameters(TheSurfaceTool::Cone(Surf),Pmid,u2,v2); } else if(TheSurfaceTool::GetType(Surf)==GeomAbs_Sphere) { ElSLib::Parameters(TheSurfaceTool::Sphere(Surf),Pmid,u2,v2); } else { //-- cout<<" Pb ds Contap_ContourGen_2.gxx (typep)"<Classify(gp_Pnt2d(u2,v2),Tol); if(in2 == TopAbs_OUT) { } else { //-- cout<<"Contap Circle *Compl* : firtsp="<Orientation(thearc); ispassing = (arcorien == TopAbs_INTERNAL || arcorien == TopAbs_EXTERNAL); TheArcTool::D1(thearc,theparam,pt2d,tg2drst); X(1) = pt2d.X(); X(2) = pt2d.Y(); PPoint.SetValue(PStart.Value(),X(1),X(2)); Func.Values(X,F,D); if (Func.IsTangent()) { PPoint.SetTangency(Standard_True); Destination(i) = seqlength+1; if (!PStart.IsNew()) { const TheVertex& vtx = PStart.Vertex(); for (k=i+1; k<=NbPoints; k++) { if (Destination(k) ==0) { const Contap_ThePathPointOfTheSearch& PStart2 = solrst.Point(k); if (!PStart2.IsNew()) { const TheVertex& vtx2 = PStart2.Vertex(); if (Domain->Identical(vtx,vtx2)) { const TheArc& thearc2 = PStart2.Arc(); theparam = PStart2.Parameter(); arcorien = Domain->Orientation(thearc2); ispassing = ispassing && (arcorien == TopAbs_INTERNAL || arcorien == TopAbs_EXTERNAL); pt2d = TheArcTool::Value(thearc2,theparam); X(1) = pt2d.X(); X(2) = pt2d.Y(); PPoint.AddUV(X(1),X(2)); Destination(k) = seqlength+1; } } } } } PPoint.SetPassing(ispassing); seqpdep.Append(PPoint); seqlength++; } else { // on a un point de depart potentiel vectg = Func.Direction3d(); dirtg = Func.Direction2d(); gp_Pnt ptbid; // TheSurfaceTool::D1(Surf,X(1),X(2),ptbid,v1,v2); Contap_TheSurfProps::DerivAndNorm(Surf,X(1),X(2),ptbid,v1,v2,normale); tg3drst = tg2drst.X()*v1 + tg2drst.Y()*v2; // normale = v1.Crossed(v2); if(normale.SquareMagnitude() < RealEpsilon()) { //-- cout<<"\n*** Contap_ContourGen_2.gxx Normale Nulle en U:"< 0. && arcorien == TopAbs_REVERSED)) { vectg.Reverse(); dirtg.Reverse(); } PPoint.SetDirections(vectg,dirtg); } else { // on garde le point comme point d`arret (tangent) PPoint.SetTangency(Standard_True); } PPoint.SetPassing(ispassing); Destination(i) = seqlength+1; seqpdep.Append(PPoint); seqlength++; } else { // traiter la transition complexe gp_Dir bidnorm(1.,1.,1.); Standard_Boolean tobeverified = Standard_False; TopAbs_Orientation LocTrans; TopTrans_CurveTransition comptrans; comptrans.Reset(vectg,bidnorm,0.); if (arcorien != TopAbs_INTERNAL && arcorien != TopAbs_EXTERNAL) { // pour essai const TheVertex& vtx = PStart.Vertex(); vtxorien = Domain->Orientation(vtx); test = test/(vectg.Magnitude()); test = test/((normale.Crossed(tg3drst)).Magnitude()); if (Abs(test) <= tole) { tobeverified = Standard_True; LocTrans = TopAbs_EXTERNAL; // et pourquoi pas INTERNAL } else { if ((test > 0. && arcorien == TopAbs_FORWARD) || (test < 0. && arcorien == TopAbs_REVERSED)){ LocTrans = TopAbs_FORWARD; } else { LocTrans = TopAbs_REVERSED; } if (arcorien == TopAbs_REVERSED) {tg3drst.Reverse();} // pas deja fait ??? } comptrans.Compare(tole,tg3drst,bidnorm,0.,LocTrans,vtxorien); } Destination(i) = seqlength+1; for (k= i+1; k<=NbPoints; k++) { if (Destination(k) == 0) { const Contap_ThePathPointOfTheSearch& PStart2 = solrst.Point(k); if (!PStart2.IsNew()) { const TheVertex& vtx2 = PStart2.Vertex(); if (Domain->Identical(PStart.Vertex(),vtx2)) { const TheArc& thearc2 = PStart2.Arc(); theparam = PStart2.Parameter(); arcorien = Domain->Orientation(thearc2); TheArcTool::D1(thearc2,theparam,pt2d,tg2drst); X(1) = pt2d.X(); X(2) = pt2d.Y(); PPoint.AddUV(X(1),X(2)); if (arcorien != TopAbs_INTERNAL && arcorien != TopAbs_EXTERNAL) { ispassing = Standard_False; tg3drst = tg2drst.X()*v1 + tg2drst.Y()*v2; test = vectg.Dot(normale.Crossed(tg3drst)); test = test/(vectg.Magnitude()); test = test /((normale.Crossed(tg3drst)).Magnitude()); vtxorien = Domain->Orientation(vtx2); if (Abs(test) <= tole) { tobeverified = Standard_True; LocTrans = TopAbs_EXTERNAL; // et pourquoi pas INTERNAL } else { if ((test > 0. && arcorien == TopAbs_FORWARD) || (test < 0. && arcorien == TopAbs_REVERSED)){ LocTrans = TopAbs_FORWARD; } else { LocTrans = TopAbs_REVERSED; } if (arcorien == TopAbs_REVERSED) {tg3drst.Reverse();} //deja fait???? } comptrans.Compare(tole,tg3drst,bidnorm,0.,LocTrans,vtxorien); } Destination(k) = seqlength+1; } } } } fairpt = Standard_True; if (!ispassing) { TopAbs_State Before = comptrans.StateBefore(); TopAbs_State After = comptrans.StateAfter(); if ((Before == TopAbs_UNKNOWN)||(After == TopAbs_UNKNOWN)) { fairpt = Standard_False; } else if (Before == TopAbs_IN) { if (After == TopAbs_IN) { ispassing = Standard_True; } else { vectg.Reverse(); dirtg.Reverse(); } } else { if (After !=TopAbs_IN) { fairpt = Standard_False; } } } // evite de partir le long d une restriction solution if (fairpt && tobeverified) { for (k=i; k <=NbPoints ; k++) { if (Destination(k)==seqlength + 1) { theparam = solrst.Point(k).Parameter(); const TheArc& thearc2 = solrst.Point(k).Arc(); arcorien = Domain->Orientation(thearc2); if (arcorien == TopAbs_FORWARD || arcorien == TopAbs_REVERSED) { TheArcTool::D1(thearc2,theparam,pt2d,tg2drst); tg3drst = tg2drst.X()*v1 + tg2drst.Y()*v2; vtxorien = Domain->Orientation(solrst.Point(k).Vertex()); if ((arcorien == TopAbs_FORWARD && vtxorien == TopAbs_REVERSED) || (arcorien == TopAbs_REVERSED && vtxorien == TopAbs_FORWARD)) { tg3drst.Reverse(); } test = vectg.Normalized().Dot(tg3drst.Normalized()); if (test >= 1. - tole) { fairpt = Standard_False; break; } } } } } if (fairpt) { PPoint.SetDirections(vectg,dirtg); PPoint.SetPassing(ispassing); seqpdep.Append(PPoint); seqlength++; } else { // il faut remettre en "ordre" si on ne garde pas le point. for (k=i; k <=NbPoints ; k++) { if (Destination(k)==seqlength + 1) { Destination(k) = -Destination(k); } } } } } } } } } } IntSurf_TypeTrans ComputeTransitionOnLine(Contap_TheSurfFunction& SFunc, const Standard_Real u, const Standard_Real v, const gp_Vec& tgline) { gp_Vec d1u,d1v; gp_Pnt pntbid; //gp_Vec tglineuv; TheSurfaceTool::D1(SFunc.Surface(),u,v,pntbid,d1u,d1v); //------------------------------------------------------ //-- Calcul de la tangente dans l espace uv --- //------------------------------------------------------ Standard_Real det,d1uT,d1vT,normu2,normv2,d1ud1v,alpha,beta; d1uT = d1u.Dot(tgline); d1vT = d1v.Dot(tgline); normu2 = d1u.Dot(d1u); normv2 = d1v.Dot(d1v); d1ud1v = d1u.Dot(d1v); det = normu2 * normv2 - d1ud1v * d1ud1v; if(det0.0) { return(IntSurf_Out); } return(IntSurf_In); } void ProcessSegments (const Contap_TheSearch& solrst, Contap_TheSequenceOfLine& slin, const Standard_Real TolArc, Contap_TheSurfFunction& SFunc, const Handle(TheTopolTool)& Domain) { Standard_Integer i,j,k; Standard_Integer nbedg = solrst.NbSegments(); Standard_Integer Nblines,Nbpts; TheArc arcRef; Contap_ThePoint ptvtx; Contap_ThePathPointOfTheSearch PStartf,PStartl; Standard_Boolean dofirst,dolast,procf,procl; Standard_Real paramf =0.,paraml =0.,U; Contap_TheLine theline; gp_Vec tgline;//,norm1,norm2; gp_Pnt valpt; gp_Vec d1u,d1v; gp_Pnt2d p2d; gp_Vec2d d2d; for (i = 1; i <= nbedg; i++) { const Contap_TheSegmentOfTheSearch& thesegsol = solrst.Segment(i); theline.SetValue(thesegsol.Curve()); // Traitement des points debut/fin du segment solution. dofirst = Standard_False; dolast = Standard_False; procf = Standard_False; procl = Standard_False; if (thesegsol.HasFirstPoint()) { dofirst = Standard_True; PStartf = thesegsol.FirstPoint(); paramf = PStartf.Parameter(); } if (thesegsol.HasLastPoint()) { dolast = Standard_True; PStartl = thesegsol.LastPoint(); paraml = PStartl.Parameter(); } // determination de la transition if (dofirst && dolast) { U = (paramf+paraml)/2.; } else if (dofirst) { U = paramf + 1.0; } else if (dolast) { U = paraml - 1.0; } else { U = 0.0; } TheArcTool::D1(thesegsol.Curve(),U,p2d,d2d); TheSurfaceTool::D1(SFunc.Surface(),p2d.X(),p2d.Y(),valpt,d1u,d1v); tgline.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); IntSurf_TypeTrans tral = ComputeTransitionOnLine(SFunc,p2d.X(),p2d.Y(),tgline); theline.SetTransitionOnS(tral); if (dofirst || dolast) { Nblines = slin.Length(); for (j=1; j<=Nblines; j++) { Nbpts = slin(j).NbVertex(); for (k=1; k<=Nbpts;k++) { ptvtx = slin(j).Vertex(k); if (dofirst) { if (ptvtx.Value().Distance(PStartf.Value()) <=TolArc) { slin(j).Vertex(k).SetMultiple(); ptvtx.SetMultiple(); ptvtx.SetParameter(paramf); theline.Add(ptvtx); procf=Standard_True; } } if (dolast) { if (ptvtx.Value().Distance(PStartl.Value()) <=TolArc) { slin(j).Vertex(k).SetMultiple(); ptvtx.SetMultiple(); ptvtx.SetParameter(paraml); theline.Add(ptvtx); procl=Standard_True; } } } // Si on a traite le pt debut et/ou fin, on ne doit pas recommencer si // il (ils) correspond(ent) a un point multiple. if (procf) { dofirst = Standard_False; } if (procl) { dolast = Standard_False; } } } // Si on n a pas trouve le point debut et./ou fin sur une des lignes // d intersection, il faut quand-meme le placer sur la restriction solution if (dofirst) { p2d = TheArcTool::Value(thesegsol.Curve(),paramf); ptvtx.SetValue(PStartf.Value(),p2d.X(),p2d.Y()); ptvtx.SetParameter(paramf); if (! PStartf.IsNew()) { ptvtx.SetVertex(PStartf.Vertex()); } theline.Add(ptvtx); } if (dolast) { p2d = TheArcTool::Value(thesegsol.Curve(),paraml); ptvtx.SetValue(PStartl.Value(),p2d.X(),p2d.Y()); ptvtx.SetParameter(paraml); if (! PStartl.IsNew()) { ptvtx.SetVertex(PStartl.Vertex()); } theline.Add(ptvtx); } // il faut chercher le points internal sur les restrictions solutions. if (thesegsol.HasFirstPoint() && thesegsol.HasLastPoint()) { ComputeInternalPointsOnRstr(theline,paramf,paraml,SFunc); } LineConstructor(slin,Domain,theline,SFunc.Surface()); //-- lbr //-- slin.Append(theline); theline.Clear(); } } void ComputeInternalPointsOnRstr (Contap_TheLine& Line, const Standard_Real Paramf, const Standard_Real Paraml, Contap_TheSurfFunction& SFunc) { // On recherche les points ou la tangente a la ligne de contour et // la direction sont alignees. // 1ere etape : recherche de changement de signe. // 2eme etape : localisation de la solution par dichotomie Standard_Integer indexinf,indexsup,i; gp_Vec tgt, vecref, vectest, vtestb, vecregard,d1u,d1v; gp_Pnt pcour; gp_Pnt2d p2d; gp_Vec2d d2d; Standard_Boolean found,ok = Standard_False,toutvu,solution; Standard_Real paramp = 0.,paraminf,paramsup,toler; if (Line.TypeContour() != Contap_Restriction) { return; } const TheArc& thearc = Line.Arc(); const TheSurface& Surf = SFunc.Surface(); Contap_TFunction TypeFunc(SFunc.FunctionType()); Standard_Integer Nbpnts = TheContTool::NbSamplesOnArc(thearc); indexinf = 1; vecregard = SFunc.Direction(); toler = TheArcTool::Resolution(thearc,Precision::Confusion()); found = Standard_False; do { paraminf = ((Nbpnts-indexinf)*Paramf + (indexinf-1)*Paraml)/(Nbpnts-1); TheArcTool::D1(thearc,paraminf,p2d,d2d); TheSurfaceTool::D1(Surf,p2d.X(),p2d.Y(),pcour,d1u,d1v); tgt.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); if (tgt.Magnitude() > gp::Resolution()) { if (TypeFunc == Contap_ContourPrs || TypeFunc==Contap_DraftPrs) { vecregard.SetXYZ(pcour.XYZ()-SFunc.Eye().XYZ()); } vecref = vecregard.Crossed(tgt); if (vecref.Magnitude() <= gp::Resolution()) { indexinf++; } else { found = Standard_True; } } else { indexinf++; } } while ((indexinf <= Nbpnts) && (!found)); indexsup = indexinf +1; toutvu = (indexsup > Nbpnts); while (!toutvu) { paramsup = ((Nbpnts-indexsup)*Paramf + (indexsup-1)*Paraml)/(Nbpnts-1); TheArcTool::D1(thearc,paramsup,p2d,d2d); TheSurfaceTool::D1(Surf,p2d.X(),p2d.Y(),pcour,d1u,d1v); tgt.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); if (tgt.Magnitude() > gp::Resolution()) { if (TypeFunc == Contap_ContourPrs || TypeFunc==Contap_DraftPrs) { vecregard.SetXYZ(pcour.XYZ()-SFunc.Eye().XYZ()); } vectest = vecregard.Crossed(tgt); } else { vectest = gp_Vec(0.,0.,0.); } if (vectest.Magnitude() <= gp::Resolution()) { // On cherche un vrai changement de signe indexsup++; } else { if (vectest.Dot(vecref) < 0.) { // Essayer de converger // cout << "Changement de signe detecte" << endl; solution = Standard_False; while (!solution) { paramp = (paraminf+paramsup)/2.; TheArcTool::D1(thearc,paramp,p2d,d2d); TheSurfaceTool::D1(Surf,p2d.X(),p2d.Y(),pcour,d1u,d1v); tgt.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); if (tgt.Magnitude() > gp::Resolution()) { if (TypeFunc == Contap_ContourPrs || TypeFunc==Contap_DraftPrs) { vecregard.SetXYZ(pcour.XYZ()-SFunc.Eye().XYZ()); } vtestb = vecregard.Crossed(tgt); } else { vtestb = gp_Vec(0.,0.,0.); } if ((vtestb.Magnitude() <= gp::Resolution())|| (Abs(paramp-paraminf) <= toler) || (Abs(paramp-paramsup) <= toler)) { // on est a la solution solution = Standard_True; ok = Standard_True; } else if (vtestb.Dot(vecref) < 0.) { paramsup = paramp; } else { paraminf = paramp; } } if (ok) { // On verifie que le point trouve ne correspond pas a un ou des // vertex deja existant(s). On teste sur le parametre paramp. for (i=1; i<=Line.NbVertex(); i++) { Contap_ThePoint& thevtx = Line.Vertex(i); if (Abs(thevtx.ParameterOnLine()-paramp) <= toler) { thevtx.SetInternal(); ok = Standard_False; // on a correspondance } } if (ok) { // il faut alors rajouter le point Contap_ThePoint internalp(pcour,p2d.X(),p2d.Y()); internalp.SetParameter(paramp); internalp.SetInternal(); Line.Add(internalp); } } paramsup = ((Nbpnts-indexsup)*Paramf + (indexsup-1)*Paraml)/(Nbpnts-1); } vecref = vectest; indexinf = indexsup; indexsup++; paraminf = paramsup; } toutvu = (indexsup > Nbpnts); } } void ComputeInternalPoints (Contap_TheLine& Line, Contap_TheSurfFunction& SFunc, const Standard_Real ureso, const Standard_Real vreso) { // On recherche les points ou la tangente a la ligne de contour et // la direction sont alignees. // 1ere etape : recheche de changement de signe. // 2eme etape : localisation de la solution par simili dichotomie Standard_Integer indexinf,indexsup,index; gp_Vec tgt, vecref, vectest, vtestb, vecregard; //gp_Pnt pprec,pcour; Standard_Boolean found,ok = Standard_False,toutvu,solution; Standard_Real paramp = 0.,U,V; math_Vector XInf(1,2),XSup(1,2),X(1,2),F(1,1); math_Matrix DF(1,1,1,2); math_Vector toler(1,2),infb(1,2),supb(1,2); if (Line.TypeContour() != Contap_Walking) { return; } Standard_Integer Nbpnts = Line.NbPnts(); const TheSurface& Surf = SFunc.Surface(); Contap_TFunction TypeFunc(SFunc.FunctionType()); toler(1) = ureso; //-- Trop long !!! TheSurfaceTool::UResolution(Surf,SFunc.Tolerance()); toler(2) = vreso; //---Beaucoup trop long !!! TheSurfaceTool::VResolution(Surf,SFunc.Tolerance()); infb(1) = TheSurfaceTool::FirstUParameter(Surf); infb(2) = TheSurfaceTool::FirstVParameter(Surf); supb(1) = TheSurfaceTool::LastUParameter(Surf); supb(2) = TheSurfaceTool::LastVParameter(Surf); math_FunctionSetRoot rsnld(SFunc,toler,30); indexinf = 1; vecregard = SFunc.Direction(); found = Standard_False; do { Line.Point(indexinf).ParametersOnS2(XInf(1),XInf(2)); SFunc.Values(XInf,F,DF); if (!SFunc.IsTangent()) { tgt = SFunc.Direction3d(); if (TypeFunc == Contap_ContourPrs || TypeFunc == Contap_DraftPrs) { vecregard.SetXYZ(Line.Point(indexinf).Value().XYZ()-SFunc.Eye().XYZ()); } vecref = vecregard.Crossed(tgt); if (vecref.Magnitude() <= gp::Resolution()) { indexinf++; } else { found = Standard_True; } } else { indexinf++; } } while ((indexinf <= Nbpnts) && (!found)); indexsup = indexinf +1; toutvu = (indexsup > Nbpnts); while (!toutvu) { Line.Point(indexsup).ParametersOnS2(XSup(1),XSup(2)); SFunc.Values(XSup,F,DF); if (!SFunc.IsTangent()) { tgt = SFunc.Direction3d(); if (TypeFunc == Contap_ContourPrs || TypeFunc == Contap_DraftPrs) { vecregard.SetXYZ(Line.Point(indexsup).Value().XYZ()-SFunc.Eye().XYZ()); } vectest = vecregard.Crossed(tgt); } else { vectest = gp_Vec(0.,0.,0.); } if (vectest.Magnitude() <= gp::Resolution()) { // On cherche un vrai changement de signe indexsup++; } else { if (vectest.Dot(vecref) < 0.) { // Essayer de converger // cout << "Changement de signe detecte" << endl; solution = Standard_False; while (!solution) { X(1) = (XInf(1) + XSup(1)) /2.; X(2) = (XInf(2) + XSup(2)) /2.; rsnld.Perform(SFunc,X,infb,supb); if (!rsnld.IsDone()) { cout << "Echec recherche internal points" << endl; solution = Standard_True; ok = Standard_False; } else { rsnld.Root(X); SFunc.Values(X,F,DF); if (Abs(F(1)) <= SFunc.Tolerance()) { if (!SFunc.IsTangent()) { tgt = SFunc.Direction3d(); if (TypeFunc == Contap_ContourPrs || TypeFunc == Contap_DraftPrs) { vecregard.SetXYZ(SFunc.Point().XYZ()-SFunc.Eye().XYZ()); } vtestb = vecregard.Crossed(tgt); } else { vtestb = gp_Vec(0.,0.,0.); } if ((vtestb.Magnitude() <= gp::Resolution())|| (Abs(X(1)-XInf(1)) <= toler(1) && Abs(X(2)-XInf(2)) <= toler(2)) || (Abs(X(1)-XSup(1)) <= toler(1) && Abs(X(2)-XSup(2)) <= toler(2))) { // on est a la solution solution = Standard_True; ok = Standard_True; } else if (vtestb.Dot(vecref) < 0.) { XSup = X; } else { XInf = X; } } else { // on n est pas sur une solution cout << "Echec recherche internal points" << endl; solution = Standard_True; ok = Standard_False; } } } if (ok) { Standard_Boolean newpoint = Standard_False; Line.Point(indexinf).ParametersOnS2(U,V); gp_Vec2d vinf(X(1)-U,X(2)-V); if (Abs(vinf.X()) <= toler(1) && Abs(vinf.Y()) <= toler(2)) { paramp = indexinf; } else { for (index = indexinf+1; index <= indexsup; index++) { Line.Point(index).ParametersOnS2(U,V); gp_Vec2d vsup(X(1)-U,X(2)-V); if (Abs(vsup.X()) <= toler(1) && Abs(vsup.Y()) <= toler(2)) { paramp = index; break; } else if (vinf.Dot(vsup) < 0.) { // on est entre les 2 points paramp = index; IntSurf_PntOn2S pt2s; pt2s.SetValue(SFunc.Point(),Standard_False,X(1),X(2)); Line.LineOn2S()->InsertBefore(index,pt2s); //-- Il faut decaler les parametres des vertex situes entre //-- index et NbPnts ################################### for(Standard_Integer v=1; v<=Line.NbVertex(); v++) { Contap_ThePoint& Vertex = Line.Vertex(v); if(Vertex.ParameterOnLine() >= index) { Vertex.SetParameter(Vertex.ParameterOnLine()+1); } } Nbpnts = Nbpnts+1; indexsup = indexsup+1; newpoint = Standard_True; break; } else { vinf = vsup; } } } Standard_Integer v; if (!newpoint) { // on est sur un point de cheminement. On regarde alors // la correspondance avec un vertex existant. newpoint = Standard_True; for (v=1; v<= Line.NbVertex(); v++) { Contap_ThePoint& Vertex = Line.Vertex(v); if(Vertex.ParameterOnLine() == paramp) { Vertex.SetInternal(); newpoint = Standard_False; } } } if (newpoint && paramp >1. && paramp < Nbpnts) { // on doit creer un nouveau vertex. Contap_ThePoint internalp(SFunc.Point(),X(1),X(2)); internalp.SetParameter(paramp); internalp.SetInternal(); Line.Add(internalp); } } Line.Point(indexsup).ParametersOnS2(XSup(1),XSup(2)); } vecref = vectest; indexinf = indexsup; indexsup++; XInf = XSup; } toutvu = (indexsup > Nbpnts); } } void Contap_ContourGen::Perform (const Handle(TheTopolTool)& Domain) { done = Standard_False; slin.Clear(); Standard_Integer i,j,k,Nbvt1,Nbvt2,ivt1,ivt2; Standard_Integer NbPointRst,NbPointIns; Standard_Integer Nblines, Nbpts, indfirst, indlast; Standard_Real U,V; gp_Pnt2d pt2d; gp_Vec2d d2d; gp_Pnt ptonsurf; gp_Vec d1u,d1v,normale,tgtrst,tgline; Standard_Real currentparam; IntSurf_Transition TLine,TArc; Contap_TheLine theline; Contap_ThePoint ptdeb,ptfin; Contap_ThePathPointOfTheSearch PStartf,PStartl; // Standard_Real TolArc = 1.e-5; Standard_Real TolArc = Precision::Confusion(); const TheSurface& Surf = mySFunc.Surface(); Standard_Real EpsU = TheSurfaceTool::UResolution(Surf,Precision::Confusion()); Standard_Real EpsV = TheSurfaceTool::VResolution(Surf,Precision::Confusion()); Standard_Real Preci = Min(EpsU,EpsV); // Standard_Real Fleche = 5.e-1; // Standard_Real Pas = 5.e-2; Standard_Real Fleche = 0.01; Standard_Real Pas = 0.005; // lbr: Il y avait Pas 0.2 -> Manque des Inters sur restr ; devrait faire un mini de 5 pts par lignes //-- le 23 janvier 98 0.05 -> 0.01 //-- ******************************************************************************** Janvier 98 Bnd_Box B1; Standard_Boolean Box1OK = Standard_True; Standard_Real Uinf = Surf->FirstUParameter(); Standard_Real Vinf = Surf->FirstVParameter(); Standard_Real Usup = Surf->LastUParameter(); Standard_Real Vsup = Surf->LastVParameter(); Standard_Boolean Uinfinfinite = Precision::IsNegativeInfinite(Uinf); Standard_Boolean Usupinfinite = Precision::IsPositiveInfinite(Usup); Standard_Boolean Vinfinfinite = Precision::IsNegativeInfinite(Vinf); Standard_Boolean Vsupinfinite = Precision::IsPositiveInfinite(Vsup); if( Uinfinfinite || Usupinfinite || Vinfinfinite || Vsupinfinite) { Box1OK = Standard_False; } else { BndLib_AddSurface::Add(Surf->Surface(),1e-8,B1); } Standard_Real x0,y0,z0,x1,y1,z1,dx,dy,dz; if(Box1OK) { B1.Get(x0,y0,z0,x1,y1,z1); dx=x1-x0; dy=y1-y0; dz=z1-z0; } else { dx=dy=dz=1.0; } if(dx10000.0) dx=10000.0; Fleche*=dx; TolArc*=dx; //-- ******************************************************************************** //gp_Pnt valpt; //jag 940616 SFunc.Set(1.e-8); // tolerance sur la fonction mySFunc.Set(Precision::Confusion()); // tolerance sur la fonction Standard_Boolean RecheckOnRegularity = Standard_True; solrst.Perform(myAFunc,Domain,TolArc,TolArc,RecheckOnRegularity); if (!solrst.IsDone()) { return; } NbPointRst = solrst.NbPoints(); IntSurf_SequenceOfPathPoint seqpdep; TColStd_Array1OfInteger Destination(1,NbPointRst+1); Destination.Init(0); if (NbPointRst != 0) { ComputeTangency(solrst,Domain,mySFunc,seqpdep,Destination); } //jag 940616 solins.Perform(SFunc,Surf,Domain,1.e-6); // 1.e-6 : tolerance dans l espace. solins.Perform(mySFunc,Surf,Domain,Precision::Confusion()); NbPointIns = solins.NbPoints(); IntSurf_SequenceOfInteriorPoint seqpins; if (NbPointIns != 0) { Standard_Boolean bKeepAllPoints = Standard_False; //IFV begin if(solrst.NbSegments() <= 0) { if(mySFunc.FunctionType() == Contap_ContourStd) { const TheSurface& Surf = mySFunc.Surface(); if(TheSurfaceTool::GetType(Surf) == GeomAbs_Torus) { gp_Torus aTor = TheSurfaceTool::Torus(Surf); gp_Dir aTorDir = aTor.Axis().Direction(); gp_Dir aProjDir = mySFunc.Direction(); if(aTorDir.Dot(aProjDir) < Precision::Confusion()) { bKeepAllPoints = Standard_True; } } } } if(bKeepAllPoints) { Standard_Integer Nbp = solins.NbPoints(), indp; for (indp=1; indp <= Nbp; indp++) { const IntSurf_InteriorPoint& pti = solins.Value(indp); seqpins.Append(pti); } } //IFV - end else { KeepInsidePoints(solins,solrst,mySFunc,seqpins); } } if (seqpdep.Length() != 0 || seqpins.Length() != 0) { Contap_TheIWalking iwalk(Preci,Fleche,Pas); iwalk.Perform(seqpdep,seqpins,mySFunc ,Surf); if(!iwalk.IsDone()) { return; } Nblines = iwalk.NbLines(); for (j=1; j<=Nblines; j++) { IntSurf_TypeTrans TypeTransOnS = IntSurf_Undecided; const Handle(Contap_TheIWLineOfTheIWalking)& iwline = iwalk.Value(j); Nbpts = iwline->NbPoints(); theline.SetLineOn2S(iwline->Line()); // jag 941018 On calcule une seule fois la transition tgline = iwline->TangentVector(k); iwline->Line()->Value(k).ParametersOnS2(U,V); TypeTransOnS = ComputeTransitionOnLine(mySFunc,U,V,tgline); theline.SetTransitionOnS(TypeTransOnS); //--------------------------------------------------------------------- //-- On ajoute a la liste des vertex les 1er et dernier points de la - //-- ligne de cheminement si ceux-ci ne sont pas presents - //--------------------------------------------------------------------- if (iwline->HasFirstPoint()) { indfirst = iwline->FirstPointIndex(); const IntSurf_PathPoint& PPoint = seqpdep(indfirst); Standard_Integer themult = PPoint.Multiplicity(); for (i=NbPointRst; i>=1; i--) { if (Destination(i) == indfirst) { PPoint.Parameters(themult,U,V); ptdeb.SetValue(PPoint.Value(),U,V); ptdeb.SetParameter(1.0); const Contap_ThePathPointOfTheSearch& PStart = solrst.Point(i); const TheArc& currentarc = PStart.Arc(); currentparam = PStart.Parameter(); if (!iwline->IsTangentAtBegining()) { TheArcTool::D1(currentarc,currentparam,pt2d,d2d); Contap_TheSurfProps::DerivAndNorm(Surf,pt2d.X(),pt2d.Y(), ptonsurf,d1u,d1v,normale); tgtrst = d2d.X()*d1u; tgtrst.Add(d2d.Y()*d1v); IntSurf::MakeTransition(PPoint.Direction3d(),tgtrst,normale, TLine,TArc); } else {// a voir. En effet, on a cheminer. Si on est sur un point // debut, on sait qu'on rentre dans la matiere TLine.SetValue(); TArc.SetValue(); } ptdeb.SetArc(currentarc,currentparam,TLine,TArc); if (!solrst.Point(i).IsNew()) { ptdeb.SetVertex(PStart.Vertex()); } theline.Add(ptdeb); themult--; } } } else { iwline->Value(1).ParametersOnS2(U,V); ptdeb.SetValue(theline.Point(1).Value(),U,V); ptdeb.SetParameter(1.0); theline.Add(ptdeb); } if (iwline->HasLastPoint()) { indlast = iwline->LastPointIndex(); const IntSurf_PathPoint& PPoint = seqpdep(indlast); Standard_Integer themult = PPoint.Multiplicity(); for (i=NbPointRst; i>=1; i--) { if (Destination(i) == indlast) { PPoint.Parameters(themult,U,V); ptfin.SetValue(PPoint.Value(),U,V); ptfin.SetParameter((Standard_Real)(Nbpts)); const Contap_ThePathPointOfTheSearch& PStart = solrst.Point(i); const TheArc& currentarc = PStart.Arc(); currentparam = PStart.Parameter(); if (!iwline->IsTangentAtEnd()) { TheArcTool::D1(currentarc,currentparam,pt2d,d2d); Contap_TheSurfProps::DerivAndNorm(Surf,pt2d.X(),pt2d.Y(), ptonsurf,d1u,d1v,normale); tgtrst = d2d.X()*d1u; tgtrst.Add(d2d.Y()*d1v); IntSurf::MakeTransition(PPoint.Direction3d().Reversed(), tgtrst,normale,TLine,TArc); } else { TLine.SetValue(); TArc.SetValue(); } ptfin.SetArc(currentarc,currentparam,TLine,TArc); if (!solrst.Point(i).IsNew()) { ptfin.SetVertex(PStart.Vertex()); } theline.Add(ptfin); themult--; } } } else { iwline->Value(Nbpts).ParametersOnS2(U,V); ptfin.SetValue(theline.Point(Nbpts).Value(),U,V); ptfin.SetParameter((Standard_Real)(Nbpts)); theline.Add(ptfin); } ComputeInternalPoints(theline,mySFunc,EpsU,EpsV); LineConstructor(slin,Domain,theline,Surf); //-- lbr //-- slin.Append(theline); theline.ResetSeqOfVertex(); } Nblines = slin.Length(); for (j=1; j<=Nblines-1; j++) { const Contap_TheLine& theli = slin(j); Nbvt1 = theli.NbVertex(); for (ivt1=1; ivt1<=Nbvt1; ivt1++) { if (!theli.Vertex(ivt1).IsOnArc()) { const gp_Pnt& pttg1 = theli.Vertex(ivt1).Value(); for (k=j+1; k<=Nblines;k++) { const Contap_TheLine& theli2 = slin(k); Nbvt2 = theli2.NbVertex(); for (ivt2=1; ivt2<=Nbvt2; ivt2++) { if (!theli2.Vertex(ivt2).IsOnArc()) { const gp_Pnt& pttg2 = theli2.Vertex(ivt2).Value(); if (pttg1.Distance(pttg2) <= TolArc) { theli.Vertex(ivt1).SetMultiple(); theli2.Vertex(ivt2).SetMultiple(); } } } } } } } } // jag 940620 On ajoute le traitement des restrictions solutions. if (solrst.NbSegments() !=0) { ProcessSegments(solrst,slin,TolArc,mySFunc,Domain); } // Ajout crad pour depanner CMA en attendant mieux if (solrst.NbSegments() !=0) { Nblines = slin.Length(); for (j=1; j<=Nblines; j++) { const Contap_TheLine& theli = slin(j); if (theli.TypeContour() == Contap_Walking) { Nbvt1 = theli.NbVertex(); for (ivt1=1; ivt1<=Nbvt1; ivt1++) { Contap_ThePoint& ptvt = theli.Vertex(ivt1); if (!ptvt.IsOnArc() && !ptvt.IsMultiple()) { Standard_Real Up,Vp; ptvt.Parameters(Up,Vp); gp_Pnt2d toproj(Up,Vp); Standard_Boolean projok; for (k=1; k<=Nblines;k++) { if (slin(k).TypeContour() == Contap_Restriction) { const TheArc& thearc = slin(k).Arc(); Standard_Real paramproj; gp_Pnt2d Ptproj; projok = TheContTool::Project(thearc,toproj,paramproj,Ptproj); if (projok) { Standard_Real dist = Ptproj.Distance(gp_Pnt2d(Up,Vp)); if (dist <= Preci) { // Calcul de la transition TheArcTool::D1(thearc,paramproj,Ptproj,d2d); // TheSurfaceTool::D1(Surf,Ptproj.X(),Ptproj.Y(), // ptonsurf,d1u,d1v); // normale = d1u.Crossed(d1v); Contap_TheSurfProps::DerivAndNorm (Surf,Ptproj.X(),Ptproj.Y(),ptonsurf,d1u,d1v,normale); tgtrst = d2d.X()*d1u; tgtrst.Add(d2d.Y()*d1v); Standard_Integer Paraml = (Standard_Integer) ptvt.ParameterOnLine(); if (Paraml == theli.NbPnts()) { tgline = gp_Vec(theli.Point(Paraml-1).Value(), ptvt.Value()); } else { tgline = gp_Vec(ptvt.Value(), theli.Point(Paraml+1).Value()); } IntSurf::MakeTransition(tgline,tgtrst,normale, TLine,TArc); ptvt.SetArc(thearc,paramproj,TLine,TArc); ptvt.SetMultiple(); ptdeb.SetValue(ptonsurf,Ptproj.X(),Ptproj.Y()); ptdeb.SetParameter(paramproj); ptdeb.SetMultiple(); slin(k).Add(ptdeb); break; } else { projok = Standard_False; } } } else { projok = Standard_False; } if (projok) { break; } } } } } } } done = Standard_True; }