12,077,195 members (48,227 online)
Add your own
alternative version

43.8K views
418 downloads
61 bookmarked
Posted

Plotting User-Defined R2 in R Functions Using C#

, 9 Apr 2013 GPL3
 Rate this:
Please Sign up or sign in to vote.
Plotting user defined R2 in R functions using C#

Introduction

This article describes very briefly (and on a basic level) how to plot user interactive 3D R2 in R surfaces using C# ASP.NET. The example enables the user to interact with the drawing in 5 aspects as below:

• function expression z = f(x,y)
• domain
• integration step
• rotation about x, y and z axis
• model (wireframe or fill)

Background

• A point in R3 is a set of 3 float values (x,y,z) which defines a position.
• R2 in R functions are expresions in the form z = f(x,y) where x and y are a subset of the function domain.
• The R2 in R domain is the R2 or better, the xy plane.

The cartesian coordinates

The objective is to get a set of z coordinates applying a generic function z=f(x,y) to a discrete domain, or better a matrix of defined x and y points as the image grid above.

How to Perform This

At first we need to define the domain. Let's choose [-1.7,1.3] for x and [-2.1,2.5] for y what means x will run from -1.7 to 1.3 and y will run from -2.1 to 2.5.

How to Run the Points

As we are working with R coordinates we have infinite points between 2 coordinates, so for this we need a step variable, which means the integration we will use to get the grid points.

Let's define our step as 0.1, and now we can show some code:

```double x0=-1.7, x1=1.3, y0=-2.1, y1=2.5;

double step = 0.1;
double x=x0;
while(x<=x1)
{
//...
y=y0;

while(y<=y1)
{
//...
y+=step;
}
x+=step;
}```

Now with above definitions we can handle a generation of z coordinates from running the xy discrete subdomain by using the generic function z = f(x,y)

```double x0=-1.7, x1=1.3, y0=-2.1, y1=2.5;

double step = 0.1;
double x=x0;
double z;

while(x<=x1)
{
//...
y=y0;

while(y<=y1)
{
//...
y+=step;
z = function(x,y); // at this point we have x,y and z coordinates
// all we need now is to keep this information in a data structure
// to plot the whole data in a next step
}
x+=step;
}```

Now the Tricky Part

We could use a `MathExpressionParser` with the expression string, but here I made it more simple with the help of a template with a tag. The process is easy: read the template file, replace the tag, and write the ASPX file which shows the image.

```string contents = ReadFile(Server.MapPath("./dynafuncapp.txt"));
contents = contents.Replace("@EXPRESSION", functionStr);
SaveFile(Server.MapPath("./dynacontent.aspx"), contents);
// note you must have write access to the folder ***```

Putting Everything Together

The Template File

