By means of Mates8, graph coding becomes a bit easier.
The web page has four textboxes so the figure gets bounded to the left, right, top and bottom; and a draw button.
Additionally, a panel control will contain the image generated by the code after the button is pressed.

Edited 2 Years Ago by xrj

<%@ Page Language="vb" AutoEventWireup="false" CodeBehind="WebForm1.aspx.vb" Inherits="mates4.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Graph</title>
    <style type="text/css" media="screen">
    .margin { margin-left: 9px; position:relative; top:-3px;}
    .grPos { position:relative; left: 0px; top: 5px; width:<% =w %>px; height: <% =h %>px;}
    </style>

</head>
<body>
    <form id="form1" runat="server">
    <div>
    
        <asp:Table ID="Table1" runat="server" CssClass="margin" Width="708" BackColor="#EADA90" BorderColor="#C0C0C0" BorderWidth="1">
        <asp:TableRow>
            <asp:TableCell>
                <asp:Table ID="Table2" runat="server" Width="100%">
                <asp:TableRow>
                    <asp:TableCell HorizontalAlign="Center">
                        <asp:Label ID="Label1" runat="server" Text="Left: "></asp:Label><br />
                        <asp:TextBox ID="tbLeft" runat="server" Width="100">-4</asp:TextBox>
                    </asp:TableCell>
                    <asp:TableCell HorizontalAlign="Center">
                        <asp:Label ID="Label2" runat="server" Text="Right: "></asp:Label><br />
                        <asp:TextBox ID="tbRight" runat="server" Width="100">4</asp:TextBox>
                    </asp:TableCell>
                    <asp:TableCell HorizontalAlign="Center">
                        <asp:Label ID="Label3" runat="server" Text="Bottom: "></asp:Label><br />
                        <asp:TextBox ID="tbBottom" runat="server" Width="100"></asp:TextBox>
                    </asp:TableCell>
                    <asp:TableCell HorizontalAlign="Center">
                        <asp:Label ID="Label4" runat="server" Text="Top: "></asp:Label><br />
                        <asp:TextBox ID="tbTop" runat="server" Width="100"></asp:TextBox>
                    </asp:TableCell>
                </asp:TableRow>
                <asp:TableRow>
                    <asp:TableCell>
                        <asp:Label ID="Label5" runat="server" Text="Function 1:" ForeColor="black"></asp:Label><br />
                        <asp:Textbox id="f1" runat="server" Columns="18" TextMode="MultiLine" Rows="5">x^3-1</asp:Textbox>
                    </asp:TableCell>
                    <asp:TableCell>
                        <asp:Label ID="Label6" runat="server" Text="Function 2:" ForeColor="blue"></asp:Label><br />
                        <asp:Textbox id="f2" runat="server" Columns="18" TextMode="MultiLine" Rows="5"></asp:Textbox>
                    </asp:TableCell>
                    <asp:TableCell>
                        <asp:Label ID="Label7" runat="server" Text="Function 3:" ForeColor="green"></asp:Label><br />
                        <asp:Textbox id="f3" runat="server" Columns="18" TextMode="MultiLine" Rows="5"></asp:Textbox>
                    </asp:TableCell>
                    <asp:TableCell>
                        <asp:Label ID="Label8" runat="server" Text="Function 4:" ForeColor="red"></asp:Label><br />
                        <asp:Textbox id="f4" runat="server" Columns="18"  TextMode="MultiLine" Rows="5">0</asp:Textbox>
                    </asp:TableCell>
                </asp:TableRow>
                <asp:TableRow>
                    <asp:TableCell ColumnSpan="4" HorizontalAlign="Center">
                        <asp:CheckBox ID="chkAutoTopBottom" Text="Auto top-bottom" runat="server" Checked="true" />
                        &nbsp;&nbsp;&nbsp;
                        <asp:Button ID="btnDraw" runat="server" Text="Draw" />
                        &nbsp;&nbsp;&nbsp;
                        <asp:Label runat="server" ID="lblMessage" Text="" ForeColor="Red" />
                    </asp:TableCell>
                </asp:TableRow>
                <asp:TableRow>
                    <asp:TableCell ColumnSpan="4">
                    </asp:TableCell>
                </asp:TableRow>
                </asp:Table>
            </asp:TableCell>
        </asp:TableRow>
        <asp:TableRow>
            <asp:TableCell>
                <asp:Table ID="TableGraphic" runat="server" Height="690" Width="100%" BackColor="#FAFAFA">
                <asp:TableRow>
                        <asp:TableCell>
                            <asp:Panel runat="server" ID="Panel1">
                            </asp:Panel>
                        </asp:TableCell>
                </asp:TableRow>
                </asp:Table>
            </asp:TableCell>
        </asp:TableRow>
        </asp:Table>
    </div>
    </form>
</body>
</html>


=================================================

Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Image
Imports System.IO

