Salome HOME
Merge branch 'V8_0_BR' V8_0_0a2 V8_0_0b1
authorvsr <vsr@opencascade.com>
Thu, 14 Jan 2016 15:03:04 +0000 (18:03 +0300)
committervsr <vsr@opencascade.com>
Thu, 14 Jan 2016 15:17:45 +0000 (18:17 +0300)
17 files changed:
CMakeLists.txt
src/CMakeLists.txt
src/GEOM/GEOM_Engine.cxx
src/GEOMGUI/GEOM_msg_en.ts
src/GEOMGUI/GEOM_msg_fr.ts
src/GEOMImpl/GEOMImpl_IShapesOperations.cxx
src/GEOMImpl/GEOMImpl_PipeDriver.cxx
src/GroupGUI/GroupGUI_GroupDlg.cxx
src/MeasureGUI/MeasureGUI_ShapeStatisticsDlg.cxx
src/Tools/CMakeLists.txt [new file with mode: 0644]
src/Tools/geom_plugins.py [new file with mode: 0644]
src/Tools/t_shape/CMakeLists.txt [new file with mode: 0644]
src/Tools/t_shape/__init__.py [new file with mode: 0644]
src/Tools/t_shape/t_shape_builder.py [new file with mode: 0644]
src/Tools/t_shape/t_shape_dialog.py [new file with mode: 0644]
src/Tools/t_shape/t_shape_dialog.ui [new file with mode: 0644]
src/Tools/t_shape/t_shape_progress.py [new file with mode: 0644]

index 66d01b35628a55ea7aa4b3c8f302f2a27df8dfac..cd26147d5542ed6bed68ce8fb1e2e8528046075a 100755 (executable)
@@ -124,11 +124,16 @@ ENDIF(SALOME_BUILD_GUI)
 ##
 
 IF(SALOME_BUILD_GUI)
-  # Qt
   IF(NOT SALOME_GUI_BUILD_WITH_QT5)
+    # Qt
     FIND_PACKAGE(SalomeQt4 REQUIRED COMPONENTS QtCore QtGui QtXml QtWebKit QtOpenGL QtNetwork)
+    # PyQt
+    FIND_PACKAGE(SalomePyQt4 REQUIRED)
   ELSE()
+    # Qt
     FIND_PACKAGE(SalomeQt5 REQUIRED)
+    # PyQt
+    FIND_PACKAGE(SalomePyQt5 REQUIRED)
   ENDIF()
 ENDIF(SALOME_BUILD_GUI)
 
index bd7e3428d56bc9104b3e6753b39a5c45c0fc9345..13d33e44460c7c33dd6e25c655cdcc58f0951d85 100755 (executable)
@@ -24,7 +24,7 @@ SET(SUBDIRS_COMMON
   ARCHIMEDE BlockFix GEOMAlgo SKETCHER GEOM ShHealOper GEOMUtils XAO XAO_Swig 
   GEOMImpl GEOM_I GEOMClient GEOM_I_Superv GEOM_SWIG GEOM_PY
   AdvancedEngine OCC2VTK
-  STLPlugin BREPPlugin STEPPlugin IGESPlugin XAOPlugin VTKPlugin
+  STLPlugin BREPPlugin STEPPlugin IGESPlugin XAOPlugin VTKPlugin Tools
   )
 
 ##
index 0859c2850d5ca9c563a5f4b8f1d09ce1df681857..e7921bed45520072b77f5adaec1feb7d13c833ca 100644 (file)
@@ -88,6 +88,7 @@ static int MYDEBUG = 0;
 typedef std::map< TCollection_AsciiString, TCollection_AsciiString > TSting2StringMap;
 typedef std::map< TCollection_AsciiString, TObjectData >             TSting2ObjDataMap;
 typedef std::map< TCollection_AsciiString, TObjectData* >            TSting2ObjDataPtrMap;
+typedef std::map< int, std::list < int > >                           TIntToListIntMap;
 
 static GEOM_Engine* TheEngine = NULL;
 
@@ -123,6 +124,11 @@ bool ProcessFunction(Handle(GEOM_Function)&             theFunction,
                      std::set<TCollection_AsciiString>& theIgnoreObjs,
                      bool&                              theIsDumpCollected);
 
+static int GetTag(const TCollection_AsciiString &theEntry);
+
+static void FillMapOfRef(const Handle(GEOM_Function) &theFunction,
+                               TIntToListIntMap      &theRefMap);
+
 void ReplaceVariables(TCollection_AsciiString& theCommand,
                       const TVariablesList&    theVariables);
 
@@ -148,6 +154,12 @@ void PublishObject (TObjectData&                              theObjectData,
                     std::map< int, TCollection_AsciiString >& theEntryToCmdMap,
                     std::set<TCollection_AsciiString>&        theMapOfPublished);
 
