 ProEssentials v9 Help .Net Reference

Chapter 6: Creating 3D Charts and 3D Graphs

A simplified outline of Scientific 3D Charting with ProEssentials: .NET, ActiveX, MFC Library, VCL

The examples with the demo and example projects are more involved so this discussion is best for a first look.

The following section discusses how to create the various 3D Charts. But before we get into the examples, there are a few topics which need extra attention.

### 3D Charts Data Format

Points is related to X axis and XData. In other words, Points defines how many polygons or 3d-bars are along the x axis. Subsets is related to the Z axis and ZData. In other words, Subsets defines how many polygons or 3d-bars are long the z axis.

When passing data for surface plotting, XData should always increase with each new point/element, and ZData should be in groups of identical values. Note how s0 is the same element for the first three and how p0, p1, and p2 are different for the first three.

(s0,p0)..(s0,p1)..(s0,p2)..(s0,pn)....(s1,p0)..(s1,p1)..(s1,p2)...

Always keep this in mind when building 3D surface charts.

1. XData should always increase with each new point, and

2. ZData should be in groups of identical values with each new point.

To further explain this requirement, note how this routine causes XData to increase with each point, and how ZData stays the same for all points in a subset.

 for s = 0 to 24   for p = 0 to 24    Pe3do1.XData(s, p) = 50 + (p * 10)    '** p in formula causes XData to increment with each p **'      Pe3do1.ZData(s, p) = 50 + (s * 50)    '** s in formula causes all points to have same ZData value **'      Pe3do1.YData(s, p) = (35 * cos(p * .2)) * (10 * sin(s * .34))   Next p Next s

To summarize, if your charts look fine in WireFrame or Solid form, but look messed up in a shaded or contoured form, check that your XData increases with each point and your ZData is in groups of identical values. Or more simply, try switching your XData to ZData and ZData to XData.

#### 3D Polygon Data PolyMode

This property controls the different modes in which the 3D Scientific Graph can operate. It's recommended that the component be reset at the start of your initialization process. You do this with a call to PEreset (OCX/VCL developers can use PEactions = 20/xReset). Immediately after the reset, set PolyMode as needed and complete the rest of the initialization.

So the start of your 3D chart implementation will always begin with...

Pe3do1.PEreset

pe3do1.PolyMode = PEPM_SURFACE ' or as needed

#### 3D Surfaces

ProEssentials can create surfaces in the following formats: WireFrame, Solid, Shaded Solid, Contoured Solid, and Pixel.

3D Surface charts are produced from XData, YData, and ZData. Generally, X-Data and Z-Data are equally spaced but this is not mandatory. Once you supply this data, the component will construct a list of polygons which will produce a surface plot of the data. The following example code shows how to construct a simple surface plot. .NET syntax and ActiveX/VCL syntax shown.

 // .NET C# Syntax ///////////////////////////////////////////////////////////// // Always start with fresh 3D chart Pe3do1.PeFunction.Reset(); Pe3do1.PePlot.PolyMode = Gigasoft.ProEssentials.Enums.PolyMode.SurfacePolygons; Pe3do1.PeConfigure.PrepareImages = true; // Set the amount of data and pass data Pe3do1.PeData.Subsets = 15; Pe3do1.PeData.Points = 15; for (int s=0; s<15; s++) {    for (int p=0; p< 15; p++)    {    Pe3do1.PeData.X[s, p] = 50 + (p * 10);    // p in formula causes XData to increment with each p    Pe3do1.PeData.Z[s, p] = 50 + (s * 50);    // s in formula causes all points to have same ZData value    Pe3do1.PeData.Y[s, p] = (float)(5+35*Math.Cos(p*.4F))*(float)(5+10*Math.Sin(s*.34F));    } } Pe3do1.PePlot.ViewingHeight = 30; Pe3do1.PePlot.DegreeOfRotation = 35; Pe3do1.PePlot.Method = Gigasoft.ProEssentials.Enums.ThreeDGraphPlottingMethod.Four; Pe3do1.PeString.MainTitle = ""; Pe3do1.PeString.SubTitle = ""; Pe3do1.PeString.XAxisLabel = "Points"; Pe3do1.PeString.ZAxisLabel = "Subsets"; Pe3do1.PeString.YAxisLabel = "Data value"; Pe3do1.PeConfigure.RenderEngine = RenderEngine.Direct3D; Pe3do1.PeColor.BitmapGradientMode = true; Pe3do1.PeColor.QuickStyle = QuickStyle.DarkNoBorder; Pe3do1.PeFunction.ReinitializeResetImage(); Pe3do1.Refresh(); /////////////////////////////////////////////////////////////////////////////// // ActiveX VCL Syntax // Dim s As Integer Dim p As Integer   '** Always start with this **' Pe3do1.PEactions = 20 ' Calls PEreset Pe3do1.PolyMode = PEPM_SURFACEPOLYGONS Pe3do1.PrepareImages = True   '** Set the amount of data and pass data **' Pe3do1.Subsets = 15 Pe3do1.Points = 15   For s = 0 To 14   For p = 0 To 14    Pe3do1.XData(s, p) = 50 + (p * 10)    '** p in formula causes XData to increment with each p **'    Pe3do1.ZData(s, p) = 50 + (s * 50)    '** s in formula causes all points to have same ZData value **'    Pe3do1.YData(s, p) = (5+35*Cos(p*.4))*(5+10*Sin(s*.34))   Next p Next s   Pe3do1.ViewingHeight = 30 Pe3do1.DegreeOfRotation = 35 Pe3do1.PlottingMethod = 4 ' surface with contour   Pe3do1.MainTitle = "" Pe3do1.SubTitle = "" Pe3do1.XAxisLabel = "Points" Pe3do1.ZAxisLabel = "Subsets" Pe3do1.YAxisLabel = "Data value" Pe3do1.RenderEngine = PERE_DIRECT3D Pe3do1.BitmapGradientMode = True Pe3do1.QuickStyle = PEQS_DARK_NO_BORDER Pe3do1.PEactions = 0

