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