Advertisement
DragonOsman

Graph.cpp

Mar 17th, 2017
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.31 KB | None | 0 0
  1. #include "Graph.h"
  2. #include<map>
  3. #include <iostream>
  4. #include <string>
  5. #include "std_lib_facilities.h"
  6.  
  7. namespace Graph_lib {
  8.  
  9.     void Shape::draw_lines() const
  10.     {
  11.         if (color().visibility() && 1<points.size())    // draw sole pixel?
  12.             for (unsigned int i = 1; i<points.size(); ++i)
  13.                 fl_line(points[i - 1].x, points[i - 1].y, points[i].x, points[i].y);
  14.     }
  15.  
  16.     void Shape::draw() const
  17.     {
  18.         Fl_Color oldc = fl_color();
  19.         // there is no good portable way of retrieving the current style
  20.         fl_color(lcolor.as_int());
  21.         fl_line_style(ls.style(), ls.width());
  22.         draw_lines();
  23.         fl_color(oldc); // reset color (to pevious) and style (to default)
  24.         fl_line_style(0);
  25.     }
  26.  
  27.  
  28.     // does two lines (p1,p2) and (p3,p4) intersect?
  29.     // if se return the distance of the intersect point as distances from p1
  30.     inline std::pair<double, double> line_intersect(Point p1, Point p2, Point p3, Point p4, bool& parallel)
  31.     {
  32.         double x1 = p1.x;
  33.         double x2 = p2.x;
  34.         double x3 = p3.x;
  35.         double x4 = p4.x;
  36.         double y1 = p1.y;
  37.         double y2 = p2.y;
  38.         double y3 = p3.y;
  39.         double y4 = p4.y;
  40.  
  41.         double denom = ((y4 - y3)*(x2 - x1) - (x4 - x3)*(y2 - y1));
  42.         if (denom == 0) {
  43.             parallel = true;
  44.             return std::pair<double, double>(0, 0);
  45.         }
  46.         parallel = false;
  47.         return std::pair<double, double>(((x4 - x3)*(y1 - y3) - (y4 - y3)*(x1 - x3)) / denom,
  48.             ((x2 - x1)*(y1 - y3) - (y2 - y1)*(x1 - x3)) / denom);
  49.     }
  50.  
  51.  
  52.     //intersection between two line segments
  53.     //Returns true if the two segments intersect,
  54.     //in which case intersection is set to the point of intersection
  55.     bool line_segment_intersect(Point p1, Point p2, Point p3, Point p4, Point& intersection) {
  56.         bool parallel;
  57.         std::pair<double, double> u = line_intersect(p1, p2, p3, p4, parallel);
  58.         if (parallel || u.first < 0 || u.first > 1 || u.second < 0 || u.second > 1) return false;
  59.         intersection.x = p1.x + u.first*(p2.x - p1.x);
  60.         intersection.y = p1.y + u.first*(p2.y - p1.y);
  61.         return true;
  62.     }
  63.  
  64.     void Polygon::add(Point p)
  65.     {
  66.         int np = number_of_points();
  67.  
  68.         if (1<np) { // check that thenew line isn't parallel to the previous one
  69.             if (p == point(np - 1)) error("polygon point equal to previous point");
  70.             bool parallel;
  71.             line_intersect(point(np - 1), p, point(np - 2), point(np - 1), parallel);
  72.             if (parallel)
  73.                 error("two polygon points lie in a straight line");
  74.         }
  75.  
  76.         for (int i = 1; i<np - 1; ++i) {    // check that new segment doesn't interset and old point
  77.             Point ignore(0, 0);
  78.             if (line_segment_intersect(point(np - 1), p, point(i - 1), point(i), ignore))
  79.                 error("intersect in polygon");
  80.         }
  81.  
  82.  
  83.         Closed_polyline::add(p);
  84.     }
  85.  
  86.  
  87.     void Polygon::draw_lines() const
  88.     {
  89.         if (number_of_points() < 3) error("less than 3 points in a Polygon");
  90.         Closed_polyline::draw_lines();
  91.     }
  92.  
  93.     void Open_polyline::draw_lines() const
  94.     {
  95.         if (fill_color().visibility()) {
  96.             fl_color(fill_color().as_int());
  97.             fl_begin_complex_polygon();
  98.             for (int i = 0; i<number_of_points(); ++i) {
  99.                 fl_vertex(point(i).x, point(i).y);
  100.             }
  101.             fl_end_complex_polygon();
  102.             fl_color(color().as_int()); // reset color
  103.         }
  104.  
  105.         if (color().visibility())
  106.             Shape::draw_lines();
  107.     }
  108.  
  109.  
  110.     void Closed_polyline::draw_lines() const
  111.     {
  112.         Open_polyline::draw_lines();
  113.  
  114.         if (color().visibility())   // draw closing line:
  115.             fl_line(point(number_of_points() - 1).x, point(number_of_points() - 1).y, point(0).x, point(0).y);
  116.     }
  117.     void Shape::move(int dx, int dy)
  118.     {
  119.         for (unsigned int i = 0; i<points.size(); ++i) {
  120.             points[i].x += dx;
  121.             points[i].y += dy;
  122.         }
  123.     }
  124.  
  125.     void Lines::draw_lines() const
  126.     {
  127.         //  if (number_of_points()%2==1) error("odd number of points in set of lines");
  128.         if (color().visibility())
  129.             for (int i = 1; i<number_of_points(); i += 2)
  130.                 fl_line(point(i - 1).x, point(i - 1).y, point(i).x, point(i).y);
  131.     }
  132.  
  133.     void Text::draw_lines() const
  134.     {
  135.         int ofnt = fl_font();
  136.         int osz = fl_size();
  137.         fl_font(fnt.as_int(), fnt_sz);
  138.         fl_draw(lab.c_str(), point(0).x, point(0).y);
  139.         fl_font(ofnt, osz);
  140.     }
  141.  
  142.     Function::Function(Fct f, double r1, double r2, Point xy, int count, double xscale, double yscale)
  143.         // graph f(x) for x in [r1:r2) using count line segments with (0,0) displayed at xy
  144.         // x coordinates are scaled by xscale and y coordinates scaled by yscale
  145.     {
  146.         if (r2 - r1 <= 0) error("bad graphing range");
  147.         if (count <= 0) error("non-positive graphing count");
  148.         double dist = (r2 - r1) / count;
  149.         double r = r1;
  150.         for (int i = 0; i<count; ++i) {
  151.             add(Point(xy.x + int(r*xscale), xy.y - int(f(r)*yscale)));
  152.             r += dist;
  153.         }
  154.     }
  155.  
  156.     void Rectangle::draw_lines() const
  157.     {
  158.         if (fill_color().visibility()) {    // fill
  159.             fl_color(fill_color().as_int());
  160.             fl_rectf(point(0).x, point(0).y, w, h);
  161.             fl_color(color().as_int()); // reset color
  162.         }
  163.  
  164.         if (color().visibility()) { // edge on top of fill
  165.             fl_color(color().as_int());
  166.             fl_rect(point(0).x, point(0).y, w, h);
  167.         }
  168.     }
  169.  
  170.  
  171.     Axis::Axis(Orientation d, Point xy, int length, int n, std::string lab)
  172.         :label(Point(0, 0), lab)
  173.     {
  174.         if (length<0) error("bad axis length");
  175.         switch (d) {
  176.         case Axis::x:
  177.         {   Shape::add(xy); // axis line
  178.         Shape::add(Point(xy.x + length, xy.y)); // axis line
  179.         if (1<n) {
  180.             int dist = length / n;
  181.             int x = xy.x + dist;
  182.             for (int i = 0; i<n; ++i) {
  183.                 notches.add(Point(x, xy.y), Point(x, xy.y - 5));
  184.                 x += dist;
  185.             }
  186.         }
  187.         // label under the line
  188.         label.move(length / 3, xy.y + 20);
  189.         break;
  190.         }
  191.         case Axis::y:
  192.         {   Shape::add(xy); // a y-axis goes up
  193.         Shape::add(Point(xy.x, xy.y - length));
  194.         if (1<n) {
  195.             int dist = length / n;
  196.             int y = xy.y - dist;
  197.             for (int i = 0; i<n; ++i) {
  198.                 notches.add(Point(xy.x, y), Point(xy.x + 5, y));
  199.                 y -= dist;
  200.             }
  201.         }
  202.         // label at top
  203.         label.move(xy.x - 10, xy.y - length - 10);
  204.         break;
  205.         }
  206.         case Axis::z:
  207.             error("z axis not implemented");
  208.         }
  209.     }
  210.  
  211.     void Axis::draw_lines() const
  212.     {
  213.         Shape::draw_lines();    // the line
  214.         notches.draw(); // the notches may have a different color from the line
  215.         label.draw();   // the label may have a different color from the line
  216.     }
  217.  
  218.  
  219.     void Axis::set_color(Color c)
  220.     {
  221.         Shape::set_color(c);
  222.         notches.set_color(c);
  223.         label.set_color(c);
  224.     }
  225.  
  226.     void Axis::move(int dx, int dy)
  227.     {
  228.         Shape::move(dx, dy);
  229.         notches.move(dx, dy);
  230.         label.move(dx, dy);
  231.     }
  232.  
  233.     void Circle::draw_lines() const
  234.     {
  235.         if (fill_color().visibility()) {    // fill
  236.             fl_color(fill_color().as_int());
  237.             fl_pie(point(0).x, point(0).y, r + r - 1, r + r - 1, 0, 360);
  238.             fl_color(color().as_int()); // reset color
  239.         }
  240.  
  241.         if (color().visibility()) {
  242.             fl_color(color().as_int());
  243.             fl_arc(point(0).x, point(0).y, r + r, r + r, 0, 360);
  244.         }
  245.     }
  246.  
  247.  
  248.     void Ellipse::draw_lines() const
  249.     {
  250.         if (fill_color().visibility()) {    // fill
  251.             fl_color(fill_color().as_int());
  252.             fl_pie(point(0).x, point(0).y, w + w - 1, h + h - 1, 0, 360);
  253.             fl_color(color().as_int()); // reset color
  254.         }
  255.  
  256.         if (color().visibility()) {
  257.             fl_color(color().as_int());
  258.             fl_arc(point(0).x, point(0).y, w + w, h + h, 0, 360);
  259.         }
  260.     }
  261.  
  262.     void draw_mark(Point xy, char c)
  263.     {
  264.         static const int dx = 4;
  265.         static const int dy = 4;
  266.         string m(1, c);
  267.         fl_draw(m.c_str(), xy.x - dx, xy.y + dy);
  268.     }
  269.  
  270.     void Marked_polyline::draw_lines() const
  271.     {
  272.         Open_polyline::draw_lines();
  273.         for (int i = 0; i<number_of_points(); ++i)
  274.             draw_mark(point(i), mark[i%mark.size()]);
  275.     }
  276.     /*
  277.     void Marks::draw_lines() const
  278.     {
  279.     for (int i=0; i<number_of_points(); ++i)
  280.     fl_draw(mark.c_str(),point(i).x-4,point(i).y+4);
  281.     }
  282.     */
  283.  
  284.  
  285.     std::map<string, Suffix::Encoding> suffix_map;
  286.  
  287.     int init_suffix_map()
  288.     {
  289.         suffix_map["jpg"] = Suffix::jpg;
  290.         suffix_map["JPG"] = Suffix::jpg;
  291.         suffix_map["jpeg"] = Suffix::jpg;
  292.         suffix_map["JPEG"] = Suffix::jpg;
  293.         suffix_map["gif"] = Suffix::gif;
  294.         suffix_map["GIF"] = Suffix::gif;
  295.         suffix_map["bmp"] = Suffix::bmp;
  296.         suffix_map["BMP"] = Suffix::bmp;
  297.         return 0;
  298.     }
  299.  
  300.     Suffix::Encoding get_encoding(const std::string& s)
  301.         // try to deduce type from file name using a lookup table
  302.     {
  303.         static int x = init_suffix_map();
  304.  
  305.         string::const_iterator p = find(s.begin(), s.end(), '.');
  306.         if (p == s.end()) return Suffix::none;  // no suffix
  307.  
  308.         string suf(p + 1, s.end());
  309.         return suffix_map[suf];
  310.     }
  311.  
  312.     bool can_open(const std::string& s)
  313.         // check if a file named s exists and can be opened for reading
  314.     {
  315.         ifstream ff(s.c_str());
  316.         return ff ? true : false;
  317.     }
  318.  
  319.  
  320.     // somewhat overelaborate constructor
  321.     // because errors related to image files can be such a pain to debug
  322.     Image::Image(Point xy, string s, Suffix::Encoding e)
  323.         :w(0), h(0), fn(xy, "")
  324.     {
  325.         add(xy);
  326.  
  327.         if (!can_open(s)) {
  328.             fn.set_label("cannot open \"" + s + '\"');
  329.             p = new Bad_image(30, 20);  // the "error image"
  330.             return;
  331.         }
  332.  
  333.         if (e == Suffix::none) e = get_encoding(s);
  334.  
  335.         switch (e) {
  336.         case Suffix::jpg:
  337.             p = new Fl_JPEG_Image(s.c_str());
  338.             break;
  339.         case Suffix::gif:
  340.             p = new Fl_GIF_Image(s.c_str());
  341.             break;
  342.             //  case Suffix::bmp:
  343.             //      p = new Fl_BMP_Image(s.c_str());
  344.             //      break;
  345.         default:    // Unsupported image encoding
  346.             fn.set_label("unsupported file type \"" + s + '\"');
  347.             p = new Bad_image(30, 20);  // the "error image"
  348.         }
  349.     }
  350.  
  351.     void Image::draw_lines() const
  352.     {
  353.         if (fn.label() != "") fn.draw_lines();
  354.  
  355.         if (w&&h)
  356.             p->draw(point(0).x, point(0).y, w, h, cx, cy);
  357.         else
  358.             p->draw(point(0).x, point(0).y);
  359.     }
  360.  
  361. } // Graph
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement