Salome HOME
Test1967: Update tolerance ratio for moving vs creating.
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_ConstraintMiddle.cpp
1 // Copyright (C) 2014-2023  CEA, EDF
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "SketchPlugin_ConstraintMiddle.h"
21
22 #include "SketcherPrs_Factory.h"
23
24 #include <GeomDataAPI_Point2D.h>
25
26 #include <ModelAPI_Validator.h>
27 #include <ModelAPI_AttributeString.h>
28
29 #include <ModelAPI_Events.h>
30 #include <SketchPlugin_Point.h>
31 #include <SketchPlugin_Tools.h>
32
33
34 class RaiiSetBoolFlag {
35 public:
36   RaiiSetBoolFlag() = delete;
37   RaiiSetBoolFlag(bool &theFlag)
38   {
39     myBoolPtr = &theFlag;
40     *myBoolPtr = true;
41   }
42   ~RaiiSetBoolFlag()
43   {
44     *myBoolPtr = false;
45   }
46 private:
47   bool *myBoolPtr;
48 };
49
50
51 SketchPlugin_ConstraintMiddle::SketchPlugin_ConstraintMiddle()
52 {
53   myBlockAttribInit = false;
54 }
55
56 // Create new point for Middle constraint
57 void SketchPlugin_ConstraintMiddle::CreatePoint()
58 {
59   // Wait all objects being created, then send update events
60   static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
61   bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
62   if (isUpdateFlushed)
63     Events_Loop::loop()->setFlushed(anUpdateEvent, false);
64
65   auto aTrPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(POINT_REF_ID()));
66
67   if (!myPoint)
68   {
69     // Get last subfeature (constraintMiddle) for set as parent
70     FeaturePtr aCurrentFeature = sketch()->subFeature(sketch()->numberOfSubs() - 1);
71     keepCurrentFeature();
72     myPoint = sketch()->addFeature(SketchPlugin_Point::ID());
73     myPoint->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(true);
74     restoreCurrentFeature();
75
76     myPoint->reference(SketchPlugin_Point::PARENT_ID())->setValue(aCurrentFeature);
77   }
78
79   AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
80     myPoint->attribute(SketchPlugin_Point::COORD_ID()));
81   aCoord->setValue(aTrPnt->pnt());
82
83   myPoint->execute();
84
85   // Init second attr for constraint
86   refattr(SketchPlugin_Constraint::ENTITY_B())->setObject(myPoint);
87
88
89   if (isUpdateFlushed)
90     Events_Loop::loop()->setFlushed(anUpdateEvent, true);
91 }
92
93 void SketchPlugin_ConstraintMiddle::initAttributes()
94 {
95   // To maintain compatibility with older study versions, keep the order of all previously existing attributes:
96   //  1) ENTITY_A
97   //  2) ENTITY_B
98   //  ----------- new attributes start here:
99   //  3) MIDDLE_TYPE
100   //  4) POINT_REF_ID
101   AttributeRefAttrPtr aAttrEntA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
102     data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId()));
103
104   AttributeRefAttrPtr aAttrEntB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
105     data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId()));
106   
107   AttributeStringPtr aMethodAttr = std::dynamic_pointer_cast<ModelAPI_AttributeString>(
108     data()->addAttribute(SketchPlugin_ConstraintMiddle::MIDDLE_TYPE(), ModelAPI_AttributeString::typeId()));
109   
110   // When loading studies from older versions (<9.12), the MIDDLE_TYPE attribute did not exist
111   // and is therefore not initialized!
112   // BUT: in case of a valid middle point constraint, the ENTITY_A and ENTITY_B attributes must be initialized
113   bool useDefaultMethod = !aMethodAttr->isInitialized();
114   if (aAttrEntA->isInitialized() && aAttrEntB->isInitialized() && useDefaultMethod)
115   {
116     // Initialize the creation method attribute (MIDDLE_TYPE) with the previously default
117     // creation method: "mid point from line and point".
118     // NOTE: ensure that the other attributes are NOT reset, as we want to keep the current inputs
119     RaiiSetBoolFlag blockEntityReset(myBlockAttribInit);
120     aMethodAttr->setValue(MIDDLE_TYPE_BY_LINE_AND_POINT());
121   }
122
123   data()->addAttribute(POINT_REF_ID(), GeomDataAPI_Point2D::typeId());
124
125   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), POINT_REF_ID());
126 }
127
128 void SketchPlugin_ConstraintMiddle::execute()
129 {
130   if (string(MIDDLE_TYPE())->value() == MIDDLE_TYPE_BY_LINE())
131   {
132     std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(POINT_REF_ID()))->setValue(1., 1.);
133     AttributeRefAttrPtr aPointRes = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
134       data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
135
136     auto aRefAttr = data()->refattr(SketchPlugin_Constraint::ENTITY_A())->object();
137     if (!aRefAttr.get())
138       return;
139
140
141     if (!attribute(ENTITY_B())->isInitialized())
142       CreatePoint(); // Create new point
143   }
144 }
145
146 void SketchPlugin_ConstraintMiddle::attributeChanged(const std::string& theID)
147 {
148   if (theID == MIDDLE_TYPE())
149   {
150     if (!myBlockAttribInit) {
151       SketchPlugin_Tools::resetAttribute(this, ENTITY_A());
152       SketchPlugin_Tools::resetAttribute(this, ENTITY_B());
153     }
154   }
155   else if (theID == POINT_REF_ID())
156   {
157     if (!myPoint)
158       return;
159
160     auto aTrPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(POINT_REF_ID()));
161     AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
162       myPoint->attribute(SketchPlugin_Point::COORD_ID()));
163     aCoord->setValue(aTrPnt->pnt());
164
165     myPoint->execute();
166   }
167 }
168
169 AISObjectPtr SketchPlugin_ConstraintMiddle::getAISObject(AISObjectPtr thePrevious)
170 {
171   if (!sketch())
172     return thePrevious;
173   AISObjectPtr anAIS = SketcherPrs_Factory::middleConstraint(this, sketch(),
174                                                              thePrevious);
175
176   return anAIS;
177 }