Advertisement
tattersail

Graph.cpp

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