Custom colors on bar chart using Zedgraph library - vb.net

Am using Zedgraph chart library but I can't seem to be able to color a bar graph depending on a specific condition. Am following along with the example found on this tutorial.
In my case, if the value isn't above 50 -which is the student.pass_mark variable-, I want to color the bar red and if its above 50 I want to color it green. Below is my code. Which so far only gives me red even though I have values of 100, 80, 110 etc.
Dim subject As String
Dim grade As Decimal
Dim colors As Color() = {}
Dim subject_names As String() = {}
For i = 0 To student.no_of_subjects
ReDim Preserve colors(i)
ReDim Preserve subject_names(i)
subject = student.subject_name
grade = student.grade
Dim x As Double = CDbl(i) + 1
Dim y As Double = grade
Dim z As Double = 0
list.Add(x, y, z)
If grade < student.pass_mark Then
colors(i) = Color.Red
Else
colors(i) = Color.Green
End If
subject_names(i) = subject
Next
Dim myCurve As BarItem = myPane.AddBar("Student Subject", list, Color.Blue)
'Dim colors As Color() = {Color.Red, Color.Yellow, Color.Green, Color.Blue, Color.Purple}
myCurve.Bar.Fill = New Fill(colors)
myCurve.Bar.Fill.Type = FillType.Solid
myCurve.Bar.Fill.RangeMin = 0
myCurve.Bar.Fill.RangeMax = 4
myPane.Chart.Fill = New Fill(Color.White, Color.FromArgb(220, 220, 255), 45)
myPane.Fill = New Fill(Color.White, Color.FromArgb(255, 255, 225), 45)
' Tell ZedGraph to calculate the axis ranges
' Set the XAxis labels
myPane.XAxis.Scale.TextLabels = subject_names
' Set the XAxis to Text type
myPane.XAxis.Type = ZedGraph.AxisType.Text
ZedChart.IsShowPointValues = True
ZedChart.AxisChange()
ZedChart.Refresh()
Also, I want to draw a line across the whole chart that shows the pass_mark so that it is quickly visible that a student' has or hasn't passed a certain subject in comparison to the passmark

I don't know whether it is still relative but you can do multi-colored bar plots in ZedGraph.
You can find the tutorial here:
http://zedgraph.dariowiz.com/indexb806.html?title=Multi-Colored_Bar_Demo
In your case you can use FillType.GradientByColorValue I assume.
For the line you can simply add a LineObj to the myPane.GraphObjList

Related

How to get rid of pixelated edges of a jpg?

For my student project, I’ve a vb.net code snippet that downloads a jpg file from a website and then sets all its pixels, which are almost white, entirely white:
Dim oColor As Color
Dim bRed As Byte
Dim bGreen As Byte
Dim bBlue As Byte
Dim imgTemp As Image = Image.FromFile("C:\DownloadedImage.jpg")
Dim bmpTemp As New Bitmap(imgTemp.Width, imgTemp.Height, Imaging.PixelFormat.Format32bppArgb)
Using gfx As Graphics = Graphics.FromImage(bmpTemp)
gfx.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
gfx.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
gfx.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
gfx.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
gfx.DrawImage(imgTemp, 0, 0)
End Using
For x = 0 To bmpTemp.Width - 1
For y = 0 To bmpTemp.Height - 1
oColor = bmpTemp.GetPixel(x, y)
bRed = oColor.R
bGreen = oColor.G
bBlue = oColor.B
If bRed <= 254 AndAlso bRed >= 254 - 20 Then '20 = White Tolerance'
bmpTemp.SetPixel(x, y, Color.White)
End If
If bGreen <= 254 AndAlso bGreen >= 254 - 20 Then
bmpTemp.SetPixel(x, y, Color.White)
End If
If bBlue <= 254 AndAlso bBlue >= 254 - 20 Then
bmpTemp.SetPixel(x, y, Color.White)
End If
Next
Next
Dim newForm As New Form With {.BackgroundImage = bmpTemp, .TransparencyKey = Color.White, .BackgroundImageLayout = ImageLayout.Zoom, .BackColor = Color.White}
newForm.Show()
The bitmap created in this way is then set as the BackgroundImage of a form whose TransparencyKey property is white. The result is not a complete failure, but the edges of the isolated object are still white and pixelated:
The result in two different sizes (left) and what I'm trying to achieve (right)
I’m now looking for a way to get rid of those ragged edges, something like Photoshop’s “Refine Edge” function.
Many thanks in advance!