Partial Public Class graphic
    Inherits System.Web.UI.Page
    Dim nID As Int32

    Const nFn As Int32 = 4
    Const nDiv As Int32 = 10
    Public Const w As Int32 = 650
    Public Const h As Int32 = 650
    Dim vMtxParser(nFn - 1) As matrixParser
    Dim vPoly(nFn - 1) As Polynomial, iP As Int32
    Dim oVars(nFn - 1) As VarsAndFns
    Dim vIsEmptyStr(nFn - 1) As Boolean
    Dim vIsPoly(nFn - 1) As Boolean
    Dim vDbl(3) As Double
    Dim sErrMsg As String = "Graphic n/a"
    Dim min As Single = Single.MaxValue
    Dim max As Single = -min
    Dim cImg As HtmlImage
    Dim origH, origW As Int32


    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim sImagePath As String = MapPath("~/precis/images/grTable.png")
        Try
            cImg = New UI.HtmlControls.HtmlImage
            cImg.Alt = "Graphic"
            cImg.Attributes.Add("class", "grPos")
            If Page.IsPostBack Then
                GetGraphic(sImagePath)
            Else
                Try
                    C_session.contador( _
                        Page, _
                        Request, _
                        Response)
                    nID = C_session.getID(Page)
                Catch ex2 As Exception

                End Try
                Using ms As New MemoryStream
                    Dim img As Image = Image.FromFile(sImagePath)
                    img.Save(ms, Imaging.ImageFormat.Png)
                    cImg.Attributes.Add("src", _
                        "data:image/png;base64," + Convert.ToBase64String(ms.ToArray))
                    cImg.Attributes.Add("style", "position:relative; left:20px; top: 10px;")
                End Using
            End If
            Me.Panel1.Controls.Add(cImg)
        Catch ex As Exception
            lblMessage.Text = "n/a"
        End Try
    End Sub
    Private Sub btnDraw_Click(sender As Object, e As EventArgs) Handles btnDraw.Click
        'Dim sImagePath As String = MapPath("~/precis/images/grTable.png")
        'GetGraphic(sImagePath)
    End Sub
    Sub GetGraphic(sGridImagePath As String)
        Try

            If Not validateInputs() Then
                lblMessage.Text = sErrMsg
                Exit Try
            End If
            Dim sFn() As String = {f1.Text, _
                                   f2.Text, _
                                   f3.Text, _
                                   f4.Text}
            Me.getvMtxP_and_vPoly(sFn)

            ' Load a square grid of ten rows
            ' and columns (i.e. 11 horizontal lines
            ' and 11 vertical lines):
            Dim bmp As New Bitmap(sGridImagePath)
            origH = bmp.Height
            origW = bmp.Width
            Dim gr As Graphics = Graphics.FromImage(bmp)
            gr.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
            gr.InterpolationMode = InterpolationMode.NearestNeighbor

            Dim vPen() As Pen = {New Pen(Brushes.Black, 0), _
                                 New Pen(Brushes.Blue, 0), _
                                 New Pen(Brushes.Green, 0), _
                                 New Pen(Brushes.Red, 0)}
            Dim grPath(nFn - 1) As GraphicsPath
            For i As Int32 = 0 To vIsEmptyStr.Length - 1
                If Not vIsEmptyStr(i) Then

                    ' Get function's path points:
                    grPath(i) = _
                        Me.evalFnToGraphicsPath( _
                        i, vDbl(0), vDbl(1), w)
                End If
            Next

            If chkAutoTopBottom.Checked Then
                vDbl(2) = max
                vDbl(3) = min
                tbTop.Text = vDbl(2).ToString(MathGlobal8.us)
                tbBottom.Text = vDbl(3).ToString(MathGlobal8.us)
            Else
                max = vDbl(2)
                min = vDbl(3)
            End If
            For i As Int32 = 0 To vIsEmptyStr.Length - 1
                If grPath(i) IsNot Nothing AndAlso _
                grPath(i).PathData.Points.Count Then
                    ' Translate Y origin:
                    gr.TranslateTransform(0, -min, MatrixOrder.Append)
                    ' Scale X, Y axis:
                    If max = min Then
                        Throw New Exception("n/a")
                    End If
                    gr.ScaleTransform(bmp.Width / w, _
                                      bmp.Height / (max - min), MatrixOrder.Append)
                    ' Add into image's Graphics gr:
                    gr.DrawPath(vPen(i), grPath(i))
                    ' restore origin and scale:
                    gr.ResetTransform()
                End If
            Next

            ' Flip image because gr's vertical axis increments
            ' downwards and graphic's Y axis will increment
            ' upwards:
            bmp.RotateFlip(RotateFlipType.Rotate180FlipX)

            ' Get a bigger bitmap...
            Dim bmp1 As New Bitmap(bmp.Width + 125, bmp.Height + 60)
            Dim gr1 As Graphics = Graphics.FromImage(bmp1)
            gr1.Clear(Color.White)

            ' ...and copy former image to (100,50) to allow 
            ' space on the left and top for the strings:
            gr1.DrawImage(bmp, New Point(100, 50))
            gr1.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias

            ' Draw X's and Y's coordinates values as strings:
            drawStrings(gr1)

            ' Release resources:
            gr.Dispose()
            bmp.Dispose()

            Using ms As New MemoryStream
                ' Save bmp1 into memory...
                bmp1.Save(ms, Imaging.ImageFormat.Png)
                ' ...and set, to the image control on the
                ' aspx page, the memory file in base64 string format:
                cImg.Src = "data:image/png;base64," + Convert.ToBase64String(ms.ToArray)
            End Using

            ' Release resources:
            gr1.Dispose()
            bmp1.Dispose()
        Catch ex As Exception
            Throw ex
            'lblMessage.Text = sErrMsg
        End Try
    End Sub
    Function validateInputs() As Boolean
        Dim mP As New matrixParser
        Try
            ' Axis' X values will be in the
            ' interval [vDbl(0), vDbl(1)]

            ' Verify tbLeft -- tbRight
            ' ------------------------
            ' eval eventual arithmetic (for ex. 2/3) ...
            mP.parse(tbLeft.Text)
            ' ...but must reduce to a double value:
            vDbl(0) = mP.retCjo(0).pRe.ToDouble

            mP.parse(tbRight.Text)
            vDbl(1) = mP.retCjo(0).pRe.ToDouble
            If vDbl(1) < vDbl(0) Then
                ' If left < right, swap values:
                Dim dbl As Double = vDbl(0)
                vDbl(0) = vDbl(1)
                vDbl(1) = dbl
            ElseIf vDbl(0) = vDbl(1) Then
                Return False
            End If
            If vDbl(1) - vDbl(0) <= 1000 * Double.MinValue Then
                Return False
            End If

            If chkAutoTopBottom.Checked = False Then
                ' Axis' Y values will be in the
                ' interval [vDbl(2), vDbl(3)]:
                ' values outside these bounds 
                ' will not be graphed.

                ' If not auto-Top-Bottom checked, consider
                ' inputs in textboxes tbTop, tbBottom.

                ' Verify tbTop -- tbBottom
                ' ------------------------
                mP.parse(tbTop.Text)
                vDbl(3) = mP.retCjo(0).pRe.ToDouble
                mP.parse(tbBottom.Text)
                vDbl(2) = mP.retCjo(0).pRe.ToDouble
                If vDbl(2) < vDbl(3) Then
                    ' If top < bottom, swap values:
                    Dim dbl As Double = vDbl(2)
                    vDbl(2) = vDbl(3)
                    vDbl(3) = dbl
                ElseIf vDbl(2) = vDbl(3) Then
                    Return False
                End If
                If vDbl(2) - vDbl(3) <= 1000 * Double.MinValue Then
                    Return False
                End If
            Else
                ' If auto-Top-Bottom checked
                ' allow any double value:
                vDbl(2) = Double.MaxValue
                vDbl(3) = -Double.MaxValue
            End If
        Catch ex As Exception
            Throw ex
            'Return False
        End Try
        Return True
    End Function
    Private Sub getvMtxP_and_vPoly(sFn() As String)
        Try
            For i As Int32 = 0 To nFn - 1
                If sFn(i) IsNot Nothing AndAlso _
                sFn(i).Length Then
                    vMtxParser(i) = New matrixParser()
                    vMtxParser(i).parse(sFn(i), "", oVars(i))
                    ' Find out if sFn is a Polynomial expression
                    ' because, if so, evaluation will be less 
                    ' time consuming:
                    If vMtxParser(i).ret.exprMtx.IsPolynomial Then
                        vIsPoly(i) = True
                        vPoly(i) = vMtxParser(i).ret.curExpr.getPolynomial
                    End If
                Else
                    vIsEmptyStr(i) = True
                End If

            Next
        Catch ex As Exception
            Throw ex
        End Try
    End Sub
    Private Sub drawStrings(ByRef gr As Graphics) ' Get graph's strings
        Try
            Dim iv As Int32 = 0
            Dim incrV As Double = (max - min) / nDiv
            Dim incrH As Double = (vDbl(1) - vDbl(0)) / nDiv
            Dim dist As Double = origH / nDiv
            Dim fntStr As New Font("Arial Narrow", 12)
            Dim ptImg As New Point(100, 30)

            Dim Vert As Double = max
            Dim Horiz As Double = vDbl(0)
            Dim oldsX As String = " "
            Dim oldsY As String = " "
            Dim nDec As Int32 = 3
            Dim maxDec As Int32 = 9
            Dim curPos As Single = 0
            For row = 0 To 10
                ' Left side strings:
                If Math.Abs(Vert) > 1000 Then
                    maxDec = 0 : nDec = 0
                Else
                    maxDec = 9 : nDec = 3
                End If
                Dim curDec As Int32 = nDec
                Dim sX As String = ""
                Do
                    sX = Math.Round(Vert, curDec).ToString(MathGlobal8.us)
                    curDec += 1
                Loop While sX = oldsX AndAlso curDec < maxDec
                oldsX = sX
                Dim s As SizeF = gr.MeasureString(sX, fntStr)
                gr.DrawString(sX, fntStr, _
                               Brushes.Black, _
                               New Point(ptImg.X - s.Width - 3, _
                                         ptImg.Y + s.Height / 2 + dist * row))
                Vert = max - incrV * (row + 1)

                ' Strings at the top:
                If Math.Abs(Horiz) > 1000 Then
                    maxDec = 0 : nDec = 0
                Else
                    maxDec = 9 : nDec = 3
                End If
                curDec = nDec
                Dim sY As String = ""
                Do
                    sY = Math.Round(Horiz, curDec).ToString(MathGlobal8.us)
                    curDec += 1
                Loop While sY = oldsY AndAlso curDec < maxDec
                oldsY = sY
                s = gr.MeasureString(sY, fntStr)
                gr.DrawString(sY, fntStr, _
                               Brushes.Black, _
                               New Point(ptImg.X - s.Width / 2 + 3 + dist * row, _
                                         ptImg.Y - 18))
                Horiz = vDbl(0) + incrH * (row + 1)
            Next
            gr.ScaleTransform(origW / w, _
                              origH / (max - min), MatrixOrder.Append)
            gr.ResetTransform()
        Catch ex As Exception
            Throw ex
        End Try
    End Sub
    Function evalFnToGraphicsPath(iFn As Int32, x1 As Double, x2 As Double, nPts As Int32) As GraphicsPath
        Dim retGP As New GraphicsPath
        Try
            Dim xStep As Single = (x2 - x1) / nPts
            Dim x As Single = x1
            Dim y As Double
            Dim i As Int32
            If vIsPoly(iFn) Then
                Dim Pa As Polynomial = vPoly(iFn)
                y = Pa.evalPrecis(New Precis(x)).ToDouble
                Dim curPt As New PointF(x, y)
                Dim bClosed As Boolean = False
                Dim nxtPt As New PointF
                i = 1
                Dim bExclude As Boolean = False
                Do
                    x = xStep * CSng(i)
                    ' Try-catch in case of for ex. singular points:
                    Try
                        ' Evaluate Pa(x+x1):
                        y = Pa.evalPrecis(New Precis(x + x1)).ToDouble
                    Catch ex As Exception
                        bExclude = True
                    End Try
                    If Not bExclude AndAlso _
                    vDbl(3) <= y AndAlso y <= vDbl(2) Then
                        nxtPt.X = i
                        nxtPt.Y = y
                        retGP.AddLine(curPt, nxtPt)
                        min = Math.Min(min, y)
                        max = Math.Max(max, y)
                        bClosed = False
                    Else
                        ' 'y' value out of bounds:
                        If Not bClosed Then
                            retGP.StartFigure()
                            bClosed = True
                        End If
                    End If
                    curPt.X = i
                    curPt.Y = y
                    i += 1
                Loop While i <= nPts
            Else
                Dim cjo As Complex
                Dim bExclude As Boolean = True ' Exclude the starting point
                Dim curPt As New PointF
                Dim bClosed As Boolean = True
                Dim nxtPt As New PointF
                Do
                    x = xStep * i
                    ' Try-catch in case of for ex. singular points:
                    Try
                        ' Evaluate Fn(x+x1):
                        cjo = vMtxParser(iFn).ret.exprMtx.getExpr(0, 0).eval_1var_DblToCjo(x + x1)
                        If cjo IsNot Nothing Then
                            If cjo.pIm.IsZero Then
                                y = cjo.pRe.ToDouble
                            Else
                                bExclude = True
                            End If
                        Else
                            bExclude = True
                        End If
                    Catch ex As Exception
                        bExclude = True
                    End Try
                    If Not bExclude AndAlso _
                    vDbl(3) <= y AndAlso y <= vDbl(2) Then
                        nxtPt.X = i
                        nxtPt.Y = y
                        retGP.AddLine(curPt, nxtPt)
                        min = Math.Min(min, y)
                        max = Math.Max(max, y)
                        bClosed = False
                    Else
                        ' 'y' value out of bounds (or first)
                        If Not bClosed Then
                            retGP.StartFigure()
                            bClosed = True
                        End If
                        bExclude = False
                    End If
                    curPt.X = i
                    curPt.Y = y
                    i += 1
                Loop While i <= nPts
            End If
        Catch ex As Exception
            Throw ex
        End Try
        Return retGP
    End Function

End Class

The above code has been replaced by this new one.
Here, the points of discontinuity have been taken into account.
So, for example, function tan(x) does not joint adjacent points Yi>>0 and Yi+1<<0 with a line.

<%@ Page Language="vb" MasterPageFile="~/mates4.Master" AutoEventWireup="false" CodeBehind="graphic.aspx.vb" Inherits="mates4.graphic" %>

