]> SALOME platform Git repositories - modules/shaper.git/blob - src/PartSet/PartSet_Validators.cpp
Salome HOME
Issue #741 fillet is wrong
[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();  
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();
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();
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();  
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();
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
186 bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute, 
187                                                 const std::list<std::string>& theArguments) const
188 {
189   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
190
191   // the type of validated attributes should be equal, attributes with different types are not validated
192   // Check RefAttr attributes
193   std::string anAttrType = theAttribute->attributeType();
194   std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
195
196   if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
197     AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
198     bool isObject = anAttr->isObject();
199     ObjectPtr anObject = anAttr->object();
200     AttributePtr anAttributeAttr = anAttr->attr();
201
202     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
203     if (anAttrs.size() > 0) {
204       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
205       for(; anAttr != anAttrs.end(); anAttr++) {
206       if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
207           std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
208                                       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttr);
209           if (aRef->isObject() != isObject)
210             continue;
211           if (isObject) {
212             if (aRef->object() == anObject)
213               return false;
214           }
215           else { // the attribute reference
216             if (aRef->attr() == theAttribute)
217               return false;
218           }
219         }
220       }
221     }
222   }
223   else if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
224     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
225     ResultPtr aContext = anAttr->context();
226     GeomShapePtr aShape = anAttr->value();
227
228     // Check selection attributes
229     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
230     if (anAttrs.size() > 0) {
231       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
232       for(; anAttr != anAttrs.end(); anAttr++) {
233         if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
234           std::shared_ptr<ModelAPI_AttributeSelection> aRef =
235                                         std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*anAttr);
236           // check the object is already presented
237           if (aRef->context() == aContext) {
238             bool aHasShape = aShape.get() != NULL;
239             if (!aHasShape || aRef->value()->isEqual(aShape))
240               return false;
241           }
242         }
243       }
244     }
245   }
246   else if (anAttrType == ModelAPI_AttributeReference::typeId()) {
247     AttributeReferencePtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
248     ObjectPtr anObject = anAttr->value();
249     // Check selection attributes
250     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeReference::typeId());
251     if (anAttrs.size() > 0) {
252       std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
253       for(; anAttr != anAttrs.end(); anAttr++) {
254         if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
255           std::shared_ptr<ModelAPI_AttributeReference> aRef =
256             std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*anAttr);
257           // check the object is already presented
258           if (aRef->value() == anObject)
259             return false;
260         }
261         return true;
262       }
263     }
264   }
265   else if(anAttrType == ModelAPI_AttributeSelectionList::typeId()) {
266     std::shared_ptr<ModelAPI_AttributeSelectionList> aCurSelList = 
267             std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
268     anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelectionList::typeId());
269     if(anAttrs.size() > 0) {
270       std::list<std::shared_ptr<ModelAPI_Attribute>>::iterator anAttrItr = anAttrs.begin();
271       for(; anAttrItr != anAttrs.end(); anAttrItr++){
272         if ((*anAttrItr).get() && (*anAttrItr)->id() != theAttribute->id()){
273           std::shared_ptr<ModelAPI_AttributeSelectionList> aRefSelList = 
274             std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*anAttrItr);
275           for(int i = 0; i < aCurSelList->size(); i++) {
276             std::shared_ptr<ModelAPI_AttributeSelection> aCurSel = aCurSelList->value(i);
277             for(int j = 0; j < aRefSelList->size(); j++) {
278               std::shared_ptr<ModelAPI_AttributeSelection> aRefSel = aRefSelList->value(j);
279               if(aCurSel->context() == aRefSel->context()) {
280                 if(aCurSel->value().get() == NULL || aRefSel->value().get() == NULL
281                   || aCurSel->value()->isEqual(aRefSel->value())) {
282                     return false;
283                 }
284               }
285             }
286           }
287         }
288       }
289     }
290   }
291   return !featureHasReferences(theAttribute);
292 }
293
294 bool PartSet_DifferentObjectsValidator::featureHasReferences(const AttributePtr& theAttribute) const
295 {
296   std::list<std::pair<std::string, std::list<ObjectPtr> > > allRefs;
297   if (theAttribute->owner().get() && theAttribute->owner()->data()->isValid())
298     theAttribute->owner()->data()->referencesToObjects(allRefs);
299   // collect object referenced by theAttribute
300   std::list<ObjectPtr>* anAttrObjs = 0;
301   std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRefIter = allRefs.begin();
302   for(; aRefIter != allRefs.end(); aRefIter++) {
303     if (theAttribute->id() == aRefIter->first)
304       anAttrObjs = &(aRefIter->second);
305   }
306   if (!anAttrObjs || anAttrObjs->empty())
307     return false; // theAttribute does not references to anything
308   // check with all others
309   for(aRefIter = allRefs.begin(); aRefIter != allRefs.end(); aRefIter++) {
310     if (theAttribute->id() == aRefIter->first)
311       continue; // do not check with myself
312     std::list<ObjectPtr>::iterator aReferenced = aRefIter->second.begin();
313     for(; aReferenced != aRefIter->second.end(); aReferenced++) {
314       std::list<ObjectPtr>::iterator aReferencedByMe = anAttrObjs->begin();
315       for(; aReferencedByMe != anAttrObjs->end(); aReferencedByMe++) {
316         if (*aReferenced == *aReferencedByMe) // found same objects!
317           return true;
318       }
319     }
320   }
321   return false;
322 }
323
324 bool PartSet_SketchEntityValidator::isValid(const AttributePtr& theAttribute,
325                                             const std::list<std::string>& theArguments) const
326 {
327   bool isSketchEntities = true;
328   std::set<std::string> anEntityKinds;
329   std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
330   for (; anIt != aLast; anIt++) {
331     anEntityKinds.insert(*anIt);
332   }
333
334   std::string anAttributeType = theAttribute->attributeType();
335   if (anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
336     AttributeSelectionListPtr aSelectionListAttr = 
337                       std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
338     // it filters only selection list attributes
339     std::string aType = aSelectionListAttr->selectionType().c_str();
340     // all context objects should be sketch entities
341     int aSize = aSelectionListAttr->size();
342     for (int i = 0; i < aSelectionListAttr->size() && isSketchEntities; i++) {
343       AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i);
344       ObjectPtr anObject = aSelectAttr->context();
345       // a context of the selection attribute is a feature result. It can be a case when the result
346       // of the feature is null, e.g. the feature is modified and has not been executed yet.
347       // The validator returns an invalid result here. The case is an extrusion built on a sketch
348       // feature. A new sketch element creation leads to an empty result.
349       if (!anObject.get())
350         isSketchEntities = false;
351       else {
352         FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
353         isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
354       }
355     }
356   }
357   if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) {
358     std::shared_ptr<ModelAPI_AttributeRefAttr> aRef = 
359                      std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
360     isSketchEntities = false;
361     if (aRef->isObject()) {
362       ObjectPtr anObject = aRef->object();
363       if (anObject.get() != NULL) {
364         FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
365         if (aFeature.get() != NULL)
366           isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
367       }
368     }
369   }
370
371   return isSketchEntities;
372 }
373
374
375
376 bool PartSet_SameTypeAttrValidator::isValid(
377   const AttributePtr& theAttribute, const std::list<std::string>& theArguments ) const
378 {
379   // there is a check whether the feature contains a point and a linear edge or two point values
380   std::string aParamA = theArguments.front();
381   SessionPtr aMgr = ModelAPI_Session::get();
382   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
383
384   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
385   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
386   if (!aRefAttr)
387     return false;
388
389   bool isObject = aRefAttr->isObject();
390   ObjectPtr anObject = aRefAttr->object();
391   if (isObject && anObject) {
392     FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
393
394     AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA);
395     ObjectPtr aOtherObject = aOtherAttr->object();
396     FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
397     return aRefFea->getKind() == aOtherFea->getKind();
398   }
399   return false;
400 }
401
402 bool PartSet_CoincidentAttr::isValid(
403   const AttributePtr& theAttribute, const std::list<std::string>& theArguments ) const
404 {
405   // there is a check whether the feature contains a point and a linear edge or two point values
406   std::string aParamA = theArguments.front();
407   SessionPtr aMgr = ModelAPI_Session::get();
408   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
409
410   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
411   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
412   if (!aRefAttr)
413     return false;
414
415   QList<FeaturePtr> aCoinsideLines;
416
417   bool isObject = aRefAttr->isObject();
418   ObjectPtr anObject = aRefAttr->object();
419   if (isObject && anObject) {
420     FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
421     AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA);
422     ObjectPtr aOtherObject = aOtherAttr->object();
423     // if the other attribute is not filled still, the result is true
424     if (!aOtherObject.get())
425       return true;
426     FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
427
428     // check that both have coincidence
429     FeaturePtr aConstrFeature;
430     std::set<FeaturePtr> aCoinList;
431     const std::set<std::shared_ptr<ModelAPI_Attribute>>& aRefsList = aRefFea->data()->refsToMe();
432     std::set<std::shared_ptr<ModelAPI_Attribute>>::const_iterator aIt;
433     for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
434       std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
435       aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
436       if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
437         AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aAttr);
438         AttributePtr aAR = aRAttr->attr();
439         if (aAR->id() != SketchPlugin_Arc::CENTER_ID()) // ignore constraint to center of arc
440           aCoinList.insert(aConstrFeature);
441           PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines,
442                                           SketchPlugin_ConstraintCoincidence::ENTITY_A());
443           PartSet_Tools::findCoincidences(aConstrFeature, aCoinsideLines,
444                                           SketchPlugin_ConstraintCoincidence::ENTITY_B());
445       }
446     }
447     // if there is no coincidence then it is not valid
448     if (aCoinList.size() == 0)
449       return false;
450
451     QList<FeaturePtr>::const_iterator anIt = aCoinsideLines.begin(), aLast = aCoinsideLines.end();
452     bool aValid = false;
453     for (; anIt != aLast && !aValid; anIt++) {
454       aValid = *anIt == aOtherFea;
455     }
456     if (aValid)
457       return true;
458   }
459   return false;
460 }
461