]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge branch 'master' of newgeom:newgeom
authorvsv <vitaly.smetannikov@opencascade.com>
Tue, 13 May 2014 14:14:38 +0000 (18:14 +0400)
committervsv <vitaly.smetannikov@opencascade.com>
Tue, 13 May 2014 14:14:38 +0000 (18:14 +0400)
33 files changed:
CMakeCommon/FindSolveSpace.cmake [new file with mode: 0644]
CMakeLists.txt
linux_env.sh
msvc10_env.bat
src/GeomData/GeomData_Dir.cpp
src/GeomData/GeomData_Point.cpp
src/GeomData/GeomData_Point2D.cpp
src/Model/Model_AttributeDocRef.cpp
src/Model/Model_AttributeDouble.cpp
src/Model/Model_AttributeRefAttr.cpp
src/Model/Model_AttributeRefAttr.h
src/Model/Model_AttributeRefList.cpp
src/Model/Model_AttributeReference.cpp
src/ModelAPI/ModelAPI_Attribute.h
src/ModelAPI/ModelAPI_AttributeRefAttr.h
src/PartSet/PartSet_OperationSketchLine.cpp
src/PartSet/PartSet_OperationSketchLine.h
src/PartSet/PartSet_Tools.cpp
src/PartSet/PartSet_Tools.h
src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/SketchPlugin_Constraint.h [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_ConstraintCoincidence.cpp [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_ConstraintCoincidence.h [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_Plugin.cpp
src/SketchPlugin/SketchPlugin_Point.cpp [new file with mode: 0644]
src/SketchPlugin/SketchPlugin_Point.h [new file with mode: 0644]
src/SketchPlugin/plugin-Sketch.xml
src/SketchSolver/CMakeLists.txt [new file with mode: 0644]
src/SketchSolver/SketchSolver.h [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintManager.cpp [new file with mode: 0644]
src/SketchSolver/SketchSolver_ConstraintManager.h [new file with mode: 0644]
src/SketchSolver/SketchSolver_Solver.cpp [new file with mode: 0644]
src/SketchSolver/SketchSolver_Solver.h [new file with mode: 0644]

diff --git a/CMakeCommon/FindSolveSpace.cmake b/CMakeCommon/FindSolveSpace.cmake
new file mode 100644 (file)
index 0000000..b373d2c
--- /dev/null
@@ -0,0 +1,6 @@
+SET(SLVS_ROOT_DIR $ENV{SOLVESPACE_ROOT_DIR})
+
+INCLUDE_DIRECTORIES(${SLVS_ROOT_DIR}/include)
+LINK_DIRECTORIES(${SLVS_ROOT_DIR}/lib)
+
+SET(SLVS_LIBRARIES ${SLVS_ROOT_DIR}/lib/slvs.lib)
index 223001654d8af64d32e6ca78337d7cd769ad1fec..18fbdfc7ca1c0001200b8802ed1aec2b4e92c936 100644 (file)
@@ -9,6 +9,7 @@ INCLUDE(FindQt)
 INCLUDE(FindBoost)
 INCLUDE(FindPython)
 INCLUDE(FindSalome)
+INCLUDE(FindSolveSpace)
 
 IF(UNIX)
     IF(CMAKE_COMPILER_IS_GNUCC)
@@ -31,6 +32,7 @@ ADD_SUBDIRECTORY (src/GeomDataAPI)
 ADD_SUBDIRECTORY (src/PartSetPlugin)
 ADD_SUBDIRECTORY (src/ConstructionPlugin)
 ADD_SUBDIRECTORY (src/SketchPlugin)
+ADD_SUBDIRECTORY (src/SketchSolver)
 ADD_SUBDIRECTORY (src/ModuleBase)
 ADD_SUBDIRECTORY (src/PartSet)
 ADD_SUBDIRECTORY (src/PyConsole)
index 170f3bf3d0bad083faf6f4411e828079081d79d8..8fb9f33ff6c1dacff7fe498a82373748eebd3249 100644 (file)
@@ -68,6 +68,10 @@ export LIBXML2_INCLUDE_DIR=${LIBXML2_ROOT_DIR}/include/libxml2
 export LIBXML2_LIB_DIR=${LIBXML2_ROOT_DIR}/lib
 export LIBXML2_BIN_DIR=${LIBXML2_ROOT_DIR}/bin
 ##
+#------ SolveSpace ------
+export SOLVESPACE_ROOT_DIR=${PDIR}/solvespace-2.0
+export LD_LIBRARY_PATH=${SOLVESPACE_ROOT_DIR}/lib:${LD_LIBRARY_PATH}
+##
 #------ OCCT ------
 export CAS_ROOT_DIR=${PDIR}/OCCT-6.7.0
 
index 7717e8047d9d515e66827a98b2cb650e8085dc98..1d2233ce4347d693a6ed7525d8893254246317e8 100644 (file)
@@ -126,6 +126,11 @@ set PATH=%CMAKEDIR%\bin;%PATH%
 @SET PATH=%BOOST_ROOT_DIR%\lib;%PATH%
 @REM -------------------------
 
+@REM -------------------------
+@SET SOLVESPACE_ROOT_DIR=%PDIR%\solvespace-2.0
+@SET PATH=%SOLVESPACE_ROOT_DIR%\lib;%PATH%
+@REM -------------------------
+
 @SET NEW_GEOM_CONFIG_FILE=%ROOT_DIR%\install\plugins
 @SET PATH=%ROOT_DIR%\install\plugins;%PATH%
 
index 5090a06267f562b7ccc9bb141e6c9b829bf7f05e..070e94562ff56705f0276b3baf85fec704454e78 100644 (file)
@@ -17,7 +17,7 @@ void GeomData_Dir::setValue(const double theX, const double theY, const double t
     myCoords->SetValue(1, theY);
     myCoords->SetValue(2, theZ);
     static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_UPDATED);
-    Model_FeatureUpdatedMessage aMsg(feature(), anEvent);
+    Model_FeatureUpdatedMessage aMsg(owner(), anEvent);
     Events_Loop::loop()->send(aMsg);
   }
 }
index faf24fe99faf49a69c14d9afd7ce7526013d60af..6ad2ac56479b99942b5c4c2ac55be0947aedb3a9 100644 (file)
@@ -16,7 +16,7 @@ void GeomData_Point::setValue(const double theX, const double theY, const double
     myCoords->SetValue(1, theY);
     myCoords->SetValue(2, theZ);
     static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_UPDATED);
-    Model_FeatureUpdatedMessage aMsg(feature(), anEvent);
+    Model_FeatureUpdatedMessage aMsg(owner(), anEvent);
     Events_Loop::loop()->send(aMsg);
   }
 }
index bbf3e55fb578d27d567beb57409ce69f80ff9457..8af702953a020f407e2360e2b054f1ec87f60820 100644 (file)
@@ -14,7 +14,7 @@ void GeomData_Point2D::setValue(const double theX, const double theY)
     myCoords->SetValue(0, theX);
     myCoords->SetValue(1, theY);
     static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_UPDATED);
-    Model_FeatureUpdatedMessage aMsg(feature(), anEvent);
+    Model_FeatureUpdatedMessage aMsg(owner(), anEvent);
     Events_Loop::loop()->send(aMsg);
   }
 }
index 82492e2d6dcac4b2850f46a12f67012823677d4e..93c8af71346ce82569f5cea6cf867f8b0d8ac55b 100644 (file)
@@ -16,7 +16,7 @@ void Model_AttributeDocRef::setValue(boost::shared_ptr<ModelAPI_Document> theDoc
     myComment->Set(TCollection_ExtendedString(theDoc->id().c_str()));
 
     static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_UPDATED);
-    Model_FeatureUpdatedMessage aMsg(feature(), anEvent);
+    Model_FeatureUpdatedMessage aMsg(owner(), anEvent);
     Events_Loop::loop()->send(aMsg);
   }
 }
index 13b4c97c650b8984971a2e0fdb7689432304a463..88b4352a56d288dd8b3b0c81a7acfdc28e5ce82f 100644 (file)
@@ -13,7 +13,7 @@ void Model_AttributeDouble::setValue(const double theValue)
   if (myReal->Get() != theValue) {
     myReal->Set(theValue);
     static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_UPDATED);
