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);
328 std::string PartSet_DifferentObjectsValidator::errorMessage(
329 const PartSet_DifferentObjectsValidator::ErrorType& theType,
330 const std::string& thEqualObject, const std::string& theFirstAttribute,
331 const std::string& theSecondAttribute) const
336 anError = "The feature uses one " + thEqualObject + " object in " +
337 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
339 case EqualAttributes:
340 anError = "The feature uses reference to one " + thEqualObject + " attribute in " +
341 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
344 anError = "The feature uses one shape in " +
345 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
348 anError = "The feature uses empty shapes in " +
349 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
358 bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute,
359 const std::list<std::string>& theArguments,
360 std::string& theError) const
362 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
364 // the type of validated attributes should be equal, attributes with different types are not validated
365 // Check RefAttr attributes
366 std::string anAttrType = theAttribute->attributeType();
367 std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
369 if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
370 AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
371 bool isObject = anAttr->isObject();
372 ObjectPtr anObject = anAttr->object();
373 AttributePtr anAttributeAttr = anAttr->attr();
375 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
376 if (anAttrs.size() > 0) {
377 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
378 for(; anAttr != anAttrs.end(); anAttr++) {
379 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
380 std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
381 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttr);
382 if (aRef->isObject() != isObject)
385 if (aRef->object() == anObject) {
386 theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
387 theAttribute->id(), aRef->id());
391 else { // the attribute reference
392 if (aRef->attr() == anAttributeAttr) {
393 theError = errorMessage(EqualAttributes,
394 anAttributeAttr.get() ? anAttributeAttr->id() : "",
395 theAttribute->id(), aRef->id());
403 else if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
404 AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
405 ResultPtr aContext = anAttr->context();
406 GeomShapePtr aShape = anAttr->value();
408 // Check selection attributes
409 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
410 if (anAttrs.size() > 0) {
411 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
412 for(; anAttr != anAttrs.end(); anAttr++) {
413 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
414 std::shared_ptr<ModelAPI_AttributeSelection> aRef =
415 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*anAttr);
416 // check the object is already presented
417 if (aRef->context() == aContext) {
418 bool aHasShape = aShape.get() != NULL;
419 if (!aHasShape || aRef->value()->isEqual(aShape)) {
420 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
428 else if (anAttrType == ModelAPI_AttributeReference::typeId()) {
429 AttributeReferencePtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
430 ObjectPtr anObject = anAttr->value();
431 // Check selection attributes
432 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeReference::typeId());
433 if (anAttrs.size() > 0) {
434 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
435 for(; anAttr != anAttrs.end(); anAttr++) {
436 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
437 std::shared_ptr<ModelAPI_AttributeReference> aRef =
438 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*anAttr);
439 // check the object is already presented
440 if (aRef->value() == anObject) {
441 theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
442 theAttribute->id(), aRef->id());
450 else if(anAttrType == ModelAPI_AttributeSelectionList::typeId()) {
451 std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList =
452 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
453 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
454 if(anAttrs.size() > 0) {
455 std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
456 for(; anAttrItr != anAttrs.end(); anAttrItr++){
457 if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
458 std::shared_ptr<ModelAPI_AttributeSelectionList> aRefSelList =
459 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*anAttrItr);
460 for(int i = 0; i < aCurSelList->size(); i++) {
461 std::shared_ptr<ModelAPI_AttributeSelection> aCurSel = aCurSelList->value(i);
462 ResultPtr aCurSelContext = aCurSel->context();
463 ResultCompSolidPtr aCurSelCompSolidPtr = ModelAPI_Tools::compSolidOwner(aCurSelContext);
464 std::shared_ptr<GeomAPI_Shape> aCurSelCompSolid;
465 if(aCurSelCompSolidPtr.get()) {
466 aCurSelCompSolid = aCurSelCompSolidPtr->shape();
468 for(int j = 0; j < aRefSelList->size(); j++) {
469 std::shared_ptr<ModelAPI_AttributeSelection> aRefSel = aRefSelList->value(j);
470 ResultPtr aRefSelContext = aRefSel->context();
471 ResultCompSolidPtr aRefSelCompSolidPtr = ModelAPI_Tools::compSolidOwner(aRefSelContext);
472 std::shared_ptr<GeomAPI_Shape> aRefSelCompSolid;
473 if(aRefSelCompSolidPtr.get()) {
474 aRefSelCompSolid = aRefSelCompSolidPtr->shape();
476 if ((aCurSelCompSolid.get() && aCurSelCompSolid->isEqual(aRefSel->value()))
477 || (aRefSelCompSolid.get() && aRefSelCompSolid->isEqual(aCurSel->value()))) {
478 theError = errorMessage(EqualShapes, "", theAttribute->id(),
482 if(aCurSelContext == aRefSelContext) {
483 if (aCurSel->value().get() == NULL || aRefSel->value().get() == NULL) {
484 theError = errorMessage(EmptyShapes, "", theAttribute->id(),
488 if (aCurSel->value()->isEqual(aRefSel->value())) {
489 theError = errorMessage(EqualShapes, "", theAttribute->id(),
500 else if (anAttrType == ModelAPI_AttributeRefList::typeId()) {
501 std::shared_ptr<ModelAPI_AttributeRefList> aCurSelList =
502 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
503 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefList::typeId());
504 if (anAttrs.size() > 0) {
505 std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
506 for (; anAttrItr != anAttrs.end(); anAttrItr++){
507 if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
508 std::shared_ptr<ModelAPI_AttributeRefList> aRefSelList =
509 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrItr);
510 for (int i = 0; i < aCurSelList->size(); i++) {
511 ObjectPtr aCurSelObject = aCurSelList->object(i);
512 for (int j = 0; j < aRefSelList->size(); j++) {
513 if (aCurSelObject == aRefSelList->object(j)) {
514 theError = errorMessage(EqualObjects,
515 aCurSelObject.get() ? aCurSelObject->data()->name() : "",
516 theAttribute->id(), aCurSelList->id());
528 bool PartSet_SketchEntityValidator::isValid(const AttributePtr& theAttribute,
529 const std::list<std::string>& theArguments,
530 std::string& theError) const
532 bool isSketchEntities = true;
533 std::set<std::string> anEntityKinds;
534 std::string anEntityKindsStr;
535 std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
536 for (; anIt != aLast; anIt++) {
537 anEntityKinds.insert(*anIt);
538 if (!anEntityKindsStr.empty())
539 anEntityKindsStr += ", ";
540 anEntityKindsStr += *anIt;
543 std::string anAttributeType = theAttribute->attributeType();
544 if (anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
545 AttributeSelectionListPtr aSelectionListAttr =
546 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
547 // all context objects should be sketch entities
548 for (int i = 0, aSize = aSelectionListAttr->size(); i < aSize && isSketchEntities; i++) {
549 AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i);
550 ObjectPtr anObject = aSelectAttr->context();
551 // a context of the selection attribute is a feature result. It can be a case when the result
552 // of the feature is null, e.g. the feature is modified and has not been executed yet.
553 // The validator returns an invalid result here. The case is an extrusion built on a sketch
554 // feature. A new sketch element creation leads to an empty result.
556 isSketchEntities = false;
558 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
559 isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
563 if (anAttributeType == ModelAPI_AttributeSelection::typeId()) {
564 AttributeSelectionPtr aSelectAttr =
565 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
566 ObjectPtr anObject = aSelectAttr->context();
567 // a context of the selection attribute is a feature result. It can be a case when the result
568 // of the feature is null, e.g. the feature is modified and has not been executed yet.
569 // The validator returns an invalid result here. The case is an extrusion built on a sketch
570 // feature. A new sketch element creation leads to an empty result.
572 isSketchEntities = false;
574 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
575 isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
578 if (anAttributeType == ModelAPI_AttributeRefList::typeId()) {
579 AttributeRefListPtr aRefListAttr =
580 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
581 // all context objects should be sketch entities
582 for (int i = 0, aSize = aRefListAttr->size(); i < aSize && isSketchEntities; i++) {
583 ObjectPtr anObject = aRefListAttr->object(i);
584 // a context of the selection attribute is a feature result. It can be a case when the result
585 // of the feature is null, e.g. the feature is modified and has not been executed yet.
586 // The validator returns an invalid result here. The case is an extrusion built on a sketch
587 // feature. A new sketch element creation leads to an empty result.
589 isSketchEntities = false;
591 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
592 isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
596 if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) {
597 std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
598 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
599 isSketchEntities = false;
600 if (aRef->isObject()) {
601 ObjectPtr anObject = aRef->object();
602 if (anObject.get() != NULL) {
603 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
604 if (aFeature.get() != NULL)
605 isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
609 if (!isSketchEntities) {
610 theError = "It refers to feature, which kind is not in the list: " + anEntityKindsStr;
613 return isSketchEntities;
616 bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute,
617 const std::list<std::string>& theArguments,
618 std::string& theError) const
620 if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
621 theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
625 // there is a check whether the feature contains a point and a linear edge or two point values
626 std::string aParamA = theArguments.front();
627 SessionPtr aMgr = ModelAPI_Session::get();
628 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
630 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
631 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
632 QList<FeaturePtr> aCoinsideLines;
634 bool isObject = aRefAttr->isObject();
635 ObjectPtr anObject = aRefAttr->object();
636 if (isObject && anObject) {
637 FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
638 AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA);
639 ObjectPtr aOtherObject = aOtherAttr->object();
640 // if the other attribute is not filled still, the result is true
641 if (!aOtherObject.get())
643 FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
645 // check that both have coincidence
646 FeaturePtr aConstrFeature;
647 std::set<FeaturePtr> aCoinList;
648 const std::set<std::shared_ptr<ModelAPI_Attribute>>& aRefsList = aRefFea->data()->refsToMe();
649 std::set<std::shared_ptr<ModelAPI_Attribute>>::const_iterator aIt;
650 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
651 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
652 aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
653 if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
654 AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
655 AttributePtr aAR = aRAttr->attr();
656 if (aAR->id() != SketchPlugin_Arc::CENTER_ID()) // ignore constraint to center of arc
657 aCoinList.insert(aConstrFeature);
658 PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines,
659 SketchPlugin_ConstraintCoincidence::ENTITY_A());
660 PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines,
661 SketchPlugin_ConstraintCoincidence::ENTITY_B());
664 // if there is no coincidence then it is not valid
665 if (aCoinList.size() > 0) {
666 QList<FeaturePtr>::const_iterator anIt = aCoinsideLines.begin(), aLast = aCoinsideLines.end();
668 for (; anIt != aLast && !aValid; anIt++) {
669 aValid = *anIt == aOtherFea;
675 theError = "There is no a common coincident point.";