f751596e |
1 | // Created on: 2014-11-21 |
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 <SelectMgr_TriangularFrustum.hxx> |
17 | |
92efcf78 |
18 | IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_TriangularFrustum,Standard_Transient) |
19 | |
f751596e |
20 | SelectMgr_TriangularFrustum::~SelectMgr_TriangularFrustum() |
21 | { |
22 | Clear(); |
23 | } |
24 | |
2157d6ac |
25 | namespace |
26 | { |
3bf9a45f |
27 | void computeFrustumNormals (const gp_Vec* theEdges, gp_Vec* theNormals) |
2157d6ac |
28 | { |
29 | // V0V1 |
d4507e82 |
30 | theNormals[0] = theEdges[0].Crossed (theEdges[3]); |
2157d6ac |
31 | // V1V2 |
d4507e82 |
32 | theNormals[1] = theEdges[1].Crossed (theEdges[4]); |
2157d6ac |
33 | // V0V2 |
d4507e82 |
34 | theNormals[2] = theEdges[0].Crossed (theEdges[5]); |
2157d6ac |
35 | // Near |
d4507e82 |
36 | theNormals[3] = theEdges[3].Crossed (theEdges[4]); |
2157d6ac |
37 | // Far |
3bf9a45f |
38 | theNormals[4] = -theNormals[3]; |
2157d6ac |
39 | } |
40 | } |
41 | |
3bf9a45f |
42 | // ======================================================================= |
43 | // function : cacheVertexProjections |
44 | // purpose : Caches projection of frustum's vertices onto its plane directions |
45 | // and {i, j, k} |
46 | // ======================================================================= |
099f3513 |
47 | void SelectMgr_TriangularFrustum::cacheVertexProjections (SelectMgr_TriangularFrustum* theFrustum) const |
f751596e |
48 | { |
f751596e |
49 | for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 5; ++aPlaneIdx) |
50 | { |
51 | Standard_Real aMax = -DBL_MAX; |
52 | Standard_Real aMin = DBL_MAX; |
3bf9a45f |
53 | const gp_XYZ& aPlane = theFrustum->myPlanes[aPlaneIdx].XYZ(); |
f751596e |
54 | for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx) |
55 | { |
3bf9a45f |
56 | Standard_Real aProjection = aPlane.Dot (theFrustum->myVertices[aVertIdx].XYZ()); |
f751596e |
57 | aMax = Max (aMax, aProjection); |
58 | aMin = Min (aMin, aProjection); |
59 | } |
3bf9a45f |
60 | theFrustum->myMaxVertsProjections[aPlaneIdx] = aMax; |
61 | theFrustum->myMinVertsProjections[aPlaneIdx] = aMin; |
f751596e |
62 | } |
63 | |
f751596e |
64 | for (Standard_Integer aDim = 0; aDim < 3; ++aDim) |
65 | { |
66 | Standard_Real aMax = -DBL_MAX; |
67 | Standard_Real aMin = DBL_MAX; |
68 | for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx) |
69 | { |
3bf9a45f |
70 | Standard_Real aProjection = theFrustum->myVertices[aVertIdx].XYZ().GetData()[aDim]; |
f751596e |
71 | aMax = Max (aMax, aProjection); |
72 | aMin = Min (aMin, aProjection); |
73 | } |
3bf9a45f |
74 | theFrustum->myMaxOrthoVertsProjections[aDim] = aMax; |
75 | theFrustum->myMinOrthoVertsProjections[aDim] = aMin; |
f751596e |
76 | } |
3bf9a45f |
77 | } |
78 | |
79 | //======================================================================= |
80 | // function : SelectMgr_TriangularFrustum |
81 | // purpose : Creates new triangular frustum with bases of triangles with |
82 | // vertices theP1, theP2 and theP3 projections onto near and |
83 | // far view frustum planes |
84 | //======================================================================= |
85 | void SelectMgr_TriangularFrustum::Build (const gp_Pnt2d& theP1, |
86 | const gp_Pnt2d& theP2, |
87 | const gp_Pnt2d& theP3) |
88 | { |
89 | // V0_Near |
90 | myVertices[0] = myBuilder->ProjectPntOnViewPlane (theP1.X(), theP1.Y(), 0.0); |
91 | // V1_Near |
92 | myVertices[1] = myBuilder->ProjectPntOnViewPlane (theP2.X(), theP2.Y(), 0.0); |
93 | // V2_Near |
94 | myVertices[2] = myBuilder->ProjectPntOnViewPlane (theP3.X(), theP3.Y(), 0.0); |
95 | // V0_Far |
96 | myVertices[3] = myBuilder->ProjectPntOnViewPlane (theP1.X(), theP1.Y(), 1.0); |
97 | // V1_Far |
98 | myVertices[4] = myBuilder->ProjectPntOnViewPlane (theP2.X(), theP2.Y(), 1.0); |
99 | // V2_Far |
100 | myVertices[5] = myBuilder->ProjectPntOnViewPlane (theP3.X(), theP3.Y(), 1.0); |
f751596e |
101 | |
102 | // V0_Near - V0_Far |
3bf9a45f |
103 | myEdgeDirs[0] = myVertices[0].XYZ() - myVertices[3].XYZ(); |
f751596e |
104 | // V1_Near - V1_Far |
3bf9a45f |
105 | myEdgeDirs[1] = myVertices[1].XYZ() - myVertices[4].XYZ(); |
f751596e |
106 | // V2_Near - V1_Far |
3bf9a45f |
107 | myEdgeDirs[2] = myVertices[2].XYZ() - myVertices[5].XYZ(); |
f751596e |
108 | // V1_Near - V0_Near |
3bf9a45f |
109 | myEdgeDirs[3] = myVertices[1].XYZ() - myVertices[0].XYZ(); |
f751596e |
110 | // V2_Near - V1_Near |
3bf9a45f |
111 | myEdgeDirs[4] = myVertices[2].XYZ() - myVertices[1].XYZ(); |
f751596e |
112 | // V1_Near - V0_Near |
3bf9a45f |
113 | myEdgeDirs[5] = myVertices[2].XYZ() - myVertices[0].XYZ(); |
114 | |
115 | computeFrustumNormals (myEdgeDirs, myPlanes); |
116 | |
117 | cacheVertexProjections (this); |
f751596e |
118 | } |
119 | |
120 | //======================================================================= |
3bf9a45f |
121 | // function : ScaleAndTransform |
122 | // purpose : IMPORTANT: Scaling makes sense only for frustum built on a single point! |
123 | // Note that this method does not perform any checks on type of the frustum. |
124 | // Returns a copy of the frustum resized according to the scale factor given |
125 | // and transforms it using the matrix given. |
126 | // There are no default parameters, but in case if: |
127 | // - transformation only is needed: @theScaleFactor must be initialized |
128 | // as any negative value; |
129 | // - scale only is needed: @theTrsf must be set to gp_Identity. |
f751596e |
130 | //======================================================================= |
099f3513 |
131 | Handle(SelectMgr_BaseFrustum) SelectMgr_TriangularFrustum::ScaleAndTransform (const Standard_Integer /*theScale*/, |
132 | const gp_GTrsf& theTrsf) const |
f751596e |
133 | { |
099f3513 |
134 | Handle(SelectMgr_TriangularFrustum) aRes = new SelectMgr_TriangularFrustum(); |
f751596e |
135 | |
91d96372 |
136 | for (Standard_Integer anIt = 0; anIt < 6; anIt++) |
137 | { |
138 | gp_Pnt aPoint = myVertices[anIt]; |
139 | theTrsf.Transforms (aPoint.ChangeCoord()); |
140 | aRes->myVertices[anIt] = aPoint; |
141 | } |
f751596e |
142 | |
143 | aRes->myIsOrthographic = myIsOrthographic; |
144 | |
f751596e |
145 | // V0_Near - V0_Far |
3bf9a45f |
146 | aRes->myEdgeDirs[0] = aRes->myVertices[0].XYZ() - aRes->myVertices[3].XYZ(); |
f751596e |
147 | // V1_Near - V1_Far |
3bf9a45f |
148 | aRes->myEdgeDirs[1] = aRes->myVertices[1].XYZ() - aRes->myVertices[4].XYZ(); |
f751596e |
149 | // V2_Near - V1_Far |
3bf9a45f |
150 | aRes->myEdgeDirs[2] = aRes->myVertices[2].XYZ() - aRes->myVertices[5].XYZ(); |
f751596e |
151 | // V1_Near - V0_Near |
3bf9a45f |
152 | aRes->myEdgeDirs[3] = aRes->myVertices[1].XYZ() - aRes->myVertices[0].XYZ(); |
f751596e |
153 | // V2_Near - V1_Near |
3bf9a45f |
154 | aRes->myEdgeDirs[4] = aRes->myVertices[2].XYZ() - aRes->myVertices[1].XYZ(); |
f751596e |
155 | // V1_Near - V0_Near |
3bf9a45f |
156 | aRes->myEdgeDirs[5] = aRes->myVertices[2].XYZ() - aRes->myVertices[0].XYZ(); |
157 | |
158 | computeFrustumNormals (aRes->myEdgeDirs, aRes->myPlanes); |
159 | |
099f3513 |
160 | cacheVertexProjections (aRes.get()); |
f751596e |
161 | |
099f3513 |
162 | return aRes; |
f751596e |
163 | } |
164 | |
165 | //======================================================================= |
166 | // function : Overlaps |
167 | // purpose : SAT intersection test between defined volume and |
168 | // given axis-aligned box |
169 | //======================================================================= |
3bf9a45f |
170 | Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const SelectMgr_Vec3& theMinPt, |
171 | const SelectMgr_Vec3& theMaxPt, |
d7fa57a7 |
172 | const SelectMgr_ViewClipRange& /*theClipRange*/, |
4a056d20 |
173 | SelectBasics_PickResult& /*thePickResult*/) const |
f751596e |
174 | { |
3bf9a45f |
175 | return hasOverlap (theMinPt, theMaxPt); |
f751596e |
176 | } |
177 | |
178 | // ======================================================================= |
179 | // function : Overlaps |
180 | // purpose : Returns true if selecting volume is overlapped by |
181 | // axis-aligned bounding box with minimum corner at point |
182 | // theMinPt and maximum at point theMaxPt |
183 | // ======================================================================= |
7ab15952 |
184 | Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const SelectMgr_Vec3& theMinPt, |
2157d6ac |
185 | const SelectMgr_Vec3& theMaxPt, |
4a056d20 |
186 | Standard_Boolean* /*theInside*/) const |
f751596e |
187 | { |
2157d6ac |
188 | return hasOverlap (theMinPt, theMaxPt, NULL); |
f751596e |
189 | } |
190 | |
191 | // ======================================================================= |
192 | // function : Overlaps |
193 | // purpose : Intersection test between defined volume and given point |
194 | // ======================================================================= |
7ab15952 |
195 | Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const gp_Pnt& thePnt, |
d7fa57a7 |
196 | const SelectMgr_ViewClipRange& /*theClipRange*/, |
4a056d20 |
197 | SelectBasics_PickResult& /*thePickResult*/) const |
f751596e |
198 | { |
199 | return hasOverlap (thePnt); |
200 | } |
201 | |
202 | // ======================================================================= |
203 | // function : Overlaps |
204 | // purpose : SAT intersection test between defined volume and given |
205 | // ordered set of points, representing line segments. The test |
206 | // may be considered of interior part or boundary line defined |
207 | // by segments depending on given sensitivity type |
208 | // ======================================================================= |
114b7bf1 |
209 | Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const TColgp_Array1OfPnt& theArrayOfPnts, |
7ab15952 |
210 | Select3D_TypeOfSensitivity theSensType, |
d7fa57a7 |
211 | const SelectMgr_ViewClipRange& /*theClipRange*/, |
4a056d20 |
212 | SelectBasics_PickResult& /*thePickResult*/) const |
f751596e |
213 | { |
214 | if (theSensType == Select3D_TOS_BOUNDARY) |
215 | { |
114b7bf1 |
216 | const Standard_Integer aLower = theArrayOfPnts.Lower(); |
217 | const Standard_Integer anUpper = theArrayOfPnts.Upper(); |
f751596e |
218 | for (Standard_Integer aPtIdx = aLower; aPtIdx <= anUpper; ++aPtIdx) |
219 | { |
114b7bf1 |
220 | const gp_Pnt& aStartPt = theArrayOfPnts.Value (aPtIdx); |
221 | const gp_Pnt& aEndPt = theArrayOfPnts.Value (aPtIdx == anUpper ? aLower : (aPtIdx + 1)); |
f751596e |
222 | if (!hasOverlap (aStartPt, aEndPt)) |
223 | { |
224 | return Standard_False; |
225 | } |
226 | } |
227 | } |
228 | else if (theSensType == Select3D_TOS_INTERIOR) |
229 | { |
3bf9a45f |
230 | gp_Vec aNorm (gp_XYZ (RealLast(), RealLast(), RealLast())); |
f751596e |
231 | return hasOverlap (theArrayOfPnts, aNorm); |
232 | } |
233 | |
234 | return Standard_False; |
235 | } |
236 | |
237 | // ======================================================================= |
238 | // function : Overlaps |
239 | // purpose : Checks if line segment overlaps selecting frustum |
240 | // ======================================================================= |
7ab15952 |
241 | Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const gp_Pnt& thePnt1, |
242 | const gp_Pnt& thePnt2, |
d7fa57a7 |
243 | const SelectMgr_ViewClipRange& /*theClipRange*/, |
4a056d20 |
244 | SelectBasics_PickResult& /*thePickResult*/) const |
f751596e |
245 | { |
246 | return hasOverlap (thePnt1, thePnt2); |
247 | } |
248 | |
249 | // ======================================================================= |
250 | // function : Overlaps |
251 | // purpose : SAT intersection test between defined volume and given |
252 | // triangle. The test may be considered of interior part or |
253 | // boundary line defined by triangle vertices depending on |
254 | // given sensitivity type |
255 | // ======================================================================= |
7ab15952 |
256 | Standard_Boolean SelectMgr_TriangularFrustum::Overlaps (const gp_Pnt& thePnt1, |
257 | const gp_Pnt& thePnt2, |
258 | const gp_Pnt& thePnt3, |
259 | Select3D_TypeOfSensitivity theSensType, |
d7fa57a7 |
260 | const SelectMgr_ViewClipRange& theClipRange, |
4a056d20 |
261 | SelectBasics_PickResult& thePickResult) const |
f751596e |
262 | { |
263 | if (theSensType == Select3D_TOS_BOUNDARY) |
264 | { |
114b7bf1 |
265 | const gp_Pnt aPntsArrayBuf[3] = { thePnt1, thePnt2, thePnt3 }; |
266 | const TColgp_Array1OfPnt aPntsArray (aPntsArrayBuf[0], 1, 3); |
d7fa57a7 |
267 | return Overlaps (aPntsArray, Select3D_TOS_BOUNDARY, theClipRange, thePickResult); |
f751596e |
268 | } |
269 | else if (theSensType == Select3D_TOS_INTERIOR) |
270 | { |
3bf9a45f |
271 | gp_Vec aNorm (gp_XYZ (RealLast(), RealLast(), RealLast())); |
f751596e |
272 | return hasOverlap (thePnt1, thePnt2, thePnt3, aNorm); |
273 | } |
274 | |
275 | return Standard_True; |
276 | } |
277 | |
278 | // ======================================================================= |
279 | // function : Clear |
280 | // purpose : Nullifies the handle for corresponding builder instance to prevent |
281 | // memory leaks |
282 | // ======================================================================= |
283 | void SelectMgr_TriangularFrustum::Clear() |
284 | { |
285 | myBuilder.Nullify(); |
286 | } |
871dcdc2 |
287 | |
288 | // ======================================================================= |
289 | // function : GetPlanes |
290 | // purpose : |
291 | // ======================================================================= |
292 | void SelectMgr_TriangularFrustum::GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const |
293 | { |
294 | SelectMgr_Vec4 aPlaneEquation; |
295 | for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 5; ++aPlaneIdx) |
296 | { |
297 | const gp_Vec& aNorm = myPlanes[aPlaneIdx]; |
298 | aPlaneEquation.x() = aNorm.X(); |
299 | aPlaneEquation.y() = aNorm.Y(); |
300 | aPlaneEquation.z() = aNorm.Z(); |
301 | aPlaneEquation.w() = - (aNorm.XYZ().Dot (myVertices[aPlaneIdx % 2 == 0 ? aPlaneIdx : 1].XYZ())); |
302 | thePlaneEquations.Append (aPlaneEquation); |
303 | } |
304 | } |