// Created on: 1992-05-07 // Created by: Jacques GOUSSARD // Copyright (c) 1992-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. // Modified by skv - Thu Jan 15 15:57:15 2004 OCC4455 #include #include #include #include #include #include #include #include #include #include #include #include #include static void PutPointsOnLine(const Handle(Adaptor3d_HSurface)& S1, const Handle(Adaptor3d_HSurface)& S2, const IntPatch_SequenceOfPathPointOfTheSOnBounds&, const IntPatch_SequenceOfLine&, const Standard_Boolean, const Handle(Adaptor3d_TopolTool)&, const IntSurf_Quadric&, const IntSurf_Quadric&, const Standard_Boolean, const Standard_Real); static Standard_Boolean MultiplePoint(const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt, const Handle(Adaptor3d_TopolTool)& Domain, const IntSurf_Quadric& QuadSurf, const gp_Vec& Normale, const IntPatch_SequenceOfLine& slin, TColStd_Array1OfInteger& Done, TColStd_Array1OfInteger& UsedLine, const Standard_Integer Index, const Standard_Boolean OnFirst, const Standard_Real theToler); static Standard_Boolean PointOnSecondDom(const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt, const Handle(Adaptor3d_TopolTool)& Domain, const IntSurf_Quadric& QuadSurf, const gp_Vec& Normale, const gp_Vec& Vtgint, const Handle(IntPatch_Line)& lin, TColStd_Array1OfInteger& Done, const Standard_Integer Index, const Standard_Real theToler); static Standard_Boolean SingleLine (const gp_Pnt&, const Handle(IntPatch_Line)&, const Standard_Real, Standard_Real&, gp_Vec&); static Standard_Boolean FindLine(gp_Pnt& Psurf, const IntPatch_SequenceOfLine& slin, const Standard_Real Tol, TColStd_ListOfReal& theLParams, gp_Vec& Vtgtint, Standard_Integer& theLineIdx, Standard_Integer OnlyThisLine, const Handle(Adaptor2d_HCurve2d)& thearc, Standard_Real& theparameteronarc, gp_Pnt& thepointonarc, const IntSurf_Quadric& QuadSurf1, const IntSurf_Quadric& QuadSurf2, Standard_Real& theOutputToler); static void ProcessSegments (const IntPatch_SequenceOfSegmentOfTheSOnBounds&, IntPatch_SequenceOfLine&, const IntSurf_Quadric&, const IntSurf_Quadric&, const Standard_Boolean, const Standard_Real); static void ProcessRLine (IntPatch_SequenceOfLine&, const IntSurf_Quadric&, const IntSurf_Quadric&, const Standard_Real, const Standard_Boolean theIsReqToKeepRLine); //-- le calcul de dist est completement faux ds la routine ci dessous a revoir (lbr le 18 nov 97) Standard_Boolean IntersectionWithAnArc(gp_Pnt& PSurf, const Handle(IntPatch_ALine)& alin, Standard_Real& para, const Handle(Adaptor2d_HCurve2d)& thearc, Standard_Real& _theparameteronarc, gp_Pnt& thepointonarc, const IntSurf_Quadric& QuadSurf, const Standard_Real u0alin, const Standard_Real u1alin) { Standard_Real dtheta,theta; #ifdef OCCT_DEBUG //Standard_Real u,v,A,B,C,cost,sint,sign; #endif //-- recherche bete du point le plus proche de thearc->Value(...) dtheta = (u1alin-u0alin)*0.01; Standard_Real du=0.000000001; if (du >= dtheta) du = dtheta/2; Standard_Real distmin = RealLast(); Standard_Real thetamin = 0.; Standard_Real theparameteronarc = _theparameteronarc; for(Standard_Real _theta=u0alin+dtheta; _theta<=u1alin-dtheta; _theta+=dtheta) { gp_Pnt P=alin->Value(_theta); Standard_Real d=P.Distance(PSurf); if(dValue(thetamin); Standard_Real ua0,va0; QuadSurf.Parameters(pp0,ua0,va0); gp_Pnt2d p2d; gp_Vec2d d2d; thearc->D1(theparameteronarc,p2d,d2d); gp_Vec2d PaPr(gp_Pnt2d(ua0,va0),p2d); distinit=PaPr.Magnitude(); } theta = thetamin; //-- recherche a partir de theta et theparameteronarc Standard_Boolean cpasok=Standard_True; Standard_Integer nbiter=0; Standard_Real drmax = (thearc->LastParameter() - thearc->FirstParameter())*0.05; Standard_Real damax = (u1alin-u0alin)*0.05; bestdist = RealLast(); do { Standard_Real ua0,va0,ua1,va1; //-- alin->Curve().InternalUVValue(theta,ua0,va0,A,B,C,cost,sint,sign); //-- alin->Curve().InternalUVValue(theta+du,ua1,va1,A,B,C,cost,sint,sign); gp_Pnt pp0 = alin->Value(theta); gp_Pnt pp1 = alin->Value(theta+du); QuadSurf.Parameters(pp0,ua0,va0); QuadSurf.Parameters(pp1,ua1,va1); gp_Vec2d D1a((ua1-ua0)/du,(va1-va0)/du); gp_Pnt2d p2d; gp_Vec2d d2d; thearc->D1(theparameteronarc,p2d,d2d); gp_Vec2d PaPr(gp_Pnt2d(ua0,va0),p2d); Standard_Real pbd=PaPr.Magnitude(); if(bestdist>pbd) { bestdist = pbd; bestpara = theparameteronarc; besttheta = theta; } D1a.SetCoord(-D1a.X(),-D1a.Y()); Standard_Real d = D1a.X() * d2d.Y() - D1a.Y() * d2d.X(); Standard_Real da = (-PaPr.X())* d2d.Y() - (-PaPr.Y()) * d2d.X(); Standard_Real dr = D1a.X() * (-PaPr.Y()) - D1a.Y() * (-PaPr.X()); if(Abs(d)>1e-15) { da/=d; dr/=d; } else { if(Abs(PaPr.X())>Abs(PaPr.Y())) { Standard_Real xx=PaPr.X(); xx*=0.5; if(D1a.X()) { da = -xx/D1a.X(); } if(d2d.X()) { dr = -xx/d2d.X(); } } else { Standard_Real yy=PaPr.Y(); yy*=0.5; if(D1a.Y()) { da = -yy/D1a.Y(); } if(d2d.Y()) { dr = -yy/d2d.Y(); } } } //-- Standard_Real da = -PaPr.Dot(D1a); //-- Standard_Real dr = -PaPr.Dot(d2d); if(da<-damax) da=-damax; else if(da>damax) da=damax; if(dr<-drmax) dr=-drmax; else if(dr>drmax) dr=drmax; if(Abs(da)<1e-10 && Abs(dr)<1e-10) { para = theta; PSurf = alin->Value(para); _theparameteronarc=theparameteronarc; thepointonarc = alin->Value(para); cpasok=Standard_False; //-- printf("\nt:%d",nbiter); return(Standard_True); } else { theta+=da; theparameteronarc+=dr; if( theparameteronarc>thearc->LastParameter() ) { theparameteronarc = thearc->LastParameter(); } if( theparameteronarcFirstParameter() ) { theparameteronarc = thearc->FirstParameter(); } if( theta < u0alin) { theta = u0alin; } if( theta > u1alin-du) { theta = u1alin-du-du; } } nbiter++; } while(cpasok && nbiter<20); if(bestdist < distinit) { para = besttheta; PSurf = alin->Value(para); _theparameteronarc=bestpara; thepointonarc = alin->Value(para); //-- printf("\nT:%d",nbiter); return(Standard_True); } //-- printf("\nF:%d",nbiter); return(Standard_False); } //-- ====================================================================== static void Recadre(const Handle(Adaptor3d_HSurface)& myHS1, const Handle(Adaptor3d_HSurface)& myHS2, Standard_Real& u1, Standard_Real& v1, Standard_Real& u2, Standard_Real& v2) { Standard_Real f,l,lmf,fpls2; GeomAbs_SurfaceType typs1 = myHS1->GetType(); GeomAbs_SurfaceType typs2 = myHS2->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: { //-- Le cas de biparametrees periodiques est gere en amont myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_False; break; } } Standard_Boolean myHS2IsUPeriodic,myHS2IsVPeriodic; switch (typs2) { case GeomAbs_Cylinder: case GeomAbs_Cone: case GeomAbs_Sphere: { myHS2IsUPeriodic = Standard_True; myHS2IsVPeriodic = Standard_False; break; } case GeomAbs_Torus: { myHS2IsUPeriodic = myHS2IsVPeriodic = Standard_True; break; } default: { //-- Le cas de biparametrees periodiques est gere en amont myHS2IsUPeriodic = myHS2IsVPeriodic = Standard_False; break; } } if(myHS1IsUPeriodic) { lmf = M_PI+M_PI; //-- myHS1->UPeriod(); f = myHS1->FirstUParameter(); l = myHS1->LastUParameter(); fpls2=0.5*(f+l); while((u1 < f)&&((fpls2-u1) > (u1+lmf-fpls2) )) { u1+=lmf; } while((u1 > l)&&((u1-fpls2) > (fpls2-(u1-lmf)) )) { u1-=lmf; } } if(myHS1IsVPeriodic) { lmf = M_PI+M_PI; //-- myHS1->VPeriod(); f = myHS1->FirstVParameter(); l = myHS1->LastVParameter(); fpls2=0.5*(f+l); while((v1 < f)&&((fpls2-v1) > (v1+lmf-fpls2) )) { v1+=lmf; } while((v1 > l)&&((v1-fpls2) > (fpls2-(v1-lmf)) )) { v1-=lmf; } //-- while(v1 < f) { v1+=lmf; } //-- while(v1 > l) { v1-=lmf; } } if(myHS2IsUPeriodic) { lmf = M_PI+M_PI; //-- myHS2->UPeriod(); f = myHS2->FirstUParameter(); l = myHS2->LastUParameter(); fpls2=0.5*(f+l); while((u2 < f)&&((fpls2-u2) > (u2+lmf-fpls2) )) { u2+=lmf; } while((u2 > l)&&((u2-fpls2) > (fpls2-(u2-lmf)) )) { u2-=lmf; } //-- while(u2 < f) { u2+=lmf; } //-- while(u2 > l) { u2-=lmf; } } if(myHS2IsVPeriodic) { lmf = M_PI+M_PI; //-- myHS2->VPeriod(); f = myHS2->FirstVParameter(); l = myHS2->LastVParameter(); fpls2=0.5*(f+l); while((v2 < f)&&((fpls2-v2) > (v2+lmf-fpls2) )) { v2+=lmf; } while((v2 > l)&&((v2-fpls2) > (fpls2-(v2-lmf)) )) { v2-=lmf; } //-- while(v2 < f) { v2+=lmf; } //-- while(v2 > l) { v2-=lmf; } } } //======================================================================= //function : PutPointsOnLine //purpose : //======================================================================= void PutPointsOnLine(const Handle(Adaptor3d_HSurface)& S1, const Handle(Adaptor3d_HSurface)& S2, const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt, const IntPatch_SequenceOfLine& slin, const Standard_Boolean OnFirst, const Handle(Adaptor3d_TopolTool)& Domain, const IntSurf_Quadric& QuadSurf, const IntSurf_Quadric& OtherQuad, const Standard_Boolean multpoint, const Standard_Real Tolarc) { // Traitement des point (de listpnt) de depart. On les replace sur // la ligne d intersection, en leur affectant la transition correcte sur // cette ligne. Standard_Integer nbpnt = listpnt.Length(); Standard_Integer nblin=slin.Length(); if (!slin.Length() || !nbpnt) { return; } // Standard_Integer i,k; Standard_Integer linenumber; Standard_Real currentparameter,tolerance; Standard_Real U1,V1,U2,V2; Standard_Boolean goon; gp_Pnt Psurf, ptbid; gp_Vec Normale, Vtgint, Vtgrst; gp_Vec d1u,d1v; gp_Pnt2d p2d; gp_Vec2d d2d; IntSurf_Transition Transline,Transarc; Handle(Adaptor2d_HCurve2d) currentarc; Handle(Adaptor3d_HVertex) vtx,vtxbis; IntPatch_Point solpnt; IntPatch_ThePathPointOfTheSOnBounds currentpointonrst; IntPatch_IType TheType; TColStd_Array1OfInteger UsedLine(1,nblin); TColStd_Array1OfInteger Done(1,nbpnt); for(i=1;i<=nbpnt;i++) Done(i) = 0; //-- Initialisation a la main for (i=1; i<=nbpnt; i++) { if (Done(i) != 1) { currentpointonrst = listpnt.Value(i); Psurf = currentpointonrst.Value(); // Point dans l espace tolerance = currentpointonrst.Tolerance(); // On recherche d abord si on a correspondance avec un "point multiple" UsedLine.Init(0); goon = Standard_True; if (multpoint) { #if 1 Normale = QuadSurf.Normale(Psurf); // Normale a la surface au point currentarc = currentpointonrst.Arc(); currentparameter = currentpointonrst.Parameter(); currentarc->D1(currentparameter,p2d,d2d); QuadSurf.D1(p2d.X(),p2d.Y(),ptbid,d1u,d1v); Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); #endif goon = MultiplePoint(listpnt,Domain,QuadSurf,Normale,slin,Done, UsedLine, i, OnFirst, Tolarc); } if (goon) { Standard_Boolean linefound = Standard_False; for(Standard_Integer indiceline = 1; indiceline <=slin.Length(); indiceline++) { if( UsedLine(indiceline) != 0 ) continue; linenumber = indiceline; //-- Attention , les points peuvent etre deplaces //-- il faut reprendre le point original currentpointonrst = listpnt.Value(i); currentarc = currentpointonrst.Arc(); currentparameter = currentpointonrst.Parameter(); Psurf = currentpointonrst.Value(); // Point dans l espace tolerance = currentpointonrst.Tolerance(); //-- // Modified by skv - Thu Jan 15 15:57:15 2004 OCC4455 Begin if (! currentpointonrst.IsNew()) { Handle(Adaptor3d_HVertex) aVtx = currentpointonrst.Vertex(); Standard_Real aVtxTol = aVtx->Resolution(currentarc); Standard_Real aTolAng = 0.01*tolerance; tolerance = Max(tolerance, aVtxTol); gp_Vec aNorm1 = QuadSurf.Normale(Psurf); gp_Vec aNorm2 = OtherQuad.Normale(Psurf); // if (aNorm1.Magnitude()>gp::Resolution() && aNorm2.Magnitude()>gp::Resolution()) { if (aNorm1.IsParallel(aNorm2, aTolAng)) tolerance = Sqrt(tolerance); }// } // Modified by skv - Thu Jan 15 15:57:15 2004 OCC4455 End gp_Pnt pointonarc; Vtgint.SetCoord(0,0,0); Standard_Real aVertTol = Tolarc; TColStd_ListOfReal aLParams; linefound = FindLine(Psurf, slin, tolerance, aLParams, Vtgint, linenumber, indiceline, currentarc, currentparameter, pointonarc, QuadSurf, OtherQuad, aVertTol); if (linefound) { #if 1 Normale = QuadSurf.Normale(Psurf); // Normale a la surface au point currentarc = currentpointonrst.Arc(); //-- currentparameter = currentpointonrst.Parameter(); currentarc->D1(currentparameter,p2d,d2d); QuadSurf.D1(p2d.X(),p2d.Y(),ptbid,d1u,d1v); Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); #endif const Handle(IntPatch_Line)& lin = slin.Value(linenumber); TheType = lin->ArcType(); if (!OnFirst) { // on cherche la correspondance entre point sur domaine // de la premiere surface et point sur domaine de la // deuxieme surface goon = PointOnSecondDom (listpnt, Domain, QuadSurf, Normale, Vtgint, lin, Done, i, aVertTol); } if (goon) { //-- Modification du 4 avril 97 tolerance->Tolarc //-- on replace sur le vertex la tolerance d entree et //-- non la tolerance qui a servi au FindLine solpnt.SetValue(Psurf, aVertTol, Standard_False); U1 = p2d.X(); V1 = p2d.Y(); OtherQuad.Parameters(Psurf,U2,V2); if (OnFirst) { Recadre(S1,S2,U1,V1,U2,V2); solpnt.SetParameters(U1,V1,U2,V2); } else { Recadre(S1,S2,U2,V2,U1,V1); solpnt.SetParameters(U2,V2,U1,V1); } if (! currentpointonrst.IsNew()) { vtx = currentpointonrst.Vertex(); solpnt.SetVertex(OnFirst,vtx); } else { //-- goon = Standard_False; ???? } if(Normale.SquareMagnitude()<1e-16) { Transline.SetValue(Standard_True,IntSurf_Undecided); Transarc.SetValue(Standard_True,IntSurf_Undecided); } else { IntSurf::MakeTransition(Vtgint,Vtgrst,Normale,Transline,Transarc); } solpnt.SetArc(OnFirst,currentarc, currentparameter, Transline,Transarc); for (TColStd_ListIteratorOfListOfReal anItr(aLParams); anItr.More(); anItr.Next()) { solpnt.SetParameter(anItr.Value()); if (TheType == IntPatch_Analytic) { Handle(IntPatch_ALine)::DownCast(lin)->AddVertex(solpnt); } else { Handle(IntPatch_GLine)::DownCast(lin)->AddVertex(solpnt); } } Done(i) = 1; if (goon) { for (k=i+1; k<= nbpnt; k++) { if (Done(k) != 1) { currentpointonrst = listpnt.Value(k); if (!currentpointonrst.IsNew()) { vtxbis = currentpointonrst.Vertex(); if(vtx.IsNull()) { } else if (Domain->Identical(vtx, vtxbis)) { solpnt.SetVertex(OnFirst,vtxbis); solpnt.SetTolerance(Tolarc); currentarc = currentpointonrst.Arc(); currentparameter = currentpointonrst.Parameter(); // currentarc->D1(currentparameter,ptbid,Vtgrst); currentarc->D1(currentparameter,p2d,d2d); Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); if(Normale.SquareMagnitude()<1e-16) { Transline.SetValue(Standard_True,IntSurf_Undecided); Transarc.SetValue(Standard_True,IntSurf_Undecided); } else { IntSurf::MakeTransition(Vtgint,Vtgrst,Normale, Transline,Transarc); } solpnt.SetArc(OnFirst,currentarc,currentparameter, Transline,Transarc); if (TheType == IntPatch_Analytic) { Handle(IntPatch_ALine)::DownCast (lin)->AddVertex(solpnt); } else { Handle(IntPatch_GLine)::DownCast (lin)->AddVertex(solpnt); } Done(k) = 1; } } } } } } } else { Done(i) = 1; // il faudra tester si IsNew ou pas // et traiter en consequence } } } } } } Standard_Boolean MultiplePoint (const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt, const Handle(Adaptor3d_TopolTool)& Domain, const IntSurf_Quadric& QuadSurf, const gp_Vec& Normale, const IntPatch_SequenceOfLine& slin, TColStd_Array1OfInteger& Done, TColStd_Array1OfInteger& UsedLine, const Standard_Integer Index, const Standard_Boolean OnFirst, const Standard_Real theToler) { // Traitement des points "multiples". Standard_Integer k,ii,jj,nbvtx; Standard_Integer nblin = slin.Length(); IntPatch_IType TheType; IntSurf_Transition Transline,Transarc; IntPatch_Point intpt; Handle(Adaptor2d_HCurve2d) currentarc; Handle(Adaptor3d_HVertex) vtx,vtxbis; Standard_Integer nbpnt = listpnt.Length(); IntPatch_ThePathPointOfTheSOnBounds currentpointonrst = listpnt.Value(Index); IntPatch_ThePathPointOfTheSOnBounds otherpt; gp_Pnt Point = currentpointonrst.Value(); TColStd_Array1OfInteger localdone(1,nbpnt); localdone.Init(0); for (ii=1; ii<=nbpnt; ii++) { localdone(ii)=Done(ii); } Standard_Real currentparameter; Standard_Real Paraint; gp_Vec Vtgint,Vtgrst; gp_Pnt ptbid; gp_Vec d1u,d1v; gp_Pnt2d p2d; gp_Vec2d d2d; Standard_Boolean goon; Standard_Boolean Retvalue = Standard_True; for (ii = 1; ii <= nblin; ii++) { const Handle(IntPatch_Line)& slinValueii = slin.Value(ii); TheType = slinValueii->ArcType(); if (TheType == IntPatch_Analytic) { nbvtx = Handle(IntPatch_ALine)::DownCast (slinValueii)->NbVertex(); } else { nbvtx = Handle(IntPatch_GLine)::DownCast (slinValueii)->NbVertex(); } jj = 1; while (jj <= nbvtx) { if (TheType == IntPatch_Analytic) { intpt = Handle(IntPatch_ALine)::DownCast (slinValueii)->Vertex(jj); } else { intpt = Handle(IntPatch_GLine)::DownCast (slinValueii)->Vertex(jj); } if (intpt.IsMultiple() && (( OnFirst && !intpt.IsOnDomS1()) || (!OnFirst && !intpt.IsOnDomS2()))) { if (Point.Distance(intpt.Value()) <= intpt.Tolerance()) { Retvalue = Standard_False; Standard_Boolean foo = SingleLine(Point,slinValueii, intpt.Tolerance(),Paraint,Vtgint); if (!foo) { return Standard_False; // ne doit pas se produire } if (!currentpointonrst.IsNew()) { goon = Standard_True; vtx = currentpointonrst.Vertex(); intpt.SetVertex(OnFirst,vtx); } else { goon = Standard_False; } currentarc = currentpointonrst.Arc(); currentparameter = currentpointonrst.Parameter(); currentarc->D1(currentparameter,p2d,d2d); QuadSurf.D1(p2d.X(),p2d.Y(),ptbid,d1u,d1v); Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); //-- Si la normale est nulle (apex d un cone) On simule une transition UNKNOWN if(Normale.SquareMagnitude()<1e-16) { Transline.SetValue(Standard_True,IntSurf_Undecided); Transarc.SetValue(Standard_True,IntSurf_Undecided); } else { IntSurf::MakeTransition(Vtgint,Vtgrst,Normale,Transline,Transarc); } //-- Avant, on ne mettait pas ce point (17 nov 97) //--printf("\n ImpImp_0 : Point(%g,%g,%g) intpt(%g,%g,%g) \n", //-- Point.X(),Point.Y(),Point.Z(),intpt.Value().X(),intpt.Value().Y(),intpt.Value().Z()); intpt.SetValue(Point); intpt.SetArc(OnFirst,currentarc,currentparameter, Transline,Transarc); intpt.SetTolerance(theToler); if (TheType == IntPatch_Analytic) { Handle(IntPatch_ALine)::DownCast (slinValueii)->Replace(jj,intpt); } else { Handle(IntPatch_GLine)::DownCast (slinValueii)->Replace(jj,intpt); } localdone(Index) = 1; if (goon) { for (k=Index+1; k<= nbpnt; k++) { if (Done(k) != 1) { otherpt= listpnt.Value(k); if (!otherpt.IsNew()) { vtxbis = otherpt.Vertex(); if (Domain->Identical(vtx, vtxbis)) { intpt.SetVertex(OnFirst,vtxbis); currentarc = otherpt.Arc(); currentparameter = otherpt.Parameter(); currentarc->D1(currentparameter,p2d,d2d); Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); if(Normale.SquareMagnitude()<1e-16) { Transline.SetValue(Standard_True,IntSurf_Undecided); Transarc.SetValue(Standard_True,IntSurf_Undecided); } else { IntSurf::MakeTransition(Vtgint,Vtgrst,Normale, Transline,Transarc); } intpt.SetArc(OnFirst,currentarc,currentparameter, Transline,Transarc); intpt.SetTolerance(theToler); if (TheType == IntPatch_Analytic) { Handle(IntPatch_ALine)::DownCast (slinValueii)->AddVertex(intpt); } else { Handle(IntPatch_GLine)::DownCast (slinValueii)->AddVertex(intpt); } UsedLine(ii) = 1; Retvalue = Standard_True; localdone(k) = 1; } } } } } //-- jj = nbvtx +1; } //-- else { jj = jj+1; //-- } } else { jj = jj+1; } } } for (ii=1; ii<=nbpnt;ii++) { Done(ii) = localdone(ii); } return Retvalue; } Standard_Boolean PointOnSecondDom (const IntPatch_SequenceOfPathPointOfTheSOnBounds& listpnt, const Handle(Adaptor3d_TopolTool)& Domain, const IntSurf_Quadric& QuadSurf, const gp_Vec& Normale, const gp_Vec& Vtgint, const Handle(IntPatch_Line)& lin, TColStd_Array1OfInteger& Done, const Standard_Integer Index, const Standard_Real theToler) // Duplication des points sur domaine de l autre surface. // On sait que le vertex sous-jacent est PntRef { Standard_Integer k,jj,nbvtx; IntPatch_IType TheType; IntSurf_Transition Transline,Transarc; IntPatch_Point intpt; Handle(Adaptor2d_HCurve2d) currentarc; Handle(Adaptor3d_HVertex) vtx,vtxbis; gp_Pnt ptbid; gp_Vec Vtgrst; gp_Vec d1u,d1v; gp_Pnt2d p2d; gp_Vec2d d2d; Standard_Integer nbpnt = listpnt.Length(); IntPatch_ThePathPointOfTheSOnBounds currentpointonrst = listpnt.Value(Index); Standard_Real currentparameter; Standard_Boolean goon; Standard_Boolean Retvalue = Standard_True; TheType = lin->ArcType(); if (TheType == IntPatch_Analytic) { nbvtx = Handle(IntPatch_ALine)::DownCast (lin)->NbVertex(); } else { nbvtx = Handle(IntPatch_GLine)::DownCast (lin)->NbVertex(); } jj = 1; while (jj <= nbvtx) { if (TheType == IntPatch_Analytic) { intpt = Handle(IntPatch_ALine)::DownCast (lin)->Vertex(jj); } else { intpt = Handle(IntPatch_GLine)::DownCast (lin)->Vertex(jj); } if (!intpt.IsOnDomS2()) { if (currentpointonrst.Value().Distance(intpt.Value()) <= intpt.Tolerance()) { Retvalue = Standard_False; if (!currentpointonrst.IsNew()) { goon = Standard_True; vtx = currentpointonrst.Vertex(); intpt.SetVertex(Standard_False,vtx); } else { goon = Standard_False; } currentarc = currentpointonrst.Arc(); currentparameter = currentpointonrst.Parameter(); currentarc->D1(currentparameter,p2d,d2d); QuadSurf.D1(p2d.X(),p2d.Y(),ptbid,d1u,d1v); Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); if(Normale.SquareMagnitude()<1e-16) { Transline.SetValue(Standard_True,IntSurf_Undecided); Transarc.SetValue(Standard_True,IntSurf_Undecided); } else { IntSurf::MakeTransition(Vtgint,Vtgrst,Normale,Transline,Transarc); } intpt.SetArc(Standard_False,currentarc,currentparameter, Transline,Transarc); intpt.SetTolerance(theToler); if (TheType == IntPatch_Analytic) { Handle(IntPatch_ALine)::DownCast (lin)->Replace(jj,intpt); } else { Handle(IntPatch_GLine)::DownCast (lin)->Replace(jj,intpt); } Done(Index) = 1; if (goon) { for (k=Index+1; k<= nbpnt; k++) { if (Done(k) != 1) { currentpointonrst = listpnt.Value(k); if (!currentpointonrst.IsNew()) { vtxbis = currentpointonrst.Vertex(); if (Domain->Identical(vtx, vtxbis)) { intpt.SetVertex(Standard_False,vtxbis); currentarc = currentpointonrst.Arc(); currentparameter = currentpointonrst.Parameter(); currentarc->D1(currentparameter,p2d,d2d); Vtgrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); if(Normale.SquareMagnitude()<1e-16) { Transline.SetValue(Standard_True,IntSurf_Undecided); Transarc.SetValue(Standard_True,IntSurf_Undecided); } else { IntSurf::MakeTransition(Vtgint,Vtgrst,Normale, Transline,Transarc); } intpt.SetArc(Standard_False,currentarc,currentparameter, Transline,Transarc); intpt.SetTolerance(theToler); if (TheType == IntPatch_Analytic) { Handle(IntPatch_ALine)::DownCast (lin)->AddVertex(intpt); } else { Handle(IntPatch_GLine)::DownCast (lin)->AddVertex(intpt); } Done(k) = 1; } } } } } //-- jj = nbvtx + 1; jj++; } else { jj = jj+1; } } else { jj = jj+1; } if (TheType == IntPatch_Analytic) { nbvtx = Handle(IntPatch_ALine)::DownCast (lin)->NbVertex(); } else { nbvtx = Handle(IntPatch_GLine)::DownCast (lin)->NbVertex(); } } return Retvalue; } Standard_Boolean FindLine(gp_Pnt& Psurf, const IntPatch_SequenceOfLine& slin, const Standard_Real Tol, TColStd_ListOfReal& theLParams, gp_Vec& Vtgtint, Standard_Integer& theLineIdx, Standard_Integer OnlyThisLine, const Handle(Adaptor2d_HCurve2d)& thearc, Standard_Real& theparameteronarc, gp_Pnt& thepointonarc, const IntSurf_Quadric& QuadSurf1, const IntSurf_Quadric& QuadSurf2, Standard_Real& theOutputToler) { if ((QuadSurf1.Distance(Psurf) > Tol) || (QuadSurf2.Distance(Psurf) > Tol)) return Standard_False; // Traitement du point de depart ayant pour representation Psurf // dans l espace. On recherche la ligne d intersection contenant ce point. // On a en sortie la ligne, et le parametre et sa tangente du point sur // la ligne d intersection. const Standard_Real aSqTol = Tol*Tol; Standard_Real aSqDistMin = RealLast(); Standard_Real aSqDist, para; Standard_Real lower,upper; gp_Pnt pt; Standard_Integer i; IntPatch_IType typarc; Standard_Real aParaInt = RealLast(); Standard_Integer nblin = slin.Length(); for (i=1; i<=nblin; i++) { if(OnlyThisLine) { i=OnlyThisLine; nblin=0; } const Handle(IntPatch_Line)& lin = slin.Value(i); typarc = lin->ArcType(); if (typarc == IntPatch_Analytic) { Standard_Boolean foo; lower = Handle(IntPatch_ALine)::DownCast (lin)->FirstParameter(foo); upper = Handle(IntPatch_ALine)::DownCast (lin)->LastParameter(foo); } else { if (Handle(IntPatch_GLine)::DownCast (lin)->HasFirstPoint()) { lower = Handle(IntPatch_GLine)::DownCast (lin)->FirstPoint().ParameterOnLine(); } else { lower = RealFirst(); } if (Handle(IntPatch_GLine)::DownCast (lin)->HasLastPoint()) { upper = Handle(IntPatch_GLine)::DownCast (lin)->LastPoint().ParameterOnLine(); } else { upper = RealLast(); } } switch (typarc) { case IntPatch_Lin : { para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Line(),Psurf); if (para <= upper && para >= lower) { pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Line()); aSqDist = Psurf.SquareDistance(pt); if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin)) { aSqDistMin = aSqDist; aParaInt = para; theLineIdx = i; } } } break; case IntPatch_Circle : { para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Circle(),Psurf); if ((para <= upper && para >= lower) || (para + 2.*M_PI <=upper && para + 2.*M_PI >= lower) || (para - 2.*M_PI <=upper && para - 2.*M_PI >= lower)) { pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Circle()); aSqDist = Psurf.SquareDistance(pt); if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin)) { aSqDistMin = aSqDist; aParaInt = para; theLineIdx = i; } } } break; case IntPatch_Ellipse : { para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Ellipse(),Psurf); if ((para <= upper && para >= lower) || (para + 2.*M_PI <=upper && para + 2.*M_PI >= lower) || (para - 2.*M_PI <=upper && para - 2.*M_PI >= lower)) { pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Ellipse()); aSqDist = Psurf.SquareDistance(pt); if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin)) { aSqDistMin = aSqDist; aParaInt = para; theLineIdx = i; } } } break; case IntPatch_Parabola : { #if 0 para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Parabola(),Psurf); if (para <= upper && para >= lower) { pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Parabola()); dist = Psurf.Distance(pt); if (dist< distmin) { distmin = dist; Paraint = para; Range = i; } } #else //-- Le calcul du parametre sur une parabole est mal fait ds ElCLib. Il ne tient pas compte //-- de la meilleure facon de calculer (axe X ou axe Y). Bilan : Si la parabole est tres //-- pointue (focal de l'ordre de 1e-2 et si le point est a un parametre grand, ca foire. ) //-- On ne peut pas modifier faciolement ds ElCLib car on ne passe pas la focale. ... const gp_Parab& Parab=Handle(IntPatch_GLine)::DownCast (lin)->Parabola(); para = ElCLib::Parameter(Parab,Psurf); if (para <= upper && para >= lower) { Standard_Integer amelioration=0; //-- cout<<"\n ****** \n"; do { Standard_Real parabis = para+0.0000001; pt = ElCLib::Value(para,Parab); aSqDist = Psurf.SquareDistance(pt); const gp_Pnt ptbis = ElCLib::Value(parabis,Parab); const Standard_Real distbis = Psurf.Distance(ptbis); const Standard_Real aDist = Sqrt(aSqDist); const Standard_Real ddist = distbis - aDist; //--cout<<" para: "<1.0e-9 || ddist<-1.0e-9 ) { para = para - aDist*(parabis - para) / ddist; } else { amelioration=100; } } while(++amelioration < 5); } #endif } break; case IntPatch_Hyperbola : { para = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Hyperbola(),Psurf); if (para <= upper && para >= lower) { pt = ElCLib::Value(para,Handle(IntPatch_GLine)::DownCast (lin)->Hyperbola()); aSqDist = Psurf.SquareDistance(pt); if ((aSqDist < aSqTol) && (aSqDist < aSqDistMin)) { aSqDistMin = aSqDist; aParaInt = para; theLineIdx = i; } } } break; case IntPatch_Analytic : { Handle(IntPatch_ALine) alin(Handle(IntPatch_ALine)::DownCast(lin)); TColStd_ListOfReal aLParams; alin->FindParameter(Psurf, aLParams); if (!aLParams.IsEmpty()) { // All found distances are already in some internal tolerance // set in alin->FindParameter(...) method. aSqDist = RealLast(); for (TColStd_ListIteratorOfListOfReal anItr(aLParams); anItr.More(); anItr.Next()) { pt = alin->Value(anItr.Value()); const Standard_Real aSqD = Psurf.SquareDistance(pt); if (aSqD < aSqDist) { aSqDist = aSqD; } } if (aSqDist < aSqDistMin) { aSqDistMin = aSqDist; theLParams = aLParams; theLineIdx = i; } } else { //-- le point n a pas ete trouve par bete projection. //-- on essaie l intersection avec la restriction en 2d Standard_Real theparamonarc = theparameteronarc; //#ifdef OCCT_DEBUG // Standard_Real anpara=para; //#endif gp_Pnt CopiePsurf=Psurf; Standard_Boolean IntersectIsOk = IntersectionWithAnArc(CopiePsurf, alin, para, thearc, theparamonarc, thepointonarc, QuadSurf1, lower, upper); aSqDist = CopiePsurf.SquareDistance(Psurf); if(IntersectIsOk) { if (aSqDist < aSqTol) { theparameteronarc = theparamonarc; Psurf = thepointonarc; aSqDistMin = aSqDist; theLParams.Append(para); theLineIdx = i; } } } } break; case IntPatch_Walking: // impossible . c est pour eviter les warnings { } case IntPatch_Restriction: // impossible . c est pour eviter les warnings { } } } if (aSqDistMin == RealLast()) return Standard_False; theOutputToler = Max(theOutputToler, Sqrt(aSqDistMin)); typarc = slin.Value(theLineIdx)->ArcType(); // Computation of tangent vector switch (typarc) { case IntPatch_Lin : theLParams.Append(aParaInt); Vtgtint = (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Line().Direction(); break; case IntPatch_Circle : theLParams.Append(aParaInt); Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Circle(), 1); break; case IntPatch_Ellipse : theLParams.Append(aParaInt); Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Ellipse(), 1); break; case IntPatch_Parabola : theLParams.Append(aParaInt); Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Parabola(), 1); break; case IntPatch_Hyperbola : theLParams.Append(aParaInt); Vtgtint = ElCLib::DN(aParaInt, (*((Handle(IntPatch_GLine)*)&slin(theLineIdx)))->Hyperbola(), 1); break; case IntPatch_Analytic: { if (!Handle(IntPatch_ALine)::DownCast(slin(theLineIdx))->D1(theLParams.Last(), pt, Vtgtint)) { //Previously (before the fix #29807) this code tried to process case //when Handle(IntPatch_ALine)::D1(...) method returns FALSE and //computed Vtgtint input argument value. Currently, any singularities //must be processed by high-level algorithms (IntPatch_SpecialPoints class). //Therefore this code has been deleted as deprecated. Vtgtint.SetCoord(0.0, 0.0, 0.0); } } break; case IntPatch_Walking: // impossible . c est pour eviter les warnings { } case IntPatch_Restriction: // impossible . c est pour eviter les warnings { } } return Standard_True; } //======================================================================= //function : SingleLine //purpose : Traitement du point de depart ayant pour representation Psurf // dans l espace. On le replace sur la ligne d intersection; On a en sortie // son parametre et sa tangente sur la ligne d intersection. // La fonction renvoie False si le point projete est a une distance // superieure a Tol du point a projeter. //======================================================================= Standard_Boolean SingleLine(const gp_Pnt& Psurf, const Handle(IntPatch_Line)& lin, const Standard_Real Tol, Standard_Real& Paraint, gp_Vec& Vtgtint) { IntPatch_IType typarc = lin->ArcType(); Standard_Real parproj = 0.; gp_Vec tgint; gp_Pnt ptproj; Standard_Boolean retvalue; switch (typarc) { case IntPatch_Lin : parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Line(),Psurf); ElCLib::D1(parproj,Handle(IntPatch_GLine)::DownCast (lin)->Line(),ptproj,tgint); break; case IntPatch_Circle : parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Circle(),Psurf); ElCLib::D1(parproj,Handle(IntPatch_GLine)::DownCast (lin)->Circle(),ptproj,tgint); break; case IntPatch_Ellipse : parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Ellipse(),Psurf); ElCLib::D1(parproj,Handle(IntPatch_GLine)::DownCast (lin)->Ellipse(),ptproj,tgint); break; case IntPatch_Parabola : parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Parabola(),Psurf); ElCLib::D1(parproj,Handle(IntPatch_GLine)::DownCast (lin)->Parabola(),ptproj,tgint); break; case IntPatch_Hyperbola : parproj = ElCLib::Parameter(Handle(IntPatch_GLine)::DownCast (lin)->Hyperbola(),Psurf); ElCLib::D1(parproj,Handle(IntPatch_GLine)::DownCast (lin)->Hyperbola(),ptproj,tgint); break; case IntPatch_Analytic : { Handle(IntPatch_ALine) alin(Handle(IntPatch_ALine)::DownCast(lin)); TColStd_ListOfReal aLParams; alin->FindParameter(Psurf, aLParams); if (!aLParams.IsEmpty()) { ptproj = Psurf; parproj = aLParams.Last(); gp_Pnt aPtemp; if (!alin->D1(parproj, aPtemp, tgint)) { //Previously (before the fix #29807) this code tried to process case //when Handle(IntPatch_ALine)::D1(...) method returns FALSE and //computed Vtgtint input argument value. Currently, any singularities //must be processed by high-level algorithms (IntPatch_SpecialPoints class). //Therefore this code has been deleted as deprecated. tgint.SetCoord(0.0, 0.0, 0.0); } } else { //-- cout << "---- Pb sur ligne analytique dans SingleLine" << endl; //-- cout << " Find Parameter"<SetArcOnS1(arcRef); } else { rline->SetArcOnS2(arcRef); } // 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(); } if (dofirst && dolast) { // determination de la transition de la ligne arcRef->D1(0.5*(paramf+paraml),p2d,d2d); if (OnFirst) { Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); } else { Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); } tgline.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); if(d1u.Magnitude()<1e-7) { //-- edge degenere ? EdgeDegenere=Standard_True; for(Standard_Integer edg=0;edg<=10;edg++) { arcRef->D1(paramf+(paraml-paramf)*edg*0.1,p2d,d2d); if (OnFirst) { Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); } else { Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); } if(d1u.Magnitude()>1e-7) { EdgeDegenere=Standard_False; } } rline = new IntPatch_RLine(Standard_False); if(OnFirst) { rline->SetArcOnS1(arcRef); } else { rline->SetArcOnS2(arcRef); } } else { norm2 = Quad2.Normale(valpt); norm1 = Quad1.Normale(valpt); if (tgline.DotCross(norm2,norm1) > 0.000000001) { trans1 = IntSurf_Out; trans2 = IntSurf_In; } else if (tgline.DotCross(norm2,norm1) < -0.000000001){ trans1 = IntSurf_In; trans2 = IntSurf_Out; } else { trans1 = trans2 = IntSurf_Undecided; } rline = new IntPatch_RLine(Standard_False,trans1,trans2); if(OnFirst) { rline->SetArcOnS1(arcRef); } else { rline->SetArcOnS2(arcRef); } } } else { rline = new IntPatch_RLine(Standard_False); if(OnFirst) { rline->SetArcOnS1(arcRef); } else { rline->SetArcOnS2(arcRef); } } if (dofirst || dolast) { Nblines = slin.Length(); for (j=1; j<=Nblines; j++) { const Handle(IntPatch_Line)& slinj = slin(j); typ = slinj->ArcType(); if (typ == IntPatch_Analytic) { Nbpts = Handle(IntPatch_ALine)::DownCast (slinj)->NbVertex(); } else if (typ == IntPatch_Restriction) { Nbpts = Handle(IntPatch_RLine)::DownCast (slinj)->NbVertex(); } else { Nbpts = Handle(IntPatch_GLine)::DownCast (slinj)->NbVertex(); } for (k=1; k<=Nbpts;k++) { if (typ == IntPatch_Analytic) { ptvtx = Handle(IntPatch_ALine)::DownCast (slinj)->Vertex(k); } else if (typ == IntPatch_Restriction) { ptvtx = Handle(IntPatch_RLine)::DownCast (slinj)->Vertex(k); } else { ptvtx = Handle(IntPatch_GLine)::DownCast (slinj)->Vertex(k); } if (EdgeDegenere==Standard_False && dofirst) { if (ptvtx.Value().Distance(PStartf.Value()) <=TolArc) { ptvtx.SetMultiple(Standard_True); ptvtx.SetTolerance(TolArc); if (typ == IntPatch_Analytic) { Handle(IntPatch_ALine)::DownCast (slinj)->Replace(k,ptvtx); } else if (typ == IntPatch_Restriction) { Handle(IntPatch_RLine)::DownCast (slinj)->Replace(k,ptvtx); } else { Handle(IntPatch_GLine)::DownCast (slinj)->Replace(k,ptvtx); } newptvtx = ptvtx; newptvtx.SetParameter(paramf); //Recalcul des transitions si point sur restriction arcRef->D1(paramf,p2d,d2d); if (OnFirst) { Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); } else { Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); } tgline.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); if (ptvtx.IsOnDomS1()) { const Handle(Adaptor2d_HCurve2d)& thearc = ptvtx.ArcOnS1(); thearc->D1(ptvtx.ParameterOnArc1(),p2d,d2d); Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); tgarc.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); norm1 = d1u.Crossed(d1v); if(norm1.SquareMagnitude()<1e-16) { TRest.SetValue(Standard_True,IntSurf_Undecided); TArc.SetValue(Standard_True,IntSurf_Undecided); } else { IntSurf::MakeTransition(tgline,tgarc,norm1,TRest,TArc); } newptvtx.SetArc(Standard_True,thearc,ptvtx.ParameterOnArc1(), TRest,TArc); } if (ptvtx.IsOnDomS2()) { const Handle(Adaptor2d_HCurve2d)& thearc = ptvtx.ArcOnS2(); thearc->D1(ptvtx.ParameterOnArc2(),p2d,d2d); Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); tgarc.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); norm2 = d1u.Crossed(d1v); if(norm2.SquareMagnitude()<1e-16) { TRest.SetValue(Standard_True,IntSurf_Undecided); TArc.SetValue(Standard_True,IntSurf_Undecided); } else { IntSurf::MakeTransition(tgline,tgarc,norm2,TRest,TArc); } newptvtx.SetArc(Standard_False,thearc,ptvtx.ParameterOnArc2(), TRest,TArc); } rline->AddVertex(newptvtx); if (!procf){ procf=Standard_True; rline->SetFirstPoint(rline->NbVertex()); } } } if (EdgeDegenere==Standard_False && dolast) { if (ptvtx.Value().Distance(PStartl.Value()) <=TolArc) { ptvtx.SetMultiple(Standard_True); ptvtx.SetTolerance(TolArc); if (typ == IntPatch_Analytic) { Handle(IntPatch_ALine)::DownCast (slinj)->Replace(k,ptvtx); } else if (typ == IntPatch_Restriction) { Handle(IntPatch_RLine)::DownCast (slinj)->Replace(k,ptvtx); } else { Handle(IntPatch_GLine)::DownCast (slinj)->Replace(k,ptvtx); } newptvtx = ptvtx; newptvtx.SetParameter(paraml); //Recalcul des transitions si point sur restriction arcRef->D1(paraml,p2d,d2d); if (OnFirst) { Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); } else { Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); } tgline.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); if (ptvtx.IsOnDomS1()) { const Handle(Adaptor2d_HCurve2d)& thearc = ptvtx.ArcOnS1(); thearc->D1(ptvtx.ParameterOnArc1(),p2d,d2d); Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); tgarc.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); norm1 = d1u.Crossed(d1v); if(norm1.SquareMagnitude()<1e-16) { TRest.SetValue(Standard_True,IntSurf_Undecided); TArc.SetValue(Standard_True,IntSurf_Undecided); } else { IntSurf::MakeTransition(tgline,tgarc,norm1,TRest,TArc); } newptvtx.SetArc(Standard_True,thearc,ptvtx.ParameterOnArc1(), TRest,TArc); } if (ptvtx.IsOnDomS2()) { const Handle(Adaptor2d_HCurve2d)& thearc = ptvtx.ArcOnS2(); thearc->D1(ptvtx.ParameterOnArc2(),p2d,d2d); Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); tgarc.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); norm2 = d1u.Crossed(d1v); if(norm2.SquareMagnitude()<1e-16) { TRest.SetValue(Standard_True,IntSurf_Undecided); TArc.SetValue(Standard_True,IntSurf_Undecided); } else { IntSurf::MakeTransition(tgline,tgarc,norm2,TRest,TArc); } newptvtx.SetArc(Standard_False,thearc,ptvtx.ParameterOnArc2(), TRest,TArc); } rline->AddVertex(newptvtx); if (!procl){ procl=Standard_True; rline->SetLastPoint(rline->NbVertex()); } } } } // 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) { ptvtx.SetValue(PStartf.Value(),PStartf.Tolerance(),Standard_False); Quad1.Parameters(PStartf.Value(),U1,V1); Quad2.Parameters(PStartf.Value(),U2,V2); ptvtx.SetParameters(U1,V1,U2,V2); ptvtx.SetParameter(paramf); if (! PStartf.IsNew()) { IntSurf_Transition Transline; IntSurf_Transition Transarc; ptvtx.SetVertex(OnFirst,PStartf.Vertex()); ptvtx.SetArc(OnFirst,PStartf.Arc(),PStartf.Parameter(), Transline,Transarc); } rline->AddVertex(ptvtx); rline->SetFirstPoint(rline->NbVertex()); } if (dolast) { ptvtx.SetValue(PStartl.Value(),PStartl.Tolerance(),Standard_False); Quad1.Parameters(PStartl.Value(),U1,V1); Quad2.Parameters(PStartl.Value(),U2,V2); ptvtx.SetParameters(U1,V1,U2,V2); ptvtx.SetParameter(paraml); if (! PStartl.IsNew()) { IntSurf_Transition Transline; IntSurf_Transition Transarc; ptvtx.SetVertex(OnFirst,PStartl.Vertex()); ptvtx.SetArc(OnFirst,PStartl.Arc(),PStartl.Parameter(), Transline,Transarc); } rline->AddVertex(ptvtx); rline->SetLastPoint(rline->NbVertex()); } slin.Append(rline); } } inline const gp_Pnt& PointValue(const Handle(IntPatch_RLine) theRLine, const Standard_Integer theIndex) { return theRLine->Point(theIndex).Value(); } inline const gp_Pnt& VertexValue( const Handle(IntPatch_RLine) theRLine, const Standard_Integer theIndex) { return theRLine->Vertex(theIndex).Value(); } static Standard_Real SquareDistance(const Handle(IntPatch_GLine)& theGLine, const gp_Pnt& theP, Extrema_ExtPC& theExtr) { Standard_Real aSQDist = RealLast(); switch(theGLine->ArcType()) { case IntPatch_Lin: aSQDist = theGLine->Line().SquareDistance(theP); break; case IntPatch_Circle: aSQDist = theGLine->Circle().SquareDistance(theP); break; default: theExtr.Perform(theP); if(!theExtr.IsDone() || !theExtr.NbExt()) { //Lines are not overlapped return aSQDist; } aSQDist = theExtr.SquareDistance(1); const Standard_Integer aNbExtr = theExtr.NbExt(); for ( Standard_Integer i = 2; i <= aNbExtr; i++) { const Standard_Real aSQD = theExtr.SquareDistance(i); if (aSQD < aSQDist) { aSQDist = aSQD; } } } return aSQDist; } static Standard_Boolean IsRLineGood(const IntSurf_Quadric& Quad1, const IntSurf_Quadric& Quad2, const Handle(IntPatch_GLine) theGLine, const Handle(IntPatch_RLine) theRLine, const Standard_Real theTol) { const Standard_Real aSQTol = theTol*theTol; const IntPatch_IType aGType = theGLine->ArcType(); Standard_Integer aNbPntsM1 = 0; const gp_Pnt& (*Value) (const Handle(IntPatch_RLine), const Standard_Integer); if(theRLine->HasPolygon()) { aNbPntsM1 = theRLine->NbPnts()-1; Value = PointValue; } else { aNbPntsM1 = theRLine->NbVertex()-1; Value = VertexValue; } if(aNbPntsM1 < 1) return Standard_False; Extrema_ExtPC anExtr; GeomAdaptor_Curve anAC; Handle(Geom_Curve) aCurv; if(aGType == IntPatch_Ellipse) aCurv = new Geom_Ellipse(theGLine->Ellipse()); else if(aGType == IntPatch_Parabola) aCurv = new Geom_Parabola(theGLine->Parabola()); else if(aGType == IntPatch_Hyperbola) aCurv = new Geom_Hyperbola(theGLine->Hyperbola()); if(!aCurv.IsNull()) { const Standard_Real anUinf = aCurv->FirstParameter(), anUsup = aCurv->LastParameter(); anAC.Load(aCurv, anUinf, anUsup); anExtr.Initialize(anAC, anUinf, anUsup); } if(aNbPntsM1 == 1) { gp_Pnt aP1(Value(theRLine, 1)), aP2(Value(theRLine, 2)); if(aP1.SquareDistance(aP2) < aSQTol) { //RLine is degenerated return Standard_False; } gp_Pnt aPMid; if(theRLine->IsArcOnS1()) { const Handle(Adaptor2d_HCurve2d)& anAC2d = theRLine->ArcOnS1(); const Standard_Real aParF = anAC2d->FirstParameter(), aParL = anAC2d->LastParameter(); gp_Pnt2d aP2d(anAC2d->Value(0.5*(aParF+aParL))); aPMid = Quad1.Value(aP2d.X(), aP2d.Y()); } else { const Handle(Adaptor2d_HCurve2d)& anAC2d = theRLine->ArcOnS2(); const Standard_Real aParF = anAC2d->FirstParameter(), aParL = anAC2d->LastParameter(); gp_Pnt2d aP2d(anAC2d->Value(0.5*(aParF+aParL))); aPMid = Quad2.Value(aP2d.X(), aP2d.Y()); } const Standard_Real aSQDist = SquareDistance(theGLine, aPMid, anExtr); return (aSQDist > aSQTol); } for(Standard_Integer i = 2; i <= aNbPntsM1; i++) { const gp_Pnt aP(Value(theRLine, i)); const Standard_Real aSQDist = SquareDistance(theGLine, aP, anExtr); if(aSQDist > aSQTol) return Standard_True; } return Standard_False; } void ProcessRLine (IntPatch_SequenceOfLine& slin, // const Handle(Adaptor3d_HSurface)& Surf1, // const Handle(Adaptor3d_HSurface)& Surf2, const IntSurf_Quadric& Quad1, const IntSurf_Quadric& Quad2, const Standard_Real _TolArc, const Standard_Boolean theIsReqToKeepRLine) { // On cherche a placer sur les restrictions solutions les points "multiples" // des autres lignes d intersection // Pas forcemment le plus efficace : on rique de projeter plusieurs fois // le meme point sur la meme restriction... Standard_Real TolArc=100.0*_TolArc; if(TolArc>0.1) TolArc=0.1; Standard_Integer i,j,k; Standard_Integer Nblin,Nbvtx, Nbpt; Standard_Boolean OnFirst = Standard_False,project = Standard_False,keeppoint = Standard_False; Handle(Adaptor2d_HCurve2d) arcref; Standard_Real paramproj,paramf,paraml; TColgp_SequenceOfPnt seq_Pnt3d; TColStd_SequenceOfReal seq_Real; gp_Pnt ptproj,toproj,valpt; gp_Pnt2d p2d; gp_Vec2d d2d; gp_Vec d1u,d1v,tgrest,tgarc,norm; IntSurf_Transition TRest,TArc; #ifndef OCCT_DEBUG Standard_Real U =0.,V =0.; #else Standard_Real U,V; #endif IntPatch_Point Ptvtx,newptvtx; IntPatch_IType typ1,typ2; Nblin = slin.Length(); for (i=1; i<=Nblin; i++) { const Handle(IntPatch_Line)& slini = slin(i); typ1 = slini->ArcType(); Standard_Boolean HasToDeleteRLine = Standard_False; if (typ1 == IntPatch_Restriction) { seq_Pnt3d.Clear(); seq_Real.Clear(); for (j=1; j<=Nblin; j++) { const Handle(IntPatch_Line)& slinj = slin(j); Nbpt = seq_Pnt3d.Length(); // important que ce soit ici typ2 = slinj->ArcType(); if (typ2 != IntPatch_Restriction) { //-- arcref = Handle(IntPatch_RLine)::DownCast (slini)->Arc(); //-- OnFirst = Handle(IntPatch_RLine)::DownCast (slini)->IsOnFirstSurface(); //-- DES CHOSES A FAIRE ICI if(Handle(IntPatch_RLine)::DownCast (slini)->IsArcOnS1()) { OnFirst=Standard_True; arcref= Handle(IntPatch_RLine)::DownCast (slini)->ArcOnS1(); } else if(Handle(IntPatch_RLine)::DownCast (slini)->IsArcOnS2()) { arcref= Handle(IntPatch_RLine)::DownCast (slini)->ArcOnS2(); OnFirst=Standard_False; } if (Handle(IntPatch_RLine)::DownCast (slini)->HasFirstPoint()) { paramf = Handle(IntPatch_RLine)::DownCast (slini)->FirstPoint().ParameterOnLine(); } else { // cout << "Pas de param debut sur rst solution" << endl; paramf = RealFirst(); } if (Handle(IntPatch_RLine)::DownCast (slini)->HasLastPoint()) { paraml = Handle(IntPatch_RLine)::DownCast (slini)->LastPoint().ParameterOnLine(); } else { // cout << "Pas de param debut sur rst solution" << endl; paraml = RealLast(); } if (typ2 == IntPatch_Analytic) { Nbvtx = Handle(IntPatch_ALine)::DownCast (slinj)->NbVertex(); } else { Nbvtx = Handle(IntPatch_GLine)::DownCast (slinj)->NbVertex(); } Standard_Boolean EdgeDegenere=Standard_True; for(Standard_Integer edg=0;EdgeDegenere && edg<=10;edg++) { arcref->D1(paramf+(paraml-paramf)*edg*0.1,p2d,d2d); if (OnFirst) { Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); } else { Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); } if(d1u.Magnitude()>1e-7) { EdgeDegenere=Standard_False; } } for (k=1; EdgeDegenere==Standard_False && k<=Nbvtx; k++) { if (typ2 == IntPatch_Analytic) { Ptvtx = Handle(IntPatch_ALine)::DownCast (slinj)->Vertex(k); } else { Ptvtx = Handle(IntPatch_GLine)::DownCast (slinj)->Vertex(k); } if ((OnFirst && !Ptvtx.IsOnDomS1()) || (!OnFirst && !Ptvtx.IsOnDomS2())) { // Si OnFirst && OnDomS1, c est qu on est a une extremite // ca doit etre traite par Process Segment... project = Standard_True; keeppoint = Standard_False; toproj = Ptvtx.Value(); Standard_Integer jj; for (jj = 1; jj <= Nbpt; jj++) { //for (Standard_Integer jj = 1; jj <= Nbpt; jj++) { if (toproj.Distance(seq_Pnt3d(jj)) < _TolArc) { project = Standard_False; break; } } if (project) { //-- il faut projeter pour trouver le point sur la rline. if (OnFirst) { Ptvtx.ParametersOnS1(U,V); } else { Ptvtx.ParametersOnS2(U,V); } project = IntPatch_HInterTool::Project(arcref,gp_Pnt2d(U,V), paramproj,p2d); if (project) { if (OnFirst) { ptproj = Quad1.Value(p2d.X(),p2d.Y()); } else { ptproj = Quad2.Value(p2d.X(),p2d.Y()); } if ((toproj.Distance(ptproj) <=100*TolArc) && (paramproj >= paramf) && (paramproj <= paraml)){ newptvtx = Ptvtx; newptvtx.SetParameter(paramproj); keeppoint = Standard_True; seq_Pnt3d.Append(toproj); seq_Real.Append(paramproj); //-- verifier que si la restriction arcref est trouvee, elle porte ce vertex for (int ri=1; ri<=Nblin; ri++) { const Handle(IntPatch_Line)& slinri = slin(ri); if (slinri->ArcType() == IntPatch_Restriction) { if(OnFirst && Handle(IntPatch_RLine)::DownCast (slinri)->IsArcOnS1()) { if(arcref == Handle(IntPatch_RLine)::DownCast (slinri)->ArcOnS1()) { Handle(IntPatch_RLine)::DownCast (slinri)->AddVertex(newptvtx); //printf("\n ImpImpIntersection_0.gxx CAS1 \n"); } } else if(OnFirst==Standard_False && Handle(IntPatch_RLine)::DownCast (slinri)->IsArcOnS2()) { if(arcref == Handle(IntPatch_RLine)::DownCast (slinri)->ArcOnS2()) { Handle(IntPatch_RLine)::DownCast (slinri)->AddVertex(newptvtx); //printf("\n ImpImpIntersection_0.gxx CAS2 \n"); } } } } // -- -------------------------------------------------- } } } else { keeppoint = Standard_True; newptvtx = Ptvtx; newptvtx.SetParameter(seq_Real(jj)); } if (keeppoint) { Ptvtx.SetMultiple(Standard_True); Ptvtx.SetTolerance(_TolArc); newptvtx.SetMultiple(Standard_True); if (typ2 == IntPatch_Analytic) { Handle(IntPatch_ALine)::DownCast (slinj)->Replace(k,Ptvtx); } else { Handle(IntPatch_GLine)::DownCast (slinj)->Replace(k,Ptvtx); } if (Ptvtx.IsOnDomS1() || Ptvtx.IsOnDomS2()) { arcref->D1(newptvtx.ParameterOnLine(),p2d,d2d); if (OnFirst) { // donc OnDomS2 Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); tgrest.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); const Handle(Adaptor2d_HCurve2d)& thearc = Ptvtx.ArcOnS2(); thearc->D1(Ptvtx.ParameterOnArc2(),p2d,d2d); Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); tgarc.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); norm = d1u.Crossed(d1v); //Quad2.Normale(valpt); if(norm.SquareMagnitude()<1e-16) { TRest.SetValue(Standard_True,IntSurf_Undecided); TArc.SetValue(Standard_True,IntSurf_Undecided); } else { IntSurf::MakeTransition(tgrest,tgarc,norm,TRest,TArc); } newptvtx.SetArc(Standard_False,thearc, Ptvtx.ParameterOnArc2(),TRest,TArc); } else { // donc OnDomS1 Quad2.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); tgrest.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); const Handle(Adaptor2d_HCurve2d)& thearc = Ptvtx.ArcOnS1(); thearc->D1(Ptvtx.ParameterOnArc1(),p2d,d2d); Quad1.D1(p2d.X(),p2d.Y(),valpt,d1u,d1v); tgarc.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v); norm = d1u.Crossed(d1v); //Quad1.Normale(valpt); if(norm.SquareMagnitude()<1e-16) { TRest.SetValue(Standard_True,IntSurf_Undecided); TArc.SetValue(Standard_True,IntSurf_Undecided); } else { IntSurf::MakeTransition(tgrest,tgarc,norm,TRest,TArc); } newptvtx.SetArc(Standard_True,thearc, Ptvtx.ParameterOnArc1(),TRest,TArc); } } //-- if (Ptvtx.IsOnDomS1() || Ptvtx.IsOnDomS2()) Handle(IntPatch_RLine)::DownCast (slini)->AddVertex(newptvtx); } //-- if (keeppoint) } //-- if ((OnFirst && !Ptvtx.IsOnDomS1())||(!OnFirst && !Ptvtx.IsOnDomS2())) } //-- boucle sur les vertex if(!theIsReqToKeepRLine) { Handle(IntPatch_GLine) aGL = Handle(IntPatch_GLine)::DownCast(slinj); if(!aGL.IsNull()) { HasToDeleteRLine = !IsRLineGood(Quad1, Quad2, aGL, Handle(IntPatch_RLine)::DownCast(slini), TolArc); } if(HasToDeleteRLine) { break; } } } //-- if (typ2 != IntPatch_Restriction) } //-- for (j=1; j<=Nblin; j++) } //-- if (typ1 == IntPatch_Restriction) if(HasToDeleteRLine) { slin.Remove(i); i--; Nblin = slin.Length(); continue; } } //-- for (i=1; i<=Nblin; i++) }