0029938: Visualization - SelectMgr_ViewerSelector::PickedPoint() should return point...
[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//=======================================================================
f751596e 56Select3D_SensitiveTriangulation::Select3D_SensitiveTriangulation (const Handle(SelectBasics_EntityOwner)& theOwnerId,
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//=======================================================================
f751596e 143Select3D_SensitiveTriangulation::Select3D_SensitiveTriangulation (const Handle(SelectBasics_EntityOwner)& theOwnerId,
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//=======================================================================
f751596e 262Standard_Boolean Select3D_SensitiveTriangulation::overlapsElement (SelectBasics_SelectingVolumeManager& theMgr,
263 Standard_Integer theElemIdx,
17017555 264 SelectBasics_PickResult& thePickResult)
7fd59977 265{
f751596e 266 const Standard_Integer& aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx);
f751596e 267
268 if (mySensType == Select3D_TOS_BOUNDARY)
269 {
270 Standard_Integer aSegmStartIdx = myFreeEdges->Value (aPrimitiveIdx * 2 + 1);
271 Standard_Integer aSegmEndIdx = myFreeEdges->Value (aPrimitiveIdx * 2 + 2);
17017555 272
273 const gp_Pnt anEdgePnts[2] =
274 {
275 myTriangul->Nodes().Value (aSegmStartIdx),
276 myTriangul->Nodes().Value (aSegmEndIdx)
277 };
278 TColgp_Array1OfPnt anEdgePntsArr (anEdgePnts[0], 1, 2);
279 Standard_Boolean isMatched = theMgr.Overlaps (anEdgePntsArr, Select3D_TOS_BOUNDARY, thePickResult);
f751596e 280 return isMatched;
281 }
282 else
283 {
284 const Poly_Array1OfTriangle& aTriangles = myTriangul->Triangles();
285 Standard_Integer aNode1, aNode2, aNode3;
286 aTriangles (aPrimitiveIdx + 1).Get (aNode1, aNode2, aNode3);
17017555 287 const gp_Pnt& aPnt1 = myTriangul->Nodes().Value (aNode1);
288 const gp_Pnt& aPnt2 = myTriangul->Nodes().Value (aNode2);
289 const gp_Pnt& aPnt3 = myTriangul->Nodes().Value (aNode3);
290 return theMgr.Overlaps (aPnt1, aPnt2, aPnt3, Select3D_TOS_INTERIOR, thePickResult);
f751596e 291 }
7fd59977 292}
ac04d101 293
2157d6ac 294//==================================================
295// Function : elementIsInside
296// Purpose :
297//==================================================
298Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
299 const Standard_Integer theElemIdx)
300{
2157d6ac 301 const Standard_Integer& aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx);
302
303 if (mySensType == Select3D_TOS_BOUNDARY)
304 {
17017555 305 const gp_Pnt& aSegmPnt1 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 1));
306 const gp_Pnt& aSegmPnt2 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 2));
3bf9a45f 307 return theMgr.Overlaps (aSegmPnt1) && theMgr.Overlaps (aSegmPnt2);
2157d6ac 308 }
309 else
310 {
17017555 311 Standard_Integer aNode1, aNode2, aNode3;
2157d6ac 312 myTriangul->Triangles() (aPrimitiveIdx + 1).Get (aNode1, aNode2, aNode3);
313
17017555 314 const gp_Pnt& aPnt1 = myTriangul->Nodes().Value (aNode1);
315 const gp_Pnt& aPnt2 = myTriangul->Nodes().Value (aNode2);
316 const gp_Pnt& aPnt3 = myTriangul->Nodes().Value (aNode3);
3bf9a45f 317 return theMgr.Overlaps (aPnt1)
318 && theMgr.Overlaps (aPnt2)
319 && theMgr.Overlaps (aPnt3);
2157d6ac 320 }
321}
322
ac04d101 323//=======================================================================
f751596e 324// function : distanceToCOG
325// purpose : Calculates distance from the 3d projection of used-picked
326// screen point to center of the geometry
ac04d101 327//=======================================================================
f751596e 328Standard_Real Select3D_SensitiveTriangulation::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
7fd59977 329{
f751596e 330 return theMgr.DistToGeometryCenter (myCDG3D);
7fd59977 331}
332
7fd59977 333//=======================================================================
f751596e 334//function : GetConnected
4bf18dff 335//purpose :
7fd59977 336//=======================================================================
f751596e 337Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangulation::GetConnected()
7fd59977 338{
f751596e 339 Standard_Boolean isInterior = mySensType == Select3D_TOS_INTERIOR;
340 Handle(Select3D_SensitiveTriangulation) aNewEntity =
341 new Select3D_SensitiveTriangulation (myOwnerId, myTriangul, myInitLocation, myFreeEdges, myCDG3D, isInterior);
7fd59977 342
f751596e 343 return aNewEntity;
7fd59977 344}
345
346//=======================================================================
f751596e 347// function : applyTransformation
348// purpose : Inner function for transformation application to bounding
349// box of the triangulation
7fd59977 350//=======================================================================
f751596e 351Select3D_BndBox3d Select3D_SensitiveTriangulation::applyTransformation()
7fd59977 352{
f751596e 353 if (!HasInitLocation())
354 return myBndBox;
aec37c15 355
f751596e 356 Select3D_BndBox3d aBndBox;
357 for (Standard_Integer aX = 0; aX <=1; ++aX)
ac04d101 358 {
f751596e 359 for (Standard_Integer aY = 0; aY <=1; ++aY)
4269bd1b 360 {
f751596e 361 for (Standard_Integer aZ = 0; aZ <= 1; ++aZ)
362 {
363 gp_Pnt aVertex = gp_Pnt (aX == 0 ? myBndBox.CornerMin().x() : myBndBox.CornerMax().x(),
364 aY == 0 ? myBndBox.CornerMin().y() : myBndBox.CornerMax().y(),
365 aZ == 0 ? myBndBox.CornerMin().z() : myBndBox.CornerMax().z());
3bf9a45f 366 aVertex.Transform (myInitLocation.Transformation());
f751596e 367 aBndBox.Add (Select3D_Vec3 (aVertex.X(), aVertex.Y(), aVertex.Z()));
368 }
4269bd1b 369 }
4bf18dff 370 }
4269bd1b 371
f751596e 372 return aBndBox;
7fd59977 373}
374
375//=======================================================================
f751596e 376// function : BoundingBox
377// purpose : Returns bounding box of the triangulation. If location
378// transformation is set, it will be applied
7fd59977 379//=======================================================================
f751596e 380Select3D_BndBox3d Select3D_SensitiveTriangulation::BoundingBox()
7fd59977 381{
f751596e 382 if (myBndBox.IsValid())
383 return applyTransformation();
384
385 const Standard_Integer aLower = myTriangul->Nodes().Lower();
386 const Standard_Integer anUpper = myTriangul->Nodes().Upper();
387 Select3D_BndBox3d aBndBox;
388 for (Standard_Integer aNodeIdx = aLower; aNodeIdx <= anUpper; ++aNodeIdx)
ac04d101 389 {
f751596e 390 const gp_Pnt& aNode = myTriangul->Nodes().Value (aNodeIdx);
391 const SelectMgr_Vec3 aNodeTransf = SelectMgr_Vec3 (aNode.X(), aNode.Y(), aNode.Z());
392 aBndBox.Add (aNodeTransf);
7fd59977 393 }
4bf18dff 394
f751596e 395 myBndBox = aBndBox;
7fd59977 396
f751596e 397 return applyTransformation();
398}
ac04d101 399
f751596e 400//=======================================================================
401// function : CenterOfGeometry
402// purpose : Returns center of triangulation. If location transformation
403// is set, it will be applied
404//=======================================================================
405gp_Pnt Select3D_SensitiveTriangulation::CenterOfGeometry() const
7fd59977 406{
3bf9a45f 407 return myCDG3D;
7fd59977 408}
409
f751596e 410//=======================================================================
411// function : NbSubElements
412// purpose : Returns the amount of nodes in triangulation
413//=======================================================================
414Standard_Integer Select3D_SensitiveTriangulation::NbSubElements()
7fd59977 415{
f751596e 416 return myTriangul->Nodes().Length();
3bf9a45f 417}
418
419//=======================================================================
420//function : HasInitLocation
421//purpose :
422//=======================================================================
423Standard_Boolean Select3D_SensitiveTriangulation::HasInitLocation() const
424{
425 return !myInitLocation.IsIdentity();
426}
427
428//=======================================================================
429//function : InvInitLocation
430//purpose :
431//=======================================================================
91d96372 432gp_GTrsf Select3D_SensitiveTriangulation::InvInitLocation() const
3bf9a45f 433{
434 return myInvInitLocation;
435}