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