0027232: Configuration - fix mblen missing building issue on Android
[occt.git] / src / Select3D / Select3D_SensitiveTriangulation.cxx
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
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <algorithm>
18
19 #include <Poly.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>
25
26 #include <Select3D_SensitiveTriangulation.hxx>
27
28
29 IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitiveTriangulation,Select3D_SensitiveSet)
30
31 static Standard_Integer NbOfFreeEdges (const Handle(Poly_Triangulation)& theTriangulation)
32 {
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++)
37   {
38     aPoly.Triangles (aTrgIdx, aTriangleNodes[0], aTriangleNodes[1], aTriangleNodes[2]);
39     for (Standard_Integer aNodeIdx = 0; aNodeIdx < 3; aNodeIdx++)
40       if (aTriangleNodes[aNodeIdx] == 0)
41         aNbFree++;
42   }
43   return aNbFree;
44 }
45
46 //=======================================================================
47 //function : Select3D_SensitiveTriangulation
48 //purpose  :
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),
55   myTriangul (theTrg),
56   myInitLocation (theInitLoc)
57 {
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);
64
65   myPrimitivesNb = theIsInterior ? aNbTriangles : NbOfFreeEdges (theTrg);
66   myBVHPrimIndexes = new TColStd_HArray1OfInteger(0, myPrimitivesNb - 1);
67   TColStd_Array1OfInteger& aBVHPrimIdxs = myBVHPrimIndexes->ChangeArray1();
68
69   if (!theIsInterior)
70   {
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++)
78     {
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++)
83       {
84         Standard_Integer aNextVert = (aVertIdx + 1) % 3;
85         if (aTriangle[aVertIdx] == 0)
86         {
87           aFreeEdges (anEdgeIdx)  = aTrNodeIdx[aVertIdx];
88           aFreeEdges (anEdgeIdx+1) = aTrNodeIdx[aNextVert];
89           anEdgeIdx += 2;
90         }
91       }
92     }
93   }
94   else
95   {
96     Standard_Integer aTrNodeIdx[3];
97     for (Standard_Integer aTrIdx = 1; aTrIdx <= aNbTriangles; aTrIdx++)
98     {
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;
101     }
102   }
103   if (aNbTriangles != 0)
104     aCenter /= aNbTriangles;
105   myCDG3D = gp_Pnt (aCenter);
106
107   myBndBox.Clear();
108   for (Standard_Integer aNodeIdx = 1; aNodeIdx <= myTriangul->NbNodes(); ++aNodeIdx)
109   {
110     myBndBox.Add (SelectMgr_Vec3 (aNodes (aNodeIdx).X(),
111                                   aNodes (aNodeIdx).Y(),
112                                   aNodes (aNodeIdx).Z()));
113   }
114
115   if (theIsInterior)
116   {
117     for (Standard_Integer aTriangleIdx = 1; aTriangleIdx <= aNbTriangles; ++aTriangleIdx)
118     {
119       aBVHPrimIdxs (aTriangleIdx - 1) = aTriangleIdx - 1;
120     }
121   }
122   else
123   {
124     Standard_Integer aStartIdx = myFreeEdges->Lower();
125     Standard_Integer anEndIdx = myFreeEdges->Upper();
126     for (Standard_Integer aFreeEdgesIdx = aStartIdx; aFreeEdgesIdx <= anEndIdx; aFreeEdgesIdx += 2)
127     {
128       aBVHPrimIdxs ((aFreeEdgesIdx - aStartIdx) / 2) = (aFreeEdgesIdx - aStartIdx) / 2;
129     }
130   }
131 }
132
133
134 //=======================================================================
135 //function : Select3D_SensitiveTriangulation
136 //purpose  :
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),
145   myTriangul (theTrg),
146   myInitLocation (theInitLoc),
147   myCDG3D (theCOG),
148   myFreeEdges (theFreeEdges)
149 {
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);
154   if (theIsInterior)
155   {
156     for (Standard_Integer aTriangleIdx = 1; aTriangleIdx <= myPrimitivesNb; ++aTriangleIdx)
157     {
158       myBVHPrimIndexes->SetValue (aTriangleIdx - 1, aTriangleIdx - 1);
159     }
160   }
161   else
162   {
163     Standard_Integer aStartIdx = myFreeEdges->Lower();
164     Standard_Integer anEndIdx = myFreeEdges->Upper();
165     for (Standard_Integer aFreeEdgesIdx = aStartIdx; aFreeEdgesIdx <= anEndIdx; aFreeEdgesIdx += 2)
166     {
167       myBVHPrimIndexes->SetValue ((aFreeEdgesIdx - aStartIdx) / 2, (aFreeEdgesIdx - aStartIdx) / 2);
168     }
169   }
170 }
171
172 //=======================================================================
173 // function : Size
174 // purpose  : Returns the length of array of triangles or edges
175 //=======================================================================
176 Standard_Integer Select3D_SensitiveTriangulation::Size() const
177 {
178   return myPrimitivesNb;
179 }
180
181 //=======================================================================
182 // function : Box
183 // purpose  : Returns bounding box of triangle/edge with index theIdx
184 //=======================================================================
185 Select3D_BndBox3d Select3D_SensitiveTriangulation::Box (const Standard_Integer theIdx) const
186 {
187   Standard_Integer aPrimIdx = myBVHPrimIndexes->Value (theIdx);
188   SelectMgr_Vec3 aMinPnt (RealLast());
189   SelectMgr_Vec3 aMaxPnt (RealFirst());
190
191   if (mySensType == Select3D_TOS_INTERIOR)
192   {
193     Standard_Integer aNode1, aNode2, aNode3;
194     myTriangul->Triangles() (aPrimIdx + 1).Get (aNode1, aNode2, aNode3);
195
196     gp_Pnt aPnt1 = myTriangul->Nodes().Value (aNode1);
197     gp_Pnt aPnt2 = myTriangul->Nodes().Value (aNode2);
198     gp_Pnt aPnt3 = myTriangul->Nodes().Value (aNode3);
199
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())));
206   }
207   else
208   {
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);
213
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()));
220   }
221
222   return Select3D_BndBox3d (aMinPnt, aMaxPnt);
223 }
224
225 //=======================================================================
226 // function : Center
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
232 {
233   const Select3D_BndBox3d& aBox = Box (theIdx);
234   SelectMgr_Vec3 aCenter = (aBox.CornerMin () + aBox.CornerMax ()) * 0.5;
235   
236   return theAxis == 0 ? aCenter.x() : (theAxis == 1 ? aCenter.y() : aCenter.z());
237 }
238
239 //=======================================================================
240 // function : Swap
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)
245 {
246   Standard_Integer anElemIdx1 = myBVHPrimIndexes->Value (theIdx1);
247   Standard_Integer anElemIdx2 = myBVHPrimIndexes->Value (theIdx2);
248
249   myBVHPrimIndexes->ChangeValue (theIdx1) = anElemIdx2;
250   myBVHPrimIndexes->ChangeValue (theIdx2) = anElemIdx1;
251 }
252
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)
261 {
262   const Standard_Integer& aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx);
263
264   if (mySensType == Select3D_TOS_BOUNDARY)
265   {
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();
275     return isMatched;
276   }
277   else
278   {
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);
286   }
287 }
288
289 //==================================================
290 // Function : elementIsInside
291 // Purpose  :
292 //==================================================
293 Standard_Boolean Select3D_SensitiveTriangulation::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
294                                                                    const Standard_Integer               theElemIdx)
295 {
296   const Standard_Integer& aPrimitiveIdx = myBVHPrimIndexes->Value (theElemIdx);
297
298   if (mySensType == Select3D_TOS_BOUNDARY)
299   {
300     gp_Pnt aSegmPnt1 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 1));
301     gp_Pnt aSegmPnt2 = myTriangul->Nodes().Value (myFreeEdges->Value (aPrimitiveIdx * 2 + 2));
302
303     return theMgr.Overlaps (aSegmPnt1) && theMgr.Overlaps (aSegmPnt2);
304   }
305   else
306   {
307     Standard_Integer aNode1;
308     Standard_Integer aNode2;
309     Standard_Integer aNode3;
310
311     myTriangul->Triangles() (aPrimitiveIdx + 1).Get (aNode1, aNode2, aNode3);
312
313     gp_Pnt aPnt1 = myTriangul->Nodes().Value (aNode1);
314     gp_Pnt aPnt2 = myTriangul->Nodes().Value (aNode2);
315     gp_Pnt aPnt3 = myTriangul->Nodes().Value (aNode3);
316
317     return theMgr.Overlaps (aPnt1)
318         && theMgr.Overlaps (aPnt2)
319         && theMgr.Overlaps (aPnt3);
320   }
321 }
322
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)
329 {
330   return theMgr.DistToGeometryCenter (myCDG3D);
331 }
332
333 //=======================================================================
334 //function : GetConnected
335 //purpose  :
336 //=======================================================================
337 Handle(Select3D_SensitiveEntity) Select3D_SensitiveTriangulation::GetConnected()
338 {
339   Standard_Boolean isInterior = mySensType == Select3D_TOS_INTERIOR;
340   Handle(Select3D_SensitiveTriangulation) aNewEntity =
341     new Select3D_SensitiveTriangulation (myOwnerId, myTriangul, myInitLocation, myFreeEdges, myCDG3D, isInterior);
342
343   return aNewEntity;
344 }
345
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()
352 {
353   if (!HasInitLocation())
354     return myBndBox;
355
356   Select3D_BndBox3d aBndBox;
357   for (Standard_Integer aX = 0; aX <=1; ++aX)
358   {
359     for (Standard_Integer aY = 0; aY <=1; ++aY)
360     {
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());
366         aVertex.Transform (myInitLocation.Transformation());
367         aBndBox.Add (Select3D_Vec3 (aVertex.X(), aVertex.Y(), aVertex.Z()));
368       }
369     }
370   }
371
372   return aBndBox;
373 }
374
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()
381 {
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)
389   {
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);
393   }
394
395   myBndBox = aBndBox;
396
397   return applyTransformation();
398 }
399
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
406 {
407   return myCDG3D;
408 }
409
410 //=======================================================================
411 // function : NbSubElements
412 // purpose  : Returns the amount of nodes in triangulation
413 //=======================================================================
414 Standard_Integer Select3D_SensitiveTriangulation::NbSubElements()
415 {
416   return myTriangul->Nodes().Length();
417 }
418
419 //=======================================================================
420 //function : HasInitLocation
421 //purpose  :
422 //=======================================================================
423 Standard_Boolean Select3D_SensitiveTriangulation::HasInitLocation() const
424 {
425   return !myInitLocation.IsIdentity();
426 }
427
428 //=======================================================================
429 //function : InvInitLocation
430 //purpose  :
431 //=======================================================================
432 gp_Trsf Select3D_SensitiveTriangulation::InvInitLocation() const
433 {
434   return myInvInitLocation;
435 }