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>
25 #include <Prs3d_Arrow.hxx>
26 #include <Prs3d_ShadingAspect.hxx>
27 #include <Prs3d_Text.hxx>
28 #include <Prs3d_TextAspect.hxx>
29 #include <Prs3d_ToolSphere.hxx>
30 #include <V3d_View.hxx>
31 #include <V3d_Viewer.hxx>
32
33 IMPLEMENT_STANDARD_RTTIEXT (V3d_Trihedron, Standard_Transient)
34
35 namespace
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 //! Create new or return existing group in the structure at specified position.
45 //! @param theStruct [in] structure holding graphic groups
46 //! @param theGroupIndex [in/out] group position, will be incremented as output
addGroup(const Handle (Graphic3d_Structure)& theStruct,Standard_Integer & theGroupIter)47 static Handle(Graphic3d_Group) addGroup (const Handle(Graphic3d_Structure)& theStruct,
48 Standard_Integer& theGroupIter)
49 {
50 const Graphic3d_SequenceOfGroup& aGroups = theStruct->Groups();
51 const Standard_Integer aGroupIndex = theGroupIter++;
52 if (!aGroups.IsEmpty()
53 && aGroupIndex <= aGroups.Upper())
54 {
55 return aGroups.Value (aGroupIndex);
56 }
57
58 return theStruct->NewGroup();
59 }
60 }
61
62 //! Dummy implementation of Graphic3d_Structure overriding ::Compute() method for handling Device Lost.
63 class V3d_Trihedron::TrihedronStructure : public Graphic3d_Structure
64 {
65 public:
66 //! Main constructor.
TrihedronStructure(const Handle (Graphic3d_StructureManager)& theManager,V3d_Trihedron * theTrihedron)67 TrihedronStructure (const Handle(Graphic3d_StructureManager)& theManager, V3d_Trihedron* theTrihedron)
68 : Graphic3d_Structure (theManager), myTrihedron (theTrihedron) {}
69
70 //! Override method to redirect to V3d_Trihedron.
Compute()71 virtual void Compute() Standard_OVERRIDE { myTrihedron->compute(); }
72
73 private:
74 V3d_Trihedron* myTrihedron;
75 };
76
77 // ============================================================================
78 // function : V3d_Trihedron
79 // purpose :
80 // ============================================================================
V3d_Trihedron()81 V3d_Trihedron::V3d_Trihedron()
82 : myScale (1.0),
83 myRatio (0.8),
84 myDiameter (0.05),
85 myNbFacettes (12),
86 myIsWireframe(Standard_False),
87 myToCompute (Standard_True)
88 {
89 myTransformPers = new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_LOWER);
90 SetPosition (Aspect_TOTP_LEFT_LOWER);
91
92 // Set material.
93 Graphic3d_MaterialAspect aShadingMaterial;
94 aShadingMaterial.SetSpecularColor(Quantity_NOC_BLACK);
95 aShadingMaterial.SetMaterialType (Graphic3d_MATERIAL_ASPECT);
96
97 for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
98 {
99 myArrowShadingAspects[anIt] = new Prs3d_ShadingAspect();
100 myTextAspects[anIt] = new Prs3d_TextAspect();
101
102 // mark texture map ON to actually disable environment map
103 myArrowShadingAspects[anIt]->Aspect()->SetTextureMapOn();
104 myArrowShadingAspects[anIt]->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
105 myArrowShadingAspects[anIt]->SetMaterial (aShadingMaterial);
106
107 myTextAspects[anIt]->SetFont (Font_NOF_ASCII_MONO);
108 myTextAspects[anIt]->SetHeight (16);
109 myTextAspects[anIt]->SetHorizontalJustification (Graphic3d_HTA_LEFT);
110 myTextAspects[anIt]->SetVerticalJustification (Graphic3d_VTA_BOTTOM);
111 }
112 myArrowShadingAspects[V3d_X]->SetColor (Quantity_NOC_RED);
113 myArrowShadingAspects[V3d_Y]->SetColor (Quantity_NOC_GREEN);
114 myArrowShadingAspects[V3d_Z]->SetColor (Quantity_NOC_BLUE);
115
116 myLabels[V3d_X] = "X";
117 myLabels[V3d_Y] = "Y";
118 myLabels[V3d_Z] = "Z";
119
120 mySphereShadingAspect = new Prs3d_ShadingAspect();
121 // mark texture map ON to actually disable environment map
122 mySphereShadingAspect->Aspect()->SetTextureMapOn();
123 mySphereShadingAspect->Aspect()->SetInteriorStyle (Aspect_IS_SOLID);
124 mySphereShadingAspect->SetMaterial (aShadingMaterial);
125 mySphereShadingAspect->SetColor (Quantity_NOC_WHITE);
126 }
127
128 // ============================================================================
129 // function : V3d_Trihedron
130 // purpose :
131 // ============================================================================
~V3d_Trihedron()132 V3d_Trihedron::~V3d_Trihedron()
133 {
134 Erase();
135 }
136
137 // ============================================================================
138 // function : SetLabelsColor
139 // purpose :
140 // ============================================================================
SetLabelsColor(const Quantity_Color & theColor)141 void V3d_Trihedron::SetLabelsColor (const Quantity_Color& theColor)
142 {
143 myTextAspects[V3d_X]->SetColor (theColor);
144 myTextAspects[V3d_Y]->SetColor (theColor);
145 myTextAspects[V3d_Z]->SetColor (theColor);
146 }
147
148 // ============================================================================
149 // function : SetLabels
150 // purpose :
151 // ============================================================================
SetLabels(const TCollection_AsciiString & theX,const TCollection_AsciiString & theY,const TCollection_AsciiString & theZ)152 void V3d_Trihedron::SetLabels (const TCollection_AsciiString& theX,
153 const TCollection_AsciiString& theY,
154 const TCollection_AsciiString& theZ)
155 {
156 if (!myLabels[V3d_X].IsEqual (theX)
157 || !myLabels[V3d_Y].IsEqual (theY)
158 || !myLabels[V3d_Z].IsEqual (theZ))
159 {
160 invalidate();
161 myLabels[V3d_X] = theX;
162 myLabels[V3d_Y] = theY;
163 myLabels[V3d_Z] = theZ;
164 }
165 }
166
167 // ============================================================================
168 // function : SetLabelsColor
169 // purpose :
170 // ============================================================================
SetLabelsColor(const Quantity_Color & theXColor,const Quantity_Color & theYColor,const Quantity_Color & theZColor)171 void V3d_Trihedron::SetLabelsColor (const Quantity_Color& theXColor,
172 const Quantity_Color& theYColor,
173 const Quantity_Color& theZColor)
174 {
175 myTextAspects[V3d_X]->SetColor (theXColor);
176 myTextAspects[V3d_Y]->SetColor (theYColor);
177 myTextAspects[V3d_Z]->SetColor (theZColor);
178 }
179
180 // ============================================================================
181 // function : SetArrowsColor
182 // purpose :
183 // ============================================================================
SetArrowsColor(const Quantity_Color & theXColor,const Quantity_Color & theYColor,const Quantity_Color & theZColor)184 void V3d_Trihedron::SetArrowsColor (const Quantity_Color& theXColor,
185 const Quantity_Color& theYColor,
186 const Quantity_Color& theZColor)
187 {
188 const Quantity_Color aColors[3] = { theXColor, theYColor, theZColor };
189 for (Standard_Integer anIt = 0; anIt < 3; ++anIt)
190 {
191 myArrowShadingAspects[anIt]->SetColor (aColors[anIt]);
192 }
193 }
194
195 // ============================================================================
196 // function : SetScale
197 // purpose :
198 // ============================================================================
SetScale(const Standard_Real theScale)199 void V3d_Trihedron::SetScale (const Standard_Real theScale)
200 {
201 if (Abs (myScale - theScale) > Precision::Confusion())
202 {
203 invalidate();
204 }
205 myScale = theScale;
206 }
207
208 // =======================================================================
209 // function : SetSizeRatio
210 // purpose :
211 // =======================================================================
SetSizeRatio(const Standard_Real theRatio)212 void V3d_Trihedron::SetSizeRatio (const Standard_Real theRatio)
213 {
214 if (Abs (myRatio - theRatio) > Precision::Confusion())
215 {
216 invalidate();
217 }
218 myRatio = theRatio;
219 }
220
221 // =======================================================================
222 // function : SetArrowDiameter
223 // purpose :
224 // =======================================================================
SetArrowDiameter(const Standard_Real theDiam)225 void V3d_Trihedron::SetArrowDiameter (const Standard_Real theDiam)
226 {
227 if (Abs (myDiameter - theDiam) > Precision::Confusion())
228 {
229 invalidate();
230 }
231 myDiameter = theDiam;
232 }
233
234 // =======================================================================
235 // function : SetNbFacets
236 // purpose :
237 // =======================================================================
SetNbFacets(const Standard_Integer theNbFacets)238 void V3d_Trihedron::SetNbFacets (const Standard_Integer theNbFacets)
239 {
240 if (Abs (myNbFacettes - theNbFacets) > 0)
241 {
242 invalidate();
243 }
244 myNbFacettes = theNbFacets;
245 }
246
247 // ============================================================================
248 // function : Display
249 // purpose :
250 // ============================================================================
Display(const V3d_View & theView)251 void V3d_Trihedron::Display (const V3d_View& theView)
252 {
253 if (myStructure.IsNull())
254 {
255 myStructure = new TrihedronStructure (theView.Viewer()->StructureManager(), this);
256 myStructure->SetTransformPersistence (myTransformPers);
257 myStructure->SetZLayer (Graphic3d_ZLayerId_Topmost);
258 myStructure->SetDisplayPriority (9);
259 myStructure->SetInfiniteState (Standard_True);
260 myStructure->CStructure()->ViewAffinity = new Graphic3d_ViewAffinity();
261 myStructure->CStructure()->ViewAffinity->SetVisible (Standard_False);
262 myStructure->CStructure()->ViewAffinity->SetVisible (theView.View()->Identification(), true);
263 myToCompute = Standard_True;
264 }
265 if (myToCompute)
266 {
267 compute();
268 }
269
270 myStructure->Display();
271 }
272
273 // ============================================================================
274 // function : Erase
275 // purpose :
276 // ============================================================================
Erase()277 void V3d_Trihedron::Erase()
278 {
279 if (!myStructure.IsNull())
280 {
281 myStructure->Erase();
282 myStructure.Nullify();
283 }
284 }
285
286 // ============================================================================
287 // function : SetPosition
288 // purpose :
289 // ============================================================================
SetPosition(const Aspect_TypeOfTriedronPosition thePosition)290 void V3d_Trihedron::SetPosition (const Aspect_TypeOfTriedronPosition thePosition)
291 {
292 Graphic3d_Vec2i anOffset (0, 0);
293 if ((thePosition & (Aspect_TOTP_LEFT | Aspect_TOTP_RIGHT)) != 0)
294 {
295 anOffset.x() = static_cast<Standard_Integer> (myScale * THE_INTERNAL_SCALE_FACTOR);
296 }
297 if ((thePosition & (Aspect_TOTP_TOP | Aspect_TOTP_BOTTOM)) != 0)
298 {
299 anOffset.y() = static_cast<Standard_Integer> (myScale * THE_INTERNAL_SCALE_FACTOR);
300 }
301
302 myTransformPers->SetCorner2d (thePosition);
303 myTransformPers->SetOffset2d (anOffset);
304 }
305
306 // ============================================================================
307 // function : compute
308 // purpose :
309 // ============================================================================
compute()310 void V3d_Trihedron::compute()
311 {
312 myToCompute = Standard_False;
313 myStructure->GraphicClear (Standard_False);
314
315 // Create trihedron.
316 const Standard_Real aScale = myScale * myRatio * THE_INTERNAL_SCALE_FACTOR;
317 const Standard_Real aCylinderLength = aScale * THE_CYLINDER_LENGTH;
318 const Standard_Real aCylinderRadius = aScale * myDiameter;
319 const Standard_Real aConeRadius = myIsWireframe ? aCylinderRadius : (aCylinderRadius * 2.0);
320 const Standard_Real aConeLength = aScale * (1.0 - THE_CYLINDER_LENGTH);
321 const Standard_Real aSphereRadius = aCylinderRadius * 2.0;
322 const Standard_Real aRayon = aScale / 30.0;
323 Standard_Integer aGroupIter = myStructure->Groups().Lower();
324 {
325 Handle(Graphic3d_Group) aSphereGroup = addGroup (myStructure, aGroupIter);
326 aSphereGroup->SetClosed (!myIsWireframe);
327
328 // Display origin.
329 if (myIsWireframe)
330 {
331 Handle(Graphic3d_ArrayOfPolylines) anCircleArray = new Graphic3d_ArrayOfPolylines (THE_CIRCLE_SERMENTS_NB + 2);
332 for (Standard_Integer anIt = THE_CIRCLE_SERMENTS_NB; anIt >= 0; --anIt)
333 {
334 anCircleArray->AddVertex (aRayon * Sin (anIt * THE_CIRCLE_SEGMENT_ANGLE),
335 aRayon * Cos (anIt * THE_CIRCLE_SEGMENT_ANGLE), 0.0);
336 }
337 anCircleArray->AddVertex (aRayon * Sin (THE_CIRCLE_SERMENTS_NB * THE_CIRCLE_SEGMENT_ANGLE),
338 aRayon * Cos (THE_CIRCLE_SERMENTS_NB * THE_CIRCLE_SEGMENT_ANGLE), 0.0);
339
340 aSphereGroup->SetGroupPrimitivesAspect (mySphereShadingAspect->Aspect());
341 aSphereGroup->AddPrimitiveArray (anCircleArray);
342 }
343 else
344 {
345 gp_Trsf aSphereTransform;
346 aSphereGroup->SetGroupPrimitivesAspect (mySphereShadingAspect->Aspect());
347 aSphereGroup->AddPrimitiveArray (Prs3d_ToolSphere::Create (aSphereRadius, myNbFacettes, myNbFacettes, aSphereTransform));
348 }
349 }
350
351 // Display axes.
352 {
353 const gp_Ax1 anAxes[3] = { gp::OX(), gp::OY(), gp::OZ() };
354 for (Standard_Integer anIter = 0; anIter < 3; ++anIter)
355 {
356 Handle(Graphic3d_Group) anAxisGroup = addGroup (myStructure, aGroupIter);
357 anAxisGroup->SetClosed (!myIsWireframe);
358 if (myIsWireframe)
359 {
360 // create a tube
361 Handle(Graphic3d_ArrayOfPrimitives) anArray = new Graphic3d_ArrayOfSegments (2);
362 anArray->AddVertex (0.0f, 0.0f, 0.0f);
363 anArray->AddVertex (anAxes[anIter].Direction().XYZ() * aCylinderLength);
364
365 anAxisGroup->SetGroupPrimitivesAspect (myArrowShadingAspects[anIter]->Aspect());
366 anAxisGroup->AddPrimitiveArray (anArray);
367 }
368
369 Handle(Graphic3d_ArrayOfTriangles) aTriangles = Prs3d_Arrow::DrawShaded (anAxes[anIter],
370 myIsWireframe ? 0.0 : aCylinderRadius,
371 aCylinderLength + aConeLength,
372 aConeRadius,
373 aConeLength,
374 myNbFacettes);
375 anAxisGroup->SetGroupPrimitivesAspect (myArrowShadingAspects[anIter]->Aspect());
376 anAxisGroup->AddPrimitiveArray (aTriangles);
377 }
378 }
379
380 // Display labels.
381 {
382 Handle(Graphic3d_Group) aLabelGroup = addGroup (myStructure, aGroupIter);
383 const gp_Pnt aPoints[3] = { gp_Pnt (aScale + 2.0 * aRayon, 0.0, -aRayon),
384 gp_Pnt ( aRayon, aScale + 3.0 * aRayon, 2.0 * aRayon),
385 gp_Pnt ( -2.0 * aRayon, 0.5 * aRayon, aScale + 3.0 * aRayon) };
386 for (Standard_Integer anAxisIter = 0; anAxisIter < 3; ++anAxisIter)
387 {
388 Prs3d_Text::Draw (aLabelGroup, myTextAspects[anAxisIter], myLabels[anAxisIter], aPoints[anAxisIter]);
389 }
390 }
391 }
392
393 //=======================================================================
394 //function : DumpJson
395 //purpose :
396 //=======================================================================
DumpJson(Standard_OStream & theOStream,Standard_Integer theDepth) const397 void V3d_Trihedron::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
398 {
399 OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
400
401 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, mySphereShadingAspect.get())
402
403 for (Standard_Integer anIter = 0; anIter < 3; anIter++)
404 {
405 const Handle(Prs3d_TextAspect)& aTextAspect = myTextAspects[anIter];
406 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, aTextAspect.get())
407 }
408 for (Standard_Integer anIter = 0; anIter < 3; anIter++)
409 {
410 const Handle(Prs3d_ShadingAspect)& anArrowShadinAspect = myArrowShadingAspects[anIter];
411 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, anArrowShadinAspect.get())
412 }
413
414 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myStructure.get())
415 OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, myTransformPers.get())
416
417 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myScale)
418 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRatio)
419 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDiameter)
420 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myNbFacettes)
421 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsWireframe)
422 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToCompute)
423 }
424