0027930: XMT file conversion loops infinitely
[occt.git] / src / IntWalk / IntWalk_IWalking_1.gxx
1 // Copyright (c) 1995-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #ifdef CHRONO
16 #include <OSD_Chronometer.hxx>
17 OSD_Chronometer Chronrsnld;
18
19 #endif
20
21 #include <NCollection_IncAllocator.hxx>
22 #include <Precision.hxx>
23
24 //==================================================================================
25 // function : IsTangentExtCheck
26 // purpose  : Additional check if the point (theU, theV) in parametric surface
27 //            is a tangent point.
28 //            If that is TRUE then we can go along any (!) direction in order to
29 //            obtain next intersection point. At present, this case is difficult
30 //            for processing. Therefore, we will return an empty intersection line
31 //            in this case.
32 //==================================================================================
33 static Standard_Boolean IsTangentExtCheck(TheIWFunction& theFunc,
34                                           const Standard_Real theU,
35                                           const Standard_Real theV,
36                                           const Standard_Real theStepU,
37                                           const Standard_Real theStepV,
38                                           const Standard_Real theUinf,
39                                           const Standard_Real theUsup,
40                                           const Standard_Real theVinf,
41                                           const Standard_Real theVsup)
42 {
43   const Standard_Real aTol = theFunc.Tolerance();
44   const Standard_Integer aNbItems = 4;
45   const Standard_Real aParU[aNbItems] = { Min(theU + theStepU, theUsup),
46                                           Max(theU - theStepU, theUinf),
47                                           theU, theU};
48   const Standard_Real aParV[aNbItems] = { theV, theV,
49                                           Min(theV + theStepV, theVsup),
50                                           Max(theV - theStepV, theVinf)};
51
52   math_Vector aX(1, 2), aVal(1, 1);
53
54   for(Standard_Integer i = 0; i < aNbItems; i++)
55   {
56     aX.Value(1) = aParU[i];
57     aX.Value(2) = aParV[i];
58
59     if(!theFunc.Value(aX, aVal))
60       continue;
61
62     if(aVal(1) > aTol)
63       return Standard_False;
64   }
65
66   return Standard_True;
67 }
68
69
70
71 IntWalk_IWalking::IntWalk_IWalking (const Standard_Real Epsilon,
72                                     const Standard_Real Deflection,
73                                     const Standard_Real Increment,
74                                     const Standard_Boolean theToFillHoles) :
75       done(Standard_False),
76       fleche(Deflection),
77       pas(Increment),
78       tolerance(1,2),
79       epsilon(Epsilon*Epsilon),
80       wd1 (IntWalk_VectorOfWalkingData::allocator_type (new NCollection_IncAllocator)),
81       wd2 (wd1.get_allocator()),
82       nbMultiplicities (wd1.get_allocator()),
83       ToFillHoles(theToFillHoles)
84 {
85 }
86
87     
88 //=======================================================================
89 //function : Reset
90 //purpose  : Clears NCollection_Vector-based containers and adds
91 //           dummy data to maintain start index of 1 and consistent with
92 //           previous TCollection_Sequence-based implementation and other
93 //           used TCollection-based containers
94 //=======================================================================
95
96 void IntWalk_IWalking::Clear()
97 {
98   wd1.clear();
99   wd2.clear();
100   IntWalk_WalkingData aDummy;
101   aDummy.etat = -10;
102   aDummy.ustart = aDummy.vstart = 0.;
103   wd1.push_back (aDummy);
104   wd2.push_back (aDummy);
105   nbMultiplicities.clear();
106   nbMultiplicities.push_back (-1);
107   
108   done = Standard_False;
109   seqAjout.Clear();
110   lines.Clear();
111 }
112
113 // ***************************************************************************
114      //  etat1=12 not tangent, not passes
115      //  etat1=11 tangent, not passes
116      //  etat1=2  not tangent, passes
117      //  etat1=1  tangent, passes
118      //  after a point is processed its state becomes negative.
119 // ***************************************************************************
120      //  etat2=13  interior start point on closed line
121      //  etat2=12  interior start point on open line 
122      //            (line initially closed -> la line s is open)       
123      //  after a point is processed (or if it is passed over during
124      //  routing) its state becomes negative.
125 // ****************************************************************************
126
127 //
128 // Perform with interior points
129 //
130 void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
131                                const ThePOLIterator& Pnts2,
132                                TheIWFunction& Func,
133                                const ThePSurface& Caro,
134                                const Standard_Boolean Reversed)
135
136 {
137   Standard_Integer I;
138   Standard_Boolean Rajout = Standard_False;
139   Standard_Integer nbPnts1 = Pnts1.Length();
140   Standard_Integer nbPnts2 = Pnts2.Length();
141   Standard_Real U,V;
142
143   Clear();
144   reversed = Reversed;
145
146   Um = ThePSurfaceTool::FirstUParameter(Caro);
147   Vm = ThePSurfaceTool::FirstVParameter(Caro);
148   UM = ThePSurfaceTool::LastUParameter(Caro);
149   VM = ThePSurfaceTool::LastVParameter(Caro);
150
151   if (UM < Um) {
152     Standard_Real utemp = UM;
153     UM = Um;
154     Um = utemp;
155   }
156   if (VM < Vm) {
157     Standard_Real vtemp = VM;
158     VM = Vm;
159     Vm = vtemp;
160   }
161
162   const Standard_Real aStepU = pas*(UM-Um), aStepV = pas*(VM-Vm);
163
164   // Loading of etat1 and etat2  as well as  ustart and vstart.
165
166   TColStd_SequenceOfReal Umult;
167   TColStd_SequenceOfReal Vmult;
168
169   Standard_Integer decal=0;
170   wd1.reserve (nbPnts1+decal);
171   nbMultiplicities.reserve (nbPnts1+decal);
172   for (I=1;I <= nbPnts1+decal; I++) {
173     const ThePointOfPath& PathPnt = Pnts1.Value(I-decal);
174     IntWalk_WalkingData aWD1;
175     aWD1.etat = 1;
176     if (!ThePointOfPathTool::IsPassingPnt(PathPnt)) 
177       aWD1.etat = 11;
178     if (!ThePointOfPathTool::IsTangent(PathPnt))   
179       ++aWD1.etat;
180
181     if(aWD1.etat==2) {   
182       aWD1.etat=11;
183     }      
184
185     ThePointOfPathTool::Value2d(PathPnt, aWD1.ustart, aWD1.vstart);
186     mySRangeU.Add(aWD1.ustart);
187     mySRangeV.Add(aWD1.vstart);
188
189     wd1.push_back (aWD1);
190     Standard_Integer aNbMult = ThePointOfPathTool::Multiplicity(PathPnt);
191     nbMultiplicities.push_back(aNbMult);
192
193     for (Standard_Integer J = 1; J <= aNbMult; J++) {
194       ThePointOfPathTool::Parameters(PathPnt, J, U, V);
195       Umult.Append(U);
196       Vmult.Append(V);
197     }
198   }
199
200   wd2.reserve (nbPnts2);
201   for (I = 1; I <= nbPnts2; I++) {
202     IntWalk_WalkingData aWD2;
203     aWD2.etat = 1;
204     const IntSurf_InteriorPoint& anIP = Pnts2.Value(I);
205     ThePointOfLoopTool::Value2d(anIP, aWD2.ustart, aWD2.vstart);
206     mySRangeU.Add(aWD2.ustart);
207     mySRangeV.Add(aWD2.vstart);
208
209     if (!IsTangentExtCheck(Func, aWD2.ustart, aWD2.vstart, aStepU, aStepV, Um, UM, Vm, VM))
210       aWD2.etat = 13;
211     
212     wd2.push_back (aWD2);
213   }
214
215   tolerance(1) = ThePSurfaceTool::UResolution(Caro,Precision::Confusion());
216   tolerance(2) = ThePSurfaceTool::VResolution(Caro,Precision::Confusion());
217
218   Func.Set(Caro);
219
220   if (mySRangeU.Delta() > Max(tolerance(1), Precision::PConfusion()))
221   {
222     mySRangeU.Enlarge(mySRangeU.Delta());
223     mySRangeU.Common(Bnd_Range(Um, UM));
224   }
225   else
226   {
227     mySRangeU = Bnd_Range(Um, UM);
228   }
229
230   if (mySRangeV.Delta() > Max(tolerance(2), Precision::PConfusion()))
231   {
232     mySRangeV.Enlarge(mySRangeV.Delta());
233     mySRangeV.Common(Bnd_Range(Vm, VM));
234   }
235   else
236   {
237     mySRangeV = Bnd_Range(Vm, VM);
238   }
239
240   // calculation of all open lines   
241   if (nbPnts1 != 0)
242     ComputeOpenLine(Umult,Vmult,Pnts1,Func,Rajout); 
243
244   // calculation of all closed lines 
245   if (nbPnts2 != 0)
246     ComputeCloseLine(Umult,Vmult,Pnts1,Pnts2,Func,Rajout);
247
248   if (ToFillHoles)
249   {
250     Standard_Integer MaxNbIter = 10, nb_iter = 0;
251     while (seqAlone.Length() > 1 && nb_iter < MaxNbIter)
252     {
253       nb_iter++;
254       IntSurf_SequenceOfInteriorPoint PntsInHoles;
255       TColStd_SequenceOfInteger CopySeqAlone = seqAlone;
256       FillPntsInHoles(Func, CopySeqAlone, PntsInHoles);
257       wd2.clear();
258       IntWalk_WalkingData aDummy;
259       aDummy.etat = -10;
260       aDummy.ustart = aDummy.vstart = 0.;
261       wd2.push_back (aDummy);
262       Standard_Integer nbHoles = PntsInHoles.Length();
263       wd2.reserve(nbHoles);
264       for (I = 1; I <= nbHoles; I++)
265       {
266         IntWalk_WalkingData aWD2;
267         aWD2.etat = 13;
268         const IntSurf_InteriorPoint& anIP = PntsInHoles.Value(I);
269         ThePointOfLoopTool::Value2d(anIP, aWD2.ustart, aWD2.vstart);
270         wd2.push_back (aWD2);
271       }
272       ComputeCloseLine(Umult,Vmult,Pnts1,PntsInHoles,Func,Rajout);
273     }
274   }
275   
276   for (I = 1; I <= nbPnts1; I++) { 
277     if (wd1[I].etat >0) seqSingle.Append(Pnts1(I));
278   }
279   done = Standard_True;
280 }
281
282
283
284 //
285 // Perform without interior point
286 //
287
288 void IntWalk_IWalking::Perform(const ThePOPIterator& Pnts1,
289                                TheIWFunction& Func,
290                                const ThePSurface& Caro,
291                                const Standard_Boolean Reversed)
292
293 {
294   Standard_Integer I;
295   Standard_Boolean Rajout = Standard_False;
296   Standard_Integer nbPnts1 = Pnts1.Length();
297   Standard_Real U,V;
298
299   reversed = Reversed;
300
301
302   // Loading of etat1 as well as ustart1 and vstart1.
303
304   TColStd_SequenceOfReal Umult;
305   TColStd_SequenceOfReal Vmult;
306
307   wd1.reserve (nbPnts1);
308   for (I=1;I <= nbPnts1; I++) {
309     const ThePointOfPath& PathPnt = Pnts1.Value(I);
310     IntWalk_WalkingData aWD1;
311     aWD1.etat = 1;
312     if (!ThePointOfPathTool::IsPassingPnt(PathPnt)) aWD1.etat = 11; 
313     if (!ThePointOfPathTool::IsTangent(PathPnt))   ++aWD1.etat;
314     ThePointOfPathTool::Value2d(PathPnt, aWD1.ustart, aWD1.vstart);
315     wd1.push_back (aWD1);
316     Standard_Integer aNbMult = ThePointOfPathTool::Multiplicity(PathPnt);
317     nbMultiplicities.push_back(aNbMult);
318
319     for (Standard_Integer J = 1; J <= aNbMult; J++) {
320       ThePointOfPathTool::Parameters(PathPnt, J, U, V);
321       Umult.Append(U);
322       Vmult.Append(V);
323     }
324   }
325
326   tolerance(1) = ThePSurfaceTool::UResolution(Caro,Precision::Confusion());
327   tolerance(2) = ThePSurfaceTool::VResolution(Caro,Precision::Confusion());
328
329   Um = ThePSurfaceTool::FirstUParameter(Caro);
330   Vm = ThePSurfaceTool::FirstVParameter(Caro);
331   UM = ThePSurfaceTool::LastUParameter(Caro);
332   VM = ThePSurfaceTool::LastVParameter(Caro);
333
334   if (UM < Um) {
335     Standard_Real utemp = UM;
336     UM = Um;
337     Um = utemp;
338   }
339   if (VM < Vm) {
340     Standard_Real vtemp = VM;
341     VM = Vm;
342     Vm = vtemp;
343   }
344
345   Func.Set(Caro);
346
347   // calcul de toutes les lignes ouvertes   
348   if (nbPnts1 != 0) ComputeOpenLine(Umult,Vmult,Pnts1,Func,Rajout); 
349
350   for (I = 1; I <= nbPnts1; I++) { 
351     if (wd1[I].etat >0) seqSingle.Append(Pnts1(I));
352   }
353   done = Standard_True;
354 }
355
356
357