1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: PartSet_Validators.cpp
4 // Created: 09 July 2014
5 // Author: Vitaly SMETANNIKOV
7 #include "PartSet_Validators.h"
9 #include "PartSet_Tools.h"
10 #include "PartSet_SketcherMgr.h"
13 #include <TopoDS_Edge.hxx>
14 #include <BRep_Tool.hxx>
15 #include <GeomAdaptor_Curve.hxx>
16 #include <GeomAbs_CurveType.hxx>
17 #include <ModuleBase_ISelection.h>
18 #include <ModuleBase_WidgetShapeSelector.h>
19 #include <ModuleBase_OperationFeature.h>
21 #include <ModelAPI_AttributeRefAttr.h>
22 #include <ModelAPI_AttributeSelection.h>
23 #include <ModelAPI_AttributeReference.h>
24 #include <ModelAPI_AttributeSelectionList.h>
25 #include <ModelAPI_AttributeRefList.h>
26 #include <ModelAPI_Object.h>
27 #include <ModelAPI_Session.h>
28 #include <ModelAPI_Tools.h>
30 #include <SketchPlugin_Sketch.h>
31 #include <SketchPlugin_ConstraintCoincidence.h>
32 #include <SketchPlugin_Arc.h>
33 #include <GeomAPI_Edge.h>
40 int shapesNbPoints(const ModuleBase_ISelection* theSelection)
42 QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
43 ModuleBase_ISelection::filterSelectionOnEqualPoints(aList);
46 foreach (ModuleBase_ViewerPrs aPrs, aList) {
47 const TopoDS_Shape& aShape = aPrs.shape();
48 if (!aShape.IsNull()) {
49 if (aShape.ShapeType() == TopAbs_VERTEX)
56 int shapesNbLines(const ModuleBase_ISelection* theSelection)
58 QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
60 foreach(ModuleBase_ViewerPrs aPrs, aList) {
61 const TopoDS_Shape& aShape = aPrs.shape();
62 if (!aShape.IsNull()) {
63 if (aShape.ShapeType() == TopAbs_EDGE) {
64 TopoDS_Edge aEdge = TopoDS::Edge(aShape);
65 Standard_Real aStart, aEnd;
66 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aStart, aEnd);
67 GeomAdaptor_Curve aAdaptor(aCurve);
68 if (aAdaptor.GetType() == GeomAbs_Line)
77 std::shared_ptr<GeomAPI_Pln> sketcherPlane(ModuleBase_Operation* theOperation)
79 std::shared_ptr<GeomAPI_Pln> aEmptyPln;
81 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
83 CompositeFeaturePtr aFeature =
84 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeatureOp->feature());
85 if (aFeature && (aFeature->getKind() == SketchPlugin_Sketch::ID()))
86 return PartSet_Tools::sketchPlane(aFeature);
93 bool isEmptySelectionValid(ModuleBase_Operation* theOperation)
95 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
96 // during the create operation empty selection is always valid
97 if (!aFeatureOp->isEditOperation()) {
101 if (PartSet_SketcherMgr::isSketchOperation(aFeatureOp)) {
102 std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
108 else// in edit operation an empty selection is always valid, performed for re-entrant operrations
113 bool PartSet_DistanceSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
115 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
116 return isEmptySelectionValid(theOperation);
118 int aCount = shapesNbPoints(theSelection) + shapesNbLines(theSelection);
119 return (aCount > 0) && (aCount < 3);
123 bool PartSet_LengthSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
125 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
126 return isEmptySelectionValid(theOperation);
128 int aCount = shapesNbLines(theSelection);
129 return (aCount == 1);
133 bool PartSet_PerpendicularSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
135 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
136 return isEmptySelectionValid(theOperation);
138 int aCount = shapesNbLines(theSelection);
139 return (aCount > 0) && (aCount < 3);
143 bool PartSet_ParallelSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
145 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
146 return isEmptySelectionValid(theOperation);
148 int aCount = shapesNbLines(theSelection);
149 return (aCount > 0) && (aCount < 3);
153 bool PartSet_RadiusSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
155 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
156 return isEmptySelectionValid(theOperation);
158 QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
159 ModuleBase_ViewerPrs aPrs;
161 foreach (ModuleBase_ViewerPrs aPrs, aList) {
162 const TopoDS_Shape& aShape = aPrs.shape();
163 if (!aShape.IsNull()) {
164 if (aShape.ShapeType() == TopAbs_EDGE) {
165 TopoDS_Edge aEdge = TopoDS::Edge(aShape);
166 Standard_Real aStart, aEnd;
167 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aStart, aEnd);
168 GeomAdaptor_Curve aAdaptor(aCurve);
169 if (aAdaptor.GetType() == GeomAbs_Circle)
174 return (aCount == 1);
178 bool PartSet_RigidSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
180 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
181 return isEmptySelectionValid(theOperation);
183 QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
184 return (aList.count() == 1);
189 bool PartSet_CoincidentSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
191 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
192 return isEmptySelectionValid(theOperation);
194 // Coincident can be applied to points and to lines
195 int aCount = shapesNbPoints(theSelection);
196 aCount += shapesNbLines(theSelection);
197 return (aCount > 0) && (aCount < 3);
201 bool PartSet_HVDirSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
203 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
204 return isEmptySelectionValid(theOperation);
206 int aCount = shapesNbLines(theSelection);
207 return (aCount == 1);
211 bool PartSet_FilletSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
213 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
214 return isEmptySelectionValid(theOperation);
216 int aCount = shapesNbPoints(theSelection);
221 bool PartSet_TangentSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
223 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
224 return isEmptySelectionValid(theOperation);
226 QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
227 if ((aList.size() == 0) || (aList.size() > 2))
230 ModuleBase_ViewerPrs aPrs = aList.first();
231 const TopoDS_Shape& aShape = aPrs.shape();
235 if (aShape.ShapeType() != TopAbs_EDGE)
238 std::shared_ptr<GeomAPI_Shape> aShapePtr(new GeomAPI_Shape);
239 aShapePtr->setImpl(new TopoDS_Shape(aShape));
240 GeomAPI_Edge aEdge1(aShapePtr);
242 if (aEdge1.isLine() || aEdge1.isArc()) {
243 if (aList.size() == 2) {
244 // Check second selection
246 const TopoDS_Shape& aShape2 = aPrs.shape();
247 if (aShape2.IsNull())
250 if (aShape2.ShapeType() != TopAbs_EDGE)
253 std::shared_ptr<GeomAPI_Shape> aShapePtr2(new GeomAPI_Shape);
254 aShapePtr2->setImpl(new TopoDS_Shape(aShape2));
255 GeomAPI_Edge aEdge2(aShapePtr2);
256 if (aEdge1.isLine() && aEdge2.isArc())
258 else if (aEdge1.isArc() && aEdge2.isLine())
269 bool PartSet_AngleSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
271 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
272 return isEmptySelectionValid(theOperation);
274 int aCount = shapesNbLines(theSelection);
275 return (aCount > 0) && (aCount < 3);
279 bool PartSet_EqualSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
281 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
282 return isEmptySelectionValid(theOperation);
284 QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
285 ModuleBase_ViewerPrs aPrs;
288 foreach (ModuleBase_ViewerPrs aPrs, aList) {
289 std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape);
290 aShape->setImpl(new TopoDS_Shape(aPrs.shape()));
291 if (aShape->isEdge()) {
293 GeomAPI_Edge aEdge(aShape);
294 if (aEdge.isLine()) {
299 } else if (aEdge.isCircle()) {
304 } else if (aEdge.isArc()) {
313 return (aCount > 0) && (aCount < 3);
317 bool PartSet_CollinearSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
319 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
320 return isEmptySelectionValid(theOperation);
322 int aCount = shapesNbLines(theSelection);
323 return (aCount > 0) && (aCount < 3);
327 bool PartSet_MiddlePointSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
329 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0)
330 return isEmptySelectionValid(theOperation);
332 return shapesNbLines(theSelection) == 1 && shapesNbPoints(theSelection) == 1;
336 std::string PartSet_DifferentObjectsValidator::errorMessage(
337 const PartSet_DifferentObjectsValidator::ErrorType& theType,
338 const std::string& thEqualObject, const std::string& theFirstAttribute,
339 const std::string& theSecondAttribute) const
344 anError = "The feature uses one " + thEqualObject + " object in " +
345 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
347 case EqualAttributes:
348 anError = "The feature uses reference to one " + thEqualObject + " attribute in " +
349 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
352 anError = "The feature uses one shape in " +
353 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
356 anError = "The feature uses empty shapes in " +
357 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
366 bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute,
367 const std::list<std::string>& theArguments,
368 std::string& theError) const
370 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
372 // the type of validated attributes should be equal, attributes with different types are not validated
373 // Check RefAttr attributes
374 std::string anAttrType = theAttribute->attributeType();
375 std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
377 if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
378 AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
379 bool isObject = anAttr->isObject();
380 ObjectPtr anObject = anAttr->object();
381 AttributePtr anAttributeAttr = anAttr->attr();
383 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
384 if (anAttrs.size() > 0) {
385 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
386 for(; anAttr != anAttrs.end(); anAttr++) {
387 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
388 std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
389 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttr);
390 if (aRef->isObject() != isObject)
393 if (aRef->object() == anObject) {
394 theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
395 theAttribute->id(), aRef->id());
399 else { // the attribute reference
400 if (aRef->attr() == anAttributeAttr) {
401 theError = errorMessage(EqualAttributes,
402 anAttributeAttr.get() ? anAttributeAttr->id() : "",
403 theAttribute->id(), aRef->id());
411 else if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
412 AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
413 ResultPtr aContext = anAttr->context();
414 GeomShapePtr aShape = anAttr->value();
416 // Check selection attributes
417 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
418 if (anAttrs.size() > 0) {
419 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
420 for(; anAttr != anAttrs.end(); anAttr++) {
421 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
422 std::shared_ptr<ModelAPI_AttributeSelection> aRef =
423 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*anAttr);
424 // check the object is already presented
425 if (aRef->context() == aContext) {
426 bool aHasShape = aShape.get() != NULL;
427 if (!aHasShape || aRef->value()->isEqual(aShape)) {
428 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
436 else if (anAttrType == ModelAPI_AttributeReference::typeId()) {
437 AttributeReferencePtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
438 ObjectPtr anObject = anAttr->value();
439 // Check selection attributes
440 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeReference::typeId());
441 if (anAttrs.size() > 0) {
442 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
443 for(; anAttr != anAttrs.end(); anAttr++) {
444 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
445 std::shared_ptr<ModelAPI_AttributeReference> aRef =
446 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*anAttr);
447 // check the object is already presented
448 if (aRef->value() == anObject) {
449 theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
450 theAttribute->id(), aRef->id());
458 else if(anAttrType == ModelAPI_AttributeSelectionList::typeId()) {
459 std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList =
460 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
461 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
462 if(anAttrs.size() > 0) {
463 std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
464 for(; anAttrItr != anAttrs.end(); anAttrItr++){
465 if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
466 std::shared_ptr<ModelAPI_AttributeSelectionList> aRefSelList =
467 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*anAttrItr);
468 for(int i = 0; i < aCurSelList->size(); i++) {
469 std::shared_ptr<ModelAPI_AttributeSelection> aCurSel = aCurSelList->value(i);
470 ResultPtr aCurSelContext = aCurSel->context();
471 ResultCompSolidPtr aCurSelCompSolidPtr = ModelAPI_Tools::compSolidOwner(aCurSelContext);
472 std::shared_ptr<GeomAPI_Shape> aCurSelCompSolid;
473 if(aCurSelCompSolidPtr.get()) {
474 aCurSelCompSolid = aCurSelCompSolidPtr->shape();
476 for(int j = 0; j < aRefSelList->size(); j++) {
477 std::shared_ptr<ModelAPI_AttributeSelection> aRefSel = aRefSelList->value(j);
478 ResultPtr aRefSelContext = aRefSel->context();
479 ResultCompSolidPtr aRefSelCompSolidPtr = ModelAPI_Tools::compSolidOwner(aRefSelContext);
480 std::shared_ptr<GeomAPI_Shape> aRefSelCompSolid;
481 if(aRefSelCompSolidPtr.get()) {
482 aRefSelCompSolid = aRefSelCompSolidPtr->shape();
484 if ((aCurSelCompSolid.get() && aCurSelCompSolid->isEqual(aRefSel->value()))
485 || (aRefSelCompSolid.get() && aRefSelCompSolid->isEqual(aCurSel->value()))) {
486 theError = errorMessage(EqualShapes, "", theAttribute->id(),
490 if(aCurSelContext == aRefSelContext) {
491 if (aCurSel->value().get() == NULL || aRefSel->value().get() == NULL) {
492 theError = errorMessage(EmptyShapes, "", theAttribute->id(),
496 if (aCurSel->value()->isEqual(aRefSel->value())) {
497 theError = errorMessage(EqualShapes, "", theAttribute->id(),
508 else if (anAttrType == ModelAPI_AttributeRefList::typeId()) {
509 std::shared_ptr<ModelAPI_AttributeRefList> aCurSelList =
510 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
511 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefList::typeId());
512 if (anAttrs.size() > 0) {
513 std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
514 for (; anAttrItr != anAttrs.end(); anAttrItr++){
515 if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
516 std::shared_ptr<ModelAPI_AttributeRefList> aRefSelList =
517 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrItr);
518 for (int i = 0; i < aCurSelList->size(); i++) {
519 ObjectPtr aCurSelObject = aCurSelList->object(i);
520 for (int j = 0; j < aRefSelList->size(); j++) {
521 if (aCurSelObject == aRefSelList->object(j)) {
522 theError = errorMessage(EqualObjects,
523 aCurSelObject.get() ? aCurSelObject->data()->name() : "",
524 theAttribute->id(), aCurSelList->id());
536 bool PartSet_SketchEntityValidator::isValid(const AttributePtr& theAttribute,
537 const std::list<std::string>& theArguments,
538 std::string& theError) const
540 bool isSketchEntities = true;
541 std::set<std::string> anEntityKinds;
542 std::string anEntityKindsStr;
543 std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
544 for (; anIt != aLast; anIt++) {
545 anEntityKinds.insert(*anIt);
546 if (!anEntityKindsStr.empty())
547 anEntityKindsStr += ", ";
548 anEntityKindsStr += *anIt;
551 std::string anAttributeType = theAttribute->attributeType();
552 if (anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
553 AttributeSelectionListPtr aSelectionListAttr =
554 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
555 // all context objects should be sketch entities
556 for (int i = 0, aSize = aSelectionListAttr->size(); i < aSize && isSketchEntities; i++) {
557 AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i);
558 ObjectPtr anObject = aSelectAttr->context();
559 // a context of the selection attribute is a feature result. It can be a case when the result
560 // of the feature is null, e.g. the feature is modified and has not been executed yet.
561 // The validator returns an invalid result here. The case is an extrusion built on a sketch
562 // feature. A new sketch element creation leads to an empty result.
564 isSketchEntities = false;
566 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
567 isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
571 if (anAttributeType == ModelAPI_AttributeSelection::typeId()) {
572 AttributeSelectionPtr aSelectAttr =
573 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
574 ObjectPtr anObject = aSelectAttr->context();
575 // a context of the selection attribute is a feature result. It can be a case when the result
576 // of the feature is null, e.g. the feature is modified and has not been executed yet.
577 // The validator returns an invalid result here. The case is an extrusion built on a sketch
578 // feature. A new sketch element creation leads to an empty result.
580 isSketchEntities = false;
582 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
583 isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
586 if (anAttributeType == ModelAPI_AttributeRefList::typeId()) {
587 AttributeRefListPtr aRefListAttr =
588 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
589 // all context objects should be sketch entities
590 for (int i = 0, aSize = aRefListAttr->size(); i < aSize && isSketchEntities; i++) {
591 ObjectPtr anObject = aRefListAttr->object(i);
592 // a context of the selection attribute is a feature result. It can be a case when the result
593 // of the feature is null, e.g. the feature is modified and has not been executed yet.
594 // The validator returns an invalid result here. The case is an extrusion built on a sketch
595 // feature. A new sketch element creation leads to an empty result.
597 isSketchEntities = false;
599 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
600 isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
604 if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) {
605 std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
606 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
607 isSketchEntities = false;
608 if (aRef->isObject()) {
609 ObjectPtr anObject = aRef->object();
610 if (anObject.get() != NULL) {
611 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
612 if (aFeature.get() != NULL)
613 isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
617 if (!isSketchEntities) {
618 theError = "It refers to feature, which kind is not in the list: " + anEntityKindsStr;
621 return isSketchEntities;
624 bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute,
625 const std::list<std::string>& theArguments,
626 std::string& theError) const
628 if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
629 theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
633 // there is a check whether the feature contains a point and a linear edge or two point values
634 std::string aParamA = theArguments.front();
635 SessionPtr aMgr = ModelAPI_Session::get();
636 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
638 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
639 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
640 QList<FeaturePtr> aCoinsideLines;
642 bool isObject = aRefAttr->isObject();
643 ObjectPtr anObject = aRefAttr->object();
644 if (isObject && anObject) {
645 FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
646 AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA);
647 ObjectPtr aOtherObject = aOtherAttr->object();
648 // if the other attribute is not filled still, the result is true
649 if (!aOtherObject.get())
651 FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
653 // check that both have coincidence
654 FeaturePtr aConstrFeature;
655 std::set<FeaturePtr> aCoinList;
656 const std::set<std::shared_ptr<ModelAPI_Attribute>>& aRefsList = aRefFea->data()->refsToMe();
657 std::set<std::shared_ptr<ModelAPI_Attribute>>::const_iterator aIt;
658 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
659 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
660 aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
661 if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
662 AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
663 AttributePtr aAR = aRAttr->attr();
664 if (aAR->id() != SketchPlugin_Arc::CENTER_ID()) // ignore constraint to center of arc
665 aCoinList.insert(aConstrFeature);
666 PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines,
667 SketchPlugin_ConstraintCoincidence::ENTITY_A());
668 PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines,
669 SketchPlugin_ConstraintCoincidence::ENTITY_B());
672 // if there is no coincidence then it is not valid
673 if (aCoinList.size() > 0) {
674 QList<FeaturePtr>::const_iterator anIt = aCoinsideLines.begin(), aLast = aCoinsideLines.end();
676 for (; anIt != aLast && !aValid; anIt++) {
677 aValid = *anIt == aOtherFea;
683 theError = "There is no a common coincident point.";