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