0029938: Visualization - SelectMgr_ViewerSelector::PickedPoint() should return point...
[occt.git] / src / MeshVS / MeshVS_CommonSensitiveEntity.cxx
1 // Created on: 2016-02-18
2 // Created by: Varvara POSKONINA
3 // Copyright (c) 2016 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 <MeshVS_CommonSensitiveEntity.hxx>
17
18 #include <MeshVS_Buffer.hxx>
19 #include <MeshVS_Drawer.hxx>
20 #include <MeshVS_DrawerAttribute.hxx>
21 #include <TColStd_PackedMapOfInteger.hxx>
22 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
23
24 IMPLEMENT_STANDARD_RTTIEXT (MeshVS_CommonSensitiveEntity, Select3D_SensitiveSet)
25
26 //=======================================================================
27 //function : Constructor
28 //purpose  :
29 //=======================================================================
30 MeshVS_CommonSensitiveEntity::MeshVS_CommonSensitiveEntity (const Handle(SelectBasics_EntityOwner)& theOwner,
31                                                             const Handle(MeshVS_Mesh)&              theParentMesh,
32                                                             const MeshVS_MeshSelectionMethod        theSelMethod)
33 : Select3D_SensitiveSet (theOwner),
34   myDataSource (theParentMesh->GetDataSource()),
35   mySelMethod (theSelMethod)
36 {
37   theParentMesh->GetDrawer()->GetInteger (MeshVS_DA_MaxFaceNodes, myMaxFaceNodes);
38   Standard_ASSERT_RAISE (myMaxFaceNodes > 0,
39     "The maximal amount of nodes in a face must be greater than zero to create sensitive entity");
40   gp_XYZ aCenter (0.0, 0.0, 0.0);
41
42   if (mySelMethod == MeshVS_MSM_NODES)
43   {
44     Standard_Integer aNbSelectableNodes = 0;
45     const TColStd_PackedMapOfInteger& anAllNodesMap = myDataSource->GetAllNodes();
46     for (TColStd_MapIteratorOfPackedMapOfInteger aNodesIter (anAllNodesMap); aNodesIter.More(); aNodesIter.Next())
47     {
48       const Standard_Integer aNodeIdx = aNodesIter.Key();
49       if (theParentMesh->IsSelectableNode (aNodeIdx))
50       {
51         const gp_Pnt aVertex = getVertexByIndex (aNodeIdx);
52         aCenter += aVertex.XYZ();
53         myBndBox.Add (SelectMgr_Vec3 (aVertex.X(), aVertex.Y(), aVertex.Z()));
54         ++aNbSelectableNodes;
55         myItemIndexes.Append (aNodeIdx);
56       }
57     }
58
59     // increase sensitivity for vertices detection
60     SetSensitivityFactor (8);
61     myCOG = aCenter / aNbSelectableNodes;
62   }
63   else if (mySelMethod == MeshVS_MSM_PRECISE)
64   {
65     const TColStd_PackedMapOfInteger& anAllNodesMap = myDataSource->GetAllNodes();
66     for (TColStd_MapIteratorOfPackedMapOfInteger aNodesIter (anAllNodesMap); aNodesIter.More(); aNodesIter.Next())
67     {
68       const Standard_Integer aNodeIdx = aNodesIter.Key();
69       const gp_Pnt aVertex = getVertexByIndex (aNodeIdx);
70       aCenter += aVertex.XYZ();
71       myBndBox.Add (SelectMgr_Vec3 (aVertex.X(), aVertex.Y(), aVertex.Z()));
72     }
73     myCOG = aCenter / anAllNodesMap.Extent();
74
75     const TColStd_PackedMapOfInteger& anAllElementsMap = myDataSource->GetAllElements();
76     MeshVS_EntityType aType;
77     for (TColStd_MapIteratorOfPackedMapOfInteger anElemIter (anAllElementsMap); anElemIter.More(); anElemIter.Next())
78     {
79       const Standard_Integer anElemIdx = anElemIter.Key();
80       if (theParentMesh->IsSelectableElem (anElemIdx)
81        && myDataSource->GetGeomType (anElemIdx, Standard_True, aType)
82        && aType == MeshVS_ET_Face)
83       {
84         myItemIndexes.Append (anElemIdx);
85       }
86     }
87   }
88 }
89
90 //=======================================================================
91 //function : Constructor
92 //purpose  :
93 //=======================================================================
94 MeshVS_CommonSensitiveEntity::MeshVS_CommonSensitiveEntity (const MeshVS_CommonSensitiveEntity& theOther)
95 : Select3D_SensitiveSet (theOther.myOwnerId),
96   myDataSource (theOther.myDataSource),
97   myItemIndexes (theOther.myItemIndexes),
98   mySelMethod (theOther.mySelMethod),
99   myMaxFaceNodes (theOther.myMaxFaceNodes),
100   myCOG (theOther.myCOG),
101   myBndBox (theOther.myBndBox)
102 {
103   //
104 }
105
106 //=======================================================================
107 //function : Destructor
108 //purpose  :
109 //=======================================================================
110 MeshVS_CommonSensitiveEntity::~MeshVS_CommonSensitiveEntity()
111 {
112   myDataSource.Nullify();
113   myItemIndexes.Clear();
114 }
115
116 //=======================================================================
117 //function : NbSubElements
118 //purpose  :
119 //=======================================================================
120 Standard_Integer MeshVS_CommonSensitiveEntity::NbSubElements()
121 {
122   return myItemIndexes.Size();
123 }
124
125 //=======================================================================
126 //function : Size
127 //purpose  :
128 //=======================================================================
129 Standard_Integer MeshVS_CommonSensitiveEntity::Size() const
130 {
131   return myItemIndexes.Size();
132 }
133
134 //=======================================================================
135 //function : getVertexByIndex
136 //purpose  :
137 //=======================================================================
138 gp_Pnt MeshVS_CommonSensitiveEntity::getVertexByIndex (const Standard_Integer theNodeIdx) const
139 {
140   Standard_Real aCoordsBuf[3];
141   TColStd_Array1OfReal aCoords (aCoordsBuf[0], 1, 3);
142   Standard_Integer aNbNodes;
143   MeshVS_EntityType aType;
144   if (!myDataSource->GetGeom (theNodeIdx, Standard_False, aCoords, aNbNodes, aType))
145   {
146     return gp_Pnt();
147   }
148   return gp_Pnt (aCoords.Value (1), aCoords.Value (2), aCoords.Value (3));
149 }
150
151 //=======================================================================
152 //function : Box
153 //purpose  :
154 //=======================================================================
155 Select3D_BndBox3d MeshVS_CommonSensitiveEntity::Box (const Standard_Integer theIdx) const
156 {
157   const Standard_Integer anItemIdx = myItemIndexes.Value (theIdx);
158   Select3D_BndBox3d aBox;
159   if (mySelMethod == MeshVS_MSM_PRECISE)
160   {
161     MeshVS_Buffer aCoordsBuf (3 * myMaxFaceNodes * sizeof (Standard_Real));
162     TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3 * myMaxFaceNodes);
163     Standard_Integer aNbNodes;
164     MeshVS_EntityType aType;
165     if (!myDataSource->GetGeom (anItemIdx, Standard_True, aCoords, aNbNodes, aType)
166       || aNbNodes == 0)
167     {
168       return aBox;
169     }
170
171     MeshVS_Buffer aNodesBuf (aNbNodes * sizeof (Standard_Integer));
172     TColStd_Array1OfInteger aElemNodes (aNodesBuf, 1, aNbNodes);
173     if (!myDataSource->GetNodesByElement (anItemIdx, aElemNodes, aNbNodes))
174     {
175       return aBox;
176     }
177
178     for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aNbNodes; aNodeIdx++)
179     {
180       const SelectMgr_Vec3 aPnt (aCoords (3 * aNodeIdx - 2),
181                                  aCoords (3 * aNodeIdx - 1),
182                                  aCoords (3 * aNodeIdx));
183       aBox.Add (aPnt);
184     }
185   }
186   else if (mySelMethod == MeshVS_MSM_NODES)
187   {
188     const gp_Pnt aVert = getVertexByIndex (anItemIdx);
189     aBox.Add (SelectMgr_Vec3 (aVert.X(), aVert.Y(), aVert.Z()));
190   }
191
192   return aBox;
193 }
194
195 //=======================================================================
196 //function : Center
197 //purpose  :
198 //=======================================================================
199 Standard_Real MeshVS_CommonSensitiveEntity::Center (const Standard_Integer theIdx,
200                                                     const Standard_Integer theAxis) const
201 {
202   const Select3D_BndBox3d& aBox = Box (theIdx);
203   SelectMgr_Vec3 aCenter = (aBox.CornerMin () + aBox.CornerMax ()) * 0.5;
204
205   return theAxis == 0 ? aCenter.x() : (theAxis == 1 ? aCenter.y() : aCenter.z());
206 }
207
208 //=======================================================================
209 //function : Swap
210 //purpose  :
211 //=======================================================================
212 void MeshVS_CommonSensitiveEntity::Swap (const Standard_Integer theIdx1,
213                                          const Standard_Integer theIdx2)
214 {
215   const Standard_Integer anItem1 = myItemIndexes.Value (theIdx1);
216   const Standard_Integer anItem2 = myItemIndexes.Value (theIdx2);
217   myItemIndexes.ChangeValue (theIdx1) = anItem2;
218   myItemIndexes.ChangeValue (theIdx2) = anItem1;
219 }
220
221 //=======================================================================
222 //function : overlapsElement
223 //purpose  :
224 //=======================================================================
225 Standard_Boolean MeshVS_CommonSensitiveEntity::overlapsElement (SelectBasics_SelectingVolumeManager& theMgr,
226                                                                 Standard_Integer theElemIdx,
227                                                                 SelectBasics_PickResult& thePickResult)
228 {
229   const Standard_Integer anItemIdx = myItemIndexes.Value (theElemIdx);
230   if (mySelMethod == MeshVS_MSM_PRECISE)
231   {
232     MeshVS_Buffer aCoordsBuf (3 * myMaxFaceNodes * sizeof (Standard_Real));
233     TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3 * myMaxFaceNodes);
234     Standard_Integer aNbNodes;
235     MeshVS_EntityType aType;
236     if (!myDataSource->GetGeom (anItemIdx, Standard_True, aCoords, aNbNodes, aType)
237       || aNbNodes == 0)
238     {
239       return Standard_False;
240     }
241
242     MeshVS_Buffer aNodesBuf (aNbNodes * sizeof (Standard_Integer));
243     TColStd_Array1OfInteger aElemNodes (aNodesBuf, 1, aNbNodes);
244     if (!myDataSource->GetNodesByElement (anItemIdx, aElemNodes, aNbNodes))
245     {
246       return Standard_False;
247     }
248     if (aNbNodes == 3)
249     {
250       return theMgr.Overlaps (gp_Pnt (aCoords (1), aCoords (2), aCoords (3)),
251                               gp_Pnt (aCoords (4), aCoords (5), aCoords (6)),
252                               gp_Pnt (aCoords (7), aCoords (8), aCoords (9)),
253                               Select3D_TOS_INTERIOR, thePickResult);
254     }
255
256     MeshVS_Buffer aFacePntsBuf (aNbNodes * 3 * sizeof (Standard_Real));
257     TColgp_Array1OfPnt aFacePnts (aFacePntsBuf, 1, aNbNodes);
258     for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aNbNodes; aNodeIdx++)
259     {
260       aFacePnts.SetValue (aNodeIdx, gp_Pnt (aCoords (3 * aNodeIdx - 2),
261                                             aCoords (3 * aNodeIdx - 1),
262                                             aCoords (3 * aNodeIdx)));
263     }
264     return theMgr.Overlaps (aFacePnts, Select3D_TOS_INTERIOR, thePickResult);
265   }
266   else if (mySelMethod == MeshVS_MSM_NODES)
267   {
268     const gp_Pnt aVert = getVertexByIndex (anItemIdx);
269     return theMgr.Overlaps (aVert, thePickResult);
270   }
271   return Standard_False;
272 }
273
274 //=======================================================================
275 //function : elementIsInside
276 //purpose  :
277 //=======================================================================
278 Standard_Boolean MeshVS_CommonSensitiveEntity::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
279                                                                 const Standard_Integer theElemIdx)
280 {
281   const Standard_Integer anItemIdx = myItemIndexes.Value (theElemIdx);
282   if (mySelMethod == MeshVS_MSM_PRECISE)
283   {
284     MeshVS_Buffer aCoordsBuf (3 * myMaxFaceNodes * sizeof (Standard_Real));
285     TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3 * myMaxFaceNodes);
286     Standard_Integer aNbNodes;
287     MeshVS_EntityType aType;
288     if (!myDataSource->GetGeom (anItemIdx, Standard_True, aCoords, aNbNodes, aType)
289       || aNbNodes == 0)
290     {
291       return Standard_False;
292     }
293
294     MeshVS_Buffer aNodesBuf (aNbNodes * sizeof (Standard_Integer));
295     TColStd_Array1OfInteger aElemNodes (aNodesBuf, 1, aNbNodes);
296     if (!myDataSource->GetNodesByElement (anItemIdx, aElemNodes, aNbNodes))
297     {
298       return Standard_False;
299     }
300
301     MeshVS_Buffer aFacePntsBuf (aNbNodes * 3 * sizeof (Standard_Real));
302     TColgp_Array1OfPnt aFacePnts (aFacePntsBuf, 1, aNbNodes);
303     for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aNbNodes; ++aNodeIdx)
304     {
305       const gp_Pnt aPnt (aCoords (3 * aNodeIdx - 2),
306                          aCoords (3 * aNodeIdx - 1),
307                          aCoords (3 * aNodeIdx));
308       if (!theMgr.Overlaps (aPnt))
309       {
310         return Standard_False;
311       }
312     }
313     return Standard_True;
314   }
315   else if (mySelMethod == MeshVS_MSM_NODES)
316   {
317     const gp_Pnt aVert = getVertexByIndex (anItemIdx);
318     return theMgr.Overlaps (aVert);
319   }
320   return Standard_False;
321 }
322
323 //=======================================================================
324 //function : distanceToCOG
325 //purpose  :
326 //=======================================================================
327 Standard_Real MeshVS_CommonSensitiveEntity::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
328 {
329   return theMgr.DistToGeometryCenter (myCOG);
330 }
331
332 //=======================================================================
333 //function : BoundingBox
334 //purpose  :
335 //=======================================================================
336 Select3D_BndBox3d MeshVS_CommonSensitiveEntity::BoundingBox()
337 {
338   return myBndBox;
339 }
340
341 //=======================================================================
342 //function : CenterOfGeometry
343 //purpose  :
344 //=======================================================================
345 gp_Pnt MeshVS_CommonSensitiveEntity::CenterOfGeometry() const
346 {
347   return myCOG;
348 }