-    Model_FeatureUpdatedMessage aMsg(feature(), anEvent);
+    Model_FeatureUpdatedMessage aMsg(owner(), anEvent);
     Events_Loop::loop()->send(aMsg);
   }
 }
index bedda92d5d92a704c0465cd42609a00dd1e52018..2d7a1bd5e4fa9d1754c9183fb13595f232940cc2 100644 (file)
 
 using namespace std;
 
-void Model_AttributeRefAttr::setValue(boost::shared_ptr<ModelAPI_Attribute> theAttr)
+bool Model_AttributeRefAttr::isFeature()
 {
-  if (value() != theAttr) {
+  return myID->Get().Length() == 0;
+}
+
+void Model_AttributeRefAttr::setAttr(boost::shared_ptr<ModelAPI_Attribute> theAttr)
+{
+  boost::shared_ptr<Model_Data> aData = 
+    boost::dynamic_pointer_cast<Model_Data>(theAttr->owner()->data());
+  string anID = aData->id(theAttr);
+  if (feature() == theAttr->owner() && myID->Get().IsEqual(anID.c_str()))
+    return; // nothing is changed
+
+  myRef->Set(aData->label());
+  myID->Set(aData->id(theAttr).c_str());
+
+  static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_UPDATED);
+  Model_FeatureUpdatedMessage aMsg(feature(), anEvent);
+  Events_Loop::loop()->send(aMsg);
+}
+
+boost::shared_ptr<ModelAPI_Attribute> Model_AttributeRefAttr::attr()
+{
+  boost::shared_ptr<ModelAPI_Feature> aFeature = feature();
+  if (aFeature) {
     boost::shared_ptr<Model_Data> aData = 
-      boost::dynamic_pointer_cast<Model_Data>(theAttr->feature()->data());
-    if (myRef.IsNull()) {
-      boost::shared_ptr<Model_Data> aMyData = 
-        boost::dynamic_pointer_cast<Model_Data>(feature()->data());
-      TDF_Reference::Set(aMyData->label(), aData->label());
-    } else {
-      myRef->Set(aData->label());
-    }
-    myID->Set(aData->id(theAttr).c_str());
+      boost::dynamic_pointer_cast<Model_Data>(aFeature->data());
+    return aData->attribute(TCollection_AsciiString(myID->Get()).ToCString());
+  }
+  // not initialized
+  return boost::shared_ptr<ModelAPI_Attribute>();
+}
+
+void Model_AttributeRefAttr::setFeature(boost::shared_ptr<ModelAPI_Feature> theFeature)
+{
+  if (myID->Get().Length() != 0 || feature() != theFeature) {
+    boost::shared_ptr<Model_Data> aData = 
+      boost::dynamic_pointer_cast<Model_Data>(theFeature->data());
+    myRef->Set(aData->label());
+    myID->Set(""); // feature is identified by the empty ID
 
     static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_UPDATED);
-    Model_FeatureUpdatedMessage aMsg(feature(), anEvent);
+    Model_FeatureUpdatedMessage aMsg(owner(), anEvent);
     Events_Loop::loop()->send(aMsg);
   }
 }
 
-boost::shared_ptr<ModelAPI_Attribute> Model_AttributeRefAttr::value()
+boost::shared_ptr<ModelAPI_Feature> Model_AttributeRefAttr::feature()
 {
-  if (!myRef.IsNull()) {
+  if (myRef->Get() != myRef->Label()) { // initialized
     boost::shared_ptr<Model_Document> aDoc = 
-      boost::dynamic_pointer_cast<Model_Document>(feature()->document());
+      boost::dynamic_pointer_cast<Model_Document>(owner()->document());
     if (aDoc) {
       TDF_Label aRefLab = myRef->Get();
       TDF_Label aFeatureLab = aRefLab.Father();
-      boost::shared_ptr<Model_Data> aData = 
-        boost::dynamic_pointer_cast<Model_Data>(aDoc->feature(aRefLab)->data());
-      return aData->attribute(TCollection_AsciiString(myID->Get()).ToCString());
+      return aDoc->feature(aRefLab);
     }
   }
   // not initialized
-  return boost::shared_ptr<ModelAPI_Attribute>();
+  return boost::shared_ptr<ModelAPI_Feature>();
 }
 
 Model_AttributeRefAttr::Model_AttributeRefAttr(TDF_Label& theLabel)
@@ -53,7 +78,7 @@ Model_AttributeRefAttr::Model_AttributeRefAttr(TDF_Label& theLabel)
   // check the attribute could be already presented in this doc (after load document)
   if (!theLabel.FindAttribute(TDataStd_Comment::GetID(), myID)) {
     // create attribute: not initialized by value yet
-    TDataStd_Comment::Set(theLabel, "");
-    // reference attribute is not set to the label!
+    myID = TDataStd_Comment::Set(theLabel, "");
+    myRef = TDF_Reference::Set(theLabel, theLabel); // not initialized: reference to itself
   }
 }
index 8422966720018c66a861df5a622ef8200e4f05a4..f9d2bc42e2ff34f001030855f18c4767ee3ccc6b 100644 (file)
 class Model_AttributeRefAttr : public ModelAPI_AttributeRefAttr
 {
   Handle_TDF_Reference myRef; ///< reference to the feature label
-  Handle_TDataStd_Comment myID; ///< ID of the referenced attirbute
+   ///< ID of the referenced attirbute (empty if this is a reference to a feature)
+  Handle_TDataStd_Comment myID;
 public:
-  /// Defines the attribute referenced from this attribute
-  MODEL_EXPORT virtual void setValue(boost::shared_ptr<ModelAPI_Attribute> theAttr);
+  /// Returns true if this attribute references to a feature (not to the attribute)
+  MODEL_EXPORT virtual bool isFeature();
+
+  /// Defines the reference to the attribute
+  MODEL_EXPORT virtual void setAttr(boost::shared_ptr<ModelAPI_Attribute> theAttr);
 
   /// Returns attribute referenced from this attribute
-  MODEL_EXPORT virtual boost::shared_ptr<ModelAPI_Attribute> value();
+  MODEL_EXPORT virtual boost::shared_ptr<ModelAPI_Attribute> attr();
+
+  /// Defines the reference to the feature
+  MODEL_EXPORT virtual void setFeature(boost::shared_ptr<ModelAPI_Feature> theFeature);
+
+  /// Returns feature referenced from this attribute
+  MODEL_EXPORT virtual boost::shared_ptr<ModelAPI_Feature> feature();
 
 protected:
   /// Objects are created for features automatically
index 0366e0a77dc9ab372d87a7f9a4541ee24ef7472f..f6520fce869300ecaacfa0ee092dd0fece340583 100644 (file)
@@ -19,7 +19,7 @@ void Model_AttributeRefList::append(boost::shared_ptr<ModelAPI_Feature> theFeatu
   myRef->Append(aData->label());
 
   static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_UPDATED);
-  Model_FeatureUpdatedMessage aMsg(feature(), anEvent);
+  Model_FeatureUpdatedMessage aMsg(owner(), anEvent);
   Events_Loop::loop()->send(aMsg);
 }
 
