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
24 IMPLEMENT_STANDARD_RTTIEXT(Select3D_InteriorSensitivePointSet,Select3D_SensitiveSet)
25
26 namespace {
27
28 // Internal class for creation of planar polygons
29 class Select3D_Plane
30 {
31 public:
32
Select3D_Plane()33 Select3D_Plane()
34 : myPlane (0.0),
35 myIsInitialized (Standard_False)
36 {}
37
Contains(const gp_Pnt & thePnt) const38 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
MakePlane(const gp_Pnt & thePnt1,const gp_Pnt & thePnt2,const gp_Pnt & thePnt3)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
Invalidate()66 void Invalidate()
67 {
68 myIsInitialized = Standard_False;
69 }
70
IsValid() const71 Standard_Boolean IsValid() const
72 {
73 return myIsInitialized;
74 }
75
76 private:
77 NCollection_Vec4<Standard_Real> myPlane;
78 Standard_Boolean myIsInitialized;
79 };
80
81 } // anonymous namespace
82
83
84 // =======================================================================
85 // function : Select3D_InteriorSensitivePointSet
86 // purpose : Splits the given point set thePoints onto planar convex
87 // polygons
88 // =======================================================================
Select3D_InteriorSensitivePointSet(const Handle (SelectMgr_EntityOwner)& theOwnerId,const TColgp_Array1OfPnt & thePoints)89 Select3D_InteriorSensitivePointSet::Select3D_InteriorSensitivePointSet (const Handle(SelectMgr_EntityOwner)& theOwnerId,
90 const TColgp_Array1OfPnt& thePoints)
91 : Select3D_SensitiveSet (theOwnerId)
92 {
93 Select3D_Plane aPlane;
94 Standard_Integer aLowerIdx = thePoints.Lower();
95 Standard_Integer anUpperIdx = thePoints.Upper();
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;
102 const gp_Pnt& aPnt3 = thePoints.Value (aPntIter);
103 aPntSum += aPnt3.XYZ();
104 SelectMgr_Vec3 aCurrPnt (aPnt3.X(), aPnt3.Y(), aPnt3.Z());
105 aBndBox.Add (aCurrPnt);
106 if (aPntIter - aLowerIdx >= 2)
107 {
108 aPnt1 = thePoints.Value (aPntIter - 2);
109 aPnt2 = thePoints.Value (aPntIter - 1);
110 }
111 if (aPntIter - aStartIdx == 2 && !aPlane.IsValid())
112 {
113 aPlane.MakePlane (aPnt1, aPnt2, aPnt3);
114 aStartIdx = aPntIter - 2;
115 anEndIdx = aPntIter;
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 }
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);
135 if (!aPlane.Contains (thePoints.Value (aPntIter)) || anAngle > Precision::Confusion())
136 {
137 // subtract 1 due to indexation from zero in sub-polygons
138 Standard_Integer anUpperBound = aPntIter - aStartIdx - 1;
139 Handle (TColgp_HArray1OfPnt) aPointsArray = new TColgp_HArray1OfPnt (0, anUpperBound);
140 for (Standard_Integer aIdx = aStartIdx; aIdx <= aStartIdx + anUpperBound; ++aIdx)
141 {
142 aPointsArray->SetValue (aIdx - aStartIdx, thePoints.Value (aIdx));
143 }
144 Handle(Select3D_SensitivePoly) aPlanarPolyg = new Select3D_SensitivePoly (theOwnerId,
145 aPointsArray,
146 Standard_True);
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 {
160 aPointsArray->SetValue (aIdx - aStartIdx, thePoints.Value (aIdx));
161 }
162 Handle(Select3D_SensitivePoly) aPlanarPolyg = new Select3D_SensitivePoly (theOwnerId,
163 aPointsArray,
164 Standard_True);
165 myPlanarPolygons.Append (aPlanarPolyg);
166 }
167 }
168 }
169 }
170
171 myCOG = aPntSum / thePoints.Length();
172 myBndBox = aBndBox;
173
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 }
179 }
180
181 // =======================================================================
182 // function : GetPoints
183 // purpose : Initializes the given array theHArrayOfPnt by 3d
184 // coordinates of vertices of the whole point set
185 // =======================================================================
GetPoints(Handle (TColgp_HArray1OfPnt)& theHArrayOfPnt)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 }
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 //=======================================================================
Size() const217 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 //=======================================================================
Box(const Standard_Integer theIdx) const227 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 //=======================================================================
Center(const Standard_Integer theIdx,const Standard_Integer theAxis) const238 Standard_Real Select3D_InteriorSensitivePointSet::Center (const Standard_Integer theIdx,
239 const Standard_Integer theAxis) const
240 {
241 const Standard_Integer aPolygIdx = myPolygonsIdxs->Value (theIdx);
242 const gp_Pnt aCOG = myPlanarPolygons.Value (aPolygIdx)->CenterOfGeometry();
243 return aCOG.Coord (theAxis - 1);
244 }
245
246 //=======================================================================
247 // function : Swap
248 // purpose : Swaps items with indexes theIdx1 and theIdx2 in the vector
249 //=======================================================================
Swap(const Standard_Integer theIdx1,const Standard_Integer theIdx2)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 :
263 // =======================================================================
overlapsElement(SelectBasics_PickResult & thePickResult,SelectBasics_SelectingVolumeManager & theMgr,Standard_Integer theElemIdx,Standard_Boolean)264 Standard_Boolean Select3D_InteriorSensitivePointSet::overlapsElement (SelectBasics_PickResult& thePickResult,
265 SelectBasics_SelectingVolumeManager& theMgr,
266 Standard_Integer theElemIdx,
267 Standard_Boolean )
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);
273 return theMgr.OverlapsPolygon (aPoints->Array1(), Select3D_TOS_INTERIOR, thePickResult);
274 }
275
276 // =======================================================================
277 // function : elementIsInside
278 // purpose :
279 // =======================================================================
elementIsInside(SelectBasics_SelectingVolumeManager & theMgr,Standard_Integer theElemIdx,Standard_Boolean theIsFullInside)280 Standard_Boolean Select3D_InteriorSensitivePointSet::elementIsInside (SelectBasics_SelectingVolumeManager& theMgr,
281 Standard_Integer theElemIdx,
282 Standard_Boolean theIsFullInside)
283 {
284 SelectBasics_PickResult aDummy;
285 return overlapsElement (aDummy, theMgr, theElemIdx, theIsFullInside);
286 }
287
288 // =======================================================================
289 // function : distanceToCOG
290 // purpose : Calculates distance from the 3d projection of used-picked
291 // screen point to center of the geometry
292 // =======================================================================
distanceToCOG(SelectBasics_SelectingVolumeManager & theMgr)293 Standard_Real Select3D_InteriorSensitivePointSet::distanceToCOG (SelectBasics_SelectingVolumeManager& theMgr)
294 {
295 return theMgr.DistToGeometryCenter (myCOG);
296 }
297
298 //=======================================================================
299 // function : BoundingBox
300 // purpose : Returns bounding box of the point set. If location
301 // transformation is set, it will be applied
302 //=======================================================================
BoundingBox()303 Select3D_BndBox3d Select3D_InteriorSensitivePointSet::BoundingBox()
304 {
305 return myBndBox;
306 }
307
308 //=======================================================================
309 // function : CenterOfGeometry
310 // purpose : Returns center of the point set. If location transformation
311 // is set, it will be applied
312 //=======================================================================
CenterOfGeometry() const313 gp_Pnt Select3D_InteriorSensitivePointSet::CenterOfGeometry() const
314 {
315 return myCOG;
316 }
317
318 //=======================================================================
319 // function : NbSubElements
320 // purpose : Returns the amount of points in set
321 //=======================================================================
NbSubElements() const322 Standard_Integer Select3D_InteriorSensitivePointSet::NbSubElements() const
323 {
324 return myPlanarPolygons.Length();
325 }
326
327 // =======================================================================
328 // function : DumpJson
329 // purpose :
330 // =======================================================================
DumpJson(Standard_OStream & theOStream,Standard_Integer theDepth) const331 void Select3D_InteriorSensitivePointSet::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
332 {
333 OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
334 OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Select3D_SensitiveSet)
335
336 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myBndBox)
337 }
338