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