]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge branch 'master' of newgeom:newgeom
authorvsv <vitaly.smetannikov@opencascade.com>
Fri, 6 Jun 2014 15:19:36 +0000 (19:19 +0400)
committervsv <vitaly.smetannikov@opencascade.com>
Fri, 6 Jun 2014 15:19:36 +0000 (19:19 +0400)
20 files changed:
src/ConstructionPlugin/ConstructionPlugin_Extrusion.cpp
src/ConstructionPlugin/ConstructionPlugin_Extrusion.h
src/GeomAlgoAPI/CMakeLists.txt
src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.h [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp [new file with mode: 0644]
src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.h [new file with mode: 0644]
src/ModuleBase/CMakeLists.txt
src/ModuleBase/ModuleBase_ModelWidget.cpp [new file with mode: 0644]
src/ModuleBase/ModuleBase_ModelWidget.h
src/ModuleBase/ModuleBase_SelectorWidget.cpp
src/ModuleBase/ModuleBase_SelectorWidget.h
src/ModuleBase/ModuleBase_WidgetBoolValue.cpp
src/ModuleBase/ModuleBase_WidgetBoolValue.h
src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp
src/ModuleBase/ModuleBase_WidgetDoubleValue.h
src/ModuleBase/ModuleBase_WidgetFactory.cpp
src/ModuleBase/ModuleBase_WidgetPoint2D.cpp
src/ModuleBase/ModuleBase_WidgetPoint2D.h
src/SketchPlugin/SketchPlugin_Sketch.cpp

index 8b5dc2d60a5767158280db1ad1d162bdd778cfdb..0af9cad3b2647396a91bb620d2439f442989f1ec 100644 (file)
@@ -10,6 +10,8 @@
 #include <ModelAPI_AttributeReference.h>
 #include <ModelAPI_AttributeBoolean.h>
 
+#include <GeomAlgoAPI_Extrusion.h>
+
 using namespace std;
 
 ConstructionPlugin_Extrusion::ConstructionPlugin_Extrusion()
@@ -20,14 +22,24 @@ void ConstructionPlugin_Extrusion::initAttributes()
 {
   data()->addAttribute(EXTRUSION_FACE, ModelAPI_AttributeReference::type());
   data()->addAttribute(EXTRUSION_SIZE, ModelAPI_AttributeDouble::type());
-  data()->addAttribute(EXTRUSION_REVERCE, ModelAPI_AttributeBoolean::type());
+  data()->addAttribute(EXTRUSION_REVERSE, ModelAPI_AttributeBoolean::type());
 }
 
-// this is for debug only
-#include <iostream>
-void ConstructionPlugin_Extrusion::execute() 
+void ConstructionPlugin_Extrusion::execute()
 {
-  // TODO: create a real shape for the point using OCC layer
-  //cout<<"X="<<data()->real(POINT_ATTR_X)->value()<<" Y="<<data()->real(POINT_ATTR_Y)->value()
-  //    <<" Z="<<data()->real(POINT_ATTR_Z)->value()<<endl;
+  boost::shared_ptr<ModelAPI_AttributeReference> aFaceRef = 
+    boost::dynamic_pointer_cast<ModelAPI_AttributeReference>(data()->attribute(EXTRUSION_FACE));
+  if (!aFaceRef)
+    return;
+  FeaturePtr aFaceFeature = aFaceRef->value();
+  if (!aFaceFeature)
+    return;
+  boost::shared_ptr<GeomAPI_Shape> aFace = aFaceFeature->data()->shape();
+  if (!aFace)
+    return;
+
+  double aSize = data()->real(EXTRUSION_SIZE)->value();
+  if (data()->boolean(EXTRUSION_REVERSE)->value())
+    aSize = -aSize;
+  data()->store(GeomAlgoAPI_Extrusion::makeExtrusion(aFace, aSize));
 }
index 5270d2d892c6a756d489202e8e1fd5c8e718b83b..5933929b83d27808c2c1ad42c6d80e06eecabd1e 100644 (file)
@@ -18,7 +18,7 @@ const std::string EXTRUSION_FACE = "extrusion_face";
 const std::string EXTRUSION_SIZE = "extrusion_size";
 
 /// attribute name of reverce direction
-const std::string EXTRUSION_REVERCE = "extrusion_reverse";
+const std::string EXTRUSION_REVERSE = "extrusion_reverse";
 
 
 class ConstructionPlugin_Extrusion: public ModelAPI_Feature
index 181bf09de2c37299ac71e89a35429ae18e2794a9..135d2747055307f087dd94627e59b5ff62c82b5a 100644 (file)
@@ -9,6 +9,8 @@ SET(PROJECT_HEADERS
     GeomAlgoAPI_FaceBuilder.h
     GeomAlgoAPI_EdgeBuilder.h
     GeomAlgoAPI_PointBuilder.h
+    GeomAlgoAPI_SketchBuilder.h
+    GeomAlgoAPI_Extrusion.h
 )
 
 SET(PROJECT_SOURCES
@@ -16,6 +18,8 @@ SET(PROJECT_SOURCES
     GeomAlgoAPI_FaceBuilder.cpp
     GeomAlgoAPI_EdgeBuilder.cpp
     GeomAlgoAPI_PointBuilder.cpp
+    GeomAlgoAPI_SketchBuilder.cpp
+    GeomAlgoAPI_Extrusion.cpp
 )
 
 ADD_DEFINITIONS(-DGEOMALGOAPI_EXPORTS ${CAS_DEFINITIONS})
@@ -31,7 +35,7 @@ INCLUDE_DIRECTORIES(
   ${CAS_INCLUDE_DIRS}
 )
 
-TARGET_LINK_LIBRARIES(GeomAlgoAPI ${PROJECT_LIBRARIES} GeomAPI ${CAS_KERNEL} ${CAS_MODELER})
+TARGET_LINK_LIBRARIES(GeomAlgoAPI ${PROJECT_LIBRARIES} GeomAPI ${CAS_TKBool} ${CAS_TKBO} ${CAS_TKPrim})
 
 SET(SWIG_SCRIPTS
   ${CMAKE_CURRENT_BINARY_DIR}/GeomAlgoAPI.py
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.cpp
new file mode 100644 (file)
index 0000000..d5affc0
--- /dev/null
@@ -0,0 +1,68 @@
+// File:        GeomAlgoAPI_Extrusion.cpp
+// Created:     06 Jun 2014
+// Author:      Artem ZHIDKOV
+
+#include <GeomAlgoAPI_Extrusion.h>
+
+#include <gp_Pln.hxx>
+
+#include <BRepPrimAPI_MakePrism.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom_Surface.hxx>
+#include <TopExp_Explorer.hxx>
+
+#include <Precision.hxx>
+const double tolerance = Precision::Angular();
+
+boost::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_Extrusion::makeExtrusion(
+                        boost::shared_ptr<GeomAPI_Shape> theShape,
+                        boost::shared_ptr<GeomAPI_Dir>   theDir,
+                        double                           theSize)
+{
+  const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
+  gp_Vec aDir(theDir->impl<gp_Dir>().XYZ() * theSize);
+
+  TopoDS_Shape aPrism = BRepPrimAPI_MakePrism(aShape, aDir);
+  if (aPrism.IsNull())
+    return boost::shared_ptr<GeomAPI_Shape>();
+
+  boost::shared_ptr<GeomAPI_Shape> aResult(new GeomAPI_Shape());
+  aResult->setImpl(new TopoDS_Shape(aPrism));
+  return aResult;
+}
+
+boost::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_Extrusion::makeExtrusion(
+                        boost::shared_ptr<GeomAPI_Shape> theShape,
+                        double                           theSize)
+{
+  bool isFirstNorm = true;
+  gp_Dir aShapeNormal;
+
+  const TopoDS_Shape& aShape = theShape->impl<TopoDS_Shape>();
+  TopExp_Explorer aFaceExp(aShape, TopAbs_FACE);
+  for ( ; aFaceExp.More(); aFaceExp.Next())
+  {
+    const TopoDS_Face& aFace = (const TopoDS_Face&)aFaceExp.Current();
+    Handle(BRep_TFace) aBFace = Handle(BRep_TFace)::DownCast(aFace.TShape());
+    if (aBFace.IsNull())
+      return boost::shared_ptr<GeomAPI_Shape>();
+
+    Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aBFace->Surface());
+    if (aPlane.IsNull()) // non-planar shapes is not supported for extrusion yet
+      continue;
+
+    const gp_Dir& aNormal = aPlane->Pln().Axis().Direction();
+    if (isFirstNorm)
+    {
+      aShapeNormal = aNormal;
+      isFirstNorm = false;
+    }
+    else if (!aShapeNormal.IsEqual(aNormal, tolerance)) // non-planar shapes is not supported for extrusion yet
+      return boost::shared_ptr<GeomAPI_Shape>();
+  }
+
+  boost::shared_ptr<GeomAPI_Dir> aDir(
+    new GeomAPI_Dir(aShapeNormal.X(), aShapeNormal.Y(), aShapeNormal.Z()));
+
+  return GeomAlgoAPI_Extrusion::makeExtrusion(theShape, aDir, theSize);
+}
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.h b/src/GeomAlgoAPI/GeomAlgoAPI_Extrusion.h
new file mode 100644 (file)
index 0000000..f2a098c
--- /dev/null
@@ -0,0 +1,42 @@
+// File:        GeomAlgoAPI_Extrusion.h
+// Created:     06 Jun 2014
+// Author:      Artem ZHIDKOV
+
+#ifndef GeomAlgoAPI_Extrusion_HeaderFile
+#define GeomAlgoAPI_Extrusion_HeaderFile
+
+#include <GeomAlgoAPI.h>
+#include <GeomAPI_Shape.h>
+#include <GeomAPI_Dir.h>
+#include <boost/shared_ptr.hpp>
+
+/**\class GeomAlgoAPI_Extrusion
+ * \ingroup DataAlgo
+ * \brief Allows to create the prism based on a given face and a direction
+ */
+
+class GEOMALGOAPI_EXPORT GeomAlgoAPI_Extrusion
+{
+public:
+  /* \brief Creates extrusion for the given shape
+   * \param[in] theShape face or wire to be extruded
+   * \param[in] theDir   direction of extrusion
+   * \param[in] theSize  the length of extrusion (if the value is less than 0, the extrusion in opposite direction)
+   * \return a solid or a face which is obtained from specified one
+   */
+  static boost::shared_ptr<GeomAPI_Shape> makeExtrusion(
+                        boost::shared_ptr<GeomAPI_Shape> theShape,
+                        boost::shared_ptr<GeomAPI_Dir>   theDir,
+                        double                           theSize);
+
+  /* \brief Creates extrusion for the given shape along the normal for this shape
+   * \param[in] theShape face or wire to be extruded
+   * \param[in] theSize  the length of extrusion (if the value is less than 0, the extrusion in opposite normal)
+   * \return a solid or a face which is obtained from specified one
+   */
+  static boost::shared_ptr<GeomAPI_Shape> makeExtrusion(
+                        boost::shared_ptr<GeomAPI_Shape> theShape,
+                        double                           theSize);
+};
+
+#endif
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp
new file mode 100644 (file)
index 0000000..1828a71
--- /dev/null
@@ -0,0 +1,590 @@
+// File:        GeomAlgoAPI_SketchBuilder.cpp
+// Created:     02 Jun 2014
+// Author:      Artem ZHIDKOV
+
+#include <GeomAlgoAPI_SketchBuilder.h>
+
+#include <set>
+
+#include <gp_Dir.hxx>
+
+#include <BOPAlgo_Builder.hxx>
+#include <BOPAlgo_Operation.hxx>
+#include <BOPAlgo_PaveFiller.hxx>
+#include <BOPTools.hxx>
+#include <BRep_Builder.hxx>
+#include <BRep_Curve3D.hxx>
+#include <BRep_TEdge.hxx>
+#include <BRep_TVertex.hxx>
+#include <BRepAlgoAPI_Cut.hxx>
+#include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRepClass_FaceClassifier.hxx>
+#include <Geom_Curve.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Wire.hxx>
+
+#include <Precision.hxx>
+const double tolerance = Precision::Confusion();
+
+/// \brief Search first vertex - the vertex with lowest x coordinate, which is used in 2 edges at least
+static const TopoDS_Shape& findStartVertex(
+          const BOPCol_IndexedDataMapOfShapeListOfShape& theMapVE,
+          const gp_Dir& theDirX, const gp_Dir& theDirY);
+
+/// \brief Search the vertex on the sketch candidate to be the next one in the loop
+static void findNextVertex(
+          const TopoDS_Shape&                            theStartVertex, 
+          const BOPCol_IndexedDataMapOfShapeListOfShape& theVertexEdgeMap,
+          const gp_Dir&                                  theStartDir,
+          const gp_Dir&                                  theNormal,
+                TopoDS_Shape&                            theNextVertex,
+                TopoDS_Shape&                            theNextEdge,
+                gp_Dir&                                  theNextDir);
+
+/// \brief Create planar face using the edges surrounding it
+static void createFace(const TopoDS_Shape&                      theStartVertex,
+                       const std::list<TopoDS_Shape>::iterator& theStartEdge,
+                       const std::list<TopoDS_Shape>::iterator& theEndOfEdges,
+                             TopoDS_Face&                       theResFace);
+
+/// \bief Create planar wire
+static void createWireList(const TopoDS_Shape&                      theStartVertex,
+                           const std::list<TopoDS_Shape>::iterator& theStartEdge,
+                           const std::list<TopoDS_Shape>::iterator& theEndOfEdges,
+                           const std::set<Handle(TopoDS_TShape)>&   theEdgesInLoops,
+                                 std::list<TopoDS_Wire>&            theResWires);
+
+/// \brief Calculate outer tengency on the edge in specified vertex
+static gp_Dir getOuterEdgeDirection(const TopoDS_Shape& theEdge,
+                                    const TopoDS_Shape& theVertex);
+
+/// \brief Unnecessary edges will be removed from the map.
+///        Positions of iterator will be updated
+static void removeWasteEdges(
+                std::list<TopoDS_Shape>::iterator&  theStartVertex,
+                std::list<TopoDS_Shape>::iterator&  theStartEdge,
+          const std::list<TopoDS_Shape>::iterator&  theEndOfVertexes,
+          const std::list<TopoDS_Shape>::iterator&  theEndOfEdges,
+          BOPCol_IndexedDataMapOfShapeListOfShape&  theMapVE);
+
+
+
+
+void GeomAlgoAPI_SketchBuilder::createFaces(
+          const boost::shared_ptr<GeomAPI_Dir>&                theDirX,
+          const boost::shared_ptr<GeomAPI_Dir>&                theDirY,
+          const boost::shared_ptr<GeomAPI_Dir>&                theNorm,
+          const std::list< boost::shared_ptr<GeomAPI_Shape> >& theFeatures,
+                std::list< boost::shared_ptr<GeomAPI_Shape> >& theResultFaces,
+                std::list< boost::shared_ptr<GeomAPI_Shape> >& theResultWires)
+{
+  // Create the list of edges with shared vertexes
+  BOPAlgo_Builder aBuilder;
+  BOPAlgo_PaveFiller aPF;
+
+  std::list< boost::shared_ptr<GeomAPI_Shape> >::const_iterator anIt = theFeatures.begin();
+  for (; anIt != theFeatures.end(); anIt++)
+  {
+    boost::shared_ptr<GeomAPI_Shape> aPreview(*anIt);
+    aBuilder.AddArgument(aPreview->impl<TopoDS_Edge>());
+  }
+  aPF.SetArguments(aBuilder.Arguments());
+  aPF.Perform();
+  int aErr = aPF.ErrorStatus();
+  if (aErr) return ;
+  aBuilder.PerformWithFiller(aPF);
+  aErr = aBuilder.ErrorStatus();
+  if (aErr) return ;
+
+  BOPCol_IndexedDataMapOfShapeListOfShape aMapVE; // map between vertexes and edges
+  BOPTools::MapShapesAndAncestors(aBuilder.Shape(), TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
+
+  gp_Dir aDirX = theDirX->impl<gp_Dir>();
+  gp_Dir aDirY = theDirY->impl<gp_Dir>();
+  gp_Dir aNorm = theNorm->impl<gp_Dir>();
+
+  // Set of edges used in loops
+  std::set<Handle(TopoDS_TShape)> anEdgesInLoops;
+  // Lists for processed vertexes and edges
+  std::list<TopoDS_Shape> aProcVertexes;
+  std::list<TopoDS_Shape> aProcEdges;
+
+  // Search the start vertex
+  TopoDS_Shape aStartVertex = findStartVertex(aMapVE, aDirX, aDirY);
+  aProcVertexes.push_back(aStartVertex);
+
+  TopoDS_Shape aCurVertex = aStartVertex;
+  gp_Dir aCurDir = aDirY;
+  gp_Dir aCurNorm = aNorm.Reversed();
+
+  // Go through the edges and find loops
+  TopoDS_Shape aNextVertex;
+  TopoDS_Shape aBindingEdge;
+  gp_Dir aNextDir;
+  while (aMapVE.Extent() > 0)
+  {
+    findNextVertex(aCurVertex, aMapVE, aCurDir, aCurNorm, aNextVertex, aBindingEdge, aNextDir);
+    aCurNorm = aNorm;
+
+    // Try to find next vertex in the list of already processed
+    std::list<TopoDS_Shape>::iterator          aVertIter = aProcVertexes.begin();
+    std::list<TopoDS_Shape>::iterator          anEdgeIter = aProcEdges.begin();
+    for ( ; aVertIter != aProcVertexes.end(); aVertIter++)
+    {
+      if (aVertIter->TShape() == aNextVertex.TShape())
+        break;
+      if (anEdgeIter != aProcEdges.end())
+        anEdgeIter++;
+    }
+
+    aProcVertexes.push_back(aNextVertex);
+    aProcEdges.push_back(aBindingEdge);
+
+    // The loop was found
+    if (aVertIter != aProcVertexes.end())
+    {
+      if (aVertIter != aProcVertexes.begin())
+      {
+        // Check the orientation of the loop
+        Handle(BRep_TVertex) aVert = Handle(BRep_TVertex)::DownCast(aVertIter->TShape());
+        const gp_Pnt& aCurPnt = aVert->Pnt();
+        aVert = Handle(BRep_TVertex)::DownCast((++aVertIter)->TShape());
+        aVertIter--;
+        const gp_Pnt& aNextPnt = aVert->Pnt();
+        std::list<TopoDS_Shape>::reverse_iterator anItBeforeLast = aProcVertexes.rbegin();
+        aVert = Handle(BRep_TVertex)::DownCast((++anItBeforeLast)->TShape()); // get the vertex before last one, because the last duplicates the start of loop
+        const gp_Pnt& aPrevPnt = aVert->Pnt();
+        gp_Vec aCN(aCurPnt, aNextPnt);
+        gp_Vec aCP(aCurPnt, aPrevPnt);
+        if (aCN.DotCross(aCP, gp_Vec(aNorm)) < -tolerance)
+        {
+          // The found loop has wrong orientation and may contain sub-loops.
+          // Need to check it onle again with another initial direction.
+          aCurVertex = *aVertIter;
+          do {
+            aProcVertexes.pop_back();
+            aProcEdges.pop_back();
+          } while (aCurVertex != aProcVertexes.back());
+          aCurDir = getOuterEdgeDirection(aProcEdges.back(), aCurVertex);
+          aCurNorm = aNorm.Reversed();
+          continue;
+        }
+      }
+
+      // When the orientation is correct or the edges looped through
+      // the first element, create new face and remove unnecessary edges.
+      TopoDS_Face aPatch;
+      createFace(*aVertIter, anEdgeIter, aProcEdges.end(), aPatch);
+      if (!aPatch.IsNull())
+      {
+        boost::shared_ptr<GeomAPI_Shape> aFace(new GeomAPI_Shape);
+        aFace->setImpl(new TopoDS_Shape(aPatch));
+        theResultFaces.push_back(aFace);
+      }
+      // push the edges used in the loop to the map
+      std::list<TopoDS_Shape>::iterator anIter;
+      for (anIter = anEdgeIter; anIter != aProcEdges.end(); anIter++)
+        anEdgesInLoops.insert(anIter->TShape());
+      // remove unnecessary edges
+      std::list<TopoDS_Shape>::iterator aCopyVLoop = aVertIter;
+      std::list<TopoDS_Shape>::iterator aCopyELoop = anEdgeIter;
+      removeWasteEdges(aVertIter, anEdgeIter, aProcVertexes.end(), aProcEdges.end(), aMapVE);
+
+      // revert the list of remaining edges
+      std::list<TopoDS_Shape> aRemainVertexes;
+      for ( ; aVertIter != aProcVertexes.end(); aVertIter++)
+        aRemainVertexes.push_front(*aVertIter);
+      std::list<TopoDS_Shape> aRemainEdges;
+      for ( ; anEdgeIter != aProcEdges.end(); anEdgeIter++)
+        aRemainEdges.push_front(*anEdgeIter);
+      // remove edges and vertexes used in the loop and add remaining ones
+      aProcVertexes.erase(aCopyVLoop, aProcVertexes.end());
+      aProcVertexes.insert(aProcVertexes.end(), aRemainVertexes.begin(), aRemainVertexes.end());
+      aProcEdges.erase(aCopyELoop, aProcEdges.end());
+      aProcEdges.insert(aProcEdges.end(), aRemainEdges.begin(), aRemainEdges.end());
+
+      // Recalculate current vertex and current direction
+      if (!aProcVertexes.empty())
+      {
+        aNextVertex = aProcVertexes.back();
+        if (!aProcEdges.empty())
+          aNextDir = getOuterEdgeDirection(aProcEdges.back(), aNextVertex);
+        else aNextDir = -aDirY;
+      }
+    }
+
+    // if next vertex connected only to alone edge, this is a part of wire (not a closed loop),
+    // we need to go back through the list of already checked edges to find a branching vertex
+    if (!aMapVE.IsEmpty() && aMapVE.Contains(aNextVertex) && 
+        aMapVE.FindFromKey(aNextVertex).Size() == 1)
+    {
+      std::list<TopoDS_Shape>::reverse_iterator aVRIter = aProcVertexes.rbegin();
+      std::list<TopoDS_Shape>::reverse_iterator aERIter = aProcEdges.rbegin();
+      for (++aERIter, ++aVRIter; aERIter != aProcEdges.rend(); aERIter++, aVRIter++)
+        if (aMapVE.FindFromKey(*aVRIter).Size() > 2)
+          break;
+      if (aERIter != aProcEdges.rend() || aMapVE.FindFromKey(*aVRIter).Size() == 1)
+      { // the branching vertex was found or current list of edges is a wire without branches
+        std::list<TopoDS_Shape>::iterator aEIter;
+        TopoDS_Shape aCurEdge;
+        if (aERIter != aProcEdges.rend())
+        {
+          aEIter = aERIter.base();
+          aCurEdge = *aERIter;
+        }
+        else
+          aEIter = aProcEdges.begin();
+        std::list<TopoDS_Wire> aTail;
+        createWireList(*aVRIter, aEIter, aProcEdges.end(), anEdgesInLoops, aTail);
+        std::list<TopoDS_Wire>::const_iterator aTailIter = aTail.begin();
+        for ( ; aTailIter != aTail.end(); aTailIter++)
+          if (!aTailIter->IsNull())
+          {
+            boost::shared_ptr<GeomAPI_Shape> aWire(new GeomAPI_Shape);
+            aWire->setImpl(new TopoDS_Shape(*aTailIter));
+            theResultWires.push_back(aWire);
+          }
+        std::list<TopoDS_Shape>::iterator aVIter = aVRIter.base();
+        std::list<TopoDS_Shape>::iterator aEItCopy = aEIter;
+        removeWasteEdges(--aVIter, aEItCopy, aProcVertexes.end(), aProcEdges.end(), aMapVE);
+
+        aProcEdges.erase(aEIter, aProcEdges.end());
+        aVIter = aVRIter.base();
+        aProcVertexes.erase(aVIter, aProcVertexes.end());
+
+        if (!aProcVertexes.empty())
+        {
+          aNextVertex = aProcVertexes.back();
+          if (!aCurEdge.IsNull())
+            aNextDir = getOuterEdgeDirection(aCurEdge, aNextVertex);
+        }
+      }
+      else
+      { // there is no branching vertex in the list of proceeded,
+        // so we should revert the list and go the opposite way
+        aProcVertexes.reverse();
+        aProcEdges.reverse();
+        aNextVertex = aProcVertexes.back();
+        aNextDir = getOuterEdgeDirection(aProcEdges.back(), aNextVertex);
+      }
+    }
+
+    // When all edges of current component of connectivity are processed,
+    // we should repeat procedure for finding initial vertex in the remaining
+    if (!aMapVE.IsEmpty() && !aMapVE.Contains(aNextVertex))
+    {
+      aProcVertexes.clear();
+      aProcEdges.clear();
+
+      TopoDS_Shape aStartEdge;
+      aStartVertex = findStartVertex(aMapVE, aDirX, aDirY);
+      aProcVertexes.push_back(aStartVertex);
+      findNextVertex(aStartVertex, aMapVE, aDirY, aNorm.Reversed(), aNextVertex, aStartEdge, aNextDir);
+      aProcVertexes.push_back(aNextVertex);
+      aProcEdges.push_back(aStartEdge);
+    }
+
+    aCurVertex = aNextVertex;
+    aCurDir = aNextDir;
+  }
+
+  if (theResultFaces.size() > 1)
+    fixIntersections(theResultFaces);
+}
+
+void GeomAlgoAPI_SketchBuilder::fixIntersections(
+          std::list< boost::shared_ptr<GeomAPI_Shape> >& theFaces)
+{
+  BRepClass_FaceClassifier aClassifier;
+
+  std::list< boost::shared_ptr<GeomAPI_Shape> >::iterator anIter1 = theFaces.begin();
+  std::list< boost::shared_ptr<GeomAPI_Shape> >::iterator anIter2;
+  for ( ; anIter1 != theFaces.end(); anIter1++)
+  {
+    anIter2 = anIter1;
+    for (++anIter2; anIter2 != theFaces.end(); anIter2++)
+    {
+      const TopoDS_Face& aF1 = (*anIter1)->impl<TopoDS_Face>();
+      TopExp_Explorer aVert2((*anIter2)->impl<TopoDS_Shape>(), TopAbs_VERTEX);
+      for ( ; aVert2.More(); aVert2.Next())
+      {
+        Handle(BRep_TVertex) aV = Handle(BRep_TVertex)::DownCast(aVert2.Current().TShape());
+        aClassifier.Perform(aF1, aV->Pnt(), tolerance);
+        if (aClassifier.State() != TopAbs_IN)
+          break;
+      }
+      if (aVert2.More())
+      { // second shape is not inside first, change the shapes order and repeat comparision
+        const TopoDS_Face& aF2 = (*anIter2)->impl<TopoDS_Face>();
+        TopExp_Explorer aVert1((*anIter1)->impl<TopoDS_Shape>(), TopAbs_VERTEX);
+        for ( ; aVert1.More(); aVert1.Next())
+        {
+          Handle(BRep_TVertex) aV = Handle(BRep_TVertex)::DownCast(aVert1.Current().TShape());
+          aClassifier.Perform(aF2, aV->Pnt(), tolerance);
+          if (aClassifier.State() != TopAbs_IN)
+            break;
+        }
+        if (!aVert1.More())
+        { // first shape should be cut from the second
+          BRepAlgoAPI_Cut aCut((*anIter2)->impl<TopoDS_Shape>(),
+                               (*anIter1)->impl<TopoDS_Shape>());
+          (*anIter2)->setImpl(new TopoDS_Shape(aCut.Shape()));
+        }
+      }
+      else
+      { // second shape should be cut from the first
+        BRepAlgoAPI_Cut aCut((*anIter1)->impl<TopoDS_Shape>(),
+                             (*anIter2)->impl<TopoDS_Shape>());
+        (*anIter1)->setImpl(new TopoDS_Shape(aCut.Shape()));
+      }
+    }
+  }
+}
+
+
+// =================== Auxiliary functions ====================================
+const TopoDS_Shape& findStartVertex(
+          const BOPCol_IndexedDataMapOfShapeListOfShape& theMapVE,
+          const gp_Dir& theDirX, const gp_Dir& theDirY)
+{
+  int aStartVertexInd = 1;
+  double aMinX = DBL_MAX;
+  double aMinY = DBL_MAX;
+  int aNbVert = theMapVE.Extent();
+  for (int i = 1; i <= aNbVert; i++)
+  {
+    const TopoDS_Vertex& aV = (const TopoDS_Vertex&)theMapVE.FindKey(i);
+    const Handle(BRep_TVertex)& aVert = (const Handle(BRep_TVertex)&)aV.TShape();
+    const gp_Pnt& aVertPnt = aVert->Pnt();
+
+    double aX = aVertPnt.XYZ().Dot(theDirX.XYZ());
+    double aY = aVertPnt.XYZ().Dot(theDirY.XYZ());
+    if ((aX < aMinX || (fabs(aX - aMinX) < tolerance && aY < aMinY)) && 
+        theMapVE.FindFromIndex(i).Extent() > 1)
+    {
+      aMinX = aX;
+      aMinY = aY;
+      aStartVertexInd = i;
+    }
+  }
+  return theMapVE.FindKey(aStartVertexInd);
+}
+
+void findNextVertex(
+          const TopoDS_Shape&                            theStartVertex,
+          const BOPCol_IndexedDataMapOfShapeListOfShape& theVertexEdgeMap,
+          const gp_Dir&                                  theStartDir,
+          const gp_Dir&                                  theNormal,
+                TopoDS_Shape&                            theNextVertex,
+                TopoDS_Shape&                            theNextEdge,
+                gp_Dir&                                  theNextDir)
+{
+  const BOPCol_ListOfShape& anEdgesList = theVertexEdgeMap.FindFromKey(theStartVertex);
+  BOPCol_ListOfShape::Iterator aEdIter(anEdgesList);
+  double aBestEdgeProj = DBL_MAX;
+  for ( ; aEdIter.More(); aEdIter.Next())
+  {
+    gp_Dir aTang = getOuterEdgeDirection(aEdIter.Value(), theStartVertex);
+    aTang.Reverse();
+
+    // The projection is normalized in segment (-1, 1),
+    // where (-1, 0] corresponds to the angles (pi/2, 0] between theStartDir and aTang
+    // and [0, 1) corresponds to the angles [0, -pi/2)
+    double aProj = (aTang.Dot(theStartDir) - 1.0) * 0.5;
+    if (fabs(fabs(aProj) - 1) < tolerance)
+      continue;
+    if (theStartDir.DotCross(aTang, theNormal) < tolerance)
+      aProj *= -1.0;
+
+    if (aProj < aBestEdgeProj)
+    {
+      aBestEdgeProj = aProj;
+      theNextEdge = aEdIter.Value();
+      TopExp_Explorer aVertExp(theNextEdge, TopAbs_VERTEX);
+      for ( ; aVertExp.More(); aVertExp.Next())
+        if (aVertExp.Current().TShape() != theStartVertex.TShape())
+        {
+          theNextVertex = aVertExp.Current();
+          theNextDir = getOuterEdgeDirection(aEdIter.Value(), theNextVertex);
+          break;
+        }
+    }
+  }
+}
+
+static void addEdgeToWire(const TopoDS_Edge&  theEdge,
+                          const BRep_Builder& theBuilder,
+                                TopoDS_Shape& theSpliceVertex,
+                                TopoDS_Wire&  theWire)
+{
+  bool isCurVertChanged = false;
+  TopoDS_Shape aCurVertChanged;
+
+  TopExp_Explorer aVertExp(theEdge, TopAbs_VERTEX);
+  for ( ; aVertExp.More(); aVertExp.Next())
+  {
+    const TopoDS_Shape& aVertex = aVertExp.Current();
+    if (aVertex.TShape() == theSpliceVertex.TShape() && 
+        aVertex.Orientation() != theEdge.Orientation())
+    { // Current vertex is the last for the edge, so its orientation is wrong, need to revert the edge
+      const Handle(BRep_TEdge)& aTEdge = (const Handle(BRep_TEdge)&)theEdge.TShape();
+      Handle(BRep_Curve3D) aEdgeCurve = 
+        Handle(BRep_Curve3D)::DownCast(aTEdge->Curves().First());
+      Handle(Geom_Curve) aCurve = aEdgeCurve->Curve3D();
+      aCurve->Reverse();
+
+      theBuilder.UpdateEdge(theEdge, aCurve, aTEdge->Tolerance());
+      break;
+    }
+    if (aVertex.TShape() != theSpliceVertex.TShape())
+    {
+      aCurVertChanged = aVertex;
+      isCurVertChanged = true;
+    }
+  }
+  theSpliceVertex = isCurVertChanged ? aCurVertChanged : aVertExp.Current();
+
+  theBuilder.Add(theWire, theEdge);
+}
+
+void createFace(const TopoDS_Shape&                      theStartVertex,
+                const std::list<TopoDS_Shape>::iterator& theStartEdge,
+                const std::list<TopoDS_Shape>::iterator& theEndOfEdges,
+                      TopoDS_Face&                       theResFace)
+{
+  TopoDS_Wire aResWire;
+  BRep_Builder aBuilder;
+  aBuilder.MakeWire(aResWire);
+
+  TopoDS_Shape aCurVertex = theStartVertex;
+  std::list<TopoDS_Shape>::const_iterator anEdgeIter = theStartEdge;
+  for ( ; anEdgeIter != theEndOfEdges; anEdgeIter++)
+  {
+    TopoDS_Edge anEdge = *((TopoDS_Edge*)(&(*anEdgeIter)));
+    addEdgeToWire(anEdge, aBuilder, aCurVertex, aResWire);
+  }
+
+  BRepBuilderAPI_MakeFace aFaceBuilder(aResWire, Standard_True/*planar face*/);
+  if (aFaceBuilder.Error() == BRepBuilderAPI_FaceDone)
+    theResFace = aFaceBuilder.Face();
+}
+
+void createWireList(const TopoDS_Shape&                      theStartVertex,
+                    const std::list<TopoDS_Shape>::iterator& theStartEdge,
+                    const std::list<TopoDS_Shape>::iterator& theEndOfEdges,
+                    const std::set<Handle(TopoDS_TShape)>&   theEdgesInLoops,
+                          std::list<TopoDS_Wire>&            theResWires)
+{
+  BRep_Builder aBuilder;
+  bool needNewWire = true;
+  TopoDS_Shape aCurVertex = theStartVertex;
+
+  std::list<TopoDS_Shape>::iterator anIter = theStartEdge;
+  while (anIter != theEndOfEdges)
+  {
+    while (anIter != theEndOfEdges && needNewWire && 
+           theEdgesInLoops.count(anIter->TShape()) != 0)
+    {
+      TopExp_Explorer aVertExp(*anIter, TopAbs_VERTEX);
+      for ( ; aVertExp.More(); aVertExp.Next())
+        if (aVertExp.Current().TShape() != aCurVertex.TShape())
+        {
+          aCurVertex = aVertExp.Current();
+          break;
+        }
+      anIter++;
+    }
+    if (anIter == theEndOfEdges)
+      break;
+
+    if (needNewWire)
+    { // The new wire should be created
+      TopoDS_Wire aWire;
+      aBuilder.MakeWire(aWire);
+      theResWires.push_back(aWire);
+      needNewWire = false;
+    }
+    else if (theEdgesInLoops.count(anIter->TShape()) != 0)
+    { // There was found the edge already used in loop.
+      // Current wire should be released and new one should started
+      needNewWire = true;
+      continue;
+    }
+
+    TopoDS_Edge anEdge = *((TopoDS_Edge*)(&(*anIter)));
+    addEdgeToWire(anEdge, aBuilder, aCurVertex, theResWires.back());
+    anIter++;
+  }
+}
+
+
+gp_Dir getOuterEdgeDirection(const TopoDS_Shape& theEdge,
+                             const TopoDS_Shape& theVertex)
+{
+  const Handle(BRep_TVertex)& aVertex = (const Handle(BRep_TVertex)&)theVertex.TShape();
+  gp_Pnt aVertexPnt = aVertex->Pnt();
+
+  const Handle(BRep_TEdge)& anEdge = (const Handle(BRep_TEdge)&)theEdge.TShape();
+
+  // Convert the edge to the curve to calculate the tangency.
+  // There should be only one curve in the edge.
+  Handle(BRep_Curve3D) aEdCurve = 
+    Handle(BRep_Curve3D)::DownCast(anEdge->Curves().First());
+  double aFirst, aLast;
+  aEdCurve->Range(aFirst, aLast);
+  Handle(Geom_Curve) aCurve = aEdCurve->Curve3D();
+
+  gp_Pnt aPnt;
+  gp_Vec aTang;
+  aCurve->D1(aFirst, aPnt, aTang);
+  if (aVertexPnt.IsEqual(aPnt, tolerance))
+    return gp_Dir(aTang.Reversed());
+
+  aCurve->D1(aLast,  aPnt, aTang);
+  return gp_Dir(aTang);
+}
+
+void removeWasteEdges(
+                std::list<TopoDS_Shape>::iterator&  theStartVertex,
+                std::list<TopoDS_Shape>::iterator&  theStartEdge,
+          const std::list<TopoDS_Shape>::iterator&  theEndOfVertexes,
+          const std::list<TopoDS_Shape>::iterator&  theEndOfEdges,
+          BOPCol_IndexedDataMapOfShapeListOfShape&  theMapVE)
+{
+  bool isVertStep = true;
+  while (theStartVertex != theEndOfVertexes && theStartEdge != theEndOfEdges)
+  {
+    BOPCol_ListOfShape& aBunch = theMapVE.ChangeFromKey(*theStartVertex);
+    BOPCol_ListOfShape::Iterator anApprEdge(aBunch);
+    for ( ; anApprEdge.More(); anApprEdge.Next())
+      if (anApprEdge.Value() == *theStartEdge)
+        break;
+    if (anApprEdge.More())
+      aBunch.Remove(anApprEdge);
+
+    if (isVertStep)
+      theStartVertex++;
+    else
+    {
+      theStartEdge++;
+      // check current vertex to be a branching point
+      // if so, it will be a new starting point to find a loop
+      if (aBunch.Size() > 1)
+        break;
+    }
+    isVertStep = !isVertStep;
+  }
+
+  // The map of vertex-edges may be changed
+  BOPCol_IndexedDataMapOfShapeListOfShape aMapVECopy;
+  BOPCol_IndexedDataMapOfShapeListOfShape::Iterator aMapIter(theMapVE);
+  for (int ind = 1; aMapIter.More(); aMapIter.Next(), ind++)
+    if (!aMapIter.Value().IsEmpty())
+      aMapVECopy.Add(theMapVE.FindKey(ind), aMapIter.Value());
+  theMapVE.Clear();
+  theMapVE.Exchange(aMapVECopy);
+}
+
diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.h b/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.h
new file mode 100644 (file)
index 0000000..eb1587a
--- /dev/null
@@ -0,0 +1,49 @@
+// File:        GeomAlgoAPI_SketchBuilder.h
+// Created:     02 Jun 2014
+// Author:      Artem ZHIDKOV
+
+#ifndef GeomAlgoAPI_SketchBuilder_HeaderFile
+#define GeomAlgoAPI_SketchBuilder_HeaderFile
+
+#include <GeomAlgoAPI.h>
+
+#include <boost/shared_ptr.hpp>
+#include <list>
+
+#include <GeomAPI_Dir.h>
+#include <GeomAPI_Shape.h>
+
+/** \class GeomAlgoAPI_SketchBuilder
+ *  \ingroup DataAlgo
+ *  \brief Creates planar faces based on the list of Sketch features
+ */
+class GEOMALGOAPI_EXPORT GeomAlgoAPI_SketchBuilder
+{
+public:
+  /** \brief Creates list of faces and unclosed wires on basis of the features of the sketch
+   *  \param[in]  theDirX        x-direction of the sketch
+   *  \param[in]  theDirY        y-direction of the sketch
+   *  \param[in]  theNorm        normal of the sketch
+   *  \param[in]  theFeatures    initial features of the sketch
+   *  \param[out] theResultFaces faces based on closed wires
+   *  \param[out] theResultWires unclosed wires of the sketch
+   *
+   *  The algorithm searches all loops of edges surrounding lesser squares.
+   *  It finds the vertex with minimal coordinates along X axis (theDirX) and then 
+   *  goes through the edges passing the surrounding area on the left.
+   */
+  static void createFaces(const boost::shared_ptr<GeomAPI_Dir>&                theDirX,
+                          const boost::shared_ptr<GeomAPI_Dir>&                theDirY,
+                          const boost::shared_ptr<GeomAPI_Dir>&                theNorm,
+                          const std::list< boost::shared_ptr<GeomAPI_Shape> >& theFeatures,
+                                std::list< boost::shared_ptr<GeomAPI_Shape> >& theResultFaces,
+                                std::list< boost::shared_ptr<GeomAPI_Shape> >& theResultWires);
+
+  /** \brief Searches intersections between the faces in the list 
+   *         and make holes in the faces to avoid intersections
+   *  \param[in,out] theFaces list of faces to proccess
+   */
+  static void fixIntersections(std::list< boost::shared_ptr<GeomAPI_Shape> >& theFaces);
+};
+
+#endif
index 22c359484374cdee38fcc68eda2918bc4fa64045..4593a68fe499a7c5c8ed37b28979c1f9d8238bc9 100644 (file)
@@ -20,6 +20,7 @@ SET(PROJECT_SOURCES
        ModuleBase_IOperation.cpp
        ModuleBase_Operation.cpp
        ModuleBase_OperationDescription.cpp
+       ModuleBase_ModelWidget.cpp
        ModuleBase_WidgetBoolValue.cpp
        ModuleBase_WidgetDoubleValue.cpp
        ModuleBase_WidgetFactory.cpp
diff --git a/src/ModuleBase/ModuleBase_ModelWidget.cpp b/src/ModuleBase/ModuleBase_ModelWidget.cpp
new file mode 100644 (file)
index 0000000..089b1e6
--- /dev/null
@@ -0,0 +1,38 @@
+// File:        ModuleBase_ModelWidget.h
+// Created:     25 Apr 2014
+// Author:      Natalia ERMOLAEVA
+
+#include "ModuleBase_ModelWidget.h"
+
+#include "Config_WidgetAPI.h"
+
+#include <QWidget>
+
+ModuleBase_ModelWidget::ModuleBase_ModelWidget(QObject* theParent, const Config_WidgetAPI* theData)
+ : QObject(theParent)
+{
+  myAttributeID = theData ? theData->widgetId() : "";
+}
+
+bool ModuleBase_ModelWidget::canFocusTo(const std::string& theAttributeName) const
+{
+  return theAttributeName == attributeID();
+}
+
+void ModuleBase_ModelWidget::focusTo()
+{
+  QList<QWidget*> aControls = getControls();
+  QList<QWidget*>::const_iterator anIt = aControls.begin(), aLast = aControls.end();
+  for (; anIt != aLast; anIt++) {
+    QWidget* aWidget = *anIt;
+    if (aWidget && aWidget->focusPolicy() != Qt::NoFocus) {
+      aWidget->setFocus();
+      break;
+    }
+  }
+}
+
+std::string ModuleBase_ModelWidget::attributeID() const
+{
+  return myAttributeID;
+}
index c203579420b29a78e13f0c0d7e907d9678e348ab..286d16f06b2baeeda38fc5875ce3b8789ff915e9 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <boost/shared_ptr.hpp>
 
+class Config_WidgetAPI;
 class ModelAPI_Feature;
 class QKeyEvent;
 
@@ -30,7 +31,8 @@ class MODULEBASE_EXPORT ModuleBase_ModelWidget : public QObject
 public:
   /// Constructor
   /// \theParent the parent object
-  ModuleBase_ModelWidget(QObject* theParent) :QObject(theParent) {};
+  /// \theData the widget configuation. The attribute of the model widget is obtained from
+  ModuleBase_ModelWidget(QObject* theParent, const Config_WidgetAPI* theData);
   /// Destructor
   virtual ~ModuleBase_ModelWidget() {};
 
@@ -42,10 +44,11 @@ public:
 
   /// Returns whether the widget can accept focus, or if it corresponds to the given attribute
   /// \param theAttribute name
-  virtual bool canFocusTo(const std::string& theAttributeName) const { return false; }
+  bool canFocusTo(const std::string& theAttributeName) const;
 
-  /// Set focus to the current widget if it corresponds to the given attribute
-  virtual void focusTo() {}
+  /// Set focus to the first control of the current widget. The focus policy of the control is checked.
+  /// If the widget has the NonFocus focus policy, it is skipped.
+  virtual void focusTo();
 
   /// Returns list of widget controls
   /// \return a control list
@@ -58,6 +61,14 @@ signals:
   /// \param theAttributeName a name of the attribute
   /// \param theEvent key release event
   void keyReleased(const std::string& theAttributeName, QKeyEvent* theEvent);
+
+protected:
+  /// Returns the attribute name
+  /// \returns the string value
+  std::string attributeID() const;
+
+private:
+  std::string myAttributeID; /// the attribute name of the model feature
 };
 
 #endif
index f6945234c70eaff528582abe1819314cc5688087..f3f19b152adac3eb91733aa5463e41638e5d44cd 100644 (file)
 ModuleBase_SelectorWidget::ModuleBase_SelectorWidget(QWidget* theParent, 
                                                      ModuleBase_IWorkshop* theWorkshop, 
                                                      const Config_WidgetAPI* theData)
-: ModuleBase_ModelWidget(theParent), myWorkshop(theWorkshop), myActivateOnStart(false)
+: ModuleBase_ModelWidget(theParent, theData), myWorkshop(theWorkshop), myActivateOnStart(false)
 {
-  myFeatureAttributeID = theData->widgetId();
-
   myContainer = new QWidget(theParent);
   QHBoxLayout* aLayout = new QHBoxLayout(myContainer);
 
@@ -74,7 +72,7 @@ bool ModuleBase_SelectorWidget::storeValue(FeaturePtr theFeature) const
 {
   DataPtr aData = theFeature->data();
   boost::shared_ptr<ModelAPI_AttributeReference> aRef = 
-    boost::dynamic_pointer_cast<ModelAPI_AttributeReference>(aData->attribute(myFeatureAttributeID));
+    boost::dynamic_pointer_cast<ModelAPI_AttributeReference>(aData->attribute(attributeID()));
 
   FeaturePtr aFeature = aRef->value();
   if (!(aFeature && aFeature->isSame(mySelectedFeature))) {
@@ -88,7 +86,7 @@ bool ModuleBase_SelectorWidget::storeValue(FeaturePtr theFeature) const
 bool ModuleBase_SelectorWidget::restoreValue(FeaturePtr theFeature)
 {
   DataPtr aData = theFeature->data();
-  boost::shared_ptr<ModelAPI_AttributeReference> aRef = aData->reference(myFeatureAttributeID);
+  boost::shared_ptr<ModelAPI_AttributeReference> aRef = aData->reference(attributeID());
 
   bool isBlocked = this->blockSignals(true);
   mySelectedFeature = aRef->value();
index 45ef3d64f82edbb7f0260c5b2d5a71879e7c0e9c..48e3984ff13e994307bd8c856b35c4dfb2854cb6 100644 (file)
@@ -63,8 +63,6 @@ private:
   void updateSelectionName();
   void raisePanel() const;
 
-  std::string myFeatureAttributeID;
-
   QWidget*     myContainer;
   QLabel*      myLabel;
   QLineEdit*   myTextLine;
index d55bd18e05620013e0f3c6abd7c8b3df079ef6c2..a34a73d6f02bedf6c2250345486d16cff2c3dff3 100644 (file)
@@ -4,7 +4,6 @@
 
 #include <ModuleBase_WidgetBoolValue.h>
 
-#include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeBoolean.h>
 #include <ModelAPI_Data.h>
 
 
 #include <QWidget>
 #include <QLayout>
-#include <QLabel>
-#include <QDoubleSpinBox>
 #include <QCheckBox>
 
 ModuleBase_WidgetBoolValue::ModuleBase_WidgetBoolValue(QWidget* theParent, const Config_WidgetAPI* theData)
-  : ModuleBase_ModelWidget(theParent)
+  : ModuleBase_ModelWidget(theParent, theData)
 {
-  myAttributeID = theData->widgetId();
   QString aText = QString::fromStdString(theData->widgetLabel());
   QString aToolTip = QString::fromStdString(theData->widgetTooltip());
   QString aDefault = QString::fromStdString(theData->getProperty("default"));
@@ -47,7 +43,7 @@ QWidget* ModuleBase_WidgetBoolValue::getControl() const
 bool ModuleBase_WidgetBoolValue::storeValue(FeaturePtr theFeature) const
 {
   DataPtr aData = theFeature->data();
-  boost::shared_ptr<ModelAPI_AttributeBoolean> aBool = aData->boolean(myAttributeID);
+  boost::shared_ptr<ModelAPI_AttributeBoolean> aBool = aData->boolean(attributeID());
 
   if (aBool->value() != myCheckBox->isChecked()) {
     aBool->setValue(myCheckBox->isChecked());
@@ -59,7 +55,7 @@ bool ModuleBase_WidgetBoolValue::storeValue(FeaturePtr theFeature) const
 bool ModuleBase_WidgetBoolValue::restoreValue(FeaturePtr theFeature)
 {
   DataPtr aData = theFeature->data();
-  boost::shared_ptr<ModelAPI_AttributeBoolean> aRef = aData->boolean(myAttributeID);
+  boost::shared_ptr<ModelAPI_AttributeBoolean> aRef = aData->boolean(attributeID());
 
   bool isBlocked = myCheckBox->blockSignals(true);
   myCheckBox->setChecked(aRef->value());
index 8753c4cfd5ba91dca9377c8a4a465ce9d8d21253..6f32ef3ef87183b2961ead0fb7389d444a4a77c9 100644 (file)
 
 class Config_WidgetAPI;
 class QWidget;
-class QLabel;
-class QDoubleSpinBox;
 class QCheckBox;
 
 class MODULEBASE_EXPORT ModuleBase_WidgetBoolValue: public ModuleBase_ModelWidget
 {
   Q_OBJECT
 public:
+  /// Constructor
+  /// \theParent the parent object
+  /// \theData the widget configuation. The attribute of the model widget is obtained from
   ModuleBase_WidgetBoolValue(QWidget* theParent, const Config_WidgetAPI* theData);
 
   virtual ~ModuleBase_WidgetBoolValue();
@@ -37,8 +38,6 @@ public:
   QWidget* getControl() const;
 
 private:
-  std::string myAttributeID;
-  
   QCheckBox* myCheckBox;
 };
 
index d65091fd1a321cc2e97e3257a404baf660b20152..0824da5b414ac1e73ec5bfe3070031ce317dab28 100644 (file)
@@ -5,7 +5,6 @@
 #include <ModuleBase_WidgetDoubleValue.h>
 
 #include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_AttributeBoolean.h>
 #include <ModelAPI_Data.h>
 
 #include <Config_Keywords.h>
 #include <QLayout>
 #include <QLabel>
 #include <QDoubleSpinBox>
-#include <QCheckBox>
+#include <QEvent>
+#include <QKeyEvent>
 
 
 ModuleBase_WidgetDoubleValue::ModuleBase_WidgetDoubleValue(QWidget* theParent, const Config_WidgetAPI* theData)
-  : ModuleBase_ModelWidget(theParent)
+  : ModuleBase_ModelWidget(theParent, theData)
 {
   myContainer = new QWidget(theParent);
   QHBoxLayout* aControlLay = new QHBoxLayout(myContainer);
@@ -34,9 +34,8 @@ ModuleBase_WidgetDoubleValue::ModuleBase_WidgetDoubleValue(QWidget* theParent, c
   myLabel->setPixmap(QPixmap(aLabelIcon));
   aControlLay->addWidget(myLabel);
 
-  myAttributeID = theData->widgetId();
   mySpinBox = new QDoubleSpinBox(myContainer);
-  QString anObjName = QString::fromStdString(myAttributeID);
+  QString anObjName = QString::fromStdString(attributeID());
   mySpinBox->setObjectName(anObjName);
 
   bool isOk = false;
@@ -75,6 +74,8 @@ ModuleBase_WidgetDoubleValue::ModuleBase_WidgetDoubleValue(QWidget* theParent, c
   aControlLay->setStretch(1, 1);
 
   connect(mySpinBox, SIGNAL(valueChanged(double)), this, SIGNAL(valuesChanged()));
+
+  mySpinBox->installEventFilter(this);
 }
 
 ModuleBase_WidgetDoubleValue::~ModuleBase_WidgetDoubleValue()
@@ -84,7 +85,7 @@ ModuleBase_WidgetDoubleValue::~ModuleBase_WidgetDoubleValue()
 bool ModuleBase_WidgetDoubleValue::storeValue(FeaturePtr theFeature) const
 {
   DataPtr aData = theFeature->data();
-  boost::shared_ptr<ModelAPI_AttributeDouble> aReal = aData->real(myAttributeID);
+  boost::shared_ptr<ModelAPI_AttributeDouble> aReal = aData->real(attributeID());
   if (aReal->value() != mySpinBox->value()) {
     aReal->setValue(mySpinBox->value());
     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
@@ -95,7 +96,7 @@ bool ModuleBase_WidgetDoubleValue::storeValue(FeaturePtr theFeature) const
 bool ModuleBase_WidgetDoubleValue::restoreValue(FeaturePtr theFeature)
 {
   DataPtr aData = theFeature->data();
-  boost::shared_ptr<ModelAPI_AttributeDouble> aRef = aData->real(myAttributeID);
+  boost::shared_ptr<ModelAPI_AttributeDouble> aRef = aData->real(attributeID());
 
   bool isBlocked = mySpinBox->blockSignals(true);
   mySpinBox->setValue(aRef->value());
@@ -111,3 +112,14 @@ QList<QWidget*> ModuleBase_WidgetDoubleValue::getControls() const
   aList.append(mySpinBox);
   return aList;
 }
+
+bool ModuleBase_WidgetDoubleValue::eventFilter(QObject *theObject, QEvent *theEvent)
+{
+  if (theObject == mySpinBox) {
+    if (theEvent->type() == QEvent::KeyRelease) {
+      emit keyReleased(attributeID(), (QKeyEvent*) theEvent);
+      return true;
+    }
+  }
+  return ModuleBase_ModelWidget::eventFilter(theObject, theEvent);
+}
index caab1955678fb6350606ba9f138f2afb33574aac..70f6de58ce510344ae127d927bd18313b9a0c578 100644 (file)
@@ -12,12 +12,14 @@ class Config_WidgetAPI;
 class QWidget;
 class QLabel;
 class QDoubleSpinBox;
-class QCheckBox;
 
 class MODULEBASE_EXPORT ModuleBase_WidgetDoubleValue: public ModuleBase_ModelWidget
 {
   Q_OBJECT
 public:
+  /// Constructor
+  /// \theParent the parent object
+  /// \theData the widget configuation. The attribute of the model widget is obtained from
   ModuleBase_WidgetDoubleValue(QWidget* theParent, const Config_WidgetAPI* theData);
 
   virtual ~ModuleBase_WidgetDoubleValue();
@@ -36,9 +38,12 @@ public:
   /// \returns the widget
   QWidget* getControl() const { return myContainer; }
 
+  /// Process key release envent on the widget spin box controls
+  /// \param theObject the object where the event happens
+  /// \param theEvent the processed event
+  virtual bool eventFilter(QObject *theObject, QEvent *theEvent);
+
 private:
-  std::string myAttributeID;
-  
   QWidget*     myContainer;
   QLabel*      myLabel;
   QDoubleSpinBox* mySpinBox;
index 1f2f6a673f3fe603a9b8df7adca4f5400123a1b3..4c011a454f7d05974be69764bf676f708b2d3af9 100644 (file)
@@ -163,9 +163,7 @@ QWidget* ModuleBase_WidgetFactory::doubleSpinBoxControl(QWidget* theParent)
 
 QWidget* ModuleBase_WidgetFactory::pointSelectorControl(QWidget* theParent)
 {
-  ModuleBase_WidgetPoint2D* aWidget = new ModuleBase_WidgetPoint2D(theParent,
-                       qs(myWidgetApi->getProperty(CONTAINER_PAGE_NAME)),
-                       myWidgetApi->widgetId());
+  ModuleBase_WidgetPoint2D* aWidget = new ModuleBase_WidgetPoint2D(theParent, myWidgetApi);
   connectWidget(aWidget, WDG_POINT_SELECTOR);
   myModelWidgets.append(aWidget);
   return aWidget->getControl();
index 2d8c814798d423fb16cbbe8a1f1dee2bc1865ae9..4bfda9ed88af3056e82806e180c2b9d7b7dddcba 100644 (file)
@@ -5,6 +5,7 @@
 #include <ModuleBase_WidgetPoint2D.h>
 
 #include <Config_Keywords.h>
+#include <Config_WidgetAPI.h>
 
 #include <Events_Loop.h>
 #include <Model_Events.h>
 #include <cfloat>
 #include <climits>
 
-ModuleBase_WidgetPoint2D::ModuleBase_WidgetPoint2D(QWidget* theParent, QString theTitle,
-                                                   const std::string& theFeatureAttributeID)
-: ModuleBase_ModelWidget(theParent), myFeatureAttributeID(theFeatureAttributeID)
+ModuleBase_WidgetPoint2D::ModuleBase_WidgetPoint2D(QWidget* theParent,
+                                                   const Config_WidgetAPI* theData)
+: ModuleBase_ModelWidget(theParent, theData)
 {
-  myGroupBox = new QGroupBox(theTitle, theParent);
+  myGroupBox = new QGroupBox(QString::fromStdString(theData->getProperty(CONTAINER_PAGE_NAME)),
+                             theParent);
   QGridLayout* aGroupLay = new QGridLayout(myGroupBox);
   aGroupLay->setContentsMargins(0, 0, 0, 0);
   aGroupLay->setColumnStretch(1, 1);
@@ -72,7 +74,7 @@ bool ModuleBase_WidgetPoint2D::storeValue(FeaturePtr theFeature) const
 {
   boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
   boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
-    boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(myFeatureAttributeID));
+    boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(attributeID()));
 
   ModuleBase_WidgetPoint2D* that = (ModuleBase_WidgetPoint2D*) this;
   bool isBlocked = that->blockSignals(true);
@@ -87,7 +89,7 @@ bool ModuleBase_WidgetPoint2D::restoreValue(FeaturePtr theFeature)
 {
   boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
   boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
-    boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(myFeatureAttributeID));
+    boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(attributeID()));
 
   bool isBlocked = this->blockSignals(true);
   myXSpin->setValue(aPoint->x());
@@ -96,17 +98,6 @@ bool ModuleBase_WidgetPoint2D::restoreValue(FeaturePtr theFeature)
   return true;
 }
 
-bool ModuleBase_WidgetPoint2D::canFocusTo(const std::string& theAttributeName)
-{
-  return theAttributeName == myFeatureAttributeID;
-}
-
-void ModuleBase_WidgetPoint2D::focusTo()
-{
-  if (!myXSpin->hasFocus() && !myYSpin->hasFocus())
-    myXSpin->setFocus();
-}
-
 QWidget* ModuleBase_WidgetPoint2D::getControl() const
 {
   return myGroupBox;
@@ -125,7 +116,7 @@ bool ModuleBase_WidgetPoint2D::eventFilter(QObject *theObject, QEvent *theEvent)
 {
   if (theObject == myXSpin || theObject == myYSpin) {
     if (theEvent->type() == QEvent::KeyRelease) {
-      emit keyReleased(myFeatureAttributeID, (QKeyEvent*) theEvent);
+      emit keyReleased(attributeID(), (QKeyEvent*) theEvent);
       return true;
     }
   }
index 85c4c938d5aa0e6dfd69a2b768debcfd44f74bff..bb0f7c84dbfa966a76577a623ae8bdefb43793ca 100644 (file)
@@ -25,10 +25,9 @@ class MODULEBASE_EXPORT ModuleBase_WidgetPoint2D : public ModuleBase_ModelWidget
 public:
   /// Constructor
   /// \theParent the parent object
-  /// \theTitle the group box title
-  /// \theFeatureAttributeID the identifier of the feature attribute
-  ModuleBase_WidgetPoint2D(QWidget* theParent, QString theTitle,
-                           const std::string& theFeatureAttributeID);
+  /// \theParent the parent object
+  /// \theData the widget configuation. The attribute of the model widget is obtained from
+  ModuleBase_WidgetPoint2D(QWidget* theParent, const Config_WidgetAPI* theData);
   /// Destructor
   virtual ~ModuleBase_WidgetPoint2D();
 
@@ -38,13 +37,6 @@ public:
 
   virtual bool restoreValue(FeaturePtr theFeature);
 
-  /// Returns whether the widget can accept focus, or if it corresponds to the given attribute
-  /// \param theAttribute name
-  virtual bool canFocusTo(const std::string& theAttributeName);
-
-  /// Set focus to the current widget if it corresponds to the given attribute
-  virtual void focusTo();
-
   /// Returns the internal parent wiget control, that can be shown anywhere
   /// \returns the widget
   QWidget* getControl() const;
@@ -53,10 +45,12 @@ public:
   /// \return a control list
   virtual QList<QWidget*> getControls() const;
 
+  /// Process key release envent on the widget spin box controls
+  /// \param theObject the object where the event happens
+  /// \param theEvent the processed event
   virtual bool eventFilter(QObject *theObject, QEvent *theEvent);
 
 private:
-  std::string myFeatureAttributeID; ///< the identifier of the feature attribute
   QGroupBox* myGroupBox; ///< the parent group box for all intenal widgets
   QDoubleSpinBox* myXSpin; ///< the spin box for the X coordinate
   QDoubleSpinBox* myYSpin; ///< the spin box for the Y coordinate
index d2c111990d926303e5c6197e3655ce4cc2552572..850058e8c1d438da7edb4a59c41fcac9d05ded49 100644 (file)
@@ -10,6 +10,7 @@
 #include <GeomDataAPI_Point.h>
 #include <GeomAlgoAPI_FaceBuilder.h>
 #include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_SketchBuilder.h>
 
 using namespace std;
 
@@ -31,6 +32,42 @@ void SketchPlugin_Sketch::initAttributes()
 
 void SketchPlugin_Sketch::execute() 
 {
+  if (!data()->isValid())
+    return ;
+  boost::shared_ptr<ModelAPI_AttributeRefList> aRefList =
+    boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(data()->attribute(SKETCH_ATTR_FEATURES));
+
+  boost::shared_ptr<GeomDataAPI_Dir> aDirX = 
+    boost::dynamic_pointer_cast<GeomDataAPI_Dir>(data()->attribute(SKETCH_ATTR_DIRX));
+  boost::shared_ptr<GeomDataAPI_Dir> aDirY = 
+    boost::dynamic_pointer_cast<GeomDataAPI_Dir>(data()->attribute(SKETCH_ATTR_DIRY));
+  boost::shared_ptr<GeomDataAPI_Dir> aNorm = 
+    boost::dynamic_pointer_cast<GeomDataAPI_Dir>(data()->attribute(SKETCH_ATTR_NORM));
+
+  std::list<boost::shared_ptr<ModelAPI_Feature> > aFeatures = aRefList->list();
+  if (aFeatures.empty())
+    return ;
+
+  std::list<boost::shared_ptr<ModelAPI_Feature> >::const_iterator anIt = aFeatures.begin(),
+                                                                  aLast = aFeatures.end();
+
+  boost::shared_ptr<SketchPlugin_Feature> aFeature;
+  std::list< boost::shared_ptr<GeomAPI_Shape> > aFeaturesPreview;
+  for (; anIt != aLast; anIt++) {
+    aFeature = boost::dynamic_pointer_cast<SketchPlugin_Feature>(*anIt);
+    boost::shared_ptr<GeomAPI_Shape> aPreview = aFeature->preview();
+    if (aPreview)
+      aFeaturesPreview.push_back(aPreview);
+  }
+
+  std::list< boost::shared_ptr<GeomAPI_Shape> > aLoops;
+  std::list< boost::shared_ptr<GeomAPI_Shape> > aWires;
+  GeomAlgoAPI_SketchBuilder::createFaces(aDirX->dir(), aDirY->dir(), aNorm->dir(),
+                                         aFeaturesPreview, aLoops, aWires);
+
+  aLoops.insert(aLoops.end(), aWires.begin(), aWires.end());
+  boost::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aLoops);
+  data()->store(aCompound);
 }
 
 const boost::shared_ptr<GeomAPI_Shape>& SketchPlugin_Sketch::preview()