VB.NET Multiple titles at same height in a windows forms chart

How do I put multiple titles into a chart at the same height?
No matter what parameters I choose I get results similar to this. My last try before asking here.
The screen shot shows the titles with a backcolor to prove what I expected.
Whenever I add 2 titles WinForms automatically puts them in different heights.
The 3. line is custom added to show you what I want to have as a result.
I could write a method but it should react to resize events and solving this with docking or alignments is preferred.
So right now the titles are inside the chartarea because I was fiddling around with DockingOffsets etc. I want them to be on top of the chartarea.
Here is my code:
Friend Function CreateTitle(ByVal titleName As TitleName, ByVal chart As Chart) As Title
Dim font As Font = Nothing
Dim foreColor As Color = Nothing
Dim backColor As Color = Nothing
Dim alignment As ContentAlignment = Nothing
Dim dockingOffset As Integer
Dim name As String = String.Empty
Dim titleText As String = String.Empty
Dim dockedToChartArea As String = String.Empty
Dim docking As Docking = Nothing
' Default settings
font = New Font("Arial", 12)
foreColor = color.blue
dockingOffset = 0
dockedToChartArea = chart.ChartAreas(0).Name
' Custom settings
Select Case titleName
Case ChartControls.TitleName.ComponentName
name = TITLENAME_COMP
titleText = chart.Name
alignment = ContentAlignment.BottomLeft
dockingOffset = 0
docking = DataVisualization.Charting.Docking.Top
backColor = Color.Coral
Case ChartControls.TitleName.TrafficLight
name = TITLENAME_TRAFFICLIGHT
titleText = "+34.6% / 1800 €"
alignment = ContentAlignment.TopRight
dockingOffset = 0
docking = DataVisualization.Charting.Docking.Top
backColor = Color.Beige
End Select
Dim title As New Title(titleText)
title.Name = name
title.Font = font
title.ForeColor = foreColor
title.BackColor = backColor
title.Alignment = alignment
title.Position = New ElementPosition()
title.Docking = docking
title.DockingOffset = dockingOffset
title.DockedToChartArea = dockedToChartArea
Return title
End Function
I call this method twice with different parameters and add them to my Titles collection.
I had to change my workaround because of requirements. It would have been very time consuming to make my workaround work for 1 .. n charts that differ in size depending on the amount of charts because then the labels would need a different size and position. So I had to find a better solution.
I have a Enum with 2 different title. The following properties are important.
Backcolor = Transparent
Only for one title choose a custom position. This turns the property "Position.Auto" to false. Take a look at my if clause at the end. So because the other property "Position.Auto" stays true because you don't manually change it you can simply assign a offset while bringing the other title manually to the same height.
.
`Friend Function CreateTitle(ByVal titleName As TitleName) As Title
Dim titleText As String = String.Empty
Dim alignment As ContentAlignment
' Custom settings
Select Case titleName
Case ChartControls.TitleName.Title1
titleText = "Title1"
alignment = ContentAlignment.MiddleLeft
Case ChartControls.TitleName.Title2
titleText = "Title2"
alignment = ContentAlignment.TopRight
End Select
Dim title As New Title()
title.Text = titleText
title.Font = New Font("Arial", 12)
title.BackColor = Color.Transparent
If titleName.Equals(CCT.ChartControls.TitleName.Title2) Then
title.Position = New ElementPosition(0, 3, 94, 5)
Else
title.DockingOffset = 0
End If
title.Alignment = alignment
Return title
End Function`
Looks like this: 2 titles on same height.

