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>
13 #include <GeomDataAPI_Point2D.h>
15 #include <ModuleBase_OperationDescription.h>
17 #include <ModelAPI_Data.h>
18 #include <ModelAPI_Document.h>
19 #include <ModelAPI_AttributeRefAttr.h>
20 #include <ModelAPI_AttributeRefList.h>
22 #include <SketchPlugin_Constraint.h>
24 #include <Geom_Line.hxx>
27 #include <XGUI_ViewerPrs.h>
28 #include <XGUI_Constants.h>
30 #include <SketchPlugin_Line.h>
32 #include <V3d_View.hxx>
33 #include <TopoDS_Vertex.hxx>
35 #include <BRep_Tool.hxx>
41 #include <QMouseEvent>
45 PartSet_OperationSketchLine::PartSet_OperationSketchLine(const QString& theId,
47 boost::shared_ptr<ModelAPI_Feature> theFeature)
48 : PartSet_OperationSketchBase(theId, theParent), mySketch(theFeature),
49 myPointSelectionMode(SM_FirstPoint)
53 PartSet_OperationSketchLine::~PartSet_OperationSketchLine()
57 bool PartSet_OperationSketchLine::canBeCommitted() const
59 return myPointSelectionMode == SM_DonePoint;
62 bool PartSet_OperationSketchLine::isGranted(ModuleBase_IOperation* theOperation) const
64 return theOperation->getDescription()->operationId().toStdString() == PartSet_OperationSketch::Type();
67 std::list<int> PartSet_OperationSketchLine::getSelectionModes(boost::shared_ptr<ModelAPI_Feature> theFeature) const
69 std::list<int> aModes;
70 if (theFeature != feature())
71 aModes = PartSet_OperationSketchBase::getSelectionModes(theFeature);
75 void PartSet_OperationSketchLine::init(boost::shared_ptr<ModelAPI_Feature> theFeature,
76 const std::list<XGUI_ViewerPrs>& /*theSelected*/,
77 const std::list<XGUI_ViewerPrs>& /*theHighlighted*/)
79 if (!theFeature || theFeature->getKind() != SKETCH_LINE_KIND)
81 // use the last point of the previous feature as the first of the new one
82 boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
83 myInitPoint = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(LINE_ATTR_END));
86 boost::shared_ptr<ModelAPI_Feature> PartSet_OperationSketchLine::sketch() const
91 void PartSet_OperationSketchLine::mouseReleased(QMouseEvent* theEvent, Handle(V3d_View) theView,
92 const std::list<XGUI_ViewerPrs>& theSelected,
93 const std::list<XGUI_ViewerPrs>& /*theHighlighted*/)
95 if (myPointSelectionMode == SM_DonePoint)
97 // if the point creation is finished, the next mouse release should commit the modification
98 // the next release can happens by double click in the viewer
100 restartOperation(PartSet_OperationSketchLine::Type(), feature());
106 bool isFoundPoint = false;
107 gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theView);
108 if (theSelected.empty()) {
109 PartSet_Tools::convertTo2D(aPoint, sketch(), theView, aX, anY);
113 XGUI_ViewerPrs aPrs = theSelected.front();
114 const TopoDS_Shape& aShape = aPrs.shape();
115 if (!aShape.IsNull()) // the point is selected
117 if (aShape.ShapeType() == TopAbs_VERTEX) {
118 const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
119 if (!aVertex.IsNull()) {
120 aPoint = BRep_Tool::Pnt(aVertex);
121 PartSet_Tools::convertTo2D(aPoint, sketch(), theView, aX, anY);
124 setConstraints(aX, anY);
127 else if (aShape.ShapeType() == TopAbs_EDGE) // the line is selected
129 boost::shared_ptr<ModelAPI_Feature> aFeature = aPrs.feature();
131 double X0, X1, X2, X3;
132 double Y0, Y1, Y2, Y3;
133 getLinePoint(aFeature, LINE_ATTR_START, X2, Y2);
134 getLinePoint(aFeature, LINE_ATTR_END, X3, Y3);
135 PartSet_Tools::convertTo2D(aPoint, sketch(), theView, X1, Y1);
137 switch (myPointSelectionMode) {
139 PartSet_Tools::projectPointOnLine(X2, Y2, X3, Y3, X1, Y1, aX, anY);
141 case SM_SecondPoint: {
142 getLinePoint(feature(), LINE_ATTR_START, X0, Y0);
143 PartSet_Tools::intersectLines(X0, Y0, X1, Y1, X2, Y2, X3, Y3, aX, anY);
155 switch (myPointSelectionMode)
157 case SM_FirstPoint: {
158 setLinePoint(feature(), aX, anY, LINE_ATTR_START);
159 setLinePoint(feature(), aX, anY, LINE_ATTR_END);
162 setPointSelectionMode(SM_SecondPoint);
165 case SM_SecondPoint: {
166 setLinePoint(feature(), aX, anY, LINE_ATTR_END);
169 setPointSelectionMode(SM_DonePoint);
177 void PartSet_OperationSketchLine::mouseMoved(QMouseEvent* theEvent, Handle(V3d_View) theView)
179 switch (myPointSelectionMode)
181 case SM_FirstPoint: {
183 gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theView);
184 PartSet_Tools::convertTo2D(aPoint, sketch(), theView, aX, anY);
185 setLinePoint(feature(), aX, anY, LINE_ATTR_START);
186 setLinePoint(feature(), aX, anY, LINE_ATTR_END);
188 emit focusActivated(LINE_ATTR_START);
193 gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theView);
194 setLinePoint(aPoint, theView, LINE_ATTR_END);
196 emit focusActivated(LINE_ATTR_END);
202 restartOperation(PartSet_OperationSketchLine::Type(), feature());
209 void PartSet_OperationSketchLine::keyReleased(std::string theName, QKeyEvent* theEvent)
211 int aKeyType = theEvent->key();
212 // the second point should be activated by any modification in the property panel
213 if (!theName.empty() /*&& aKeyType == Qt::Key_Return*/) {
214 if (theName == LINE_ATTR_START) {
215 setPointSelectionMode(SM_SecondPoint, false);
217 else if (theName == LINE_ATTR_END) {
218 setPointSelectionMode(SM_DonePoint, false);
221 keyReleased(theEvent->key());
224 void PartSet_OperationSketchLine::keyReleased(const int theKey)
227 case Qt::Key_Return: {
228 if (myPointSelectionMode == SM_DonePoint)
231 restartOperation(PartSet_OperationSketchLine::Type(), feature());
235 //emit launchOperation(PartSet_OperationSketchLine::Type(), boost::shared_ptr<ModelAPI_Feature>());
238 case Qt::Key_Escape: {
239 if (myPointSelectionMode == SM_DonePoint)
251 void PartSet_OperationSketchLine::startOperation()
253 PartSet_OperationSketchBase::startOperation();
254 setPointSelectionMode(!myInitPoint ? SM_FirstPoint : SM_SecondPoint);
256 emit multiSelectionEnabled(false);
259 void PartSet_OperationSketchLine::abortOperation()
261 emit featureConstructed(feature(), FM_Hide);
262 PartSet_OperationSketchBase::abortOperation();
265 void PartSet_OperationSketchLine::stopOperation()
267 PartSet_OperationSketchBase::stopOperation();
268 emit multiSelectionEnabled(true);
271 void PartSet_OperationSketchLine::afterCommitOperation()
273 PartSet_OperationSketchBase::afterCommitOperation();
274 emit featureConstructed(feature(), FM_Deactivation);
277 boost::shared_ptr<ModelAPI_Feature> PartSet_OperationSketchLine::createFeature(const bool theFlushMessage)
279 boost::shared_ptr<ModelAPI_Feature> aNewFeature = ModuleBase_Operation::createFeature(false);
281 boost::shared_ptr<SketchPlugin_Feature> aFeature =
282 boost::dynamic_pointer_cast<SketchPlugin_Feature>(sketch());
284 aFeature->addSub(aNewFeature);
287 setLinePoint(aNewFeature, myInitPoint->x(), myInitPoint->y(), LINE_ATTR_START);
288 setLinePoint(aNewFeature, myInitPoint->x(), myInitPoint->y(), LINE_ATTR_END);
290 boost::shared_ptr<ModelAPI_Data> aData = aNewFeature->data();
291 boost::shared_ptr<GeomDataAPI_Point2D> aPoint = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>
292 (aData->attribute(LINE_ATTR_START));
293 createConstraint(myInitPoint, aPoint);
296 emit featureConstructed(aNewFeature, FM_Activation);
302 void PartSet_OperationSketchLine::createConstraint(boost::shared_ptr<GeomDataAPI_Point2D> thePoint1,
303 boost::shared_ptr<GeomDataAPI_Point2D> thePoint2)
305 boost::shared_ptr<ModelAPI_Document> aDoc = document();
306 boost::shared_ptr<ModelAPI_Feature> aFeature = aDoc->addFeature("SketchConstraintCoincidence");
309 boost::shared_ptr<SketchPlugin_Feature> aSketch =
310 boost::dynamic_pointer_cast<SketchPlugin_Feature>(sketch());
311 aSketch->addSub(aFeature);
314 boost::shared_ptr<ModelAPI_Data> aData = aFeature->data();
316 boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef1 =
317 boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aData->attribute(CONSTRAINT_ATTR_ENTITY_A));
318 aRef1->setAttr(thePoint1);
320 boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef2 =
321 boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aData->attribute(CONSTRAINT_ATTR_ENTITY_B));
322 aRef2->setAttr(thePoint2);
324 if (aFeature) // TODO: generate an error if feature was not created
328 void PartSet_OperationSketchLine::setConstraints(double theX, double theY)
330 std::string aPointArg;
331 switch (myPointSelectionMode)
334 aPointArg = LINE_ATTR_START;
337 aPointArg = LINE_ATTR_END;
343 boost::shared_ptr<ModelAPI_Feature> aSkFeature = feature();
345 boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
346 boost::shared_ptr<GeomDataAPI_Point2D> aPoint = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>
347 (aData->attribute(aPointArg));
348 aData = sketch()->data();
349 boost::shared_ptr<ModelAPI_AttributeRefList> aRefList =
350 boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(aData->attribute(SKETCH_ATTR_FEATURES));
352 std::list<boost::shared_ptr<ModelAPI_Feature> > aFeatures = aRefList->list();
353 std::list<boost::shared_ptr<ModelAPI_Feature> >::const_iterator anIt = aFeatures.begin(),
354 aLast = aFeatures.end();
355 for (; anIt != aLast; anIt++) {
356 boost::shared_ptr<ModelAPI_Feature> aFeature = *anIt;
357 boost::shared_ptr<GeomDataAPI_Point2D> aFPoint = findLinePoint(aFeature, theX, theY);
359 createConstraint(aFPoint, aPoint);
363 void PartSet_OperationSketchLine::getLinePoint(boost::shared_ptr<ModelAPI_Feature> theFeature,
364 const std::string& theAttribute,
365 double& theX, double& theY)
367 if (!theFeature || theFeature->getKind() != SKETCH_LINE_KIND)
369 boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
370 boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
371 boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
376 boost::shared_ptr<GeomDataAPI_Point2D> PartSet_OperationSketchLine::findLinePoint(
377 boost::shared_ptr<ModelAPI_Feature> theFeature,
378 double theX, double theY)
380 boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D;
381 if (!theFeature || theFeature->getKind() != SKETCH_LINE_KIND)
383 boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
385 boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
386 boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(LINE_ATTR_START));
387 if (fabs(aPoint->x() - theX) < Precision::Confusion() && fabs(aPoint->y() - theY) < Precision::Confusion() )
390 aPoint = boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(LINE_ATTR_END));
391 if (fabs(aPoint->x() - theX) < Precision::Confusion() && fabs(aPoint->y() - theY) < Precision::Confusion() )
397 void PartSet_OperationSketchLine::setLinePoint(boost::shared_ptr<ModelAPI_Feature> theFeature,
398 double theX, double theY,
399 const std::string& theAttribute)
403 boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
404 boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
405 boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
406 aPoint->setValue(theX, theY);
409 void PartSet_OperationSketchLine::setLinePoint(const gp_Pnt& thePoint,
410 Handle(V3d_View) theView,
411 const std::string& theAttribute)
414 PartSet_Tools::convertTo2D(thePoint, sketch(), theView, aX, anY);
415 boost::shared_ptr<ModelAPI_Data> aData = feature()->data();
416 boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
417 boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
418 aPoint->setValue(aX, anY);
421 void PartSet_OperationSketchLine::setPointSelectionMode(const PointSelectionMode& theMode,
422 const bool isToEmitSignal)
424 myPointSelectionMode = theMode;
425 if (isToEmitSignal) {
429 aName = LINE_ATTR_START;
432 aName = LINE_ATTR_END;
435 aName = XGUI::PROP_PANEL_OK;
440 emit focusActivated(aName);