1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include <PartSet_Tools.h>
22 #include <PartSet_Module.h>
23 #include <PartSet_SketcherMgr.h>
25 #include <ModelAPI_Data.h>
26 #include <ModelAPI_AttributeDouble.h>
27 #include <ModelAPI_AttributeRefList.h>
28 #include <ModelAPI_Document.h>
29 #include <ModelAPI_Session.h>
30 #include <ModelAPI_ResultConstruction.h>
31 #include <ModelAPI_Events.h>
32 #include <ModelAPI_Validator.h>
33 #include <ModelAPI_Tools.h>
35 #include <ModuleBase_IViewWindow.h>
37 #include <ModelGeomAlgo_Point2D.h>
39 #include <Events_Loop.h>
41 #include <SketcherPrs_Tools.h>
43 #include <XGUI_ModuleConnector.h>
44 #include <XGUI_Displayer.h>
45 #include <XGUI_Workshop.h>
46 #include <XGUI_SelectionMgr.h>
47 #include <XGUI_Selection.h>
49 #include <GeomDataAPI_Point.h>
50 #include <GeomDataAPI_Dir.h>
51 #include <GeomDataAPI_Point2D.h>
52 #include <GeomAPI_Pln.h>
53 #include <GeomAPI_Pnt2d.h>
54 #include <GeomAPI_Pnt.h>
55 #include <GeomAPI_Edge.h>
56 #include <GeomAPI_Vertex.h>
58 #include <GeomAPI_Dir.h>
59 #include <GeomAPI_XYZ.h>
61 #include <SketchPlugin_Feature.h>
62 #include <SketchPlugin_Sketch.h>
63 #include <SketchPlugin_ConstraintCoincidence.h>
64 #include <SketchPlugin_ConstraintDistance.h>
65 #include <SketchPlugin_ConstraintLength.h>
66 #include <SketchPlugin_ConstraintRadius.h>
67 #include <SketchPlugin_ConstraintRigid.h>
68 #include <SketchPlugin_Constraint.h>
69 #include <SketchPlugin_Circle.h>
70 #include <SketchPlugin_Arc.h>
71 #include <SketchPlugin_Line.h>
72 #include <SketchPlugin_Point.h>
74 #include <ModuleBase_IWorkshop.h>
75 #include <ModuleBase_ViewerPrs.h>
76 #include <ModuleBase_Tools.h>
78 #include <V3d_View.hxx>
80 #include <gp_Circ.hxx>
81 #include <ProjLib.hxx>
83 #include <Geom_Line.hxx>
84 #include <GeomAPI_ProjectPointOnCurve.hxx>
85 #include <BRep_Tool.hxx>
87 #include <TopoDS_Edge.hxx>
88 #include <TopoDS_Vertex.hxx>
89 #include <AIS_InteractiveObject.hxx>
90 #include <StdSelect_BRepOwner.hxx>
91 #include <SelectMgr_IndexedMapOfOwner.hxx>
93 #include <QMouseEvent>
99 const double PRECISION_TOLERANCE = 0.000001;
100 const int AIS_DEFAULT_WIDTH = 2;
102 int PartSet_Tools::getAISDefaultWidth()
104 return AIS_DEFAULT_WIDTH;
107 gp_Pnt PartSet_Tools::convertClickToPoint(QPoint thePoint, Handle(V3d_View) theView)
109 if (theView.IsNull())
112 V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
113 theView->Eye(XEye, YEye, ZEye);
115 theView->At(XAt, YAt, ZAt);
116 gp_Pnt EyePoint(XEye, YEye, ZEye);
117 gp_Pnt AtPoint(XAt, YAt, ZAt);
119 gp_Vec EyeVector(EyePoint, AtPoint);
120 gp_Dir EyeDir(EyeVector);
122 gp_Pln PlaneOfTheView = gp_Pln(AtPoint, EyeDir);
123 Standard_Real X, Y, Z;
124 theView->Convert(thePoint.x(), thePoint.y(), X, Y, Z);
125 gp_Pnt ConvertedPoint(X, Y, Z);
127 gp_Pnt2d ConvertedPointOnPlane = ProjLib::Project(PlaneOfTheView, ConvertedPoint);
128 gp_Pnt ResultPoint = ElSLib::Value(ConvertedPointOnPlane.X(), ConvertedPointOnPlane.Y(),
133 void PartSet_Tools::convertTo2D(const gp_Pnt& thePoint, FeaturePtr theSketch,
134 Handle(V3d_View) theView,
135 double& theX, double& theY)
140 AttributeDoublePtr anAttr;
141 std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
143 std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
144 aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
146 std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
147 aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
148 std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
149 aData->attribute(SketchPlugin_Sketch::NORM_ID()));
150 std::shared_ptr<GeomAPI_XYZ> anY = aNorm->xyz()->cross(aX->xyz());
152 gp_Pnt anOriginPnt(anOrigin->x(), anOrigin->y(), anOrigin->z());
153 gp_Vec aVec(anOriginPnt, thePoint);
155 if (!theView.IsNull()) {
156 V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
157 theView->Eye(XEye, YEye, ZEye);
159 theView->At(XAt, YAt, ZAt);
160 gp_Pnt EyePoint(XEye, YEye, ZEye);
161 gp_Pnt AtPoint(XAt, YAt, ZAt);
163 gp_Vec anEyeVec(EyePoint, AtPoint);
164 anEyeVec.Normalize();
166 std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
167 aData->attribute(SketchPlugin_Sketch::NORM_ID()));
168 gp_Vec aNormalVec(aNormal->x(), aNormal->y(), aNormal->z());
170 double aDen = anEyeVec * aNormalVec;
171 double aLVec = aDen != 0 ? aVec * aNormalVec / aDen : DBL_MAX;
173 gp_Vec aDeltaVec = anEyeVec * aLVec;
174 aVec = aVec - aDeltaVec;
176 theX = aVec.X() * aX->x() + aVec.Y() * aX->y() + aVec.Z() * aX->z();
177 theY = aVec.X() * anY->x() + aVec.Y() * anY->y() + aVec.Z() * anY->z();
180 std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::convertTo2D(FeaturePtr theSketch,
181 const std::shared_ptr<GeomAPI_Pnt>& thePnt)
183 std::shared_ptr<GeomAPI_Pnt2d> aRes;
184 if (theSketch->getKind() != SketchPlugin_Sketch::ID())
186 std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
187 theSketch->data()->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
188 std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
189 theSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
190 std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
191 theSketch->data()->attribute(SketchPlugin_Sketch::DIRX_ID()));
192 std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
193 return thePnt->to2D(aC->pnt(), aX->dir(), aY);
197 std::shared_ptr<GeomAPI_Pnt> PartSet_Tools::convertTo3D(const double theX, const double theY,
198 FeaturePtr theSketch)
200 std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
202 std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
203 aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
204 std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
205 aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
206 std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
207 aData->attribute(SketchPlugin_Sketch::NORM_ID()));
208 std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
210 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d =
211 std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(theX, theY));
213 return aPnt2d->to3D(aC->pnt(), aX->dir(), aY);
216 std::shared_ptr<ModelAPI_Document> PartSet_Tools::document()
218 return ModelAPI_Session::get()->moduleDocument();
221 void PartSet_Tools::setFeatureValue(FeaturePtr theFeature, double theValue,
222 const std::string& theAttribute)
226 std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
227 AttributeDoublePtr anAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
228 aData->attribute(theAttribute));
230 anAttribute->setValue(theValue);
233 double PartSet_Tools::featureValue(FeaturePtr theFeature, const std::string& theAttribute,
239 std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
240 AttributeDoublePtr anAttribute = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
241 aData->attribute(theAttribute));
243 aValue = anAttribute->value();
250 FeaturePtr PartSet_Tools::feature(FeaturePtr theFeature, const std::string& theAttribute,
251 const std::string& theKind)
257 std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
258 std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
259 ModelAPI_AttributeRefAttr>(aData->attribute(theAttribute));
261 aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anAttr->object());
262 if (!theKind.empty() && aFeature && aFeature->getKind() != theKind) {
263 aFeature = FeaturePtr();
269 void PartSet_Tools::createConstraint(CompositeFeaturePtr theSketch,
270 std::shared_ptr<GeomDataAPI_Point2D> thePoint1,
271 std::shared_ptr<GeomDataAPI_Point2D> thePoint2)
275 aFeature = theSketch->addFeature(SketchPlugin_ConstraintCoincidence::ID());
277 std::shared_ptr<ModelAPI_Document> aDoc = document();
278 aFeature = aDoc->addFeature(SketchPlugin_ConstraintCoincidence::ID());
281 std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
283 std::shared_ptr<ModelAPI_AttributeRefAttr> aRef1 = std::dynamic_pointer_cast<
284 ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
285 aRef1->setAttr(thePoint1);
287 std::shared_ptr<ModelAPI_AttributeRefAttr> aRef2 = std::dynamic_pointer_cast<
288 ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
289 aRef2->setAttr(thePoint2);
291 // we need to flush created signal in order to coincidence is processed by solver
292 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
295 std::shared_ptr<GeomAPI_Pln> PartSet_Tools::sketchPlane(CompositeFeaturePtr theSketch)
297 std::shared_ptr<GeomAPI_Pln> aPlane;
299 std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
300 theSketch->data()->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
301 std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
302 theSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
304 if (aNormal.get() && aNormal->isInitialized() &&
305 anOrigin.get() && anOrigin->isInitialized())
306 aPlane = std::shared_ptr<GeomAPI_Pln>(new GeomAPI_Pln(anOrigin->pnt(), aNormal->dir()));
311 std::shared_ptr<GeomAPI_Pnt> PartSet_Tools::point3D(std::shared_ptr<GeomAPI_Pnt2d> thePoint2D,
312 CompositeFeaturePtr theSketch)
314 std::shared_ptr<GeomAPI_Pnt> aPoint;
315 if (!theSketch || !thePoint2D)
318 DataPtr aData = theSketch->data();
319 std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
320 aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
321 std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
322 aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
323 std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
324 aData->attribute(SketchPlugin_Sketch::NORM_ID()));
325 std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
327 return thePoint2D->to3D(aC->pnt(), aX->dir(), aY);
330 ResultPtr PartSet_Tools::findFixedObjectByExternal(const TopoDS_Shape& theShape,
331 const ObjectPtr& theObject,
332 CompositeFeaturePtr theSketch)
335 if (theShape.ShapeType() == TopAbs_EDGE) {
336 // Check that we already have such external edge
337 std::shared_ptr<GeomAPI_Edge> aInEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge());
338 aInEdge->setImpl(new TopoDS_Shape(theShape));
339 aResult = findExternalEdge(theSketch, aInEdge);
341 if (theShape.ShapeType() == TopAbs_VERTEX) {
342 std::shared_ptr<GeomAPI_Vertex> aInVert = std::shared_ptr<GeomAPI_Vertex>(new GeomAPI_Vertex());
343 aInVert->setImpl(new TopoDS_Shape(theShape));
344 aResult = findExternalVertex(theSketch, aInVert);
349 ResultPtr PartSet_Tools::createFixedObjectByExternal(const TopoDS_Shape& theShape,
350 const ObjectPtr& theObject,
351 CompositeFeaturePtr theSketch,
352 const bool theTemporary)
354 if (theShape.ShapeType() == TopAbs_EDGE) {
355 Standard_Real aStart, aEnd;
356 Handle(V3d_View) aNullView;
357 FeaturePtr aMyFeature;
359 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(TopoDS::Edge(theShape), aStart, aEnd);
360 GeomAdaptor_Curve aAdaptor(aCurve);
361 std::shared_ptr<GeomAPI_Edge> anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge);
362 anEdge->setImpl(new TopoDS_Shape(theShape));
363 if (aAdaptor.GetType() == GeomAbs_Line) {
365 aMyFeature = theSketch->addFeature(SketchPlugin_Line::ID());
366 if (!theObject.get()) {
367 // There is no selected result
368 std::shared_ptr<GeomAPI_Pnt> aPnt1 = anEdge->firstPoint();
369 std::shared_ptr<GeomAPI_Pnt> aPnt2 = anEdge->lastPoint();
370 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d1 = convertTo2D(theSketch, aPnt1);
371 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d2 = convertTo2D(theSketch, aPnt2);
373 std::shared_ptr<ModelAPI_Data> aData = aMyFeature->data();
374 std::shared_ptr<GeomDataAPI_Point2D> aPoint1 =
375 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
376 aData->attribute(SketchPlugin_Line::START_ID()));
377 std::shared_ptr<GeomDataAPI_Point2D> aPoint2 =
378 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
379 aData->attribute(SketchPlugin_Line::END_ID()));
381 aPoint1->setValue(aPnt2d1);
382 aPoint2->setValue(aPnt2d2);
384 // If this is an axis then its name has to be changed correspondently
385 std::string aSuffix = "";
386 bool aXdir = fabs(aPnt1->x() - aPnt2->x()) > Precision::Confusion();
387 bool aYdir = fabs(aPnt1->y() - aPnt2->y()) > Precision::Confusion();
388 bool aZdir = fabs(aPnt1->z() - aPnt2->z()) > Precision::Confusion();
389 if (aXdir && (!aYdir) && (!aZdir))
391 else if ((!aXdir) && aYdir && (!aZdir))
393 else if ((!aXdir) && (!aYdir) && aZdir)
395 if (aSuffix.length() > 0)
396 aData->setName("Axis_" + aSuffix);
397 aMyFeature->execute();
400 } else if (aAdaptor.GetType() == GeomAbs_Circle) {
401 if (anEdge->isArc()) {
403 aMyFeature = theSketch->addFeature(SketchPlugin_Arc::ID());
404 if (theShape.Orientation() == TopAbs_REVERSED)
405 aMyFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(true);
409 aMyFeature = theSketch->addFeature(SketchPlugin_Circle::ID());
413 DataPtr aData = aMyFeature->data();
414 AttributeSelectionPtr anAttr =
415 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
416 (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
418 ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
419 // selection shape has no result owner => the trihedron axis
420 // TODO: make reference to the real axes when
421 // they are implemented in the initialization plugin
423 ObjectPtr aPointObj = ModelAPI_Session::get()->moduleDocument()->objectByName(
424 ModelAPI_ResultConstruction::group(), "Origin");
425 if (aPointObj.get()) { // if initialization plugin performed well
426 aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aPointObj);
430 aRes = aMyFeature->firstResult();
432 if (anAttr.get() && aRes.get()) {
433 std::shared_ptr<GeomAPI_Shape> anEdge(new GeomAPI_Shape);
434 anEdge->setImpl(new TopoDS_Shape(theShape));
436 anAttr->setValue(aRes, anEdge);
437 //if (!theTemporary) {
438 aMyFeature->execute();
440 // issue #2125: Naming problem: two edges in Naming for one circle on solid
441 // this is result of boolean and seamedge
442 if (aAdaptor.GetType() == GeomAbs_Circle) {
443 ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
444 if (!aFactory->validate(aMyFeature)) {
445 anAttr->setValue(ResultPtr(), GeomShapePtr());
446 std::set<FeaturePtr> aFeatures;
447 aFeatures.insert(aMyFeature);
448 ModelAPI_Tools::removeFeaturesAndReferences(aFeatures);
449 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
450 Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
457 // FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
458 // aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
459 // setObject(aMyFeature->lastResult());
460 // // we need to flush created signal in order to fixed constraint is processed by solver
461 // Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
463 return aMyFeature->lastResult();
467 if (theShape.ShapeType() == TopAbs_VERTEX) {
468 FeaturePtr aMyFeature = theSketch->addFeature(SketchPlugin_Point::ID());
471 DataPtr aData = aMyFeature->data();
472 AttributeSelectionPtr anAttr =
473 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
474 (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
476 ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
477 // if there is no object,
478 // it means that this is the origin point: search it in the module document
480 ObjectPtr aPointObj = ModelAPI_Session::get()->moduleDocument()->objectByName(
481 ModelAPI_ResultConstruction::group(), "Origin");
482 if (aPointObj.get()) { // if initialization plugin performed well
483 aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aPointObj);
486 // reference to itself with name "Origin" (but this may cause the infinitive cycling)
488 // If the point is selected not from Result object
489 std::shared_ptr<GeomAPI_Shape> aShape =
490 std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
491 aShape->setImpl(new TopoDS_Shape(theShape));
493 std::shared_ptr<GeomAPI_Vertex> aVertex =
494 std::shared_ptr<GeomAPI_Vertex>(new GeomAPI_Vertex(aShape));
495 std::shared_ptr<GeomAPI_Pnt> aPnt = aVertex->point();
497 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = convertTo2D(theSketch, aPnt);
498 std::shared_ptr<GeomDataAPI_Point2D> aPoint =
499 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
500 aData->attribute(SketchPlugin_Point::COORD_ID()));
501 aPoint->setValue(aPnt2d);
502 if ((aPnt->x() < Precision::Confusion()) &&
503 (aPnt->y() < Precision::Confusion()) &&
504 (aPnt->z() < Precision::Confusion()))
505 aData->setName("Origin");
507 aMyFeature->execute();
508 aRes = aMyFeature->firstResult();
510 if (anAttr.get() && aRes.get()) {
511 std::shared_ptr<GeomAPI_Shape> aVert(new GeomAPI_Shape);
512 aVert->setImpl(new TopoDS_Shape(theShape));
514 anAttr->setValue(aRes, aVert);
515 //if (theTemporary) {
516 aMyFeature->execute();
519 // FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
520 // aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
521 // setObject(aMyFeature->lastResult());
522 // // we need to flush created signal in order to fixed constraint is processed by solver
523 // Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
525 return aMyFeature->lastResult();
532 bool PartSet_Tools::isContainPresentation(const QList<ModuleBase_ViewerPrsPtr>& theSelected,
533 const ModuleBase_ViewerPrsPtr& thePrs)
535 foreach (ModuleBase_ViewerPrsPtr aPrs, theSelected) {
536 if (aPrs->object() == thePrs->object())
542 ResultPtr PartSet_Tools::findExternalEdge(CompositeFeaturePtr theSketch,
543 std::shared_ptr<GeomAPI_Edge> theEdge)
545 for (int i = 0; i < theSketch->numberOfSubs(); i++) {
546 FeaturePtr aFeature = theSketch->subFeature(i);
547 std::shared_ptr<SketchPlugin_Feature> aSketchFea =
548 std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
549 // not displayed result of feature projection should not be returned as external edge
550 if (aSketchFea && aSketchFea->canBeDisplayed()) {
551 if (aSketchFea->isExternal()) {
552 std::list<ResultPtr> aResults = aSketchFea->results();
553 std::list<ResultPtr>::const_iterator aIt;
554 for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) {
555 ResultConstructionPtr aRes =
556 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aIt);
558 std::shared_ptr<GeomAPI_Shape> aShape = aRes->shape();
560 if (theEdge->isEqual(aShape))
572 ResultPtr PartSet_Tools::findExternalVertex(CompositeFeaturePtr theSketch,
573 std::shared_ptr<GeomAPI_Vertex> theVert)
575 for (int i = 0; i < theSketch->numberOfSubs(); i++) {
576 FeaturePtr aFeature = theSketch->subFeature(i);
577 std::shared_ptr<SketchPlugin_Feature> aSketchFea =
578 std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
580 if (aSketchFea->isExternal()) {
581 std::list<ResultPtr> aResults = aSketchFea->results();
582 std::list<ResultPtr>::const_iterator aIt;
583 for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) {
584 ResultConstructionPtr aRes =
585 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aIt);
587 std::shared_ptr<GeomAPI_Shape> aShape = aRes->shape();
589 if (theVert->isEqual(aShape))
601 bool PartSet_Tools::hasVertexShape(const ModuleBase_ViewerPrsPtr& thePrs, FeaturePtr theSketch,
602 Handle(V3d_View) theView, double& theX, double& theY)
604 bool aHasVertex = false;
606 const GeomShapePtr& aShape = thePrs->shape();
607 if (aShape.get() && !aShape->isNull() && aShape->shapeType() == GeomAPI_Shape::VERTEX)
609 const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
610 const TopoDS_Vertex& aVertex = TopoDS::Vertex(aTDShape);
611 if (!aVertex.IsNull())
613 gp_Pnt aPoint = BRep_Tool::Pnt(aVertex);
614 PartSet_Tools::convertTo2D(aPoint, theSketch, theView, theX, theY);
622 GeomShapePtr PartSet_Tools::findShapeBy2DPoint(const AttributePtr& theAttribute,
623 ModuleBase_IWorkshop* theWorkshop)
626 XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWorkshop);
627 XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
629 // 2. find visualized vertices of the attribute and if the attribute of the vertex is
630 // the same, return it
631 FeaturePtr anAttributeFeature = ModelAPI_Feature::feature(theAttribute->owner());
632 // 2.1 get visualized results of the feature
633 const std::list<ResultPtr>& aResList = anAttributeFeature->results();
634 std::list<ResultPtr>::const_iterator anIt = aResList.begin(), aLast = aResList.end();
635 for (; anIt != aLast; anIt++) {
636 AISObjectPtr aAISObj = aDisplayer->getAISObject(*anIt);
637 if (aAISObj.get() != NULL) {
638 Handle(AIS_InteractiveObject) anAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
639 // 2.2 find selected owners of a visualizedd object
640 SelectMgr_IndexedMapOfOwner aSelectedOwners;
641 aConnector->workshop()->selector()->selection()->entityOwners(anAISIO, aSelectedOwners);
642 for (Standard_Integer i = 1, n = aSelectedOwners.Extent(); i <= n; i++) {
643 Handle(SelectMgr_EntityOwner) anOwner = aSelectedOwners(i);
644 if (!anOwner.IsNull()) {
645 Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast(anOwner);
646 if (!aBRepOwner.IsNull() && aBRepOwner->HasShape()) {
647 const TopoDS_Shape& aBRepShape = aBRepOwner->Shape();
648 if (aBRepShape.ShapeType() == TopAbs_VERTEX) {
649 // 2.3 if the owner is vertex and an attribute of the vertex is equal to the initial
650 // attribute, returns the shape
651 PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(theWorkshop->module());
652 PartSet_SketcherMgr* aSketchMgr = aModule->sketchMgr();
653 AttributePtr aPntAttr = PartSet_Tools::findAttributeBy2dPoint(anAttributeFeature,
654 aBRepShape, aSketchMgr->activeSketch());
655 if (aPntAttr.get() != NULL && aPntAttr == theAttribute) {
656 aShape = std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape);
657 aShape->setImpl(new TopoDS_Shape(aBRepShape));
669 std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getPoint(
670 std::shared_ptr<ModelAPI_Feature>& theFeature,
671 const std::string& theAttribute)
673 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = ModelGeomAlgo_Point2D::getPointOfRefAttr(
674 theFeature.get(), theAttribute, SketchPlugin_Point::ID(),
675 SketchPlugin_Point::COORD_ID());
676 if (aPointAttr.get() != NULL)
677 return aPointAttr->pnt();
678 return std::shared_ptr<GeomAPI_Pnt2d>();
681 std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getPnt2d(QMouseEvent* theEvent,
682 ModuleBase_IViewWindow* theWindow,
683 const FeaturePtr& theSketch)
685 gp_Pnt aPnt = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
687 Handle(V3d_View) aView = theWindow->v3dView();
688 PartSet_Tools::convertTo2D(aPnt, theSketch, aView, aX, anY);
690 return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aX, anY));
693 FeaturePtr findFirstCoincidenceByData(const DataPtr& theData,
694 std::shared_ptr<GeomAPI_Pnt2d> thePoint)
696 FeaturePtr aCoincident;
698 const std::set<AttributePtr>& aRefsList = theData->refsToMe();
699 std::set<AttributePtr>::const_iterator aIt;
700 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
701 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
702 FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
703 if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
704 std::shared_ptr<GeomAPI_Pnt2d> a2dPnt =
705 PartSet_Tools::getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
706 if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) {
707 aCoincident = aConstrFeature;
710 a2dPnt = PartSet_Tools::getPoint(aConstrFeature,
711 SketchPlugin_ConstraintCoincidence::ENTITY_B());
712 if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) {
713 aCoincident = aConstrFeature;
722 FeaturePtr PartSet_Tools::findFirstCoincidence(const FeaturePtr& theFeature,
723 std::shared_ptr<GeomAPI_Pnt2d> thePoint)
725 FeaturePtr aCoincident;
726 if (theFeature.get() == NULL)
729 const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
730 std::set<AttributePtr>::const_iterator aIt;
731 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
732 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
733 FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
734 if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
735 std::shared_ptr<GeomAPI_Pnt2d> a2dPnt =
736 PartSet_Tools::getPoint(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A());
737 if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) {
738 aCoincident = aConstrFeature;
741 a2dPnt = PartSet_Tools::getPoint(aConstrFeature,
742 SketchPlugin_ConstraintCoincidence::ENTITY_B());
743 if (a2dPnt.get() && thePoint->isEqual(a2dPnt)) {
744 aCoincident = aConstrFeature;
751 if (!aCoincident.get()) {
752 std::list<ResultPtr> aResults = theFeature->results();
753 std::list<ResultPtr>::const_iterator aIt;
754 for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) {
755 ResultPtr aResult = *aIt;
756 aCoincident = findFirstCoincidenceByData(aResult->data(), thePoint);
757 if (aCoincident.get())
764 void PartSet_Tools::findCoincidences(FeaturePtr theStartCoin, QList<FeaturePtr>& theList,
765 QList<FeaturePtr>& theCoincidencies,
766 std::string theAttr, QList<bool>& theIsAttributes)
768 std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincedencePoint(theStartCoin);
769 if (aOrig.get() == NULL)
772 AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
775 ObjectPtr aObj = aPnt->object();
776 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
777 if (aFeature.get()) {
778 if (!theList.contains(aFeature)) {
779 theList.append(aFeature);
780 theCoincidencies.append(theStartCoin);
781 theIsAttributes.append(true); // point attribute on a feature
782 const std::set<AttributePtr>& aRefsList = aFeature->data()->refsToMe();
783 std::set<AttributePtr>::const_iterator aIt;
784 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
785 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
786 FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
787 if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
788 if (!theCoincidencies.contains(aConstrFeature)) {
789 std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincedencePoint(aConstrFeature);
790 if (aPnt.get() && aOrig->isEqual(aPnt)) {
791 findCoincidences(aConstrFeature, theList, theCoincidencies,
792 SketchPlugin_ConstraintCoincidence::ENTITY_A(), theIsAttributes);
793 findCoincidences(aConstrFeature, theList, theCoincidencies,
794 SketchPlugin_ConstraintCoincidence::ENTITY_B(), theIsAttributes);
802 ResultConstructionPtr aResult = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aObj);
804 FeaturePtr aFeature = ModelAPI_Feature::feature(aPnt->object());
805 if (!theList.contains(aFeature))
806 theList.append(aFeature);
807 theCoincidencies.append(theStartCoin);
808 theIsAttributes.append(false); // point attribute on a feature
810 const std::set<AttributePtr>& aRefsList = aResult->data()->refsToMe();
811 std::set<AttributePtr>::const_iterator aIt;
812 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
813 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
814 FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
815 if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
816 if (!theCoincidencies.contains(aConstrFeature)) {
817 std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincedencePoint(aConstrFeature);
818 if (aPnt.get() && aOrig->isEqual(aPnt)) {
819 findCoincidences(aConstrFeature, theList, theCoincidencies,
820 SketchPlugin_ConstraintCoincidence::ENTITY_A(), theIsAttributes);
821 findCoincidences(aConstrFeature, theList, theCoincidencies,
822 SketchPlugin_ConstraintCoincidence::ENTITY_B(), theIsAttributes);
831 std::shared_ptr<GeomAPI_Pnt2d> PartSet_Tools::getCoincedencePoint(FeaturePtr theStartCoin)
833 std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(),
834 SketchPlugin_Constraint::ENTITY_A());
835 if (aPnt.get() == NULL)
836 aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(), SketchPlugin_Constraint::ENTITY_B());
840 AttributePtr PartSet_Tools::findAttributeBy2dPoint(ObjectPtr theObj,
841 const TopoDS_Shape theShape,
842 FeaturePtr theSketch)
845 AttributePtr anAttribute;
846 FeaturePtr aFeature = ModelAPI_Feature::feature(theObj);
848 if (theShape.ShapeType() == TopAbs_VERTEX) {
849 const TopoDS_Vertex& aVertex = TopoDS::Vertex(theShape);
850 if (!aVertex.IsNull()) {
851 gp_Pnt aPoint = BRep_Tool::Pnt(aVertex);
852 std::shared_ptr<GeomAPI_Pnt> aValue = std::shared_ptr<GeomAPI_Pnt>(
853 new GeomAPI_Pnt(aPoint.X(), aPoint.Y(), aPoint.Z()));
855 // find the given point in the feature attributes
856 std::list<AttributePtr> anAttiributes =
857 aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
858 std::list<AttributePtr>::const_iterator anIt = anAttiributes.begin(),
859 aLast = anAttiributes.end();
860 for (; anIt != aLast && !anAttribute; anIt++) {
861 std::shared_ptr<GeomDataAPI_Point2D> aCurPoint =
862 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt);
863 if (!aCurPoint->isInitialized())
866 std::shared_ptr<GeomAPI_Pnt> aPnt =
867 convertTo3D(aCurPoint->x(), aCurPoint->y(), theSketch);
868 if (aPnt && (aPnt->distance(aValue) < Precision::Confusion())) {
869 anAttribute = aCurPoint;
879 void PartSet_Tools::sendSubFeaturesEvent(const CompositeFeaturePtr& theComposite,
880 const Events_ID theEventId)
882 if (!theComposite.get())
885 static Events_Loop* aLoop = Events_Loop::loop();
886 for (int i = 0; i < theComposite->numberOfSubs(); i++) {
887 FeaturePtr aSubFeature = theComposite->subFeature(i);
888 static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
889 aECreator->sendUpdated(aSubFeature, theEventId);
891 Events_Loop::loop()->flush(theEventId);
894 bool PartSet_Tools::isAuxiliarySketchEntity(const ObjectPtr& theObject)
896 bool isAuxiliaryFeature = false;
898 FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObject);
899 std::string anAuxiliaryAttribute = SketchPlugin_SketchEntity::AUXILIARY_ID();
900 AttributeBooleanPtr anAuxiliaryAttr = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
901 anObjectFeature->data()->attribute(anAuxiliaryAttribute));
902 if (anAuxiliaryAttr.get())
903 isAuxiliaryFeature = anAuxiliaryAttr->value();
906 return isAuxiliaryFeature;