0029993: Visualization - AIS_TextLabel computes selection primitive only for attachme...
[occt.git] / src / AIS / AIS_TextLabel.cxx
1 // Created on: 2014-11-10
2 // Copyright (c) 2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <AIS_TextLabel.hxx>
16
17 #include <AIS_InteractiveContext.hxx>
18 #include <Font_FTFont.hxx>
19 #include <Font_FontMgr.hxx>
20 #include <Font_Rect.hxx>
21 #include <Graphic3d_AspectText3d.hxx>
22 #include <Graphic3d_RenderingParams.hxx>
23
24 #include <Prs3d_Text.hxx>
25 #include <Prs3d_TextAspect.hxx>
26
27 #include <Select3D_SensitiveFace.hxx>
28 #include <Select3D_SensitivePoint.hxx>
29 #include <SelectMgr_Selection.hxx>
30 #include <SelectMgr_EntityOwner.hxx>
31
32 #include <V3d_Viewer.hxx>
33
34 IMPLEMENT_STANDARD_RTTIEXT(AIS_TextLabel,AIS_InteractiveObject)
35
36 //=======================================================================
37 //function : AIS_TextLabel
38 //purpose  :
39 //=======================================================================
40 AIS_TextLabel::AIS_TextLabel()
41 : myText              ("?"),
42   myHasOrientation3D  (Standard_False),
43   myHasOwnAnchorPoint (Standard_True),
44   myHasFlipping       (Standard_False)
45 {
46   myDrawer->SetTextAspect (new Prs3d_TextAspect());
47   myDrawer->SetDisplayMode (0);
48 }
49
50 //=======================================================================
51 //function : SetColor
52 //purpose  :
53 //=======================================================================
54 void AIS_TextLabel::SetColor (const Quantity_Color& theColor)
55 {
56   hasOwnColor = Standard_True;
57   myDrawer->SetColor (theColor);
58   myDrawer->TextAspect()->SetColor (theColor);
59   SynchronizeAspects();
60 }
61
62 //=======================================================================
63 //function : SetTransparency
64 //purpose  :
65 //=======================================================================
66 void AIS_TextLabel::SetTransparency (const Standard_Real theValue)
67 {
68   Quantity_ColorRGBA aTextColor (myDrawer->TextAspect()->Aspect()->Color());
69   aTextColor.SetAlpha (Standard_ShortReal(1.0 - theValue));
70
71   Quantity_ColorRGBA aSubColor (myDrawer->TextAspect()->Aspect()->ColorSubTitle());
72   aSubColor.SetAlpha (aTextColor.Alpha());
73
74   myDrawer->TextAspect()->Aspect()->SetColor (aTextColor);
75   myDrawer->TextAspect()->Aspect()->SetColorSubTitle (aSubColor);
76   myDrawer->SetTransparency (Standard_ShortReal(theValue));
77   SynchronizeAspects();
78 }
79
80 //=======================================================================
81 //function : SetText
82 //purpose  :
83 //=======================================================================
84 void AIS_TextLabel::SetText (const TCollection_ExtendedString& theText)
85 {
86   myText = theText;
87 }
88
89 //=======================================================================
90 //function : SetPosition
91 //purpose  :
92 //=======================================================================
93 void AIS_TextLabel::SetPosition (const gp_Pnt& thePosition)
94 {
95   myOrientation3D.SetLocation (thePosition);
96 }
97
98 //=======================================================================
99 //function : SetHJustification
100 //purpose  :
101 //=======================================================================
102 void AIS_TextLabel::SetHJustification (const Graphic3d_HorizontalTextAlignment theHJust)
103 {
104   myDrawer->TextAspect()->SetHorizontalJustification (theHJust);
105 }
106
107 //=======================================================================
108 //function : SetVJustification
109 //purpose  : Setup vertical justification.
110 //=======================================================================
111 void AIS_TextLabel::SetVJustification (const Graphic3d_VerticalTextAlignment theVJust)
112 {
113   myDrawer->TextAspect()->SetVerticalJustification (theVJust);
114 }
115
116 //=======================================================================
117 //function : SetAngle
118 //purpose  :
119 //=======================================================================
120 void AIS_TextLabel::SetAngle (const Standard_Real theAngle)
121 {
122   myDrawer->TextAspect()->Aspect()->SetTextAngle (theAngle * 180.0 / M_PI);
123 }
124
125 //=======================================================================
126 //function : SetZoom
127 //purpose  :
128 //=======================================================================
129 void AIS_TextLabel::SetZoomable (const Standard_Boolean theIsZoomable)
130 {
131   myDrawer->TextAspect()->Aspect()->SetTextZoomable (theIsZoomable == Standard_True);
132 }
133
134 //=======================================================================
135 //function : SetHeight
136 //purpose  :
137 //=======================================================================
138 void AIS_TextLabel::SetHeight (const Standard_Real theHeight)
139 {
140   myDrawer->TextAspect()->SetHeight (theHeight);
141 }
142
143 //=======================================================================
144 //function : SetAngle
145 //purpose  :
146 //=======================================================================
147 void AIS_TextLabel::SetFontAspect (const Font_FontAspect theFontAspect)
148 {
149   myDrawer->TextAspect()->Aspect()->SetTextFontAspect (theFontAspect);
150 }
151
152 //=======================================================================
153 //function : SetFont
154 //purpose  :
155 //=======================================================================
156 void AIS_TextLabel::SetFont (Standard_CString theFont)
157 {
158   myDrawer->TextAspect()->SetFont (theFont);
159 }
160
161 //=======================================================================
162 //function : SetOrientation3D
163 //purpose  :
164 //=======================================================================
165 void AIS_TextLabel::SetOrientation3D (const gp_Ax2& theOrientation)
166 {
167   myHasOrientation3D = Standard_True;
168   myOrientation3D    = theOrientation;
169 }
170
171 //=======================================================================
172 //function : UnsetOrientation3D
173 //purpose  :
174 //=======================================================================
175 void AIS_TextLabel::UnsetOrientation3D ()
176 {
177   myHasOrientation3D = Standard_False;
178 }
179
180 //=======================================================================
181 //function : Position
182 //purpose  :
183 //=======================================================================
184 const gp_Pnt& AIS_TextLabel::Position() const
185 {
186   return myOrientation3D.Location();
187 }
188
189 //=======================================================================
190 //function : FontName
191 //purpose  :
192 //=======================================================================
193 const TCollection_AsciiString& AIS_TextLabel::FontName() const
194 {
195   return myDrawer->TextAspect()->Aspect()->Font();
196 }
197
198 //=======================================================================
199 //function : FontAspect
200 //purpose  :
201 //=======================================================================
202 Font_FontAspect AIS_TextLabel::FontAspect() const
203 {
204   return myDrawer->TextAspect()->Aspect()->GetTextFontAspect();
205 }
206
207 //=======================================================================
208 //function : Orientation3D
209 //purpose  :
210 //=======================================================================
211 const gp_Ax2& AIS_TextLabel::Orientation3D() const
212 {
213   return myOrientation3D;
214 }
215
216 //=======================================================================
217 //function : HasOrientation3D
218 //purpose  :
219 //=======================================================================
220 Standard_Boolean AIS_TextLabel::HasOrientation3D() const
221 {
222   return myHasOrientation3D;
223 }
224
225 //=======================================================================
226 //function : SetFlipping
227 //purpose  :
228 //=======================================================================
229 void AIS_TextLabel::SetFlipping (const Standard_Boolean theIsFlipping)
230 {
231   myHasFlipping = theIsFlipping;
232 }
233
234 //=======================================================================
235 //function : HasFlipping
236 //purpose  :
237 //=======================================================================
238 Standard_Boolean AIS_TextLabel::HasFlipping() const
239 {
240   return myHasFlipping;
241 }
242
243 //=======================================================================
244 //function : SetDisplayType
245 //purpose  :
246 //=======================================================================
247 void AIS_TextLabel::SetDisplayType (const Aspect_TypeOfDisplayText theDisplayType)
248 {
249   myDrawer->TextAspect()->Aspect()->SetDisplayType(theDisplayType);
250 }
251
252 //=======================================================================
253 //function : SetColorSubTitle
254 //purpose  :
255 //=======================================================================
256 void AIS_TextLabel::SetColorSubTitle (const Quantity_Color& theColor)
257 {
258   myDrawer->TextAspect()->Aspect()->SetColorSubTitle(theColor);
259 }
260
261 //=======================================================================
262 //function : Compute
263 //purpose  :
264 //=======================================================================
265 void AIS_TextLabel::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePrsMgr*/,
266                              const Handle(Prs3d_Presentation)&             thePrs,
267                              const Standard_Integer                        theMode)
268 {
269   switch (theMode)
270   {
271     case 0:
272     {
273       Handle(Prs3d_TextAspect) anAsp = myDrawer->TextAspect();
274       gp_Pnt aPosition = Position();
275
276       const Standard_Boolean isTextZoomable = anAsp->Aspect()->GetTextZoomable();
277       if (myHasOrientation3D)
278       {
279         anAsp->Aspect()->SetTextZoomable (myHasFlipping ? Standard_True : Standard_False);
280         SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_ZoomPers, aPosition));
281         aPosition = gp::Origin();
282       }
283       else if (isTextZoomable
284             || TransformPersistence().IsNull()
285             || TransformPersistence()->Mode() != Graphic3d_TMF_2d)
286       {
287         Handle(Graphic3d_TransformPers) aTrsfPers =
288           new Graphic3d_TransformPers (isTextZoomable ? Graphic3d_TMF_RotatePers : Graphic3d_TMF_ZoomRotatePers, aPosition);
289         SetTransformPersistence (aTrsfPers);
290         aPosition = gp::Origin();
291       }
292
293       gp_Pnt aCenterOfLabel;
294       Standard_Real aWidth, aHeight;
295
296       Standard_Boolean isInit = calculateLabelParams (aPosition, aCenterOfLabel, aWidth, aHeight);
297       if (myHasOrientation3D)
298       {
299         if (myHasFlipping)
300         {
301           gp_Ax2 aFlippingAxes (aCenterOfLabel, myOrientation3D.Direction(), myOrientation3D.XDirection());
302           Prs3d_Root::CurrentGroup (thePrs)->SetFlippingOptions (Standard_True, aFlippingAxes);
303         }
304         gp_Ax2 anOrientation = myOrientation3D;
305         anOrientation.SetLocation (aPosition);
306         Standard_Boolean aHasOwnAnchor = HasOwnAnchorPoint();
307         if (myHasFlipping)
308         {
309           aHasOwnAnchor = Standard_False; // always not using own anchor if flipping
310         }
311         Prs3d_Text::Draw (Prs3d_Root::CurrentGroup (thePrs), anAsp, myText, anOrientation, aHasOwnAnchor);
312         if (myHasFlipping && isInit)
313         {
314           Prs3d_Root::CurrentGroup (thePrs)->SetFlippingOptions (Standard_False, gp_Ax2());
315         }
316       }
317       else
318       {
319         Prs3d_Text::Draw (Prs3d_Root::CurrentGroup (thePrs), anAsp, myText, aPosition);
320       }
321
322       if (isInit)
323       {
324         const Standard_Real aDx = aWidth * 0.5;
325         const Standard_Real aDy = aHeight * 0.5;
326         gp_Trsf aLabelPlane = calculateLabelTrsf (aPosition, aCenterOfLabel);
327
328         gp_Pnt aMinPnt = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
329         gp_Pnt aMaxPnt = gp_Pnt ( aDx,  aDy, 0.0).Transformed (aLabelPlane);
330
331         Graphic3d_BndBox4f& aBox = Prs3d_Root::CurrentGroup (thePrs)->ChangeBoundingBox();
332         aBox.Add (Graphic3d_Vec4 ((float) aMinPnt.X(), (float) aMinPnt.Y(), (float) aMinPnt.Z(), 1.0));
333         aBox.Add (Graphic3d_Vec4 ((float) aMaxPnt.X(), (float) aMaxPnt.Y(), (float) aMaxPnt.Z(), 1.0));
334       }
335
336       break;
337     }
338   }
339 }
340
341 //=======================================================================
342 //function : ComputeSelection
343 //purpose  :
344 //=======================================================================
345 void AIS_TextLabel::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
346                                       const Standard_Integer             theMode)
347 {
348   switch (theMode)
349   {
350     case 0:
351     {
352       Handle(SelectMgr_EntityOwner) anEntityOwner   = new SelectMgr_EntityOwner (this, 10);
353
354       gp_Pnt aPosition = Position();
355       if (!TransformPersistence().IsNull() && TransformPersistence()->Mode() != Graphic3d_TMF_2d)
356       {
357         aPosition = gp::Origin();
358       }
359
360       gp_Pnt aCenterOfLabel;
361       Standard_Real aWidth, aHeight;
362
363       if (!calculateLabelParams (aPosition, aCenterOfLabel, aWidth, aHeight))
364       {
365         Handle(Select3D_SensitivePoint) aTextSensitive = new Select3D_SensitivePoint (anEntityOwner, aPosition);
366         theSelection->Add (aTextSensitive);
367         break;
368       }
369
370       const Standard_Real aDx = aWidth * 0.5;
371       const Standard_Real aDy = aHeight * 0.5;
372       gp_Trsf aLabelPlane = calculateLabelTrsf (aPosition, aCenterOfLabel);
373
374       // sensitive planar rectangle for text
375       TColgp_Array1OfPnt aRectanglePoints (1, 5);
376       aRectanglePoints.ChangeValue (1) = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
377       aRectanglePoints.ChangeValue (2) = gp_Pnt (-aDx,  aDy, 0.0).Transformed (aLabelPlane);
378       aRectanglePoints.ChangeValue (3) = gp_Pnt ( aDx,  aDy, 0.0).Transformed (aLabelPlane);
379       aRectanglePoints.ChangeValue (4) = gp_Pnt ( aDx, -aDy, 0.0).Transformed (aLabelPlane);
380       aRectanglePoints.ChangeValue (5) = aRectanglePoints.Value (1);
381
382       Handle(Select3D_SensitiveFace) aTextSensitive =
383         new Select3D_SensitiveFace (anEntityOwner, aRectanglePoints, Select3D_TOS_INTERIOR);
384       theSelection->Add (aTextSensitive);
385
386       break;
387     }
388   }
389 }
390
391 //=======================================================================
392 //function : calculateLabelParams
393 //purpose  :
394 //=======================================================================
395 Standard_Boolean AIS_TextLabel::calculateLabelParams (const gp_Pnt& thePosition,
396                                                       gp_Pnt& theCenterOfLabel,
397                                                       Standard_Real& theWidth,
398                                                       Standard_Real& theHeight) const
399 {
400   // Get width and height of text
401   Handle(Prs3d_TextAspect) anAsp = myDrawer->TextAspect();
402   Font_FTFontParams aFontParams;
403   aFontParams.PointSize = (unsigned int) anAsp->Height();
404   aFontParams.Resolution = GetContext()->CurrentViewer()->DefaultRenderingParams().Resolution;
405
406   Handle(Font_FTFont) aFont = Font_FTFont::FindAndCreate (anAsp->Aspect()->Font(),
407                                                           anAsp->Aspect()->GetTextFontAspect(),
408                                                           aFontParams);
409   if (aFont.IsNull())
410   { 
411     return Standard_False;
412   }
413
414   const NCollection_String aText (myText.ToExtString());
415   Font_Rect aBndBox = aFont->BoundingBox (aText, anAsp->HorizontalJustification(), anAsp->VerticalJustification());
416   theWidth = Abs (aBndBox.Width());
417   theHeight = Abs (aBndBox.Height());
418
419   theCenterOfLabel = thePosition;
420   if (anAsp->VerticalJustification() == Graphic3d_VTA_BOTTOM)
421   {
422     theCenterOfLabel.ChangeCoord() += myOrientation3D.YDirection().XYZ() * theHeight * 0.5;
423   }
424   else if (anAsp->VerticalJustification() == Graphic3d_VTA_TOP)
425   {
426     theCenterOfLabel.ChangeCoord() -= myOrientation3D.YDirection().XYZ() * theHeight * 0.5;
427   }
428   if (anAsp->HorizontalJustification() == Graphic3d_HTA_LEFT)
429   {
430     theCenterOfLabel.ChangeCoord() += myOrientation3D.XDirection().XYZ() * theWidth * 0.5;
431   }
432   else if (anAsp->HorizontalJustification() == Graphic3d_HTA_RIGHT)
433   {
434     theCenterOfLabel.ChangeCoord() -= myOrientation3D.XDirection().XYZ() * theWidth * 0.5;
435   }
436
437   return Standard_True;
438 }
439
440 //=======================================================================
441 //function : calculateLabelTrsf
442 //purpose  :
443 //=======================================================================
444 gp_Trsf AIS_TextLabel::calculateLabelTrsf (const gp_Pnt& thePosition, gp_Pnt& theCenterOfLabel) const
445 {
446   const Standard_Real anAngle = myDrawer->TextAspect()->Aspect()->TextAngle() * M_PI / 180.0;
447   const gp_Ax1 aRotAxis (thePosition, gp_Dir (0.0, 0.0, 1.0));
448
449   gp_Ax2 anOrientation = myOrientation3D;
450   anOrientation.Rotate (aRotAxis, anAngle);
451   theCenterOfLabel.Rotate (aRotAxis, anAngle);
452
453   gp_Trsf aLabelPlane;
454   aLabelPlane.SetTransformation (anOrientation, gp::XOY());
455   aLabelPlane.SetTranslationPart (theCenterOfLabel.XYZ());
456
457   return aLabelPlane;
458 }