// Created on: 1993-03-22 // Created by: Laurent BUCHARD // Copyright (c) 1993-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 #ifdef DRAW #include #endif //======================================================================= //function : Constructor //purpose : //======================================================================= ApproxInt_MultiLine::ApproxInt_MultiLine() { PtrOnmySvSurfaces = NULL; myLine = NULL; indicemin = 0; indicemax = 0; nbp3d = 0; nbp2d = 0; myApproxU1V1 = Standard_False; myApproxU2V2 = Standard_False; p2donfirst = Standard_True; Xo = 0.; Yo = 0.; Zo = 0.; U1o = 0.; V1o = 0.; U2o = 0.; V2o = 0.; } //======================================================================= //function : Constructor //purpose : //======================================================================= ApproxInt_MultiLine:: ApproxInt_MultiLine(const Handle_TheLine& line, const Standard_Address svsurf, const Standard_Integer NbP3d, const Standard_Integer NbP2d, const Standard_Boolean ApproxU1V1, const Standard_Boolean ApproxU2V2, const Standard_Real xo, const Standard_Real yo, const Standard_Real zo, const Standard_Real u1o, const Standard_Real v1o, const Standard_Real u2o, const Standard_Real v2o, const Standard_Boolean P2DOnFirst, const Standard_Integer IndMin, const Standard_Integer IndMax): PtrOnmySvSurfaces(svsurf), myLine(line), indicemin(Min(IndMin, IndMax)), indicemax(Max(IndMin, IndMax)), nbp3d(NbP3d), nbp2d(NbP2d), myApproxU1V1(ApproxU1V1), myApproxU2V2(ApproxU2V2), p2donfirst(P2DOnFirst), Xo(xo), Yo(yo), Zo(zo), U1o(u1o), V1o(v1o), U2o(u2o), V2o(v2o) { #ifdef OCCT_DEBUG //if(indicemin == indicemax) //{ // cout<<"ApproxInt_MultiLine: indicemin = indicemax = " << indicemin << endl; //} #endif } //======================================================================= //function : Constructor //purpose : //======================================================================= ApproxInt_MultiLine:: ApproxInt_MultiLine(const Handle_TheLine& line, const Standard_Integer NbP3d, const Standard_Integer NbP2d, const Standard_Boolean ApproxU1V1, const Standard_Boolean ApproxU2V2, const Standard_Real xo, const Standard_Real yo, const Standard_Real zo, const Standard_Real u1o, const Standard_Real v1o, const Standard_Real u2o, const Standard_Real v2o, const Standard_Boolean P2DOnFirst, const Standard_Integer IndMin, const Standard_Integer IndMax): PtrOnmySvSurfaces(0), myLine(line), indicemin(Min(IndMin, IndMax)), indicemax(Max(IndMin, IndMax)), nbp3d(NbP3d), nbp2d(NbP2d), myApproxU1V1(ApproxU1V1), myApproxU2V2(ApproxU2V2), p2donfirst(P2DOnFirst), Xo(xo), Yo(yo), Zo(zo), U1o(u1o), V1o(v1o), U2o(u2o), V2o(v2o) { #ifdef OCCT_DEBUG //if(indicemin == indicemax) //{ // cout<<"ApproxInt_MultiLine: indicemin = indicemax = " << indicemin << endl; //} #endif } //-------------------------------------------------------------------------------- Standard_Integer ApproxInt_MultiLine::FirstPoint() const { return indicemin; } //-------------------------------------------------------------------------------- Standard_Integer ApproxInt_MultiLine::LastPoint() const { return indicemax; } //-------------------------------------------------------------------------------- Approx_Status ApproxInt_MultiLine::WhatStatus() const { if(PtrOnmySvSurfaces) return Approx_PointsAdded; else return Approx_NoPointsAdded; } //-------------------------------------------------------------------------------- Standard_Integer ApproxInt_MultiLine::NbP3d() const { return nbp3d; } //-------------------------------------------------------------------------------- Standard_Integer ApproxInt_MultiLine::NbP2d() const { return nbp2d; } //================================================================================ void ApproxInt_MultiLine::Value(const Standard_Integer Index, TColgp_Array1OfPnt& TabPnt) const { const gp_Pnt aP = myLine->Point(Index).Value(); TabPnt(1).SetCoord(aP.X()+Xo, aP.Y()+Yo, aP.Z()+Zo); } //======================================================================= //function : Value //purpose : //======================================================================= void ApproxInt_MultiLine::Value(const Standard_Integer Index, TColgp_Array1OfPnt2d& TabPnt2d) const { IntSurf_PntOn2S POn2S(myLine->Point(Index)); Standard_Real u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0; POn2S.Parameters(u1, v1, u2, v2); if(nbp2d==1) { if(p2donfirst) { TabPnt2d(1).SetCoord(u1+U1o, v1+V1o); } else { TabPnt2d(1).SetCoord(u2+U2o, v2+V2o); } } else { TabPnt2d(1).SetCoord(u1+U1o, v1+V1o); if(TabPnt2d.Length() >= 2) { TabPnt2d(2).SetCoord(u2+U2o, v2+V2o); } } } //======================================================================= //function : Value //purpose : //======================================================================= void ApproxInt_MultiLine::Value(const Standard_Integer Index, TColgp_Array1OfPnt& TabPnt, TColgp_Array1OfPnt2d& TabPnt2d) const { Value(Index, TabPnt); Value(Index, TabPnt2d); } //======================================================================= //function : Tangency //purpose : //======================================================================= Standard_Boolean ApproxInt_MultiLine::Tangency( const Standard_Integer Index, TColgp_Array1OfVec& TabVec) const { if(PtrOnmySvSurfaces==NULL) return Standard_False; const IntSurf_PntOn2S& POn2S = myLine->Point(Index); Standard_Real u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0; POn2S.Parameters(u1,v1,u2,v2); Standard_Boolean ret= ((TheSvSurfaces *)PtrOnmySvSurfaces)->Tangency(u1, v1, u2, v2, TabVec(1)); if(!ret) { TabVec(1).SetCoord(0.0, 0.0, 0.0); } return ret; } //======================================================================= //function : Tangency //purpose : //======================================================================= Standard_Boolean ApproxInt_MultiLine::Tangency( const Standard_Integer Index, TColgp_Array1OfVec2d& TabVec2d) const { if(PtrOnmySvSurfaces==NULL) return Standard_False; const IntSurf_PntOn2S& POn2S = myLine->Point(Index); Standard_Real u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0; POn2S.Parameters(u1,v1,u2,v2); Standard_Boolean ret = Standard_False; if(nbp2d==1) { if(p2donfirst) { ret=((TheSvSurfaces *)PtrOnmySvSurfaces)->TangencyOnSurf1(u1, v1, u2, v2, TabVec2d(1)); } else { ret=((TheSvSurfaces *)PtrOnmySvSurfaces)->TangencyOnSurf2(u1, v1, u2, v2, TabVec2d(1)); } } else { ret=((TheSvSurfaces *)PtrOnmySvSurfaces)->TangencyOnSurf1(u1, v1, u2, v2, TabVec2d(1)); if(ret) { if(TabVec2d.Length()>=2) { ret = (ret && ((TheSvSurfaces *)PtrOnmySvSurfaces)-> TangencyOnSurf2(u1, v1, u2, v2, TabVec2d(2))); } } } if(!ret) { TabVec2d(1) = gp_Vec2d(0.0, 0.0); if(TabVec2d.Length() >= 2) { TabVec2d(2) = gp_Vec2d(0.0,0.0); } } return ret; } //======================================================================= //function : Tangency //purpose : //======================================================================= Standard_Boolean ApproxInt_MultiLine::Tangency( const Standard_Integer Index, TColgp_Array1OfVec& TabVec, TColgp_Array1OfVec2d& TabVec2d) const { return (Tangency(Index, TabVec) && Tangency(Index, TabVec2d)); } //======================================================================= //function : MakeMLBetween //purpose : //======================================================================= ApproxInt_MultiLine ApproxInt_MultiLine::MakeMLBetween( const Standard_Integer Low, const Standard_Integer High, const Standard_Integer aNbPntsToInsert) const { if(PtrOnmySvSurfaces==NULL) { //-- cout<<"\n Erreur dans : ApproxInt_MultiLine ApproxInt_MultiLine::MakeMLBetween "<GetUseSolver(); if (!aSaveUseSolver) { ((TheSvSurfaces *)PtrOnmySvSurfaces)->SetUseSolver(Standard_True); } Standard_Integer NbPntsToInsert=aNbPntsToInsert; if(NbPntsToInsert<(High-Low)) NbPntsToInsert=(High-Low); Standard_Integer NbPnts = NbPntsToInsert + High - Low + 1; Standard_Integer NbPntsmin = High-Low; NbPntsmin+=NbPntsmin; if(NbPntsPoint(Low).Parameters(u1,v1,u2,v2); U1(Low) = u1; V1(Low) = v1; U2(Low) = u2; V2(Low) = v2; AC(Low) =0.0; #if 0 for( i=Low+1; i<=High; i++) { myLine->Point(i).Parameters(u1,v1,u2,v2); U1(i) = u1; V1(i) = v1; U2(i) = u2; V2(i) = v2; Standard_Real du1=u1-U1(i-1); Standard_Real dv1=v1-V1(i-1); AC(i) = AC(i-1) + sqrt((du1*du1)+(dv1*dv1)); } #else //-- Essai du 19 juin 96 (parametrage selon abs curv en XYZ) for( i=Low+1; i<=High; i++) { myLine->Point(i).Parameters(u1,v1,u2,v2); U1(i) = u1; V1(i) = v1; U2(i) = u2; V2(i) = v2; AC(i) = AC(i-1) + (myLine->Point(i-1).Value()).Distance(myLine->Point(i).Value()); } #endif //------------------------------------------------------------- //-- Creation des structures contenant les resultats Handle(IntSurf_LineOn2S) ResultPntOn2SLine = new IntSurf_LineOn2S(); IntSurf_PntOn2S StartPOn2S; TColStd_Array1OfReal StartParams(1,4); ds = AC(High) / (NbPnts-1); Standard_Integer Indice = Low; Standard_Boolean HasBeenInserted = Standard_False; Standard_Real dsmin = ds*0.3; Standard_Real smax = AC(High); for(i=2,s=ds; (s < smax && Indice <= High-1); i++,s+=ds) { //---------------------------------------------------------- //-- Recherche des indices des points -- //-- Point : 2 i NbPnts-1 -- //-- s s -- //-- Current Indice tel que AC(Indice)<= s < AC(Indice+1) -- //---------------------------------------------------------- while(AC(Indice+1) <= s) { if(!HasBeenInserted) ResultPntOn2SLine->Add(myLine->Point(Indice)); HasBeenInserted = Standard_False; Indice++; if (Indice == High) break; } if (Indice == High) break; if(!HasBeenInserted && AC(Indice) <= s) { ResultPntOn2SLine->Add(myLine->Point(Indice)); HasBeenInserted = Standard_True; } Standard_Real a = s - AC(Indice); Standard_Real b = AC(Indice+1) - s; Standard_Real nab = 1.0/(a+b); //---------------------------------------------------------- //-- Verification : Si Dist au prochain point < dsmin -- //-- Si Dist au precedent point < dsmin -- //-- -- //---------------------------------------------------------- if((a>dsmin) && (b>dsmin)) { u1 = (U1(Indice) * b + U1(Indice+1) * a) * nab; v1 = (V1(Indice) * b + V1(Indice+1) * a) * nab; u2 = (U2(Indice) * b + U2(Indice+1) * a) * nab; v2 = (V2(Indice) * b + V2(Indice+1) * a) * nab; if(((TheSvSurfaces *)PtrOnmySvSurfaces)->Compute(u1,v1,u2,v2,P,T,TS1,TS2)) { StartPOn2S.SetValue(P,u1,v1,u2,v2); //-- cout<<" Insertion du point calcule : "<Add(StartPOn2S); } else { //-- cout<<" Probleme Non Traite ds ApproxInt_ApproxIntIntersection "<Add(myLine->Point(Indice)); //-- cout<<" Insertion du point :"<Add(myLine->Point(Indice)); HasBeenInserted = Standard_True; } } else { s+= (dsmin - ds); } } } ResultPntOn2SLine->Add(myLine->Point(High)); //-- Point NbPnts Handle(TheLine) temp = new TheLine(ResultPntOn2SLine,Standard_False); //-- Verification a posteriori //-- On verifie qu il n y a pas de virage trop important en 2d et en 3d temp->Point(1).Parameters(u1,v1,u2,v2); gp_Pnt2d P1A(u1,v1); gp_Pnt2d P2A(u2,v2); temp->Point(2).Parameters(u1,v1,u2,v2); gp_Pnt2d P1B(u1,v1); gp_Pnt2d P2B(u2,v2); gp_Pnt2d P1C,P2C; Standard_Integer CodeErreur=0; for(i=3,NbPnts=temp->NbPnts();CodeErreur==0 && i<=NbPnts; i++) { Standard_Real d,du,dv,duv2; temp->Point(i).Parameters(u1,v1,u2,v2); //-- Virage P1A P1B P1C P1C.SetCoord(u1,v1); du = P1B.X()-P1A.X(); dv = P1B.Y()-P1A.Y(); duv2= 0.25*(du*du+dv*dv); u1 = P1B.X() + du; v1 = P1B.Y() + dv; du = P1C.X() - u1; dv = P1C.Y() - v1; d = du*du+dv*dv; if(d>duv2) { CodeErreur = 1; CodeErreur = 1; break; } //-- Virage P2A P2B P2C P2C.SetCoord(u2,v2); du = P2B.X()-P2A.X(); dv = P2B.Y()-P2A.Y(); duv2= 0.25*(du*du+dv*dv); u2 = P2B.X() + du; v2 = P2B.Y() + dv; du = P2C.X() - u2; dv = P2C.Y() - v2; d = du*du+dv*dv; if(d>duv2) { CodeErreur = 2; break; } P1A=P1B; P2A=P2B; P1B=P1C; P2B=P2C; } #ifdef OCCT_DEBUG //if (temp->NbPnts() < NbPntsToInsert + High - Low + 1) //{ // cout<<" *** Pas assez de points entre :"<< // Low<<" et "< "<NbPnts()<NbPnts() >= NbPntsToInsert + High - Low + 1) && (CodeErreur==0)) { ((TheSvSurfaces *)PtrOnmySvSurfaces)->SetUseSolver(aSaveUseSolver); return (ApproxInt_MultiLine( temp, (High-Low>10)? PtrOnmySvSurfaces : NULL, nbp3d, nbp2d, myApproxU1V1, myApproxU2V2, Xo,Yo,Zo, U1o,V1o, U2o,V2o, p2donfirst, 1,ResultPntOn2SLine->NbPoints())); } else { //-- cout<<" ApproxInt_MultiLine "<SetUseSolver(aSaveUseSolver); theNewMultiLine = ApproxInt_MultiLine( temp, PtrOnmySvSurfaces, nbp3d, nbp2d, myApproxU1V1, myApproxU2V2, Xo,Yo,Zo, U1o,V1o, U2o,V2o, p2donfirst, 1,ResultPntOn2SLine->NbPoints()); return Standard_True; } //======================================================================= //function : Dump //purpose : //======================================================================= void ApproxInt_MultiLine::Dump() const { TColgp_Array1OfPnt anArr1(1, 1); TColgp_Array1OfPnt2d anArr2(1, 2); const Standard_Integer anIndF = FirstPoint(), anIndL = LastPoint(); for(Standard_Integer ind = anIndF; ind <= anIndL; ind++) { Value(ind, anArr1, anArr2); printf("%4d [%+10.20f %+10.20f %+10.20f] " "[%+10.20f %+10.20f] [%+10.20f %+10.20f]\n", ind, anArr1(1).X(), anArr1(1).Y(), anArr1(1).Z(), anArr2(1).X(), anArr2(1).Y(),anArr2(2).X(),anArr2(2).Y()); } }