0030895: Coding Rules - specify std namespace explicitly for std::cout and streams
[occt.git] / src / BinTools / BinTools_Curve2dSet.cxx
CommitLineData
b311480e 1// Created on: 2004-05-18
2// Created by: Sergey ZARITCHNY
973c2be1 3// Copyright (c) 2004-2014 OPEN CASCADE SAS
b311480e 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
b311480e 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
b311480e 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
7fd59977 15
42cf5bc1 16
17#include <BinTools.hxx>
18#include <BinTools_Curve2dSet.hxx>
19#include <Geom2d_BezierCurve.hxx>
20#include <Geom2d_BSplineCurve.hxx>
7fd59977 21#include <Geom2d_Circle.hxx>
42cf5bc1 22#include <Geom2d_Curve.hxx>
7fd59977 23#include <Geom2d_Ellipse.hxx>
7fd59977 24#include <Geom2d_Hyperbola.hxx>
42cf5bc1 25#include <Geom2d_Line.hxx>
7fd59977 26#include <Geom2d_OffsetCurve.hxx>
42cf5bc1 27#include <Geom2d_Parabola.hxx>
28#include <Geom2d_TrimmedCurve.hxx>
7fd59977 29#include <gp_Circ2d.hxx>
30#include <gp_Elips2d.hxx>
7fd59977 31#include <gp_Hypr2d.hxx>
42cf5bc1 32#include <gp_Lin2d.hxx>
33#include <gp_Parab2d.hxx>
7fd59977 34#include <Standard_ErrorHandler.hxx>
42cf5bc1 35#include <Standard_Failure.hxx>
36#include <Standard_OutOfRange.hxx>
37#include <Standard_Stream.hxx>
38#include <TColgp_Array1OfPnt2d.hxx>
39#include <TColStd_Array1OfInteger.hxx>
40#include <TColStd_Array1OfReal.hxx>
7fd59977 41
42#define LINE 1
43#define CIRCLE 2
44#define ELLIPSE 3
45#define PARABOLA 4
46#define HYPERBOLA 5
47#define BEZIER 6
48#define BSPLINE 7
49#define TRIMMED 8
50#define OFFSET 9
51
52//=======================================================================
53//function : BinTools_Curve2dSet
54//purpose :
55//=======================================================================
56
57BinTools_Curve2dSet::BinTools_Curve2dSet()
58{
59}
60
61
62//=======================================================================
63//function : Clear
64//purpose :
65//=======================================================================
66
67void BinTools_Curve2dSet::Clear()
68{
69 myMap.Clear();
70}
71
72
73//=======================================================================
74//function : Add
75//purpose :
76//=======================================================================
77
78Standard_Integer BinTools_Curve2dSet::Add(const Handle(Geom2d_Curve)& S)
79{
80 return myMap.Add(S);
81}
82
83
84//=======================================================================
85//function : Curve2d
86//purpose :
87//=======================================================================
88
89Handle(Geom2d_Curve) BinTools_Curve2dSet::Curve2d
90 (const Standard_Integer I)const
91{
92 return Handle(Geom2d_Curve)::DownCast(myMap(I));
93}
94
95
96//=======================================================================
97//function : Index
98//purpose :
99//=======================================================================
100
101Standard_Integer BinTools_Curve2dSet::Index
102 (const Handle(Geom2d_Curve)& S)const
103{
104 return myMap.FindIndex(S);
105}
106
107//=======================================================================
108//function : operator << (gp_Pnt2d)
109//purpose :
110//=======================================================================
111
112static Standard_OStream& operator <<(Standard_OStream& OS, const gp_Pnt2d P)
113
114{
115 BinTools::PutReal(OS, P.X());
116 return BinTools::PutReal(OS, P.Y());
117}
118
119//=======================================================================
120//function : operator << (gp_Dir2d D)
121//purpose :
122//=======================================================================
123
124static Standard_OStream& operator <<(Standard_OStream& OS, const gp_Dir2d D)
125{
126 BinTools::PutReal(OS, D.X());
127 return BinTools::PutReal(OS, D.Y());
128}
129
130//=======================================================================
131//function : operator << ((Geom2d_Line)& L)
132//purpose :
133//=======================================================================
134
135static Standard_OStream& operator <<(Standard_OStream& OS, const Handle(Geom2d_Line)& L)
136{
137
138 OS << (Standard_Byte)LINE;
139 gp_Lin2d C2d = L->Lin2d();
140 OS << C2d.Location();//Pnt2d
141 OS << C2d.Direction();//Dir2d
142 return OS;
143}
144
145//=======================================================================
146//function : operator << ((Geom2d_Circle)& C)
147//purpose :
148//=======================================================================
149
150static Standard_OStream& operator <<(Standard_OStream& OS, const Handle(Geom2d_Circle)& C)
151{
152 OS << (Standard_Byte)CIRCLE;
153 gp_Circ2d C2d = C->Circ2d();
154 OS << C2d.Location();
155 OS << C2d.XAxis().Direction();
156 OS << C2d.YAxis().Direction();
157 BinTools::PutReal(OS, C2d.Radius());
158 return OS;
159}
160
161//=======================================================================
162//function : operator <<(Geom2d_Ellipse)
163//purpose :
164//=======================================================================
165
166static Standard_OStream& operator <<(Standard_OStream& OS, const Handle(Geom2d_Ellipse)& E)
167{
168 OS << (Standard_Byte)ELLIPSE;
169 gp_Elips2d C2d = E->Elips2d();
170 OS << C2d.Location();
171 OS << C2d.XAxis().Direction();
172 OS << C2d.YAxis().Direction();
173 BinTools::PutReal(OS, C2d.MajorRadius());
174 BinTools::PutReal(OS, C2d.MinorRadius());
175 return OS;
176}
177
178//=======================================================================
179//function : operator << (Geom2d_Parabola)
180//purpose :
181//=======================================================================
182
183static Standard_OStream& operator <<(Standard_OStream& OS, const Handle(Geom2d_Parabola)& P)
184{
185 OS << (Standard_Byte)PARABOLA;
186 gp_Parab2d C2d = P->Parab2d();
187 OS << C2d.Location();//Loc
188 OS << C2d.Axis().XAxis().Direction();//XDir
189 OS << C2d.Axis().YAxis().Direction();//YDir
190 BinTools::PutReal(OS, C2d.Focal());//Focal
191 return OS;
192}
193
194//=======================================================================
195//function : operator <<(Geom2d_Hyperbola)
196//purpose :
197//=======================================================================
198
199static Standard_OStream& operator <<(Standard_OStream& OS, const Handle(Geom2d_Hyperbola)& H)
200{
201 OS << (Standard_Byte)HYPERBOLA;
202 gp_Hypr2d C2d = H->Hypr2d();
203 OS << C2d.Location(); //Loc
204 OS << C2d.XAxis().Direction();//XDir
205 OS << C2d.YAxis().Direction();//YDir
206 BinTools::PutReal(OS, C2d.MajorRadius());//MajR
207 BinTools::PutReal(OS, C2d.MinorRadius());
208 return OS;
209}
210
211//=======================================================================
212//function : operator <<(Geom2d_BezierCurve)
213//purpose :
214//=======================================================================
215
216static Standard_OStream& operator <<(Standard_OStream& OS, const Handle(Geom2d_BezierCurve)& B)
217{
218 OS << (Standard_Byte)BEZIER;
219 Standard_Boolean aRational = B->IsRational() ? 1:0;
220 BinTools::PutBool(OS, aRational); //rational
221 // poles and weights
222 Standard_Integer i,aDegree = B->Degree();
223 BinTools::PutExtChar(OS, (Standard_ExtCharacter)aDegree); //Degree
224 for (i = 1; i <= aDegree+1; i++) {
225 OS << B->Pole(i); //Pnt2d
226 if (aRational)
227 BinTools::PutReal(OS, B->Weight(i));//Real
228 }
229 return OS;
230}
231
232//=======================================================================
233//function : operator <<(Geom2d_BSplineCurve)
234//purpose :
235//=======================================================================
236
237static Standard_OStream& operator <<(Standard_OStream& OS, const Handle(Geom2d_BSplineCurve)& B)
238{
239 OS << (Standard_Byte)BSPLINE;
240 Standard_Boolean aRational = B->IsRational() ? 1:0;
241 BinTools::PutBool(OS, aRational); //rational
242 Standard_Boolean aPeriodic = B->IsPeriodic() ? 1:0;
243 BinTools::PutBool(OS, aPeriodic); //periodic
244 // poles and weights
245 Standard_Integer i,aDegree,aNbPoles,aNbKnots;
246 aDegree = B->Degree();
247 aNbPoles = B->NbPoles();
248 aNbKnots = B->NbKnots();
249 BinTools::PutExtChar(OS, (Standard_ExtCharacter) aDegree);
250 BinTools::PutInteger(OS, aNbPoles);
251 BinTools::PutInteger(OS, aNbKnots);
252 for (i = 1; i <= aNbPoles; i++) {
253 OS << B->Pole(i); // Pnt2d
254 if (aRational)
255 BinTools::PutReal(OS, B->Weight(i));
256 }
257
258 for (i = 1; i <= aNbKnots; i++) {
259 BinTools::PutReal(OS, B->Knot(i));
260 BinTools::PutInteger(OS, B->Multiplicity(i));
261 }
262
263 return OS;
264}
265
266//=======================================================================
267//function : operator <<(Geom2d_TrimmedCurve)
268//purpose :
269//=======================================================================
270
271static Standard_OStream& operator <<(Standard_OStream& OS, const Handle(Geom2d_TrimmedCurve)& C)
272{
273 OS << (Standard_Byte)TRIMMED;
274 BinTools::PutReal(OS, C->FirstParameter());
275 BinTools::PutReal(OS, C->LastParameter());
276 BinTools_Curve2dSet::WriteCurve2d(C->BasisCurve(),OS);
277 return OS;
278}
279
280//=======================================================================
281//function : operator <<(Geom2d_OffsetCurve)
282//purpose :
283//=======================================================================
284
285static Standard_OStream& operator <<(Standard_OStream& OS, const Handle(Geom2d_OffsetCurve)& C)
286{
287 OS << (Standard_Byte)OFFSET;
288 BinTools::PutReal(OS,C->Offset());//Offset
289 BinTools_Curve2dSet::WriteCurve2d(C->BasisCurve(),OS);
290 return OS;
291}
292
293//=======================================================================
294//function : WriteCurve2d
295//purpose :
296//=======================================================================
297
298void BinTools_Curve2dSet::WriteCurve2d(const Handle(Geom2d_Curve)& C,
299 Standard_OStream& OS)
300{
7fd59977 301 Handle(Standard_Type) TheType = C->DynamicType();
302 try {
303 OCC_CATCH_SIGNALS
304 if ( TheType == STANDARD_TYPE(Geom2d_Circle)) {
305 OS << Handle(Geom2d_Circle)::DownCast(C);
306 }
307 else if ( TheType ==STANDARD_TYPE(Geom2d_Line)) {
308 OS << Handle(Geom2d_Line)::DownCast(C);
309 }
310 else if ( TheType == STANDARD_TYPE(Geom2d_Ellipse)) {
311 OS << Handle(Geom2d_Ellipse)::DownCast(C);
312 }
313 else if ( TheType == STANDARD_TYPE(Geom2d_Parabola)) {
314 OS << Handle(Geom2d_Parabola)::DownCast(C);
315 }
316 else if ( TheType == STANDARD_TYPE(Geom2d_Hyperbola)) {
317 OS << Handle(Geom2d_Hyperbola)::DownCast(C);
318 }
319 else if ( TheType == STANDARD_TYPE(Geom2d_BezierCurve)) {
320 OS << Handle(Geom2d_BezierCurve)::DownCast(C);
321 }
322 else if ( TheType == STANDARD_TYPE(Geom2d_BSplineCurve)) {
323 OS << Handle(Geom2d_BSplineCurve)::DownCast(C);
324 }
325 else if ( TheType == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
326 OS << Handle(Geom2d_TrimmedCurve)::DownCast(C);
327 }
328 else if ( TheType == STANDARD_TYPE(Geom2d_OffsetCurve)) {
329 OS << Handle(Geom2d_OffsetCurve)::DownCast(C);
330 }
331 else {
9775fa61 332 throw Standard_Failure("UNKNOWN CURVE2d TYPE");
7fd59977 333 }
334 }
9775fa61 335 catch(Standard_Failure const& anException) {
4525373b 336 Standard_SStream aMsg;
04232180 337 aMsg << "EXCEPTION in BinTools_Curve2dSet::WriteCurve2d(..)" << std::endl;
338 aMsg << anException << std::endl;
9775fa61 339 throw Standard_Failure(aMsg.str().c_str());
7fd59977 340 }
341}
342
343//=======================================================================
344//function : Write
345//purpose :
346//=======================================================================
347
348void BinTools_Curve2dSet::Write(Standard_OStream& OS)const
349{
350 Standard_Integer i, aNbCurves = myMap.Extent();
351 OS << "Curve2ds "<< aNbCurves << "\n";
352 for (i = 1; i <= aNbCurves; i++) {
353 WriteCurve2d(Handle(Geom2d_Curve)::DownCast(myMap(i)),OS);
354 }
355}
356
357
358//=======================================================================
359//function : ReadPnt2d
360//purpose :
361//=======================================================================
362
363static Standard_IStream& operator>>(Standard_IStream& IS, gp_Pnt2d& P)
364{
365 Standard_Real X=0.,Y=0.;
366 BinTools::GetReal(IS, X);
367 BinTools::GetReal(IS, Y);
368 P.SetCoord(X,Y);
369 return IS;
370}
371
372//=======================================================================
373//function : ReadDir2d
374//purpose :
375//=======================================================================
376
377static Standard_IStream& operator>>(Standard_IStream& IS, gp_Dir2d& D)
378{
379 Standard_Real X=0.,Y=0.;
380 BinTools::GetReal(IS, X);
381 BinTools::GetReal(IS, Y);
382 D.SetCoord(X,Y);
383 return IS;
384}
385
386
387//=======================================================================
388//function : ReadCurve2d
389//purpose :
390//=======================================================================
391
392static Standard_IStream& operator>>(Standard_IStream& IS,
393 Handle(Geom2d_Line)& L)
394{
395 gp_Pnt2d P(0.,0.);
396 gp_Dir2d AX(1.,0.);
397 IS >> P >> AX;
398 L = new Geom2d_Line(P,AX);
399 return IS;
400}
401
402//=======================================================================
403//function : ReadCurve2d
404//purpose :
405//=======================================================================
406static Standard_IStream& operator>>(Standard_IStream& IS,
407 Handle(Geom2d_Circle)& C)
408{
409 gp_Pnt2d P(0.,0.);
410 gp_Dir2d AX(1.,0.),AY(1.,0.);
411 Standard_Real R=0.;
412 IS >> P >> AX >> AY;
413 BinTools::GetReal(IS, R);
414 C = new Geom2d_Circle(gp_Ax22d(P,AX,AY),R);
415 return IS;
416}
417
418//=======================================================================
419//function : ReadCurve2d
420//purpose :
421//=======================================================================
422
423static Standard_IStream& operator>>(Standard_IStream& IS,
424 Handle(Geom2d_Ellipse)& E)
425{
426 gp_Pnt2d P(0.,0.);
427 gp_Dir2d AX(1.,0.),AY(1.,0.);
428 Standard_Real R1=0., R2=0.;
429 IS >> P >> AX >> AY;
430 BinTools::GetReal(IS, R1);
431 BinTools::GetReal(IS, R2);
432 E = new Geom2d_Ellipse(gp_Ax22d(P,AX,AY),R1,R2);
433 return IS;
434}
435
436//=======================================================================
437//function : ReadCurve2d
438//purpose :
439//=======================================================================
440
441static Standard_IStream& operator>>(Standard_IStream& IS,
442 Handle(Geom2d_Parabola)& C)
443{
444 gp_Pnt2d P(0.,0.);
445 gp_Dir2d AX(1.,0.),AY(1.,0.);
446 Standard_Real R1=0.;
447 IS >> P >> AX >> AY;
448 BinTools::GetReal(IS, R1);
449 C = new Geom2d_Parabola(gp_Ax22d(P,AX,AY),R1);
450 return IS;
451}
452
453//=======================================================================
454//function : ReadCurve2d
455//purpose :
456//=======================================================================
457
458static Standard_IStream& operator>>(Standard_IStream& IS,
459 Handle(Geom2d_Hyperbola)& H)
460{
461 gp_Pnt2d P(0.,0.);
462 gp_Dir2d AX(1.,0.),AY(1.,0.);
463 Standard_Real R1=0.,R2=0.;
464 IS >> P >> AX >> AY;
465 BinTools::GetReal(IS, R1);
466 BinTools::GetReal(IS, R2);
467 H = new Geom2d_Hyperbola(gp_Ax22d(P,AX,AY),R1,R2);
468 return IS;
469}
470
471//=======================================================================
472//function : ReadCurve2d
473//purpose :
474//=======================================================================
475
476static Standard_IStream& operator>>(Standard_IStream& IS,
477 Handle(Geom2d_BezierCurve)& B)
478{
479 Standard_Boolean rational=Standard_False;
480 BinTools::GetBool(IS, rational);
481
482// poles and weights
483 Standard_Integer i=0,degree=0;
484// degree;
485 Standard_ExtCharacter aVal='\0';
486 BinTools::GetExtChar(IS, aVal);
487 degree = (Standard_Integer)aVal;
488
489 TColgp_Array1OfPnt2d poles(1,degree+1);
490 TColStd_Array1OfReal weights(1,degree+1);
491
492 for (i = 1; i <= degree+1; i++) {
493 IS >> poles(i);//Pnt2d
494 if (rational)
495 BinTools::GetReal(IS, weights(i));
496 }
497
498 if (rational)
499 B = new Geom2d_BezierCurve(poles,weights);
500 else
501 B = new Geom2d_BezierCurve(poles);
502
503 return IS;
504}
505
506//=======================================================================
507//function : ReadCurve2d
508//purpose :
509//=======================================================================
510
511static Standard_IStream& operator>>(Standard_IStream& IS,
512 Handle(Geom2d_BSplineCurve)& B)
513{
514
515 Standard_Boolean rational=Standard_False,periodic=Standard_False;
516 BinTools::GetBool(IS, rational);
517 BinTools::GetBool(IS, periodic);
518// poles and weights
519 Standard_Integer i=0,degree=0,nbpoles=0,nbknots=0;
520 Standard_ExtCharacter aVal='\0';
521
522 BinTools::GetExtChar(IS, aVal);
523 degree = (Standard_Integer)aVal;
524
525 BinTools::GetInteger(IS, nbpoles);
526
527 BinTools::GetInteger(IS, nbknots);
528
529 TColgp_Array1OfPnt2d poles(1,nbpoles);
530 TColStd_Array1OfReal weights(1,nbpoles);
531
532 for (i = 1; i <= nbpoles; i++) {
533 IS >> poles(i);//Pnt2d
534 if (rational)
535 BinTools::GetReal(IS, weights(i));
536 }
537
538 TColStd_Array1OfReal knots(1,nbknots);
539 TColStd_Array1OfInteger mults(1,nbknots);
540
541 for (i = 1; i <= nbknots; i++) {
542 BinTools::GetReal(IS, knots(i));
543 BinTools::GetInteger(IS, mults(i));
544 }
545
546 if (rational)
547 B = new Geom2d_BSplineCurve(poles,weights,knots,mults,degree,periodic);
548 else
549 B = new Geom2d_BSplineCurve(poles,knots,mults,degree,periodic);
550
551 return IS;
552}
553
554//=======================================================================
555//function : ReadCurve2d
556//purpose :
557//=======================================================================
558
559static Standard_IStream& operator>>(Standard_IStream& IS,
560 Handle(Geom2d_TrimmedCurve)& C)
561{
562 Standard_Real p1=0.,p2=0.;
563 BinTools::GetReal(IS, p1);//FirstParameter
564 BinTools::GetReal(IS, p2);//LastParameter
565 Handle(Geom2d_Curve) BC;
566 BinTools_Curve2dSet::ReadCurve2d(IS,BC);
567 C = new Geom2d_TrimmedCurve(BC,p1,p2);
568 return IS;
569}
570
571//=======================================================================
572//function : ReadCurve2d
573//purpose :
574//=======================================================================
575
576static Standard_IStream& operator>>(Standard_IStream& IS,
577 Handle(Geom2d_OffsetCurve)& C)
578{
579 Standard_Real p=0.;
580 BinTools::GetReal(IS, p);//Offset
581 Handle(Geom2d_Curve) BC;
582 BinTools_Curve2dSet::ReadCurve2d(IS,BC);
583 C = new Geom2d_OffsetCurve(BC,p);
584 return IS;
585}
586
587//=======================================================================
588//function : ReadCurve2d
589//purpose :
590//=======================================================================
591
592Standard_IStream& BinTools_Curve2dSet::ReadCurve2d(Standard_IStream& IS,
593 Handle(Geom2d_Curve)& C)
594{
7fd59977 595 try {
596 OCC_CATCH_SIGNALS
597 const Standard_Byte ctype = (Standard_Byte) IS.get();
598 switch (ctype) {
599
600 case LINE :
601 {
602 Handle(Geom2d_Line) CC;
603 IS >> CC;
604 C = CC;
605 }
606 break;
607
608 case CIRCLE :
609 {
610 Handle(Geom2d_Circle) CC;
611 IS >> CC;
612 C = CC;
613 }
614 break;
615
616 case ELLIPSE :
617 {
618 Handle(Geom2d_Ellipse) CC;
619 IS >> CC;
620 C = CC;
621 }
622 break;
623
624 case PARABOLA :
625 {
626 Handle(Geom2d_Parabola) CC;
627 IS >> CC;
628 C = CC;
629 }
630 break;
631
632 case HYPERBOLA :
633 {
634 Handle(Geom2d_Hyperbola) CC;
635 IS >> CC;
636 C = CC;
637 }
638 break;
639
640 case BEZIER :
641 {
642 Handle(Geom2d_BezierCurve) CC;
643 IS >> CC;
644 C = CC;
645 }
646 break;
647
648 case BSPLINE :
649 {
650 Handle(Geom2d_BSplineCurve) CC;
651 IS >> CC;
652 C = CC;
653 }
654 break;
655
656 case TRIMMED :
657 {
658 Handle(Geom2d_TrimmedCurve) CC;
659 IS >> CC;
660 C = CC;
661 }
662 break;
663
664 case OFFSET :
665 {
666 Handle(Geom2d_OffsetCurve) CC;
667 IS >> CC;
668 C = CC;
669 }
670 break;
671
672 default:
673 {
674 C = NULL;
9775fa61 675 throw Standard_Failure("UNKNOWN CURVE2d TYPE");
7fd59977 676 }
677 break;
678 }
679 }
9775fa61 680 catch(Standard_Failure const& anException) {
7fd59977 681 C = NULL;
4525373b 682 Standard_SStream aMsg;
04232180 683 aMsg <<"EXCEPTION in BinTools_Curve2dSet::ReadCurve2d(...)" << std::endl;
684 aMsg << anException << std::endl;
9775fa61 685 throw Standard_Failure(aMsg.str().c_str());
7fd59977 686 }
687 return IS;
688}
689
690//=======================================================================
691//function : Read
692//purpose :
693//=======================================================================
694
695void BinTools_Curve2dSet::Read(Standard_IStream& IS)
696{
697 char buffer[255];
63c629aa 698
7fd59977 699 IS >> buffer;
700 if (IS.fail() || strcmp(buffer,"Curve2ds")) {
701 Standard_SStream aMsg;
04232180 702 aMsg << "BinTools_Curve2dSet::Read: Not a Curve2d table"<<std::endl;
0797d9d3 703#ifdef OCCT_DEBUG
04232180 704 std::cout <<"Curve2dSet buffer: " << buffer << std::endl;
7fd59977 705#endif
9775fa61 706 throw Standard_Failure(aMsg.str().c_str());
7fd59977 707 return;
708 }
709
710 Handle(Geom2d_Curve) C;
711 Standard_Integer i, aNbCurves;
712 IS >> aNbCurves;
713 IS.get();//remove <lf>
714 for (i = 1; i <= aNbCurves; i++) {
715 BinTools_Curve2dSet::ReadCurve2d(IS,C);
716 myMap.Add(C);
717 }
718}
719
720
721