<asp:Content ID="Content5" ContentPlaceHolderID="head" runat="server">
        <style type="text/css" media="screen">
    .margin { margin-left: 10px; position:relative; top:0px;}
    .grPos { position:relative; left: 20px; top: 0px;}
    </style>
</asp:Content>
<asp:Content ID="Content1" ContentPlaceHolderID="content2L" runat="server" Visible="false">
    <h3><asp:Label runat="server" >&nbsp;&nbsp;Function grapher</asp:Label></h3>
</asp:Content>
<asp:Content ID="Content6" ContentPlaceHolderID="scriptID" runat="server" Visible="false">
    <script type="text/javascript">
        if (document.getElementById)
            getElemById = function (id) {
                return document.getElementById(id);
            }

        else if (document.all)
            getElemById = function (id) {
                return document.all[id];
                // note that we use square brackets here
            }
        function coord(e, mi) {
            try {
                var Xm,Xb,Xmargin,Ym,Yb,Ymargin,Xmin;
                Xm = getElemById('<% = Xm.ClientID %>').value; Xm = parseFloat(Xm);
                Xb = getElemById('<% = Xb.ClientID%>').value; Xb = parseFloat(Xb);
                Xmargin = getElemById('<% = Xmargin.ClientID%>').value; Xmargin = parseFloat(Xmargin);
                Xmin = getElemById('<% = Xmin.ClientID%>').value; Xmin = parseFloat(Xmin);
                Ym = getElemById('<% = Ym.ClientID%>').value; Ym = parseFloat(Ym);
                Yb = getElemById('<% = Yb.ClientID%>').value; Yb = parseFloat(Yb);
                Ymargin = getElemById('<% = Ymargin.ClientID%>').value; Ymargin = parseFloat(Ymargin);
                var rct = mi.getBoundingClientRect();
                var x0 = e.clientX - rct.left - Xmargin;
                var y0 = e.clientY - rct.top - Ymargin;
                var oX = getElemById('<% =tbX.ClientID %>');
                var oY = getElemById('<% =tbY.ClientID%>');
                oX.value = Xm * x0 + Xb;
                oY.value = -Ym * y0 + Yb;
                var str = '' + oX.value;
                var pos = str.indexOf('.');
                if(pos>-1 && str.length - pos>2 && Math.abs(oX.value)>1)
                { oX.value = Math.round(oX.value * 1000 + 0.005) / 1000;}
                str = '' + oY.value;
                pos = str.indexOf('.');
                if (pos > -1 && str.length - pos > 2 && Math.abs(oY.value) > 1)
                { oY.value = Math.round(oY.value * 1000 + 0.005) / 1000; }
            }
            catch (err) {
                alert(err);
            }
        }
    </script>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="content2R" runat="server" Visible="false">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="maincontent" runat="server">

        <asp:Table ID="Table1" runat="server" CssClass="margin" Width="700" BackColor="#EADA90" BorderColor="#C0C0C0" BorderWidth="1">
        <asp:TableRow>
            <asp:TableCell HorizontalAlign="Left">
                <asp:Table ID="Table2" runat="server" Width="100%">
                <asp:TableRow>
                    <asp:TableCell HorizontalAlign="Center">
                        <asp:Label ID="Label1" runat="server" Text="Left: "></asp:Label><br />
                        <asp:TextBox ID="tbLeft" runat="server" Width="100">-4</asp:TextBox>
                    </asp:TableCell>
                    <asp:TableCell HorizontalAlign="Center">
                        <asp:Label ID="Label2" runat="server" Text="Right: "></asp:Label><br />
                        <asp:TextBox ID="tbRight" runat="server" Width="100">4</asp:TextBox>
                    </asp:TableCell>
                    <asp:TableCell HorizontalAlign="Center">
                        <asp:Label ID="Label3" runat="server" Text="Bottom: "></asp:Label><br />
                        <asp:TextBox ID="tbBottom" runat="server" Width="100"></asp:TextBox>
                    </asp:TableCell>
                    <asp:TableCell HorizontalAlign="Center">
                        <asp:Label ID="Label4" runat="server" Text="Top: "></asp:Label><br />
                        <asp:TextBox ID="tbTop" runat="server" Width="100"></asp:TextBox>
                    </asp:TableCell>
                </asp:TableRow>
                <asp:TableRow>
                    <asp:TableCell>
                        <asp:Label ID="Label5" runat="server" Text="Function 1:" ForeColor="black"></asp:Label><br />
                        <asp:Textbox id="f1" runat="server" Columns="18" TextMode="MultiLine" Rows="5">x^3-1</asp:Textbox>
                    </asp:TableCell>
                    <asp:TableCell>
                        <asp:Label ID="Label6" runat="server" Text="Function 2:" ForeColor="blue"></asp:Label><br />
                        <asp:Textbox id="f2" runat="server" Columns="18" TextMode="MultiLine" Rows="5"></asp:Textbox>
                    </asp:TableCell>
                    <asp:TableCell>
                        <asp:Label ID="Label7" runat="server" Text="Function 3:" ForeColor="green"></asp:Label><br />
                        <asp:Textbox id="f3" runat="server" Columns="18" TextMode="MultiLine" Rows="5"></asp:Textbox>
                    </asp:TableCell>
                    <asp:TableCell>
                        <asp:Label ID="Label8" runat="server" Text="Function 4:" ForeColor="red"></asp:Label><br />
                        <asp:Textbox id="f4" runat="server" Columns="18"  TextMode="MultiLine" Rows="5">0</asp:Textbox>
                    </asp:TableCell>
                </asp:TableRow>
                <asp:TableRow>
                    <asp:TableCell HorizontalAlign="Left">
                        <asp:Table runat="server">
                        <asp:TableRow>
                            <asp:TableCell>
                                <asp:Label runat="server" ForeColor="Red" Text="X: " />
                                <asp:TextBox runat="server" ID="tbX" Text="" Width="120" />
                            </asp:TableCell>
                        </asp:TableRow>
                        </asp:Table>
                    </asp:TableCell>
                    <asp:TableCell HorizontalAlign="Left">
                        <asp:Table runat="server">
                        <asp:TableRow>
                            <asp:TableCell>
                                <asp:Label runat="server" ForeColor="Red" Text="Y: " />
                                <asp:TextBox runat="server" ID="tbY" Text="" Width="120" />
                            </asp:TableCell>
                        </asp:TableRow>
                        </asp:Table>
                    </asp:TableCell>
                    <asp:TableCell ColumnSpan="2" HorizontalAlign="Center">
                        <asp:CheckBox ID="chkAutoTopBottom" Text="Auto top-bottom" runat="server" Checked="true" />
                        &nbsp;&nbsp;&nbsp;
                        <asp:Button ID="btnDraw" runat="server" Text="Draw" />
                        &nbsp;&nbsp;&nbsp;
                        <asp:Label runat="server" ID="lblMessage" Text="" ForeColor="Red" />
                    </asp:TableCell>
                </asp:TableRow>
                <asp:TableRow>
                    <asp:TableCell ColumnSpan="4">
                    </asp:TableCell>
                </asp:TableRow>
                </asp:Table>
            </asp:TableCell>
        </asp:TableRow>
        <asp:TableRow>
            <asp:TableCell HorizontalAlign="Left">
                <asp:Table ID="TableGraphic" runat="server" Width="100%" BackColor="#FAFAFA" HorizontalAlign="Left">
                <asp:TableRow>
                        <asp:TableCell HorizontalAlign="Left">
                            <asp:Panel runat="server" ID="Panel1">
                            </asp:Panel>
                        </asp:TableCell>
                </asp:TableRow>
                </asp:Table>
            </asp:TableCell>
        </asp:TableRow>
        </asp:Table>


</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="afterMC" runat="server" Visible="false">
    <asp:HiddenField runat="server" ID="Xm" Value="0" />
    <asp:HiddenField runat="server" ID="Xb" Value="0" />
    <asp:HiddenField runat="server" ID="Xmargin" Value="0" />
    <asp:HiddenField runat="server" ID="Xmin" Value="0" />
    <asp:HiddenField runat="server" ID="Ym" Value="0" />
    <asp:HiddenField runat="server" ID="Yb" Value="0" />
    <asp:HiddenField runat="server" ID="Ymargin" Value="0" />
</asp:Content>

===============================================================

Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Image
Imports System.IO

Partial Public Class graphic
    Inherits System.Web.UI.Page
    Dim nID As Int32

    Const nFn As Int32 = 4
    Const nDiv As Int32 = 10
    Public Const w As Int32 = 600
    Public Const h As Int32 = 600
    Dim vMtxParser(nFn - 1) As matrixParser
    Dim vPoly(nFn - 1) As Polynomial, iP As Int32
    Dim oVars(nFn - 1) As VarsAndFns
    Dim vFn() As String
    Dim vIsEmptyStr(nFn - 1) As Boolean
    Dim vIsPoly(nFn - 1) As Boolean
    Dim vDbl(3) As Double
    Dim sErrMsg As String = "Graphic n/a"
    Dim min As Single = Single.MaxValue
    Dim max As Single = -min
    Dim cImg As HtmlImage
    Dim origH, origW As Int32
    Dim marginPt0 As New Point(110, 60)
    Dim marginPt1 As New Point(100, 50)
    Const margDch As Int32 = 65

    Sub logfile(ex As Exception)
        Try
            Dim sFn() As String = {f1.Text, _
                       f2.Text, _
                       f3.Text, _
                       f4.Text}
            Dim sTB() As String = {tbLeft.Text, _
                       tbRight.Text, _
                       tbBottom.Text, _
                       tbTop.Text}
            C_session.logFile(ex, _
                 Join(sFn, "|"), _
                Join(sTB, "|"), Page, nID, "polycalc.txt")
        Catch ex2 As Exception

        End Try
    End Sub
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim sImagePath As String = MapPath("~/precis/images/grTable.png")
        Try
            cImg = New UI.HtmlControls.HtmlImage
            cImg.Alt = "Graphic"
            cImg.Attributes.Add("class", "grPos")
            GetGraphic(sImagePath)
            Me.Panel1.Controls.Add(cImg)
        Catch ex As Exception
            logfile(ex)
            lblMessage.Text = "n/a"
        End Try
    End Sub

    Private Sub btnDraw_Click(sender As Object, e As EventArgs) Handles btnDraw.Click
    End Sub
    Sub GetGraphic(sGridImagePath As String)
        Try

            If Not validateInputs() Then
                lblMessage.Text = sErrMsg
                Exit Try
            End If
            vFn = {f1.Text, _
                   f2.Text, _
                   f3.Text, _
                   f4.Text}
            Me.getvMtxP_and_vPoly(vFn)

            ' Load a square grid of ten rows
            ' and columns (i.e. 11 horizontal lines
            ' and 11 vertical lines):
            Dim bmp As New Bitmap(sGridImagePath)
            origH = bmp.Height
            origW = bmp.Width
            Dim gr As Graphics = Graphics.FromImage(bmp)
            gr.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
            gr.InterpolationMode = InterpolationMode.HighQualityBicubic

            Dim vPen() As Pen = {New Pen(Brushes.Black, 0), _
                                 New Pen(Brushes.Blue, 0), _
                                 New Pen(Brushes.Green, 0), _
                                 New Pen(Brushes.Red, 0)}


            Dim vPts(-1)()() As PointF, iv As Int32
            ' vPts(i) holds all the points of a function (for ex. f(x)=1/x)
            ' vPts(i)(j) has all the points of a continous interval of the
            '            function. If f(x)=1/x, point x=0 is a discontinuity (f(x)=infinity):
            '            vPts(i)(0) has all the points f(x)=1/x where x<0
            '            vPts(i)(0) has all the points f(x)=1/x where x>0
            ' vPts(i)(j)(k) is a concrete point of the function, for example:
            '            vPts(i)(0)(0) may be point (x=-4, y=1/-4)
            '            vPts(i)(0)(1) may be point (x=-3.9, y=1/-3.9)
            '            ....
            '            vPts(i)(1)(0) may be point (x=0.1, y=1/0.1)
            '            vPts(i)(1)(1) may be point (x=0.2, y=1/0.2)
            '            ....
            ' (here, the increment 0.1 is ficticious, really the step depends on
            ' the interval Xleft, Xright and the number of points to draw,
            ' see method evalFnToGraphicsPath())
            For i As Int32 = 0 To vIsEmptyStr.Length - 1
                If Not vIsEmptyStr(i) Then

                    ' Get function's path points:
                    ReDim Preserve vPts(iv)
                    vPts(iv) = _
                        Me.evalFnToGraphicsPath( _
                        i, vDbl(0), vDbl(1), w)
                    iv += 1
                End If
            Next
            iv = 0
            For i As Int32 = 0 To vIsEmptyStr.Length - 1
                If Not vIsEmptyStr(i) Then

                    ' Get function's path points:
                    For j As Int32 = 0 To vPts(iv).GetLength(0) - 1
                        gr.TranslateTransform(0, -min, MatrixOrder.Append)
                        ' Scale X, Y axis:
                        If max <> min Then
                            gr.ScaleTransform(bmp.Width / w, _
                                              bmp.Height / (max - min), MatrixOrder.Append)
                        End If
                        ' Add into image's Graphics gr:
                        gr.DrawCurve(vPen(i), vPts(iv)(j))
                        ' restore origin and scale:
                        gr.ResetTransform()
                    Next
                    iv += 1
                End If
            Next

            If chkAutoTopBottom.Checked Then
                vDbl(2) = max
                vDbl(3) = min
                tbTop.Text = vDbl(2).ToString(MathGlobal8.us)
                tbBottom.Text = vDbl(3).ToString(MathGlobal8.us)
            Else
                max = vDbl(2)
                min = vDbl(3)
            End If
            mouseeventInit(bmp.Width, bmp.Height)

            ' Flip image because gr's vertical axis increments
            ' downwards and graphic's Y axis will increment
            ' upwards:
            bmp.RotateFlip(RotateFlipType.Rotate180FlipX)

            ' Get a bigger bitmap...
            Dim bmp1 As New Bitmap(w + margDch, h) ' bmp.Width + marginPt0.X, bmp.Height + marginPt0.Y)
            Dim gr1 As Graphics = Graphics.FromImage(bmp1)
            gr1.Clear(Color.White)

            ' ...and copy former image to (100,50) to allow 
            ' space on the left and top for the strings:
            gr1.DrawImage(bmp, New Point(marginPt1.X, marginPt1.Y))
            gr1.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias

            ' Draw X's and Y's coordinates values as strings:
            drawStrings(gr1)

            ' Release resources:
            gr.Dispose()
            bmp.Dispose()

            Using ms As New MemoryStream
                ' Save bmp1 into memory...
                bmp1.Save(ms, Imaging.ImageFormat.Png)
                ' ...and set, to the image control on the
                ' aspx page, the memory file in base64 string format:
                cImg.Src = "data:image/png;base64," + Convert.ToBase64String(ms.ToArray)
            End Using

            ' Release resources:
            gr1.Dispose()
            bmp1.Dispose()
        Catch ex As Exception
            Throw ex
            'lblMessage.Text = sErrMsg
        End Try
    End Sub
    Sub mouseeventInit(bmpW As Int32, bmpH As Int32)
        Try
            'If Not Page.IsPostBack Then
            '    Exit Sub
            'End If
            cImg.Attributes.Add("onmousemove", "coord(event,this);")

            ' Set Xm,Xb,Ym,Yb for mouseover event:
            Dim m As Double = (max - min) / bmpH
            Ym.Value = m.ToString(MathGlobal8.us)
            Yb.Value = ((max + min + m * bmpH) / 2.0).ToString(MathGlobal8.us)
            Ymargin.Value = (marginPt0.Y * bmpH / h).ToString(MathGlobal8.us)
            m = (vDbl(1) - vDbl(0)) / bmpW
            Xm.Value = m.ToString(MathGlobal8.us)
            Xb.Value = ((vDbl(1) + vDbl(0) - m * bmpW) / 2.0).ToString(MathGlobal8.us)
            Xmargin.Value = (marginPt1.X).ToString(MathGlobal8.us)
            Xmin.Value = min '.ToString(MathGlobal8.us)
        Catch ex As Exception
            Throw ex
        End Try
    End Sub
    Function validateInputs() As Boolean
        Dim mP As New matrixParser
        Try
            ' Axis' X values will be in the
            ' interval [vDbl(0), vDbl(1)]

            ' Verify tbLeft -- tbRight
            ' ------------------------
            ' eval eventual arithmetic (for ex. 2/3) ...
            mP.parse(tbLeft.Text)
            ' ...but must reduce to a double value:
            vDbl(0) = mP.retCjo(0).pRe.ToDouble

            mP.parse(tbRight.Text)
            vDbl(1) = mP.retCjo(0).pRe.ToDouble
            If vDbl(1) < vDbl(0) Then
                ' If left < right, swap values:
                Dim dbl As Double = vDbl(0)
                vDbl(0) = vDbl(1)
                vDbl(1) = dbl
            ElseIf vDbl(0) = vDbl(1) Then
                Return False
            End If
            If vDbl(1) - vDbl(0) <= 1000 * Double.MinValue Then
                Return False
            End If

            If chkAutoTopBottom.Checked = False Then
                ' Axis' Y values will be in the
                ' interval [vDbl(2), vDbl(3)]:
                ' values outside these bounds 
                ' will not be graphed.

                ' If not auto-Top-Bottom checked, consider
                ' inputs in textboxes tbTop, tbBottom.

                ' Verify tbTop -- tbBottom
                ' ------------------------
                mP.parse(tbTop.Text)
                vDbl(3) = mP.retCjo(0).pRe.ToDouble
                mP.parse(tbBottom.Text)
                vDbl(2) = mP.retCjo(0).pRe.ToDouble
                If vDbl(2) < vDbl(3) Then
                    ' If top < bottom, swap values:
                    Dim dbl As Double = vDbl(2)
                    vDbl(2) = vDbl(3)
                    vDbl(3) = dbl
                ElseIf vDbl(2) = vDbl(3) Then
                    Return False
                End If
                If vDbl(2) - vDbl(3) <= 1000 * Double.MinValue Then
                    Return False
                End If
            Else
                ' If auto-Top-Bottom checked
                ' allow any double value:
                vDbl(2) = Double.MaxValue
                vDbl(3) = -Double.MaxValue
            End If
        Catch ex As Exception
            Throw ex
            'Return False
        End Try
        Return True
    End Function
    Private Sub getvMtxP_and_vPoly(sFn() As String)
        Try
            For i As Int32 = 0 To nFn - 1
                If sFn(i) IsNot Nothing AndAlso _
                sFn(i).Length Then
                    vMtxParser(i) = New matrixParser()
                    vMtxParser(i).parse(sFn(i), "", oVars(i))
                    If oVars(i).length <= 1 Then
                        ' Find out if sFn is a Polynomial expression
                        ' because, if so, evaluation will be less 
                        ' time consuming:
                        If vMtxParser(i).ret.exprMtx.IsPolynomial Then
                            vIsPoly(i) = True
                            vPoly(i) = vMtxParser(i).ret.curExpr.getPolynomial
                        End If
                    Else
                        ' more than 1 variable, discard:
                        vIsEmptyStr(i) = True
                    End If
                Else
                    vIsEmptyStr(i) = True
                End If

            Next
        Catch ex As Exception
            Throw ex
        End Try
    End Sub
    Private Sub drawStrings(ByRef gr As Graphics) ' Get graph's strings
        Try
            Dim iv As Int32 = 0
            Dim incrV As Double = (max - min) / nDiv
            Dim incrH As Double = (vDbl(1) - vDbl(0)) / nDiv
            Dim dist As Double = origH / nDiv
            Dim fntStr As New Font("Calibri", 11)
            Dim ptImg As New Point(100, 30)

            Dim oldsX(10) As String
            Dim Xdec(10) As Int32
            Dim oldsY(10) As String
            Dim Ydec(10) As Int32
            Dim nDec As Int32 = 3
            Dim maxDec As Int32 = 9
            Dim curPos As Single = 0
