Salome HOME
patch for correct compilation on Linux
[modules/hydro.git] / src / HYDROData / HYDROData_Stream.cxx
index 985f62713e91cc8afecd219e26cd1af2aaad2f1a..061fa93576bcd5a669ab101be61c92a85c3c9886 100644 (file)
@@ -2,9 +2,32 @@
 #include "HYDROData_Stream.h"
 
 #include "HYDROData_Document.h"
+#include "HYDROData_PolylineXY.h"
+#include "HYDROData_Profile.h"
 
-#include <TopoDS_Shape.hxx>
+#include <BRep_Builder.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <BRepBuilderAPI_MakeWire.hxx>
+#include <BRepBuilderAPI_MakeFace.hxx>
 
+#include <TopoDS.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopoDS_Shell.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <BRepProj_Projection.hxx>
+#include <BRepExtrema_ExtCC.hxx>
+#include <gp_Ax1.hxx>
+#include <gp_Ax2.hxx>
+#include <gp_Ax3.hxx>
+#include <gp_Vec.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Pln.hxx>
+#include <gp.hxx>
+#include <Precision.hxx>
 #include <QStringList>
 
 #define PYTHON_STREAM_ID "KIND_STREAM"
@@ -26,7 +49,7 @@ QStringList HYDROData_Stream::DumpToPython( MapOfTreatedObjects& theTreatedObjec
 {
   QStringList aResList;
 
-  Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( this );
+  Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myLab );
   if ( aDocument.IsNull() )
     return aResList;
 
@@ -44,17 +67,335 @@ QStringList HYDROData_Stream::DumpToPython( MapOfTreatedObjects& theTreatedObjec
   return aResList;
 }
 
+HYDROData_SequenceOfObjects HYDROData_Stream::GetAllReferenceObjects() const
+{
+  HYDROData_SequenceOfObjects aResSeq = HYDROData_Object::GetAllReferenceObjects();
+
+  Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
+  if ( !aHydAxis.IsNull() )
+    aResSeq.Append( aHydAxis );
+
+  HYDROData_SequenceOfObjects aSeqOfProfiles = GetProfiles();
+  aResSeq.Append( aSeqOfProfiles );
+
+  return aResSeq;
+}
+
 TopoDS_Shape HYDROData_Stream::GetTopShape() const
 {
-  // TODO
   return getTopShape();
 }
 
 TopoDS_Shape HYDROData_Stream::GetShape3D() const
 {
-  // TODO
   return getShape3D();
 }
 
+void HYDROData_Stream::Update()
+{
+  HYDROData_NaturalObject::Update();
+
+  Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
+  HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
+  if ( aHydAxis.IsNull() || aRefProfiles.IsEmpty() )
+    return; 
+
+  TopoDS_Shell a2dShell;
+  BRep_Builder a2dShellBuilder;
+  a2dShellBuilder.MakeShell( a2dShell );
+
+  bool anIsFirst = true;
+  gp_Pnt aPrevFirstPoint, aPrevLastPoint;
+  
+  // Construct the top presentation
+  HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
+  for ( ; anIter.More(); anIter.Next() )
+  {
+    Handle(HYDROData_Profile) aProfile =
+      Handle(HYDROData_Profile)::DownCast( anIter.Value() );
+    if ( aProfile.IsNull() )
+      continue;
+
+    gp_XY aPnt1, aPnt2;
+    if ( !aProfile->GetFirstPoint( aPnt1 ) || !aProfile->GetLastPoint( aPnt2 ) )
+      continue;
+    
+    gp_Pnt aCurFirstPoint( aPnt1.X(), aPnt1.Y(), 0 );
+    gp_Pnt aCurLastPoint(  aPnt2.X(), aPnt2.Y(), 0 );
+
+    if ( anIsFirst )
+    {
+      aPrevFirstPoint = aCurFirstPoint;
+      aPrevLastPoint = aCurLastPoint;
+      anIsFirst = false;
+      continue;
+    }
+
+    BRepBuilderAPI_MakeEdge aFirstEdge( aPrevFirstPoint, aPrevLastPoint );
+    BRepBuilderAPI_MakeEdge aSecondEdge( aPrevLastPoint, aCurLastPoint );
+    BRepBuilderAPI_MakeEdge aThirdEdge( aCurLastPoint, aCurFirstPoint );
+    BRepBuilderAPI_MakeEdge aFourthEdge( aCurFirstPoint, aPrevFirstPoint );
+
+    BRepBuilderAPI_MakeWire aMakeWire( aFirstEdge.Edge(), aSecondEdge.Edge(), 
+                                       aThirdEdge.Edge(), aFourthEdge.Edge() );
+    
+    TopoDS_Wire aSectProfileWire = aMakeWire.Wire();
+    
+    BRepBuilderAPI_MakeFace aMakeFace( aSectProfileWire, Standard_True );
+    aMakeFace.Build();
+    if( aMakeFace.IsDone() )
+    {
+      a2dShellBuilder.Add( a2dShell, aMakeFace.Face() );
+    }
+
+    aPrevFirstPoint = aCurFirstPoint;
+    aPrevLastPoint = aCurLastPoint;
+  }
+
+  SetTopShape( a2dShell );
+
+  // Construct the 3D presentation
+  /// TODO
+}
+
+bool HYDROData_Stream::SetHydraulicAxis( const Handle(HYDROData_PolylineXY)& theAxis )
+{
+  Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
+
+  if ( theAxis.IsNull() )
+  {
+    RemoveHydraulicAxis();
+    return !aPrevAxis.IsNull();
+  }
+
+  if ( IsEqual( aPrevAxis, theAxis ) )
+    return false;
 
+  TopoDS_Wire aHydraulicWire = TopoDS::Wire( theAxis->GetShape() );
+  if ( aHydraulicWire.IsNull() )
+    return false; // The polyline must be a single wire
+
+  SetReferenceObject( theAxis, DataTag_HydraulicAxis );
+
+  // Update the order of profiles
+  updateProfilesOrder();
+
+  // Indicate model of the need to update the stream presentation
+  SetToUpdate( true );
+
+  return true;
+}
+
+Handle(HYDROData_PolylineXY) HYDROData_Stream::GetHydraulicAxis() const
+{
+  return Handle(HYDROData_PolylineXY)::DownCast( 
+           GetReferenceObject( DataTag_HydraulicAxis ) );
+}
+
+void HYDROData_Stream::RemoveHydraulicAxis()
+{
+  Handle(HYDROData_PolylineXY) aPrevAxis = GetHydraulicAxis();
+  if ( aPrevAxis.IsNull() )
+    return;
+
+  ClearReferenceObjects( DataTag_HydraulicAxis );
+
+  // We remove the reference profiles
+  RemoveProfiles();
+
+  // Indicate model of the need to update the stream presentation
+  SetToUpdate( true );
+}
+
+bool HYDROData_Stream::HasIntersection( const Handle(HYDROData_Profile)& theProfile, const TopoDS_Face& thePlane,
+                                                                          Standard_Real& outPar ) const
+{
+  Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
+  if ( theProfile.IsNull() || aHydAxis.IsNull() )
+    return false; 
+
+  TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() ); //guide line
+  TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
+  if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
+    return false;
+
+  // TODO
+  return true; // temporary
+  BRepProj_Projection aProjector (aProfileWire, thePlane, gp::OZ().Direction());
+  if(!aProjector.IsDone())
+    return false;
+  TopoDS_Shape aPrjProfile = aProjector.Shape();
+  if(aPrjProfile.IsNull())
+    return false;
+  TopoDS_Vertex aV1, aV2;
+  if(aPrjProfile.ShapeType() == TopAbs_EDGE)
+         TopExp::Vertices(TopoDS::Edge(aPrjProfile), aV1, aV2);          
+  else if(aPrjProfile.ShapeType() == TopAbs_WIRE)  
+         TopExp::Vertices(TopoDS::Wire(aPrjProfile), aV1, aV2);          
+  else if(aPrjProfile.ShapeType() == TopAbs_COMPOUND){
+    TopExp_Explorer anExp(aPrjProfile, TopAbs_WIRE);
+       if(anExp.More()) {
+               TopExp::Vertices(TopoDS::Wire(anExp.Current()), aV1, aV2);        
+       } else {
+         anExp.Init(aPrjProfile, TopAbs_EDGE);
+         if(anExp.More()) {
+               TopExp::Vertices(TopoDS::Edge(anExp.Current()), aV1, aV2);        
+         }
+       }
+  }
+  if(aV1.IsNull() || aV2.IsNull())
+       return false;
+  gp_Pnt aPnt1 = BRep_Tool::Pnt(aV1);
+  gp_Pnt aPnt2 = BRep_Tool::Pnt(aV2);
+  aPnt1.SetZ(0.0);
+  aPnt2.SetZ(0.0);
+  BRepBuilderAPI_MakeEdge aMk(aPnt1, aPnt2); 
+  if(!aMk.IsDone())
+    return false;
+  const TopoDS_Edge& anEdg2 = aMk.Edge();//Section edge
+  Standard_Integer aNum(0);
+  
+  TopExp_Explorer anExplo(aHydraulicWire, TopAbs_EDGE);
+  for(;anExplo.More();anExplo.Next()) aNum++;
+  // check for self-intersection
+  const Standard_Real SquareTolerance = Precision::Confusion()*Precision::Confusion();
+  Standard_Boolean hasInt(false);
+  Standard_Real aSqDist(DBL_MAX);
+  Standard_Integer anIndx(0);
+  BRepExtrema_ExtCC aCC;
+  aCC.Initialize(anEdg2);
+  outPar = 0.0;
+  anExplo.Init(aHydraulicWire, TopAbs_EDGE);
+  for(Standard_Integer j=1;anExplo.More();anExplo.Next(),j++) {
+       const TopoDS_Edge& anEdg1 = TopoDS::Edge(anExplo.Current());
+       if(anEdg1.IsNull())
+         continue;     
+       aCC.Perform(anEdg1);
+    if(aCC.IsDone()) {
+    for(Standard_Integer i=1; i<= aCC.NbExt();i++)
+      if(aCC.SquareDistance(i) < aSqDist) {
+        aSqDist = aCC.SquareDistance(i);
+        anIndx = i;
+               hasInt = true;          
+         }  
+       }
+       if(hasInt) {    
+      if(aSqDist <= SquareTolerance) {
+        const gp_Pnt& aPnt = aCC.PointOnE1(anIndx);
+        if(aNum > 1) {
+          TopExp::Vertices(anEdg1, aV1, aV2, Standard_True);
+                 outPar += BRep_Tool::Pnt(aV1).Distance(aPnt);
+           } else {
+          Standard_Real aPar = aCC.ParameterOnE1(anIndx);
+                 outPar = aPar;
+           }
+           break;
+         } else {
+        if(aNum > 1) {
+          TopExp::Vertices(anEdg1, aV1, aV2);
+             outPar += BRep_Tool::Pnt(aV1).Distance(BRep_Tool::Pnt(aV2));
+           }
+         }
+       }
+  }
+  return true;
+}
+
+bool HYDROData_Stream::AddProfile( const Handle(HYDROData_Profile)& theProfile )
+{
+  if ( theProfile.IsNull() )
+    return false; 
+  gp_Ax2 aX2(gp::XOY());
+  gp_Ax3 aX3(aX2);
+  gp_Pln aPln(aX3);
+  BRepBuilderAPI_MakeFace aMkr(aPln);
+  if(!aMkr.IsDone())
+       return false;
+  const TopoDS_Face& aPlane = TopoDS::Face(aMkr.Shape());
+  Standard_Real aPar(.0);
+  if ( HasReference( theProfile, DataTag_Profile ) || !HasIntersection( theProfile, aPlane, aPar ) )
+    return false; // Object is already in reference list or it has no intersection
+
+  insertProfileInToOrder( theProfile );
+  
+  // Indicate model of the need to update the stream presentation
+  SetToUpdate( true );
+
+  return true;
+}
+
+HYDROData_SequenceOfObjects HYDROData_Stream::GetProfiles() const
+{
+  return GetReferenceObjects( DataTag_Profile );
+}
+
+bool HYDROData_Stream::RemoveProfile( const Handle(HYDROData_Profile)& theProfile )
+{
+  if ( theProfile.IsNull() || !HasReference( theProfile, DataTag_Profile ) )
+    return false;
+
+  RemoveReferenceObject( theProfile->Label(), DataTag_Profile );
+
+  // Indicate model of the need to update the stream presentation
+  SetToUpdate( true );
+
+  return true;
+}
+
+void HYDROData_Stream::RemoveProfiles()
+{
+  bool anIsToUpdate = IsMustBeUpdated() || NbReferenceObjects( DataTag_Profile ) > 0;
+
+  ClearReferenceObjects( DataTag_Profile );
+
+  // Indicate model of the need to update the stream presentation
+  SetToUpdate( anIsToUpdate );
+}
+
+void HYDROData_Stream::insertProfileInToOrder( const Handle(HYDROData_Profile)& theProfile )
+{
+  Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
+  if ( theProfile.IsNull() || aHydAxis.IsNull() )
+    return; 
+
+  TopoDS_Wire aHydraulicWire = TopoDS::Wire( aHydAxis->GetShape() );
+  TopoDS_Wire aProfileWire = TopoDS::Wire( theProfile->GetTopShape() );
+  if ( aHydraulicWire.IsNull() || aProfileWire.IsNull() )
+    return;
+
+  // TODO
+  AddReferenceObject( theProfile, DataTag_Profile ); // temporary for testing only
+}
+
+void HYDROData_Stream::updateProfilesOrder()
+{
+  HYDROData_SequenceOfObjects aRefProfiles = GetProfiles();
+  if ( aRefProfiles.IsEmpty() )
+    return;
+
+  // At first we remove all profiles from order
+  RemoveProfiles();
+
+  Handle(HYDROData_PolylineXY) aHydAxis = GetHydraulicAxis();
+  if ( aHydAxis.IsNull() )
+    return;
+  gp_Ax2 aX2(gp::XOY());
+  gp_Ax3 aX3(aX2);
+  gp_Pln aPln(aX3);
+  BRepBuilderAPI_MakeFace aMkr(aPln);
+  if(!aMkr.IsDone())
+       return;
+  const TopoDS_Face& aPlane = TopoDS::Face(aMkr.Shape());
+  Standard_Real aPar(.0);
+  HYDROData_SequenceOfObjects::Iterator anIter( aRefProfiles );
+  for ( ; anIter.More(); anIter.Next() )
+  {
+    Handle(HYDROData_Profile) aProfile =
+      Handle(HYDROData_Profile)::DownCast( anIter.Value() );
+    if ( aProfile.IsNull() || !HasIntersection( aProfile, aPlane, aPar ) )
+      continue;
+
+    insertProfileInToOrder( aProfile );
+  }
+}