+static TCollection_AsciiString GetPublishCommands
+                   (const int                                       theTag,
+                    const std::map< int, TCollection_AsciiString > &theEntryToCmdMap,
+                    const TIntToListIntMap                         &theMapRefs,
+                          std::set< int >                          &thePublished);
+
 //================================================================================
 /*!
  * \brief Fix up the name of python variable
@@ -674,6 +686,7 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
   // Mantis issue 0020768
   Standard_Integer objectCounter = 0;
   Resource_DataMapOfAsciiStringAsciiString aNameToEntry;
+  TIntToListIntMap                         aRefMap;
 
   if (aDoc->Main().FindAttribute(GEOM_Function::GetFunctionTreeID(), aRoot)) {
     TDataStd_ChildNodeIterator Itr(aRoot);
@@ -702,6 +715,10 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
             continue; // aCurScript is already at the end of aFuncScript
         aFuncScript += aCurScript;
       }
+
+      // Fill the map of references.
+      FillMapOfRef(aFunction, aRefMap);
+
       if (isDumpCollected ) {
         // Replace entries by the names
         ReplaceEntriesByNames( aFuncScript, aEntry2ObjData, isPublished,
@@ -717,9 +734,16 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
                          aNameToEntry, anEntryToCmdMap, anIgnoreObjMap );
         }
         // add publishing commands to the script
+        std::set< int >                                    aPublished;
         std::map< int, TCollection_AsciiString >::iterator anEntryToCmd = anEntryToCmdMap.begin();
-        for ( ; anEntryToCmd != anEntryToCmdMap.end(); ++anEntryToCmd )
-          aFuncScript += anEntryToCmd->second;
+
+        for ( ; anEntryToCmd != anEntryToCmdMap.end(); ++anEntryToCmd ) {
+          const TCollection_AsciiString aPublishCmds =
+              GetPublishCommands(anEntryToCmd->first, anEntryToCmdMap,
+                                 aRefMap, aPublished);
+
+          aFuncScript += aPublishCmds;
+        }
 
         // PTv, 0020001 add result objects from RestoreGivenSubShapes into ignore list,
         //  because they will be published during command execution
@@ -772,9 +796,16 @@ TCollection_AsciiString GEOM_Engine::DumpPython(int theDocID,
                      aNameToEntry, anEntryToCmdMap, anIgnoreObjMap );
     }
     // add publishing commands to the script
+    std::set< int >                                    aPublished;
     std::map< int, TCollection_AsciiString >::iterator anEntryToCmd = anEntryToCmdMap.begin();
-    for ( ; anEntryToCmd != anEntryToCmdMap.end(); ++anEntryToCmd )
-      aScript += anEntryToCmd->second;
+
+    for ( ; anEntryToCmd != anEntryToCmdMap.end(); ++anEntryToCmd ) {
+      const TCollection_AsciiString aPublishCmds =
+          GetPublishCommands(anEntryToCmd->first, anEntryToCmdMap,
+                             aRefMap, aPublished);
+
+      aScript += aPublishCmds;
+    }
   }
 
   //RNV: issue 16219: EDF PAL 469: "RemoveFromStudy" Function
@@ -1197,6 +1228,64 @@ bool ProcessFunction(Handle(GEOM_Function)&             theFunction,
   return true;
 }
 
+//=============================================================================
+/*!
+ *  GetTag: Returns the tag from entry
+ */
+//=============================================================================
+int GetTag(const TCollection_AsciiString &theEntry)
+{
+  const int aGeomObjDepth = 3;
+  const int aTag          = theEntry.Token(":", aGeomObjDepth).IntegerValue();
+
+  return aTag;
+}
+
+//=============================================================================
+/*!
+ *  FillMapOfRef: Fill the map of references
+ */
+//=============================================================================
+void FillMapOfRef(const Handle(GEOM_Function) &theFunction,
+                        TIntToListIntMap      &theRefMap)
+{
+  TDF_LabelSequence       aSeq;
+  TCollection_AsciiString anObjEntry;
+  int                     anObjTag;
+
+  TDF_Tool::Entry(theFunction->GetOwnerEntry(), anObjEntry);
+  anObjTag = GetTag(anObjEntry);
+  theFunction->GetDependency(aSeq);
+
+  const Standard_Integer aLen = aSeq.Length();
+  Standard_Integer       i;
+
+  for (i = 1; i <= aLen; i++) {
+    TDF_Label             aRefLabel = aSeq.Value(i);
+    Handle(TDF_Reference) aRef;
+
+    if (aRefLabel.FindAttribute(TDF_Reference::GetID(), aRef)) {
+      if (!aRef.IsNull() && !aRef->Get().IsNull()) {
+        Handle(TDataStd_TreeNode) aT;
+
+        if (TDataStd_TreeNode::Find(aRef->Get(), aT)) {
+          TDF_Label             aDepLabel = aT->Label();
+          Handle(GEOM_Function) aRefFunct = GEOM_Function::GetFunction(aDepLabel);
+
+          if (!aRefFunct.IsNull()) {
+            // Get entry of the referenced object.
+            TDF_Tool::Entry(aRefFunct->GetOwnerEntry(), anObjEntry);
+
+            const int aRefTag = GetTag(anObjEntry);
+
+            theRefMap[anObjTag].push_back(aRefTag);
+          }
+        }
+      }
+    }
+  }
+}
+
 //=============================================================================
 /*!
  *  FindEntries: Returns a sequence of start/end positions of entries in the string
@@ -1726,8 +1815,6 @@ void PublishObject (TObjectData&                              theObjectData,
   if ( stEntry2DataPtr != theStEntry2ObjDataPtr.end() )
     aFatherData = stEntry2DataPtr->second;
 
-  const int geomObjDepth = 3;
-
   // treat multiply published object
   if ( theObjectData._pyName.IsEmpty() )
   {
@@ -1741,7 +1828,7 @@ void PublishObject (TObjectData&                              theObjectData,
     aCreationCommand += theObjectData._pyName + " = " + data0._pyName;
 
     // store aCreationCommand before publishing commands
-    int tag = theObjectData._entry.Token( ":", geomObjDepth ).IntegerValue();
+    int tag = GetTag(theObjectData._entry);
     theEntryToCmdMap.insert( std::make_pair( tag + 2*theEntry2ObjData.size(), aCreationCommand ));
   }
 
@@ -1756,12 +1843,57 @@ void PublishObject (TObjectData&                              theObjectData,
   aCommand += theObjectData._pyName + ", '" + theObjectData._name + "' )";
 
   // bind a command to the study entry
-  int tag = theObjectData._entry.Token( ":", geomObjDepth ).IntegerValue();
+  int tag = GetTag(theObjectData._entry);
   theEntryToCmdMap.insert( std::make_pair( tag, aCommand ));
 
   theObjectData._studyEntry.Clear(); // not to publish any more
 }
 
+//================================================================================
+/*!
+ * \brief Returns the string of publishing commands. Take into account that
+ *  references should be published prior to the objects refer to them.
+ */
+//================================================================================
+TCollection_AsciiString GetPublishCommands
+                   (const int                                       theTag,
+                    const std::map< int, TCollection_AsciiString > &theEntryToCmdMap,
+                    const TIntToListIntMap                         &theMapRefs,
+                          std::set< int >                          &thePublished)
+{
+  TCollection_AsciiString aResult;
+
+  if (!thePublished.count(theTag)) {
+    // This object is not published yet.
+    std::map< int, TCollection_AsciiString >::const_iterator anIt =
+      theEntryToCmdMap.find(theTag);
+
+    if (anIt != theEntryToCmdMap.end()) {
+      // There is a pubish cmd.
+      TIntToListIntMap::const_iterator aRefIt = theMapRefs.find(theTag);
+
+      if (aRefIt != theMapRefs.end()) {
+        // Recursively publish all references.
+        std::list< int >::const_iterator aRefTagIt = aRefIt->second.begin();
+  
+        for(; aRefTagIt != aRefIt->second.end(); ++aRefTagIt) {
+          const TCollection_AsciiString aRefCmd = GetPublishCommands
+            (*aRefTagIt, theEntryToCmdMap, theMapRefs, thePublished);
+
+          aResult += aRefCmd;
+        }
+      }
+
+      // Add the object command.
+      aResult += anIt->second;
+    }
+
+    thePublished.insert(theTag);
+  }
+
+  return aResult;
+}
+
 //================================================================================
 /*!
  * \brief Constructor
index 2f225edbdfc22452eeecfecae315cd2c05525567..5a094f30350e99d841b479aa8bd979c7027a9e99 100644 (file)
@@ -5350,7 +5350,7 @@ shells and solids on the other hand.</translation>
     </message>
     <message>
         <source>GEOM_PLUGINS_OTHER</source>
-        <translation>Other</translation>
+        <translation>Python Plugins</translation>
     </message>
     <message>
         <source>SHOW_ONLY_SELECTED</source>
index 1a1231364e262448b3064b9240238cbe36347ea7..01acd20ca6eab1a8ae9b5a00f7a97c0e5efe2a39 100644 (file)
@@ -5342,7 +5342,7 @@ le paramètre &apos;%1&apos; aux préférences du module Géométrie.</translati
     </message>
     <message>
         <source>GEOM_PLUGINS_OTHER</source>
-        <translation>Autre</translation>
+        <translation>Plugins Python</translation>
     </message>
     <message>
         <source>SHOW_ONLY_SELECTED</source>
index 3ed4513ecd8181068f80fe7d1710f8d0a9fd8d12..65716670c9e393839fade61a8d9ac9b74a4c3655 100644 (file)
@@ -74,6 +74,7 @@
 #include <Geom_Plane.hxx>
 #include <Geom_SphericalSurface.hxx>
 #include <Geom_Surface.hxx>
+#include <Geom_TrimmedCurve.hxx>
 #include <Precision.hxx>
 #include <TColStd_HArray1OfInteger.hxx>
 #include <TDF_Tool.hxx>
@@ -4636,6 +4637,8 @@ static bool isSameEdge(const TopoDS_Edge& theEdge1, const TopoDS_Edge& theEdge2)
   U = U11+range*2.0/3.0;
   gp_Pnt P2 = C1->Value(U);     //Compute a point on two thirds of the edge's length
 
+  C2 = new Geom_TrimmedCurve(C2, U21, U22);
+
   if(!GeomLib_Tool::Parameter(C2, P1, MAX_TOLERANCE, U) ||  U < U21 || U > U22)
     return false;
 
index cf660675f21080d4e5eaccf0a7fc0fdb6505ee33..ef5b07e7943a51d232e5e7aa9ed7e7a13bcdebf7 100644 (file)
 #define GROUP_SIDE2 3
 #define GROUP_OTHER 4
 
+static const Standard_Real TolPipeSurf = 5.e-4;
+
 static bool FillGroups(const TopTools_SequenceOfShape         *theGroups,
                        const TopTools_IndexedMapOfShape       &theIndices,
                              Handle(TColStd_HArray1OfInteger) *theGroupIds);
@@ -182,7 +184,8 @@ static Standard_Boolean BuildPipeShell(BRepOffsetAPI_MakePipeShell &theBuilder)
 
   Standard_Boolean isDone = theBuilder.IsDone();
 
-  if (!isDone) {
+  if (!isDone ||
+      theBuilder.ErrorOnSurface() > TolPipeSurf) {
     // Try to use Descrete Trihedron mode.
     theBuilder.SetDiscreteMode();
     theBuilder.Build();
@@ -3124,7 +3127,7 @@ Standard_Integer GEOMImpl_PipeDriver::Execute (TFunction_Logbook& log) const
       GeomFill_Trihedron theBestMode = EvaluateBestSweepMode(aWirePath);
       BRepOffsetAPI_MakePipe aMkPipe(aWirePath, aShapeBase, theBestMode);
 
-      if (aMkPipe.IsDone()) {
+      if (aMkPipe.IsDone() && aMkPipe.ErrorOnSurface() <= TolPipeSurf) {
         aShape = aMkPipe.Shape();
 
         if (!CreateGroups(aShapeBase, aWirePath, aMkPipe, aCI)) {
index 52a6cbe7851562b250f21082f74bebfecd5a0c59..c856096150462d128e40d21b502073a69a356c01 100644 (file)
@@ -881,6 +881,12 @@ int GroupGUI_GroupDlg::getSelectedSubshapes (TColStd_IndexedMapOfInteger& theMap
         TopoDS_Shape aShape;
         if (GEOMBase::GetShape(aGeomObj, aShape)) {
           if (aGeomObj->GetType() == GEOM_GROUP || aShape.ShapeType() == getShapeType()) {
+            if (subSelectionWay() != ALL_SUBSHAPES &&
+                GEOMBase::GetName(aGeomObj) == myShape2Name->text()) {
+              // Skip selected in place object.
+              continue;
+            }
+
             TopTools_IndexedMapOfShape aMainMap;
             TopoDS_Shape aMainShape = GEOM_Client::get_client().GetShape(GeometryGUI::GetGeomGen(), myMainObj);
             TopExp::MapShapes(aMainShape, aMainMap);
index 9387cf4a873273d1aead1510eed7e378b6611c5e..681c0bab5e453c872988efd93d0866768aa9c297 100644 (file)
@@ -311,9 +311,9 @@ void MeasureGUI_ShapeStatisticsDlg::updateTypes( QList<GEOM::GeomObjPtr> theShap
     if ( hasEdges != 0 )
       hasEdges = aShOp->NumberOfSubShapes( aShapePtr.get(), TopAbs_EDGE ) > 0;
     if ( hasFaces != 0 )
-      hasEdges = aShOp->NumberOfSubShapes( aShapePtr.get(), TopAbs_FACE ) > 0;
+      hasFaces = aShOp->NumberOfSubShapes( aShapePtr.get(), TopAbs_FACE ) > 0;
     if ( hasSolids != 0 )
-      hasEdges = aShOp->NumberOfSubShapes( aShapePtr.get(), TopAbs_SOLID ) > 0;
+      hasSolids = aShOp->NumberOfSubShapes( aShapePtr.get(), TopAbs_SOLID ) > 0;
   }
   fillTypes( hasEdges, hasFaces, hasSolids );
 }
diff --git a/src/Tools/CMakeLists.txt b/src/Tools/CMakeLists.txt
new file mode 100644 (file)
index 0000000..57f854f
--- /dev/null
@@ -0,0 +1,31 @@
+# Copyright (C) 2012-2014  EDF R&D
+#
+# 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, or (at your option) any later version.
+#
+# 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
+#
+
+ADD_SUBDIRECTORY(t_shape)
+
+
+IF(SALOME_BUILD_GUI)
+    # scripts / static
+    SET(plugin_SCRIPTS
+       geom_plugins.py
+    )
+
+    # --- rules ---
+    SALOME_INSTALL_SCRIPTS("${plugin_SCRIPTS}" ${SALOME_GEOM_INSTALL_PLUGINS})
+ENDIF()
diff --git a/src/Tools/geom_plugins.py b/src/Tools/geom_plugins.py
new file mode 100644 (file)
index 0000000..3959615
--- /dev/null
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010-2014  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, or (at your option) any later version.
+#
+# 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
+#
+# Author : Renaud Nédélec (OpenCascade S.A.S)
+
+import salome_pluginsmanager
+
+def t_shape_fluid(context):
+    #from salome.geom.t_shape import t_shape_builder
+    from salome.geom.t_shape import t_shape_dialog
+    from salome.geom.t_shape import t_shape_progress
+    import xalome
+    from PyQt4.QtGui import QMessageBox
+    activeStudy = context.study
+    
+    dialog = t_shape_dialog.TShapeDialog()
+
+    # Get the parameter values from a gui dialog box. If the dialog is
+    # closed using the Ok button, then the data are requested from the
+    # gui and used to create the shape of the tube.
+    dialog.exec_()
+    if dialog.wasOk():
+      r1, r2, h1, h2, thickness = dialog.getData()
+      #QMessageBox.about(None, "Building in progress", "building shape, please be patient")
+      #shape = t_shape_builder.build_shape(activeStudy, r1, r2, h1, h2, thickness)
+      shapeBuilder = t_shape_progress.t_shape_progress()
+      shape = shapeBuilder.run(activeStudy, r1, r2, h1, h2, thickness)
+      entry = xalome.addToStudy(activeStudy, shape, "T_shape_fluid" )
+      xalome.displayShape(entry)
+    #if dialog.wasOk():
+        #radius, length, width = dialog.getData()
+        #shape = tubebuilder.createGeometry(activeStudy, radius, length, width)
+        #entry = xalome.addToStudy(activeStudy, shape, "Tube" )
+        #xalome.displayShape(entry)
+
+
+salome_pluginsmanager.AddFunction('T shape fluid',
+                                  'Creates the fluid part of a pipe T-shape',
+                                  t_shape_fluid)
\ No newline at end of file
diff --git a/src/Tools/t_shape/CMakeLists.txt b/src/Tools/t_shape/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e4332a5
--- /dev/null
@@ -0,0 +1,55 @@
+# Copyright (C) 2012-2014  EDF R&D
+#
+# 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, or (at your option) any later version.
+#
+# 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
+#
+IF(SALOME_BUILD_GUI)
+  INCLUDE(UsePyQt)
+ENDIF()
+
+# --- scripts ---
+
+# base scripts
+SET(base_SCRIPTS
+  __init__.py
+  t_shape_builder.py
+  )
+
+IF(SALOME_BUILD_GUI)
+   # gui scripts 
+   SET(gui_SCRIPTS
+     t_shape_dialog.py
+     t_shape_dialog.ui
+     t_shape_progress.py
+     )
+
+  # uic files / to be processed by pyuic
+  SET(_pyuic_files
+    t_shape_dialog.ui
+    )
+
+  # scripts / pyuic wrappings
+  PYQT_WRAP_UIC(_pyuic_SCRIPTS ${_pyuic_files})
+ENDIF()
+
+# --- rules ---
+
+SALOME_INSTALL_SCRIPTS("${base_SCRIPTS}" ${SALOME_INSTALL_PYTHON}/salome/geom/t_shape)
+
+IF(SALOME_BUILD_GUI)
+  SALOME_INSTALL_SCRIPTS("${gui_SCRIPTS}" ${SALOME_INSTALL_PYTHON}/salome/geom/t_shape)
+  SALOME_INSTALL_SCRIPTS("${_pyuic_SCRIPTS}" ${SALOME_INSTALL_PYTHON}/salome/geom/t_shape)
+ENDIF()
\ No newline at end of file
diff --git a/src/Tools/t_shape/__init__.py b/src/Tools/t_shape/__init__.py
new file mode 100644 (file)
index 0000000..40a96af
--- /dev/null
@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-
diff --git a/src/Tools/t_shape/t_shape_builder.py b/src/Tools/t_shape/t_shape_builder.py
new file mode 100644 (file)
index 0000000..72ab22b
--- /dev/null
@@ -0,0 +1,390 @@
+# -*- coding: utf-8 -*-
+
+import sys
+import salome
+
+import GEOM
+from salome.geom import geomBuilder
+import math
+import SALOMEDS
+import time
+
+geompy = None
+
+def demidisk(study, r1, a1, roty=0, solid_thickness=0):
+  if solid_thickness < 1e-7:
+    with_solid = False
+  else:
+    with_solid = True
+
+  #geompy = geomBuilder.New(study)
+  
+  O = geompy.MakeVertex(0, 0, 0)
+  OX = geompy.MakeVectorDXDYDZ(1, 0, 0) 
+  OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
+  OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
+  
+  v=range(8)
+  l=range(8)
+  v0 = geompy.MakeVertex(0, 0, 0)
+  v[0] = geompy.MakeVertex(0, r1/2.0, 0)
+  v[1] = geompy.MakeVertex(0, r1, 0)
+  l[1] = geompy.MakeLineTwoPnt(v[0], v[1])
+  l[2] = geompy.MakeRotation(l[1], OX, a1*math.pi/180.0)
+  v[4] = geompy.MakeRotation(v[0], OX, a1*math.pi/180.0)
+  v[6] = geompy.MakeRotation(v[1], OX, a1*math.pi/180.0)
+
+  v[2] = geompy.MakeVertex(0, -r1/2.0, 0)
+  v[3] = geompy.MakeVertex(0, -r1, 0)
+  l[3] = geompy.MakeLineTwoPnt(v[2], v[3])
+  l[4] = geompy.MakeRotation(l[3], OX, -a1*math.pi/180.0)
+  v[5] = geompy.MakeRotation(v[2], OX, -a1*math.pi/180.0)
+  v[7] = geompy.MakeRotation(v[3], OX, -a1*math.pi/180.0)
+
+  l[5] = geompy.MakeLineTwoPnt(v[4], v[5])
+  l[6] = geompy.MakeLineTwoPnt(v[0], v[4])
+  l[7] = geompy.MakeLineTwoPnt(v[2], v[5])
+
+  v7 = geompy.MakeVertex(0, 0, r1)
+  arc1 = geompy.MakeArc(v[1], v7, v[3])
+  l[0] = geompy.MakeLineTwoPnt(v[1], v[3])
+  face1 = geompy.MakeFaceWires([arc1, l[0]], 1)
+  part1 = geompy.MakePartition([face1], [l[2], l[4], l[5], l[6], l[7]], [], [], geompy.ShapeType["FACE"], 0, [], 0, True)
+  
+  if with_solid:
+    # Add some faces corresponding to the solid layer outside
+    # the fluid part
+    
+    # --- Vertices
+    v0 = geompy.MakeVertex(0, r1 + solid_thickness, 0)
+    v1 = geompy.MakeRotation(v0, OX, a1*math.pi/180.0)
+    v2 = geompy.MakeRotation(v0, OX, math.pi - (a1*math.pi/180.0))
+    v3 = geompy.MakeRotation(v0, OX, math.pi)
+    v.extend([v0,v1,v3,v2]) # The order is important for use in pointsProjetes
+    # --- Lines
+    l0 = geompy.MakeLineTwoPnt(v[1], v0)
+    l2 = geompy.MakeRotation(l0, OX, a1*math.pi/180.0)
+    l3 = geompy.MakeRotation(l0, OX, math.pi - (a1*math.pi/180.0))
+    # --- Faces
+    face2 = geompy.MakeRevolution(l0, OX, a1*math.pi/180.0)
+    face3 = geompy.MakeRevolution(l2, OX, math.pi - 2*a1*math.pi/180.0)
+    face4 = geompy.MakeRevolution(l3, OX, a1*math.pi/180.0)
+    # --- Compound of the "fluid part" of the divided disk and the additional faces
+    compound1 = geompy.MakeCompound([part1, face2, face3, face4])
+    # --- Glue edges
+    part1 = geompy.MakeGlueEdges(compound1,1e-7)
+  if roty != 0:
+    vrot = [ geompy.MakeRotation(vert, OY, roty*math.pi/180.0) for vert in v ]
+    lrot = [ geompy.MakeRotation(lin, OY, roty*math.pi/180.0) for lin in l ]
+    arc = geompy.MakeRotation(arc1, OY, roty*math.pi/180.0)
+    part = geompy.MakeRotation(part1, OY, roty*math.pi/180.0)
+    return vrot, lrot, arc, part
+  else:
+    return v, l, arc1, part1
+
+def pointsProjetes(study, vref, face):
+  #geompy = geomBuilder.New(study)
+  vface = geompy.ExtractShapes(face, geompy.ShapeType["VERTEX"], True)
+  vord = range(len(vref))
+  plan = geompy.MakePlaneThreePnt(vref[0], vref[1], vref[-1], 10000)
+  vproj = [ geompy.MakeProjection(vert, plan) for vert in vface ]
+  for i,v in enumerate(vproj):
+    dist = [ (geompy.MinDistance(v, vr), j) for j,vr in enumerate(vref) ]
+    dist.sort()
+    if dist[0][0] < 1.e-3:
+      vord[dist[0][1]] = vface[i]
+  return vord
+
+def arcsProjetes(study, vf, face):
+  #geompy = geomBuilder.New(study)
+  lface = geompy.ExtractShapes(face, geompy.ShapeType["EDGE"], True)
+  lord = range(3)
+  ends = [vf[1], vf[6], vf[7], vf[3]]
+  for i in range(3):
+    for lf in lface:
+      pts = geompy.ExtractShapes(lf, geompy.ShapeType["VERTEX"], True)
+      if (((geompy.MinDistance(pts[0], ends[i]) < 0.001) and (geompy.MinDistance(pts[1], ends[i+1]) < 0.001)) or
+          ((geompy.MinDistance(pts[1], ends[i]) < 0.001) and (geompy.MinDistance(pts[0], ends[i+1]) < 0.001))):
+        lord[i] = lf
+        #print "arc_%d OK"%i
+        break
+    pass
+  return lord
+def build_shape(study, r1, r2, h1, h2, solid_thickness=0, progressBar=None ):
+  """ Builds the final shape """
+
+  if progressBar is not None:
+    time0 = time.time()
+    print time.time() -time0
+    
+  if solid_thickness < 1e-7:
+    with_solid = False
+  else:
+    with_solid = True
+  
+  global geompy
+  geompy = geomBuilder.New(study)
+  
+  O = geompy.MakeVertex(0, 0, 0)
+  OX = geompy.MakeVectorDXDYDZ(1, 0, 0) 
+  OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
+  OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
+  
+  a1 = 45.0
+  seuilmax = 0.1
+  ratio = float(r2)/float(r1)
+  if ratio > (1.0 -seuilmax):
+    a1 = 45.0*(1.0 -ratio)/seuilmax
+
+  # --- Creation of the jonction faces
+  [faci, sect45, arc1, l1, lord90, lord45, edges, arcextru] = jonction(study, r1, r2,\
+                                                                       h1, h2, a1)
+  if progressBar is not None:
+    progressBar.addSteps(2)
+    print time.time() -time0
+    
+  if with_solid:
+    # The same code is executed again with different external radiuses in order
+    # to get the needed faces and edges to build the solid layer of the pipe
+    [faci_ext, sect45_ext, arc1_ext, l1_ext, \
+     lord90_ext, lord45_ext, edges_ext, arcextru_ext] = jonction(study, r1 + solid_thickness, r2 + solid_thickness,\
+                                                                 h1, h2, a1)
+    faces_jonction_ext = []
+    for i,l in enumerate(lord90):
+      faces_jonction_ext.append(geompy.MakeQuad2Edges(lord90[i],lord90_ext[i]))
+    for i in [1, 3, 6, 7]:
+      faces_jonction_ext.append(geompy.MakeQuad2Edges(edges[i],edges_ext[i]))
+    for i,l in enumerate(lord45):
+      faces_jonction_ext.append(geompy.MakeQuad2Edges(lord45[i],lord45_ext[i]))
+   
+  if progressBar is not None:
+    progressBar.addSteps(4)
+    print time.time() -time0
+    
+  # --- extrusion droite des faces de jonction, pour reconstituer les demi cylindres
+  if with_solid:    
+    sect45 = geompy.MakeCompound([sect45]+faces_jonction_ext[-3:])
+    sect45 = geompy.MakeGlueEdges(sect45, 1e-7)
+    
+  if progressBar is not None:
+    progressBar.addSteps(1)
+    print time.time() -time0
+    
+  extru1 = geompy.MakePrismVecH(sect45, OX, h1+10)
+
+  faces_coupe = faci[5:]
+  if with_solid:
+    faces_coupe = faci[5:]+faces_jonction_ext[:3]
+  base2 = geompy.MakePartition(faces_coupe, [], [], [], geompy.ShapeType["FACE"], 0, [], 0, True)
+  extru2 = geompy.MakePrismVecH(base2, OZ, h2)
+
+  if progressBar is not None:
+    progressBar.addSteps(1)
+    print time.time() -time0
+    
+  # --- partition et coupe
+
+  if with_solid:
+     demiDisque = geompy.MakeFaceWires([arc1_ext, l1_ext[0]], 1)
+  else:
+     demiDisque = geompy.MakeFaceWires([arc1, l1[0]], 1)
+  demiCylindre = geompy.MakePrismVecH(demiDisque, OX, h1)
+
+  if progressBar is not None:
+    progressBar.addSteps(1)
+    print time.time() -time0
+    
+  box = geompy.MakeBox(0, -2*(r1+h1), -2*(r1+h1), 2*(r1+h1), 2*(r1+h1), 2*(r1+h1))
+  rot = geompy.MakeRotation(box, OY, 45*math.pi/180.0)
+
+  # NOTE: The following Cut takes almost half of the total execution time
+  garder = geompy.MakeCutList(demiCylindre, [extru2, rot], True)
+  
+  if progressBar is not None:
+    progressBar.addSteps(9)
+    print time.time() -time0
+
+  faces_coupe = faci[:5]
+  if with_solid:
+    faces_coupe.extend(faces_jonction_ext[-7:])
+  raccord = geompy.MakePartition([garder], faces_coupe + [arcextru], [], [], geompy.ShapeType["SOLID"], 0, [], 0, True)
+  assemblage = geompy.MakeCompound([raccord, extru1, extru2])
+  assemblage = geompy.MakeGlueFaces(assemblage, 1e-7)
+
+  if progressBar is not None:
+    progressBar.addSteps(3)
+    print time.time() -time0
+
+  box = geompy.MakeBox(-1, -(r1+r2+2*solid_thickness), -1, h1, r1+r2+2*solid_thickness, h2)
+  
+  # NOTE: This operation takes about 1/4 of the total execution time
+  final = geompy.MakeCommonList([box, assemblage], True)
+  
+  if progressBar is not None:
+    progressBar.addSteps(5)
+    print time.time() -time0
+    
+  # --- Partie inférieure
+  
+  v3, l3, arc3, part3 = demidisk(study, r1, a1, 180.0, solid_thickness)
+  extru3 = geompy.MakePrismVecH(part3, OX, h1)
+
+  # --- Symétrie
+
+  compound = geompy.MakeCompound([final, extru3])
+  plane = geompy.MakePlane(O,OX,2000)
+  compound_mirrored = geompy.MakeMirrorByPlane(compound, plane)
+  final = geompy.MakeCompound([compound, compound_mirrored])
+
+  if progressBar is not None:
+    progressBar.addSteps(1)
+    print time.time() -time0
+      
+  return final
+
+
+def jonction(study, r1, r2, h1, h2, a1):
+  """ Builds the jonction faces and
+  returns what is needed to build the whole pipe
+  """
+  #geompy = geomBuilder.New(study)
+  
+  O = geompy.MakeVertex(0, 0, 0)
+  OX = geompy.MakeVectorDXDYDZ(1, 0, 0) 
+  OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
+  OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
+  
+  # --- sections droites des deux demi cylindres avec le partionnement
+  v1, l1, arc1, part1 = demidisk(study, r1, a1, 0.)
+  v2, l2, arc2, part2 = demidisk(study, r2, a1, 90.0)
+  # --- extrusion des sections --> demi cylindres de travail, pour en extraire les sections utilisées au niveau du Té
+  #     et enveloppe cylindrique du cylindre principal
+
+  demicyl1 = geompy.MakePrismVecH(part1, OX, h1)
+  demicyl2 = geompy.MakePrismVecH(part2, OZ, h2)
+  arcextru = geompy.MakePrismVecH(arc1, OX, h1)
+  
+  # --- plan de coupe à 45° sur le cylindre principal,
+  #     section à 45° du cylndre principal,
+  #     section du cylindre secondaire par l'enveloppe cylindrique du cylindre principal
+
+  plan1 = geompy.MakePlane(O, OX, 4*r1)
+  planr = geompy.MakeRotation(plan1, OY, 45*math.pi/180.0)
+
+  sect45 = geompy.MakeCommonList([demicyl1, planr], True)
+  sect90 = geompy.MakeCommonList([demicyl2, arcextru], True)
+  #geompy.addToStudy(sect90, "sect90")
+
+  # --- liste ordonnée des points projetés sur les deux sections
+
+  vord45 = pointsProjetes(study, v1, sect45)
+  vord90 = pointsProjetes(study, v2, sect90)
+
+  # --- identification des projections des trois arcs de cercle, sur les deux sections.
+  
+  lord45 = arcsProjetes(study, vord45, sect45)
+  lord90 = arcsProjetes(study, vord90, sect90)
+  # --- abaissement des quatre points centraux de la section du cylindre secondaire
+  
+  dz = -r2/2.0
+  for i in (0, 2, 4, 5):
+    vord90[i] = geompy.TranslateDXDYDZ(vord90[i], 0, 0, dz, True)
+    #geompy.addToStudyInFather(sect90, vord90[i], 'vm%d'%i)
+    
+  # --- création des deux arêtes curvilignes sur l'enveloppe cylindrique du cylindre principal, à la jonction
+
+  curv = [None for i in range(4)] # liaisons entre les points 1, 3, 6 et 7 des 2 sections
+
+  curv[0] = geompy.MakeArcCenter(O, vord90[1] , vord45[1], False)
+  curv[1] = geompy.MakeArcCenter(O, vord90[3] , vord45[3], False)
+
+  lipts = ((6, 6, 4), (7, 7, 5))
+  for i, ipts in enumerate(lipts):
+    #print i, ipts
+    p0 = vord90[ipts[0]]
+    p1 = vord45[ipts[1]]
+    p2 = vord45[ipts[2]]
+    plan = geompy.MakePlaneThreePnt(p0, p1, p2, 10000)
+    #geompy.addToStudy(plan, "plan%d"%i)
+    section = geompy.MakeSection(plan, arcextru, True)
+    secpart = geompy.MakePartition([section], [sect45, sect90], [], [], geompy.ShapeType["EDGE"], 0, [], 0, True)
+    #geompy.addToStudy(secpart, "secpart%d"%i)
+    lsec = geompy.ExtractShapes(secpart, geompy.ShapeType["EDGE"], True)
+
+    for l in lsec:
+      pts = geompy.ExtractShapes(l, geompy.ShapeType["VERTEX"], True)
+      if (((geompy.MinDistance(pts[0], p0) < 0.001) and (geompy.MinDistance(pts[1], p1) < 0.001)) or
+          ((geompy.MinDistance(pts[1], p0) < 0.001) and (geompy.MinDistance(pts[0], p1) < 0.001))):
+        curv[i+2] =l
+        #print "curv_%d OK"%i
+        break
+    
+  # --- creation des arêtes droites manquantes, des faces et volumes pour les quatre volumes de la jonction
+
+  edges = [None for i in range(8)]
+  edges[0] = geompy.MakeLineTwoPnt(vord45[0], vord90[0])
+  edges[1] = curv[0]
+  edges[2] = geompy.MakeLineTwoPnt(vord45[2], vord90[2])
+  edges[3] = curv[1]
+  edges[4] = geompy.MakeLineTwoPnt(vord45[4], vord90[4])
+  edges[5] = geompy.MakeLineTwoPnt(vord45[5], vord90[5])
+  edges[6] = curv[2]
+  edges[7] = curv[3]
+  ed45 = [None for i in range(8)]
+  ed45[0] = geompy.MakeLineTwoPnt(vord45[0], vord45[2])
+  ed45[1] = geompy.MakeLineTwoPnt(vord45[0], vord45[1])
+  ed45[2] = geompy.MakeLineTwoPnt(vord45[4], vord45[6])
+  ed45[3] = geompy.MakeLineTwoPnt(vord45[2], vord45[3])
+  ed45[4] = geompy.MakeLineTwoPnt(vord45[5], vord45[7])
+  ed45[5] = geompy.MakeLineTwoPnt(vord45[4], vord45[5])
+  ed45[6] = geompy.MakeLineTwoPnt(vord45[0], vord45[4])
+  ed45[7] = geompy.MakeLineTwoPnt(vord45[2], vord45[5])
+  ed90 = [None for i in range(8)]
+  ed90[0] = geompy.MakeLineTwoPnt(vord90[0], vord90[2])
+  ed90[1] = geompy.MakeLineTwoPnt(vord90[0], vord90[1])
+  ed90[2] = geompy.MakeLineTwoPnt(vord90[4], vord90[6])
+  ed90[3] = geompy.MakeLineTwoPnt(vord90[2], vord90[3])
+  ed90[4] = geompy.MakeLineTwoPnt(vord90[5], vord90[7])
+  ed90[5] = geompy.MakeLineTwoPnt(vord90[4], vord90[5])
+  ed90[6] = geompy.MakeLineTwoPnt(vord90[0], vord90[4])
+  ed90[7] = geompy.MakeLineTwoPnt(vord90[2], vord90[5])
+
+  faci = []
+  faci.append(geompy.MakeFaceWires([ed45[6], edges[0], ed90[6], edges[4]], 0))
+  faci.append(geompy.MakeFaceWires([ed45[7], edges[2], ed90[7], edges[5]], 0))
+  faci.append(geompy.MakeFaceWires([ed45[2], edges[4], ed90[2], edges[6]], 0))
+  faci.append(geompy.MakeFaceWires([ed45[5], edges[4], ed90[5], edges[5]], 0))
+  faci.append(geompy.MakeFaceWires([ed45[4], edges[5], ed90[4], edges[7]], 0))
+  faci.append(geompy.MakeFaceWires([ed90[0], ed90[6],  ed90[5], ed90[7]], 0))
+  faci.append(geompy.MakeFaceWires([ed90[1], ed90[6],  ed90[2], lord90[0]], 0))
+  faci.append(geompy.MakeFaceWires([ed90[2], ed90[5],  ed90[4], lord90[1]], 0))
+  faci.append(geompy.MakeFaceWires([ed90[3], ed90[7],  ed90[4], lord90[2]], 0))
+  return faci, sect45, arc1, l1, lord90, lord45, edges, arcextru
+
+def test_t_shape_builder():
+  """For testing purpose"""
+  salome.salome_init()
+  theStudy = salome.myStudy
+  geompy = geomBuilder.New(theStudy)
+  for r1 in [1., 100.]:
+    for r2 in [0.9*r1, 0.5*r1, 0.1*r1, 0.05*r1]:
+      for thickness in [r1/100., r1/10., r1/2.]:
+        print r1, r2, thickness
+        h1 = r1 * 2.0
+        h2 = h1
+        try:
+          res = build_shape(theStudy, r1, r2, h1, h2, thickness)
+          geompy.addToStudy(res, "res_%f_%f_%f"%(r1,r2, thickness))
+        except:
+          print "problem with res_%f_%f_%f"%(r1,r2, thickness)
+  
+if __name__=="__main__":
+  """For testing purpose"""
+  test_t_shape_builder()
diff --git a/src/Tools/t_shape/t_shape_dialog.py b/src/Tools/t_shape/t_shape_dialog.py
new file mode 100644 (file)
index 0000000..c385efd
--- /dev/null
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010-2014  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, or (at your option) any later version.
+#
+# 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
+#
+# Author : Renaud Nédélec (OpenCascade S.A.S)
+
+import sys
+from PyQt4 import QtGui
+from PyQt4 import QtCore
+
+from t_shape_dialog_ui import Ui_Dialog
+
+
+class TShapeDialog(QtGui.QDialog):
+    def __init__(self):
+      QtGui.QDialog.__init__(self, None, QtCore.Qt.Tool)
+      # Set up the user interface from Designer.
+      self.ui = Ui_Dialog()
+      self.ui.setupUi(self)
+      self.show()
+      self._wasOk = False
+      self.ui.dsb_solidThickness.setEnabled(False)
+      self.ui.label_5.setEnabled(False)
+      self.ui.dsb_bigRadius.setValue(50.0)
+      self.ui.dsb_smallRadius.setValue(40.0)
+      self.ui.dsb_bigHeight.setValue(80.0)
+      self.ui.dsb_smallHeight.setValue(80.0)
+   
+    def accept(self):
+      self._wasOk = True
+      QtGui.QDialog.accept(self)
+      
+    def getData(self):
+      r1 = self.ui.dsb_bigRadius.value()
+      r2 = self.ui.dsb_smallRadius.value()
+      h1 = self.ui.dsb_bigHeight.value()
+      h2 = self.ui.dsb_smallHeight.value()
+      thickness = 0.0
+      if self.ui.cb_buildSolid.isChecked():
+        thickness = self.ui.dsb_solidThickness.value()
+      
+      return r1, r2, h1, h2, thickness
+
+    def reject(self):
+        self._wasOk = False
+        QtGui.QDialog.reject(self)
+
+    def wasOk(self):
+        return self._wasOk
+
+     
+# ================     
+# Tests
+# ================
+
+def main( args ):
+    import sys
+    app = QtGui.QApplication(sys.argv)
+    Dialog = TShapeDialog()
+    ui = Ui_Dialog()
+    ui.setupUi(Dialog)
+    Dialog.show()
+    sys.exit(app.exec_())
+
+if __name__=="__main__":
+    main(sys.argv)
diff --git a/src/Tools/t_shape/t_shape_dialog.ui b/src/Tools/t_shape/t_shape_dialog.ui
new file mode 100644 (file)
index 0000000..55a4823
--- /dev/null
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>349</width>
+    <height>283</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout_3">
+   <item row="0" column="0">
+    <layout class="QGridLayout" name="gridLayout">
+     <item row="2" column="1">
+      <widget class="QDoubleSpinBox" name="dsb_smallRadius">
+       <property name="decimals">
+        <number>5</number>
+       </property>
+       <property name="maximum">
+        <double>100000.000000000000000</double>
+       </property>
+       <property name="value">
+        <double>40.000000000000000</double>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="0">
+      <widget class="QLabel" name="label">
+       <property name="text">
+        <string>Big pipe radius</string>
+       </property>
+      </widget>
+     </item>
+     <item row="3" column="1">
+      <widget class="QDoubleSpinBox" name="dsb_bigHeight">
+       <property name="decimals">
+        <number>5</number>
+       </property>
+       <property name="maximum">
+        <double>1000000.000000000000000</double>
+       </property>
+       <property name="value">
+        <double>80.000000000000000</double>
+       </property>
+      </widget>
+     </item>
+     <item row="4" column="1">
+      <widget class="QDoubleSpinBox" name="dsb_smallHeight">
+       <property name="decimals">
+        <number>5</number>
+       </property>
+       <property name="maximum">
+        <double>1000000.000000000000000</double>
+       </property>
+       <property name="value">
+        <double>80.000000000000000</double>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QDoubleSpinBox" name="dsb_bigRadius">
+       <property name="decimals">
+        <number>5</number>
+       </property>
+       <property name="maximum">
+        <double>100000.000000000000000</double>
+       </property>
+       <property name="value">
+        <double>50.000000000000000</double>
+       </property>
+      </widget>
+     </item>
+     <item row="3" column="0">
+      <widget class="QLabel" name="label_3">
+       <property name="text">
+        <string>Big pipe  height</string>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="0">
+      <widget class="QLabel" name="label_2">
+       <property name="text">
+        <string>Small pipe  radius</string>
+       </property>
+      </widget>
+     </item>
+     <item row="4" column="0">
+      <widget class="QLabel" name="label_4">
+       <property name="text">
+        <string>Small  pipe height</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="1" column="0">
+    <layout class="QGridLayout" name="gridLayout_2">
+     <item row="0" column="0">
+      <widget class="QCheckBox" name="cb_buildSolid">
+       <property name="text">
+        <string>Build solid part</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="0">
+      <widget class="QLabel" name="label_5">
+       <property name="text">
+        <string>Solid thickness</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="1">
+      <widget class="QDoubleSpinBox" name="dsb_solidThickness">
+       <property name="decimals">
+        <number>5</number>
+       </property>
+       <property name="maximum">
+        <double>1000000.000000000000000</double>
+       </property>
+       <property name="value">
+        <double>5.000000000000000</double>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="2" column="0">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>Dialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>205</x>
+     <y>241</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>250</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>Dialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>205</x>
+     <y>241</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>214</x>
+     <y>250</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>cb_buildSolid</sender>
+   <signal>clicked(bool)</signal>
+   <receiver>label_5</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>99</x>
+     <y>170</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>107</x>
+     <y>205</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>cb_buildSolid</sender>
+   <signal>clicked(bool)</signal>
+   <receiver>dsb_solidThickness</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>150</x>
+     <y>170</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>277</x>
+     <y>212</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/src/Tools/t_shape/t_shape_progress.py b/src/Tools/t_shape/t_shape_progress.py
new file mode 100644 (file)
index 0000000..38f8045
--- /dev/null
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2010-2014  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, or (at your option) any later version.
+#
+# 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
+#
+# Author : Renaud Nédélec (OpenCascade S.A.S)
+
+from salome.geom.t_shape import t_shape_builder
+from PyQt4.QtGui import QProgressDialog
+from PyQt4 import QtCore
+
+class t_shape_progress(QProgressDialog):
+    _totSteps = 0
+    _nmaxSteps = 27
+    
+    def __init__(self, parent=None):
+      QProgressDialog.__init__(self, "t_shape fluid build", "stop", 0, self._nmaxSteps, parent, QtCore.Qt.Tool)
+      self.show()
+        
+    def run(self, activeStudy, r1, r2, h1, h2, thickness):
+      shape = t_shape_builder.build_shape(activeStudy, r1, r2, h1, h2, thickness, self)
+      self.setValue(self._nmaxSteps)
+      return shape
+      
+    def addSteps(self, nbSteps):
+      self._totSteps += nbSteps
+      self.setValue(self._totSteps)