Plotting libraries for .NET

G

Giovanni Dicanio

Hi,

do you know any good and free 2D and 3D plotting libraries for .NET ?

I need them for a project (which is starting as an "experiment", and is no
commercial, at least at this first step, so the need for a free library).

I found this:

http://www.zedgraph.org/

which seems very good for 2D.

Do you know anything for 3D i.e. to plot 3D surfaces from functions of form
z=f(x,y) ?

Thanks in advance,
Giovanni
 
R

rowe_newsgroups

Hi,

do you know any good and free 2D and 3D plotting libraries for .NET ?

I need them for a project (which is starting as an "experiment", and is no
commercial, at least at this first step, so the need for a free library).

I found this:

http://www.zedgraph.org/

which seems very good for 2D.

Do you know anything for 3D i.e. to plot 3D surfaces from functions of form
z=f(x,y) ?

Thanks in advance,
Giovanni

You might check codeproject.com, but I doubt they can be freely
distributed.

Thanks,

Seth Rowe
 
R

rowe_newsgroups

You might check codeproject.com, but I doubt they can be freely
distributed.

Thanks,

Seth Rowe

I wanted to mention, but completely forgot, that 3D graphs in .Net
might be rather slow. One option is to do the graphing through the
DirectX api, which would give much better performance and comes with
windows so you don't have to worry about licensing and distributing a
third party library. But on the other hand, the learning curve will
most likely be much, much steeper.

Thanks,

Seth Rowe [MVP]
 
G

Gunga Din

Giovanni Dicanio said:
Hi,

do you know any good and free 2D and 3D plotting libraries for .NET ?

I need them for a project (which is starting as an "experiment", and is no
commercial, at least at this first step, so the need for a free library).

I found this:

http://www.zedgraph.org/

which seems very good for 2D.

Do you know anything for 3D i.e. to plot 3D surfaces from functions of
form z=f(x,y) ?

Thanks in advance,
Giovanni

You can see http://www.tyburn-consultancy.co.uk is of any help...
 
B

BobF

Giovanni Dicanio said:
Hi,

do you know any good and free 2D and 3D plotting libraries for .NET ?

I need them for a project (which is starting as an "experiment", and is no
commercial, at least at this first step, so the need for a free library).

I found this:

http://www.zedgraph.org/

which seems very good for 2D.

Do you know anything for 3D i.e. to plot 3D surfaces from functions of
form z=f(x,y) ?

Thanks in advance,
Giovanni

Hey, G, have you looked at Scilab? scilab.org

It's not a .Net library, but it may be something you can use.
 
G

Giovanni Dicanio

I wanted to mention, but completely forgot, that 3D graphs in .Net
might be rather slow. One option is to do the graphing through the
DirectX api, which would give much better performance and comes with
windows so you don't have to worry about licensing and distributing a
third party library. But on the other hand, the learning curve will
most likely be much, much steeper.

Thanks Seth.

I know about DirectX, I also coded in C++ using it.

I was thinking about an already-built .Net component.

Thanks,
Giovanni
 
G

Giovanni Dicanio

Hey, G, have you looked at Scilab? scilab.org

It's not a .Net library, but it may be something you can use.

Thanks Bob!

I will look at it!

If Scilab is C or C++ code, I could use C++/CLI, and expose the component to
the .Net world.

Thanks,
G
 
J

jan zegan

Hi,

do you know any good and free 2D and 3D plotting libraries for .NET ?

I need them for a project (which is starting as an "experiment", and is no
commercial, at least at this first step, so the need for a free library).

I found this:

http://www.zedgraph.org/

which seems very good for 2D.

Do you know anything for 3D i.e. to plot 3D surfaces from functions of form
z=f(x,y) ?

Thanks in advance,
Giovanni

You can also check out <a href="http://www.nplot.com/">NPLOT</a> for
2D.
 
J

jan zegan

Hi,

do you know any good and free 2D and 3D plotting libraries for .NET ?

I need them for a project (which is starting as an "experiment", and is no
commercial, at least at this first step, so the need for a free library).

I found this:

http://www.zedgraph.org/

which seems very good for 2D.

Do you know anything for 3D i.e. to plot 3D surfaces from functions of form
z=f(x,y) ?

Thanks in advance,
Giovanni

You can also check out http://www.nplot.com for 2D.
 
R

rowe_newsgroups

Thanks Seth.

I know about DirectX, I also coded in C++ using it.

I was thinking about an already-built .Net component.

Thanks,
Giovanni

Ahh, you left off your C++ MVP tag in your first post, now seeing that
I doubt the learning curve of Dx will matter!

:)

Thanks,

Seth Rowe [MVP]
 
B

BobF

