Salome HOME
Sketcher: Remove obsolete interfaces. Code cleanup.
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_FeatureBuilder.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:    PlaneGCSSolver_AttributeBuilder.cpp
4 // Created: 10 Feb 2017
5 // Author:  Artem ZHIDKOV
6
7 #include <PlaneGCSSolver_FeatureBuilder.h>
8 #include <PlaneGCSSolver_EdgeWrapper.h>
9 #include <PlaneGCSSolver_PointWrapper.h>
10 #include <PlaneGCSSolver_ScalarWrapper.h>
11
12 #include <SketchPlugin_Arc.h>
13 #include <SketchPlugin_Circle.h>
14 #include <SketchPlugin_IntersectionPoint.h>
15 #include <SketchPlugin_Line.h>
16 #include <SketchPlugin_Point.h>
17
18 #include <GeomAPI_Dir2d.h>
19 #include <GeomAPI_Pnt2d.h>
20 #include <GeomAPI_XY.h>
21
22 static bool isAttributeApplicable(const std::string& theAttrName,
23                                   const std::string& theOwnerName);
24
25 static EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes);
26 static EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes);
27 static EntityWrapperPtr createArc(const AttributeEntityMap&    theAttributes,
28                                   PlaneGCSSolver_Storage*      theStorage,
29                                   std::list<GCSConstraintPtr>& theArcConstraints);
30
31
32 PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(
33     PlaneGCSSolver_Storage* theStorage)
34   : PlaneGCSSolver_AttributeBuilder(theStorage)
35 {
36 }
37
38 PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(const StoragePtr& theStorage)
39   : PlaneGCSSolver_AttributeBuilder(theStorage)
40 {
41 }
42
43 EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createAttribute(
44     AttributePtr theAttribute)
45 {
46   FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
47   EntityWrapperPtr anAttr;
48   if (isAttributeApplicable(theAttribute->id(), anOwner->getKind()))
49     anAttr = PlaneGCSSolver_AttributeBuilder::createAttribute(theAttribute);
50   if (anAttr)
51     myAttributes[theAttribute] = anAttr;
52   return anAttr;
53 }
54
55 EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createFeature(FeaturePtr theFeature)
56 {
57   EntityWrapperPtr aResult;
58   if (myStorage)
59     aResult = myStorage->entity(theFeature);
60   if (aResult)
61     return aResult;
62
63   // Process SketchPlugin features only
64   std::shared_ptr<SketchPlugin_Feature> aFeature =
65       std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
66   if (!aFeature)
67     return aResult;
68
69   // Verify the feature by its kind
70   const std::string& aFeatureKind = aFeature->getKind();
71   // Line
72   if (aFeatureKind == SketchPlugin_Line::ID())
73     aResult = createLine(myAttributes);
74   // Circle
75   else if (aFeatureKind == SketchPlugin_Circle::ID())
76     aResult = createCircle(myAttributes);
77   // Arc
78   else if (aFeatureKind == SketchPlugin_Arc::ID())
79     aResult = createArc(myAttributes, myStorage, myFeatureConstraints);
80   // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
81   else if (aFeatureKind == SketchPlugin_Point::ID() ||
82            aFeatureKind == SketchPlugin_IntersectionPoint::ID()) {
83     AttributeEntityMap::const_iterator anIt = myAttributes.begin();
84     for (; anIt != myAttributes.end(); ++anIt)
85       if (anIt->first->id() == SketchPlugin_Point::COORD_ID()) {
86         aResult = anIt->second;
87         break;
88       }
89   }
90
91   if (aResult && !myStorage)
92     aResult->setExternal(true);
93
94   myAttributes.clear();
95   return aResult;
96 }
97
98
99
100
101
102 // ==============   Auxiliary functions   =====================================
103 EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes)
104 {
105   std::shared_ptr<GCS::Line> aNewLine(new GCS::Line);
106
107   AttributeEntityMap::const_iterator anIt = theAttributes.begin();
108   for (; anIt != theAttributes.end(); ++anIt) {
109     std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
110         std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
111     if (!aPoint)
112       continue;
113
114     if (anIt->first->id() == SketchPlugin_Line::START_ID())
115       aNewLine->p1 = *(aPoint->point());
116     else if (anIt->first->id() == SketchPlugin_Line::END_ID())
117       aNewLine->p2 = *(aPoint->point());
118   }
119
120   return EntityWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewLine));
121 }
122
123 EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes)
124 {
125   std::shared_ptr<GCS::Circle> aNewCircle(new GCS::Circle);
126
127   AttributeEntityMap::const_iterator anIt = theAttributes.begin();
128   for (; anIt != theAttributes.end(); ++anIt) {
129     if (anIt->first->id() == SketchPlugin_Circle::CENTER_ID()) {
130       std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
131           std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
132       aNewCircle->center = *(aPoint->point());
133     }
134     else if(anIt->first->id() == SketchPlugin_Circle::RADIUS_ID()) {
135       ScalarWrapperPtr aScalar =
136           std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
137       aNewCircle->rad = aScalar->scalar();
138     }
139   }
140
141   return EntityWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewCircle));
142 }
143
144 static double* createParameter(PlaneGCSSolver_Storage* theStorage)
145 {
146   return theStorage ? theStorage->createParameter() : (new double(0));
147 }
148
149 EntityWrapperPtr createArc(const AttributeEntityMap&    theAttributes,
150                            PlaneGCSSolver_Storage*      theStorage,
151                            std::list<GCSConstraintPtr>& theArcConstraints)
152 {
153   std::shared_ptr<GCS::Arc> aNewArc(new GCS::Arc);
154
155   // Base attributes of arc (center, start and end points)
156   AttributeEntityMap::const_iterator anIt = theAttributes.begin();
157   for (; anIt != theAttributes.end(); ++anIt) {
158     std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
159         std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
160     if (!aPoint)
161       continue;
162
163     if (anIt->first->id() == SketchPlugin_Arc::CENTER_ID())
164       aNewArc->center = *(aPoint->point());
165     else if (anIt->first->id() == SketchPlugin_Arc::START_ID())
166       aNewArc->start = *(aPoint->point());
167     else if (anIt->first->id() == SketchPlugin_Arc::END_ID())
168       aNewArc->end = *(aPoint->point());
169   }
170
171   // Additional atrtributes of arc necessary for PlaneGCS solver
172   // (start and end angles, radius)
173   aNewArc->startAngle = createParameter(theStorage);
174   aNewArc->endAngle   = createParameter(theStorage);
175   aNewArc->rad        = createParameter(theStorage);
176
177   static std::shared_ptr<GeomAPI_Dir2d> OX(new GeomAPI_Dir2d(1.0, 0.0));
178   std::shared_ptr<GeomAPI_Pnt2d> aCenter(
179       new GeomAPI_Pnt2d(*aNewArc->center.x, *aNewArc->center.y));
180   std::shared_ptr<GeomAPI_Pnt2d> aStart(
181       new GeomAPI_Pnt2d(*aNewArc->start.x, *aNewArc->start.y));
182
183   *aNewArc->rad = aStart->distance(aCenter);
184
185   std::shared_ptr<GeomAPI_Dir2d> aDir(new GeomAPI_Dir2d(aStart->xy()->decreased(aCenter->xy())));
186   *aNewArc->startAngle = OX->angle(aDir);
187
188   aDir = std::shared_ptr<GeomAPI_Dir2d>(
189       new GeomAPI_Dir2d((*aNewArc->end.x) - aCenter->x(), (*aNewArc->end.y) - aCenter->y()));
190   *aNewArc->endAngle = OX->angle(aDir);
191
192   if (theStorage) {
193     // Additional constaints to fix arc's extra DoF (if the arc is not external):
194     // 1. distances from center till start and end points are equal to radius
195     theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
196         aNewArc->center, aNewArc->start, aNewArc->rad)));
197     theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
198         aNewArc->center, aNewArc->end, aNewArc->rad)));
199     // 2. angles of start and end points should be equal to the arc angles
200     theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
201         aNewArc->center, aNewArc->start, aNewArc->startAngle)));
202     theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
203         aNewArc->center, aNewArc->end, aNewArc->endAngle)));
204   }
205
206   return EntityWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewArc));
207 }
208
209 bool isAttributeApplicable(const std::string& theAttrName, const std::string& theOwnerName)
210 {
211   if (theOwnerName == SketchPlugin_Arc::ID()) {
212     return theAttrName == SketchPlugin_Arc::CENTER_ID() ||
213            theAttrName == SketchPlugin_Arc::START_ID() ||
214            theAttrName == SketchPlugin_Arc::END_ID();
215   }
216   else if (theOwnerName == SketchPlugin_Circle::ID()) {
217     return theAttrName == SketchPlugin_Circle::CENTER_ID() ||
218            theAttrName == SketchPlugin_Circle::RADIUS_ID();
219   }
220   else if (theOwnerName == SketchPlugin_Line::ID()) {
221     return theAttrName == SketchPlugin_Line::START_ID() ||
222            theAttrName == SketchPlugin_Line::END_ID();
223   }
224
225   // suppose that all remaining features are points
226   return theAttrName == SketchPlugin_Point::COORD_ID();
227 }