Salome HOME
Changes in the presentations of features
[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
26
27 const int CONSTRAINT_TEXT_HEIGHT = 28; /// the text height of the constraint
28 const int CONSTRAINT_TEXT_SELECTION_TOLERANCE = 20; /// the text selection tolerance
29
30 // Initialization of color constants
31 int Colors::COLOR_BROWN = Quantity_NOC_BROWN;
32
33
34 GeomAPI_AISObject::GeomAPI_AISObject()
35   : GeomAPI_Interface(new Handle(AIS_InteractiveObject)())
36 {
37 }
38
39 void GeomAPI_AISObject::createShape(boost::shared_ptr<GeomAPI_Shape> theShape)
40 {
41   const TopoDS_Shape& aTDS = (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   {
47     Handle(AIS_Shape) aShapeAIS = Handle(AIS_Shape)::DownCast(anAIS);
48     if (aShapeAIS)
49     {
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   }
60   else
61     setImpl(new Handle(AIS_InteractiveObject)(new AIS_Shape(aTDS)));
62 }
63
64
65 void GeomAPI_AISObject::createDistance(boost::shared_ptr<GeomAPI_Pnt> theStartPoint,
66                                        boost::shared_ptr<GeomAPI_Pnt> theEndPoint,
67                                        boost::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
68                                        boost::shared_ptr<GeomAPI_Pln> thePlane,
69                                        double                         theDistance)
70 {
71   double aFlyout = 0;
72   if (theFlyoutPoint)
73   {
74     boost::shared_ptr<GeomAPI_Lin> aLine = 
75       boost::shared_ptr<GeomAPI_Lin>(new GeomAPI_Lin(theStartPoint, theEndPoint));
76     double aDist = aLine->distance(theFlyoutPoint);
77
78     boost::shared_ptr<GeomAPI_XYZ> aLineDir = theEndPoint->xyz()->decreased(theStartPoint->xyz());
79     boost::shared_ptr<GeomAPI_XYZ> aFOutDir = theFlyoutPoint->xyz()->decreased(theStartPoint->xyz());
80     boost::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   {
89     Handle(AIS_LengthDimension) aDimAIS = new AIS_LengthDimension(
90       theStartPoint->impl<gp_Pnt>(), theEndPoint->impl<gp_Pnt>(), 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     aDimAIS->DimensionAspect()->MakeUnitsDisplayed(false);
99     aDimAIS->SetDimensionAspect(anAspect);
100     aDimAIS->SetSelToleranceForText2d(CONSTRAINT_TEXT_SELECTION_TOLERANCE);
101     aDimAIS->SetFlyout(aFlyout);
102
103     setImpl(new Handle(AIS_InteractiveObject)(aDimAIS));
104   }
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(boost::shared_ptr<GeomAPI_Circ> theCircle,
120                                      boost::shared_ptr<GeomAPI_Pnt>  theFlyoutPoint,
121                                      double                          theRadius)
122 {
123   boost::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   boost::shared_ptr<GeomAPI_Pnt> anAnchor = theCircle->project(theFlyoutPoint);
132   boost::shared_ptr<GeomAPI_XYZ> anAnchorXYZ = anAnchor->xyz();
133   anAnchorXYZ = anAnchorXYZ->decreased(aCenter->xyz());
134   boost::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   {
143     Handle(AIS_RadiusDimension) aDimAIS = 
144       new AIS_RadiusDimension(theCircle->impl<gp_Circ>(), anAnchor->impl<gp_Pnt>());
145     aDimAIS->SetCustomValue(theRadius);
146
147     Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
148     anAspect->MakeArrows3d (Standard_False);
149     anAspect->MakeText3d(false);
150     anAspect->TextAspect()->SetHeight(CONSTRAINT_TEXT_HEIGHT);
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   }
158   else
159   {
160     // update presentation
161     Handle(AIS_RadiusDimension) aDimAIS = Handle(AIS_RadiusDimension)::DownCast(anAIS);
162     if (!aDimAIS.IsNull())
163     {
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(boost::shared_ptr<GeomAPI_Shape> theLine1,
172                                        boost::shared_ptr<GeomAPI_Shape> theLine2,
173                                        boost::shared_ptr<GeomAPI_Pnt>   theFlyoutPoint,
174                                        boost::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   {
180     Handle(AIS_ParallelRelation) aParallel = 
181       new AIS_ParallelRelation(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   }
187   else
188   {
189     Handle(AIS_ParallelRelation) aParallel = Handle(AIS_ParallelRelation)::DownCast(anAIS);
190     if (!aParallel.IsNull())
191     {
192       aParallel->SetFirstShape(theLine1->impl<TopoDS_Shape>());
193       aParallel->SetSecondShape(theLine2->impl<TopoDS_Shape>());
194       aParallel->SetPlane(aPlane);
195       if (theFlyoutPoint)
196         aParallel->SetPosition(theFlyoutPoint->impl<gp_Pnt>());
197       aParallel->Redisplay(Standard_True);
198     }
199   }
200 }
201
202 void GeomAPI_AISObject::createPerpendicular(boost::shared_ptr<GeomAPI_Shape> theLine1,
203                                             boost::shared_ptr<GeomAPI_Shape> theLine2,
204                                             boost::shared_ptr<GeomAPI_Pln>   thePlane)
205 {
206   Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
207   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
208   if (anAIS.IsNull())
209   {
210     Handle(AIS_PerpendicularRelation) aPerpendicular = 
211       new AIS_PerpendicularRelation(theLine1->impl<TopoDS_Shape>(), theLine2->impl<TopoDS_Shape>(), aPlane);
212
213     setImpl(new Handle(AIS_InteractiveObject)(aPerpendicular));
214   }
215   else
216   {
217     Handle(AIS_PerpendicularRelation) aPerpendicular = Handle(AIS_PerpendicularRelation)::DownCast(anAIS);
218     if (!aPerpendicular.IsNull())
219     {
220       aPerpendicular->SetFirstShape(theLine1->impl<TopoDS_Shape>());
221       aPerpendicular->SetSecondShape(theLine2->impl<TopoDS_Shape>());
222       aPerpendicular->SetPlane(aPlane);
223       aPerpendicular->Redisplay(Standard_True);
224     }
225   }
226 }
227
228
229 void GeomAPI_AISObject::setColor(const int& theColor)
230 {
231   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
232   if (anAIS.IsNull())
233     return ;
234   anAIS->SetColor(Quantity_Color((Quantity_NameOfColor)theColor));
235 }
236
237 void GeomAPI_AISObject::setWidth(const double& theWidth)
238 {
239   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
240   if (anAIS.IsNull())
241     return ;
242   anAIS->SetWidth(theWidth);
243 }
244
245 bool GeomAPI_AISObject::empty() const
246 {
247   Handle(AIS_InteractiveObject) anAIS = 
248     const_cast<GeomAPI_AISObject*>(this)->impl<Handle(AIS_InteractiveObject)>();
249   if (anAIS.IsNull())
250     return true;
251   return false;
252 }
253