repite:
            Dim Vert As Double = max
            Dim Horiz As Double = vDbl(0)
            For row = 0 To 10
                ' Left side strings:
                Dim sX As String = ""
                If Math.Abs(Vert) > 1000 Then
                    sX = Vert.ToString("e" + Xdec(row).ToString, MathGlobal8.us)
                Else
                    sX = Math.Round(Vert, Xdec(row)).ToString(MathGlobal8.us)
                End If
                For i As Int32 = 0 To row - 1
                    If oldsX(i) = sX Then
                        If Xdec(row) < maxDec Then
                            Xdec(i) += 1
                            Xdec(row) += 1
                            GoTo repite
                        End If
                    End If
                Next
                oldsX(row) = sX
                Vert = max - incrV * (row + 1)

                ' Strings at the top:
                Dim sY As String = ""
                If Math.Abs(Horiz) > 1000 Then
                    sY = Horiz.ToString("e" + Ydec(row).ToString, MathGlobal8.us)
                Else
                    sY = Math.Round(Horiz, Ydec(row)).ToString(MathGlobal8.us)
                End If
                For i As Int32 = 0 To row - 1
                    If oldsY(i) = sY Then
                        If Ydec(row) < maxDec Then
                            Ydec(i) += 1
                            Ydec(row) += 1
                            GoTo repite
                        End If
                    End If
                Next
                oldsY(row) = sY
                Horiz = vDbl(0) + incrH * (row + 1)
            Next
            For row = 0 To 10
                Dim s As SizeF = gr.MeasureString(oldsX(row), fntStr)
                gr.DrawString(oldsX(row), fntStr, _
                               Brushes.Black, _
                               New Point(ptImg.X - s.Width - 3, _
                                         ptImg.Y + s.Height / 2 + dist * row))

                s = gr.MeasureString(oldsY(row), fntStr)
                gr.DrawString(oldsY(row), fntStr, _
                               Brushes.Black, _
                               New Point(ptImg.X - s.Width / 2 - 1 + dist * row, _
                                         ptImg.Y - 2))
            Next
            gr.ScaleTransform(origW / w, _
                              origH / (max - min), MatrixOrder.Append)
            gr.ResetTransform()
        Catch ex As Exception
            Throw ex
        End Try
    End Sub
    Function evalFnToGraphicsPath(iFn As Int32, x1 As Double, x2 As Double, nPts As Int32) As PointF()()
        Dim pts(0)() As PointF, iP0, iP1 As Int32
        Try
            Dim xStep As Single = (x2 - x1) / nPts
            Dim x As Single = x1
            Dim y As Double
            Dim i As Int32
            ReDim pts(0)(nPts)

            Dim bClosed As Boolean = False
            Dim bExclude As Boolean = False
            Dim PaZeros(-1) As Double
            Dim nZeros As Int32 = 0
            Dim iCurZero As Int32 = 0
            Dim DenP As Polynomial = Nothing
            Dim curPt As New PointF
            Dim oldPt0, oldPt1 As PointF
            Dim diff As Double = Double.MaxValue
            Dim cjo As Complex
            Dim expr As Expression = vMtxParser(iFn).ret.exprMtx.getExpr(0, 0)
            Dim Pa As Polynomial = vPoly(iFn)
            Do
                x = xStep * CSng(i)
                ' Try-catch in case of for ex. singular points:
                Try
                    If vIsPoly(iFn) Then
                        ' Evaluate Pa(x+x1):
                        y = Pa.evalPrecis(New Precis(x + x1)).ToDouble
                    Else
                        cjo = expr.eval_1var_DblToCjo(x + x1)
                        If cjo IsNot Nothing Then
                            If cjo.pIm.IsZero Then
                                y = cjo.pRe.ToDouble
                            Else
                                bExclude = True
                            End If
                        Else
                            bExclude = True
                        End If
                    End If
                Catch ex As Exception
                    bExclude = True
                End Try
                If iP1 > 2 AndAlso Not bExclude AndAlso _
                vDbl(3) <= y AndAlso y <= vDbl(2) Then
                    ' Get the slope of line oldPt0-oldPt1:
                    Dim m1 As Single = (oldPt1.Y - oldPt0.Y) / 1
                    ' ...and of line oldPt1-(x,y):
                    Dim m2 As Single = (y - oldPt1.Y) / 1
                    Dim atg As Double = Math.Abs(Math.PI / 2 - Math.Abs(Math.Atan2(m1, m2)))
                    'If atg < diff Then
                    '    diff = atg
                    '    lblMessage.Text = diff.ToString(MathGlobal8.us)
                    'End If
                    If Math.Sign(m1) <> Math.Sign(m2) AndAlso _
                    Math.Abs(m1) > 10 AndAlso Math.Abs(m2) > 10 AndAlso _
                    atg < 1.6 Then
                        bExclude = True
                    End If
                End If
                If iP1 Then
                    oldPt1.X = pts(iP0)(iP1 - 1).X
                    oldPt1.Y = pts(iP0)(iP1 - 1).Y
                    If iP1 > 1 Then
                        oldPt0.X = pts(iP0)(iP1 - 2).X
                        oldPt0.Y = pts(iP0)(iP1 - 2).Y
                    End If
                End If
                If bExclude Then
                    ' 'y' value out of bounds 
                    If Not bClosed Then
                        ReDim Preserve pts(iP0)(iP1 - 1)
                        iP0 += 1
                        ReDim Preserve pts(iP0), pts(iP0)(nPts - 1)
                        iP1 = 0
                    End If
                    bExclude = False
                Else
                    pts(iP0)(iP1).X = i
                    pts(iP0)(iP1).Y = y
                    iP1 += 1
                    min = Math.Min(min, y)
                    max = Math.Max(max, y)
                    bClosed = False
                End If
                i += 1
            Loop While i <= nPts
            ReDim Preserve pts(iP0)(iP1 - 1)

        Catch ex As Exception
            Throw ex
        End Try
        Return pts
    End Function

End Class

Because of some fixes I take the opportunity to attach a zip file including the image, mates8.dll (v8.3.58), the markup file and the code behind file.

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="fnGrapher.aspx.vb" Inherits="fnGrapher" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Function grapher</title>
    <style type="text/css" media="screen">
        body { font-family: Calibri;
               font-size: medium;
        }
    .margin { margin-left: 10px; position:relative; top:0px;}
    .grPos { position:relative; left: 20px; top: 0px;}
    </style>
        <script type="text/javascript">
            if (document.getElementById)
                getElemById = function (id) {
                    return document.getElementById(id);
                }

            else if (document.all)
                getElemById = function (id) {
                    return document.all[id];
                    // note that we use square brackets here
                }
            function coord(e, mi) {
                try {
                    var Xm, Xb, Xmargin, Ym, Yb, Ymargin, Xmin;
                    Xm = getElemById('<% = Xm.ClientID %>').value; Xm = parseFloat(Xm);
                Xb = getElemById('<% = Xb.ClientID%>').value; Xb = parseFloat(Xb);
                Xmargin = getElemById('<% = Xmargin.ClientID%>').value; Xmargin = parseFloat(Xmargin);
                Xmin = getElemById('<% = Xmin.ClientID%>').value; Xmin = parseFloat(Xmin);
                Ym = getElemById('<% = Ym.ClientID%>').value; Ym = parseFloat(Ym);
                Yb = getElemById('<% = Yb.ClientID%>').value; Yb = parseFloat(Yb);
                Ymargin = getElemById('<% = Ymargin.ClientID%>').value; Ymargin = parseFloat(Ymargin);
                var rct = mi.getBoundingClientRect();
                var x0 = e.clientX - rct.left - Xmargin;
                var y0 = e.clientY - rct.top - Ymargin;
                var oX = getElemById('<% =tbX.ClientID %>');
                var oY = getElemById('<% =tbY.ClientID%>');
                oX.value = Xm * x0 + Xb;
                oY.value = -Ym * y0 + Yb;
                var str = '' + oX.value;
                var pos = str.indexOf('.');
                if (pos > -1 && str.length - pos > 2 && Math.abs(oX.value) > 1)
                { oX.value = Math.round(oX.value * 1000 + 0.005) / 1000; }
                str = '' + oY.value;
                pos = str.indexOf('.');
                if (pos > -1 && str.length - pos > 2 && Math.abs(oY.value) > 1)
                { oY.value = Math.round(oY.value * 1000 + 0.005) / 1000; }
            }
            catch (err) {
                alert(err);
            }
        }
    </script>