@@ -40,7 +40,7 @@ list<boost::shared_ptr<ModelAPI_Feature> > Model_AttributeRefList::list()
 {
   std::list< boost::shared_ptr<ModelAPI_Feature> > aResult;
   boost::shared_ptr<Model_Document> aDoc = 
-    boost::dynamic_pointer_cast<Model_Document>(feature()->document());
+    boost::dynamic_pointer_cast<Model_Document>(owner()->document());
   if (aDoc) {
     const TDF_LabelList& aList = myRef->List();
     for(TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) {
index ab247fdc9d72db1835ca3635e3731cbcfeb15e5d..105639b742fdda4b3b8b17887361e436875b2ff3 100644 (file)
@@ -18,14 +18,14 @@ void Model_AttributeReference::setValue(boost::shared_ptr<ModelAPI_Feature> theF
       boost::dynamic_pointer_cast<Model_Data>(theFeature->data());
     if (myRef.IsNull()) {
       boost::shared_ptr<Model_Data> aMyData = 
-        boost::dynamic_pointer_cast<Model_Data>(feature()->data());
+        boost::dynamic_pointer_cast<Model_Data>(owner()->data());
       TDF_Reference::Set(aMyData->label(), aData->label());
     } else {
       myRef->Set(aData->label());
     }
 
     static Events_ID anEvent = Events_Loop::eventByName(EVENT_FEATURE_UPDATED);
-    Model_FeatureUpdatedMessage aMsg(feature(), anEvent);
+    Model_FeatureUpdatedMessage aMsg(owner(), anEvent);
     Events_Loop::loop()->send(aMsg);
   }
 }
@@ -34,7 +34,7 @@ boost::shared_ptr<ModelAPI_Feature> Model_AttributeReference::value()
 {
   if (!myRef.IsNull()) {
     boost::shared_ptr<Model_Document> aDoc = 
-      boost::dynamic_pointer_cast<Model_Document>(feature()->document());
+      boost::dynamic_pointer_cast<Model_Document>(owner()->document());
     if (aDoc) {
       TDF_Label aRefLab = myRef->Get();
       return aDoc->feature(aRefLab);
index d00bbc76a4d8132db951fd9f71a2440384d82e12..acea353df4d61d3be87566b1ea1da3232a3fe844 100644 (file)
@@ -32,7 +32,7 @@ public:
     {myFeature = theFeature;}
 
   /// Returns the owner of this attribute
-  MODELAPI_EXPORT const boost::shared_ptr<ModelAPI_Feature>& feature()
+  MODELAPI_EXPORT const boost::shared_ptr<ModelAPI_Feature>& owner()
   {return myFeature;}
 protected:
   /// Objects are created for features automatically
index d9c5f3a6041044750589e7112dd4c6ce8b7c8484..4fd8834669118d033d802c416da5250ec6152965 100644 (file)
@@ -9,18 +9,27 @@
 
 /**\class ModelAPI_AttributeRefAttr
  * \ingroup DataModel
- * \brief Attribute that contains reference to an attribute of a feature 
- * (located in the same document).
+ * \brief Attribute that contains reference to an attribute of a feature or reference to 
+ * a feature (switchable)
  */
 
 class ModelAPI_AttributeRefAttr : public ModelAPI_Attribute
 {
 public:
-  /// Defines the attribute referenced from this attribute
-  MODELAPI_EXPORT virtual void setValue(boost::shared_ptr<ModelAPI_Attribute> theAttr) = 0;
+  /// Returns true if this attribute references to a feature (not to the attribute)
+  MODELAPI_EXPORT virtual bool isFeature() = 0;
+
+  /// Defines the reference to the attribute
+  MODELAPI_EXPORT virtual void setAttr(boost::shared_ptr<ModelAPI_Attribute> theAttr) = 0;
 
   /// Returns attribute referenced from this attribute
-  MODELAPI_EXPORT virtual boost::shared_ptr<ModelAPI_Attribute> value() = 0;
+  MODELAPI_EXPORT virtual boost::shared_ptr<ModelAPI_Attribute> attr() = 0;
+
+  /// Defines the reference to the feature
+  MODELAPI_EXPORT virtual void setFeature(boost::shared_ptr<ModelAPI_Feature> theFeature) = 0;
+
+  /// Returns feature referenced from this attribute
+  MODELAPI_EXPORT virtual boost::shared_ptr<ModelAPI_Feature> feature() = 0;
 
   /// Returns the type of this class of attributes
   MODELAPI_EXPORT static std::string type() {return "RefAttr";}
index 2538cfd5f02b6d645a45be775357f009512a974a..9235348a7f68f2fdbf6bac9dd651800fdde95f1f 100644 (file)
 #include <GeomDataAPI_Point2D.h>
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Document.h>
+#include <ModelAPI_AttributeRefAttr.h>
+
+#include <SketchPlugin_Constraint.h>
+
+#include <Geom_Line.hxx>
+#include <gp_Lin.hxx>
+
+#include <XGUI_ViewerPrs.h>
 
 #include <SketchPlugin_Line.h>
 
 #include <V3d_View.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS.hxx>
+#include <BRep_Tool.hxx>
 
 #ifdef _DEBUG
 #include <QDebug>
@@ -57,16 +68,59 @@ void PartSet_OperationSketchLine::init(boost::shared_ptr<ModelAPI_Feature> theFe
 void PartSet_OperationSketchLine::mouseReleased(QMouseEvent* theEvent, Handle(V3d_View) theView,
                                                 const std::list<XGUI_ViewerPrs>& theSelected)
 {
+  double aX, anY;
+
   gp_Pnt aPoint = PartSet_Tools::ConvertClickToPoint(theEvent->pos(), theView);
+  if (theSelected.empty()) {
+    PartSet_Tools::ConvertTo2D(aPoint, mySketch, theView, aX, anY);
+  }
+  else {
+    XGUI_ViewerPrs aPrs = theSelected.front();
+    const TopoDS_Shape& aShape = aPrs.shape();
+    if (!aShape.IsNull()) // the point is selected
+    {
+      if (aShape.ShapeType() == TopAbs_VERTEX) {
+        const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
+        if (!aVertex.IsNull()) {
+          aPoint = BRep_Tool::Pnt(aVertex);
+          PartSet_Tools::ConvertTo2D(aPoint, mySketch, theView, aX, anY);
+        }
+      }
+      else if (aShape.ShapeType() == TopAbs_EDGE) // the line is selected
+      {
+        boost::shared_ptr<ModelAPI_Feature> aFeature = aPrs.feature();
+        if (aFeature) {
+          double X0, X1, X2, X3;
+          double Y0, Y1, Y2, Y3;
+          getLinePoint(aFeature, LINE_ATTR_START, X2, Y2);
+          getLinePoint(aFeature, LINE_ATTR_END, X3, Y3);
+          PartSet_Tools::ConvertTo2D(aPoint, mySketch, theView, X1, Y1);
+
+          switch (myPointSelectionMode) {
+            case SM_FirstPoint:
+              PartSet_Tools::ProjectPointOnLine(X2, Y2, X3, Y3, X1, Y1, aX, anY);
+            break;
+            case SM_SecondPoint: {
+              getLinePoint(feature(), LINE_ATTR_START, X0, Y0);
+              PartSet_Tools::IntersectLines(X0, Y0, X1, Y1, X2, Y2, X3, Y3, aX, anY);
+            }
+            break;
+            default:
+            break;
+          }
+        }
+      }
+    }
+  }
   switch (myPointSelectionMode)
   {
     case SM_FirstPoint: {
-      setLinePoint(aPoint, theView, LINE_ATTR_START);
+      setLinePoint(aX, anY, LINE_ATTR_START);
       myPointSelectionMode = SM_SecondPoint;
     }
     break;
     case SM_SecondPoint: {
-      setLinePoint(aPoint, theView, LINE_ATTR_END);
+      setLinePoint(aX, anY, LINE_ATTR_END);
       commit();
       emit featureConstructed(feature(), FM_Deactivation);
       emit launchOperation(PartSet_OperationSketchLine::Type(), feature());
@@ -113,6 +167,7 @@ void PartSet_OperationSketchLine::startOperation()
 {
   PartSet_OperationSketchBase::startOperation();
   myPointSelectionMode = !myInitPoint ? SM_FirstPoint : SM_SecondPoint;
+  emit multiSelectionEnabled(false);
 }
 
 void PartSet_OperationSketchLine::abortOperation()
@@ -121,6 +176,12 @@ void PartSet_OperationSketchLine::abortOperation()
   PartSet_OperationSketchBase::abortOperation();
 }
 
+void PartSet_OperationSketchLine::stopOperation()
+{
+  PartSet_OperationSketchBase::stopOperation();
+  emit multiSelectionEnabled(true);
+}
+
 boost::shared_ptr<ModelAPI_Feature> PartSet_OperationSketchLine::createFeature()
 {
   boost::shared_ptr<ModelAPI_Feature> aNewFeature = ModuleBase_Operation::createFeature();
@@ -135,21 +196,64 @@ boost::shared_ptr<ModelAPI_Feature> PartSet_OperationSketchLine::createFeature()
     boost::shared_ptr<GeomDataAPI_Point2D> aPoint = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>
                                                                 (aData->attribute(LINE_ATTR_START));
     aPoint->setValue(myInitPoint->x(), myInitPoint->y());
+
+    //createConstraint(myInitPoint, aPoint);
   }
 
   emit featureConstructed(aNewFeature, FM_Activation);
   return aNewFeature;
 }
 
-void PartSet_OperationSketchLine::setLinePoint(const gp_Pnt& thePoint,
-                                               Handle(V3d_View) theView,
+void PartSet_OperationSketchLine::createConstraint(boost::shared_ptr<GeomDataAPI_Point2D> thePoint1,
+                                                   boost::shared_ptr<GeomDataAPI_Point2D> thePoint2)
+{
+  boost::shared_ptr<ModelAPI_Document> aDoc = document();
+  boost::shared_ptr<ModelAPI_Feature> aFeature = aDoc->addFeature("SketchConstraintCoincidence");
+
+  boost::shared_ptr<ModelAPI_Data> aData = aFeature->data();
+
+  boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef1 =
+        boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aData->attribute(CONSTRAINT_ATTR_ENTITY_A));
+  aRef1->setAttr(thePoint1);
+
+  boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef2 =
+        boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aData->attribute(CONSTRAINT_ATTR_ENTITY_B));
+  aRef2->setAttr(thePoint2);
+
+  if (aFeature) // TODO: generate an error if feature was not created
+    aFeature->execute();
+}
+
+void PartSet_OperationSketchLine::getLinePoint(boost::shared_ptr<ModelAPI_Feature> theFeature,
+                                               const std::string& theAttribute,
+                                               double& theX, double& theY)
+{
+  if (!theFeature)
+    return;
+  boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
+  boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
+        boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
+  theX = aPoint->x();
+  theY = aPoint->y();
+}
+
+void PartSet_OperationSketchLine::setLinePoint(double theX, double theY,
                                                const std::string& theAttribute)
 {
   boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
   boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
         boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
+  aPoint->setValue(theX, theY);
+}
 
+void PartSet_OperationSketchLine::setLinePoint(const gp_Pnt& thePoint,
+                                               Handle(V3d_View) theView,
+                                               const std::string& theAttribute)
+{
   double aX, anY;
   PartSet_Tools::ConvertTo2D(thePoint, mySketch, theView, aX, anY);
+  boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
+  boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
+        boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
   aPoint->setValue(aX, anY);
 }
index 8dda6b9c625c1c4d391d86f72ae2a449c4bc49b0..d92224aaab9621a1a760f4f608dd55253cc40d31 100644 (file)
@@ -72,13 +72,35 @@ protected:
   /// Before the feature is aborted, it should be hidden from the viewer
   virtual void abortOperation();
 
+  /// Virtual method called when operation stopped - committed or aborted.
+  /// Restore the multi selection state
+  virtual void stopOperation();
+
   /// Creates an operation new feature
   /// In addition to the default realization it appends the created line feature to
   /// the sketch feature
   /// \returns the created feature
   virtual boost::shared_ptr<ModelAPI_Feature> createFeature();
 
+  /// Creates a constraint on two points
+  /// \param thePoint1 the first point
+  /// \param thePoint1 the second point
+  void createConstraint(boost::shared_ptr<GeomDataAPI_Point2D> thePoint1,
+                        boost::shared_ptr<GeomDataAPI_Point2D> thePoint2);
+
 protected:
+  /// \brief Get the line point 2d coordinates.
+  /// \param theFeature the line feature
+  /// \param theAttribute the start or end attribute of the line
+  /// \param theX the horizontal coordinate
+  /// \param theY the vertical coordinate
+  void getLinePoint(boost::shared_ptr<ModelAPI_Feature> theFeature, const std::string& theAttribute,
+                    double& theX, double& theY);
+  /// \brief Save the point to the line.
+  /// \param theX the horizontal coordinate
+  /// \param theY the vertical coordinate
+  /// \param theAttribute the start or end attribute of the line
+  void setLinePoint(double theX, double theY, const std::string& theAttribute);
   /// \brief Save the point to the line.
   /// \param thePoint the 3D point in the viewer
   /// \param theAttribute the start or end attribute of the line
index 04a41572a457de064d2738ef8a746171bcd1f0c9..3caf619cac56abe93aec6f184246c39c315b0f8b 100644 (file)
@@ -4,21 +4,30 @@
 
 #include <PartSet_Tools.h>
 
-#include <V3d_View.hxx>
-#include <gp_Pln.hxx>
-#include <ProjLib.hxx>
-#include <ElSLib.hxx>
-
 #include <ModelAPI_Data.h>
 #include <ModelAPI_AttributeDouble.h>
+
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Dir.h>
+
+#include <GeomAPI_Dir.h>
+#include <GeomAPI_XYZ.h>
+
 #include <SketchPlugin_Sketch.h>
 
+#include <V3d_View.hxx>
+#include <gp_Pln.hxx>
+#include <ProjLib.hxx>
+#include <ElSLib.hxx>
+#include <Geom_Line.hxx>
+#include <GeomAPI_ProjectPointOnCurve.hxx>
+
 #ifdef _DEBUG
 #include <QDebug>
 #endif
 
+const double PRECISION_TOLERANCE = 0.000001;
+
 gp_Pnt PartSet_Tools::ConvertClickToPoint(QPoint thePoint, Handle(V3d_View) theView)
 {
   if (theView.IsNull())
@@ -80,8 +89,8 @@ void PartSet_Tools::ConvertTo2D(const gp_Pnt& thePoint, boost::shared_ptr<ModelA
                   boost::dynamic_pointer_cast<GeomDataAPI_Dir>(aData->attribute(SKETCH_ATTR_NORM));
     gp_Vec aNormalVec(aNormal->x(), aNormal->y(), aNormal->z());
 
-    double aDen = anEyeVec*aNormalVec;
-    double aLVec = aDen != 0 ? aVec*aNormalVec/aDen : aVec*aNormalVec;
+    double aDen = anEyeVec * aNormalVec;
+    double aLVec = aDen != 0 ? aVec * aNormalVec / aDen : DBL_MAX;
 
     gp_Vec aDeltaVec = anEyeVec*aLVec;
     aVec = aVec - aDeltaVec;
@@ -89,3 +98,44 @@ void PartSet_Tools::ConvertTo2D(const gp_Pnt& thePoint, boost::shared_ptr<ModelA
   theX = aVec.X() * aX->x() + aVec.Y() * aX->y() + aVec.Z() * aX->z();
   theY = aVec.X() * anY->x() + aVec.Y() * anY->y() + aVec.Z() * anY->z();
 }
+
+void PartSet_Tools::IntersectLines(double theX0, double theY0, double theX1, double theY1,
+                                   double theX2, double theY2, double theX3, double theY3,
+                                   double& theX, double& theY)
+{
+  double aV1 = theX1 - theX0, aV2 = theY1 - theY0;
+  double aW1 = theX3 - theX2, aW2 = theY3 - theY2;
+
+  double aT2 = 0;
+  if (aV1  != 0 && aV2 != 0)
+    aT2 = (( theY2 - theY0 )/aV2 - ( theX2 - theX0 )/aV1) / ( aW1/aV1 - aW2/aV2 );
+  else
+    aT2 = DBL_MAX;
+
+  theX  = theX2 + aT2*aW1;
+  theY = theY2 + aT2*aW2;
+
+  // the coordinates of two lines are on the common line
+  //It is not possible to use Precision::Confusion(), because it is e-0.8, but V is sometimes e-6
+  Standard_Real aPrec = PRECISION_TOLERANCE;
+  if (fabs(theX - theX0) < aPrec && fabs(theY - theY0) < aPrec) {
+    ProjectPointOnLine(theX2, theY2, theX3, theY3, theX1, theY1, theX, theY);    
+  }
+}
+
+void PartSet_Tools::ProjectPointOnLine(double theX1, double theY1, double theX2, double theY2,
+                                       double thePointX, double thePointY, double& theX, double& theY)
+{
+  theX = theY = 0;
+
+  Handle(Geom_Line) aLine = new Geom_Line(gp_Pnt(theX1, theY1, 0),
+                                     gp_Dir(gp_Vec(gp_Pnt(theX1, theY1, 0), gp_Pnt(theX2, theY2, 0))));
+  GeomAPI_ProjectPointOnCurve aProj(gp_Pnt(thePointX, thePointY, 0), aLine);
+
+  Standard_Integer aNbPoint = aProj.NbPoints();
+  if (aNbPoint > 0) {
+    gp_Pnt aPoint = aProj.Point(1);
+    theX = aPoint.X();
+    theY = aPoint.Y();
+  }
+}
index 19cdccb2ed1580255fbc50945cc48bd4d269d75e..ecb28b7444f022ad8b7ed99404832f981295e9e4 100644 (file)
@@ -35,6 +35,32 @@ public:
   /// \param theY the Y coordinate
   static void ConvertTo2D(const gp_Pnt& thePoint, boost::shared_ptr<ModelAPI_Feature> theSketch,
                           Handle(V3d_View) theView, double& theX, double& theY);
+
+  /// Returns the point of intersection of the two lines, the first is (v0, v1), the second is (v2, v3),
+  /// where vi - {xi,yi}. If the v0 is on the second line, the result is a projection of the v1 to this line
+  /// \param theX0 the horizontal coordinate of 0 point
+  /// \param theY0 the vertical coordinate of 0 point
+  /// \param theX1 the horizontal coordinate of 1 point
+  /// \param theY1 the vertical coordinate of 1 point
+  /// \param theX2 the horizontal coordinate of 2 point
+  /// \param theY2 the vertical coordinate of 2 point
+  /// \param theX3 the horizontal coordinate of 3 point
+  /// \param theY3 the vertical coordinate of 3 point
+  /// \param theX the output horizontal coordinate of the intersection point
+  /// \param theY the outpup vertical coordinate of the intersection point
+  static void IntersectLines(double theX0, double theY0, double theX1, double theY1,
+                             double theX2, double theY2, double theX3, double theY3,
+                             double& theX, double& theY);
+
+  /// Returns the coordinates of projection of the point to the line
+  /// \param thePointX the projected point horizontal coordinate
+  /// \param thePointY the projected point vertictal coordinate
+  /// \param theX1 the horizontal coordinate of the first line point
+  /// \param theY1 the vertical coordinate of the first line point
+  /// \param theX2 the horizontal coordinate of the second line point
+  /// \param theY2 the vertical coordinate of the second line point
+  static void ProjectPointOnLine(double theX1, double theY1, double theX2, double theY2,
+                                 double thePointX, double thePointY, double& theX, double& theY);
 };
 
 #endif
index 347fabe8818e0f69d364c882db8d78958406e317..eb5956ec2a58ba921311c12eb593b55d1c8ecd84 100644 (file)
@@ -6,6 +6,9 @@ SET(PROJECT_HEADERS
     SketchPlugin_Plugin.h
     SketchPlugin_Sketch.h
     SketchPlugin_Line.h
+    SketchPlugin_Point.h
+    SketchPlugin_Constraint.h
+    SketchPlugin_ConstraintCoincidence.h
 )
 
 SET(PROJECT_SOURCES
@@ -13,6 +16,8 @@ SET(PROJECT_SOURCES
     SketchPlugin_Plugin.cpp
     SketchPlugin_Sketch.cpp
     SketchPlugin_Line.cpp
+    SketchPlugin_Point.cpp
+    SketchPlugin_ConstraintCoincidence.cpp
 )
 
 SET(PROJECT_LIBRARIES
diff --git a/src/SketchPlugin/SketchPlugin_Constraint.h b/src/SketchPlugin/SketchPlugin_Constraint.h
new file mode 100644 (file)
index 0000000..e69a316
--- /dev/null
@@ -0,0 +1,68 @@
+// File:    SketchPlugin_Constraint.h
+// Created: 08 May 2014
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchPlugin_Constraint_HeaderFile
+#define SketchPlugin_Constraint_HeaderFile
+
+#include "SketchPlugin.h"
+#include "SketchPlugin_Feature.h"
+#include <ModelAPI_AttributeReference.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <list>
+
+/*  Description: 
+ *    Each constraint uses a set of parameters. In the SolveSpace library 
+ *    these parameters are named "valA", "ptA", "ptB", "entityA", "entityB". 
+ *    The "ptA" and "ptB" parameters represents a point in the constraint.
+ *    The "entityA" and "entityB" represents any other object (and a point too).
+ *    And the "valA" represents a real value.
+ *
+ *    The attributes below are named independent of the SolveSpace.
+ *    Some of them may be unused. 
+ *
+ *    Also the list of possible attributes is provided to simplify assignment.
+ */
+/// The value parameter for the constraint
+const std::string CONSTRAINT_ATTR_VALUE("ConstraintValue");
+/// First entity for the constraint
+const std::string CONSTRAINT_ATTR_ENTITY_A("ConstraintEntityA");
+/// Second entity for the constraint
+const std::string CONSTRAINT_ATTR_ENTITY_B("ConstraintEntityB");
+/// Third entity for the constraint
+const std::string CONSTRAINT_ATTR_ENTITY_C("ConstraintEntityC");
+/// Fourth entity for the constraint
+const std::string CONSTRAINT_ATTR_ENTITY_D("ConstraintEntityD");
+/// List of constraint attributes
+const std::string CONSTRAINT_ATTRIBUTES[4] = 
+                      {CONSTRAINT_ATTR_ENTITY_A, CONSTRAINT_ATTR_ENTITY_B, 
+                       CONSTRAINT_ATTR_ENTITY_C, CONSTRAINT_ATTR_ENTITY_D};
+
+
+/** \class SketchPlugin_Constraint
+ *  \ingroup DataModel
+ *  \brief Feature for creation of a new constraint between other features.
+ *         Base class for all constraints.
+ */
+class SketchPlugin_Constraint: public SketchPlugin_Feature
+{
+public:
+  /// \brief Returns the kind of a feature
+  SKETCHPLUGIN_EXPORT virtual const std::string& getKind() 
+  {static std::string MY_KIND = "SketchConstraint"; return MY_KIND;}
+
+  /// \brief Returns to which group in the document must be added feature
+  SKETCHPLUGIN_EXPORT virtual const std::string& getGroup() 
+  {static std::string MY_GROUP = "Sketch"; return MY_GROUP;}
+
+  /** \brief Adds sub-feature of the higher level feature (sub-element of the sketch)
+   *  \param theFeature sub-feature
+   */
+  SKETCHPLUGIN_EXPORT virtual const void addSub(
+    const boost::shared_ptr<ModelAPI_Feature>& theFeature) {}
+
+  /// \brief Use plugin manager for features creation
+  SketchPlugin_Constraint() {}
+};
+
+#endif
diff --git a/src/SketchPlugin/SketchPlugin_ConstraintCoincidence.cpp b/src/SketchPlugin/SketchPlugin_ConstraintCoincidence.cpp
new file mode 100644 (file)
index 0000000..6cd5c1b
--- /dev/null
@@ -0,0 +1,30 @@
+// File:    SketchPlugin_ConstraintCoincidence.cpp
+// Created: 08 May 2014
+// Author:  Artem ZHIDKOV
+
+#include "SketchPlugin_ConstraintCoincidence.h"
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_Data.h>
+#include <SketchPlugin_Point.h>
+
+SketchPlugin_ConstraintCoincidence::SketchPlugin_ConstraintCoincidence()
+{
+}
+
+void SketchPlugin_ConstraintCoincidence::initAttributes()
+{
+  data()->addAttribute(CONSTRAINT_ATTR_ENTITY_A, ModelAPI_AttributeRefAttr::type());
+  data()->addAttribute(CONSTRAINT_ATTR_ENTITY_B, ModelAPI_AttributeRefAttr::type());
+}
+
+void SketchPlugin_ConstraintCoincidence::execute()
+{
+}
+
+const boost::shared_ptr<GeomAPI_Shape>&  SketchPlugin_ConstraintCoincidence::preview()
+{
+  /// \todo Preview for point coincidence
+  return getPreview();
+}
+
diff --git a/src/SketchPlugin/SketchPlugin_ConstraintCoincidence.h b/src/SketchPlugin/SketchPlugin_ConstraintCoincidence.h
new file mode 100644 (file)
index 0000000..fe75115
--- /dev/null
@@ -0,0 +1,43 @@
+// File:    SketchPlugin_ConstraintCoincidence.h
+// Created: 08 May 2014
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchPlugin_ConstraintCoincidence_HeaderFile
+#define SketchPlugin_ConstraintCoincidence_HeaderFile
+
+#include "SketchPlugin.h"
+#include "SketchPlugin_Constraint.h"
+#include <list>
+
+
+/** \class SketchPlugin_ConstraintCoincidence
+ *  \ingroup DataModel
+ *  \brief Feature for creation of a new constraint which defines equvalence of two points
+ *
+ *  These constraint has two attributes: CONSTRAINT_ATTR_POINT_A and CONSTRAINT_ATTR_POINT_B
+ */
+class SketchPlugin_ConstraintCoincidence: public SketchPlugin_Constraint
+{
+public:
+  /// \brief Returns the kind of a feature
+  SKETCHPLUGIN_EXPORT virtual const std::string& getKind() 
+  {static std::string MY_KIND = "SketchConstraintCoincidence"; return MY_KIND;}
+
+  /// \brief Returns to which group in the document must be added feature
+  SKETCHPLUGIN_EXPORT virtual const std::string& getGroup() 
+  {static std::string MY_GROUP = "Sketch"; return MY_GROUP;}
+
+  /// \brief Creates a new part document if needed
+  SKETCHPLUGIN_EXPORT virtual void execute();
+
+  /// \brief Request for initialization of data model of the feature: adding all attributes
+  SKETCHPLUGIN_EXPORT virtual void initAttributes();
+
+  /// \brief Returns the sketch preview
+  SKETCHPLUGIN_EXPORT virtual const boost::shared_ptr<GeomAPI_Shape>& preview();
+
+  /// \brief Use plugin manager for features creation
+  SketchPlugin_ConstraintCoincidence();
+};
+
+#endif
index ab95647eedc7b0abec58d235f20d2536a1b23dab..bef72b89daba45c662e0d7ba3e670cb0ecc9b5c1 100644 (file)
@@ -1,6 +1,7 @@
 #include "SketchPlugin_Plugin.h"
 #include "SketchPlugin_Sketch.h"
 #include "SketchPlugin_Line.h"
+#include "SketchPlugin_ConstraintCoincidence.h"
 #include <ModelAPI_PluginManager.h>
 #include <ModelAPI_Document.h>
 
@@ -23,6 +24,9 @@ boost::shared_ptr<ModelAPI_Feature> SketchPlugin_Plugin::createFeature(string th
   else if (theFeatureID == "SketchLine") {
     return boost::shared_ptr<ModelAPI_Feature>(new SketchPlugin_Line);
   }
+  else if (theFeatureID == "SketchConstraintCoincidence") {
+    return boost::shared_ptr<ModelAPI_Feature>(new SketchPlugin_ConstraintCoincidence);
+  }
   // feature of such kind is not found
   return boost::shared_ptr<ModelAPI_Feature>();
 }
diff --git a/src/SketchPlugin/SketchPlugin_Point.cpp b/src/SketchPlugin/SketchPlugin_Point.cpp
new file mode 100644 (file)
index 0000000..1d9601a
--- /dev/null
@@ -0,0 +1,37 @@
+// File:    SketchPlugin_Point.cpp
+// Created: 07 May 2014
+// Author:  Artem ZHIDKOV
+
+#include "SketchPlugin_Point.h"
+#include "SketchPlugin_Sketch.h"
+#include <ModelAPI_Data.h>
+#include <GeomDataAPI_Point2D.h>
+
+using namespace std;
+
+SketchPlugin_Point::SketchPlugin_Point()
+{
+}
+
+void SketchPlugin_Point::initAttributes()
+{
+  data()->addAttribute(POINT_ATTR_COORD, GeomDataAPI_Point2D::type());
+}
+
+void SketchPlugin_Point::execute() 
+{
+}
+
+const boost::shared_ptr<GeomAPI_Shape>& SketchPlugin_Point::preview()
+{
+  SketchPlugin_Sketch* aSketch = sketch();
+  // compute a point in 3D view
+  boost::shared_ptr<GeomDataAPI_Point2D> aPoint = 
+    boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(POINT_ATTR_COORD));
+  boost::shared_ptr<GeomAPI_Pnt> aPoint3D(aSketch->to3D(aPoint->x(), aPoint->y()));
+  // make a visible point
+  //boost::shared_ptr<GeomAPI_Shape> anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, anEnd);
+  //setPreview(anEdge);
+
+  return getPreview();
+}
diff --git a/src/SketchPlugin/SketchPlugin_Point.h b/src/SketchPlugin/SketchPlugin_Point.h
new file mode 100644 (file)
index 0000000..f4ecc49
--- /dev/null
@@ -0,0 +1,48 @@
+// File:    SketchPlugin_Point.h
+// Created: 07 May 2014
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchPlugin_Point_HeaderFile
+#define SketchPlugin_Point_HeaderFile
+
+#include "SketchPlugin.h"
+#include "SketchPlugin_Feature.h"
+#include <list>
+
+/// Coordinates of the point
+const std::string POINT_ATTR_COORD("PointCoordindates");
+
+/**\class SketchPlugin_Point
+ * \ingroup DataModel
+ * \brief Feature for creation of a new point.
+ */
+class SketchPlugin_Point: public SketchPlugin_Feature
+{
+public:
+  /// Returns the kind of a feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getKind() 
+  {static std::string MY_KIND = "SketchPoint"; return MY_KIND;}
+
+  /// Returns to which group in the document must be added feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getGroup() 
+  {static std::string MY_GROUP = "Sketch"; return MY_GROUP;}
+
+  /// Creates a new part document if needed
+ SKETCHPLUGIN_EXPORT virtual void execute();
+
+  /// Request for initialization of data model of the feature: adding all attributes
+ SKETCHPLUGIN_EXPORT virtual void initAttributes();
+
+  /// Returns the sketch preview
+  SKETCHPLUGIN_EXPORT virtual const boost::shared_ptr<GeomAPI_Shape>& preview();
+
+  /// Adds sub-feature of the higher level feature (sub-element of the sketch)
+  /// \param theFeature sub-feature
+  SKETCHPLUGIN_EXPORT virtual const void addSub(
+    const boost::shared_ptr<ModelAPI_Feature>& theFeature) {};
+
+  /// Use plugin manager for features creation
+  SketchPlugin_Point();
+};
+
+#endif
index 2feedd6d7372fbe64d3e6094a55d30616ae332d5..29cf61b04a16a7c8ad45c3e60295d10fdf4c4dcf 100644 (file)
@@ -5,10 +5,12 @@
         <label text="Select a plane on which to create a sketch" tooltip="Select a plane on which to create a sketch"/> 
       <!--icon=":pictures/x_point.png"-->
       </feature>
+      <feature id="SketchPoint" text="Point" tooltip="Create a new point" icon=":icons/point.png" />
       <feature id="SketchLine" text="Line" tooltip="Create a new line" icon=":icons/line.png">
         <point_selector id="StartPoint" title="Start point" tooltip="Start point of the line"/>
         <point_selector id="EndPoint" title="End point" tooltip="End point of the line"/>
       </feature>
+      <feature id="SketchConstraintCoincidence" text="Points coincidence" tooltip="Create constraint for the coincidence of two points" icon="" />
     </group>
   </workbench>
 </plugin>
diff --git a/src/SketchSolver/CMakeLists.txt b/src/SketchSolver/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5d04a4a
--- /dev/null
@@ -0,0 +1,37 @@
+INCLUDE(Common)
+INCLUDE(FindSolveSpace)
+
+SET(PROJECT_HEADERS
+    SketchSolver.h
+    SketchSolver_Solver.h
+    SketchSolver_ConstraintManager.h
+)
+
+SET(PROJECT_SOURCES
+    SketchSolver_Solver.cpp
+    SketchSolver_ConstraintManager.cpp
+)
+
+SET(PROJECT_LIBRARIES
+    ${SLVS_LIBRARIES}
+    SketchPlugin
+)
+
+INCLUDE_DIRECTORIES(
+    ../SketchPlugin
+    ../ModelAPI
+    ../GeomAPI
+)
+
+ADD_DEFINITIONS(-DSKETCHSOLVER_EXPORTS ${BOOST_DEFINITIONS})
+
+ADD_LIBRARY(SketchSolver SHARED 
+    ${PROJECT_SOURCES} 
+    ${PROJECT_HEADERS}
+)
+
+TARGET_LINK_LIBRARIES(SketchSolver
+    ${PROJECT_LIBRARIES}
+)
+
+INSTALL(TARGETS SketchSolver DESTINATION plugins)
diff --git a/src/SketchSolver/SketchSolver.h b/src/SketchSolver/SketchSolver.h
new file mode 100644 (file)
index 0000000..2f98bf5
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef SKETCHSOLVER_H
+#define SKETCHSOLVER_H
+
+#if defined SKETCHSOLVER_EXPORTS
+#if defined WIN32
+#define SKETCHSOLVER_EXPORT              __declspec( dllexport )
+#else
+#define SKETCHSOLVER_EXPORT
+#endif
+#else
+#if defined WIN32
+#define SKETCHSOLVER_EXPORT              __declspec( dllimport )
+#else
+#define SKETCHSOLVER_EXPORT
+#endif
+#endif
+
+#endif
diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.cpp b/src/SketchSolver/SketchSolver_ConstraintManager.cpp
new file mode 100644 (file)
index 0000000..7984b03
--- /dev/null
@@ -0,0 +1,194 @@
+// File:    SketchSolver_ConstraintManager.cpp
+// Created: 08 May 2014
+// Author:  Artem ZHIDKOV
+
+#include "SketchSolver_ConstraintManager.h"
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_Data.h>
+#include <SketchPlugin_Constraint.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_Line.h>
+
+
+/// This value is used to give unique index to the groups
+static Slvs_hGroup myGroupIndexer = 0;
+
+// ========================================================
+// ========= SketchSolver_ConstraintManager ===============
+// ========================================================
+SketchSolver_ConstraintManager::SketchSolver_ConstraintManager()
+{
+  myGroups.clear();
+}
+
+SketchSolver_ConstraintManager::~SketchSolver_ConstraintManager()
+{
+  myGroups.clear();
+}
+
+void SketchSolver_ConstraintManager::findGroups(
+              boost::shared_ptr<SketchPlugin_Constraint> theConstraint, 
+              std::vector<Slvs_hGroup>&                  theGroupIDs) const
+{
+  std::vector<SketchSolver_ConstraintGroup>::const_iterator aGroupIter;
+  for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
+    if (aGroupIter->isInteract(theConstraint))
+      theGroupIDs.push_back(aGroupIter->getId());
+}
+
+
+// ========================================================
+// =========  SketchSolver_ConstraintGroup  ===============
+// ========================================================
+
+SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::SketchSolver_ConstraintGroup()
+  : myID(++myGroupIndexer),
+    myParamMaxID(0),
+    myEntityMaxID(0),
+    myConstrMaxID(0),
+    myConstraintMap()
+{
+  myParams.clear();
+  myEntities.clear();
+  myConstraints.clear();
+
+  // The workplane will be initialized on first constraint, so its handle is NULL meanwhile
+  myWorkplane.h = 0;
+
+  // Nullify all elements of the set of equations
+  myConstrSet.param = 0;
+  myConstrSet.entity = 0;
+  myConstrSet.constraint = 0;
+  myConstrSet.failed = 0;
+}
+
+SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::~SketchSolver_ConstraintGroup()
+{
+  myParams.clear();
+  myEntities.clear();
+  myConstraints.clear();
+  myConstraintMap.clear();
+
+  if (myConstrSet.param)
+    delete [] myConstrSet.param;
+  if (myConstrSet.entity)
+    delete [] myConstrSet.entity;
+  if (myConstrSet.constraint)
+    delete [] myConstrSet.constraint;
+  if (myConstrSet.failed)
+    delete [] myConstrSet.failed;
+}
+
+bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::isInteract(
+                boost::shared_ptr<SketchPlugin_Constraint> theConstraint) const
+{
+  /// \todo Should be implemented
+  return false;
+}
+
+bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::addConstraint(
+                boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
+{
+  if (myWorkplane.h == 0)
+  {
+//    // Create workplane when first constraint is added
+//    std::list< boost::shared_ptr<ModelAPI_Attribute> > aWPAttr;
+//    theConstraint->getSketchParameters(aWPAttr);
+//    if (!addWorkplane(aWPAttr))
+//      return false;
+  }
+
+  // Create constraint parameters
+  double aDistance = 0.0; // scalar value of the constraint
+  boost::shared_ptr<ModelAPI_AttributeDouble> aDistAttr =
+    boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theConstraint->data()->attribute(CONSTRAINT_ATTR_VALUE));
+  if (aDistAttr.get())
+    aDistance = aDistAttr->value();
+
+  /// \todo Specify the entities
+  Slvs_hEntity aPtA, aPtB, aEntityA, aEntityB; // parameters of the constraint
+  boost::shared_ptr<ModelAPI_Attribute> aEntAttr = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_A);
+  aPtA = addEntity(aEntAttr);
+  if (aPtA == 0) return false;
+  aEntAttr = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_B);
+  aPtB = addEntity(aEntAttr);
+  if (aPtB == 0) return false;
+  aEntAttr = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_C);
+  aEntityA = addEntity(aEntAttr);
+  if (aEntityA == 0) return false;
+  aEntAttr = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_D);
+  aEntityB = addEntity(aEntAttr);
+  if (aEntityB == 0) return false;
+
+  // Constraint type
+  int aConstrType = getConstraintType(theConstraint);
+  if (aConstrType == 0) return false;
+
+  // Create SolveSpace constraint structure
+  Slvs_Constraint aConstraint = 
+    Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType, myWorkplane.h, 
+                        aDistance, aPtA, aPtB, aEntityA, aEntityB);
+  myConstraints.push_back(aConstraint);
+  myConstraintMap[theConstraint] = *(myConstraints.rbegin());
+
+  return true;
+}
+
+Slvs_hEntity SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::addEntity(
+                boost::shared_ptr<ModelAPI_Attribute> theEntity)
+{
+  /// \todo Should be implemented
+  return 0;
+}
+
+bool SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::addWorkplane(
+                std::list< boost::shared_ptr<ModelAPI_Attribute> >& theParams)
+{
+  /// \todo Should be implemented
+  return false;
+}
+
+int SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup::getConstraintType(
+                const boost::shared_ptr<SketchPlugin_Constraint>& theConstraint) const
+{
+//  if (theConstraint->getKind() == SketchPlugin_ConstraintDistance().getKind())
+//  {
+//    boost::shared_ptr<ModelAPI_Attribute> aPtA  = theConstraint->data()->attribute(CONSTRAINT_ATTR_POINT_A);
+//    boost::shared_ptr<ModelAPI_Attribute> aPtB  = theConstraint->data()->attribute(CONSTRAINT_ATTR_POINT_B);
+//    boost::shared_ptr<ModelAPI_Attribute> aEntA = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_A);
+//    boost::shared_ptr<ModelAPI_Attribute> aEntB = theConstraint->data()->attribute(CONSTRAINT_ATTR_ENTITY_B);
+//    boost::shared_ptr<ModelAPI_AttributeDouble> aDistance = 
+//      boost::shared_dynamic_cast<ModelAPI_AttributeDouble>(theConstraint->data()->attribute(CONSTRAINT_ATTR_VALUE));
+//    if (aPtA.get()) // ptA is an attribute of the constraint
+//    {
+////      if (aEntA.get()) // entityA is an attribute of the constraint
+////      {
+////        if (aEntA->feature()->getKind() == SketchPlugin_Line().getKind()) // entityA is a line
+////        {
+////          if (aEntB.get() && aEntB->feature()->getKind() == SketchPlugin_Line().getKind()) // entityB is a line too
+////            return SLVS_C_ANGLE;
+////          else if (aPtB.get()) // ptB is also an attribute of the constraint
+////            return SLVS_C_PROJ_PT_DISTANCE;
+////          else
+////            return SLVS_C_PT_LINE_DISTANCE;
+////        }
+////        /// \todo Implement other point-entity distances
+////      }
+////      else 
+//      if (aPtB.get()) // ptB is an attribute of the constrtaint => point-point distance
+//      {
+//        if (aDistance->value() == 0.0)
+//          return SLVS_C_POINTS_COINCIDENT;
+//        else 
+//          return SLVS_C_PT_PT_DISTANCE;
+//      }
+//    }
+//    else if (aEntA.get() && !aEntB.get() && !aPtB.get())
+//      return SLVS_C_DIAMETER;
+//    return SLVS_C_UNKNOWN;
+//  }
+  /// \todo Implement other kind of constrtaints
+
+  return SLVS_C_UNKNOWN;
+}
diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.h b/src/SketchSolver/SketchSolver_ConstraintManager.h
new file mode 100644 (file)
index 0000000..7bd108d
--- /dev/null
@@ -0,0 +1,138 @@
+// File:    SketchSolver_ConstraintManager.h
+// Created: 08 May 2014
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintManager_Headerfile
+#define SketchSolver_ConstraintManager_Headerfile
+
+#include "SketchSolver.h"
+
+#include <SketchPlugin_Constraint.h>
+
+// Need to be defined before including SolveSpace to avoid additional dependances on Windows platform
+#if defined(WIN32) && !defined(HAVE_C99_INTEGER_TYPES)
+typedef unsigned int UINT32;
+#endif
+#include <string.h>
+#include <slvs.h>
+
+#include <map>
+#include <vector>
+
+
+// Unknown constraint (for error reporting)
+#define SLVS_C_UNKNOWN 0
+
+/** \class   SketchSolver_ConstraintManager
+ *  \ingroup DataModel
+ *  \brief   Transforms the Constraint feature into the format understandable by SolveSpace library.
+ *
+ *  Constraints created for SolveSpace library will be divided into the groups.
+ *  The division order based on connectedness of the features by the constraints.
+ *  The groups may be fused or separated according to the new constraints.
+ */
+class SketchSolver_ConstraintManager
+{
+public:
+  SketchSolver_ConstraintManager();
+  ~SketchSolver_ConstraintManager();
+
+  /** \brief Adds a constraint into the manager
+   *  \param[in] theConstraint constraint to be added
+   *  \return \c true if the constraint added successfully
+   */
+  SKETCHSOLVER_EXPORT bool addConstraint(boost::shared_ptr<SketchPlugin_Constraint> theConstraint);
+
+  /** \brief Removes a constraint from the manager
+   *  \param[in] theConstraint constraint to be removed
+   *  \return \c true if the constraint removed successfully
+   */
+  SKETCHSOLVER_EXPORT bool removeConstraint(boost::shared_ptr<SketchPlugin_Constraint> theConstraint);
+
+private:
+  class SketchSolver_ConstraintGroup;
+
+  /** \brief Searches list of groups which interact with specified constraint
+   *  \param[in]  theConstraint constraint to be found
+   *  \param[out] theGroups     list of group indexes interacted with constraint
+   */
+  void findGroups(boost::shared_ptr<SketchPlugin_Constraint> theConstraint, 
+                  std::vector<Slvs_hGroup>&                  theGroupIDs) const;
+
+private:
+  std::vector<SketchSolver_ConstraintGroup> myGroups; ///< groups of constraints
+};
+
+
+/** \class   SketchSolver_ConstraintGroup
+ *  \ingroup DataModel
+ *  \brief   Keeps the group of constraints which based on the same entities
+ */
+class SketchSolver_ConstraintManager::SketchSolver_ConstraintGroup
+{
+public:
+  SketchSolver_ConstraintGroup();
+  ~SketchSolver_ConstraintGroup();
+
+  /// \brief Returns group's unique identifier
+  const Slvs_hGroup& getId() const
+  {return myID;}
+
+  /** \brief Adds a constraint into the group
+   *  \param[in] theConstraint constraint to be added
+   *  \return \c true if the constraint added successfully
+   */
+  bool addConstraint(boost::shared_ptr<SketchPlugin_Constraint> theConstraint);
+
+  /** \brief Removes a constraint into the group
+   *  \param[in] theConstraint constraint to be removed
+   *  \return \c true if the constraint removed successfully
+   */
+  bool removeConstraint(boost::shared_ptr<SketchPlugin_Constraint> theConstraint);
+
+  /** \brief Verifies the constraint uses the objects from this group
+   *  \param[in] theConstraint constraint for verification of interaction
+   *  \return \c true if the constrained objects are used in current group
+   */
+  bool isInteract(boost::shared_ptr<SketchPlugin_Constraint> theConstraint) const;
+
+protected:
+  /** \brief Creates a workplane from the sketch parameters
+   *  \param[in] theParams list of the basic parameters of the workplane
+   *  \return \c true if success
+   */
+  bool addWorkplane(std::list< boost::shared_ptr<ModelAPI_Attribute> >& theParams);
+
+  /** \brief Adds an entity into the group
+   *  \param[in] theEntity the object of constraint
+   *  \return identifier of created entity or 0 if entity was not added
+   */
+  Slvs_hEntity addEntity(boost::shared_ptr<ModelAPI_Attribute> theEntity);
+
+  /** \brief Adds a parameter into the group
+   *  \param[in] theParam parameter to be added
+   *  \return identifier of created parameter or 0 if it was not added
+   */
+  Slvs_hParam addParameter(double theParam);
+
+  /** \brief Compute constraint type according to SolveSpace identifiers
+   *  \param[in] theConstraint constraint which type should be determined
+   *  \return identifier of constraint type
+   */
+  int getConstraintType(const boost::shared_ptr<SketchPlugin_Constraint>& theConstraint) const;
+
+private:
+  Slvs_hGroup                  myID;            ///< the index of the group
+  Slvs_Entity                  myWorkplane;     ///< Workplane for the current group
+  std::vector<Slvs_Param>      myParams;        ///< List of parameters of the constraints
+  Slvs_hParam                  myParamMaxID;    ///< Actual maximal ID of parameters
+  std::vector<Slvs_Entity>     myEntities;      ///< List of entities of the constaints
+  Slvs_hEntity                 myEntityMaxID;   ///< Actual maximal ID of entities
+  std::vector<Slvs_Constraint> myConstraints;   ///< List of constraints in SolveSpace format
+  Slvs_hConstraint             myConstrMaxID;   ///< Actual maximal ID of constraints
+  Slvs_System                  myConstrSet;     ///< SolveSpace's set of equations obtained by constraints
+  std::map<boost::shared_ptr<SketchPlugin_Constraint>, Slvs_Constraint> 
+                               myConstraintMap; ///< The map between SketchPlugin and SolveSpace constraints
+};
+
+#endif
diff --git a/src/SketchSolver/SketchSolver_Solver.cpp b/src/SketchSolver/SketchSolver_Solver.cpp
new file mode 100644 (file)
index 0000000..bf86e4d
--- /dev/null
@@ -0,0 +1,5 @@
+// File:    SketchSolver_Solver.cpp
+// Created: 07 May 2014
+// Author:  Artem ZHIDKOV
+
+#include "SketchSolver_Solver.h"
diff --git a/src/SketchSolver/SketchSolver_Solver.h b/src/SketchSolver/SketchSolver_Solver.h
new file mode 100644 (file)
index 0000000..beb2f24
--- /dev/null
@@ -0,0 +1,10 @@
+// File:    SketchSolver_Solver.h
+// Created: 07 May 2014
+// Author:  Artem ZHIDKOV
+
+#ifndef SketchSolver_Solver_Headerfile
+#define SketchSolver_Solver_Headerfile
+
+#include "SketchSolver.h"
+
+#endif