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
Function Plotter - Drawer.cs

Drawer.cs

Caricato da: Crybot
Scarica il programma completo

  1. using System.Collections.Generic;
  2. using System.Drawing;
  3. using System.Linq;
  4.  
  5. namespace DrawGraph
  6. {
  7.     internal class Drawer
  8.     {
  9.         private const int WheelConstant = 120;
  10.         private const int ZoomMultiplier = 4;
  11.  
  12.         private readonly Pen _axesPen;
  13.         private readonly Color _backColor;
  14.         private readonly List<Function> _currentFunctions;
  15.         private readonly Graph _graph;
  16.  
  17.         public Drawer(Graph graph, Pen graphPen, Pen axesPen, Pen functionPen, Color backColor)
  18.         {
  19.             _graph = graph;
  20.             GraphPen = graphPen;
  21.             FunctionPen = functionPen;
  22.             _axesPen = axesPen;
  23.             _backColor = backColor;
  24.             _currentFunctions = new List<Function>();
  25.             DrawGrid = DrawTicks = DrawAxes = true;
  26.         }
  27.  
  28.         public Drawer(Graph graph)
  29.             : this(graph, new Pen(Brushes.Black, 2), new Pen(Brushes.Black, 2), new Pen(Brushes.Black, 2), Color.White)
  30.         {
  31.         }
  32.  
  33.         public Drawer(Graph graph, Color backColor)
  34.             : this(graph, new Pen(Brushes.Black, 2), new Pen(Brushes.Black, 2), new Pen(Brushes.Black, 2), backColor)
  35.         {
  36.         }
  37.  
  38.         public Drawer(Graph graph, Pen functionPen)
  39.             : this(graph, new Pen(Brushes.Black, 2), new Pen(Brushes.Black, 2), functionPen, Color.White)
  40.         {
  41.         }
  42.  
  43.         public Drawer(Graph graph, Pen functionPen, Color backColor)
  44.             : this(graph, new Pen(Brushes.Black, 2), new Pen(Brushes.Black, 2), functionPen, backColor)
  45.         {
  46.         }
  47.  
  48.         public Pen GraphPen { get; set; }
  49.  
  50.         public Pen FunctionPen { get; set; }
  51.  
  52.         public Graph Graph
  53.         {
  54.             get { return _graph; }
  55.         }
  56.  
  57.         public bool DrawGrid { get; set; }
  58.         public bool DrawTicks { get; set; }
  59.         public bool DrawAxes { get; set; }
  60.  
  61.         private PointF TransformPoint(PointF point)
  62.         {
  63.             //the point (0,0) of the form is the upper left corner, so every graph point needs a conversion
  64.             return new PointF(point.X*Graph.CellSize + Graph.Center.X, -point.Y*Graph.CellSize + Graph.Center.Y);
  65.         }
  66.  
  67.         // draw a single function
  68.         private void DrawFunction(Graphics g, Function f)
  69.         {
  70.             // a list of list of points is required to properly skip imaginary number(e.g sqrt(-1))    
  71.             var pointsList = new List<List<PointF>> {new List<PointF>()};
  72.  
  73.             bool lastNan = false;
  74.             for (float x = -Graph.NumOfCells/2; x < Graph.NumOfCells/2; x += Graph.Step)
  75.                 // from -X border to X border og the graph
  76.             {
  77.                 float y = f.Apply(x); // the y value of x is calculated thanks to reflection
  78.                 PointF point = TransformPoint(new PointF(x, y));
  79.                 // then the point obtained is converted to "real" coordinates
  80.  
  81.                 //when an imaginary number is discovered it creates a new separated list of points to draw
  82.                 //every list of points will be drawn singularly
  83.                 if (double.IsNaN(y))
  84.                 {
  85.                     if (!lastNan) // it creates a new list of points only if the last number wasn't imaginary
  86.                     {
  87.                         pointsList.Add(new List<PointF>());
  88.                         lastNan = true;
  89.                     }
  90.                 }
  91.  
  92.                     // if a point exceeds the borders of the graph his Y components is set to not visible, to prevent overflow.
  93.                 else if (point.Y > Graph.Heigth)
  94.                 {
  95.                     pointsList[pointsList.Count - 1].Add(new PointF(point.X, Graph.Heigth + FunctionPen.Width));
  96.                 }
  97.                 else if (point.Y < 0)
  98.                 {
  99.                     pointsList[pointsList.Count - 1].Add(new PointF(point.X, -FunctionPen.Width));
  100.                 }
  101.                 else
  102.                 {
  103.                     lastNan = false;
  104.                     pointsList[pointsList.Count - 1].Add(point); //
  105.                 }
  106.             }
  107.  
  108.             //draws each list of points only if the list has a number of elements > 1
  109.             foreach (var list in pointsList.Where(list => list.Count > 1))
  110.             {
  111.                 g.DrawLines(FunctionPen, list.ToArray());
  112.             }
  113.         }
  114.  
  115.         public void DrawGraph(Graphics g)
  116.         {
  117.             g.Clear(_backColor);
  118.  
  119.             if (DrawGrid || DrawTicks)
  120.             {
  121.                 for (int i = 0; i <= Graph.NumOfCells; i++)
  122.                 {
  123.                     if (DrawGrid)
  124.                     {
  125.                         //draw grid
  126.                         g.DrawLine(Pens.Gray, i*Graph.CellSize, 0, i*Graph.CellSize, Graph.NumOfCells*Graph.CellSize);
  127.                         g.DrawLine(Pens.Gray, 0, i*Graph.CellSize, Graph.NumOfCells*Graph.CellSize, i*Graph.CellSize);
  128.                     }
  129.  
  130.                     if (DrawTicks)
  131.                     {
  132.                         //draw tick marks
  133.                         g.DrawLine(_axesPen, Graph.Center.X - Graph.TickSize/2, i*Graph.CellSize,
  134.                                    Graph.Center.X + Graph.TickSize/2, i*Graph.CellSize);
  135.                         g.DrawLine(_axesPen, i*Graph.CellSize, Graph.Center.Y - Graph.TickSize/2, i*Graph.CellSize,
  136.                                    Graph.Center.Y + Graph.TickSize/2);
  137.                     }
  138.                 }
  139.             }
  140.             if (DrawAxes)
  141.             {
  142.                 //draw axes
  143.                 g.DrawLine(_axesPen, 0, Graph.Center.Y, Graph.Width, Graph.Center.Y);
  144.                 g.DrawLine(_axesPen, Graph.Center.X, 0, Graph.Center.X, Graph.Heigth);
  145.             }
  146.         }
  147.  
  148.         public void DrawFunctions(Graphics g)
  149.         {
  150.             // draw all the current functions
  151.             foreach (Function f in _currentFunctions)
  152.             {
  153.                 DrawFunction(g, f);
  154.             }
  155.         }
  156.  
  157.         public void Zoom(int delta)
  158.         {
  159.             int value = (delta/WheelConstant)*ZoomMultiplier;
  160.  
  161.             if (Graph.NumOfCells - value <= Graph.MinNumOfCells)
  162.             {
  163.                 Graph.NumOfCells = Graph.MinNumOfCells;
  164.             }
  165.             else if (Graph.NumOfCells - value >= Graph.MaxNumOfCells)
  166.             {
  167.                 Graph.NumOfCells = Graph.MaxNumOfCells;
  168.             }
  169.             else
  170.             {
  171.                 Graph.NumOfCells -= value;
  172.             }
  173.         }
  174.  
  175.         public void AddFunction(Function f)
  176.         {
  177.             _currentFunctions.Add(f);
  178.         }
  179.  
  180.         public void ClearFunctionList()
  181.         {
  182.             if (_currentFunctions.Count > 0)
  183.                 _currentFunctions.Clear();
  184.         }
  185.     }
  186. }