// 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;
            }
        }
Beispiel #4
0
        // Process the models.
        private void ProcessModels(bool invertTextures, bool zIsUp)
        {
            // Make the dictionary of materials.
            foreach (ObjMaterial material in AllMaterials)
            {
                // Make the material's MaterialGroup.
                material.MatGroup = new MaterialGroup();

                // Transparency. (Not used.)
                byte alpha = (byte)(material.Alpha * 255);

                // Diffuse.
                byte            diffR     = (byte)(material.Kd.X * 255);
                byte            diffG     = (byte)(material.Kd.Y * 255);
                byte            diffB     = (byte)(material.Kd.Z * 255);
                Color           diffColor = Color.FromArgb(255, diffR, diffG, diffB);
                SolidColorBrush diffBrush = new SolidColorBrush(diffColor);
                DiffuseMaterial diffMat   = new DiffuseMaterial(diffBrush);
                material.MatGroup.Children.Add(diffMat);

                // If it has a file, use it.
                if (material.Filename != null)
                {
                    // Use the file.
                    string     filename = material.Filename;
                    ImageBrush imgBrush = new ImageBrush();
                    imgBrush.ViewportUnits = BrushMappingMode.Absolute;
                    imgBrush.TileMode      = TileMode.Tile;

                    // Invert the texture if necessary.
                    if (invertTextures)
                    {
                        TransformGroup trans = new TransformGroup();
                        trans.Children.Add(new ScaleTransform(1, -1));
                        trans.Children.Add(new TranslateTransform(0, 1));
                        imgBrush.Transform = trans;
                    }

                    imgBrush.ImageSource = new BitmapImage(new Uri(filename, UriKind.Relative));
                    DiffuseMaterial imgMat = new DiffuseMaterial(imgBrush);
                    material.MatGroup.Children.Add(imgMat);
                }

                // Specular.
                byte             specR     = (byte)(material.Ks.X * 255);
                byte             specG     = (byte)(material.Ks.Y * 255);
                byte             specB     = (byte)(material.Ks.Z * 255);
                Color            specColor = Color.FromArgb(255, specR, specG, specB);
                SolidColorBrush  specBrush = new SolidColorBrush(specColor);
                SpecularMaterial specMat   = new SpecularMaterial(specBrush, material.Ns);
                material.MatGroup.Children.Add(specMat);

                // We ignore Ka and Tr.

                // Add it to the materials dictionary.
                MtlMaterials.Add(material.Name, material);
            }

            // Convert the object models into meshes.
            foreach (ObjModel model in AllObjectModels)
            {
                // Make the mesh.
                MeshGeometry3D mesh = new MeshGeometry3D();
                Meshes.Add(mesh);
                MeshNames.Add(model.Name);
                MaterialNames.Add(model.MaterialName);

                // Make a new list of smoothing groups.
                Dictionary <int, Dictionary <Point3D, int> > smoothingGroups =
                    new Dictionary <int, Dictionary <Point3D, int> >();

                // Entry 0 is null (no smoothing).
                smoothingGroups.Add(0, null);

                // Make the faces.
                foreach (ObjFace face in model.Faces)
                {
                    // Make the face's vertices.
                    int       numPoints = face.Vertices.Count;
                    Point3D[] points    = new Point3D[numPoints];
                    for (int i = 0; i < numPoints; i++)
                    {
                        points[i] = AllVertices[face.Vertices[i] - 1];
                    }

                    // Get texture coordinates if present.
                    Point[] textureCoords = null;
                    if (face.TextureCoords.Count > 0)
                    {
                        textureCoords = new Point[numPoints];
                        for (int i = 0; i < numPoints; i++)
                        {
                            textureCoords[i] = AllTextureCoordinates[face.TextureCoords[i] - 1];
                        }
                    }

                    // Get normals if present.
                    Vector3D[] normals = null;
                    if (face.Normals.Count > 0)
                    {
                        normals = new Vector3D[numPoints];
                        for (int i = 0; i < numPoints; i++)
                        {
                            normals[i] = AllNormals[face.Normals[i] - 1];
                        }
                    }

                    // Get the point dictionary for this smoothing group.
                    // Add new groups if needed.
                    if (!smoothingGroups.ContainsKey(face.SmoothingGroup))
                    {
                        smoothingGroups.Add(face.SmoothingGroup,
                                            new Dictionary <Point3D, int>());
                    }
                    Dictionary <Point3D, int> pointDict = smoothingGroups[face.SmoothingGroup];

                    // Make the polygon.
                    mesh.AddPolygon(pointDict: pointDict,
                                    textureCoords: textureCoords, normals: normals,
                                    points: points);
                }

                // If Z is up, rotate the model.
                if (zIsUp)
                {
                    mesh.ApplyTransformation(D3.Rotate(D3.XVector(), D3.Origin, -90));
                }
            }
        }
        // Define the model.
        private void DefineModel(Model3DGroup group)
        {
            // Axes.
            //MeshExtensions.AddAxes(group);

            // General positioning parameters.
            Point3D origin = new Point3D(-2, -3, 0);
            double  barDx  = 1;
            double  barGap = 0.25;

            // Load the data.
            double[,] values = LoadData();
            int numX = values.GetUpperBound(0) + 1;
            int numZ = values.GetUpperBound(1) + 1;

            Brush[]  barBrushes  = { Brushes.Green, Brushes.Blue, Brushes.White, Brushes.Red };
            string[] frontLabels =
            { " 1960", " 1970", " 1980", " 1990", " 2000", " 2010" };

            // See how big the bars will be.
            double widX    = numX * barDx + (numX - 1) * barGap;
            double widZ    = numZ * barDx + (numZ - 1) * barGap;
            double hgt     = YMax * YScale;
            double barXmin = origin.X - widX / 2;
            double barXmax = barXmin + widX;
            double barYmin = origin.Y;
            double barYmax = barYmin + hgt;
            double barZmin = origin.Z - barDx / 2;
            double barZmax = barZmin + barDx;

            // Bars.
            FontFamily ff = new FontFamily("Franklin Gothic Demi");

            MakeStackedBars(barXmin, barYmin, barZmin, barDx, barGap, values,
                            frontLabels, barBrushes, Brushes.Transparent, Brushes.Black,
                            ff, group);

            // Title.
            MakeLabel("US Military",
                      new Point3D(barXmin, barYmax + 1, barZmin - 0.1),
                      D3.XVector(widX), D3.YVector(1),
                      Brushes.Transparent, Brushes.Green, 0.9, ff,
                      HorizontalAlignment.Center, VerticalAlignment.Center, group);
            MakeLabel("Composition",
                      new Point3D(barXmin, barYmax, barZmin - 0.1),
                      D3.XVector(widX), D3.YVector(1),
                      Brushes.Transparent, Brushes.Green, 0.9, ff,
                      HorizontalAlignment.Center, VerticalAlignment.Center, group);

            // Lines behind.
            MeshGeometry3D mesh = new MeshGeometry3D();
            Point3D        p1   = new Point3D(barXmin - barGap / 2, barYmin, barZmin - 0.1);
            Point3D        p2   = new Point3D(barXmax + barGap / 2, barYmin, barZmin - 0.1);

            for (double y = 0; y < YMax; y += 500000)
            {
                p1.Y = barYmin + y * YScale;
                p2.Y = p1.Y;
                mesh.AddSegment(0.05, p1, p2);
            }
            group.Children.Add(mesh.MakeModel(Brushes.Red));

            // Line labels.
            p1 = new Point3D(barXmax + barGap, barYmin, barZmin - 0.1);
            for (double y = 0; y < YMax; y += 1000000)
            {
                p1.Y = barYmin + y * YScale - 0.25;
                string text = ((int)(y / 1000000)).ToString() + " M";
                MakeLabel(text, p1,
                          D3.XVector(0.5), D3.YVector(0.5),
                          Brushes.Transparent, Brushes.Black, 0.25, ff,
                          HorizontalAlignment.Left, VerticalAlignment.Center, group);
            }

            // Key.
            const double textWidth = 1.5;
            Point3D      point     = new Point3D(barXmax + 2 * barGap + 0.5, barYmin, barZmin);

            MakeLabel("", point,
                      D3.XVector(0.5), D3.YVector(0.5),
                      Brushes.Green, Brushes.Black, 0.3, ff,
                      HorizontalAlignment.Left, VerticalAlignment.Center, group);
            point.X += 0.5;
            MakeLabel(" Army", point,
                      D3.XVector(textWidth), D3.YVector(0.5),
                      Brushes.Transparent, Brushes.Black, 0.3, ff,
                      HorizontalAlignment.Left, VerticalAlignment.Center, group);
            point.X -= 0.5;
            point.Y += 0.75;
            MakeLabel("", point,
                      D3.XVector(0.5), D3.YVector(0.5),
                      Brushes.Blue, Brushes.Black, 0.3, ff,
                      HorizontalAlignment.Left, VerticalAlignment.Center, group);
            point.X += 0.5;
            MakeLabel(" Navy", point,
                      D3.XVector(textWidth), D3.YVector(0.5),
                      Brushes.Transparent, Brushes.Black, 0.3, ff,
                      HorizontalAlignment.Left, VerticalAlignment.Center, group);
            point.X -= 0.5;
            point.Y += 0.75;
            MakeLabel("", point,
                      D3.XVector(0.5), D3.YVector(0.5),
                      Brushes.White, Brushes.Black, 0.3, ff,
                      HorizontalAlignment.Left, VerticalAlignment.Center, group);
            point.X += 0.5;
            MakeLabel(" Air Force", point,
                      D3.XVector(textWidth), D3.YVector(0.5),
                      Brushes.Transparent, Brushes.Black, 0.3, ff,
                      HorizontalAlignment.Left, VerticalAlignment.Center, group);
            point.Y += 0.75;
            point.X -= 0.5;
            MakeLabel("", point,
                      D3.XVector(0.5), D3.YVector(0.5),
                      Brushes.Red, Brushes.Black, 0.3, ff,
                      HorizontalAlignment.Left, VerticalAlignment.Center, group);
            point.X += 0.5;
            MakeLabel(" Marines", point,
                      D3.XVector(textWidth), D3.YVector(0.5),
                      Brushes.Transparent, Brushes.Black, 0.3, ff,
                      HorizontalAlignment.Left, VerticalAlignment.Center, group);
        }