VTK
vtkCubeAxesActor.h
Go to the documentation of this file.
1/*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkCubeAxesActor.h
5 Language: C++
6
7Copyright (c) 1993-2001 Ken Martin, Will Schroeder, Bill Lorensen
8All rights reserve
9 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
10
11 This software is distributed WITHOUT ANY WARRANTY; without even
12 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 PURPOSE. See the above copyright notice for more information.
14=========================================================================*/
59#ifndef vtkCubeAxesActor_h
60#define vtkCubeAxesActor_h
61
62#include "vtkRenderingAnnotationModule.h" // For export macro
63#include "vtkActor.h"
64
65class vtkAxisActor;
66class vtkCamera;
67class vtkTextProperty;
68class vtkStringArray;
69
70class VTKRENDERINGANNOTATION_EXPORT vtkCubeAxesActor : public vtkActor
71{
72public:
74 void PrintSelf(ostream& os, vtkIndent indent);
75
81
83
92
94
97 vtkSetMacro( RebuildAxes, bool );
98 vtkGetMacro( RebuildAxes, bool );
100
102
108 vtkSetVector6Macro(Bounds,double);
109 vtkGetVector6Macro(Bounds,double);
111
113
117 virtual void GetRenderedBounds(double rBounds[6]);
118 virtual double* GetRenderedBounds();
120
122
130 vtkSetVector2Macro( XAxisRange, double );
131 vtkSetVector2Macro( YAxisRange, double );
132 vtkSetVector2Macro( ZAxisRange, double );
133 vtkGetVector2Macro( XAxisRange, double );
134 vtkGetVector2Macro( YAxisRange, double );
136
137
144
145 vtkGetVector2Macro( ZAxisRange, double );
146
148
153 void SetScreenSize(double screenSize);
154 vtkGetMacro(ScreenSize, double);
156
158
162 void SetLabelOffset(double offset);
163 vtkGetMacro(LabelOffset, double);
165
167
171 void SetTitleOffset(double offset);
172 vtkGetMacro(TitleOffset, double);
174
176
180 virtual void SetCamera(vtkCamera*);
181 vtkGetObjectMacro(Camera,vtkCamera);
183
185 {
186 VTK_FLY_OUTER_EDGES = 0,
187 VTK_FLY_CLOSEST_TRIAD = 1,
188 VTK_FLY_FURTHEST_TRIAD = 2,
189 VTK_FLY_STATIC_TRIAD = 3,
190 VTK_FLY_STATIC_EDGES = 4
191 };
192
194
199 vtkSetClampMacro(FlyMode, int, VTK_FLY_OUTER_EDGES, VTK_FLY_STATIC_EDGES);
200 vtkGetMacro(FlyMode, int);
202 {this->SetFlyMode(VTK_FLY_OUTER_EDGES);};
204 {this->SetFlyMode(VTK_FLY_CLOSEST_TRIAD);};
206 {this->SetFlyMode(VTK_FLY_FURTHEST_TRIAD);};
208 {this->SetFlyMode(VTK_FLY_STATIC_TRIAD);};
210 {this->SetFlyMode(VTK_FLY_STATIC_EDGES);};
212
214
218 vtkSetStringMacro(XTitle);
220 vtkSetStringMacro(XUnits);
222 vtkSetStringMacro(YTitle);
224 vtkSetStringMacro(YUnits);
226 vtkSetStringMacro(ZTitle);
228 vtkSetStringMacro(ZUnits);
231
233
237 vtkSetStringMacro(XLabelFormat);
238 vtkGetStringMacro(XLabelFormat);
239 vtkSetStringMacro(YLabelFormat);
240 vtkGetStringMacro(YLabelFormat);
241 vtkSetStringMacro(ZLabelFormat);
242 vtkGetStringMacro(ZLabelFormat);
244
246
251 vtkSetClampMacro(Inertia, int, 1, VTK_INT_MAX);
252 vtkGetMacro(Inertia, int);
254
256
261 vtkSetMacro(CornerOffset, double);
262 vtkGetMacro(CornerOffset, double);
264
271
273
276 vtkSetMacro( EnableDistanceLOD, int );
277 vtkGetMacro( EnableDistanceLOD, int );
279
281
284 vtkSetClampMacro( DistanceLODThreshold, double, 0.0, 1.0 );
285 vtkGetMacro( DistanceLODThreshold, double);
287
289
292 vtkSetMacro( EnableViewAngleLOD, int );
293 vtkGetMacro( EnableViewAngleLOD, int );
295
297
300 vtkSetClampMacro( ViewAngleLODThreshold, double, 0., 1. );
301 vtkGetMacro( ViewAngleLODThreshold, double );
303
305
308 vtkSetMacro(XAxisVisibility,int);
309 vtkGetMacro(XAxisVisibility,int);
310 vtkBooleanMacro(XAxisVisibility,int);
311 vtkSetMacro(YAxisVisibility,int);
312 vtkGetMacro(YAxisVisibility,int);
313 vtkBooleanMacro(YAxisVisibility,int);
314 vtkSetMacro(ZAxisVisibility,int);
315 vtkGetMacro(ZAxisVisibility,int);
316 vtkBooleanMacro(ZAxisVisibility,int);
318
320
323 vtkSetMacro(XAxisLabelVisibility,int);
324 vtkGetMacro(XAxisLabelVisibility,int);
325 vtkBooleanMacro(XAxisLabelVisibility,int);
327
328 vtkSetMacro(YAxisLabelVisibility,int);
329 vtkGetMacro(YAxisLabelVisibility,int);
330 vtkBooleanMacro(YAxisLabelVisibility,int);
331
332 vtkSetMacro(ZAxisLabelVisibility,int);
333 vtkGetMacro(ZAxisLabelVisibility,int);
334 vtkBooleanMacro(ZAxisLabelVisibility,int);
335
337
340 vtkSetMacro(XAxisTickVisibility,int);
341 vtkGetMacro(XAxisTickVisibility,int);
342 vtkBooleanMacro(XAxisTickVisibility,int);
344
345 vtkSetMacro(YAxisTickVisibility,int);
346 vtkGetMacro(YAxisTickVisibility,int);
347 vtkBooleanMacro(YAxisTickVisibility,int);
348
349 vtkSetMacro(ZAxisTickVisibility,int);
350 vtkGetMacro(ZAxisTickVisibility,int);
351 vtkBooleanMacro(ZAxisTickVisibility,int);
352
354
357 vtkSetMacro(XAxisMinorTickVisibility,int);
358 vtkGetMacro(XAxisMinorTickVisibility,int);
359 vtkBooleanMacro(XAxisMinorTickVisibility,int);
361
362 vtkSetMacro(YAxisMinorTickVisibility,int);
363 vtkGetMacro(YAxisMinorTickVisibility,int);
364 vtkBooleanMacro(YAxisMinorTickVisibility,int);
365
366 vtkSetMacro(ZAxisMinorTickVisibility,int);
367 vtkGetMacro(ZAxisMinorTickVisibility,int);
368 vtkBooleanMacro(ZAxisMinorTickVisibility,int);
369
370 vtkSetMacro(DrawXGridlines,int);
371 vtkGetMacro(DrawXGridlines,int);
372 vtkBooleanMacro(DrawXGridlines,int);
373
374 vtkSetMacro(DrawYGridlines,int);
375 vtkGetMacro(DrawYGridlines,int);
376 vtkBooleanMacro(DrawYGridlines,int);
377
378 vtkSetMacro(DrawZGridlines,int);
379 vtkGetMacro(DrawZGridlines,int);
380 vtkBooleanMacro(DrawZGridlines,int);
381
382 vtkSetMacro(DrawXInnerGridlines,int);
383 vtkGetMacro(DrawXInnerGridlines,int);
384 vtkBooleanMacro(DrawXInnerGridlines,int);
385
386 vtkSetMacro(DrawYInnerGridlines,int);
387 vtkGetMacro(DrawYInnerGridlines,int);
388 vtkBooleanMacro(DrawYInnerGridlines,int);
389
390 vtkSetMacro(DrawZInnerGridlines,int);
391 vtkGetMacro(DrawZInnerGridlines,int);
392 vtkBooleanMacro(DrawZInnerGridlines,int);
393
394 vtkSetMacro(DrawXGridpolys,int);
395 vtkGetMacro(DrawXGridpolys,int);
396 vtkBooleanMacro(DrawXGridpolys,int);
397
398 vtkSetMacro(DrawYGridpolys,int);
399 vtkGetMacro(DrawYGridpolys,int);
400 vtkBooleanMacro(DrawYGridpolys,int);
401
402 vtkSetMacro(DrawZGridpolys,int);
403 vtkGetMacro(DrawZGridpolys,int);
404 vtkBooleanMacro(DrawZGridpolys,int);
405
410
415
417
427
429
439
441
451
453
463
465 {
466 VTK_TICKS_INSIDE = 0,
467 VTK_TICKS_OUTSIDE = 1,
468 VTK_TICKS_BOTH = 2
469 };
470
472
475 vtkSetClampMacro(TickLocation, int, VTK_TICKS_INSIDE, VTK_TICKS_BOTH);
476 vtkGetMacro(TickLocation, int);
478
480 { this->SetTickLocation(VTK_TICKS_INSIDE); };
482 { this->SetTickLocation(VTK_TICKS_OUTSIDE); };
484 { this->SetTickLocation(VTK_TICKS_BOTH); };
485
486 void SetLabelScaling(bool, int, int, int);
487
489
494 void SetUseTextActor3D( int val );
497
499
503 void SetUse2DMode( int val );
506
510 void SetSaveTitlePosition( int val );
511
513
516 vtkSetVector6Macro(OrientedBounds,double);
517 vtkGetVector6Macro(OrientedBounds, double);
519
521
524 vtkSetMacro(UseOrientedBounds, int);
525 vtkGetMacro(UseOrientedBounds, int);
527
529
532 vtkSetVector3Macro(AxisBaseForX,double);
533 vtkGetVector3Macro(AxisBaseForX, double);
535
537
540 vtkSetVector3Macro(AxisBaseForY,double);
541 vtkGetVector3Macro(AxisBaseForY, double);
543
545
548 vtkSetVector3Macro(AxisBaseForZ,double);
549 vtkGetVector3Macro(AxisBaseForZ, double);
551
553
557 vtkSetVector3Macro(AxisOrigin,double);
558 vtkGetVector3Macro(AxisOrigin, double);
560
562
565 vtkSetMacro(UseAxisOrigin, int);
566 vtkGetMacro(UseAxisOrigin, int);
568
570
573 vtkSetMacro(GridLineLocation,int);
574 vtkGetMacro(GridLineLocation,int);
576
578
583 vtkSetMacro(StickyAxes,int);
584 vtkGetMacro(StickyAxes,int);
585 vtkBooleanMacro(StickyAxes,int);
587
589
596 vtkSetMacro(CenterStickyAxes,int);
597 vtkGetMacro(CenterStickyAxes,int);
598 vtkBooleanMacro(CenterStickyAxes,int);
600
602 {
603 VTK_GRID_LINES_ALL = 0,
604 VTK_GRID_LINES_CLOSEST = 1,
605 VTK_GRID_LINES_FURTHEST = 2
606 };
607
608protected:
611
617 void ComputeStickyAxesBoundingSphere(vtkViewport* viewport, const double bounds[6],
618 double sphereCenter[3], double & sphereRadius);
619
623 void GetViewportLimitedBounds(vtkViewport* viewport, double bounds[6]);
624
629 static void GetBoundsPointBits(unsigned int pointIndex,
630 unsigned int & xBit,
631 unsigned int & yBit,
632 unsigned int & zBit);
633
637 static void GetBoundsPoint(unsigned int pointIndex, const double bounds[6], double point[3]);
638
639 int LabelExponent(double min, double max);
640
641 int Digits(double min, double max);
642
643 double MaxOf(double, double);
644 double MaxOf(double, double, double, double);
645
646 double FFix(double);
647 double FSign(double, double);
648 int FRound( double fnt );
649 int GetNumTicks( double range, double fxt);
650
651 void UpdateLabels(vtkAxisActor **axis, int index);
652
653 double Bounds[6]; //Define bounds explicitly
654
656
658
659 // Expose internally closest axis index computation
660 int FindClosestAxisIndex(double pts[8][3]);
661
662 // Expose internally furthest axis index computation
663 int FindFurtherstAxisIndex(double pts[8][3]);
664
665 // Expose internally the boundary edge fly mode axis index computation
666 void FindBoundaryEdge(int &indexOfAxisX, int &indexOfAxisY, int &indexOfAxisZ,
667 double pts[8][3]);
668
674 void UpdateGridLineVisibility(int axisIndex);
675
676 // VTK_ALL_GRID_LINES 0
677 // VTK_CLOSEST_GRID_LINES 1
678 // VTK_FURTHEST_GRID_LINES 2
680
685
690
696
702
708
714
716 {
717 NUMBER_OF_ALIGNED_AXIS = 4
718 };
719
721
725 vtkAxisActor *XAxes[NUMBER_OF_ALIGNED_AXIS];
726 vtkAxisActor *YAxes[NUMBER_OF_ALIGNED_AXIS];
727 vtkAxisActor *ZAxes[NUMBER_OF_ALIGNED_AXIS];
729
731
732 char *XTitle;
733 char *XUnits;
734 char *YTitle;
735 char *YUnits;
736 char *ZTitle;
737 char *ZUnits;
738
742
744
748
752
756
760
764
768
772
776
778
780
782
783 int InertiaLocs[3];
784
786
787 vtkTextProperty* TitleTextProperty[3];
788 vtkStringArray* AxisLabels[3];
789
790 vtkTextProperty* LabelTextProperty[3];
791
804
805 double RenderedBounds[6];
806 double OrientedBounds[6];
808
809 double AxisOrigin[3];
811
812 double AxisBaseForX[3];
813 double AxisBaseForY[3];
814 double AxisBaseForZ[3];
815
816private:
817 vtkCubeAxesActor(const vtkCubeAxesActor&) VTK_DELETE_FUNCTION;
818 void operator=(const vtkCubeAxesActor&) VTK_DELETE_FUNCTION;
819
820 vtkSetStringMacro(ActualXLabel);
821 vtkSetStringMacro(ActualYLabel);
822 vtkSetStringMacro(ActualZLabel);
823
825 int LastUseOrientedBounds;
826 int LastXPow;
827 int LastYPow;
828 int LastZPow;
829
830 int UserXPow;
831 int UserYPow;
832 int UserZPow;
833
834 bool AutoLabelScaling;
835
836 int LastXAxisDigits;
837 int LastYAxisDigits;
838 int LastZAxisDigits;
839
840 double LastXRange[2];
841 double LastYRange[2];
842 double LastZRange[2];
843 double LastBounds[6];
844
845 int LastFlyMode;
846
847 int RenderAxesX[NUMBER_OF_ALIGNED_AXIS];
848 int RenderAxesY[NUMBER_OF_ALIGNED_AXIS];
849 int RenderAxesZ[NUMBER_OF_ALIGNED_AXIS];
850
851 int NumberOfAxesX;
852 int NumberOfAxesY;
853 int NumberOfAxesZ;
854
855 bool MustAdjustXValue;
856 bool MustAdjustYValue;
857 bool MustAdjustZValue;
858
859 bool ForceXLabelReset;
860 bool ForceYLabelReset;
861 bool ForceZLabelReset;
862
863 double XAxisRange[2];
864 double YAxisRange[2];
865 double ZAxisRange[2];
866
867 double LabelScale;
868 double TitleScale;
869
870 double ScreenSize;
871 double LabelOffset;
872 double TitleOffset;
873
875
879 double MajorStart[3];
880 double DeltaMajor[3];
882
883 int RenderGeometry(bool &initialRender, vtkViewport *viewport, bool checkAxisVisibility,int (vtkAxisActor::*renderMethod)(vtkViewport*));
884
885 void TransformBounds(vtkViewport *viewport, const double bounds[6],
886 double pts[8][3]);
887 void AdjustAxes(double bounds[6],
888 double xCoords[NUMBER_OF_ALIGNED_AXIS][6],
889 double yCoords[NUMBER_OF_ALIGNED_AXIS][6],
890 double zCoords[NUMBER_OF_ALIGNED_AXIS][6],
891 double xRange[2], double yRange[2], double zRange[2]);
892
893 bool ComputeTickSize(double bounds[6]);
894 void AdjustValues(const double xRange[2],
895 const double yRange[2],
896 const double zRange[2]);
897 void AdjustRange(const double bounds[6]);
898 void BuildAxes(vtkViewport *);
899 void DetermineRenderAxes(vtkViewport *);
900 void SetNonDependentAttributes(void);
901 void BuildLabels(vtkAxisActor *axes[NUMBER_OF_ALIGNED_AXIS]);
902 void AdjustTicksComputeRange(vtkAxisActor *axes[NUMBER_OF_ALIGNED_AXIS],
903 double rangeMin, double rangeMax);
904
905 void AutoScale(vtkViewport *viewport);
906 void AutoScale(vtkViewport *viewport, vtkAxisActor *axes[NUMBER_OF_ALIGNED_AXIS]);
907 double AutoScale(vtkViewport *viewport, double screenSize, double position[3]);
908};
909
910
911#endif
represents an object (geometry & properties) in a rendered scene
Definition: vtkActor.h:52
Create an axis with tick marks and labels.
Definition: vtkAxisActor.h:75
a virtual camera for 3D rendering
Definition: vtkCamera.h:51
create a plot of a bounding box edges - used for navigation
void FindBoundaryEdge(int &indexOfAxisX, int &indexOfAxisY, int &indexOfAxisZ, double pts[8][3])
void SetTickLocationToInside(void)
vtkProperty * GetZAxesGridpolysProperty()
int EnableDistanceLOD
If enabled the actor will not be visible at a certain distance from the camera.
void SetXAxesGridlinesProperty(vtkProperty *)
Get/Set axes (outer) gridlines actors properties.
void GetViewportLimitedBounds(vtkViewport *viewport, double bounds[6])
Get bounds such that the axes are entirely within a viewport.
void UpdateGridLineVisibility(int axisIndex)
This will Update AxisActors with GridVisibility when those should be dynamaic regarding the viewport.
void SetScreenSize(double screenSize)
Explicitly specify the screen size of title and label text.
int CenterStickyAxes
Flag for centering sticky axes.
virtual int RenderOpaqueGeometry(vtkViewport *)
Draw the axes as per the vtkProp superclass' API.
virtual int RenderTranslucentGeometry(vtkViewport *)
double FSign(double, double)
void SetYAxesInnerGridlinesProperty(vtkProperty *)
void SetUse2DMode(int val)
Get/Set 2D mode NB: Use vtkTextActor for titles in 2D instead of vtkAxisFollower.
vtkProperty * GetZAxesGridlinesProperty()
vtkProperty * GetXAxesLinesProperty()
vtkProperty * GetXAxesInnerGridlinesProperty()
int EnableViewAngleLOD
If enabled the actor will not be visible at a certain view angle.
vtkProperty * XAxesInnerGridlinesProperty
void SetXAxesGridpolysProperty(vtkProperty *)
Get/Set axes gridPolys actors properties.
void SetTitleOffset(double offset)
Explicitly specify the distance between title and labels.
virtual int RenderOverlay(vtkViewport *)
void SetZAxesGridpolysProperty(vtkProperty *)
vtkProperty * YAxesLinesProperty
void SetFlyModeToClosestTriad()
void SetYAxesGridpolysProperty(vtkProperty *)
int StickyAxes
Flag for axes stickiness.
void SetZAxesInnerGridlinesProperty(vtkProperty *)
void SetZAxesGridlinesProperty(vtkProperty *)
double ViewAngleLODThreshold
This determines at what view angle to geometry will make the geometry not visibile.
void SetAxisLabels(int axis, vtkStringArray *value)
static vtkCubeAxesActor * New()
Instantiate object with label format "6.3g" and the number of labels per axis set to 3.
int FRound(double fnt)
int FindClosestAxisIndex(double pts[8][3])
vtkProperty * YAxesInnerGridlinesProperty
void ComputeStickyAxesBoundingSphere(vtkViewport *viewport, const double bounds[6], double sphereCenter[3], double &sphereRadius)
Computes a bounding sphere used to determine the sticky bounding box.
void ReleaseGraphicsResources(vtkWindow *)
Release any graphics resources that are being consumed by this actor.
static void GetBoundsPoint(unsigned int pointIndex, const double bounds[6], double point[3])
Get a point on the bounding box by point index.
vtkProperty * YAxesGridlinesProperty
void SetLabelOffset(double offset)
Explicitly specify the distance between labels and the axis.
vtkProperty * GetXAxesGridlinesProperty()
void PrintSelf(ostream &os, vtkIndent indent)
Methods invoked by print to print information about the object including superclasses.
vtkTextProperty * GetLabelTextProperty(int)
Returns the text property for the labels on an axis.
void SetZAxesLinesProperty(vtkProperty *)
void SetFlyModeToStaticEdges()
void SetFlyModeToStaticTriad()
void SetYAxesLinesProperty(vtkProperty *)
vtkStringArray * GetAxisLabels(int axis)
Explicitly specify the axis labels along an axis as an array of strings instead of using the values.
virtual double * GetRenderedBounds()
vtkProperty * GetYAxesGridlinesProperty()
vtkProperty * GetZAxesLinesProperty()
void SetSaveTitlePosition(int val)
For 2D mode only: save axis title positions for later use.
vtkTextProperty * GetTitleTextProperty(int)
Returns the text property for the title on an axis.
vtkProperty * YAxesGridpolysProperty
vtkProperty * XAxesGridlinesProperty
static void GetBoundsPointBits(unsigned int pointIndex, unsigned int &xBit, unsigned int &yBit, unsigned int &zBit)
Get the bits for a bounds point.
int HasTranslucentPolygonalGeometry()
Does this prop have some translucent polygonal geometry?
void SetXAxesInnerGridlinesProperty(vtkProperty *)
Get/Set axes inner gridlines actors properties.
void SetLabelScaling(bool, int, int, int)
void SetTickLocationToOutside(void)
vtkProperty * ZAxesLinesProperty
void SetUseTextActor3D(int val)
Use or not vtkTextActor3D for titles and labels.
double FFix(double)
int FindFurtherstAxisIndex(double pts[8][3])
vtkProperty * XAxesGridpolysProperty
vtkProperty * GetXAxesGridpolysProperty()
vtkProperty * ZAxesGridlinesProperty
vtkProperty * ZAxesInnerGridlinesProperty
double MaxOf(double, double, double, double)
int GetNumTicks(double range, double fxt)
void UpdateLabels(vtkAxisActor **axis, int index)
vtkProperty * GetYAxesInnerGridlinesProperty()
vtkProperty * XAxesLinesProperty
int Digits(double min, double max)
vtkProperty * GetZAxesInnerGridlinesProperty()
virtual int RenderTranslucentPolygonalGeometry(vtkViewport *)
virtual void SetCamera(vtkCamera *)
Set/Get the camera to perform scaling and translation of the vtkCubeAxesActor.
virtual void GetRenderedBounds(double rBounds[6])
Method used to properly return the bounds of the cube axis itself with all its labels.
double MaxOf(double, double)
vtkProperty * GetYAxesLinesProperty()
int LabelExponent(double min, double max)
vtkProperty * ZAxesGridpolysProperty
void SetXAxesLinesProperty(vtkProperty *)
Get/Set axes actors properties.
void SetYAxesGridlinesProperty(vtkProperty *)
vtkProperty * GetYAxesGridpolysProperty()
void SetTickLocationToBoth(void)
void SetFlyModeToFurthestTriad()
double DistanceLODThreshold
Default is 0.80 This determines at what fraction of camera far clip range, actor is not visible.
a simple class to control print indentation
Definition: vtkIndent.h:40
represent surface properties of a geometric object
Definition: vtkProperty.h:65
a vtkAbstractArray subclass for strings
represent text properties.
record modification and/or execution time
Definition: vtkTimeStamp.h:36
abstract specification for Viewports
Definition: vtkViewport.h:48
window superclass for vtkRenderWindow
Definition: vtkWindow.h:35
@ point
Definition: vtkX3D.h:236
@ value
Definition: vtkX3D.h:220
@ range
Definition: vtkX3D.h:238
@ position
Definition: vtkX3D.h:261
@ index
Definition: vtkX3D.h:246
@ offset
Definition: vtkX3D.h:438
vtkSetMacro(IgnoreDriverBugs, bool)
Updates the extensions string.
vtkTimeStamp BuildTime
Updates the extensions string.
vtkBooleanMacro(IgnoreDriverBugs, bool)
Updates the extensions string.
vtkGetStringMacro(ExtensionsString)
Returns a string listing all available extensions.
#define VTK_INT_MAX
Definition: vtkType.h:153
#define max(a, b)