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 | |
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 : Destructor |
92 | //purpose : |
93 | //======================================================================= |
94 | MeshVS_CommonSensitiveEntity::~MeshVS_CommonSensitiveEntity() |
95 | { |
96 | myDataSource.Nullify(); |
97 | myItemIndexes.Clear(); |
98 | } |
99 | |
100 | //======================================================================= |
101 | //function : NbSubElements |
102 | //purpose : |
103 | //======================================================================= |
104 | Standard_Integer MeshVS_CommonSensitiveEntity::NbSubElements() |
105 | { |
106 | return myItemIndexes.Size(); |
107 | } |
108 | |
109 | //======================================================================= |
110 | //function : Size |
111 | //purpose : |
112 | //======================================================================= |
113 | Standard_Integer MeshVS_CommonSensitiveEntity::Size() const |
114 | { |
115 | return myItemIndexes.Size(); |
116 | } |
117 | |
118 | //======================================================================= |
119 | //function : getVertexByIndex |
120 | //purpose : |
121 | //======================================================================= |
122 | gp_Pnt MeshVS_CommonSensitiveEntity::getVertexByIndex (const Standard_Integer theNodeIdx) const |
123 | { |
124 | Standard_Real aCoordsBuf[3]; |
125 | TColStd_Array1OfReal aCoords (aCoordsBuf[0], 1, 3); |
126 | Standard_Integer aNbNodes; |
127 | MeshVS_EntityType aType; |
128 | if (!myDataSource->GetGeom (theNodeIdx, Standard_False, aCoords, aNbNodes, aType)) |
129 | { |
130 | return gp_Pnt(); |
131 | } |
132 | return gp_Pnt (aCoords.Value (1), aCoords.Value (2), aCoords.Value (3)); |
133 | } |
134 | |
135 | //======================================================================= |
136 | //function : Box |
137 | //purpose : |
138 | //======================================================================= |
139 | Select3D_BndBox3d MeshVS_CommonSensitiveEntity::Box (const Standard_Integer theIdx) const |
140 | { |
141 | const Standard_Integer anItemIdx = myItemIndexes.Value (theIdx); |
142 | Select3D_BndBox3d aBox; |
143 | if (mySelMethod == MeshVS_MSM_PRECISE) |
144 | { |
145 | MeshVS_Buffer aCoordsBuf (3 * myMaxFaceNodes * sizeof (Standard_Real)); |
146 | TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3 * myMaxFaceNodes); |
147 | Standard_Integer aNbNodes; |
148 | MeshVS_EntityType aType; |
149 | if (!myDataSource->GetGeom (anItemIdx, Standard_True, aCoords, aNbNodes, aType) |
150 | || aNbNodes == 0) |
151 | { |
152 | return aBox; |
153 | } |
154 | |
155 | MeshVS_Buffer aNodesBuf (aNbNodes * sizeof (Standard_Integer)); |
156 | TColStd_Array1OfInteger aElemNodes (aNodesBuf, 1, aNbNodes); |
157 | if (!myDataSource->GetNodesByElement (anItemIdx, aElemNodes, aNbNodes)) |
158 | { |
159 | return aBox; |
160 | } |
161 | |
162 | for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aNbNodes; aNodeIdx++) |
163 | { |
164 | const SelectMgr_Vec3 aPnt (aCoords (3 * aNodeIdx - 2), |
165 | aCoords (3 * aNodeIdx - 1), |
166 | aCoords (3 * aNodeIdx)); |
167 | aBox.Add (aPnt); |
168 | } |
169 | } |
170 | else if (mySelMethod == MeshVS_MSM_NODES) |
171 | { |
172 | const gp_Pnt aVert = getVertexByIndex (anItemIdx); |
173 | aBox.Add (SelectMgr_Vec3 (aVert.X(), aVert.Y(), aVert.Z())); |
174 | } |
175 | |
176 | return aBox; |
177 | } |
178 | |
179 | //======================================================================= |
180 | //function : Center |
181 | //purpose : |
182 | //======================================================================= |
183 | Standard_Real MeshVS_CommonSensitiveEntity::Center (const Standard_Integer theIdx, |
184 | const Standard_Integer theAxis) const |
185 | { |
186 | const Select3D_BndBox3d& aBox = Box (theIdx); |
187 | SelectMgr_Vec3 aCenter = (aBox.CornerMin () + aBox.CornerMax ()) * 0.5; |
188 | |
189 | return theAxis == 0 ? aCenter.x() : (theAxis == 1 ? aCenter.y() : aCenter.z()); |
190 | } |
191 | |
192 | //======================================================================= |
193 | //function : Swap |
194 | //purpose : |
195 | //======================================================================= |
196 | void MeshVS_CommonSensitiveEntity::Swap (const Standard_Integer theIdx1, |
197 | const Standard_Integer theIdx2) |
198 | { |
199 | const Standard_Integer anItem1 = myItemIndexes.Value (theIdx1); |
200 | const Standard_Integer anItem2 = myItemIndexes.Value (theIdx2); |
201 | myItemIndexes.ChangeValue (theIdx1) = anItem2; |
202 | myItemIndexes.ChangeValue (theIdx2) = anItem1; |
203 | } |
204 | |
205 | //======================================================================= |
206 | //function : overlapsElement |
207 | //purpose : |
208 | //======================================================================= |
209 | Standard_Boolean MeshVS_CommonSensitiveEntity::overlapsElement (SelectBasics_SelectingVolumeManager& theMgr, |
210 | Standard_Integer theElemIdx, |
211 | Standard_Real& theMatchDepth) |
212 | { |
213 | const Standard_Integer anItemIdx = myItemIndexes.Value (theElemIdx); |
214 | if (mySelMethod == MeshVS_MSM_PRECISE) |
215 | { |
216 | MeshVS_Buffer aCoordsBuf (3 * myMaxFaceNodes * sizeof (Standard_Real)); |
217 | TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3 * myMaxFaceNodes); |
218 | Standard_Integer aNbNodes; |
219 | MeshVS_EntityType aType; |
220 | if (!myDataSource->GetGeom (anItemIdx, Standard_True, aCoords, aNbNodes, aType) |
221 | || aNbNodes == 0) |
222 | { |
223 | return Standard_False; |
224 | } |
225 | |
226 | MeshVS_Buffer aNodesBuf (aNbNodes * sizeof (Standard_Integer)); |
227 | TColStd_Array1OfInteger aElemNodes (aNodesBuf, 1, aNbNodes); |
228 | if (!myDataSource->GetNodesByElement (anItemIdx, aElemNodes, aNbNodes)) |
229 | { |
230 | return Standard_False; |
231 | } |
232 | if (aNbNodes == 3) |
233 | { |
234 | return theMgr.Overlaps (gp_Pnt (aCoords (1), aCoords (2), aCoords (3)), |
235 | gp_Pnt (aCoords (4), aCoords (5), aCoords (6)), |
236 | gp_Pnt (aCoords (7), aCoords (8), aCoords (9)), |
237 | Select3D_TOS_INTERIOR, theMatchDepth); |
238 | } |
239 | |
240 | MeshVS_Buffer aFacePntsBuf (aNbNodes * 3 * sizeof (Standard_Real)); |
241 | TColgp_Array1OfPnt aFacePnts (aFacePntsBuf, 1, aNbNodes); |
242 | for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aNbNodes; aNodeIdx++) |
243 | { |
244 | aFacePnts.SetValue (aNodeIdx, gp_Pnt (aCoords (3 * aNodeIdx - 2), |
245 | aCoords (3 * aNodeIdx - 1), |
246 | aCoords (3 * aNodeIdx))); |
247 | } |
248 | return theMgr.Overlaps (aFacePnts, Select3D_TOS_INTERIOR, theMatchDepth); |
249 | } |
250 | else if (mySelMethod == MeshVS_MSM_NODES) |
251 | { |
252 | const gp_Pnt aVert = getVertexByIndex (anItemIdx); |
253 | return theMgr.Overlaps (aVert, theMatchDepth); |
254 | } |
255 | return Standard_False; |
256 | } |
257 | |
258 | //======================================================================= |
259 | //function : elementIsInside |
260 | //purpose : |
261 | //======================================================================= |
262 | Standard_Boolean MeshVS_CommonSensitiveEntity::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr, |
263 | const Standard_Integer theElemIdx) |
264 | { |
265 | const Standard_Integer anItemIdx = myItemIndexes.Value (theElemIdx); |
266 | if (mySelMethod == MeshVS_MSM_PRECISE) |
267 | { |
268 | MeshVS_Buffer aCoordsBuf (3 * myMaxFaceNodes * sizeof (Standard_Real)); |
269 | TColStd_Array1OfReal aCoords (aCoordsBuf, 1, 3 * myMaxFaceNodes); |
270 | Standard_Integer aNbNodes; |
271 | MeshVS_EntityType aType; |
272 | if (!myDataSource->GetGeom (anItemIdx, Standard_True, aCoords, aNbNodes, aType) |
273 | || aNbNodes == 0) |
274 | { |
275 | return Standard_False; |
276 | } |
277 | |
278 | MeshVS_Buffer aNodesBuf (aNbNodes * sizeof (Standard_Integer)); |
279 | TColStd_Array1OfInteger aElemNodes (aNodesBuf, 1, aNbNodes); |
280 | if (!myDataSource->GetNodesByElement (anItemIdx, aElemNodes, aNbNodes)) |
281 | { |
282 | return Standard_False; |
283 | } |
284 | |
285 | MeshVS_Buffer aFacePntsBuf (aNbNodes * 3 * sizeof (Standard_Real)); |
286 | TColgp_Array1OfPnt aFacePnts (aFacePntsBuf, 1, aNbNodes); |
287 | for (Standard_Integer aNodeIdx = 1; aNodeIdx <= aNbNodes; ++aNodeIdx) |
288 | { |
289 | const gp_Pnt aPnt (aCoords (3 * aNodeIdx - 2), |
290 | aCoords (3 * aNodeIdx - 1), |
291 | aCoords (3 * aNodeIdx)); |
292 | if (!theMgr.Overlaps (aPnt)) |
293 | { |
294 | return Standard_False; |
295 | } |
296 | } |
297 | return Standard_True; |
298 | } |
299 | else if (mySelMethod == MeshVS_MSM_NODES) |
300 | { |
301 | const gp_Pnt aVert = getVertexByIndex (anItemIdx); |
302 | return theMgr.Overlaps (aVert); |
303 | } |
304 | return Standard_False; |
305 | } |
306 | |
307 | //======================================================================= |
308 | //function : distanceToCOG |
309 | //purpose : |
310 | //======================================================================= |
311 | Standard_Real MeshVS_CommonSensitiveEntity::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) |
312 | { |
313 | return theMgr.DistToGeometryCenter (myCOG); |
314 | } |
315 | |
316 | //======================================================================= |
317 | //function : BoundingBox |
318 | //purpose : |
319 | //======================================================================= |
320 | Select3D_BndBox3d MeshVS_CommonSensitiveEntity::BoundingBox() |
321 | { |
322 | return myBndBox; |
323 | } |