|
About Y axis |
Posted by Daniel on Oct-21-2015 23:11 |
|
Hi Peter,
I am about to create a horizontaly stacked bar chart with a certain scale range of 255
where I want to represent the available subnets distribution for some classes. The idea is I
don't know how to set the Y axis so that to force it to my maximum value. So considering
a chart like below how to change that 700 value (that is chose by CD library) to 255 ?
Please consider that I work in VB classic. Thank you in advance.
Regards,
Daniel
|
Re: About Y axis |
Posted by Daniel on Oct-22-2015 01:05 |
|
Hi Peter,
Meanwhile I found that method I need is somethinh like Call c.yAxis().setLinearScale(0,
256, 32). The main issue that remains is I cannot represent in the chart my 2 categories
:
"subnet used" and "subnet available".
Let's say I will have this common scenario in Class1:
- from 0-31 is "used" (red)
- from 32-63 is "available" (green)
- from 64-127 is again "used" (red)
- and finally, from 128-255 is "available" (green).
How to represent all these data on my first stacked bar chart (Class1) ?
The code I have written so far is as follows:
Public Sub createChart(viewer As Object)
Dim data0() As Variant, data1() As Variant
data0 = Array(156)
data1 = Array(100)
Dim labels() 'The labels for the bar chart
labels = Array("Class1", "Class2", "Class3", "Class4", "Class5")
Dim c As XYChart
Set c = cd.XYChart(1200, 400)
Call c.setBackground(c.linearGradientColor(0, 0, 0, 100, &H99CCFF, &HFFFFFF),
&H888888)
Call c.setRoundedFrame
Call c.setDropShadow
Dim title As ChartDirector.TextBox
Set title = c.addTitle("Subnet Usage", "ariali.ttf", 15)
Call title.setMargin2(0, 0, 15, 15)
Call c.setPlotArea(50, title.getHeight(), c.getWidth() * 6 / 10, c.getHeight() _
- title.getHeight() - 50, &HE8F0F8, -1, cd.Transparent, &HAAAAAA)
Call c.swapXY 'Swap the x and y axes to create a horizontal bar chart
Dim legendBox As legendBox
Set legendBox = c.addLegend(c.getWidth() - 10, title.getHeight(), True, "arial.ttf", 8)
Call legendBox.setAlignment(cd.TopRight)
'Both axes set to transparent
Call c.xAxis().setColors(cd.Transparent)
Call c.yAxis().setColors(cd.Transparent)
Call c.yAxis().setLinearScale(0, 256, 32) 'Y linear scale
Call c.xAxis().setLabels(labels) 'Set the labels on the x axis
Dim layer As BarLayer
Set layer = c.addBarLayer2(cd.Stack)
Call layer.addDataSet(data0, &HFF0000, "Used")
Call layer.addDataSet(data1, &HFF00, "Available")
Call layer.setBorderColor(cd.Transparent, cd.softLighting(cd.Top)) 'Soft lighting effect
Call layer.setDataLabelStyle().setAlignment(cd.Center) 'data label at the middle of
the the bar
Call layer.setLegend(cd.ReverseLegend)
Call c.packPlotArea(15, title.getHeight(), c.layoutLegend().getLeftX() - 10,
c.getHeight() - 15) 'Plot area
Set viewer.Picture = c.makePicture() 'Output the chart
End Sub
|
Re: About Y axis |
Posted by Peter Kwan on Oct-23-2015 03:02 |
|
Hi Daniel,
For your case, instead of a bar, I think it can consider as a "binary series" having 256
elements. Each element can be either 1 or 0 to represent used or unused. The chart can
then be plotted like the "Binary Series" sample code. For example:
' Create a XYChart object of size 250 x 250 pixels
Dim c
Set c = cd.XYChart(1000, 250)
' Set the plotarea at (30, 20) and of size 200 x 200 pixels
Call c.setPlotArea(100, 20, 880, 200)
'Random data
Dim data(255)
Randomize
For i = 0 To Ubound(data)
If Rnd > 0.5 Then data(i) = 1
Next
'Add a horizontal binary series as y = 1
Dim pos
pos = 1
Dim shiftedLine1
shiftedLine1 = cd.ArrayMath(data).subtract(0.5).mul(0.8).add(pos).result()
Dim reverseShiftedLine1
reverseShiftedLine1 = cd.ArrayMath(data).subtract(0.5).mul(-0.8).add(pos).result()
Dim layer1
Set layer1 = c.addStepLineLayer(shiftedLine1, cd.Transparent)
Call layer1.addDataSet(reverseShiftedLine1, cd.Transparent)
Call c.addInterLineLayer(layer1.getLine(0), layer1.getLine(1), &H00aa22, &Hcc2200)
' Set the labels on the x axis.
Call c.xAxis().setLinearScale(0, 256, 32)
Call c.yAxis().setLabels(Array("AAA", "BBB", "CCC"))
Call c.yAxis().setIndent(True)
Set viewer.Picture = c.makePicture() 'Output the chart
Hope this can help.
Regards
Peter Kwan
|
Re: About Y axis |
Posted by Daniel on Oct-23-2015 17:29 |
|
Hi Peter,
Thank you very much for your hint. Sincerely, I didn't take into account this approach,
which is very useful when you want to evaluate each IP address within a class but digging
in the CD ArrayMath class I have noted another interesting function called 'aggregate' (that
'Aggregates a data array by merging groups of elements') which seems to be suited to my
needs. In the CD documentation this function is detailed as follows: 'if the ArrayMath
object consists of an array of 50 elements, and only the elements at 0, 10, 20, 30, 40 are
not NoValue, then the groups will be defined as positions 0 - 9, 10 - 19, 20 - 29, 30 - 39
and 40 - 49'. Considering these specifications, do you think I could use it in my array so
that to mention the start and the end of an used subnet inerval. Even this method is not
proper for this type of chart, could you provide me a small example how could this
aggregate function be used to design some categories on a single barchart ?
Thank you in advance. |
Re: About Y axis |
Posted by Daniel on Oct-23-2015 21:13 |
|
Hi again,
My input data have following format:
ClassC Range
10.246.194.0 144 - 159
10.246.195.0 224 - 255
10.246.196.0 0 - 47
10.246.196.0 64 - 79
and considering your suggestions I have created a chart which is very closed to what I
want to represent in the chart. To include all possible classes (that could be 100-200) I
intend to create an array of arrays, making the chart scrollable, however as you
can see the Y axis appears as shifted to a median value, depending in a way on how
values are distributed inside my 2 arrays: isUsed() and unUsed().
The adapted routine that I used is below:
Public Sub createChart(viewer As Object)
Dim c As XYChart
Set c = cd.XYChart(1000, 250)
Call c.setPlotArea(100, 20, 880, 200)
Dim isUsed(255) As Variant, unUsed(255) As Variant, i As Long
For i = 0 To 255
If (i >= 0 And i <= 47) Or (i >= 64 And i <= 79) Then
isUsed(i) = 1
Else
unUsed(i) = 1
End If
Next i
Dim layer1 As StepLineLayer
Set layer1 = c.addStepLineLayer(isUsed, cd.Transparent)
Call layer1.addDataSet(unUsed, cd.Transparent)
Call c.addInterLineLayer(layer1.getLine(0), layer1.getLine(1), &HAA22, &HCC2200)
Call c.xAxis().setLinearScale(0, 256, 32)
Call c.yAxis().setLabels(Array("10.246.196.0", "ClassC1", "ClassC2"))
Call c.yAxis().setIndent(True)
Set viewer.Picture = c.makePicture() 'Output the chart
End Sub
And for the latest class from my example (10.246.196.0) the results will be displayed as
below. If you have alternatives of improving this type of chart please advice me.
|
Re: About Y axis |
Posted by Peter Kwan on Oct-23-2015 22:15 |
|
Hi Daniel,
For your existing code, you just need to offset the y-coordinate to put the bar in the
correct position. Instead of using 0 to 1 for the values, you may use -0.4 to 0.4 so that
the bar will be centered on the y = 0 line (the "10.246.196.0" label position). For the next
bar at Class C1, the value would then be 0.6 to 1.4. I choose -0.4 to 0.4 to leave a gap
between bars.
So the code is like:
Dim offset
offset = 0
For i = 0 To 255
If (i >= 0 And i <= 47) Or (i >= 64 And i <= 79) Then
isUsed(i) = -0.4 + offset
unUsed(i) = 0.4 + offset
Else
unUsed(i) = 0.4 + offset
isUsed(i) = -0.4 + offset
End If
Next i
In fact, the above is equivalent to my original code, which uses ArrayMath to adjust the
range from 0 to 1 to -0.4 to 0.4, and add an offset to shift the bar upwards and
downwards
shiftedLine1 = cd.ArrayMath(data).subtract(0.5).mul(0.8).add(pos).result()
reverseShiftedLine1 = cd.ArrayMath(data).subtract(0.5).mul(-0.8).add(pos).result()
In the above code, the "subtract(0.5)" part is to change (0, 1) to (-0.5, 0.5). The
mul(0.8) changes the latter to (-0.4, 0.4). Finally, the add(pos) shifted the bar upwards
or downwards to the desired position.
There are other methods to draw the same chart depending on the nature of your data.
For example, if your data consists of 3 arrays - the "labels", the "startAddrArray", the
"endAddressArray", like:
labels startAddr endAddr
10.246.194.0 144 159
10.246.195.0 224 255
10.246.196.0 0 47
10.246.196.0 64 79
You can also consider it to be like a "gnatt chart". (See the "Multi-Color Gantt Chart"
sample code). You can create a bar that covers 0 to 255 as the background. Then you
can add the 4 bars create the used segments.
Hope this can help.
Regards
Peter Kwan |
Re: About Y axis |
Posted by Daniel on Oct-24-2015 00:54 |
|
Hi Peter,
I think the +- signs should be changed a bit to make the chart to work properly:
For i = 0 To 255
If (i >= 0 And i <= 47) Or (i >= 64 And i <= 79) Then
isUsed(i) = 0.2 + offset
unUsed(i) = -0.2 + offset
Else
isUsed(i) = -0.2 + offset
unUsed(i) = 0.2 + offset
End If
Next i
I tried to reproduce the same things in the Gantt variant but I am stuck in some details.
For example, in gantt we should use a task index (start range, end range and color for
each bar) ...This means I should keep in control this new array also. Until now I
succeeded to adapt my conditions to a gantt chart but it doesn't work properly...For
instance, how to add the used subnets (red color segments) in the same barchart
together with current green intervals (used subnets) ? Are you sure is a gannt chart
feasible for my project ? Thank you.
Public Sub createChart(viewer As Object)
Dim StartDate()
StartDate = Array(144, 224, 0, 64)
Dim EndDate()
EndDate = Array(159, 255, 47, 79)
Dim labels()
labels = Array("Class1", "Class2", "Class3", "Class4")
Dim c As XYChart
Set c = cd.XYChart(620, 280, &HCCCCFF, &H0, 1)
Call c.addTitle("Simple Gantt Chart Demo", "timesbi.ttf", 15,
&HFFFFFF).setBackground(&H80)
Call c.setPlotArea(140, 55, 460, 200, &HFFFFFF, &HEEEEEE, cd.lineColor, &HC0C0C0,
&HC0C0C0).setGridWidth(1, 1, 1, 1)
Call c.swapXY
Call c.yAxis().setDateScale(0, 256, 32)
Call c.setYAxisOnRight
Call c.xAxis().setLabels(labels)
Call c.addBoxWhiskerLayer(StartDate, EndDate, Empty, Empty, Empty, &HCC00,
cd.SameAsMainColor, cd.SameAsMainColor)
Set viewer.Picture = c.makePicture()
End Sub
|
Re: About Y axis |
Posted by Peter Kwan on Oct-27-2015 01:20 |
|
Hi Daniel,
The "Multi-Color Gantt Chart" sample code demonstrates how to put multiple bars in the
same "task" ("subnet" for your case). This is by using an extra array "taskNo" array.
In general, ChartDirector expects the data to be in a certain format. If your data are not
in the format expected by ChartDirector, you may need to develop some code to convert
the data to the format expected by ChartDirector. For your case, with one subnet, the
data are
Dim StartDate()
StartDate = Array(144, 224, 0, 64)
Dim EndDate()
EndDate = Array(159, 255, 47, 79)
'All bars belong to labels(0)
Dim taskNo()
taskNo = Array(0, 0, 0, 0)
.....
Dim layer
Set layer = c.addBoxWhiskerLayer(StartDate, EndDate, Empty, Empty, Empty, &HCC00,
cd.SameAsMainColor, cd.SameAsMainColor)
Call layer.setXData(taskNo)
If you have more subnets, simply append their data to the above StartDate, endDate and
taskNo arrays.
Hope this can help.
Regards
Peter Kwan |
Re: About Y axis |
Posted by Daniel on Oct-28-2015 19:11 |
|
Hi Peter,
Considering a gantt chart for the subnet usage distribution I wrote following lines:
Public Sub createChart(viewer As Object)
Dim StartDate1(), StartDate2()
StartDate1 = Array(0, 64, 144, 224)
StartDate2 = Array(48, 80, 160)
Dim EndDate1(), EndDate2()
EndDate1 = Array(48, 80, 160, 256)
EndDate2 = Array(64, 144, 224)
Dim labels()
labels = Array("Class1", "Class2", "Class3", "Class4")
Dim taskNo()
taskNo = Array(0, 0, 0, 0)
Dim c As XYChart
Set c = cd.XYChart(620, 280, &HCCCCFF, &H0, 1)
Call c.addTitle("Simple Gantt Chart Demo", "timesbi.ttf", 15,
&HFFFFFF).setBackground(&H80)
Call c.setPlotArea(140, 55, 460, 200, &HFFFFFF, &HEEEEEE, cd.LineColor, &HC0C0C0,
&HC0C0C0).setGridWidth(1, 1, 1, 1)
Call c.swapXY
Call c.yAxis().setDateScale(0, 256, 16)
Call c.setYAxisOnRight
Call c.xAxis().setLabels(labels)
Dim layer1 As BoxWhiskerLayer
Dim layer2 As BoxWhiskerLayer
Set layer1 = c.addBoxWhiskerLayer(StartDate1, EndDate1, Empty, Empty, Empty,
&HCC00, cd.SameAsMainColor, cd.SameAsMainColor)
Set layer2 = c.addBoxWhiskerLayer(StartDate2, EndDate2, Empty, Empty, Empty,
&HCC2200, cd.SameAsMainColor, cd.SameAsMainColor)
Call layer1.setXData(taskNo)
Call layer2.setXData(taskNo)
Set viewer.Picture = c.makePicture()
End Sub
As you can see the red and green lines seem to have a different width while I expected
a constant size. Is it possible to adjust this width using a certain method or property?
A second question is related to StartDate and EndDate arrays. To plot the subnet usage I
need 2 arrays, one for start and other for end data, but the green line is interrupted
where the other range should be represented with a red color. Is it possible to fill this
red range without to create other 2 arrays for this purpose ? Thank you.
|
Re: About Y axis |
Posted by Peter Kwan on Oct-28-2015 23:33 |
|
Hi Daniel,
In the original Multi-Color gantt chart sample code, the BaseBoxLayer.setDataWidth is used
to control the bar width. Also, you may consider not to use the startDate2 and endDate2
for the red segments. Instead, you may just create a single red segment from 0 to 256 as
the background. For example:
Set layer1 = c.addBoxWhiskerLayer(StartDate1, EndDate1, Empty, Empty, Empty, &HCC00,
cd.SameAsMainColor, cd.SameAsMainColor)
Call layer1.setXData(taskNo)
Call layer1.setDataWidth(Int(200 * 4 / 5 / (UBound(labels) + 1)))
Set layer2 = c.addBoxWhiskerLayer(Array(0), Array(256), Empty, Empty, Empty, &HCC2200,
cd.SameAsMainColor, cd.SameAsMainColor)
Call layer2.setXData(Array(0))
Call layer2.setDataWidth(Int(200 * 4 / 5 / (UBound(labels) + 1)))
Hope this can help.
Regards
Peter Kwan |
Re: About Y axis |
Posted by Daniel on Oct-29-2015 00:19 |
|
Hi Peter,
Thank you very much for this hint. Indeed, the trick with that red segment as background
solved my issue. Also, it is great that line width is now automatically adjusted by upper
UBound(labels). Just one detail I have noted. The values from StartDate1 array seem to be
displayed with a small offset (1 unit I think) to the left side...Is it an optical ilussion or the
range limits are somehow truncated inside the addBoxWhiskerLayer function? Thank you.
|
Re: About Y axis |
Posted by Peter Kwan on Oct-29-2015 23:41 |
|
Hi Daniel,
For the address range from 64 to 80, after magnification using Photoshop, I found that the
image is as attached. The green bar starts from the grid line at 64 and ends at the grid line
at 80. So the chart looks accurate to me.
Regards
Peter Kwan
|
Re: About Y axis |
Posted by Daniel on Dec-26-2015 18:25 |
|
Hi Peter,
Even I still see that the grey line of the grid is not aligned on the middle of my colors (red
and green range) I will consider it as an optical ilussion. At the moment is more important
to calibrate the viewport of the gant chart so that to be able to scroll it verticaly. But
because I met other issues I will rise a new post on this topic. Thank you. |
Re: About Y axis |
Posted by Peter Kwan on Dec-29-2015 03:07 |
|
Hi Daniel,
One possible optical illusion is that many LCD monitors will shift the red block to the left by
a small amount.
In many monitors, each pixel is actually 3 subpixels RGB arranged horizontally from left to
right. The red subpixel is on the left, and so a red block will appear to shift to the left
slightly. Some people can see that a very thin dark edge between the red block and the
green block if the red block is on the left side, and a bright edge if the red block is on the
right side. This also cause the red block to appear further from the grid line (which is in the
green block) if the red block is on the left side, but not if the red block is on the right side.
Regards
Peter Kwan |
|