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