Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
MGraphing2009 - Graph.vb

Graph.vb

Caricato da: Totem
Scarica il programma completo

  1. Imports System.CodeDom
  2. Imports System.CodeDom.Compiler
  3. Imports System.Reflection
  4. Imports System.ComponentModel
  5.  
  6. Public Class IntervalConverter
  7.     Inherits ExpandableObjectConverter
  8.  
  9.     Public Shared DefaultConverter As New IntervalConverter()
  10.  
  11.     Public Overrides Function CanConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal sourceType As System.Type) As Boolean
  12.         Return (sourceType Is GetType(String))
  13.     End Function
  14.  
  15.     Public Overrides Function CanConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal destinationType As System.Type) As Boolean
  16.         Return (destinationType Is GetType(Interval))
  17.     End Function
  18.  
  19.     Public Overrides Function ConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object) As Object
  20.         If TypeOf value Is String Then
  21.             Dim Str As String = value
  22.             Dim Bounds() As String = Str.Split(",")
  23.  
  24.             If Bounds.Length < 2 Then
  25.                 Return Nothing
  26.             End If
  27.  
  28.             Dim Result As Interval
  29.             Dim LowerStr As String = Bounds(0).Trim().ToLower()
  30.             Dim UpperStr As String = Bounds(1).Trim().ToLower()
  31.  
  32.             If LowerStr = "-infinity" Or LowerStr = "-infinito" Or LowerStr = "negativeinfinity" Then
  33.                 Result.LowerBound = Double.NegativeInfinity
  34.             Else
  35.                 Result.LowerBound = CType(Bounds(0).Trim, Double)
  36.             End If
  37.  
  38.             If UpperStr = "+infinity" Or LowerStr = "+infinito" Or UpperStr = "positiveinfinity" Then
  39.                 Result.UpperBound = Double.PositiveInfinity
  40.             Else
  41.                 Result.UpperBound = CType(Bounds(1).Trim, Double)
  42.             End If
  43.  
  44.             Return Result
  45.         End If
  46.             Return MyBase.ConvertFrom(context, culture, value)
  47.     End Function
  48.  
  49.     Public Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object
  50.         If TypeOf value Is Interval Then
  51.             Dim Int As Interval = value
  52.             Return String.Format("{0}, {1}", Int.LowerBound, Int.UpperBound)
  53.         End If
  54.         Return MyBase.ConvertTo(context, culture, value, destinationType)
  55.     End Function
  56.  
  57. End Class
  58.  
  59. Public Structure Interval
  60.     Public Shared ReadOnly R As New Interval(Double.NegativeInfinity, Double.PositiveInfinity)
  61.  
  62.     Private _LowerBound As Double
  63.     Private _UpperBound As Double
  64.  
  65.     <Browsable(True), _
  66.     DisplayName("Estremo inferiore")> _
  67.     Public Property LowerBound() As Double
  68.         Get
  69.             Return _LowerBound
  70.         End Get
  71.         Set(ByVal value As Double)
  72.             _LowerBound = value
  73.         End Set
  74.     End Property
  75.  
  76.     <Browsable(True), _
  77.     DisplayName("Estremo superiore")> _
  78.     Public Property UpperBound() As Double
  79.         Get
  80.             Return _UpperBound
  81.         End Get
  82.         Set(ByVal value As Double)
  83.             _UpperBound = value
  84.         End Set
  85.     End Property
  86.  
  87.     <Browsable(False)> _
  88.     Public ReadOnly Property Length() As Double
  89.         Get
  90.             Return Me.UpperBound - Me.LowerBound
  91.         End Get
  92.     End Property
  93.  
  94.     Sub New(ByVal LowerBound As Double, ByVal UpperBound As Double)
  95.         Me.LowerBound = LowerBound
  96.         Me.UpperBound = UpperBound
  97.     End Sub
  98.  
  99.     Public Function IsXIncluded(ByVal X As Double) As Boolean
  100.         Return (X >= Me.LowerBound) And (X <= Me.UpperBound)
  101.     End Function
  102.  
  103.     Public Function Intersects(ByVal I As Interval)
  104.         If Me.LowerBound = I.LowerBound Or Me.LowerBound = I.UpperBound Or _
  105.            Me.UpperBound = I.LowerBound Or Me.UpperBound = I.UpperBound Then
  106.             Return True
  107.         End If
  108.         If ((Me.LowerBound > I.LowerBound) And Not (Me.LowerBound > I.UpperBound)) Or _
  109.            ((Me.UpperBound < I.UpperBound) And Not (Me.UpperBound < I.LowerBound)) Then
  110.             Return True
  111.         Else
  112.             Return False
  113.         End If
  114.     End Function
  115.  
  116.     Public Shared Function Union(ByVal I1 As Interval, ByVal I2 As Interval) As Interval?
  117.         If Not I1.Intersects(I2) Then
  118.             Return Nothing
  119.         End If
  120.  
  121.         Dim Result As Interval
  122.  
  123.         Result.LowerBound = Math.Min(I1.LowerBound, I2.LowerBound)
  124.         Result.UpperBound = Math.Max(I1.UpperBound, I2.UpperBound)
  125.  
  126.         Return Result
  127.     End Function
  128.  
  129.     Public Shared Operator =(ByVal I1 As Interval, ByVal I2 As Interval) As Boolean
  130.         Return (I1.LowerBound = I2.LowerBound) And (I1.UpperBound = I2.UpperBound)
  131.     End Operator
  132.  
  133.     Public Shared Operator <>(ByVal I1 As Interval, ByVal I2 As Interval) As Boolean
  134.         Return Not (I1 = I2)
  135.     End Operator
  136.  
  137. End Structure
  138.  
  139. Class IntervalComparer
  140.     Implements IComparer(Of Interval)
  141.  
  142.     Public Function Compare(ByVal x As Interval, ByVal y As Interval) As Integer Implements System.Collections.Generic.IComparer(Of Interval).Compare
  143.         If x = y Then
  144.             Return 0
  145.         Else
  146.             If x.LowerBound > y.UpperBound Then
  147.                 Return 1
  148.             ElseIf y.LowerBound > x.UpperBound Then
  149.                 Return -1
  150.             End If
  151.         End If
  152.     End Function
  153.  
  154. End Class
  155.  
  156. Public Class FunctionDomain
  157.     Inherits List(Of Interval)
  158.  
  159.     Private Shared DefaultComparer As New IntervalComparer()
  160.  
  161.     Public Function IsInDomain(ByVal X As Double) As Boolean
  162.         If Me.Count = 0 Then
  163.             Return True
  164.         End If
  165.  
  166.         Dim Result As Boolean = False
  167.  
  168.         For Each I As Interval In Me
  169.             Result = Result Or I.IsXIncluded(X)
  170.         Next
  171.  
  172.         Return Result
  173.     End Function
  174.  
  175.     Public Function IsR() As Boolean
  176.         Return (Me.Count = 0) OrElse (Me.Count = 1 And Me(0) = Interval.R)
  177.     End Function
  178.  
  179.     Public Shadows Sub Add(ByVal item As Interval)
  180.         For I As Int16 = 0 To Me.Count - 1
  181.             If Me(I).Intersects(item) Then
  182.                 Me(I) = Interval.Union(Me(I), item)
  183.                 Exit Sub
  184.             End If
  185.         Next
  186.  
  187.         MyBase.Add(item)
  188.     End Sub
  189.  
  190.     Public Function GetUndefinedIntervals(ByVal MainInterval As Interval) As Interval()
  191.         If Me.Count = 0 Then
  192.             Return New Interval() {}
  193.         End If
  194.  
  195.         Me.Sort(DefaultComparer)
  196.  
  197.         Dim Lower As Double = MainInterval.LowerBound
  198.         Dim Result As New List(Of Interval)
  199.         Dim Temp As Interval
  200.  
  201.         For Each I As Interval In Me
  202.             If I.LowerBound > Lower Then
  203.                 Temp = New Interval(Lower, I.LowerBound)
  204.                 Result.Add(Temp)
  205.             End If
  206.             Lower = I.UpperBound
  207.         Next
  208.  
  209.         If MainInterval.UpperBound > Lower Then
  210.             Temp = New Interval(Lower, MainInterval.UpperBound)
  211.             Result.Add(Temp)
  212.         End If
  213.  
  214.         Return Result.ToArray()
  215.     End Function
  216.  
  217. End Class
  218.  
  219. Public Class [Function]
  220.  
  221.     Public Enum RelationType
  222.         GraterThan
  223.         Equals
  224.         LessThan
  225.     End Enum
  226.  
  227.     Private _Color As Color
  228.     Private _Expression As String
  229.     Private _RawExpression As String
  230.     Private _Type As RelationType
  231.     Private _Domain As FunctionDomain
  232.     Private _Name As String
  233.  
  234.     Private Evaluator As Object
  235.     Public EvaluateFunction As MethodInfo
  236.  
  237.     Public Property Color() As Color
  238.         Get
  239.             Return _Color
  240.         End Get
  241.         Set(ByVal value As Color)
  242.             _Color = value
  243.         End Set
  244.     End Property
  245.  
  246.     Public Property Expression() As String
  247.         Get
  248.             Return _Expression
  249.         End Get
  250.         Set(ByVal value As String)
  251.             _Expression = value
  252.             Me.CreateEvaluator()
  253.         End Set
  254.     End Property
  255.  
  256.     Public Property RawExpression() As String
  257.         Get
  258.             Return _RawExpression
  259.         End Get
  260.         Set(ByVal value As String)
  261.             _RawExpression = value
  262.         End Set
  263.     End Property
  264.  
  265.     Public Property Type() As RelationType
  266.         Get
  267.             Return _Type
  268.         End Get
  269.         Set(ByVal value As RelationType)
  270.             _Type = value
  271.         End Set
  272.     End Property
  273.  
  274.     Public Property Name() As String
  275.         Get
  276.             Return _Name
  277.         End Get
  278.         Set(ByVal value As String)
  279.             _Name = value
  280.         End Set
  281.     End Property
  282.  
  283.     Public ReadOnly Property Domain() As FunctionDomain
  284.         Get
  285.             Return _Domain
  286.         End Get
  287.     End Property
  288.  
  289.  
  290.     Sub New()
  291.         _Domain = New FunctionDomain
  292.         Me.Color = Drawing.Color.Black
  293.         Me.Expression = "Return x"
  294.         Me.Type = RelationType.Equals
  295.     End Sub
  296.  
  297.     Sub New(ByVal Type As RelationType, ByVal Expression As String)
  298.         _Domain = New FunctionDomain
  299.         Me.Color = Drawing.Color.Black
  300.         Me.Expression = Expression
  301.         Me.Type = Type
  302.     End Sub
  303.  
  304.     Private Sub CreateEvaluator()
  305.         Dim Code As String = String.Format(My.Resources.EvaluatorCode, Me.Expression)
  306.  
  307.         Dim Parameters As New CodeDom.Compiler.CompilerParameters
  308.         With Parameters
  309.             .GenerateExecutable = False
  310.  
  311.             .TreatWarningsAsErrors = True
  312.             .TempFiles.KeepFiles = False
  313.             .GenerateInMemory = True
  314.  
  315.             .ReferencedAssemblies.Add("Microsoft.VisualBasic.dll")
  316.             .ReferencedAssemblies.Add("System.dll")
  317.         End With
  318.  
  319.         Dim Provider As New VBCodeProvider
  320.         Dim CompResults As CompilerResults = Provider.CompileAssemblyFromSource(Parameters, Code)
  321.  
  322.         If CompResults.Errors.Count > 0 Then
  323.             Throw New FormatException("Espressione non valida!")
  324.         Else
  325.             Dim Asm As Reflection.Assembly = CompResults.CompiledAssembly
  326.             Me.Evaluator = Asm.CreateInstance("Evaluator")
  327.             Me.EvaluateFunction = Evaluator.GetType.GetMethod("Evaluate")
  328.         End If
  329.     End Sub
  330.  
  331.     Public Sub ValidateExpression()
  332.         Dim Reader As New IO.StringReader(Me.RawExpression)
  333.         Dim Parts As New Dictionary(Of String, String)
  334.         Dim Line, LineParts() As String
  335.         Dim Result As New System.Text.StringBuilder
  336.  
  337.         Do
  338.             Line = Reader.ReadLine()
  339.             LineParts = Line.Split(":")
  340.  
  341.             If LineParts.Count < 2 Then
  342.                 Continue Do
  343.             End If
  344.  
  345.             Parts.Add(LineParts(0).Trim(), LineParts(1).Trim())
  346.             If LineParts(0).Contains("allx") Then
  347.                 Exit Do
  348.             End If
  349.         Loop While Reader.Peek > -1
  350.         Reader.Close()
  351.         Reader = Nothing
  352.         Line = Nothing
  353.         LineParts = Nothing
  354.  
  355.         If Parts.ContainsKey("allx") Then
  356.             Result.AppendFormat("Return {0}", Parts("allx"))
  357.         Else
  358.             For Each Condition As String In Parts.Keys
  359.                 Result.AppendFormat("If {0} Then : Return {1} : End If{2}", _
  360.                     Condition, Parts(Condition), Environment.NewLine)
  361.             Next
  362.         End If
  363.  
  364.         Me.Expression = Result.ToString()
  365.         Parts.Clear()
  366.         Parts = Nothing
  367.         Result = Nothing
  368.     End Sub
  369.  
  370.     Public Function Apply(ByVal X As Double) As Double
  371.         Return EvaluateFunction.Invoke(Nothing, New Object() {X})
  372.     End Function
  373.  
  374.     Public Function FindZero(ByVal IntervalLowerBound As Double, ByVal IntervalUpperBound As Double, ByVal Epsilon As Double) As Double?
  375.         Dim a, b, c As Double
  376.         Dim fa, fb, fc As Double
  377.         Dim Result, LastEpsilon As Double
  378.  
  379.         a = IntervalLowerBound
  380.         b = IntervalUpperBound
  381.  
  382.         If Me.Apply(a) * Me.Apply(b) > 0 Then
  383.             Return Nothing
  384.         End If
  385.  
  386.         Do
  387.             c = (a + b) / 2
  388.             fa = Me.Apply(a)
  389.             fb = Me.Apply(b)
  390.             fc = Me.Apply(c)
  391.  
  392.             If fa = 0 Then
  393.                 c = a
  394.                 Exit Do
  395.             End If
  396.             If fb = 0 Then
  397.                 c = b
  398.                 Exit Do
  399.             End If
  400.             If fc = 0 Then
  401.                 Exit Do
  402.             End If
  403.  
  404.             If fa * fc < 0 Then
  405.                 b = c
  406.             Else
  407.                 a = c
  408.             End If
  409.  
  410.             If Math.Abs(a - b) = LastEpsilon Then
  411.                 Exit Do
  412.             End If
  413.             LastEpsilon = Math.Abs(a - b)
  414.         Loop Until Math.Abs(a - b) < Epsilon
  415.  
  416.         Result = c
  417.  
  418.         Return Result
  419.     End Function
  420.  
  421.     Public Overrides Function ToString() As String
  422.         Return String.Format("{0}(x)", Me.Name)
  423.     End Function
  424.  
  425. End Class
  426.  
  427. Public Class GraphCreator
  428.     Private _BackColor, _AxisColor, _GridColor As Color
  429.     Private _AxisThickness, _GridThickness, _FunctionThickness As Single
  430.     Private _XExtension, _YExtension As Interval
  431.     Private _XIncrement, _YIncrement As Double
  432.     Private _DrawValues, _DrawNonDefinitionIntervals As Boolean
  433.     Private _ValueDecimalPlaces As Int16
  434.     Private _Functions As List(Of [Function])
  435.     Private _OutputSize As Size
  436.     Private _Font As Font
  437.     Private _PixelSpan As Int16 = 2
  438.  
  439.     <Browsable(True), _
  440.     DisplayName("Colore sfondo"), _
  441.     Description("Imposta il colore di sfondo del grafico.")> _
  442.     Public Property BackColor() As Color
  443.         Get
  444.             Return _BackColor
  445.         End Get
  446.         Set(ByVal Value As Color)
  447.             _BackColor = Value
  448.         End Set
  449.     End Property
  450.  
  451.     <Browsable(True), _
  452.     DisplayName("Colore assi"), _
  453.     Description("Imposta il colore degli assi cartesiani.")> _
  454.     Public Property AxisColor() As Color
  455.         Get
  456.             Return _AxisColor
  457.         End Get
  458.         Set(ByVal Value As Color)
  459.             _AxisColor = Value
  460.         End Set
  461.     End Property
  462.  
  463.     <Browsable(True), _
  464.     DisplayName("Colore griglia"), _
  465.     Description("Imposta il colore della griglia.")> _
  466.     Public Property GridColor() As Color
  467.         Get
  468.             Return _GridColor
  469.         End Get
  470.         Set(ByVal Value As Color)
  471.             _GridColor = Value
  472.         End Set
  473.     End Property
  474.  
  475.     <Browsable(True), _
  476.     DisplayName("Spessore assi"), _
  477.     Description("Imposta lo spessore degli assi cartesiani.")> _
  478.     Public Property AxisThickness() As Single
  479.         Get
  480.             Return _AxisThickness
  481.         End Get
  482.         Set(ByVal Value As Single)
  483.             _AxisThickness = Value
  484.         End Set
  485.     End Property
  486.  
  487.     <Browsable(True), _
  488.     DisplayName("Spessore griglia"), _
  489.     Description("Imposta lo spessore della griglia.")> _
  490.     Public Property GridThickness() As Single
  491.         Get
  492.             Return _GridThickness
  493.         End Get
  494.         Set(ByVal Value As Single)
  495.             _GridThickness = Value
  496.         End Set
  497.     End Property
  498.  
  499.     <Browsable(True), _
  500.     DisplayName("Spessore funzioni"), _
  501.     Description("Imposta lo spessore della linea con cui vengono disegnate le funzioni.")> _
  502.     Public Property FunctionThickness() As Single
  503.         Get
  504.             Return _FunctionThickness
  505.         End Get
  506.         Set(ByVal value As Single)
  507.             _FunctionThickness = value
  508.         End Set
  509.     End Property
  510.  
  511.     <Browsable(True), _
  512.     DisplayName("Intervallo X"), _
  513.     Description("Imposta l'intervallo di valori che il grafico mostra sull'asse X."), _
  514.     TypeConverter(GetType(IntervalConverter))> _
  515.     Public Property XExtension() As Interval
  516.         Get
  517.             Return _XExtension
  518.         End Get
  519.         Set(ByVal Value As Interval)
  520.             _XExtension = Value
  521.         End Set
  522.     End Property
  523.  
  524.     <Browsable(True), _
  525.     DisplayName("Intervallo Y"), _
  526.     Description("Imposta l'intervallo di valori che il grafico mostra sull'asse Y."), _
  527.     TypeConverter(GetType(IntervalConverter))> _
  528.     Public Property YExtension() As Interval
  529.         Get
  530.             Return _YExtension
  531.         End Get
  532.         Set(ByVal Value As Interval)
  533.             _YExtension = Value
  534.         End Set
  535.     End Property
  536.  
  537.     <Browsable(True), _
  538.     DisplayName("Griglia X"), _
  539.     Description("Indica ogni quanto disegnare la griglia verticale e i valori sull'asse X.")> _
  540.     Public Property XIncrement() As Double
  541.         Get
  542.             Return _XIncrement
  543.         End Get
  544.         Set(ByVal Value As Double)
  545.             _XIncrement = Value
  546.         End Set
  547.     End Property
  548.  
  549.     <Browsable(True), _
  550.     DisplayName("Griglia Y"), _
  551.     Description("Indica ogni quanto disegnare la griglia orizzontale e i valori sull'asse Y.")> _
  552.     Public Property YIncrement() As Double
  553.         Get
  554.             Return _YIncrement
  555.         End Get
  556.         Set(ByVal Value As Double)
  557.             _YIncrement = Value
  558.         End Set
  559.     End Property
  560.  
  561.     <Browsable(True), _
  562.     DisplayName("Valori"), _
  563.     Description("Indica se disegnare i valori sugli assi.")> _
  564.     Public Property DrawValues() As Boolean
  565.         Get
  566.             Return _DrawValues
  567.         End Get
  568.         Set(ByVal Value As Boolean)
  569.             _DrawValues = Value
  570.         End Set
  571.     End Property
  572.  
  573.     <Browsable(True), _
  574.     DisplayName("Limitazioni"), _
  575.     Description("Determina se tratteggiare le zone del grafico in cui la funzione non è definita.")> _
  576.     Public Property DrawNonDefinitionIntervals() As Boolean
  577.         Get
  578.             Return _DrawNonDefinitionIntervals
  579.         End Get
  580.         Set(ByVal value As Boolean)
  581.             _DrawNonDefinitionIntervals = value
  582.         End Set
  583.     End Property
  584.  
  585.     <Browsable(True), _
  586.     DisplayName("Cifre decimali"), _
  587.     Description("Imposta il numero di cifre decimali visualizzate dai valori sugli assi.")> _
  588.     Public Property ValueDecimalPlaces() As Int16
  589.         Get
  590.             Return _ValueDecimalPlaces
  591.         End Get
  592.         Set(ByVal value As Int16)
  593.             _ValueDecimalPlaces = value
  594.         End Set
  595.     End Property
  596.  
  597.     <Browsable(True), _
  598.     DisplayName("Dimensione grafico"), _
  599.     Description("Imposta le dimensioni del grafico, in pixel.")> _
  600.     Public Property OutputSize() As Size
  601.         Get
  602.             Return _OutputSize
  603.         End Get
  604.         Set(ByVal value As Size)
  605.             _OutputSize = value
  606.         End Set
  607.     End Property
  608.  
  609.     <Browsable(True), _
  610.     DisplayName("Font"), _
  611.     Description("Imposta il font da utilizzare per disegnare i valori e le etichette.")> _
  612.     Public Property Font() As Font
  613.         Get
  614.             Return _Font
  615.         End Get
  616.         Set(ByVal value As Font)
  617.             _Font = value
  618.         End Set
  619.     End Property
  620.  
  621.     <Browsable(True), _
  622.     DisplayName("Precisione"), _
  623.     Description("La funzione viene calcolata per punti, ma il numero di pixel disponibile è limitato. Questo numero indica ogni quanti pixel ricalcolare i valori della funzione.")> _
  624.     Public Property PixelSpan() As Int16
  625.         Get
  626.             Return _PixelSpan
  627.         End Get
  628.         Set(ByVal value As Int16)
  629.             _PixelSpan = value
  630.         End Set
  631.     End Property
  632.  
  633.     <Browsable(False)> _
  634.     Public ReadOnly Property Functions() As List(Of [Function])
  635.         Get
  636.             Return _Functions
  637.         End Get
  638.     End Property
  639.  
  640.     Private ReadOnly Property IsYAxisVisible() As Boolean
  641.         Get
  642.             Return (Me.XExtension.LowerBound <= 0 And Me.XExtension.UpperBound >= 0)
  643.         End Get
  644.     End Property
  645.  
  646.     Private ReadOnly Property IsXAxisVisible() As Boolean
  647.         Get
  648.             Return (Me.YExtension.LowerBound <= 0 And Me.YExtension.UpperBound >= 0)
  649.         End Get
  650.     End Property
  651.  
  652.     Private ReadOnly Property IsOriginVisible() As Boolean
  653.         Get
  654.             Return (Me.IsYAxisVisible) And (Me.IsXAxisVisible)
  655.         End Get
  656.     End Property
  657.  
  658.     Private ReadOnly Property Origin() As Point
  659.         Get
  660.             Return New Point(Me.OutputSize.Width * (0 - Me.XExtension.LowerBound) / Me.XExtension.Length, _
  661.                 CInt(Me.OutputSize.Height * (Me.YExtension.UpperBound - 0) / Me.YExtension.Length))
  662.         End Get
  663.     End Property
  664.  
  665.  
  666.     Sub New()
  667.         Me.BackColor = Color.White
  668.         Me.AxisColor = Color.Black
  669.         Me.GridColor = Color.Gainsboro
  670.  
  671.         Me.AxisThickness = 1
  672.         Me.GridThickness = 1
  673.         Me.FunctionThickness = 1
  674.  
  675.         Me.XExtension = New Interval(-20, 20)
  676.         Me.YExtension = New Interval(-15, 15)
  677.         Me.XIncrement = 1
  678.         Me.YIncrement = 1
  679.  
  680.         Me.OutputSize = New Size(800, 600)
  681.  
  682.         Me.Font = New Font("Microsoft Sans Serif", 12, FontStyle.Regular)
  683.  
  684.         _Functions = New List(Of [Function])
  685.     End Sub
  686.  
  687.     Public Function CreateGraph() As Bitmap
  688.         Dim Result As New Bitmap(Me.OutputSize.Width, Me.OutputSize.Height)
  689.         Dim G As Graphics = Graphics.FromImage(Result)
  690.  
  691.         Dim GridPen As New Pen(Me.GridColor, Me.GridThickness)
  692.         Dim AxisPen As New Pen(Me.AxisColor, Me.AxisThickness)
  693.         Dim AxisBrush As New SolidBrush(Me.AxisColor)
  694.         Dim O As Point
  695.  
  696.         O = Me.Origin
  697.  
  698.         G.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
  699.  
  700.         G.Clear(Me.BackColor)
  701.  
  702.         'Griglia verticale
  703.         Dim Px As Int32
  704.         For Ix As Double = Me.XExtension.LowerBound To Me.XExtension.UpperBound Step Me.XIncrement
  705.             Px = CInt(Me.OutputSize.Width * (Ix - Me.XExtension.LowerBound) / Me.XExtension.Length)
  706.             G.DrawLine(GridPen, Px, 0, Px, Me.OutputSize.Height + 1)
  707.             If (Me.DrawValues) And (Me.IsXAxisVisible) Then
  708.                 Dim Val As String = String.Format("{0:N" & Me.ValueDecimalPlaces & "}", Ix)
  709.                 Dim ValSize As SizeF = G.MeasureString(Val, Me.Font)
  710.                 G.DrawLine(AxisPen, Px, O.Y, Px, O.Y + 3)
  711.                 G.DrawString(Val, Me.Font, AxisBrush, Px - ValSize.Width / 2, O.Y + 5)
  712.             End If
  713.         Next
  714.  
  715.         'Griglia orizzontale
  716.         Dim Py As Int32
  717.         For Iy As Double = Me.YExtension.LowerBound To Me.YExtension.UpperBound Step Me.YIncrement
  718.             Py = CInt(Me.OutputSize.Height * (Me.YExtension.UpperBound - Iy) / Me.YExtension.Length)
  719.             G.DrawLine(GridPen, 0, Py, Me.OutputSize.Width + 1, Py)
  720.             If (Me.DrawValues) And (Me.IsYAxisVisible) Then
  721.                 Dim Val As String = String.Format("{0:N" & Me.ValueDecimalPlaces & "}", Iy)
  722.                 Dim ValSize As SizeF = G.MeasureString(Val, Me.Font)
  723.                 G.DrawLine(AxisPen, O.X, Py, O.X - 3, Py)
  724.                 G.DrawString(Val, Me.Font, AxisBrush, O.X - 5 - ValSize.Width, Py - ValSize.Height / 2)
  725.             End If
  726.         Next
  727.  
  728.         'Asse Y
  729.         If Me.IsYAxisVisible Then
  730.             G.DrawLine(AxisPen, O.X, 0, O.X, Me.OutputSize.Height + 1)
  731.         End If
  732.         'Asse X
  733.         If Me.IsXAxisVisible Then
  734.             G.DrawLine(AxisPen, 0, O.Y, Me.OutputSize.Width + 1, O.Y)
  735.         End If
  736.  
  737.         Dim Points As New List(Of Point)
  738.         Dim Y As Double
  739.         Dim XEpsilon As Double = Me.PixelSpan * Me.XExtension.Length / Me.OutputSize.Width
  740.  
  741.         For Each F As [Function] In Me.Functions
  742.             If Me.DrawNonDefinitionIntervals Then
  743.                 For Each I As Interval In F.Domain.GetUndefinedIntervals(Me.XExtension)
  744.                     G.FillRectangle(New Drawing2D.HatchBrush(Drawing2D.HatchStyle.BackwardDiagonal, Color.FromArgb(125, F.Color), Color.Transparent), _
  745.                         CInt(Me.OutputSize.Width * (I.LowerBound - Me.XExtension.LowerBound) / Me.XExtension.Length), _
  746.                         0, CInt(Me.OutputSize.Width * I.Length / Me.XExtension.Length), Me.OutputSize.Height + 1)
  747.                 Next
  748.             End If
  749.  
  750.             For X As Double = Me.XExtension.LowerBound To Me.XExtension.UpperBound Step (Me.PixelSpan * Me.XExtension.Length / Me.OutputSize.Width)
  751.                 Try
  752.                     If Not F.Domain.IsInDomain(X) Then
  753.                         If Points.Count > 0 Then
  754.                             G.DrawCurve(New Pen(F.Color, Me.FunctionThickness), Points.ToArray)
  755.                             Points.Clear()
  756.                         End If
  757.                         Continue For
  758.                     End If
  759.                    
  760.                     Y = F.Apply(X)
  761.                     Points.Add(New Point( _
  762.                         Me.OutputSize.Width * (X - Me.XExtension.LowerBound) / Me.XExtension.Length, _
  763.                         Me.OutputSize.Height * (Me.YExtension.UpperBound - Y) / Me.YExtension.Length))
  764.                 Catch Ex As Exception
  765.                 End Try
  766.             Next
  767.  
  768.             If Points.Count > 0 Then
  769.                 Try
  770.                     G.DrawCurve(New Pen(F.Color, Me.FunctionThickness), Points.ToArray)
  771.                 Catch Ex As Exception
  772.  
  773.                 End Try
  774.  
  775.                 If F.Type = [Function].RelationType.GraterThan Then
  776.                     Dim P As New Drawing2D.GraphicsPath()
  777.                     Points.Add(New Point(Me.OutputSize.Width, 0))
  778.                     Points.Add(New Point(0, 0))
  779.                     P.AddCurve(Points.ToArray)
  780.                     P.CloseFigure()
  781.                     G.FillPath(New SolidBrush(Color.FromArgb(50, F.Color.R, F.Color.G, F.Color.B)), P)
  782.                 End If
  783.  
  784.                 If F.Type = [Function].RelationType.LessThan Then
  785.                     Dim P As New Drawing2D.GraphicsPath()
  786.                     Points.Add(New Point(Me.OutputSize.Width, Me.OutputSize.Height))
  787.                     Points.Add(New Point(0, Me.OutputSize.Height))
  788.                     P.AddCurve(Points.ToArray)
  789.                     P.CloseFigure()
  790.                     G.FillPath(New SolidBrush(Color.FromArgb(50, F.Color.R, F.Color.G, F.Color.B)), P)
  791.                 End If
  792.             End If
  793.  
  794.             Points.Clear()
  795.         Next
  796.  
  797.         Return Result
  798.     End Function
  799. End Class