Salome HOME
9f166d7a45e63dafe520072f1bdb6dd07163aa17
[modules/hydro.git] / src / HYDROData / HYDROData_Stream.cxx
1 // Copyright (C) 2014-2015  EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
6 //
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10 // Lesser General Public License for more details.
11 //
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
15 //
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
17 //
18
19 #include "HYDROData_Stream.h"
20
21 #include "HYDROData_Document.h"
22 #include "HYDROData_PolylineXY.h"
23 #include "HYDROData_Polyline3D.h"
24 #include "HYDROData_Profile.h"
25 #include "HYDROData_ShapesGroup.h"
26 #include "HYDROData_ShapesTool.h"
27 #include "HYDROData_IAltitudeObject.h"
28 #include "HYDROData_IProfilesInterpolator.h"
29 #include "HYDROData_Tool.h"
30 #include "HYDROData_DTM.h"
31
32 #include <TDataStd_RealArray.hxx>
33
34 #include <Precision.hxx>
35
36 #include <NCollection_DataMap.hxx>
37
38 #include <TColStd_Array1OfReal.hxx>
39 #include <TColStd_ListOfReal.hxx>
40 #include <TColStd_ListIteratorOfListOfReal.hxx>
41 #include <TCollection_CompareOfReal.hxx>
42 #include <TColgp_Array1OfPnt.hxx>
43 #include <TColgp_HArray1OfPnt.hxx>
44
45 #include <TopoDS.hxx>
46 #include <TopoDS_Wire.hxx>
47 #include <TopoDS_Shell.hxx>
48 #include <TopoDS_Face.hxx>
49 #include <TopoDS_Edge.hxx>
50 #include <TopoDS_Vertex.hxx>
51 #include <TopExp.hxx>
52 #include <TopExp_Explorer.hxx>
53
54 #include <Bnd_Box.hxx>
55
56 #include <BRep_Builder.hxx>
57 #include <BRepBuilderAPI_MakeEdge.hxx>
58 #include <BRepBuilderAPI_MakeWire.hxx>
59 #include <BRepBuilderAPI_MakeFace.hxx>
60
61 #include <BRepBndLib.hxx>
62 #include <BRepProj_Projection.hxx>
63 #include <BRepExtrema_ExtCC.hxx>
64 #include <BRepCheck_Analyzer.hxx>
65
66 #include <gp.hxx>
67 #include <gp_Ax1.hxx>
68 #include <gp_Ax2.hxx>
69 #include <gp_Ax3.hxx>
70 #include <gp_Vec.hxx>
71 #include <gp_Pnt.hxx>
72 #include <gp_Pln.hxx>
73
74 #include <GeomAPI_Interpolate.hxx>
75 #include <Geom_BSplineCurve.hxx>
76
77 #include <TopTools_HArray1OfShape.hxx>
78
79 #include <SortTools_QuickSortOfReal.hxx>
80
81 #include <QColor>
82 #include <QStringList>
83
84 //#define DEB_STREAM 1
85 #ifdef DEB_STREAM
86 //#define DEB_HASINT 1
87 //#define DEB_UPDATE 1
88 #include <BRepTools.hxx>
89 #include <TCollection_AsciiString.hxx>
90 #endif
91
92 typedef NCollection_DataMap<Standard_Real, Handle(HYDROData_Profile)> HYDROData_DataMapOfRealOfHDProfile;
93
94 IMPLEMENT_STANDARD_HANDLE(HYDROData_Stream,HYDROData_NaturalObject)
95 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Stream,HYDROData_NaturalObject)
96
97
98 HYDROData_Stream::HYDROData_Stream()
99 : HYDROData_NaturalObject( Geom_3d )
100 {
101 }
102
103 HYDROData_Stream::~HYDROData_Stream()
104 {
105 }
106
107 void HYDROData_Stream::SetLabel( const TDF_Label& theLabel )
108 {
109   HYDROData_NaturalObject::SetLabel( theLabel );
110
111   if( GetAltitudeObject().IsNull() )
112   {
113     Handle(HYDROData_Document) aDoc = HYDROData_Document::Document( myLab );
114     Handle(HYDROData_DTM) aDTM = 
115       Handle(HYDROData_DTM)::DownCast( aDoc->CreateObject( KIND_DTM ) );
116     SetAltitudeObject( aDTM );
117   }
118 }
119
120 QStringList HYDROData_Stream::DumpToPython( const QString&       thePyScriptPath,
121                                             MapOfTreatedObjects& theTreatedObjects ) const
122 {
123   QStringList aResList = dumpObjectCreation( theTreatedObjects );
124   QString aName = GetObjPyName();
125
126   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
127   setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aHydAxis, "SetHydraulicAxis" );
128
129   HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
130   for ( int i = 1, aNb = aSeqOfProfiles.Size(); i <= aNb; ++i )
131   {
132     const Handle(HYDROData_Entity) aProfile = aSeqOfProfiles.Value( i );
133     setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aProfile, "AddProfile" );
134   }
135
136   // Set bottom polyline if exists
137   const Handle(HYDROData_Polyline3D) aBottomPolyline = GetBottomPolyline();
138   if ( !aBottomPolyline.IsNull() ) {
139     setPythonReferenceObject( thePyScriptPath, theTreatedObjects, aResList, aBottomPolyline, "SetBottomPolyline" );
140   }
141
142   QString aDDZs = QString::number( GetDDZ(), 'f', 3 );
143   QString aSSteps = QString::number( GetSpatialStep(), 'f', 3 );
144   aResList << QString( "%1.SetDDZ( %2 )" ).arg( aName ).arg( aDDZs );
145   aResList << QString( "%1.SetSpatialStep( %2 )" ).arg( aName ).arg( aSSteps );
146
147   aResList << QString( "" );
148   aResList << QString( "%1.Update()" ).arg( aName );
149   aResList << QString( "" );
150
151   return aResList;
152 }
153
154 HYDROData_SequenceOfObjects HYDROData_Stream::GetAllReferenceObjects() const
155 {
156   HYDROData_SequenceOfObjects aResSeq = HYDROData_Object::GetAllReferenceObjects();
157
158   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
159   if ( !aHydAxis.IsNull() )
160     aResSeq.Append( aHydAxis );
161
162   HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
163   aResSeq.Append( aSeqOfProfiles );
164
165   return aResSeq;
166 }
167
168 Handle(Geom_BSplineCurve) HYDROData_Stream::buildInterpolationCurve( 
169   const Handle(TColgp_HArray1OfPnt)& theArrayOfPnt )
170 {
171   Handle(Geom_BSplineCurve) aBSpline;
172   GeomAPI_Interpolate anInterpolator (theArrayOfPnt, Standard_False, 1.0e-5); 
173   anInterpolator.Perform() ;
174   if (anInterpolator.IsDone()) 
175     aBSpline = anInterpolator.Curve();
176   return aBSpline; 
177 }
178
179 void HYDROData_Stream::Update()
180 {
181   updateProfilesOrder();
182
183   // Update bottom polyline if exists
184   const Handle(HYDROData_Polyline3D) aBottomPolyline = GetBottomPolyline();
185   if ( !aBottomPolyline.IsNull() ) {
186     if ( GenerateBottomPolyline() ) {
187       Handle(HYDROData_PolylineXY) aPolylineXY = aBottomPolyline->GetPolylineXY();
188       if ( !aPolylineXY.IsNull() ) {
189         aPolylineXY->Update();
190       }
191       aBottomPolyline->Update();
192     }
193   }
194
195   UpdatePrs();
196 }
197
198 bool HYDROData_Stream::IsHas2dPrs() const
199 {
200   return true;
201 }
202
203 bool HYDROData_Stream::CreatePresentations( const Handle(HYDROData_PolylineXY)& theHydAxis,
204                                             const HYDROData_SequenceOfObjects&  theProfiles,
205                                             PrsDefinition&                      thePrs )
206 {
207   if ( theHydAxis.IsNull() || theProfiles.Length() < 2 )
208     return false;
209
210   Handle(TColgp_HArray1OfPnt) anArrayOfFPnt    = new TColgp_HArray1OfPnt(1, theProfiles.Length());
211   Handle(TColgp_HArray1OfPnt) anArrayOfLPnt    = new TColgp_HArray1OfPnt(1, theProfiles.Length());  
212   Handle(TopTools_HArray1OfShape) anArrOfProfiles = new TopTools_HArray1OfShape(1, theProfiles.Length());
213   Handle(TopTools_HArray1OfShape) anArrOf2DProfiles = new TopTools_HArray1OfShape(1, theProfiles.Length());
214
215   // Pre-processing
216   HYDROData_SequenceOfObjects::Iterator anIter( theProfiles );
217   for (int i=1 ; anIter.More(); anIter.Next(),i++ )
218   {
219     Handle(HYDROData_Profile) aProfile =
220       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
221     if ( aProfile.IsNull() )
222       continue;
223
224     const TopoDS_Shape& aProf3d = aProfile->GetShape3D();
225     gp_XY aPnt1, aPnt2;
226     if ( !aProfile->GetLeftPoint( aPnt1, false ) || !aProfile->GetRightPoint( aPnt2, false ) )
227       continue;
228
229     anArrOfProfiles->SetValue(i,aProfile->GetShape3D());//aProfile->GetTopShape();
230     anArrOf2DProfiles->SetValue(i,aProfile->GetTopShape());
231
232     gp_Pnt aCurFP, aCurLP;
233     TopoDS_Vertex aV1, aV2;
234     TopExp::Vertices(TopoDS::Wire(aProf3d), aV1, aV2);
235        gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
236     if(aP1.X() == aPnt1.X() && aP1.Y() == aPnt1.Y())
237       aCurFP = aP1;
238     else
239       aCurLP = aP1;
240     aP1 = BRep_Tool::Pnt(aV2);
241     if(aP1.X() == aPnt2.X() && aP1.Y() == aPnt2.Y())
242       aCurLP = aP1;
243     else
244       aCurFP = aP1;
245     anArrayOfFPnt->SetValue(i,aCurFP);
246     anArrayOfLPnt->SetValue(i,aCurLP);
247   }
248
249   return CreatePresentations( anArrayOfFPnt, anArrayOfLPnt, anArrOfProfiles, anArrOf2DProfiles, thePrs );
250 }
251
252 void HYDROData_Stream::UpdatePrs()
253 {
254   HYDROData_NaturalObject::Update();
255
256   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
257   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
258
259   PrsDefinition aResultPrs;
260   if ( !CreatePresentations( aHydAxis, aRefProfiles, aResultPrs ) )
261     return;
262
263   SetShape3D( aResultPrs.myPrs3D );
264   SetTopShape( aResultPrs.myPrs2D );
265
266   // Create the stream groups
267   QString aLeftGroupName = GetName() + "_Left_Bank";
268
269   Handle(HYDROData_ShapesGroup) aLeftGroup = createGroupObject();
270   aLeftGroup->SetName( aLeftGroupName );
271   aLeftGroup->AddShape( aResultPrs.myLeftBank );
272
273   QString aRightGroupName = GetName() + "_Right_Bank";
274
275   Handle(HYDROData_ShapesGroup) aRightGroup = createGroupObject();
276   aRightGroup->SetName( aRightGroupName );
277   aRightGroup->AddShape( aResultPrs.myRightBank );
278
279   QString anInGroupName = GetName() + "_Inlet";
280
281   Handle(HYDROData_ShapesGroup) anInGroup = createGroupObject();
282   anInGroup->SetName( anInGroupName );
283   anInGroup->AddShape( aResultPrs.myInlet );
284
285   QString anOutGroupName = GetName() + "_Outlet";
286   
287   Handle(HYDROData_ShapesGroup) anOutGroup = createGroupObject();
288   anOutGroup->SetName( anOutGroupName );
289   anOutGroup->AddShape( aResultPrs.myOutlet );
290 }
291
292 QColor HYDROData_Stream::DefaultFillingColor() const
293 {
294   return QColor( Qt::green );
295 }
296
297 QColor HYDROData_Stream::DefaultBorderColor() const
298 {
299   return QColor( Qt::transparent );
300 }
301
302 bool HYDROData_Stream::IsValidAsAxis( const Handle(HYDROData_PolylineXY)& theHydAxis )
303 {
304   if ( theHydAxis.IsNull() )
305     return false;
306
307   TopoDS_Shape aHydraulicShape = theHydAxis->GetShape();
308   if ( aHydraulicShape.IsNull() || 
309        aHydraulicShape.ShapeType() != TopAbs_WIRE ||
310        BRep_Tool::IsClosed( aHydraulicShape ) )
311     return false; // The polyline must be a single not closed wire
312
313   return true;
314 }
315
316 TopoDS_Shape HYDROData_Stream::GetLeftShape() const
317 {
318   HYDROData_SequenceOfObjects aGroups = GetGroups();
319   return HYDROData_Tool::getFirstShapeFromGroup( aGroups, 1);
320 }
321
322 TopoDS_Shape HYDROData_Stream::GetRightShape() const
323 {
324   HYDROData_SequenceOfObjects aGroups = GetGroups();
325   return HYDROData_Tool::getFirstShapeFromGroup( aGroups, 2);
326 }
327
328 TopoDS_Shape HYDROData_Stream::GetInletShape() const
329 {
330   HYDROData_SequenceOfObjects aGroups = GetGroups();
331   return HYDROData_Tool::getFirstShapeFromGroup( aGroups, 3);
332 }
333
334 TopoDS_Shape HYDROData_Stream::GetOutletShape() const
335 {
336   HYDROData_SequenceOfObjects aGroups = GetGroups();
337   return HYDROData_Tool::getFirstShapeFromGroup( aGroups, 4);
338 }
339
340 Handle_HYDROData_DTM HYDROData_Stream::DTM() const
341 {
342   return Handle(HYDROData_DTM)::DownCast( GetAltitudeObject() );
343 }
344
345 double HYDROData_Stream::GetDDZ() const
346 {
347   return DTM()->GetDDZ();
348 }
349
350 void HYDROData_Stream::SetDDZ( double theDDZ )
351 {
352   DTM()->SetDDZ( theDDZ );
353 }
354   
355 double HYDROData_Stream::GetSpatialStep() const
356 {
357   return DTM()->GetSpatialStep();
358 }
359
360 void HYDROData_Stream::SetSpatialStep( double theSpatialStep )
361 {
362   DTM()->SetSpatialStep( theSpatialStep );
363 }
364
365 bool HYDROData_Stream::SetHydraulicAxis( const Handle(HYDROData_PolylineXY)& theAxis )
366 {
367   if ( !IsValidAsAxis( theAxis ) )
368     return false;
369
370   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
371   if ( IsEqual( aPrevAxis, theAxis ) )
372     return true;
373
374   SetReferenceObject( theAxis, DataTag_HydraulicAxis );
375
376   // Update the order of profiles
377   updateProfilesOrder();
378
379   // Indicate model of the need to update the stream presentation
380   Changed( Geom_3d );
381
382   return true;
383 }
384
385 Handle(HYDROData_PolylineXY) HYDROData_Stream::GetHydraulicAxis() const
386 {
387   return Handle(HYDROData_PolylineXY)::DownCast( 
388            GetReferenceObject( DataTag_HydraulicAxis ) );
389 }
390
391 void HYDROData_Stream::RemoveHydraulicAxis()
392 {
393   Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
394   if ( aPrevAxis.IsNull() )
395     return;
396
397   ClearReferenceObjects( DataTag_HydraulicAxis );
398
399   // We remove the reference profiles
400   RemoveProfiles();
401
402   // Indicate model of the need to update the stream presentation
403   Changed( Geom_3d );
404 }
405
406 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_Profile)& theProfile,
407                                         const TopoDS_Face&               thePlane,
408                                         Standard_Real&                   theOutPar ) const
409 {
410   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
411   return HasIntersection( aHydAxis, theProfile, thePlane, theOutPar );
412 }
413
414 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_PolylineXY)& theHydAxis, 
415                                         const Handle(HYDROData_Profile)&    theProfile, 
416                                         const TopoDS_Face&                  thePlane,
417                                         Standard_Real&                      theOutPar )
418 {
419   if ( theProfile.IsNull() || !IsValidAsAxis( theHydAxis ) )
420     return false; 
421
422   TopoDS_Wire aHydraulicWire = TopoDS::Wire( theHydAxis->GetShape() ); //guide line
423   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
424   if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
425     return false;
426
427   BRepProj_Projection aProjector (aProfileWire, thePlane, gp::OZ().Direction());
428   if(!aProjector.IsDone())
429     return false;
430   TopoDS_Shape aPrjProfile = aProjector.Shape();
431   if(aPrjProfile.IsNull())
432     return false;
433   TopoDS_Vertex aV1, aV2;
434   if(aPrjProfile.ShapeType() == TopAbs_EDGE)
435     TopExp::Vertices(TopoDS::Edge(aPrjProfile), aV1, aV2);
436   else if(aPrjProfile.ShapeType() == TopAbs_WIRE)  
437     TopExp::Vertices(TopoDS::Wire(aPrjProfile), aV1, aV2);
438   else if(aPrjProfile.ShapeType() == TopAbs_COMPOUND){
439     TopExp_Explorer anExp(aPrjProfile, TopAbs_WIRE);
440     if(anExp.More()) {
441       TopExp::Vertices(TopoDS::Wire(anExp.Current()), aV1, aV2);
442     } else {
443       anExp.Init(aPrjProfile, TopAbs_EDGE);
444       if(anExp.More()) {
445         TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV1, aV2);
446       }
447     }
448   }
449   if(aV1.IsNull() || aV2.IsNull())
450     return false;
451   gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1);
452   gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2);
453   aPnt1.SetZ(0.0);
454   aPnt2.SetZ(0.0);
455   BRepBuilderAPI_MakeEdge aMk(aPnt1, aPnt2); 
456   if(!aMk.IsDone())
457     return false;
458   const TopoDS_Edge& anEdg2 = aMk.Edge();//Section edge
459   Standard_Integer aNum(0);
460   
461   TopExp_Explorer anExplo(aHydraulicWire, TopAbs_EDGE);
462   for(;anExplo.More();anExplo.Next()) aNum++;
463   // check for self-intersection
464   const Standard_Real SquareTolerance = Precision::Confusion()*Precision::Confusion();
465   Standard_Boolean hasInt(false);
466   Standard_Real aSqDist(DBL_MAX);
467   Standard_Integer anIndx(0);
468   BRepExtrema_ExtCC aCC;
469   aCC.Initialize(anEdg2);
470   theOutPar = 0.0;
471   anExplo.Init(aHydraulicWire, TopAbs_EDGE);
472   for(Standard_Integer j=1;anExplo.More();anExplo.Next(),j++) {
473     const TopoDS_Edge& anEdg1 = TopoDS::Edge(anExplo.Current());
474     if(anEdg1.IsNull())
475       continue;
476     Standard_Boolean hasSol(false);
477     aCC.Perform(anEdg1);
478     if(aCC.IsDone()) {
479     // find minimal dist
480     for(Standard_Integer i=1; i<= aCC.NbExt();i++)
481       if(aCC.SquareDistance(i) < aSqDist) {
482         aSqDist = aCC.SquareDistance(i);
483         anIndx = i;
484         hasSol = true;
485       }  
486     }
487     if(hasSol) {
488       if(aSqDist <= SquareTolerance) { // hasInt
489         const gp_Pnt& aPnt = aCC.PointOnE1(anIndx);
490         if(aNum > 1) {
491           TopExp::Vertices(anEdg1, aV1, aV2, Standard_True);
492           theOutPar += BRep_Tool::Pnt(aV1).Distance(aPnt);
493         } else {
494           Standard_Real aPar = aCC.ParameterOnE1(anIndx);
495           theOutPar = aPar;
496         }
497         hasInt = true;
498         break;
499       } else {
500           // no ints-n
501         if(aNum > 1) {
502           TopExp::Vertices(anEdg1, aV1, aV2);
503           theOutPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
504         }
505       }
506     } else if(aNum > 1) {
507       TopExp::Vertices(anEdg1, aV1, aV2);
508       theOutPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
509     }
510   }
511   if(hasInt)
512     return true;
513   return false;
514 }
515
516 bool HYDROData_Stream::AddProfile( const Handle(HYDROData_Profile)& theProfile )
517 {
518   if ( theProfile.IsNull() )
519     return false;
520
521   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
522   if ( aHydAxis.IsNull() )
523     return false;
524
525   TopoDS_Face aPlane;
526   if(!BuildFace(aHydAxis, aPlane))
527     return false;
528
529   Standard_Real aPar(.0);
530   if ( HasReference( theProfile, DataTag_Profile ) || !HasIntersection( theProfile, aPlane, aPar ) )
531     return false; // Object is already in reference list or it has no intersection
532   
533   int aProfileIndex = insertParameter( aPar );
534   insertProfileInToOrder( theProfile, aProfileIndex );
535   
536   // Indicate model of the need to update the stream presentation
537   Changed( Geom_3d );
538
539   return true;
540 }
541
542 bool HYDROData_Stream::SetProfiles( const HYDROData_SequenceOfObjects& theProfiles,
543                                     const bool&                        theIsToOrder )
544 {
545   if ( theIsToOrder )
546   {
547     for ( int i = 1; i <= theProfiles.Length(); ++i )
548     {
549       Handle(HYDROData_Profile) aProfile = 
550         Handle(HYDROData_Profile)::DownCast( theProfiles.Value( i ) );
551       if ( aProfile.IsNull() )
552         continue;
553
554       if ( !AddProfile( aProfile ) )
555       {
556         DTM()->SetProfiles( HYDROData_SequenceOfObjects() );
557         return false;
558       }
559     }
560   }
561   else // Just store the sequence of objects as is
562   {
563     bool anIsToUpdate = true;
564
565     HYDROData_SequenceOfObjects anOldProfiles = GetProfiles();
566     if ( anOldProfiles.Length() == theProfiles.Length() )
567     {
568       anIsToUpdate = false;
569
570       for ( int i = 1; i <= theProfiles.Length(); ++i )
571       {
572         Handle(HYDROData_Entity) anOldProfile = anOldProfiles.Value( i );
573         Handle(HYDROData_Entity) aNewProfile = theProfiles.Value( i );
574         if ( !IsEqual( anOldProfile, aNewProfile ) )
575         {
576           anIsToUpdate = true;
577           break;
578         }
579       }
580     }
581     
582     SetReferenceObjects( theProfiles, DataTag_Profile );
583
584     if ( anIsToUpdate )
585       Changed( Geom_3d );
586   }
587
588   DTM()->SetProfiles( GetProfiles() );
589   return true;
590 }
591
592 HYDROData_SequenceOfObjects HYDROData_Stream::GetProfiles() const
593 {
594   return GetReferenceObjects( DataTag_Profile );
595 }
596
597 bool HYDROData_Stream::RemoveProfile( const Handle(HYDROData_Profile)& theProfile )
598 {
599   if ( theProfile.IsNull() )
600     return false;
601
602   int aProfileIndex = -1;
603
604   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
605   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
606   for ( int i = 0 ; anIter.More(); anIter.Next(), ++i )
607   {
608     Handle(HYDROData_Profile) aProfile =
609       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
610     if ( aProfile.IsNull() )
611       continue;
612
613     if ( IsEqual( theProfile, aProfile ) )
614     {
615       aProfileIndex = i;
616       break;
617     }
618   }
619
620   if ( aProfileIndex == -1 )
621     return false;
622
623   RemoveReferenceObject( theProfile->Label(), DataTag_Profile );
624
625   // Remove parameter for removed profile
626   removeParameter( aProfileIndex );
627
628   // Indicate model of the need to update the stream presentation
629   Changed( Geom_3d );
630
631   return true;
632 }
633
634 void HYDROData_Stream::RemoveProfiles()
635 {
636   ClearReferenceObjects( DataTag_Profile );
637
638   // Remove the parameters array
639   removeParametersArray();
640
641   // Indicate model of the need to update the stream presentation
642   Changed( Geom_3d );
643 }
644
645 void HYDROData_Stream::insertProfileInToOrder( const Handle(HYDROData_Profile)& theProfile,
646                                                const int                        theBeforeIndex )
647 {
648   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
649   if ( theProfile.IsNull() || aHydAxis.IsNull() )
650     return; 
651
652   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
653   TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
654   if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
655     return;
656
657   if ( theBeforeIndex == -1 )
658     AddReferenceObject( theProfile, DataTag_Profile );
659   else
660     InsertReferenceObject( theProfile, DataTag_Profile, theBeforeIndex );
661 }
662
663 bool HYDROData_Stream::BuildFace( const Handle(HYDROData_PolylineXY)& theHydAxis,
664                                   TopoDS_Face&                        thePlane )
665 {
666   if ( !IsValidAsAxis( theHydAxis ) )
667     return false;
668
669   TopoDS_Wire aHydraulicWire = TopoDS::Wire( theHydAxis->GetShape() );
670
671   gp_Ax2 aX2(gp::XOY());
672   gp_Ax3 aX3(aX2);
673   gp_Pln aPln(aX3);   
674   Bnd_Box B;
675   BRepBndLib::Add(aHydraulicWire,B);
676   Standard_Real axmin,aymin,azmin,axmax,aymax,azmax;
677   B.Get(axmin,aymin,azmin,axmax,aymax,azmax);
678   BRepBuilderAPI_MakeFace aMkr(aPln, axmin-500., axmax+500., aymin-500., aymax+500.); // to be tuned later according max/ Profile deviation
679   if(!aMkr.IsDone() || aMkr.Shape().IsNull()) return false;
680   thePlane = TopoDS::Face(aMkr.Shape());
681   return true;
682 }
683
684 void HYDROData_Stream::updateProfilesOrder()
685 {
686   HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
687   if ( aRefProfiles.IsEmpty() )
688     return;
689
690   // At first we remove all profiles from order
691   RemoveProfiles();
692
693   Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
694   if ( aHydAxis.IsNull() )
695     return; 
696
697   TopoDS_Face aPlane;
698   if ( !BuildFace( aHydAxis, aPlane ) )
699     return;
700
701   Standard_Real aPar( .0 );
702
703 #ifdef DEB_HASINT
704   BRep_Builder aBB;
705   TopoDS_Compound aCmp;
706   aBB.MakeCompound(aCmp);
707 #endif
708
709   HYDROData_DataMapOfRealOfHDProfile aDM;  
710   TColStd_ListOfReal aList;
711   HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
712   for (int i = 1 ; anIter.More(); anIter.Next(), i++ )
713   {
714     Handle(HYDROData_Profile) aProfile =
715       Handle(HYDROData_Profile)::DownCast( anIter.Value() );
716 #ifdef DEB_HASINT
717   TopoDS_Wire aProfileWire = TopoDS::Wire( aProfile->GetTopShape() );
718   aBB.Add( aCmp, aProfileWire ); 
719 #endif
720     if ( aProfile.IsNull() || !HasIntersection( aProfile, aPlane, aPar ) )
721       continue;
722     
723     aDM.Bind( aPar, aProfile );
724     aList.Append( aPar );
725   }
726   
727   if ( aList.IsEmpty() )
728     return;
729
730   TColStd_Array1OfReal anArr( 1, aList.Extent() );
731
732   TColStd_ListIteratorOfListOfReal it( aList );
733   for ( int j = 1; it.More(); it.Next(), j++ )
734     anArr( j ) = it.Value();
735
736   // sorting
737   if ( aList.Extent() > 1 )
738   {
739     TCollection_CompareOfReal Compar;
740     SortTools_QuickSortOfReal::Sort( anArr, Compar );
741
742     for (int j = 1; j <= anArr.Length(); j++) {
743       const Standard_Real aKey =  anArr(j);
744       const Handle(HYDROData_Profile)& aProfile = aDM.Find(aKey);
745       insertProfileInToOrder( aProfile );
746     }
747   } else if ( aList.Extent() == 1 ) {
748      const Standard_Real aKey = aList.Last();
749      const Handle(HYDROData_Profile)& aProfile = aDM.Find(aKey);
750      insertProfileInToOrder( aProfile );
751   } 
752
753   setParametersArray( anArr );
754
755 #ifdef DEB_HASINT
756   TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
757   BRepTools::Write(aHydraulicWire, "Path.brep");
758   BRepTools::Write(aCmp, "Prof.brep");
759 #endif
760 }
761
762 ObjectKind HYDROData_Stream::getAltitudeObjectType() const
763 {
764   return KIND_DTM;
765 }
766
767 void HYDROData_Stream::setParametersArray( const TColStd_Array1OfReal& theArray )
768 {
769   if ( theArray.Length() == 0 )
770   {
771     removeParametersArray();
772     return;
773   }
774
775   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray );
776   
777   Handle(TDataStd_RealArray) aParamsArray = 
778     TDataStd_RealArray::Set( aLabel, theArray.Lower(), theArray.Upper() );
779
780   for ( int i = theArray.Lower(), n = theArray.Upper(); i <= n; ++i )
781   {
782     const Standard_Real& aParam = theArray( i );
783     aParamsArray->SetValue( i, aParam );
784   }
785 }
786
787 TColStd_Array1OfReal* HYDROData_Stream::getParametersArray() const
788 {
789   TColStd_Array1OfReal* anArray = NULL;
790
791   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
792   if ( !aLabel.IsNull() )
793   {
794     Handle(TDataStd_RealArray) aParamsArray;
795     if ( aLabel.FindAttribute( TDataStd_RealArray::GetID(), aParamsArray ) )
796     {
797       anArray = new TColStd_Array1OfReal( aParamsArray->Lower(), aParamsArray->Upper() );
798       for ( int i = aParamsArray->Lower(), n = aParamsArray->Upper(); i <= n; ++i )
799       {
800         const Standard_Real& aParam = aParamsArray->Value( i );
801         anArray->SetValue( i, aParam );
802       }
803     }
804   }
805
806   return anArray;
807 }
808
809 void HYDROData_Stream::removeParametersArray()
810 {
811   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
812   if ( !aLabel.IsNull() )
813     aLabel.ForgetAllAttributes();
814 }
815
816 int HYDROData_Stream::insertParameter( const Standard_Real& theParam )
817 {
818   int aResIndex = -1;
819
820   TColStd_Array1OfReal* anArr = getParametersArray();
821   if ( anArr )
822   {
823     aResIndex = 0;
824
825     TColStd_Array1OfReal aNewArr( anArr->Lower(), anArr->Upper() + 1 );
826
827     bool isInserted = false;
828     for ( int i = anArr->Lower(), j = i, n = anArr->Upper(); i <= n; ++i, ++j )
829     {
830       const Standard_Real& aStoredParam = anArr->Value( i );
831       if ( !isInserted )
832       {
833         if ( theParam > aStoredParam )
834         {
835           aResIndex++;
836         }
837         else
838         {
839           aNewArr( j ) = theParam;
840           isInserted = true;
841           ++j;
842         }
843       }
844
845       aNewArr( j ) = aStoredParam;
846     }
847
848     if ( !isInserted )
849     {
850       aResIndex = -1;
851       aNewArr( aNewArr.Upper() ) = theParam;
852     }
853     
854     setParametersArray( aNewArr );
855     delete anArr;
856   }
857   else
858   {
859     TColStd_Array1OfReal aNewArr( 1, 1 );
860     aNewArr.SetValue( 1, theParam );
861     setParametersArray( aNewArr );
862   }
863
864   return aResIndex;
865 }
866
867 void HYDROData_Stream::removeParameter( const int& theIndex )
868 {
869   TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
870   if ( aLabel.IsNull() )
871     return;
872
873   Handle(TDataStd_RealArray) aParamsArray;
874   if ( !aLabel.FindAttribute( TDataStd_RealArray::GetID(), aParamsArray ) )
875     return;
876
877   if ( aParamsArray->Length() == 1 )
878   {
879     removeParametersArray();
880     return;
881   }
882
883   TColStd_Array1OfReal aNewArr( aParamsArray->Lower(), aParamsArray->Upper() - 1 );
884
885   for ( int i = aParamsArray->Lower(), j = i, k = 0, n = aParamsArray->Upper(); i <= n; ++i, ++k )
886   {
887     const Standard_Real& aStoredParam = aParamsArray->Value( i );
888     if ( k == theIndex )
889       continue;
890
891     aNewArr.SetValue( j, aStoredParam );
892     ++j;
893   }
894
895   setParametersArray( aNewArr );
896 }
897
898 bool HYDROData_Stream::GenerateBottomPolyline()
899 {
900   // Get the document
901   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
902   if ( aDocument.IsNull() ) {
903     return false;
904   }
905
906   // Collect bottom points ( one bottom point from each profile of the stream )
907   HYDROData_Profile::ProfilePoints aBottomPoints;
908   
909   HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
910   for ( int i = 1, aNb = aSeqOfProfiles.Size(); i <= aNb; i++ ) {
911     const Handle(HYDROData_Profile) aProfile = 
912       Handle(HYDROData_Profile)::DownCast( aSeqOfProfiles.Value( i ) );
913     if ( aProfile.IsNull() ) {
914       continue;
915     }
916     
917     aBottomPoints.Append( aProfile->GetBottomPoint() );
918   }
919
920   int aNbBottomPoints = aBottomPoints.Size();
921
922   if ( aNbBottomPoints < 2 ) {
923     return false;
924   }
925
926   // Create bottom polyline object if the stream doesn't contain it yet
927   Handle(HYDROData_Polyline3D) aBottom = GetBottomPolyline();
928   if ( aBottom.IsNull() ) {
929     aBottom = Handle(HYDROData_Polyline3D)::DownCast( aDocument->CreateObject( KIND_POLYLINE ) );  
930     QString aBaseName = GetName() + "_bottom";
931     QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName, QStringList(), true );
932     aBottom->SetName( aName );
933
934     SetReferenceObject( aBottom, DataTag_BottomPolyline );
935   }
936   
937   // Create 2D polyline if the bottom polyline doesn't contain it yet
938   Handle(HYDROData_PolylineXY) aPolylineXY = aBottom->GetPolylineXY();
939   if ( aPolylineXY.IsNull() ) {
940     aPolylineXY = Handle(HYDROData_PolylineXY)::DownCast( aDocument->CreateObject( KIND_POLYLINEXY ) );
941     QString aBaseName = GetName() + "_bottom_2d";
942     QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName, QStringList(), true );
943     aPolylineXY->SetName( aName );
944     aBottom->SetPolylineXY( aPolylineXY, false );
945   }
946
947   aPolylineXY->RemoveSections();
948   aPolylineXY->AddSection( "", HYDROData_PolylineXY::SECTION_SPLINE, false );
949   
950   // Create profile if the bottom polyline doesn't contain it yet
951   Handle(HYDROData_ProfileUZ) aProfileUZ = aBottom->GetProfileUZ();
952   if ( aProfileUZ.IsNull() ) {
953     Handle(HYDROData_Profile) aProfile = 
954       Handle(HYDROData_Profile)::DownCast( aDocument->CreateObject( KIND_PROFILE ) );
955     QString aBaseName = GetName() + "_bottom_profile";
956     QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName, QStringList(), true );
957     aProfile->SetName( aName );
958     aProfileUZ = aProfile->GetProfileUZ( true );
959     aBottom->SetProfileUZ( aProfileUZ );
960   }
961   
962   aProfileUZ->RemoveSection( 0 );
963
964   aProfileUZ->CalculateAndAddPoints(aBottomPoints, aPolylineXY);
965   
966   return true;
967 }
968
969 Handle(HYDROData_Polyline3D) HYDROData_Stream::GetBottomPolyline() const
970 {
971   return Handle(HYDROData_Polyline3D)::DownCast( 
972            GetReferenceObject( DataTag_BottomPolyline ) );
973 }
974
975 bool HYDROData_Stream::SetBottomPolyline( const Handle(HYDROData_Polyline3D)& theBottom )
976 {
977   if ( theBottom.IsNull() ) {
978     return false;
979   }
980
981   SetReferenceObject( theBottom, DataTag_BottomPolyline );
982
983   return true;
984 }
985
986 bool HYDROData_Stream::Interpolate( HYDROData_IProfilesInterpolator* theInterpolator )
987 {
988   // Get the document
989   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
990   if ( aDocument.IsNull() ) {
991     return false;
992   }
993   
994   if ( theInterpolator->GetCalculatedProfilesNumber() < 1 ) {
995     theInterpolator->Calculate();
996   }
997
998   if ( theInterpolator->GetErrorCode() != OK ) {
999     return false;
1000   }
1001
1002   bool isOK = true;
1003
1004   for ( int aProfileInd = 0; aProfileInd < theInterpolator->GetCalculatedProfilesNumber(); aProfileInd++ ) {
1005     // Get calculated point coordinates
1006     HYDROData_Profile::ProfilePoints aResultPoints = theInterpolator->GetResultProfilePoints( aProfileInd );
1007     if ( aResultPoints.IsEmpty() ) {
1008       isOK = false;
1009       continue;
1010     }
1011         
1012     // Create profile object
1013     Handle(HYDROData_Profile) aProfile = 
1014       Handle(HYDROData_Profile)::DownCast( aDocument->CreateObject( KIND_PROFILE ) );
1015     QString aBaseName = GetName() + "_interp_profile";
1016     QString aName = HYDROData_Tool::GenerateObjectName( aDocument, aBaseName );
1017     aProfile->SetName( aName );
1018
1019     // Fill the profile with points
1020     aProfile->SetProfilePoints( aResultPoints );
1021
1022     // Add profile to the stream
1023     bool isAdded = AddProfile( aProfile );
1024     if ( !isAdded ) {
1025       aProfile->Remove();
1026     }
1027     else
1028       aProfile->Update();
1029   }
1030
1031   if ( isOK )
1032     Update();
1033
1034   return isOK;
1035 }
1036
1037 void HYDROData_Stream::CopyTo( const Handle(HYDROData_Entity)& theDestination,
1038                                bool isGenerateNewName ) const
1039 {
1040   // Get the document
1041   Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
1042   if ( aDocument.IsNull() ) {
1043     return;
1044   }
1045
1046   // Call base method
1047   HYDROData_Entity::CopyTo( theDestination, isGenerateNewName );
1048
1049   Handle(HYDROData_Stream) aStreamCopy = 
1050     Handle(HYDROData_Stream)::DownCast( theDestination );
1051
1052   // Copy bottom polyline if exists
1053   if ( !aStreamCopy.IsNull() ) {
1054     const Handle(HYDROData_Polyline3D) aBottom = GetBottomPolyline();
1055     if ( !aBottom.IsNull() ) {
1056       aStreamCopy->ClearReferenceObjects( DataTag_BottomPolyline );
1057       aStreamCopy->GenerateBottomPolyline();
1058       const Handle(HYDROData_Polyline3D) aBottomCopy = aStreamCopy->GetBottomPolyline();
1059       if ( !aBottomCopy.IsNull() && !aBottomCopy->GetPolylineXY().IsNull() ) {
1060         aBottomCopy->GetPolylineXY()->Update();
1061         aBottomCopy->Update();
1062       }
1063     }
1064   }
1065 }
1066
1067 bool HYDROData_Stream::CreatePresentations( const Handle(TColgp_HArray1OfPnt)     theArrayOfFPnt,
1068                                             const Handle(TColgp_HArray1OfPnt)     theArrayOfLPnt,
1069                                             const Handle(TopTools_HArray1OfShape) theArrOfProfiles,
1070                                             const Handle(TopTools_HArray1OfShape) theArrOf2DProfiles,
1071                                             PrsDefinition&                        thePrs )
1072 {
1073   if ( theArrayOfFPnt.IsNull() || theArrayOfLPnt.IsNull() || theArrOfProfiles.IsNull() ) {
1074     return false;
1075   }
1076
1077   if ( theArrayOfFPnt->Length() != theArrayOfLPnt->Length() ) {
1078     return false;
1079   }
1080   
1081   // Construct of the 3D presentation
1082   Handle(Geom_BSplineCurve) aBSpline = buildInterpolationCurve (theArrayOfFPnt);
1083   if(aBSpline.IsNull())
1084     return false;
1085
1086   TopoDS_Edge anEdgLeft, anEdgRight;
1087   
1088   BRepBuilderAPI_MakeEdge aMakeEdge(aBSpline);
1089   if(aMakeEdge.IsDone()) 
1090     anEdgLeft = aMakeEdge.Edge();
1091
1092   if(anEdgLeft.IsNull())
1093     return false;
1094
1095   aBSpline.Nullify();
1096   aBSpline = buildInterpolationCurve (theArrayOfLPnt);  
1097   if(aBSpline.IsNull())
1098     return false;
1099
1100   aMakeEdge.Init(aBSpline);
1101   if(aMakeEdge.IsDone()) 
1102     anEdgRight = aMakeEdge.Edge();
1103
1104   if(anEdgRight.IsNull())
1105     return false;
1106
1107   BRep_Builder aBB;
1108   TopoDS_Compound aCmp;
1109   aBB.MakeCompound(aCmp);
1110   for (int i=1 ; i < theArrOfProfiles->Length() +1; i++ )  
1111     aBB.Add(aCmp, theArrOfProfiles->Value(i));
1112
1113   aBB.Add(aCmp,anEdgLeft);
1114   aBB.Add(aCmp,anEdgRight);
1115   BRepCheck_Analyzer aCh(aCmp);
1116   if(aCh.IsValid())
1117     thePrs.myPrs3D = aCmp;
1118 #ifdef DEB_UPDATE
1119   else {
1120     BRepTools::Write(aCmp, "str3d.brep");
1121     thePrs.myPrs3D = aCmp;
1122   }
1123 #endif
1124
1125   // Construct the top presentation
1126   int aNbPoints = theArrayOfFPnt->Length();
1127   Handle(TColgp_HArray1OfPnt) anArrayOfFPnt = new TColgp_HArray1OfPnt(1, aNbPoints);
1128   Handle(TColgp_HArray1OfPnt) anArrayOfLPnt = new TColgp_HArray1OfPnt(1, aNbPoints);  
1129   for( int i=1; i <= aNbPoints; i++ ) {
1130       gp_Pnt aPnt = theArrayOfFPnt->Value(i);
1131       aPnt.SetZ(.0); // make 2d
1132       anArrayOfFPnt->SetValue(i, aPnt);
1133       aPnt = theArrayOfLPnt->Value(i);
1134       aPnt.SetZ(.0);
1135       anArrayOfLPnt->SetValue(i, aPnt);
1136   }
1137
1138   aBSpline.Nullify();
1139   aBSpline = buildInterpolationCurve (anArrayOfFPnt);  
1140   if(aBSpline.IsNull())
1141     return false; 
1142
1143   aMakeEdge.Init(aBSpline);
1144   if(aMakeEdge.IsDone()) 
1145       anEdgLeft = aMakeEdge.Edge();
1146
1147   aBSpline.Nullify();
1148   aBSpline = buildInterpolationCurve (anArrayOfLPnt);  
1149   if(aBSpline.IsNull())
1150     return false; 
1151
1152   aMakeEdge.Init(aBSpline);
1153   if(aMakeEdge.IsDone()) 
1154     anEdgRight = aMakeEdge.Edge();
1155   if(anEdgRight.IsNull())
1156     return false;
1157
1158   BRepBuilderAPI_MakeEdge aMakeEdge2(anArrayOfFPnt->Value(1),anArrayOfLPnt->Value(1));
1159   TopoDS_Edge aBotEdge, aTopEdge;
1160   if(aMakeEdge2.IsDone()) 
1161     aBotEdge = aMakeEdge2.Edge();
1162
1163   BRepBuilderAPI_MakeEdge aMakeEdge3(anArrayOfFPnt->Value(anArrayOfFPnt->Length()),anArrayOfLPnt->Value(anArrayOfLPnt->Length()));
1164   if(aMakeEdge3.IsDone()) 
1165     aTopEdge = aMakeEdge3.Edge();
1166
1167   // Make wire for 2D presentation with updating of corresponding edges
1168   BRepBuilderAPI_MakeWire aMakeWire;
1169   
1170   aMakeWire.Add( aBotEdge );
1171   thePrs.myInlet = aMakeWire.Edge();
1172
1173   aMakeWire.Add( anEdgLeft );
1174   thePrs.myLeftBank = aMakeWire.Edge();
1175
1176   aMakeWire.Add( aTopEdge );
1177   thePrs.myOutlet = aMakeWire.Edge();
1178
1179   aMakeWire.Add( anEdgRight );
1180   thePrs.myRightBank = aMakeWire.Edge();
1181
1182   TopoDS_Wire aSectProfileWire;
1183   if(aMakeWire.IsDone())
1184     aSectProfileWire = aMakeWire.Wire();
1185
1186   BRepBuilderAPI_MakeFace aMakeFace( aSectProfileWire, Standard_True );
1187   TopoDS_Face aFace;
1188   aMakeFace.Build();
1189   if( aMakeFace.IsDone() )
1190     aFace = aMakeFace.Face();
1191
1192   TopoDS_Shape aPrs2D;
1193
1194   if ( !theArrOf2DProfiles.IsNull() ) {
1195     aCmp.Nullify();
1196     aBB.MakeCompound(aCmp);
1197     aBB.Add(aCmp,aFace);
1198     for(int i=1;i <= theArrOf2DProfiles->Length(); i++)
1199       aBB.Add(aCmp, theArrOf2DProfiles->Value(i));
1200
1201     aPrs2D = aCmp;
1202   } else {
1203     aPrs2D = aFace;
1204   }
1205
1206   aCh.Init(aPrs2D);
1207   if(aCh.IsValid())
1208    thePrs.myPrs2D = aPrs2D;
1209 #ifdef DEB_UPDATE
1210   else {
1211     BRepTools::Write(aPrs2D, "str2d.brep");
1212     thePrs.myPrs2D = aPrs2D;
1213   }
1214 #endif
1215
1216   return true;
1217 }