Click here to Skip to main content
14,774,409 members
Articles » Multimedia » General Graphics » Graphics
Article
Posted 23 Jul 2007

Stats

61.5K views
574 downloads
65 bookmarked

Plotting User-Defined R2 in R Functions Using C#

Rate me:
Please Sign up or sign in to vote.
4.88/5 (34 votes)
15 Jul 2016GPL3
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)

Screenshot - main.png

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.

X,Y,Z Axis and a subdomain in R2
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>">
<head><title>Dynafunc</title>
</head>
<body style="padding-right: 0px; padding-left: 0px; padding-bottom:
0px; margin: 0px;    padding-top: 0px; text-align: center;">
    <form id="form1" runat="server">

    </form>
</body>
</html>

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>">

<html xmlns="<a href="http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>">
<head id="Head1" runat="server">
    <title>Dynafunc</title>
</head>
<body style="padding-right: 0px; padding-left: 0px; padding-bottom: 0px;
margin: 0px;
    padding-top: 0px; text-align: center;">
    <form id="form1" runat="server">

        <!--#include file="~/template.aspx"-->
        <asp:Panel ID="PlotPanel" runat="server" Font-Names="Verdana"
            Font-Size="12px" Height="285px"
            Width="376px" ForeColor="DarkSlateGray" ScrollBars="Vertical"
            BorderColor="Gray"
            BorderStyle="Solid" BorderWidth="1px">
            <table border="0" cellpadding="0" cellspacing="0" width="100%"
             id="TABLE1">
                <tr style="background-color: Silver">
                    <td style="height: 16px" colspan="3">
                        <strong>R2 in R dynamically generated
                                function</strong></td>

                    <td rowspan="1" style="width: 30%; height: 16px"
                        valign="top">
                        <strong></strong>
                    </td>
                </tr>
                <tr>
                    <td style="width: 20%; height: 18px;">

                        &nbsp;</td>
                    <td style="width: 1px; height: 18px;">
                    </td>
                    <td style="width: 20%; height: 18px;">
                        &nbsp;</td>

                    <td rowspan="1" style="width: 30%; height: 18px;"
                        valign="top">
                        &nbsp;</td>
                </tr>
                <tr>
                    <td style="height: 1px; text-align: center;" colspan="3">
                        &nbsp;
                        <asp:Image ID="imageFunction" runat="server"
                         ImageUrl="./dynacontent.aspx" /></td>

                    <td rowspan="8" style="width: 10%; height: 1px;"
                        valign="top">
                    </td>
                </tr>
                <tr>
                    <td style="width: 20%; height: 1px;">
                        Function</td>

                    <td style="width: 1px; height: 26px;">
                    </td>
                    <td style="width: 100px; height: 26px;" align="left">
                        <asp:TextBox ID="function" runat="server"
                         Width="300px" Height="16px"
                         Font-Names="Verdana"
                         Font-Size="12px" ForeColor="DarkGreen">
                     pow(x,3)-7*x*y-pow(y,4)</asp:TextBox></td>
                </tr>

                <tr>
                    <td style="width: 20%; height: 1px;">
                        Domain</td>
                    <td style="width: 1px; height: 1px;">
                    </td>
                    <td style="width: 20%;" align="left">

                        <asp:TextBox ID="xmin" runat="server" Width="32px"
                            Font-Names="Verdana" Font-Size="12px"
                            ForeColor="DarkGreen">-2</asp:TextBox>&lt;x&lt;
                        <asp:TextBox ID="xmax" runat="server"
                                Width="32px" Font-Names="Verdana"
                                Font-Size="12px" ForeColor="DarkGreen">
                                2</asp:TextBox>
                        <asp:TextBox ID="ymin" runat="server" Width="32px"
                            Font-Names="Verdana" Font-Size="12px"
                            ForeColor="DarkGreen">-2</asp:TextBox>&lt;y&lt;
                        <asp:TextBox ID="ymax" runat="server"
                            Width="32px" Font-Names="Verdana"
                            Font-Size="12px"
                            ForeColor="DarkGreen">2</asp:TextBox></td>
                </tr>
                <tr>
                    <td style="width: 20%; height: 1px;">
                        Integration</td>
                    <td style="width: 1px; height: 16px;">
                    </td>

                    <td style="width: 20%;" align="left">
                        <asp:TextBox ID="integ" runat="server" Width="40px"
                            Font-Names="Verdana" Font-Size="12px"
                            ForeColor="DarkGreen">0.05</asp:TextBox></td>
                </tr>
                <tr>
                    <td style="width: 20%; height: 1px">
                        View</td>
                    <td style="width: 1px; height: 16px">
                    </td>
                    <td style="width: 20%; height: 16px" align="left">
                        <asp:RadioButton ID="view1" runat="server"
                          Text="Wireframe" Checked="True" GroupName="view" />
                        <asp:RadioButton ID="view2" runat="server"
                          Text="Fill" GroupName="view" />
                        &nbsp; &nbsp; &nbsp;
                        <br />
                        Rotation (x,y,z)
                        <asp:TextBox ID="eyex" runat="server" Width="40px"
                            Font-Names="Verdana" Font-Size="12px"
                            ForeColor="DarkGreen">0.0</asp:TextBox>
                        <asp:TextBox ID="eyey" runat="server" Width="40px"
                            Font-Names="Verdana" Font-Size="12px"
                            ForeColor="DarkGreen">0.0</asp:TextBox>
                        <asp:TextBox ID="eyez" runat="server" Width="40px"
                            Font-Names="Verdana" Font-Size="12px"
                            ForeColor="DarkGreen">-0.39</asp:TextBox>
                        rad</td>
                </tr>
                <tr>
                    <td style="width: 20%; height: 1px;">
                    </td>
                    <td style="width: 1px">
                    </td>
                    <td style="width: 20%" align="left">
                        <asp:Button ID="PlotBtn" runat="server"
                         Font-Names="Arial" Text="Plot"  BackColor="White" />
                    </td>
                </tr>
                <tr>
                    <td style="width: 20%; height: 1px">
                    </td>
                    <td style="width: 1px">
                    </td>
                    <td align="left" style="width: 20%">
                        <asp:Label ID="outputTxt" runat="server"
                            Font-Names="Arial"
                            Font-Size="X-Small" ForeColor="MidnightBlue"
                            Height="28px" Text="Label" Width="100%">
</asp:Label></td>
                </tr>
            </table>
        </asp:Panel>
     </form>
</body>
</html>

sin(pow(x,3)-7*x*y-pow(y,4))
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)

Share

About the Author


Comments and Discussions

 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey26-Feb-12 22:44
professionalManoj Kumar Choubey26-Feb-12 22:44 
GeneralWoa Pin
L8N8Hack16-Sep-07 18:30
MemberL8N8Hack16-Sep-07 18:30 
That's a lot of uncommented code! But cool, none-the-less.
GeneralNeat! Pin
Jay Gatsby20-Aug-07 15:56
MemberJay Gatsby20-Aug-07 15:56 
GeneralCool [modified] Pin
Emil - Gabriel23-Jul-07 21:43
MemberEmil - Gabriel23-Jul-07 21:43 
AnswerRe: Cool Pin
andalmeida24-Jul-07 3:37
Memberandalmeida24-Jul-07 3:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

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