0028010: Visualization, Prs3d_Arrow - add Shading presentation builder
[occt.git] / src / V3d / V3d_Trihedron.cxx
CommitLineData
caf231b0 1// Created on: 2016-10-11
2// Created by: Ilya SEVRIKOV
3// Copyright (c) 2016 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 <V3d_Trihedron.hxx>
17
18#include <gp_Ax3.hxx>
19#include <Graphic3d_ArrayOfPolylines.hxx>
20#include <Graphic3d_ArrayOfSegments.hxx>
21#include <Graphic3d_ArrayOfTriangles.hxx>
22#include <Graphic3d_Camera.hxx>
23#include <Graphic3d_TransformPers.hxx>
24#include <Prs3d.hxx>
62ef08df 25#include <Prs3d_Arrow.hxx>
caf231b0 26#include <Prs3d_LineAspect.hxx>
27#include <Prs3d_ShadingAspect.hxx>
28#include <Prs3d_Text.hxx>
29#include <Prs3d_TextAspect.hxx>
62ef08df 30#include <Prs3d_ToolSphere.hxx>
caf231b0 31#include <V3d_View.hxx>
32
33IMPLEMENT_STANDARD_RTTIEXT (V3d_Trihedron, Standard_Transient)
34
35namespace
36{
37 //! Compensates difference between old implementation (without transform persistence) and current implementation.
38 static const Standard_Real THE_INTERNAL_SCALE_FACTOR = 500.0;
39
40 static const Standard_ShortReal THE_CYLINDER_LENGTH = 0.75f;
41 static const Standard_Integer THE_CIRCLE_SERMENTS_NB = 24;
42 static const Standard_Real THE_CIRCLE_SEGMENT_ANGLE = 2.0 * M_PI / THE_CIRCLE_SERMENTS_NB;
43}
44
45//! Dummy implementation of Graphic3d_Structure overriding ::Compute() method for handling Device Lost.
46class V3d_Trihedron::TrihedronStructure : public Graphic3d_Structure
47{
48public:
49 //! Main constructor.
50 TrihedronStructure (const Handle(Graphic3d_StructureManager)& theManager, V3d_Trihedron* theTrihedron)
51 : Graphic3d_Structure (theManager), myTrihedron (theTrihedron) {}
52
53 //! Override method to redirect to V3d_Trihedron.
54 virtual void Compute() Standard_OVERRIDE { myTrihedron->compute(); }
55
56private:
57 V3d_Trihedron* myTrihedron;
58};
59
60// ============================================================================
61// function : V3d_Trihedron
62// purpose :
63// ============================================================================
64V3d_Trihedron::V3d_Trihedron()
65: myScale (1.0),
66 myRatio (0.8),
67 myDiameter (0.05),
68 myNbFacettes (12),
69 myIsWireframe(Standard_False),
70 myToCompute (Standard_True)
71{
72 myTransformPers = new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_LOWER);
73 SetPosition (Aspect_TOTP_LEFT_LOWER);
74
75 // Set material.
76 Graphic3d_MaterialAspect aShadingMaterial;
77 aShadingMaterial.SetReflectionModeOff (Graphic3d_TOR_SPECULAR);
78 aShadingMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT);
79
80 for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
81 {
82 myArrowShadingAspects[anIt] = new Prs3d_ShadingAspect();
83 myArrowLineAspects[anIt] = new Prs3d_LineAspect (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0);
84
85 // mark texture map ON to actually disable environment map
86 myArrowShadingAspects[anIt]->Aspect()->SetTextureMapOn();
87 myArrowShadingAspects[anIt]->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
88 myArrowShadingAspects[anIt]->SetMaterial (aShadingMaterial);
89 }
90 myArrowShadingAspects[0]->SetColor (Quantity_NOC_RED);
91 myArrowLineAspects [0]->SetColor (Quantity_NOC_RED);
92 myArrowShadingAspects[1]->SetColor (Quantity_NOC_GREEN);
93 myArrowLineAspects [1]->SetColor (Quantity_NOC_GREEN);
94 myArrowShadingAspects[2]->SetColor (Quantity_NOC_BLUE1);
95 myArrowLineAspects [2]->SetColor (Quantity_NOC_BLUE1);
96
97 mySphereShadingAspect = new Prs3d_ShadingAspect();
98 mySphereLineAspect = new Prs3d_LineAspect (Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0);
99
100 // mark texture map ON to actually disable environment map
101 mySphereShadingAspect->Aspect()->SetTextureMapOn();
102 mySphereShadingAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
103 mySphereShadingAspect->SetMaterial (aShadingMaterial);
104 mySphereShadingAspect->SetColor (Quantity_NOC_WHITE);
105
106 myTextAspect = new Prs3d_TextAspect();
107 myTextAspect->SetFont ("Courier");
108 myTextAspect->SetHeight (16);
109 myTextAspect->SetHorizontalJustification (Graphic3d_HTA_LEFT);
110 myTextAspect->SetVerticalJustification (Graphic3d_VTA_BOTTOM);
111}
112
113// ============================================================================
114// function : SetLabelsColor
115// purpose :
116// ============================================================================
117void V3d_Trihedron::SetLabelsColor (const Quantity_Color& theColor)
118{
119 myTextAspect->SetColor (theColor);
120}
121
122// ============================================================================
123// function : SetArrowsColor
124// purpose :
125// ============================================================================
126void V3d_Trihedron::SetArrowsColor (const Quantity_Color& theXColor,
127 const Quantity_Color& theYColor,
128 const Quantity_Color& theZColor)
129{
130 const Quantity_Color aColors[3] = { theXColor, theYColor, theZColor };
131 for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
132 {
133 myArrowShadingAspects[anIt]->SetColor (aColors[anIt]);
134 myArrowLineAspects [anIt]->SetColor (aColors[anIt]);
135 }
136}
137
138// ============================================================================
139// function : SetScale
140// purpose :
141// ============================================================================
142void V3d_Trihedron::SetScale (const Standard_Real theScale)
143{
144 if (Abs (myScale - theScale) > Precision::Confusion())
145 {
146 invalidate();
147 }
148 myScale = theScale;
149}
150
151// =======================================================================
152// function : SetSizeRatio
153// purpose :
154// =======================================================================
155void V3d_Trihedron::SetSizeRatio (const Standard_Real theRatio)
156{
157 if (Abs (myRatio - theRatio) > Precision::Confusion())
158 {
159 invalidate();
160 }
161 myRatio = theRatio;
162}
163
164// =======================================================================
165// function : SetArrowDiameter
166// purpose :
167// =======================================================================
168void V3d_Trihedron::SetArrowDiameter (const Standard_Real theDiam)
169{
170 if (Abs (myDiameter - theDiam) > Precision::Confusion())
171 {
172 invalidate();
173 }
174 myDiameter = theDiam;
175}
176
177// =======================================================================
178// function : SetNbFacets
179// purpose :
180// =======================================================================
181void V3d_Trihedron::SetNbFacets (const Standard_Integer theNbFacets)
182{
183 if (Abs (myNbFacettes - theNbFacets) > 0)
184 {
185 invalidate();
186 }
187 myNbFacettes = theNbFacets;
188}
189
190// ============================================================================
191// function : Display
192// purpose :
193// ============================================================================
194void V3d_Trihedron::Display (const V3d_View& theView)
195{
196 if (myStructure.IsNull())
197 {
198 myStructure = new TrihedronStructure (theView.Viewer()->StructureManager(), this);
199 myStructure->SetTransformPersistence (myTransformPers);
200 myStructure->SetZLayer (Graphic3d_ZLayerId_Topmost);
201 myStructure->SetDisplayPriority (9);
202 myStructure->SetInfiniteState (Standard_True);
203 myStructure->CStructure()->ViewAffinity = new Graphic3d_ViewAffinity();
204 myStructure->CStructure()->ViewAffinity->SetVisible (Standard_False);
205 myStructure->CStructure()->ViewAffinity->SetVisible (theView.View()->Identification(), true);
206 }
207 if (myToCompute)
208 {
209 compute();
210 }
211
212 myStructure->Display();
213}
214
215// ============================================================================
216// function : Erase
217// purpose :
218// ============================================================================
219void V3d_Trihedron::Erase()
220{
221 if (!myStructure.IsNull())
222 {
223 myStructure->Erase();
224 myStructure.Nullify();
225 }
226}
227
228// ============================================================================
229// function : SetPosition
230// purpose :
231// ============================================================================
232void V3d_Trihedron::SetPosition (const Aspect_TypeOfTriedronPosition thePosition)
233{
234 Graphic3d_Vec2i anOffset (0, 0);
235 if ((thePosition & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0)
236 {
237 anOffset.x() = static_cast<Standard_Integer> (myScale * THE_INTERNAL_SCALE_FACTOR);
238 }
239 if ((thePosition & (Aspect_TOTP_TOP | Aspect_TOTP_BOTTOM)) != 0)
240 {
241 anOffset.y() = static_cast<Standard_Integer> (myScale * THE_INTERNAL_SCALE_FACTOR);
242 }
243
244 myTransformPers->SetCorner2d (thePosition);
245 myTransformPers->SetOffset2d (anOffset);
246}
247
248// ============================================================================
249// function : compute
250// purpose :
251// ============================================================================
252void V3d_Trihedron::compute()
253{
254 myStructure->GraphicClear (Standard_False);
255
256 // Create trihedron.
62ef08df 257 const Standard_Real aScale = myScale * myRatio * THE_INTERNAL_SCALE_FACTOR;
258 const Standard_Real aCylinderLength = aScale * THE_CYLINDER_LENGTH;
259 const Standard_Real aCylinderRadius = aScale * myDiameter;
260 const Standard_Real aConeRadius = myIsWireframe ? aCylinderRadius : (aCylinderRadius * 2.0);
261 const Standard_Real aConeLength = aScale * (1.0 - THE_CYLINDER_LENGTH);
262 const Standard_Real aSphereRadius = aCylinderRadius * 2.0;
263 const Standard_Real aRayon = aScale / 30.0;
caf231b0 264 {
265 Handle(Graphic3d_Group) aSphereGroup = myStructure->NewGroup();
266
267 // Display origin.
268 if (myIsWireframe)
269 {
270 Handle(Graphic3d_ArrayOfPolylines) anCircleArray = new Graphic3d_ArrayOfPolylines (THE_CIRCLE_SERMENTS_NB + 2);
271 for (Standard_Integer anIt = THE_CIRCLE_SERMENTS_NB; anIt >= 0; --anIt)
272 {
273 anCircleArray->AddVertex (aRayon * Sin (anIt * THE_CIRCLE_SEGMENT_ANGLE),
274 aRayon * Cos (anIt * THE_CIRCLE_SEGMENT_ANGLE), 0.0);
275 }
276 anCircleArray->AddVertex (aRayon * Sin (THE_CIRCLE_SERMENTS_NB * THE_CIRCLE_SEGMENT_ANGLE),
277 aRayon * Cos (THE_CIRCLE_SERMENTS_NB * THE_CIRCLE_SEGMENT_ANGLE), 0.0);
278
279 aSphereGroup->SetGroupPrimitivesAspect (mySphereLineAspect->Aspect());
280 aSphereGroup->AddPrimitiveArray (anCircleArray);
281 }
282 else
283 {
284 gp_Trsf aSphereTransform;
285 aSphereGroup->SetGroupPrimitivesAspect (mySphereShadingAspect->Aspect());
62ef08df 286 aSphereGroup->AddPrimitiveArray (Prs3d_ToolSphere::Create (aSphereRadius, myNbFacettes, myNbFacettes, aSphereTransform));
caf231b0 287 }
288 }
289
290 // Display axes.
291 {
292 const gp_Ax1 anAxes[3] = { gp::OX(), gp::OY(), gp::OZ() };
293 for (Standard_Integer anIter = 0; anIter < 3; ++anIter)
294 {
295 Handle(Graphic3d_Group) anAxisGroup = myStructure->NewGroup();
caf231b0 296 if (myIsWireframe)
297 {
62ef08df 298 // create a tube
caf231b0 299 Handle(Graphic3d_ArrayOfPrimitives) anArray = new Graphic3d_ArrayOfSegments (2);
300 anArray->AddVertex (0.0f, 0.0f, 0.0f);
301 anArray->AddVertex (anAxes[anIter].Direction().XYZ() * aCylinderLength);
302
303 anAxisGroup->SetGroupPrimitivesAspect (myArrowLineAspects[anIter]->Aspect());
304 anAxisGroup->AddPrimitiveArray (anArray);
305 }
caf231b0 306
62ef08df 307 Handle(Graphic3d_ArrayOfTriangles) aTriangles = Prs3d_Arrow::DrawShaded (anAxes[anIter],
308 myIsWireframe ? 0.0 : aCylinderRadius,
309 aCylinderLength + aConeLength,
310 aConeRadius,
311 aConeLength,
312 myNbFacettes);
313 anAxisGroup->SetGroupPrimitivesAspect (myArrowShadingAspects[anIter]->Aspect());
314 anAxisGroup->AddPrimitiveArray (aTriangles);
caf231b0 315 }
316 }
317
318 // Display labels.
319 {
320 Handle(Graphic3d_Group) aLabelGroup = myStructure->NewGroup();
321 const TCollection_ExtendedString aLabels[3] = { "X", "Y", "Z" };
322 const gp_Pnt aPoints[3] = { gp_Pnt (aScale + 2.0 * aRayon, 0.0, -aRayon),
323 gp_Pnt ( aRayon, aScale + 3.0 * aRayon, 2.0 * aRayon),
324 gp_Pnt ( -2.0 * aRayon, 0.5 * aRayon, aScale + 3.0 * aRayon) };
325 for (Standard_Integer anAxisIter = 0; anAxisIter < 3; ++anAxisIter)
326 {
327 Prs3d_Text::Draw (aLabelGroup, myTextAspect, aLabels[anAxisIter], aPoints[anAxisIter]);
328 }
329 }
330}