Giovanni Dicanio said:
Thanks!

Giovanni

While you're at it, check out graphviz at graphviz.org. This is the package
doxygen uses. Not 3D, but great for diagramming.
 
M

Michel Walsh

If it is limited to functions of the kind z=f(x,y), then all you need from
DirectX is to draw a list of triangles, which is quite basic, and I don't
think any package can simplify it. Sure, that would not be the case if you
want to draw general curves, not known in advance, given even a simple
sphere has its problem (where given a single x, and a single y, you may end
up with more than on z), or even worse such a Mobius strip (not orientable,
so standard culling for hidden surface may have to be revisited); but for
z=f(x, y), if the xoy domain is a rectangle, that should be almost a
"DirectX-101 home-work". You want an old VB6 example doing it? :)



Vanderghast, Access MVP
 
G

Giovanni Dicanio

but for z=f(x, y), if the xoy domain is a rectangle, that should be almost
a "DirectX-101 home-work". You want an old VB6 example doing it? :)

Yes, I know the problem of spheres.
But I would be happy with plotting of z=f(x,y) on a rectangle XY domain, and
with some zoom, pan and rotation.

I would be happy also to read your VB6 code (note that, even if my strongest
programming language is C++, I do like VB[.NET]).

I could try to develop this plotting software, too. As you also say, this
would not be particularly difficult, at least for the special case I'm
interested in. But this is not the focus of my project; so I would prefer
reusing an already developed and tested component, and focus on other
aspects.

I'm also aware that CodeProject has a very good COM 3D plotter (written in
C++ with ATL), so I may also use it and use COM Interop from the .NET world.

Thanks,
Giovanni
 
M

Michel Walsh

I got one in C# after all... If you know a place where I can post binaries,
I would gladly post the "debug" directory of the project.

You will need the Dx SDK and the references Microsoft.DirectX (1.0.290.0)
and Direct3D (1.0.2902.0).

I tried to keep the stuff to a minimum. X axis is coral, Z axis is blue.
Culling is set to none but the triangles are ready with their normal for the
Right Hand (but you will need 'two passes' if you use some culling, in order
to display the 'back' of the 'sheet').

Vanderghast, Access MVP
----------------------------

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX; // <------ add
using Microsoft.DirectX.Direct3D; // <------ add




namespace D3Surface
{
public partial class Form1 : Form
{
private Device device = null; // Direct3D 'device'

private int nframe = 0; // counting the number of frames
private Boolean re_init = true;

private IndexBuffer ib = null; // will hold the index
// allowing to built the triangles
// the 'index buffer'
private short[] indices = null; // working var to define ib

private VertexBuffer vb = null; // will hold the vertexes
// of the triangles, the 'vertex buffer'
private CustomVertex.PositionNormalColored[] vert = null;
// working var to define vb

public Form1()
{
InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.Opaque, true);
}

private void Form1_Paint(object sender, PaintEventArgs e)
{
InitializeGraphics(); // not a D3X definition, but ours.


device.Clear(ClearFlags.Target | ClearFlags.ZBuffer,
System.Drawing.Color.FromArgb(255, 221, 204, 102).ToArgb(),
1.0f, 0);

#region device rendering
device.BeginScene();

{
SetupCamera(); // not a D3X definition, but ours.
PlayScenario(); // not a D3X definition, but ours.
}

device.EndScene();
device.Present();
#endregion

this.Invalidate(); // dirty-loop driving the rendering


}

/// <summary> some curve y=fct(x, z)
/// defined over the normalized interval (-1, -1), (+1, +1)
/// </summary>
/// <param name="x"></param>
/// <param name="z"></param>
/// <returns></returns>
private float MyCurve(float x, float z)
{
return 0.15f*x + 0.5f*(float)Math.Sin(Math.PI * 3* x) +
..2f*(float)Math.Sin(Math.PI * 2.0f * z);
}

/// <summary> Set up a moving camera
/// </summary>
private void SetupCamera()
{
// an an engineer, I use Right Hand rules
device.Transform.Projection = Matrix.PerspectiveFovRH(
(float)Math.PI / 4, this.Width / (float)this.Height,
1.0f, 10.0f);

// move the camera between each rendered frame
// in a circle of radius 3, at a constant height Y=-1.
float X = 3.0f * (float)Math.Cos(nframe / 100.0f);
float Z = 3.0f * (float)Math.Sin(nframe / 100.0f);
device.Transform.View = Matrix.LookAtRH(
new Vector3(X, -1.0f, Z), // camera position
new Vector3(0, 0, 0), // where we look at
new Vector3(0, 1.0f, 0)); // head up direction

++nframe; // update our frame count.
}

/// <summary> Play the scenario, always the same,
/// one object, a predefined simple curve z=f(x, y)
/// over the (normalized) square domain (-1, -1) to (+1, +1).
/// </summary>
private void PlayScenario()
{
DrawXZpositive(System.Drawing.Color.Coral,
System.Drawing.Color.DarkBlue);
device.VertexFormat = CustomVertex.PositionNormalColored.Format;

#region ligths
device.RenderState.Lighting = true;
device.RenderState.Ambient = System.Drawing.Color.FromArgb(255,
127, 127, 127);
device.RenderState.AmbientMaterialSource = ColorSource.Color1;
// since we have no material, use the color of the
vertex

device.RenderState.DiffuseMaterialSource = ColorSource.Color1;
device.Lights[0].Type = LightType.Directional;
device.Lights[0].DiffuseColor = new
ColorValue(-1.0f, -1.0f, -1.0f);
device.Lights[0].Direction = new Vector3(-1.0f, -2.0f, 0.5f);
device.Lights[0].Enabled = true;

#endregion
device.RenderState.CullMode = Cull.None;
device.SetStreamSource(0, vb, 0);
device.Indices = ib;

device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0,
441, 0, 800);
// The magical constants in this call come from this:
// we define a grid of 20 * 20 rectangles (from (-1,-1) to
(+1,+1))
// which makes 21 points by 21 points = 441 points, or
vertices.
// Each rectangle, or quad, is rendered with two triangles,
// 20 * 20 * 2 = 800 triangles.
// The method allows us to 'skip' some node, we won't, we start
// from the beginning of our data for each drawing.
}

