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