1 // File: PartSet_OperationSketchLine.h
2 // Created: 20 Apr 2014
3 // Author: Natalia ERMOLAEVA
5 #include <PartSet_OperationSketchLine.h>
7 #include <PartSet_Tools.h>
8 #include <PartSet_OperationSketch.h>
10 #include <SketchPlugin_Feature.h>
11 #include <SketchPlugin_Sketch.h>
12 #include <SketchPlugin_ConstraintCoincidence.h>
14 #include <GeomDataAPI_Point2D.h>
16 #include <ModuleBase_OperationDescription.h>
18 #include <ModelAPI_Data.h>
19 #include <ModelAPI_Document.h>
20 #include <ModelAPI_AttributeRefAttr.h>
21 #include <ModelAPI_AttributeRefList.h>
23 #include <SketchPlugin_Constraint.h>
25 #include <Geom_Line.hxx>
28 #include <XGUI_ViewerPrs.h>
29 #include <XGUI_Constants.h>
31 #include <SketchPlugin_Line.h>
33 #include <V3d_View.hxx>
34 #include <TopoDS_Vertex.hxx>
36 #include <BRep_Tool.hxx>
42 #include <QMouseEvent>
46 PartSet_OperationSketchLine::PartSet_OperationSketchLine(const QString& theId,
48 FeaturePtr theFeature)
49 : PartSet_OperationSketchBase(theId, theParent), mySketch(theFeature),
50 myPointSelectionMode(SM_FirstPoint)
54 PartSet_OperationSketchLine::~PartSet_OperationSketchLine()
58 bool PartSet_OperationSketchLine::canBeCommitted() const
60 return myPointSelectionMode == SM_DonePoint;
63 bool PartSet_OperationSketchLine::isGranted(ModuleBase_IOperation* theOperation) const
65 return theOperation->getDescription()->operationId().toStdString() == PartSet_OperationSketch::Type();
68 std::list<int> PartSet_OperationSketchLine::getSelectionModes(FeaturePtr theFeature) const
70 std::list<int> aModes;
71 if (theFeature != feature())
72 aModes = PartSet_OperationSketchBase::getSelectionModes(theFeature);
76 void PartSet_OperationSketchLine::init(FeaturePtr theFeature,
77 const std::list<XGUI_ViewerPrs>& /*theSelected*/,
78 const std::list<XGUI_ViewerPrs>& /*theHighlighted*/)
80 if (!theFeature || theFeature->getKind() != SKETCH_LINE_KIND)
82 // use the last point of the previous feature as the first of the new one
83 boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
84 myInitPoint = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(LINE_ATTR_END));
87 FeaturePtr PartSet_OperationSketchLine::sketch() const
92 void PartSet_OperationSketchLine::mouseReleased(QMouseEvent* theEvent, Handle(V3d_View) theView,
93 const std::list<XGUI_ViewerPrs>& theSelected,
94 const std::list<XGUI_ViewerPrs>& /*theHighlighted*/)
96 if (myPointSelectionMode == SM_DonePoint)
98 // if the point creation is finished, the next mouse release should commit the modification
99 // the next release can happens by double click in the viewer
101 restartOperation(PartSet_OperationSketchLine::Type(), feature());
107 bool isFoundPoint = false;
108 gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theView);
109 if (theSelected.empty()) {
110 PartSet_Tools::convertTo2D(aPoint, sketch(), theView, aX, anY);
114 XGUI_ViewerPrs aPrs = theSelected.front();
115 const TopoDS_Shape& aShape = aPrs.shape();
116 if (!aShape.IsNull()) // the point is selected
118 if (aShape.ShapeType() == TopAbs_VERTEX) {
119 const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
120 if (!aVertex.IsNull()) {
121 aPoint = BRep_Tool::Pnt(aVertex);
122 PartSet_Tools::convertTo2D(aPoint, sketch(), theView, aX, anY);
125 setConstraints(aX, anY);
128 else if (aShape.ShapeType() == TopAbs_EDGE) // the line is selected
130 FeaturePtr aFeature = aPrs.feature();
132 double X0, X1, X2, X3;
133 double Y0, Y1, Y2, Y3;
134 getLinePoint(aFeature, LINE_ATTR_START, X2, Y2);
135 getLinePoint(aFeature, LINE_ATTR_END, X3, Y3);
136 PartSet_Tools::convertTo2D(aPoint, sketch(), theView, X1, Y1);
138 switch (myPointSelectionMode) {
140 PartSet_Tools::projectPointOnLine(X2, Y2, X3, Y3, X1, Y1, aX, anY);
142 case SM_SecondPoint: {
143 getLinePoint(feature(), LINE_ATTR_START, X0, Y0);
144 PartSet_Tools::intersectLines(X0, Y0, X1, Y1, X2, Y2, X3, Y3, aX, anY);
156 switch (myPointSelectionMode)
158 case SM_FirstPoint: {
159 setLinePoint(feature(), aX, anY, LINE_ATTR_START);
160 setLinePoint(feature(), aX, anY, LINE_ATTR_END);
163 setPointSelectionMode(SM_SecondPoint);
166 case SM_SecondPoint: {
167 setLinePoint(feature(), aX, anY, LINE_ATTR_END);
170 setPointSelectionMode(SM_DonePoint);
178 void PartSet_OperationSketchLine::mouseMoved(QMouseEvent* theEvent, Handle(V3d_View) theView)
180 switch (myPointSelectionMode)
182 case SM_FirstPoint: {
184 gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theView);
185 PartSet_Tools::convertTo2D(aPoint, sketch(), theView, aX, anY);
186 setLinePoint(feature(), aX, anY, LINE_ATTR_START);
187 setLinePoint(feature(), aX, anY, LINE_ATTR_END);
189 emit focusActivated(LINE_ATTR_START);
194 gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theView);
195 setLinePoint(aPoint, theView, LINE_ATTR_END);
197 emit focusActivated(LINE_ATTR_END);
203 restartOperation(PartSet_OperationSketchLine::Type(), feature());
210 void PartSet_OperationSketchLine::keyReleased(std::string theName, QKeyEvent* theEvent)
212 int aKeyType = theEvent->key();
213 // the second point should be activated by any modification in the property panel
214 if (!theName.empty() /*&& aKeyType == Qt::Key_Return*/) {
215 if (theName == LINE_ATTR_START) {
216 setPointSelectionMode(SM_SecondPoint, false);
218 else if (theName == LINE_ATTR_END) {
219 setPointSelectionMode(SM_DonePoint, false);
222 keyReleased(theEvent->key());
225 void PartSet_OperationSketchLine::keyReleased(const int theKey)
228 case Qt::Key_Return: {
229 if (myPointSelectionMode == SM_DonePoint)
232 restartOperation(PartSet_OperationSketchLine::Type(), feature());
236 //emit launchOperation(PartSet_OperationSketchLine::Type(), FeaturePtr());
239 case Qt::Key_Escape: {
240 if (myPointSelectionMode == SM_DonePoint)
252 void PartSet_OperationSketchLine::startOperation()
254 PartSet_OperationSketchBase::startOperation();
255 setPointSelectionMode(!myInitPoint ? SM_FirstPoint : SM_SecondPoint);
257 emit multiSelectionEnabled(false);
260 void PartSet_OperationSketchLine::abortOperation()
262 emit featureConstructed(feature(), FM_Hide);
263 PartSet_OperationSketchBase::abortOperation();
266 void PartSet_OperationSketchLine::stopOperation()
268 PartSet_OperationSketchBase::stopOperation();
269 emit multiSelectionEnabled(true);
272 void PartSet_OperationSketchLine::afterCommitOperation()
274 PartSet_OperationSketchBase::afterCommitOperation();
275 emit featureConstructed(feature(), FM_Deactivation);
278 FeaturePtr PartSet_OperationSketchLine::createFeature(const bool theFlushMessage)
280 FeaturePtr aNewFeature = ModuleBase_Operation::createFeature(false);
282 boost::shared_ptr<SketchPlugin_Feature> aFeature =
283 boost::dynamic_pointer_cast<SketchPlugin_Feature>(sketch());
285 aFeature->addSub(aNewFeature);
288 setLinePoint(aNewFeature, myInitPoint->x(), myInitPoint->y(), LINE_ATTR_START);
289 setLinePoint(aNewFeature, myInitPoint->x(), myInitPoint->y(), LINE_ATTR_END);
291 boost::shared_ptr<ModelAPI_Data> aData = aNewFeature->data();
292 boost::shared_ptr<GeomDataAPI_Point2D> aPoint = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>
293 (aData->attribute(LINE_ATTR_START));
294 createConstraint(myInitPoint, aPoint);
297 emit featureConstructed(aNewFeature, FM_Activation);
303 void PartSet_OperationSketchLine::createConstraint(boost::shared_ptr<GeomDataAPI_Point2D> thePoint1,
304 boost::shared_ptr<GeomDataAPI_Point2D> thePoint2)
306 boost::shared_ptr<ModelAPI_Document> aDoc = document();
307 FeaturePtr aFeature = aDoc->addFeature(SKETCH_CONSTRAINT_COINCIDENCE_KIND);
310 boost::shared_ptr<SketchPlugin_Feature> aSketch =
311 boost::dynamic_pointer_cast<SketchPlugin_Feature>(sketch());
312 aSketch->addSub(aFeature);
315 boost::shared_ptr<ModelAPI_Data> aData = aFeature->data();
317 boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef1 =
318 boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aData->attribute(CONSTRAINT_ATTR_ENTITY_A));
319 aRef1->setAttr(thePoint1);
321 boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef2 =
322 boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aData->attribute(CONSTRAINT_ATTR_ENTITY_B));
323 aRef2->setAttr(thePoint2);
325 if (aFeature) // TODO: generate an error if feature was not created
329 void PartSet_OperationSketchLine::setConstraints(double theX, double theY)
331 std::string aPointArg;
332 switch (myPointSelectionMode)
335 aPointArg = LINE_ATTR_START;
338 aPointArg = LINE_ATTR_END;
344 FeaturePtr aSkFeature = feature();
346 boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
347 boost::shared_ptr<GeomDataAPI_Point2D> aPoint = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>
348 (aData->attribute(aPointArg));
349 aData = sketch()->data();
350 boost::shared_ptr<ModelAPI_AttributeRefList> aRefList =
351 boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(aData->attribute(SKETCH_ATTR_FEATURES));
353 std::list<FeaturePtr > aFeatures = aRefList->list();
354 std::list<FeaturePtr >::const_iterator anIt = aFeatures.begin(),
355 aLast = aFeatures.end();
356 for (; anIt != aLast; anIt++) {
357 FeaturePtr aFeature = *anIt;
358 boost::shared_ptr<GeomDataAPI_Point2D> aFPoint = findLinePoint(aFeature, theX, theY);
360 createConstraint(aFPoint, aPoint);
364 void PartSet_OperationSketchLine::getLinePoint(FeaturePtr theFeature,
365 const std::string& theAttribute,
366 double& theX, double& theY)
368 if (!theFeature || theFeature->getKind() != SKETCH_LINE_KIND)
370 boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
371 boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
372 boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
377 boost::shared_ptr<GeomDataAPI_Point2D> PartSet_OperationSketchLine::findLinePoint(
378 FeaturePtr theFeature,
379 double theX, double theY)
381 boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D;
382 if (!theFeature || theFeature->getKind() != SKETCH_LINE_KIND)
384 boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
386 boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
387 boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(LINE_ATTR_START));
388 if (fabs(aPoint->x() - theX) < Precision::Confusion() && fabs(aPoint->y() - theY) < Precision::Confusion() )
391 aPoint = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(LINE_ATTR_END));
392 if (fabs(aPoint->x() - theX) < Precision::Confusion() && fabs(aPoint->y() - theY) < Precision::Confusion() )
398 void PartSet_OperationSketchLine::setLinePoint(FeaturePtr theFeature,
399 double theX, double theY,
400 const std::string& theAttribute)
404 boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
405 boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
406 boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
407 aPoint->setValue(theX, theY);
410 void PartSet_OperationSketchLine::setLinePoint(const gp_Pnt& thePoint,
411 Handle(V3d_View) theView,
412 const std::string& theAttribute)
415 PartSet_Tools::convertTo2D(thePoint, sketch(), theView, aX, anY);
416 boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
417 boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
418 boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
419 aPoint->setValue(aX, anY);
422 void PartSet_OperationSketchLine::setPointSelectionMode(const PointSelectionMode& theMode,
423 const bool isToEmitSignal)
425 myPointSelectionMode = theMode;
426 if (isToEmitSignal) {
430 aName = LINE_ATTR_START;
433 aName = LINE_ATTR_END;
436 aName = XGUI::PROP_PANEL_OK;
441 emit focusActivated(aName);