6

如果我在 C# 中有一个二维数组,我将如何在 Matlab 中将此数组的内容绘制为二维图?我正在使用扩展方法,即

my2DArray.PlotInMatlab();
4

1 回答 1

9

最后我得到了很好的效果。这是一个示例图,由调用 Matlab .m 文件的 .NET 4.0 C# 控制台应用程序生成:

在此处输入图像描述

好处是我们可以使用 Matlab 的所有功能来绘制图形,只需要几行 .NET。

如何在 .NET 中执行此操作:

  1. 在 Visual Studio 2010 中为 C# 创建一个新的 .NET 控制台应用程序,并将其更改为 .NET 4.0(右键单击项目,选择“属性”)。

    1. .NET 主要():

      using System;
      using System.Diagnostics;
      
      namespace MyPlotGraphUsingMatlabRuntimes
      {
          /// <summary>
          /// Display a graph in Matlab, from a .NET console app.
          /// </summary>
          class Program
          {
              static void Main(string[] args)
              {
                  var x = new double[100];
                  var y = new double[100];
                  for (int i = 0; i < 100; i++) {
                      x[i] = i;
                      y[i] = 2 ^ i;
                  }
                  MyHelper.MyMatlab.MyGraph2D(x,y);
                  Console.Write("[any key to exit]");
                  Console.ReadKey();
              }
          }
      }
      
    2. .NET 类,提供扩展方法以与 Matlab 进行互操作(命名文件MyMatlab.cs)。

      using System;
      using System.Collections.Generic;
      using MathWorks.MATLAB.NET.Arrays;
      namespace MyHelper
      {
          /// <summary>
          /// Collection of chained classes to make Matlab access easier.
          /// </summary>
          public static class MyMatlab
          {
              /// <summary>
              /// Returns a double in a format that can be passed into Matlab.
              /// </summary>
              /// <param name="toMatlab">Double to convert into a form we can pass into Matlab.</param>
              /// <returns>A double in Matlab format.</returns>
              public static MWNumericArray MyToMatlab(this double toMatlab)
              {
                  return new MWNumericArray(toMatlab);
              }
              /// <summary>
              /// Converts an array that contains a single Matlab return parameter back into a .NET double.
              /// </summary>
              /// <param name="toDouble">MWArray variable, returned from Matlab code.</param>
              /// <returns>.NET double.</returns>
              public static double MyToDouble(this MWArray toDouble)
              {
                  var matNumericArray = (MWNumericArray)toDouble;
                  return matNumericArray.ToScalarDouble();
              }
              /// <summary>
              /// Converts an array that contains multiple Matlab return parameters back into a list of .NET doubles.
              /// </summary>
              /// <param name="toList">MWArray variable, returned from Matlab code.</param>
              /// <returns>List of .NET doubles.</returns>
              public static List<double> MyToDoubleList(this MWArray toList)
              {
                  var matNumericArray = toList;
                  var netArray = (MWNumericArray)matNumericArray.ToArray();
      
                  var result = new List<double>();
                  // Console.Write("{0}", netArray[1]);
                  for (int i = 1; i <= netArray.NumberOfElements; i++) // Matlab arrays are 1-based, thus the odd indexing.
                  {
                      result.Add(netArray[i].ToScalarDouble());
                  }
                  return result;
              }
              /// <summary>
              /// Converts an array that contains multiple Matlab return parameters back into a list of .NET ints.
              /// </summary>
              /// <param name="toList">MWArray variable, returned from Matlab code.</param>
              /// <returns>List of .NET ints.</returns>
              public static List<int> MyToMWNumericArray(this MWArray toList)
              {
                  var matNumericArray = toList;
                  var netArray = (MWNumericArray)matNumericArray.ToArray();
      
                  var result = new List<int>();
                  // Console.Write("{0}", netArray[1]);
                  for (int i = 1; i <= netArray.NumberOfElements; i++) // Matlab arrays are 1-based, thus the odd indexing.
                  {
                      result.Add(netArray[i].ToScalarInteger());
                  }
                  return result;
              }
              /// <summary>
              /// Converts an int[] array into a Matlab parameters.
              /// </summary>
              /// <param name="intArray">MWArray variable, returned from Matlab code.</param>
              /// <returns>List of .NET ints.</returns>
              public static MWNumericArray MyToMWNumericArray(this int[] intArray)
              {
                  return new MWNumericArray(1, intArray.Length, intArray); // rows, columns int[] realData
              }
              /// <summary>
              /// Converts an double[] array into parameter for a Matlab call.
              /// </summary>
              /// <param name="arrayOfDoubles">Array of doubles.</param>
              /// <returns>MWNumericArray suitable for passing into a Matlab call.</returns>
              public static MWNumericArray MyToMWNumericArray(this double[] arrayOfDoubles)
              {
                  return new MWNumericArray(1, arrayOfDoubles.Length, arrayOfDoubles); // rows, columns int[] realData
              }
              /// <summary>
              /// Converts an List of doubles into a parameter for a Matlab call.
              /// </summary>
              /// <param name="listOfDoubles">List of doubles.</param>
              /// <returns>MWNumericArray suitable for passing into a Matlab call.</returns>
              public static MWNumericArray MyToMWNumericArray(this List<double> listOfDoubles)
              {
                  return new MWNumericArray(1, listOfDoubles.Count, listOfDoubles.ToArray()); // rows, columns int[] realData
              }
              /// <summary>
              /// Converts a list of some type into an array of the same type.
              /// </summary>
              /// <param name="toArray">List of some type.</param>
              /// <returns>Array of some type.</returns>
              public static T[] MyToArray<T>(this List<T> toArray)
              {
                  var copy = new T[toArray.Count];
                  for (int i = 0; i < toArray.Count; i++) {
                      copy[i] = toArray[i];
                  }
                  return copy;
              }
              static private readonly MatlabGraph.Graph MatlabInstance = new MatlabGraph.Graph();
              /// <summary>
              /// Plot a 2D graph.
              /// </summary>
              /// <param name="x">Array of doubles, x axis.</param>
              /// <param name="y">Array of doubles, y axis.</param>
              /// <param name="title">Title of plot.</param>
              /// <param name="xaxis">X axis label.</param>
              /// <param name="yaxis">Y axis label.</param>
              static public void MyGraph2D(List<double> x, List<double> y, string title = "title", string xaxis = "xaxis", string yaxis = "yaxis")
              {
                  MatlabInstance.Graph2D(x.MyToMWNumericArray(), y.MyToMWNumericArray(), title, xaxis, yaxis);
              }
              /// <summary>
              /// Plot a 2D graph.
              /// </summary>
              /// <param name="x">Array of doubles, x axis.</param>
              /// <param name="y">Array of doubles, y axis.</param>
              /// <param name="title">Title of plot.</param>
              /// <param name="xaxis">X axis label.</param>
              /// <param name="yaxis">Y axis label.</param>
              static public void MyGraph2D(double[] x, double[] y, string title = "title", string xaxis = "xaxis", string yaxis = "yaxis")
              {
                  MatlabInstance.Graph2D(x.MyToMWNumericArray(), y.MyToMWNumericArray(), title, xaxis, yaxis);
              }
              /// <summary>
              /// Unit test for this class. Displays a graph using Matlab.
              /// </summary>
              static public void Unit()
              {
                  {
                      var x = new double[100];
                      var y = new double[100];
                      for (int i = 0; i < 100; i++) {
                          x[i] = i;
                          y[i] = Math.Sin(i);
                      }
                      MyGraph2D(x, y);                
                  }
      
                  {
                      var x = new double[100];
                      var y = new double[100];
                      for (int i = 0; i < 100; i++) {
                          x[i] = i;
                          y[i] = 2 ^ i;
                      }
                      MyGraph2D(x, y);
                  }
              }
          }
      }
      
  2. 接下来,我们将 .m 文件导出到 .NET 程序集中。我使用了 Matlab 2010a(这也适用于 2010b)。使用 Matlab,32 位版本(Matlab 启动时在初始屏幕中显示 32 位或 64 位)。

    1. 下面的 Matlab 代码显示了一个图形。将其另存为 Graph2D.m.

      function Graph2D (x,y, titleTop, labelX, labelY)
      
      % Create figure
      myNewFigure = figure;
      
      plot(x,y)
      
      title({titleTop});
      xlabel({labelX});
      ylabel({labelY});
      
    2. 通过在控制台中键入以下内容在 Matlab 中进行测试(确保 Current Folder 在 Matlab 工具栏中更改为与 相同的目录Graph2D.m):

      x = 0:.2:20;
      y = sin(x)./sqrt(x+1);
      Graph2D(x,y,'myTitle', 'my x-axis', 'my y-axis')
      
    3. 在Matlab部署工具中,添加一个类 Graph,添加文件 Graph2D.m,然后打包进去 MatlabGraph.dll (在settings里面把组件名改成 MatlabGraph ,这个决定了生成的.dll的名字)。

    4. 在您的 .NET 项目中,添加对 MatlabGraph.dll (我们刚刚编译的 .NET .dll Graph2D.m)的引用。这将是 如果它与 Matlab32-bit 的版本一起编译 。32-bit

    5. 在您的 .NET 项目中,添加对 32 位版本的MWArray.dll. 您可以通过搜索 Matlab 安装目录来找到它。
    6. 再次,确保一切都是一致 32-bit的,或者一致 64-bit的。
      1. 如果选择 32-bit,您的 .NET 应用程序必须编译为 x32,您必须使用 32-bit Matlab 的版本(它将显示 32-bit 在启动屏幕中)导出 .NET .dll,并且必须将 32-bit 版本导入MWArray.dll 到您的 .NET 项目中。
      2. 如果您选择 64-bit,将您的 .NET 应用程序编译成 All CPU,您必须使用 64-bit Matlab 的版本(它将显示 64-bit 在启动屏幕中)导出 .NET .dll,并且必须将 .NET 的 64-bit 版本 导入MWArray.dll 到您的 .NET 项目中。
    7. 运行 .NET 应用程序,它将通过调用 Matlab 运行时显示上图。
  3. 如果要将其部署到新 PC,则必须在这台 PC 上安装 .NET 运行时(这些是免费的)。
  4. 这样做的好处是您可以使用 Matlab 的所有功能在 Matlab 中根据自己的喜好自定义图形。您可以制作 3-D 图:在 Matlab 中使用 创建一个新图形,使用 File..New..Figure自定义它 Insert,然后使用 生成 .m 代码 File..Generate M file。新生成的 .m 文件中的行的作用相当明显,您可以将它们复制到原始 Graph2D.m 文件中,然后重新 生成 .m 文件MatlabGraph.dll。例如,为图形添加标题会title({'My new title});在自动生成的 .m 文件中添加一行。
  5. 如果有兴趣,我可以提供 .NET 中的完整 C# 示例项目。
于 2011-10-08T14:51:31.657 回答