1 // Created on: 1997-05-15
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
20 #include <Poly_Connect.hxx>
21 #include <TColStd_Array1OfInteger.hxx>
22 #include <Select3D_SensitiveTriangle.hxx>
23 #include <Precision.hxx>
24 #include <Select3D_TypeOfSensitivity.hxx>
26 #include <Select3D_SensitiveTriangulation.hxx>
29 IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveTriangulation,Select3D_SensitiveSet)
31 static Standard_Integer NbOfFreeEdges (const Handle(Poly_Triangulation)& theTriangulation)
33 Standard_Integer aNbFree = 0;
34 Poly_Connect aPoly (theTriangulation);
35 Standard_Integer aTriangleNodes[3];
36 for (Standard_Integer aTrgIdx = 1; aTrgIdx <= theTriangulation->NbTriangles(); aTrgIdx++)
38 aPoly.Triangles (aTrgIdx, aTriangleNodes[0], aTriangleNodes[1], aTriangleNodes[2]);
39 for (Standard_Integer aNodeIdx = 0; aNodeIdx < 3; aNodeIdx++)
40 if (aTriangleNodes[aNodeIdx] == 0)
46 //=======================================================================
47 //function : Select3D_SensitiveTriangulation
49 //=======================================================================
50 Select3D_SensitiveTriangulation::Select3D_SensitiveTriangulation (const Handle(SelectBasics_EntityOwner)& theOwnerId,
51 const Handle(Poly_Triangulation)& theTrg,
52 const TopLoc_Location& theInitLoc,
53 const Standard_Boolean theIsInterior)
54 : Select3D_SensitiveSet (theOwnerId),
56 myInitLocation (theInitLoc)
58 myInvInitLocation = myInitLocation.Transformation().Inverted();
59 mySensType = theIsInterior ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
60 const Poly_Array1OfTriangle& aTriangles = myTriangul->Triangles();
61 const TColgp_Array1OfPnt& aNodes = myTriangul->Nodes();
62 Standard_Integer aNbTriangles (myTriangul->NbTriangles());
63 gp_XYZ aCenter (0.0, 0.0, 0.0);
65 myPrimitivesNb = theIsInterior ? aNbTriangles : NbOfFreeEdges (theTrg);
66 myBVHPrimIndexes = new TColStd_HArray1OfInteger(0, myPrimitivesNb - 1);
67 TColStd_Array1OfInteger& aBVHPrimIdxs = myBVHPrimIndexes->ChangeArray1();
71 Standard_Integer anEdgeIdx = 1;
72 myFreeEdges = new TColStd_HArray1OfInteger (1, 2 * myPrimitivesNb);
73 TColStd_Array1OfInteger& aFreeEdges = myFreeEdges->ChangeArray1();
74 Poly_Connect aPoly (myTriangul);
75 Standard_Integer aTriangle[3];
76 Standard_Integer aTrNodeIdx[3];
77 for (Standard_Integer aTriangleIdx = 1; aTriangleIdx <= aNbTriangles; aTriangleIdx++)
79 aPoly.Triangles (aTriangleIdx, aTriangle[0], aTriangle[1], aTriangle[2]);
80 aTriangles (aTriangleIdx).Get (aTrNodeIdx[0], aTrNodeIdx[1], aTrNodeIdx[2]);
81 aCenter += (aNodes (aTrNodeIdx[0]).XYZ() + aNodes (aTrNodeIdx[1]).XYZ()+ aNodes (aTrNodeIdx[2]).XYZ()) / 3.0;
82 for (Standard_Integer aVertIdx = 0; aVertIdx < 3; aVertIdx++)
84 Standard_Integer aNextVert = (aVertIdx + 1) % 3;
85 if (aTriangle[aVertIdx] == 0)
87 aFreeEdges (anEdgeIdx) = aTrNodeIdx[aVertIdx];
88 aFreeEdges (anEdgeIdx+1) = aTrNodeIdx[aNextVert];
96 Standard_Integer aTrNodeIdx[3];
97 for (Standard_Integer aTrIdx = 1; aTrIdx <= aNbTriangles; aTrIdx++)
99 aTriangles (aTrIdx).Get (aTrNodeIdx[0], aTrNodeIdx[1], aTrNodeIdx[2]);
100 aCenter += (aNodes (aTrNodeIdx[0]).XYZ() + aNodes (aTrNodeIdx[1]).XYZ()+ aNodes (aTrNodeIdx[2]).XYZ()) / 3.0;
103 if (aNbTriangles != 0)
104 aCenter /= aNbTriangles;
105 myCDG3D = gp_Pnt (aCenter);
108 for (Standard_Integer aNodeIdx = 1; aNodeIdx <= myTriangul->NbNodes(); ++aNodeIdx)
110 myBndBox.Add (SelectMgr_Vec3 (aNodes (aNodeIdx).X(),
111 aNodes (aNodeIdx).Y(),
112 aNodes (aNodeIdx).Z()));
117 for (Standard_Integer aTriangleIdx = 1; aTriangleIdx <= aNbTriangles; ++aTriangleIdx)
119 aBVHPrimIdxs (aTriangleIdx - 1) = aTriangleIdx - 1;
124 Standard_Integer aStartIdx = myFreeEdges->Lower();
125 Standard_Integer anEndIdx = myFreeEdges->Upper();
126 for (Standard_Integer aFreeEdgesIdx = aStartIdx; aFreeEdgesIdx <= anEndIdx; aFreeEdgesIdx += 2)
128 aBVHPrimIdxs ((aFreeEdgesIdx - aStartIdx) / 2) = (aFreeEdgesIdx - aStartIdx) / 2;
134 //=======================================================================
135 //function : Select3D_SensitiveTriangulation
137 //=======================================================================
138 Select3D_SensitiveTriangulation::Select3D_SensitiveTriangulation (const Handle(SelectBasics_EntityOwner)& theOwnerId,
139 const Handle(Poly_Triangulation)& theTrg,
140 const TopLoc_Location& theInitLoc,
141 const Handle(TColStd_HArray1OfInteger)& theFreeEdges,
142 const gp_Pnt& theCOG,
143 const Standard_Boolean theIsInterior)
144 : Select3D_SensitiveSet (theOwnerId),
146 myInitLocation (theInitLoc),
148 myFreeEdges (theFreeEdges)
150 myInvInitLocation = myInitLocation.Transformation().Inverted();
151 mySensType = theIsInterior ? Select3D_TOS_INTERIOR : Select3D_TOS_BOUNDARY;
152 myPrimitivesNb = theIsInterior ? theTrg->Triangles().Length() : theFreeEdges->Length() / 2;
153 myBVHPrimIndexes = new TColStd_HArray1OfInteger(0, myPrimitivesNb - 1);
156 for (Standard_Integer aTriangleIdx = 1; aTriangleIdx <= myPrimitivesNb; ++aTriangleIdx)
158 myBVHPrimIndexes->SetValue (aTriangleIdx - 1, aTriangleIdx - 1);
163 Standard_Integer aStartIdx = myFreeEdges->Lower();
164 Standard_Integer anEndIdx = myFreeEdges->Upper();
165 for (Standard_Integer aFreeEdgesIdx = aStartIdx; aFreeEdgesIdx <= anEndIdx; aFreeEdgesIdx += 2)
167 myBVHPrimIndexes->SetValue ((aFreeEdgesIdx - aStartIdx) / 2, (aFreeEdgesIdx - aStartIdx) / 2);
172 //=======================================================================
174 // purpose : Returns the length of array of triangles or edges
175 //=======================================================================
176 Standard_Integer Select3D_SensitiveTriangulation::Size() const
178 return myPrimitivesNb;
181 //=======================================================================
183 // purpose : Returns bounding box of triangle/edge with index theIdx
184 //=======================================================================
185 Select3D_BndBox3d Select3D_SensitiveTriangulation::Box (const Standard_Integer theIdx) const
187 Standard_Integer aPrimIdx = myBVHPrimIndexes->Value (theIdx);
188 SelectMgr_Vec3 aMinPnt (RealLast());
189 SelectMgr_Vec3 aMaxPnt (RealFirst());
191 if (mySensType == Select3D_TOS_INTERIOR)
193 Standard_Integer aNode1, aNode2, aNode3;
194 myTriangul->Triangles() (aPrimIdx + 1).Get (aNode1, aNode2, aNode3);
196 gp_Pnt aPnt1 = myTriangul->Nodes().Value (aNode1);
197 gp_Pnt aPnt2 = myTriangul->Nodes().Value (aNode2);
198 gp_Pnt aPnt3 = myTriangul->Nodes().Value (aNode3);
200 aMinPnt = SelectMgr_Vec3 (Min (aPnt1.X(), Min (aPnt2.X(), aPnt3.X())),
201 Min (aPnt1.Y(), Min (aPnt2.Y(), aPnt3.Y())),
202 Min (aPnt1.Z(), Min (aPnt2.Z(), aPnt3.Z())));
203 aMaxPnt = SelectMgr_Vec3 (Max (aPnt1.X(), Max (aPnt2.X(), aPnt3.X())),
204 Max (aPnt1.Y(), Max (aPnt2.Y(), aPnt3.Y())),
205 Max (aPnt1.Z(), Max (aPnt2.Z(), aPnt3.Z())));
209 Standard_Integer aNodeIdx1 = myFreeEdges->Value (myFreeEdges->Lower() + aPrimIdx);
210 Standard_Integer aNodeIdx2 = myFreeEdges->Value (myFreeEdges->Lower() + aPrimIdx + 1);
211 gp_Pnt aNode1 = myTriangul->Nodes().Value (aNodeIdx1);
212 gp_Pnt aNode2 = myTriangul->Nodes().Value (aNodeIdx2);
214 aMinPnt = SelectMgr_Vec3 (Min (aNode1.X(), aNode2.X()),
215 Min (aNode1.Y(), aNode2.Y()),
216 Min (aNode1.Z(), aNode2.Z()));
217 aMaxPnt = SelectMgr_Vec3 (Max (aNode1.X(), aNode2.X()),
218 Max (aNode1.Y(), aNode2.Y()),
219 Max (aNode1.Z(), aNode2.Z()));
222 return Select3D_BndBox3d (aMinPnt, aMaxPnt);
225 //=======================================================================
227 // purpose : Returns geometry center of triangle/edge with index theIdx
228 // in array along the given axis theAxis
229 //=======================================================================
230 Standard_Real Select3D_SensitiveTriangulation::Center (const Standard_Integer theIdx,
231 const Standard_Integer theAxis) const
233 const Select3D_BndBox3d& aBox = Box (theIdx);
234 SelectMgr_Vec3 aCenter = (aBox.CornerMin () + aBox.CornerMax ()) * 0.5;
236 return theAxis == 0 ? aCenter.x() : (theAxis == 1 ? aCenter.y() : aCenter.z());
239 //=======================================================================
241 // purpose : Swaps items with indexes theIdx1 and theIdx2 in array
242 //=======================================================================
243 void Select3D_SensitiveTriangulation::Swap (const Standard_Integer theIdx1,
244 const Standard_Integer theIdx2)
246 Standard_Integer anElemIdx1 = myBVHPrimIndexes->Value (theIdx1);
247 Standard_Integer anElemIdx2 = myBVHPrimIndexes->Value (theIdx2);
249 myBVHPrimIndexes->ChangeValue (theIdx1) = anElemIdx2;
250 myBVHPrimIndexes->ChangeValue (theIdx2) = anElemIdx1;
253 //=======================================================================
254 // function : overlapsElement
255 // purpose : Checks whether the element with index theIdx overlaps the
256 // current selecting volume
257 //=======================================================================
258 Standard_Boolean Select3D_SensitiveTriangulation::overlapsElement (SelectBasics_SelectingVolumeManager& theMgr,
259 Standard_Integer theElemIdx,
260 Standard_Real& theMatchDepth)
262 const Standard_Integer& aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx);
264 if (mySensType == Select3D_TOS_BOUNDARY)
266 Standard_Integer aSegmStartIdx = myFreeEdges->Value (aPrimitiveIdx * 2 + 1);
267 Standard_Integer aSegmEndIdx = myFreeEdges->Value (aPrimitiveIdx * 2 + 2);
268 Handle(TColgp_HArray1OfPnt) anEdgePnts = new TColgp_HArray1OfPnt (1, 2);
269 gp_Pnt aSegmStart = myTriangul->Nodes().Value (aSegmStartIdx);
270 gp_Pnt aSegmEnd = myTriangul->Nodes().Value (aSegmEndIdx);
271 anEdgePnts->SetValue (1, aSegmStart);
272 anEdgePnts->SetValue (2, aSegmEnd);
273 Standard_Boolean isMatched = theMgr.Overlaps (anEdgePnts, Select3D_TOS_BOUNDARY, theMatchDepth);
274 anEdgePnts.Nullify();
279 const Poly_Array1OfTriangle& aTriangles = myTriangul->Triangles();
280 Standard_Integer aNode1, aNode2, aNode3;
281 aTriangles (aPrimitiveIdx + 1).Get (aNode1, aNode2, aNode3);
282 gp_Pnt aPnt1 = myTriangul->Nodes().Value (aNode1);
283 gp_Pnt aPnt2 = myTriangul->Nodes().Value (aNode2);
284 gp_Pnt aPnt3 = myTriangul->Nodes().Value (aNode3);
285 return theMgr.Overlaps (aPnt1, aPnt2, aPnt3, Select3D_TOS_INTERIOR, theMatchDepth);
289 //==================================================
290 // Function : elementIsInside
292 //==================================================
293 Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
294 const Standard_Integer theElemIdx)
296 const Standard_Integer& aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx);
298 if (mySensType == Select3D_TOS_BOUNDARY)
300 gp_Pnt aSegmPnt1 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 1));
301 gp_Pnt aSegmPnt2 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 2));
303 return theMgr.Overlaps (aSegmPnt1) && theMgr.Overlaps (aSegmPnt2);
307 Standard_Integer aNode1;
308 Standard_Integer aNode2;
309 Standard_Integer aNode3;
311 myTriangul->Triangles() (aPrimitiveIdx + 1).Get (aNode1, aNode2, aNode3);
313 gp_Pnt aPnt1 = myTriangul->Nodes().Value (aNode1);
314 gp_Pnt aPnt2 = myTriangul->Nodes().Value (aNode2);
315 gp_Pnt aPnt3 = myTriangul->Nodes().Value (aNode3);
317 return theMgr.Overlaps (aPnt1)
318 && theMgr.Overlaps (aPnt2)
319 && theMgr.Overlaps (aPnt3);
323 //=======================================================================
324 // function : distanceToCOG
325 // purpose : Calculates distance from the 3d projection of used-picked
326 // screen point to center of the geometry
327 //=======================================================================
328 Standard_Real Select3D_SensitiveTriangulation::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
330 return theMgr.DistToGeometryCenter (myCDG3D);
333 //=======================================================================
334 //function : GetConnected
336 //=======================================================================
337 Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangulation::GetConnected()
339 Standard_Boolean isInterior = mySensType == Select3D_TOS_INTERIOR;
340 Handle(Select3D_SensitiveTriangulation) aNewEntity =
341 new Select3D_SensitiveTriangulation (myOwnerId, myTriangul, myInitLocation, myFreeEdges, myCDG3D, isInterior);
346 //=======================================================================
347 // function : applyTransformation
348 // purpose : Inner function for transformation application to bounding
349 // box of the triangulation
350 //=======================================================================
351 Select3D_BndBox3d Select3D_SensitiveTriangulation::applyTransformation()
353 if (!HasInitLocation())
356 Select3D_BndBox3d aBndBox;
357 for (Standard_Integer aX = 0; aX <=1; ++aX)
359 for (Standard_Integer aY = 0; aY <=1; ++aY)
361 for (Standard_Integer aZ = 0; aZ <= 1; ++aZ)
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());
366 aVertex.Transform (myInitLocation.Transformation());
367 aBndBox.Add (Select3D_Vec3 (aVertex.X(), aVertex.Y(), aVertex.Z()));
375 //=======================================================================
376 // function : BoundingBox
377 // purpose : Returns bounding box of the triangulation. If location
378 // transformation is set, it will be applied
379 //=======================================================================
380 Select3D_BndBox3d Select3D_SensitiveTriangulation::BoundingBox()
382 if (myBndBox.IsValid())
383 return applyTransformation();
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)
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);
397 return applyTransformation();
400 //=======================================================================
401 // function : CenterOfGeometry
402 // purpose : Returns center of triangulation. If location transformation
403 // is set, it will be applied
404 //=======================================================================
405 gp_Pnt Select3D_SensitiveTriangulation::CenterOfGeometry() const
410 //=======================================================================
411 // function : NbSubElements
412 // purpose : Returns the amount of nodes in triangulation
413 //=======================================================================
414 Standard_Integer Select3D_SensitiveTriangulation::NbSubElements()
416 return myTriangul->Nodes().Length();
419 //=======================================================================
420 //function : HasInitLocation
422 //=======================================================================
423 Standard_Boolean Select3D_SensitiveTriangulation::HasInitLocation() const
425 return !myInitLocation.IsIdentity();
428 //=======================================================================
429 //function : InvInitLocation
431 //=======================================================================
432 gp_Trsf Select3D_SensitiveTriangulation::InvInitLocation() const
434 return myInvInitLocation;