a0df6dd2c84729936a04fe1af3f745a10ffdfe50
[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_Color& theColor)
148 {
149   AIS_InteractiveObject::SetColor(theColor);
150
151   if (!myDrawer->HasOwnPointAspect())
152   {
153     myDrawer->SetPointAspect (new Prs3d_PointAspect (Aspect_TOM_POINT, theColor, 1.0));
154     if (myDrawer->HasLink())
155     {
156       *myDrawer->PointAspect()->Aspect() = *myDrawer->Link()->PointAspect()->Aspect();
157     }
158   }
159   if (!myDrawer->HasOwnShadingAspect())
160   {
161     myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
162     if (myDrawer->HasLink())
163     {
164       *myDrawer->ShadingAspect()->Aspect() = *myDrawer->Link()->ShadingAspect()->Aspect();
165     }
166   }
167
168   // Override color
169   myDrawer->ShadingAspect()->SetColor (theColor);
170   myDrawer->PointAspect()  ->SetColor (theColor);
171
172   const PrsMgr_Presentations&        aPrsList     = Presentations();
173   Handle(Graphic3d_AspectMarker3d)   aPointAspect = myDrawer->PointAspect()->Aspect();
174   Handle(Graphic3d_AspectFillArea3d) anAreaAspect = myDrawer->ShadingAspect()->Aspect();
175   for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
176   {
177     const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
178     if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
179     {
180       continue;
181     }
182
183     const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
184     for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
185     {
186       const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
187       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_MARKER))
188       {
189         aGroup->SetGroupPrimitivesAspect (aPointAspect);
190       }
191       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
192       {
193         aGroup->SetGroupPrimitivesAspect (anAreaAspect);
194       }
195     }
196   }
197 }
198
199 //=======================================================================
200 //function : UnsetColor
201 //purpose  :
202 //=======================================================================
203 void AIS_PointCloud::UnsetColor()
204 {
205   if (!HasColor())
206   {
207     return;
208   }
209
210   AIS_InteractiveObject::UnsetColor();
211
212   if (!HasWidth())
213   {
214     myDrawer->SetPointAspect (Handle(Prs3d_PointAspect)());
215   }
216   else
217   {
218     myDrawer->PointAspect()->SetColor (myDrawer->HasLink()
219                                      ? myDrawer->Link()->PointAspect()->Aspect()->Color()
220                                      : Quantity_Color (Quantity_NOC_YELLOW));
221   }
222
223   if (HasMaterial()
224    || IsTransparent())
225   {
226     Graphic3d_MaterialAspect aDefaultMat (Graphic3d_NOM_BRASS);
227     Graphic3d_MaterialAspect aMat = aDefaultMat;
228     if (HasMaterial() || myDrawer->HasLink())
229     {
230       aMat = AIS_GraphicTool::GetMaterial (HasMaterial() ? myDrawer : myDrawer->Link());
231     }
232     if (HasMaterial())
233     {
234       Quantity_Color aColor = aDefaultMat.AmbientColor();
235       if (myDrawer->HasLink())
236       {
237         aColor = myDrawer->Link()->ShadingAspect()->Color (myCurrentFacingModel);
238       }
239       aMat.SetColor (aColor);
240     }
241     if (IsTransparent())
242     {
243       Standard_Real aTransp = myDrawer->ShadingAspect()->Transparency (myCurrentFacingModel);
244       aMat.SetTransparency (Standard_ShortReal(aTransp));
245     }
246     myDrawer->ShadingAspect()->SetMaterial (aMat, myCurrentFacingModel);
247   }
248   else
249   {
250     myDrawer->SetShadingAspect (Handle(Prs3d_ShadingAspect)());
251   }
252   myDrawer->SetPointAspect (Handle(Prs3d_PointAspect)());
253
254   // modify shading presentation without re-computation
255   const PrsMgr_Presentations&        aPrsList   = Presentations();
256   Handle(Graphic3d_AspectFillArea3d) anAreaAsp  = myDrawer->Link()->ShadingAspect()->Aspect();
257   Handle(Graphic3d_AspectMarker3d)   aMarkerAsp = myDrawer->Link()->PointAspect()->Aspect();
258   for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
259   {
260     const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
261     if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
262     {
263       continue;
264     }
265
266     const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
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_MaterialAspect& theMat)
291 {
292   if (!myDrawer->HasOwnShadingAspect())
293   {
294     myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
295     if (myDrawer->HasLink())
296     {
297       *myDrawer->ShadingAspect()->Aspect() = *myDrawer->Link()->ShadingAspect()->Aspect();
298     }
299   }
300   hasOwnMaterial = Standard_True;
301
302   myDrawer->ShadingAspect()->SetMaterial (theMat, myCurrentFacingModel);
303   if (HasColor())
304   {
305     myDrawer->ShadingAspect()->SetColor (myDrawer->Color(), myCurrentFacingModel);
306   }
307   myDrawer->ShadingAspect()->SetTransparency (myDrawer->Transparency(), myCurrentFacingModel);
308
309   // modify shading presentation without re-computation
310   const PrsMgr_Presentations&        aPrsList  = Presentations();
311   Handle(Graphic3d_AspectFillArea3d) anAreaAsp = myDrawer->ShadingAspect()->Aspect();
312   for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
313   {
314     const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
315     if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
316     {
317       continue;
318     }
319
320     const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
321     for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
322     {
323       const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
324       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
325       {
326         aGroup->SetGroupPrimitivesAspect (anAreaAsp);
327       }
328     }
329   }
330 }
331
332 //=======================================================================
333 //function : UnsetMaterial
334 //purpose  :
335 //=======================================================================
336 void AIS_PointCloud::UnsetMaterial()
337 {
338   if (!HasMaterial())
339   {
340     return;
341   }
342
343   if (HasColor()
344    || IsTransparent())
345   {
346     Graphic3d_MaterialAspect aDefaultMat (Graphic3d_NOM_BRASS);
347     myDrawer->ShadingAspect()->SetMaterial (myDrawer->HasLink() ?
348                                             myDrawer->Link()->ShadingAspect()->Material (myCurrentFacingModel) :
349                                             aDefaultMat,
350                                             myCurrentFacingModel);
351     if (HasColor())
352     {
353       myDrawer->ShadingAspect()->SetColor        (myDrawer->Color(),        myCurrentFacingModel);
354       myDrawer->ShadingAspect()->SetTransparency (myDrawer->Transparency(), myCurrentFacingModel);
355     }
356   }
357   else
358   {
359     myDrawer->SetShadingAspect (Handle(Prs3d_ShadingAspect)());
360   }
361   hasOwnMaterial = Standard_False;
362
363   // modify shading presentation without re-computation
364   const PrsMgr_Presentations&        aPrsList  = Presentations();
365   Handle(Graphic3d_AspectFillArea3d) anAreaAsp = myDrawer->ShadingAspect()->Aspect();
366   for (Standard_Integer aPrsIt = 1; aPrsIt <= aPrsList.Length(); ++aPrsIt)
367   {
368     const PrsMgr_ModedPresentation& aPrsModed = aPrsList.Value (aPrsIt);
369     if (aPrsModed.Mode() != AIS_PointCloud::DM_Points)
370     {
371       continue;
372     }
373
374     const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
375     for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
376     {
377       const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
378       if (aGroup->IsGroupPrimitivesAspectSet (Graphic3d_ASPECT_FILL_AREA))
379       {
380         aGroup->SetGroupPrimitivesAspect (anAreaAsp);
381       }
382     }
383   }
384 }
385
386 //=======================================================================
387 //function : Compute
388 //purpose  :
389 //=======================================================================
390 void AIS_PointCloud::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePrsMgr*/,
391                               const Handle(Prs3d_Presentation)&           thePrs,
392                               const Standard_Integer                      theMode)
393 {
394   switch (theMode)
395   {
396     case AIS_PointCloud::DM_Points:
397     {
398       const Handle(Graphic3d_ArrayOfPoints) aPoints = GetPoints();
399       if (aPoints.IsNull())
400       {
401         return;
402       }
403
404       Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePrs);
405       aGroup->SetGroupPrimitivesAspect (myDrawer->PointAspect()->Aspect());
406       aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
407       aGroup->AddPrimitiveArray (aPoints);
408       break;
409     }
410     case AIS_PointCloud::DM_BndBox:
411     {
412       Bnd_Box aBndBox = GetBoundingBox();
413       if (aBndBox.IsVoid())
414       {
415         return;
416       }
417
418       StdPrs_BndBox::Add (thePrs, aBndBox, myDrawer);
419       break;
420     }
421   }
422 }
423
424 //=======================================================================
425 //function : ComputeSelection
426 //purpose  :
427 //=======================================================================
428 void AIS_PointCloud::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
429                                        const Standard_Integer             theMode)
430 {
431   Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner (this);
432   switch (theMode)
433   {
434     case SM_Points:
435     {
436       const Handle(Graphic3d_ArrayOfPoints) aPoints = GetPoints();
437       if (!aPoints.IsNull()
438        && !aPoints->Attributes().IsNull())
439       {
440         Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anOwner);
441         aSensitive->SetSensitivityFactor (8);
442         aSensitive->InitPoints (aPoints->Attributes(), aPoints->Indices(), TopLoc_Location());
443         aSensitive->BVH();
444         theSelection->Add (aSensitive);
445         return;
446       }
447       break;
448     }
449     case SM_BndBox:
450     {
451       break;
452     }
453     default:
454     {
455       return;
456     }
457   }
458
459   Bnd_Box aBndBox = GetBoundingBox();
460   if (aBndBox.IsVoid())
461   {
462     return;
463   }
464   Handle(Select3D_SensitiveBox) aSensBox = new Select3D_SensitiveBox (anOwner, aBndBox);
465   theSelection->Add (aSensBox);
466 }