Salome HOME
Merge from V6_main_20120808 08Aug12
[modules/geom.git] / src / OCC2VTK / GEOM_EdgeSource.cxx
diff --git a/src/OCC2VTK/GEOM_EdgeSource.cxx b/src/OCC2VTK/GEOM_EdgeSource.cxx
new file mode 100755 (executable)
index 0000000..d7d3a41
--- /dev/null
@@ -0,0 +1,275 @@
+// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "GEOM_EdgeSource.h" 
+#include <vtkObjectFactory.h> 
+
+#include <vtkPoints.h> 
+#include <vtkCellArray.h> 
+
+#include <BRep_Tool.hxx>
+#include <Poly_Polygon3D.hxx>
+#include <Poly_Triangulation.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+#include <Poly_PolygonOnTriangulation.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <GCPnts_AbscissaPoint.hxx>
+#include <vtkStripper.h>  
+#include <vtkPolyData.h>  
+
+vtkStandardNewMacro(GEOM_EdgeSource);
+GEOM_EdgeSource::GEOM_EdgeSource() :
+  myIsVector(false)
+{ 
+} 
+GEOM_EdgeSource::~GEOM_EdgeSource() 
+{ 
+} 
+
+void GEOM_EdgeSource::AddEdge (const TopoDS_Edge& theEdge,
+                               bool theIsVector)
+{
+  myEdgeSet.Add(theEdge);
+  myIsVector = theIsVector;
+}
+
+void
+GEOM_EdgeSource:: 
+Execute()
+{
+  vtkPolyData* aPolyData = GetOutput();
+  aPolyData->Allocate();
+  vtkPoints* aPts = vtkPoints::New();
+  aPolyData->SetPoints(aPts);
+  aPts->Delete();
+
+  TEdgeSet::Iterator anIter (myEdgeSet);
+  for (; anIter.More(); anIter.Next()) {
+    TopoDS_Edge anEdge = anIter.Value();
+    if ( !myIsVector )
+      // draw curve direction (issue 0021087)
+      anEdge.Orientation( TopAbs_FORWARD );
+    OCC2VTK(anEdge,aPolyData,aPts,myIsVector||myIsVectorMode);
+  }
+}
+
+void GEOM_EdgeSource::OCC2VTK (const TopoDS_Edge& theEdge,  
+                               vtkPolyData* thePolyData, 
+                               vtkPoints* thePts,
+                               bool theIsVector) 
+{
+  Handle(Poly_PolygonOnTriangulation) aEdgePoly;
+  Standard_Integer i = 1;
+  Handle(Poly_Triangulation) T;
+  TopLoc_Location aEdgeLoc;
+  BRep_Tool::PolygonOnTriangulation(theEdge, aEdgePoly, T, aEdgeLoc, i);
+
+  Handle(Poly_Polygon3D) P;
+  if(aEdgePoly.IsNull())
+    P = BRep_Tool::Polygon3D(theEdge, aEdgeLoc);
+
+  if(P.IsNull() && aEdgePoly.IsNull())
+    return;
+  
+  // Location edges
+  //---------------
+  gp_Trsf edgeTransf;
+  Standard_Boolean isidtrsf = true;
+  if(!aEdgeLoc.IsIdentity())  {
+    isidtrsf = false;
+    edgeTransf = aEdgeLoc.Transformation();
+  }
+
+  gp_Pnt aP1, aP2;
+
+  if (aEdgePoly.IsNull()) {
+    Standard_Integer aNbNodes = P->NbNodes();
+    const TColgp_Array1OfPnt& aNodesP = P->Nodes();
+
+    aP1 = aNodesP(1);
+    aP2 = aNodesP(aNbNodes);
+
+    for (int j = 1; j < aNbNodes; j++) {
+      gp_Pnt pt1 = aNodesP(j);
+      gp_Pnt pt2 = aNodesP(j+1);
+
+      if (!isidtrsf) {
+        // apply edge transformation
+        pt1.Transform(edgeTransf);
+        pt2.Transform(edgeTransf);
+      }
+
+      float aCoord1[3] = {pt1.X(), pt1.Y(), pt1.Z()};
+      vtkIdType anIds[2];
+      anIds[0] = thePts->InsertNextPoint(aCoord1);
+
+      float aCoord2[3] = {pt2.X(), pt2.Y(), pt2.Z()};
+      anIds[1] = thePts->InsertNextPoint(aCoord2);
+
+      thePolyData->InsertNextCell(VTK_LINE,2,anIds);
+    }
+  } else {
+    Standard_Integer aNbNodes = aEdgePoly->NbNodes();
+    const TColStd_Array1OfInteger& aNodeIds = aEdgePoly->Nodes();
+    const TColgp_Array1OfPnt& anId2Pnts = T->Nodes();
+
+    aP1 = anId2Pnts(aNodeIds(1));
+    aP2 = anId2Pnts(aNodeIds(aNbNodes));
+
+    for(int j = 1; j < aNbNodes; j++) {
+      Standard_Integer id1 = aNodeIds(j);
+      Standard_Integer id2 = aNodeIds(j+1);
+      
+      gp_Pnt pt1 = anId2Pnts(id1);
+      gp_Pnt pt2 = anId2Pnts(id2);
+          
+      if(!isidtrsf) {
+        // apply edge transformation
+        pt1.Transform(edgeTransf);
+        pt2.Transform(edgeTransf);
+      }
+      
+      float aCoord1[3] = {pt1.X(), pt1.Y(), pt1.Z()};
+      vtkIdType anIds[2];
+      anIds[0] = thePts->InsertNextPoint(aCoord1);
+
+      float aCoord2[3] = {pt2.X(), pt2.Y(), pt2.Z()};
+      anIds[1] = thePts->InsertNextPoint(aCoord2);
+
+      thePolyData->InsertNextCell(VTK_LINE,2,anIds);
+    }
+  }
+
+  
+  // vector representation has an arrow on its end
+  if (theIsVector)
+  {
+    if (!isidtrsf) {
+      // apply edge transformation
+      aP1.Transform(edgeTransf);
+      aP2.Transform(edgeTransf);
+    }
+
+    // draw an arrow
+
+    double fp,lp;
+    gp_Vec aDirVec;
+    Handle(Geom_Curve) C = BRep_Tool::Curve(theEdge,fp,lp);
+    if ( theEdge.Orientation() == TopAbs_FORWARD ) {
+      C->D1(lp, aP2, aDirVec);
+    } else {
+      C->D1(fp, aP1, aDirVec);
+      aP2 = aP1;
+    }
+
+    GeomAdaptor_Curve aAdC;
+    aAdC.Load(C, fp, lp);
+    Standard_Real aDist = GCPnts_AbscissaPoint::Length(aAdC, fp, lp); 
+    if (aDist < gp::Resolution()) return;
+
+    gp_Dir aDirection;
+
+    if ( theEdge.Orientation() == TopAbs_FORWARD )
+      aDirection = aDirVec;
+    else
+      aDirection = -aDirVec;
+
+    Standard_Real anAngle = M_PI/180.*5.;
+    Standard_Real aLength = aDist/10.;
+
+    Standard_Real dx,dy,dz;
+    aDirection.Coord(dx,dy,dz);
+
+    // Arrow Point
+    Standard_Real xo,yo,zo;
+    aP2.Coord(xo,yo,zo);
+
+    // Center of circle that arrow based
+    gp_XYZ aPc = aP2.XYZ() - aDirection.XYZ() * aLength;
+
+    // Construction of the base vectors for the arrow circle
+    gp_Dir aDirN;
+    if      (Abs(dx) <= Abs(dy) && Abs(dx) <= Abs(dz)) aDirN = gp::DX();
+    else if (Abs(dy) <= Abs(dz) && Abs(dy) <= Abs(dx)) aDirN = gp::DY();
+    else aDirN = gp::DZ();
+
+    gp_Dir aDirI = aDirection ^ aDirN;
+    gp_Dir aDirJ = aDirection ^ aDirI;
+
+    // Add points and segments, composing the arrow
+    Standard_Real cosinus, sinus, Tg = tan(anAngle);
+
+    float coord[3] = {xo, yo, zo};
+
+    vtkIdType ptLoc = thePts->InsertNextPoint(coord);
+    vtkIdType ptFirst = 0;
+    vtkIdType ptPrev = 0;
+    vtkIdType ptCur = 0;
+
+    vtkIdType pts[2];
+
+    int NbPoints = 15;
+    for (int i = 1; i <= NbPoints; i++, ptPrev = ptCur)
+    {
+      cosinus = cos(2. * M_PI / NbPoints * (i-1));   
+      sinus   = sin(2. * M_PI / NbPoints * (i-1));
+
+      gp_XYZ aP = aPc + (aDirI.XYZ() * cosinus + aDirJ.XYZ() * sinus) * aLength * Tg;
+      coord[0] = aP.X();
+      coord[1] = aP.Y();
+      coord[2] = aP.Z();
+
+      // insert pts
+      ptCur = thePts->InsertNextPoint(coord);
+      pts[0] = ptCur;
+
+      if (i == 1) {
+        ptFirst = ptCur;
+      }
+      else {
+        // insert line (ptCur,ptPrev)
+        pts[1] = ptPrev;
+        thePolyData->InsertNextCell(VTK_LINE,2,pts);
+      }
+
+      // insert line (ptCur,ptLoc)
+      pts[1] = ptLoc;
+      thePolyData->InsertNextCell(VTK_LINE,2,pts);
+    }
+
+    // insert line (ptCur,ptFirst)
+    pts[0] = ptCur;
+    pts[1] = ptFirst;
+    thePolyData->InsertNextCell(VTK_LINE,2,pts);
+  }
+}
+
+void GEOM_EdgeSource::SetVectorMode (bool theMode)
+{
+  myIsVectorMode = theMode;
+}
+
+bool GEOM_EdgeSource::GetVectorMode ()
+{
+  return !myIsVector && myIsVectorMode;
+}