// Make rows of bars in the X and Z directions. private void MakeRowColumnBars(double xmin, double ymin, double zmin, double dx, double gap, double[,] values, string[] frontLabels, string[] sideLabels, Brush[,] barBrushes, Brush[] bgBrushes, Brush[] fgBrushes, FontFamily ff, Model3DGroup group) { int numX = values.GetUpperBound(0) + 1; int numZ = values.GetUpperBound(1) + 1; double x = xmin; double z; double fontSize = 0.3; for (int ix = 0; ix < numX; ix++) { z = zmin; for (int iz = 0; iz < numZ; iz++) { // Make the bar. MeshGeometry3D barMesh = new MeshGeometry3D(); Point3D corner = new Point3D(x, ymin, z); barMesh.AddBox(corner, D3.XVector(dx), D3.YVector(YScale * values[ix, iz]), D3.ZVector(dx)); group.Children.Add(barMesh.MakeModel(barBrushes[ix, iz])); z += dx + gap; } // Display the front label. const double textWid = 2; MakeLabel(frontLabels[ix], new Point3D(x + dx, ymin, z + textWid), D3.ZVector(-textWid), D3.XVector(-dx), bgBrushes[ix], fgBrushes[ix], fontSize, ff, HorizontalAlignment.Left, VerticalAlignment.Center, group); x += dx + gap; } // Display the side labels. z = zmin + dx; double xmax = xmin + numX * dx + (numX - 1) * gap; for (int iz = 0; iz < numZ; iz++) { const double textWid = 2; MakeLabel(sideLabels[iz], new Point3D(xmax + gap, ymin, z), D3.XVector(textWid), D3.ZVector(-dx), Brushes.Transparent, Brushes.Black, fontSize, ff, HorizontalAlignment.Left, VerticalAlignment.Center, group); //MakeLabel(sideLabels[iz], // new Point3D(xmin - textWid - gap, ymin, z), // D3.XVector(textWid), D3.ZVector(-dx), // Brushes.Transparent, Brushes.Black, fontSize, ff, // HorizontalAlignment.Left, VerticalAlignment.Center, group); z += dx + gap; } }
// Make a row of bars in the X direction. private void MakeBars(double xmin, double ymin, double zmin, double dx, double gap, double[] values, string[] frontLabels, string[] topLabels, Brush[] barBrushes, Brush[] bgBrushes, Brush[] fgBrushes, FontFamily ff, Model3DGroup group) { double x = xmin; double fontSize = 0.4; for (int i = 0; i < values.Length; i++) { // Make the bar. MeshGeometry3D barMesh = new MeshGeometry3D(); Point3D corner = new Point3D(x, ymin, zmin); barMesh.AddBox(corner, D3.XVector(dx), D3.YVector(YScale * values[i]), D3.ZVector(dx)); group.Children.Add(barMesh.MakeModel(barBrushes[i])); // Display the front label. const double textWid = 1.8; MakeLabel(frontLabels[i], new Point3D(x + dx, ymin, textWid + zmin + dx + gap), D3.ZVector(-textWid), D3.XVector(-dx), bgBrushes[i], fgBrushes[i], fontSize, ff, HorizontalAlignment.Left, VerticalAlignment.Center, group); // Display the top label. MakeLabel(topLabels[i], new Point3D(x, ymin + YScale * values[i], zmin - 0.1), D3.XVector(dx), D3.YVector(dx), Brushes.Transparent, fgBrushes[i], fontSize, ff, HorizontalAlignment.Center, VerticalAlignment.Bottom, group); x += dx + gap; } }
// Make a row of stacked bars in the X direction. private void MakeStackedBars(double xmin, double ymin, double zmin, double dx, double gap, double[,] values, string[] frontLabels, Brush[] barBrushes, Brush bgBrush, Brush fgBrush, FontFamily ff, Model3DGroup group) { double x = xmin; int numX = values.GetUpperBound(0) + 1; int numZ = values.GetUpperBound(1) + 1; double fontSize = 0.45; for (int ix = 0; ix < numX; ix++) { double y = ymin; for (int iz = 0; iz < numZ; iz++) { // Make this piece of the bar. MeshGeometry3D barMesh = new MeshGeometry3D(); Point3D corner = new Point3D(x, y, zmin); barMesh.AddBox(corner, D3.XVector(dx), D3.YVector(YScale * values[ix, iz]), D3.ZVector(dx)); group.Children.Add(barMesh.MakeModel(barBrushes[iz])); y += YScale * values[ix, iz]; } // Display the front label. const double textWid = 1.5; MakeLabel(frontLabels[ix], new Point3D(x + dx, ymin, textWid + zmin + dx + gap), D3.ZVector(-textWid), D3.XVector(-dx), bgBrush, fgBrush, fontSize, FontFamily, HorizontalAlignment.Left, VerticalAlignment.Center, group); x += dx + gap; } }
// Define the model. private void DefineModel(Model3DGroup group) { // Axes. //MeshExtensions.AddAxes(group); // General positioning parameters. Point3D origin = new Point3D(0, -1, 0); double[] values = LoadData(); double[] heights = LoadHeights(); Brush[] brushes = { Brushes.Red, Brushes.Green, Brushes.Blue, Brushes.Orange }; double radius = 3; double height = 1; MakeRaggedPieSlices(origin, radius, values, heights, brushes, 60, group); // Title. FontFamily ff = new FontFamily("Franklin Gothic Demi"); Point3D ll = new Point3D(-radius, origin.Y + height + 2, radius); double fontSize = 0.9; MakeLabel("Sales Makeup", ll, D3.ZVector(-2 * radius), D3.YVector(1.25), Brushes.Transparent, Brushes.Blue, fontSize, ff, HorizontalAlignment.Center, VerticalAlignment.Center, group); // Key. string[,] keyLabels = { { "", "A", "B", "C", "D" }, { "Units", "", "", "", "" }, { "$ (M)", "", "", "", "" }, }; for (int i = 1; i < 5; i++) { keyLabels[1, i] = values[i - 1].ToString() + "%"; keyLabels[2, i] = "$" + (100 * heights[i - 1]).ToString(); } Brush[,] keyBrushes = { { Brushes.Red, Brushes.Green, Brushes.Blue, Brushes.Orange, }, { Brushes.Red, Brushes.Green, Brushes.Blue, Brushes.Orange, }, }; const double wid = 1; const double hgt = 0.6; const double xgap = 0.1; const double ygap = 0.1; int numRows = keyLabels.GetUpperBound(0) + 1; int numCols = keyLabels.GetUpperBound(1) + 1; double keyWid = numCols * wid + (numCols - 1) * xgap; double keyHgt = numRows * hgt + (numRows - 1) * ygap; double y = origin.Y + height + keyHgt - hgt + 1.5; fontSize = 0.4; for (int row = 0; row < numRows; row++) { double x = -keyWid / 2; for (int col = 0; col < numCols; col++) { ll = new Point3D(x, y, -radius); Brush fgBrush = Brushes.Black; Brush bgBrush = Brushes.Transparent; if ((row > 0) && (col > 0)) { fgBrush = Brushes.White; bgBrush = keyBrushes[row - 1, col - 1]; } MakeLabel(keyLabels[row, col], ll, D3.XVector(wid), D3.YVector(hgt), bgBrush, fgBrush, fontSize, ff, HorizontalAlignment.Center, VerticalAlignment.Center, group); x += wid + xgap; } y -= hgt + ygap; } }