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"
12 #include <TopoDS_Edge.hxx>
13 #include <BRep_Tool.hxx>
14 #include <GeomAdaptor_Curve.hxx>
15 #include <GeomAbs_CurveType.hxx>
16 #include <GeomValidators_Tools.h>
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);
92 bool PartSet_DistanceSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
94 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
95 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
96 if (!aFeatureOp->isEditOperation()) {
99 std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
105 int aCount = shapesNbPoints(theSelection) + shapesNbLines(theSelection);
106 return (aCount > 0) && (aCount < 3);
110 bool PartSet_LengthSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
112 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
113 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
114 if (!aFeatureOp->isEditOperation()) {
117 std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
123 int aCount = shapesNbLines(theSelection);
124 return (aCount == 1);
128 bool PartSet_PerpendicularSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
130 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
131 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
132 if (!aFeatureOp->isEditOperation()) {
135 std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
141 int aCount = shapesNbLines(theSelection);
142 return (aCount > 0) && (aCount < 3);
146 bool PartSet_ParallelSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
148 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
149 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
150 if (!aFeatureOp->isEditOperation()) {
153 std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
159 int aCount = shapesNbLines(theSelection);
160 return (aCount > 0) && (aCount < 3);
164 bool PartSet_RadiusSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
166 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
167 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
168 if (!aFeatureOp->isEditOperation()) {
171 std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
177 QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
178 ModuleBase_ViewerPrs aPrs;
180 foreach (ModuleBase_ViewerPrs aPrs, aList) {
181 const TopoDS_Shape& aShape = aPrs.shape();
182 if (!aShape.IsNull()) {
183 if (aShape.ShapeType() == TopAbs_EDGE) {
184 TopoDS_Edge aEdge = TopoDS::Edge(aShape);
185 Standard_Real aStart, aEnd;
186 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aStart, aEnd);
187 GeomAdaptor_Curve aAdaptor(aCurve);
188 if (aAdaptor.GetType() == GeomAbs_Circle)
193 return (aCount == 1);
197 bool PartSet_RigidSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
199 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
200 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
201 if (!aFeatureOp->isEditOperation()) {
204 std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
210 QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
211 return (aList.count() == 1);
216 bool PartSet_CoincidentSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
218 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
219 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
220 if (!aFeatureOp->isEditOperation()) {
223 std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
229 // Coincident can be applied to points and to lines
230 int aCount = shapesNbPoints(theSelection);
231 aCount += shapesNbLines(theSelection);
232 return (aCount > 0) && (aCount < 3);
236 bool PartSet_HVDirSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
238 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
239 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
240 if (!aFeatureOp->isEditOperation()) {
243 std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
249 int aCount = shapesNbLines(theSelection);
250 return (aCount == 1);
254 bool PartSet_FilletSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
256 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
257 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
258 if (!aFeatureOp->isEditOperation()) {
261 std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
267 int aCount = shapesNbLines(theSelection);
268 return (aCount > 0) && (aCount < 3);
272 bool PartSet_TangentSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
274 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
275 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
276 if (!aFeatureOp->isEditOperation()) {
279 std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
285 QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
286 if ((aList.size() == 0) || (aList.size() > 2))
289 ModuleBase_ViewerPrs aPrs = aList.first();
290 const TopoDS_Shape& aShape = aPrs.shape();
294 if (aShape.ShapeType() != TopAbs_EDGE)
297 std::shared_ptr<GeomAPI_Shape> aShapePtr(new GeomAPI_Shape);
298 aShapePtr->setImpl(new TopoDS_Shape(aShape));
299 GeomAPI_Edge aEdge1(aShapePtr);
301 if (aEdge1.isLine() || aEdge1.isArc()) {
302 if (aList.size() == 2) {
303 // Check second selection
305 const TopoDS_Shape& aShape2 = aPrs.shape();
306 if (aShape2.IsNull())
309 if (aShape2.ShapeType() != TopAbs_EDGE)
312 std::shared_ptr<GeomAPI_Shape> aShapePtr2(new GeomAPI_Shape);
313 aShapePtr2->setImpl(new TopoDS_Shape(aShape2));
314 GeomAPI_Edge aEdge2(aShapePtr2);
315 if (aEdge1.isLine() && aEdge2.isArc())
317 else if (aEdge1.isArc() && aEdge2.isLine())
328 bool PartSet_AngleSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
330 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
331 ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
332 if (!aFeatureOp->isEditOperation()) {
335 std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
341 int aCount = shapesNbLines(theSelection);
342 return (aCount > 0) && (aCount < 3);
346 std::string PartSet_DifferentObjectsValidator::errorMessage(
347 const PartSet_DifferentObjectsValidator::ErrorType& theType,
348 const std::string& thEqualObject, const std::string& theFirstAttribute,
349 const std::string& theSecondAttribute) const
354 anError = "The feature uses one " + thEqualObject + " object in " +
355 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
357 case EqualAttributes:
358 anError = "The feature uses reference to one " + thEqualObject + " attribute in " +
359 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
362 anError = "The feature uses one shape in " +
363 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
366 anError = "The feature uses empty shapes in " +
367 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
376 bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute,
377 const std::list<std::string>& theArguments,
378 std::string& theError) const
380 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
382 // the type of validated attributes should be equal, attributes with different types are not validated
383 // Check RefAttr attributes
384 std::string anAttrType = theAttribute->attributeType();
385 std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
387 if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
388 AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
389 bool isObject = anAttr->isObject();
390 ObjectPtr anObject = anAttr->object();
391 AttributePtr anAttributeAttr = anAttr->attr();
393 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
394 if (anAttrs.size() > 0) {
395 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
396 for(; anAttr != anAttrs.end(); anAttr++) {
397 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
398 std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
399 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttr);
400 if (aRef->isObject() != isObject)
403 if (aRef->object() == anObject) {
404 theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
405 theAttribute->id(), aRef->id());
409 else { // the attribute reference
410 if (aRef->attr() == anAttributeAttr) {
411 theError = errorMessage(EqualAttributes,
412 anAttributeAttr.get() ? anAttributeAttr->id() : "",
413 theAttribute->id(), aRef->id());
421 else if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
422 AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
423 ResultPtr aContext = anAttr->context();
424 GeomShapePtr aShape = anAttr->value();
426 // Check selection attributes
427 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
428 if (anAttrs.size() > 0) {
429 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
430 for(; anAttr != anAttrs.end(); anAttr++) {
431 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
432 std::shared_ptr<ModelAPI_AttributeSelection> aRef =
433 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*anAttr);
434 // check the object is already presented
435 if (aRef->context() == aContext) {
436 bool aHasShape = aShape.get() != NULL;
437 if (!aHasShape || aRef->value()->isEqual(aShape)) {
438 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
446 else if (anAttrType == ModelAPI_AttributeReference::typeId()) {
447 AttributeReferencePtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
448 ObjectPtr anObject = anAttr->value();
449 // Check selection attributes
450 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeReference::typeId());
451 if (anAttrs.size() > 0) {
452 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
453 for(; anAttr != anAttrs.end(); anAttr++) {
454 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
455 std::shared_ptr<ModelAPI_AttributeReference> aRef =
456 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*anAttr);
457 // check the object is already presented
458 if (aRef->value() == anObject) {
459 theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
460 theAttribute->id(), aRef->id());
468 else if(anAttrType == ModelAPI_AttributeSelectionList::typeId()) {
469 std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList =
470 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
471 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
472 if(anAttrs.size() > 0) {
473 std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
474 for(; anAttrItr != anAttrs.end(); anAttrItr++){
475 if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
476 std::shared_ptr<ModelAPI_AttributeSelectionList> aRefSelList =
477 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*anAttrItr);
478 for(int i = 0; i < aCurSelList->size(); i++) {
479 std::shared_ptr<ModelAPI_AttributeSelection> aCurSel = aCurSelList->value(i);
480 ResultPtr aCurSelContext = aCurSel->context();
481 ResultCompSolidPtr aCurSelCompSolidPtr = ModelAPI_Tools::compSolidOwner(aCurSelContext);
482 std::shared_ptr<GeomAPI_Shape> aCurSelCompSolid;
483 if(aCurSelCompSolidPtr.get()) {
484 aCurSelCompSolid = aCurSelCompSolidPtr->shape();
486 for(int j = 0; j < aRefSelList->size(); j++) {
487 std::shared_ptr<ModelAPI_AttributeSelection> aRefSel = aRefSelList->value(j);
488 ResultPtr aRefSelContext = aRefSel->context();
489 ResultCompSolidPtr aRefSelCompSolidPtr = ModelAPI_Tools::compSolidOwner(aRefSelContext);
490 std::shared_ptr<GeomAPI_Shape> aRefSelCompSolid;
491 if(aRefSelCompSolidPtr.get()) {
492 aRefSelCompSolid = aRefSelCompSolidPtr->shape();
494 if ((aCurSelCompSolid.get() && aCurSelCompSolid->isEqual(aRefSel->value()))
495 || (aRefSelCompSolid.get() && aRefSelCompSolid->isEqual(aCurSel->value()))) {
496 theError = errorMessage(EqualShapes, "", theAttribute->id(),
500 if(aCurSelContext == aRefSelContext) {
501 if (aCurSel->value().get() == NULL || aRefSel->value().get() == NULL) {
502 theError = errorMessage(EmptyShapes, "", theAttribute->id(),
506 if (aCurSel->value()->isEqual(aRefSel->value())) {
507 theError = errorMessage(EqualShapes, "", theAttribute->id(),
518 else if (anAttrType == ModelAPI_AttributeRefList::typeId()) {
519 std::shared_ptr<ModelAPI_AttributeRefList> aCurSelList =
520 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
521 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefList::typeId());
522 if (anAttrs.size() > 0) {
523 std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
524 for (; anAttrItr != anAttrs.end(); anAttrItr++){
525 if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
526 std::shared_ptr<ModelAPI_AttributeRefList> aRefSelList =
527 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrItr);
528 for (int i = 0; i < aCurSelList->size(); i++) {
529 ObjectPtr aCurSelObject = aCurSelList->object(i);
530 for (int j = 0; j < aRefSelList->size(); j++) {
531 if (aCurSelObject == aRefSelList->object(j)) {
532 theError = errorMessage(EqualObjects,
533 aCurSelObject.get() ? aCurSelObject->data()->name() : "",
534 theAttribute->id(), aCurSelList->id());
546 bool PartSet_SketchEntityValidator::isValid(const AttributePtr& theAttribute,
547 const std::list<std::string>& theArguments,
548 std::string& theError) const
550 bool isSketchEntities = true;
551 std::set<std::string> anEntityKinds;
552 std::string anEntityKindsStr;
553 std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
554 for (; anIt != aLast; anIt++) {
555 anEntityKinds.insert(*anIt);
556 if (!anEntityKindsStr.empty())
557 anEntityKindsStr += ", ";
558 anEntityKindsStr += *anIt;
561 std::string anAttributeType = theAttribute->attributeType();
562 if (anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
563 AttributeSelectionListPtr aSelectionListAttr =
564 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
565 // all context objects should be sketch entities
566 for (int i = 0, aSize = aSelectionListAttr->size(); i < aSize && isSketchEntities; i++) {
567 AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i);
568 ObjectPtr anObject = aSelectAttr->context();
569 // a context of the selection attribute is a feature result. It can be a case when the result
570 // of the feature is null, e.g. the feature is modified and has not been executed yet.
571 // The validator returns an invalid result here. The case is an extrusion built on a sketch
572 // feature. A new sketch element creation leads to an empty result.
574 isSketchEntities = false;
576 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
577 isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
581 if (anAttributeType == ModelAPI_AttributeRefList::typeId()) {
582 AttributeRefListPtr aRefListAttr =
583 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
584 // all context objects should be sketch entities
585 for (int i = 0, aSize = aRefListAttr->size(); i < aSize && isSketchEntities; i++) {
586 ObjectPtr anObject = aRefListAttr->object(i);
587 // a context of the selection attribute is a feature result. It can be a case when the result
588 // of the feature is null, e.g. the feature is modified and has not been executed yet.
589 // The validator returns an invalid result here. The case is an extrusion built on a sketch
590 // feature. A new sketch element creation leads to an empty result.
592 isSketchEntities = false;
594 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
595 isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
599 if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) {
600 std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
601 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
602 isSketchEntities = false;
603 if (aRef->isObject()) {
604 ObjectPtr anObject = aRef->object();
605 if (anObject.get() != NULL) {
606 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
607 if (aFeature.get() != NULL)
608 isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
612 if (!isSketchEntities) {
613 theError = "It refers to feature, which kind is not in the list: " + anEntityKindsStr;
616 return isSketchEntities;
619 bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute,
620 const std::list<std::string>& theArguments,
621 std::string& theError) const
623 if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
624 theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
628 // there is a check whether the feature contains a point and a linear edge or two point values
629 std::string aParamA = theArguments.front();
630 SessionPtr aMgr = ModelAPI_Session::get();
631 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
633 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
634 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
635 QList<FeaturePtr> aCoinsideLines;
637 bool isObject = aRefAttr->isObject();
638 ObjectPtr anObject = aRefAttr->object();
639 if (isObject && anObject) {
640 FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
641 AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA);
642 ObjectPtr aOtherObject = aOtherAttr->object();
643 // if the other attribute is not filled still, the result is true
644 if (!aOtherObject.get())
646 FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
648 // check that both have coincidence
649 FeaturePtr aConstrFeature;
650 std::set<FeaturePtr> aCoinList;
651 const std::set<std::shared_ptr<ModelAPI_Attribute>>& aRefsList = aRefFea->data()->refsToMe();
652 std::set<std::shared_ptr<ModelAPI_Attribute>>::const_iterator aIt;
653 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
654 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
655 aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
656 if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
657 AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
658 AttributePtr aAR = aRAttr->attr();
659 if (aAR->id() != SketchPlugin_Arc::CENTER_ID()) // ignore constraint to center of arc
660 aCoinList.insert(aConstrFeature);
661 PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines,
662 SketchPlugin_ConstraintCoincidence::ENTITY_A());
663 PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines,
664 SketchPlugin_ConstraintCoincidence::ENTITY_B());
667 // if there is no coincidence then it is not valid
668 if (aCoinList.size() > 0) {
669 QList<FeaturePtr>::const_iterator anIt = aCoinsideLines.begin(), aLast = aCoinsideLines.end();
671 for (; anIt != aLast && !aValid; anIt++) {
672 aValid = *anIt == aOtherFea;
678 theError = "There is no a common coincident point.";