Visit Gigasoft's Web Site
ProEssentials v6 Help

Chapter 6: Creating 3D Charts and 3D Graphs

 

An outline of Scientific 3D Charting and 3D Graphing with ProEssentials v6 graphing controls: .NET, ActiveX, MFC Library, VCL

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

When passing data to a 3D Scientific Graph Control, the 3D Scientific Graph can only handle data passed Subset By Point. In other words, (s0,p0)..(s0,p1)..(s0,p2).. and so on. Look at SubsetByPoint for the case when TRUE.

 

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

 

For simple wire frames and solids it doesn't make much difference, but for contour, shading, and hidden line removal logic, the order of the points in the polygons is critical. Calculations are based on normal vectors and vector mathematics and the order of points determines if the vector is positive or negative.

 

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 can have a bottom or top 2D contour within the image. This contour can be in lines or colors. See ShowContour.

 

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.

 

Dim s As Integer

Dim p As Integer

 

'** Always start with this **'

Pe3do1.PEactions = 20

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.DegreeOfRotation = 55

Pe3do1.ViewingHeight = 8

 

Pe3do1.PlottingMethod = 2 ' surface with shading

Pe3do1.ShowContour = PESC_BOTTOMLINES

Pe3do1.ManualContourLine = 50

 

Pe3do1.MainTitle = "3D Example"

Pe3do1.SubTitle = ""

 

Pe3do1.XAxisLabel = "Points"

Pe3do1.ZAxisLabel = "Subsets"

Pe3do1.YAxisLabel = "Data value"

 

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 is basically an abstract value ranging from 50 to -50.

 

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.

 

Contour bottom lines are added with ShowContour, and ManualContourLine is used to add more lines to the bottom contour.

 

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.

 

Dim s As Integer

Dim p As Integer

 

Pe3do1.PEactions = 20

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(100+s*18, 100+s*18, 100+s*18)

Next s

 

Pe3do1.SubsetLabels(0) = "Hello"

Pe3do1.SubsetLabels(1) = "World"

 

Pe3do1.PointLabels(0) = "Texas"

Pe3do1.PointLabels(1) = "Washington"

 

Pe3do1.DegreeOfRotation = 309

Pe3do1.ViewingHeight = 4

Pe3do1.FontSize = PEFS_SMALL

 

Pe3do1.PlottingMethod = 1

 

Pe3do1.MainTitle = "3D Bar Chart"

Pe3do1.SubTitle = ""

 

Pe3do1.XAxisLabel = "Points"

Pe3do1.ZAxisLabel = "Subsets"

Pe3do1.YAxisLabel = "Data value"

 

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"

 

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 in this mode. 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.

 

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.DegreeOfRotation = 160

Pe3do1.ViewingHeight = 9

Pe3do1.FontSize = PEFS_SMALL

Pe3do1.SubsetsToLegend(0) = -1

 

Pe3do1.PlottingMethod = 2 'Points Plus Line

 

Pe3do1.MainTitle = "3D Scatter Chart"

Pe3do1.SubTitle = ""

 

Pe3do1.XAxisLabel = "Points"

Pe3do1.ZAxisLabel = "Subsets"

Pe3do1.YAxisLabel = "Data value"

 

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, the objects should not intersect.

 

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.

 

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(128, 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(128, 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(128, 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(128, 128, 128)

 

'** Pass the polygon data into object **'

Call PEvset(Pe3do1, PEP_structPOLYDATA, MyPolys(0), 4)

 

Pe3do1.DegreeOfRotation = 160

Pe3do1.ViewingHeight = 19

Pe3do1.FontSize = PEFS_SMALL

 

Pe3do1.PlottingMethod = 2 'Solid Shading

 

Pe3do1.MainTitle = "3D Object Chart"

Pe3do1.SubTitle = ""

 

Pe3do1.ShowXAxis = PESA_EMPTY

Pe3do1.ShowYAxis = PESA_EMPTY

Pe3do1.ShowZAxis = PESA_EMPTY

Pe3do1.ShowBoundingBox = PESBB_ALWAYS

 

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.

 

Finally, ShowBoundingBox is used to add a bounding box to image.