Salome HOME
Issue #117: The same for Radius dimensions
[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 const int CONSTRAINT_TEXT_HEIGHT = 28;  /// the text height of the constraint
27 const int CONSTRAINT_TEXT_SELECTION_TOLERANCE = 20;  /// the text selection tolerance
28
29 // Initialization of color constants
30 int Colors::COLOR_BROWN = Quantity_NOC_BROWN;
31 int Colors::COLOR_RED = Quantity_NOC_RED;
32 int Colors::COLOR_GREEN = Quantity_NOC_GREEN;
33 int Colors::COLOR_BLUE = Quantity_NOC_BLUE1;
34
35 GeomAPI_AISObject::GeomAPI_AISObject()
36     : GeomAPI_Interface(new Handle(AIS_InteractiveObject)())
37 {
38 }
39
40 void GeomAPI_AISObject::createShape(boost::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(boost::shared_ptr<GeomAPI_Pnt> theStartPoint,
64                                        boost::shared_ptr<GeomAPI_Pnt> theEndPoint,
65                                        boost::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
66                                        boost::shared_ptr<GeomAPI_Pln> thePlane, double theDistance)
67 {
68   double aFlyout = 0;
69   if (theFlyoutPoint) {
70     boost::shared_ptr<GeomAPI_Lin> aLine = boost::shared_ptr<GeomAPI_Lin>(
71         new GeomAPI_Lin(theStartPoint, theEndPoint));
72     double aDist = aLine->distance(theFlyoutPoint);
73
74     boost::shared_ptr<GeomAPI_XYZ> aLineDir = theEndPoint->xyz()->decreased(theStartPoint->xyz());
75     boost::shared_ptr<GeomAPI_XYZ> aFOutDir = theFlyoutPoint->xyz()->decreased(
76         theStartPoint->xyz());
77     boost::shared_ptr<GeomAPI_XYZ> aNorm = thePlane->direction()->xyz();
78     if (aLineDir->cross(aFOutDir)->dot(aNorm) < 0)
79       aDist = -aDist;
80     aFlyout = aDist;
81   }
82
83   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
84   if (anAIS.IsNull()) {
85     Handle(AIS_LengthDimension) aDimAIS = new AIS_LengthDimension(theStartPoint->impl<gp_Pnt>(),
86                                                                   theEndPoint->impl<gp_Pnt>(),
87                                                                   thePlane->impl<gp_Pln>());
88     aDimAIS->SetCustomValue(theDistance);
89
90     Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
91     anAspect->MakeArrows3d(Standard_False);
92     anAspect->MakeText3d(false);
93     anAspect->TextAspect()->SetHeight(CONSTRAINT_TEXT_HEIGHT);
94     anAspect->MakeTextShaded(false);
95     anAspect->ArrowAspect()->SetLength(theDistance / 10.);
96     aDimAIS->DimensionAspect()->MakeUnitsDisplayed(false);
97     aDimAIS->SetDimensionAspect(anAspect);
98     aDimAIS->SetSelToleranceForText2d(CONSTRAINT_TEXT_SELECTION_TOLERANCE);
99     aDimAIS->SetFlyout(aFlyout);
100
101     setImpl(new Handle(AIS_InteractiveObject)(aDimAIS));
102   } else {
103     // update presentation
104     Handle(AIS_LengthDimension) aDimAIS = Handle(AIS_LengthDimension)::DownCast(anAIS);
105     if (!aDimAIS.IsNull()) {
106       aDimAIS->SetMeasuredGeometry(theStartPoint->impl<gp_Pnt>(), theEndPoint->impl<gp_Pnt>(),
107                                    thePlane->impl<gp_Pln>());
108       aDimAIS->SetCustomValue(theDistance);
109       aDimAIS->SetFlyout(aFlyout);
110
111       aDimAIS->Redisplay(Standard_True);
112     }
113   }
114 }
115
116 void GeomAPI_AISObject::createRadius(boost::shared_ptr<GeomAPI_Circ> theCircle,
117                                      boost::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
118                                      double theRadius)
119 {
120   boost::shared_ptr<GeomAPI_Pnt> aCenter = theCircle->center();
121
122   // TODO: a bug in AIS_RadiusDimension:
123   // The anchor point can't be myCirc.Location() - an exception is raised.
124   // But we need exactly this case...
125   // We want to show a radius dimension starting from the circle centre and 
126   // ending at the user-defined point.
127   // Also, if anchor point coincides with myP2, the radius dimension is not displayed at all.
128   boost::shared_ptr<GeomAPI_Pnt> anAnchor = theCircle->project(theFlyoutPoint);
129   boost::shared_ptr<GeomAPI_XYZ> anAnchorXYZ = anAnchor->xyz();
130   anAnchorXYZ = anAnchorXYZ->decreased(aCenter->xyz());
131   boost::shared_ptr<GeomAPI_Dir> aDeltaDir(new GeomAPI_Dir(anAnchorXYZ));
132   const double aDelta = 1e-3;
133   anAnchor->setX(anAnchor->x() + aDelta * aDeltaDir->x());
134   anAnchor->setY(anAnchor->y() + aDelta * aDeltaDir->y());
135   anAnchor->setZ(anAnchor->z() + aDelta * aDeltaDir->z());
136
137   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
138   if (anAIS.IsNull()) {
139     Handle(AIS_RadiusDimension) aDimAIS = new AIS_RadiusDimension(theCircle->impl<gp_Circ>(),
140                                                                   anAnchor->impl<gp_Pnt>());
141     aDimAIS->SetCustomValue(theRadius);
142
143     Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
144     anAspect->MakeArrows3d(Standard_False);
145     anAspect->MakeText3d(false);
146     anAspect->TextAspect()->SetHeight(CONSTRAINT_TEXT_HEIGHT);
147     anAspect->ArrowAspect()->SetLength(theRadius / 5.);
148     anAspect->MakeTextShaded(false);
149     aDimAIS->DimensionAspect()->MakeUnitsDisplayed(false);
150     aDimAIS->SetDimensionAspect(anAspect);
151     aDimAIS->SetSelToleranceForText2d(CONSTRAINT_TEXT_SELECTION_TOLERANCE);
152
153     setImpl(new Handle(AIS_InteractiveObject)(aDimAIS));
154   } else {
155     // update presentation
156     Handle(AIS_RadiusDimension) aDimAIS = Handle(AIS_RadiusDimension)::DownCast(anAIS);
157     if (!aDimAIS.IsNull()) {
158       aDimAIS->SetMeasuredGeometry(theCircle->impl<gp_Circ>(), anAnchor->impl<gp_Pnt>());
159       aDimAIS->SetCustomValue(theRadius);
160       aDimAIS->Redisplay(Standard_True);
161     }
162   }
163 }
164
165 void GeomAPI_AISObject::createParallel(boost::shared_ptr<GeomAPI_Shape> theLine1,
166                                        boost::shared_ptr<GeomAPI_Shape> theLine2,
167                                        boost::shared_ptr<GeomAPI_Pnt> theFlyoutPoint,
168                                        boost::shared_ptr<GeomAPI_Pln> thePlane)
169 {
170   Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
171   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
172   if (anAIS.IsNull()) {
173     Handle(AIS_ParallelRelation) aParallel = new AIS_ParallelRelation(
174         theLine1->impl<TopoDS_Shape>(), theLine2->impl<TopoDS_Shape>(), aPlane);
175     if (theFlyoutPoint)
176       aParallel->SetPosition(theFlyoutPoint->impl<gp_Pnt>());
177
178     setImpl(new Handle(AIS_InteractiveObject)(aParallel));
179   } else {
180     Handle(AIS_ParallelRelation) aParallel = Handle(AIS_ParallelRelation)::DownCast(anAIS);
181     if (!aParallel.IsNull()) {
182       aParallel->SetFirstShape(theLine1->impl<TopoDS_Shape>());
183       aParallel->SetSecondShape(theLine2->impl<TopoDS_Shape>());
184       aParallel->SetPlane(aPlane);
185       if (theFlyoutPoint)
186         aParallel->SetPosition(theFlyoutPoint->impl<gp_Pnt>());
187       aParallel->Redisplay(Standard_True);
188     }
189   }
190 }
191
192 void GeomAPI_AISObject::createPerpendicular(boost::shared_ptr<GeomAPI_Shape> theLine1,
193                                             boost::shared_ptr<GeomAPI_Shape> theLine2,
194                                             boost::shared_ptr<GeomAPI_Pln> thePlane)
195 {
196   Handle(Geom_Plane) aPlane = new Geom_Plane(thePlane->impl<gp_Pln>());
197   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
198   if (anAIS.IsNull()) {
199     Handle(AIS_PerpendicularRelation) aPerpendicular = new AIS_PerpendicularRelation(
200         theLine1->impl<TopoDS_Shape>(), theLine2->impl<TopoDS_Shape>(), aPlane);
201
202     setImpl(new Handle(AIS_InteractiveObject)(aPerpendicular));
203   } else {
204     Handle(AIS_PerpendicularRelation) aPerpendicular = Handle(AIS_PerpendicularRelation)::DownCast(
205         anAIS);
206     if (!aPerpendicular.IsNull()) {
207       aPerpendicular->SetFirstShape(theLine1->impl<TopoDS_Shape>());
208       aPerpendicular->SetSecondShape(theLine2->impl<TopoDS_Shape>());
209       aPerpendicular->SetPlane(aPlane);
210       aPerpendicular->Redisplay(Standard_True);
211     }
212   }
213 }
214
215 void GeomAPI_AISObject::setColor(const int& theColor)
216 {
217   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
218   if (anAIS.IsNull())
219     return;
220   Quantity_Color aColor((Quantity_NameOfColor) theColor);
221   anAIS->SetColor(aColor);
222   Handle(AIS_Dimension) aDimAIS = Handle(AIS_Dimension)::DownCast(anAIS);
223   if (!aDimAIS.IsNull()) {
224     aDimAIS->DimensionAspect()->SetCommonColor(aColor);
225   }
226 }
227
228 void GeomAPI_AISObject::setWidth(const double& theWidth)
229 {
230   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
231   if (anAIS.IsNull())
232     return;
233   anAIS->SetWidth(theWidth);
234 }
235
236 void GeomAPI_AISObject::setColor(int theR, int theG, int theB)
237 {
238   Handle(AIS_InteractiveObject) anAIS = impl<Handle(AIS_InteractiveObject)>();
239   if (anAIS.IsNull())
240     return;
241   Quantity_Color aColor(theR / 255., theG / 255., theB / 255., Quantity_TOC_RGB);
242   anAIS->SetColor(aColor);
243   Handle(AIS_Dimension) aDimAIS = Handle(AIS_Dimension)::DownCast(anAIS);
244   if (!aDimAIS.IsNull()) {
245     aDimAIS->DimensionAspect()->SetCommonColor(aColor);
246   }
247 }
248
249 bool GeomAPI_AISObject::empty() const
250 {
251   Handle(AIS_InteractiveObject) anAIS = const_cast<GeomAPI_AISObject*>(this)
252       ->impl<Handle(AIS_InteractiveObject)>();
253   if (anAIS.IsNull())
254     return true;
255   return false;
256 }
257