Salome HOME
First implementation of the sketch drawer: helper for creation of sketch on imported...
authormpv <mpv@opencascade.com>
Wed, 28 Nov 2018 14:24:45 +0000 (17:24 +0300)
committermpv <mpv@opencascade.com>
Wed, 28 Nov 2018 14:24:45 +0000 (17:24 +0300)
14 files changed:
src/FeaturesPlugin/FeaturesPlugin_Validators.cpp
src/GeomAPI/GeomAPI_Pln.cpp
src/GeomAPI/GeomAPI_Pln.h
src/GeomAlgoAPI/GeomAlgoAPI_ShapeTools.cpp
src/Model/Model_AttributeSelection.cpp
src/Model/Model_Document.h
src/Model/Model_Update.cpp
src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/SketchPlugin_Line.h
src/SketchPlugin/SketchPlugin_Plugin.cpp
src/SketchPlugin/SketchPlugin_SketchDrawer.cpp [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_SketchDrawer.h [new file with mode: 0644]
src/SketchPlugin/icons/drawer.png [new file with mode: 0644]
src/SketchPlugin/plugin-Sketch.xml

index bc2f92a4d19534c14d4f8a9b57e1f08dc71d17cc..724b9d5abe645a1706f0ecb490330b4a192c218a 100644 (file)
@@ -411,7 +411,7 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute
     if (aContext.get())
       aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
     if(aConstruction.get()) {
-      // Construciotn selected. Check that is is not infinite.
+      // Construction selected. Check that it is not infinite.
       if(aConstruction->isInfinite()) {
         theError = "Error: Infinite constructions is not allowed as base.";
         return false;
@@ -430,7 +430,6 @@ bool FeaturesPlugin_ValidatorBaseForGeneration::isValidAttribute(const Attribute
           return true;
         }
       }
-
       return false;
     }
 
index 60e417c7c5df4d79f6c29ab2f9ecb2c8533f2c86..9ccd1a9508fad214b29e838c3e91efb227fc1a7e 100644 (file)
@@ -120,6 +120,13 @@ double GeomAPI_Pln::distance(const std::shared_ptr<GeomAPI_Pln> thePlane) const
   return aMyPln.Distance(anOtherPln);
 }
 
+double GeomAPI_Pln::distance(const std::shared_ptr<GeomAPI_Pnt> thePoint) const
+{
+  const gp_Pln& aMyPln = impl<gp_Pln>();
+  const gp_Pnt& aPnt = thePoint->impl<gp_Pnt>();
+  return aMyPln.Distance(aPnt);
+}
+
 void GeomAPI_Pln::translate(const std::shared_ptr<GeomAPI_Dir> theDir, double theDist)
 {
   gp_Vec aVec(theDir->impl<gp_Dir>());
index 863a72f617edfe1329eacf23220c0222a08bb000..af1d1fe7cf9a4c4b3fbf661083b6268ff3061593 100644 (file)
@@ -82,6 +82,10 @@ class GeomAPI_Pln : public GeomAPI_Interface
   GEOMAPI_EXPORT
   double distance(const std::shared_ptr<GeomAPI_Pln> thePlane) const;
 
+  /// \return distance from a point to this plane.
+  GEOMAPI_EXPORT
+  double distance(const std::shared_ptr<GeomAPI_Pnt> thePoint) const;
+
   /// Translates the plane along direction theDir on distance theDist
   GEOMAPI_EXPORT
   void translate(const std::shared_ptr<GeomAPI_Dir> theDir, const double theDist);
index a47c77c7f28d1fa298a72a1613b71a5eabdd06ff..a9390272b8aa6e6fd0fffac277a3a75432185e10 100644 (file)
@@ -234,14 +234,14 @@ std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::combineShapes(
     }
   }
 
-  // Map subshapes and shapes.
+  // Map sub-shapes and shapes.
   TopTools_IndexedDataMapOfShapeListOfShape aMapSA;
   TopExp::MapShapesAndAncestors(aShapesComp, aTS, aTA, aMapSA);
   if(aMapSA.IsEmpty()) {
     return aResult;
   }
 
