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.
17 #include <Select3D_SensitiveTriangulation.hxx>
20 #include <Poly_Connect.hxx>
21 #include <TColStd_Array1OfInteger.hxx>
22 #include <Select3D_SensitiveTriangle.hxx>
23 #include <Precision.hxx>
24 #include <Select3D_TypeOfSensitivity.hxx>
28 IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveTriangulation,Select3D_SensitiveSet)
32 static Standard_Integer NbOfFreeEdges (const Handle(Poly_Triangulation)& theTriangulation)
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++)
39 aPoly.Triangles (aTrgIdx, aTriangleNodes[0], aTriangleNodes[1], aTriangleNodes[2]);
40 for (Standard_Integer aNodeIdx = 0; aNodeIdx < 3; ++aNodeIdx)
42 if (aTriangleNodes[aNodeIdx] == 0)
52 //=======================================================================
53 //function : Select3D_SensitiveTriangulation
55 //=======================================================================
56 Select3D_SensitiveTriangulation::Select3D_SensitiveTriangulation (const Handle(SelectMgr_EntityOwner)& theOwnerId,
57 const Handle(Poly_Triangulation)& theTrg,
58 const TopLoc_Location& theInitLoc,
59 const Standard_Boolean theIsInterior)
60 : Select3D_SensitiveSet (theOwnerId),
62 myInitLocation (theInitLoc)
64 myInvInitLocation = myInitLocation.Transformation().Inverted();
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);
71 myPrimitivesNb = theIsInterior ? aNbTriangles : NbOfFreeEdges (theTrg);
72 myBVHPrimIndexes = new TColStd_HArray1OfInteger(0, myPrimitivesNb - 1);
73 TColStd_Array1OfInteger& aBVHPrimIdxs = myBVHPrimIndexes->ChangeArray1();
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++)
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++)
90 Standard_Integer aNextVert = (aVertIdx + 1) % 3;
91 if (aTriangle[aVertIdx] == 0)
93 aFreeEdges (anEdgeIdx) = aTrNodeIdx[aVertIdx];
94 aFreeEdges (anEdgeIdx+1) = aTrNodeIdx[aNextVert];
102 Standard_Integer aTrNodeIdx[3];
103 for (Standard_Integer aTrIdx = 1; aTrIdx <= aNbTriangles; aTrIdx++)
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;
109 if (aNbTriangles != 0)
110 aCenter /= aNbTriangles;
111 myCDG3D = gp_Pnt (aCenter);
114 for (Standard_Integer aNodeIdx = 1; aNodeIdx <= myTriangul->NbNodes(); ++aNodeIdx)
116 myBndBox.Add (SelectMgr_Vec3 (aNodes (aNodeIdx).X(),
117 aNodes (aNodeIdx).Y(),
118 aNodes (aNodeIdx).Z()));
123 for (Standard_Integer aTriangleIdx = 1; aTriangleIdx <= aNbTriangles; ++aTriangleIdx)
125 aBVHPrimIdxs (aTriangleIdx - 1) = aTriangleIdx - 1;
130 Standard_Integer aStartIdx = myFreeEdges->Lower();
131 Standard_Integer anEndIdx = myFreeEdges->Upper();
132 for (Standard_Integer aFreeEdgesIdx = aStartIdx; aFreeEdgesIdx <= anEndIdx; aFreeEdgesIdx += 2)
134 aBVHPrimIdxs ((aFreeEdgesIdx - aStartIdx) / 2) = (aFreeEdgesIdx - aStartIdx) / 2;
139 //=======================================================================
140 //function : Select3D_SensitiveTriangulation
142 //=======================================================================
143 Select3D_SensitiveTriangulation::Select3D_SensitiveTriangulation (const Handle(SelectMgr_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),
151 myInitLocation (theInitLoc),
153 myFreeEdges (theFreeEdges)
155 myInvInitLocation = myInitLocation.Transformation().Inverted();
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);
161 for (Standard_Integer aTriangleIdx = 1; aTriangleIdx <= myPrimitivesNb; ++aTriangleIdx)
163 myBVHPrimIndexes->SetValue (aTriangleIdx - 1, aTriangleIdx - 1);
168 Standard_Integer aStartIdx = myFreeEdges->Lower();
169 Standard_Integer anEndIdx = myFreeEdges->Upper();
170 for (Standard_Integer aFreeEdgesIdx = aStartIdx; aFreeEdgesIdx <= anEndIdx; aFreeEdgesIdx += 2)
172 myBVHPrimIndexes->SetValue ((aFreeEdgesIdx - aStartIdx) / 2, (aFreeEdgesIdx - aStartIdx) / 2);
177 //=======================================================================
179 // purpose : Returns the length of array of triangles or edges
180 //=======================================================================
181 Standard_Integer Select3D_SensitiveTriangulation::Size() const
183 return myPrimitivesNb;
186 //=======================================================================
188 // purpose : Returns bounding box of triangle/edge with index theIdx
189 //=======================================================================
190 Select3D_BndBox3d Select3D_SensitiveTriangulation::Box (const Standard_Integer theIdx) const
192 Standard_Integer aPrimIdx = myBVHPrimIndexes->Value (theIdx);
193 SelectMgr_Vec3 aMinPnt (RealLast());
194 SelectMgr_Vec3 aMaxPnt (RealFirst());
196 if (mySensType == Select3D_TOS_INTERIOR)
198 Standard_Integer aNode1, aNode2, aNode3;
199 myTriangul->Triangles() (aPrimIdx + 1).Get (aNode1, aNode2, aNode3);
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);
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())));
214 Standard_Integer aNodeIdx1 = myFreeEdges->Value (myFreeEdges->Lower() + aPrimIdx);
215 Standard_Integer aNodeIdx2 = myFreeEdges->Value (myFreeEdges->Lower() + aPrimIdx + 1);
216 const gp_Pnt& aNode1 = myTriangul->Nodes().Value (aNodeIdx1);
217 const gp_Pnt& aNode2 = myTriangul->Nodes().Value (aNodeIdx2);
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()));
227 return Select3D_BndBox3d (aMinPnt, aMaxPnt);
230 //=======================================================================
232 // purpose : Returns geometry center of triangle/edge with index theIdx
233 // in array along the given axis theAxis
234 //=======================================================================
235 Standard_Real Select3D_SensitiveTriangulation::Center (const Standard_Integer theIdx,
236 const Standard_Integer theAxis) const
238 const Select3D_BndBox3d& aBox = Box (theIdx);
239 const SelectMgr_Vec3 aCenter = (aBox.CornerMin () + aBox.CornerMax ()) * 0.5;
240 return aCenter[theAxis];
243 //=======================================================================
245 // purpose : Swaps items with indexes theIdx1 and theIdx2 in array
246 //=======================================================================
247 void Select3D_SensitiveTriangulation::Swap (const Standard_Integer theIdx1,
248 const Standard_Integer theIdx2)
250 Standard_Integer anElemIdx1 = myBVHPrimIndexes->Value (theIdx1);
251 Standard_Integer anElemIdx2 = myBVHPrimIndexes->Value (theIdx2);
253 myBVHPrimIndexes->ChangeValue (theIdx1) = anElemIdx2;
254 myBVHPrimIndexes->ChangeValue (theIdx2) = anElemIdx1;
257 //=======================================================================
258 // function : overlapsElement
259 // purpose : Checks whether the element with index theIdx overlaps the
260 // current selecting volume
261 //=======================================================================
262 Standard_Boolean Select3D_SensitiveTriangulation::overlapsElement (SelectBasics_PickResult& thePickResult,
263 SelectBasics_SelectingVolumeManager& theMgr,
264 Standard_Integer theElemIdx,
265 Standard_Boolean theIsFullInside)
269 return Standard_True;
272 const Standard_Integer aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx);
273 if (mySensType == Select3D_TOS_BOUNDARY)
275 Standard_Integer aSegmStartIdx = myFreeEdges->Value (aPrimitiveIdx * 2 + 1);
276 Standard_Integer aSegmEndIdx = myFreeEdges->Value (aPrimitiveIdx * 2 + 2);
278 const gp_Pnt anEdgePnts[2] =
280 myTriangul->Nodes().Value (aSegmStartIdx),
281 myTriangul->Nodes().Value (aSegmEndIdx)
283 TColgp_Array1OfPnt anEdgePntsArr (anEdgePnts[0], 1, 2);
284 Standard_Boolean isMatched = theMgr.Overlaps (anEdgePntsArr, Select3D_TOS_BOUNDARY, thePickResult);
289 const Poly_Array1OfTriangle& aTriangles = myTriangul->Triangles();
290 Standard_Integer aNode1, aNode2, aNode3;
291 aTriangles (aPrimitiveIdx + 1).Get (aNode1, aNode2, aNode3);
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);
299 //==================================================
300 // Function : elementIsInside
302 //==================================================
303 Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
304 Standard_Integer theElemIdx,
305 Standard_Boolean theIsFullInside)
309 return Standard_True;
312 const Standard_Integer aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx);
313 if (mySensType == Select3D_TOS_BOUNDARY)
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));
317 if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
319 SelectBasics_PickResult aDummy;
320 return theMgr.Overlaps (aSegmPnt1, aSegmPnt2, aDummy);
322 return theMgr.Overlaps (aSegmPnt1) && theMgr.Overlaps (aSegmPnt2);
326 Standard_Integer aNode1, aNode2, aNode3;
327 myTriangul->Triangles() (aPrimitiveIdx + 1).Get (aNode1, aNode2, aNode3);
329 const gp_Pnt& aPnt1 = myTriangul->Nodes().Value (aNode1);
330 const gp_Pnt& aPnt2 = myTriangul->Nodes().Value (aNode2);
331 const gp_Pnt& aPnt3 = myTriangul->Nodes().Value (aNode3);
332 if (theMgr.GetActiveSelectionType() == SelectBasics_SelectingVolumeManager::Polyline)
334 SelectBasics_PickResult aDummy;
335 return theMgr.Overlaps (aPnt1, aPnt2, aPnt3, mySensType, aDummy);
337 return theMgr.Overlaps (aPnt1)
338 && theMgr.Overlaps (aPnt2)
339 && theMgr.Overlaps (aPnt3);
343 //=======================================================================
344 // function : distanceToCOG
345 // purpose : Calculates distance from the 3d projection of used-picked
346 // screen point to center of the geometry
347 //=======================================================================
348 Standard_Real Select3D_SensitiveTriangulation::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
350 return theMgr.DistToGeometryCenter (myCDG3D);
353 //=======================================================================
354 //function : GetConnected
356 //=======================================================================
357 Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangulation::GetConnected()
359 Standard_Boolean isInterior = mySensType == Select3D_TOS_INTERIOR;
360 Handle(Select3D_SensitiveTriangulation) aNewEntity =
361 new Select3D_SensitiveTriangulation (myOwnerId, myTriangul, myInitLocation, myFreeEdges, myCDG3D, isInterior);
366 //=======================================================================
367 // function : applyTransformation
368 // purpose : Inner function for transformation application to bounding
369 // box of the triangulation
370 //=======================================================================
371 Select3D_BndBox3d Select3D_SensitiveTriangulation::applyTransformation()
373 if (!HasInitLocation())
376 Select3D_BndBox3d aBndBox;
377 for (Standard_Integer aX = 0; aX <=1; ++aX)
379 for (Standard_Integer aY = 0; aY <=1; ++aY)
381 for (Standard_Integer aZ = 0; aZ <= 1; ++aZ)
383 gp_Pnt aVertex = gp_Pnt (aX == 0 ? myBndBox.CornerMin().x() : myBndBox.CornerMax().x(),
384 aY == 0 ? myBndBox.CornerMin().y() : myBndBox.CornerMax().y(),
385 aZ == 0 ? myBndBox.CornerMin().z() : myBndBox.CornerMax().z());
386 aVertex.Transform (myInitLocation.Transformation());
387 aBndBox.Add (Select3D_Vec3 (aVertex.X(), aVertex.Y(), aVertex.Z()));
395 //=======================================================================
396 // function : BoundingBox
397 // purpose : Returns bounding box of the triangulation. If location
398 // transformation is set, it will be applied
399 //=======================================================================
400 Select3D_BndBox3d Select3D_SensitiveTriangulation::BoundingBox()
402 if (myBndBox.IsValid())
403 return applyTransformation();
405 const Standard_Integer aLower = myTriangul->Nodes().Lower();
406 const Standard_Integer anUpper = myTriangul->Nodes().Upper();
407 Select3D_BndBox3d aBndBox;
408 for (Standard_Integer aNodeIdx = aLower; aNodeIdx <= anUpper; ++aNodeIdx)
410 const gp_Pnt& aNode = myTriangul->Nodes().Value (aNodeIdx);
411 const SelectMgr_Vec3 aNodeTransf = SelectMgr_Vec3 (aNode.X(), aNode.Y(), aNode.Z());
412 aBndBox.Add (aNodeTransf);
417 return applyTransformation();
420 //=======================================================================
421 // function : CenterOfGeometry
422 // purpose : Returns center of triangulation. If location transformation
423 // is set, it will be applied
424 //=======================================================================
425 gp_Pnt Select3D_SensitiveTriangulation::CenterOfGeometry() const
430 //=======================================================================
431 // function : NbSubElements
432 // purpose : Returns the amount of nodes in triangulation
433 //=======================================================================
434 Standard_Integer Select3D_SensitiveTriangulation::NbSubElements() const
436 return myTriangul->Nodes().Length();
439 //=======================================================================
440 //function : HasInitLocation
442 //=======================================================================
443 Standard_Boolean Select3D_SensitiveTriangulation::HasInitLocation() const
445 return !myInitLocation.IsIdentity();
448 //=======================================================================
449 //function : InvInitLocation
451 //=======================================================================
452 gp_GTrsf Select3D_SensitiveTriangulation::InvInitLocation() const
454 return myInvInitLocation;
457 // =======================================================================
458 // function : DumpJson
460 // =======================================================================
461 void Select3D_SensitiveTriangulation::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
463 OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
464 OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Select3D_SensitiveSet)
466 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myTriangul.get())
467 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myInitLocation)
468 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, mySensType)
469 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPrimitivesNb)
470 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myBndBox)