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"
10 #include <TopoDS_Edge.hxx>
11 #include <BRep_Tool.hxx>
12 #include <GeomAdaptor_Curve.hxx>
13 #include <GeomAbs_CurveType.hxx>
14 #include <GeomValidators_Tools.h>
15 #include <ModuleBase_ISelection.h>
16 #include <ModuleBase_WidgetShapeSelector.h>
18 #include <ModelAPI_AttributeRefAttr.h>
19 #include <ModelAPI_AttributeSelection.h>
20 #include <ModelAPI_AttributeReference.h>
21 #include <ModelAPI_AttributeSelectionList.h>
22 #include <ModelAPI_Object.h>
23 #include <ModelAPI_Session.h>
25 #include <SketchPlugin_Sketch.h>
32 int shapesNbPoints(const ModuleBase_ISelection* theSelection)
34 QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected();
36 foreach (ModuleBase_ViewerPrs aPrs, aList) {
37 const TopoDS_Shape& aShape = aPrs.shape();
38 if (!aShape.IsNull()) {
39 if (aShape.ShapeType() == TopAbs_VERTEX)
46 int shapesNbLines(const ModuleBase_ISelection* theSelection)
48 QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected();
50 foreach(ModuleBase_ViewerPrs aPrs, aList) {
51 const TopoDS_Shape& aShape = aPrs.shape();
52 if (!aShape.IsNull()) {
53 if (aShape.ShapeType() == TopAbs_EDGE) {
54 TopoDS_Edge aEdge = TopoDS::Edge(aShape);
55 Standard_Real aStart, aEnd;
56 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aStart, aEnd);
57 GeomAdaptor_Curve aAdaptor(aCurve);
58 if (aAdaptor.GetType() == GeomAbs_Line)
66 bool PartSet_DistanceSelection::isValid(const ModuleBase_ISelection* theSelection) const
68 int aCount = shapesNbPoints(theSelection) + shapesNbLines(theSelection);
69 return (aCount > 0) && (aCount < 3);
72 bool PartSet_LengthSelection::isValid(const ModuleBase_ISelection* theSelection) const
74 int aCount = shapesNbLines(theSelection);
78 bool PartSet_PerpendicularSelection::isValid(const ModuleBase_ISelection* theSelection) const
80 int aCount = shapesNbLines(theSelection);
81 return (aCount > 0) && (aCount < 3);
84 bool PartSet_ParallelSelection::isValid(const ModuleBase_ISelection* theSelection) const
86 int aCount = shapesNbLines(theSelection);
87 return (aCount > 0) && (aCount < 3);
90 bool PartSet_RadiusSelection::isValid(const ModuleBase_ISelection* theSelection) const
92 QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected();
93 ModuleBase_ViewerPrs aPrs;
95 foreach (ModuleBase_ViewerPrs aPrs, aList) {
96 const TopoDS_Shape& aShape = aPrs.shape();
97 if (!aShape.IsNull()) {
98 if (aShape.ShapeType() == TopAbs_EDGE) {
99 TopoDS_Edge aEdge = TopoDS::Edge(aShape);
100 Standard_Real aStart, aEnd;
101 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge, aStart, aEnd);
102 GeomAdaptor_Curve aAdaptor(aCurve);
103 if (aAdaptor.GetType() == GeomAbs_Circle)
108 return (aCount == 1);
111 bool PartSet_RigidSelection::isValid(const ModuleBase_ISelection* theSelection) const
113 QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected();
114 return (aList.count() == 1);
118 bool PartSet_CoincidentSelection::isValid(const ModuleBase_ISelection* theSelection) const
120 int aCount = shapesNbPoints(theSelection);
121 return (aCount > 0) && (aCount < 3);
124 bool PartSet_HVDirSelection::isValid(const ModuleBase_ISelection* theSelection) const
126 int aCount = shapesNbLines(theSelection);
127 return (aCount == 1);
130 bool PartSet_TangentSelection::isValid(const ModuleBase_ISelection* theSelection) const
132 QList<ModuleBase_ViewerPrs> aList = theSelection->getSelected();
133 ModuleBase_ViewerPrs aPrs;
134 if (aList.size() != 2)
137 ModuleBase_ViewerPrs aPrs1 = aList.first();
138 ModuleBase_ViewerPrs aPrs2 = aList.last();
140 const TopoDS_Shape& aShape1 = aPrs1.shape();
141 const TopoDS_Shape& aShape2 = aPrs2.shape();
142 if (aShape1.IsNull() || aShape2.IsNull())
145 if ((aShape1.ShapeType() != TopAbs_EDGE) || (aShape2.ShapeType() != TopAbs_EDGE))
148 TopoDS_Edge aEdge1 = TopoDS::Edge(aShape1);
149 TopoDS_Edge aEdge2 = TopoDS::Edge(aShape2);
151 Standard_Real aStart, aEnd;
152 Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(aEdge1, aStart, aEnd);
153 Handle(Geom_Curve) aCurve2 = BRep_Tool::Curve(aEdge2, aStart, aEnd);
155 GeomAdaptor_Curve aAdaptor1(aCurve1);
156 GeomAdaptor_Curve aAdaptor2(aCurve2);
157 if (aAdaptor1.GetType() == GeomAbs_Circle)
158 return aAdaptor2.GetType() == GeomAbs_Line;
159 else if (aAdaptor2.GetType() == GeomAbs_Circle)
160 return aAdaptor1.GetType() == GeomAbs_Line;
165 bool PartSet_DifferentObjectsValidator::isValid(const AttributePtr& theAttribute,
166 const std::list<std::string>& theArguments) const
168 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
170 // the type of validated attributes should be equal, attributes with different types are not validated
171 // Check RefAttr attributes
172 std::string anAttrType = theAttribute->attributeType();
173 std::list<std::shared_ptr<ModelAPI_Attribute> > anAttrs;
175 if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
176 AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
177 bool isObject = anAttr->isObject();
178 ObjectPtr anObject = anAttr->object();
179 AttributePtr anAttributeAttr = anAttr->attr();
181 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
182 if (anAttrs.size() > 0) {
183 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
184 for(; anAttr != anAttrs.end(); anAttr++) {
185 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
186 std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
187 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttr);
188 if (aRef->isObject() != isObject)
191 if (aRef->object() == anObject)
194 else { // the attribute reference
195 if (aRef->attr() == theAttribute)
202 else if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
203 AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
204 ResultPtr aContext = anAttr->context();
205 GeomShapePtr aShape = anAttr->value();
207 // Check selection attributes
208 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeSelection::typeId());
209 if (anAttrs.size() > 0) {
210 std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
211 for(; anAttr != anAttrs.end(); anAttr++) {
212 if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
213 std::shared_ptr<ModelAPI_AttributeSelection> aRef =
214 std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(*anAttr);
215 // check the object is already presented
216 if (aRef->context() == aContext) {
217 bool aHasShape = aShape.get() != NULL;
218 if (!aHasShape || aRef->value()->isEqual(aShape))
225 else if (anAttrType == ModelAPI_AttributeReference::typeId()) {
226 AttributeReferencePtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
227 ObjectPtr anObject = anAttr->value();
228 // Check selection attributes
229 anAttrs = aFeature->data()->attributes(ModelAPI_AttributeReference::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_AttributeReference> aRef =
235 std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*anAttr);
236 // check the object is already presented
237 if (aRef->value() == anObject)
244 return !featureHasReferences(theAttribute);
247 bool PartSet_DifferentObjectsValidator::featureHasReferences(const AttributePtr& theAttribute) const
249 std::list<std::pair<std::string, std::list<ObjectPtr> > > allRefs;
250 if (theAttribute->owner().get() && theAttribute->owner()->data().get())
251 theAttribute->owner()->data()->referencesToObjects(allRefs);
252 // collect object referenced by theAttribute
253 std::list<ObjectPtr>* anAttrObjs = 0;
254 std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRefIter = allRefs.begin();
255 for(; aRefIter != allRefs.end(); aRefIter++) {
256 if (theAttribute->id() == aRefIter->first)
257 anAttrObjs = &(aRefIter->second);
259 if (!anAttrObjs || anAttrObjs->empty())
260 return false; // theAttribute does not references to anything
261 // check with all others
262 for(aRefIter = allRefs.begin(); aRefIter != allRefs.end(); aRefIter++) {
263 if (theAttribute->id() == aRefIter->first)
264 continue; // do not check with myself
265 std::list<ObjectPtr>::iterator aReferenced = aRefIter->second.begin();
266 for(; aReferenced != aRefIter->second.end(); aReferenced++) {
267 std::list<ObjectPtr>::iterator aReferencedByMe = anAttrObjs->begin();
268 for(; aReferencedByMe != anAttrObjs->end(); aReferencedByMe++) {
269 if (*aReferenced == *aReferencedByMe) // found same objects!
277 bool PartSet_SketchEntityValidator::isValid(const AttributePtr& theAttribute,
278 const std::list<std::string>& theArguments) const
280 bool isSketchEntities = true;
281 std::set<std::string> anEntityKinds;
282 std::list<std::string>::const_iterator anIt = theArguments.begin(), aLast = theArguments.end();
283 for (; anIt != aLast; anIt++) {
284 anEntityKinds.insert(*anIt);
287 std::string anAttributeType = theAttribute->attributeType();
288 if (anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
289 AttributeSelectionListPtr aSelectionListAttr =
290 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
291 // it filters only selection list attributes
292 std::string aType = aSelectionListAttr->selectionType().c_str();
293 // all context objects should be sketch entities
294 int aSize = aSelectionListAttr->size();
295 for (int i = 0; i < aSelectionListAttr->size() && isSketchEntities; i++) {
296 AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(i);
297 ObjectPtr anObject = aSelectAttr->context();
298 // a context of the selection attribute is a feature result. It can be a case when the result
299 // of the feature is null, e.g. the feature is modified and has not been executed yet.
300 // The validator returns an invalid result here. The case is an extrusion built on a sketch
301 // feature. A new sketch element creation leads to an empty result.
303 isSketchEntities = false;
305 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
306 isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
310 if (anAttributeType == ModelAPI_AttributeRefAttr::typeId()) {
311 std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
312 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
313 isSketchEntities = false;
314 if (aRef->isObject()) {
315 ObjectPtr anObject = aRef->object();
316 if (anObject.get() != NULL) {
317 FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
318 if (aFeature.get() != NULL)
319 isSketchEntities = anEntityKinds.find(aFeature->getKind()) != anEntityKinds.end();
324 return isSketchEntities;
329 bool PartSet_SameTypeAttrValidator::isValid(
330 const AttributePtr& theAttribute, const std::list<std::string>& theArguments ) const
332 // there is a check whether the feature contains a point and a linear edge or two point values
333 std::string aParamA = theArguments.front();
334 SessionPtr aMgr = ModelAPI_Session::get();
335 ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
337 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
338 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
342 bool isObject = aRefAttr->isObject();
343 ObjectPtr anObject = aRefAttr->object();
344 if (isObject && anObject) {
345 FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
347 AttributeRefAttrPtr aOtherAttr = aFeature->data()->refattr(aParamA);
348 ObjectPtr aOtherObject = aOtherAttr->object();
349 FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
350 return aRefFea->getKind() == aOtherFea->getKind();