The above code produces the following example image. Notice how the first two lines reset the component and set the PolyMode property.

The next few lines set the amount of data and pass random data into the chart. Notice how XData increases with each data point as described in the above Data Format section.

The control is rotated with the DegreeOfRotation property and tilted with the ViewingHeight property. DegreeOfRotation accepts values from 0 to 359 degrees. ViewingHeight ranging from 90 to -90.

Next, the PlottingMethod property is set. Refer to PlottingMethod for more information. Note that the possible PlottingMethod values change based on the setting of PolyMode.

Finally, we set some titles and labels as is done with all other ProEssentials controls.

#### 3D Bar Charts

ProEssentials can create 3D Bar Charts in the following formats: WireFrame, Solid, and Shaded Solid.

Similar to the Graph control, the 3D Bar chart only needs YData.

Subsets defines how many rows are along z axis and Points defines how many columns are along x axis.

SubsetLabels and PointLabels are used to label rows and columns. SubsetColors is used to control colors of subset bars.

Once you supply the data, the control will construct a list of polygons which will produce a 3D Bar Chart of the data. The following example code shows how to construct a simple 3D Bar Chart.

 // .NET C# Syntax ///////////////////////////////////////////////////////////// // Always start with a fresh 3D chart Pe3do1.PeFunction.Reset(); Pe3do1.PePlot.PolyMode = Gigasoft.ProEssentials.Enums.PolyMode.ThreeDBar; Pe3do1.PeConfigure.PrepareImages = true; // Set the amount of data and pass data Pe3do1.PeData.Subsets = 10; Pe3do1.PeData.Points = 10; for (s=0; s<10; s++) {    for (p=0; p< 10; p++)       Pe3do1.PeData.Y[s, p] = (float)(5+35*Math.Cos(p*.4F))*(float)(5+10*Math.Sin(s*.34F));    Pe3do1.PeColor.SubsetColors[s] = Color.FromArgb(255, 10+((s+1)*23),10+((s+1)*23),10+((s+1)*23)); } Pe3do1.PeString.SubsetLabels = "Hello"; Pe3do1.PeString.SubsetLabels = "World"; Pe3do1.PeString.PointLabels = "Texas"; Pe3do1.PeString.PointLabels = "Washington"; Pe3do1.PePlot.DegreeOfRotation = 309; Pe3do1.PePlot.ViewingHeight = 20; Pe3do1.PeFunction.SetLight(0, .51F, 1.52F, -2.41F); Pe3do1.PeFont.FontSize = FontSize.Small; Pe3do1.PeFont.Fixed = true; Pe3do1.PePlot.Method = Gigasoft.ProEssentials.Enums.ThreeDGraphPlottingMethod.One; Pe3do1.PeString.MainTitle = ""; Pe3do1.PeString.SubTitle = ""; Pe3do1.PeString.XAxisLabel = "Points"; Pe3do1.PeString.ZAxisLabel = "Subsets"; Pe3do1.PeString.YAxisLabel = "Data value"; Pe3do1.PeConfigure.RenderEngine = RenderEngine.Direct3D; Pe3do1.PeColor.BitmapGradientMode = true; Pe3do1.PeColor.QuickStyle = QuickStyle.LightLine; Pe3do1.PeFunction.ReinitializeResetImage(); Pe3do1.Refresh(); /////////////////////////////////////////////////////////////////////////////// // ActiveX VCL Syntax // Dim s As Integer Dim p As Integer   Pe3do1.PEactions = 20 ' Calls PEreset Pe3do1.PolyMode = PEPM_3DBAR   Pe3do1.PrepareImages = True Pe3do1.Subsets = 10 Pe3do1.Points = 10   For s = 0 To 9   For p = 0 To 9    Pe3do1.YData(s, p) = (5+35*Cos(p*.4))*(5+10*Sin(s*.34))   Next p   Pe3do1.SubsetColors(s) = RGB(10+s*23, 10+s*23, 10+s*23) Next s   Pe3do1.SubsetLabels(0) = "Hello" Pe3do1.SubsetLabels(1) = "World" Pe3do1.PointLabels(0) = "Texas" Pe3do1.PointLabels(1) = "Washington"   Pe3do1.DegreeOfRotation = 309 Pe3do1.ViewingHeight = 20 Call Pe3do1.DxSetLight(0, 0.51, 1.52, -2.41) Pe3do1.FontSize = PEFS_SMALL Pe3do1.FixedFonts = True Pe3do1.PlottingMethod = 1 ' Bar Pe3do1.MainTitle = "" Pe3do1.SubTitle = "" Pe3do1.XAxisLabel = "Points" Pe3do1.ZAxisLabel = "Subsets" Pe3do1.YAxisLabel = "Data value" Pe3do1.RenderEngine = PERE_DIRECT3D Pe3do1.BitmapGradientMode = True Pe3do1.QuickStyle = PEQS_LIGH_LINE Pe3do1.PEactions = 0