</head>
<body>
    <form id="form1" runat="server">
    <div style="width:100%">
        <asp:Table ID="Table1" runat="server" CssClass="margin" Width="700" BackColor="#EADA90" BorderColor="#C0C0C0" BorderWidth="1" HorizontalAlign="Center">
        <asp:TableRow>
            <asp:TableCell HorizontalAlign="Left">
                <asp:Table ID="Table2" runat="server" Width="100%">
                <asp:TableRow>
                    <asp:TableCell HorizontalAlign="Center">
                        <asp:Label ID="Label1" runat="server" Text="Left: "></asp:Label><br />
                        <asp:TextBox ID="tbLeft" runat="server" Width="100">-4</asp:TextBox>
                    </asp:TableCell>
                    <asp:TableCell HorizontalAlign="Center">
                        <asp:Label ID="Label2" runat="server" Text="Right: "></asp:Label><br />
                        <asp:TextBox ID="tbRight" runat="server" Width="100">4</asp:TextBox>
                    </asp:TableCell>
                    <asp:TableCell HorizontalAlign="Center">
                        <asp:Label ID="Label3" runat="server" Text="Bottom: "></asp:Label><br />
                        <asp:TextBox ID="tbBottom" runat="server" Width="100"></asp:TextBox>
                    </asp:TableCell>
                    <asp:TableCell HorizontalAlign="Center">
                        <asp:Label ID="Label4" runat="server" Text="Top: "></asp:Label><br />
                        <asp:TextBox ID="tbTop" runat="server" Width="100"></asp:TextBox>
                    </asp:TableCell>
                </asp:TableRow>
                <asp:TableRow>
                    <asp:TableCell>
                        <asp:Label ID="Label5" runat="server" Text="Function 1:" ForeColor="black"></asp:Label><br />
                        <asp:Textbox id="f1" runat="server" Columns="18" TextMode="MultiLine" Rows="5">x^3-1</asp:Textbox>
                    </asp:TableCell>
                    <asp:TableCell>
                        <asp:Label ID="Label6" runat="server" Text="Function 2:" ForeColor="blue"></asp:Label><br />
                        <asp:Textbox id="f2" runat="server" Columns="18" TextMode="MultiLine" Rows="5"></asp:Textbox>
                    </asp:TableCell>
                    <asp:TableCell>
                        <asp:Label ID="Label7" runat="server" Text="Function 3:" ForeColor="green"></asp:Label><br />
                        <asp:Textbox id="f3" runat="server" Columns="18" TextMode="MultiLine" Rows="5"></asp:Textbox>
                    </asp:TableCell>
                    <asp:TableCell>
                        <asp:Label ID="Label8" runat="server" Text="Function 4:" ForeColor="red"></asp:Label><br />
                        <asp:Textbox id="f4" runat="server" Columns="18"  TextMode="MultiLine" Rows="5">0</asp:Textbox>
                    </asp:TableCell>
                </asp:TableRow>
                <asp:TableRow>
                    <asp:TableCell HorizontalAlign="Left">
                        <asp:Table runat="server">
                        <asp:TableRow>
                            <asp:TableCell>
                                <asp:Label runat="server" ForeColor="Red" Text="X: " ></asp:Label>
                                <asp:TextBox runat="server" ID="tbX" Text="" Width="120" ></asp:TextBox>
                            </asp:TableCell>
                        </asp:TableRow>
                        </asp:Table>
                    </asp:TableCell>
                    <asp:TableCell HorizontalAlign="Left">
                        <asp:Table runat="server">
                        <asp:TableRow>
                            <asp:TableCell>
                                <asp:Label runat="server" ForeColor="Red" Text="Y: " ></asp:Label>
                                <asp:TextBox runat="server" ID="tbY" Text="" Width="120" ></asp:TextBox>
                            </asp:TableCell>
                        </asp:TableRow>
                        </asp:Table>
                    </asp:TableCell>
                    <asp:TableCell ColumnSpan="2" HorizontalAlign="Center">
                        <asp:Table runat="server">
                            <asp:TableRow>
                                <asp:TableCell Wrap="false">
                                    <asp:CheckBox ID="chkAutoTopBottom" Text="Auto top-bottom" runat="server" Checked="true" ></asp:CheckBox>
                                </asp:TableCell>
                                <asp:TableCell Width="100">
                                    <asp:Button ID="btnDraw" runat="server" Text="Draw" ></asp:Button>
                                </asp:TableCell>
                                <asp:TableCell>
                                </asp:TableCell>
                            </asp:TableRow>
                        </asp:Table>
                    </asp:TableCell>
                    <asp:TableCell>
                    </asp:TableCell>
                </asp:TableRow>
                <asp:TableRow>
                    <asp:TableCell ColumnSpan="4">
                    </asp:TableCell>
                </asp:TableRow>
                </asp:Table>
            </asp:TableCell>
        </asp:TableRow>
        <asp:TableRow>
            <asp:TableCell HorizontalAlign="Left">
                <asp:Label runat="server" ID="lblMessage" Text="" ForeColor="Red" ></asp:Label>
            </asp:TableCell>
       </asp:TableRow>
        <asp:TableRow>
            <asp:TableCell HorizontalAlign="Left">
                <asp:Table ID="TableGraphic" runat="server" Width="100%" BackColor="#FAFAFA" HorizontalAlign="Left">
                <asp:TableRow>
                        <asp:TableCell HorizontalAlign="Left">
                            <asp:Panel runat="server" ID="Panel1">
                            </asp:Panel>
                        </asp:TableCell>
                </asp:TableRow>
                </asp:Table>
            </asp:TableCell>
        </asp:TableRow>
        </asp:Table>    
    <asp:HiddenField runat="server" ID="Xm" Value="0" ></asp:HiddenField>
    <asp:HiddenField runat="server" ID="Xb" Value="0" ></asp:HiddenField>
    <asp:HiddenField runat="server" ID="Xmargin" Value="0" ></asp:HiddenField>
    <asp:HiddenField runat="server" ID="Xmin" Value="0" ></asp:HiddenField>
    <asp:HiddenField runat="server" ID="Ym" Value="0" ></asp:HiddenField>
    <asp:HiddenField runat="server" ID="Yb" Value="0" ></asp:HiddenField>
    <asp:HiddenField runat="server" ID="Ymargin" Value="0" ></asp:HiddenField>
    </div>
    </form>
</body>
</html>
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Image
Imports System.IO
Imports mates8