Creating a chart in VisualBasic.net which has a Y axis comprising of string values

I'd like to create a chart in VB.net which has X and Y values in the form of a string.
Example below:
Sorry for the bad drawing, but this is what I'd like it to do
Can anybody help me find the settings to do this?
I can transfer data to a graph but it ends up looking like this:
This is what my current graph looks like. As you can see, I can't get the Y axis working.
(also dont worry about the X axis containing the grades, that's just something I need to fix. The grades string() still contains the right data)
This is a sample of my code: (don't worry about delimitegrades(), that just formats data for the grades into 'A', 'B', etc)
Subjects is a string() list.
Grades is an array which contains the data I need to insert. ChrtSubgrade is the chart itself.
Public Sub CreateGraph(ByVal name As String, subjects() As String)
MsgBox("Generating graph for " & name)
chrtSubgrade.Series.Clear()
chrtSubgrade.Series.Add("Data")
chrtSubgrade.Series(0).ChartType = DataVisualization.Charting.SeriesChartType.Column
chrtSubgrade.Series(0).YValueType = DataVisualization.Charting.ChartValueType.String
chrtSubgrade.Series(0).IsValueShownAsLabel = True
delimitgrades(subjects)
For i = 0 To subjects.Count - 2
chrtSubgrade.Series(0).Points.AddXY(subjects(i), grades(i))
Next
I've breakpointed all the code and the arrays and data transfer is fine so I believe it's just down to how I'm creating the graph.
I can't link the chart to a database since I'm drawing the source data from an XML file.
Thanks very much for any help you might be able to give.
I figured out a new method. Instead of using the VB charting tools I made my own. Here's the code:
Public Sub CreateGraph(ByVal name As String, subjects() As String)
delimitgrades(subjects) 'collects the info from subjects which contains the grade data and make a new array from it containing only grades
MsgBox("Generating graph for " & name)
Dim mygraphics As Graphics = Graphics.FromHwnd(hwnd:=ActiveForm.Handle) 'defines a new graphics set on the Grades window
Dim axespen As New Pen(Color.Black, 5) 'makes a pen so I can draw the axes
Dim Xaxisleft As New Point(30, 350) 'defines the left point of the X axis
Dim Xaxisright As New Point(400, 350) 'defines the right point of the X axis
Dim Yaxisbottom As New Point(30, 350) 'defines the bottom point of the Y axis
Dim yaxistop As New Point(30, 80) 'defines the top point of the Y axis
For i = 0 To 4 'for each possible grade - A* through D
Dim labelgrade As New Label 'makes a label
With labelgrade 'with said label
.BackColor = Color.Transparent 'makes its background colourless
.AutoSize = True 'resizes the bounding box
Select Case i 'examines I - the counting variable
Case Is = 0 ' if its 0
.Text = "A*" ' sets the labels text to A*
.Location = New Point(2, 100) 'moves it to the right place
Case Is = 1 'etc
.Text = "A"
.Location = New Point(2, 140)
Case Is = 2
.Text = "B"
.Location = New Point(2, 180)
Case Is = 3
.Text = "C"
.Location = New Point(2, 220)
Case Is = 4
.Text = "D"
.Location = New Point(2, 260)
End Select '/etc
End With
Controls.Add(labelgrade) 'inserts the label into the form
Next
For i = 0 To subjects.Count - 2 'the last part of the subjects array is empty so it counts to the last position containing data
Dim labelsubject As New Label 'makes a new label
Dim labelxoffset As Integer = 30 'defines the variable xoffset which is used to determine where all labels should be placed
With labelsubject 'with this label
.BackColor = Color.Transparent 'make the background colourless
.AutoSize = True 'resize the bounding box
Select Case i 'examine i
Case Is = 0 'if this is the first label placed onto the form
.Text = subjects(i) 'take the first entry in the subjects array
.Location = New Point(30, 355) 'place the label on the X axis in the first position
Case Else 'otherwise
.Text = subjects(i) 'take the right name from the array and make the label reflect this name
.Location = New Point(labelxoffset + (i * 70), 365) 'set its location depending on which place it is in the array using xoffset
End Select
End With
Controls.Add(labelsubject) 'add the label to the form
Next
'Axes
mygraphics.DrawLine(axespen, Xaxisleft, Xaxisright) 'create
mygraphics.DrawLine(axespen, Yaxisbottom, yaxistop) 'the axes
'bars
For i = 0 To grades.Count - 1 'from 0 to the second to last entry in the grades array (this is because of how I formed the grades array. It still works.
Dim grade As String = grades(i) 'create a temp variable to store the correct entry from the grades array
Dim gradeindex As Integer = Nothing ' create the index integer, this is used to determine how high the bar should go
Dim gradepen As New Pen(Color.Green, 50) 'make the pen for the bars
Dim p1 As New Point(30, 350) 'define point 1 as above the first label
Dim p2 As New Point 'create point 2
Dim x As Integer = (58 + (70 * i)) 'create a new xoffset integer
Dim yoffset As Integer = 348 ' create the yoffset integer. This is to place the bottom point of the bar correctly
Select Case grade 'examine grade
Case Is = "A*" 'if its A*
gradeindex = 100 'the top y coord is 100
p1 = New Point(x, yoffset) 'p1 is now x, yoffset
p2 = New Point(x, gradeindex) 'p2 is now x, gradeindex
Case Is = "A" 'etc
gradeindex = 140
p1 = New Point(x, yoffset)
p2 = New Point(x, gradeindex)
Case Is = "B"
gradeindex = 180
p1 = New Point(x, yoffset)
p2 = New Point(x, gradeindex)
Case Is = "C"
gradeindex = 220
p1 = New Point(x, yoffset)
p2 = New Point(x, gradeindex)
gradepen = New Pen(Color.Orange, 50) 'make the grade pen orange
Case Is = "D"
gradeindex = 260
p1 = New Point(x, yoffset)
p2 = New Point(x, gradeindex)
gradepen = New Pen(Color.Red, 50) 'make the grade pen red
End Select '/etc
mygraphics.DrawLine(gradepen, p1, p2) 'draw the line from p1 to p2
Next
End Sub
Here's the output for someone who has the following data: German;A* , Maths;A , French;A* , Bio;C , Bus(business for example);B
Output
Hope this helps anyone else having this issue. Thanks!

Aligning zeros in two Y Axis of DataVisualization.Charting.Chart

I have two series in a DataVisualization.Charting.Chart and two AxisY (AxisY1, and AxisY2). I was able to draw both series on a chart but the zeros for the left axis and right axis are not aligned. How can I align the zeros for the two axis?
NetChart.Series.Clear()
NetChart.Series.Add("Net")
NetChart.Series.Add("Net Cum.")
NetChart.Series(0).Points.Clear()
NetChart.Series(1).Points.Clear()
Dim netSaleDT As DataTable = SomeDataTable
netSaleDT.Columns.Add("CumulativeNet", GetType(Decimal))
Dim index As Integer = 0
Dim cumulSum As Decimal = 0
For Each drow As DataRow In netSaleDT.Rows
cumulSum += Convert.ToDecimal(drow("Net"))
drow("CumulativeNet") = cumulSum
NetChart.Series(0).Points.AddXY(drow("myMonth"), Convert.ToDecimal(drow("Net")))
NetChart.Series(1).Points.AddXY(drow("myMonth"), Convert.ToDecimal(drow("CumulativeNet")))
NetChart.Series(0).Points(index).AxisLabel = drow("myMonth")
index += 1
Next
NetChart.Series(0).YAxisType = System.Windows.Forms.DataVisualization.Charting.AxisType.Primary
NetChart.Series(1).YAxisType = System.Windows.Forms.DataVisualization.Charting.AxisType.Secondary
NetChart.Series(1).ChartType = DataVisualization.Charting.SeriesChartType.Line
NetChart.ChartAreas(0).AxisX.Interval = 2
NetChart.ChartAreas(0).AxisY.LabelStyle.Format = "C"
NetChart.ChartAreas(0).AxisY2.LabelStyle.Format = "C"
NetChart.Series(1).BorderWidth = 2
NetChart.Series(1).Color = Color.Blue
NetChart.ChartAreas(0).AxisY2.Enabled = DataVisualization.Charting.AxisEnabled.True
NetChart.ChartAreas(0).AxisY2.LabelStyle.Enabled = True
Is the axis properties set to auto?
If they are you need to manually set each axis programatically.
http://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.axis.minimum%28v=vs.110%29.aspx
When I set the min/max I usually do something like this:
Dim myChart As Excel.ChartObject = CType(xlCharts.Item(y), ChartObject)
Dim chartPage As Excel.Chart = myChart.Chart
chartPage.Axes(Excel.XlAxisType.xlCategory).minimumscale = minimum
chartPage.Axes(Excel.XlAxisType.xlCategory).maximumscale = maximum
This changes the x axis scale, to change the Y scale:
http://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.chartarea.axisy%28v=vs.110%29.aspx
and to change the secondary y scale:
http://msdn.microsoft.com/en-us/library/system.windows.forms.datavisualization.charting.chartarea.axisy2%28v=vs.110%29.aspx
Hope this helps
*Edit
Well i was trying to not give you the whole answer
But I suppose:
Dim myChart As Excel.ChartObject = CType(QoE.xLSheet1.ChartObjects(0), ChartObject)
Dim chartPage As Excel.Chart = myChart.Chart
chartPage.Axes(Excel.XlAxisGroup.xlPrimary).minimumscale = 0
chartPage.Axes(Excel.XlAxisGroup.xlSecondary).minimumscale = 0
Set the chart object to whatever chart you are trying to change, then set both the primary and secondary y axis to 0

string with surrounding color

i want to make an image in vb.net which is a string
it should be made of 2 colors one as forecolor the other as a color surrounding the first one
how should i make it using code?
my result must be some thing like this image(yellow as forecolor and red! as background)
[the string is in persian]
right now i first make the string using
Dim result As New Bitmap(100, 100)
Dim g As Graphics = Graphics.FromImage(result)
g.DrawString("My string", New Font("Arial", 40), New SolidBrush(Color.yellow), 22, 22)
and then process this image by checking every single pixel and if they are close to the string i color them as red , the code is this
kr = font_color.R
kg = font_color.G
kb = font_color.B
For i = 0 To (img.Height - 1) Step 1
prg.Value = prg.Value + 1
For j = 0 To (img.Width - 1)
If (kr = img.GetPixel(j, i).R And kg = img.GetPixel(j, i).G And kb = img.GetPixel(j, i).B) Then
'some code
ElseIf (isnabor(j, i) = True) Then'checks if it is close enough or not
img.SetPixel(j, i, back_color)
Else
img.SetPixel(j, i, Color.Transparent)
End If
Next
Next
The problem is that it takes a long time for a large image
any better way?
Try using GraphicsPath. Check the following links for more information
www.codeproject.com/Articles/42529/Outline-Text
www.java2s.com/Tutorial/VB/0300__2D-Graphics/Textoutline.htm
www.java2s.com/Tutorial/VB/0300__2D-Graphics/AddstringtoGraphicsPath.htm
Bob Powell: Text Effects
by the help of my friend i found the answer here it is:
Dim result As New Bitmap(1000, 1000)
Dim grp As Graphics = Graphics.FromImage(result)
Dim gp As New Drawing2D.GraphicsPath
Dim useFont As Font = New Font("IranNastaliq", 100, FontStyle.Regular)
grp.TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias
grp.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
gp.AddString(rr.Lines(aa), useFont.FontFamily, FontStyle.Regular, 100, New Point(0, 0), StringFormat.GenericTypographic)
useFont.Dispose()
grp.FillPath(Brushes.White, gp)
grp.DrawPath(Pens.Black, gp)
gp.Dispose()
pic.Image = result