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