/// <summary> Set the device, if required, and
/// pre-compute the data, before starting any rendering.
/// </summary>
private void InitializeGraphics()
{
if (null == device)
{
PresentParameters pp = new PresentParameters();
pp.Windowed = true;
pp.SwapEffect = SwapEffect.Discard;

pp.AutoDepthStencilFormat = DepthFormat.D16;
pp.EnableAutoDepthStencil = true;

device = new Device(0, // first adapter
DeviceType.Hardware,
this, // this window
CreateFlags.SoftwareVertexProcessing,
pp);

}

if (re_init)
{

re_init = false;
// technically, we should use a mesh, but to avoid
// to have to define texture, we just use a
// vertex buffer and an index buffer.
#region compute the (x, y, z) values
// The vertex buffer contains the ... vertexes... of
// each triangle to be rendered. A vertex is defined
// by a (x, y, z) value, a color, and a NORMAL to
// the surface of the ... triangle. But since a given vertex
// may be part of many triangles, ... more about it later

// we make a grid (x, z) of 21 by 21 points.
float[] x = new float[21];
float[] z = new float[21];

for (int i = 0; i < 21; i++)
{
x = (float)(-1 + i / 10m);
z = x;
}

vert = new CustomVertex.PositionNormalColored[441];
// a grid of 21 x values,by 21 z values = 441 points

Boolean raiseConcern = false;
int k = 0;
for (int i = 0; i < 21; i++)
{
for (int j = 0; j < 21; j++)
{
float y = MyCurve(x, z[j]);
if (Math.Abs(y) >= 3) raiseConcern = true;
vert[k++] = new CustomVertex.PositionNormalColored(
new Vector3(x, y, z[j]),
new Vector3(0, 1, 0), // will be overwritten
Color.DarkOliveGreen.ToArgb());

}
}

if (raiseConcern)
System.Windows.Forms.MessageBox.Show("The curve may
appear out limit, or nothing could be viewable...");
// hint: have I forgot to normalize my curve definition?
// Remember the camera runs on a circle of
radius 3,
// centered on (0, -1, 0), always
looking
// at the origin.

#endregion
#region fill the index buffer
// Each of the quad, in the grid we just have defined,
// can be split into 2 triangles.
// The index buffer is a collection of multiple set of
// 3 integers: each set of 3 integers define the indexes
// in our vertexes array
// to be used in order to define one triangle.
indices = new short[2400]; // 20*20 quads * 2 = 800
triangles
// 800 triangle * 3 vertex per triangle = 2400

k = 0;
for (short strip = 0; strip < 20; strip++)
{
short baseStrip = (short)(strip * 21);
short topStrip = (short)(baseStrip + 21);
for (short j = 0; j < 20; j++)
{
// 2 triangles per quads. The first one:
indices[k++] = (short)(baseStrip+j);
indices[k++] = (short)(topStrip + j);
indices[k++] = (short)(baseStrip + j + 1);
// the second one:
indices[k++] = (short)(baseStrip + j + 1);
indices[k++] = (short)(topStrip + j);
indices[k++] = (short)(topStrip + j + 1);
}
}

ib = new IndexBuffer(typeof(short),
indices.Length,
device,
Usage.WriteOnly,
Pool.Default);

ib.Created += new EventHandler(this.OnIndexBufferCreated);
OnIndexBufferCreated(ib, null);


#endregion
Vector3[] wn = new Vector3[800]; // the weighted normal of
800 triangles
#region compute the normal to each triangle

// Now that we can 'draw' each triangle, time to compute
// the normal of each triangle, the perpendicular to the
// triangle, in space.
// Since there is two possible directions,
// we choose one, I use the righ hand, RH, rule.
// The indexex were defined with that in mind, so
// all triangles are RH 'ready'.
// Math tell us that the normal of a triangle can be
// computed using a Vector3 cross product.
// url: http://mathworld.wolfram.com/CrossProduct.html

// the following expression compute a vector in the normal
// direction, but with an intensity equal to twice
// the area of the triangle

k = 0;
for (int i = 0; i < 2400; i += 3)
{
Vector3 a = vert[indices].Position;
Vector3 b = vert[indices[i + 1]].Position;
Vector3 c = vert[indices[i + 2]].Position;

wn[k++] = Vector3.Cross(b - a, c - a);
}

#endregion
#region move the normal to the vertexes
// That normal should be given to each vertex defining
// a triangle. But to add 'smootness' all triangles
// sharing the same (x, y, z) will also have to share
// the same vertex. So, for all the possible normal
// to be assigned to a vertex, we will simply average
// them, in proportion of the area of the triangle
// that produced them.

// we will first add the weighted normal from each triangle
// the vertex belong to
Vector3[] cumul = new Vector3[441]; // 441 vertexes

k = 0;
for (int i = 0; i < 2400; i += 3)
{
cumul[indices] += wn[k];
cumul[indices[i + 1]] += wn[k];
cumul[indices[i + 2]] += wn[k];
k++;
}

// and next, we will normalize each
// normal (make its module, intensity, =1)

for (int i = 0; i < 441; i++)
{
if (cumul.Length() != 0)
{
Vector3 nn = Vector3.Normalize(cumul);
vert.Nx = nn.X;
vert.Ny = nn.Y;
vert.Nz = nn.Z;
}
else
{
System.Diagnostics.Trace.WriteLine(String.Format("Vertex
{0} has no normal", i));
}

}
#endregion
#region fill the vertex buffer
vb = new
VertexBuffer(typeof(CustomVertex.PositionNormalColored),
441, // 441 vertexes
device,
Usage.Dynamic | Usage.WriteOnly,
CustomVertex.PositionNormalColored.Format,
Pool.Default);

vb.Created += new EventHandler(this.OnVertexBufferCreate);
OnVertexBufferCreate(vb, null);

#endregion
}

}

private void DrawXZpositive(System.Drawing.Color colorX,
System.Drawing.Color colorZ)
{
device.RenderState.Lighting = false;
CustomVertex.PositionColored[] TwoPoints = new
CustomVertex.PositionColored[2];
device.VertexFormat = CustomVertex.PositionColored.Format;
device.Transform.World = Matrix.Identity;
TwoPoints[0] = new CustomVertex.PositionColored(new Vector3(0,
0, 0), colorX.ToArgb());
TwoPoints[1] = new CustomVertex.PositionColored(new Vector3(2,
0, 0), colorX.ToArgb());
device.DrawUserPrimitives(PrimitiveType.LineList, 1, TwoPoints);
TwoPoints[0] = new CustomVertex.PositionColored(new Vector3(0,
0, 0), colorZ.ToArgb());
TwoPoints[1] = new CustomVertex.PositionColored(new Vector3(0,
0, 2), colorZ.ToArgb());
device.DrawUserPrimitives(PrimitiveType.LineList, 1, TwoPoints);
device.VertexFormat = CustomVertex.PositionNormalColored.Format;
device.SetStreamSource(0, vb, 0);
device.RenderState.Lighting = true;
}
/// <summary> To handle resizing of our vertex buffer and other
cases...
/// </summary>
/// <param name="sender">the vertex buffer</param>
/// <param name="e">null</param>
private void OnVertexBufferCreate(object sender, EventArgs e)
{
VertexBuffer buffer = (VertexBuffer)sender;
buffer.SetData(vert, 0, LockFlags.None);
}
/// <summary> To handle cases where the index buffer is
re-created...
/// </summary>
/// <param name="sender">the index buffer</param>
/// <param name="e">null</param>
private void OnIndexBufferCreated(object sender, EventArgs e)
{
IndexBuffer buffer = (IndexBuffer)sender;
buffer.SetData(indices, 0, LockFlags.None);
}

}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top