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