Salome HOME
Merge branch 'master' of newgeom:newgeom
[modules/shaper.git] / src / PartSet / PartSet_Tools.cpp
1 // File:        PartSet_Tools.h
2 // Created:     28 Apr 2014
3 // Author:      Natalia ERMOLAEVA
4
5 #include <PartSet_Tools.h>
6
7 #include <ModelAPI_Data.h>
8 #include <ModelAPI_AttributeDouble.h>
9 #include <ModelAPI_AttributeRefList.h>
10 #include <ModelAPI_Document.h>
11
12 #include <GeomDataAPI_Point.h>
13 #include <GeomDataAPI_Dir.h>
14 #include <GeomDataAPI_Point2D.h>
15 #include <GeomAPI_Pln.h>
16 #include <GeomAPI_Pnt2d.h>
17 #include <GeomAPI_Pnt.h>
18
19 #include <GeomAPI_Dir.h>
20 #include <GeomAPI_XYZ.h>
21
22 #include <SketchPlugin_Feature.h>
23 #include <SketchPlugin_Sketch.h>
24 #include <SketchPlugin_ConstraintCoincidence.h>
25 #include <SketchPlugin_Constraint.h>
26
27 #include <PartSet_FeatureLinePrs.h>
28 #include <PartSet_FeaturePointPrs.h>
29 #include <PartSet_FeatureCirclePrs.h>
30 #include <PartSet_FeatureArcPrs.h>
31
32 #include <PartSet_ConstraintLengthPrs.h>
33 #include <PartSet_ConstraintRadiusPrs.h>
34 #include <PartSet_ConstraintDistancePrs.h>
35
36 #include <XGUI_ViewerPrs.h>
37
38 #include <V3d_View.hxx>
39 #include <gp_Pln.hxx>
40 #include <ProjLib.hxx>
41 #include <ElSLib.hxx>
42 #include <Geom_Line.hxx>
43 #include <GeomAPI_ProjectPointOnCurve.hxx>
44
45 #ifdef _DEBUG
46 #include <QDebug>
47 #endif
48
49 const double PRECISION_TOLERANCE = 0.000001;
50
51 gp_Pnt PartSet_Tools::convertClickToPoint(QPoint thePoint, Handle(V3d_View) theView)
52 {
53   if (theView.IsNull())
54     return gp_Pnt();
55
56   V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
57   theView->Eye(XEye, YEye, ZEye);
58
59   theView->At(XAt, YAt, ZAt);
60   gp_Pnt EyePoint(XEye, YEye, ZEye);
61   gp_Pnt AtPoint(XAt, YAt, ZAt);
62
63   gp_Vec EyeVector(EyePoint, AtPoint);
64   gp_Dir EyeDir(EyeVector);
65
66   gp_Pln PlaneOfTheView = gp_Pln(AtPoint, EyeDir);
67   Standard_Real X, Y, Z;
68   theView->Convert(thePoint.x(), thePoint.y(), X, Y, Z);
69   gp_Pnt ConvertedPoint(X, Y, Z);
70
71   gp_Pnt2d ConvertedPointOnPlane = ProjLib::Project(PlaneOfTheView, ConvertedPoint);
72   gp_Pnt ResultPoint = ElSLib::Value(ConvertedPointOnPlane.X(), ConvertedPointOnPlane.Y(), PlaneOfTheView);
73   return ResultPoint;
74 }
75
76 void PartSet_Tools::convertTo2D(const gp_Pnt& thePoint, FeaturePtr theSketch,
77                                 Handle(V3d_View) theView, double& theX, double& theY)
78 {
79   if (!theSketch)
80     return;
81
82   AttributeDoublePtr anAttr;
83   boost::shared_ptr<ModelAPI_Data> aData = theSketch->data();
84
85   boost::shared_ptr<GeomDataAPI_Point> anOrigin = 
86     boost::dynamic_pointer_cast<GeomDataAPI_Point>(aData->attribute(SKETCH_ATTR_ORIGIN));
87
88   boost::shared_ptr<GeomDataAPI_Dir> aX = 
89     boost::dynamic_pointer_cast<GeomDataAPI_Dir>(aData->attribute(SKETCH_ATTR_DIRX));
90   boost::shared_ptr<GeomDataAPI_Dir> anY = 
91     boost::dynamic_pointer_cast<GeomDataAPI_Dir>(aData->attribute(SKETCH_ATTR_DIRY));
92
93   gp_Pnt anOriginPnt(anOrigin->x(), anOrigin->y(), anOrigin->z());
94   gp_Vec aVec(anOriginPnt, thePoint);
95
96   if (!theView.IsNull())
97   {
98     V3d_Coordinate XEye, YEye, ZEye, XAt, YAt, ZAt;
99     theView->Eye(XEye, YEye, ZEye);
100
101     theView->At(XAt, YAt, ZAt);
102     gp_Pnt EyePoint(XEye, YEye, ZEye);
103     gp_Pnt AtPoint(XAt, YAt, ZAt);
104
105     gp_Vec anEyeVec(EyePoint, AtPoint);
106     anEyeVec.Normalize();
107
108     boost::shared_ptr<GeomDataAPI_Dir> aNormal = 
109                   boost::dynamic_pointer_cast<GeomDataAPI_Dir>(aData->attribute(SKETCH_ATTR_NORM));
110     gp_Vec aNormalVec(aNormal->x(), aNormal->y(), aNormal->z());
111
112     double aDen = anEyeVec * aNormalVec;
113     double aLVec = aDen != 0 ? aVec * aNormalVec / aDen : DBL_MAX;
114
115     gp_Vec aDeltaVec = anEyeVec*aLVec;
116     aVec = aVec - aDeltaVec;
117   }
118   theX = aVec.X() * aX->x() + aVec.Y() * aX->y() + aVec.Z() * aX->z();
119   theY = aVec.X() * anY->x() + aVec.Y() * anY->y() + aVec.Z() * anY->z();
120 }
121
122 void PartSet_Tools::convertTo3D(const double theX, const double theY,
123                                 FeaturePtr theSketch,
124                                 gp_Pnt& thePoint)
125 {
126   if (!theSketch)
127     return;
128
129   boost::shared_ptr<ModelAPI_Data> aData = theSketch->data();
130
131   boost::shared_ptr<GeomDataAPI_Point> aC = 
132     boost::dynamic_pointer_cast<GeomDataAPI_Point>(aData->attribute(SKETCH_ATTR_ORIGIN));
133   boost::shared_ptr<GeomDataAPI_Dir> aX = 
134     boost::dynamic_pointer_cast<GeomDataAPI_Dir>(aData->attribute(SKETCH_ATTR_DIRX));
135   boost::shared_ptr<GeomDataAPI_Dir> aY = 
136     boost::dynamic_pointer_cast<GeomDataAPI_Dir>(aData->attribute(SKETCH_ATTR_DIRY));
137
138   boost::shared_ptr<GeomAPI_XYZ> aSum = aC->pnt()->xyz()->added(
139     aX->dir()->xyz()->multiplied(theX))->added(aY->dir()->xyz()->multiplied(theY));
140
141   boost::shared_ptr<GeomAPI_Pnt> aPoint = boost::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(aSum));
142   thePoint = gp_Pnt(aPoint->x(), aPoint->y(), aPoint->z());
143 }
144
145 boost::shared_ptr<PartSet_FeaturePrs> PartSet_Tools::createFeaturePrs(const std::string& theKind,
146                                                                       FeaturePtr theSketch,
147                                                                       FeaturePtr theFeature)
148 {
149   boost::shared_ptr<PartSet_FeaturePrs> aFeaturePrs;
150
151   if (theKind == PartSet_FeaturePointPrs::getKind()) {
152     aFeaturePrs = boost::shared_ptr<PartSet_FeaturePrs>(new PartSet_FeaturePointPrs(theSketch));
153   }
154   else if (theKind == PartSet_FeatureLinePrs::getKind()) {
155     aFeaturePrs = boost::shared_ptr<PartSet_FeaturePrs>(new PartSet_FeatureLinePrs(theSketch));
156   }
157   else if (theKind == PartSet_FeatureCirclePrs::getKind()) {
158     aFeaturePrs = boost::shared_ptr<PartSet_FeaturePrs>(new PartSet_FeatureCirclePrs(theSketch));
159   }
160   else if (theKind == PartSet_FeatureArcPrs::getKind()) {
161     aFeaturePrs = boost::shared_ptr<PartSet_FeaturePrs>(new PartSet_FeatureArcPrs(theSketch));
162   }
163   else if (theKind == PartSet_ConstraintLengthPrs::getKind()) {
164     aFeaturePrs = boost::shared_ptr<PartSet_FeaturePrs>(new PartSet_ConstraintLengthPrs(theSketch));
165   }
166   else if (theKind == PartSet_ConstraintRadiusPrs::getKind()) {
167     aFeaturePrs = boost::shared_ptr<PartSet_ConstraintRadiusPrs>(new PartSet_ConstraintRadiusPrs(theSketch));
168   }
169   else if (theKind == PartSet_ConstraintDistancePrs::getKind()) {
170     aFeaturePrs = boost::shared_ptr<PartSet_ConstraintDistancePrs>(new PartSet_ConstraintDistancePrs(theSketch));
171   }
172
173
174   if (theFeature && aFeaturePrs)
175     aFeaturePrs->init(theFeature);
176
177   return aFeaturePrs;
178 }
179
180 FeaturePtr PartSet_Tools::nearestFeature(QPoint thePoint, Handle_V3d_View theView,
181                                          FeaturePtr theSketch,
182                                          const std::list<XGUI_ViewerPrs>& theFeatures)
183 {
184   double aX, anY;
185   gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(thePoint, theView);
186   PartSet_Tools::convertTo2D(aPoint, theSketch, theView, aX, anY);
187
188   FeaturePtr aFeature;
189   std::list<XGUI_ViewerPrs>::const_iterator anIt = theFeatures.begin(), aLast = theFeatures.end();
190
191   FeaturePtr aDeltaFeature;   
192   double aMinDelta = -1;
193   XGUI_ViewerPrs aPrs;
194   for (; anIt != aLast; anIt++) {
195     aPrs = *anIt;
196     if (!aPrs.feature())
197       continue;
198     boost::shared_ptr<SketchPlugin_Feature> aSketchFeature = 
199                            boost::dynamic_pointer_cast<SketchPlugin_Feature>(aPrs.feature());
200     if (!aSketchFeature)
201       continue;
202     double aDelta = aSketchFeature->distanceToPoint(
203                                boost::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aX, anY)));
204     if (aMinDelta < 0 || aMinDelta > aDelta) {
205       aMinDelta = aDelta;
206       aDeltaFeature = aPrs.feature();
207     }
208   }
209   return aDeltaFeature;
210 }
211
212 boost::shared_ptr<ModelAPI_Document> PartSet_Tools::document()
213 {
214   return ModelAPI_PluginManager::get()->rootDocument();
215 }
216
217 void PartSet_Tools::setFeaturePoint(FeaturePtr theFeature, double theX, double theY,
218                                     const std::string& theAttribute)
219 {
220   if (!theFeature)
221     return;
222   boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
223   boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
224         boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(theAttribute));
225   if (aPoint)
226     aPoint->setValue(theX, theY);
227 }
228
229 void PartSet_Tools::setFeatureValue(FeaturePtr theFeature, double theValue,
230                                     const std::string& theAttribute)
231 {
232   if (!theFeature)
233     return;
234   boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
235   AttributeDoublePtr anAttribute =
236         boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aData->attribute(theAttribute));
237   if (anAttribute)
238     anAttribute->setValue(theValue);
239 }
240
241 double PartSet_Tools::featureValue(FeaturePtr theFeature, const std::string& theAttribute,
242                                    bool& isValid)
243 {
244   isValid = false;
245   double aValue;
246   if (theFeature) {
247     boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
248     AttributeDoublePtr anAttribute =
249           boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aData->attribute(theAttribute));
250     if (anAttribute) {
251       aValue = anAttribute->value();
252       isValid = true;
253     }
254   }
255   return aValue;
256 }
257
258 FeaturePtr PartSet_Tools::feature(FeaturePtr theFeature, const std::string& theAttribute,
259                                   const std::string& theKind)
260 {
261   FeaturePtr aFeature;
262   if (!theFeature)
263     return aFeature;
264
265   boost::shared_ptr<ModelAPI_Data> aData = theFeature->data();
266   boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = 
267           boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aData->attribute(theAttribute));
268   if (anAttr) {
269     aFeature = anAttr->feature();
270     if (!theKind.empty() && aFeature && aFeature->getKind() != theKind) {
271       aFeature = FeaturePtr();
272     }
273   }
274   return aFeature;
275 }
276
277 void PartSet_Tools::createConstraint(FeaturePtr theSketch,
278                                      boost::shared_ptr<GeomDataAPI_Point2D> thePoint1,
279                                      boost::shared_ptr<GeomDataAPI_Point2D> thePoint2)
280 {
281   boost::shared_ptr<ModelAPI_Document> aDoc = document();
282   FeaturePtr aFeature = aDoc->addFeature(SKETCH_CONSTRAINT_COINCIDENCE_KIND);
283
284   if (theSketch) {
285     boost::shared_ptr<SketchPlugin_Feature> aSketch = 
286                            boost::dynamic_pointer_cast<SketchPlugin_Feature>(theSketch);
287     aSketch->addSub(aFeature);
288   }
289
290   boost::shared_ptr<ModelAPI_Data> aData = aFeature->data();
291
292   boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef1 =
293         boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aData->attribute(CONSTRAINT_ATTR_ENTITY_A));
294   aRef1->setAttr(thePoint1);
295
296   boost::shared_ptr<ModelAPI_AttributeRefAttr> aRef2 =
297         boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aData->attribute(CONSTRAINT_ATTR_ENTITY_B));
298   aRef2->setAttr(thePoint2);
299
300   if (aFeature) // TODO: generate an error if feature was not created
301     aFeature->execute();
302 }
303
304 void PartSet_Tools::setConstraints(FeaturePtr theSketch, FeaturePtr theFeature,
305                                    const std::string& theAttribute, double theX, double theY)
306 {
307   // find a feature point by the selection mode
308   //boost::shared_ptr<GeomDataAPI_Point2D> aPoint = featurePoint(theMode);
309   boost::shared_ptr<GeomDataAPI_Point2D> aPoint =
310         boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->data()->attribute(theAttribute));
311   if (!aPoint)
312     return;
313
314   // get all sketch features. If the point with the given coordinates belong to any sketch feature,
315   // the constraint is created between the feature point and the found sketch point
316   boost::shared_ptr<ModelAPI_Data> aData = theSketch->data();
317   boost::shared_ptr<ModelAPI_AttributeRefList> aRefList =
318         boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(aData->attribute(SKETCH_ATTR_FEATURES));
319
320   std::list<FeaturePtr > aFeatures = aRefList->list();
321   std::list<FeaturePtr >::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end();
322   for (; anIt != aLast; anIt++)
323   {
324     FeaturePtr aFeature = *anIt;
325     boost::shared_ptr<GeomDataAPI_Point2D> aFPoint;// = aFeature->findPoint(theX, theY);
326     if (aFPoint)
327       PartSet_Tools::createConstraint(theSketch, aFPoint, aPoint);
328   }
329 }
330
331 boost::shared_ptr<GeomDataAPI_Point2D> PartSet_Tools::findPoint(FeaturePtr theFeature,
332                                                                 double theX, double theY)
333 {
334   boost::shared_ptr<PartSet_FeaturePrs> aFeaturePrs = PartSet_Tools::createFeaturePrs(
335                                            theFeature->getKind(), FeaturePtr(), theFeature);
336
337   boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D;
338   if (aFeaturePrs)
339     aPoint2D = aFeaturePrs->findPoint(theFeature, theX, theY);
340
341   return aPoint2D;
342 }
343
344 boost::shared_ptr<GeomAPI_Pln> PartSet_Tools::sketchPlane(FeaturePtr theSketch)
345 {
346   boost::shared_ptr<GeomAPI_Pln> aPlane;
347   double aA, aB, aC, aD;
348
349   boost::shared_ptr<ModelAPI_Data> aData = theSketch->data();
350   boost::shared_ptr<GeomDataAPI_Point> anOrigin = 
351     boost::dynamic_pointer_cast<GeomDataAPI_Point>(aData->attribute(SKETCH_ATTR_ORIGIN));
352   boost::shared_ptr<GeomDataAPI_Dir> aNormal = 
353     boost::dynamic_pointer_cast<GeomDataAPI_Dir>(aData->attribute(SKETCH_ATTR_NORM));
354   aA = aNormal->x();
355   aB = aNormal->y();
356   aC = aNormal->z();
357   aD = 0;
358
359   aPlane = boost::shared_ptr<GeomAPI_Pln>(new GeomAPI_Pln(aA, aB, aC, aD));
360   return aPlane;
361 }
362
363 boost::shared_ptr<GeomAPI_Pnt> PartSet_Tools::point3D(
364                                                 boost::shared_ptr<GeomAPI_Pnt2d> thePoint2D,
365                                                 FeaturePtr theSketch)
366 {
367   boost::shared_ptr<GeomAPI_Pnt> aPoint;
368   if (!theSketch || !thePoint2D)
369     return aPoint;
370
371   boost::shared_ptr<GeomDataAPI_Point> aC = 
372     boost::dynamic_pointer_cast<GeomDataAPI_Point>(theSketch->data()->attribute(SKETCH_ATTR_ORIGIN));
373   boost::shared_ptr<GeomDataAPI_Dir> aX = 
374     boost::dynamic_pointer_cast<GeomDataAPI_Dir>(theSketch->data()->attribute(SKETCH_ATTR_DIRX));
375   boost::shared_ptr<GeomDataAPI_Dir> aY = 
376     boost::dynamic_pointer_cast<GeomDataAPI_Dir>(theSketch->data()->attribute(SKETCH_ATTR_DIRY));
377
378   return thePoint2D->to3D(aC->pnt(), aX->dir(), aY->dir());
379 }
380
381 bool PartSet_Tools::isConstraintFeature(const std::string& theKind)
382 {
383   return theKind == PartSet_ConstraintLengthPrs::getKind() ||
384          theKind == PartSet_ConstraintDistancePrs::getKind() ||
385          theKind == PartSet_ConstraintRadiusPrs::getKind();
386 }