Salome HOME
Merge branch 'Dev_1.1.0' of newgeom:newgeom into Dev_1.1.0
[modules/shaper.git] / src / GeomAPI / GeomAPI_AISObject.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        GeomAPI_AISObject.cpp
4 // Created:     25 Jun 2014
5 // Author:      Artem ZHIDKOV
6
7 #include <GeomAPI_AISObject.h>
8
9 #include <GeomAPI_Circ.h>
10 #include <GeomAPI_Dir.h>
11 #include <GeomAPI_Lin.h>
12 #include <GeomAPI_Pln.h>
13 #include <GeomAPI_Pnt.h>
14 #include <GeomAPI_Shape.h>
15 #include <GeomAPI_XYZ.h>
16
17 #include <Geom_Plane.hxx>
18 #include <TopoDS_Shape.hxx>
19 #include <Quantity_NameOfColor.hxx>
20 #include <BRepBndLib.hxx>
21
22 #include <AIS_InteractiveObject.hxx>
23 #include <AIS_InteractiveContext.hxx>
24 #include <AIS_LengthDimension.hxx>
25 #include <AIS_ParallelRelation.hxx>
26 #include <AIS_PerpendicularRelation.hxx>
27 #include <AIS_RadiusDimension.hxx>
28 #include <AIS_Shape.hxx>
29 #include <AIS_FixRelation.hxx>
30 #include <Prs3d_PointAspect.hxx>
31
32 #include <Graphic3d_AspectLine3d.hxx>
33
34 const double tolerance = 1e-7;
35
36 const int CONSTRAINT_TEXT_HEIGHT = 28;  /// the text height of the constraint
37 const int CONSTRAINT_TEXT_SELECTION_TOLERANCE = 20;  /// the text selection tolerance
38
39 GeomAPI_AISObject::GeomAPI_AISObject()
40     : GeomAPI_Interface(new Handle(AIS_InteractiveObject)())
41 {
42 }
43
44 void GeomAPI_AISObject::createShape(std::shared_ptr<GeomAPI_Shape> theShape)
45 {
46   const TopoDS_Shape& aTDS =
47       (theShape && theShape->implPtr<TopoDS_Shape>()) ?
48           theShape->impl<TopoDS_Shape>() : TopoDS_Shape();
49
50   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
51   if (!anAIS.IsNull()) {
52     Handle(AIS_Shape) aShapeAIS = Handle(AIS_Shape)::DownCast(anAIS);
53     if (aShapeAIS) {
54       // if the AIS object is displayed in the opened local context in some mode, additional
55       // AIS sub objects are created there. They should be rebuild for correct selecting.
56       // It is possible to correct it by closing local context before the shape set and opening
57       // after. Another workaround to thrown down the selection and reselecting the AIS.
58       // If there was a problem here, try the first solution with close/open local context.
59
60       aShapeAIS->Set(aTDS);
61       aShapeAIS->Redisplay(Standard_True);
62     }
63   } else
64     setImpl(new Handle(AIS_InteractiveObject)(new AIS_Shape(aTDS)));
65 }
66
67 void GeomAPI_AISObject::createDistance(std::shared_ptr<GeomAPI_Pnt> theStartPoint,
68                                        std::shared_ptr<GeomAPI_Pnt> theEndPoint,
69                                        std::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
70                                        std::shared_ptr<GeomAPI_Pln> thePlane, double theDistance)
71 {
72   double aFlyout = 0;
73   if (theFlyoutPoint) {
74     double aDist = 0.0;
75     if (theStartPoint->distance(theEndPoint) < tolerance)
76       aDist = theStartPoint->distance(theFlyoutPoint);
77     else {
78       std::shared_ptr<GeomAPI_Lin> aLine = std::shared_ptr<GeomAPI_Lin>(
79           new GeomAPI_Lin(theStartPoint, theEndPoint));
80       aDist = aLine->distance(theFlyoutPoint);
81     }
82
83     std::shared_ptr<GeomAPI_XYZ> aLineDir = theEndPoint->xyz()->decreased(theStartPoint->xyz());
84     std::shared_ptr<GeomAPI_XYZ> aFOutDir = theFlyoutPoint->xyz()->decreased(
85         theStartPoint->xyz());
86     std::shared_ptr<GeomAPI_XYZ> aNorm = thePlane->direction()->xyz();
87     if (aLineDir->cross(aFOutDir)->dot(aNorm) < 0)
88       aDist = -aDist;
89     aFlyout = aDist;
90   }
91
92   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
93   if (anAIS.IsNull()) {
94     Handle(AIS_LengthDimension) aDimAIS = new AIS_LengthDimension(theStartPoint->impl<gp_Pnt>(),
95                                                                   theEndPoint->impl<gp_Pnt>(),
96                                                                   thePlane->impl<gp_Pln>());
97     aDimAIS->SetCustomValue(theDistance);
98
99     Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
100     anAspect->MakeArrows3d(Standard_False);
101     anAspect->MakeText3d(Standard_False);
102     anAspect->TextAspect()->SetHeight(CONSTRAINT_TEXT_HEIGHT);
103     anAspect->MakeTextShaded(Standard_True);
104     anAspect->ArrowAspect()->SetLength(theDistance / 10.);
105     aDimAIS->DimensionAspect()->MakeUnitsDisplayed(false);
106     aDimAIS->SetDimensionAspect(anAspect);
107     aDimAIS->SetSelToleranceForText2d(CONSTRAINT_TEXT_SELECTION_TOLERANCE);
108     aDimAIS->SetFlyout(aFlyout);
109
110     setImpl(new Handle(AIS_InteractiveObject)(aDimAIS));
111   } else {
112     // update presentation
113     Handle(AIS_LengthDimension) aDimAIS = Handle(AIS_LengthDimension)::DownCast(anAIS);
114     if (!aDimAIS.IsNull()) {
115       aDimAIS->SetMeasuredGeometry(theStartPoint->impl<gp_Pnt>(), theEndPoint->impl<gp_Pnt>(),
116                                    thePlane->impl<gp_Pln>());
117       aDimAIS->SetCustomValue(theDistance);
118       aDimAIS->SetFlyout(aFlyout);
119
120       aDimAIS->Redisplay(Standard_True);
121     }
122   }
123 }
124
125 void GeomAPI_AISObject::createRadius(std::shared_ptr<GeomAPI_Circ> theCircle,
126                                      std::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
127                                      double theRadius)
128 {
129   std::shared_ptr<GeomAPI_Pnt> aCenter = theCircle->center();
130
131   // TODO: a bug in AIS_RadiusDimension:
132   // The anchor point can't be myCirc.Location() - an exception is raised.
133   // But we need exactly this case...
134   // We want to show a radius dimension starting from the circle centre and 
135   // ending at the user-defined point.
136   // Also, if anchor point coincides with myP2, the radius dimension is not displayed at all.
137   std::shared_ptr<GeomAPI_Pnt> anAnchor = theCircle->project(theFlyoutPoint);
138   std::shared_ptr<GeomAPI_XYZ> anAnchorXYZ = anAnchor->xyz();
139   anAnchorXYZ = anAnchorXYZ->decreased(aCenter->xyz());
140   std::shared_ptr<GeomAPI_Dir> aDeltaDir(new GeomAPI_Dir(anAnchorXYZ));
141   const double aDelta = 1e-3;
142   anAnchor->setX(anAnchor->x() + aDelta * aDeltaDir->x());
143   anAnchor->setY(anAnchor->y() + aDelta * aDeltaDir->y());
144   anAnchor->setZ(anAnchor->z() + aDelta * aDeltaDir->z());
145
146   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
147   if (anAIS.IsNull()) {
148     Handle(AIS_RadiusDimension) aDimAIS = new AIS_RadiusDimension(theCircle->impl<gp_Circ>(),
149                                                                   anAnchor->impl<gp_Pnt>());
150     aDimAIS->SetCustomValue(theRadius);
151
152     Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
153     anAspect->MakeArrows3d(Standard_False);
154     anAspect->MakeText3d(false);
155     anAspect->TextAspect()->SetHeight(CONSTRAINT_TEXT_HEIGHT);
156     anAspect->ArrowAspect()->SetLength(theRadius / 5.);
157     anAspect->MakeTextShaded(false);
158     aDimAIS->DimensionAspect()->MakeUnitsDisplayed(false);
159     aDimAIS->SetDimensionAspect(anAspect);
160     aDimAIS->SetSelToleranceForText2d(CONSTRAINT_TEXT_SELECTION_TOLERANCE);
161
162     setImpl(new Handle(AIS_InteractiveObject)(aDimAIS));
163   } else {
164     // update presentation
165     Handle(AIS_RadiusDimension) aDimAIS = Handle(AIS_RadiusDimension)::DownCast(anAIS);
166     if (!aDimAIS.IsNull()) {
167       aDimAIS->SetMeasuredGeometry(theCircle->impl<gp_Circ>(), anAnchor->impl<gp_Pnt>());
168       aDimAIS->SetCustomValue(theRadius);
169       aDimAIS->Redisplay(Standard_True);
170     }
171   }
172 }
173
174 void GeomAPI_AISObject::createParallel(std::shared_ptr<GeomAPI_Shape> theLine1,
175                                        std::shared_ptr<GeomAPI_Shape> theLine2,
176                                        std::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
177                                        std::shared_ptr<GeomAPI_Pln> thePlane)
178 {
179   Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
180   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
181   if (anAIS.IsNull()) {
182     Handle(AIS_ParallelRelation) aParallel = new AIS_ParallelRelation(
183         theLine1->impl<TopoDS_Shape>(), theLine2->impl<TopoDS_Shape>(), aPlane);
184     if (theFlyoutPoint)
185       aParallel->SetPosition(theFlyoutPoint->impl<gp_Pnt>());
186
187     setImpl(new Handle(AIS_InteractiveObject)(aParallel));
188   } else {
189     Handle(AIS_ParallelRelation) aParallel = Handle(AIS_ParallelRelation)::DownCast(anAIS);
190     if (!aParallel.IsNull()) {
191       aParallel->SetFirstShape(theLine1->impl<TopoDS_Shape>());
192       aParallel->SetSecondShape(theLine2->impl<TopoDS_Shape>());
193       aParallel->SetPlane(aPlane);
194       if (theFlyoutPoint)
195         aParallel->SetPosition(theFlyoutPoint->impl<gp_Pnt>());
196       aParallel->Redisplay(Standard_True);
197     }
198   }
199 }
200
201 void GeomAPI_AISObject::createPerpendicular(std::shared_ptr<GeomAPI_Shape> theLine1,
202                                             std::shared_ptr<GeomAPI_Shape> theLine2,
203                                             std::shared_ptr<GeomAPI_Pln> thePlane)
204 {
205   Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
206   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
207   if (anAIS.IsNull()) {
208     Handle(AIS_PerpendicularRelation) aPerpendicular = new AIS_PerpendicularRelation(
209         theLine1->impl<TopoDS_Shape>(), theLine2->impl<TopoDS_Shape>(), aPlane);
210
211     setImpl(new Handle(AIS_InteractiveObject)(aPerpendicular));
212   } else {
213     Handle(AIS_PerpendicularRelation) aPerpendicular = Handle(AIS_PerpendicularRelation)::DownCast(
214         anAIS);
215     if (!aPerpendicular.IsNull()) {
216       aPerpendicular->SetFirstShape(theLine1->impl<TopoDS_Shape>());
217       aPerpendicular->SetSecondShape(theLine2->impl<TopoDS_Shape>());
218       aPerpendicular->SetPlane(aPlane);
219       aPerpendicular->Redisplay(Standard_True);
220     }
221   }
222 }
223
224
225 void GeomAPI_AISObject::createFixed(std::shared_ptr<GeomAPI_Shape> theShape,
226                                     std::shared_ptr<GeomAPI_Pln> thePlane)
227 {
228   Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
229   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
230   TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
231   Handle(AIS_FixRelation) aFixPrs;
232   if (anAIS.IsNull()) {
233     aFixPrs = new AIS_FixRelation(aShape, aPlane);
234
235     setImpl(new Handle(AIS_InteractiveObject)(aFixPrs));
236   } else {
237     aFixPrs = Handle(AIS_FixRelation)::DownCast(anAIS);
238     if (!aFixPrs.IsNull()) {
239       aFixPrs->SetFirstShape(aShape);
240       aFixPrs->SetPlane(aPlane);
241       aFixPrs->Redisplay(Standard_True);
242     }
243   }
244   if (!aFixPrs.IsNull()) {
245     Bnd_Box aBox;
246     BRepBndLib::Add(aShape, aBox);
247     double aXmin, aXmax, aYmin, aYmax, aZmin, aZmax;
248     aBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
249     gp_Pnt aXYZ1(aXmin, aXmax, aYmin);
250     gp_Pnt aXYZ2(aXmax, aYmax, aZmax);
251     double aDist = aXYZ1.Distance(aXYZ2);
252     if (aDist > Precision::Confusion()) {
253       aFixPrs->SetArrowSize(aDist/8.);
254     }
255   }
256 }
257
258 void GeomAPI_AISObject::setColor(const int& theColor)
259 {
260   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
261   if (anAIS.IsNull())
262     return;
263   Quantity_Color aColor((Quantity_NameOfColor) theColor);
264   anAIS->SetColor(aColor);
265   Handle(AIS_Dimension) aDimAIS = Handle(AIS_Dimension)::DownCast(anAIS);
266   if (!aDimAIS.IsNull()) {
267     aDimAIS->DimensionAspect()->SetCommonColor(aColor);
268   }
269   Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
270   aContext->SetColor(anAIS, aColor, false);
271 }
272
273 bool GeomAPI_AISObject::setWidth(const double& theWidth)
274 {
275   bool isChanged = false;
276   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
277   if (!anAIS.IsNull()) {
278     isChanged = anAIS->Width() != theWidth;
279     if (isChanged)
280       anAIS->SetWidth(theWidth);
281   }
282   return isChanged;
283 }
284
285 bool GeomAPI_AISObject::setColor(int theR, int theG, int theB)
286 {
287   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
288   if (anAIS.IsNull())
289     return false;
290   Quantity_Color aColor(theR / 255., theG / 255., theB / 255., Quantity_TOC_RGB);
291   Quantity_Color aCurrentColor;
292   anAIS->Color(aCurrentColor);
293   // do not set the same color to the presentation
294   if (aColor.IsEqual(aCurrentColor))
295     return false;
296
297   anAIS->SetColor(aColor);
298   Handle(AIS_Dimension) aDimAIS = Handle(AIS_Dimension)::DownCast(anAIS);
299   if (!aDimAIS.IsNull()) {
300     aDimAIS->DimensionAspect()->SetCommonColor(aColor);
301   }
302   Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
303   aContext->SetColor(anAIS, aColor, false);
304   return true;
305 }
306
307 void GeomAPI_AISObject::getColor(int& theR, int& theG, int& theB)
308 {
309   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
310   if (anAIS.IsNull())
311     return;
312
313   Quantity_Color aColor = anAIS->Color();
314   theR = (int)(aColor.Red()*255.);
315   theG = (int)(aColor.Green()*255.);
316   theB = (int)(aColor.Blue()*255.);
317 }
318
319 bool GeomAPI_AISObject::empty() const
320 {
321   Handle(AIS_InteractiveObject) anAIS = const_cast<GeomAPI_AISObject*>(this)
322       ->impl<Handle(AIS_InteractiveObject)>();
323   if (anAIS.IsNull())
324     return true;
325   return false;
326 }
327
328 int GeomAPI_AISObject::getShapeType() const
329 {
330   Handle(AIS_InteractiveObject) anAIS = const_cast<GeomAPI_AISObject*>(this)
331       ->impl<Handle(AIS_InteractiveObject)>();
332   if (!anAIS.IsNull()) {
333     Handle(AIS_Shape) aAISShape = Handle(AIS_Shape)::DownCast(anAIS);
334     if (!aAISShape.IsNull()) {
335       return aAISShape->Shape().ShapeType();
336     }
337   }
338   return -1;
339 }
340
341 void GeomAPI_AISObject::setPointMarker(int theType, double theScale)
342 {
343   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
344   if (!anAIS.IsNull()) {
345     Handle(AIS_Drawer) aDrawer = anAIS->Attributes();
346     if (aDrawer->HasPointAspect()) {
347       Handle(Prs3d_PointAspect) aPA = aDrawer->PointAspect();
348       aPA->SetTypeOfMarker((Aspect_TypeOfMarker)theType);
349       aPA->SetScale(theScale);
350     } else {
351       Quantity_NameOfColor aCol = Quantity_NOC_YELLOW;
352       aDrawer->SetPointAspect(new Prs3d_PointAspect((Aspect_TypeOfMarker)theType, aCol, theScale));
353     }
354   }
355 }
356
357 bool GeomAPI_AISObject::setLineStyle(int theStyle)
358 {
359   bool isChanged = false;
360   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
361   if (!anAIS.IsNull()) {
362     Handle(AIS_Drawer) aDrawer = anAIS->Attributes();
363     Handle(Prs3d_LineAspect) aLineAspect;
364
365     Aspect_TypeOfLine aType = (Aspect_TypeOfLine)theStyle;
366     if (aDrawer->HasLineAspect()) {
367       aLineAspect = aDrawer->LineAspect();
368     }
369     if (aDrawer->HasWireAspect()) {
370       aLineAspect = aDrawer->WireAspect();
371     }
372     Quantity_Color aCurrentColor;
373     Aspect_TypeOfLine aCurrentType;
374     Standard_Real aCurrentWidth;
375     aLineAspect->Aspect()->Values(aCurrentColor, aCurrentType, aCurrentWidth);
376     isChanged = aType != aCurrentType;
377     if (isChanged) {
378       aLineAspect->SetTypeOfLine(aType);
379     }
380   }
381   return isChanged;
382 }
383
384
385 bool GeomAPI_AISObject::setTransparensy(double theVal)
386 {
387   bool isChanged = false;
388   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
389   if (!anAIS.IsNull()) {
390     Handle(AIS_InteractiveContext) aContext = anAIS->GetContext();
391     if (!aContext.IsNull()) {
392       double aCurrentValue = anAIS->Transparency();
393       isChanged = aCurrentValue != theVal;
394       if (isChanged)
395         aContext->SetTransparency(anAIS, theVal, false);
396     }
397   }
398  return isChanged;
399 }