0029570: Visualization, Graphic3d_Aspect - merge Graphic3d_Group aspects
[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 IMPLEMENT_STANDARD_RTTIEXT(AIS_PointCloudOwner, SelectMgr_EntityOwner)
36 IMPLEMENT_STANDARD_RTTIEXT(AIS_PointCloud, AIS_InteractiveObject)
37
38 //=======================================================================
39 //function : AIS_PointCloudOwner
40 //purpose  :
41 //=======================================================================
42 AIS_PointCloudOwner::AIS_PointCloudOwner (const Handle(AIS_PointCloud)& theOrigin)
43 : SelectMgr_EntityOwner ((const Handle(SelectMgr_SelectableObject)& )theOrigin,  5),
44   myDetPoints (new TColStd_HPackedMapOfInteger()),
45   mySelPoints (new TColStd_HPackedMapOfInteger())
46 {
47   //
48 }
49
50 //=======================================================================
51 //function : ~AIS_PointCloudOwner
52 //purpose  :
53 //=======================================================================
54 AIS_PointCloudOwner::~AIS_PointCloudOwner()
55 {
56   //
57 }
58
59 //=======================================================================
60 //function : HilightWithColor
61 //purpose  :
62 //=======================================================================
63 Standard_Boolean AIS_PointCloudOwner::IsForcedHilight() const
64 {
65   return true;
66 }
67
68 //=======================================================================
69 //function : HilightWithColor
70 //purpose  :
71 //=======================================================================
72 void AIS_PointCloudOwner::HilightWithColor (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
73                                                       const Handle(Prs3d_Drawer)& theStyle,
74                                                       const Standard_Integer )
75 {
76   Handle(AIS_PointCloud) anObj = Handle(AIS_PointCloud)::DownCast (Selectable());
77   if (anObj.IsNull())
78   {
79     throw Standard_ProgramError ("Internal Error within AIS_PointCloud::PointsOwner!");
80   }
81
82   const Handle(TColStd_HPackedMapOfInteger)& aMap = thePrsMgr->IsImmediateModeOn()
83                                                   ? myDetPoints
84                                                   : mySelPoints;
85   Handle(Prs3d_Presentation) aPrs = thePrsMgr->IsImmediateModeOn()
86                                   ? anObj->GetHilightPresentation(thePrsMgr)
87                                   : anObj->GetSelectPresentation (thePrsMgr);
88   const Graphic3d_ZLayerId aZLayer = theStyle->ZLayer() != -1
89                                    ? theStyle->ZLayer()
90                                    : (thePrsMgr->IsImmediateModeOn() ? Graphic3d_ZLayerId_Top : anObj->ZLayer());
91   aMap->ChangeMap().Clear();
92   for (SelectMgr_SequenceOfSelection::Iterator aSelIter (anObj->Selections()); aSelIter.More(); aSelIter.Next())
93   {
94     const Handle(SelectMgr_Selection)& aSel = aSelIter.Value();
95     for (NCollection_Vector<Handle(SelectMgr_SensitiveEntity)>::Iterator aSelEntIter (aSel->Entities()); aSelEntIter.More(); aSelEntIter.Next())
96     {
97       const Handle(SelectMgr_SensitiveEntity)& aSelEnt = aSelEntIter.Value();
98       if (aSelEnt->BaseSensitive()->OwnerId() == this)
99       {
100         if (Handle(Select3D_SensitivePrimitiveArray) aSensitive = Handle(Select3D_SensitivePrimitiveArray)::DownCast (aSelEnt->BaseSensitive()))
101         {
102           aMap->ChangeMap() = aSensitive->LastDetectedElementMap()->Map();
103           if (aSensitive->LastDetectedElement() != -1)
104           {
105             aMap->ChangeMap().Add (aSensitive->LastDetectedElement());
106           }
107           break;
108         }
109       }
110     }
111   }
112
113   aPrs->Clear();
114   if (aPrs->GetZLayer() != aZLayer)
115   {
116     aPrs->SetZLayer (aZLayer);
117   }
118   if (aMap->Map().IsEmpty())
119   {
120     return;
121   }
122
123   const Handle(Graphic3d_ArrayOfPoints) anAllPoints = anObj->GetPoints();
124   if (anAllPoints.IsNull())
125   {
126     return;
127   }
128
129   Handle(Graphic3d_ArrayOfPoints) aPoints = new Graphic3d_ArrayOfPoints (aMap->Map().Extent());
130   for (TColStd_PackedMapOfInteger::Iterator aPntIter (aMap->Map()); aPntIter.More(); aPntIter.Next())
131   {
132     const gp_Pnt aPnt = anAllPoints->Vertice (aPntIter.Key() + 1);
133     aPoints->AddVertex (aPnt);
134   }
135
136   Handle(Graphic3d_Group) aGroup = aPrs->NewGroup();
137   aGroup->SetGroupPrimitivesAspect (theStyle->PointAspect()->Aspect());
138   aGroup->AddPrimitiveArray (aPoints);
139   if (thePrsMgr->IsImmediateModeOn())
140   {
141     thePrsMgr->AddToImmediateList (aPrs);
142   }
143   else
144   {
145     aPrs->Display();
146   }
147 }
148
149 //=======================================================================
150 //function : Unhilight
151 //purpose  :
152 //=======================================================================
153 void AIS_PointCloudOwner::Unhilight (const Handle(PrsMgr_PresentationManager)& , const Standard_Integer )
154 {
155   if (Handle(Prs3d_Presentation) aPrs = Selectable()->GetSelectPresentation (Handle(PrsMgr_PresentationManager3d)()))
156   {
157     aPrs->Erase();
158   }
159 }
160
161 //=======================================================================
162 //function : Clear
163 //purpose  :
164 //=======================================================================
165 void AIS_PointCloudOwner::Clear (const Handle(PrsMgr_PresentationManager)& thePrsMgr, const Standard_Integer theMode)
166 {
167   SelectMgr_EntityOwner::Clear (thePrsMgr, theMode);
168 }
169
170 //==================================================
171 // Function: AIS_PointCloud
172 // Purpose : Constructor
173 //==================================================
174 AIS_PointCloud::AIS_PointCloud()
175 {
176   myDrawer->SetupOwnShadingAspect();
177   myDrawer->ShadingAspect()->Aspect()->SetMarkerType (Aspect_TOM_POINT);
178
179   SetDisplayMode (AIS_PointCloud::DM_Points);
180   SetHilightMode (AIS_PointCloud::DM_BndBox);
181
182   myDynHilightDrawer->SetPointAspect (new Prs3d_PointAspect (Aspect_TOM_PLUS, Quantity_NOC_CYAN1, 1.0));
183 }
184
185 //=======================================================================
186 //function : GetPoints
187 //purpose  :
188 //=======================================================================
189 const Handle(Graphic3d_ArrayOfPoints) AIS_PointCloud::GetPoints() const
190 {
191   return myPoints;
192 }
193
194 //=======================================================================
195 //function : GetBoundingBox
196 //purpose  :
197 //=======================================================================
198 Bnd_Box AIS_PointCloud::GetBoundingBox() const
199 {
200   return myBndBox;
201 }
202
203 //! Auxiliary method
204 static inline Bnd_Box getBoundingBox (const Handle(Graphic3d_ArrayOfPoints)& thePoints)
205 {
206   Bnd_Box aBndBox;
207   if (thePoints.IsNull())
208   {
209     return aBndBox;
210   }
211
212   const Standard_Integer aNbVertices = thePoints->VertexNumber();
213   for (Standard_Integer aVertIter = 1; aVertIter <= aNbVertices; ++aVertIter)
214   {
215     aBndBox.Add (thePoints->Vertice (aVertIter));
216   }
217   return aBndBox;
218 }
219
220 //=======================================================================
221 //function : SetPoints
222 //purpose  :
223 //=======================================================================
224 void AIS_PointCloud::SetPoints (const Handle(Graphic3d_ArrayOfPoints)& thePoints)
225 {
226   myPoints = thePoints;
227   myBndBox = getBoundingBox (thePoints);
228 }
229
230 //=======================================================================
231 //function : SetPoints
232 //purpose  :
233 //=======================================================================
234 void AIS_PointCloud::SetPoints (const Handle(TColgp_HArray1OfPnt)&     theCoords,
235                                 const Handle(Quantity_HArray1OfColor)& theColors,
236                                 const Handle(TColgp_HArray1OfDir)&     theNormals)
237 {
238   myPoints.Nullify();
239   myBndBox.SetVoid();
240   if (theCoords.IsNull())
241   {
242     return;
243   }
244
245   const Standard_Integer aNbPoints = theCoords->Length();
246   if ((!theNormals.IsNull() && theNormals->Length() != aNbPoints)
247    || (!theColors.IsNull()  && theColors->Length()  != aNbPoints))
248   {
249     // invalid input
250     return;
251   }
252
253   const Standard_Boolean hasColors  = !theColors.IsNull()  && theColors->Length()  == aNbPoints;
254   const Standard_Boolean hasNormals = !theNormals.IsNull() && theNormals->Length() == aNbPoints;
255
256   const Standard_Integer aDiffColors  = hasColors  ? (theColors->Lower()  - theCoords->Lower()) : 0;
257   const Standard_Integer aDiffNormals = hasNormals ? (theNormals->Lower() - theCoords->Lower()) : 0;
258
259   myPoints = new Graphic3d_ArrayOfPoints (aNbPoints, hasColors, hasNormals);
260   for (Standard_Integer aPntIter = theCoords->Lower(); aPntIter <= theCoords->Upper(); ++aPntIter)
261   {
262     myPoints->AddVertex (theCoords->Value (aPntIter));
263     if (hasColors)
264     {
265       myPoints->SetVertexColor (myPoints->VertexNumber(),
266                                 theColors->Value (aPntIter + aDiffColors));
267     }
268     if (hasNormals)
269     {
270       myPoints->SetVertexNormal (myPoints->VertexNumber(),
271                                  theNormals->Value (aPntIter + aDiffNormals));
272     }
273   }
274   myBndBox = getBoundingBox (myPoints);
275 }
276
277 //=======================================================================
278 //function : SetColor
279 //purpose  :
280 //=======================================================================
281 void AIS_PointCloud::SetColor (const Quantity_Color& theColor)
282 {
283   AIS_InteractiveObject::SetColor(theColor);
284
285   myDrawer->ShadingAspect()->SetColor (theColor);
286   SynchronizeAspects();
287 }
288
289 //=======================================================================
290 //function : UnsetColor
291 //purpose  :
292 //=======================================================================
293 void AIS_PointCloud::UnsetColor()
294 {
295   if (!HasColor())
296   {
297     return;
298   }
299
300   AIS_InteractiveObject::UnsetColor();
301   {
302     Graphic3d_MaterialAspect aDefaultMat (Graphic3d_NOM_BRASS);
303     Graphic3d_MaterialAspect aMat = aDefaultMat;
304     Quantity_Color aColor = aDefaultMat.Color();
305     if (myDrawer->HasLink())
306     {
307       aColor = myDrawer->Link()->ShadingAspect()->Color (myCurrentFacingModel);
308     }
309     if (HasMaterial() || myDrawer->HasLink())
310     {
311       aMat = AIS_GraphicTool::GetMaterial (HasMaterial() ? myDrawer : myDrawer->Link());
312     }
313     if (HasMaterial())
314     {
315       aMat.SetColor (aColor);
316     }
317     if (IsTransparent())
318     {
319       Standard_Real aTransp = myDrawer->ShadingAspect()->Transparency (myCurrentFacingModel);
320       aMat.SetTransparency (Standard_ShortReal(aTransp));
321     }
322     myDrawer->ShadingAspect()->SetMaterial (aMat, myCurrentFacingModel);
323     myDrawer->ShadingAspect()->Aspect()->SetInteriorColor (aColor);
324   }
325
326   SynchronizeAspects();
327 }
328
329 //=======================================================================
330 //function : SetMaterial
331 //purpose  :
332 //=======================================================================
333 void AIS_PointCloud::SetMaterial (const Graphic3d_MaterialAspect& theMat)
334 {
335   hasOwnMaterial = Standard_True;
336
337   myDrawer->ShadingAspect()->SetMaterial (theMat, myCurrentFacingModel);
338   if (HasColor())
339   {
340     myDrawer->ShadingAspect()->SetColor (myDrawer->Color(), myCurrentFacingModel);
341   }
342   myDrawer->ShadingAspect()->SetTransparency (myDrawer->Transparency(), myCurrentFacingModel);
343   SynchronizeAspects();
344 }
345
346 //=======================================================================
347 //function : UnsetMaterial
348 //purpose  :
349 //=======================================================================
350 void AIS_PointCloud::UnsetMaterial()
351 {
352   if (!HasMaterial())
353   {
354     return;
355   }
356
357   {
358     Graphic3d_MaterialAspect aDefaultMat (Graphic3d_NOM_BRASS);
359     myDrawer->ShadingAspect()->SetMaterial (myDrawer->HasLink() ?
360                                             myDrawer->Link()->ShadingAspect()->Material (myCurrentFacingModel) :
361                                             aDefaultMat,
362                                             myCurrentFacingModel);
363     if (HasColor())
364     {
365       myDrawer->ShadingAspect()->SetColor        (myDrawer->Color(),        myCurrentFacingModel);
366       myDrawer->ShadingAspect()->SetTransparency (myDrawer->Transparency(), myCurrentFacingModel);
367     }
368   }
369   hasOwnMaterial = Standard_False;
370   SynchronizeAspects();
371 }
372
373 //=======================================================================
374 //function : Compute
375 //purpose  :
376 //=======================================================================
377 void AIS_PointCloud::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePrsMgr*/,
378                               const Handle(Prs3d_Presentation)&           thePrs,
379                               const Standard_Integer                      theMode)
380 {
381   switch (theMode)
382   {
383     case AIS_PointCloud::DM_Points:
384     {
385       const Handle(Graphic3d_ArrayOfPoints) aPoints = GetPoints();
386       if (aPoints.IsNull())
387       {
388         return;
389       }
390
391       Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
392       aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
393       aGroup->AddPrimitiveArray (aPoints);
394       break;
395     }
396     case AIS_PointCloud::DM_BndBox:
397     {
398       Bnd_Box aBndBox = GetBoundingBox();
399       if (aBndBox.IsVoid())
400       {
401         return;
402       }
403
404       StdPrs_BndBox::Add (thePrs, aBndBox, myDrawer);
405       break;
406     }
407   }
408 }
409
410 //=======================================================================
411 //function : ComputeSelection
412 //purpose  :
413 //=======================================================================
414 void AIS_PointCloud::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
415                                        const Standard_Integer             theMode)
416 {
417   Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner (this);
418   switch (theMode)
419   {
420     case SM_Points:
421     case SM_SubsetOfPoints:
422     {
423       const Handle(Graphic3d_ArrayOfPoints) aPoints = GetPoints();
424       if (!aPoints.IsNull()
425        && !aPoints->Attributes().IsNull())
426       {
427         if (theMode == SM_SubsetOfPoints)
428         {
429           anOwner = new AIS_PointCloudOwner (this);
430         }
431
432         // split large point clouds into several groups
433         const Standard_Integer aNbGroups = aPoints->Attributes()->NbElements > 500000 ? 8 : 1;
434         Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anOwner);
435         aSensitive->SetDetectElements (true);
436         aSensitive->SetDetectElementMap (theMode == SM_SubsetOfPoints);
437         aSensitive->SetSensitivityFactor (8);
438         aSensitive->InitPoints (aPoints->Attributes(), aPoints->Indices(), TopLoc_Location(), true, aNbGroups);
439         aSensitive->BVH();
440         theSelection->Add (aSensitive);
441         return;
442       }
443       break;
444     }
445     case SM_BndBox:
446     {
447       break;
448     }
449     default:
450     {
451       return;
452     }
453   }
454
455   Bnd_Box aBndBox = GetBoundingBox();
456   if (aBndBox.IsVoid())
457   {
458     return;
459   }
460   Handle(Select3D_SensitiveBox) aSensBox = new Select3D_SensitiveBox (anOwner, aBndBox);
461   theSelection->Add (aSensBox);
462 }