1 // Created on: 1993-10-07
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
22 #include <MAT2d_MiniPath.ixx>
23 #include <MAT2d_Connexion.hxx>
24 #include <MAT2d_Array2OfConnexion.hxx>
25 #include <Extrema_POnCurv2d.hxx>
26 #include <Extrema_ExtCC2d.hxx>
27 #include <Extrema_ExtPC2d.hxx>
28 #include <Geom2dAdaptor_Curve.hxx>
29 #include <Geom2d_Point.hxx>
30 #include <Geom2d_CartesianPoint.hxx>
31 #include <TColStd_SequenceOfInteger.hxx>
32 #include <TColGeom2d_SequenceOfGeometry.hxx>
33 #include <Standard_NotImplemented.hxx>
35 //============================================================================
36 //function : MAT2d_MiniPath()
38 //============================================================================
39 MAT2d_MiniPath::MAT2d_MiniPath()
43 //============================================================================
45 //purpose : Calcul du chemin reliant les differents elements de <aFigure>.
46 // le chemin part de la ligne <IndStart>.
47 // <Sense> = True les lignes sont orientes dans le sens trigo.
48 //============================================================================
49 void MAT2d_MiniPath::Perform
50 (const MAT2d_SequenceOfSequenceOfGeometry& Figure,
51 const Standard_Integer IndStart,
52 const Standard_Boolean Sense)
56 Standard_Integer NbLines = Figure.Length();
57 MAT2d_Array2OfConnexion Connexion (1,NbLines,1,NbLines);
61 if (Sense) theDirection = -1.;
63 //----------------------------------------------------------------------
64 // Calcul des connexions qui realisent le minimum de distance entre les
65 // differents elements de la figure.
66 //----------------------------------------------------------------------
67 for (i = 1; i < NbLines; i++) {
68 for (j =i+1; j <= NbLines; j++){
69 Connexion(i,j) = MinimumL1L2(Figure,i,j);
70 Connexion(j,i) = Connexion(i,j)->Reverse();
74 TColStd_SequenceOfInteger Set1;
75 TColStd_SequenceOfInteger Set2;
76 Standard_Real DistS1S2;
77 Standard_Integer IndiceLine1,IndiceLine2;
78 Standard_Integer ISuiv =0,MinOnSet1 =0,MinOnSet2 =0;
79 //---------------------------------------------------------------------------
80 // - 0 Set1 est initialise avec la ligne de depart.
81 // Set2 contient toutes les autres.
82 //---------------------------------------------------------------------------
84 Set1.Append(IndStart);
86 for (i=1 ; i<=NbLines ; i++){
92 //---------------------------------------------------------------------------
93 // - 1 Recherche de la connexion C la plus courte entre Set1 et Set2.
94 // - 2 La ligne de Set2 realisant le minimum de distance est inseree dans
95 // Set1 et supprime dans Set2.
96 // - 3 Insertion de la connexion dans l ensemble des connexions.
97 // - 4 Si Set2 est non vide retour en 1.
98 //---------------------------------------------------------------------------
100 while (!Set2.IsEmpty()){
101 DistS1S2 = RealLast();
102 for (i = 1; i <= Set1.Length(); i++) {
103 IndiceLine1 = Set1.Value(i);
104 for (j = 1 ; j<= Set2.Length() ;j++) {
105 IndiceLine2 = Set2.Value(j);
106 if(Connexion(IndiceLine1,IndiceLine2)->Distance() < DistS1S2) {
108 DistS1S2 = Connexion(IndiceLine1,IndiceLine2)->Distance();
109 MinOnSet1 = IndiceLine1;
110 MinOnSet2 = IndiceLine2;
114 Set1.Append(Set2.Value(ISuiv));
116 Append(Connexion(MinOnSet1,MinOnSet2));
119 //----------------------------------------------------------------
120 // Construction du chemin en parcourant l ensemble des connexions.
121 //----------------------------------------------------------------
126 //============================================================================
128 //purpose : Insertion d une nouvelle connexion dans le chemin.
130 // Les connexions et les lignes constituent un arbre dont
131 // - les noeuds sont les lignes.
132 // - les connexions sont les branches.
134 //============================================================================
135 void MAT2d_MiniPath::Append(const Handle(MAT2d_Connexion)& C)
137 Handle(MAT2d_Connexion) CC;
139 if (!theConnexions.IsBound(C->IndexFirstLine())) {
140 MAT2d_SequenceOfConnexion Seq;
141 theConnexions.Bind(C->IndexFirstLine(),Seq);
142 theConnexions(C->IndexFirstLine()).Append(C);
143 theFather.Bind(C->IndexSecondLine(),C);
147 MAT2d_SequenceOfConnexion& Seq = theConnexions(C->IndexFirstLine());
148 Standard_Integer IndexAfter = 0;
149 Standard_Integer NbConnexions = Seq.Length();
151 for (Standard_Integer i = 1; i <= NbConnexions; i++) {
153 if (CC->IsAfter(C,theDirection)){
158 //----------------------------------------------------------------------
159 // Insertion de <C> avant <IAfter>.
160 // Si <IAfter> = 0 => Pas de connexions apres <C> => <C> est la
162 //----------------------------------------------------------------------
163 if (IndexAfter == 0) {
167 Seq.InsertBefore(IndexAfter,C);
169 theFather.Bind(C->IndexSecondLine(),C);
173 //============================================================================
175 //purpose : Retour de la sequence de connexions definissant le chemin.
176 //============================================================================
177 const MAT2d_SequenceOfConnexion& MAT2d_MiniPath::Path() const
182 //============================================================================
183 //function : IsConnexionsFrom
185 //============================================================================
186 Standard_Boolean MAT2d_MiniPath::IsConnexionsFrom
187 (const Standard_Integer i) const
189 return (theConnexions.IsBound(i));
192 //============================================================================
193 //function : Connexions
194 //purpose : Retour de la sequence de connexions issue de la ligne <i>.
195 //============================================================================
196 MAT2d_SequenceOfConnexion& MAT2d_MiniPath::ConnexionsFrom
197 (const Standard_Integer i)
199 return theConnexions.ChangeFind(i);
202 //============================================================================
205 //============================================================================
206 Standard_Boolean MAT2d_MiniPath::IsRoot(const Standard_Integer ILine) const
208 return (ILine == indStart);
211 //============================================================================
213 //purpose : Retour de la premiere connexion qui arrive sur la ligne i
214 //============================================================================
215 Handle(MAT2d_Connexion) MAT2d_MiniPath::Father(const Standard_Integer ILine)
217 return theFather.ChangeFind(ILine);
221 //============================================================================
222 //function : RunOnConnexions
223 //purpose : Construction de <thePath> en parcourant <theConnexions>.
224 //============================================================================
225 void MAT2d_MiniPath::RunOnConnexions()
228 Handle(MAT2d_Connexion) C;
229 const MAT2d_SequenceOfConnexion& SC = theConnexions(indStart);
233 for ( i = 1; i <= SC.Length(); i++) {
236 ExploSons(thePath,C);
237 thePath.Append(C->Reverse());
241 //============================================================================
242 //function : ExploSons
244 //============================================================================
245 void MAT2d_MiniPath::ExploSons( MAT2d_SequenceOfConnexion& CResult,
246 const Handle(MAT2d_Connexion)& CRef )
249 Standard_Integer Index = CRef->IndexSecondLine();
251 if (!theConnexions.IsBound(Index)) return;
253 const MAT2d_SequenceOfConnexion& SC = theConnexions(Index);
254 Handle(MAT2d_Connexion) CRR = CRef->Reverse();
255 Handle(MAT2d_Connexion) C;
257 for ( i = 1; i <= SC.Length(); i++) {
259 if (C->IsAfter(CRR,theDirection)) {
261 ExploSons(CResult,C);
262 CResult.Append(C->Reverse());
266 for ( i = 1; i <= SC.Length(); i++) {
268 if (!C->IsAfter(CRR,theDirection)) {
270 ExploSons(CResult,C);
271 CResult.Append(C->Reverse());
280 //============================================================================
281 //function : MinimumL1L2
282 //purpose : Calcul de la connexion realisant le minimum de distance entre les
283 // lignes d indice <IL1> et <IL2> dans <Figure>.
284 //============================================================================
285 Handle(MAT2d_Connexion) MAT2d_MiniPath::MinimumL1L2
286 (const MAT2d_SequenceOfSequenceOfGeometry& Figure,
287 const Standard_Integer IL1,
288 const Standard_Integer IL2) const
290 Extrema_POnCurv2d PointOnCurv1,PointOnCurv2;
291 Standard_Integer IC1,IC2,IMinC1 =0,IMinC2 =0,i;
292 Standard_Real DistL1L2_2,DistP1P2_2;
293 Standard_Real ParameterOnC1 =0.,ParameterOnC2 =0.;
294 TColGeom2d_SequenceOfGeometry L1,L2;
295 gp_Pnt2d Point1,Point2,P1,P2;
296 Handle(Geom2d_Curve) Item1;
297 Handle(Geom2d_Curve) Item2;
299 L1 = Figure.Value(IL1);
300 L2 = Figure.Value(IL2);
302 DistL1L2_2 = RealLast();
304 //---------------------------------------------------------------------------
305 // Calcul des extremas de distances entre les composants de L1 et de L2.
306 //---------------------------------------------------------------------------
308 for (IC1 = 1; IC1 <= L1.Length(); IC1++) {
310 Handle(Standard_Type) Type1 = L1.Value(IC1)->DynamicType();
311 if (Type1 != STANDARD_TYPE(Geom2d_CartesianPoint)) {
312 Item1 = Handle(Geom2d_Curve)::DownCast(L1.Value(IC1));
315 P1 = Handle(Geom2d_Point)::DownCast(L1.Value(IC1))->Pnt2d();
318 for (IC2 = 1; IC2 <= L2.Length(); IC2++) {
320 Handle(Standard_Type) Type2 = L2.Value(IC2)->DynamicType();
321 if (Type2 != STANDARD_TYPE(Geom2d_CartesianPoint)) {
322 Item2 = Handle(Geom2d_Curve)::DownCast(L2.Value(IC2));
325 P2 = Handle(Geom2d_Point)::DownCast(L2.Value(IC2))->Pnt2d();
328 if (Type1 == STANDARD_TYPE(Geom2d_CartesianPoint) &&
329 Type2 == STANDARD_TYPE(Geom2d_CartesianPoint) ) {
330 DistP1P2_2 = P1.SquareDistance(P2);
331 if (DistP1P2_2 <= DistL1L2_2) {
332 DistL1L2_2 = DistP1P2_2;
341 else if (Type1 == STANDARD_TYPE(Geom2d_CartesianPoint)) {
342 Geom2dAdaptor_Curve C2(Item2);
343 Extrema_ExtPC2d Extremas(P1,C2);
344 if (Extremas.IsDone()){
345 for (i = 1; i <= Extremas.NbExt(); i++) {
346 if (Extremas.SquareDistance(i) < DistL1L2_2) {
347 DistL1L2_2 = Extremas.SquareDistance(i);
350 PointOnCurv2 = Extremas.Point(i);
352 ParameterOnC2 = PointOnCurv2.Parameter();
354 Point2 = PointOnCurv2.Value();
359 else if (Type2 == STANDARD_TYPE(Geom2d_CartesianPoint)) {
360 Geom2dAdaptor_Curve C1(Item1);
361 Extrema_ExtPC2d Extremas(P2,C1);
362 if (Extremas.IsDone()){
363 for (i=1;i<=Extremas.NbExt();i++) {
364 if (Extremas.SquareDistance(i) < DistL1L2_2) {
365 DistL1L2_2 = Extremas.SquareDistance(i);
368 PointOnCurv1 = Extremas.Point(i);
370 ParameterOnC1 = PointOnCurv1.Parameter();
371 Point1 = PointOnCurv1.Value();
378 Geom2dAdaptor_Curve C1(Item1);
379 Geom2dAdaptor_Curve C2(Item2);
380 Extrema_ExtCC2d Extremas(C1,C2);
381 if (!Extremas.IsParallel() && Extremas.IsDone()){
382 for ( i=1; i <= Extremas.NbExt(); i++) {
383 if (Extremas.SquareDistance(i) < DistL1L2_2) {
384 DistL1L2_2 = Extremas.SquareDistance(i);
387 Extremas.Points(i,PointOnCurv1,PointOnCurv2);
388 ParameterOnC1 = PointOnCurv1.Parameter();
389 ParameterOnC2 = PointOnCurv2.Parameter();
390 Point1 = PointOnCurv1.Value();
391 Point2 = PointOnCurv2.Value();
398 Handle(MAT2d_Connexion) ConnexionL1L2;
399 ConnexionL1L2 = new MAT2d_Connexion(IL1,IL2,IMinC1,IMinC2,sqrt (DistL1L2_2),
400 ParameterOnC1,ParameterOnC2,
402 return ConnexionL1L2;