-  // Get all shapes with common subshapes and free shapes.
+  // Get all shapes with common sub-shapes and free shapes.
   NCollection_Map<TopoDS_Shape> aFreeShapes;
   NCollection_Vector<NCollection_Map<TopoDS_Shape>> aShapesWithCommonSubshapes;
   for(TopTools_IndexedDataMapOfShapeListOfShape::Iterator
@@ -299,7 +299,7 @@ std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::combineShapes(
     }
   }
 
-  // Combine shapes with common subshapes.
+  // Combine shapes with common sub-shapes.
   for(NCollection_Vector<NCollection_Map<TopoDS_Shape>>::Iterator
       anIter(aShapesWithCommonSubshapes); anIter.More(); anIter.Next()) {
     TopoDS_Shell aShell;
@@ -444,7 +444,7 @@ std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::groupSharedTopology(
         aKeysIt.Next()) {
         const TopTools_ListOfShape& anOtherConnected = aVertexShapesMap(aKeysIt.Value());
         if (!anOtherConnected.Contains(aConnected)) {
-          // Other connected group does not containt shape from our connected group
+          // Other connected group does not contain shape from our connected group
           continue;
         }
         // Other is connected to our, so add them to our connected
index fd20f15660e9dd16c6288850f053670bc808d291..5b382b22100a121cc88f7ba40c9777ad6cdb37d2 100644 (file)
@@ -178,18 +178,6 @@ bool Model_AttributeSelection::setValue(const ObjectPtr& theContext,
     std::shared_ptr<GeomAPI_Shape> aSubShape;
     if (theSubShape.get() && !aConstruction->shape()->isEqual(theSubShape))
       aSubShape = theSubShape; // the whole context
-    if (aConstruction->isInfinite()) {
-      // For correct naming selection, put the shape into the naming structure.
-      // It seems sub-shapes are not needed: only this shape is (and can be) selected.
-      /*
-      TNaming_Builder aBuilder(aSelLab);
-      aBuilder.Generated(aConstruction->shape()->impl<TopoDS_Shape>());
-      std::string anInfinitiveName = contextName(aConstruction);
-      TDataStd_Name::Set(aSelLab, anInfinitiveName.c_str());
-      std::dynamic_pointer_cast<Model_Document>(owner()->document())
-        ->addNamingName(aSelLab, anInfinitiveName.c_str());
-        */
-    }
   } else if (theContext->groupName() == ModelAPI_ResultPart::group()) {
     aSelLab.ForgetAllAttributes(true);
     TDataStd_UAttribute::Set(aSelLab, kPART_REF_ID);
index 6704492421acce1afc9af777cf090749e8dd16e9..f4c6233d1c72cd18e37a588fda9c798295f3d6fe 100644 (file)
@@ -38,8 +38,8 @@ class ModelAPI_AttributeSelectionList;
 /**\class Model_Document
  * \ingroup DataModel
  * \brief Document for internal data structure of any object storage.
- * Document contains all data that must be stored/retrived in the file.
- * Also it provides acces to this data: open/save, transactions management etc.
+ * Document contains all data that must be stored/retrieved in the file.
+ * Also it provides access to this data: open/save, transactions management etc.
  */
 class Model_Document : public ModelAPI_Document
 {
@@ -66,11 +66,11 @@ class Model_Document : public ModelAPI_Document
     const char* theDirName, const char* theFileName, std::list<std::string>& theResults);
 
   //! Removes document data
-  //! \param theForever if it is false, document is just hiden
+  //! \param theForever if it is false, document is just hidden
   //!                   (to keep possibility make it back on Undo/Redo)
   MODEL_EXPORT virtual void close(const bool theForever = false);
 
-  //! Starts a new operation (opens a tansaction)
+  //! Starts a new operation (opens a transaction)
   MODEL_EXPORT virtual void startOperation();
   //! Finishes the previously started operation (closes the transaction)
   //! \returns true if transaction in this document is not empty and really was performed
@@ -82,11 +82,11 @@ class Model_Document : public ModelAPI_Document
   //! Returns true if document was modified (since creation/opening)
   MODEL_EXPORT virtual bool isModified();
 
-  //! Returns True if there are available Undos
+  //! Returns True if there are available Undo-s
   MODEL_EXPORT virtual bool canUndo();
   //! Undoes last operation
   MODEL_EXPORT virtual void undo();
-  //! Returns True if there are available Redos
+  //! Returns True if there are available Redo-s
   MODEL_EXPORT virtual bool canRedo();
   //! Redoes last operation
   MODEL_EXPORT virtual void redo();
@@ -176,15 +176,15 @@ class Model_Document : public ModelAPI_Document
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Feature> internalFeature(const int theIndex);
   //! Performs synchronization of transactions with the module document:
   //! If some document is not active (by undo of activation) but in memory,
-  //! on activation the transactions must be synchronised because all redos performed
-  //! wihtout this participation
+  //! on activation the transactions must be synchronized because all redo-s performed
+  //! without this participation
   MODEL_EXPORT virtual void synchronizeTransactions();
 
   //! Returns feature by the id of the feature (produced by the Data "featureId" method)
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Feature> featureById(const int theId);
 
 
-  /// Creates a construction cresults
+  /// Creates construction results
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_ResultConstruction> createConstruction(
       const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
   /// Creates a body results
@@ -229,7 +229,7 @@ class Model_Document : public ModelAPI_Document
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Folder> findFolderBelow(
       const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures);
   //! Search a folder containing the given feature.
-  //! Addtionally calculates a zero-based index of the feature in this folder.
+  //! Additionally calculates a zero-based index of the feature in this folder.
   //! \param theFeature feature to search
   //! \param theIndexInFolder zero-based index in the folder or -1 if the feature is top-level.
   //! \return the folder containing the feature or empty pointer if the feature is top-level.
@@ -238,7 +238,7 @@ class Model_Document : public ModelAPI_Document
       int& theIndexInFolder);
   //! Add a list of features to the folder. The correctness of the adding is not performed
   //! (such checks have been done in corresponding find.. method).
-  //! \return \c true if the movement is successfull
+  //! \return \c true if the movement is successful
   MODEL_EXPORT virtual bool moveToFolder(
       const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
       const std::shared_ptr<ModelAPI_Folder>& theFolder);
@@ -252,7 +252,7 @@ class Model_Document : public ModelAPI_Document
       const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
       const bool theBefore = true);
 
-  ///! Returns true if parametric updater need to execute feature on recomputartion
+  ///! Returns true if parametric updater need to execute feature on recomputation
   ///! On abort, undo or redo it is not necessary: results in document are updated automatically
   bool executeFeatures() {return myExecuteFeatures;}
 
@@ -321,22 +321,22 @@ class Model_Document : public ModelAPI_Document
   }
 
   //! performs compactification of all nested operations into one
-  //! \returns true if resulting transaction is not empty and can be undoed
+  //! \returns true if resulting transaction is not empty and can be undone
   void compactNested();
 
   //! Returns all loaded sub documents
   const std::set<int> subDocuments() const;
 
-  //! The implementation of undo: with or without recoursive calls in the sub-documents
+  //! The implementation of undo: with or without recursive calls in the sub-documents
   void undoInternal(const bool theWithSubs, const bool theSynchronize);
 
   //! Stores the Id of the current operation (normally is called for the root document)
   void operationId(const std::string& theId);
 
-  //! Returns the list of Ids of the operations that can be undoed (called for the root document)
+  //! Returns the list of Ids of the operations that can be undone (called for the root document)
   std::list<std::string> undoList() const;
 
-  //! Returns the list of Ids of the operations that can be redoed (called for the root document)
+  //! Returns the list of Ids of the operations that can be redone (called for the root document)
   std::list<std::string> redoList() const;
 
   //! Internally makes document know that feature was removed or added in history after creation
@@ -366,7 +366,7 @@ class Model_Document : public ModelAPI_Document
   /// Normally is called outside of the transaction, just before "save".
   virtual void storeNodesState(const std::list<bool>& theStates);
 
-  /// Returns the stored nodes states. Normally it is calles just after "open".
+  /// Returns the stored nodes states. Normally it is called just after "open".
   /// Appends the values to theStates list.
   virtual void restoreNodesState(std::list<bool>& theStates) const;
 
@@ -378,15 +378,15 @@ class Model_Document : public ModelAPI_Document
   /// searches in this document result that contains this label
   ResultPtr resultByLab(const TDF_Label& theLab);
 
-  /// returns true if theThis is later in the features trre and dependencies than theOther
+  /// returns true if theThis is later in the features tree and dependencies than theOther
   bool isLaterByDep(FeaturePtr theThis, FeaturePtr theOther);
 
   /// appends the latest transaction to the previous one (used for AutoUpdate enabling transaction)
   void appendTransactionToPrevious();
 
-  /// Sets the automatic recomutation flag: true means enabled
+  /// Sets the automatic recomputation flag: true means enabled
   void setAutoRecomutationState(const bool theState);
-  /// Returns the current automatic recomutation flag: true means enabled
+  /// Returns the current automatic recomputation flag: true means enabled
   bool autoRecomutationState() const;
 
   friend class Model_Application;
@@ -413,7 +413,7 @@ class Model_Document : public ModelAPI_Document
 
   //! counter value of transaction on the last "save" call, used for "IsModified" method
   int myTransactionSave;
-  //! number of nested transactions performed (list becasue may be nested inside of nested)
+  //! number of nested transactions performed (list because may be nested inside of nested)
   //! the list is empty if not nested transaction is performed
   std::list<int> myNestedNum;
 
index 23d96f4298a3d909c0a248f30e9c9f3e19a32080..45aee1b8a7b7df33eb6e0ab6403c2efd87ccbb5a 100755 (executable)
@@ -409,7 +409,8 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
     }
 
     if (anActiveDoc.get() && aCurrent.get() && aCurrent->data()->isValid()) {
-      if (anActiveDoc->currentFeature(false) != aCurrent)
+      if (anActiveDoc->currentFeature(false) != aCurrent &&
+          ModelAPI_Tools::compositeOwner(anActiveDoc->currentFeature(false)) == aCurrent)
         anActiveDoc->setCurrentFeature(aCurrent, false); // #2156 make the current feature back
     }
 
