1 // Created on: 2014-11-21
2 // Created by: Varvara POSKONINA
3 // Copyright (c) 2005-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <SelectMgr_TriangularFrustum.hxx>
18 #include <SelectMgr_FrustumBuilder.hxx>
20 IMPLEMENT_STANDARD_RTTIEXT(SelectMgr_TriangularFrustum,Standard_Transient)
22 SelectMgr_TriangularFrustum::~SelectMgr_TriangularFrustum()
29 void computeFrustumNormals (const gp_Vec* theEdges, gp_Vec* theNormals)
32 theNormals[0] = theEdges[0].Crossed (theEdges[3]);
34 theNormals[1] = theEdges[1].Crossed (theEdges[4]);
36 theNormals[2] = theEdges[0].Crossed (theEdges[5]);
38 theNormals[3] = theEdges[3].Crossed (theEdges[4]);
40 theNormals[4] = -theNormals[3];
44 // =======================================================================
45 // function : cacheVertexProjections
46 // purpose : Caches projection of frustum's vertices onto its plane directions
48 // =======================================================================
49 void SelectMgr_TriangularFrustum::cacheVertexProjections (SelectMgr_TriangularFrustum* theFrustum) const
51 for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 5; ++aPlaneIdx)
53 Standard_Real aMax = -DBL_MAX;
54 Standard_Real aMin = DBL_MAX;
55 const gp_XYZ& aPlane = theFrustum->myPlanes[aPlaneIdx].XYZ();
56 for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx)
58 Standard_Real aProjection = aPlane.Dot (theFrustum->myVertices[aVertIdx].XYZ());
59 aMax = Max (aMax, aProjection);
60 aMin = Min (aMin, aProjection);
62 theFrustum->myMaxVertsProjections[aPlaneIdx] = aMax;
63 theFrustum->myMinVertsProjections[aPlaneIdx] = aMin;
66 for (Standard_Integer aDim = 0; aDim < 3; ++aDim)
68 Standard_Real aMax = -DBL_MAX;
69 Standard_Real aMin = DBL_MAX;
70 for (Standard_Integer aVertIdx = 0; aVertIdx < 6; ++aVertIdx)
72 Standard_Real aProjection = theFrustum->myVertices[aVertIdx].XYZ().GetData()[aDim];
73 aMax = Max (aMax, aProjection);
74 aMin = Min (aMin, aProjection);
76 theFrustum->myMaxOrthoVertsProjections[aDim] = aMax;
77 theFrustum->myMinOrthoVertsProjections[aDim] = aMin;
81 //=======================================================================
84 //=======================================================================
85 void SelectMgr_TriangularFrustum::Init (const gp_Pnt2d& theP1,
86 const gp_Pnt2d& theP2,
87 const gp_Pnt2d& theP3)
89 mySelTriangle.Points[0] = theP1;
90 mySelTriangle.Points[1] = theP2;
91 mySelTriangle.Points[2] = theP3;
94 //=======================================================================
97 //=======================================================================
98 void SelectMgr_TriangularFrustum::Build()
101 myVertices[0] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[0].X(), mySelTriangle.Points[0].Y(), 0.0);
103 myVertices[1] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[1].X(), mySelTriangle.Points[1].Y(), 0.0);
105 myVertices[2] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[2].X(), mySelTriangle.Points[2].Y(), 0.0);
107 myVertices[3] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[0].X(), mySelTriangle.Points[0].Y(), 1.0);
109 myVertices[4] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[1].X(), mySelTriangle.Points[1].Y(), 1.0);
111 myVertices[5] = myBuilder->ProjectPntOnViewPlane (mySelTriangle.Points[2].X(), mySelTriangle.Points[2].Y(), 1.0);
114 myEdgeDirs[0] = myVertices[0].XYZ() - myVertices[3].XYZ();
116 myEdgeDirs[1] = myVertices[1].XYZ() - myVertices[4].XYZ();
118 myEdgeDirs[2] = myVertices[2].XYZ() - myVertices[5].XYZ();
120 myEdgeDirs[3] = myVertices[1].XYZ() - myVertices[0].XYZ();
122 myEdgeDirs[4] = myVertices[2].XYZ() - myVertices[1].XYZ();
124 myEdgeDirs[5] = myVertices[2].XYZ() - myVertices[0].XYZ();
126 computeFrustumNormals (myEdgeDirs, myPlanes);
128 cacheVertexProjections (this);
131 //=======================================================================
132 // function : ScaleAndTransform
133 // purpose : IMPORTANT: Scaling makes sense only for frustum built on a single point!
134 // Note that this method does not perform any checks on type of the frustum.
135 // Returns a copy of the frustum resized according to the scale factor given
136 // and transforms it using the matrix given.
137 // There are no default parameters, but in case if:
138 // - transformation only is needed: @theScaleFactor must be initialized
139 // as any negative value;
140 // - scale only is needed: @theTrsf must be set to gp_Identity.
141 //=======================================================================
142 Handle(SelectMgr_BaseIntersector) SelectMgr_TriangularFrustum::ScaleAndTransform (const Standard_Integer,
143 const gp_GTrsf& theTrsf,
144 const Handle(SelectMgr_FrustumBuilder)&) const
146 Handle(SelectMgr_TriangularFrustum) aRes = new SelectMgr_TriangularFrustum();
148 for (Standard_Integer anIt = 0; anIt < 6; anIt++)
150 gp_Pnt aPoint = myVertices[anIt];
151 theTrsf.Transforms (aPoint.ChangeCoord());
152 aRes->myVertices[anIt] = aPoint;
155 aRes->myIsOrthographic = myIsOrthographic;
158 aRes->myEdgeDirs[0] = aRes->myVertices[0].XYZ() - aRes->myVertices[3].XYZ();
160 aRes->myEdgeDirs[1] = aRes->myVertices[1].XYZ() - aRes->myVertices[4].XYZ();
162 aRes->myEdgeDirs[2] = aRes->myVertices[2].XYZ() - aRes->myVertices[5].XYZ();
164 aRes->myEdgeDirs[3] = aRes->myVertices[1].XYZ() - aRes->myVertices[0].XYZ();
166 aRes->myEdgeDirs[4] = aRes->myVertices[2].XYZ() - aRes->myVertices[1].XYZ();
168 aRes->myEdgeDirs[5] = aRes->myVertices[2].XYZ() - aRes->myVertices[0].XYZ();
170 computeFrustumNormals (aRes->myEdgeDirs, aRes->myPlanes);
172 cacheVertexProjections (aRes.get());
174 aRes->mySelTriangle = mySelTriangle;
179 //=======================================================================
180 // function : OverlapsBox
181 // purpose : SAT intersection test between defined volume and
182 // given axis-aligned box
183 //=======================================================================
184 Standard_Boolean SelectMgr_TriangularFrustum::OverlapsBox (const SelectMgr_Vec3& theMinPt,
185 const SelectMgr_Vec3& theMaxPt,
186 const SelectMgr_ViewClipRange& /*theClipRange*/,
187 SelectBasics_PickResult& /*thePickResult*/) const
189 return hasBoxOverlap (theMinPt, theMaxPt);
192 // =======================================================================
193 // function : OverlapsBox
194 // purpose : Returns true if selecting volume is overlapped by
195 // axis-aligned bounding box with minimum corner at point
196 // theMinPt and maximum at point theMaxPt
197 // =======================================================================
198 Standard_Boolean SelectMgr_TriangularFrustum::OverlapsBox (const SelectMgr_Vec3& theMinPt,
199 const SelectMgr_Vec3& theMaxPt,
200 Standard_Boolean* /*theInside*/) const
202 return hasBoxOverlap (theMinPt, theMaxPt, NULL);
205 // =======================================================================
206 // function : OverlapsPoint
207 // purpose : Intersection test between defined volume and given point
208 // =======================================================================
209 Standard_Boolean SelectMgr_TriangularFrustum::OverlapsPoint (const gp_Pnt& thePnt,
210 const SelectMgr_ViewClipRange& /*theClipRange*/,
211 SelectBasics_PickResult& /*thePickResult*/) const
213 return hasPointOverlap (thePnt);
216 // =======================================================================
217 // function : OverlapsPolygon
218 // purpose : SAT intersection test between defined volume and given
219 // ordered set of points, representing line segments. The test
220 // may be considered of interior part or boundary line defined
221 // by segments depending on given sensitivity type
222 // =======================================================================
223 Standard_Boolean SelectMgr_TriangularFrustum::OverlapsPolygon (const TColgp_Array1OfPnt& theArrayOfPnts,
224 Select3D_TypeOfSensitivity theSensType,
225 const SelectMgr_ViewClipRange& /*theClipRange*/,
226 SelectBasics_PickResult& /*thePickResult*/) const
228 if (theSensType == Select3D_TOS_BOUNDARY)
230 const Standard_Integer aLower = theArrayOfPnts.Lower();
231 const Standard_Integer anUpper = theArrayOfPnts.Upper();
232 for (Standard_Integer aPtIdx = aLower; aPtIdx <= anUpper; ++aPtIdx)
234 const gp_Pnt& aStartPt = theArrayOfPnts.Value (aPtIdx);
235 const gp_Pnt& aEndPt = theArrayOfPnts.Value (aPtIdx == anUpper ? aLower : (aPtIdx + 1));
236 if (!hasSegmentOverlap (aStartPt, aEndPt))
238 return Standard_False;
242 else if (theSensType == Select3D_TOS_INTERIOR)
244 gp_Vec aNorm (gp_XYZ (RealLast(), RealLast(), RealLast()));
245 return hasPolygonOverlap (theArrayOfPnts, aNorm);
248 return Standard_False;
251 // =======================================================================
252 // function : OverlapsSegment
253 // purpose : Checks if line segment overlaps selecting frustum
254 // =======================================================================
255 Standard_Boolean SelectMgr_TriangularFrustum::OverlapsSegment (const gp_Pnt& thePnt1,
256 const gp_Pnt& thePnt2,
257 const SelectMgr_ViewClipRange& /*theClipRange*/,
258 SelectBasics_PickResult& /*thePickResult*/) const
260 return hasSegmentOverlap (thePnt1, thePnt2);
263 // =======================================================================
264 // function : OverlapsTriangle
265 // purpose : SAT intersection test between defined volume and given
266 // triangle. The test may be considered of interior part or
267 // boundary line defined by triangle vertices depending on
268 // given sensitivity type
269 // =======================================================================
270 Standard_Boolean SelectMgr_TriangularFrustum::OverlapsTriangle (const gp_Pnt& thePnt1,
271 const gp_Pnt& thePnt2,
272 const gp_Pnt& thePnt3,
273 Select3D_TypeOfSensitivity theSensType,
274 const SelectMgr_ViewClipRange& theClipRange,
275 SelectBasics_PickResult& thePickResult) const
277 if (theSensType == Select3D_TOS_BOUNDARY)
279 const gp_Pnt aPntsArrayBuf[3] = { thePnt1, thePnt2, thePnt3 };
280 const TColgp_Array1OfPnt aPntsArray (aPntsArrayBuf[0], 1, 3);
281 return OverlapsPolygon (aPntsArray, Select3D_TOS_BOUNDARY, theClipRange, thePickResult);
283 else if (theSensType == Select3D_TOS_INTERIOR)
285 gp_Vec aNorm (gp_XYZ (RealLast(), RealLast(), RealLast()));
286 return hasTriangleOverlap (thePnt1, thePnt2, thePnt3, aNorm);
289 return Standard_True;
292 // =======================================================================
294 // purpose : Nullifies the handle for corresponding builder instance to prevent
296 // =======================================================================
297 void SelectMgr_TriangularFrustum::Clear()
302 // =======================================================================
303 // function : GetPlanes
305 // =======================================================================
306 void SelectMgr_TriangularFrustum::GetPlanes (NCollection_Vector<SelectMgr_Vec4>& thePlaneEquations) const
308 SelectMgr_Vec4 aPlaneEquation;
309 for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < 5; ++aPlaneIdx)
311 const gp_Vec& aNorm = myPlanes[aPlaneIdx];
312 aPlaneEquation.x() = aNorm.X();
313 aPlaneEquation.y() = aNorm.Y();
314 aPlaneEquation.z() = aNorm.Z();
315 aPlaneEquation.w() = - (aNorm.XYZ().Dot (myVertices[aPlaneIdx % 2 == 0 ? aPlaneIdx : 1].XYZ()));
316 thePlaneEquations.Append (aPlaneEquation);
320 //=======================================================================
321 //function : DumpJson
323 //=======================================================================
324 void SelectMgr_TriangularFrustum::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
326 OCCT_DUMP_CLASS_BEGIN (theOStream, SelectMgr_TriangularFrustum)
327 OCCT_DUMP_BASE_CLASS (theOStream, theDepth, SelectMgr_Frustum)