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