```<%@ Page Language="c#" Debug="true" Explicit="True" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDb" %>
<%@ Import Namespace="System.Data.OleDb" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Web.Mail" %>

<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="Microsoft.CSharp" %>
<%@ Import Namespace="System.Drawing.Imaging" %>
<%@ Import Namespace="System.CodeDom.Compiler" %>
<%@ Import Namespace="System.Reflection" %>
<%@ Import Namespace="System.Collections" %>
<script language="C#" runat="server">
// Rotation aboout X axis
void RotX(ref double cy, ref double cz, double angle)
{
double y = cy * System.Math.Cos(angle) - cz * System.Math.Sin(angle);
double z = cy * System.Math.Sin(angle) + cz * System.Math.Cos(angle);
cy = y;
cz = z;
}
// Rotation aboout Y axis
void RotY(ref double cx, ref double cz, double angle)
{
double x = cx * System.Math.Cos(angle) - cz * System.Math.Sin(angle);
double z = cx * System.Math.Sin(angle) + cz * System.Math.Cos(angle);
cx = x;
cz = z;
}
// Rotation aboout Z axis
void RotZ(ref double cy, ref double cx, double angle)
{
double x = cx * System.Math.Cos(angle) - cy * System.Math.Sin(angle);
double y = cx * System.Math.Sin(angle) + cy * System.Math.Cos(angle);
cx = x;
cy = y;
}
// The z=f(x,y) function with tricky tag to be replaced
protected double stFunction(double x, double y)
{
return (@EXPRESSION);
}
// Save file helper
public void SaveFile(string filepath, string outputstr)
{
System.IO.FileStream file = new System.IO.FileStream(filepath,
System.IO.FileMode.Create, System.IO.FileAccess.Write);
System.IO.StreamWriter writer = new System.IO.StreamWriter(file);
writer.Write(outputstr);
writer.Flush();
writer.Close();
file.Close();
}
private void Page_Load(object sender, System.EventArgs e)
{
double xleft = (double) Session["xleft"];
double xright = (double) Session["xright"];
double yleft = (double) Session["yleft"];
double yright = (double) Session["yright"];
double step = (double) Session["step"];
if (Math.Abs(step) < 1.0E-5)
{
Response.Write("Integration is 0");
return;
}
int maxcount = 1000000;
int sizeX = (int)Math.Ceiling(((xright - xleft) / step)) + 1;
int sizeY = (int)Math.Ceiling(((yright - yleft) / step)) + 1;
int size = sizeX * sizeY;
if (size > maxcount)
{
Response.Write("Overflow");
return;
}
double[,] surface = new double[sizeX, sizeY];
double x = xleft;
double y;
int indexX = 0;
int indexY = 0;
while (x <= xright)
{
y = yleft;
indexY = 0;
while (y <= yright)
{
surface[indexX, indexY] = stFunction(x, y);//mp.eval(x, y);
indexY++;
y += step;
}
x += step;
indexX++;
}
Session["surface"] = surface;

Bitmap newBitmap = new Bitmap(200, 200, PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(newBitmap);
Color clrBackground = Color.Black;
g.FillRectangle(new SolidBrush(clrBackground),
new Rectangle(0, 0, 200, 200));
Rectangle rect = new Rectangle(0, 0, 200, 200);
double xmin = (double)Session["xleft"];
double ymin = (double)Session["yleft"];
double xmax = (double)Session["xright"];
double ymax = (double)Session["yright"];
double eyex = (double)Session["eyex"];
double eyey = (double)Session["eyey"];
double eyez = (double)Session["eyez"];
int idx = 0;
x = xmin;
while ((x < xmax) && (idx < sizeX - 1))
{
y = ymin;
int idy = 0;
while ((y < ymax) && (idy < sizeY - 2) && (idx < sizeX - 1))
{
double z1 = surface[idx, idy];
double z2 = surface[idx + 1, idy];
double z3 = surface[idx + 1, idy + 1];
double z4 = surface[idx, idy + 1];
double xx1 = x, yy1 = y, zz1 = z1;
double xx2 = x + step, yy2 = y, zz2 = z2;
double xx3 = x + step, yy3 = y + step, zz3 = z3;
double xx4 = x, yy4 = y + step, zz4 = z4;
RotX(ref yy1, ref zz1, eyex);
RotY(ref xx1, ref zz1, eyey);
RotZ(ref xx1, ref yy1, eyez);
RotX(ref yy2, ref zz2, eyex);
RotY(ref xx2, ref zz2, eyey);
RotZ(ref xx2, ref yy2, eyez);
RotX(ref yy3, ref zz3, eyex);
RotY(ref xx3, ref zz3, eyey);
RotZ(ref xx3, ref yy3, eyez);
RotX(ref yy4, ref zz4, eyex);
RotY(ref xx4, ref zz4, eyey);
RotZ(ref xx4, ref yy4, eyez);
double p1x = ((xx1 - xmin) / (xmax - xmin)) * (200.0 - 0.0) + 0.0;
double p1y = ((yy1 - ymin) / (ymax - ymin)) * (200.0 - 0.0) + 0.0;
double p2x = ((xx2 - xmin) / (xmax - xmin)) * (200.0 - 0.0) + 0.0;
double p2y = ((yy2 - ymin) / (ymax - ymin)) * (200.0 - 0.0) + 0.0;
double p3x = ((xx3 - xmin) / (xmax - xmin)) * (200.0 - 0.0) + 0.0;
double p3y = ((yy3 - ymin) / (ymax - ymin)) * (200.0 - 0.0) + 0.0;
double p4x = ((xx4 - xmin) / (xmax - xmin)) * (200.0 - 0.0) + 0.0;
double p4y = ((yy4 - ymin) / (ymax - ymin)) * (200.0 - 0.0) + 0.0;
int ip1x = (int)Math.Ceiling(p1x);
int ip1y = (int)Math.Ceiling(p1y);
int iz1 = (int)Math.Abs((255.0 * zz1));
if (iz1 < 0) iz1 = 0;
if (iz1 > 255) iz1 = 255;
int ip2x = (int)Math.Ceiling(p2x);
int ip2y = (int)Math.Ceiling(p2y);
int ip3x = (int)Math.Ceiling(p3x);
int ip3y = (int)Math.Ceiling(p3y);
int ip4x = (int)Math.Ceiling(p4x);
int ip4y = (int)Math.Ceiling(p4y);
int view = (int)Session["view"];
if (view == 1)
{
Pen greenPen = new Pen(Color.FromArgb(0, iz1, 0));
g.DrawLine(greenPen, ip1x, ip1y, ip2x, ip2y);
g.DrawLine(greenPen, ip1x, ip1y, ip4x, ip4y);
g.DrawLine(greenPen, ip2x, ip2y, ip4x, ip4y);
g.DrawLine(greenPen, ip2x, ip2y, ip4x, ip4y);
g.DrawLine(greenPen, ip2x, ip2y, ip3x, ip3y);
g.DrawLine(greenPen, ip3x, ip3y, ip4x, ip4y);
greenPen.Dispose();
}
else
if (view == 2)
{
Point[] points = new Point[3];
points[0].X = ip1x;
points[0].Y = ip1y;
points[1].X = ip2x;
points[1].Y = ip2y;
points[2].X = ip4x;
points[2].Y = ip4y;
Brush greenBrush = new SolidBrush(Color.FromArgb(0,
iz1, 0));
g.FillPolygon(greenBrush, points);
points = new Point[3];
points[0].X = ip2x;
points[0].Y = ip2y;
points[1].X = ip4x;
points[1].Y = ip4y;
points[2].X = ip3x;
points[2].Y = ip3y;
g.FillPolygon(greenBrush, points);
greenBrush.Dispose();
}
idy++;
y += step;
}
x += step;
idx++;
}
// output the image
MemoryStream tempStream = new MemoryStream();
newBitmap.Save(tempStream, ImageFormat.Png);
Response.ClearContent();
Response.ContentType = "image/png";
Response.BinaryWrite(tempStream.ToArray());
Response.Flush();
}

</script>
<html xmlns="<a href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>">```