The following image was produced by the above code. Notice the similarity in code to that of the 3D Surface plot. The only significant differences from the previous example are...

1. only pass YData.

1. assigns custom SubsetColors to color bars sharing same subset.

1. assigns a few SubsetLabels and PointLabels. Note in the image the first two subset labels "Hello" and "World", and first two point labels "Texas" and "Washington"

1. We added a call to set the light position, DxSetLight. or ActiveX DxSetLight. Note setting DegreePrompting = True is recommended to learn coordinates to use with DxSetLight. Holding the middle mouse down while dragging moves the light.

#### 3D Scatter Charts

The 3D scatter chart is much like a 2D scatter chart with the addition of ZData. Each data point thus has its own XData, YData, and ZData coordinates.

Possible plotting methods are points, lines, and points plus lines. Theres also an Area plotting method which will produce area layers along the z axis. This can be used to construct a Waterfall chart.

Comparison Subsets are supported so mixing Points and Lines is possible. See PlottingMethod, and PlottingMethodII, and ComparisonSubsets.

Graph annotations are also supported in this mode. See GraphAnnotationType and GraphAnnotationZ.

The following example code shows how to construct a simple 3D Scatter Chart.

 // .NET C# Syntax ///////////////////////////////////////////////////////////// // Always start with this Pe3do1.PeFunction.Reset(); Pe3do1.PePlot.PolyMode = Gigasoft.ProEssentials.Enums.PolyMode.Scatter; Pe3do1.PeConfigure.PrepareImages = true; // Set the amount of data and pass data Pe3do1.PeData.Subsets = 10; Pe3do1.PeData.Points = 10; for (s=0; s<10; s++) {    for (p = 0; p < 10; p++)    {       Pe3do1.PeData.X[s, p] = (float)(5+35*Math.Sin(p*.4F))*(float)(5+10*Math.Cos(s*.34F));       Pe3do1.PeData.Z[s, p] = (float)(5+35*Math.Sin(p*.4F))*(float)(5+10*Math.Sin(s*.34F));       Pe3do1.PeData.Y[s, p] = (float)(5+35*Math.Cos(p*.4F))*(float)(5+10*Math.Sin(s*.34F));    }    Pe3do1.PePlot.SubsetPointTypes[s] = PointType.DotSolid; } Pe3do1.PePlot.PointSize = PointSize.Large; Pe3do1.PePlot.Option.DxFitControlShape = false; Pe3do1.PePlot.Option.DegreePrompting = true; Pe3do1.PePlot.DegreeOfRotation = 200; Pe3do1.PePlot.ViewingHeight = 30; Pe3do1.PeFont.FontSize = FontSize.Small; Pe3do1.PeFont.Fixed = true; Pe3do1.PeFunction.SetLight(0, 0.0F, -2.0F, 2.1F); Pe3do1.PeLegend.SubsetsToLegend = -1; Pe3do1.PePlot.Method = Gigasoft.ProEssentials.Enums.ThreeDGraphPlottingMethod.Two; Pe3do1.PeString.MainTitle = ""; Pe3do1.PeString.SubTitle = ""; Pe3do1.PeString.XAxisLabel = "Points"; Pe3do1.PeString.ZAxisLabel = "Subsets"; Pe3do1.PeString.YAxisLabel = "Data value"; Pe3do1.PeConfigure.RenderEngine = RenderEngine.Direct3D; Pe3do1.PeColor.BitmapGradientMode = true; Pe3do1.PeColor.QuickStyle = QuickStyle.LightInset; Pe3do1.PeFunction.ReinitializeResetImage(); Pe3do1.Refresh(); /////////////////////////////////////////////////////////////////////////////// // ActiveX VCL Syntax // Dim s As Integer Dim p As Integer   Pe3do1.PEactions = 20 Pe3do1.PolyMode = PEPM_SCATTER   Pe3do1.PrepareImages = True Pe3do1.Subsets = 10 Pe3do1.Points = 10   For s = 0 To 9   For p = 0 To 9    Pe3do1.XData(s, p)=(5+35*Sin(p*.4))*(5+10*Cos(s*.34))    Pe3do1.ZData(s, p)=(5+35*Sin(p*.4))*(5+10*Sin(s*.34))    Pe3do1.YData(s, p)=(5+35*Cos(p*.4))*(5+10*Sin(s*.34))   Next p   Pe3do1.SubsetPointTypes(s) = PEPT_DOTSOLID Next s   Pe3do1.PointSize = PEPS_LARG; Pe3do1.DxFitControlShape = false Pe3do1.DegreePrompting = True Pe3do1.DegreeOfRotation = 200 Pe3do1.ViewingHeight = 30 Pe3do1.FontSize = PEFS_SMALL Pe3do1.FixedFonts = True Call Pe3do1.DxSetLight(0, 0.0, 2.0, -2.1) Pe3do1.SubsetsToLegend(0) = -1   Pe3do1.PlottingMethod = 2 'Points Plus Line   Pe3do1.MainTitle = "" Pe3do1.SubTitle = "" Pe3do1.XAxisLabel = "Points" Pe3do1.ZAxisLabel = "Subsets" Pe3do1.YAxisLabel = "Data value" Pe3do1.RenderEngine = PERE_DIRECT3D Pe3do1.BitmapGradientMode = True Pe3do1.QuickStyle = PEQS_LIGH_LINE Pe3do1.PEactions = 0

The following image is produced by the above code. Again this code is very similar to the first surface plot example. The significant differences are:

1. passes XData, YData, and ZData, however, no concern is needed with respect to the format of the data as in the 3D Surface example. The scatter chart can plot any data point at any location.

1. optionally assigns custom SubsetPointTypes so all subsets use PEPT_DOTSOLID.

1. optionally disables the legend with the SubsetsToLegend property.

#### 3D Polygon Data Interface

The 3D Polygon data interface allows the developer to supply their own list of polygons to be rendered. WireFrame, Solid, and Shaded Solid images can be produced from this data.

Its important that polygon vertices are ordered properly. The polygon vertices must be ordered in a counter-clockwise order as viewed from outside of the control. This is only necessary for hidden line removal and shading purposes. If you are only producing a wireframe image, the ordering of vertices is not critical. In the process of producing a shaded object, and rotating this object, if you notice polygons getting darker where they should be getting lighter, then reverse the order of the vertices within those polygons. You should first concentrate on getting the polygons into the object and producing a wireframe. Once the wireframe is plotting, then look at the shaded surface during rotation and determine if vertices need to be in a different order.

Also, note that the polygon vertices should be normalized to logical units between -10 and 10 for all three axes.

AddSkirts should be set to TRUE if the polygon data forms an enclosed surface and you want to produce a surface or shaded surface image.

More than one object can be placed into 3D space, however, ideally the objects should not intersect if polygons are large.

The following example code shows how to construct a simple 3D object using the 3D Polygon Interface. This particular example creates a pyramid consisting of 4 polygons, each with 3 vertices.

 // .NET C# Syntax ///////////////////////////////////////////////////////////// Pe3do1.PeFunction.Reset(); Pe3do1.PePlot.PolyMode = Gigasoft.ProEssentials.Enums.PolyMode.PolygonData; Pe3do1.PeConfigure.PrepareImages = true; Gigasoft.ProEssentials.Structs.PolygonData[] MyPolys = new Gigasoft.ProEssentials.Structs.PolygonData; // Define first polygon MyPolys.Vertice0X = 0; MyPolys.Vertice0Y = -10.0F; MyPolys.Vertice0Z = -10; MyPolys.Vertice1X = -10; MyPolys.Vertice1Y = -10; MyPolys.Vertice1Z = 0; MyPolys.Vertice2X = 0; MyPolys.Vertice2Y = 10; MyPolys.Vertice2Z = 0; MyPolys.NumberOfVertices = 3; MyPolys.PolyColor = Color.FromArgb(255, 8, 128, 128).ToArgb(); // Define second polygon MyPolys.Vertice0X = -10; MyPolys.Vertice0Y = -10; MyPolys.Vertice0Z = 0; MyPolys.Vertice1X = 0; MyPolys.Vertice1Y = -10; MyPolys.Vertice1Z = 10; MyPolys.Vertice2X = 0; MyPolys.Vertice2Y = 10; MyPolys.Vertice2Z = 0; MyPolys.NumberOfVertices = 3; MyPolys.PolyColor = Color.FromArgb(255, 8, 128, 128).ToArgb(); // Define third polygon MyPolys.Vertice0X = 0; MyPolys.Vertice0Y = -10; MyPolys.Vertice0Z = 10; MyPolys.Vertice1X = 10; MyPolys.Vertice1Y = -10; MyPolys.Vertice1Z = 0; MyPolys.Vertice2X = 0; MyPolys.Vertice2Y = 10; MyPolys.Vertice2Z = 0; MyPolys.NumberOfVertices = 3; MyPolys.PolyColor = Color.FromArgb(255, 8, 128, 128).ToArgb(); // Define fourth polygon MyPolys.Vertice0X = 10; MyPolys.Vertice0Y = -10; MyPolys.Vertice0Z = 0; MyPolys.Vertice1X = 0; MyPolys.Vertice1Y = -10; MyPolys.Vertice1Z = -10; MyPolys.Vertice2X = 0; MyPolys.Vertice2Y = 10; MyPolys.Vertice2Z = 0; MyPolys.NumberOfVertices = 3; MyPolys.PolyColor = Color.FromArgb(255, 8, 128, 128).ToArgb(); // Pass the polygon data into object Gigasoft.ProEssentials.Api.PEvsetW(Pe3do1.PeSpecial.HObject,        Gigasoft.ProEssentials.DllProperties.PolyData, MyPolys, 4); Pe3do1.PePlot.DegreeOfRotation = 200; Pe3do1.PePlot.ViewingHeight = 30; Pe3do1.PeFont.FontSize = FontSize.Small; Pe3do1.PeFunction.SetLight(0, 2.0F, -1.0F, -2.1F); Pe3do1.PePlot.Method = Gigasoft.ProEssentials.Enums.ThreeDGraphPlottingMethod.Two; Pe3do1.PeString.MainTitle = ""; Pe3do1.PeString.SubTitle = ""; Pe3do1.PeGrid.Option.ShowXAxis = ShowAxis.Empty; Pe3do1.PeGrid.Option.ShowYAxis = ShowAxis.Empty; Pe3do1.PeGrid.Option.ShowZAxis = ShowAxis.Empty; Pe3do1.PeConfigure.RenderEngine = RenderEngine.Direct3D; Pe3do1.PeColor.BitmapGradientMode = true; Pe3do1.PeColor.QuickStyle = QuickStyle.LightNoBorder; Pe3do1.PeFunction.ReinitializeResetImage(); Pe3do1.Refresh(); /////////////////////////////////////////////////////////////////////////////// // ActiveX VCL Syntax // Pe3do1.PEactions = 20 Pe3do1.PolyMode = PEPM_POLYGONDATA   Pe3do1.PrepareImages = True   ReDim MyPolys(4) As POLYGONDATA   '** Define first polygon **' MyPolys(0).Vertices(0).x = 0 MyPolys(0).Vertices(0).y = -10 MyPolys(0).Vertices(0).Z = -10 MyPolys(0).Vertices(1).x = -10 MyPolys(0).Vertices(1).y = -10 MyPolys(0).Vertices(1).Z = 0 MyPolys(0).Vertices(2).x = 0 MyPolys(0).Vertices(2).y = 10 MyPolys(0).Vertices(2).Z = 0 MyPolys(0).NumberOfVertices = 3 MyPolys(0).PolyColor = RGB(8, 128, 128)   '** Define second polygon **' MyPolys(1).Vertices(0).x = -10 MyPolys(1).Vertices(0).y = -10 MyPolys(1).Vertices(0).Z = 0 MyPolys(1).Vertices(1).x = 0 MyPolys(1).Vertices(1).y = -10 MyPolys(1).Vertices(1).Z = 10 MyPolys(1).Vertices(2).x = 0 MyPolys(1).Vertices(2).y = 10 MyPolys(1).Vertices(2).Z = 0 MyPolys(1).NumberOfVertices = 3 MyPolys(1).PolyColor = RGB(8, 128, 128)   '** Define third polygon **' MyPolys(2).Vertices(0).x = 0 MyPolys(2).Vertices(0).y = -10 MyPolys(2).Vertices(0).Z = 10 MyPolys(2).Vertices(1).x = 10 MyPolys(2).Vertices(1).y = -10 MyPolys(2).Vertices(1).Z = 0 MyPolys(2).Vertices(2).x = 0 MyPolys(2).Vertices(2).y = 10 MyPolys(2).Vertices(2).Z = 0 MyPolys(2).NumberOfVertices = 3 MyPolys(2).PolyColor = RGB(8, 128, 128)   '** Define fourth polygon **' MyPolys(3).Vertices(0).x = 10 MyPolys(3).Vertices(0).y = -10 MyPolys(3).Vertices(0).Z = 0 MyPolys(3).Vertices(1).x = 0 MyPolys(3).Vertices(1).y = -10 MyPolys(3).Vertices(1).Z = -10 MyPolys(3).Vertices(2).x = 0 MyPolys(3).Vertices(2).y = 10 MyPolys(3).Vertices(2).Z = 0 MyPolys(3).NumberOfVertices = 3 MyPolys(3).PolyColor = RGB(8, 128, 128)   '** Pass the polygon data into object **' Call PEvset(Pe3do1, PEP_structPOLYDATA, MyPolys(0), 4)   Pe3do1.DegreeOfRotation = 200 Pe3do1.ViewingHeight = 30 Pe3do1.FontSize = PEFS_SMALL Call Pe3do1.DxSetLight(0, 2.0, -1.0, -2.1) Pe3do1.PlottingMethod = 2 'Solid Shading   Pe3do1.MainTitle = "" Pe3do1.SubTitle = ""   Pe3do1.ShowXAxis = PESA_EMPTY Pe3do1.ShowYAxis = PESA_EMPTY Pe3do1.ShowZAxis = PESA_EMPTY Pe3do1.RenderEngine = PERE_DIRECT3D Pe3do1.BitmapGradientMode = True Pe3do1.QuickStyle = PEQS_LIGHT_NO_BORDER Pe3do1.PEactions = 0

The above code produces the following image. Note how the vertices values range from -10 to 10.

Note the use of PEvset to transfer the polygon data into the control.

Note how ShowXAxis, ShowYAxis, and ShowZAxis are used to hide the axes of the chart. Or you can manually scale the axes as needed. ©2022 Gigasoft, Inc. | All rights reserved. Gigasoft is a registered trademark, and ProEssentials a trademark of Gigasoft, Inc.