2108d9a2 |
1 | // Created on: 2017-07-25 |
2 | // Created by: Anastasia BOBYLEVA |
3 | // Copyright (c) 2017-2019 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 <AIS_ViewCube.hxx> |
17 | |
18 | #include <AIS_AnimationCamera.hxx> |
19 | #include <AIS_InteractiveContext.hxx> |
20 | #include <gp_Ax2.hxx> |
21 | #include <Graphic3d_ViewAffinity.hxx> |
b383a61f |
22 | #include <Graphic3d_Text.hxx> |
2108d9a2 |
23 | #include <NCollection_Lerp.hxx> |
24 | #include <Prs3d.hxx> |
25 | #include <Prs3d_Arrow.hxx> |
26 | #include <Prs3d_DatumAspect.hxx> |
27 | #include <Prs3d_Root.hxx> |
28 | #include <Prs3d_Text.hxx> |
29 | #include <Prs3d_ToolDisk.hxx> |
30 | #include <Prs3d_ToolSphere.hxx> |
31 | #include <Select3D_SensitivePrimitiveArray.hxx> |
32 | #include <SelectMgr_SequenceOfOwner.hxx> |
33 | #include <V3d.hxx> |
34 | #include <V3d_View.hxx> |
35 | |
36 | IMPLEMENT_STANDARD_RTTIEXT(AIS_ViewCube, AIS_InteractiveObject) |
37 | IMPLEMENT_STANDARD_RTTIEXT(AIS_ViewCubeOwner, SelectMgr_EntityOwner) |
38 | |
39 | namespace |
40 | { |
41 | static const Standard_Integer THE_NB_ROUND_SPLITS = 8; |
42 | static const Standard_Integer THE_NB_DISK_SLICES = 20; |
43 | static const Standard_Integer THE_NB_ARROW_FACETTES = 20; |
44 | |
45 | //! Return the number of non-zero components. |
46 | static Standard_Integer nbDirectionComponents (const gp_Dir& theDir) |
47 | { |
48 | Standard_Integer aNbComps = 0; |
49 | for (Standard_Integer aCompIter = 1; aCompIter <= 3; ++aCompIter) |
50 | { |
51 | if (Abs (theDir.Coord (aCompIter)) > gp::Resolution()) |
52 | { |
53 | ++aNbComps; |
54 | } |
55 | } |
56 | return aNbComps; |
57 | } |
58 | } |
59 | |
60 | //! Simple sensitive element for picking by point only. |
61 | class AIS_ViewCubeSensitive : public Select3D_SensitivePrimitiveArray |
62 | { |
63 | DEFINE_STANDARD_RTTI_INLINE(AIS_ViewCubeSensitive, Select3D_SensitivePrimitiveArray) |
64 | public: |
65 | //! Constructor. |
66 | AIS_ViewCubeSensitive (const Handle(SelectMgr_EntityOwner)& theOwner, |
67 | const Handle(Graphic3d_ArrayOfTriangles)& theTris) |
68 | : Select3D_SensitivePrimitiveArray (theOwner) |
69 | { |
70 | InitTriangulation (theTris->Attributes(), theTris->Indices(), TopLoc_Location()); |
71 | } |
72 | |
73 | //! Checks whether element overlaps current selecting volume. |
74 | virtual Standard_Boolean Matches (SelectBasics_SelectingVolumeManager& theMgr, |
75 | SelectBasics_PickResult& thePickResult) Standard_OVERRIDE |
76 | { |
77 | return isValidRay (theMgr) |
78 | && Select3D_SensitivePrimitiveArray::Matches (theMgr, thePickResult); |
79 | } |
80 | |
81 | //! Checks if picking ray can be used for detection. |
82 | bool isValidRay (const SelectBasics_SelectingVolumeManager& theMgr) const |
83 | { |
84 | if (theMgr.GetActiveSelectionType() != SelectBasics_SelectingVolumeManager::Point) |
85 | { |
86 | // disallow rectangular selection |
87 | return false; |
88 | } |
89 | |
90 | if (AIS_ViewCubeOwner* anOwner = dynamic_cast<AIS_ViewCubeOwner* >(myOwnerId.get())) |
91 | { |
92 | const Standard_Real anAngleToler = 10.0 * M_PI / 180.0; |
93 | const gp_Vec aRay (theMgr.GetNearPickedPnt(), theMgr.GetFarPickedPnt()); |
94 | const gp_Dir aDir = V3d::GetProjAxis (anOwner->MainOrientation()); |
95 | return !aRay.IsNormal (aDir, anAngleToler); |
96 | } |
97 | return true; |
98 | } |
99 | }; |
100 | |
101 | //======================================================================= |
102 | //function : IsBoxSide |
103 | //purpose : |
104 | //======================================================================= |
105 | bool AIS_ViewCube::IsBoxSide (V3d_TypeOfOrientation theOrient) |
106 | { |
107 | return nbDirectionComponents (V3d::GetProjAxis (theOrient)) == 1; |
108 | } |
109 | |
110 | //======================================================================= |
111 | //function : IsBoxEdge |
112 | //purpose : |
113 | //======================================================================= |
114 | bool AIS_ViewCube::IsBoxEdge (V3d_TypeOfOrientation theOrient) |
115 | { |
116 | return nbDirectionComponents (V3d::GetProjAxis (theOrient)) == 2; |
117 | } |
118 | |
119 | //======================================================================= |
120 | //function : IsBoxCorner |
121 | //purpose : |
122 | //======================================================================= |
123 | bool AIS_ViewCube::IsBoxCorner (V3d_TypeOfOrientation theOrient) |
124 | { |
125 | return nbDirectionComponents (V3d::GetProjAxis (theOrient)) == 3; |
126 | } |
127 | |
128 | //======================================================================= |
129 | //function : AIS_ViewCube |
130 | //purpose : |
131 | //======================================================================= |
132 | AIS_ViewCube::AIS_ViewCube() |
133 | : myBoxEdgeAspect (new Prs3d_ShadingAspect()), |
134 | myBoxCornerAspect (new Prs3d_ShadingAspect()), |
135 | mySize (1.0), |
136 | myBoxEdgeMinSize (2.0), |
137 | myBoxEdgeGap (0.0), |
138 | myBoxFacetExtension (1.0), |
139 | myAxesPadding (1.0), |
140 | myCornerMinSize (2.0), |
141 | myRoundRadius (0.0), |
142 | myToDisplayAxes (true), |
143 | myToDisplayEdges (true), |
144 | myToDisplayVertices (true), |
145 | myIsYup (false), |
146 | myViewAnimation (new AIS_AnimationCamera ("AIS_ViewCube", Handle(V3d_View)())), |
147 | myStartState(new Graphic3d_Camera()), |
148 | myEndState (new Graphic3d_Camera()), |
149 | myDuration (0.5), |
150 | myToAutoStartAnim (true), |
151 | myIsFixedAnimation (true), |
152 | myToFitSelected (true), |
153 | myToResetCameraUp (false) |
154 | { |
155 | myInfiniteState = true; |
156 | myIsMutable = true; |
157 | myDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost); |
158 | myTransformPersistence = new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_LOWER, Graphic3d_Vec2i (100, 100)); |
159 | |
160 | myDrawer->SetTextAspect (new Prs3d_TextAspect()); |
161 | myDrawer->SetShadingAspect (new Prs3d_ShadingAspect()); |
162 | |
163 | myDynHilightDrawer = new Prs3d_Drawer(); |
164 | myDynHilightDrawer->SetLink (myDrawer); |
165 | myDynHilightDrawer->SetShadingAspect (new Prs3d_ShadingAspect()); |
166 | |
167 | setDefaultAttributes(); |
168 | setDefaultHighlightAttributes(); |
169 | |
170 | // setup default labels |
171 | myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Front, "FRONT"); |
172 | myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Back, "BACK"); |
173 | myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Top, "TOP"); |
174 | myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Bottom, "BOTTOM"); |
175 | myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Left, "LEFT"); |
176 | myBoxSideLabels.Bind (V3d_TypeOfOrientation_Zup_Right, "RIGHT"); |
177 | |
178 | myAxesLabels.Bind (Prs3d_DP_XAxis, "X"); |
179 | myAxesLabels.Bind (Prs3d_DP_YAxis, "Y"); |
180 | myAxesLabels.Bind (Prs3d_DP_ZAxis, "Z"); |
181 | |
182 | // define default size |
183 | SetSize (70.0); |
184 | } |
185 | |
186 | //======================================================================= |
187 | //function : setDefaultAttributes |
188 | //purpose : |
189 | //======================================================================= |
190 | void AIS_ViewCube::setDefaultAttributes() |
191 | { |
192 | myDrawer->TextAspect()->SetHorizontalJustification(Graphic3d_HTA_CENTER); |
193 | myDrawer->TextAspect()->SetVerticalJustification (Graphic3d_VTA_CENTER); |
194 | myDrawer->TextAspect()->SetColor (Quantity_NOC_BLACK); |
195 | myDrawer->TextAspect()->SetFont (Font_NOF_SANS_SERIF); |
196 | myDrawer->TextAspect()->SetHeight (16.0); |
b383a61f |
197 | myDrawer->TextAspect()->Aspect()->SetTextZoomable (true); // the whole object is drawn within transformation-persistence |
2108d9a2 |
198 | // this should be forced back-face culling regardless Closed flag |
199 | myDrawer->TextAspect()->Aspect()->SetSuppressBackFaces (true); |
200 | |
201 | Graphic3d_MaterialAspect aMat (Graphic3d_NOM_UserDefined); |
202 | aMat.SetColor (Quantity_NOC_WHITE); |
203 | aMat.SetAmbientColor (Quantity_NOC_GRAY60); |
204 | |
205 | const Handle(Graphic3d_AspectFillArea3d)& aShading = myDrawer->ShadingAspect()->Aspect(); |
206 | aShading->SetInteriorStyle (Aspect_IS_SOLID); |
207 | // this should be forced back-face culling regardless Closed flag |
208 | aShading->SetSuppressBackFaces (true); |
209 | aShading->SetInteriorColor (aMat.Color()); |
210 | aShading->SetFrontMaterial (aMat); |
211 | myDrawer->SetFaceBoundaryDraw (false); |
212 | |
213 | *myBoxEdgeAspect ->Aspect() = *aShading; |
214 | myBoxEdgeAspect->SetColor (Quantity_NOC_GRAY30); |
215 | *myBoxCornerAspect->Aspect() = *aShading; |
216 | myBoxCornerAspect->SetColor (Quantity_NOC_GRAY30); |
217 | } |
218 | |
219 | //======================================================================= |
220 | //function : setDefaultHighlightAttributes |
221 | //purpose : |
222 | //======================================================================= |
223 | void AIS_ViewCube::setDefaultHighlightAttributes() |
224 | { |
225 | Graphic3d_MaterialAspect aHighlightMaterial; |
226 | aHighlightMaterial.SetReflectionModeOff (Graphic3d_TOR_AMBIENT); |
227 | aHighlightMaterial.SetReflectionModeOff (Graphic3d_TOR_DIFFUSE); |
228 | aHighlightMaterial.SetReflectionModeOff (Graphic3d_TOR_SPECULAR); |
229 | aHighlightMaterial.SetReflectionModeOff (Graphic3d_TOR_EMISSION); |
230 | aHighlightMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT); |
231 | myDynHilightDrawer->SetShadingAspect (new Prs3d_ShadingAspect()); |
232 | myDynHilightDrawer->ShadingAspect()->SetMaterial (aHighlightMaterial); |
233 | myDynHilightDrawer->ShadingAspect()->SetColor (Quantity_NOC_CYAN1); |
234 | myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost); |
235 | myDynHilightDrawer->SetColor (Quantity_NOC_CYAN1); |
236 | } |
237 | |
238 | //======================================================================= |
239 | //function : SetYup |
240 | //purpose : |
241 | //======================================================================= |
242 | void AIS_ViewCube::SetYup (Standard_Boolean theIsYup, |
243 | Standard_Boolean theToUpdateLabels) |
244 | { |
245 | if (myIsYup == theIsYup) |
246 | { |
247 | return; |
248 | } |
249 | |
250 | myIsYup = theIsYup; |
251 | |
252 | static const V3d_TypeOfOrientation THE_ZUP_ORI_LIST[6] = |
253 | { |
254 | V3d_TypeOfOrientation_Zup_Front, V3d_TypeOfOrientation_Zup_Back, |
255 | V3d_TypeOfOrientation_Zup_Top, V3d_TypeOfOrientation_Zup_Bottom, |
256 | V3d_TypeOfOrientation_Zup_Left, V3d_TypeOfOrientation_Zup_Right |
257 | }; |
258 | static const V3d_TypeOfOrientation THE_YUP_ORI_LIST[6] = |
259 | { |
260 | V3d_TypeOfOrientation_Yup_Front, V3d_TypeOfOrientation_Yup_Back, |
261 | V3d_TypeOfOrientation_Yup_Top, V3d_TypeOfOrientation_Yup_Bottom, |
262 | V3d_TypeOfOrientation_Yup_Left, V3d_TypeOfOrientation_Yup_Right |
263 | }; |
264 | if (theToUpdateLabels) |
265 | { |
266 | NCollection_Array1<TCollection_AsciiString> aLabels (0, 5); |
267 | for (Standard_Integer aLabelIter = 0; aLabelIter < 6; ++aLabelIter) |
268 | { |
269 | myBoxSideLabels.Find (!myIsYup ? THE_YUP_ORI_LIST[aLabelIter] : THE_ZUP_ORI_LIST[aLabelIter], |
270 | aLabels.ChangeValue (aLabelIter)); |
271 | } |
272 | for (Standard_Integer aLabelIter = 0; aLabelIter < 6; ++aLabelIter) |
273 | { |
274 | myBoxSideLabels.Bind (myIsYup ? THE_YUP_ORI_LIST[aLabelIter] : THE_ZUP_ORI_LIST[aLabelIter], |
275 | aLabels.Value (aLabelIter)); |
276 | } |
277 | } |
278 | |
279 | SetToUpdate(); |
280 | } |
281 | |
282 | //======================================================================= |
283 | //function : ResetStyles |
284 | //purpose : |
285 | //======================================================================= |
286 | void AIS_ViewCube::ResetStyles() |
287 | { |
288 | UnsetAttributes(); |
289 | UnsetHilightAttributes(); |
290 | |
291 | myBoxEdgeMinSize = 2.0; |
292 | myCornerMinSize = 2.0; |
293 | myBoxEdgeGap = 0.0; |
294 | myRoundRadius = 0.0; |
295 | |
296 | myToDisplayAxes = true; |
297 | myToDisplayEdges = true; |
298 | myToDisplayVertices = true; |
299 | |
300 | myBoxFacetExtension = 1.0; |
301 | myAxesPadding = 1.0; |
302 | SetSize (70.0); |
303 | } |
304 | |
305 | //======================================================================= |
306 | //function : SetSize |
307 | //purpose : |
308 | //======================================================================= |
309 | void AIS_ViewCube::SetSize (Standard_Real theValue, |
310 | Standard_Boolean theToAdaptAnother) |
311 | { |
312 | const bool isNewSize = Abs (mySize - theValue) > Precision::Confusion(); |
313 | mySize = theValue; |
314 | if (theToAdaptAnother) |
315 | { |
316 | if (myBoxFacetExtension > 0.0) |
317 | { |
318 | SetBoxFacetExtension (mySize * 0.15); |
319 | } |
320 | if (myAxesPadding > 0.0) |
321 | { |
322 | SetAxesPadding (mySize * 0.1); |
323 | } |
324 | SetFontHeight (mySize * 0.16); |
325 | } |
326 | if (isNewSize) |
327 | { |
328 | SetToUpdate(); |
329 | } |
330 | } |
331 | |
332 | //======================================================================= |
333 | //function : SetRoundRadius |
334 | //purpose : |
335 | //======================================================================= |
336 | void AIS_ViewCube::SetRoundRadius (const Standard_Real theValue) |
337 | { |
338 | Standard_OutOfRange_Raise_if (theValue < 0.0 || theValue > 0.5, |
339 | "AIS_ViewCube::SetRoundRadius(): theValue should be in [0; 0.5]"); |
340 | if (Abs (myRoundRadius - theValue) > Precision::Confusion()) |
341 | { |
342 | myRoundRadius = theValue; |
343 | SetToUpdate(); |
344 | } |
345 | } |
346 | |
347 | //======================================================================= |
348 | //function : createRoundRectangleTriangles |
349 | //purpose : |
350 | //======================================================================= |
caa309aa |
351 | void AIS_ViewCube::createRoundRectangleTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris, |
352 | Standard_Integer& theNbNodes, |
353 | Standard_Integer& theNbTris, |
354 | const gp_XY& theSize, |
355 | Standard_Real theRadius, |
356 | const gp_Trsf& theTrsf) |
2108d9a2 |
357 | { |
358 | const Standard_Real aRadius = Min (theRadius, Min (theSize.X(), theSize.Y()) * 0.5); |
359 | const gp_XY aHSize (theSize.X() * 0.5 - aRadius, theSize.Y() * 0.5 - aRadius); |
360 | const gp_Dir aNorm = gp::DZ().Transformed (theTrsf); |
caa309aa |
361 | const Standard_Integer aVertFirst = !theTris.IsNull() ? theTris->VertexNumber() : 0; |
2108d9a2 |
362 | if (aRadius > 0.0) |
363 | { |
364 | const Standard_Integer aNbNodes = (THE_NB_ROUND_SPLITS + 1) * 4 + 1; |
caa309aa |
365 | theNbNodes += aNbNodes; |
366 | theNbTris += aNbNodes; |
367 | if (theTris.IsNull()) |
368 | { |
369 | return; |
370 | } |
2108d9a2 |
371 | |
caa309aa |
372 | theTris->AddVertex (gp_Pnt (0.0, 0.0, 0.0).Transformed (theTrsf)); |
2108d9a2 |
373 | for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter) |
374 | { |
375 | const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (M_PI * 0.5, 0.0, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS)); |
caa309aa |
376 | theTris->AddVertex (gp_Pnt (aHSize.X() + aRadius * Cos (anAngle), aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf)); |
2108d9a2 |
377 | } |
378 | for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter) |
379 | { |
380 | const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (0.0, -M_PI * 0.5, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS)); |
caa309aa |
381 | theTris->AddVertex (gp_Pnt (aHSize.X() + aRadius * Cos (anAngle), -aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf)); |
2108d9a2 |
382 | } |
383 | for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter) |
384 | { |
385 | const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (-M_PI * 0.5, -M_PI, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS)); |
caa309aa |
386 | theTris->AddVertex (gp_Pnt (-aHSize.X() + aRadius * Cos (anAngle), -aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf)); |
2108d9a2 |
387 | } |
388 | for (Standard_Integer aNodeIter = 0; aNodeIter <= THE_NB_ROUND_SPLITS; ++aNodeIter) |
389 | { |
390 | const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (-M_PI, -M_PI * 1.5, Standard_Real(aNodeIter) / Standard_Real(THE_NB_ROUND_SPLITS)); |
caa309aa |
391 | theTris->AddVertex (gp_Pnt (-aHSize.X() + aRadius * Cos (anAngle), aHSize.Y() + aRadius * Sin (anAngle), 0.0).Transformed (theTrsf)); |
2108d9a2 |
392 | } |
393 | |
394 | // split triangle fan |
caa309aa |
395 | theTris->AddTriangleFanEdges (aVertFirst + 1, theTris->VertexNumber(), true); |
2108d9a2 |
396 | } |
397 | else |
398 | { |
caa309aa |
399 | theNbNodes += 4; |
400 | theNbTris += 2; |
401 | if (theTris.IsNull()) |
402 | { |
403 | return; |
404 | } |
405 | |
406 | theTris->AddVertex (gp_Pnt (-aHSize.X(), -aHSize.Y(), 0.0).Transformed (theTrsf)); |
407 | theTris->AddVertex (gp_Pnt (-aHSize.X(), aHSize.Y(), 0.0).Transformed (theTrsf)); |
408 | theTris->AddVertex (gp_Pnt ( aHSize.X(), aHSize.Y(), 0.0).Transformed (theTrsf)); |
409 | theTris->AddVertex (gp_Pnt ( aHSize.X(), -aHSize.Y(), 0.0).Transformed (theTrsf)); |
410 | theTris->AddQuadTriangleEdges (aVertFirst + 1, aVertFirst + 2, aVertFirst + 3, aVertFirst + 4); |
2108d9a2 |
411 | } |
412 | |
caa309aa |
413 | for (Standard_Integer aVertIter = aVertFirst + 1; aVertIter <= theTris->VertexNumber(); ++aVertIter) |
2108d9a2 |
414 | { |
caa309aa |
415 | theTris->SetVertexNormal (aVertIter, -aNorm); |
2108d9a2 |
416 | } |
2108d9a2 |
417 | } |
418 | |
419 | //======================================================================= |
420 | //function : createBoxPartTriangles |
421 | //purpose : |
422 | //======================================================================= |
caa309aa |
423 | void AIS_ViewCube::createBoxPartTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris, |
424 | Standard_Integer& theNbNodes, |
425 | Standard_Integer& theNbTris, |
426 | V3d_TypeOfOrientation theDir) const |
2108d9a2 |
427 | { |
428 | if (IsBoxSide (theDir)) |
429 | { |
caa309aa |
430 | createBoxSideTriangles (theTris, theNbNodes, theNbTris, theDir); |
2108d9a2 |
431 | } |
432 | else if (IsBoxEdge (theDir) |
433 | && myToDisplayEdges) |
434 | { |
caa309aa |
435 | createBoxEdgeTriangles (theTris, theNbNodes, theNbTris, theDir); |
2108d9a2 |
436 | } |
437 | else if (IsBoxCorner (theDir) |
438 | && myToDisplayVertices) |
439 | { |
caa309aa |
440 | createBoxCornerTriangles (theTris, theNbNodes, theNbTris, theDir); |
2108d9a2 |
441 | } |
2108d9a2 |
442 | } |
443 | |
444 | //======================================================================= |
445 | //function : createBoxSideTriangles |
446 | //purpose : |
447 | //======================================================================= |
caa309aa |
448 | void AIS_ViewCube::createBoxSideTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris, |
449 | Standard_Integer& theNbNodes, |
450 | Standard_Integer& theNbTris, |
451 | V3d_TypeOfOrientation theDirection) const |
2108d9a2 |
452 | { |
453 | const gp_Dir aDir = V3d::GetProjAxis (theDirection); |
454 | const gp_Pnt aPos = aDir.XYZ() * (mySize * 0.5 + myBoxFacetExtension); |
455 | const gp_Ax2 aPosition (aPos, aDir.Reversed()); |
456 | |
457 | gp_Ax3 aSystem (aPosition); |
458 | gp_Trsf aTrsf; |
459 | aTrsf.SetTransformation (aSystem, gp_Ax3()); |
460 | |
caa309aa |
461 | createRoundRectangleTriangles (theTris, theNbNodes, theNbTris, |
462 | gp_XY (mySize, mySize), myRoundRadius * mySize, aTrsf); |
2108d9a2 |
463 | } |
464 | |
465 | //======================================================================= |
466 | //function : createBoxEdgeTriangles |
467 | //purpose : |
468 | //======================================================================= |
caa309aa |
469 | void AIS_ViewCube::createBoxEdgeTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris, |
470 | Standard_Integer& theNbNodes, |
471 | Standard_Integer& theNbTris, |
472 | V3d_TypeOfOrientation theDirection) const |
2108d9a2 |
473 | { |
474 | const Standard_Real aThickness = Max (myBoxFacetExtension * gp_XY (1.0, 1.0).Modulus() - myBoxEdgeGap, myBoxEdgeMinSize); |
475 | |
476 | const gp_Dir aDir = V3d::GetProjAxis (theDirection); |
477 | const gp_Pnt aPos = aDir.XYZ() * (mySize * 0.5 * gp_XY (1.0, 1.0).Modulus() + myBoxFacetExtension * Cos (M_PI_4)); |
478 | const gp_Ax2 aPosition (aPos, aDir.Reversed()); |
479 | |
480 | gp_Ax3 aSystem (aPosition); |
481 | gp_Trsf aTrsf; |
482 | aTrsf.SetTransformation (aSystem, gp_Ax3()); |
483 | |
caa309aa |
484 | createRoundRectangleTriangles (theTris, theNbNodes, theNbTris, |
485 | gp_XY (aThickness, mySize), myRoundRadius * mySize, aTrsf); |
2108d9a2 |
486 | } |
487 | |
488 | //======================================================================= |
489 | //function : createBoxCornerTriangles |
490 | //purpose : |
491 | //======================================================================= |
caa309aa |
492 | void AIS_ViewCube::createBoxCornerTriangles (const Handle(Graphic3d_ArrayOfTriangles)& theTris, |
493 | Standard_Integer& theNbNodes, |
494 | Standard_Integer& theNbTris, |
495 | V3d_TypeOfOrientation theDir) const |
2108d9a2 |
496 | { |
497 | const Standard_Real aHSize = mySize * 0.5; |
498 | const gp_Dir aDir = V3d::GetProjAxis (theDir); |
499 | const gp_XYZ aHSizeDir = aDir.XYZ() * (aHSize * gp_Vec (1.0, 1.0, 1.0).Magnitude()); |
caa309aa |
500 | const Standard_Integer aVertFirst = !theTris.IsNull() ? theTris->VertexNumber() : 0; |
2108d9a2 |
501 | if (myRoundRadius > 0.0) |
502 | { |
caa309aa |
503 | theNbNodes += THE_NB_DISK_SLICES + 1; |
504 | theNbTris += THE_NB_DISK_SLICES + 1; |
505 | if (theTris.IsNull()) |
506 | { |
507 | return; |
508 | } |
509 | |
2108d9a2 |
510 | const Standard_Real anEdgeHWidth = myBoxFacetExtension * gp_XY (1.0, 1.0).Modulus() * 0.5; |
511 | const Standard_Real aHeight = anEdgeHWidth * Sqrt (2.0 / 3.0); // tetrahedron height |
512 | const gp_Pnt aPos = aDir.XYZ() * (aHSize * gp_Vec (1.0, 1.0, 1.0).Magnitude() + aHeight); |
513 | const gp_Ax2 aPosition (aPos, aDir.Reversed()); |
514 | gp_Ax3 aSystem (aPosition); |
515 | gp_Trsf aTrsf; |
516 | aTrsf.SetTransformation (aSystem, gp_Ax3()); |
517 | const Standard_Real aRadius = Max (myBoxFacetExtension * 0.5 / Cos (M_PI_4), myCornerMinSize); |
2108d9a2 |
518 | |
caa309aa |
519 | theTris->AddVertex (gp_Pnt (0.0, 0.0, 0.0).Transformed (aTrsf)); |
520 | for (Standard_Integer aNodeIter = 0; aNodeIter < THE_NB_DISK_SLICES; ++aNodeIter) |
521 | { |
522 | const Standard_Real anAngle = NCollection_Lerp<Standard_Real>::Interpolate (2.0 * M_PI, 0.0, Standard_Real(aNodeIter) / Standard_Real(THE_NB_DISK_SLICES)); |
523 | theTris->AddVertex (gp_Pnt (aRadius * Cos (anAngle), aRadius * Sin (anAngle), 0.0).Transformed (aTrsf)); |
524 | } |
525 | theTris->AddTriangleFanEdges (aVertFirst + 1, theTris->VertexNumber(), true); |
2108d9a2 |
526 | } |
527 | else |
528 | { |
caa309aa |
529 | theNbNodes += 3; |
530 | theNbTris += 1; |
531 | if (theTris.IsNull()) |
532 | { |
533 | return; |
534 | } |
535 | |
536 | theTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (aDir.X(), 0.0, 0.0).XYZ()); |
537 | theTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (0.0, aDir.Y(), 0.0).XYZ()); |
538 | theTris->AddVertex (aHSizeDir + myBoxFacetExtension * gp_Dir (0.0, 0.0, aDir.Z()).XYZ()); |
539 | |
540 | const gp_XYZ aNode1 = theTris->Vertice (aVertFirst + 1).XYZ(); |
541 | const gp_XYZ aNode2 = theTris->Vertice (aVertFirst + 2).XYZ(); |
542 | const gp_XYZ aNode3 = theTris->Vertice (aVertFirst + 3).XYZ(); |
543 | const gp_XYZ aNormTri = ((aNode2 - aNode1).Crossed (aNode3 - aNode1)); |
544 | if (aNormTri.Dot (aDir.XYZ()) < 0.0) |
545 | { |
546 | theTris->AddTriangleEdges (aVertFirst + 1, aVertFirst + 3, aVertFirst + 2); |
547 | } |
548 | else |
549 | { |
550 | theTris->AddTriangleEdges (aVertFirst + 1, aVertFirst + 2, aVertFirst + 3); |
551 | } |
2108d9a2 |
552 | } |
553 | |
caa309aa |
554 | for (Standard_Integer aVertIter = aVertFirst + 1; aVertIter <= theTris->VertexNumber(); ++aVertIter) |
2108d9a2 |
555 | { |
caa309aa |
556 | theTris->SetVertexNormal (aVertIter, aDir); |
2108d9a2 |
557 | } |
2108d9a2 |
558 | } |
559 | |
560 | //======================================================================= |
561 | //function : Compute |
562 | //purpose : |
563 | //======================================================================= |
564 | void AIS_ViewCube::Compute (const Handle(PrsMgr_PresentationManager3d)& , |
565 | const Handle(Prs3d_Presentation)& thePrs, |
566 | const Standard_Integer theMode) |
567 | { |
568 | thePrs->SetInfiniteState (true); |
569 | if (theMode != 0) |
570 | { |
571 | return; |
572 | } |
573 | |
574 | const gp_Pnt aLocation = (mySize * 0.5 + myBoxFacetExtension + myAxesPadding) * gp_XYZ (-1.0, -1.0, -1.0); |
575 | |
576 | // Display axes |
577 | if (myToDisplayAxes) |
578 | { |
579 | const Standard_Real anAxisSize = mySize + 2.0 * myBoxFacetExtension + myAxesPadding; |
580 | const Handle(Prs3d_DatumAspect)& aDatumAspect = myDrawer->DatumAspect(); |
581 | for (Standard_Integer anAxisIter = Prs3d_DP_XAxis; anAxisIter <= Prs3d_DP_ZAxis; ++anAxisIter) |
582 | { |
583 | const Prs3d_DatumParts aPart = (Prs3d_DatumParts )anAxisIter; |
584 | if (!aDatumAspect->DrawDatumPart (aPart)) |
585 | { |
586 | continue; |
587 | } |
588 | |
589 | gp_Ax1 anAx1; |
590 | switch (aPart) |
591 | { |
592 | case Prs3d_DP_XAxis: anAx1 = gp_Ax1 (aLocation, gp::DX()); break; |
593 | case Prs3d_DP_YAxis: anAx1 = gp_Ax1 (aLocation, gp::DY()); break; |
594 | case Prs3d_DP_ZAxis: anAx1 = gp_Ax1 (aLocation, gp::DZ()); break; |
595 | default: break; |
596 | } |
597 | |
598 | Handle(Graphic3d_Group) anAxisGroup = thePrs->NewGroup(); |
599 | anAxisGroup->SetGroupPrimitivesAspect (aDatumAspect->ShadingAspect (aPart)->Aspect()); |
600 | |
601 | const Standard_Real anArrowLength = 0.2 * anAxisSize; |
602 | Handle(Graphic3d_ArrayOfTriangles) aTriangleArray = Prs3d_Arrow::DrawShaded (anAx1, 1.0, anAxisSize, 3.0, anArrowLength, THE_NB_ARROW_FACETTES); |
603 | anAxisGroup->AddPrimitiveArray (aTriangleArray); |
604 | |
605 | TCollection_AsciiString anAxisLabel; |
606 | if (aDatumAspect->ToDrawLabels() |
607 | && myAxesLabels.Find (aPart, anAxisLabel) |
608 | && !anAxisLabel.IsEmpty()) |
609 | { |
610 | Handle(Graphic3d_Group) anAxisLabelGroup = thePrs->NewGroup(); |
611 | gp_Pnt aTextOrigin = anAx1.Location().Translated (gp_Vec (anAx1.Direction().X() * (anAxisSize + anArrowLength), |
612 | anAx1.Direction().Y() * (anAxisSize + anArrowLength), |
613 | anAx1.Direction().Z() * (anAxisSize + anArrowLength))); |
614 | Prs3d_Text::Draw (anAxisLabelGroup, aDatumAspect->TextAspect(), TCollection_ExtendedString (anAxisLabel), aTextOrigin); |
615 | } |
616 | } |
617 | |
618 | // Display center |
619 | { |
620 | Handle(Graphic3d_Group) aGroup = thePrs->NewGroup(); |
621 | Handle(Prs3d_ShadingAspect) anAspectCen = new Prs3d_ShadingAspect(); |
622 | anAspectCen->SetColor (Quantity_NOC_WHITE); |
623 | aGroup->SetGroupPrimitivesAspect (anAspectCen->Aspect()); |
624 | Prs3d_ToolSphere aTool (4.0, THE_NB_DISK_SLICES, THE_NB_DISK_SLICES); |
625 | gp_Trsf aTrsf; |
626 | aTrsf.SetTranslation (gp_Vec (gp::Origin(), aLocation)); |
627 | Handle(Graphic3d_ArrayOfTriangles) aCenterArray; |
628 | aTool.FillArray (aCenterArray, aTrsf); |
629 | aGroup->AddPrimitiveArray (aCenterArray); |
630 | } |
631 | } |
632 | |
caa309aa |
633 | // Display box sides |
2108d9a2 |
634 | { |
caa309aa |
635 | Standard_Integer aNbNodes = 0, aNbTris = 0; |
636 | for (Standard_Integer aPartIter = V3d_Xpos; aPartIter <= Standard_Integer(V3d_Zneg); ++aPartIter) |
637 | { |
638 | createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, (V3d_TypeOfOrientation )aPartIter); |
639 | } |
640 | if (aNbNodes > 0) |
641 | { |
642 | Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_VertexNormal); |
643 | Handle(Graphic3d_ArrayOfSegments) aSegs; |
644 | if (myDrawer->FaceBoundaryDraw()) |
645 | { |
646 | aSegs = new Graphic3d_ArrayOfSegments (aNbNodes, aNbNodes * 2, Graphic3d_ArrayFlags_None); |
647 | } |
648 | aNbNodes = aNbTris = 0; |
649 | for (Standard_Integer aPartIter = V3d_Xpos; aPartIter <= Standard_Integer(V3d_Zneg); ++aPartIter) |
650 | { |
651 | Standard_Integer aTriNodesFrom = aTris->VertexNumber(); |
652 | const Standard_Integer aTriFrom = aNbTris; |
653 | createBoxPartTriangles (aTris, aNbNodes, aNbTris, (V3d_TypeOfOrientation )aPartIter); |
654 | if (aSegs.IsNull()) |
655 | { |
656 | continue; |
657 | } |
658 | |
659 | const Standard_Integer aFirstNode = aSegs->VertexNumber(); |
660 | for (Standard_Integer aVertIter = (aNbTris - aTriFrom) > 2 ? aTriNodesFrom + 2 : aTriNodesFrom + 1; // skip triangle fan center |
661 | aVertIter <= aTris->VertexNumber(); ++aVertIter) |
662 | { |
663 | aSegs->AddVertex (aTris->Vertice (aVertIter)); |
664 | } |
665 | aSegs->AddPolylineEdges (aFirstNode + 1, aSegs->VertexNumber(), true); |
666 | } |
2108d9a2 |
667 | |
caa309aa |
668 | { |
669 | Handle(Graphic3d_Group) aGroupSides = thePrs->NewGroup(); |
670 | aGroupSides->SetClosed (true); // should be replaced by forced back-face culling aspect |
671 | aGroupSides->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect()); |
672 | aGroupSides->AddPrimitiveArray (aTris); |
673 | } |
2108d9a2 |
674 | |
caa309aa |
675 | if (!aSegs.IsNull()) |
676 | { |
677 | Handle(Graphic3d_Group) aGroupSegs = thePrs->NewGroup(); |
678 | aGroupSegs->SetGroupPrimitivesAspect (myDrawer->FaceBoundaryAspect()->Aspect()); |
679 | aGroupSegs->AddPrimitiveArray (aSegs); |
680 | } |
681 | } |
2108d9a2 |
682 | |
caa309aa |
683 | // Display box sides labels |
2108d9a2 |
684 | Handle(Graphic3d_Group) aTextGroup = thePrs->NewGroup(); |
2108d9a2 |
685 | aTextGroup->SetGroupPrimitivesAspect (myDrawer->TextAspect()->Aspect()); |
caa309aa |
686 | for (Standard_Integer aPartIter = V3d_Xpos; aPartIter <= Standard_Integer(V3d_Zneg); ++aPartIter) |
2108d9a2 |
687 | { |
688 | const V3d_TypeOfOrientation anOrient = (V3d_TypeOfOrientation )aPartIter; |
caa309aa |
689 | |
690 | TCollection_AsciiString aLabel; |
691 | if (!myBoxSideLabels.Find (anOrient, aLabel) |
692 | || aLabel.IsEmpty()) |
2108d9a2 |
693 | { |
caa309aa |
694 | continue; |
695 | } |
696 | |
697 | const gp_Dir aDir = V3d::GetProjAxis (anOrient); |
698 | gp_Dir anUp = myIsYup ? gp::DY() : gp::DZ(); |
699 | if (myIsYup) |
700 | { |
701 | if (anOrient == V3d_Ypos |
702 | || anOrient == V3d_Yneg) |
2108d9a2 |
703 | { |
caa309aa |
704 | anUp = -gp::DZ(); |
2108d9a2 |
705 | } |
caa309aa |
706 | } |
707 | else |
708 | { |
709 | if (anOrient == V3d_Zpos) |
2108d9a2 |
710 | { |
caa309aa |
711 | anUp = gp::DY(); |
2108d9a2 |
712 | } |
caa309aa |
713 | else if (anOrient == V3d_Zneg) |
2108d9a2 |
714 | { |
caa309aa |
715 | anUp = -gp::DY(); |
2108d9a2 |
716 | } |
717 | } |
caa309aa |
718 | |
719 | const Standard_Real anOffset = 2.0; // extra offset to avoid overlapping with triangulation |
720 | const gp_Pnt aPos = aDir.XYZ() * (mySize * 0.5 + myBoxFacetExtension + anOffset); |
721 | const gp_Ax2 aPosition (aPos, aDir, anUp.Crossed (aDir)); |
b383a61f |
722 | |
723 | Handle(Graphic3d_Text) aText = new Graphic3d_Text ((Standard_ShortReal)myDrawer->TextAspect()->Height()); |
724 | aText->SetText (aLabel); |
725 | aText->SetOrientation (aPosition); |
726 | aText->SetOwnAnchorPoint (false); |
727 | aText->SetHorizontalAlignment(myDrawer->TextAspect()->HorizontalJustification()); |
728 | aText->SetVerticalAlignment (myDrawer->TextAspect()->VerticalJustification()); |
729 | aTextGroup->AddText (aText); |
caa309aa |
730 | } |
731 | } |
732 | |
733 | // Display box edges |
734 | { |
735 | Standard_Integer aNbNodes = 0, aNbTris = 0; |
736 | for (Standard_Integer aPartIter = V3d_XposYpos; aPartIter <= Standard_Integer(V3d_YposZneg); ++aPartIter) |
737 | { |
738 | createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, (V3d_TypeOfOrientation )aPartIter); |
739 | } |
740 | if (aNbNodes > 0) |
741 | { |
742 | Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_VertexNormal); |
743 | aNbNodes = aNbTris = 0; |
744 | for (Standard_Integer aPartIter = V3d_XposYpos; aPartIter <= Standard_Integer(V3d_YposZneg); ++aPartIter) |
745 | { |
746 | const V3d_TypeOfOrientation anOrient = (V3d_TypeOfOrientation )aPartIter; |
747 | createBoxPartTriangles (aTris, aNbNodes, aNbTris, anOrient); |
748 | } |
749 | |
750 | Handle(Graphic3d_Group) aGroupEdges = thePrs->NewGroup(); |
751 | aGroupEdges->SetClosed (true); |
752 | aGroupEdges->SetGroupPrimitivesAspect (myBoxEdgeAspect->Aspect()); |
753 | aGroupEdges->AddPrimitiveArray (aTris); |
754 | } |
755 | } |
756 | |
757 | // Display box corners |
758 | { |
759 | Standard_Integer aNbNodes = 0, aNbTris = 0; |
760 | for (Standard_Integer aPartIter = V3d_XposYposZpos; aPartIter <= Standard_Integer(V3d_XnegYnegZneg); ++aPartIter) |
761 | { |
762 | createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, (V3d_TypeOfOrientation )aPartIter); |
763 | } |
764 | if (aNbNodes > 0) |
765 | { |
766 | Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_VertexNormal); |
767 | aNbNodes = aNbTris = 0; |
768 | for (Standard_Integer aPartIter = V3d_XposYposZpos; aPartIter <= Standard_Integer(V3d_XnegYnegZneg); ++aPartIter) |
769 | { |
770 | const V3d_TypeOfOrientation anOrient = (V3d_TypeOfOrientation )aPartIter; |
771 | createBoxPartTriangles (aTris, aNbNodes, aNbTris, anOrient); |
772 | } |
773 | |
774 | Handle(Graphic3d_Group) aGroupCorners = thePrs->NewGroup(); |
775 | aGroupCorners->SetClosed (true); |
776 | aGroupCorners->SetGroupPrimitivesAspect (myBoxCornerAspect->Aspect()); |
777 | aGroupCorners->AddPrimitiveArray (aTris); |
2108d9a2 |
778 | } |
779 | } |
780 | } |
781 | |
782 | //======================================================================= |
783 | //function : ComputeSelection |
784 | //purpose : |
785 | //======================================================================= |
786 | void AIS_ViewCube::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection, |
787 | const Standard_Integer theMode) |
788 | { |
789 | if (theMode != 0) |
790 | { |
791 | return; |
792 | } |
793 | |
794 | for (Standard_Integer aPartIter = 0; aPartIter <= Standard_Integer(V3d_XnegYnegZneg); ++aPartIter) |
795 | { |
796 | const V3d_TypeOfOrientation anOri = (V3d_TypeOfOrientation )aPartIter; |
caa309aa |
797 | Standard_Integer aNbNodes = 0, aNbTris = 0; |
798 | createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, anOri); |
799 | if (aNbNodes <= 0) |
2108d9a2 |
800 | { |
caa309aa |
801 | continue; |
2108d9a2 |
802 | } |
caa309aa |
803 | |
804 | Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_None); |
805 | aNbNodes = aNbTris = 0; |
806 | createBoxPartTriangles (aTris, aNbNodes, aNbTris, anOri); |
807 | |
808 | Standard_Integer aSensitivity = 2; |
809 | if (IsBoxCorner (anOri)) |
810 | { |
811 | aSensitivity = 8; |
812 | } |
813 | else if (IsBoxEdge (anOri)) |
814 | { |
815 | aSensitivity = 4; |
816 | } |
817 | Handle(AIS_ViewCubeOwner) anOwner = new AIS_ViewCubeOwner (this, anOri); |
818 | Handle(AIS_ViewCubeSensitive) aTriSens = new AIS_ViewCubeSensitive (anOwner, aTris); |
819 | aTriSens->SetSensitivityFactor (aSensitivity); |
820 | theSelection->Add (aTriSens); |
2108d9a2 |
821 | } |
822 | } |
823 | |
824 | //======================================================================= |
825 | //function : HasAnimation |
826 | //purpose : |
827 | //======================================================================= |
828 | Standard_Boolean AIS_ViewCube::HasAnimation() const |
829 | { |
830 | return !myViewAnimation->IsStopped(); |
831 | } |
832 | |
caa309aa |
833 | //======================================================================= |
834 | //function : viewFitAll |
835 | //purpose : |
836 | //======================================================================= |
837 | void AIS_ViewCube::viewFitAll (const Handle(V3d_View)& theView, |
838 | const Handle(Graphic3d_Camera)& theCamera) |
839 | { |
840 | Bnd_Box aBndBox = myToFitSelected ? GetContext()->BoundingBoxOfSelection() : theView->View()->MinMaxValues(); |
841 | if (aBndBox.IsVoid() |
842 | && myToFitSelected) |
843 | { |
844 | aBndBox = theView->View()->MinMaxValues(); |
845 | } |
846 | if (!aBndBox.IsVoid()) |
847 | { |
848 | theView->FitMinMax (theCamera, aBndBox, 0.01, 10.0 * Precision::Confusion()); |
849 | } |
850 | } |
851 | |
2108d9a2 |
852 | //======================================================================= |
853 | //function : StartAnimation |
854 | //purpose : |
855 | //======================================================================= |
856 | void AIS_ViewCube::StartAnimation (const Handle(AIS_ViewCubeOwner)& theOwner) |
857 | { |
858 | Handle(V3d_View) aView = GetContext()->LastActiveView(); |
859 | if (theOwner.IsNull() |
860 | || aView.IsNull()) |
861 | { |
862 | return; |
863 | } |
864 | |
865 | myStartState->Copy (aView->Camera()); |
866 | myEndState ->Copy (aView->Camera()); |
867 | |
868 | { |
caa309aa |
869 | { |
870 | Handle(Graphic3d_Camera) aBackupCamera = aView->Camera(); |
871 | const bool wasImmediateUpdate = aView->SetImmediateUpdate (false); |
872 | aView->SetCamera (myEndState); |
873 | aView->SetProj (theOwner->MainOrientation(), myIsYup); |
874 | aView->SetCamera (aBackupCamera); |
875 | aView->SetImmediateUpdate (wasImmediateUpdate); |
876 | } |
2108d9a2 |
877 | |
caa309aa |
878 | const gp_Dir aNewDir = myEndState->Direction(); |
2108d9a2 |
879 | if (!myToResetCameraUp |
caa309aa |
880 | && !aNewDir.IsEqual (myStartState->Direction(), Precision::Angular())) |
2108d9a2 |
881 | { |
882 | // find the Up direction closest to current instead of default one |
883 | const gp_Ax1 aNewDirAx1 (gp::Origin(), aNewDir); |
caa309aa |
884 | const gp_Dir anOldUp = myStartState->Up(); |
2108d9a2 |
885 | const gp_Dir anUpList[4] = |
886 | { |
caa309aa |
887 | myEndState->Up(), |
888 | myEndState->Up().Rotated (aNewDirAx1, M_PI_2), |
889 | myEndState->Up().Rotated (aNewDirAx1, M_PI), |
890 | myEndState->Up().Rotated (aNewDirAx1, M_PI * 1.5), |
2108d9a2 |
891 | }; |
892 | |
893 | Standard_Real aBestAngle = Precision::Infinite(); |
894 | gp_Dir anUpBest; |
895 | for (Standard_Integer anUpIter = 0; anUpIter < 4; ++anUpIter) |
896 | { |
897 | Standard_Real anAngle = anUpList[anUpIter].Angle (anOldUp); |
898 | if (aBestAngle > anAngle) |
899 | { |
900 | aBestAngle = anAngle; |
901 | anUpBest = anUpList[anUpIter]; |
902 | } |
903 | } |
caa309aa |
904 | myEndState->SetUp (anUpBest); |
2108d9a2 |
905 | } |
906 | |
caa309aa |
907 | viewFitAll (aView, myEndState); |
2108d9a2 |
908 | } |
909 | |
910 | myViewAnimation->SetView (aView); |
911 | myViewAnimation->SetCameraStart (myStartState); |
912 | myViewAnimation->SetCameraEnd (myEndState); |
913 | myViewAnimation->SetOwnDuration (myDuration); |
914 | myViewAnimation->StartTimer (0.0, 1.0, true, false); |
915 | } |
916 | |
917 | //======================================================================= |
918 | //function : updateAnimation |
919 | //purpose : |
920 | //======================================================================= |
921 | Standard_Boolean AIS_ViewCube::updateAnimation() |
922 | { |
923 | const Standard_Real aPts = myViewAnimation->UpdateTimer(); |
924 | if (aPts >= myDuration) |
925 | { |
926 | myViewAnimation->Stop(); |
927 | onAnimationFinished(); |
928 | myViewAnimation->SetView (Handle(V3d_View)()); |
929 | return Standard_False; |
930 | } |
931 | return Standard_True; |
932 | } |
933 | |
934 | //======================================================================= |
935 | //function : UpdateAnimation |
936 | //purpose : |
937 | //======================================================================= |
938 | Standard_Boolean AIS_ViewCube::UpdateAnimation (const Standard_Boolean theToUpdate) |
939 | { |
940 | Handle(V3d_View) aView = myViewAnimation->View(); |
941 | if (!HasAnimation() |
942 | || !updateAnimation()) |
943 | { |
944 | return Standard_False; |
945 | } |
946 | |
947 | if (theToUpdate |
948 | && !aView.IsNull()) |
949 | { |
950 | aView->IsInvalidated() ? aView->Redraw() : aView->RedrawImmediate(); |
951 | } |
952 | |
953 | onAfterAnimation(); |
954 | return Standard_True; |
955 | } |
956 | |
957 | //======================================================================= |
958 | //function : HandleClick |
959 | //purpose : |
960 | //======================================================================= |
961 | void AIS_ViewCube::HandleClick (const Handle(AIS_ViewCubeOwner)& theOwner) |
962 | { |
963 | if (!myToAutoStartAnim) |
964 | { |
965 | return; |
966 | } |
967 | |
968 | StartAnimation (theOwner); |
969 | if (!myIsFixedAnimation) |
970 | { |
971 | return; |
972 | } |
973 | for (; HasAnimation(); ) |
974 | { |
975 | UpdateAnimation (true); |
976 | } |
977 | } |
978 | |
979 | //======================================================================= |
980 | //function : HilightOwnerWithColor |
981 | //purpose : |
982 | //======================================================================= |
983 | void AIS_ViewCube::HilightOwnerWithColor (const Handle(PrsMgr_PresentationManager3d)& thePrsMgr, |
984 | const Handle(Prs3d_Drawer)& theStyle, |
985 | const Handle(SelectMgr_EntityOwner)& theOwner) |
986 | { |
987 | if (theOwner.IsNull() |
988 | || !thePrsMgr->IsImmediateModeOn()) |
989 | { |
990 | return; |
991 | } |
992 | |
993 | const Graphic3d_ZLayerId aLayer = theStyle->ZLayer() != Graphic3d_ZLayerId_UNKNOWN ? theStyle->ZLayer() : myDrawer->ZLayer(); |
994 | const AIS_ViewCubeOwner* aCubeOwner = dynamic_cast<AIS_ViewCubeOwner* >(theOwner.get()); |
995 | |
996 | Handle(Prs3d_Presentation) aHiPrs = GetHilightPresentation (thePrsMgr); |
997 | aHiPrs->Clear(); |
998 | aHiPrs->CStructure()->ViewAffinity = thePrsMgr->StructureManager()->ObjectAffinity (Handle(Standard_Transient)(this)); |
999 | aHiPrs->SetTransformPersistence (TransformPersistence()); |
1000 | aHiPrs->SetZLayer (aLayer); |
1001 | |
1002 | { |
1003 | Handle(Graphic3d_Group) aGroup = aHiPrs->NewGroup(); |
1004 | aGroup->SetGroupPrimitivesAspect (theStyle->ShadingAspect()->Aspect()); |
caa309aa |
1005 | Standard_Integer aNbNodes = 0, aNbTris = 0; |
1006 | createBoxPartTriangles (Handle(Graphic3d_ArrayOfTriangles)(), aNbNodes, aNbTris, aCubeOwner->MainOrientation()); |
1007 | if (aNbNodes > 0) |
2108d9a2 |
1008 | { |
caa309aa |
1009 | Handle(Graphic3d_ArrayOfTriangles) aTris = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, Graphic3d_ArrayFlags_None); |
1010 | aNbNodes = aNbTris = 0; |
1011 | createBoxPartTriangles (aTris, aNbNodes, aNbTris, aCubeOwner->MainOrientation()); |
2108d9a2 |
1012 | aGroup->AddPrimitiveArray (aTris); |
1013 | } |
1014 | } |
1015 | |
1016 | if (thePrsMgr->IsImmediateModeOn()) |
1017 | { |
1018 | thePrsMgr->AddToImmediateList (aHiPrs); |
1019 | } |
1020 | } |
1021 | |
1022 | //======================================================================= |
1023 | //function : HilightSelected |
1024 | //purpose : |
1025 | //======================================================================= |
1026 | void AIS_ViewCube::HilightSelected (const Handle(PrsMgr_PresentationManager3d)& , |
1027 | const SelectMgr_SequenceOfOwner& theSeq) |
1028 | { |
1029 | // this method should never be called since AIS_InteractiveObject::HandleClick() has been overridden |
1030 | if (theSeq.Size() == 1) |
1031 | { |
1032 | //HandleClick (Handle(AIS_ViewCubeOwner)::DownCast (theSeq.First())); |
1033 | } |
1034 | } |