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