\feff0025129: Visualization - add interactive object for Points Cloud objects
[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_Drawer.hxx>
19 #include <AIS_GraphicTool.hxx>
20 #include <Graphic3d_AspectFillArea3d.hxx>
21 #include <Graphic3d_AspectMarker3d.hxx>
22 #include <Graphic3d_Group.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->HasPointAspect())
157   {
158     myDrawer->SetPointAspect (new Prs3d_PointAspect (Aspect_TOM_POINT, theColor, 1.0));
159     *myDrawer->PointAspect()->Aspect() = *myDrawer->Link()->PointAspect()->Aspect();
160   }
161   if (!myDrawer->HasShadingAspect())
162   {
163     myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
164     *myDrawer->ShadingAspect()->Aspect() = *myDrawer->Link()->ShadingAspect()->Aspect();
165   }
166
167   // Override color
168   myDrawer->ShadingAspect()->SetColor (theColor);
169   myDrawer->PointAspect()  ->SetColor (theColor);
170
171   const PrsMgr_Presentations&        aPrsList     = Presentations();
172   Handle(Graphic3d_AspectMarker3d)   aPointAspect = myDrawer->PointAspect()->Aspect();
173   Handle(Graphic3d_AspectFillArea3d) anAreaAspect = myDrawer->ShadingAspect()->Aspect();
174   for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
175   {
176     const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
177     if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
178     {
179       continue;
180     }
181
182     const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
183
184     // Set aspects for presentation
185     aPrs->SetPrimitivesAspect (aPointAspect);
186     aPrs->SetPrimitivesAspect (anAreaAspect);
187
188     // Go through all groups to change color for all primitives
189     for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
190     {
191       const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
192       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_MARKER))
193       {
194         aGroup->SetGroupPrimitivesAspect (aPointAspect);
195       }
196       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
197       {
198         aGroup->SetGroupPrimitivesAspect (anAreaAspect);
199       }
200     }
201   }
202 }
203
204 //=======================================================================
205 //function : UnsetColor
206 //purpose  :
207 //=======================================================================
208 void AIS_PointCloud::UnsetColor()
209 {
210   if (!HasColor())
211   {
212     return;
213   }
214
215   AIS_InteractiveObject::UnsetColor();
216
217   if (!HasWidth())
218   {
219     myDrawer->SetPointAspect (Handle(Prs3d_PointAspect)());
220   }
221   else
222   {
223     Quantity_Color      aColor;
224     Aspect_TypeOfMarker aType  = Aspect_TOM_POINT;
225     Standard_Real       aScale = 1.0;
226     myDrawer->Link()->PointAspect()->Aspect()->Values (aColor, aType, aScale);
227     myDrawer->PointAspect()->SetColor (aColor);
228   }
229
230   if (HasMaterial()
231    || IsTransparent())
232   {
233     Graphic3d_MaterialAspect aMat = AIS_GraphicTool::GetMaterial (HasMaterial() ? myDrawer : myDrawer->Link());
234     if (HasMaterial())
235     {
236       Quantity_Color aColor = myDrawer->Link()->ShadingAspect()->Color (myCurrentFacingModel);
237       aMat.SetColor (aColor);
238     }
239     if (IsTransparent())
240     {
241       Standard_Real aTransp = myDrawer->ShadingAspect()->Transparency (myCurrentFacingModel);
242       aMat.SetTransparency (aTransp);
243     }
244     myDrawer->ShadingAspect()->SetMaterial (aMat, myCurrentFacingModel);
245   }
246   else
247   {
248     myDrawer->SetShadingAspect (Handle(Prs3d_ShadingAspect)());
249   }
250   myDrawer->SetPointAspect (Handle(Prs3d_PointAspect)());
251
252   // modify shading presentation without re-computation
253   const PrsMgr_Presentations&        aPrsList   = Presentations();
254   Handle(Graphic3d_AspectFillArea3d) anAreaAsp  = myDrawer->Link()->ShadingAspect()->Aspect();
255   Handle(Graphic3d_AspectMarker3d)   aMarkerAsp = myDrawer->Link()->PointAspect()->Aspect();
256   for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
257   {
258     const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
259     if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
260     {
261       continue;
262     }
263
264     const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
265     aPrs->SetPrimitivesAspect (anAreaAsp);
266     aPrs->SetPrimitivesAspect (aMarkerAsp);
267     for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
268     {
269       const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
270
271       // Check if aspect of given type is set for the group,
272       // because setting aspect for group with no already set aspect
273       // can lead to loss of presentation data
274       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
275       {
276         aGroup->SetGroupPrimitivesAspect (anAreaAsp);
277       }
278       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_MARKER))
279       {
280         aGroup->SetGroupPrimitivesAspect (aMarkerAsp);
281       }
282     }
283   }
284 }
285
286 //=======================================================================
287 //function : SetMaterial
288 //purpose  :
289 //=======================================================================
290 void AIS_PointCloud::SetMaterial (const Graphic3d_NameOfMaterial theMatName)
291 {
292   SetMaterial (Graphic3d_MaterialAspect (theMatName));
293 }
294
295 //=======================================================================
296 //function : SetMaterial
297 //purpose  :
298 //=======================================================================
299 void AIS_PointCloud::SetMaterial (const Graphic3d_MaterialAspect& theMat)
300 {
301   if (!myDrawer->HasShadingAspect())
302   {
303     myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
304     *myDrawer->ShadingAspect()->Aspect() = *myDrawer->Link()->ShadingAspect()->Aspect();
305   }
306   hasOwnMaterial = Standard_True;
307
308   myDrawer->ShadingAspect()->SetMaterial (theMat, myCurrentFacingModel);
309   if (HasColor())
310   {
311     myDrawer->ShadingAspect()->SetColor (myOwnColor, myCurrentFacingModel);
312   }
313   myDrawer->ShadingAspect()->SetTransparency (myTransparency, myCurrentFacingModel);
314
315   // modify shading presentation without re-computation
316   const PrsMgr_Presentations&        aPrsList  = Presentations();
317   Handle(Graphic3d_AspectFillArea3d) anAreaAsp = myDrawer->ShadingAspect()->Aspect();
318   for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
319   {
320     const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
321     if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
322     {
323       continue;
324     }
325
326     const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
327     aPrs->SetPrimitivesAspect (anAreaAsp);
328     for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
329     {
330       const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
331       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
332       {
333         aGroup->SetGroupPrimitivesAspect (anAreaAsp);
334       }
335     }
336   }
337 }
338
339 //=======================================================================
340 //function : UnsetMaterial
341 //purpose  :
342 //=======================================================================
343 void AIS_PointCloud::UnsetMaterial()
344 {
345   if (!HasMaterial())
346   {
347     return;
348   }
349
350   if (HasColor()
351    || IsTransparent())
352   {
353     myDrawer->ShadingAspect()->SetMaterial (myDrawer->Link()->ShadingAspect()->Material (myCurrentFacingModel),
354                                             myCurrentFacingModel);
355     if (HasColor())
356     {
357       myDrawer->ShadingAspect()->SetColor        (myOwnColor,     myCurrentFacingModel);
358       myDrawer->ShadingAspect()->SetTransparency (myTransparency, myCurrentFacingModel);
359     }
360   }
361   else
362   {
363     myDrawer->SetShadingAspect (Handle(Prs3d_ShadingAspect)());
364   }
365   hasOwnMaterial = Standard_False;
366
367   // modify shading presentation without re-computation
368   const PrsMgr_Presentations&        aPrsList  = Presentations();
369   Handle(Graphic3d_AspectFillArea3d) anAreaAsp = myDrawer->ShadingAspect()->Aspect();
370   for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
371   {
372     const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
373     if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
374     {
375       continue;
376     }
377
378     const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
379     aPrs->SetPrimitivesAspect (anAreaAsp);
380     for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
381     {
382       const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
383       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
384       {
385         aGroup->SetGroupPrimitivesAspect (anAreaAsp);
386       }
387     }
388   }
389 }
390
391 //=======================================================================
392 //function : Compute
393 //purpose  :
394 //=======================================================================
395 void AIS_PointCloud::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePrsMgr*/,
396                               const Handle(Prs3d_Presentation)&           thePrs,
397                               const Standard_Integer                      theMode)
398 {
399   thePrs->Clear();
400   switch (theMode)
401   {
402     case AIS_PointCloud::DM_Points:
403     {
404       const Handle(Graphic3d_ArrayOfPoints) aPoints = GetPoints();
405       if (aPoints.IsNull())
406       {
407         return;
408       }
409
410       Handle(Graphic3d_AspectMarker3d) aMarkerAspect = myDrawer->PointAspect()->Aspect();
411       if (!myDrawer->HasPointAspect())
412       {
413         aMarkerAspect->SetType (Aspect_TOM_POINT);
414       }
415
416       Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePrs);
417       aGroup->SetGroupPrimitivesAspect (aMarkerAspect);
418       aGroup->AddPrimitiveArray (aPoints);
419       break;
420     }
421     case AIS_PointCloud::DM_BndBox:
422     {
423       Bnd_Box aBndBox = GetBoundingBox();
424       if (aBndBox.IsVoid())
425       {
426         return;
427       }
428
429       StdPrs_WFDeflectionRestrictedFace::AddBox (thePrs, aBndBox, myDrawer);
430       break;
431     }
432   }
433 }
434
435 //=======================================================================
436 //function : ComputeSelection
437 //purpose  :
438 //=======================================================================
439 void AIS_PointCloud::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
440                                        const Standard_Integer             /*theMode*/)
441 {
442   Bnd_Box aBndBox = GetBoundingBox();
443   if (aBndBox.IsVoid())
444   {
445     return;
446   }
447
448   Handle(SelectMgr_EntityOwner) anOwner  = new SelectMgr_EntityOwner (this);
449   Handle(Select3D_SensitiveBox) aSensBox = new Select3D_SensitiveBox (anOwner, aBndBox);
450   theSelection->Add (aSensBox);
451 }