0024612: Wrong pcurve of the section curve
[occt.git] / src / IntWalk / IntWalk_IWalking_4.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 #include <NCollection_IncAllocator.hxx>
16
17 void IntWalk_IWalking::ComputeCloseLine(const TColStd_SequenceOfReal& Umult,
18                                         const TColStd_SequenceOfReal& Vmult,
19                                         const ThePOPIterator& Pnts1,
20                                         const ThePOLIterator& Pnts2,
21                                         TheIWFunction& Func,
22                                         Standard_Boolean& Rajout ) 
23 // *********** Processing of closed line **********************
24 //
25 // for any interior non-processed point 
26 //       calculate the step of advancement=step depending on the arrow and max step
27 //       calculate a point of approach (this point is on the tangent to the section
28 // of distance = no interior point)
29 //  conditions 
30 //            (all calculated points do not form a closed loop)  
31 //                              or                    
32 //            (all points do not form an open line going from 
33 //            one border of the domain to the other or from a point tangent
34 //            to the border or from 2 tangent points : single cases)
35 //  
36 //     frame the point of approach on borders if necessary
37 //     calculate the point
38 //     if point not found divide the step
39 //     test of stop    
40 //     calculate step depending on the arrow and the max step (stop possible)
41 //
42 // ******************************************************************** 
43 {
44
45   Standard_Integer I,N = 0;
46   Standard_Real aBornInf[2], aBornSup[2], aUVap[2];
47   math_Vector BornInf(aBornInf,1,2), BornSup(aBornSup,1,2);
48   math_Vector Uvap(aUVap,1,2);// parameters of current approach
49   Standard_Real PasC;  // step of advancement on the tangent
50   Standard_Real PasCu; // step of advancement current by U
51   Standard_Real PasCv; // step of advancement current by V
52   Standard_Real PasSav; // save first step of advancement
53   Standard_Boolean Arrive;// show if line ends
54   Standard_Boolean Cadre; // show if on border of the  domains
55   Standard_Boolean ArretAjout; // show if on the added point
56   IntSurf_PntOn2S Psol;
57   Handle(IntWalk_TheIWLine)  CurrentLine; //line under construction
58   ThePointOfPath PathPnt;
59   ThePointOfLoop LoopPnt;
60
61   Standard_Boolean Tgtbeg,Tgtend;
62
63   Standard_Integer StepSign;
64   
65   IntWalk_StatusDeflection Status,StatusPrecedent;
66   Standard_Integer NbDivision ;   // number of divisions of step 
67   // during calculation of  1 section
68
69   Standard_Integer Ipass ;
70   //index in the iterator of points on edge of point of passage  
71
72
73   BornInf(1) = Um;
74   BornSup(1) = UM;
75   BornInf(2) = Vm;
76   BornSup(2) = VM;
77   
78   math_FunctionSetRoot Rsnld(Func,tolerance);
79   Standard_Integer nbLoop = Pnts2.Length();
80
81   for (I = 1;I<=nbLoop;I++) {
82     if (wd2[I].etat > 12)
83     { // start point of closed line
84       LoopPnt = Pnts2.Value(I);
85       previousPoint.SetValue(ThePointOfLoopTool::Value3d(LoopPnt),reversed,
86            wd2[I].ustart,wd2[I].vstart);
87       previousd3d = ThePointOfLoopTool::Direction3d(LoopPnt);
88       previousd2d = ThePointOfLoopTool::Direction2d(LoopPnt);
89
90       CurrentLine = new IntWalk_TheIWLine (new NCollection_IncAllocator());
91       CurrentLine->AddPoint(previousPoint);
92       CurrentLine->SetTangentVector(previousd3d,1);
93       Tgtbeg = Standard_False;
94       Tgtend = Standard_False;
95       Uvap(1) = wd2[I].ustart;
96       Uvap(2) = wd2[I].vstart;
97
98       StepSign = 1;
99
100       // first step of advancement
101
102       Standard_Real d2dx = Abs(previousd2d.X()); 
103       Standard_Real d2dy = Abs(previousd2d.Y()); 
104       if (d2dx < tolerance(1)) {
105         PasC = pas * (VM-Vm)/d2dy;
106       }
107       else if (d2dy < tolerance(2)) {
108         PasC = pas * (UM-Um)/d2dx;
109       }
110       else {
111         PasC = pas * Min((UM-Um)/d2dx,(VM-Vm)/d2dy);
112       }
113
114       PasSav = PasC;
115
116       Arrive = Standard_False;
117       ArretAjout = Standard_False;
118       NbDivision = 0;
119       StatusPrecedent = IntWalk_OK;
120       Standard_Integer aNbIter = 10;
121       while (!Arrive) {  // as no test of stop is passed
122         Cadre=Cadrage(BornInf,BornSup,Uvap,PasC, StepSign);  // border?
123 #ifdef CHRONO
124         Chronrsnld.Start();
125 #endif
126
127         Rsnld.Perform(Func,Uvap,BornInf,BornSup);
128
129 #ifdef CHRONO
130         Chronrsnld.Stop();
131 #endif
132
133         if (Cadre) { // update of limits.
134           BornInf(1) = Um;BornSup(1) = UM;BornInf(2) = Vm;BornSup(2) = VM;
135         }
136         if (Rsnld.IsDone()) {
137           if (Abs(Func.Root()) > Func.Tolerance()) { // no solution for the tolerance
138             PasC = PasC/2.;
139             PasCu = Abs(PasC*previousd2d.X());
140             PasCv = Abs(PasC*previousd2d.Y());
141
142             if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
143               if (CurrentLine->NbPoints()==1) break;
144               Arrive = Standard_True;
145               CurrentLine->AddStatusFirstLast(Standard_False,
146                 Standard_False,Standard_False);
147               Rajout = Standard_True;
148               seqAjout.Append(lines.Length()+1);
149               Tgtend = Standard_True;
150             }
151           }
152           else { // there is a solution
153             Rsnld.Root(Uvap);
154             Arrive = TestArretPassage(Umult,Vmult,Uvap,I,Ipass);
155             if (Arrive) {//reset proper parameter to test the arrow.
156               Psol = CurrentLine->Value(1);
157               if (!reversed) {
158                 Psol.ParametersOnS2(Uvap(1),Uvap(2));
159               }
160               else {
161                 Psol.ParametersOnS1(Uvap(1),Uvap(2));
162               }
163               Cadre=Standard_False; 
164               //in case if there is a frame and arrival at the same time
165             }
166             else { // modif jag 940615
167               if (Rajout) {    // test on added points
168                 ArretAjout =TestArretAjout(Func,Uvap,N,Psol);
169                 if (ArretAjout) {
170                   if (N >0) {
171                     Tgtend = lines.Value(N)->IsTangentAtEnd();
172                     N = -N;
173                   }
174                   else {
175                     Tgtend = lines.Value(-N)->IsTangentAtBegining();
176                   }
177                   Arrive = (wd2[I].etat == 12);
178                 }
179               }
180
181               if (!ArretAjout&& Cadre) {  // test on already marked points
182                 if (CurrentLine->NbPoints() == 1)  break; // cancel the line
183                 TestArretCadre(Umult,Vmult,CurrentLine,Func,Uvap,N);
184                 //              if (N==0) {
185                 if (N <= 0) { // jag 941017
186                   MakeWalkingPoint(2,Uvap(1),Uvap(2),Func,Psol);
187                   Tgtend = Func.IsTangent(); // jag 940616
188                   N = -N;
189                 }
190                 Arrive = (wd2[I].etat == 12); // the line is open
191               }
192             }
193             Status = TestDeflection(Func, Arrive,Uvap,StatusPrecedent,
194                                                 NbDivision,PasC,StepSign);
195
196             StatusPrecedent = Status; 
197             if (Status == IntWalk_PasTropGrand) {// division of the step
198               Arrive = Standard_False;
199               ArretAjout = Standard_False;
200               Tgtend = Standard_False; // jag 940616
201               if (!reversed) {
202                 previousPoint.ParametersOnS2(Uvap(1),Uvap(2));
203               }
204               else {
205                 previousPoint.ParametersOnS1(Uvap(1),Uvap(2));
206               }
207             }
208             else if (ArretAjout || Cadre) {
209
210               if (Arrive) { // line s is open
211                 CurrentLine->AddStatusLast(Standard_False);
212                 if (Status != IntWalk_ArretSurPointPrecedent) {
213                   CurrentLine->AddPoint(Psol);                      
214                 }
215                 if (Cadre && N==0) {
216                   Rajout = Standard_True;
217                   seqAjout.Append(lines.Length()+1);
218                 }
219
220               }
221               else { // open
222                 wd2[I].etat = 12; // declare it open
223                 Tgtbeg = Tgtend;
224                 Tgtend = Standard_False;
225                 ArretAjout = Standard_False;
226                 StepSign = -1;
227                 StatusPrecedent = IntWalk_OK;
228                 PasC = PasSav;
229                 if (Status == IntWalk_ArretSurPointPrecedent) {
230                   OpenLine(0,Psol,Pnts1,Func,CurrentLine);
231                 }
232                 else {
233                   OpenLine(-lines.Length()-1,Psol,Pnts1,Func,CurrentLine);
234                 }
235                 if (Cadre && N==0) {
236                   Rajout = Standard_True;
237                   seqAjout.Append(-lines.Length()-1);
238                 }
239               }
240             }
241             else if ( Status == IntWalk_ArretSurPointPrecedent) {
242               if (CurrentLine->NbPoints() == 1) { //cancel the line
243                 Arrive = Standard_False;
244                 break;
245               }
246               if (wd2[I].etat >12) { //the line should become open
247                 wd2[I].etat = 12; //declare it open
248                 ArretAjout = Standard_False;
249                 OpenLine(0,Psol,Pnts1,Func,CurrentLine);
250                 StepSign = -1;
251                 StatusPrecedent = IntWalk_OK;
252                 Arrive = Standard_False;
253                 PasC = PasSav;
254                 Rajout = Standard_True;
255                 seqAjout.Append(-lines.Length()-1);
256               }
257               else { // line s is open                 
258                 Arrive =Standard_True;
259                 CurrentLine->AddStatusLast(Standard_False);
260                 Rajout = Standard_True;
261                 seqAjout.Append(lines.Length()+1);
262               } 
263             }
264             else if (Arrive)  {
265               if (wd2[I].etat > 12) {  //line closed good case
266                 CurrentLine->AddStatusFirstLast(Standard_True,
267                   Standard_False,Standard_False);
268                 CurrentLine->AddPoint(CurrentLine->Value(1));              
269               }
270               else if (N >0) { //point of stop given at input 
271                 PathPnt = Pnts1.Value(N);
272                 CurrentLine->AddStatusLast(Standard_True,N,PathPnt);
273                 AddPointInCurrentLine(N,PathPnt,CurrentLine);
274               }
275             }
276             else if (Status == IntWalk_ArretSurPoint) {
277               if (wd2[I].etat >12) { //line should become open
278                 wd2[I].etat = 12; //declare it open
279                 Tgtbeg = Standard_True;
280                 Tgtend = Standard_False;
281                 N= -lines.Length()-1;
282                 Psol.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
283                 OpenLine(N,Psol,Pnts1,Func,CurrentLine);
284                 StepSign = -1;
285                 Rajout = Standard_True;
286                 seqAjout.Append(N);
287                 StatusPrecedent = IntWalk_OK;
288                 Arrive = Standard_False;
289                 PasC = PasSav;  
290               }
291               else { 
292                 Arrive = Standard_True;                   
293                 if (Ipass!=0) { //point of passage, point of stop
294                   PathPnt = Pnts1.Value(Ipass);
295                   CurrentLine->AddStatusLast(Standard_True,Ipass,PathPnt);
296                   AddPointInCurrentLine(Ipass,PathPnt,CurrentLine);
297                 }
298                 else {
299                   CurrentLine->AddStatusLast(Standard_False);
300                   IntSurf_PntOn2S newP;
301                   newP.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
302                   CurrentLine->AddPoint(newP);
303                   Rajout = Standard_True;
304                   seqAjout.Append(lines.Length()+1);
305                 }
306               }
307             }
308             else if (Status == IntWalk_OK) { 
309               if (Ipass!=0) CurrentLine->AddIndexPassing(Ipass);
310               previousPoint.SetValue(Func.Point(),reversed,Uvap(1),Uvap(2));
311               previousd3d = Func.Direction3d();
312               previousd2d = Func.Direction2d();
313               CurrentLine->AddPoint(previousPoint);
314             }
315             else if (Status == IntWalk_PointConfondu)
316             {
317               aNbIter --;
318             }
319           }
320         }
321         else { //no numerical solution NotDone
322           PasC = PasC/2.;
323           PasCu = Abs(PasC*previousd2d.X());
324           PasCv = Abs(PasC*previousd2d.Y());
325
326           if (PasCu <= tolerance(1) && PasCv <= tolerance(2)) {
327             if (CurrentLine->NbPoints() == 1)  break; // cancel the line
328             Arrive = Standard_True;
329             CurrentLine->AddStatusFirstLast(Standard_False,Standard_False,
330               Standard_False);
331             Tgtend = Standard_True;
332             Rajout = Standard_True;
333             seqAjout.Append(lines.Length()+1);
334           }  
335         }
336
337         if(aNbIter < 0)
338           break;
339       }// end of started line 
340       if (Arrive) {
341         CurrentLine->SetTangencyAtBegining(Tgtbeg);
342         CurrentLine->SetTangencyAtEnd(Tgtend);
343
344         lines.Append(CurrentLine);
345         wd2[I].etat=-wd2[I].etat; //mark point as processed
346       }
347     } //end of processing of start point
348   } //end of all start points
349 }
350
351
352
353
354
355