Partial Class fnGrapher
    Inherits System.Web.UI.Page
    Dim nID As Int32

    Const nFn As Int32 = 4
    Const nDiv As Int32 = 10
    Public Const w As Int32 = 600
    Public Const h As Int32 = 600
    Dim vMtxParser(nFn - 1) As matrixParser
    Dim vPoly(nFn - 1) As Polynomial, iP As Int32
    Dim oVars(nFn - 1) As VarsAndFns
    Dim vFn() As String
    Dim vIsEmptyStr(nFn - 1) As Boolean
    Dim vIsPoly(nFn - 1) As Boolean
    Dim vDbl(3) As Double
    Dim sErrMsg As String = "Graphic n/a"
    Dim min As Single = Single.MaxValue
    Dim max As Single = -min
    Dim cImg As HtmlImage
    Dim origH, origW As Int32
    Dim marginPt0 As New Point(110, 60)
    Dim marginPt1 As New Point(100, 50)
    Dim iComplexPts, iOutOfRange As Int32
    Const margDch As Int32 = 65

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim sImagePath As String = MapPath("~/grTable.png")
        Try
            lblMessage.Visible = False
            lblMessage.Text = ""
            iComplexPts = 0 : iOutOfRange = 0
            cImg = New UI.HtmlControls.HtmlImage
            cImg.Alt = "Graphic"
            cImg.Attributes.Add("class", "grPos")

            GetGraphic(sImagePath)

            Me.Panel1.Controls.Add(cImg)
            If iComplexPts OrElse iOutOfRange Then
                If iComplexPts Then
                    lblMessage.Text = iComplexPts.ToString + " complex points couldn't be drawn."
                End If
                If iOutOfRange Then
                    lblMessage.Text += iOutOfRange.ToString + " out of range points couldn't be drawn."
                End If
            End If
        Catch ex As Exception
            If lblMessage.Text.Length = 0 Then
                If iComplexPts OrElse iOutOfRange Then
                    If iComplexPts Then
                        lblMessage.Text = iComplexPts.ToString + " complex points couldn't be drawn."
                    End If
                    If iOutOfRange Then
                        lblMessage.Text += iOutOfRange.ToString + " out of range points couldn't be drawn."
                    End If
                Else
                    lblMessage.Text = "n/a"
                End If
            End If
        Finally
            If lblMessage.Text.Length Then
                lblMessage.Visible = True
            End If
        End Try
    End Sub

    Private Sub btnDraw_Click(sender As Object, e As EventArgs) Handles btnDraw.Click
        'Dim sImagePath As String = MapPath("~/precis/images/grTable.png")
        'GetGraphic(sImagePath)
    End Sub
    Sub GetGraphic(sGridImagePath As String)
        Try

            If Not validateInputs() Then
                lblMessage.Text = "n/a: invalid input values."
                Exit Try
            End If
            vFn = {f1.Text, _
                   f2.Text, _
                   f3.Text, _
                   f4.Text}
            Me.getvMtxP_and_vPoly(vFn)

            ' Load a square grid of ten rows
            ' and columns (i.e. 11 horizontal lines
            ' and 11 vertical lines):
            Dim bmp As New Bitmap(sGridImagePath)
            origH = bmp.Height
            origW = bmp.Width
            Dim gr As Graphics = Graphics.FromImage(bmp)
            gr.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
            gr.InterpolationMode = InterpolationMode.HighQualityBicubic

            Dim vPen() As Pen = {New Pen(Brushes.Black, 0), _
                                 New Pen(Brushes.Blue, 0), _
                                 New Pen(Brushes.Green, 0), _
                                 New Pen(Brushes.Red, 0)}


            Dim vPts(-1)()() As PointF, iv As Int32
            ' vPts(i) holds all the points of a function (for ex. f(x)=1/x)
            ' vPts(i)(j) has all the points of a continous interval of the
            '            function. If f(x)=1/x, point x=0 is a discontinuity (f(x)=infinity):
            '            vPts(i)(0) has all the points f(x)=1/x where x<0
            '            vPts(i)(0) has all the points f(x)=1/x where x>0
            ' vPts(i)(j)(k) is a concrete point of the function, for example:
            '            vPts(i)(0)(0) may be point (x=-4, y=1/-4)
            '            vPts(i)(0)(1) may be point (x=-3.9, y=1/-3.9)
            '            ....
            '            vPts(i)(1)(0) may be point (x=0.1, y=1/0.1)
            '            vPts(i)(1)(1) may be point (x=0.2, y=1/0.2)
            '            ....
            ' (here, the increment 0.1 is ficticious, really the step depends on
            ' the interval Xleft, Xright and the number of points to draw,
            ' see method evalFnToGraphicsPath())
            Dim max2 As Double = -Double.MaxValue
            Dim min2 As Double = Double.MaxValue
            For i As Int32 = 0 To vIsEmptyStr.Length - 1
                If Not vIsEmptyStr(i) Then

                    ' Get function's path points:
                    ReDim Preserve vPts(iv)
                    vPts(iv) = _
                        Me.evalFnToGraphicsPath( _
                        i, vDbl(0), vDbl(1), w)
                    iv += 1
                    max2 = Math.Max(max2, max)
                    min2 = Math.Min(min2, min)
                End If
            Next
            max = max2 : min = min2
            iv = 0
            For i As Int32 = 0 To vIsEmptyStr.Length - 1
                If Not vIsEmptyStr(i) Then

                    ' Get function's path points:
                    For j As Int32 = 0 To vPts(iv).GetLength(0) - 1
                        gr.TranslateTransform(0, -min, MatrixOrder.Append)
                        ' Scale X, Y axis:
                        If max <> min Then
                            gr.ScaleTransform(bmp.Width / w, _
                                              bmp.Height / (max - min), MatrixOrder.Append)
                        End If
                        ' Add into image's Graphics gr:
                        gr.DrawCurve(vPen(i), vPts(iv)(j))

                        If chkAutoTopBottom.Checked Then
                        End If
                        ' restore origin and scale:
                        gr.ResetTransform()
                    Next
                    iv += 1
                End If
            Next

            If chkAutoTopBottom.Checked Then
                vDbl(2) = max
                vDbl(3) = min
                tbTop.Text = vDbl(2).ToString(MathGlobal8.us)
                tbBottom.Text = vDbl(3).ToString(MathGlobal8.us)
            Else
                max = vDbl(2)
                min = vDbl(3)
            End If
            If max = min Then
                lblMessage.Text = "n/a: top and bottom values can't be equal or void."
                Throw New Exception(lblMessage.Text)
            End If
            mouseeventInit(bmp.Width, bmp.Height)

            ' Flip image because gr's vertical axis increments
            ' downwards and graphic's Y axis will increment
            ' upwards:
            bmp.RotateFlip(RotateFlipType.Rotate180FlipX)

            ' Get a bigger bitmap...
            Dim bmp1 As New Bitmap(w + margDch, h) ' bmp.Width + marginPt0.X, bmp.Height + marginPt0.Y)
            Dim gr1 As Graphics = Graphics.FromImage(bmp1)
            gr1.Clear(Color.White)

            ' ...and copy former image to (100,50) to allow 
            ' space on the left and top for the strings:
            gr1.DrawImage(bmp, New Point(marginPt1.X, marginPt1.Y))
            gr1.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias

            ' Draw X's and Y's coordinates values as strings:
            drawStrings(gr1)

            ' Release resources:
            gr.Dispose()
            bmp.Dispose()

            Using ms As New MemoryStream
                ' Save bmp1 into memory...
                bmp1.Save(ms, Imaging.ImageFormat.Png)
                ' ...and set, to the image control on the
                ' aspx page, the memory file in base64 string format:
                cImg.Src = "data:image/png;base64," + Convert.ToBase64String(ms.ToArray)
            End Using

            ' Release resources:
            gr1.Dispose()
            bmp1.Dispose()
        Catch ex As Exception
            Throw ex
            'lblMessage.Text = sErrMsg
        End Try
    End Sub
    Sub mouseeventInit(bmpW As Int32, bmpH As Int32)
        Try
            'If Not Page.IsPostBack Then
            '    Exit Sub
            'End If
            cImg.Attributes.Add("onmousemove", "coord(event,this);")

            ' Set Xm,Xb,Ym,Yb for mouseover event:
            Dim m As Double = (max - min) / bmpH
            Ym.Value = m.ToString(MathGlobal8.us)
            Yb.Value = ((max + min + m * bmpH) / 2.0).ToString(MathGlobal8.us)
            Ymargin.Value = (marginPt0.Y * bmpH / h).ToString(MathGlobal8.us)
            m = (vDbl(1) - vDbl(0)) / bmpW
            Xm.Value = m.ToString(MathGlobal8.us)
            Xb.Value = ((vDbl(1) + vDbl(0) - m * bmpW) / 2.0).ToString(MathGlobal8.us)
            Xmargin.Value = (marginPt1.X).ToString(MathGlobal8.us)
            Xmin.Value = min '.ToString(MathGlobal8.us)
        Catch ex As Exception
            Throw ex
        End Try
    End Sub
    Function validateInputs() As Boolean
        Dim mP As New matrixParser
        Try
            ' Axis' X values will be in the
            ' interval [vDbl(0), vDbl(1)]

            ' Verify tbLeft -- tbRight
            ' ------------------------
            ' eval eventual arithmetic (for ex. 2/3) ...
            If tbLeft.Text = "" Then tbLeft.Text = "-4"
            If tbRight.Text = "" Then tbRight.Text = "4"
            If tbTop.Text = "" Then tbLeft.Text = "4"
            If tbBottom.Text = "" Then tbLeft.Text = "-4"
            mP.parse(tbLeft.Text)
            ' ...but must reduce to a double value:
            vDbl(0) = mP.retCjo(0).pRe.ToDouble

            mP.parse(tbRight.Text)
            vDbl(1) = mP.retCjo(0).pRe.ToDouble
            If vDbl(1) < vDbl(0) Then
                ' If left < right, swap values:
                Dim dbl As Double = vDbl(0)
                vDbl(0) = vDbl(1)
                vDbl(1) = dbl
            ElseIf vDbl(0) = vDbl(1) Then
                Return False
            End If
            If vDbl(1) - vDbl(0) <= 1000 * Double.MinValue Then
                Return False
            End If

            If chkAutoTopBottom.Checked = False Then
                ' Axis' Y values will be in the
                ' interval [vDbl(2), vDbl(3)]:
                ' values outside these bounds 
                ' will not be graphed.

                ' If not auto-Top-Bottom checked, consider
                ' inputs in textboxes tbTop, tbBottom.

                ' Verify tbTop -- tbBottom
                ' ------------------------
                mP.parse(tbTop.Text)
                vDbl(3) = mP.retCjo(0).pRe.ToDouble
                mP.parse(tbBottom.Text)
                vDbl(2) = mP.retCjo(0).pRe.ToDouble
                If vDbl(2) < vDbl(3) Then
                    ' If top < bottom, swap values:
                    Dim dbl As Double = vDbl(2)
                    vDbl(2) = vDbl(3)
                    vDbl(3) = dbl
                ElseIf vDbl(2) = vDbl(3) Then
                    Return False
                End If
                If vDbl(2) - vDbl(3) <= 1000 * Double.MinValue Then
                    Return False
                End If
            Else
                ' If auto-Top-Bottom checked
                ' allow any double value:
                vDbl(2) = Double.MaxValue
                vDbl(3) = -Double.MaxValue
            End If
        Catch ex As Exception
            Throw ex
            'Return False
        End Try
        Return True
    End Function
    Private Sub getvMtxP_and_vPoly(sFn() As String)
        Try
            For i As Int32 = 0 To nFn - 1
                If sFn(i) IsNot Nothing AndAlso _
                sFn(i).Length Then
                    vMtxParser(i) = New matrixParser()
                    vMtxParser(i).parse(sFn(i), "", oVars(i))
                    If oVars(i).length <= 1 Then
                        ' Find out if sFn is a Polynomial expression
                        ' because, if so, evaluation will be less 
                        ' time consuming:
                        If vMtxParser(i).ret.exprMtx.IsPolynomial Then
                            vIsPoly(i) = True
                            vPoly(i) = vMtxParser(i).ret.curExpr.getPolynomial
                        End If
                    Else
                        ' more than 1 variable, discard:
                        'vIsEmptyStr(i) = True
                        lblMessage.Text = "<span style=""color:black"">n/a: more than one variable {"
                        For nV As Int32 = 0 To oVars(i).length - 1
                            lblMessage.Text += oVars(i).getVarNameByID(nV)
                            If nV < oVars(i).length - 1 Then
                                lblMessage.Text += ","
                            Else
                                lblMessage.Text += "}"
                            End If
                        Next
                        lblMessage.Text += " in function " + sFn(i)
                        lblMessage.Text += " <br />Tip: for ex. enter x^2-1, do NOT enter the definition" + _
                            " <span style=""color:red"">f(x)=</span>x^2-1</span>"
                        Throw New Exception(lblMessage.Text)
                    End If
                Else
                    vIsEmptyStr(i) = True
                End If

            Next
        Catch ex As Exception
            Throw ex
        End Try
    End Sub
    Private Sub drawStrings(ByRef gr As Graphics) ' Get graph's strings
        Try
            Dim iv As Int32 = 0
            Dim incrV As Double = (max - min) / nDiv
            Dim incrH As Double = (vDbl(1) - vDbl(0)) / nDiv
            Dim dist As Double = origH / nDiv
            Dim fntStr As New Font("Calibri", 10)

            Dim ptImg As New Point(100, 30)

            Dim oldsX(10) As String
            Dim Xdec(10) As Int32
            Dim oldsY(10) As String
            Dim Ydec(10) As Int32
            Dim nDec As Int32 = 3
            Dim maxDec As Int32 = 9
            Dim curPos As Single = 0
