]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchPlugin/SketchPlugin_Validators.cpp
Salome HOME
"2.11 Constraint with a point from the intersection between an outer edge and plane...
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_Validators.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        SketchPlugin_Validators.cpp
4 // Created:     01 Aug 2014
5 // Author:      Vitaly SMETANNIKOV
6
7 #include "SketchPlugin_Validators.h"
8
9 #include "SketchPlugin_Arc.h"
10 #include "SketchPlugin_Circle.h"
11 #include "SketchPlugin_ConstraintCoincidence.h"
12 #include "SketchPlugin_ConstraintDistance.h"
13 #include "SketchPlugin_ConstraintRigid.h"
14 #include "SketchPlugin_Line.h"
15 #include "SketchPlugin_Point.h"
16 #include "SketchPlugin_Sketch.h"
17 #include "SketchPlugin_Tools.h"
18
19 #include "SketcherPrs_Tools.h"
20
21 #include <ModelAPI_Data.h>
22 #include <ModelAPI_Validator.h>
23 #include <ModelAPI_AttributeDouble.h>
24 #include <ModelAPI_AttributeRefAttr.h>
25
26 #include <ModelAPI_AttributeRefAttrList.h>
27 #include <ModelAPI_AttributeRefList.h>
28 #include <ModelAPI_AttributeSelectionList.h>
29 #include <ModelAPI_AttributeString.h>
30 #include <ModelAPI_Session.h>
31 #include <ModelAPI_ResultConstruction.h>
32
33 #include <GeomAPI_Lin.h>
34 #include <GeomAPI_Edge.h>
35 #include <GeomAPI_Vertex.h>
36 #include <GeomDataAPI_Point2D.h>
37
38 #include <cmath>
39
40 const double tolerance = 1.e-7;
41
42 bool SketchPlugin_DistanceAttrValidator::isValid(const AttributePtr& theAttribute, 
43                                                  const std::list<std::string>& theArguments,
44                                                  std::string& theError) const
45 {
46   if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
47     theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
48     return false;
49   }
50
51   // there is a check whether the feature contains a point and a linear edge or two point values
52   std::string aParamA = theArguments.front();
53   SessionPtr aMgr = ModelAPI_Session::get();
54   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
55
56   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
57   bool isObject = aRefAttr->isObject();
58   if (!isObject) {
59     // an attribute is a point. A point value is valid always for the distance
60     return true;
61   } else {
62     // 1. check whether the references object is a linear
63     ObjectPtr anObject = aRefAttr->object();
64
65     const ModelAPI_AttributeValidator* aShapeValidator = 
66       dynamic_cast<const ModelAPI_AttributeValidator*>(aFactory->validator("GeomValidators_ShapeType"));
67     std::list<std::string> anArguments;
68     anArguments.push_back("circle");
69     std::string aCircleError;
70     bool aShapeValid = aShapeValidator->isValid(aRefAttr, anArguments, aCircleError);
71     // the circle line is not a valid case
72     if (aShapeValid) {
73       theError = "Circle can not be used in distance constraint";
74       return false;
75     }
76       
77     anArguments.clear();
78     anArguments.push_back("line");
79     std::string aLineError;
80     aShapeValid = aShapeValidator->isValid(aRefAttr, anArguments, aLineError);
81     // if the attribute value is not a line, that means it is a vertex. A vertex is always valid
82     if (aShapeValid) {
83       FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
84       // If it is a line then we have to check that first attribute id not a line
85       std::shared_ptr<SketchPlugin_Feature> aSFeature =
86         std::dynamic_pointer_cast<SketchPlugin_Feature>(theAttribute->owner());
87       SketchPlugin_Sketch* aSketch = aSFeature->sketch();
88       std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(aSketch);
89       std::shared_ptr<GeomDataAPI_Point2D> aPoint = SketcherPrs_Tools::getFeaturePoint(
90         aFeature->data(), aParamA, aPlane);
91       if (!aPoint.get()) {
92         theError = "One of parameters of distance constraint should be a point";
93         return false;
94       }
95     }
96   }
97   return true;
98 }
99
100
101 static bool hasCoincidentPoint(FeaturePtr theFeature1, FeaturePtr theFeature2)
102 {
103   FeaturePtr aConstrFeature;
104   std::list<AttributePtr> anAttrList;
105   if (theFeature1->getKind() == SketchPlugin_Circle::ID() ||
106       theFeature2->getKind() == SketchPlugin_Circle::ID())
107     return false;
108   if (theFeature2->getKind() == SketchPlugin_Line::ID()) {
109     anAttrList.push_back(theFeature2->attribute(SketchPlugin_Line::START_ID()));
110     anAttrList.push_back(theFeature2->attribute(SketchPlugin_Line::END_ID()));
111   } else if (theFeature2->getKind() == SketchPlugin_Arc::ID()) {
112     anAttrList.push_back(theFeature2->attribute(SketchPlugin_Arc::START_ID()));
113     anAttrList.push_back(theFeature2->attribute(SketchPlugin_Arc::END_ID()));
114   }
115
116   const std::set<AttributePtr>& aRefsList = theFeature1->data()->refsToMe();
117   std::set<AttributePtr>::const_iterator aRefIt = aRefsList.begin();
118   for (; aRefIt != aRefsList.end(); ++aRefIt) {
119     aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
120     if (aConstrFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
121       continue;
122     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
123     AttributePtr anAttr = aRefAttr->attr();
124     if (anAttr->id() == SketchPlugin_Arc::CENTER_ID())
125       continue;
126
127     anAttr = aConstrFeature->attribute(SketchPlugin_Constraint::ENTITY_A());
128     if (anAttr == *aRefIt)
129       anAttr = aConstrFeature->attribute(SketchPlugin_Constraint::ENTITY_B());
130
131     aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
132     if (!aRefAttr)
133       continue;
134     anAttr = aRefAttr->attr();
135     for (std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
136          anIt != anAttrList.end(); ++anIt)
137       if (*anIt == anAttr)
138         return true;
139   }
140   return false;
141 }
142
143 bool SketchPlugin_TangentAttrValidator::isValid(const AttributePtr& theAttribute, 
144                                                 const std::list<std::string>& theArguments,
145                                                 std::string& theError) const
146 {
147   if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
148     theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
149     return false;
150   }
151
152   // there is a check whether the feature contains a point and a linear edge or two point values
153   std::string aParamA = theArguments.front();
154   SessionPtr aMgr = ModelAPI_Session::get();
155   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
156
157   FeaturePtr anAttributeFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
158   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
159
160   bool isObject = aRefAttr->isObject();
161   ObjectPtr anObject = aRefAttr->object();
162   if (isObject && anObject.get()) {
163     FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
164
165     AttributeRefAttrPtr aOtherAttr = anAttributeFeature->data()->refattr(aParamA);
166     ObjectPtr aOtherObject = aOtherAttr->object();
167     FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
168     if (!aOtherFea)
169       return true;
170
171     if ((aRefFea->getKind() == SketchPlugin_Arc::ID() ||
172         aOtherFea->getKind() == SketchPlugin_Arc::ID()) &&
173         !hasCoincidentPoint(aRefFea, aOtherFea))
174       return false;
175
176     if (aRefFea->getKind() == SketchPlugin_Line::ID()) {
177       if (aOtherFea->getKind() != SketchPlugin_Arc::ID() &&
178           aOtherFea->getKind() != SketchPlugin_Circle::ID()) {
179         theError = "It refers to a " + SketchPlugin_Line::ID() + ", but " + aParamA + " is neither an "
180           + SketchPlugin_Arc::ID() + " nor " + SketchPlugin_Circle::ID();
181         return false;
182       }
183     }
184     else if (aRefFea->getKind() == SketchPlugin_Arc::ID()) {
185       if (aOtherFea->getKind() != SketchPlugin_Line::ID() &&
186         aOtherFea->getKind() != SketchPlugin_Arc::ID()) {
187         theError = "It refers to an " + SketchPlugin_Arc::ID() + ", but " + aParamA + " is not a "
188           + SketchPlugin_Line::ID() + " or an " + SketchPlugin_Arc::ID();
189         return false;
190       }
191     }
192     else if (aRefFea->getKind() == SketchPlugin_Circle::ID()) {
193       if (aOtherFea->getKind() != SketchPlugin_Line::ID()) {
194         theError = "It refers to an " + SketchPlugin_Circle::ID() + ", but " + aParamA + " is not a "
195           + SketchPlugin_Line::ID();
196         return false;
197       }
198     }
199     else {
200       theError = "It refers to " + aRefFea->getKind() + ", but should refer to " + SketchPlugin_Line::ID()
201         + " or " + SketchPlugin_Arc::ID() + " or " + SketchPlugin_Circle::ID();
202       return false;
203     }
204     return true;
205   }
206   else {
207     theError = "It uses an empty object";
208     return false;
209   }
210
211   return true;
212 }
213
214 bool SketchPlugin_NotFixedValidator::isValid(const AttributePtr& theAttribute,
215                                              const std::list<std::string>& theArguments,
216                                              std::string& theError) const
217 {
218   if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
219     theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
220     return false;
221   }
222
223   std::shared_ptr<SketchPlugin_Feature> aFeature =
224       std::dynamic_pointer_cast<SketchPlugin_Feature>(theAttribute->owner());
225   if (!aFeature)
226     return true;
227
228   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
229
230   SketchPlugin_Sketch* aSketch = aFeature->sketch();
231   int aNbFeatures = aSketch->numberOfSubs();
232   for (int anInd = 0; anInd < aNbFeatures; anInd++) {
233     FeaturePtr aSubFeature = aSketch->subFeature(anInd);
234     if (aSubFeature->getKind() != SketchPlugin_ConstraintRigid::ID() || aSubFeature == aFeature)
235       continue;
236     AttributeRefAttrPtr aRAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
237         aSubFeature->attribute(SketchPlugin_ConstraintRigid::ENTITY_A()));
238     if (aRefAttr->isObject()) {
239       if (aRefAttr->object() == aRAttr->object()) {
240         ObjectPtr anObject = aRefAttr->object();
241         std::string aName = anObject.get() ? anObject->data()->name() : "";
242         theError = "The object " + aName + " has been already fixed.";
243         return false;
244       }
245     }
246     else if (aRefAttr->attr() == aRAttr->attr()) {
247       AttributePtr anAttribute = aRefAttr->attr();
248       std::string aName = anAttribute.get() ? anAttribute->id() : "";
249       theError = "The attribute " + aName + " has been already fixed.";
250       return false;
251     }
252   }
253   return true;
254 }
255
256 bool SketchPlugin_EqualAttrValidator::isValid(const AttributePtr& theAttribute, 
257                                               const std::list<std::string>& theArguments,
258                                               std::string& theError) const
259 {
260   if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
261     theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
262     return false;
263   }
264
265   std::string aParamA = theArguments.front();
266   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
267   AttributeRefAttrPtr aRefAttr[2];
268   aRefAttr[0] = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
269   aRefAttr[1] = aFeature->data()->refattr(aParamA);
270
271   if (!aRefAttr[0]->isObject() || !aRefAttr[1]->isObject()) {
272     theError = "Attributes can not be used in equal constraint";
273     return false;
274   }
275
276   std::string aType[2];
277   std::list<std::string> anArguments;
278   for (int i = 0; i < 2; i++) {
279     ObjectPtr anObject = aRefAttr[i]->object();
280     if (!anObject.get()) {
281       theError = "An empty object is used.";
282       return false;
283     }
284
285     aFeature = ModelAPI_Feature::feature(anObject);
286     if (!aFeature.get()) {
287       theError = "An empty feature is used.";
288       return false;
289     }
290
291     aType[i] = aFeature->getKind();
292     if (aFeature->getKind() != SketchPlugin_Line::ID() &&
293         aFeature->getKind() != SketchPlugin_Circle::ID() &&
294         aFeature->getKind() != SketchPlugin_Arc::ID()) {
295       theError = "The " + aFeature->getKind() + " feature kind of attribute is wrong. It should be " +
296                  SketchPlugin_Line::ID() + " or " + SketchPlugin_Circle::ID() + " or " + 
297                  SketchPlugin_Arc::ID();
298       // wrong type of attribute
299       return false;
300     }
301   }
302
303   if ((aType[0] == SketchPlugin_Line::ID() || aType[1] == SketchPlugin_Line::ID()) &&
304       aType[0] != aType[1]) {
305     theError = "Feature with kinds " + aType[0] + " and " + aType[1] + "can not be equal.";
306     return false;
307   }
308   return true;
309 }
310
311 bool SketchPlugin_MirrorAttrValidator::isValid(const AttributePtr& theAttribute, 
312                                                const std::list<std::string>& theArguments,
313                                                std::string& theError) const
314 {
315   if (theAttribute->attributeType() != ModelAPI_AttributeRefList::typeId()) {
316     theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
317     return false;
318   }
319
320   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
321   AttributeRefListPtr aSelAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
322
323   AttributeRefListPtr aRefListOfMirrored = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
324       aFeature->attribute(SketchPlugin_Constraint::ENTITY_C()));
325   std::list<ObjectPtr> aMirroredObjects = aRefListOfMirrored->list();
326
327   for(int anInd = 0; anInd < aSelAttr->size(); anInd++) {
328     ObjectPtr aSelObject = aSelAttr->object(anInd);
329     std::string aName = aSelObject.get() ? aSelObject->data()->name() : "";
330     std::list<ObjectPtr>::iterator aMirIter = aMirroredObjects.begin();
331     for (; aMirIter != aMirroredObjects.end(); aMirIter++)
332       if (aSelObject == *aMirIter) {
333         theError = "The object " + aName + " is a result of mirror";
334         return false;
335       }
336   }
337   return true;
338 }
339
340 bool SketchPlugin_CoincidenceAttrValidator::isValid(const AttributePtr& theAttribute, 
341                                                     const std::list<std::string>& theArguments,
342                                                     std::string& theError) const
343 {
344   if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
345     theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
346     return false;
347   }
348
349   // there is a check whether the feature contains a point and a linear edge or two point values
350   std::string aParamA = theArguments.front();
351   SessionPtr aMgr = ModelAPI_Session::get();
352   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
353
354   FeaturePtr aConstraint = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
355   AttributeRefAttrPtr aRefAttrA = aConstraint->data()->refattr(aParamA);
356   if (!aRefAttrA) {
357     theError = "The " + aParamA + " attribute " + " should be " + ModelAPI_AttributeRefAttr::typeId();
358     return false;
359   }
360
361   AttributeRefAttrPtr aRefAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
362
363   // first attribute is a point, it may coincide with any object
364   if (!aRefAttrA->isObject())
365     return true;
366   else {
367     ObjectPtr anObject = aRefAttrA->object();
368     if (!anObject.get()) {
369       theError = aParamA + " attribute has an empty object";
370       return false;
371     }
372     FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttrA->object());
373     if (!aFeature.get()) {
374       theError = aParamA + " attribute has an empty feature";
375       return false;
376     }
377
378     if (aFeature->getKind() == SketchPlugin_Point::ID())
379       return true;
380   }
381
382   // second attribute is a point, it may coincide with any object
383   if (!aRefAttrB->isObject())
384     return true;
385   else {
386     FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttrB->object());
387     if (!aFeature) {
388       theError = theAttribute->id() + " attribute has an empty object";
389       return false;
390     }
391     if (aFeature->getKind() == SketchPlugin_Point::ID())
392       return true;
393   }
394   theError = "There is no an attribute filled by a point";
395   return false;
396 }
397
398
399 bool SketchPlugin_CopyValidator::isValid(const AttributePtr& theAttribute, 
400                                          const std::list<std::string>& theArguments,
401                                          std::string& theError) const
402 {
403   if (theAttribute->attributeType() != ModelAPI_AttributeRefList::typeId()) {
404     theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
405     return false;
406   }
407
408   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
409   AttributeRefListPtr aSelAttr = 
410     std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
411
412   AttributeRefListPtr aRefListOfInitial = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
413       aFeature->attribute(SketchPlugin_Constraint::ENTITY_A()));
414   AttributeRefListPtr aRefListOfCopied = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
415       aFeature->attribute(SketchPlugin_Constraint::ENTITY_B()));
416   std::list<ObjectPtr> anInitialObjects = aRefListOfInitial->list();
417   std::list<ObjectPtr> aCopiedObjects = aRefListOfCopied->list();
418
419   std::list<ObjectPtr>::iterator anObjIter;
420   for(int anInd = 0; anInd < aSelAttr->size(); anInd++) {
421     ObjectPtr aSelObject = aSelAttr->object(anInd);
422     anObjIter = anInitialObjects.begin();
423     for (; anObjIter != anInitialObjects.end(); anObjIter++)
424       if (aSelObject == *anObjIter)
425         break;
426     if (anObjIter != anInitialObjects.end())
427       continue;
428     anObjIter = aCopiedObjects.begin();
429     for (; anObjIter != aCopiedObjects.end(); anObjIter++)
430       if (aSelObject == *anObjIter) {
431         std::string aName = aSelObject.get() ? aSelObject->data()->name() : "";
432         theError = "The object " + aName + " is a result of copy";
433         return false;
434       }
435   }
436   return true;
437 }
438
439 bool SketchPlugin_SolverErrorValidator::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
440                                                 const std::list<std::string>& theArguments,
441                                                 std::string& theError) const
442 {
443   AttributeStringPtr aAttributeString = theFeature->string(SketchPlugin_Sketch::SOLVER_ERROR());
444
445   if (!aAttributeString->value().empty()) {
446     theError = aAttributeString->value();
447     return false;
448   }
449
450   return true;
451 }
452
453 bool SketchPlugin_SolverErrorValidator::isNotObligatory(std::string theFeature, std::string theAttribute)
454 {
455   return true;
456 }
457
458 bool SketchPlugin_FilletVertexValidator::isValid(const AttributePtr& theAttribute,
459                                                  const std::list<std::string>& theArguments,
460                                                  std::string& theError) const
461 {
462   if(!theAttribute.get() || !theAttribute->isInitialized()) {
463     theError = "Error: List of points is not initialized.";
464     return false;
465   }
466
467   FeaturePtr aFilletFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
468   AttributeRefAttrListPtr aPointsRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(theAttribute);
469   if(aPointsRefList->size() == 0) {
470     theError = "Error: List of points is empty.";
471     return false;
472   }
473
474   AttributeRefAttrListPtr aBasePointsRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(
475     aFilletFeature->attribute(SketchPlugin_Constraint::ENTITY_C()));
476   AttributeRefListPtr aResultEdgesRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
477     aFilletFeature->attribute(SketchPlugin_Constraint::ENTITY_B()));
478
479   std::list<std::pair<ObjectPtr, AttributePtr>> aPointsList = aPointsRefList->list();
480   for(std::list<std::pair<ObjectPtr, AttributePtr>>::const_iterator anIt = aPointsList.cbegin(); anIt != aPointsList.cend(); anIt++) {
481     ObjectPtr anObject = (*anIt).first;
482     AttributePtr aPointAttribute = (*anIt).second;
483
484     // If we alredy have some result then:
485     // - if it is the same point all ok, just skip it
486     // - if it is point on the fillet arc then it is not valid
487     if(aBasePointsRefList->size() > 0) {
488       if(aBasePointsRefList->isInList(aPointAttribute)) {
489         continue;
490       }
491
492       // Check that selected point not on the one of the result fillet arc.
493       for(int anIndex = 0; anIndex < aBasePointsRefList->size(); anIndex++) {
494         if(aResultEdgesRefList->size() > 0) {
495           FeaturePtr aResultArc;
496           aResultArc = ModelAPI_Feature::feature(aResultEdgesRefList->object(anIndex * 3 + 2));
497           AttributePtr anArcStart = aResultArc->attribute(SketchPlugin_Arc::START_ID());
498           AttributePtr anArcEnd = aResultArc->attribute(SketchPlugin_Arc::END_ID());
499           std::shared_ptr<GeomAPI_Pnt2d> anArcStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anArcStart)->pnt();
500           std::shared_ptr<GeomAPI_Pnt2d> anArcEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anArcEnd)->pnt();
501           std::shared_ptr<GeomAPI_Pnt2d> aSelectedPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aPointAttribute)->pnt();
502           double aDistSelectedArcStart = aSelectedPnt->distance(anArcStartPnt);
503           double aDistSelectedArcEnd = aSelectedPnt->distance(anArcEndPnt);
504           if(aDistSelectedArcStart < tolerance || aDistSelectedArcEnd < tolerance) {
505             return false;
506           }
507         }
508       }
509     }
510
511     // Obtain constraint coincidence for the fillet point.
512     const std::set<AttributePtr>& aRefsList = aPointAttribute->owner()->data()->refsToMe();
513     FeaturePtr aConstraintCoincidence;
514     for(std::set<AttributePtr>::const_iterator anIt = aRefsList.cbegin(); anIt != aRefsList.cend(); ++anIt) {
515       std::shared_ptr<ModelAPI_Attribute> aAttr = (*anIt);
516       FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
517       if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
518         AttributeRefAttrPtr anAttrRefA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
519           aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_A()));
520         AttributeRefAttrPtr anAttrRefB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
521           aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_B()));
522         if(anAttrRefA.get() && !anAttrRefA->isObject()) {
523           AttributePtr anAttrA = anAttrRefA->attr();
524           if(aPointAttribute == anAttrA) {
525             aConstraintCoincidence = aConstrFeature;
526             break;
527           }
528         }
529         if(anAttrRefB.get() && !anAttrRefB->isObject()) {
530           AttributePtr anAttrB = anAttrRefB->attr();
531           if(aPointAttribute == anAttrB) {
532             aConstraintCoincidence = aConstrFeature;
533             break;
534           }
535         }
536       }
537     }
538
539     if(!aConstraintCoincidence.get()) {
540       theError = "Error: one of the selected point does not have coicidence.";
541       return false;
542     }
543
544     // Get coincides from constraint.
545     std::set<FeaturePtr> aCoinsides;
546     SketchPlugin_Tools::findCoincidences(aConstraintCoincidence,
547                                          SketchPlugin_ConstraintCoincidence::ENTITY_A(),
548                                          aCoinsides);
549     SketchPlugin_Tools::findCoincidences(aConstraintCoincidence,
550                                          SketchPlugin_ConstraintCoincidence::ENTITY_B(),
551                                          aCoinsides);
552
553     // Remove points from set of coincides.
554     std::set<FeaturePtr> aNewSetOfCoincides;
555     for(std::set<FeaturePtr>::iterator anIt = aCoinsides.begin(); anIt != aCoinsides.end(); ++anIt) {
556       if((*anIt)->getKind() == SketchPlugin_Line::ID() ||
557          (*anIt)->getKind() == SketchPlugin_Arc::ID()) {
558         aNewSetOfCoincides.insert(*anIt);
559       }
560     }
561     aCoinsides = aNewSetOfCoincides;
562
563     // If we still have more than two coincides remove auxilary entities from set of coincides.
564     if(aCoinsides.size() > 2) {
565       aNewSetOfCoincides.clear();
566       for(std::set<FeaturePtr>::iterator anIt = aCoinsides.begin(); anIt != aCoinsides.end(); ++anIt) {
567         if(!(*anIt)->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()) {
568           aNewSetOfCoincides.insert(*anIt);
569         }
570       }
571       aCoinsides = aNewSetOfCoincides;
572     }
573
574     if(aCoinsides.size() != 2) {
575       theError = ("Error: One of the selected points does not have two suitable edges for fillet.");
576       return false;
577     }
578
579     // Check that lines not collinear
580     std::set<FeaturePtr>::iterator anIt = aCoinsides.begin();
581     FeaturePtr aFirstFeature = *anIt++;
582     FeaturePtr aSecondFeature = *anIt;
583     if(aFirstFeature->getKind() == SketchPlugin_Line::ID() && aSecondFeature->getKind() == SketchPlugin_Line::ID()) {
584       std::string aStartAttr = SketchPlugin_Line::START_ID();
585       std::string anEndAttr = SketchPlugin_Line::END_ID();
586       std::shared_ptr<GeomAPI_Pnt2d> aFirstStartPnt, aFirstEndPnt, aSecondStartPnt, aSecondEndPnt;
587       aFirstStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aFirstFeature->attribute(aStartAttr))->pnt();
588       aFirstEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aFirstFeature->attribute(anEndAttr))->pnt();
589       aSecondStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aSecondFeature->attribute(aStartAttr))->pnt();
590       aSecondEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aSecondFeature->attribute(anEndAttr))->pnt();
591       double aCheck1 = abs((aFirstEndPnt->x() - aFirstStartPnt->x()) * (aSecondStartPnt->y() - aFirstStartPnt->y()) -
592         (aSecondStartPnt->x() - aFirstStartPnt->x()) * (aFirstEndPnt->y() - aFirstStartPnt->y()));
593       double aCheck2 = abs((aFirstEndPnt->x() - aFirstStartPnt->x()) * (aSecondEndPnt->y() - aFirstStartPnt->y()) -
594         (aSecondEndPnt->x() - aFirstStartPnt->x()) * (aFirstEndPnt->y() - aFirstStartPnt->y()));
595       if(aCheck1 < 1.e-7 && aCheck2 < 1.e-7) {
596         return false;
597       }
598     }
599   }
600
601   return true;
602 }
603
604 bool SketchPlugin_MiddlePointAttrValidator::isValid(const AttributePtr& theAttribute, 
605                                                     const std::list<std::string>& theArguments,
606                                                     std::string& theError) const
607 {
608   if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
609     theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
610     return false;
611   }
612
613   // there is a check whether the feature contains a point and a linear edge or two point values
614   std::string aParamA = theArguments.front();
615   SessionPtr aMgr = ModelAPI_Session::get();
616   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
617
618   FeaturePtr anAttributeFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
619   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
620   AttributeRefAttrPtr anOtherAttr = anAttributeFeature->data()->refattr(aParamA);
621
622   AttributeRefAttrPtr aRefAttrs[2] = {aRefAttr, anOtherAttr};
623   int aNbPoints = 0;
624   int aNbLines = 0;
625   for (int i = 0; i < 2; ++i) {
626     if (!aRefAttrs[i]->isObject())
627       ++aNbPoints;
628     else {
629       FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttrs[i]->object());
630       if (!aFeature) {
631         if (aNbPoints + aNbLines != 0)
632           return true;
633         else continue;
634       }
635
636       if (aFeature->getKind() == SketchPlugin_Point::ID())
637         ++aNbPoints;
638       else if (aFeature->getKind() == SketchPlugin_Line::ID())
639         ++aNbLines;
640     }
641   }
642
643   if (aNbPoints != 1 || aNbLines != 1) {
644     theError = "Middle point constraint allows points and lines only";
645     return false;
646   }
647   return true;
648 }
649
650 bool SketchPlugin_ArcTangentPointValidator::isValid(const AttributePtr& theAttribute,
651                                                     const std::list<std::string>& /*theArguments*/,
652                                                     std::string& theError) const
653 {
654   if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
655     theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
656     return false;
657   }
658   AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
659   AttributePtr anAttr = aRefAttr->attr();
660   if (!anAttr) {
661     theError = "The attribute " + theAttribute->id() + " should be a point";
662     return false;
663   }
664
665   FeaturePtr anAttrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anAttr->owner());
666   const std::string& aFeatureType = anAttrFeature->getKind();
667   if (aFeatureType == SketchPlugin_Arc::ID()) {
668     // selected point should not be a center of arc
669     const std::string& aPntId = anAttr->id();
670     if (aPntId != SketchPlugin_Arc::START_ID() && aPntId != SketchPlugin_Arc::END_ID()) {
671       theError = "The attribute " + aPntId + " is not supported";
672       return false;
673     }
674   }
675   else if (aFeatureType == SketchPlugin_Line::ID()) {
676     // selected point should be bound point of line
677     const std::string& aPntId = anAttr->id();
678     if (aPntId != SketchPlugin_Line::START_ID() && aPntId != SketchPlugin_Line::END_ID()) {
679       theError = "The attribute " + aPntId + " is not supported";
680       return false;
681     }
682   }
683   else {
684     theError = "Unable to build tangent arc on " + anAttrFeature->getKind();
685     return false;
686   }
687
688   return true;
689 }
690
691 bool SketchPlugin_IntersectionValidator::isValid(const AttributePtr& theAttribute,
692                                                  const std::list<std::string>& theArguments,
693                                                  std::string& theError) const
694 {
695   if (theAttribute->attributeType() != ModelAPI_AttributeSelection::typeId()) {
696     theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
697     return false;
698   }
699   AttributeSelectionPtr aLineAttr =
700                               std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
701   std::shared_ptr<GeomAPI_Edge> anEdge;
702   if(aLineAttr && aLineAttr->value() && aLineAttr->value()->isEdge()) {
703     anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aLineAttr->value()));
704   } else if(aLineAttr->context() && aLineAttr->context()->shape() && aLineAttr->context()->shape()->isEdge()) {
705     anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aLineAttr->context()->shape()));
706   }
707
708   if (!anEdge || !anEdge->isLine()) {
709     theError = "The attribute " + theAttribute->id() + " should be a line";
710     return false;
711   }
712
713   std::shared_ptr<GeomAPI_Dir> aLineDir = anEdge->line()->direction();
714
715   // find a sketch
716   std::shared_ptr<SketchPlugin_Sketch> aSketch;
717   std::set<AttributePtr> aRefs = aLineAttr->owner()->data()->refsToMe();
718   std::set<AttributePtr>::const_iterator anIt = aRefs.begin();
719   for (; anIt != aRefs.end(); ++anIt) {
720     CompositeFeaturePtr aComp =
721         std::dynamic_pointer_cast<ModelAPI_CompositeFeature>((*anIt)->owner());
722     if (aComp && aComp->getKind() == SketchPlugin_Sketch::ID()) {
723       aSketch = std::dynamic_pointer_cast<SketchPlugin_Sketch>(aComp);
724       break;
725     }
726   }
727   if (!aSketch) {
728     theError = "There is no sketch referring to the current feature";
729     return false;
730   }
731
732   std::shared_ptr<GeomAPI_Pln> aPlane = aSketch->plane();
733   std::shared_ptr<GeomAPI_Dir> aNormal = aPlane->direction();
734   return fabs(aNormal->dot(aLineDir)) > tolerance * tolerance;
735 }