0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / AIS / AIS_LightSource.cxx
1 // Created on: 2020-09-07
2 // Created by: Maria KRYLOVA
3 // Copyright (c) 2020 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <AIS_LightSource.hxx>
17
18 #include <AIS_InteractiveContext.hxx>
19 #include <gp_Quaternion.hxx>
20 #include <Graphic3d_ArrayOfPoints.hxx>
21 #include <Graphic3d_ArrayOfPolylines.hxx>
22 #include <Graphic3d_ArrayOfSegments.hxx>
23 #include <Graphic3d_CView.hxx>
24 #include <Graphic3d_Group.hxx>
25 #include <Prs3d_ArrowAspect.hxx>
26 #include <Prs3d_PointAspect.hxx>
27 #include <Prs3d_Text.hxx>
28 #include <Prs3d_ToolCylinder.hxx>
29 #include <Prs3d_ToolSphere.hxx>
30 #include <Select3D_SensitivePoint.hxx>
31 #include <Select3D_SensitiveSphere.hxx>
32 #include <V3d_View.hxx>
33
34 IMPLEMENT_STANDARD_RTTIEXT(AIS_LightSource, AIS_InteractiveObject)
35 IMPLEMENT_STANDARD_RTTIEXT(AIS_LightSourceOwner, SelectMgr_EntityOwner)
36
37 // =======================================================================
38 // function : AIS_LightSourceOwner
39 // purpose  :
40 // =======================================================================
41 AIS_LightSourceOwner::AIS_LightSourceOwner (const Handle(AIS_LightSource)& theObject,
42                                             Standard_Integer thePriority)
43 : SelectMgr_EntityOwner ((const Handle(SelectMgr_SelectableObject)&)theObject, thePriority)
44 {
45   //
46 }
47
48 // =======================================================================
49 // function : HandleMouseClick
50 // purpose  :
51 // =======================================================================
52 Standard_Boolean AIS_LightSourceOwner::HandleMouseClick (const Graphic3d_Vec2i& ,
53                                                          Aspect_VKeyMouse theKey,
54                                                          Aspect_VKeyFlags theFlags,
55                                                          bool )
56 {
57   AIS_LightSource* aLightSource = dynamic_cast<AIS_LightSource*>(mySelectable);
58   if (aLightSource != NULL
59    && aLightSource->ToSwitchOnClick()
60    && theKey == Aspect_VKeyMouse_LeftButton
61    && theFlags == Aspect_VKeyFlags_NONE)
62   {
63     aLightSource->Light()->SetEnabled (!aLightSource->Light()->IsEnabled());
64     aLightSource->updateLightAspects();
65     return true;
66   }
67   return false;
68 }
69
70 //=======================================================================
71 //function : HilightWithColor
72 //purpose  :
73 //=======================================================================
74 void AIS_LightSourceOwner::HilightWithColor (const Handle(PrsMgr_PresentationManager)& thePM,
75                                              const Handle(Prs3d_Drawer)& theStyle,
76                                              const Standard_Integer theMode)
77 {
78   Handle(AIS_LightSource) aLightSource = Handle(AIS_LightSource)::DownCast (mySelectable);
79   if (aLightSource.IsNull())
80   {
81     return;
82   }
83
84   if (aLightSource->Light()->Type() == Graphic3d_TypeOfLightSource_Directional && aLightSource->myIsDraggable)
85   {
86     Handle(Prs3d_Presentation) aPrs = aLightSource->GetHilightPresentation (thePM);
87     const Graphic3d_ZLayerId aZLayer = theStyle->ZLayer() != -1
88                                      ? theStyle->ZLayer()
89                                      : (thePM->IsImmediateModeOn() ? Graphic3d_ZLayerId_Top : aLightSource->ZLayer());
90     aPrs->Clear();
91     if (aPrs->GetZLayer() != aZLayer)
92     {
93       aPrs->SetZLayer (aZLayer);
94     }
95     Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
96     const gp_Pnt aDetPnt = aLightSource->mySensSphere->LastDetectedPoint();
97     if (aDetPnt.X() == RealLast())
98     {
99       return;
100     }
101     aPoints->AddVertex (aDetPnt);
102     Handle(Graphic3d_Group) aGroup = aPrs->NewGroup();
103     const Handle(Prs3d_PointAspect) aPointAspect = new Prs3d_PointAspect (Aspect_TOM_O_POINT, theStyle->Color(), 3.0f);
104     aGroup->SetGroupPrimitivesAspect (aPointAspect->Aspect());
105     aGroup->AddPrimitiveArray (aPoints);
106
107     const Standard_Real aRadius = aLightSource->Size() * 0.5;
108     const Standard_Integer aNbPnts = int (aLightSource->ArcSize() * 180 / (M_PI * aRadius));
109     TColgp_Array1OfPnt aCircPoints (0, aNbPnts);
110     const gp_Dir aDirNorm (gp_Vec (gp::Origin(), aDetPnt));
111     gp_Dir aDirNormToPln (gp::DY());
112     if (!gp::DX().IsParallel (aDirNorm, Precision::Angular()))
113     {
114       aDirNormToPln = gp::DX().Crossed (aDirNorm);
115     }
116     for (Standard_Integer aStep = 0; aStep < aNbPnts; ++aStep)
117     {
118       aCircPoints.SetValue (aStep, (aDetPnt.Rotated (gp_Ax1 (gp::Origin(), aDirNormToPln), M_PI / 90 * (aStep - aNbPnts / 2))));
119     }
120
121     Handle(Graphic3d_Group) aCircGroup = aPrs->NewGroup();
122     Handle(Graphic3d_ArrayOfPolylines) aPolylines = new Graphic3d_ArrayOfPolylines (aNbPnts * 2, 2);
123     aPolylines->AddBound (aNbPnts);
124
125     for (Standard_Integer anIdx = 0; anIdx < aNbPnts; ++anIdx)
126     {
127       aPolylines->AddVertex (aCircPoints.Value (anIdx).Rotated (gp_Ax1 (gp::Origin(), aDirNorm), M_PI / 2));
128     }
129     aPolylines->AddBound (aNbPnts);
130     for (Standard_Integer anIdx = 0; anIdx < aNbPnts; ++anIdx)
131     {
132       aPolylines->AddVertex (aCircPoints.Value (anIdx));
133     }
134     aCircGroup->AddPrimitiveArray (aPolylines, Standard_False);
135     aCircGroup->SetGroupPrimitivesAspect (theStyle->ArrowAspect()->Aspect());
136     if (thePM->IsImmediateModeOn())
137     {
138       thePM->AddToImmediateList (aPrs);
139     }
140     else
141     {
142       aPrs->Display();
143     }
144   }
145   else
146   {
147     base_type::HilightWithColor (thePM, theStyle, theMode);;
148   }
149 }
150
151 //=======================================================================
152 //function : IsForcedHilight
153 //purpose  :
154 //=======================================================================
155 Standard_Boolean AIS_LightSourceOwner::IsForcedHilight() const
156 {
157   Handle(AIS_LightSource) aLightSource = Handle(AIS_LightSource)::DownCast (mySelectable);
158   if (aLightSource.IsNull())
159   {
160     return Standard_False;
161   }
162   if (aLightSource->Light()->Type() == Graphic3d_TypeOfLightSource_Directional)
163   {
164     return Standard_True;
165   }
166   return Standard_False;
167 }
168
169 // =======================================================================
170 // function : Constructor
171 // purpose  :
172 // =======================================================================
173 AIS_LightSource::AIS_LightSource (const Handle(Graphic3d_CLight)& theLight)
174 : myLightSource (theLight),
175   myCodirMarkerType (Aspect_TOM_X),
176   myOpposMarkerType (Aspect_TOM_O_POINT),
177   mySize (50),
178   myNbArrows (5),
179   myNbSplitsQuadric (theLight->Type() == Graphic3d_TypeOfLightSource_Ambient ? 10 : 30),
180   myNbSplitsArrow (20),
181   mySensSphereArcSize (25),
182   myIsZoomable (theLight->Type() == Graphic3d_TypeOfLightSource_Positional
183              || theLight->Type() == Graphic3d_TypeOfLightSource_Spot),
184   myIsDraggable (theLight->Type() == Graphic3d_TypeOfLightSource_Directional),
185   myToDisplayName (true),
186   myToDisplayRange (true),
187   myToSwitchOnClick (true)
188 {
189   myMarkerTypes[0] = Aspect_TOM_O_X;
190   myMarkerTypes[1] = Aspect_TOM_O_POINT;
191
192   myInfiniteState = true;
193
194   const Quantity_Color aColor = theLight->Color();
195   myDrawer->SetPointAspect (new Prs3d_PointAspect (myMarkerTypes[1], aColor, 3.0f));
196   myDisabledMarkerAspect = new Graphic3d_AspectMarker3d (Aspect_TOM_EMPTY, aColor, 3.0f);
197
198   Graphic3d_MaterialAspect aMat (Graphic3d_NameOfMaterial_UserDefined);
199   aMat.SetColor (aColor);
200   myDrawer->SetArrowAspect (new Prs3d_ArrowAspect());
201   myDrawer->ArrowAspect()->SetColor (aColor);
202   myDrawer->ArrowAspect()->Aspect()->SetShadingModel (Graphic3d_TypeOfShadingModel_Unlit);
203   myDrawer->ArrowAspect()->Aspect()->ChangeFrontMaterial() = aMat;
204   myDrawer->ArrowAspect()->Aspect()->SetMarkerType (Aspect_TOM_EMPTY);
205   myDrawer->ArrowAspect()->Aspect()->SetMarkerScale (2.0f);
206   myArrowLineAspectShadow = new Graphic3d_AspectLine3d (Quantity_NOC_BLACK, Aspect_TOL_SOLID,
207                                                         theLight->Type() != Graphic3d_TypeOfLightSource_Ambient ? 3.0f : 1.0f);
208
209   myDrawer->SetupOwnShadingAspect();
210   myDrawer->ShadingAspect()->SetColor (aColor);
211   myDrawer->ShadingAspect()->SetMaterial (aMat);
212   myDrawer->ShadingAspect()->SetTransparency (0.5f);
213   myDrawer->ShadingAspect()->Aspect()->SetShadingModel (Graphic3d_TypeOfShadingModel_Unlit);
214
215   myDrawer->SetTextAspect (new Prs3d_TextAspect());
216   myDrawer->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_SHADOW);
217   myDrawer->TextAspect()->Aspect()->SetColorSubTitle (Quantity_NOC_BLACK);
218   myDrawer->TextAspect()->SetHorizontalJustification (Graphic3d_HTA_LEFT);
219   myDrawer->TextAspect()->SetVerticalJustification (Graphic3d_VTA_TOPFIRSTLINE);
220
221   updateLightTransformPersistence();
222
223   myDrawer->SetDisplayMode (0);
224   myDynHilightDrawer = new Prs3d_Drawer();
225   myDynHilightDrawer->Link (myDrawer);
226   myDynHilightDrawer->SetDisplayMode (1);
227   myDynHilightDrawer->SetColor (Quantity_NOC_CYAN1);
228
229   if (!myTransformPersistence.IsNull()
230     && myTransformPersistence->IsTrihedronOr2d())
231   {
232     myDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
233     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
234     myDrawer->TextAspect()->SetHorizontalJustification (Graphic3d_HTA_CENTER);
235     myDrawer->TextAspect()->SetVerticalJustification (Graphic3d_VTA_TOP);
236   }
237 }
238
239 //=======================================================================
240 //function : ProcessDragging
241 //purpose  :
242 //=======================================================================
243 Standard_Boolean AIS_LightSource::ProcessDragging (const Handle(AIS_InteractiveContext)& theCtx,
244                                                    const Handle(V3d_View)& theView,
245                                                    const Handle(SelectMgr_EntityOwner)& theOwner,
246                                                    const Graphic3d_Vec2i& theDragFrom,
247                                                    const Graphic3d_Vec2i& theDragTo,
248                                                    const AIS_DragAction theAction)
249 {
250   if (Light()->Type() != Graphic3d_TypeOfLightSource_Directional)
251   {
252     return Standard_False;
253   }
254
255   switch (theAction)
256   {
257     case AIS_DragAction_Start:
258     {
259       myLocTrsfStart = LocalTransformation();
260       return Standard_True;
261     }
262     case AIS_DragAction_Confirmed:
263     {
264       return Standard_True;
265     }
266     case AIS_DragAction_Update:
267     {
268       mySensSphere->ResetLastDetectedPoint();
269       SetLocalTransformation (myLocTrsfStart);
270       theCtx->MainSelector()->Pick (theDragFrom.x(), theDragFrom.y(), theView);
271       gp_Pnt aStartPosition = mySensSphere->LastDetectedPoint();
272
273       mySensSphere->ResetLastDetectedPoint();
274       theCtx->MainSelector()->Pick (theDragTo.x(), theDragTo.y(), theView);
275       gp_Pnt aCurrPosition = mySensSphere->LastDetectedPoint();
276       if (aCurrPosition.X() != RealLast()
277        && aStartPosition.Distance (aCurrPosition) > Precision::Confusion())
278       {
279         gp_Quaternion aQRot;
280         aQRot.SetRotation (gp_Vec (gp_Pnt (0, 0, 0), aStartPosition), gp_Vec (gp_Pnt (0, 0, 0), aCurrPosition));
281         gp_Trsf aTrsf;
282         aTrsf.SetRotation (aQRot);
283         SetLocalTransformation (myLocTrsfStart * aTrsf);
284         const Standard_Integer aHiMod = HasHilightMode() ? HilightMode() : 0;
285         theOwner->UpdateHighlightTrsf (theCtx->CurrentViewer(), theCtx->MainPrsMgr(), aHiMod);
286       }
287       return Standard_True;
288     }
289     case AIS_DragAction_Abort:
290     {
291       return Standard_True;
292     }
293     case AIS_DragAction_Stop:
294     {
295       GetHilightPresentation (theCtx->MainPrsMgr())->Clear();
296       break;
297     }
298   }
299   return Standard_False;
300 }
301
302 // =======================================================================
303 // function : updateLightAspects
304 // purpose  :
305 // =======================================================================
306 void AIS_LightSource::updateLightAspects()
307 {
308   const Quantity_Color aBaseColor = myLightSource->Color();
309   const Quantity_Color aDimColor (aBaseColor.Rgb() * 0.3f);
310   const Quantity_Color aColor = myLightSource->IsEnabled() ? aBaseColor : aDimColor;
311   myDrawer->PointAspect()->SetColor (aColor);
312   myDrawer->PointAspect()->Aspect()->SetMarkerType (MarkerType (myLightSource->IsEnabled()));
313   myDrawer->PointAspect()->Aspect()->SetMarkerImage(MarkerImage(myLightSource->IsEnabled()));
314
315   myDisabledMarkerAspect->SetColor (aColor);
316   myDisabledMarkerAspect->SetMarkerScale(myDrawer->PointAspect()->Aspect()->MarkerScale());
317   myDisabledMarkerAspect->SetMarkerType (myLightSource->IsEnabled() ? Aspect_TOM_EMPTY : MarkerType (false));
318   myDisabledMarkerAspect->SetMarkerImage(MarkerImage (false));
319
320   myDrawer->ShadingAspect()->SetColor (aColor);
321   myDrawer->ArrowAspect()  ->SetColor (aColor);
322   myDrawer->ArrowAspect()->Aspect()->ChangeFrontMaterial().SetColor (aColor);
323
324   if (myLightSource->Type() == Graphic3d_TypeOfLightSource_Directional)
325   {
326     const Standard_Real anAngleTol = 2.0 * M_PI / 180.0;
327     Aspect_TypeOfMarker aDirMark = Aspect_TOM_EMPTY;
328     if (myLightSource->IsEnabled()
329      && myLightSource->IsHeadlight()
330      && myLightSource->Direction().IsParallel (gp::DZ(), anAngleTol))
331     {
332       aDirMark = myLightSource->Direction().IsOpposite (-gp::DZ(), anAngleTol) ? myOpposMarkerType : myCodirMarkerType;
333     }
334     myDrawer->ArrowAspect()->Aspect()->SetMarkerType (aDirMark);
335   }
336   SynchronizeAspects();
337 }
338
339 // =======================================================================
340 // function : updateLightTransformPersistence
341 // purpose  :
342 // =======================================================================
343 void AIS_LightSource::updateLightTransformPersistence()
344 {
345   Handle(Graphic3d_TransformPers) aTrsfPers = myTransformPersistence;
346   switch (myLightSource->Type())
347   {
348     case Graphic3d_TypeOfLightSource_Ambient:
349     {
350       if (!myIsZoomable)
351       {
352         if (aTrsfPers.IsNull() || !aTrsfPers->IsTrihedronOr2d())
353         {
354           aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_UPPER, Graphic3d_Vec2i(50));
355         }
356       }
357       else
358       {
359         aTrsfPers.Nullify();
360       }
361       break;
362     }
363     case Graphic3d_TypeOfLightSource_Directional:
364     {
365       Graphic3d_TransModeFlags aMode = myLightSource->IsHeadlight() ? Graphic3d_TMF_2d : Graphic3d_TMF_TriedronPers;
366       if (myIsZoomable)
367       {
368         aMode = myLightSource->IsHeadlight() ? Graphic3d_TMF_CameraPers : Graphic3d_TMF_None;
369       }
370       if (aMode != Graphic3d_TMF_None)
371       {
372         if (aTrsfPers.IsNull() || aTrsfPers->Mode() != aMode)
373         {
374           if (aMode == Graphic3d_TMF_CameraPers)
375           {
376             aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_CameraPers);
377           }
378           else
379           {
380             aTrsfPers = new Graphic3d_TransformPers (aMode, Aspect_TOTP_LEFT_UPPER, Graphic3d_Vec2i(50));
381           }
382         }
383       }
384       else
385       {
386         aTrsfPers.Nullify();
387       }
388       break;
389     }
390     case Graphic3d_TypeOfLightSource_Positional:
391     case Graphic3d_TypeOfLightSource_Spot:
392     {
393       Graphic3d_TransModeFlags aMode = myLightSource->IsHeadlight()
394                                      ? Graphic3d_TMF_CameraPers
395                                      : (!myIsZoomable ? Graphic3d_TMF_ZoomPers : Graphic3d_TMF_None);
396       if (aMode != Graphic3d_TMF_None)
397       {
398         if (aTrsfPers.IsNull() || aTrsfPers->Mode() != aMode)
399         {
400           if (aMode == Graphic3d_TMF_CameraPers)
401           {
402             aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_CameraPers);
403           }
404           else
405           {
406             aTrsfPers = new Graphic3d_TransformPers (aMode, myLightSource->Position());
407           }
408         }
409         if (aMode == Graphic3d_TMF_ZoomPers)
410         {
411           aTrsfPers->SetAnchorPoint (myLightSource->Position());
412         }
413       }
414       else
415       {
416         aTrsfPers.Nullify();
417       }
418       break;
419     }
420   }
421
422   SetTransformPersistence (aTrsfPers);
423 }
424
425 // =======================================================================
426 // function : updateLightLocalTransformation
427 // purpose  :
428 // =======================================================================
429 void AIS_LightSource::updateLightLocalTransformation()
430 {
431   myLocalTransformation.Nullify();
432   switch (myLightSource->Type())
433   {
434     case Graphic3d_TypeOfLightSource_Ambient:
435     {
436       if (myIsZoomable)
437       {
438         gp_Trsf aTrsf;
439         aTrsf.SetTranslation (gp::Origin(), myLightSource->Position());
440         myLocalTransformation = new TopLoc_Datum3D (aTrsf);
441       }
442       break;
443     }
444     case Graphic3d_TypeOfLightSource_Directional:
445     {
446       const gp_Pnt aLightPos = (myIsZoomable && !myLightSource->IsHeadlight())
447                              ? myLightSource->DisplayPosition()
448                              : gp::Origin();
449       gp_Trsf aTrsf;
450       const gp_Ax2 anAx2 (aLightPos, -myLightSource->Direction());
451       aTrsf.SetTransformation (anAx2, gp_Ax3());
452       myLocalTransformation = new TopLoc_Datum3D (aTrsf);
453       break;
454     }
455     case Graphic3d_TypeOfLightSource_Positional:
456     {
457       if (myIsZoomable)
458       {
459         gp_Trsf aTrsf;
460         aTrsf.SetTranslation (gp::Origin(), myLightSource->Position());
461         myLocalTransformation = new TopLoc_Datum3D (aTrsf);
462       }
463       break;
464     }
465     case Graphic3d_TypeOfLightSource_Spot:
466     {
467       gp_Trsf aTrsf;
468       const gp_Ax2 anAx2 (myIsZoomable ? myLightSource->Position() : gp::Origin(), -myLightSource->Direction());
469       aTrsf.SetTransformation (anAx2, gp_Ax3());
470       myLocalTransformation = new TopLoc_Datum3D (aTrsf);
471       break;
472     }
473   }
474   UpdateTransformation();
475 }
476
477 // =======================================================================
478 // function : setLocalTransformation
479 // purpose  :
480 // =======================================================================
481 void AIS_LightSource::setLocalTransformation (const Handle(TopLoc_Datum3D)& theTrsf)
482 {
483   const gp_Trsf aTrsf = !theTrsf.IsNull() ? theTrsf->Transformation() : gp_Trsf();
484   switch (myLightSource->Type())
485   {
486     case Graphic3d_TypeOfLightSource_Ambient:
487     {
488       break;
489     }
490     case Graphic3d_TypeOfLightSource_Directional:
491     {
492       gp_Dir aNewDir = (-gp::DZ()).Transformed (aTrsf);
493       myLightSource->SetDirection (aNewDir);
494       if (myIsZoomable)
495       {
496         gp_Pnt aNewPos = gp::Origin().Transformed (aTrsf);
497         myLightSource->SetDisplayPosition (aNewPos);
498       }
499       break;
500     }
501     case Graphic3d_TypeOfLightSource_Positional:
502     {
503       gp_Pnt aNewPos = gp::Origin().Transformed (aTrsf);
504       myLightSource->SetPosition (aNewPos);
505       break;
506     }
507     case Graphic3d_TypeOfLightSource_Spot:
508     {
509       gp_Pnt aNewPos = gp::Origin().Transformed (aTrsf);
510       myLightSource->SetPosition (aNewPos);
511
512       gp_Dir aNewDir = (-gp::DZ()).Transformed (aTrsf);
513       myLightSource->SetDirection (aNewDir);
514       break;
515     }
516   }
517
518   base_type::setLocalTransformation (new TopLoc_Datum3D (aTrsf));
519
520   updateLightAspects();
521   updateLightTransformPersistence();
522 }
523
524 // =======================================================================
525 // function : Compute
526 // purpose  :
527 // =======================================================================
528 void AIS_LightSource::Compute (const Handle(PrsMgr_PresentationManager)& ,
529                                const Handle(Prs3d_Presentation)& thePrs,
530                                const Standard_Integer theMode)
531 {
532   thePrs->SetInfiniteState (myInfiniteState);
533   if (theMode != 0
534    && theMode != 1)
535   {
536     return;
537   }
538
539   if (theMode == 0)
540   {
541     updateLightAspects();
542     updateLightTransformPersistence();
543     updateLightLocalTransformation();
544   }
545
546   switch (myLightSource->Type())
547   {
548     case Graphic3d_TypeOfLightSource_Ambient:     computeAmbient    (thePrs, theMode); break;
549     case Graphic3d_TypeOfLightSource_Directional: computeDirectional(thePrs, theMode); break;
550     case Graphic3d_TypeOfLightSource_Positional:  computePositional (thePrs, theMode); break;
551     case Graphic3d_TypeOfLightSource_Spot:        computeSpot       (thePrs, theMode); break;
552   }
553
554   if (myToDisplayName)
555   {
556     TCollection_AsciiString aPrefix = !myTransformPersistence.IsNull()
557                                     && myTransformPersistence->IsTrihedronOr2d()
558                                     ? "\n" : "   ";
559     TCollection_AsciiString aName = aPrefix + myLightSource->Name();
560     Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), aName, gp::Origin());
561   }
562 }
563
564 // =======================================================================
565 // function : computeAmbient
566 // purpose  :
567 // =======================================================================
568 void AIS_LightSource::computeAmbient (const Handle(Prs3d_Presentation)& thePrs,
569                                       const Standard_Integer theMode)
570 {
571   const gp_XYZ aLightPos = gp::Origin().XYZ();
572   if (theMode == 0)
573   {
574     Handle(Graphic3d_ArrayOfTriangles) aSphereArray = Prs3d_ToolSphere::Create (mySize * 0.25, myNbSplitsQuadric, myNbSplitsQuadric, gp_Trsf());
575     Handle(Graphic3d_Group) aSphereGroup = thePrs->NewGroup();
576     aSphereGroup->SetClosed (true);
577     aSphereGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
578     aSphereGroup->AddPrimitiveArray (aSphereArray);
579   }
580   if (theMode == 0
581    || theMode == 1)
582   {
583     const Standard_Real aLen = mySize * 0.25;
584     const Standard_Integer aNbArrows = 6;
585     const gp_Dir aDirList[6] = { -gp::DX(), gp::DX(), -gp::DY(), gp::DY(), -gp::DZ(), gp::DZ() };
586
587     const Prs3d_ToolCylinder aCylTool (mySize * 0.1, 0.0, mySize * 0.2, myNbSplitsArrow, myNbSplitsArrow);
588     Handle(Graphic3d_ArrayOfTriangles) aTrisArray = new Graphic3d_ArrayOfTriangles (aNbArrows * aCylTool.VerticesNb(),
589                                                                                     aNbArrows * aCylTool.TrianglesNb() * 3,
590                                                                                     Graphic3d_ArrayFlags_VertexNormal);
591     Handle(Graphic3d_ArrayOfSegments) aLineArray = new Graphic3d_ArrayOfSegments (aNbArrows * 2);
592     for (Standard_Integer anArrIter = 0; anArrIter < aNbArrows; ++anArrIter)
593     {
594       const gp_Dir& aDir = aDirList[anArrIter];
595       const gp_XYZ  aPnt = aLightPos + aDir.XYZ() * aLen;
596       if (!aLineArray.IsNull())
597       {
598         aLineArray->AddVertex (aPnt + aDir.XYZ() * aLen * 0.5);
599         aLineArray->AddVertex (aPnt + aDir.XYZ() * aLen * 1.5);
600       }
601       if (!aTrisArray.IsNull())
602       {
603         const gp_Ax3 aSystem (aPnt + aDir.XYZ() * aLen, -aDir);
604         gp_Trsf aTrsfCone;
605         aTrsfCone.SetTransformation (aSystem, gp_Ax3());
606         aCylTool.FillArray (aTrisArray, aTrsfCone);
607       }
608     }
609
610     if (!aLineArray.IsNull())
611     {
612       Handle(Graphic3d_Group) aDirGroupShadow = thePrs->NewGroup();
613       aDirGroupShadow->SetGroupPrimitivesAspect (myArrowLineAspectShadow);
614       aDirGroupShadow->AddPrimitiveArray (aLineArray);
615     }
616     if (!aTrisArray.IsNull())
617     {
618       Handle(Graphic3d_Group) anArrowGroup = thePrs->NewGroup();
619       anArrowGroup->SetClosed (true);
620       anArrowGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
621       anArrowGroup->AddPrimitiveArray (aTrisArray);
622     }
623   }
624
625   {
626     Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
627     aPoints->AddVertex (aLightPos);
628     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
629     aGroup->SetGroupPrimitivesAspect (theMode == 1 ? myDrawer->PointAspect()->Aspect() : myDisabledMarkerAspect);
630     aGroup->AddPrimitiveArray (aPoints);
631   }
632 }
633
634 // =======================================================================
635 // function : computeDirectional
636 // purpose  :
637 // =======================================================================
638 void AIS_LightSource::computeDirectional (const Handle(Prs3d_Presentation)& thePrs,
639                                           const Standard_Integer theMode)
640 {
641   const Standard_Real aDistance = mySize * 0.5;
642   const Standard_Real aStep = aDistance * 0.5;
643
644   // light source direction is set to local transformation
645   const gp_Dir aLightDir = -gp::DZ();
646   const gp_XYZ aLightPos = -aStep * aLightDir.XYZ();
647
648   Standard_Integer aNbArrows = 1;
649   if      (myNbArrows >= 9) { aNbArrows = 9; }
650   else if (myNbArrows >= 5) { aNbArrows = 5; }
651   else if (myNbArrows >= 3) { aNbArrows = 3; }
652   TColgp_Array1OfPnt aPoints (1, aNbArrows);
653   {
654     const gp_Ax2 anAxes (gp::Origin(), aLightDir);
655     const gp_XYZ aDY = anAxes.YDirection().XYZ() * aStep;
656     const gp_XYZ aDX = anAxes.XDirection().XYZ() * aStep;
657     const gp_XYZ aDXY = aDX + aDY;
658     switch (aNbArrows)
659     {
660       case 9:
661       {
662         aPoints.SetValue (6, aLightPos + aDY);
663         aPoints.SetValue (7, aLightPos + aDX);
664         aPoints.SetValue (8, aLightPos - aDY);
665         aPoints.SetValue (9, aLightPos - aDX);
666       }
667       Standard_FALLTHROUGH
668       case 5:
669       {
670         aPoints.SetValue (4, aLightPos - aDY + aDX);
671         aPoints.SetValue (5, aLightPos + aDY - aDX);
672       }
673       Standard_FALLTHROUGH
674       case 3:
675       {
676         aPoints.SetValue (2, aLightPos + aDXY);
677         aPoints.SetValue (3, aLightPos - aDXY);
678       }
679       Standard_FALLTHROUGH
680       case 1:
681       {
682         aPoints.SetValue (1, aLightPos);
683         break;
684       }
685     }
686   }
687
688   const Prs3d_ToolCylinder aCylTool (aDistance * 0.1, 0.0, aDistance * 0.2, myNbSplitsArrow, myNbSplitsArrow);
689   Handle(Graphic3d_ArrayOfTriangles) aTrisArray;
690   if (theMode == 0)
691   {
692     aTrisArray = new Graphic3d_ArrayOfTriangles (aNbArrows * aCylTool.VerticesNb(),
693                                                  aNbArrows * aCylTool.TrianglesNb() * 3,
694                                                  Graphic3d_ArrayFlags_VertexNormal);
695   }
696   Handle(Graphic3d_ArrayOfPoints) aPntArray = new Graphic3d_ArrayOfPoints (aNbArrows);
697   Handle(Graphic3d_ArrayOfSegments) aLineArray = new Graphic3d_ArrayOfSegments (aNbArrows * 2);
698   for (Standard_Integer aPntIter = aPoints.Lower(); aPntIter <= aPoints.Upper(); ++aPntIter)
699   {
700     const gp_Pnt aPnt = aPoints.Value (aPntIter);
701     if (!aPntArray.IsNull())
702     {
703       aPntArray->AddVertex (aPnt);
704     }
705     if (!aLineArray.IsNull())
706     {
707       aLineArray->AddVertex (aPnt);
708       aLineArray->AddVertex (gp_Pnt (aPnt.XYZ() + aLightDir.XYZ() * aDistance));
709     }
710     if (!aTrisArray.IsNull())
711     {
712       const gp_Ax3 aSystem (aPnt.XYZ() + aLightDir.XYZ() * aDistance, aLightDir);
713       gp_Trsf aTrsfCone;
714       aTrsfCone.SetTransformation (aSystem, gp_Ax3());
715       aCylTool.FillArray (aTrisArray, aTrsfCone);
716     }
717   }
718
719   if (!aLineArray.IsNull() && theMode == 0)
720   {
721     Handle(Graphic3d_Group) aDirGroupShadow = thePrs->NewGroup();
722     aDirGroupShadow->SetGroupPrimitivesAspect (myArrowLineAspectShadow);
723     aDirGroupShadow->AddPrimitiveArray (aLineArray);
724   }
725   if (!aLineArray.IsNull())
726   {
727     Handle(Graphic3d_Group) aDirGroup = thePrs->NewGroup();
728     aDirGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
729     aDirGroup->AddPrimitiveArray (aLineArray);
730   }
731   if (!aTrisArray.IsNull())
732   {
733     Handle(Graphic3d_Group) anArrowGroup = thePrs->NewGroup();
734     anArrowGroup->SetClosed (true);
735     anArrowGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
736     anArrowGroup->AddPrimitiveArray (aTrisArray);
737   }
738   if (!aPntArray.IsNull())
739   {
740     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
741     aGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
742     aGroup->AddPrimitiveArray (aPntArray);
743   }
744   {
745     Handle(Graphic3d_ArrayOfPoints) aPntArray2 = new Graphic3d_ArrayOfPoints (1);
746     aPntArray2->AddVertex (aLightPos);
747     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
748     aGroup->SetGroupPrimitivesAspect (myDisabledMarkerAspect);
749     aGroup->AddPrimitiveArray (aPntArray2);
750   }
751 }
752
753 // =======================================================================
754 // function : computePositional
755 // purpose  :
756 // =======================================================================
757 void AIS_LightSource::computePositional (const Handle(Prs3d_Presentation)& thePrs,
758                                          const Standard_Integer theMode)
759 {
760   // light source position is set to local transformation
761   const gp_XYZ aLightPos = gp::Origin().XYZ();
762   const Standard_Real aRadius = (myIsZoomable && myLightSource->HasRange()) ? myLightSource->Range() : 0.0;
763   if (theMode == 0
764    && aRadius > 0.0
765    && myToDisplayRange)
766   {
767     Handle(Graphic3d_ArrayOfTriangles) aPosRangeArray = Prs3d_ToolSphere::Create (aRadius, myNbSplitsQuadric, myNbSplitsQuadric, gp_Trsf());
768     Handle(Graphic3d_Group) aRangeGroup = thePrs->NewGroup();
769     aRangeGroup->SetClosed (true);
770     aRangeGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
771     aRangeGroup->AddPrimitiveArray (aPosRangeArray);
772   }
773   {
774     Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
775     aPoints->AddVertex (aLightPos);
776     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
777     aGroup->SetGroupPrimitivesAspect (myDrawer->PointAspect()->Aspect());
778     aGroup->AddPrimitiveArray (aPoints);
779   }
780 }
781
782 // =======================================================================
783 // function : computeSpot
784 // purpose  :
785 // =======================================================================
786 void AIS_LightSource::computeSpot (const Handle(Prs3d_Presentation)& thePrs,
787                                    const Standard_Integer theMode)
788 {
789   // light source position and direction are set to local transformation
790   const gp_Dir aLightDir = -gp::DZ();
791   const gp_XYZ aLightPos = gp::Origin().XYZ();
792   const Standard_Real aDistance = (myIsZoomable && myLightSource->HasRange()) ? myLightSource->Range() : mySize;
793   {
794     Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (1);
795     aPoints->AddVertex (aLightPos);
796
797     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
798     aGroup->SetGroupPrimitivesAspect (myDrawer->PointAspect()->Aspect());
799     aGroup->AddPrimitiveArray (aPoints);
800   }
801
802   {
803     Handle(Graphic3d_ArrayOfSegments) aDirArray = new Graphic3d_ArrayOfSegments (2);
804     aDirArray->AddVertex (aLightPos);
805     aDirArray->AddVertex (gp_Pnt (aLightPos + aLightDir.XYZ() * aDistance));
806
807     Handle(Graphic3d_Group) aDirGroupShadow = thePrs->NewGroup();
808     aDirGroupShadow->SetClosed (true);
809     aDirGroupShadow->SetGroupPrimitivesAspect (myArrowLineAspectShadow);
810     aDirGroupShadow->AddPrimitiveArray (aDirArray);
811
812     Handle(Graphic3d_Group) aDirGroup = thePrs->NewGroup();
813     aDirGroup->SetClosed (true);
814     aDirGroup->SetGroupPrimitivesAspect (myDrawer->ArrowAspect()->Aspect());
815     aDirGroup->AddPrimitiveArray (aDirArray);
816   }
817
818   if (theMode == 0
819    && myToDisplayRange)
820   {
821     const Standard_ShortReal aHalfAngle = myLightSource->Angle() / 2.0f;
822     const Standard_Real aRadius = aDistance * Tan (aHalfAngle);
823     gp_Ax3  aSystem (aLightPos + aLightDir.XYZ() * aDistance, -aLightDir);
824     gp_Trsf aTrsfCone;
825     aTrsfCone.SetTransformation (aSystem, gp_Ax3());
826     Handle(Graphic3d_ArrayOfTriangles) aSpotRangeArray = Prs3d_ToolCylinder::Create (aRadius, 0.0, aDistance,
827                                                                                      myNbSplitsQuadric, myNbSplitsQuadric, aTrsfCone);
828
829     Handle(Graphic3d_Group) aRangeGroup = thePrs->NewGroup();
830     aRangeGroup->SetClosed (true);
831     aRangeGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
832     aRangeGroup->AddPrimitiveArray (aSpotRangeArray);
833   }
834 }
835
836 // =======================================================================
837 // function : ComputeSelection
838 // purpose  :
839 // =======================================================================
840 void AIS_LightSource::ComputeSelection (const Handle(SelectMgr_Selection)& theSel,
841                                         const Standard_Integer theMode)
842 {
843   if (theMode != 0)
844   {
845     return;
846   }
847
848   Handle(AIS_LightSourceOwner) anEntityOwner = new AIS_LightSourceOwner (this, 15);
849   {
850     if (myLightSource->Type() == Graphic3d_TypeOfLightSource_Directional)
851     {
852       mySensSphere = new Select3D_SensitiveSphere (anEntityOwner, gp::Origin(), mySize * 0.5);
853       theSel->Add (mySensSphere);
854     }
855
856     Handle(Select3D_SensitivePoint) aSensPosition = new Select3D_SensitivePoint (anEntityOwner, gp::Origin());
857     aSensPosition->SetSensitivityFactor (12);
858     if (!myTransformPersistence.IsNull()
859       && myTransformPersistence->IsTrihedronOr2d())
860     {
861       aSensPosition->SetSensitivityFactor (Max (12, Standard_Integer (mySize * 0.5)));
862     }
863     theSel->Add (aSensPosition);
864   }
865 }