Пример #1
0
        // 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;
            }
        }
Пример #2
0
        // Define the model.
        private void DefineModel(Model3DGroup group)
        {
            // Axes.
            //MeshExtensions.AddAxes(group);

            // Make a scatter plot.
            Point3D[]    values        = LoadData();
            string[]     xlabels       = { "10 mpg", "20 mpg", "30 mpg", "40 mpg" };
            string[]     ylabels       = { "$10 k", "$20 k", "$30 k", "$40 k", "$50 k", "$60 k" };
            string[]     zlabels       = { "100 hp", "200 hp", "300 hp", "400 hp" };
            const double labelGap      = 0.25;
            const double labelWid      = 2.25;
            const double labelHgt      = 0.75;
            const double labelFontSize = 0.6;
            const double titleHgt      = 1.5;
            const double titleFontSize = 0.7;

            MakeScatterPlot(group,
                            new Point3D(-3, -4, -3), 7, 9, 7,
                            values, Brushes.Red,
                            0.05, 0.04, Brushes.Blue, Brushes.LightBlue, Brushes.Red,
                            labelWid, labelHgt, labelGap, labelFontSize, Brushes.Blue,
                            titleHgt, titleFontSize, Brushes.DarkBlue,
                            10, 40, 5, 10, "Mileage", xlabels,
                            10000, 60000, 5000, 10000, "Base Price", ylabels,
                            100, 400, 50, 100, "Horsepower", zlabels);

            // Title.
            FontFamily ff       = new FontFamily("Franklin Gothic Demi");
            Point3D    ll       = new Point3D(-4, 7, 2);
            double     fontSize = 0.9;

            MakeLabel("Car Cost, Mileage,", ll,
                      new Vector3D(6, 0, -6), D3.YVector(1.25),
                      Brushes.Transparent, Brushes.Black, fontSize, ff,
                      HorizontalAlignment.Center, VerticalAlignment.Center, group);
            ll.Y -= 1;
            MakeLabel("and Horsepower", ll,
                      new Vector3D(6, 0, -6), D3.YVector(1.25),
                      Brushes.Transparent, Brushes.Black, fontSize, ff,
                      HorizontalAlignment.Center, VerticalAlignment.Center, group);
        }
Пример #3
0
        // 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;
            }
        }
Пример #4
0
        // 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;
            }
        }
