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