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