2f118c1adb7c9c4be8a0ba731f00c6262b413292
[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(SelectMgr_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_PickResult& thePickResult,
226                                                                 SelectBasics_SelectingVolumeManager& theMgr,
227                                                                 Standard_Integer theElemIdx,
228                                                                 Standard_Boolean theIsFullInside)
229 {
230   if (theIsFullInside)
231   {
232     return Standard_True;
233   }
234
235   const Standard_Integer anItemIdx = myItemIndexes.Value (theElemIdx);
236   if (mySelMethod == MeshVS_MSM_PRECISE)
237   {
238     MeshVS_Buffer aCoordsBuf (3 * myMaxFaceNodes * sizeof (Standard_Real));
239     TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3 * myMaxFaceNodes);
240     Standard_Integer aNbNodes;
241     MeshVS_EntityType aType;
242     if (!myDataSource->GetGeom (anItemIdx, Standard_True, aCoords, aNbNodes, aType)
243       || aNbNodes == 0)
244     {
245       return Standard_False;
246     }
247
248     MeshVS_Buffer aNodesBuf (aNbNodes * sizeof (Standard_Integer));
249     TColStd_Array1OfInteger aElemNodes (aNodesBuf, 1, aNbNodes);
250     if (!myDataSource->GetNodesByElement (anItemIdx, aElemNodes, aNbNodes))
251     {
252       return Standard_False;
253     }
254     if (aNbNodes == 3)
255     {
256       return theMgr.Overlaps (gp_Pnt (aCoords (1), aCoords (2), aCoords (3)),
257                               gp_Pnt (aCoords (4), aCoords (5), aCoords (6)),
258                               gp_Pnt (aCoords (7), aCoords (8), aCoords (9)),
259                               Select3D_TOS_INTERIOR, thePickResult);
260     }
261
262     MeshVS_Buffer aFacePntsBuf (aNbNodes * 3 * sizeof (Standard_Real));
263     TColgp_Array1OfPnt aFacePnts (aFacePntsBuf, 1, aNbNodes);
264     for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aNbNodes; aNodeIdx++)
265     {
266       aFacePnts.SetValue (aNodeIdx, gp_Pnt (aCoords (3 * aNodeIdx - 2),
267                                             aCoords (3 * aNodeIdx - 1),
268                                             aCoords (3 * aNodeIdx)));
269     }
270     return theMgr.Overlaps (aFacePnts, Select3D_TOS_INTERIOR, thePickResult);
271   }
272   else if (mySelMethod == MeshVS_MSM_NODES)
273   {
274     const gp_Pnt aVert = getVertexByIndex (anItemIdx);
275     return theMgr.Overlaps (aVert, thePickResult);
276   }
277   return Standard_False;
278 }
279
280 //=======================================================================
281 //function : elementIsInside
282 //purpose  :
283 //=======================================================================
284 Standard_Boolean MeshVS_CommonSensitiveEntity::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
285                                                                 Standard_Integer theElemIdx,
286                                                                 Standard_Boolean theIsFullInside)
287 {
288   if (theIsFullInside)
289   {
290     return Standard_True;
291   }
292
293   const Standard_Integer anItemIdx = myItemIndexes.Value (theElemIdx);
294   if (mySelMethod == MeshVS_MSM_PRECISE)
295   {
296     MeshVS_Buffer aCoordsBuf (3 * myMaxFaceNodes * sizeof (Standard_Real));
297     TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3 * myMaxFaceNodes);
298     Standard_Integer aNbNodes;
299     MeshVS_EntityType aType;
300     if (!myDataSource->GetGeom (anItemIdx, Standard_True, aCoords, aNbNodes, aType)
301       || aNbNodes == 0)
302     {
303       return Standard_False;
304     }
305
306     MeshVS_Buffer aNodesBuf (aNbNodes * sizeof (Standard_Integer));
307     TColStd_Array1OfInteger aElemNodes (aNodesBuf, 1, aNbNodes);
308     if (!myDataSource->GetNodesByElement (anItemIdx, aElemNodes, aNbNodes))
309     {
310       return Standard_False;
311     }
312
313     MeshVS_Buffer aFacePntsBuf (aNbNodes * 3 * sizeof (Standard_Real));
314     TColgp_Array1OfPnt aFacePnts (aFacePntsBuf, 1, aNbNodes);
315     for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aNbNodes; ++aNodeIdx)
316     {
317       const gp_Pnt aPnt (aCoords (3 * aNodeIdx - 2),
318                          aCoords (3 * aNodeIdx - 1),
319                          aCoords (3 * aNodeIdx));
320       if (!theMgr.Overlaps (aPnt))
321       {
322         return Standard_False;
323       }
324     }
325     return Standard_True;
326   }
327   else if (mySelMethod == MeshVS_MSM_NODES)
328   {
329     const gp_Pnt aVert = getVertexByIndex (anItemIdx);
330     return theMgr.Overlaps (aVert);
331   }
332   return Standard_False;
333 }
334
335 //=======================================================================
336 //function : distanceToCOG
337 //purpose  :
338 //=======================================================================
339 Standard_Real MeshVS_CommonSensitiveEntity::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
340 {
341   return theMgr.DistToGeometryCenter (myCOG);
342 }
343
344 //=======================================================================
345 //function : BoundingBox
346 //purpose  :
347 //=======================================================================
348 Select3D_BndBox3d MeshVS_CommonSensitiveEntity::BoundingBox()
349 {
350   return myBndBox;
351 }
352
353 //=======================================================================
354 //function : CenterOfGeometry
355 //purpose  :
356 //=======================================================================
357 gp_Pnt MeshVS_CommonSensitiveEntity::CenterOfGeometry() const
358 {
359   return myCOG;
360 }