Pages

Sunday, October 20, 2013

Generating complex math visualizations in SVG using C# and ILNumerics

Re Posting  this article from hanselman blog. he is my Google+  friend

I was recently turned on to the ILNumerics library. It's a high performance math library for .NET developers that my math skills can barely comprehend. It has a clean and elegant syntax, but more importantly, it's visualization graphics engine is thoughtful, flexible, and well-factored.
Having worked on a lot of websites, including ones that do a lot of backend image generationresizing and analysis (like check imaging almost 10 years ago) I was impressed at how easily I was able to get an equation onto a basic website with ILNumerics and SVG.
Of course, it's not just a web library, in fact, most of the samples are WPF and WinForms, so it's an engine that you can use anywhere. Regardless, as a web person, I wanted to see how quickly I could get something into my browser.
The ILNumerics website has a cool sample 3D graph on their home page that was generics with this code:
var scene = new ILScene {
  new ILPlotCube(twoDMode: false) {
    new ILSurface(ILSpecialData.sincf(40, 60, 2.5f)) {
    }
  }
};
scene.First<ILPlotCube>().Rotation = Matrix4.Rotation(
      new Vector3(1f,0.23f,1), 0.7f);
scene;
However, you'll notice in their sample they just end with the variable "scene." That's a no-op there, but it's their coder way of saying "at this point, the scene variable holds a representation of our plot. Do with it as you will."
NOTE: Do check out their home page...the little sample there is deeper than you'd think. The dropdown shows they can generate PNGs, JPGs, JPG HD, SVG, but also "EXE." Hm, download a random EXE from the internet? Yes please! ;) Take a risk and you'll get a nice self-contained EXE visualizer that not only renders the graph but lets you rotate it. You can download the ILView 3D viewer and play around, it's harmless - all the code for ILView is on GitHub! The best part is that it has a built in REPL so you can type your C# right there and see the results! It even runs on Linux and uses Mono. ;)
ILNumeric
Back to my goal. I want to use the library on a basic website and dynamically generate an SVG of this plot.
Here's the same plot, put inside an ASP.NET HttpHandler (which could also be made routable and used in ASP.NET MVC/Web Forms, etc.)
public void ProcessRequest(HttpContext context)
{
    var scene = new ILScene {
          new ILPlotCube(twoDMode: false) {
            new ILSurface(ILSpecialData.sincf(40, 60, 2.5f)) {
            }
          }
        };
    scene.First<ILPlotCube>().Rotation = Matrix4.Rotation(
        new Vector3(1f, 0.23f, 1), 0.7f);
 
    var driver = new ILSVGDriver(context.Response.OutputStream, 1200, 800, scene, Color.White);
    driver.Render();
}
Here I'm passing context.Response.OutputStream to their ILSVGDriver and saving the result not to a file, but directly out to the browser. I could certainly save it to cloud blob storage or a local file system for caching, reuse or email.
using (FileStream fs = new FileStream(@"test.svg", FileMode.Create)) {
    new ILSVGDriver(fs, scene: whateveryoursceneis).Render();
}
While a SVG is preferable, one could also make a PNG.
var driver = new ILGDIDriver(1280, 800, whateveryoursceneis);
driver.Render();
driver.BackBuffer.Bitmap.Save("whatever", System.Drawing.Imaging.ImageFormat.Png);
It's so much more than a plot visualizer, though. It reminds me a little of D3.js, except more math focused and less live-data binding. It's almost as flexible though, with many kinds of visualizations beyond what you'd expect.
3D graph that looks like a mountainDonut graph
Three 3D graphs in one plotTopographical plot
Infinite TrianglesHalf a sphere intersected by a blue gear
Here's the code to show a green sphere that's composed of triangles, but has the top chopped off, as an example. This is just 10 lines of code, and could be made less.
var scene = new ILScene();
// create a new sphere
var sphere = new ILSphere();
// the sphere is a group containing the Fill (ILTriangles)
// and the Wireframe (ILLines) of the sphere. Both shapes
// share the same vertex positions buffer. Hence, we only
// need to alter one of them:
using (ILScope.Enter()) {
  // take the vertex positions from the Fill.Positions buffer
  ILArray<float> pos = sphere.Fill.Positions.Storage;
  // set all vertices with a Y coordinate larger than 0.3 to 0.3
  pos[1, pos[1, ":"] > 0.3f] = 0.3f;
  // write all values back to the buffer
  sphere.Fill.Positions.Update(pos);
}
// add the "sphere" to the scene
scene.Camera.Add(sphere);
// add another light (for niceness only)
scene.Add(new ILPointLight() {
  Position = new Vector3(-0, 1, -2)
}); 
// move the camera upwards
scene.Camera.Position = new Vector3(0,3,-10);
// display the scene
scene;
And this gives you:
Half a green sphere
It's a really amazing project. ILNumerics is GPL3 and also uses OpenTK for OpenGL bindings, and Mono.CSharp for C# compiling and evaluation. ILView is under the MIT/X11 license.
You can get it via NuGet with just "Install-Package ILNumerics." Check it out and tell your friends, scientists, and friends of Edward Tufte.

No comments:

Post a Comment