]> SALOME platform Git repositories - modules/shaper.git/blob - src/PartSet/PartSet_Validators.cpp
Salome HOME
Implementation of the Angle constraint (issue #788)
[modules/shaper.git] / src / PartSet / PartSet_Validators.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        PartSet_Validators.cpp
4 // Created:     09 July 2014
5 // Author:      Vitaly SMETANNIKOV
6
7 #include "PartSet_Validators.h"
8
9 #include "PartSet_Tools.h"
10
11 #include <TopoDS.hxx>
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
20 #include <ModelAPI_AttributeRefAttr.h>
21 #include <ModelAPI_AttributeSelection.h>
22 #include <ModelAPI_AttributeReference.h>
23 #include <ModelAPI_AttributeSelectionList.h>
24 #include <ModelAPI_Object.h>
25 #include <ModelAPI_Session.h>
26
27 #include <SketchPlugin_Sketch.h>
28 #include <SketchPlugin_ConstraintCoincidence.h>
29 #include <SketchPlugin_Arc.h>
30 #include <GeomAPI_Edge.h>
31
32 #include <list>
33 #ifdef _DEBUG
34 #include <iostream>
35 #endif
36
37 int shapesNbPoints(const ModuleBase_ISelection* theSelection)
38 {
39   QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
40   int aCount = 0;
41   foreach (ModuleBase_ViewerPrs aPrs, aList) {
42     const TopoDS_Shape& aShape = aPrs.shape();
43     if (!aShape.IsNull()) {
44       if (aShape.ShapeType() == TopAbs_VERTEX)
45         aCount++;
46     }
47   }
48   return aCount;
49 }
50
51 int shapesNbLines(const ModuleBase_ISelection* theSelection)
52 {
53   QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
54   int aCount = 0;
55   foreach(ModuleBase_ViewerPrs aPrs, aList) {
56     const TopoDS_Shape& aShape = aPrs.shape();
57     if (!aShape.IsNull()) {
58       if (aShape.ShapeType() == TopAbs_EDGE) {
59         TopoDS_Edge aEdge = TopoDS::Edge(aShape);
60         Standard_Real aStart, aEnd;
61         Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aStart, aEnd);
62         GeomAdaptor_Curve aAdaptor(aCurve);
63         if (aAdaptor.GetType() == GeomAbs_Line)
64           aCount++;
65       }
66     }
67   }
68   return aCount;
69 }
70
71 bool PartSet_DistanceSelection::isValid(const ModuleBase_ISelection* theSelection) const
72 {
73   int aCount = shapesNbPoints(theSelection) + shapesNbLines(theSelection);
74   return (aCount > 0) && (aCount < 3);
75 }
76
77 bool PartSet_LengthSelection::isValid(const ModuleBase_ISelection* theSelection) const
78 {
79   int aCount = shapesNbLines(theSelection);
80   return (aCount == 1);
81 }
82
83 bool PartSet_PerpendicularSelection::isValid(const ModuleBase_ISelection* theSelection) const
84 {
85   int aCount = shapesNbLines(theSelection);
86   return (aCount > 0) && (aCount < 3);
87 }
88
89 bool PartSet_ParallelSelection::isValid(const ModuleBase_ISelection* theSelection) const
90 {
91   int aCount = shapesNbLines(theSelection);
92   return (aCount > 0) && (aCount < 3);
93 }
94
95 bool PartSet_RadiusSelection::isValid(const ModuleBase_ISelection* theSelection) const
96 {
97   QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
98   ModuleBase_ViewerPrs aPrs;
99   int aCount = 0;
100   foreach (ModuleBase_ViewerPrs aPrs, aList) {
101     const TopoDS_Shape& aShape = aPrs.shape();
102     if (!aShape.IsNull()) {
103       if (aShape.ShapeType() == TopAbs_EDGE) {
104         TopoDS_Edge aEdge = TopoDS::Edge(aShape);
105         Standard_Real aStart, aEnd;
106         Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aStart, aEnd);
107         GeomAdaptor_Curve aAdaptor(aCurve);
108         if (aAdaptor.GetType() == GeomAbs_Circle)
109           aCount++;
110       }
111     }
112   }
113   return (aCount == 1);
114 }
115
116 bool PartSet_RigidSelection::isValid(const ModuleBase_ISelection* theSelection) const
117 {
118   QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
119   return (aList.count() == 1);
120 }
121
122
123 bool PartSet_CoincidentSelection::isValid(const ModuleBase_ISelection* theSelection) const
124 {
125   int aCount = shapesNbPoints(theSelection);
126   return (aCount > 0) && (aCount < 3);
127 }
128
129 bool PartSet_HVDirSelection::isValid(const ModuleBase_ISelection* theSelection) const
130 {
131   int aCount = shapesNbLines(theSelection);
132   return (aCount == 1);
133 }
134
135 bool PartSet_FilletSelection::isValid(const ModuleBase_ISelection* theSelection) const
136 {
137   int aCount = shapesNbLines(theSelection);
138   return (aCount > 0) && (aCount < 3);
139 }
140
141 bool PartSet_TangentSelection::isValid(const ModuleBase_ISelection* theSelection) const
142 {
143   QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected(ModuleBase_ISelection::Viewer);
144   if ((aList.size() == 0) || (aList.size() > 2))
145     return false;
146
147   ModuleBase_ViewerPrs aPrs = aList.first();
148   const TopoDS_Shape& aShape = aPrs.shape();
149   if (aShape.IsNull())
150     return false;
151
152   if (aShape.ShapeType() != TopAbs_EDGE)
153     return false;
154
155   std::shared_ptr<GeomAPI_Shape> aShapePtr(new GeomAPI_Shape);
156   aShapePtr->setImpl(new TopoDS_Shape(aShape));
157   GeomAPI_Edge aEdge1(aShapePtr);
158
159   if (aEdge1.isLine() || aEdge1.isArc()) {
160     if (aList.size() == 2) {
161       // Check second selection
162       aPrs = aList.last();
163       const TopoDS_Shape& aShape2 = aPrs.shape();
164       if (aShape2.IsNull())
165         return false;
166
167       if (aShape2.ShapeType() != TopAbs_EDGE)
168         return false;
169
170       std::shared_ptr<GeomAPI_Shape> aShapePtr2(new GeomAPI_Shape);
171       aShapePtr2->setImpl(new TopoDS_Shape(aShape2));
172       GeomAPI_Edge aEdge2(aShapePtr2);
173       if (aEdge1.isLine() && aEdge2.isArc())
174         return true;
175       else if (aEdge1.isArc() && aEdge2.isLine())
176         return true;
177       else
178         return false;
179     } else
180       return true;
181   }
182   return false;
183 }
184
185 bool PartSet_AngleSelection::isValid(const ModuleBase_ISelection* theSelection) const
186 {
187   int aCount = shapesNbLines(theSelection);
188   return (aCount > 0) && (aCount < 3);
189 }
190
191
192 bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute, 
193                                                 const std::list<std::string>& theArguments,
194                                                 std::string& theError) const
195 {
196   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
197
198   // the type of validated attributes should be equal, attributes with different types are not validated
199   // Check RefAttr attributes
200   std::string anAttrType = theAttribute->attributeType();
201   std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
202
203   if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
204     AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
205     bool isObject = anAttr->isObject();
206     ObjectPtr anObject = anAttr->object();
207     AttributePtr anAttributeAttr = anAttr->attr();
208
209     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
210     if (anAttrs.size() > 0) {
211       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
212       for(; anAttr != anAttrs.end(); anAttr++) {
213       if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
214           std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
215                                       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttr);
216           if (aRef->isObject() != isObject)
217             continue;
218           if (isObject) {
219             if (aRef->object() == anObject)
220               return false;
221           }
222           else { // the attribute reference
223             if (aRef->attr() == theAttribute)
224               return false;
225           }
226         }
227       }
228     }
229   }
230   else if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
231     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
232     ResultPtr aContext = anAttr->context();
233     GeomShapePtr aShape = anAttr->value();
234
235     // Check selection attributes
236     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
237     if (anAttrs.size() > 0) {
238       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
239       for(; anAttr != anAttrs.end(); anAttr++) {
240         if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
241           std::shared_ptr<ModelAPI_AttributeSelection> aRef =
242                                         std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*anAttr);
243           // check the object is already presented
244           if (aRef->context() == aContext) {
245             bool aHasShape = aShape.get() != NULL;
246             if (!aHasShape || aRef->value()->isEqual(aShape))
247               return false;
248           }
249         }
250       }
251     }
252   }
253   else if (anAttrType == ModelAPI_AttributeReference::typeId()) {
254     AttributeReferencePtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
255     ObjectPtr anObject = anAttr->value();
256     // Check selection attributes
257     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeReference::typeId());
258     if (anAttrs.size() > 0) {
259       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
260       for(; anAttr != anAttrs.end(); anAttr++) {
261         if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
262           std::shared_ptr<ModelAPI_AttributeReference> aRef =
263             std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*anAttr);
264           // check the object is already presented
265           if (aRef->value() == anObject)
266             return false;
267         }
268         return true;
269       }
270     }
271   }
272   else if(anAttrType == ModelAPI_AttributeSelectionList::typeId()) {
273     std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList = 
274             std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
275     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
276     if(anAttrs.size() > 0) {
277       std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
278       for(; anAttrItr != anAttrs.end(); anAttrItr++){
279         if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
280           std::shared_ptr<ModelAPI_AttributeSelectionList> aRefSelList = 
281             std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*anAttrItr);
282           for(int i = 0; i < aCurSelList->size(); i++) {
283             std::shared_ptr<ModelAPI_AttributeSelection> aCurSel = aCurSelList->value(i);
284             for(int j = 0; j < aRefSelList->size(); j++) {
285               std::shared_ptr<ModelAPI_AttributeSelection> aRefSel = aRefSelList->value(j);
286               if(aCurSel->context() == aRefSel->context()) {
287                 if(aCurSel->value().get() == NULL || aRefSel->value().get() == NULL
288                   || aCurSel->value()->isEqual(aRefSel->value())) {
289                     return false;
290                 }
291               }
292             }
293           }
294         }
295       }
296     }
297   }
298   return !featureHasReferences(theAttribute);
299 }
300
301 bool PartSet_DifferentObjectsValidator::featureHasReferences(const AttributePtr& theAttribute) const
302 {
303   std::list<std::pair<std::string, std::list<ObjectPtr> > > allRefs;
304   if (theAttribute->owner().get() && theAttribute->owner()->data()->isValid())
305     theAttribute->owner()->data()->referencesToObjects(allRefs);
306   // collect object referenced by theAttribute
307   std::list<ObjectPtr>* anAttrObjs = 0;
308   std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRefIter = allRefs.begin();
309   for(; aRefIter != allRefs.end(); aRefIter++) {
310     if (theAttribute->id() == aRefIter->first)
311       anAttrObjs = &(aRefIter->second);
312   }
313   if (!anAttrObjs || anAttrObjs->empty())
314     return false; // theAttribute does not references to anything
315   // check with all others
316   for(aRefIter = allRefs.begin(); aRefIter != allRefs.end(); aRefIter++) {
317     if (theAttribute->id() == aRefIter->first)
318       continue; // do not check with myself
319     std::list<ObjectPtr>::iterator aReferenced = aRefIter->second.begin();
320     for(; aReferenced != aRefIter->second.end(); aReferenced++) {
321       std::list<ObjectPtr>::iterator aReferencedByMe = anAttrObjs->begin();
322       for(; aReferencedByMe != anAttrObjs->end(); aReferencedByMe++) {
323         if (*aReferenced == *aReferencedByMe) // found same objects!
324           return true;
325       }
326     }
327   }
328   return false;
329 }
330
331 bool PartSet_SketchEntityValidator::isValid(const AttributePtr& theAttribute,
332                                             const std::list<std::string>& theArguments,
333                                             std::string& theError) const
334 {
335   bool isSketchEntities = true;
336   std::set<std::string> anEntityKinds;
337   std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
338   for (; anIt != aLast; anIt++) {
339     anEntityKinds.insert(*anIt);
340   }
341
342   std::string anAttributeType = theAttribute->attributeType();
343   if (anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
344     AttributeSelectionListPtr aSelectionListAttr = 
345                       std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
346     // it filters only selection list attributes
347     std::string aType = aSelectionListAttr->selectionType().c_str();
348     // all context objects should be sketch entities
349     int aSize = aSelectionListAttr->size();
350     for (int i = 0; i < aSelectionListAttr->size() && isSketchEntities; i++) {
351       AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i);
352       ObjectPtr anObject = aSelectAttr->context();
353       // a context of the selection attribute is a feature result. It can be a case when the result
354       // of the feature is null, e.g. the feature is modified and has not been executed yet.
355       // The validator returns an invalid result here. The case is an extrusion built on a sketch
356       // feature. A new sketch element creation leads to an empty result.
357       if (!anObject.get())
358         isSketchEntities = false;
359       else {
360         FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
361         isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
362       }
363     }
364   }
365   if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) {
366     std::shared_ptr<ModelAPI_AttributeRefAttr> aRef = 
367                      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
368     isSketchEntities = false;
369     if (aRef->isObject()) {
370       ObjectPtr anObject = aRef->object();
371       if (anObject.get() != NULL) {
372         FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
373         if (aFeature.get() != NULL)
374           isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
375       }
376     }
377   }
378
379   return isSketchEntities;
380 }
381
382
383
384 bool PartSet_SameTypeAttrValidator::isValid(const AttributePtr& theAttribute, 
385                                             const std::list<std::string>& theArguments,
386                                             std::string& theError ) const
387 {
388   // there is a check whether the feature contains a point and a linear edge or two point values
389   std::string aParamA = theArguments.front();
390   SessionPtr aMgr = ModelAPI_Session::get();
391   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
392
393   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
394   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
395   if (!aRefAttr)
396     return false;
397
398   bool isObject = aRefAttr->isObject();
399   ObjectPtr anObject = aRefAttr->object();
400   if (isObject && anObject) {
401     FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
402
403     AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA);
404     ObjectPtr aOtherObject = aOtherAttr->object();
405     FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
406     return aRefFea->getKind() == aOtherFea->getKind();
407   }
408   return false;
409 }
410
411 bool PartSet_CoincidentAttr::isValid(const AttributePtr& theAttribute, 
412                                      const std::list<std::string>& theArguments,
413                                      std::string& theError) const
414 {
415   // there is a check whether the feature contains a point and a linear edge or two point values
416   std::string aParamA = theArguments.front();
417   SessionPtr aMgr = ModelAPI_Session::get();
418   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
419
420   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
421   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
422   if (!aRefAttr)
423     return false;
424
425   QList<FeaturePtr> aCoinsideLines;
426
427   bool isObject = aRefAttr->isObject();
428   ObjectPtr anObject = aRefAttr->object();
429   if (isObject && anObject) {
430     FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
431     AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA);
432     ObjectPtr aOtherObject = aOtherAttr->object();
433     // if the other attribute is not filled still, the result is true
434     if (!aOtherObject.get())
435       return true;
436     FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
437
438     // check that both have coincidence
439     FeaturePtr aConstrFeature;
440     std::set<FeaturePtr> aCoinList;
441     const std::set<std::shared_ptr<ModelAPI_Attribute>>& aRefsList = aRefFea->data()->refsToMe();
442     std::set<std::shared_ptr<ModelAPI_Attribute>>::const_iterator aIt;
443     for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
444       std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
445       aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
446       if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
447         AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
448         AttributePtr aAR = aRAttr->attr();
449         if (aAR->id() != SketchPlugin_Arc::CENTER_ID()) // ignore constraint to center of arc
450           aCoinList.insert(aConstrFeature);
451           PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines,
452                                           SketchPlugin_ConstraintCoincidence::ENTITY_A());
453           PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines,
454                                           SketchPlugin_ConstraintCoincidence::ENTITY_B());
455       }
456     }
457     // if there is no coincidence then it is not valid
458     if (aCoinList.size() == 0)
459       return false;
460
461     QList<FeaturePtr>::const_iterator anIt = aCoinsideLines.begin(), aLast = aCoinsideLines.end();
462     bool aValid = false;
463     for (; anIt != aLast && !aValid; anIt++) {
464       aValid = *anIt == aOtherFea;
465     }
466     if (aValid)
467       return true;
468   }
469   return false;
470 }
471