The Main File

```<%@ Page Language="c#" Debug="true" Explicit="True" %>
<%@ Import Namespace="System.Data" %>

<%@ Import Namespace="System.Data.OleDb" %>
<%@ Import Namespace="System.Data.OleDb" %>
<%@ Import Namespace="System.Drawing" %>
<%@ Import Namespace="System.Web.Mail" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="Microsoft.CSharp" %>
<%@ Import Namespace="System.Drawing.Imaging" %>
<%@ Import Namespace="System.CodeDom.Compiler" %>
<%@ Import Namespace="System.Reflection" %>

<%@ Import Namespace="System.Collections" %>
<script language="C#" runat="server">
// Read file helper
public string ReadFile(string filepath)
{
System.IO.FileStream file = new System.IO.FileStream(filepath,
System.IO.FileMode.Open, System.IO.FileAccess.Read);
System.IO.StreamReader reader = new System.IO.StreamReader(file);
string contents = reader.ReadToEnd();
reader.Close();
file.Close();
return contents;
}
// Save file helper
public void SaveFile(string filepath, string outputstr)
{
System.IO.FileStream file = new System.IO.FileStream(filepath,
System.IO.FileMode.Create, System.IO.FileAccess.Write);
System.IO.StreamWriter writer = new System.IO.StreamWriter(file);
writer.Write(outputstr);
writer.Flush();
writer.Close();
file.Close();
}
private void Page_Load(object sender, System.EventArgs e)
{
outputTxt.Text = "";
String functionStr = function.Text;
functionStr = functionStr.Replace("sin", "Math.Sin");
functionStr = functionStr.Replace("cos", "Math.Cos");
functionStr = functionStr.Replace("cos", "Math.Cos");
functionStr = functionStr.Replace("sqrt", "Math.Sqrt");
functionStr = functionStr.Replace("sinh", "Math.Sinh");
functionStr = functionStr.Replace("acos", "Math.Acos");
functionStr = functionStr.Replace("cosh", "Math.Cosh");
functionStr = functionStr.Replace("abs", "Math.Abs");
functionStr = functionStr.Replace("asin", "Math.Asin");
functionStr = functionStr.Replace("ceiling", "Math.Ceiling");
functionStr = functionStr.Replace("exp", "Math.Exp");
functionStr = functionStr.Replace("floor", "Math.Floor");
functionStr = functionStr.Replace("log", "Math.Log");
functionStr = functionStr.Replace("log10", "Math.Log10");
functionStr = functionStr.Replace("pi", "Math.PI");
functionStr = functionStr.Replace("pow", "Math.Pow");
functionStr = functionStr.Replace("tan", "Math.Tan");
functionStr = functionStr.Replace("tanh", "Math.Tanh");
functionStr = functionStr.Replace("round", "Math.Round");
string contents = ReadFile(Server.MapPath("./dynafuncapp.txt"));
contents = contents.Replace("@EXPRESSION", functionStr);
SaveFile(Server.MapPath("./dynacontent.aspx"), contents);
double xleft = double.Parse(xmin.Text);
double xright = double.Parse(xmax.Text);
double yleft = double.Parse(ymin.Text);
double yright = double.Parse(ymax.Text);
double step = double.Parse(integ.Text);

if (Math.Abs(step) < 1.0E-5)
{
Response.Write("Integration is 0");
return;
}
int maxcount = 1000000;
int sizeX = (int)Math.Ceiling(((xright - xleft) / step)) + 1;
int sizeY = (int)Math.Ceiling(((yright - yleft) / step)) + 1;
int size = sizeX * sizeY;
outputTxt.Text += "Grid size = " + size.ToString() + " points";
if (size > maxcount)
{
Response.Write("Overflow");
return;
}
outputTxt.Text += "<br>[" + sizeX.ToString() + "," +
sizeY.ToString() + "]";
Session["xleft"] = xleft;
Session["yleft"] = yleft;
Session["xright"] = xright;
Session["yright"] = yright;
Session["step"] = step;
if (view1.Checked)
Session["view"] = (int)1;
if (view2.Checked)
Session["view"] = (int)2;
Session["eyex"] = double.Parse(eyex.Text);
Session["eyey"] = double.Parse(eyey.Text);
Session["eyez"] = double.Parse(eyez.Text);
Session["sizex"] = sizeX;
Session["sizey"] = sizeY;
}
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"<a href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</a>">```

Sample of generated function
sin(pow(x,3)-7*x*y-pow(y,4))

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)

About the Author

 Engineer IBM Brazil
Senior Analyst

Founder of TIHunter Vagas de TI

Linkedin Profile

Comments and Discussions

 First Prev Next
 My vote of 5 manoj kumar choubey26-Feb-12 22:44 manoj kumar choubey 26-Feb-12 22:44
 Woa L8N8Hack16-Sep-07 18:30 L8N8Hack 16-Sep-07 18:30
 Neat! Jay Gatsby20-Aug-07 15:56 Jay Gatsby 20-Aug-07 15:56
 Cool [modified] sk8er_boy28723-Jul-07 21:43 sk8er_boy287 23-Jul-07 21:43
 Re: Cool andalmeida24-Jul-07 3:37 andalmeida 24-Jul-07 3:37
 Last Visit: 31-Dec-99 19:00     Last Update: 12-Feb-16 16:05 Refresh 1

General    News    Suggestion    Question    Bug    Answer    Joke    Praise    Rant    Admin

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160212.1 | Last Updated 9 Apr 2013
Article Copyright 2007 by andalmeida
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid