1 // Copyright (C) 2014-2022 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 email : webmaster.salome@opencascade.com
20 #include "PartSet_Validators.h"
22 #include "PartSet_Tools.h"
23 #include "PartSet_SketcherMgr.h"
26 #include <TopoDS_Edge.hxx>
27 #include <BRep_Tool.hxx>
28 #include <GeomAdaptor_Curve.hxx>
29 #include <GeomAbs_CurveType.hxx>
30 #include <ModuleBase_ISelection.h>
31 #include <ModuleBase_WidgetShapeSelector.h>
32 #include <ModuleBase_OperationFeature.h>
33 #include <ModuleBase_ViewerPrs.h>
35 #include <GeomDataAPI_Point2D.h>
36 #include <GeomAPI_Pnt2d.h>
38 #include <Events_InfoMessage.h>
40 #include <ModelAPI_AttributeRefAttr.h>
41 #include <ModelAPI_AttributeSelection.h>
42 #include <ModelAPI_AttributeReference.h>
43 #include <ModelAPI_AttributeSelectionList.h>
44 #include <ModelAPI_AttributeRefList.h>
45 #include <ModelAPI_Object.h>
46 #include <ModelAPI_ResultBody.h>
47 #include <ModelAPI_Session.h>
48 #include <ModelAPI_Tools.h>
50 #include <SketchPlugin_Sketch.h>
51 #include <SketchPlugin_ConstraintCoincidence.h>
52 #include <SketchPlugin_Arc.h>
53 #include <SketchPlugin_Point.h>
54 #include <GeomAPI_Edge.h>
56 #include <Locale_Convert.h>
59 #include <unordered_map>
64 int shapesNbPoints(const ModuleBase_ISelection* theSelection)
66 QList<ModuleBase_ViewerPrsPtr> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
67 ModuleBase_ISelection::filterSelectionOnEqualPoints(aList);
70 foreach (ModuleBase_ViewerPrsPtr aPrs, aList) {
71 const GeomShapePtr& aShape = aPrs->shape();
72 if (aShape.get() && !aShape->isNull()) {
73 if (aShape->shapeType() == GeomAPI_Shape::VERTEX)
80 typedef std::unordered_map<int, int> ShapeQuantity;
82 int shapesNbEdges(const ModuleBase_ISelection* theSelection, ShapeQuantity& theEdges)
84 QList<ModuleBase_ViewerPrsPtr> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
86 foreach(ModuleBase_ViewerPrsPtr aPrs, aList) {
87 const GeomShapePtr& aShape = aPrs->shape();
88 if (aShape.get() && !aShape->isNull()) {
89 if (aShape->shapeType() == GeomAPI_Shape::EDGE) {
90 const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
91 TopoDS_Edge aEdge = TopoDS::Edge(aTDShape);
92 Standard_Real aStart, aEnd;
93 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aStart, aEnd);
94 GeomAdaptor_Curve aAdaptor(aCurve);
95 theEdges[(int)aAdaptor.GetType()] += 1;
104 std::shared_ptr<GeomAPI_Pln> sketcherPlane(ModuleBase_Operation* theOperation)
106 std::shared_ptr<GeomAPI_Pln> aEmptyPln;
108 ModuleBase_OperationFeature* aFeatureOp =
109 dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
111 CompositeFeaturePtr aFeature =
112 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeatureOp->feature());
113 if (aFeature && (aFeature->getKind() == SketchPlugin_Sketch::ID()))
114 return PartSet_Tools::sketchPlane(aFeature);
121 bool isEmptySelectionValid(ModuleBase_Operation* theOperation)
123 ModuleBase_OperationFeature* aFeatureOp =
124 dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
125 // during the create operation empty selection is always valid
126 if (!aFeatureOp->isEditOperation()) {
130 if (PartSet_SketcherMgr::isSketchOperation(aFeatureOp)) {
131 std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
138 // in edit operation an empty selection is always valid, performed for re-entrant operrations
143 bool PartSet_DistanceSelection::isValid(const ModuleBase_ISelection* theSelection,
144 ModuleBase_Operation* theOperation) const
146 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
147 return isEmptySelectionValid(theOperation);
149 int aNbPoints = shapesNbPoints(theSelection);
150 ShapeQuantity aShapes;
151 int aNbEdges = shapesNbEdges(theSelection, aShapes);
152 return (aNbPoints >= 0 && aNbPoints < 3) &&
153 (aShapes[GeomAbs_Line] == aNbEdges && aNbEdges >= 0 && aNbEdges < 2);
157 bool PartSet_LengthSelection::isValid(const ModuleBase_ISelection* theSelection,
158 ModuleBase_Operation* theOperation) const
160 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
161 return isEmptySelectionValid(theOperation);
163 int aNbPoints = shapesNbPoints(theSelection);
164 ShapeQuantity aShapes;
165 int aNbEdges = shapesNbEdges(theSelection, aShapes);
166 return aNbPoints == 0 && (aShapes[GeomAbs_Line] == aNbEdges && aNbEdges == 1);
170 bool PartSet_PerpendicularSelection::isValid(const ModuleBase_ISelection* theSelection,
171 ModuleBase_Operation* theOperation) const
173 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
174 return isEmptySelectionValid(theOperation);
176 int aNbPoints = shapesNbPoints(theSelection);
177 ShapeQuantity aShapes;
178 int aNbEdges = shapesNbEdges(theSelection, aShapes);
179 return aNbPoints == 0 && aShapes[GeomAbs_Line] == aNbEdges && aNbEdges > 0 && aNbEdges < 3;
183 bool PartSet_ParallelSelection::isValid(const ModuleBase_ISelection* theSelection,
184 ModuleBase_Operation* theOperation) const
186 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
187 return isEmptySelectionValid(theOperation);
189 int aNbPoints = shapesNbPoints(theSelection);
190 ShapeQuantity aShapes;
191 int aNbEdges = shapesNbEdges(theSelection, aShapes);
192 return aNbPoints == 0 && aShapes[GeomAbs_Line] == aNbEdges && aNbEdges > 0 && aNbEdges < 3;
196 bool PartSet_RadiusSelection::isValid(const ModuleBase_ISelection* theSelection,
197 ModuleBase_Operation* theOperation) const
199 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
200 return isEmptySelectionValid(theOperation);
202 int aNbPoints = shapesNbPoints(theSelection);
203 ShapeQuantity aShapes;
204 int aNbEdges = shapesNbEdges(theSelection, aShapes);
205 return aNbPoints == 0 && (aShapes[GeomAbs_Circle] == aNbEdges && aNbEdges == 1);
209 bool PartSet_RigidSelection::isValid(const ModuleBase_ISelection* theSelection,
210 ModuleBase_Operation* theOperation) const
212 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
213 return isEmptySelectionValid(theOperation);
215 QList<ModuleBase_ViewerPrsPtr> aList =
216 theSelection->getSelected(ModuleBase_ISelection::Viewer);
218 foreach (ModuleBase_ViewerPrsPtr aPrs, aList) {
219 ObjectPtr aObj = aPrs->object();
221 FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
222 if (aFeature.get()) {
223 CompositeFeaturePtr aComp = ModelAPI_Tools::compositeOwner(aFeature);
224 if (aComp.get() && (aComp->getKind() == SketchPlugin_Sketch::ID()))
229 return (aCount == 1);
234 bool PartSet_CoincidentSelection::isValid(const ModuleBase_ISelection* theSelection,
235 ModuleBase_Operation* theOperation) const
237 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
238 return isEmptySelectionValid(theOperation);
240 // Coincident can be applied to points and to lines
241 int aNbPoints = shapesNbPoints(theSelection);
242 ShapeQuantity aShapes;
243 int aNbEdges = shapesNbEdges(theSelection, aShapes);
244 return (aNbPoints >= 0 && aNbPoints < 3) && (aNbEdges >= 0 && aNbEdges < 2);
248 bool PartSet_HVDirSelection::isValid(const ModuleBase_ISelection* theSelection,
249 ModuleBase_Operation* theOperation) const
251 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
252 return isEmptySelectionValid(theOperation);
254 int aNbPoints = shapesNbPoints(theSelection);
255 ShapeQuantity aShapes;
256 int aNbEdges = shapesNbEdges(theSelection, aShapes);
257 return aNbPoints == 0 && (aShapes[GeomAbs_Line] == aNbEdges && aNbEdges == 1);
261 bool PartSet_FilletSelection::isValid(const ModuleBase_ISelection* theSelection,
262 ModuleBase_Operation* theOperation) const
264 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
265 return isEmptySelectionValid(theOperation);
267 int aCount = shapesNbPoints(theSelection);
268 ShapeQuantity aShapes;
269 int aNbEdges = shapesNbEdges(theSelection, aShapes);
270 return aCount > 1 && aNbEdges == 0;
274 bool PartSet_TangentSelection::isValid(const ModuleBase_ISelection* theSelection,
275 ModuleBase_Operation* theOperation) const
277 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
278 return isEmptySelectionValid(theOperation);
280 int aNbPoints = shapesNbPoints(theSelection);
281 ShapeQuantity aShapes;
282 int aNbEdges = shapesNbEdges(theSelection, aShapes);
283 return aNbPoints == 0 && (aNbEdges == 1 || (aNbEdges == 2 && aShapes[GeomAbs_Line] == 1));
287 bool PartSet_AngleSelection::isValid(const ModuleBase_ISelection* theSelection,
288 ModuleBase_Operation* theOperation) const
290 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
291 return isEmptySelectionValid(theOperation);
293 int aNbPoints = shapesNbPoints(theSelection);
294 ShapeQuantity aShapes;
295 int aNbEdges = shapesNbEdges(theSelection, aShapes);
296 return aNbPoints == 0 && aShapes[GeomAbs_Line] == aNbEdges && aNbEdges > 0 && aNbEdges < 3;
300 bool PartSet_EqualSelection::isValid(const ModuleBase_ISelection* theSelection,
301 ModuleBase_Operation* theOperation) const
303 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
304 return isEmptySelectionValid(theOperation);
306 int aNbPoints = shapesNbPoints(theSelection);
307 ShapeQuantity aShapes;
308 int aNbEdges = shapesNbEdges(theSelection, aShapes);
309 return aNbPoints == 0 && (aNbEdges > 0 && aNbEdges < 3) &&
310 (aShapes[GeomAbs_Line] == aNbEdges ||
311 aShapes[GeomAbs_Circle] == aNbEdges ||
312 aShapes[GeomAbs_Ellipse] == aNbEdges);
316 bool PartSet_CollinearSelection::isValid(const ModuleBase_ISelection* theSelection,
317 ModuleBase_Operation* theOperation) const
319 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
320 return isEmptySelectionValid(theOperation);
322 int aNbPoints = shapesNbPoints(theSelection);
323 ShapeQuantity aShapes;
324 int aNbEdges = shapesNbEdges(theSelection, aShapes);
325 return aNbPoints == 0 && aShapes[GeomAbs_Line] == aNbEdges && aNbEdges > 0 && aNbEdges < 3;
329 bool PartSet_MiddlePointSelection::isValid(const ModuleBase_ISelection* theSelection,
330 ModuleBase_Operation* theOperation) const
332 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0)
333 return isEmptySelectionValid(theOperation);
335 int aNbPoints = shapesNbPoints(theSelection);
336 ShapeQuantity aShapes;
337 int aNbEdges = shapesNbEdges(theSelection, aShapes);
338 return (aNbPoints >= 0 && aNbPoints < 3) && (aNbEdges >= 0 && aNbEdges < 2);
342 bool PartSet_MultyTranslationSelection::isValid(const ModuleBase_ISelection* theSelection,
343 ModuleBase_Operation* theOperation) const
345 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
346 return isEmptySelectionValid(theOperation);
348 ShapeQuantity aShapes;
349 int aNbEdges = shapesNbEdges(theSelection, aShapes);
354 bool PartSet_SplitSelection::isValid(const ModuleBase_ISelection* theSelection,
355 ModuleBase_Operation* theOperation) const
357 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
358 return isEmptySelectionValid(theOperation);
360 ShapeQuantity aShapes;
361 int aNbEdges = shapesNbEdges(theSelection, aShapes);
366 bool PartSet_ProjectionSelection::isValid(const ModuleBase_ISelection* theSelection,
367 ModuleBase_Operation* theOperation) const
369 return theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0 &&
370 isEmptySelectionValid(theOperation);
373 bool PartSet_IntersectionSelection::isValid(const ModuleBase_ISelection* theSelection,
374 ModuleBase_Operation* theOperation) const
376 return theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0 &&
377 isEmptySelectionValid(theOperation);
381 std::string PartSet_DifferentObjectsValidator::errorMessage(
382 const PartSet_DifferentObjectsValidator::ErrorType& theType,
383 const std::string& thEqualObject, const std::string& theFirstAttribute,
384 const std::string& theSecondAttribute) const
389 anError = "The feature uses one " + thEqualObject + " object in " +
390 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
392 case EqualAttributes:
393 anError = "The feature uses reference to one " + thEqualObject + " attribute in " +
394 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
397 anError = "The feature uses one shape in " +
398 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
401 anError = "The feature uses empty shapes in " +
402 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
411 bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute,
412 const std::list<std::string>& theArguments,
413 Events_InfoMessage& theError) const
415 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
417 // the type of validated attributes should be equal, attributes with
418 // different types are not validated
419 // Check RefAttr attributes
420 std::string anAttrType = theAttribute->attributeType();
421 std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
423 if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
424 AttributeRefAttrPtr anAttr =
425 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
426 bool isObject = anAttr->isObject();
427 ObjectPtr anObject = anAttr->object();
429 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
430 if (anAttrs.size() > 0) {
431 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttrs.begin();
432 for(; anAttrIter != anAttrs.end(); anAttrIter++) {
433 if ((*anAttrIter).get() && (*anAttrIter)->id() != theAttribute->id()) {
434 std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
435 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
436 if (aRef->isObject() != isObject)
439 if (aRef->object() == anObject) {
440 theError = errorMessage(EqualObjects,
441 anObject.get() ? Locale::Convert::toString(anObject->data()->name()) : "",
442 theAttribute->id(), aRef->id());
446 else { // the attribute reference
447 AttributePtr anAttributeAttr = anAttr->attr();
448 if (aRef->attr() == anAttributeAttr) {
449 theError = errorMessage(EqualAttributes,
450 anAttributeAttr.get() ? anAttributeAttr->id() : "",
451 theAttribute->id(), aRef->id());
459 else if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
460 AttributeSelectionPtr anAttrSel =
461 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
462 ResultPtr aContext = anAttrSel->context();
463 FeaturePtr aContextFeature = anAttrSel->contextFeature();
464 GeomShapePtr aShape = anAttrSel->value();
466 // Check selection attributes
467 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
468 if (anAttrs.size() > 0) {
469 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
470 for(; anAttr != anAttrs.end(); anAttr++) {
471 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
472 std::shared_ptr<ModelAPI_AttributeSelection> aRef =
473 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*anAttr);
474 // check the object is already presented
475 if (aRef->context() == aContext) {
476 bool aHasShape = aShape.get() != NULL;
477 if (!aHasShape || aRef->value()->isEqual(aShape)) {
478 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
482 // check the whole selected feature contains the result
483 if (aContextFeature.get()) {
484 if (aRef->contextFeature().get()) {
485 if (aContextFeature == aRef->contextFeature()) {
486 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
489 } else if (aRef->context().get() &&
490 aRef->context()->document()->feature(aRef->context()) == aContextFeature) {
491 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
494 } else if (aRef->contextFeature().get() && aContext.get()) {
495 if (aContext->document()->feature(aContext) == aRef->contextFeature()) {
496 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
504 else if (anAttrType == ModelAPI_AttributeReference::typeId()) {
505 AttributeReferencePtr anAttrRef =
506 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
507 ObjectPtr anObject = anAttrRef->value();
508 // Check selection attributes
509 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeReference::typeId());
510 if (anAttrs.size() > 0) {
511 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
512 for(; anAttr != anAttrs.end(); anAttr++) {
513 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
514 std::shared_ptr<ModelAPI_AttributeReference> aRef =
515 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*anAttr);
516 // check the object is already presented
517 if (aRef->value() == anObject) {
518 theError = errorMessage(EqualObjects,
519 anObject.get() ? Locale::Convert::toString(anObject->data()->name()) : "",
520 theAttribute->id(), aRef->id());
528 else if(anAttrType == ModelAPI_AttributeSelectionList::typeId()) {
529 std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList =
530 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
531 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
532 if(anAttrs.size() > 0) {
533 std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
534 for(; anAttrItr != anAttrs.end(); anAttrItr++){
535 if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
536 std::shared_ptr<ModelAPI_AttributeSelectionList> aRefSelList =
537 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*anAttrItr);
538 for(int i = 0; i < aCurSelList->size(); i++) {
539 std::shared_ptr<ModelAPI_AttributeSelection> aCurSel = aCurSelList->value(i);
540 ResultPtr aCurSelContext = aCurSel->context();
541 FeaturePtr aCurSelFeature = aCurSel->contextFeature();
542 ResultBodyPtr aCurSelCompSolidPtr = ModelAPI_Tools::bodyOwner(aCurSelContext);
543 std::shared_ptr<GeomAPI_Shape> aCurSelCompSolid;
544 if(aCurSelCompSolidPtr.get()) {
545 aCurSelCompSolid = aCurSelCompSolidPtr->shape();
547 for(int j = 0; j < aRefSelList->size(); j++) {
548 std::shared_ptr<ModelAPI_AttributeSelection> aRefSel = aRefSelList->value(j);
549 ResultPtr aRefSelContext = aRefSel->context();
550 FeaturePtr aRefSelFeature = aRefSel->contextFeature();
551 ResultBodyPtr aRefSelCompSolidPtr =
552 ModelAPI_Tools::bodyOwner(aRefSelContext);
553 std::shared_ptr<GeomAPI_Shape> aRefSelCompSolid;
554 if (aRefSelCompSolidPtr.get()) {
555 aRefSelCompSolid = aRefSelCompSolidPtr->shape();
557 if ((aCurSelCompSolid.get() && aCurSelCompSolid->isEqual(aRefSel->value()))
558 || (aRefSelCompSolid.get() && aRefSelCompSolid->isEqual(aCurSel->value()))) {
559 theError = errorMessage(EqualShapes, "", theAttribute->id(),
563 if (aCurSelContext == aRefSelContext) {
564 if (aCurSel->value().get() == NULL || aRefSel->value().get() == NULL) {
565 theError = errorMessage(EmptyShapes, "", theAttribute->id(), aRefSel->id());
568 if (aCurSel->value()->isEqual(aRefSel->value())) {
569 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
574 // check the whole selected feature contains the result
575 if (aCurSelFeature.get()) {
576 if (aRefSelFeature.get()) {
577 if (aCurSelFeature == aRefSelFeature) {
578 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
582 else if (aRefSelContext.get() &&
583 aRefSelContext->document()->feature(aRefSelContext) == aCurSelFeature) {
584 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
588 else if (aRefSelFeature.get() && aCurSelContext.get()) {
589 if (aCurSelContext->document()->feature(aCurSelContext) == aRefSelFeature) {
590 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
600 else if (anAttrType == ModelAPI_AttributeRefList::typeId()) {
601 std::shared_ptr<ModelAPI_AttributeRefList> aCurSelList =
602 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
603 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefList::typeId());
604 if (anAttrs.size() > 0) {
605 std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
606 for (; anAttrItr != anAttrs.end(); anAttrItr++){
607 if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
608 std::shared_ptr<ModelAPI_AttributeRefList> aRefSelList =
609 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrItr);
610 for (int i = 0; i < aCurSelList->size(); i++) {
611 ObjectPtr aCurSelObject = aCurSelList->object(i);
612 for (int j = 0; j < aRefSelList->size(); j++) {
613 if (aCurSelObject == aRefSelList->object(j)) {
614 theError = errorMessage(EqualObjects,
616 Locale::Convert::toString(aCurSelObject->data()->name()) : "",
617 theAttribute->id(), aCurSelList->id());
629 bool PartSet_DifferentPointsValidator::isValid(const AttributePtr& theAttribute,
630 const std::list<std::string>& theArguments,
631 Events_InfoMessage& theError) const
633 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
635 // the type of validated attributes should be equal, attributes with
636 // different types are not validated
637 // Check RefAttr attributes
638 std::string anAttrType = theAttribute->attributeType();
639 std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
640 if (anAttrType != ModelAPI_AttributeRefAttr::typeId())
643 // obtain point of the given attribute
644 AttributePoint2DPtr anAttributePoint = getRefPointAttribute(theAttribute);
645 if (!anAttributePoint.get() || !anAttributePoint->isInitialized())
648 // obtain point of the parameter attribute
649 AttributePoint2DPtr anArgumentPoint = getRefPointAttribute
650 (aFeature->attribute(theArguments.front()));
652 if (!anArgumentPoint.get() || !anArgumentPoint->isInitialized())
655 return !anAttributePoint->pnt()->isEqual(anArgumentPoint->pnt());
658 AttributePoint2DPtr PartSet_DifferentPointsValidator::getRefPointAttribute
659 (const AttributePtr& theAttribute) const
661 AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
663 AttributePoint2DPtr aPointAttribute;
664 if (anAttr->isObject()) {
665 ObjectPtr anObject = anAttr->object();
666 if (anObject.get()) {
667 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
668 if (aFeature->getKind() == SketchPlugin_Point::ID())
669 aPointAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>
670 (aFeature->attribute(SketchPlugin_Point::COORD_ID()));
674 aPointAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
676 return aPointAttribute;
679 bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute,
680 const std::list<std::string>& theArguments,
681 Events_InfoMessage& theError) const
683 if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
684 theError = "The attribute with the %1 type is not processed";
685 theError.arg(theAttribute->attributeType());
689 // there is a check whether the feature contains a point and a linear edge or two point values
690 std::string aParamA = theArguments.front();
692 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
693 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
694 QList<FeaturePtr> aCoinsideLines;
695 QList<FeaturePtr> aCoins;
697 bool isObject = aRefAttr->isObject();
698 ObjectPtr anObject = aRefAttr->object();
699 if (isObject && anObject) {
700 FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
701 AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA);
702 ObjectPtr aOtherObject = aOtherAttr->object();
703 // if the other attribute is not filled still, the result is true
704 if (!aOtherObject.get())
706 FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
708 // check that both have coincidence
709 FeaturePtr aConstrFeature;
710 std::set<FeaturePtr> aCoinList;
711 const std::set<std::shared_ptr<ModelAPI_Attribute>>& aRefsList = aRefFea->data()->refsToMe();
712 std::set<std::shared_ptr<ModelAPI_Attribute>>::const_iterator aIt;
713 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
714 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
715 aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
716 if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
717 AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
718 AttributePtr aAR = aRAttr->attr();
719 if (aAR->id() != SketchPlugin_Arc::CENTER_ID()) // ignore constraint to center of arc
720 aCoinList.insert(aConstrFeature);
721 QList<bool> anIsAttributes;
722 PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, aCoins,
723 SketchPlugin_ConstraintCoincidence::ENTITY_A(),
725 PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, aCoins,
726 SketchPlugin_ConstraintCoincidence::ENTITY_B(),
730 // if there is no coincidence then it is not valid
731 if (aCoinList.size() > 0) {
732 QList<FeaturePtr>::const_iterator anIt = aCoinsideLines.begin(), aLast = aCoinsideLines.end();
734 for (; anIt != aLast && !aValid; anIt++) {
735 aValid = *anIt == aOtherFea;
741 theError = "There is no a common coincident point.";