f751596e |
1 | // Created on: 2014-08-15 |
2 | // Created by: Varvara POSKONINA |
3 | // Copyright (c) 2005-2014 OPEN CASCADE SAS |
4 | // |
5 | // This file is part of Open CASCADE Technology software library. |
6 | // |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
12 | // |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
15 | |
16 | #include <gp_Pnt.hxx> |
17 | #include <gp_XYZ.hxx> |
18 | |
19 | #include <TColgp_Array1OfPnt.hxx> |
20 | #include <TColgp_HArray1OfPnt.hxx> |
21 | |
22 | #include <Select3D_InteriorSensitivePointSet.hxx> |
23 | |
92efcf78 |
24 | IMPLEMENT_STANDARD_RTTIEXT(Select3D_InteriorSensitivePointSet,Select3D_SensitiveSet) |
25 | |
bf3977c9 |
26 | namespace { |
27 | |
f751596e |
28 | // Internal class for creation of planar polygons |
29 | class Select3D_Plane |
30 | { |
31 | public: |
32 | |
33 | Select3D_Plane() |
34 | : myPlane (0.0), |
35 | myIsInitialized (Standard_False) |
36 | {} |
37 | |
38 | Standard_Boolean Contains (const gp_Pnt& thePnt) const |
39 | { |
40 | if (!myIsInitialized) |
41 | return Standard_False; |
42 | |
43 | Standard_Real aRes = myPlane.x() * thePnt.X() + |
44 | myPlane.y() * thePnt.Y() + |
45 | myPlane.z() * thePnt.Z() + |
46 | myPlane.w(); |
47 | |
48 | if (aRes < Precision::Confusion()) |
49 | return Standard_True; |
50 | |
51 | return Standard_False; |
52 | } |
53 | |
54 | void MakePlane (const gp_Pnt& thePnt1, |
55 | const gp_Pnt& thePnt2, |
56 | const gp_Pnt& thePnt3) |
57 | { |
58 | const gp_XYZ& aVec1 = thePnt2.XYZ() - thePnt1.XYZ(); |
59 | const gp_XYZ& aVec2 = thePnt3.XYZ() - thePnt1.XYZ(); |
60 | const gp_XYZ& aDir = aVec1.Crossed (aVec2); |
61 | Standard_Real aD = aDir.Dot (thePnt1.XYZ().Reversed()); |
62 | myPlane = NCollection_Vec4<Standard_Real> (aDir.X(), aDir.Y(), aDir.Z(), aD); |
63 | myIsInitialized = Standard_True; |
64 | } |
65 | |
66 | void Invalidate() |
67 | { |
68 | myIsInitialized = Standard_False; |
69 | } |
70 | |
71 | Standard_Boolean IsValid() const |
72 | { |
73 | return myIsInitialized; |
74 | } |
75 | |
76 | private: |
77 | NCollection_Vec4<Standard_Real> myPlane; |
78 | Standard_Boolean myIsInitialized; |
79 | }; |
80 | |
bf3977c9 |
81 | } // anonymous namespace |
82 | |
bf3977c9 |
83 | |
f751596e |
84 | // ======================================================================= |
85 | // function : Select3D_InteriorSensitivePointSet |
86 | // purpose : Splits the given point set thePoints onto planar convex |
87 | // polygons |
88 | // ======================================================================= |
89 | Select3D_InteriorSensitivePointSet::Select3D_InteriorSensitivePointSet (const Handle(SelectBasics_EntityOwner)& theOwnerId, |
90 | const TColgp_Array1OfPnt& thePoints) |
91 | : Select3D_SensitiveSet (theOwnerId) |
92 | { |
93 | Select3D_Plane aPlane; |
f751596e |
94 | Standard_Integer aLowerIdx = thePoints.Lower(); |
95 | Standard_Integer anUpperIdx = thePoints.Upper(); |
f751596e |
96 | Standard_Integer aStartIdx = aLowerIdx, anEndIdx = 0; |
97 | Select3D_BndBox3d aBndBox; |
98 | gp_XYZ aPntSum (0.0, 0.0, 0.0); |
99 | for (Standard_Integer aPntIter = aLowerIdx; aPntIter <= anUpperIdx; ++aPntIter) |
100 | { |
101 | gp_Pnt aPnt1, aPnt2; |
1c22cc2d |
102 | const gp_Pnt& aPnt3 = thePoints.Value (aPntIter); |
f751596e |
103 | aPntSum += aPnt3.XYZ(); |
104 | SelectMgr_Vec3 aCurrPnt (aPnt3.X(), aPnt3.Y(), aPnt3.Z()); |
105 | aBndBox.Add (aCurrPnt); |
106 | if (aPntIter - aLowerIdx >= 2) |
107 | { |
1c22cc2d |
108 | aPnt1 = thePoints.Value (aPntIter - 2); |
109 | aPnt2 = thePoints.Value (aPntIter - 1); |
f751596e |
110 | } |
111 | if (aPntIter - aStartIdx == 2 && !aPlane.IsValid()) |
112 | { |
113 | aPlane.MakePlane (aPnt1, aPnt2, aPnt3); |
114 | aStartIdx = aPntIter - 2; |
115 | anEndIdx = aPntIter; |
1c22cc2d |
116 | |
117 | if (anEndIdx == anUpperIdx) |
118 | { |
119 | Handle (TColgp_HArray1OfPnt) aPointsArray = new TColgp_HArray1OfPnt (0, anEndIdx - aStartIdx); |
120 | for (Standard_Integer aIdx = aStartIdx; aIdx <= anEndIdx; ++aIdx) |
121 | { |
122 | aPointsArray->SetValue (aIdx - aStartIdx, thePoints.Value(aIdx)); |
123 | } |
124 | Handle(Select3D_SensitivePoly) aPlanarPolyg = new Select3D_SensitivePoly (theOwnerId, |
125 | aPointsArray, |
126 | Standard_False); |
127 | myPlanarPolygons.Append (aPlanarPolyg); |
128 | } |
f751596e |
129 | } |
130 | else if (aPlane.IsValid()) |
131 | { |
132 | const gp_XYZ& aVec1 = aPnt1.XYZ() - aPnt2.XYZ(); |
133 | const gp_XYZ& aVec2 = aPnt3.XYZ() - aPnt2.XYZ(); |
134 | Standard_Real anAngle = aVec1.Dot (aVec2); |
1c22cc2d |
135 | if (!aPlane.Contains (thePoints.Value (aPntIter)) || anAngle > Precision::Confusion()) |
f751596e |
136 | { |
7bb2b829 |
137 | // subtract 1 due to indexation from zero in sub-polygons |
138 | Standard_Integer anUpperBound = aPntIter - aStartIdx - 1; |
f751596e |
139 | Handle (TColgp_HArray1OfPnt) aPointsArray = new TColgp_HArray1OfPnt (0, anUpperBound); |
140 | for (Standard_Integer aIdx = aStartIdx; aIdx <= aStartIdx + anUpperBound; ++aIdx) |
141 | { |
1c22cc2d |
142 | aPointsArray->SetValue (aIdx - aStartIdx, thePoints.Value (aIdx)); |
f751596e |
143 | } |
144 | Handle(Select3D_SensitivePoly) aPlanarPolyg = new Select3D_SensitivePoly (theOwnerId, |
145 | aPointsArray, |
2157d6ac |
146 | Standard_True); |
f751596e |
147 | myPlanarPolygons.Append (aPlanarPolyg); |
148 | aStartIdx = aPntIter; |
149 | anEndIdx = aPntIter; |
150 | aPlane.Invalidate(); |
151 | } |
152 | else |
153 | { |
154 | anEndIdx++; |
155 | if (anEndIdx == anUpperIdx) |
156 | { |
157 | Handle (TColgp_HArray1OfPnt) aPointsArray = new TColgp_HArray1OfPnt (0, anEndIdx - aStartIdx); |
158 | for (Standard_Integer aIdx = aStartIdx; aIdx <= anEndIdx; ++aIdx) |
159 | { |
1c22cc2d |
160 | aPointsArray->SetValue (aIdx - aStartIdx, thePoints.Value (aIdx)); |
f751596e |
161 | } |
162 | Handle(Select3D_SensitivePoly) aPlanarPolyg = new Select3D_SensitivePoly (theOwnerId, |
163 | aPointsArray, |
2157d6ac |
164 | Standard_True); |
f751596e |
165 | myPlanarPolygons.Append (aPlanarPolyg); |
166 | } |
167 | } |
168 | } |
169 | } |
170 | |
1c22cc2d |
171 | myCOG = aPntSum / thePoints.Length(); |
172 | myBndBox = aBndBox; |
173 | |
f751596e |
174 | myPolygonsIdxs = new TColStd_HArray1OfInteger (0, myPlanarPolygons.Length() - 1); |
175 | for (Standard_Integer aIdx = 0; aIdx < myPlanarPolygons.Length(); ++aIdx) |
176 | { |
177 | myPolygonsIdxs->SetValue (aIdx, aIdx); |
178 | } |
f751596e |
179 | } |
180 | |
f751596e |
181 | // ======================================================================= |
182 | // function : GetPoints |
183 | // purpose : Initializes the given array theHArrayOfPnt by 3d |
184 | // coordinates of vertices of the whole point set |
185 | // ======================================================================= |
186 | void Select3D_InteriorSensitivePointSet::GetPoints (Handle(TColgp_HArray1OfPnt)& theHArrayOfPnt) |
187 | { |
188 | Standard_Integer aSize = 0; |
189 | for (Standard_Integer anIdx = 0; anIdx < myPlanarPolygons.Length(); ++anIdx) |
190 | { |
191 | const Handle(Select3D_SensitivePoly)& aPolygon = myPlanarPolygons.Value (anIdx); |
192 | aSize += aPolygon->NbSubElements(); |
193 | } |
f751596e |
194 | |
195 | theHArrayOfPnt = new TColgp_HArray1OfPnt (1, aSize); |
196 | Standard_Integer anOutputPntArrayIdx = 1; |
197 | |
198 | for (Standard_Integer aPolygIdx = 0; aPolygIdx < myPlanarPolygons.Length(); ++aPolygIdx) |
199 | { |
200 | const Handle(Select3D_SensitivePoly)& aPolygon = myPlanarPolygons.Value (aPolygIdx); |
201 | Handle(TColgp_HArray1OfPnt) aPoints; |
202 | aPolygon->Points3D (aPoints); |
203 | Standard_Integer anUpper = aPolygIdx < myPlanarPolygons.Length() - 1 ? aPoints->Upper() : aPoints->Upper() + 1; |
204 | for (Standard_Integer aPntIter = 1; aPntIter < anUpper; ++aPntIter) |
205 | { |
206 | theHArrayOfPnt->SetValue (anOutputPntArrayIdx, aPoints->Value (aPntIter)); |
207 | anOutputPntArrayIdx++; |
208 | } |
209 | aPoints.Nullify(); |
210 | } |
211 | } |
212 | |
213 | //======================================================================= |
214 | // function : Size |
215 | // purpose : Returns the length of vector of planar convex polygons |
216 | //======================================================================= |
217 | Standard_Integer Select3D_InteriorSensitivePointSet::Size() const |
218 | { |
219 | return myPlanarPolygons.Length(); |
220 | } |
221 | |
222 | //======================================================================= |
223 | // function : Box |
224 | // purpose : Returns bounding box of planar convex polygon with index |
225 | // theIdx |
226 | //======================================================================= |
227 | Select3D_BndBox3d Select3D_InteriorSensitivePointSet::Box (const Standard_Integer theIdx) const |
228 | { |
229 | Standard_Integer aPolygIdx = myPolygonsIdxs->Value (theIdx); |
230 | return myPlanarPolygons.Value (aPolygIdx)->BoundingBox(); |
231 | } |
232 | |
233 | //======================================================================= |
234 | // function : Center |
235 | // purpose : Returns geometry center of planar convex polygon with index |
236 | // theIdx in the vector along the given axis theAxis |
237 | //======================================================================= |
238 | Standard_Real Select3D_InteriorSensitivePointSet::Center (const Standard_Integer theIdx, |
239 | const Standard_Integer theAxis) const |
240 | { |
39b7b2a4 |
241 | const Standard_Integer aPolygIdx = myPolygonsIdxs->Value (theIdx); |
242 | const gp_Pnt aCOG = myPlanarPolygons.Value (aPolygIdx)->CenterOfGeometry(); |
243 | return aCOG.Coord (theAxis - 1); |
f751596e |
244 | } |
245 | |
246 | //======================================================================= |
247 | // function : Swap |
248 | // purpose : Swaps items with indexes theIdx1 and theIdx2 in the vector |
249 | //======================================================================= |
250 | void Select3D_InteriorSensitivePointSet::Swap (const Standard_Integer theIdx1, |
251 | const Standard_Integer theIdx2) |
252 | { |
253 | Standard_Integer aPolygIdx1 = myPolygonsIdxs->Value (theIdx1); |
254 | Standard_Integer aPolygIdx2 = myPolygonsIdxs->Value (theIdx2); |
255 | |
256 | myPolygonsIdxs->ChangeValue (theIdx1) = aPolygIdx2; |
257 | myPolygonsIdxs->ChangeValue (theIdx2) = aPolygIdx1; |
258 | } |
259 | |
260 | // ======================================================================= |
261 | // function : overlapsElement |
262 | // purpose : Checks whether the planar convex polygon with index theIdx |
263 | // in myPlanarPolygons overlaps the current selecting volume |
264 | // ======================================================================= |
265 | Standard_Boolean Select3D_InteriorSensitivePointSet::overlapsElement (SelectBasics_SelectingVolumeManager& theMgr, |
266 | Standard_Integer theElemIdx, |
17017555 |
267 | SelectBasics_PickResult& thePickResult) |
f751596e |
268 | { |
269 | Standard_Integer aPolygIdx = myPolygonsIdxs->Value (theElemIdx); |
270 | const Handle(Select3D_SensitivePoly)& aPolygon = myPlanarPolygons.Value (aPolygIdx); |
271 | Handle(TColgp_HArray1OfPnt) aPoints; |
272 | aPolygon->Points3D (aPoints); |
17017555 |
273 | return theMgr.Overlaps (aPoints, Select3D_TOS_INTERIOR, thePickResult); |
f751596e |
274 | } |
275 | |
2157d6ac |
276 | // ======================================================================= |
277 | // function : elementIsInside |
278 | // purpose : |
279 | // ======================================================================= |
280 | Standard_Boolean Select3D_InteriorSensitivePointSet::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr, |
281 | const Standard_Integer theElemIdx) |
282 | { |
17017555 |
283 | SelectBasics_PickResult aDummy; |
2157d6ac |
284 | return overlapsElement (theMgr, theElemIdx, aDummy); |
285 | } |
286 | |
f751596e |
287 | // ======================================================================= |
288 | // function : distanceToCOG |
289 | // purpose : Calculates distance from the 3d projection of used-picked |
290 | // screen point to center of the geometry |
291 | // ======================================================================= |
292 | Standard_Real Select3D_InteriorSensitivePointSet::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr) |
293 | { |
294 | return theMgr.DistToGeometryCenter (myCOG); |
295 | } |
296 | |
297 | //======================================================================= |
298 | // function : BoundingBox |
299 | // purpose : Returns bounding box of the point set. If location |
300 | // transformation is set, it will be applied |
301 | //======================================================================= |
302 | Select3D_BndBox3d Select3D_InteriorSensitivePointSet::BoundingBox() |
303 | { |
304 | return myBndBox; |
305 | } |
306 | |
307 | //======================================================================= |
308 | // function : CenterOfGeometry |
309 | // purpose : Returns center of the point set. If location transformation |
310 | // is set, it will be applied |
311 | //======================================================================= |
312 | gp_Pnt Select3D_InteriorSensitivePointSet::CenterOfGeometry() const |
313 | { |
314 | return myCOG; |
315 | } |
316 | |
f751596e |
317 | //======================================================================= |
318 | // function : NbSubElements |
319 | // purpose : Returns the amount of points in set |
320 | //======================================================================= |
321 | Standard_Integer Select3D_InteriorSensitivePointSet::NbSubElements() |
322 | { |
323 | return myPlanarPolygons.Length(); |
324 | } |