0025773: Visualization - remove AIS_Drawer class and transfer its Link() logic to...
[occt.git] / src / AIS / AIS_PointCloud.cxx
1 // Created on: 2014-08-13
2 // Created by: Maxim GLIBIN
3 // Copyright (c) 2014 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_PointCloud.hxx>
17
18 #include <AIS_GraphicTool.hxx>
19 #include <Graphic3d_AspectFillArea3d.hxx>
20 #include <Graphic3d_AspectMarker3d.hxx>
21 #include <Graphic3d_Group.hxx>
22 #include <Prs3d_Drawer.hxx>
23 #include <Prs3d_PointAspect.hxx>
24 #include <Prs3d_Presentation.hxx>
25 #include <Prs3d_Root.hxx>
26 #include <Prs3d_ShadingAspect.hxx>
27 #include <PrsMgr_ModedPresentation.hxx>
28 #include <PrsMgr_Presentations.hxx>
29 #include <Select3D_SensitiveBox.hxx>
30 #include <SelectMgr_EntityOwner.hxx>
31 #include <SelectMgr_Selection.hxx>
32 #include <StdPrs_WFDeflectionRestrictedFace.hxx>
33
34 IMPLEMENT_STANDARD_HANDLE (AIS_PointCloud, AIS_InteractiveObject)
35 IMPLEMENT_STANDARD_RTTIEXT(AIS_PointCloud, AIS_InteractiveObject)
36
37 //==================================================
38 // Function: AIS_PointCloud
39 // Purpose : Constructor
40 //==================================================
41 AIS_PointCloud::AIS_PointCloud()
42 {
43   SetDisplayMode (AIS_PointCloud::DM_Points);
44   SetHilightMode (AIS_PointCloud::DM_BndBox);
45 }
46
47 //=======================================================================
48 //function : GetPoints
49 //purpose  :
50 //=======================================================================
51 const Handle(Graphic3d_ArrayOfPoints) AIS_PointCloud::GetPoints() const
52 {
53   return myPoints;
54 }
55
56 //=======================================================================
57 //function : GetBoundingBox
58 //purpose  :
59 //=======================================================================
60 Bnd_Box AIS_PointCloud::GetBoundingBox() const
61 {
62   return myBndBox;
63 }
64
65 //! Auxiliary method
66 static inline Bnd_Box getBoundingBox (const Handle(Graphic3d_ArrayOfPoints)& thePoints)
67 {
68   Bnd_Box aBndBox;
69   if (thePoints.IsNull())
70   {
71     return aBndBox;
72   }
73
74   const Standard_Integer aNbVertices = thePoints->VertexNumber();
75   for (Standard_Integer aVertIter = 1; aVertIter <= aNbVertices; ++aVertIter)
76   {
77     aBndBox.Add (thePoints->Vertice (aVertIter));
78   }
79   return aBndBox;
80 }
81
82 //=======================================================================
83 //function : SetPoints
84 //purpose  :
85 //=======================================================================
86 void AIS_PointCloud::SetPoints (const Handle(Graphic3d_ArrayOfPoints)& thePoints)
87 {
88   myPoints = thePoints;
89   myBndBox = getBoundingBox (thePoints);
90 }
91
92 //=======================================================================
93 //function : SetPoints
94 //purpose  :
95 //=======================================================================
96 void AIS_PointCloud::SetPoints (const Handle(TColgp_HArray1OfPnt)&     theCoords,
97                                 const Handle(Quantity_HArray1OfColor)& theColors,
98                                 const Handle(TColgp_HArray1OfDir)&     theNormals)
99 {
100   myPoints.Nullify();
101   myBndBox.SetVoid();
102   if (theCoords.IsNull())
103   {
104     return;
105   }
106
107   const Standard_Integer aNbPoints = theCoords->Length();
108   if ((!theNormals.IsNull() && theNormals->Length() != aNbPoints)
109    || (!theColors.IsNull()  && theColors->Length()  != aNbPoints))
110   {
111     // invalid input
112     return;
113   }
114
115   const Standard_Boolean hasColors  = !theColors.IsNull()  && theColors->Length()  == aNbPoints;
116   const Standard_Boolean hasNormals = !theNormals.IsNull() && theNormals->Length() == aNbPoints;
117
118   const Standard_Integer aDiffColors  = hasColors  ? (theColors->Lower()  - theCoords->Lower()) : 0;
119   const Standard_Integer aDiffNormals = hasNormals ? (theNormals->Lower() - theCoords->Lower()) : 0;
120
121   myPoints = new Graphic3d_ArrayOfPoints (aNbPoints, hasColors, hasNormals);
122   for (Standard_Integer aPntIter = theCoords->Lower(); aPntIter <= theCoords->Upper(); ++aPntIter)
123   {
124     myPoints->AddVertex (theCoords->Value (aPntIter));
125     if (hasColors)
126     {
127       myPoints->SetVertexColor (myPoints->VertexNumber(),
128                                 theColors->Value (aPntIter + aDiffColors));
129     }
130     if (hasNormals)
131     {
132       myPoints->SetVertexNormal (myPoints->VertexNumber(),
133                                  theNormals->Value (aPntIter + aDiffNormals));
134     }
135   }
136   myBndBox = getBoundingBox (myPoints);
137 }
138
139 //=======================================================================
140 //function : SetColor
141 //purpose  :
142 //=======================================================================
143 void AIS_PointCloud::SetColor (const Quantity_NameOfColor theColor)
144 {
145   SetColor (Quantity_Color (theColor));
146 }
147
148 //=======================================================================
149 //function : SetColor
150 //purpose  :
151 //=======================================================================
152 void AIS_PointCloud::SetColor (const Quantity_Color& theColor)
153 {
154   AIS_InteractiveObject::SetColor(theColor);
155
156   if (!myDrawer->HasOwnPointAspect())
157   {
158     myDrawer->SetPointAspect (new Prs3d_PointAspect (Aspect_TOM_POINT, theColor, 1.0));
159     if (myDrawer->HasLink())
160     {
161       *myDrawer->PointAspect()->Aspect() = *myDrawer->Link()->PointAspect()->Aspect();
162     }
163   }
164   if (!myDrawer->HasOwnShadingAspect())
165   {
166     myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
167     if (myDrawer->HasLink())
168     {
169       *myDrawer->ShadingAspect()->Aspect() = *myDrawer->Link()->ShadingAspect()->Aspect();
170     }
171   }
172
173   // Override color
174   myDrawer->ShadingAspect()->SetColor (theColor);
175   myDrawer->PointAspect()  ->SetColor (theColor);
176
177   const PrsMgr_Presentations&        aPrsList     = Presentations();
178   Handle(Graphic3d_AspectMarker3d)   aPointAspect = myDrawer->PointAspect()->Aspect();
179   Handle(Graphic3d_AspectFillArea3d) anAreaAspect = myDrawer->ShadingAspect()->Aspect();
180   for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
181   {
182     const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
183     if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
184     {
185       continue;
186     }
187
188     const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
189
190     // Set aspects for presentation
191     aPrs->SetPrimitivesAspect (aPointAspect);
192     aPrs->SetPrimitivesAspect (anAreaAspect);
193
194     // Go through all groups to change color for all primitives
195     for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
196     {
197       const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
198       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_MARKER))
199       {
200         aGroup->SetGroupPrimitivesAspect (aPointAspect);
201       }
202       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
203       {
204         aGroup->SetGroupPrimitivesAspect (anAreaAspect);
205       }
206     }
207   }
208 }
209
210 //=======================================================================
211 //function : UnsetColor
212 //purpose  :
213 //=======================================================================
214 void AIS_PointCloud::UnsetColor()
215 {
216   if (!HasColor())
217   {
218     return;
219   }
220
221   AIS_InteractiveObject::UnsetColor();
222
223   if (!HasWidth())
224   {
225     myDrawer->SetPointAspect (Handle(Prs3d_PointAspect)());
226   }
227   else
228   {
229     Quantity_Color      aColor = Quantity_NOC_YELLOW;
230     Aspect_TypeOfMarker aType  = Aspect_TOM_POINT;
231     Standard_Real       aScale = 1.0;
232     if (myDrawer->HasLink())
233     {
234       myDrawer->Link()->PointAspect()->Aspect()->Values (aColor, aType, aScale);
235     }
236     myDrawer->PointAspect()->SetColor (aColor);
237   }
238
239   if (HasMaterial()
240    || IsTransparent())
241   {
242     Graphic3d_MaterialAspect aDefaultMat (Graphic3d_NOM_BRASS);
243     Graphic3d_MaterialAspect aMat = aDefaultMat;
244     if (HasMaterial() || myDrawer->HasLink())
245     {
246       aMat = AIS_GraphicTool::GetMaterial (HasMaterial() ? myDrawer : myDrawer->Link());
247     }
248     if (HasMaterial())
249     {
250       Quantity_Color aColor = aDefaultMat.AmbientColor();
251       if (myDrawer->HasLink())
252       {
253         aColor = myDrawer->Link()->ShadingAspect()->Color (myCurrentFacingModel);
254       }
255       aMat.SetColor (aColor);
256     }
257     if (IsTransparent())
258     {
259       Standard_Real aTransp = myDrawer->ShadingAspect()->Transparency (myCurrentFacingModel);
260       aMat.SetTransparency (aTransp);
261     }
262     myDrawer->ShadingAspect()->SetMaterial (aMat, myCurrentFacingModel);
263   }
264   else
265   {
266     myDrawer->SetShadingAspect (Handle(Prs3d_ShadingAspect)());
267   }
268   myDrawer->SetPointAspect (Handle(Prs3d_PointAspect)());
269
270   // modify shading presentation without re-computation
271   const PrsMgr_Presentations&        aPrsList   = Presentations();
272   Handle(Graphic3d_AspectFillArea3d) anAreaAsp  = myDrawer->Link()->ShadingAspect()->Aspect();
273   Handle(Graphic3d_AspectMarker3d)   aMarkerAsp = myDrawer->Link()->PointAspect()->Aspect();
274   for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
275   {
276     const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
277     if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
278     {
279       continue;
280     }
281
282     const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
283     aPrs->SetPrimitivesAspect (anAreaAsp);
284     aPrs->SetPrimitivesAspect (aMarkerAsp);
285     for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
286     {
287       const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
288
289       // Check if aspect of given type is set for the group,
290       // because setting aspect for group with no already set aspect
291       // can lead to loss of presentation data
292       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
293       {
294         aGroup->SetGroupPrimitivesAspect (anAreaAsp);
295       }
296       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_MARKER))
297       {
298         aGroup->SetGroupPrimitivesAspect (aMarkerAsp);
299       }
300     }
301   }
302 }
303
304 //=======================================================================
305 //function : SetMaterial
306 //purpose  :
307 //=======================================================================
308 void AIS_PointCloud::SetMaterial (const Graphic3d_NameOfMaterial theMatName)
309 {
310   SetMaterial (Graphic3d_MaterialAspect (theMatName));
311 }
312
313 //=======================================================================
314 //function : SetMaterial
315 //purpose  :
316 //=======================================================================
317 void AIS_PointCloud::SetMaterial (const Graphic3d_MaterialAspect& theMat)
318 {
319   if (!myDrawer->HasOwnShadingAspect())
320   {
321     myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
322     if (myDrawer->HasLink())
323     {
324       *myDrawer->ShadingAspect()->Aspect() = *myDrawer->Link()->ShadingAspect()->Aspect();
325     }
326   }
327   hasOwnMaterial = Standard_True;
328
329   myDrawer->ShadingAspect()->SetMaterial (theMat, myCurrentFacingModel);
330   if (HasColor())
331   {
332     myDrawer->ShadingAspect()->SetColor (myOwnColor, myCurrentFacingModel);
333   }
334   myDrawer->ShadingAspect()->SetTransparency (myTransparency, myCurrentFacingModel);
335
336   // modify shading presentation without re-computation
337   const PrsMgr_Presentations&        aPrsList  = Presentations();
338   Handle(Graphic3d_AspectFillArea3d) anAreaAsp = myDrawer->ShadingAspect()->Aspect();
339   for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
340   {
341     const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
342     if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
343     {
344       continue;
345     }
346
347     const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
348     aPrs->SetPrimitivesAspect (anAreaAsp);
349     for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
350     {
351       const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
352       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
353       {
354         aGroup->SetGroupPrimitivesAspect (anAreaAsp);
355       }
356     }
357   }
358 }
359
360 //=======================================================================
361 //function : UnsetMaterial
362 //purpose  :
363 //=======================================================================
364 void AIS_PointCloud::UnsetMaterial()
365 {
366   if (!HasMaterial())
367   {
368     return;
369   }
370
371   if (HasColor()
372    || IsTransparent())
373   {
374     Graphic3d_MaterialAspect aDefaultMat (Graphic3d_NOM_BRASS);
375     myDrawer->ShadingAspect()->SetMaterial (myDrawer->HasLink() ?
376                                             myDrawer->Link()->ShadingAspect()->Material (myCurrentFacingModel) :
377                                             aDefaultMat,
378                                             myCurrentFacingModel);
379     if (HasColor())
380     {
381       myDrawer->ShadingAspect()->SetColor        (myOwnColor,     myCurrentFacingModel);
382       myDrawer->ShadingAspect()->SetTransparency (myTransparency, myCurrentFacingModel);
383     }
384   }
385   else
386   {
387     myDrawer->SetShadingAspect (Handle(Prs3d_ShadingAspect)());
388   }
389   hasOwnMaterial = Standard_False;
390
391   // modify shading presentation without re-computation
392   const PrsMgr_Presentations&        aPrsList  = Presentations();
393   Handle(Graphic3d_AspectFillArea3d) anAreaAsp = myDrawer->ShadingAspect()->Aspect();
394   for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
395   {
396     const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
397     if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
398     {
399       continue;
400     }
401
402     const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
403     aPrs->SetPrimitivesAspect (anAreaAsp);
404     for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
405     {
406       const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
407       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
408       {
409         aGroup->SetGroupPrimitivesAspect (anAreaAsp);
410       }
411     }
412   }
413 }
414
415 //=======================================================================
416 //function : Compute
417 //purpose  :
418 //=======================================================================
419 void AIS_PointCloud::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePrsMgr*/,
420                               const Handle(Prs3d_Presentation)&           thePrs,
421                               const Standard_Integer                      theMode)
422 {
423   thePrs->Clear();
424   switch (theMode)
425   {
426     case AIS_PointCloud::DM_Points:
427     {
428       const Handle(Graphic3d_ArrayOfPoints) aPoints = GetPoints();
429       if (aPoints.IsNull())
430       {
431         return;
432       }
433
434       Handle(Graphic3d_AspectMarker3d) aMarkerAspect = myDrawer->PointAspect()->Aspect();
435       if (!myDrawer->HasOwnPointAspect())
436       {
437         aMarkerAspect->SetType (Aspect_TOM_POINT);
438       }
439
440       Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePrs);
441       aGroup->SetGroupPrimitivesAspect (aMarkerAspect);
442       aGroup->AddPrimitiveArray (aPoints);
443       break;
444     }
445     case AIS_PointCloud::DM_BndBox:
446     {
447       Bnd_Box aBndBox = GetBoundingBox();
448       if (aBndBox.IsVoid())
449       {
450         return;
451       }
452
453       StdPrs_WFDeflectionRestrictedFace::AddBox (thePrs, aBndBox, myDrawer);
454       break;
455     }
456   }
457 }
458
459 //=======================================================================
460 //function : ComputeSelection
461 //purpose  :
462 //=======================================================================
463 void AIS_PointCloud::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
464                                        const Standard_Integer             /*theMode*/)
465 {
466   Bnd_Box aBndBox = GetBoundingBox();
467   if (aBndBox.IsVoid())
468   {
469     return;
470   }
471
472   Handle(SelectMgr_EntityOwner) anOwner  = new SelectMgr_EntityOwner (this);
473   Handle(Select3D_SensitiveBox) aSensBox = new Select3D_SensitiveBox (anOwner, aBndBox);
474   theSelection->Add (aSensBox);
475 }