0031322: Visualization, Select3D_SensitiveEntity - method NbSubElements() should...
[occt.git] / src / Select3D / Select3D_SensitiveTriangulation.cxx
CommitLineData
b311480e 1// Created on: 1997-05-15
2// Created by: Robert COUBLANC
3// Copyright (c) 1997-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
b311480e 16
0609d8ee 17#include <Select3D_SensitiveTriangulation.hxx>
7fd59977 18
4bf18dff 19#include <Poly.hxx>
7fd59977 20#include <Poly_Connect.hxx>
7fd59977 21#include <TColStd_Array1OfInteger.hxx>
22#include <Select3D_SensitiveTriangle.hxx>
23#include <Precision.hxx>
f751596e 24#include <Select3D_TypeOfSensitivity.hxx>
7fd59977 25
0609d8ee 26#include <algorithm>
7fd59977 27
92efcf78 28IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveTriangulation,Select3D_SensitiveSet)
29
0609d8ee 30namespace
7fd59977 31{
0609d8ee 32 static Standard_Integer NbOfFreeEdges (const Handle(Poly_Triangulation)& theTriangulation)
f751596e 33 {
0609d8ee 34 Standard_Integer aNbFree = 0;
35 Poly_Connect aPoly (theTriangulation);
36 Standard_Integer aTriangleNodes[3];
37 for (Standard_Integer aTrgIdx = 1; aTrgIdx <= theTriangulation->NbTriangles(); aTrgIdx++)
38 {
39 aPoly.Triangles (aTrgIdx, aTriangleNodes[0], aTriangleNodes[1], aTriangleNodes[2]);
40 for (Standard_Integer aNodeIdx = 0; aNodeIdx < 3; ++aNodeIdx)
41 {
42 if (aTriangleNodes[aNodeIdx] == 0)
43 {
44 ++aNbFree;
45 }
46 }
47 }
48 return aNbFree;
f751596e 49 }
7fd59977 50}
51
7fd59977 52//=======================================================================
53//function : Select3D_SensitiveTriangulation
4bf18dff 54//purpose :
7fd59977 55//=======================================================================
0ef04197 56Select3D_SensitiveTriangulation::Select3D_SensitiveTriangulation (const Handle(SelectMgr_EntityOwner)& theOwnerId,
f751596e 57 const Handle(Poly_Triangulation)& theTrg,
58 const TopLoc_Location& theInitLoc,
59 const Standard_Boolean theIsInterior)
60: Select3D_SensitiveSet (theOwnerId),
61 myTriangul (theTrg),
d48df25d 62 myInitLocation (theInitLoc)
7fd59977 63{
3bf9a45f 64 myInvInitLocation = myInitLocation.Transformation().Inverted();
f751596e 65 mySensType = theIsInterior ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
66 const Poly_Array1OfTriangle& aTriangles = myTriangul->Triangles();
67 const TColgp_Array1OfPnt& aNodes = myTriangul->Nodes();
68 Standard_Integer aNbTriangles (myTriangul->NbTriangles());
69 gp_XYZ aCenter (0.0, 0.0, 0.0);
70
71 myPrimitivesNb = theIsInterior ? aNbTriangles : NbOfFreeEdges (theTrg);
72 myBVHPrimIndexes = new TColStd_HArray1OfInteger(0, myPrimitivesNb - 1);
73 TColStd_Array1OfInteger& aBVHPrimIdxs = myBVHPrimIndexes->ChangeArray1();
74
75 if (!theIsInterior)
ac04d101 76 {
f751596e 77 Standard_Integer anEdgeIdx = 1;
78 myFreeEdges = new TColStd_HArray1OfInteger (1, 2 * myPrimitivesNb);
79 TColStd_Array1OfInteger& aFreeEdges = myFreeEdges->ChangeArray1();
80 Poly_Connect aPoly (myTriangul);
81 Standard_Integer aTriangle[3];
82 Standard_Integer aTrNodeIdx[3];
83 for (Standard_Integer aTriangleIdx = 1; aTriangleIdx <= aNbTriangles; aTriangleIdx++)
ac04d101 84 {
f751596e 85 aPoly.Triangles (aTriangleIdx, aTriangle[0], aTriangle[1], aTriangle[2]);
86 aTriangles (aTriangleIdx).Get (aTrNodeIdx[0], aTrNodeIdx[1], aTrNodeIdx[2]);
87 aCenter += (aNodes (aTrNodeIdx[0]).XYZ() + aNodes (aTrNodeIdx[1]).XYZ()+ aNodes (aTrNodeIdx[2]).XYZ()) / 3.0;
88 for (Standard_Integer aVertIdx = 0; aVertIdx < 3; aVertIdx++)
ac04d101 89 {
f751596e 90 Standard_Integer aNextVert = (aVertIdx + 1) % 3;
91 if (aTriangle[aVertIdx] == 0)
ac04d101 92 {
f751596e 93 aFreeEdges (anEdgeIdx) = aTrNodeIdx[aVertIdx];
94 aFreeEdges (anEdgeIdx+1) = aTrNodeIdx[aNextVert];
95 anEdgeIdx += 2;
ac04d101 96 }
7fd59977 97 }
98 }
99 }
f751596e 100 else
101 {
102 Standard_Integer aTrNodeIdx[3];
103 for (Standard_Integer aTrIdx = 1; aTrIdx <= aNbTriangles; aTrIdx++)
ac04d101 104 {
f751596e 105 aTriangles (aTrIdx).Get (aTrNodeIdx[0], aTrNodeIdx[1], aTrNodeIdx[2]);
106 aCenter += (aNodes (aTrNodeIdx[0]).XYZ() + aNodes (aTrNodeIdx[1]).XYZ()+ aNodes (aTrNodeIdx[2]).XYZ()) / 3.0;
7fd59977 107 }
108 }
f751596e 109 if (aNbTriangles != 0)
110 aCenter /= aNbTriangles;
111 myCDG3D = gp_Pnt (aCenter);
7fd59977 112
f751596e 113 myBndBox.Clear();
114 for (Standard_Integer aNodeIdx = 1; aNodeIdx <= myTriangul->NbNodes(); ++aNodeIdx)
115 {
116 myBndBox.Add (SelectMgr_Vec3 (aNodes (aNodeIdx).X(),
117 aNodes (aNodeIdx).Y(),
118 aNodes (aNodeIdx).Z()));
7fd59977 119 }
4bf18dff 120
f751596e 121 if (theIsInterior)
122 {
123 for (Standard_Integer aTriangleIdx = 1; aTriangleIdx <= aNbTriangles; ++aTriangleIdx)
124 {
125 aBVHPrimIdxs (aTriangleIdx - 1) = aTriangleIdx - 1;
126 }
127 }
128 else
129 {
130 Standard_Integer aStartIdx = myFreeEdges->Lower();
131 Standard_Integer anEndIdx = myFreeEdges->Upper();
132 for (Standard_Integer aFreeEdgesIdx = aStartIdx; aFreeEdgesIdx <= anEndIdx; aFreeEdgesIdx += 2)
133 {
134 aBVHPrimIdxs ((aFreeEdgesIdx - aStartIdx) / 2) = (aFreeEdgesIdx - aStartIdx) / 2;
135 }
136 }
7fd59977 137}
138
7fd59977 139//=======================================================================
f751596e 140//function : Select3D_SensitiveTriangulation
4bf18dff 141//purpose :
7fd59977 142//=======================================================================
0ef04197 143Select3D_SensitiveTriangulation::Select3D_SensitiveTriangulation (const Handle(SelectMgr_EntityOwner)& theOwnerId,
f751596e 144 const Handle(Poly_Triangulation)& theTrg,
145 const TopLoc_Location& theInitLoc,
146 const Handle(TColStd_HArray1OfInteger)& theFreeEdges,
147 const gp_Pnt& theCOG,
148 const Standard_Boolean theIsInterior)
149: Select3D_SensitiveSet (theOwnerId),
150 myTriangul (theTrg),
151 myInitLocation (theInitLoc),
152 myCDG3D (theCOG),
d48df25d 153 myFreeEdges (theFreeEdges)
4269bd1b 154{
3bf9a45f 155 myInvInitLocation = myInitLocation.Transformation().Inverted();
f751596e 156 mySensType = theIsInterior ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
157 myPrimitivesNb = theIsInterior ? theTrg->Triangles().Length() : theFreeEdges->Length() / 2;
158 myBVHPrimIndexes = new TColStd_HArray1OfInteger(0, myPrimitivesNb - 1);
159 if (theIsInterior)
7fd59977 160 {
f751596e 161 for (Standard_Integer aTriangleIdx = 1; aTriangleIdx <= myPrimitivesNb; ++aTriangleIdx)
7fd59977 162 {
f751596e 163 myBVHPrimIndexes->SetValue (aTriangleIdx - 1, aTriangleIdx - 1);
7fd59977 164 }
165 }
7fd59977 166 else
167 {
f751596e 168 Standard_Integer aStartIdx = myFreeEdges->Lower();
169 Standard_Integer anEndIdx = myFreeEdges->Upper();
170 for (Standard_Integer aFreeEdgesIdx = aStartIdx; aFreeEdgesIdx <= anEndIdx; aFreeEdgesIdx += 2)
7fd59977 171 {
f751596e 172 myBVHPrimIndexes->SetValue ((aFreeEdgesIdx - aStartIdx) / 2, (aFreeEdgesIdx - aStartIdx) / 2);
7fd59977 173 }
4bf18dff 174 }
4269bd1b 175}
7fd59977 176
177//=======================================================================
f751596e 178// function : Size
179// purpose : Returns the length of array of triangles or edges
7fd59977 180//=======================================================================
f751596e 181Standard_Integer Select3D_SensitiveTriangulation::Size() const
7fd59977 182{
f751596e 183 return myPrimitivesNb;
7fd59977 184}
185
7fd59977 186//=======================================================================
f751596e 187// function : Box
188// purpose : Returns bounding box of triangle/edge with index theIdx
7fd59977 189//=======================================================================
f751596e 190Select3D_BndBox3d Select3D_SensitiveTriangulation::Box (const Standard_Integer theIdx) const
4bf18dff 191{
f751596e 192 Standard_Integer aPrimIdx = myBVHPrimIndexes->Value (theIdx);
193 SelectMgr_Vec3 aMinPnt (RealLast());
194 SelectMgr_Vec3 aMaxPnt (RealFirst());
7fd59977 195
f751596e 196 if (mySensType == Select3D_TOS_INTERIOR)
ac04d101 197 {
f751596e 198 Standard_Integer aNode1, aNode2, aNode3;
199 myTriangul->Triangles() (aPrimIdx + 1).Get (aNode1, aNode2, aNode3);
200
17017555 201 const gp_Pnt& aPnt1 = myTriangul->Nodes().Value (aNode1);
202 const gp_Pnt& aPnt2 = myTriangul->Nodes().Value (aNode2);
203 const gp_Pnt& aPnt3 = myTriangul->Nodes().Value (aNode3);
f751596e 204
205 aMinPnt = SelectMgr_Vec3 (Min (aPnt1.X(), Min (aPnt2.X(), aPnt3.X())),
206 Min (aPnt1.Y(), Min (aPnt2.Y(), aPnt3.Y())),
207 Min (aPnt1.Z(), Min (aPnt2.Z(), aPnt3.Z())));
208 aMaxPnt = SelectMgr_Vec3 (Max (aPnt1.X(), Max (aPnt2.X(), aPnt3.X())),
209 Max (aPnt1.Y(), Max (aPnt2.Y(), aPnt3.Y())),
210 Max (aPnt1.Z(), Max (aPnt2.Z(), aPnt3.Z())));
211 }
212 else
213 {
214 Standard_Integer aNodeIdx1 = myFreeEdges->Value (myFreeEdges->Lower() + aPrimIdx);
215 Standard_Integer aNodeIdx2 = myFreeEdges->Value (myFreeEdges->Lower() + aPrimIdx + 1);
17017555 216 const gp_Pnt& aNode1 = myTriangul->Nodes().Value (aNodeIdx1);
217 const gp_Pnt& aNode2 = myTriangul->Nodes().Value (aNodeIdx2);
f751596e 218
219 aMinPnt = SelectMgr_Vec3 (Min (aNode1.X(), aNode2.X()),
220 Min (aNode1.Y(), aNode2.Y()),
221 Min (aNode1.Z(), aNode2.Z()));
222 aMaxPnt = SelectMgr_Vec3 (Max (aNode1.X(), aNode2.X()),
223 Max (aNode1.Y(), aNode2.Y()),
224 Max (aNode1.Z(), aNode2.Z()));
7fd59977 225 }
7fd59977 226
f751596e 227 return Select3D_BndBox3d (aMinPnt, aMaxPnt);
7fd59977 228}
229
230//=======================================================================
f751596e 231// function : Center
232// purpose : Returns geometry center of triangle/edge with index theIdx
233// in array along the given axis theAxis
7fd59977 234//=======================================================================
f751596e 235Standard_Real Select3D_SensitiveTriangulation::Center (const Standard_Integer theIdx,
236 const Standard_Integer theAxis) const
7fd59977 237{
f751596e 238 const Select3D_BndBox3d& aBox = Box (theIdx);
17017555 239 const SelectMgr_Vec3 aCenter = (aBox.CornerMin () + aBox.CornerMax ()) * 0.5;
240 return aCenter[theAxis];
7fd59977 241}
242
7fd59977 243//=======================================================================
f751596e 244// function : Swap
245// purpose : Swaps items with indexes theIdx1 and theIdx2 in array
7fd59977 246//=======================================================================
f751596e 247void Select3D_SensitiveTriangulation::Swap (const Standard_Integer theIdx1,
248 const Standard_Integer theIdx2)
7fd59977 249{
f751596e 250 Standard_Integer anElemIdx1 = myBVHPrimIndexes->Value (theIdx1);
251 Standard_Integer anElemIdx2 = myBVHPrimIndexes->Value (theIdx2);
4bf18dff 252
f751596e 253 myBVHPrimIndexes->ChangeValue (theIdx1) = anElemIdx2;
254 myBVHPrimIndexes->ChangeValue (theIdx2) = anElemIdx1;
7fd59977 255}
256
7fd59977 257//=======================================================================
f751596e 258// function : overlapsElement
259// purpose : Checks whether the element with index theIdx overlaps the
260// current selecting volume
7fd59977 261//=======================================================================
4a056d20 262Standard_Boolean Select3D_SensitiveTriangulation::overlapsElement (SelectBasics_PickResult& thePickResult,
263 SelectBasics_SelectingVolumeManager& theMgr,
f751596e 264 Standard_Integer theElemIdx,
4a056d20 265 Standard_Boolean theIsFullInside)
7fd59977 266{
4a056d20 267 if (theIsFullInside)
268 {
269 return Standard_True;
270 }
f751596e 271
4a056d20 272 const Standard_Integer aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx);
f751596e 273 if (mySensType == Select3D_TOS_BOUNDARY)
274 {
275 Standard_Integer aSegmStartIdx = myFreeEdges->Value (aPrimitiveIdx * 2 + 1);
276 Standard_Integer aSegmEndIdx = myFreeEdges->Value (aPrimitiveIdx * 2 + 2);
17017555 277
278 const gp_Pnt anEdgePnts[2] =
279 {
280 myTriangul->Nodes().Value (aSegmStartIdx),
281 myTriangul->Nodes().Value (aSegmEndIdx)
282 };
283 TColgp_Array1OfPnt anEdgePntsArr (anEdgePnts[0], 1, 2);
284 Standard_Boolean isMatched = theMgr.Overlaps (anEdgePntsArr, Select3D_TOS_BOUNDARY, thePickResult);
f751596e 285 return isMatched;
286 }
287 else
288 {
289 const Poly_Array1OfTriangle& aTriangles = myTriangul->Triangles();
290 Standard_Integer aNode1, aNode2, aNode3;
291 aTriangles (aPrimitiveIdx + 1).Get (aNode1, aNode2, aNode3);
17017555 292 const gp_Pnt& aPnt1 = myTriangul->Nodes().Value (aNode1);
293 const gp_Pnt& aPnt2 = myTriangul->Nodes().Value (aNode2);
294 const gp_Pnt& aPnt3 = myTriangul->Nodes().Value (aNode3);
295 return theMgr.Overlaps (aPnt1, aPnt2, aPnt3, Select3D_TOS_INTERIOR, thePickResult);
f751596e 296 }
7fd59977 297}
ac04d101 298
2157d6ac 299//==================================================
300// Function : elementIsInside
301// Purpose :
302//==================================================
303Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
4a056d20 304 Standard_Integer theElemIdx,
305 Standard_Boolean theIsFullInside)
2157d6ac 306{
4a056d20 307 if (theIsFullInside)
308 {
309 return Standard_True;
310 }
2157d6ac 311
4a056d20 312 const Standard_Integer aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx);
2157d6ac 313 if (mySensType == Select3D_TOS_BOUNDARY)
314 {
17017555 315 const gp_Pnt& aSegmPnt1 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 1));
316 const gp_Pnt& aSegmPnt2 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 2));
3bf9a45f 317 return theMgr.Overlaps (aSegmPnt1) && theMgr.Overlaps (aSegmPnt2);
2157d6ac 318 }
319 else
320 {
17017555 321 Standard_Integer aNode1, aNode2, aNode3;
2157d6ac 322 myTriangul->Triangles() (aPrimitiveIdx + 1).Get (aNode1, aNode2, aNode3);
323
17017555 324 const gp_Pnt& aPnt1 = myTriangul->Nodes().Value (aNode1);
325 const gp_Pnt& aPnt2 = myTriangul->Nodes().Value (aNode2);
326 const gp_Pnt& aPnt3 = myTriangul->Nodes().Value (aNode3);
3bf9a45f 327 return theMgr.Overlaps (aPnt1)
328 && theMgr.Overlaps (aPnt2)
329 && theMgr.Overlaps (aPnt3);
2157d6ac 330 }
331}
332
ac04d101 333//=======================================================================
f751596e 334// function : distanceToCOG
335// purpose : Calculates distance from the 3d projection of used-picked
336// screen point to center of the geometry
ac04d101 337//=======================================================================
f751596e 338Standard_Real Select3D_SensitiveTriangulation::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
7fd59977 339{
f751596e 340 return theMgr.DistToGeometryCenter (myCDG3D);
7fd59977 341}
342
7fd59977 343//=======================================================================
f751596e 344//function : GetConnected
4bf18dff 345//purpose :
7fd59977 346//=======================================================================
f751596e 347Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangulation::GetConnected()
7fd59977 348{
f751596e 349 Standard_Boolean isInterior = mySensType == Select3D_TOS_INTERIOR;
350 Handle(Select3D_SensitiveTriangulation) aNewEntity =
351 new Select3D_SensitiveTriangulation (myOwnerId, myTriangul, myInitLocation, myFreeEdges, myCDG3D, isInterior);
7fd59977 352
f751596e 353 return aNewEntity;
7fd59977 354}
355
356//=======================================================================
f751596e 357// function : applyTransformation
358// purpose : Inner function for transformation application to bounding
359// box of the triangulation
7fd59977 360//=======================================================================
f751596e 361Select3D_BndBox3d Select3D_SensitiveTriangulation::applyTransformation()
7fd59977 362{
f751596e 363 if (!HasInitLocation())
364 return myBndBox;
aec37c15 365
f751596e 366 Select3D_BndBox3d aBndBox;
367 for (Standard_Integer aX = 0; aX <=1; ++aX)
ac04d101 368 {
f751596e 369 for (Standard_Integer aY = 0; aY <=1; ++aY)
4269bd1b 370 {
f751596e 371 for (Standard_Integer aZ = 0; aZ <= 1; ++aZ)
372 {
373 gp_Pnt aVertex = gp_Pnt (aX == 0 ? myBndBox.CornerMin().x() : myBndBox.CornerMax().x(),
374 aY == 0 ? myBndBox.CornerMin().y() : myBndBox.CornerMax().y(),
375 aZ == 0 ? myBndBox.CornerMin().z() : myBndBox.CornerMax().z());
3bf9a45f 376 aVertex.Transform (myInitLocation.Transformation());
f751596e 377 aBndBox.Add (Select3D_Vec3 (aVertex.X(), aVertex.Y(), aVertex.Z()));
378 }
4269bd1b 379 }
4bf18dff 380 }
4269bd1b 381
f751596e 382 return aBndBox;
7fd59977 383}
384
385//=======================================================================
f751596e 386// function : BoundingBox
387// purpose : Returns bounding box of the triangulation. If location
388// transformation is set, it will be applied
7fd59977 389//=======================================================================
f751596e 390Select3D_BndBox3d Select3D_SensitiveTriangulation::BoundingBox()
7fd59977 391{
f751596e 392 if (myBndBox.IsValid())
393 return applyTransformation();
394
395 const Standard_Integer aLower = myTriangul->Nodes().Lower();
396 const Standard_Integer anUpper = myTriangul->Nodes().Upper();
397 Select3D_BndBox3d aBndBox;
398 for (Standard_Integer aNodeIdx = aLower; aNodeIdx <= anUpper; ++aNodeIdx)
ac04d101 399 {
f751596e 400 const gp_Pnt& aNode = myTriangul->Nodes().Value (aNodeIdx);
401 const SelectMgr_Vec3 aNodeTransf = SelectMgr_Vec3 (aNode.X(), aNode.Y(), aNode.Z());
402 aBndBox.Add (aNodeTransf);
7fd59977 403 }
4bf18dff 404
f751596e 405 myBndBox = aBndBox;
7fd59977 406
f751596e 407 return applyTransformation();
408}
ac04d101 409
f751596e 410//=======================================================================
411// function : CenterOfGeometry
412// purpose : Returns center of triangulation. If location transformation
413// is set, it will be applied
414//=======================================================================
415gp_Pnt Select3D_SensitiveTriangulation::CenterOfGeometry() const
7fd59977 416{
3bf9a45f 417 return myCDG3D;
7fd59977 418}
419
f751596e 420//=======================================================================
421// function : NbSubElements
422// purpose : Returns the amount of nodes in triangulation
423//=======================================================================
fe758dbe 424Standard_Integer Select3D_SensitiveTriangulation::NbSubElements() const
7fd59977 425{
f751596e 426 return myTriangul->Nodes().Length();
3bf9a45f 427}
428
429//=======================================================================
430//function : HasInitLocation
431//purpose :
432//=======================================================================
433Standard_Boolean Select3D_SensitiveTriangulation::HasInitLocation() const
434{
435 return !myInitLocation.IsIdentity();
436}
437
438//=======================================================================
439//function : InvInitLocation
440//purpose :
441//=======================================================================
91d96372 442gp_GTrsf Select3D_SensitiveTriangulation::InvInitLocation() const
3bf9a45f 443{
444 return myInvInitLocation;
445}