index 5a0f477a34fcfbe37e22e66e559b1c95ee54cda6..d0c9f5f33b2d5bf00d59aae975be2ca29989ba26 100644 (file)
@@ -66,6 +66,7 @@ SET(PROJECT_HEADERS
     SketchPlugin_Tools.h
     SketchPlugin_Trim.h
     SketchPlugin_Validators.h
+    SketchPlugin_SketchDrawer.h
 )
 
 SET(PROJECT_SOURCES
@@ -111,6 +112,7 @@ SET(PROJECT_SOURCES
     SketchPlugin_Tools.cpp
     SketchPlugin_Trim.cpp
     SketchPlugin_Validators.cpp
+    SketchPlugin_SketchDrawer.cpp
 )
 
 SET(PROJECT_LIBRARIES
index d51c6608f79225a3944b8d74e107f113627a32b7..11444e0ef521be034f79e39931065af07641a2c7 100644 (file)
@@ -77,7 +77,7 @@ class SketchPlugin_Line : public SketchPlugin_SketchEntity,
   SKETCHPLUGIN_EXPORT virtual void execute();
 
   /// Apply information of the message to current object. It fills start attribute of
-  /// the currrent feature by last attribute of the message feature, build coincidence
+  /// the current feature by last attribute of the message feature, build coincidence
   /// if message has selected object
   virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage);
 
@@ -92,7 +92,7 @@ class SketchPlugin_Line : public SketchPlugin_SketchEntity,
   SketchPlugin_Line();
 
 private:
-  /// Calculates the lenght of the line and fill the lenght attribute with the value
+  /// Calculates the length of the line and fill the length attribute with the value
   void updateLenghtValue();
 
 protected:
index 6a47d8539057fdbf43ae8913aaddeb4671550b55..f7bc806d56ed4e79ae57a26aac2017a7074580e6 100644 (file)
@@ -54,6 +54,7 @@
 #include <SketchPlugin_ExternalValidator.h>
 #include <SketchPlugin_Ellipse.h>
 #include <SketchPlugin_MacroEllipse.h>
+#include <SketchPlugin_SketchDrawer.h>
 
 #include <SketcherPrs_Tools.h>
 
@@ -244,6 +245,8 @@ FeaturePtr SketchPlugin_Plugin::createFeature(std::string theFeatureID)
     return FeaturePtr(new SketchPlugin_Ellipse);
   } else if (theFeatureID == SketchPlugin_MacroEllipse::ID()) {
     return FeaturePtr(new SketchPlugin_MacroEllipse);
+  } else if (theFeatureID == SketchPlugin_SketchDrawer::ID()) {
+    return FeaturePtr(new SketchPlugin_SketchDrawer);
   }
   // feature of such kind is not found
   return FeaturePtr();
