Salome HOME
Implementation '22873: EDF 8651 GEOM: Annotate shapes into the OCC viewer' issue
[modules/geom.git] / src / OBJECT / GEOM_Annotation.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  GEOM OBJECT : interactive object for Geometry entities visualization
24 //  File   : GEOM_Annotation.hxx
25 //  Module : GEOM
26 //
27 #include <GEOM_Annotation.hxx>
28
29 // OCCT includes
30 #include <AIS_InteractiveContext.hxx>
31 #include <Font_FTFont.hxx>
32 #include <Graphic3d_ArrayOfPoints.hxx>
33 #include <Graphic3d_ArrayOfSegments.hxx>
34 #include <Graphic3d_Camera.hxx>
35 #include <Graphic3d_HorizontalTextAlignment.hxx>
36 #include <Graphic3d_VerticalTextAlignment.hxx>
37 #include <Graphic3d_Vec4.hxx>
38 #include <OpenGl_Context.hxx>
39 #include <OpenGl_GraphicDriver.hxx>
40 #include <OpenGl_Group.hxx>
41 #include <OpenGl_PrimitiveArray.hxx>
42 #include <OpenGl_Structure.hxx>
43 #include <OpenGl_Text.hxx>
44 #include <OpenGl_View.hxx>
45 #include <OpenGl_Workspace.hxx>
46 #include <Prs3d_PointAspect.hxx>
47 #include <Prs3d_Root.hxx>
48 #include <Prs3d_Text.hxx>
49 #include <Prs3d_IsoAspect.hxx>
50 #include <Select3D_SensitiveBox.hxx>
51 #include <SelectMgr_EntityOwner.hxx>
52 #include <V3d_Viewer.hxx>
53 #include <V3d_View.hxx>
54
55 IMPLEMENT_STANDARD_RTTIEXT( GEOM_Annotation, AIS_InteractiveObject )
56
57 // =======================================================================
58 // function : Constructor
59 // purpose  :
60 // =======================================================================
61 GEOM_Annotation::GEOM_Annotation() : AIS_InteractiveObject()
62 {
63   SetPosition( gp_Pnt( 0.0, 0.0, 0.0 ) );
64   SetIsScreenFixed( Standard_False );
65   SetAttachPoint( gp_Pnt( 0.0, 0.0, 0.0 ) );
66   SetDisplayMode( 0 );
67   SetZLayer( Graphic3d_ZLayerId_Default );
68   SetAutoHide( Standard_True );
69   SetHilightMode( HighlightAll );
70   SetMutable( Standard_True );
71   SetDepthCulling( Standard_True );
72
73   Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
74   aTextAspect->SetHeight( 20.0 );
75   aTextAspect->SetColor( Quantity_Color( 1.0, 1.0, 1.0, Quantity_TOC_RGB ) );
76   myDrawer->SetTextAspect( aTextAspect );
77
78   Handle(Prs3d_LineAspect) aLineAspect =
79     new Prs3d_LineAspect( Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0 );
80   myDrawer->SetLineAspect( aLineAspect );
81
82   Handle(Prs3d_LineAspect) aHiddenLineAspect =
83     new Prs3d_LineAspect( Quantity_NOC_WHITE, Aspect_TOL_DOT, 1.0 );
84   myDrawer->SetHiddenLineAspect( aHiddenLineAspect );
85
86   Handle(Prs3d_PointAspect) aPointAspect =
87     new Prs3d_PointAspect( Aspect_TOM_POINT, Quantity_NOC_WHITE, 4.0 );
88   myDrawer->SetPointAspect( aPointAspect );
89 }
90
91 // =======================================================================
92 // function : SetText
93 // purpose  :
94 // =======================================================================
95 void GEOM_Annotation::SetText( const TCollection_ExtendedString& theText )
96 {
97   if (myText != theText)
98   {
99     SetToUpdate();
100   }
101
102   myText = theText;
103 }
104
105 // =======================================================================
106 // function : SetPosition
107 // purpose  :
108 // =======================================================================
109 void GEOM_Annotation::SetPosition( const gp_Pnt& thePosition )
110 {
111   SetPosition( thePosition, Standard_True );
112 }
113
114 // =======================================================================
115 // function : SetPosition
116 // purpose  :
117 // =======================================================================
118 void GEOM_Annotation::SetPosition( const gp_Pnt& thePosition, const Standard_Boolean theUpdateSelection )
119 {
120   myPosition = thePosition;
121
122   if ( !myIsScreenFixed )
123   {
124     Handle(Graphic3d_TransformPers) aPersistence =
125       new Graphic3d_TransformPers( Graphic3d_TMF_ZoomRotatePers, thePosition );
126
127     AIS_InteractiveObject::SetTransformPersistence( aPersistence );
128   }
129
130   SetToUpdate();
131
132   if( theUpdateSelection )
133   {
134     UpdateSelection();
135   }
136 }
137
138 // =======================================================================
139 // function : SetIsScreenFixed
140 // purpose  :
141 // =======================================================================
142 void GEOM_Annotation::SetIsScreenFixed( const Standard_Boolean theIsFixed )
143 {
144   myIsScreenFixed = theIsFixed;
145
146   Handle(Graphic3d_TransformPers) aPersistence;
147
148   if (!myIsScreenFixed)
149   {
150     aPersistence = new Graphic3d_TransformPers( Graphic3d_TMF_ZoomRotatePers, myPosition );
151   }
152   else
153   {
154     aPersistence = new Graphic3d_TransformPers( Graphic3d_TMF_2d, Aspect_TOTP_CENTER );
155   }
156
157   AIS_InteractiveObject::SetTransformPersistence( aPersistence );
158
159   SetZLayer( myIsScreenFixed ? Graphic3d_ZLayerId_Topmost : Graphic3d_ZLayerId_Default );
160
161   SetToUpdate();
162
163   UpdateSelection();
164 }
165
166 // =======================================================================
167 // function : Set2dPosition
168 // purpose  :
169 // =======================================================================
170 void GEOM_Annotation::Set2dPosition( const Handle(V3d_View)& theView )
171 {
172   if ( myIsScreenFixed )
173   {
174     return;
175   }
176
177   gp_Pnt aPosition2d = ConvertPosition2d( myPosition, myAttach, theView );
178
179   SetIsScreenFixed( Standard_True );
180
181   SetPosition( aPosition2d );
182 }
183
184 // =======================================================================
185 // function : Set3dPosition
186 // purpose  :
187 // =======================================================================
188 void GEOM_Annotation::Set3dPosition( const Handle(V3d_View)& theView )
189 {
190   if ( !myIsScreenFixed )
191   {
192     return;
193   }
194
195   gp_Pnt aPosition3d = ConvertPosition3d( myPosition, myAttach, theView );
196
197   SetIsScreenFixed( Standard_False );
198
199   SetPosition( aPosition3d );
200 }
201
202 // =======================================================================
203 // function : SetAttachPoint
204 // purpose  :
205 // =======================================================================
206 void GEOM_Annotation::SetAttachPoint( const gp_Pnt& thePoint )
207 {
208   myAttach = thePoint;
209 }
210
211 // =======================================================================
212 // function : SetHilightShape
213 // purpose  : Sets shape (annotated shape) that will be used for hilighting.
214 // =======================================================================
215 void GEOM_Annotation::SetHilightShape( const TopoDS_Shape& theShape )
216 {
217   if ( myShape.IsEqual( theShape ) )
218   {
219     return;
220   }
221
222   myShape = theShape;
223   SetToUpdate();
224   UpdateSelection();
225 }
226
227 // =======================================================================
228 // function : SetColor
229 // purpose  :
230 // =======================================================================
231 void GEOM_Annotation::SetColor( const Quantity_Color& theColor )
232 {
233   SetTextColor( theColor );
234   SetLineColor( theColor );
235 }
236
237 // =======================================================================
238 // function : SetTextColor
239 // purpose  :
240 // =======================================================================
241 void GEOM_Annotation::SetTextColor( const Quantity_Color& theColor )
242 {
243   myDrawer->TextAspect()->SetColor( theColor );
244
245   SetToUpdate();
246 }
247
248 // =======================================================================
249 // function : SetLineColor
250 // purpose  :
251 // =======================================================================
252 void GEOM_Annotation::SetLineColor( const Quantity_Color& theColor )
253 {
254   myDrawer->LineAspect()->SetColor( theColor );
255   myDrawer->HiddenLineAspect()->SetColor( theColor );
256   myDrawer->PointAspect()->SetColor( theColor );
257
258   SetToUpdate();
259 }
260
261 // =======================================================================
262 // function : SetLineWidth
263 // purpose  :
264 // =======================================================================
265 void GEOM_Annotation::SetLineWidth( const Standard_Real theLineWidth )
266 {
267   if ( GetLineWidth() != theLineWidth )
268   {
269     myDrawer->LineAspect()->SetWidth( theLineWidth );
270     myDrawer->HiddenLineAspect()->SetWidth( theLineWidth );
271
272     SetToUpdate();
273   }
274 }
275
276 // =======================================================================
277 // function : SetLineStyle
278 // purpose  :
279 // =======================================================================
280 void GEOM_Annotation::SetLineStyle( const Aspect_TypeOfLine theStyle )
281 {
282   if ( GetLineStyle() != theStyle )
283   {
284     myDrawer->LineAspect()->SetTypeOfLine( theStyle );
285
286     SetToUpdate();
287   }
288 }
289
290 // =======================================================================
291 // function : SetHiddenLineStyle
292 // purpose  :
293 // =======================================================================
294 void GEOM_Annotation::SetHiddenLineStyle( const Aspect_TypeOfLine theStyle )
295 {
296   if ( GetHiddenLineStyle() != theStyle )
297   {
298     myDrawer->HiddenLineAspect()->SetTypeOfLine( theStyle );
299
300     SetToUpdate();
301   }
302 }
303
304 // =======================================================================
305 // function : SetTextHeight
306 // purpose  :
307 // =======================================================================
308 void GEOM_Annotation::SetTextHeight( const Standard_Real theHeight )
309 {
310   if ( GetTextHeight() != theHeight )
311   {
312     myDrawer->TextAspect()->SetHeight( theHeight );
313
314     SetToUpdate();
315   }
316 }
317
318 // =======================================================================
319 // function : SetFontAspect
320 // purpose  :
321 // =======================================================================
322 void GEOM_Annotation::SetFontAspect( const Font_FontAspect theFontAspect )
323 {
324   if ( GetFontAspect() != theFontAspect )
325   {
326     myDrawer->TextAspect()->Aspect()->SetTextFontAspect( theFontAspect );
327
328     SetToUpdate();
329   }
330 }
331
332 // =======================================================================
333 // function : SetFont
334 // purpose  :
335 // =======================================================================
336 void GEOM_Annotation::SetFont( const TCollection_AsciiString& theFont )
337 {
338   if ( GetFont() != theFont )
339   {
340     myDrawer->TextAspect()->Aspect()->SetFont( theFont );
341
342     SetToUpdate();
343   }
344 }
345
346 // =======================================================================
347 // function : SetDepthCulling
348 // purpose  :
349 // =======================================================================
350 void GEOM_Annotation::SetDepthCulling( const Standard_Boolean theToEnable )
351 {
352   if ( GetDepthCulling() != theToEnable )
353   {
354     myIsDepthCulling = theToEnable;
355
356     SetToUpdate();
357   }
358 }
359
360 // =======================================================================
361 // function : SetDefaultZLayer
362 // purpose  :
363 // =======================================================================
364 void GEOM_Annotation::SetDefaultZLayer()
365 {
366   SetZLayer( myIsScreenFixed ? Graphic3d_ZLayerId_Topmost : Graphic3d_ZLayerId_Default );
367
368   SetToUpdate();
369 }
370
371 // =======================================================================
372 // function : GetDefaultPosition
373 // purpose  :
374 // =======================================================================
375 gp_Pnt GEOM_Annotation::GetDefaultPosition( const Standard_Boolean theIsScreenFixed,
376                                             const gp_Pnt& theAttachPnt,
377                                             const Standard_Real theOffset,
378                                             const Handle(V3d_View)& theView )
379 {
380   Standard_Integer aWinWidth = 0;
381   Standard_Integer aWinHeight = 0;
382   theView->Window()->Size( aWinWidth, aWinHeight );
383
384   gp_Pnt aPositionProj = theView->Camera()->Project( theAttachPnt );
385   aPositionProj.SetX( (aPositionProj.X() / 2.) * aWinWidth  + theOffset );
386   aPositionProj.SetY( (aPositionProj.Y() / 2.) * aWinHeight + theOffset );
387   aPositionProj.SetZ( 0.0 );
388
389   if ( theIsScreenFixed )
390   {
391     return aPositionProj;
392   }
393
394   gp_Pnt aAttachProj = theView->Camera()->Project ( theAttachPnt );
395   gp_Pnt aPosition3d = theView->Camera()->UnProject ( gp_Pnt ( aPositionProj.X() / aWinWidth * 2.,
396                                                                aPositionProj.Y() / aWinHeight * 2., 
397                                                                aAttachProj.Z() ));
398
399   return aPosition3d;
400 }
401
402 // =======================================================================
403 // function : ConvertPosition2d
404 // purpose  :
405 // =======================================================================
406 gp_Pnt GEOM_Annotation::ConvertPosition2d( const gp_Pnt& thePosition,
407                                            const gp_Pnt& /*theAttach*/,
408                                            const Handle(V3d_View)& theView )
409 {
410   Standard_Integer aWinWidth = 0;
411   Standard_Integer aWinHeight = 0;
412   theView->Window()->Size( aWinWidth, aWinHeight );
413
414   gp_Pnt aPositionProj = theView->Camera()->Project( thePosition );
415   aPositionProj.SetX( (aPositionProj.X() / 2.) * aWinWidth );
416   aPositionProj.SetY( (aPositionProj.Y() / 2.) * aWinHeight );
417   aPositionProj.SetZ( 0.0 );
418   return aPositionProj;
419 }
420
421 // =======================================================================
422 // function : ConvertPosition3d
423 // purpose  :
424 // =======================================================================
425 gp_Pnt GEOM_Annotation::ConvertPosition3d( const gp_Pnt& thePosition,
426                                            const gp_Pnt& theAttach,
427                                            const Handle(V3d_View)& theView )
428 {
429   Standard_Integer aWinWidth = 0;
430   Standard_Integer aWinHeight = 0;
431   theView->Window()->Size( aWinWidth, aWinHeight );
432
433   gp_Pnt aAttachProj = theView->Camera()->Project( theAttach );
434   gp_Pnt aPosition3d =  theView->Camera()->UnProject(
435     gp_Pnt ( thePosition.X() / aWinWidth * 2., thePosition.Y() / aWinHeight * 2., aAttachProj.Z() ) );
436
437   return aPosition3d;
438 }
439
440 // =======================================================================
441 // function : Compute
442 // purpose  :
443 // =======================================================================
444 void GEOM_Annotation::Compute( const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
445                                const Handle(Prs3d_Presentation)&           thePresentation,
446                                const Standard_Integer                      theMode )
447 {
448   thePresentation->Clear();
449
450   if (theMode < 0)
451   {
452     return;
453   }
454
455   Handle(OpenGl_Group) aGroup = Handle(OpenGl_Group)::DownCast( Prs3d_Root::NewGroup( thePresentation ) );
456   if (aGroup.IsNull())
457   {
458     return;
459   }
460
461   Handle(Prs3d_TextAspect) anAsp = myDrawer->TextAspect();
462   NCollection_String aUtfText( myText.ToExtString() );
463   OpenGl_Annotation* aAnnotationDraw =
464     new OpenGl_Annotation( this, static_cast<Standard_Integer>( anAsp->Height() ), aGroup->GlStruct()->GlDriver() );
465
466   aAnnotationDraw->SetDepthMode( 0 );
467   aGroup->SetGroupPrimitivesAspect( myDrawer->TextAspect()->Aspect() );
468   aGroup->SetGroupPrimitivesAspect( myDrawer->LineAspect()->Aspect() );
469   aGroup->SetGroupPrimitivesAspect( myDrawer->PointAspect()->Aspect() );
470   aGroup->AddElement( aAnnotationDraw );
471
472   if ( !myIsDepthCulling )
473   {
474     OpenGl_Annotation* aAnnotationDraw =
475       new OpenGl_Annotation( this, static_cast<Standard_Integer>( anAsp->Height() ), aGroup->GlStruct()->GlDriver() );
476
477     aAnnotationDraw->SetDepthMode( GL_GREATER );
478     aGroup->SetPrimitivesAspect( myDrawer->TextAspect()->Aspect() );
479     aGroup->SetPrimitivesAspect( myDrawer->HiddenLineAspect()->Aspect() );
480     aGroup->SetPrimitivesAspect( myDrawer->PointAspect()->Aspect() );
481     aGroup->AddElement( aAnnotationDraw );
482   }
483
484   Bnd_Box aBox = TextBoundingBox();
485   if ( myIsScreenFixed )
486   {
487     gp_Trsf aOffset2d;
488     aOffset2d.SetTranslation( gp_Vec( myPosition.X(), myPosition.Y(), 0.0 ) );
489     aBox = aBox.Transformed( aOffset2d );
490   }
491
492   const gp_Pnt aBoxMin = aBox.CornerMin();
493   const gp_Pnt aBoxMax = aBox.CornerMax();
494   aGroup->ChangeBoundingBox() = Graphic3d_BndBox4f (
495     Graphic3d_Vec4( static_cast<Standard_ShortReal>( aBoxMin.X() ),
496                     static_cast<Standard_ShortReal>( aBoxMin.Y() ),
497                     static_cast<Standard_ShortReal>( aBoxMin.Z() ), 1.0F ),
498     Graphic3d_Vec4( static_cast<Standard_ShortReal>( aBoxMax.X() ),
499                     static_cast<Standard_ShortReal>( aBoxMax.Y() ),
500                     static_cast<Standard_ShortReal>( aBoxMax.Z() ), 1.0F ) );
501 }
502
503 // =======================================================================
504 // function : ComputeSelection
505 // purpose  :
506 // =======================================================================
507 void GEOM_Annotation::ComputeSelection( const Handle(SelectMgr_Selection)& theSelection,
508                                         const Standard_Integer             theMode )
509 {
510   if (theMode != GlobalSelectionMode())
511   {
512     return;
513   }
514
515   theSelection->Clear();
516
517   Bnd_Box aBox = TextBoundingBox();
518   if ( myIsScreenFixed )
519   {
520     gp_Trsf aOffset2d;
521     aOffset2d.SetTranslation( gp_Vec( myPosition.X(), myPosition.Y(), 0.0 ) );
522     aBox = aBox.Transformed( aOffset2d );
523   }
524
525   const Handle(GEOM_AnnotationOwner) anEntityOwner = new GEOM_AnnotationOwner( myShape, this, 10 );
526   const Handle(GEOM_AnnotationSensEntity) aSensitive =
527     new GEOM_AnnotationSensEntity( anEntityOwner, aBox, myIsDepthCulling );
528
529   theSelection->Add( aSensitive );
530 }
531
532 // =======================================================================
533 // function : TextBoundingBox
534 // purpose  :
535 // =======================================================================
536 Bnd_Box GEOM_Annotation::TextBoundingBox() const
537 {
538   Handle(Prs3d_TextAspect) anAsp = myDrawer->TextAspect();
539   Font_FTFont aFont;
540   unsigned int aResolution = GetContext()->CurrentViewer()->DefaultRenderingParams().Resolution;
541   if ( aFont.Init( anAsp->Aspect()->Font().ToCString(),
542                    anAsp->Aspect()->GetTextFontAspect(),
543                   (unsigned int)anAsp->Height(),
544                   aResolution ) )
545   {
546     const NCollection_String aText( (Standard_Utf16Char* )myText.ToExtString() );
547     const Font_Rect aFontRect = aFont.BoundingBox( aText, Graphic3d_HTA_CENTER, Graphic3d_VTA_CENTER );
548     Bnd_Box aBox;
549     aBox.Add( gp_Pnt( aFontRect.Left, aFontRect.Bottom, 0.0 ) );
550     aBox.Add( gp_Pnt( aFontRect.Right, aFontRect.Top, 0.0 ) );
551     return aBox;
552   }
553
554   return Bnd_Box();
555 }
556
557 // =======================================================================
558 // function : BeginDrag
559 // purpose  :
560 // =======================================================================
561 void GEOM_Annotation::BeginDrag()
562 {
563   myStartPosition = myPosition;
564 }
565
566 // =======================================================================
567 // function : Drag
568 // purpose  :
569 // =======================================================================
570 void GEOM_Annotation::Drag( const Standard_Integer theDx,
571                             const Standard_Integer theDy,
572                             const Handle(V3d_View)& theView )
573 {
574   if (myIsScreenFixed)
575   {
576     SetPosition( myStartPosition.Translated( gp_Vec( theDx, theDy, 0.0 ) ), Standard_False );
577   }
578   else
579   {
580     Standard_Integer aWidth, aHeight;
581     theView->Window()->Size( aWidth, aHeight );
582     gp_Pnt aNormalized = theView->Camera()->Project( myStartPosition );
583     gp_Pnt aNormalizedDrag =
584       aNormalized.Translated( gp_Vec( static_cast<Standard_Real>(theDx) * 2.0 / aWidth,
585                                       static_cast<Standard_Real>(theDy) * 2.0 / aHeight,
586                                       0.0 ) );
587
588     SetPosition( theView->Camera()->UnProject( aNormalizedDrag ), Standard_False );
589   }
590 }
591
592 // =======================================================================
593 // function : EndDrag
594 // purpose  :
595 // =======================================================================
596 void GEOM_Annotation::EndDrag()
597 {
598   UpdateSelection();
599 }
600
601 // =======================================================================
602 // function : UndoDrag
603 // purpose  :
604 // =======================================================================
605 void GEOM_Annotation::UndoDrag()
606 {
607   SetPosition( myStartPosition, Standard_True );
608 }
609
610 // =======================================================================
611 // subclass : OpenGl_Annotation
612 // function : Constructor
613 // purpose  : 
614 // =======================================================================
615 GEOM_Annotation::OpenGl_Annotation::OpenGl_Annotation( GEOM_Annotation* theAnnotation,
616                                                        const Standard_Integer theTextHeight,
617                                                        const OpenGl_GraphicDriver* theDriver )
618 : OpenGl_Element(),
619   myDepthMode( 0 ),
620   myAISObject( theAnnotation ),
621   myText( theAnnotation->myText.ToExtString() ),
622   myTextLineY( 0.f ),
623   myTextDPI( 0 )
624 {
625   // graphical resources for drawing text and underline
626   myTextParams.Height = theTextHeight;
627   myTextParams.HAlign = Graphic3d_HTA_CENTER;
628   myTextParams.VAlign = Graphic3d_VTA_CENTER;
629   myTextDraw = new OpenGl_Text( myText.ToCString(), OpenGl_Vec3(), myTextParams );
630   myTextLineDraw = new OpenGl_PrimitiveArray( theDriver );
631
632   // graphical resources for drawing extension line and marker
633   Handle(Graphic3d_ArrayOfSegments)
634   aExtVertexArray = new Graphic3d_ArrayOfSegments( 2 );
635   aExtVertexArray->AddVertex( 0.0, 0.0, 0.0 );
636   aExtVertexArray->AddVertex( 0.0, 0.0, 1.0 );
637   myExtLineDraw = new OpenGl_PrimitiveArray( theDriver, Graphic3d_TOPA_SEGMENTS,
638     aExtVertexArray->Indices(), aExtVertexArray->Attributes(), aExtVertexArray->Bounds() );
639
640   Handle(Graphic3d_ArrayOfPoints)
641   aExtMakerArray = new Graphic3d_ArrayOfPoints( 1 );
642   aExtMakerArray->AddVertex( 0.0, 0.0, 1.0 );
643   myExtMarkerDraw = new OpenGl_PrimitiveArray( theDriver, Graphic3d_TOPA_POINTS,
644     aExtMakerArray->Indices(), aExtMakerArray->Attributes(), aExtMakerArray->Bounds() );
645 }
646
647 // =======================================================================
648 // subclass : OpenGl_Annotation
649 // function : Destructor
650 // purpose  : 
651 // =======================================================================
652 GEOM_Annotation::OpenGl_Annotation::~OpenGl_Annotation()
653 {
654   Release( NULL );
655 }
656
657 // =======================================================================
658 // subclass : OpenGl_Annotation
659 // function : Release
660 // purpose  : Releases GL resources with the given GL context.
661 // =======================================================================
662 void GEOM_Annotation::OpenGl_Annotation::Release( OpenGl_Context* theCtx )
663 {
664   if (myTextDraw)
665   {
666     myTextDraw->Release( theCtx );
667     myTextLineDraw->Release( theCtx );
668     myExtLineDraw->Release( theCtx );
669     myExtMarkerDraw->Release( theCtx );
670   }
671   myTextDraw      = NULL;
672   myTextLineDraw  = NULL;
673   myExtLineDraw   = NULL;
674   myExtMarkerDraw = NULL;
675 }
676
677 // =======================================================================
678 // subclass : OpenGl_Annotation
679 // function : Render
680 // purpose  : Renders the annotation graphical elements.
681 // =======================================================================
682 void GEOM_Annotation::OpenGl_Annotation::Render( const Handle(OpenGl_Workspace)& theWorkspace ) const
683 {
684   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
685
686   // ---------------------------------------------------------------------
687   // initialize text's font and configure some properties when DPI changes
688   // ---------------------------------------------------------------------
689
690   const unsigned int aDPI = theWorkspace->View()->RenderingParams().Resolution;
691   if (myTextDPI != aDPI)
692   {
693     const OpenGl_AspectText* anAspect = theWorkspace->AspectText();
694
695     // getting string size will also initialize font library
696     myTextDraw->StringSize( aContext,
697       myText, *anAspect, myTextParams, aDPI,
698       myTextSize.x, myTextSize.a, myTextSize.d );
699
700     myTextDPI = aDPI;
701     myTextSize.y = myTextSize.a - myTextSize.d;
702     switch (myTextParams.HAlign)
703     {
704       case Graphic3d_HTA_LEFT:   myTextUnderline.x() = 0.f; break;
705       case Graphic3d_HTA_CENTER: myTextUnderline.x() = -myTextSize.x / 2.f; break;
706       case Graphic3d_HTA_RIGHT:  myTextUnderline.x() = -myTextSize.x; break;
707       default:
708         break;
709     }
710     switch (myTextParams.VAlign)
711     {
712       case Graphic3d_VTA_TOPFIRSTLINE:
713       case Graphic3d_VTA_TOP:    myTextUnderline.y() = -myTextSize.y; break;
714       case Graphic3d_VTA_CENTER: myTextUnderline.y() = -myTextSize.y / 2.f; break;
715       case Graphic3d_VTA_BOTTOM: myTextUnderline.y() = myTextSize.d; break;
716       default:
717         break;
718     }
719
720     Handle(Graphic3d_ArrayOfSegments)
721     aVertexArray = new Graphic3d_ArrayOfSegments( 2 );
722     aVertexArray->AddVertex( myTextUnderline.x(), myTextUnderline.y(), 0.0f );
723     aVertexArray->AddVertex( myTextUnderline.x() + myTextSize.x, myTextUnderline.y(), 0.0f );
724     myTextLineDraw->InitBuffers( aContext, Graphic3d_TOPA_SEGMENTS,
725       aVertexArray->Indices(), aVertexArray->Attributes(), aVertexArray->Bounds() );
726   }
727
728   // ---------------------------------------------
729   // perform view culling test by attachment point
730   // ---------------------------------------------
731
732   const OpenGl_Vec4 aAttach( static_cast<float>( myAISObject->myAttach.X() ),
733                              static_cast<float>( myAISObject->myAttach.Y() ),
734                              static_cast<float>( myAISObject->myAttach.Z() ), 1.F );
735
736   const Handle(Graphic3d_Camera) aCamera = theWorkspace->View()->Camera();
737   const OpenGl_Mat4& aCameraProjMat = aCamera->ProjectionMatrixF();
738   const OpenGl_Mat4& aCameraViewMat = aCamera->OrientationMatrixF();
739   const OpenGl_Vec4 aAttachView = aCameraViewMat * aAttach;
740   if (myAISObject->myIsAutoHide)
741   {
742     const OpenGl_Vec4 aAttachClip = aCameraProjMat * aAttachView;
743     if (Abs( aAttachClip.x() ) > aAttachClip.w()
744      || Abs( aAttachClip.y() ) > aAttachClip.w()
745      || Abs( aAttachClip.z() ) > aAttachClip.w())
746     {
747       return;
748     }
749   }
750
751   const bool toHighlight = theWorkspace->ToHighlight();
752
753   if (toHighlight && myAISObject->myHilightMode == HighlightLabel)
754   {
755     theWorkspace->SetHighlight( false );
756     theWorkspace->ApplyAspectLine();
757   }
758
759   GLint myOldDepthMode = 0;
760
761   if ( myDepthMode )
762   {
763     aContext->core11fwd->glGetIntegerv( GL_DEPTH_FUNC, &myOldDepthMode );
764     aContext->core11fwd->glDepthFunc( myDepthMode );
765   }
766
767   // -------------------------------------------------------------
768   // render text label in current persistence matrix and underline
769   // -------------------------------------------------------------
770
771   if ( myAISObject->myIsScreenFixed )
772   {
773     // use text position property instead of matrix setup 
774     // to avoid jittering when dragging text
775     myTextDraw->SetPosition( OpenGl_Vec3( static_cast<float>( myAISObject->myPosition.X() ),
776                                           static_cast<float>( myAISObject->myPosition.Y() ),
777                                           static_cast<float>( myAISObject->myPosition.Z() ) ) );
778   }
779
780   myTextDraw->Render( theWorkspace );
781
782   // ------------------------------------------------------------
783   // render annotation text's underline
784   // ------------------------------------------------------------
785
786   if ( myAISObject->myIsScreenFixed )
787   {
788     // setup local transformation (in 2D persistence reference)
789     // to represent position of annotation label on screen
790     const OpenGl_Mat4& aViewMat = aContext->WorldViewState.Current();
791     OpenGl_Mat4 aPositionMat;
792     aPositionMat.SetValue( 0, 3, static_cast<float>( myAISObject->myPosition.X() ) );
793     aPositionMat.SetValue( 1, 3, static_cast<float>( myAISObject->myPosition.Y() ) );
794     aPositionMat.SetValue( 2, 3, static_cast<float>( myAISObject->myPosition.Z() ) );
795     OpenGl_Mat4 aPosViewMat = aViewMat * aPositionMat;
796     aContext->WorldViewState.Push();
797     aContext->WorldViewState.SetCurrent( aPosViewMat );
798     aContext->ApplyModelViewMatrix();
799   }
800
801   myTextLineDraw->Render( theWorkspace );
802
803   // ------------------------------------------------------------
804   // render dynamic extension line using synthetic transformation
805   // ------------------------------------------------------------
806
807   OpenGl_Vec4 aCenter (0.f, 0.f, 0.f, 1.f);
808   switch (myTextParams.HAlign)
809   {
810     case Graphic3d_HTA_LEFT:   aCenter.x() =  myTextSize.x / 2.f; break;
811     case Graphic3d_HTA_CENTER: aCenter.x() = 0.f; break;
812     case Graphic3d_HTA_RIGHT:  aCenter.x() = -myTextSize.x / 2.f; break;
813     default: break;
814   }
815   switch (myTextParams.VAlign)
816   {
817     case Graphic3d_VTA_TOPFIRSTLINE:
818     case Graphic3d_VTA_TOP:    aCenter.y() = -myTextSize.y / 2.f; break;
819     case Graphic3d_VTA_CENTER: aCenter.y() = 0.f; break;
820     case Graphic3d_VTA_BOTTOM: aCenter.y() =  myTextSize.y / 2.f; break;
821     default: break;
822   }
823
824   // compute label's center in view coordinate space
825   const OpenGl_Mat4& aViewMat = aContext->WorldViewState.Current();
826   const OpenGl_Vec4 aCenterView = aViewMat * aCenter;
827
828   // the value below defines whether the extension line should be hanging
829   // on the left side of the label or on the right
830   const bool isLeftHanded = aAttachView.x() < aCenterView.x();
831
832   // compute extension line point at the text label in view coordinate space
833   const OpenGl_Vec4 aHingeView = aViewMat * OpenGl_Vec4(
834     ( isLeftHanded ? myTextUnderline.x() : myTextUnderline.x() + myTextSize.x ), myTextUnderline.y(), 0.0f, 1.0f );
835
836   // prepare matrix to specify geometry of extension line in view space
837   // by multiplication of unit z coordinate vector on given matrix.
838   OpenGl_Mat4 aExtGeometryMat;
839   aExtGeometryMat.SetColumn( 2, aAttachView - aHingeView );
840   aExtGeometryMat.SetColumn( 3, aHingeView );
841
842   // setup and draw
843   aContext->ModelWorldState.Push();
844   aContext->ModelWorldState.SetIdentity();
845   aContext->WorldViewState.Push();
846   aContext->WorldViewState.SetCurrent( aExtGeometryMat );
847   aContext->ApplyModelViewMatrix();
848
849   myExtLineDraw->Render( theWorkspace );
850   myExtMarkerDraw->Render( theWorkspace );
851
852   // ------------------------------------------------------------
853   // restore original state
854   // ------------------------------------------------------------
855
856   aContext->ModelWorldState.Pop();
857   aContext->WorldViewState.Pop();
858
859   if ( myOldDepthMode )
860   {
861     aContext->core11fwd->glDepthFunc( myOldDepthMode );
862   }
863
864   if ( myAISObject->myIsScreenFixed )
865   {
866     aContext->WorldViewState.Pop();
867   }
868
869   aContext->ApplyModelViewMatrix();
870
871   if ( toHighlight != theWorkspace->ToHighlight() )
872   {
873     theWorkspace->SetHighlight( toHighlight );
874   }
875 }
876
877 // =======================================================================
878 // subclass : GEOM_AnnotationOwner
879 // function : HilightWithColor
880 // purpose  : Perform highlighting of the presentation.
881 // =======================================================================
882 void GEOM_Annotation::GEOM_AnnotationOwner::HilightWithColor( const Handle(PrsMgr_PresentationManager3d)& thePM,
883                                                               const Handle(Graphic3d_HighlightStyle)& theStyle,
884                                                               const Standard_Integer theMode )
885 {
886   if ( myPrsSh.IsNull() )
887   {
888     Handle(Prs3d_Drawer) aDrawer = new Prs3d_Drawer;
889     aDrawer->Link( Selectable()->HilightAttributes() );
890
891     Handle(Prs3d_IsoAspect) aUIsoAspect = new Prs3d_IsoAspect(
892       aDrawer->UIsoAspect()->Aspect()->Color(),
893       aDrawer->UIsoAspect()->Aspect()->Type(),
894       aDrawer->UIsoAspect()->Aspect()->Width(), 0 );
895
896     Handle(Prs3d_IsoAspect) aVIsoAspect = new Prs3d_IsoAspect(
897       aDrawer->UIsoAspect()->Aspect()->Color(),
898       aDrawer->UIsoAspect()->Aspect()->Type(),
899       aDrawer->UIsoAspect()->Aspect()->Width(), 0 );
900
901     aDrawer->SetIsoOnPlane( Standard_False );
902     aDrawer->SetUIsoAspect( aUIsoAspect );
903     aDrawer->SetVIsoAspect( aVIsoAspect );
904     myPrsSh = new StdSelect_Shape( myShape, aDrawer );
905   }
906
907   myPrsSh->SetZLayer ( Selectable()->ZLayer() );
908
909   thePM->Color( Selectable(), theStyle, theMode, NULL, Graphic3d_ZLayerId_Topmost );
910
911   thePM->Color( myPrsSh, theStyle, theMode, Selectable(), Graphic3d_ZLayerId_Topmost );
912 }
913
914 // =======================================================================
915 // subclass : GEOM_AnnotationOwner
916 // function : Unhilight
917 // purpose  : Removes highlighting from the type of shape.
918 // =======================================================================
919 void GEOM_Annotation::GEOM_AnnotationOwner::Unhilight ( const Handle(PrsMgr_PresentationManager)& thePM,
920                                                         const Standard_Integer theMode )
921 {
922   SelectMgr_EntityOwner::Unhilight( thePM, theMode );
923
924   thePM->Unhighlight( myPrsSh, theMode );
925 }
926
927 // =======================================================================
928 // subclass : GEOM_AnnotationOwner
929 // function : Clear
930 // purpose  : Clears the presentation manager object aPM of all shapes
931 // with the given selection mode.
932 // =======================================================================
933 void GEOM_Annotation::GEOM_AnnotationOwner::Clear ( const Handle(PrsMgr_PresentationManager)& thePM,
934                                                     const Standard_Integer theMode )
935 {
936   SelectMgr_EntityOwner::Clear( thePM, theMode );
937
938   if ( !myPrsSh.IsNull() ) {
939     thePM->Clear( myPrsSh, theMode );
940   }
941
942   myPrsSh.Nullify();
943 }