2 #include "HYDROData_Stream.h"
4 #include "HYDROData_Document.h"
5 #include "HYDROData_PolylineXY.h"
6 #include "HYDROData_Profile.h"
8 #include <BRep_Builder.hxx>
9 #include <BRepBuilderAPI_MakeEdge.hxx>
10 #include <BRepBuilderAPI_MakeWire.hxx>
11 #include <BRepBuilderAPI_MakeFace.hxx>
13 #include <TDataStd_RealArray.hxx>
16 #include <TopoDS_Wire.hxx>
17 #include <TopoDS_Shell.hxx>
18 #include <TopoDS_Face.hxx>
19 #include <TopoDS_Edge.hxx>
20 #include <TopoDS_Vertex.hxx>
22 #include <TopExp_Explorer.hxx>
23 #include <BRepProj_Projection.hxx>
24 #include <BRepExtrema_ExtCC.hxx>
32 #include <Bnd_Box.hxx>
33 #include <BRepBndLib.hxx>
34 #include <TColStd_Array1OfReal.hxx>
35 #include <Precision.hxx>
36 #include <QStringList>
38 #include <NCollection_DataMap.hxx>
39 typedef NCollection_DataMap<Standard_Real, Handle(HYDROData_Profile)> HYDROData_DataMapOfRealOfHDProfile;
40 //typedef HYDROData_DataMapOfRealOfHDProfile::Iterator HYDROData_DataMapIteratorOfDataMapOfRealOfHDProfile;
41 #include <TColStd_ListOfReal.hxx>
42 #include <TColStd_ListIteratorOfListOfReal.hxx>
43 #include <TCollection_CompareOfReal.hxx>
44 #include <SortTools_QuickSortOfReal.hxx>
45 #include <TColgp_Array1OfPnt.hxx>
46 #include <TColgp_HArray1OfPnt.hxx>
47 #include <GeomAPI_Interpolate.hxx>
48 #include <Geom_BSplineCurve.hxx>
49 #include <TopTools_Array1OfShape.hxx>
50 //#define DEB_HASINT 1
52 #include <BRepTools.hxx>
53 #include <TCollection_AsciiString.hxx>
54 #include <BRep_Builder.hxx>
57 #define PYTHON_STREAM_ID "KIND_STREAM"
59 IMPLEMENT_STANDARD_HANDLE(HYDROData_Stream,HYDROData_NaturalObject)
60 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Stream,HYDROData_NaturalObject)
63 HYDROData_Stream::HYDROData_Stream()
64 : HYDROData_NaturalObject()
68 HYDROData_Stream::~HYDROData_Stream()
72 QStringList HYDROData_Stream::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
76 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
77 if ( aDocument.IsNull() )
80 QString aDocName = aDocument->GetDocPyName();
81 QString aStreamName = GetName();
83 aResList << QString( "%1 = %2.CreateObject( %3 );" )
84 .arg( aStreamName ).arg( aDocName ).arg( PYTHON_STREAM_ID );
85 aResList << QString( "%1.SetName( \"%2\" );" )
86 .arg( aStreamName ).arg( aStreamName );
87 aResList << QString( "" );
94 HYDROData_SequenceOfObjects HYDROData_Stream::GetAllReferenceObjects() const
96 HYDROData_SequenceOfObjects aResSeq = HYDROData_Object::GetAllReferenceObjects();
98 Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
99 if ( !aHydAxis.IsNull() )
100 aResSeq.Append( aHydAxis );
102 HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
103 aResSeq.Append( aSeqOfProfiles );
108 TopoDS_Shape HYDROData_Stream::GetTopShape() const
110 return getTopShape();
112 TopoDS_Shape HYDROData_Stream::GetShape3D() const
117 void HYDROData_Stream::Update()
119 HYDROData_NaturalObject::Update();
121 Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
122 HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
123 if ( aHydAxis.IsNull() || aRefProfiles.IsEmpty() )
126 TopoDS_Shell a2dShell;
127 BRep_Builder a2dShellBuilder;
128 a2dShellBuilder.MakeShell( a2dShell );
130 bool anIsFirst = true;
131 gp_Pnt aPrevFirstPoint, aPrevLastPoint;
132 Handle(TColgp_HArray1OfPnt) anArrayOfFPnt = new TColgp_HArray1OfPnt(1, aRefProfiles.Length());
133 Handle(TColgp_HArray1OfPnt) anArrayOfLPnt = new TColgp_HArray1OfPnt(1, aRefProfiles.Length());
134 TopTools_Array1OfShape anArrOfProfiles(1, aRefProfiles.Length());
135 // Construct the top presentation
136 HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
137 for (int i=1 ; anIter.More(); anIter.Next(),i++ )
139 Handle(HYDROData_Profile) aProfile =
140 Handle(HYDROData_Profile)::DownCast( anIter.Value() );
141 if ( aProfile.IsNull() )
143 const TopoDS_Shape& aProf3d = aProfile->GetShape3D();
145 if ( !aProfile->GetFirstPoint( aPnt1 ) || !aProfile->GetLastPoint( aPnt2 ) )
147 anArrOfProfiles.SetValue(i,aProfile->GetShape3D());
149 gp_Pnt aCurFirstPoint( aPnt1.X(), aPnt1.Y(), 0 ), aCurFP;
150 gp_Pnt aCurLastPoint( aPnt2.X(), aPnt2.Y(), 0 ), aCurLP;
151 TopoDS_Vertex aV1, aV2;
152 TopExp::Vertices(TopoDS::Wire(aProf3d), aV1, aV2);
153 gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
154 if(aP1.X() == aPnt1.X() && aP1.Y() == aPnt1.Y())
158 aP1 = BRep_Tool::Pnt(aV2);
159 if(aP1.X() == aPnt2.X() && aP1.Y() == aPnt2.Y())
163 anArrayOfFPnt->SetValue(i,aCurFP);
164 anArrayOfLPnt->SetValue(i,aCurLP);
167 aPrevFirstPoint = aCurFirstPoint;
168 aPrevLastPoint = aCurLastPoint;
173 BRepBuilderAPI_MakeEdge aFirstEdge( aPrevFirstPoint, aPrevLastPoint );
174 BRepBuilderAPI_MakeEdge aSecondEdge( aPrevLastPoint, aCurLastPoint );
175 BRepBuilderAPI_MakeEdge aThirdEdge( aCurLastPoint, aCurFirstPoint );
176 BRepBuilderAPI_MakeEdge aFourthEdge( aCurFirstPoint, aPrevFirstPoint );
178 BRepBuilderAPI_MakeWire aMakeWire( aFirstEdge.Edge(), aSecondEdge.Edge(),
179 aThirdEdge.Edge(), aFourthEdge.Edge() );
181 TopoDS_Wire aSectProfileWire = aMakeWire.Wire();
183 BRepBuilderAPI_MakeFace aMakeFace( aSectProfileWire, Standard_True );
185 if( aMakeFace.IsDone() )
187 a2dShellBuilder.Add( a2dShell, aMakeFace.Face() );
190 aPrevFirstPoint = aCurFirstPoint;
191 aPrevLastPoint = aCurLastPoint;
194 SetTopShape( a2dShell );
196 // Construct the 3D presentation
197 Handle(Geom_BSplineCurve) aBSpline;
198 GeomAPI_Interpolate anInterpolator (anArrayOfFPnt, Standard_False, 1.0e-5);
199 anInterpolator.Perform() ;
200 if (anInterpolator.IsDone())
201 aBSpline = anInterpolator.Curve();
204 if(aBSpline.IsNull())
206 TopoDS_Edge anEdgLeft, anEdgRight;
207 BRepBuilderAPI_MakeEdge aMakeEdge(aBSpline);
208 if(aMakeEdge.IsDone())
209 anEdgLeft = aMakeEdge.Edge();
210 GeomAPI_Interpolate anInterpolator2 (anArrayOfLPnt, Standard_False, 1.0e-5);
211 anInterpolator2.Perform() ;
212 if (anInterpolator2.IsDone())
213 aBSpline = anInterpolator2.Curve();
216 if(aBSpline.IsNull())
218 aMakeEdge.Init(aBSpline);
219 if(aMakeEdge.IsDone())
220 anEdgRight = aMakeEdge.Edge();
222 TopoDS_Compound aCmp;
223 aBB.MakeCompound(aCmp);
224 anIter.Init( aRefProfiles );
225 for (int i=1 ; i < anArrOfProfiles.Length() +1; i++ )
226 aBB.Add(aCmp, anArrOfProfiles.Value(i));
227 aBB.Add(aCmp,anEdgLeft);
228 aBB.Add(aCmp,anEdgRight);
230 //BRepTools::Write(aCmp, "str3d.brep");
233 bool HYDROData_Stream::SetHydraulicAxis( const Handle(HYDROData_PolylineXY)& theAxis )
235 Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
237 if ( theAxis.IsNull() )
239 RemoveHydraulicAxis();
240 return !aPrevAxis.IsNull();
243 if ( IsEqual( aPrevAxis, theAxis ) )
246 TopoDS_Wire aHydraulicWire = TopoDS::Wire( theAxis->GetShape() );
247 if ( aHydraulicWire.IsNull() )
248 return false; // The polyline must be a single wire
250 SetReferenceObject( theAxis, DataTag_HydraulicAxis );
252 // Update the order of profiles
253 updateProfilesOrder();
255 // Indicate model of the need to update the stream presentation
261 Handle(HYDROData_PolylineXY) HYDROData_Stream::GetHydraulicAxis() const
263 return Handle(HYDROData_PolylineXY)::DownCast(
264 GetReferenceObject( DataTag_HydraulicAxis ) );
267 void HYDROData_Stream::RemoveHydraulicAxis()
269 Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
270 if ( aPrevAxis.IsNull() )
273 ClearReferenceObjects( DataTag_HydraulicAxis );
275 // We remove the reference profiles
278 // Indicate model of the need to update the stream presentation
282 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_Profile)& theProfile, const TopoDS_Face& thePlane,
283 Standard_Real& outPar ) const
285 Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
286 if ( theProfile.IsNull() || aHydAxis.IsNull() )
289 TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() ); //guide line
290 TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
291 if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
294 BRepProj_Projection aProjector (aProfileWire, thePlane, gp::OZ().Direction());
295 if(!aProjector.IsDone())
297 TopoDS_Shape aPrjProfile = aProjector.Shape();
298 if(aPrjProfile.IsNull())
300 TopoDS_Vertex aV1, aV2;
301 if(aPrjProfile.ShapeType() == TopAbs_EDGE)
302 TopExp::Vertices(TopoDS::Edge(aPrjProfile), aV1, aV2);
303 else if(aPrjProfile.ShapeType() == TopAbs_WIRE)
304 TopExp::Vertices(TopoDS::Wire(aPrjProfile), aV1, aV2);
305 else if(aPrjProfile.ShapeType() == TopAbs_COMPOUND){
306 TopExp_Explorer anExp(aPrjProfile, TopAbs_WIRE);
308 TopExp::Vertices(TopoDS::Wire(anExp.Current()), aV1, aV2);
310 anExp.Init(aPrjProfile, TopAbs_EDGE);
312 TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV1, aV2);
316 if(aV1.IsNull() || aV2.IsNull())
318 gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1);
319 gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2);
322 BRepBuilderAPI_MakeEdge aMk(aPnt1, aPnt2);
325 const TopoDS_Edge& anEdg2 = aMk.Edge();//Section edge
326 Standard_Integer aNum(0);
328 TopExp_Explorer anExplo(aHydraulicWire, TopAbs_EDGE);
329 for(;anExplo.More();anExplo.Next()) aNum++;
330 // check for self-intersection
331 const Standard_Real SquareTolerance = Precision::Confusion()*Precision::Confusion();
332 Standard_Boolean hasInt(false);
333 Standard_Real aSqDist(DBL_MAX);
334 Standard_Integer anIndx(0);
335 BRepExtrema_ExtCC aCC;
336 aCC.Initialize(anEdg2);
338 anExplo.Init(aHydraulicWire, TopAbs_EDGE);
339 for(Standard_Integer j=1;anExplo.More();anExplo.Next(),j++) {
340 const TopoDS_Edge& anEdg1 = TopoDS::Edge(anExplo.Current());
343 Standard_Boolean hasSol(false);
347 for(Standard_Integer i=1; i<= aCC.NbExt();i++)
348 if(aCC.SquareDistance(i) < aSqDist) {
349 aSqDist = aCC.SquareDistance(i);
355 if(aSqDist <= SquareTolerance) { // hasInt
356 const gp_Pnt& aPnt = aCC.PointOnE1(anIndx);
358 TopExp::Vertices(anEdg1, aV1, aV2, Standard_True);
359 outPar += BRep_Tool::Pnt(aV1).Distance(aPnt);
361 Standard_Real aPar = aCC.ParameterOnE1(anIndx);
369 TopExp::Vertices(anEdg1, aV1, aV2);
370 outPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
373 } else if(aNum > 1) {
374 TopExp::Vertices(anEdg1, aV1, aV2);
375 outPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
384 bool HYDROData_Stream::AddProfile( const Handle(HYDROData_Profile)& theProfile )
386 if ( theProfile.IsNull() )
389 Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
390 if ( aHydAxis.IsNull() )
394 if(!BuildFace(aHydAxis, aPlane))
397 Standard_Real aPar(.0);
398 if ( HasReference( theProfile, DataTag_Profile ) || !HasIntersection( theProfile, aPlane, aPar ) )
399 return false; // Object is already in reference list or it has no intersection
401 int aProfileIndex = insertParameter( aPar );
402 insertProfileInToOrder( theProfile, aProfileIndex );
404 // Indicate model of the need to update the stream presentation
410 HYDROData_SequenceOfObjects HYDROData_Stream::GetProfiles() const
412 return GetReferenceObjects( DataTag_Profile );
415 bool HYDROData_Stream::RemoveProfile( const Handle(HYDROData_Profile)& theProfile )
417 if ( theProfile.IsNull() )
420 int aProfileIndex = -1;
422 HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
423 HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
424 for ( int i = 0 ; anIter.More(); anIter.Next(), ++i )
426 Handle(HYDROData_Profile) aProfile =
427 Handle(HYDROData_Profile)::DownCast( anIter.Value() );
428 if ( aProfile.IsNull() )
431 if ( IsEqual( theProfile, aProfile ) )
438 if ( aProfileIndex == -1 )
441 RemoveReferenceObject( theProfile->Label(), DataTag_Profile );
443 // Remove parameter for removed profile
444 removeParameter( aProfileIndex );
446 // Indicate model of the need to update the stream presentation
452 void HYDROData_Stream::RemoveProfiles()
454 bool anIsToUpdate = IsMustBeUpdated() || NbReferenceObjects( DataTag_Profile ) > 0;
456 ClearReferenceObjects( DataTag_Profile );
458 // Remove the parameters array
459 removeParametersArray();
461 // Indicate model of the need to update the stream presentation
462 SetToUpdate( anIsToUpdate );
465 void HYDROData_Stream::insertProfileInToOrder( const Handle(HYDROData_Profile)& theProfile,
466 const int theBeforeIndex )
468 Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
469 if ( theProfile.IsNull() || aHydAxis.IsNull() )
472 TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
473 TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
474 if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
477 if ( theBeforeIndex == -1 )
478 AddReferenceObject( theProfile, DataTag_Profile );
480 InsertReferenceObject( theProfile, DataTag_Profile, theBeforeIndex );
483 bool HYDROData_Stream::BuildFace( const Handle(HYDROData_PolylineXY)& theHydAxis, TopoDS_Face& thePlane) const
485 if ( theHydAxis.IsNull() ) return false;
486 TopoDS_Wire aHydraulicWire = TopoDS::Wire( theHydAxis->GetShape() );
487 if(aHydraulicWire.IsNull()) return false;
488 gp_Ax2 aX2(gp::XOY());
492 BRepBndLib::Add(aHydraulicWire,B);
493 Standard_Real axmin,aymin,azmin,axmax,aymax,azmax;
494 B.Get(axmin,aymin,azmin,axmax,aymax,azmax);
495 BRepBuilderAPI_MakeFace aMkr(aPln, axmin-500., axmax+500., aymin-500., aymax+500.); // to be tuned later according max/ Profile deviation
496 if(!aMkr.IsDone() || aMkr.Shape().IsNull()) return false;
497 thePlane = TopoDS::Face(aMkr.Shape());
501 void HYDROData_Stream::updateProfilesOrder()
503 HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
504 if ( aRefProfiles.IsEmpty() )
507 // At first we remove all profiles from order
510 Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
511 if ( aHydAxis.IsNull() )
515 if ( !BuildFace( aHydAxis, aPlane ) )
518 Standard_Real aPar( .0 );
522 TopoDS_Compound aCmp;
523 aBB.MakeCompound(aCmp);
526 HYDROData_DataMapOfRealOfHDProfile aDM;
527 TColStd_ListOfReal aList;
528 HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
529 for (int i = 1 ; anIter.More(); anIter.Next(), i++ )
531 Handle(HYDROData_Profile) aProfile =
532 Handle(HYDROData_Profile)::DownCast( anIter.Value() );
534 TopoDS_Wire aProfileWire = TopoDS::Wire( aProfile->GetTopShape() );
535 aBB.Add( aCmp, aProfileWire );
537 if ( aProfile.IsNull() || !HasIntersection( aProfile, aPlane, aPar ) )
540 aDM.Bind( aPar, aProfile );
541 aList.Append( aPar );
544 if ( aList.IsEmpty() )
547 TColStd_Array1OfReal anArr( 1, aList.Extent() );
549 TColStd_ListIteratorOfListOfReal it( aList );
550 for ( int j = 1; it.More(); it.Next(), j++ )
551 anArr( j ) = it.Value();
554 if ( aList.Extent() > 1 )
556 TCollection_CompareOfReal Compar;
557 SortTools_QuickSortOfReal::Sort( anArr, Compar );
559 for (int j = 1; j <= anArr.Length(); j++) {
560 const Standard_Real aKey = anArr(j);
561 const Handle(HYDROData_Profile)& aProfile = aDM.Find(aKey);
562 insertProfileInToOrder( aProfile );
564 } else if ( aList.Extent() == 1 ) {
565 const Standard_Real aKey = aList.Last();
566 const Handle(HYDROData_Profile)& aProfile = aDM.Find(aKey);
567 insertProfileInToOrder( aProfile );
570 setParametersArray( anArr );
573 TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
574 BRepTools::Write(aHydraulicWire, "Path.brep");
575 BRepTools::Write(aCmp, "Prof.brep");
579 void HYDROData_Stream::setParametersArray( const TColStd_Array1OfReal& theArray )
581 if ( theArray.Length() == 0 )
583 removeParametersArray();
587 TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray );
589 Handle(TDataStd_RealArray) aParamsArray =
590 TDataStd_RealArray::Set( aLabel, theArray.Lower(), theArray.Upper() );
592 for ( int i = theArray.Lower(), n = theArray.Upper(); i <= n; ++i )
594 const Standard_Real& aParam = theArray( i );
595 aParamsArray->SetValue( i, aParam );
599 TColStd_Array1OfReal* HYDROData_Stream::getParametersArray() const
601 TColStd_Array1OfReal* anArray = NULL;
603 TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
604 if ( !aLabel.IsNull() )
606 Handle(TDataStd_RealArray) aParamsArray;
607 if ( aLabel.FindAttribute( TDataStd_RealArray::GetID(), aParamsArray ) )
609 anArray = new TColStd_Array1OfReal( aParamsArray->Lower(), aParamsArray->Upper() );
610 for ( int i = aParamsArray->Lower(), n = aParamsArray->Upper(); i <= n; ++i )
612 const Standard_Real& aParam = aParamsArray->Value( i );
613 anArray->SetValue( i, aParam );
621 void HYDROData_Stream::removeParametersArray()
623 TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
624 if ( !aLabel.IsNull() )
625 aLabel.ForgetAllAttributes();
628 int HYDROData_Stream::insertParameter( const Standard_Real& theParam )
632 TColStd_Array1OfReal* anArr = getParametersArray();
637 TColStd_Array1OfReal aNewArr( anArr->Lower(), anArr->Upper() + 1 );
639 bool isInserted = false;
640 for ( int i = anArr->Lower(), j = i, n = anArr->Upper(); i <= n; ++i, ++j )
642 const Standard_Real& aStoredParam = anArr->Value( i );
645 if ( theParam > aStoredParam )
651 aNewArr( j ) = theParam;
657 aNewArr( j ) = aStoredParam;
663 aNewArr( aNewArr.Upper() ) = theParam;
666 setParametersArray( aNewArr );
671 TColStd_Array1OfReal aNewArr( 1, 1 );
672 aNewArr.SetValue( 1, theParam );
673 setParametersArray( aNewArr );
679 void HYDROData_Stream::removeParameter( const int& theIndex )
681 TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
682 if ( aLabel.IsNull() )
685 Handle(TDataStd_RealArray) aParamsArray;
686 if ( !aLabel.FindAttribute( TDataStd_RealArray::GetID(), aParamsArray ) )
689 TColStd_Array1OfReal aNewArr( aParamsArray->Lower(), aParamsArray->Upper() - 1 );
691 for ( int i = aParamsArray->Lower(), j = i, k = 0, n = aParamsArray->Upper(); i <= n; ++i, ++k )
693 const Standard_Real& aStoredParam = aParamsArray->Value( i );
697 aNewArr.SetValue( j, aStoredParam );
701 setParametersArray( aNewArr );