diff --git a/src/SketchPlugin/SketchPlugin_SketchDrawer.cpp b/src/SketchPlugin/SketchPlugin_SketchDrawer.cpp
new file mode 100644 (file)
index 0000000..43f3f49
--- /dev/null
@@ -0,0 +1,212 @@
+// Copyright (C) 2014-2017  CEA/DEN, 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "SketchPlugin_SketchDrawer.h"
+
+#include "SketchPlugin_Arc.h"
+#include "SketchPlugin_Line.h"
+#include "SketchPlugin_Circle.h"
+#include "SketchPlugin_Point.h"
+#include "SketchPlugin_Sketch.h"
+#include "SketchPlugin_ConstraintDistance.h"
+#include "SketchPlugin_ConstraintCoincidence.h"
+#include "SketchPlugin_ConstraintLength.h"
+#include "SketchPlugin_ConstraintRadius.h"
+#include "SketchPlugin_ConstraintVertical.h"
+#include "SketchPlugin_ConstraintHorizontal.h"
+#include "SketchPlugin_ConstraintDistanceVertical.h"
+#include "SketchPlugin_ConstraintDistanceHorizontal.h"
+#include "SketchPlugin_Tools.h"
+
+#include <GeomAPI_Face.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Circ.h>
+#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_DataMapOfShapeShape.h>
+
+#include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_ResultConstruction.h>
+
+static const double kTOL = 1.e-6;
+
+SketchPlugin_SketchDrawer::SketchPlugin_SketchDrawer() : ModelAPI_Feature()
+{}
+
+void SketchPlugin_SketchDrawer::initAttributes()
+{
+  data()->addAttribute(BASE_ID(), ModelAPI_AttributeSelection::typeId());
+  data()->addAttribute(PLANE_ID(), ModelAPI_AttributeSelection::typeId());
+}
+
+// sets a point attribute of the feature by 3D point on the sketch
+static void setPoint(FeaturePtr theFeature, const std::string& theAttrID,
+  std::shared_ptr<SketchPlugin_Sketch> theSketch, GeomPointPtr thePoint,
+  std::list<std::pair<GeomPnt2dPtr, std::string> >& aPoints)
+{
+  GeomPnt2dPtr aPnt2D = theSketch->to2D(thePoint);
+  std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+    theFeature->attribute(theAttrID))->setValue(aPnt2D);
+  aPoints.push_back(std::pair<GeomPnt2dPtr, std::string>(aPnt2D, theAttrID));
+}
+
+void SketchPlugin_SketchDrawer::execute()
+{
+  GeomShapePtr aBase = selection(BASE_ID())->value();
+  if (!aBase.get() && selection(BASE_ID())->context().get())
+    aBase = selection(BASE_ID())->context()->shape();
+  if (!aBase.get()) {
+    setError("Error: a base shape can not be obtained");
+    return; // invalid case
+  }
+
+  ObjectPtr aPlaneContext = selection(PLANE_ID())->contextObject();
+  GeomShapePtr aPlaneShape = selection(PLANE_ID())->value();
+  if (!aPlaneShape.get() || aPlaneShape->shapeType() != GeomAPI_Shape::FACE) {
+    setError("Error: a sketch plane can not be obtained");
+    return; // invalid case
+  }
+  GeomFacePtr aPlaneFace(new GeomAPI_Face(aPlaneShape));
+  GeomPlanePtr aPlane = aPlaneFace->getPlane();
+
+  // create and initialize sketch
+  DocumentPtr aMyDoc = document();
+  std::shared_ptr<SketchPlugin_Sketch> aSketch =
+    std::dynamic_pointer_cast<SketchPlugin_Sketch>(aMyDoc->addFeature(SketchPlugin_Sketch::ID()));
+  /*if (aPlaneContext->groupName() == ModelAPI_ResultConstruction::group()) { // by coordinates
+    std::dynamic_pointer_cast<GeomDataAPI_Point>(
+      aSketch->attribute(SketchPlugin_Sketch::ORIGIN_ID()))->setValue(aPlane->location());
+    std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+      aSketch->attribute(SketchPlugin_Sketch::NORM_ID()))->setValue(aPlane->direction());
+
+  } else {*/
+  // by selection of plane
+  aSketch->selection(SketchPlugin_SketchEntity::EXTERNAL_ID())->
+    setValue(selection(PLANE_ID())->context(), aPlaneShape);
+  // if reference to non-construction, remove reference, but keep the sketch position
+  if (aPlaneContext->groupName() != ModelAPI_ResultConstruction::group()) {
+    aSketch->selection(SketchPlugin_SketchEntity::EXTERNAL_ID())->
+      setValue(ResultPtr(), GeomShapePtr());
+  }
+
+  // iterate all edges of the base to find all edges that belong to this plane
+  GeomAPI_DataMapOfShapeShape alreadyProcessed;
+  std::list<AttributePoint2DPtr> aCreatedPoints;// points to check and set coincidence
+  for(GeomAPI_ShapeExplorer anEdges(aBase, GeomAPI_Shape::EDGE); anEdges.more(); anEdges.next()) {
+    if (!alreadyProcessed.bind(anEdges.current(), anEdges.current()))
+      continue; // skip duplicated edges
+    GeomEdgePtr anEdge(new GeomAPI_Edge(anEdges.current()));
+    if (anEdge->isDegenerated())
+      continue; // skip degenerated edges
+    GeomPointPtr aStart = anEdge->firstPoint();
+    GeomPointPtr anEnd = anEdge->lastPoint();
+    if (aPlane->distance(aStart) >= kTOL || aPlane->distance(anEnd) >= kTOL)
+      continue; // skip edges not in plane
+
+    FeaturePtr anItem;
+    std::list<std::pair<GeomPnt2dPtr, std::string> > aPoints; // created point to attribute ID
+    if (anEdge->isLine()) { // line is already in the plane: create by two points
+      anItem = aSketch->addFeature(SketchPlugin_Line::ID());
+      setPoint(anItem, SketchPlugin_Line::START_ID(), aSketch, aStart, aPoints);
+      setPoint(anItem, SketchPlugin_Line::END_ID(), aSketch, anEnd, aPoints);
+      anItem->execute(); // for constraints setting on result
+      // add a vertical or horizontal constraints
+      bool isHorVertConstr = true;
+      if (abs(aPoints.front().first->x() - aPoints.back().first->x()) < kTOL) {
+        FeaturePtr aVert = aSketch->addFeature(SketchPlugin_ConstraintVertical::ID());
+        aVert->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(anItem->firstResult());
+      } else if (abs(aPoints.front().first->y() - aPoints.back().first->y()) < kTOL) {
+        FeaturePtr aHor = aSketch->addFeature(SketchPlugin_ConstraintHorizontal::ID());
+        aHor->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(anItem->firstResult());
+      } else {
+        isHorVertConstr = false;
+      }
+      if (isHorVertConstr) { // only length constraint is enough
+        FeaturePtr aLen = aSketch->addFeature(SketchPlugin_ConstraintLength::ID());
+        aLen->refattr(SketchPlugin_ConstraintLength::ENTITY_A())->setObject(anItem->firstResult());
+        aLen->real(SketchPlugin_ConstraintLength::VALUE())->setValue(anEdge->length());
+      } else { // set horizontal and vertical distance constraints
+        FeaturePtr aVDist = aSketch->addFeature(SketchPlugin_ConstraintDistanceVertical::ID());
+        aVDist->refattr(SketchPlugin_Constraint::ENTITY_A())
+          ->setAttr(anItem->attribute(SketchPlugin_Line::START_ID()));
+        aVDist->refattr(SketchPlugin_Constraint::ENTITY_B())
+          ->setAttr(anItem->attribute(SketchPlugin_Line::END_ID()));
+        aVDist->real(SketchPlugin_ConstraintDistanceVertical::VALUE())
+          ->setValue(aPoints.back().first->y() - aPoints.front().first->y());
+        FeaturePtr aHDist = aSketch->addFeature(SketchPlugin_ConstraintDistanceHorizontal::ID());
+        aHDist->refattr(SketchPlugin_Constraint::ENTITY_A())
+          ->setAttr(anItem->attribute(SketchPlugin_Line::START_ID()));
+        aHDist->refattr(SketchPlugin_Constraint::ENTITY_B())
+          ->setAttr(anItem->attribute(SketchPlugin_Line::END_ID()));
+        aHDist->real(SketchPlugin_ConstraintDistanceVertical::VALUE())
+          ->setValue(aPoints.back().first->x() - aPoints.front().first->x());
+      }
+    } else if (anEdge->isArc()) { // check also center
+      GeomPointPtr aCenter = anEdge->circle()->center();
+      if (aPlane->distance(aCenter) >= kTOL)
+        continue;
+      // create arc by 3 points
+      anItem = aSketch->addFeature(SketchPlugin_Arc::ID());
+      setPoint(anItem, SketchPlugin_Arc::CENTER_ID(), aSketch, aCenter, aPoints);
+      setPoint(anItem, SketchPlugin_Arc::START_ID(), aSketch, aStart, aPoints);
+      setPoint(anItem, SketchPlugin_Arc::END_ID(), aSketch, anEnd, aPoints);
+      anItem->execute(); // for constraints setting on result
+      // set radius constraint
+      FeaturePtr aRad = aSketch->addFeature(SketchPlugin_ConstraintRadius::ID());
+      aRad->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(anItem->lastResult());
+    } else if (anEdge->isCircle()) { // check also center and middle (at value 2.)
+      GeomPointPtr aCenter = anEdge->circle()->center();
+      if (aPlane->distance(aCenter) >= kTOL || aPlane->distance(anEdge->middlePoint()) >= kTOL)
+        continue;
+      // circle by center and radius
+      anItem = aSketch->addFeature(SketchPlugin_Circle::ID());
+      setPoint(anItem, SketchPlugin_Circle::CENTER_ID(), aSketch, aCenter, aPoints);
+      anItem->real(SketchPlugin_Circle::RADIUS_ID())->setValue(anEdge->circle()->radius());
+      anItem->execute(); // for constraints setting on result
+      // set radius constraint
+      FeaturePtr aRad = aSketch->addFeature(SketchPlugin_ConstraintRadius::ID());
+      aRad->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(anItem->lastResult());
+    } else {
+      continue; // other types of edges are not supported, only lines, circles and arcs
+    }
+    // check some resulting points are coincident to existing
+    std::list<std::pair<GeomPnt2dPtr, std::string> >::iterator aPIter = aPoints.begin();
+    for(; aPIter != aPoints.end(); aPIter++) {
+      AttributePoint2DPtr aPointAttr =
+        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anItem->attribute(aPIter->second));
+      std::list<AttributePoint2DPtr>::iterator aCoincIter = aCreatedPoints.begin();
+      for(; aCoincIter != aCreatedPoints.end(); aCoincIter++) {
+        double aDX = (*aCoincIter)->x() - aPIter->first->x();
+        if (abs(aDX) >= kTOL)
+          continue;
+        double aDY = (*aCoincIter)->y() - aPIter->first->y();
+        if (abs(aDY) >= kTOL)
+          continue;
+        // create a coincidence constraint
+        FeaturePtr aCoinc = aSketch->addFeature(SketchPlugin_ConstraintCoincidence::ID());
+        aCoinc->refattr(SketchPlugin_Constraint::ENTITY_A())->setAttr(aPointAttr);
+        aCoinc->refattr(SketchPlugin_Constraint::ENTITY_B())->setAttr(*aCoincIter);
+        break; // only one coincidence per point
+      }
+      aCreatedPoints.push_back(aPointAttr);
+    }
+  }
+  aMyDoc->setCurrentFeature(aSketch, false);
+}
diff --git a/src/SketchPlugin/SketchPlugin_SketchDrawer.h b/src/SketchPlugin/SketchPlugin_SketchDrawer.h
new file mode 100644 (file)
index 0000000..6f6da26
--- /dev/null
@@ -0,0 +1,79 @@
+// Copyright (C) 2014-2017  CEA/DEN, 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<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef SketchPlugin_SketchDrawer_H_
+#define SketchPlugin_SketchDrawer_H_
+
+#include "SketchPlugin.h"
+#include <ModelAPI_Feature.h>
+
+/// \class SketchPlugin_SketchDrawer
+/// \ingroup Plugins
+/// \brief Feature for creation of a sketch on selected base object and plane. It tries
+///  to make sketch elements equal to edges and vertices of the objects that belong to
+///  the selected plane.
+class SketchPlugin_SketchDrawer: public ModelAPI_Feature
+{
+ public:
+  /// A constructor
+  SketchPlugin_SketchDrawer();
+
+  /// Feature kind.
+  inline static const std::string& ID()
+  {
+    static const std::string MY_FEATURE_ID("SketchDrawer");
+    return MY_FEATURE_ID;
+  }
+
+  /// Attribute name of the base shape selected.
+  inline static const std::string& BASE_ID()
+  {
+    static const std::string ID("base_shape");
+    return ID;
+  }
+  /// Attribute name of the plane selected.
+  inline static const std::string& PLANE_ID()
+  {
+    static const std::string ID("plane");
+    return ID;
+  }
+
+  /// \return the kind of a feature.
+  SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = SketchPlugin_SketchDrawer::ID();
+    return MY_KIND;
+  }
+
+  /// Creates a new sketch.
+  SKETCHPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes.
+  SKETCHPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Reimplemented from ModelAPI_Feature::isMacro(). Means that feature is removed on apply.
+  /// \returns true
+  SKETCHPLUGIN_EXPORT virtual bool isMacro() const {return true;}
+
+  /// No preview is generated until it is applied.
+  SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const {return false;}
+};
+
+#endif
diff --git a/src/SketchPlugin/icons/drawer.png b/src/SketchPlugin/icons/drawer.png
new file mode 100644 (file)
index 0000000..e3f53d1
Binary files /dev/null and b/src/SketchPlugin/icons/drawer.png differ
index f901724080e90d661af4e81cb636b60f16cdc364..928c21d0d126bfa2c5c459b109469241703cfd74 100644 (file)
@@ -1057,4 +1057,18 @@ email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com
     </group>
 
   </workbench>
+  <workbench id="Macros" document="Part">
+    <group id="Samples">
+
+      <feature id="SketchDrawer" title="Sketch drawer" tooltip="Creates sketch using elements of selected shape belonging to selected plane"
+            icon="icons/Sketch/drawer.png"
+            helpfile="sketchDrawer.html">
+        <shape_selector id="base_shape" label="Shape:" tooltip="Select a shape for extraction to sketch."
+            shape_types="objects" concealment="false"/>
+        <shape_selector id="plane" label="Plane:" tooltip="Select plane for sketch" shape_types="face">
+          <validator id="GeomValidators_Face" parameters="plane"/>
+        </shape_selector>
+      </feature>
+    </group>
+  </workbench>
 </plugin>