// Created on: 1993-07-12 // Created by: Yves FRICAUD // 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 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. #define Debug(expr) cout<<" MAT2d_Tool2d.cxx : expr :"< #include #include #endif #ifdef DRAW #include #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef DRAW static Handle(DrawTrSurf_Curve2d) draw; #endif #ifdef DEB static void MAT2d_DrawCurve(const Handle(Geom2d_Curve)& aCurve, const Standard_Integer Indice); static Standard_Boolean Store = Standard_False; #endif //===================================================================== // static functions //===================================================================== static IntRes2d_Domain Domain (const Handle(Geom2d_TrimmedCurve)& Bisector1, const Standard_Real Tolerance); static Handle(Standard_Type) Type (const Handle(Geom2d_Geometry)& acurve); static Standard_Boolean AreNeighbours(const Standard_Integer IEdge1, const Standard_Integer IEdge2, const Standard_Integer NbEdge); static void SetTrim(Bisector_Bisec& Bis , Handle(Geom2d_Curve)& Line1); static Standard_Real MAT2d_TOLCONF = 1.e-7; //============================================================================ //function : //purpose : //============================================================================ MAT2d_Tool2d::MAT2d_Tool2d() { theDirection = 1.; theNumberOfBisectors = 0; theNumberOfVecs = 0; theNumberOfPnts = 0; } //============================================================================= //function : InitItems //purpose : //============================================================================= void MAT2d_Tool2d::InitItems(const Handle(MAT2d_Circuit)& EquiCircuit) { theGeomBisectors.Clear(); theGeomPnts.Clear(); theGeomVecs.Clear(); theLinesLength.Clear(); theNumberOfBisectors = 0; theNumberOfVecs = 0; theNumberOfPnts = 0; theCircuit = EquiCircuit; } //============================================================================= //function : Sense //purpose : //============================================================================= void MAT2d_Tool2d::Sense(const MAT_Side aside) { if(aside == MAT_Left) theDirection = 1.; else theDirection = -1.; } //============================================================================= //function : NumberOfItems //purpose : //============================================================================= Standard_Integer MAT2d_Tool2d::NumberOfItems() const { return theCircuit->NumberOfItems(); } //============================================================================= //function : ToleranceOfConfusion //purpose : //============================================================================= Standard_Real MAT2d_Tool2d::ToleranceOfConfusion() const { return 2*MAT2d_TOLCONF; } //============================================================================= //function : FirstPoint //purpose : //============================================================================= Standard_Integer MAT2d_Tool2d::FirstPoint(const Standard_Integer anitem, Standard_Real& dist ) { Handle(Geom2d_Curve) curve; Handle(Geom2d_Point) point; theNumberOfPnts++; if (theCircuit->ConnexionOn(anitem)){ gp_Pnt2d P1 = theCircuit->Connexion(anitem)->PointOnFirst(); gp_Pnt2d P2 = theCircuit->Connexion(anitem)->PointOnSecond(); theGeomPnts.Bind(theNumberOfPnts,gp_Pnt2d((P1.X() + P2.X())*0.5, (P1.Y() + P2.Y())*0.5)); dist = P1.Distance(P2)*0.5; return theNumberOfPnts; } Handle(Standard_Type) type; type = theCircuit->Value(anitem)->DynamicType(); dist = 0.; if ( type != STANDARD_TYPE(Geom2d_CartesianPoint)){ curve = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(anitem)); theGeomPnts.Bind(theNumberOfPnts,curve->Value(curve->FirstParameter())); } else{ point = Handle(Geom2d_Point)::DownCast(theCircuit->Value(anitem)); theGeomPnts.Bind(theNumberOfPnts,point->Pnt2d()); } return theNumberOfPnts; } //============================================================================= //function : TangentBefore //purpose : //============================================================================= Standard_Integer MAT2d_Tool2d::TangentBefore(const Standard_Integer anitem) { Standard_Integer item; Handle(Geom2d_Curve) curve; theNumberOfVecs++; item = (anitem == theCircuit->NumberOfItems()) ? 1 : (anitem + 1); if (theCircuit->ConnexionOn(item)){ Standard_Real x1,y1,x2,y2; theCircuit->Connexion(item)->PointOnFirst().Coord(x1,y1); theCircuit->Connexion(item)->PointOnSecond().Coord(x2,y2); theGeomVecs.Bind(theNumberOfVecs,gp_Vec2d((x2-x1),(y2-y1))); return theNumberOfVecs; } Handle(Standard_Type) type; type = theCircuit->Value(anitem)->DynamicType(); if ( type != STANDARD_TYPE(Geom2d_CartesianPoint)){ curve = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(anitem)); theGeomVecs.Bind(theNumberOfVecs,curve->DN(curve->LastParameter(),1)); } else { curve = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(item)); theGeomVecs.Bind(theNumberOfVecs,curve->DN(curve->FirstParameter(),1)); } return theNumberOfVecs; } //============================================================================= //function : TangentAfter //purpose : //============================================================================= Standard_Integer MAT2d_Tool2d::TangentAfter(const Standard_Integer anitem) { Standard_Integer item; Handle(Geom2d_Curve) curve; gp_Vec2d thevector; theNumberOfVecs++; if (theCircuit->ConnexionOn(anitem)){ Standard_Real x1,y1,x2,y2; theCircuit->Connexion(anitem)->PointOnFirst().Coord(x1,y1); theCircuit->Connexion(anitem)->PointOnSecond().Coord(x2,y2); theGeomVecs.Bind(theNumberOfVecs,gp_Vec2d((x1-x2),(y1-y2))); return theNumberOfVecs; } Handle(Standard_Type) type; type = theCircuit->Value(anitem)->DynamicType(); if ( type != STANDARD_TYPE(Geom2d_CartesianPoint)){ curve = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(anitem)); thevector = curve->DN(curve->FirstParameter(),1); } else { item = (anitem == 1) ? theCircuit->NumberOfItems() : (anitem - 1); curve = Handle(Geom2d_Curve)::DownCast(theCircuit->Value(item)); thevector = curve->DN(curve->LastParameter(),1); } theGeomVecs.Bind(theNumberOfVecs,thevector.Reversed()); return theNumberOfVecs; } //============================================================================= //function : Tangent //purpose : //============================================================================= Standard_Integer MAT2d_Tool2d::Tangent(const Standard_Integer bisector) { theNumberOfVecs++; theGeomVecs.Bind(theNumberOfVecs,GeomBis(bisector).Value() ->DN(GeomBis(bisector).Value() ->LastParameter(),1)); return theNumberOfVecs; } //============================================================================= //function : CreateBisector //purpose : //============================================================================= void MAT2d_Tool2d::CreateBisector(const Handle(MAT_Bisector)& abisector) { Handle(Geom2d_Point) point1,point2; Handle(Geom2d_Geometry) elt1,elt2; Bisector_Bisec bisector; Standard_Real tolerance = MAT2d_TOLCONF ; Standard_Integer edge1number = abisector->FirstEdge()->EdgeNumber(); Standard_Integer edge2number = abisector->SecondEdge()->EdgeNumber(); Standard_Boolean ontheline = AreNeighbours(edge1number, edge2number, NumberOfItems()); Standard_Boolean InitialNeighbour = ontheline; if(theCircuit->ConnexionOn(edge2number)) ontheline = Standard_False; elt1 = theCircuit->Value(edge1number); elt2 = theCircuit->Value(edge2number); Handle(Standard_Type) type1; type1 = theCircuit->Value(edge1number)->DynamicType(); Handle(Standard_Type) type2; type2 = theCircuit->Value(edge2number)->DynamicType(); Handle(Geom2d_Curve) item1; Handle(Geom2d_Curve) item2; if ( type1 != STANDARD_TYPE(Geom2d_CartesianPoint)){ item1 = Handle(Geom2d_Curve)::DownCast(elt1); } if ( type2 != STANDARD_TYPE(Geom2d_CartesianPoint)){ item2 = Handle(Geom2d_Curve)::DownCast(elt2); } #ifdef DEB Standard_Boolean Affich = Standard_False; if (Affich) { cout<Dump(1,1); cout<Dump(1,1); cout<IssuePoint()), GeomVec (abisector->FirstVector()), GeomVec (abisector->SecondVector()), theDirection,tolerance,ontheline); } else if(type1 == STANDARD_TYPE(Geom2d_CartesianPoint) && type2 == STANDARD_TYPE(Geom2d_CartesianPoint)) { point1 = Handle(Geom2d_Point)::DownCast(elt1); point2 = Handle(Geom2d_Point)::DownCast(elt2); bisector.Perform(point1,point2, GeomPnt (abisector->IssuePoint()), GeomVec (abisector->FirstVector()), GeomVec (abisector->SecondVector()), theDirection,tolerance,ontheline); } else if(type1 == STANDARD_TYPE(Geom2d_CartesianPoint)) { point1 = Handle(Geom2d_Point)::DownCast(elt1); bisector.Perform(point1,item2, GeomPnt (abisector->IssuePoint()), GeomVec (abisector->FirstVector()), GeomVec (abisector->SecondVector()), theDirection,tolerance,ontheline); } else { point2 = Handle(Geom2d_Point)::DownCast(elt2); bisector.Perform(item1,point2, GeomPnt (abisector->IssuePoint()), GeomVec (abisector->FirstVector()), GeomVec (abisector->SecondVector()), theDirection,tolerance,ontheline); } //------------------------------ // Restriction de la bisectrice. //----------------------------- TrimBisec(bisector,edge1number,InitialNeighbour,1); TrimBisec(bisector,edge2number,InitialNeighbour,2); theNumberOfBisectors++; theGeomBisectors.Bind(theNumberOfBisectors,bisector); abisector->BisectorNumber(theNumberOfBisectors); abisector->Sense(1); #ifdef DEB Standard_Boolean AffichDraw = Standard_False; if (AffichDraw) Dump(abisector->BisectorNumber(),1); if (Store) { Handle(Standard_Type) Type1 = Type(bisector.Value()->BasisCurve()); Handle(Geom2d_Curve) BasisCurve; if (Type1 == STANDARD_TYPE(Bisector_BisecAna)) { BasisCurve = Handle(Bisector_BisecAna) ::DownCast(bisector.Value()->BasisCurve())->Geom2dCurve(); #ifdef DRAW char *name = new char[100]; sprintf(name,"BISSEC_%d",abisector->BisectorNumber()); DrawTrSurf::Set(name,BasisCurve); delete [] name; #endif } } #endif } //============================================================================= //function : TrimBisec //purpose : Restriction de la bisectrice. // Restriction des bissectrice separant deux elements lies par une // connexion ou l un au moins des elements est un cercle. // Cette restriction est necessaire a la logique de l algorithme. //============================================================================= void MAT2d_Tool2d::TrimBisec ( Bisector_Bisec& B1, const Standard_Integer IndexEdge, const Standard_Boolean InitialNeighbour, const Standard_Integer StartOrEnd ) const { Handle(Geom2d_Curve) Curve; Handle(Geom2d_TrimmedCurve) LineSupportDomain,Line; Handle(Geom2d_Line) Line1,Line2; //gp_Vec2d Tan1,Tan2; gp_Pnt2d Ori; //PEdge; Standard_Integer INext; INext = (IndexEdge == theCircuit->NumberOfItems()) ? 1 : (IndexEdge + 1); Handle(Standard_Type) EdgeType = theCircuit->Value(IndexEdge)->DynamicType(); if (EdgeType != STANDARD_TYPE(Geom2d_CartesianPoint)) { if(!InitialNeighbour) { Curve = Handle(Geom2d_TrimmedCurve) ::DownCast(theCircuit->Value(IndexEdge))->BasisCurve(); EdgeType = Curve->DynamicType(); //------------------------------------------------------------------- // si l edge est liee a sa voisine precedente par une connexion. //------------------------------------------------------------------- if (theCircuit->ConnexionOn(IndexEdge) && StartOrEnd == 1){ if (EdgeType == STANDARD_TYPE(Geom2d_Circle)) { Ori = Handle(Geom2d_Circle)::DownCast(Curve)->Location(); gp_Pnt2d P2 = theCircuit->Connexion(IndexEdge)->PointOnFirst(); Line1 = new Geom2d_Line (Ori,gp_Dir2d(P2.X() - Ori.X(), P2.Y() - Ori.Y())); } } //----------------------------------------------------------------------- // Si l edge est liee a sa voisine suivante par une connexion. //----------------------------------------------------------------------- if (theCircuit->ConnexionOn(INext) && StartOrEnd == 2){ if (EdgeType == STANDARD_TYPE(Geom2d_Circle)) { Ori = Handle(Geom2d_Circle)::DownCast(Curve)->Location(); gp_Pnt2d P2 = theCircuit->Connexion(INext)->PointOnSecond(); Line2 = new Geom2d_Line (Ori,gp_Dir2d(P2.X() - Ori.X(), P2.Y() - Ori.Y())); } } if (Line1.IsNull() && Line2.IsNull()) return; //----------------------------------------------------------------------- // Restriction de la bisectrice par les demi-droites liees aux connexions // si elles existent. //----------------------------------------------------------------------- if (!Line1.IsNull()) { Line = new Geom2d_TrimmedCurve(Line1,0.,Precision::Infinite()); SetTrim(B1,Line); } if (!Line2.IsNull()) { Line = new Geom2d_TrimmedCurve(Line2,0.,Precision::Infinite()); SetTrim(B1,Line); } } } } //============================================================================= //function : TrimBisector //purpose : //============================================================================= Standard_Boolean MAT2d_Tool2d::TrimBisector (const Handle(MAT_Bisector)& abisector) { Standard_Real param = abisector->FirstParameter(); #ifdef DEB Standard_Boolean Affich = Standard_False; if (Affich) cout<<"TRIM de "<BisectorNumber()<BisectorNumber()).ChangeValue()); if(bisector->BasisCurve()->IsPeriodic() && param == Precision::Infinite()) { param = bisector->FirstParameter() + 2*M_PI; } if (param > bisector->BasisCurve()->LastParameter()) { param = bisector->BasisCurve()->LastParameter(); } if(bisector->FirstParameter() == param) return Standard_False; bisector->SetTrim(bisector->FirstParameter(),param); return Standard_True; } //============================================================================= //function : TrimBisector //purpose : //============================================================================= Standard_Boolean MAT2d_Tool2d::TrimBisector (const Handle(MAT_Bisector)& abisector, const Standard_Integer apoint) { Standard_Real Param; Handle(Geom2d_TrimmedCurve) Bisector = Handle(Geom2d_TrimmedCurve):: DownCast(ChangeGeomBis(abisector->BisectorNumber()).ChangeValue()); Handle(Bisector_Curve) Bis = Handle(Bisector_Curve):: DownCast(Bisector->BasisCurve()); // Param = ParameterOnCurve(Bisector,theGeomPnts.Value(apoint)); Param = Bis->Parameter(GeomPnt (apoint)); if (Bisector->BasisCurve()->IsPeriodic()) { if (Bisector->FirstParameter() > Param) Param = Param + 2*M_PI; } if(Bisector->FirstParameter() >= Param)return Standard_False; if(Bisector->LastParameter() < Param)return Standard_False; Bisector->SetTrim(Bisector->FirstParameter(),Param); #ifdef DEB Standard_Boolean Affich = Standard_False; if (Affich) MAT2d_DrawCurve(Bisector,2); #endif return Standard_True; } //============================================================================= //function : Projection //purpose : //============================================================================= Standard_Boolean MAT2d_Tool2d::Projection (const Standard_Integer IEdge , const gp_Pnt2d& PCom , Standard_Real& Distance) const { gp_Pnt2d PEdge; Handle(Geom2d_Geometry) Elt = theCircuit->Value(IEdge); Handle(Standard_Type) Type = Elt->DynamicType(); Handle(Geom2d_TrimmedCurve) Curve; Standard_Integer INext; Standard_Real Eps = MAT2d_TOLCONF;//*10.; if (Type == STANDARD_TYPE(Geom2d_CartesianPoint)) { PEdge = Handle(Geom2d_Point)::DownCast(Elt)->Pnt2d(); Distance = PCom.Distance(PEdge); } else { Distance = Precision::Infinite(); Curve = Handle(Geom2d_TrimmedCurve)::DownCast(Elt); //----------------------------------------------------------------------- // Calcul des parametres MinMax sur l edge si celui ci est lies a ses // voisins par des connexions la courbe de calcul est limitee par // celles_ci. //----------------------------------------------------------------------- Standard_Real ParamMin = Curve->FirstParameter(); Standard_Real ParamMax = Curve->LastParameter(); if (theCircuit->ConnexionOn(IEdge)) { ParamMin = theCircuit->Connexion(IEdge)->ParameterOnSecond(); } INext = (IEdge == theCircuit->NumberOfItems()) ? 1 : (IEdge + 1); if (theCircuit->ConnexionOn(INext)) { ParamMax = theCircuit->Connexion(INext)->ParameterOnFirst(); if (Curve->BasisCurve()->IsPeriodic()){ ElCLib::AdjustPeriodic(0.,2*M_PI,Eps,ParamMin,ParamMax); } } //--------------------------------------------------------------------- // Constuction de la courbe pour les extremas et ajustement des bornes. //--------------------------------------------------------------------- Geom2dAdaptor_Curve C1(Curve); GeomAbs_CurveType TypeC1 = C1.GetType(); if (TypeC1 == GeomAbs_Circle) { Standard_Real R = C1.Circle().Radius(); Standard_Real EpsCirc = Eps; if ( R < 1.) EpsCirc = Eps/R; if (!((ParamMax - ParamMin + 2*EpsCirc) < 2*M_PI)) { ParamMax = ParamMax + EpsCirc; ParamMin = ParamMin - EpsCirc; } } else { ParamMax = ParamMax + Eps; ParamMin = ParamMin - Eps; } //----------------------------------------------------- // Calcul des extremas et stockage minimum de distance. //----------------------------------------------------- Extrema_ExtPC2d Extremas(PCom,C1,ParamMin,ParamMax); if (Extremas.IsDone()){ if (Extremas.NbExt() == 0 ) return Standard_False; // Pas de solution! for (Standard_Integer i = 1; i <= Extremas.NbExt(); i++) { if (Extremas.SquareDistance(i) < Distance * Distance) { Distance = sqrt (Extremas.SquareDistance(i)); } } } else { if (TypeC1 == GeomAbs_Circle) { Distance = C1.Circle().Radius(); } } } return Standard_True; } //============================================================================= //function : IsSameDistance // purpose : //============================================================================= Standard_Boolean MAT2d_Tool2d::IsSameDistance ( const Handle(MAT_Bisector)& BisectorOne, const Handle(MAT_Bisector)& BisectorTwo, const gp_Pnt2d& PCom, Standard_Real& Distance) const { TColStd_Array1OfReal Dist(1,4); Standard_Integer IEdge1,IEdge2,IEdge3,IEdge4; IEdge1 = BisectorOne->FirstEdge() ->EdgeNumber(); IEdge2 = BisectorOne->SecondEdge()->EdgeNumber(); IEdge3 = BisectorTwo->FirstEdge() ->EdgeNumber(); IEdge4 = BisectorTwo->SecondEdge()->EdgeNumber(); Projection(IEdge1,PCom,Dist(1)); Projection(IEdge2,PCom,Dist(2)); if (IEdge3 == IEdge1) Dist(3) = Dist(1); else if (IEdge3 == IEdge2) Dist(3) = Dist(2); else Projection(IEdge3,PCom,Dist(3)); if (IEdge4 == IEdge1) Dist(4) = Dist(1); else if (IEdge4 == IEdge2) Dist(4) = Dist(2); else Projection(IEdge4,PCom,Dist(4)); #ifdef DEB Standard_Boolean Affich = Standard_False; if (Affich) for (Standard_Integer j = 1; j <= 4;j++){ cout <<"Distance number : "< EpsDist) { Distance = Precision::Infinite(); return Standard_False; } } return Standard_True; } //============================================================================= //function : IntersectBisector //purpose : //============================================================================= Standard_Real MAT2d_Tool2d::IntersectBisector ( const Handle(MAT_Bisector)& BisectorOne, const Handle(MAT_Bisector)& BisectorTwo, Standard_Integer& IntPnt) { Standard_Real Tolerance = MAT2d_TOLCONF; Standard_Real Param1,Param2; Standard_Real Parama,Paramb; Standard_Real Distance = 0.,DistanceMini; Standard_Boolean SolutionValide; gp_Pnt2d PointSolution; Handle(Geom2d_TrimmedCurve) Bisector1 = Handle(Geom2d_TrimmedCurve) ::DownCast(ChangeGeomBis(BisectorOne->BisectorNumber()).ChangeValue()); Handle(Geom2d_TrimmedCurve) Bisector2 = Handle(Geom2d_TrimmedCurve) ::DownCast(ChangeGeomBis(BisectorTwo->BisectorNumber()).ChangeValue()); if(Bisector1.IsNull() || Bisector2.IsNull()) return Precision::Infinite(); //------------------------------------------------------------------------- // Si les deux bissectrices separent des elements consecutifs et qu elles // sont issues des connexions C1 et C2. // Si C1 est la reverse de C2 ,alors les deux bissectrices sont issues // du meme point. Dans ce cas l intersection n est pas validee. //------------------------------------------------------------------------- Standard_Integer IS1 = BisectorOne->SecondEdge()->EdgeNumber(); Standard_Integer IS2 = BisectorTwo->SecondEdge()->EdgeNumber(); Standard_Integer IF1 = BisectorOne->FirstEdge() ->EdgeNumber(); Standard_Integer IF2 = BisectorTwo->FirstEdge() ->EdgeNumber(); if (AreNeighbours(IF1,IS1,NumberOfItems()) && AreNeighbours(IF2,IS2,NumberOfItems()) && theCircuit->ConnexionOn(IS2) && theCircuit->ConnexionOn(IS1) ) { Handle(MAT2d_Connexion) C1,C2; C1 = theCircuit->Connexion(IS1); C2 = theCircuit->Connexion(IS2); if (C2->IndexFirstLine() == C1->IndexSecondLine() && C1->IndexFirstLine() == C2->IndexSecondLine() ) return Precision::Infinite(); } // ----------------------------------------- // Construction des domaines d intersection. // ----------------------------------------- IntRes2d_Domain Domain1 = Domain(Bisector1,Tolerance); IntRes2d_Domain Domain2 = Domain(Bisector2,Tolerance); if (Domain1.LastParameter() - Domain1.FirstParameter() < Tolerance) return Precision::Infinite(); if (Domain2.LastParameter() - Domain2.FirstParameter() < Tolerance) return Precision::Infinite(); #ifdef DEB Standard_Boolean Affich = Standard_False; if (Affich) { cout<BisectorNumber()<< " et de "<BisectorNumber()<BasisCurve())->Dump(-1,1); cout<BasisCurve())->Dump(-1,1); cout<BisectorNumber()),Domain1, GeomBis(BisectorTwo->BisectorNumber()),Domain2, Tolerance,Tolerance,Standard_True); // Geom2dInt_GInter Intersect; // Intersect.Perform(Bisector1,Domain1,Bisector2,Domain2,Tolerance,Tolerance); // ------------------------------------------------------------------------- // Exploitation du resultat de l intersection et selection du point solution // equidistant des deux edges et le plus proche en parametre de l origine // des bissectrices. // ------------------------------------------------------------------------- if(!Intersect.IsDone()) return Precision::Infinite(); if(Intersect.IsEmpty()) return Precision::Infinite(); DistanceMini = Precision::Infinite(); Param1 = Precision::Infinite(); Param2 = Precision::Infinite(); SolutionValide = Standard_False; if(Intersect.NbSegments() >= 1) { Standard_Real MaxSegmentLength = 10.*Tolerance; for (Standard_Integer i=1;i<=Intersect.NbSegments();i++) { IntRes2d_IntersectionSegment Segment = Intersect.Segment(i); Standard_Boolean PointRetenu = Standard_False; gp_Pnt2d PointOnSegment; // ---------------------------------------------------------------- // Si les segments sont petits, recherche des points sur le segment // equidistants des edges. // ---------------------------------------------------------------- if ((Segment.HasFirstPoint() && Segment.HasLastPoint())) { gp_Pnt2d P1,P2; Standard_Real SegmentLength; P1 = Segment.FirstPoint().Value(); P2 = Segment.LastPoint().Value(); SegmentLength = P1.Distance(P2); if (SegmentLength <= Tolerance) { PointOnSegment = P1; if(IsSameDistance(BisectorOne,BisectorTwo, PointOnSegment,Distance)) PointRetenu = Standard_True; } else if (SegmentLength <= MaxSegmentLength) { gp_Dir2d Dir(P2.X()-P1.X(),P2.Y()-P1.Y()); Standard_Real Dist = 0.; while (Dist <= SegmentLength + Tolerance){ PointOnSegment = P1.Translated(Dist*Dir); if(IsSameDistance(BisectorOne,BisectorTwo, PointOnSegment,Distance)) { PointRetenu = Standard_True; break; } Dist = Dist + Tolerance; } } } // ---------------------------------------------------------------- // Sauvegarde du point equidistant des edges de plus petit // parametre sur les bissectrices. // ---------------------------------------------------------------- if(PointRetenu) { Parama = Handle(Bisector_Curve)::DownCast(Bisector1->BasisCurve()) ->Parameter(PointOnSegment); Paramb = Handle(Bisector_Curve)::DownCast(Bisector2->BasisCurve()) ->Parameter(PointOnSegment); if(Parama < Param1 && Paramb < Param2) { Param1 = Parama; Param2 = Paramb; DistanceMini = Distance; PointSolution = PointOnSegment; SolutionValide = Standard_True; } } } } if(Intersect.NbPoints() != 1) { for(Standard_Integer i=1; i<=Intersect.NbPoints(); i++) { if(IsSameDistance(BisectorOne,BisectorTwo, Intersect.Point(i).Value(),Distance) && Distance > Tolerance ) { Parama = Intersect.Point(i).ParamOnFirst(); Paramb = Intersect.Point(i).ParamOnSecond(); if (Parama < Param1 && Paramb < Param2) { Param1 = Parama; Param2 = Paramb; DistanceMini = Distance; PointSolution = Intersect.Point(i).Value(); SolutionValide = Standard_True; } } } } else { PointSolution = Intersect.Point(1).Value(); Param1 = Intersect.Point(1).ParamOnFirst(); Param2 = Intersect.Point(1).ParamOnSecond(); SolutionValide = IsSameDistance(BisectorOne,BisectorTwo, PointSolution,DistanceMini); } if (!SolutionValide) return Precision::Infinite(); theNumberOfPnts++; theGeomPnts.Bind(theNumberOfPnts,PointSolution); IntPnt = theNumberOfPnts; //----------------------------------------------------------------------- // Si le point d intersection est quasi confondue avec une des extremites // de l une ou l autre des bisectrices, l intersection n est pas validee. // // SAUF si une des bisectrices est issue d une connexion et que les // edges separes par les bissectrices sont des voisines sur le contour // initiales. // en effet le milieu de la connexion P qui est l origine d une des // bissectrices peut etre sur l autre bissectrice. // P est donc point d intersection // et la bissectrice issue de la connexion est de longueur nulle. // (ex : un rectangle dans un rectangle ou la connexion est entre un coin // et un cote). //----------------------------------------------------------------------- Standard_Integer IndexEdge1,IndexEdge2,IndexEdge3,IndexEdge4; Standard_Boolean ExtremiteControle = Standard_True; IndexEdge1 = BisectorOne->FirstEdge() ->EdgeNumber(); IndexEdge2 = BisectorOne->SecondEdge()->EdgeNumber(); IndexEdge3 = BisectorTwo->FirstEdge() ->EdgeNumber(); IndexEdge4 = BisectorTwo->SecondEdge()->EdgeNumber(); if (theCircuit->ConnexionOn(IndexEdge2)){ // -------------------------------------- // BisectorOne est issue d une connexion. // -------------------------------------- if (AreNeighbours(IndexEdge1,IndexEdge2,NumberOfItems()) && AreNeighbours(IndexEdge3,IndexEdge4,NumberOfItems()) && IndexEdge2 == IndexEdge3 ){ ExtremiteControle = Standard_False; Param1 = Param1 + Tolerance; } } if (theCircuit->ConnexionOn(IndexEdge4)){ // -------------------------------------- // BisectorTwo est issue d une connexion. // -------------------------------------- if (AreNeighbours(IndexEdge1,IndexEdge2,NumberOfItems()) && AreNeighbours(IndexEdge3,IndexEdge4,NumberOfItems()) && IndexEdge2 == IndexEdge3 ){ ExtremiteControle = Standard_False; Param2 = Param2 + Tolerance; } } if (ExtremiteControle) { if(Bisector1->StartPoint().Distance(PointSolution) < Tolerance || Bisector2->StartPoint().Distance(PointSolution) < Tolerance ) return Precision::Infinite(); } if(BisectorOne->SecondParameter() < Precision::Infinite() && BisectorOne->SecondParameter() < Param1*(1. - Tolerance )) return Precision::Infinite(); if(BisectorTwo->FirstParameter() < Precision::Infinite() && BisectorTwo->FirstParameter() < Param2*(1.- Tolerance)) return Precision::Infinite(); BisectorOne->SecondParameter(Param1); BisectorTwo->FirstParameter (Param2); #ifdef DEB if (Affich) { cout<<" coordonnees : "<BisectorNumber()).Value()->Value(Param1); gp_Pnt2d P2 = GeomBis(Bis->BisectorNumber()).Value()->Value(Param2); Dist = P1.Distance(P2); } return Dist; } //============================================================================= //function : Dump //purpose : //============================================================================= #ifndef DEB void MAT2d_Tool2d::Dump(const Standard_Integer , const Standard_Integer ) const { Standard_NotImplemented::Raise(); #else void MAT2d_Tool2d::Dump(const Standard_Integer bisector, const Standard_Integer) const { if(bisector == -1) return; if(bisector > theNumberOfBisectors) return; Handle(Geom2d_Curve) thebisector = GeomBis(bisector).Value(); MAT2d_DrawCurve(thebisector,3); #endif } //============================================================================= //function : GeomBis //purpose : //============================================================================= const Bisector_Bisec& MAT2d_Tool2d::GeomBis (const Standard_Integer Index) const { return theGeomBisectors.Find(Index); } //============================================================================= //function : ChangeGeomBis //purpose : //============================================================================= Bisector_Bisec& MAT2d_Tool2d::ChangeGeomBis(const Standard_Integer Index) { return theGeomBisectors.ChangeFind(Index); } //============================================================================= //function : GeomElt //purpose : //============================================================================= Handle(Geom2d_Geometry) MAT2d_Tool2d::GeomElt(const Standard_Integer Index) const { return theCircuit->Value(Index); } //============================================================================= //function : GeomPnt //purpose : //============================================================================= const gp_Pnt2d& MAT2d_Tool2d::GeomPnt(const Standard_Integer Index) const { return theGeomPnts.Find(Index); } //============================================================================= //function : GeomVec //purpose : //============================================================================= const gp_Vec2d& MAT2d_Tool2d::GeomVec(const Standard_Integer Index)const { return theGeomVecs.Find(Index); } //============================================================================= //function : Circuit //purpose : //============================================================================= Handle(MAT2d_Circuit) MAT2d_Tool2d::Circuit()const { return theCircuit; } //============================================================================= //function : BisecFusion //purpose : //============================================================================= void MAT2d_Tool2d::BisecFusion(const Standard_Integer I1, const Standard_Integer I2) { Standard_Real DU,UL1,UF1; Handle(Geom2d_TrimmedCurve) Bisector1; Handle(Geom2d_TrimmedCurve) Bisector2; Bisector1 = Handle(Geom2d_TrimmedCurve)::DownCast(GeomBis(I1).Value()); Bisector2 = Handle(Geom2d_TrimmedCurve)::DownCast(GeomBis(I2).Value()); UF1 = Bisector1->FirstParameter(); UL1 = Bisector1->LastParameter(); Handle(Standard_Type) Type1 = Bisector1->BasisCurve()->DynamicType(); if (Type1 == STANDARD_TYPE(Bisector_BisecCC)) { //------------------------------------------------------------------------------------ // les bissectrice courbe/courbe sont construites avec un point de depart // elles ne peuvent pas etre trimes par un point se trouvant de l autre cote du // point de depart. // pour faire la fusion des deux bissectrices on reconstruit la bissectrice entre les // deux courbes avec comme point de depart le dernier point de la Bisector2. // on trime ensuite la courbe par le dernier point de Bisector1. //------------------------------------------------------------------------------------ Standard_Real Tolerance = MAT2d_TOLCONF; Bisector_Bisec Bis; gp_Vec2d VBid(1,0); gp_Pnt2d P2 = Bisector2->Value(Bisector2->LastParameter()); gp_Pnt2d P1 = Bisector1->Value(Bisector1->LastParameter()); Handle(Bisector_BisecCC) BCC1 = Handle(Bisector_BisecCC)::DownCast(Bisector1->BasisCurve()); Bis.Perform(BCC1->Curve(2), BCC1->Curve(1), P2, VBid, VBid, theDirection, Tolerance, Standard_False); Bisector1 = Handle(Geom2d_TrimmedCurve)::DownCast(Bis.Value()); BCC1 = Handle(Bisector_BisecCC) ::DownCast(Bisector1->BasisCurve()); UF1 = BCC1->FirstParameter(); UL1 = BCC1->Parameter(P1); Bisector1->SetTrim(UF1,UL1); theGeomBisectors.Bind(I1,Bis); } else { DU = Bisector2->LastParameter() - Bisector2->FirstParameter(); UF1 = UF1 - DU; Handle(Bisector_BisecAna) BAna = Handle(Bisector_BisecAna)::DownCast(Bisector1->BasisCurve()); //---------------------------- uncomment if new method Bisector_BisecAna::SetTrim(f,l) is not used // Handle(Geom2d_Curve) C2d = BAna->Geom2dCurve(); // Handle(Geom2d_TrimmedCurve) trimC2d = new Geom2d_TrimmedCurve(C2d, UF1, UL1); // BAna->Init(trimC2d); //--------------------------- end BAna->SetTrim(UF1,UL1); // put comment if SetTrim(f,l) is not used Bisector1->SetTrim(UF1,UL1); } } //============================================================================= //function : Type //purpose : //============================================================================= static Handle(Standard_Type) Type(const Handle(Geom2d_Geometry)& aGeom) { Handle(Standard_Type) type = aGeom->DynamicType(); Handle(Geom2d_Curve) curve; if (type == STANDARD_TYPE(Geom2d_TrimmedCurve)) { curve = Handle(Geom2d_TrimmedCurve)::DownCast(aGeom)->BasisCurve(); type = curve->DynamicType(); } return type; } //========================================================================== //function : AreNeighbours //purpose : Return TRUE si IEdge1 et IEdge2 correspondent a des elements // consecutifs sur un contour ferme de NbEdge elements. //========================================================================== Standard_Boolean AreNeighbours(const Standard_Integer IEdge1, const Standard_Integer IEdge2, const Standard_Integer NbEdge) { if (Abs(IEdge1 - IEdge2) == 1) return Standard_True; else if (Abs(IEdge1 - IEdge2) == NbEdge -1) return Standard_True; else return Standard_False; } //========================================================================== //function : SetTrim //purpose : //========================================================================== void SetTrim(Bisector_Bisec& Bis, Handle(Geom2d_Curve)& Line1) { Geom2dInt_GInter Intersect; Standard_Real Distance; Standard_Real Tolerance = MAT2d_TOLCONF; Handle(Geom2d_TrimmedCurve) Bisector = Handle(Geom2d_TrimmedCurve)::DownCast(Bis.ChangeValue()); IntRes2d_Domain Domain1 = Domain(Bisector,Tolerance); Standard_Real UB1 = Bisector->FirstParameter(); Standard_Real UB2 = Bisector->LastParameter(); gp_Pnt2d FirstPointBisector = Bisector->Value(UB1); Standard_Real UTrim = Precision::Infinite(); Geom2dAdaptor_Curve AdapBisector(Bisector); Geom2dAdaptor_Curve AdapLine1 (Line1); Intersect.Perform(AdapBisector, Domain1, AdapLine1, Tolerance, Tolerance); if (Intersect.IsDone() && !Intersect.IsEmpty()) { for (Standard_Integer i = 1; i <= Intersect.NbPoints(); i++) { gp_Pnt2d PInt = Intersect.Point(i).Value(); Distance = FirstPointBisector.Distance(PInt); if (Distance > 10.*Tolerance && Intersect.Point(i).ParamOnFirst() < UTrim ) { UTrim = Intersect.Point(i).ParamOnFirst(); } } } // ------------------------------------------------------------------------ // Restriction de la Bissectrice par le point d intersection de plus petit // parametre. // ------------------------------------------------------------------------ if (UTrim < UB2 && UTrim > UB1) Bisector->SetTrim(UB1,UTrim); } //========================================================================== //function : Domain //purpose : //========================================================================== IntRes2d_Domain Domain(const Handle(Geom2d_TrimmedCurve)& Bisector1, const Standard_Real Tolerance) { Standard_Real Param1 = Bisector1->FirstParameter(); Standard_Real Param2 = Bisector1->LastParameter(); if(Param2 > 10000.) { Param2 = 10000.; Handle(Standard_Type) Type1 = Type(Bisector1->BasisCurve()); Handle(Geom2d_Curve) BasisCurve; if (Type1 == STANDARD_TYPE(Bisector_BisecAna)) { BasisCurve = Handle(Bisector_BisecAna) ::DownCast(Bisector1->BasisCurve())->Geom2dCurve(); Type1 = BasisCurve->DynamicType(); } gp_Parab2d gpParabola; gp_Hypr2d gpHyperbola; Standard_Real Focus; Standard_Real Limit = 50000.; if (Type1 == STANDARD_TYPE(Geom2d_Parabola)) { gpParabola = Handle(Geom2d_Parabola)::DownCast(BasisCurve)->Parab2d(); Focus = gpParabola.Focal(); Standard_Real Val1 = Sqrt(Limit*Focus); Standard_Real Val2 = Sqrt(Limit*Limit); Param2 = (Val1 <= Val2 ? Val1:Val2); } else if (Type1 == STANDARD_TYPE(Geom2d_Hyperbola)) { gpHyperbola = Handle(Geom2d_Hyperbola)::DownCast(BasisCurve)->Hypr2d(); Standard_Real Majr = gpHyperbola.MajorRadius(); Standard_Real Minr = gpHyperbola.MinorRadius(); Standard_Real Valu1 = Limit/Majr; Standard_Real Valu2 = Limit/Minr; Standard_Real Val1 = Log(Valu1+Sqrt(Valu1*Valu1-1)); Standard_Real Val2 = Log(Valu2+Sqrt(Valu2*Valu2+1)); Param2 = (Val1 <= Val2 ? Val1:Val2); } } IntRes2d_Domain Domain1(Bisector1->Value(Param1),Param1,Tolerance, Bisector1->Value(Param2),Param2,Tolerance); if(Bisector1->BasisCurve()->IsPeriodic()) { Domain1.SetEquivalentParameters(0.,2.*M_PI); } return Domain1; } #ifdef DEB //========================================================================== //function : MAT2d_DrawCurve //purpose : Affichage d une courbe de Geom2d. dans une couleur // definie par . // Indice = 1 jaune, // Indice = 2 bleu, // Indice = 3 rouge, // Indice = 4 vert. //========================================================================== void MAT2d_DrawCurve(const Handle(Geom2d_Curve)& aCurve, const Standard_Integer /*Indice*/) { Handle(Standard_Type) type = aCurve->DynamicType(); Handle(Geom2d_Curve) curve,CurveDraw; #ifdef DRAW Handle(DrawTrSurf_Curve2d) dr; Draw_Color Couleur; #endif if (type == STANDARD_TYPE(Geom2d_TrimmedCurve)) { curve = Handle(Geom2d_TrimmedCurve)::DownCast(aCurve)->BasisCurve(); type = curve->DynamicType(); // PB de representation des courbes semi_infinies. gp_Parab2d gpParabola; gp_Hypr2d gpHyperbola; Standard_Real Focus; Standard_Real Limit = 50000.; Standard_Real delta = 400; // PB de representation des courbes semi_infinies. if (aCurve->LastParameter() == Precision::Infinite()) { if (type == STANDARD_TYPE(Geom2d_Parabola)) { gpParabola = Handle(Geom2d_Parabola)::DownCast(curve)->Parab2d(); Focus = gpParabola.Focal(); Standard_Real Val1 = Sqrt(Limit*Focus); Standard_Real Val2 = Sqrt(Limit*Limit); delta= (Val1 <= Val2 ? Val1:Val2); } else if (type == STANDARD_TYPE(Geom2d_Hyperbola)) { gpHyperbola = Handle(Geom2d_Hyperbola)::DownCast(curve)->Hypr2d(); Standard_Real Majr = gpHyperbola.MajorRadius(); Standard_Real Minr = gpHyperbola.MinorRadius(); Standard_Real Valu1 = Limit/Majr; Standard_Real Valu2 = Limit/Minr; Standard_Real Val1 = Log(Valu1+Sqrt(Valu1*Valu1-1)); Standard_Real Val2 = Log(Valu2+Sqrt(Valu2*Valu2+1)); delta = (Val1 <= Val2 ? Val1:Val2); } CurveDraw = new Geom2d_TrimmedCurve(aCurve, aCurve->FirstParameter(), aCurve->FirstParameter() + delta); } else { CurveDraw = aCurve; } // fin PB. } else { CurveDraw = aCurve; } #ifdef DRAW if (Indice == 1) Couleur = Draw_jaune; else if (Indice == 2) Couleur = Draw_bleu; else if (Indice == 3) Couleur = Draw_rouge; else if (Indice == 4) Couleur = Draw_vert; if (type == STANDARD_TYPE(Geom2d_Circle)) dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,30); else if (type == STANDARD_TYPE(Geom2d_Line)) dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,2); else dr = new DrawTrSurf_Curve2d(CurveDraw,Couleur,500); dout << dr; dout.Flush(); #endif } #endif