Integration of OCCT 6.5.0 from SVN
[occt.git] / src / BRepExtrema / BRepExtrema_DistShapeShape.cxx
CommitLineData
7fd59977 1// File: BRepExtrema_DistShapeShape.cxx
2// Created: Mon Apr 22 17:03:37 1996
3// Modified : Mps(10-04-97) portage WNT
4// Author: Maria PUMBORIOS
5// Author: Herve LOUESSARD
6// <mps@sgi64>
7
8#include <BRepExtrema_DistShapeShape.ixx>
9#include <Standard_OStream.hxx>
10#include <TopTools_IndexedMapOfShape.hxx>
11#include <BRepBndLib.hxx>
12#include <Bnd_Box.hxx>
13#include <TopExp.hxx>
14#include <TCollection.hxx>
15#include <Standard_Real.hxx>
16#include <BRepExtrema_DistanceSS.hxx>
17#include <TopoDS.hxx>
18#include <TopAbs.hxx>
19#include <TopoDS_Vertex.hxx>
20#include <TopoDS_Edge.hxx>
21#include <TopoDS_Face.hxx>
22#include <TopAbs_ShapeEnum.hxx>
23#include <Precision.hxx>
24#include <BRepExtrema_SeqOfSolution.hxx>
25#include <BRepExtrema_SolutionElem.hxx>
26#include <Bnd_SeqOfBox.hxx>
27#include <BRepExtrema_UnCompatibleShape.hxx>
28#include <BRep_Tool.hxx>
29#include <BRepClass3d_SolidClassifier.hxx>
30
31static void Decomposition(const TopoDS_Shape& S,
32 TopTools_IndexedMapOfShape& MapV,
33 TopTools_IndexedMapOfShape& MapE,
34 TopTools_IndexedMapOfShape& MapF)
35{
36 MapV.Clear();
37 MapE.Clear();
38 MapF.Clear();
39 TopExp::MapShapes(S,TopAbs_VERTEX,MapV);
40 TopExp::MapShapes(S,TopAbs_EDGE,MapE);
41 TopExp::MapShapes(S,TopAbs_FACE,MapF);
42}
43
44static void BoxCalculation(const TopTools_IndexedMapOfShape& Map,
45 Bnd_SeqOfBox& SBox)
46{
47 Standard_Integer i = 0;
48 for(i = 1; i <= Map.Extent(); i++) {
49 Bnd_Box box;
50 BRepBndLib::Add( Map(i), box);
51 SBox.Append(box);
52 }
53}
54
55static Standard_Real DistanceInitiale(const TopoDS_Vertex V1,
56 const TopoDS_Vertex V2)
57{
58 gp_Pnt P1,P2;
59 P1= BRep_Tool::Pnt(V1);
60 P2= BRep_Tool::Pnt(V2);
61 return(P1.Distance(P2));
62}
63
64//=======================================================================
65//function : DistanceMapMap
66//purpose :
67//=======================================================================
68
69void BRepExtrema_DistShapeShape::DistanceMapMap(const TopTools_IndexedMapOfShape& Map1,
70 const TopTools_IndexedMapOfShape& Map2,
71 const Bnd_SeqOfBox& LBox1,
72 const Bnd_SeqOfBox& LBox2)
73{
74 Standard_Integer i = 0, j = 0;
75 Bnd_Box box1, box2;
76 TopoDS_Shape S1, S2;
77 BRepExtrema_SeqOfSolution seq1, seq2;
78
79 Standard_Integer n1 = Map1.Extent();
80 Standard_Integer n2 = Map2.Extent();
81 for(i = 1; i <= n1; i++) {
82 box1= LBox1.Value(i);
83 S1= TopoDS_Shape (Map1(i));
84 for(j = 1; j <= n2; j++) {
85 box2= LBox2.Value(j);
86 S2 = TopoDS_Shape (Map2(j));
87 BRepExtrema_DistanceSS dist(S1,S2,box1,box2,myDistRef,myEps);
88 if(dist.IsDone())
89 if(dist.DistValue() < (myDistRef-myEps)) {
90 ListeDeSolutionShape1.Clear();
91 ListeDeSolutionShape2.Clear();
92 seq1= dist.Seq1Value();
93 seq2= dist.Seq2Value();
94 ListeDeSolutionShape1.Append(seq1);
95 ListeDeSolutionShape2.Append(seq2);
96 myDistRef=dist.DistValue();
97 }
98 else if(fabs (dist.DistValue()-myDistRef)< myEps ) {
99 seq1= dist.Seq1Value();
100 seq2= dist.Seq2Value();
101 ListeDeSolutionShape1.Append(seq1);
102 ListeDeSolutionShape2.Append(seq2);
103 // Modified by Sergey KHROMOV - Tue Mar 6 12:15:39 2001 Begin
104 if (myDistRef > dist.DistValue())
105 myDistRef=dist.DistValue();
106 // Modified by Sergey KHROMOV - Tue Mar 6 12:15:37 2001 End
107 }
108 }
109 }
110}
111
112//=======================================================================
113//function : BRepExtrema_DistShapeShape
114//purpose :
115//=======================================================================
116
117BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape()
118{
119 myEps = Precision::Confusion();
120}
121
122//=======================================================================
123//function : BRepExtrema_DistShapeShape
124//purpose :
125//=======================================================================
126BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape(const TopoDS_Shape& Shape1,
127 const TopoDS_Shape& Shape2)
128{
129 myEps = Precision::Confusion();
130 LoadS1(Shape1);
131 LoadS2(Shape2);
132 Perform();
133}
134
135//=======================================================================
136//function : BRepExtrema_DistShapeShape
137//purpose :
138//=======================================================================
139
140BRepExtrema_DistShapeShape::BRepExtrema_DistShapeShape(const TopoDS_Shape& Shape1,
141 const TopoDS_Shape& Shape2,
142 const Standard_Real theDeflection)
143{
144 myEps = theDeflection;
145 LoadS1(Shape1);
146 LoadS2(Shape2);
147 Perform();
148}
149
150//=======================================================================
151//function : SetDeflection
152//purpose :
153//=======================================================================
154
155void BRepExtrema_DistShapeShape::SetDeflection(const Standard_Real theDeflection)
156{
157 myEps = theDeflection;
158}
159
160//=======================================================================
161//function : LoadS1
162//purpose :
163//=======================================================================
164
165void BRepExtrema_DistShapeShape::LoadS1(const TopoDS_Shape& Shape1)
166{
167 myShape1 = Shape1;
168 Decomposition(Shape1, myMapV1, myMapE1, myMapF1);
169}
170
171//=======================================================================
172//function : LoadS2
173//purpose :
174//=======================================================================
175
176void BRepExtrema_DistShapeShape::LoadS2(const TopoDS_Shape& Shape2)
177{
178 myShape2 = Shape2;
179 Decomposition(Shape2, myMapV2, myMapE2, myMapF2);
180}
181
182//=======================================================================
183//function : Perform
184//purpose :
185//=======================================================================
186
187Standard_Boolean BRepExtrema_DistShapeShape::Perform()
188{
189 myIsDone=Standard_False;
190 myInnerSol=Standard_False;
191 ListeDeSolutionShape1.Clear();
192 ListeDeSolutionShape2.Clear();
193
194 if( myShape1.IsNull() || myShape2.IsNull() )
195 return Standard_False;
196
197 Bnd_SeqOfBox BV1, BV2, BE1, BE2, BF1, BF2;
198 Standard_Real tol = 0.001;
199 gp_Pnt P;
200 Standard_Integer nbv1,nbv2;
201
202 // traitement des solides
203 TopAbs_ShapeEnum Type1 = myShape1.ShapeType();
204 TopAbs_ShapeEnum Type2 = myShape2.ShapeType();
205 if((Type1==TopAbs_SOLID) || (Type1 == TopAbs_COMPSOLID)) {
206 BRepClass3d_SolidClassifier Classi(myShape1);
207 nbv2=myMapV2.Extent();
208 nbv1=0;
209 do {
210 nbv1++;
211 TopoDS_Vertex V2 = TopoDS::Vertex(myMapV2(nbv1));
212 P=BRep_Tool::Pnt(V2);
213 Classi.Perform(P,tol);
214 if(Classi.State()==TopAbs_IN) {
215 myInnerSol = Standard_True;
216 myNbSolution = 1;
217 myDistRef = 0;
218 myIsDone = Standard_True;
219 BRepExtrema_SolutionElem Sol(0,P,BRepExtrema_IsVertex,V2);
220 ListeDeSolutionShape1.Append(Sol);
221 ListeDeSolutionShape2.Append(Sol);
222 }
223 } while ( (nbv1<nbv2) && (! myInnerSol));
224 }
225
226 if(((Type2==TopAbs_SOLID)||(Type2==TopAbs_COMPSOLID))&&(!myInnerSol)) {
227 BRepClass3d_SolidClassifier Classi(myShape2);
228 nbv1= myMapV1.Extent();
229 nbv2=0;
230 do {
231 nbv2++;
232 TopoDS_Vertex V1=TopoDS::Vertex(myMapV1(nbv2));
233 P=BRep_Tool::Pnt(V1);
234 Classi.Perform(P,tol);
235 if (Classi.State()==TopAbs_IN) {
236 myInnerSol = Standard_True;
237 myNbSolution = 1;
238 myDistRef = 0;
239 myIsDone = Standard_True;
240 BRepExtrema_SolutionElem Sol (0,P,BRepExtrema_IsVertex,V1);
241 ListeDeSolutionShape1.Append(Sol);
242 ListeDeSolutionShape2.Append(Sol);
243 }
244 } while ((nbv2<nbv1) && (! myInnerSol));
245 }
246
247 if (!myInnerSol) {
248 BoxCalculation( myMapV1,BV1);
249 BoxCalculation( myMapE1,BE1);
250 BoxCalculation( myMapF1,BF1);
251 BoxCalculation( myMapV2,BV2);
252 BoxCalculation( myMapE2,BE2);
253 BoxCalculation( myMapF2,BF2);
254
255 if (myMapV1.Extent()!=0 && myMapV2.Extent()!=0) {
256 TopoDS_Vertex V1 = TopoDS::Vertex(myMapV1(1));
257 TopoDS_Vertex V2 = TopoDS::Vertex(myMapV2(1));
258 myDistRef = DistanceInitiale(V1, V2);
259 }
260 else
261 myDistRef= 1.e30;
262
263 DistanceMapMap( myMapV1, myMapV2, BV1, BV2);
264 DistanceMapMap( myMapV1, myMapE2, BV1, BE2);
265 DistanceMapMap( myMapE1, myMapV2, BE1, BV2);
266 DistanceMapMap( myMapV1, myMapF2, BV1, BF2);
267 DistanceMapMap( myMapF1, myMapV2, BF1, BV2);
268 DistanceMapMap( myMapE1, myMapE2, BE1, BE2);
269 DistanceMapMap( myMapE1, myMapF2, BE1, BF2);
270 DistanceMapMap( myMapF1, myMapE2, BF1, BE2);
271
272 if( (fabs(myDistRef)) > myEps )
273 DistanceMapMap(myMapF1,myMapF2,BF1,BF2);
274
275 // Modified by Sergey KHROMOV - Tue Mar 6 11:55:03 2001 Begin
276 Standard_Integer i = 0;
277 for(i = 1; i <= ListeDeSolutionShape1.Length(); i++)
278 if (ListeDeSolutionShape1.Value(i).Dist() > myDistRef + myEps) {
279 ListeDeSolutionShape1.Remove(i);
280 ListeDeSolutionShape2.Remove(i);
281 }
282 // Modified by Sergey KHROMOV - Tue Mar 6 11:55:04 2001 End
283 myNbSolution = ListeDeSolutionShape1.Length();
284 if( myNbSolution > 0 )
285 myIsDone = Standard_True;
286 else
287 myIsDone = Standard_False;
288 }
289 return myIsDone;
290}
291
292//=======================================================================
293//function :
294//purpose :
295//=======================================================================
296
297Standard_Boolean BRepExtrema_DistShapeShape:: InnerSolution () const
298{
299 return (myInnerSol);
300}
301
302//=======================================================================
303//function : IsDone
304//purpose :
305//=======================================================================
306
307Standard_Boolean BRepExtrema_DistShapeShape::IsDone() const
308{
309 return (myIsDone);
310}
311
312//=======================================================================
313//function : NbSolution
314//purpose :
315//=======================================================================
316
317Standard_Integer BRepExtrema_DistShapeShape::NbSolution() const
318{
319 if (myIsDone == Standard_False) {
320 StdFail_NotDone::Raise
321 ("BRepExtrema_DistShapeShape::NbSolution: There's no solution ");
322 }
323 return (myNbSolution);
324}
325
326//=======================================================================
327//function : Value
328//purpose :
329//=======================================================================
330
331Standard_Real BRepExtrema_DistShapeShape::Value() const
332{
333 if (myIsDone == Standard_False) {
334 StdFail_NotDone::Raise
335 ("BRepExtrema_DistShapeShape::Value: There's no solution ");
336 }
337 return (myDistRef);
338}
339
340//=======================================================================
341//function : PointOnShape1
342//purpose :
343//=======================================================================
344
345gp_Pnt BRepExtrema_DistShapeShape::PointOnShape1(const Standard_Integer N) const
346{
347 if (myIsDone == Standard_False)
348 { StdFail_NotDone::Raise
349 ("BRepExtrema_DistShapeShape::PointOnShape1: There's no solution ");
350 }
351 if ((N<1)||(N>myNbSolution))
352 { Standard_OutOfRange::Raise
353 ("BRepExtrema_DistShapeShape::PointOnShape1: Nth solution doesn't exist ");
354 }
355 return ((ListeDeSolutionShape1.Value(N)).Point());
356}
357
358//=======================================================================
359//function : PointOnShape2
360//purpose :
361//=======================================================================
362
363gp_Pnt BRepExtrema_DistShapeShape::PointOnShape2(const Standard_Integer N) const
364{
365 if (myIsDone == Standard_False)
366 { StdFail_NotDone::Raise
367 ("BRepExtrema_DistShapeShape::PointOnShape2: There's no solution ");
368 }
369 if ((N<1)||(N>myNbSolution))
370 { Standard_OutOfRange::Raise
371 ("BRepExtrema_DistShapeShape::PointOnShape2: Nth solution doesn't exist ");
372 }
373 return ((ListeDeSolutionShape2.Value(N)).Point());
374}
375
376//=======================================================================
377//function : SupportTypeShape1
378//purpose :
379//=======================================================================
380
381BRepExtrema_SupportType BRepExtrema_DistShapeShape::SupportTypeShape1(const Standard_Integer N) const
382{
383 if (myIsDone == Standard_False)
384 { StdFail_NotDone::Raise
385 ("BRepExtrema_DistShapeShape::SupportTypeShape1: There's no solution ");
386 }
387 if ((N<1)||(N>myNbSolution))
388 { Standard_OutOfRange::Raise
389 ("BRepExtrema_DistShapeShape::SupportTypeShape1: Nth solution doesn't exist ");
390 }
391 return ((ListeDeSolutionShape1.Value(N)).SupportKind());
392}
393
394//=======================================================================
395//function : SupportTypeShape2
396//purpose :
397//=======================================================================
398
399BRepExtrema_SupportType BRepExtrema_DistShapeShape::SupportTypeShape2(const Standard_Integer N) const
400{
401 if (myIsDone == Standard_False)
402 { StdFail_NotDone::Raise
403 ("BRepExtrema_DistShapeShape::SupportTypeShape2: There's no solution ");
404 }
405 if ((N<1)||(N>myNbSolution))
406 { Standard_OutOfRange::Raise
407 ("BRepExtrema_DistShapeShape::SupportTypeShape2: Nth solution doesn't exist ");
408 }
409 return ((ListeDeSolutionShape2.Value(N)).SupportKind());
410}
411
412//=======================================================================
413//function : SupportOnShape1
414//purpose :
415//=======================================================================
416
417TopoDS_Shape BRepExtrema_DistShapeShape::SupportOnShape1(const Standard_Integer N) const
418{
419 BRepExtrema_SupportType Type;
420 TopoDS_Shape a_shape;
421
422 if (myIsDone == Standard_False)
423 { StdFail_NotDone::Raise
424 ("BRepExtrema_DistShapeShape::SupportOnShape1: There's no solution ");
425 }
426 if ((N<1)||(N>myNbSolution))
427 { Standard_OutOfRange::Raise
428 ("BRepExtrema_DistShapeShape::SupportOnShape1: Nth solution doesn't exist ");
429 }
430 Type = ((ListeDeSolutionShape1.Value(N)).SupportKind());
431 switch ( Type)
432 { case BRepExtrema_IsVertex : a_shape=ListeDeSolutionShape1.Value(N).Vertex();
433 break;
434 case BRepExtrema_IsOnEdge : a_shape=ListeDeSolutionShape1.Value(N).Edge();
435 break;
436 case BRepExtrema_IsInFace : a_shape=ListeDeSolutionShape1.Value(N).Face();
437 break;
438 default :{}
439 }
440 return a_shape ;
441}
442
443//=======================================================================
444//function : SupportOnShape2
445//purpose :
446//=======================================================================
447
448TopoDS_Shape BRepExtrema_DistShapeShape::SupportOnShape2(const Standard_Integer N) const
449{
450 BRepExtrema_SupportType Type;
451 TopoDS_Shape a_shape ;
452
453 if (myIsDone == Standard_False)
454 { StdFail_NotDone::Raise
455 ("BRepExtrema_DistShapeShape::SupportOnShape2: There's no solution ");
456 }
457 if ((N<1)||(N>myNbSolution))
458 { Standard_OutOfRange::Raise
459 ("BRepExtrema_DistShapeShape::SupportOnShape2: Nth solution doesn't exist ");
460 }
461 Type = ((ListeDeSolutionShape2.Value(N)).SupportKind());
462 switch ( Type)
463 { case BRepExtrema_IsVertex : a_shape=ListeDeSolutionShape2.Value(N).Vertex();
464 break;
465 case BRepExtrema_IsOnEdge : a_shape=ListeDeSolutionShape2.Value(N).Edge();
466 break;
467 case BRepExtrema_IsInFace : a_shape=ListeDeSolutionShape2.Value(N).Face();
468 break;
469 default :{}
470 }
471 return a_shape ;
472}
473
474//=======================================================================
475//function : ParOnEdgeS1
476//purpose :
477//=======================================================================
478
479void BRepExtrema_DistShapeShape::ParOnEdgeS1(const Standard_Integer N, Standard_Real& t) const
480{
481 BRepExtrema_SupportType Type;
482
483 if (myIsDone == Standard_False)
484 { StdFail_NotDone::Raise
485 ("BRepExtrema_DistShapeShape::ParOnEdgeS1: There's no solution ");
486 }
487 if ((N<1)||(N>myNbSolution))
488 { Standard_OutOfRange::Raise
489 ("BRepExtrema_DistShapeShape::ParOnEdgeS1: Nth solution doesn't exist ");
490 }
491
492 Type = ((ListeDeSolutionShape1.Value(N)).SupportKind());
493 if (Type != BRepExtrema_IsOnEdge)
494 { BRepExtrema_UnCompatibleShape::Raise
495 ("BRepExtrema_DistShapeShape::ParOnEdgeS1:ParOnEdgeS1 is impossible without EDGE ");
496 }
497
498 (ListeDeSolutionShape1.Value(N)).EdgeParameter(t);
499}
500
501//=======================================================================
502//function : ParOnEdgeS2
503//purpose :
504//=======================================================================
505
506void BRepExtrema_DistShapeShape::ParOnEdgeS2(const Standard_Integer N, Standard_Real& t) const
507{
508 BRepExtrema_SupportType Type;
509
510 if (myIsDone == Standard_False)
511 { StdFail_NotDone::Raise
512 ("BRepExtrema_DistShapeShape::ParOnEdgeS2: There's no solution ");
513 }
514 if ((N<1)||(N>myNbSolution))
515 { Standard_OutOfRange::Raise
516 ("BRepExtrema_DistShapeShape::ParOnEdgeS2: Nth solution doesn't exist ");
517 }
518
519 Type = ((ListeDeSolutionShape2.Value(N)).SupportKind());
520 if (Type != BRepExtrema_IsOnEdge)
521 { BRepExtrema_UnCompatibleShape::Raise
522 ("BRepExtrema_DistShapeShape::ParOnEdgeS2:ParOnEdgeS2 is impossible without EDGE ");
523 }
524
525 (ListeDeSolutionShape2.Value(N)).EdgeParameter(t);
526}
527
528//=======================================================================
529//function : ParOnFaceS1
530//purpose :
531//=======================================================================
532
533void BRepExtrema_DistShapeShape::ParOnFaceS1(const Standard_Integer N, Standard_Real& u, Standard_Real& v) const
534{
535 BRepExtrema_SupportType Type;
536
537 if (myIsDone == Standard_False)
538 { StdFail_NotDone::Raise
539 ("BRepExtrema_DistShapeShape::ParOnFaceS1: There's no solution ");
540 }
541 if ((N<1)||(N>myNbSolution))
542 { Standard_OutOfRange::Raise
543 ("BRepExtrema_DistShapeShape::ParOnFaceS1: Nth solution doesn't exist ");
544 }
545
546 Type = ((ListeDeSolutionShape1.Value(N)).SupportKind());
547 if (Type != BRepExtrema_IsInFace)
548 { BRepExtrema_UnCompatibleShape::Raise
549 ("BRepExtrema_DistShapeShape::ParOnFaceS1:ParOnFaceS1 is impossible without FACE ");
550 }
551
552 (ListeDeSolutionShape1.Value(N)).FaceParameter(u, v);
553}
554
555void BRepExtrema_DistShapeShape::ParOnFaceS2(const Standard_Integer N, Standard_Real& u, Standard_Real& v) const
556{
557 BRepExtrema_SupportType Type;
558
559 if (myIsDone == Standard_False)
560 { StdFail_NotDone::Raise
561 ("BRepExtrema_DistShapeShape::ParOnFaceS2: There's no solution ");
562 }
563 if ((N<1)||(N>myNbSolution))
564 { Standard_OutOfRange::Raise
565 ("BRepExtrema_DistShapeShape::ParOnFaceS2: Nth solution doesn't exist ");
566 }
567 Type = ((ListeDeSolutionShape2.Value(N)).SupportKind());
568 if (Type != BRepExtrema_IsInFace)
569 { BRepExtrema_UnCompatibleShape::Raise
570 ("BRepExtrema_DistShapeShape::ParOnFaceS2:ParOnFaceS2 is impossible without FACE ");
571 }
572
573 (ListeDeSolutionShape2.Value(N)).FaceParameter(u, v);
574
575}
576
577//=======================================================================
578//function : Dump
579//purpose :
580//=======================================================================
581
582void BRepExtrema_DistShapeShape::Dump(Standard_OStream& o) const
583{
584 Standard_Integer i;
585 Standard_Real r1,r2;
586 BRepExtrema_SupportType Type1, Type2;
587
588 o<< "the distance value is : " << Value()<<endl;
589 o<< "the number of solutions is :"<<NbSolution()<<endl;
590 o<<endl;
591 for (i=1;i<=NbSolution();i++) {
592 o<<"solution number "<<i<<": "<< endl;
593 o<<"the type of the solution on the first shape is " <<Standard_Integer( SupportTypeShape1(i)) <<endl;
594 o<<"the type of the solution on the second shape is "<<Standard_Integer( SupportTypeShape2(i))<< endl;
595 o<< "the coordinates of the point on the first shape are: "<<endl;
596 o<<"X=" <<PointOnShape1(i).X()<<" Y=" <<PointOnShape1(i).Y()<<" Z="<<PointOnShape1(i).Z()<<endl;
597 o<< "the coordinates of the point on the second shape are: "<<endl;
598 o<<"X="<< PointOnShape2(i).X()<< " Y="<<PointOnShape2(i).Y()<<" Z="<< PointOnShape2(i).Z()<<endl;
599
600 Type1=SupportTypeShape1(i);
601 Type2=SupportTypeShape2(i);
602 if (Type1 == BRepExtrema_IsOnEdge)
603 {
604 ParOnEdgeS1(i,r1);
605 o << "parameter on the first edge : t= " << r1 << endl;
606 }
607 if (Type1 == BRepExtrema_IsInFace)
608 {
609 ParOnFaceS1(i,r1,r2);
610 o << "parameters on the first face : u= " << r1 << " v=" << r2 << endl;
611 }
612 if (Type2 == BRepExtrema_IsOnEdge)
613 {
614 ParOnEdgeS2(i,r1);
615 o << "parameter on the second edge : t=" << r1 << endl;
616 }
617 if (Type2 == BRepExtrema_IsInFace)
618 {
619 ParOnFaceS2(i,r1,r2);
620 o << "parameters on the second face : u= " << r1 << " v=" << r2 << endl;
621 }
622
623 o<<endl;
624 }
625}