repite:
            Dim Vert As Double = max
            Dim Horiz As Double = vDbl(0)
            For row = 0 To 10
                ' Left side strings:
                Dim sX As String = ""
                If Vert < 100 AndAlso Xdec(row) < 2 Then
                    Xdec(row) = 2
                ElseIf Vert < 10 AndAlso Xdec(row) < 3 Then
                    Xdec(row) = 3
                End If
                If Math.Abs(Vert) > 10 ^ 5 Then
                    If Xdec(row) < 2 Then Xdec(row) = 2
                    sX = Vert.ToString("g" + Xdec(row).ToString, MathGlobal8.us)
                Else
                    sX = Math.Round(Vert, Xdec(row)).ToString(MathGlobal8.us)
                End If
                For i As Int32 = 0 To row - 1
                    If oldsX(i) = sX Then
                        If Xdec(row) < maxDec Then
                            Xdec(i) += 1
                            Xdec(row) += 1
                            GoTo repite
                        End If
                    End If
                Next
                oldsX(row) = sX
                Vert = max - incrV * (row + 1)

                ' Strings at the top:
                Dim sY As String = ""
                If Horiz < 100 AndAlso Ydec(row) < 2 Then
                    Ydec(row) = 2
                ElseIf Horiz < 10 AndAlso Ydec(row) < 3 Then
                    Ydec(row) = 3
                End If
                If Math.Abs(Horiz) > 10 ^ 5 Then
                    If Ydec(row) < 2 Then Ydec(row) = 2
                    sY = Horiz.ToString("g" + Ydec(row).ToString, MathGlobal8.us)
                Else
                    sY = Math.Round(Horiz, Ydec(row)).ToString(MathGlobal8.us)
                End If
                For i As Int32 = 0 To row - 1
                    If oldsY(i) = sY Then
                        If Ydec(row) < maxDec Then
                            Ydec(i) += 1
                            Ydec(row) += 1
                            GoTo repite
                        End If
                    End If
                Next
                oldsY(row) = sY
                Horiz = vDbl(0) + incrH * (row + 1)
            Next
            For row = 0 To 10
                Dim s As SizeF = gr.MeasureString(oldsX(row), fntStr)
                gr.DrawString(oldsX(row), fntStr, _
                               Brushes.Black, _
                               New Point(ptImg.X - s.Width - 3, _
                                         ptImg.Y + s.Height / 2 + dist * row))

                s = gr.MeasureString(oldsY(row), fntStr)
                gr.DrawString(oldsY(row), fntStr, _
                               Brushes.Black, _
                               New Point(ptImg.X - s.Width / 2 - 1 + dist * row, _
                                         ptImg.Y - 2))
            Next
            gr.ScaleTransform(origW / w, _
                              origH / (max - min), MatrixOrder.Append)
            gr.ResetTransform()
        Catch ex As Exception
            Throw ex
        End Try
    End Sub
    Function evalFnToGraphicsPath(iFn As Int32, x1 As Double, x2 As Double, nPts As Int32) As PointF()()
        Dim pts(0)() As PointF, iP0, iP1 As Int32
        Try
            Dim xStep As Single = (x2 - x1) / nPts
            Dim x As Single = x1
            Dim y As Double
            Dim i As Int32
            ReDim pts(0)(nPts)

            Dim bClosed As Boolean = False
            Dim bExclude As Boolean = False
            Dim PaZeros(-1) As Double
            Dim nZeros As Int32 = 0
            Dim iCurZero As Int32 = 0
            Dim DenP As Polynomial = Nothing
            Dim curPt As New PointF
            Dim oldPt0, oldPt1 As PointF
            Dim diff As Double = Double.MaxValue
            Dim cjo As Complex
            Dim expr As Expression = vMtxParser(iFn).ret.exprMtx.getExpr(0, 0)
            Dim Pa As Polynomial = vPoly(iFn)
            Do
                x = xStep * CSng(i)
                ' Try-catch in case of for ex. singular points:
                Try
                    If vIsPoly(iFn) Then
                        ' Evaluate Pa(x+x1):
                        y = Pa.evalPrecis(New Precis(x + x1)).ToDouble
                    Else
                        cjo = expr.eval_1var_DblToCjo(x + x1)
                        If cjo IsNot Nothing Then
                            If cjo.pIm.IsZero Then
                                y = cjo.pRe.ToDouble
                            Else
                                bExclude = True
                                iComplexPts += 1
                            End If
                        Else
                            bExclude = True
                        End If
                    End If
                Catch ex As Exception
                    bExclude = True
                End Try
                If Not bExclude AndAlso _
                (vDbl(3) > y OrElse vDbl(2) < y) Then
                    bExclude = True
                End If
                If iP1 > 2 AndAlso Not bExclude AndAlso _
                vDbl(3) <= y AndAlso y <= vDbl(2) Then
                    ' Get the slope of line oldPt0-oldPt1:
                    Dim m1 As Single = (oldPt1.Y - oldPt0.Y) / 1
                    ' ...and of line oldPt1-(x,y):
                    Dim m2 As Single = (y - oldPt1.Y) / 1
                    Dim atg As Double = Math.Abs(Math.PI / 2 - Math.Abs(Math.Atan2(m1, m2)))
                    'If atg < diff Then
                    '    diff = atg
                    '    lblMessage.Text = diff.ToString(MathGlobal8.us)
                    'End If
                    If Math.Sign(m1) <> Math.Sign(m2) AndAlso _
                    Math.Abs(m1) > 10 AndAlso Math.Abs(m2) > 10 AndAlso _
                    atg < 1.6 Then
                        bExclude = True
                    End If
                End If
                If iP1 Then
                    oldPt1.X = pts(iP0)(iP1 - 1).X
                    oldPt1.Y = pts(iP0)(iP1 - 1).Y
                    If iP1 > 1 Then
                        oldPt0.X = pts(iP0)(iP1 - 2).X
                        oldPt0.Y = pts(iP0)(iP1 - 2).Y
                    End If
                End If
                If bExclude OrElse Double.IsInfinity(y) _
                OrElse Double.IsNaN(y) Then
                    If Double.IsInfinity(y) OrElse _
                    Double.IsNaN(y) Then
                        iOutOfRange += 1
                    End If
                    ' 'y' value out of bounds 
                    If Not bClosed Then
                        If iP1 Then
                            ReDim Preserve pts(iP0)(iP1 - 1)
                            iP0 += 1
                            ReDim Preserve pts(iP0), pts(iP0)(nPts - 1)
                            iP1 = 0
                        End If
                    End If
                    bExclude = False
                Else
                    pts(iP0)(iP1).X = i
                    pts(iP0)(iP1).Y = y
                    iP1 += 1
                    min = Math.Min(min, y)
                    max = Math.Max(max, y)
                    bClosed = False
                End If
                i += 1
            Loop While i <= nPts
            If iP1 Then
                ReDim Preserve pts(iP0)(iP1 - 1)
            ElseIf iP0 Then
                ReDim Preserve pts(iP0 - 1)
            Else
                ReDim Preserve pts(-1)
            End If

        Catch ex As Exception
            Throw ex
        End Try
        Return pts
    End Function

End Class

In a recent fix Line #137 has been replaced by:

            If Me.chkAutoTopBottom.Checked Then
                max = max2 : min = min2
            Else
                max = vDbl(2) : min = vDbl(3)
            End If

and, in mouseEventInit() method - line #226 -, Ymargin.value by:

            Ymargin.Value = ((marginPt0.Y + marginPt1.Y) / 2.0 * bmpH / h).ToString(MathGlobal8.us)

In order to improve the messages, lines 171 through 174:

 If max = min Then
   lblMessage.Text = "n/a: top and bottom values can't be equal or void."
   Throw New Exception(lblMessage.Text)
 End If

may be replaced by:

            If max = min Then
                If vDbl(2) = vDbl(3) Then
                    lblMessage.Text = "n/a: top and bottom values can't be equal or void."
                Else
                    lblMessage.Text = iComplexPts.ToString + " complex points couldn't be drawn."
                End If
                Throw New Exception(lblMessage.Text)
            End If

Also, depending on the criteria one follows for functions having complex values, lines 455-476:

              cjo = expr.eval_1var_DblToCjo(x + x1)
              If cjo IsNot Nothing Then
                  If cjo.pIm.IsZero Then
                       y = cjo.pRe.ToDouble
                  Else
                       bExclude = True
                       iComplexPts += 1
                  End If
              Else
                  bExclude = True
              End If

may be replaced by:

                        cjo = expr.eval_1var_DblToCjo(x + x1)
                        If cjo IsNot Nothing Then
                            y = cjo.pRe.ToDouble
                            Dim dbIm As Double = cjo.pIm.ToDouble
                            If (Not cjo.pRe.IsZero AndAlso _
                            Math.Abs(cjo.pIm.ToDouble / cjo.pRe.ToDouble) > 10 ^ -8) OrElse _
                           (cjo.pRe.IsZero AndAlso Not cjo.pIm.IsZero) Then
                                bExclude = True
                                iComplexPts += 1
                            End If
                        Else
                            bExclude = True
                        End If