1 // Copyright (C) 2014-2019 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>
57 #include <unordered_map>
62 int shapesNbPoints(const ModuleBase_ISelection* theSelection)
64 QList<ModuleBase_ViewerPrsPtr> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
65 ModuleBase_ISelection::filterSelectionOnEqualPoints(aList);
68 foreach (ModuleBase_ViewerPrsPtr aPrs, aList) {
69 const GeomShapePtr& aShape = aPrs->shape();
70 if (aShape.get() && !aShape->isNull()) {
71 if (aShape->shapeType() == GeomAPI_Shape::VERTEX)
78 typedef std::unordered_map<GeomAbs_CurveType, int> ShapeQuantity;
80 int shapesNbEdges(const ModuleBase_ISelection* theSelection, ShapeQuantity& theEdges)
82 QList<ModuleBase_ViewerPrsPtr> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
84 foreach(ModuleBase_ViewerPrsPtr aPrs, aList) {
85 const GeomShapePtr& aShape = aPrs->shape();
86 if (aShape.get() && !aShape->isNull()) {
87 if (aShape->shapeType() == GeomAPI_Shape::EDGE) {
88 const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
89 TopoDS_Edge aEdge = TopoDS::Edge(aTDShape);
90 Standard_Real aStart, aEnd;
91 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aStart, aEnd);
92 GeomAdaptor_Curve aAdaptor(aCurve);
93 theEdges[aAdaptor.GetType()] += 1;
102 std::shared_ptr<GeomAPI_Pln> sketcherPlane(ModuleBase_Operation* theOperation)
104 std::shared_ptr<GeomAPI_Pln> aEmptyPln;
106 ModuleBase_OperationFeature* aFeatureOp =
107 dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
109 CompositeFeaturePtr aFeature =
110 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeatureOp->feature());
111 if (aFeature && (aFeature->getKind() == SketchPlugin_Sketch::ID()))
112 return PartSet_Tools::sketchPlane(aFeature);
119 bool isEmptySelectionValid(ModuleBase_Operation* theOperation)
121 ModuleBase_OperationFeature* aFeatureOp =
122 dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
123 // during the create operation empty selection is always valid
124 if (!aFeatureOp->isEditOperation()) {
128 if (PartSet_SketcherMgr::isSketchOperation(aFeatureOp)) {
129 std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
136 // in edit operation an empty selection is always valid, performed for re-entrant operrations
141 bool PartSet_DistanceSelection::isValid(const ModuleBase_ISelection* theSelection,
142 ModuleBase_Operation* theOperation) const
144 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
145 return isEmptySelectionValid(theOperation);
147 int aNbPoints = shapesNbPoints(theSelection);
148 ShapeQuantity aShapes;
149 int aNbEdges = shapesNbEdges(theSelection, aShapes);
150 return (aNbPoints >= 0 && aNbPoints < 3) &&
151 (aShapes[GeomAbs_Line] == aNbEdges && aNbEdges >= 0 && aNbEdges < 2);
155 bool PartSet_LengthSelection::isValid(const ModuleBase_ISelection* theSelection,
156 ModuleBase_Operation* theOperation) const
158 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
159 return isEmptySelectionValid(theOperation);
161 int aNbPoints = shapesNbPoints(theSelection);
162 ShapeQuantity aShapes;
163 int aNbEdges = shapesNbEdges(theSelection, aShapes);
164 return aNbPoints == 0 && (aShapes[GeomAbs_Line] == aNbEdges && aNbEdges == 1);
168 bool PartSet_PerpendicularSelection::isValid(const ModuleBase_ISelection* theSelection,
169 ModuleBase_Operation* theOperation) const
171 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
172 return isEmptySelectionValid(theOperation);
174 int aNbPoints = shapesNbPoints(theSelection);
175 ShapeQuantity aShapes;
176 int aNbEdges = shapesNbEdges(theSelection, aShapes);
177 return aNbPoints == 0 && aShapes[GeomAbs_Line] == aNbEdges && aNbEdges > 0 && aNbEdges < 3;
181 bool PartSet_ParallelSelection::isValid(const ModuleBase_ISelection* theSelection,
182 ModuleBase_Operation* theOperation) const
184 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
185 return isEmptySelectionValid(theOperation);
187 int aNbPoints = shapesNbPoints(theSelection);
188 ShapeQuantity aShapes;
189 int aNbEdges = shapesNbEdges(theSelection, aShapes);
190 return aNbPoints == 0 && aShapes[GeomAbs_Line] == aNbEdges && aNbEdges > 0 && aNbEdges < 3;
194 bool PartSet_RadiusSelection::isValid(const ModuleBase_ISelection* theSelection,
195 ModuleBase_Operation* theOperation) const
197 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
198 return isEmptySelectionValid(theOperation);
200 int aNbPoints = shapesNbPoints(theSelection);
201 ShapeQuantity aShapes;
202 int aNbEdges = shapesNbEdges(theSelection, aShapes);
203 return aNbPoints == 0 && (aShapes[GeomAbs_Circle] == aNbEdges && aNbEdges == 1);
207 bool PartSet_RigidSelection::isValid(const ModuleBase_ISelection* theSelection,
208 ModuleBase_Operation* theOperation) const
210 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
211 return isEmptySelectionValid(theOperation);
213 QList<ModuleBase_ViewerPrsPtr> aList =
214 theSelection->getSelected(ModuleBase_ISelection::Viewer);
216 foreach (ModuleBase_ViewerPrsPtr aPrs, aList) {
217 ObjectPtr aObj = aPrs->object();
219 FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
220 if (aFeature.get()) {
221 CompositeFeaturePtr aComp = ModelAPI_Tools::compositeOwner(aFeature);
222 if (aComp.get() && (aComp->getKind() == SketchPlugin_Sketch::ID()))
227 return (aCount == 1);
232 bool PartSet_CoincidentSelection::isValid(const ModuleBase_ISelection* theSelection,
233 ModuleBase_Operation* theOperation) const
235 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
236 return isEmptySelectionValid(theOperation);
238 // Coincident can be applied to points and to lines
239 int aNbPoints = shapesNbPoints(theSelection);
240 ShapeQuantity aShapes;
241 int aNbEdges = shapesNbEdges(theSelection, aShapes);
242 return (aNbPoints >= 0 && aNbPoints < 3) && (aNbEdges >= 0 && aNbEdges < 2);
246 bool PartSet_HVDirSelection::isValid(const ModuleBase_ISelection* theSelection,
247 ModuleBase_Operation* theOperation) const
249 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
250 return isEmptySelectionValid(theOperation);
252 int aNbPoints = shapesNbPoints(theSelection);
253 ShapeQuantity aShapes;
254 int aNbEdges = shapesNbEdges(theSelection, aShapes);
255 return aNbPoints == 0 && (aShapes[GeomAbs_Line] == aNbEdges && aNbEdges == 1);
259 bool PartSet_FilletSelection::isValid(const ModuleBase_ISelection* theSelection,
260 ModuleBase_Operation* theOperation) const
262 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
263 return isEmptySelectionValid(theOperation);
265 int aCount = shapesNbPoints(theSelection);
266 ShapeQuantity aShapes;
267 int aNbEdges = shapesNbEdges(theSelection, aShapes);
268 return aCount > 1 && aNbEdges == 0;
272 bool PartSet_TangentSelection::isValid(const ModuleBase_ISelection* theSelection,
273 ModuleBase_Operation* theOperation) const
275 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
276 return isEmptySelectionValid(theOperation);
278 int aNbPoints = shapesNbPoints(theSelection);
279 ShapeQuantity aShapes;
280 int aNbEdges = shapesNbEdges(theSelection, aShapes);
281 return aNbPoints == 0 && (aNbEdges == 1 || (aNbEdges == 2 && aShapes[GeomAbs_Line] == 1));
285 bool PartSet_AngleSelection::isValid(const ModuleBase_ISelection* theSelection,
286 ModuleBase_Operation* theOperation) const
288 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
289 return isEmptySelectionValid(theOperation);
291 int aNbPoints = shapesNbPoints(theSelection);
292 ShapeQuantity aShapes;
293 int aNbEdges = shapesNbEdges(theSelection, aShapes);
294 return aNbPoints == 0 && aShapes[GeomAbs_Line] == aNbEdges && aNbEdges > 0 && aNbEdges < 3;
298 bool PartSet_EqualSelection::isValid(const ModuleBase_ISelection* theSelection,
299 ModuleBase_Operation* theOperation) const
301 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
302 return isEmptySelectionValid(theOperation);
304 int aNbPoints = shapesNbPoints(theSelection);
305 ShapeQuantity aShapes;
306 int aNbEdges = shapesNbEdges(theSelection, aShapes);
307 return aNbPoints == 0 && (aNbEdges > 0 && aNbEdges < 3) &&
308 (aShapes[GeomAbs_Line] == aNbEdges ||
309 aShapes[GeomAbs_Circle] == aNbEdges ||
310 aShapes[GeomAbs_Ellipse] == aNbEdges);
314 bool PartSet_CollinearSelection::isValid(const ModuleBase_ISelection* theSelection,
315 ModuleBase_Operation* theOperation) const
317 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
318 return isEmptySelectionValid(theOperation);
320 int aNbPoints = shapesNbPoints(theSelection);
321 ShapeQuantity aShapes;
322 int aNbEdges = shapesNbEdges(theSelection, aShapes);
323 return aNbPoints == 0 && aShapes[GeomAbs_Line] == aNbEdges && aNbEdges > 0 && aNbEdges < 3;
327 bool PartSet_MiddlePointSelection::isValid(const ModuleBase_ISelection* theSelection,
328 ModuleBase_Operation* theOperation) const
330 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0)
331 return isEmptySelectionValid(theOperation);
333 int aNbPoints = shapesNbPoints(theSelection);
334 ShapeQuantity aShapes;
335 int aNbEdges = shapesNbEdges(theSelection, aShapes);
336 return (aNbPoints >= 0 && aNbPoints < 3) && (aNbEdges >= 0 && aNbEdges < 2);
340 bool PartSet_MultyTranslationSelection::isValid(const ModuleBase_ISelection* theSelection,
341 ModuleBase_Operation* theOperation) const
343 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
344 return isEmptySelectionValid(theOperation);
346 ShapeQuantity aShapes;
347 int aNbEdges = shapesNbEdges(theSelection, aShapes);
352 bool PartSet_SplitSelection::isValid(const ModuleBase_ISelection* theSelection,
353 ModuleBase_Operation* theOperation) const
355 if (theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0) {
356 return isEmptySelectionValid(theOperation);
358 ShapeQuantity aShapes;
359 int aNbEdges = shapesNbEdges(theSelection, aShapes);
364 bool PartSet_ProjectionSelection::isValid(const ModuleBase_ISelection* theSelection,
365 ModuleBase_Operation* theOperation) const
367 return theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0 &&
368 isEmptySelectionValid(theOperation);
371 bool PartSet_IntersectionSelection::isValid(const ModuleBase_ISelection* theSelection,
372 ModuleBase_Operation* theOperation) const
374 return theSelection->getSelected(ModuleBase_ISelection::Viewer).size() == 0 &&
375 isEmptySelectionValid(theOperation);
379 std::string PartSet_DifferentObjectsValidator::errorMessage(
380 const PartSet_DifferentObjectsValidator::ErrorType& theType,
381 const std::string& thEqualObject, const std::string& theFirstAttribute,
382 const std::string& theSecondAttribute) const
387 anError = "The feature uses one " + thEqualObject + " object in " +
388 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
390 case EqualAttributes:
391 anError = "The feature uses reference to one " + thEqualObject + " attribute in " +
392 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
395 anError = "The feature uses one shape in " +
396 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
399 anError = "The feature uses empty shapes in " +
400 theFirstAttribute + " and " + theSecondAttribute + " attributes.";
409 bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute,
410 const std::list<std::string>& theArguments,
411 Events_InfoMessage& theError) const
413 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
415 // the type of validated attributes should be equal, attributes with
416 // different types are not validated
417 // Check RefAttr attributes
418 std::string anAttrType = theAttribute->attributeType();
419 std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
421 if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
422 AttributeRefAttrPtr anAttr =
423 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
424 bool isObject = anAttr->isObject();
425 ObjectPtr anObject = anAttr->object();
427 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
428 if (anAttrs.size() > 0) {
429 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttrs.begin();
430 for(; anAttrIter != anAttrs.end(); anAttrIter++) {
431 if ((*anAttrIter).get() && (*anAttrIter)->id() != theAttribute->id()) {
432 std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
433 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
434 if (aRef->isObject() != isObject)
437 if (aRef->object() == anObject) {
438 theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
439 theAttribute->id(), aRef->id());
443 else { // the attribute reference
444 AttributePtr anAttributeAttr = anAttr->attr();
445 if (aRef->attr() == anAttributeAttr) {
446 theError = errorMessage(EqualAttributes,
447 anAttributeAttr.get() ? anAttributeAttr->id() : "",
448 theAttribute->id(), aRef->id());
456 else if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
457 AttributeSelectionPtr anAttr =
458 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
459 ResultPtr aContext = anAttr->context();
460 FeaturePtr aContextFeature = anAttr->contextFeature();
461 GeomShapePtr aShape = anAttr->value();
463 // Check selection attributes
464 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
465 if (anAttrs.size() > 0) {
466 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
467 for(; anAttr != anAttrs.end(); anAttr++) {
468 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
469 std::shared_ptr<ModelAPI_AttributeSelection> aRef =
470 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*anAttr);
471 // check the object is already presented
472 if (aRef->context() == aContext) {
473 bool aHasShape = aShape.get() != NULL;
474 if (!aHasShape || aRef->value()->isEqual(aShape)) {
475 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
479 // check the whole selected feature contains the result
480 if (aContextFeature.get()) {
481 if (aRef->contextFeature().get()) {
482 if (aContextFeature == aRef->contextFeature()) {
483 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
486 } else if (aRef->context().get() &&
487 aRef->context()->document()->feature(aRef->context()) == aContextFeature) {
488 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
491 } else if (aRef->contextFeature().get() && aContext.get()) {
492 if (aContext->document()->feature(aContext) == aRef->contextFeature()) {
493 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRef->id());
501 else if (anAttrType == ModelAPI_AttributeReference::typeId()) {
502 AttributeReferencePtr anAttr =
503 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
504 ObjectPtr anObject = anAttr->value();
505 // Check selection attributes
506 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeReference::typeId());
507 if (anAttrs.size() > 0) {
508 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
509 for(; anAttr != anAttrs.end(); anAttr++) {
510 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
511 std::shared_ptr<ModelAPI_AttributeReference> aRef =
512 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*anAttr);
513 // check the object is already presented
514 if (aRef->value() == anObject) {
515 theError = errorMessage(EqualObjects, anObject.get() ? anObject->data()->name() : "",
516 theAttribute->id(), aRef->id());
524 else if(anAttrType == ModelAPI_AttributeSelectionList::typeId()) {
525 std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList =
526 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
527 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
528 if(anAttrs.size() > 0) {
529 std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
530 for(; anAttrItr != anAttrs.end(); anAttrItr++){
531 if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
532 std::shared_ptr<ModelAPI_AttributeSelectionList> aRefSelList =
533 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*anAttrItr);
534 for(int i = 0; i < aCurSelList->size(); i++) {
535 std::shared_ptr<ModelAPI_AttributeSelection> aCurSel = aCurSelList->value(i);
536 ResultPtr aCurSelContext = aCurSel->context();
537 FeaturePtr aCurSelFeature = aCurSel->contextFeature();
538 ResultBodyPtr aCurSelCompSolidPtr = ModelAPI_Tools::bodyOwner(aCurSelContext);
539 std::shared_ptr<GeomAPI_Shape> aCurSelCompSolid;
540 if(aCurSelCompSolidPtr.get()) {
541 aCurSelCompSolid = aCurSelCompSolidPtr->shape();
543 for(int j = 0; j < aRefSelList->size(); j++) {
544 std::shared_ptr<ModelAPI_AttributeSelection> aRefSel = aRefSelList->value(j);
545 ResultPtr aRefSelContext = aRefSel->context();
546 FeaturePtr aRefSelFeature = aRefSel->contextFeature();
547 ResultBodyPtr aRefSelCompSolidPtr =
548 ModelAPI_Tools::bodyOwner(aRefSelContext);
549 std::shared_ptr<GeomAPI_Shape> aRefSelCompSolid;
550 if (aRefSelCompSolidPtr.get()) {
551 aRefSelCompSolid = aRefSelCompSolidPtr->shape();
553 if ((aCurSelCompSolid.get() && aCurSelCompSolid->isEqual(aRefSel->value()))
554 || (aRefSelCompSolid.get() && aRefSelCompSolid->isEqual(aCurSel->value()))) {
555 theError = errorMessage(EqualShapes, "", theAttribute->id(),
559 if (aCurSelContext == aRefSelContext) {
560 if (aCurSel->value().get() == NULL || aRefSel->value().get() == NULL) {
561 theError = errorMessage(EmptyShapes, "", theAttribute->id(), aRefSel->id());
564 if (aCurSel->value()->isEqual(aRefSel->value())) {
565 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
570 // check the whole selected feature contains the result
571 if (aCurSelFeature.get()) {
572 if (aRefSelFeature.get()) {
573 if (aCurSelFeature == aRefSelFeature) {
574 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
578 else if (aRefSelContext.get() &&
579 aRefSelContext->document()->feature(aRefSelContext) == aCurSelFeature) {
580 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
584 else if (aRefSelFeature.get() && aCurSelContext.get()) {
585 if (aCurSelContext->document()->feature(aCurSelContext) == aRefSelFeature) {
586 theError = errorMessage(EqualShapes, "", theAttribute->id(), aRefSel->id());
596 else if (anAttrType == ModelAPI_AttributeRefList::typeId()) {
597 std::shared_ptr<ModelAPI_AttributeRefList> aCurSelList =
598 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
599 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefList::typeId());
600 if (anAttrs.size() > 0) {
601 std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
602 for (; anAttrItr != anAttrs.end(); anAttrItr++){
603 if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
604 std::shared_ptr<ModelAPI_AttributeRefList> aRefSelList =
605 std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrItr);
606 for (int i = 0; i < aCurSelList->size(); i++) {
607 ObjectPtr aCurSelObject = aCurSelList->object(i);
608 for (int j = 0; j < aRefSelList->size(); j++) {
609 if (aCurSelObject == aRefSelList->object(j)) {
610 theError = errorMessage(EqualObjects,
611 aCurSelObject.get() ? aCurSelObject->data()->name() : "",
612 theAttribute->id(), aCurSelList->id());
624 bool PartSet_DifferentPointsValidator::isValid(const AttributePtr& theAttribute,
625 const std::list<std::string>& theArguments,
626 Events_InfoMessage& theError) const
628 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
630 // the type of validated attributes should be equal, attributes with
631 // different types are not validated
632 // Check RefAttr attributes
633 std::string anAttrType = theAttribute->attributeType();
634 std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
635 if (anAttrType != ModelAPI_AttributeRefAttr::typeId())
638 // obtain point of the given attribute
639 AttributePoint2DPtr anAttributePoint = getRefPointAttribute(theAttribute);
640 if (!anAttributePoint.get() || !anAttributePoint->isInitialized())
643 // obtain point of the parameter attribute
644 AttributePoint2DPtr anArgumentPoint = getRefPointAttribute
645 (aFeature->attribute(theArguments.front()));
647 if (!anArgumentPoint.get() || !anArgumentPoint->isInitialized())
650 return !anAttributePoint->pnt()->isEqual(anArgumentPoint->pnt());
653 AttributePoint2DPtr PartSet_DifferentPointsValidator::getRefPointAttribute
654 (const AttributePtr& theAttribute) const
656 AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
658 AttributePoint2DPtr aPointAttribute;
659 if (anAttr->isObject()) {
660 ObjectPtr anObject = anAttr->object();
661 if (anObject.get()) {
662 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
663 if (aFeature->getKind() == SketchPlugin_Point::ID())
664 aPointAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>
665 (aFeature->attribute(SketchPlugin_Point::COORD_ID()));
669 aPointAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
671 return aPointAttribute;
674 bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute,
675 const std::list<std::string>& theArguments,
676 Events_InfoMessage& theError) const
678 if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
679 theError = "The attribute with the %1 type is not processed";
680 theError.arg(theAttribute->attributeType());
684 // there is a check whether the feature contains a point and a linear edge or two point values
685 std::string aParamA = theArguments.front();
686 SessionPtr aMgr = ModelAPI_Session::get();
687 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
689 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
690 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
691 QList<FeaturePtr> aCoinsideLines;
692 QList<FeaturePtr> aCoins;
694 bool isObject = aRefAttr->isObject();
695 ObjectPtr anObject = aRefAttr->object();
696 if (isObject && anObject) {
697 FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
698 AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA);
699 ObjectPtr aOtherObject = aOtherAttr->object();
700 // if the other attribute is not filled still, the result is true
701 if (!aOtherObject.get())
703 FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
705 // check that both have coincidence
706 FeaturePtr aConstrFeature;
707 std::set<FeaturePtr> aCoinList;
708 const std::set<std::shared_ptr<ModelAPI_Attribute>>& aRefsList = aRefFea->data()->refsToMe();
709 std::set<std::shared_ptr<ModelAPI_Attribute>>::const_iterator aIt;
710 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
711 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
712 aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
713 if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
714 AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
715 AttributePtr aAR = aRAttr->attr();
716 if (aAR->id() != SketchPlugin_Arc::CENTER_ID()) // ignore constraint to center of arc
717 aCoinList.insert(aConstrFeature);
718 QList<bool> anIsAttributes;
719 PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, aCoins,
720 SketchPlugin_ConstraintCoincidence::ENTITY_A(),
722 PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines, aCoins,
723 SketchPlugin_ConstraintCoincidence::ENTITY_B(),
727 // if there is no coincidence then it is not valid
728 if (aCoinList.size() > 0) {
729 QList<FeaturePtr>::const_iterator anIt = aCoinsideLines.begin(), aLast = aCoinsideLines.end();
731 for (; anIt != aLast && !aValid; anIt++) {
732 aValid = *anIt == aOtherFea;
738 theError = "There is no a common coincident point.";