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 //#define DEB_HASINT 1
47 #include <BRepTools.hxx>
48 #include <TCollection_AsciiString.hxx>
49 #include <BRep_Builder.hxx>
52 #define PYTHON_STREAM_ID "KIND_STREAM"
54 IMPLEMENT_STANDARD_HANDLE(HYDROData_Stream,HYDROData_NaturalObject)
55 IMPLEMENT_STANDARD_RTTIEXT(HYDROData_Stream,HYDROData_NaturalObject)
58 HYDROData_Stream::HYDROData_Stream()
59 : HYDROData_NaturalObject()
63 HYDROData_Stream::~HYDROData_Stream()
67 QStringList HYDROData_Stream::DumpToPython( MapOfTreatedObjects& theTreatedObjects ) const
71 Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
72 if ( aDocument.IsNull() )
75 QString aDocName = aDocument->GetDocPyName();
76 QString aStreamName = GetName();
78 aResList << QString( "%1 = %2.CreateObject( %3 );" )
79 .arg( aStreamName ).arg( aDocName ).arg( PYTHON_STREAM_ID );
80 aResList << QString( "%1.SetName( \"%2\" );" )
81 .arg( aStreamName ).arg( aStreamName );
82 aResList << QString( "" );
89 HYDROData_SequenceOfObjects HYDROData_Stream::GetAllReferenceObjects() const
91 HYDROData_SequenceOfObjects aResSeq = HYDROData_Object::GetAllReferenceObjects();
93 Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
94 if ( !aHydAxis.IsNull() )
95 aResSeq.Append( aHydAxis );
97 HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
98 aResSeq.Append( aSeqOfProfiles );
103 TopoDS_Shape HYDROData_Stream::GetTopShape() const
105 return getTopShape();
108 TopoDS_Shape HYDROData_Stream::GetShape3D() const
113 void HYDROData_Stream::Update()
115 HYDROData_NaturalObject::Update();
117 Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
118 HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
119 if ( aHydAxis.IsNull() || aRefProfiles.IsEmpty() )
122 TopoDS_Shell a2dShell;
123 BRep_Builder a2dShellBuilder;
124 a2dShellBuilder.MakeShell( a2dShell );
126 bool anIsFirst = true;
127 gp_Pnt aPrevFirstPoint, aPrevLastPoint;
129 // Construct the top presentation
130 HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
131 for ( ; anIter.More(); anIter.Next() )
133 Handle(HYDROData_Profile) aProfile =
134 Handle(HYDROData_Profile)::DownCast( anIter.Value() );
135 if ( aProfile.IsNull() )
139 if ( !aProfile->GetFirstPoint( aPnt1 ) || !aProfile->GetLastPoint( aPnt2 ) )
142 gp_Pnt aCurFirstPoint( aPnt1.X(), aPnt1.Y(), 0 );
143 gp_Pnt aCurLastPoint( aPnt2.X(), aPnt2.Y(), 0 );
147 aPrevFirstPoint = aCurFirstPoint;
148 aPrevLastPoint = aCurLastPoint;
153 BRepBuilderAPI_MakeEdge aFirstEdge( aPrevFirstPoint, aPrevLastPoint );
154 BRepBuilderAPI_MakeEdge aSecondEdge( aPrevLastPoint, aCurLastPoint );
155 BRepBuilderAPI_MakeEdge aThirdEdge( aCurLastPoint, aCurFirstPoint );
156 BRepBuilderAPI_MakeEdge aFourthEdge( aCurFirstPoint, aPrevFirstPoint );
158 BRepBuilderAPI_MakeWire aMakeWire( aFirstEdge.Edge(), aSecondEdge.Edge(),
159 aThirdEdge.Edge(), aFourthEdge.Edge() );
161 TopoDS_Wire aSectProfileWire = aMakeWire.Wire();
163 BRepBuilderAPI_MakeFace aMakeFace( aSectProfileWire, Standard_True );
165 if( aMakeFace.IsDone() )
167 a2dShellBuilder.Add( a2dShell, aMakeFace.Face() );
170 aPrevFirstPoint = aCurFirstPoint;
171 aPrevLastPoint = aCurLastPoint;
174 SetTopShape( a2dShell );
176 // Construct the 3D presentation
180 bool HYDROData_Stream::SetHydraulicAxis( const Handle(HYDROData_PolylineXY)& theAxis )
182 Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
184 if ( theAxis.IsNull() )
186 RemoveHydraulicAxis();
187 return !aPrevAxis.IsNull();
190 if ( IsEqual( aPrevAxis, theAxis ) )
193 TopoDS_Wire aHydraulicWire = TopoDS::Wire( theAxis->GetShape() );
194 if ( aHydraulicWire.IsNull() )
195 return false; // The polyline must be a single wire
197 SetReferenceObject( theAxis, DataTag_HydraulicAxis );
199 // Update the order of profiles
200 updateProfilesOrder();
202 // Indicate model of the need to update the stream presentation
208 Handle(HYDROData_PolylineXY) HYDROData_Stream::GetHydraulicAxis() const
210 return Handle(HYDROData_PolylineXY)::DownCast(
211 GetReferenceObject( DataTag_HydraulicAxis ) );
214 void HYDROData_Stream::RemoveHydraulicAxis()
216 Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
217 if ( aPrevAxis.IsNull() )
220 ClearReferenceObjects( DataTag_HydraulicAxis );
222 // We remove the reference profiles
225 // Indicate model of the need to update the stream presentation
229 bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_Profile)& theProfile, const TopoDS_Face& thePlane,
230 Standard_Real& outPar ) const
232 Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
233 if ( theProfile.IsNull() || aHydAxis.IsNull() )
236 TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() ); //guide line
237 TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
238 if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
241 BRepProj_Projection aProjector (aProfileWire, thePlane, gp::OZ().Direction());
242 if(!aProjector.IsDone())
244 TopoDS_Shape aPrjProfile = aProjector.Shape();
245 if(aPrjProfile.IsNull())
247 TopoDS_Vertex aV1, aV2;
248 if(aPrjProfile.ShapeType() == TopAbs_EDGE)
249 TopExp::Vertices(TopoDS::Edge(aPrjProfile), aV1, aV2);
250 else if(aPrjProfile.ShapeType() == TopAbs_WIRE)
251 TopExp::Vertices(TopoDS::Wire(aPrjProfile), aV1, aV2);
252 else if(aPrjProfile.ShapeType() == TopAbs_COMPOUND){
253 TopExp_Explorer anExp(aPrjProfile, TopAbs_WIRE);
255 TopExp::Vertices(TopoDS::Wire(anExp.Current()), aV1, aV2);
257 anExp.Init(aPrjProfile, TopAbs_EDGE);
259 TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV1, aV2);
263 if(aV1.IsNull() || aV2.IsNull())
265 gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1);
266 gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2);
269 BRepBuilderAPI_MakeEdge aMk(aPnt1, aPnt2);
272 const TopoDS_Edge& anEdg2 = aMk.Edge();//Section edge
273 Standard_Integer aNum(0);
275 TopExp_Explorer anExplo(aHydraulicWire, TopAbs_EDGE);
276 for(;anExplo.More();anExplo.Next()) aNum++;
277 // check for self-intersection
278 const Standard_Real SquareTolerance = Precision::Confusion()*Precision::Confusion();
279 Standard_Boolean hasInt(false);
280 Standard_Real aSqDist(DBL_MAX);
281 Standard_Integer anIndx(0);
282 BRepExtrema_ExtCC aCC;
283 aCC.Initialize(anEdg2);
285 anExplo.Init(aHydraulicWire, TopAbs_EDGE);
286 for(Standard_Integer j=1;anExplo.More();anExplo.Next(),j++) {
287 const TopoDS_Edge& anEdg1 = TopoDS::Edge(anExplo.Current());
290 Standard_Boolean hasSol(false);
294 for(Standard_Integer i=1; i<= aCC.NbExt();i++)
295 if(aCC.SquareDistance(i) < aSqDist) {
296 aSqDist = aCC.SquareDistance(i);
302 if(aSqDist <= SquareTolerance) { // hasInt
303 const gp_Pnt& aPnt = aCC.PointOnE1(anIndx);
305 TopExp::Vertices(anEdg1, aV1, aV2, Standard_True);
306 outPar += BRep_Tool::Pnt(aV1).Distance(aPnt);
308 Standard_Real aPar = aCC.ParameterOnE1(anIndx);
316 TopExp::Vertices(anEdg1, aV1, aV2);
317 outPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
320 } else if(aNum > 1) {
321 TopExp::Vertices(anEdg1, aV1, aV2);
322 outPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
331 bool HYDROData_Stream::AddProfile( const Handle(HYDROData_Profile)& theProfile )
333 if ( theProfile.IsNull() )
336 Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
337 if ( aHydAxis.IsNull() )
341 if(!BuildFace(aHydAxis, aPlane))
344 Standard_Real aPar(.0);
345 if ( HasReference( theProfile, DataTag_Profile ) || !HasIntersection( theProfile, aPlane, aPar ) )
346 return false; // Object is already in reference list or it has no intersection
348 int aProfileIndex = insertParameter( aPar );
349 insertProfileInToOrder( theProfile, aProfileIndex );
351 // Indicate model of the need to update the stream presentation
357 HYDROData_SequenceOfObjects HYDROData_Stream::GetProfiles() const
359 return GetReferenceObjects( DataTag_Profile );
362 bool HYDROData_Stream::RemoveProfile( const Handle(HYDROData_Profile)& theProfile )
364 if ( theProfile.IsNull() )
367 int aProfileIndex = -1;
369 HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
370 HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
371 for ( int i = 0 ; anIter.More(); anIter.Next(), ++i )
373 Handle(HYDROData_Profile) aProfile =
374 Handle(HYDROData_Profile)::DownCast( anIter.Value() );
375 if ( aProfile.IsNull() )
378 if ( IsEqual( theProfile, aProfile ) )
385 if ( aProfileIndex == -1 )
388 RemoveReferenceObject( theProfile->Label(), DataTag_Profile );
390 // Remove parameter for removed profile
391 removeParameter( aProfileIndex );
393 // Indicate model of the need to update the stream presentation
399 void HYDROData_Stream::RemoveProfiles()
401 bool anIsToUpdate = IsMustBeUpdated() || NbReferenceObjects( DataTag_Profile ) > 0;
403 ClearReferenceObjects( DataTag_Profile );
405 // Remove the parameters array
406 removeParametersArray();
408 // Indicate model of the need to update the stream presentation
409 SetToUpdate( anIsToUpdate );
412 void HYDROData_Stream::insertProfileInToOrder( const Handle(HYDROData_Profile)& theProfile,
413 const int theBeforeIndex )
415 Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
416 if ( theProfile.IsNull() || aHydAxis.IsNull() )
419 TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
420 TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
421 if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
424 if ( theBeforeIndex == -1 )
425 AddReferenceObject( theProfile, DataTag_Profile );
427 InsertReferenceObject( theProfile, DataTag_Profile, theBeforeIndex );
430 bool HYDROData_Stream::BuildFace( const Handle(HYDROData_PolylineXY)& theHydAxis, TopoDS_Face& thePlane) const
432 if ( theHydAxis.IsNull() ) return false;
433 TopoDS_Wire aHydraulicWire = TopoDS::Wire( theHydAxis->GetShape() );
434 if(aHydraulicWire.IsNull()) return false;
435 gp_Ax2 aX2(gp::XOY());
439 BRepBndLib::Add(aHydraulicWire,B);
440 Standard_Real axmin,aymin,azmin,axmax,aymax,azmax;
441 B.Get(axmin,aymin,azmin,axmax,aymax,azmax);
442 BRepBuilderAPI_MakeFace aMkr(aPln, axmin-500., axmax+500., aymin-500., aymax+500.); // to be tuned later according max/ Profile deviation
443 if(!aMkr.IsDone() || aMkr.Shape().IsNull()) return false;
444 thePlane = TopoDS::Face(aMkr.Shape());
448 void HYDROData_Stream::updateProfilesOrder()
450 HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
451 if ( aRefProfiles.IsEmpty() )
454 // At first we remove all profiles from order
457 Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
458 if ( aHydAxis.IsNull() )
462 if ( !BuildFace( aHydAxis, aPlane ) )
465 Standard_Real aPar( .0 );
469 TopoDS_Compound aCmp;
470 aBB.MakeCompound(aCmp);
473 HYDROData_DataMapOfRealOfHDProfile aDM;
474 TColStd_ListOfReal aList;
475 HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
476 for (int i = 1 ; anIter.More(); anIter.Next(), i++ )
478 Handle(HYDROData_Profile) aProfile =
479 Handle(HYDROData_Profile)::DownCast( anIter.Value() );
481 TopoDS_Wire aProfileWire = TopoDS::Wire( aProfile->GetTopShape() );
482 aBB.Add( aCmp, aProfileWire );
484 if ( aProfile.IsNull() || !HasIntersection( aProfile, aPlane, aPar ) )
487 aDM.Bind( aPar, aProfile );
488 aList.Append( aPar );
491 if ( aList.IsEmpty() )
494 TColStd_Array1OfReal anArr( 1, aList.Extent() );
496 TColStd_ListIteratorOfListOfReal it( aList );
497 for ( int j = 1; it.More(); it.Next(), j++ )
498 anArr( j ) = it.Value();
501 if ( aList.Extent() > 1 )
503 TCollection_CompareOfReal Compar;
504 SortTools_QuickSortOfReal::Sort( anArr, Compar );
506 for (int j = 1; j <= anArr.Length(); j++) {
507 const Standard_Real aKey = anArr(j);
508 const Handle(HYDROData_Profile)& aProfile = aDM.Find(aKey);
509 insertProfileInToOrder( aProfile );
511 } else if ( aList.Extent() == 1 ) {
512 const Standard_Real aKey = aList.Last();
513 const Handle(HYDROData_Profile)& aProfile = aDM.Find(aKey);
514 insertProfileInToOrder( aProfile );
517 setParametersArray( anArr );
520 TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
521 BRepTools::Write(aHydraulicWire, "Path.brep");
522 BRepTools::Write(aCmp, "Prof.brep");
526 void HYDROData_Stream::setParametersArray( const TColStd_Array1OfReal& theArray )
528 if ( theArray.Length() == 0 )
530 removeParametersArray();
534 TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray );
536 Handle(TDataStd_RealArray) aParamsArray =
537 TDataStd_RealArray::Set( aLabel, theArray.Lower(), theArray.Upper() );
539 for ( int i = theArray.Lower(), n = theArray.Upper(); i <= n; ++i )
541 const Standard_Real& aParam = theArray( i );
542 aParamsArray->SetValue( i, aParam );
546 TColStd_Array1OfReal* HYDROData_Stream::getParametersArray() const
548 TColStd_Array1OfReal* anArray = NULL;
550 TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
551 if ( !aLabel.IsNull() )
553 Handle(TDataStd_RealArray) aParamsArray;
554 if ( aLabel.FindAttribute( TDataStd_RealArray::GetID(), aParamsArray ) )
556 anArray = new TColStd_Array1OfReal( aParamsArray->Lower(), aParamsArray->Upper() );
557 for ( int i = aParamsArray->Lower(), n = aParamsArray->Upper(); i <= n; ++i )
559 const Standard_Real& aParam = aParamsArray->Value( i );
560 anArray->SetValue( i, aParam );
568 void HYDROData_Stream::removeParametersArray()
570 TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
571 if ( !aLabel.IsNull() )
572 aLabel.ForgetAllAttributes();
575 int HYDROData_Stream::insertParameter( const Standard_Real& theParam )
579 TColStd_Array1OfReal* anArr = getParametersArray();
584 TColStd_Array1OfReal aNewArr( anArr->Lower(), anArr->Upper() + 1 );
586 bool isInserted = false;
587 for ( int i = anArr->Lower(), j = i, n = anArr->Upper(); i <= n; ++i, ++j )
589 const Standard_Real& aStoredParam = anArr->Value( i );
592 if ( theParam > aStoredParam )
598 aNewArr( j ) = theParam;
604 aNewArr( j ) = aStoredParam;
610 aNewArr( aNewArr.Upper() ) = theParam;
613 setParametersArray( aNewArr );
618 TColStd_Array1OfReal aNewArr( 1, 1 );
619 aNewArr.SetValue( 1, theParam );
620 setParametersArray( aNewArr );
626 void HYDROData_Stream::removeParameter( const int& theIndex )
628 TDF_Label aLabel = myLab.FindChild( DataTag_ParamsArray, false );
629 if ( aLabel.IsNull() )
632 Handle(TDataStd_RealArray) aParamsArray;
633 if ( !aLabel.FindAttribute( TDataStd_RealArray::GetID(), aParamsArray ) )
636 TColStd_Array1OfReal aNewArr( aParamsArray->Lower(), aParamsArray->Upper() - 1 );
638 for ( int i = aParamsArray->Lower(), j = i, k = 0, n = aParamsArray->Upper(); i <= n; ++i, ++k )
640 const Standard_Real& aStoredParam = aParamsArray->Value( i );
644 aNewArr.SetValue( j, aStoredParam );
648 setParametersArray( aNewArr );