Skip to content

Instantly share code, notes, and snippets.

@danielmoore
Created May 28, 2011 22:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save danielmoore/997319 to your computer and use it in GitHub Desktop.
Save danielmoore/997319 to your computer and use it in GitHub Desktop.
Creates a new pie chart using WPK
param([string] $CountProperty = 'Count',
[string] $NameProperty = 'Name',
[double] $Width = 400,
[double] $Height = 300,
[string] $WindowTitle = 'Pie Graph',
[string] $ChartTitle = $null,
[Parameter(ValueFromPipeline = $true)] $Items,
[switch] $Show = $false)
begin {
Import-Module wpk
$total = 0
$count = 0
$computed = @()
function Get-Brightness($color) {
$sum = 0
foreach($channel in 'R','G','B') { $sum += $color.$channel }
return $sum / 255 / 3
}
$palette = [Windows.Media.Brushes] `
| gm -Static -MemberType Property `
| % { [Windows.Media.Brushes]::$($_.Name) } `
| ? { $brightness = Get-Brightness $_.Color; $brightness -gt 0.5 -and $brightness -lt 0.75 }
}
process {
if(-not $items) { return }
if ($items -isnot [Collections.IEnumerable]) { $Items = @($Items) }
foreach($item in $items.GetEnumerator()){
trap { Write-Error "Error processing item... Skipping "; continue; }
$computed += New-Object PSObject -Property @{
Name = $item.$NameProperty
Count = $item.$CountProperty
Brush = $palette[$count % $palette.Length]
Percentage = 0
}
$total += $item.$CountProperty
$count++
}
}
end {
if($total -gt 0) { foreach($item in $computed){ $item.Percentage = $item.Count / $total } }
$computed = $computed | sort -Descending Count
$legendContent = New-Grid `
-ColumnDefinitions (0..3 | % { New-ColumnDefinition -Width Auto }) `
-RowDefinitions (1..$computed.Length | % { New-RowDefinition }) `
-Children ($computed | % { $row = 0 } {
New-Border -Row $row -Column 0 -Background $_.Brush -BorderThickness 1 -BorderBrush Black -Width 10 -Height 10 -Margin 5 | Write-Output
New-TextBlock -Row $row -Column 1 -Text $_.Name -Margin 5 | Write-Output
New-TextBlock -Row $row -Column 2 -Text $_.Count.ToString('N') -Margin 5 | Write-Output
New-TextBlock -Row $row -Column 3 -Text $_.Percentage.ToString('P0') -Margin 5 | Write-Output
$row++
})
$legend = New-Border -Dock Right -VerticalAlignment Center -BorderBrush Black -BorderThickness 1 -Margin 5 -Child $legendContent
$canvas = New-Canvas -Margin 20
function Get-PieSlicePaths {
function New-Point ($x, $y) { return New-Object -TypeName 'System.Windows.Point' -ArgumentList $x, $y }
$size = [Math]::Min($canvas.ActualWidth, $canvas.ActualHeight)
$arcSize = New-Object -TypeName 'System.Windows.Size' -ArgumentList ($size / 2), ($size /2)
$origin = New-Point ($canvas.ActualWidth / 2) ($canvas.ActualHeight / 2)
$radius = $size / 2
function Convert-ToCartesian($r, $theta) {
$thetaRadians = $theta * 2 * [Math]::PI
$x = $origin.X + $r * [Math]::Sin($thetaRadians)
$y = $origin.Y - $r * [Math]::Cos($thetaRadians)
return New-Point $x $y
}
$theta = 0
$previousRadial = New-Point $origin.X ($origin.Y - $arcSize.Height)
foreach($item in $computed) {
$theta += $item.Percentage
$nextRadial = Convert-ToCartesian $radius $theta
$isLargeArc = $item.Percentage -gt 0.5
$geom = New-StreamGeometry
$ctx = $geom.Open()
try {
$ctx.BeginFigure($origin, $true, $true)
$ctx.LineTo($previousRadial, $true, $false)
$ctx.ArcTo($nextRadial, $arcSize, 0, $isLargeArc, 'Clockwise', $true, $false)
$ctx.LineTo($origin, $true, $false)
} finally { $ctx.Close() }
New-Path -Data $geom -Fill $item.Brush -Stroke ([Windows.Media.Brushes]::Black) -StrokeThickness 1 | Write-Output
$previousRadial = $nextRadial
}
}
if($chartTitle) { $chartTitleTextBlock = New-TextBlock -Text $chartTitle -FontSize 24 -FontWeight 'Bold' -TextAlignment 'Center' -Dock 'Top' }
$container = New-DockPanel -Children ($chartTitleTextBlock, $legend, $canvas | ? { $_ })
$window = New-Window -Content $container -Title $WindowTitle -Width $width -Height $height
$window.add_Loaded({ Get-PieSlicePaths | % { $canvas.Children.Add($_) } })
$window.add_SizeChanged({ $canvas.Children.Clear(); Get-PieSlicePaths | % { $canvas.Children.Add($_) } })
if($show) { Show-Window $window }
else { return $window }
}
@danielmoore
Copy link
Author

http://yfrog.com/h0nyydp
.\New-PieChart.ps1 -CountProperty 'Value' -ChartTitle 'This is a Test Chart' -Items @{ Alpha = 40; Beta = 30; Delta = 20; Gamma = 10 } -Show

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment