0029938: Visualization - SelectMgr_ViewerSelector::PickedPoint() should return point...
[occt.git] / src / Select3D / Select3D_SensitivePoly.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <Select3D_SensitivePoly.hxx>
15
16 IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitivePoly,Select3D_SensitiveSet)
17
18 //==================================================
19 // Function: Select3D_SensitivePoly
20 // Purpose :
21 //==================================================
22 Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectBasics_EntityOwner)& theOwnerId,
23                                                 const TColgp_Array1OfPnt& thePoints,
24                                                 const Standard_Boolean theIsBVHEnabled)
25 : Select3D_SensitiveSet (theOwnerId),
26   myPolyg (thePoints.Upper() - thePoints.Lower() + 1)
27 {
28   Standard_Integer aLowerIdx = thePoints.Lower();
29   Standard_Integer anUpperIdx = thePoints.Upper();
30   gp_XYZ aPntSum (0.0, 0.0, 0.0);
31
32   Select3D_BndBox3d aBndBox;
33   for (Standard_Integer aIdx = aLowerIdx; aIdx <= anUpperIdx; ++aIdx)
34   {
35     aPntSum += thePoints.Value (aIdx).XYZ();
36     const SelectMgr_Vec3 aPnt (thePoints.Value (aIdx).X(),
37                                thePoints.Value (aIdx).Y(),
38                                thePoints.Value (aIdx).Z());
39     aBndBox.Add (aPnt);
40     myPolyg.SetPnt (aIdx - aLowerIdx, thePoints.Value (aIdx));
41   }
42
43   myBndBox = aBndBox;
44   myCOG = aPntSum / myPolyg.Size();
45
46   if (theIsBVHEnabled)
47   {
48     const Standard_Integer aPntsNum = myPolyg.Size();
49     mySegmentIndexes = new TColStd_HArray1OfInteger (0, aPntsNum - 2);
50     for (Standard_Integer aSegmIter = 0; aSegmIter < aPntsNum - 1; ++aSegmIter)
51     {
52       mySegmentIndexes->SetValue (aSegmIter, aSegmIter);
53     }
54   }
55
56   myIsComputed = Standard_True;
57 }
58
59 //==================================================
60 // Function: Select3D_SensitivePoly
61 // Purpose :
62 //==================================================
63 Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectBasics_EntityOwner)& theOwnerId,
64                                                 const Handle(TColgp_HArray1OfPnt)& thePoints,
65                                                 const Standard_Boolean theIsBVHEnabled)
66 : Select3D_SensitiveSet (theOwnerId),
67   myPolyg (thePoints->Upper() - thePoints->Lower() + 1)
68 {
69   Standard_Integer aLowerIdx = thePoints->Lower();
70   Standard_Integer anUpperIdx = thePoints->Upper();
71   gp_XYZ aPntSum (0.0, 0.0, 0.0);
72
73   Select3D_BndBox3d aBndBox;
74   for (Standard_Integer aIdx = aLowerIdx; aIdx <= anUpperIdx; ++aIdx)
75   {
76     aPntSum += thePoints->Value (aIdx).XYZ();
77     const SelectMgr_Vec3 aPnt (thePoints->Value (aIdx).X(),
78                                thePoints->Value (aIdx).Y(),
79                                thePoints->Value (aIdx).Z());
80     aBndBox.Add (aPnt);
81     myPolyg.SetPnt (aIdx - aLowerIdx, thePoints->Value (aIdx));
82   }
83
84   myBndBox = aBndBox;
85   myCOG = aPntSum / myPolyg.Size();
86
87   if (theIsBVHEnabled)
88   {
89     const Standard_Integer aPntsNum = myPolyg.Size();
90     mySegmentIndexes = new TColStd_HArray1OfInteger (0, aPntsNum - 2);
91     for (Standard_Integer aSegmIter = 0; aSegmIter < aPntsNum - 1; ++aSegmIter)
92     {
93       mySegmentIndexes->SetValue (aSegmIter, aSegmIter);
94     }
95   }
96
97   myIsComputed = Standard_True;
98 }
99
100 //==================================================
101 // Function: Creation
102 // Purpose :
103 //==================================================
104 Select3D_SensitivePoly::Select3D_SensitivePoly (const Handle(SelectBasics_EntityOwner)& theOwnerId,
105                                                 const Standard_Boolean theIsBVHEnabled,
106                                                 const Standard_Integer theNbPnts)
107 : Select3D_SensitiveSet (theOwnerId),
108   myPolyg (theNbPnts)
109 {
110   if (theIsBVHEnabled)
111   {
112     mySegmentIndexes = new TColStd_HArray1OfInteger (0, theNbPnts - 2);
113     for (Standard_Integer aIdx = 0; aIdx < theNbPnts - 1; ++aIdx)
114     {
115       mySegmentIndexes->SetValue (aIdx, aIdx);
116     }
117   }
118   myCOG = gp_Pnt (RealLast(), RealLast(), RealLast());
119   myIsComputed = Standard_False;
120 }
121
122 //==================================================
123 // function : BoundingBox
124 // purpose  : Returns bounding box of a polygon. If location
125 //            transformation is set, it will be applied
126 //==================================================
127 Select3D_BndBox3d Select3D_SensitivePoly::BoundingBox()
128 {
129   if (myBndBox.IsValid())
130     return myBndBox;
131
132   Select3D_BndBox3d aBndBox;
133   for (Standard_Integer aPntIter = 0; aPntIter < myPolyg.Size(); ++aPntIter)
134   {
135     SelectMgr_Vec3 aPnt (myPolyg.Pnt (aPntIter).x,
136                          myPolyg.Pnt (aPntIter).y,
137                          myPolyg.Pnt (aPntIter).z);
138     aBndBox.Add (aPnt);
139   }
140
141   myBndBox = aBndBox;
142
143   return myBndBox;
144 }
145
146 //==================================================
147 // Function: Size
148 // Purpose : Returns the amount of segments of
149 //           the poly
150 //==================================================
151 Standard_Integer Select3D_SensitivePoly::Size() const
152 {
153   if (!mySegmentIndexes.IsNull())
154     return mySegmentIndexes->Length();
155
156   return -1;
157 }
158
159 //==================================================
160 // Function: Box
161 // Purpose : Returns bounding box of segment with
162 //           index theIdx
163 //==================================================
164 Select3D_BndBox3d Select3D_SensitivePoly::Box (const Standard_Integer theIdx) const
165 {
166   if (mySegmentIndexes.IsNull())
167     return Select3D_BndBox3d (SelectMgr_Vec3 (RealLast()));
168
169   const Standard_Integer aSegmentIdx = mySegmentIndexes->Value (theIdx);
170   gp_Pnt aPnt1 = myPolyg.Pnt3d (aSegmentIdx);
171   gp_Pnt aPnt2 = myPolyg.Pnt3d (aSegmentIdx + 1);
172
173   const SelectMgr_Vec3 aMinPnt (Min (aPnt1.X(), aPnt2.X()),
174                                 Min (aPnt1.Y(), aPnt2.Y()),
175                                 Min (aPnt1.Z(), aPnt2.Z()));
176   const SelectMgr_Vec3 aMaxPnt (Max (aPnt1.X(), aPnt2.X()),
177                                 Max (aPnt1.Y(), aPnt2.Y()),
178                                 Max (aPnt1.Z(), aPnt2.Z()));
179
180   return Select3D_BndBox3d (aMinPnt, aMaxPnt);
181 }
182
183 //==================================================
184 // Function: Center
185 // Purpose : Returns geometry center of sensitive
186 //           entity index theIdx in the vector along
187 //           the given axis theAxis
188 //==================================================
189 Standard_Real Select3D_SensitivePoly::Center (const Standard_Integer theIdx,
190                                               const Standard_Integer theAxis) const
191 {
192   if (mySegmentIndexes.IsNull())
193     return RealLast();
194
195   const Select3D_BndBox3d aBndBox = Box (theIdx);
196   const SelectMgr_Vec3 aCenter = (aBndBox.CornerMin() + aBndBox.CornerMax()) * 0.5;
197   return theAxis == 0 ? aCenter.x() : (theAxis == 1 ? aCenter.y() : aCenter.z());
198 }
199
200 //==================================================
201 // Function: Swap
202 // Purpose : Swaps items with indexes theIdx1 and
203 //           theIdx2 in the vector
204 //==================================================
205 void Select3D_SensitivePoly::Swap (const Standard_Integer theIdx1,
206                                    const Standard_Integer theIdx2)
207 {
208   if (mySegmentIndexes.IsNull())
209     return;
210
211   const Standard_Integer aSegmentIdx1 = mySegmentIndexes->Value (theIdx1);
212   const Standard_Integer aSegmentIdx2 = mySegmentIndexes->Value (theIdx2);
213   mySegmentIndexes->ChangeValue (theIdx1) = aSegmentIdx2;
214   mySegmentIndexes->ChangeValue (theIdx2) = aSegmentIdx1;
215 }
216
217 //==================================================
218 // Function: overlapsElement
219 // Purpose : Checks whether the segment with index
220 //           theIdx overlaps the current selecting
221 //           volume
222 //==================================================
223 Standard_Boolean Select3D_SensitivePoly::overlapsElement (SelectBasics_SelectingVolumeManager& theMgr,
224                                                           Standard_Integer theElemIdx,
225                                                           SelectBasics_PickResult& thePickResult)
226 {
227   if (mySegmentIndexes.IsNull())
228     return Standard_False;
229
230   const Standard_Integer aSegmentIdx = mySegmentIndexes->Value (theElemIdx);
231   gp_Pnt aPnt1 = myPolyg.Pnt3d (aSegmentIdx);
232   gp_Pnt aPnt2 = myPolyg.Pnt3d (aSegmentIdx + 1);
233
234   return theMgr.Overlaps (aPnt1, aPnt2, thePickResult);
235 }
236
237 //==================================================
238 // Function : elementIsInside
239 // Purpose  :
240 //==================================================
241 Standard_Boolean Select3D_SensitivePoly::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
242                                                           const Standard_Integer               theElemIdx)
243 {
244   const Standard_Integer aSegmentIdx = mySegmentIndexes->Value (theElemIdx);
245
246   return theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 0))
247       && theMgr.Overlaps (myPolyg.Pnt3d (aSegmentIdx + 1));
248 }
249
250 //==================================================
251 // Function: distanceToCOG
252 // Purpose : Calculates distance from the 3d
253 //           projection of used-picked screen point
254 //           to center of the geometry
255 //==================================================
256 Standard_Real Select3D_SensitivePoly::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
257 {
258   if (!myIsComputed)
259   {
260     gp_XYZ aCenter (0.0, 0.0, 0.0);
261     for (Standard_Integer aIdx = 0; aIdx < myPolyg.Size(); ++aIdx)
262     {
263       aCenter += myPolyg.Pnt (aIdx);
264     }
265     myCOG = aCenter / myPolyg.Size();
266     myIsComputed = Standard_True;
267   }
268
269   return theMgr.DistToGeometryCenter (myCOG);
270 }
271
272 //==================================================
273 // Function: NbSubElements
274 // Purpose : Returns the amount of segments in poly
275 //==================================================
276 Standard_Integer Select3D_SensitivePoly::NbSubElements()
277 {
278   return myPolyg.Size();
279 }
280
281 //==================================================
282 // Function: CenterOfGeometry
283 // Purpose : Returns center of the point set. If
284 //           location transformation is set, it will
285 //           be applied
286 //==================================================
287 gp_Pnt Select3D_SensitivePoly::CenterOfGeometry() const
288 {
289   if (!myIsComputed)
290   {
291     gp_XYZ aCenter (0.0, 0.0, 0.0);
292     for (Standard_Integer aIdx = 0; aIdx < myPolyg.Size(); ++aIdx)
293     {
294       aCenter += myPolyg.Pnt (aIdx);
295     }
296     myCOG = aCenter / myPolyg.Size();
297     myIsComputed = Standard_True;
298   }
299
300   return myCOG;
301 }