Пример #5
0
        // Make a box with the back XY, YZ, and ZX planes labeled with lines,
        // tick marks, and labels every 1 unit.
        public void MakePlotBox(Model3DGroup group,
                                Point3D corner, double xLength, double yLength, double zLength,
                                double boxThickness, double lineThickness,
                                Brush boxBrush, Brush lineBrush, Brush tickBrush,
                                double labelWid, double labelHgt, double labelGap, double labelFontSize, Brush labelBrush,
                                double titleHgt, double titleFontSize, Brush titleBrush,
                                double xmin, double xmax, double tickDx, double labelDx, string xtitle, string[] xlabels,
                                double ymin, double ymax, double tickDy, double labelDy, string ytitle, string[] ylabels,
                                double zmin, double zmax, double tickDz, double labelDz, string ztitle, string[] zlabels)
        {
            const double tickWid = 0.2;
            FontFamily   ff      = new FontFamily("Franklin Gothic Demi");

            // Draw the box outline.
            Vector3D       vx      = D3.XVector(xLength);
            Vector3D       vy      = D3.YVector(yLength);
            Vector3D       vz      = D3.ZVector(zLength);
            MeshGeometry3D boxMesh = new MeshGeometry3D();

            boxMesh.AddSegment(boxThickness, corner, corner + vx);
            boxMesh.AddSegment(boxThickness, corner, corner + vy);
            boxMesh.AddSegment(boxThickness, corner, corner + vz);
            boxMesh.AddSegment(boxThickness, corner + vy, corner + vy + vx);
            boxMesh.AddSegment(boxThickness, corner + vy, corner + vy + vz);
            boxMesh.AddSegment(boxThickness, corner + vx, corner + vx + vy);
            boxMesh.AddSegment(boxThickness, corner + vx, corner + vx + vz);
            boxMesh.AddSegment(boxThickness, corner + vz, corner + vz + vx);
            boxMesh.AddSegment(boxThickness, corner + vz, corner + vz + vy);
            group.Children.Add(boxMesh.MakeModel(boxBrush));

            // Minimum X, Y, and Z values, and scales.
            double px1    = corner.X;
            double px2    = corner.X + xLength;
            double py1    = corner.Y;
            double py2    = corner.Y + yLength;
            double pz1    = corner.Z;
            double pz2    = corner.Z + zLength;
            double xScale = xLength / (xmax - xmin);
            double yScale = yLength / (ymax - ymin);
            double zScale = zLength / (zmax - zmin);

            // Lines and labels.
            MeshGeometry3D lineMesh = new MeshGeometry3D();

            // Lines with different X values.
            Point3D ll;
            int     i = 0;

            for (double x = xmin; x < xmax + labelDx / 2; x += labelDx)
            {
                double px = px1 + (x - xmin) * xScale;

                // Label the line.
                ll = new Point3D(px + labelHgt / 2, py1, pz2 + labelWid + labelGap);
                MakeLabel(xlabels[i++], ll, D3.ZVector(-labelWid), D3.XVector(-labelHgt),
                          Brushes.Transparent, labelBrush, labelFontSize, ff,
                          HorizontalAlignment.Right, VerticalAlignment.Center, group);

                // Draw the line.
                if ((x > xmin) && (x < xmax - labelDx / 2))
                {
                    lineMesh.AddSegment(lineThickness,
                                        new Point3D(px, py1, pz1),
                                        new Point3D(px, py2, pz1));
                    lineMesh.AddSegment(lineThickness,
                                        new Point3D(px, py1, pz1),
                                        new Point3D(px, py1, pz2));
                }
            }

            // Lines with different Y values.
            i = 0;
            for (double y = ymin; y < ymax + labelDy / 2; y += labelDy)
            {
                double py = py1 + (y - ymin) * yScale;

                // Label the line.
                if (y > ymin)
                {
                    ll = new Point3D(px1, py - labelHgt / 2, pz2 + labelWid + labelGap);
                    MakeLabel(ylabels[i], ll, D3.ZVector(-labelWid), D3.YVector(labelHgt),
                              Brushes.Transparent, labelBrush, labelFontSize, ff,
                              HorizontalAlignment.Right, VerticalAlignment.Center, group);
                }
                i++;

                // Draw the line.
                if ((y > ymin) && (y < ymax - labelDy / 2))
                {
                    lineMesh.AddSegment(lineThickness,
                                        new Point3D(px1, py, pz1),
                                        new Point3D(px2, py, pz1));
                    lineMesh.AddSegment(lineThickness,
                                        new Point3D(px1, py, pz1),
                                        new Point3D(px1, py, pz2));
                }
            }

            // Lines with different Z values.
            i = 0;
            for (double z = zmin; z < zmax + labelDz / 2; z += labelDz)
            {
                double pz = pz1 + (z - zmin) * zScale;

                // Label the line.
                ll = new Point3D(px2 + labelGap, py1, pz + labelHgt / 2);
                MakeLabel(zlabels[i++], ll, D3.XVector(labelWid), D3.ZVector(-labelHgt),
                          Brushes.Transparent, labelBrush, labelFontSize, ff,
                          HorizontalAlignment.Left, VerticalAlignment.Center, group);

                // Draw the line.
                if ((z > zmin) && (z < zmax - labelDz / 2))
                {
                    lineMesh.AddSegment(lineThickness,
                                        new Point3D(px1, py1, pz),
                                        new Point3D(px2, py1, pz));
                    lineMesh.AddSegment(lineThickness,
                                        new Point3D(px1, py1, pz),
                                        new Point3D(px1, py2, pz));
                }
            }
            group.Children.Add(lineMesh.MakeModel(lineBrush));

            // Tick marks.
            MeshGeometry3D tickMesh = new MeshGeometry3D();

            // Lines with different X values.
            for (double x = xmin + tickDx; x < xmax + tickDx / 2; x += tickDx)
            {
                double px = px1 + (x - xmin) * xScale;
                tickMesh.AddSegment(lineThickness,
                                    new Point3D(px, py1, pz2 - tickWid),
                                    new Point3D(px, py1, pz2 + tickWid));
            }

            // Lines with different Y values.
            for (double y = ymin + tickDy; y < ymax + tickDy / 2; y += tickDy)
            {
                double py = py1 + (y - ymin) * yScale;
                tickMesh.AddSegment(lineThickness,
                                    new Point3D(px1, py, pz2 - tickWid),
                                    new Point3D(px1, py, pz2 + tickWid));
            }

            // Lines with different Z values.
            for (double z = zmin; z < zmax + tickDz / 2; z += tickDz)
            {
                double pz = pz1 + (z - zmin) * zScale;
                tickMesh.AddSegment(lineThickness,
                                    new Point3D(px2 - tickWid, py1, pz),
                                    new Point3D(px2 + tickWid, py1, pz));
            }
            group.Children.Add(tickMesh.MakeModel(lineBrush));

            // Draw titles.
            ll = new Point3D(
                px1,
                py1,
                pz2 + labelWid + labelGap + titleHgt);
            MakeLabel(xtitle, ll, D3.XVector(xLength), D3.ZVector(-titleHgt),
                      Brushes.Transparent, titleBrush, titleFontSize, ff,
                      HorizontalAlignment.Center, VerticalAlignment.Top, group);

            ll = new Point3D(
                px1,
                py2,
                pz2 + labelWid + labelGap + titleHgt);
            MakeLabel(ytitle, ll, D3.YVector(-yLength), D3.ZVector(-titleHgt),
                      Brushes.Transparent, titleBrush, titleFontSize, ff,
                      HorizontalAlignment.Center, VerticalAlignment.Top, group);

            ll = new Point3D(
                px2 + labelWid + labelGap + titleHgt,
                py1,
                pz2);
            MakeLabel(ztitle, ll, D3.ZVector(-zLength), D3.XVector(-titleHgt),
                      Brushes.Transparent, titleBrush, titleFontSize, ff,
                      HorizontalAlignment.Center, VerticalAlignment.Top, group);
        }
        // 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));
                }
            }
        }