Advertisement
grumblesnake

Graph.cpp

May 17th, 2018
310
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.74 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 se 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 thenew 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.  
  245. void Ellipse::draw_lines() const
  246. {
  247. if (fill_color().visibility()) { // fill
  248. fl_color(fill_color().as_int());
  249. fl_pie(point(0).x,point(0).y,w+w-1,h+h-1,0,360);
  250. fl_color(color().as_int()); // reset color
  251. }
  252.  
  253. if (color().visibility()) {
  254. fl_color(color().as_int());
  255. fl_arc(point(0).x,point(0).y,w+w,h+h,0,360);
  256. }
  257. }
  258.  
  259. void draw_mark(Point xy, char c)
  260. {
  261. static const int dx = 4;
  262. static const int dy = 4;
  263. string m(1,c);
  264. fl_draw(m.c_str(),xy.x-dx,xy.y+dy);
  265. }
  266.  
  267. void Marked_polyline::draw_lines() const
  268. {
  269. Open_polyline::draw_lines();
  270. for (int i=0; i<number_of_points(); ++i)
  271. draw_mark(point(i),mark[i%mark.size()]);
  272. }
  273. /*
  274. void Marks::draw_lines() const
  275. {
  276. for (int i=0; i<number_of_points(); ++i)
  277. fl_draw(mark.c_str(),point(i).x-4,point(i).y+4);
  278. }
  279. */
  280.  
  281.  
  282. std::map<string,Suffix::Encoding> suffix_map;
  283.  
  284. int init_suffix_map()
  285. {
  286. suffix_map["jpg"] = Suffix::jpg;
  287. suffix_map["JPG"] = Suffix::jpg;
  288. suffix_map["jpeg"] = Suffix::jpg;
  289. suffix_map["JPEG"] = Suffix::jpg;
  290. suffix_map["gif"] = Suffix::gif;
  291. suffix_map["GIF"] = Suffix::gif;
  292. suffix_map["bmp"] = Suffix::bmp;
  293. suffix_map["BMP"] = Suffix::bmp;
  294. return 0;
  295. }
  296.  
  297. Suffix::Encoding get_encoding(const string& s)
  298. // try to deduce type from file name using a lookup table
  299. {
  300. static int x = init_suffix_map();
  301.  
  302. string::const_iterator p = find(s.begin(),s.end(),'.');
  303. if (p==s.end()) return Suffix::none; // no suffix
  304.  
  305. string suf(p+1,s.end());
  306. return suffix_map[suf];
  307. }
  308.  
  309. bool can_open(const string& s)
  310. // check if a file named s exists and can be opened for reading
  311. {
  312. ifstream ff(s.c_str());
  313. return bool(ff);
  314. }
  315.  
  316.  
  317. // somewhat overelaborate constructor
  318. // because errors related to image files can be such a pain to debug
  319. Image::Image(Point xy, string s, Suffix::Encoding e)
  320. :w(0), h(0), fn(xy,"")
  321. {
  322. add(xy);
  323.  
  324. if (!can_open(s)) {
  325. fn.set_label("cannot open \""+s+'\"');
  326. p = new Bad_image(30,20); // the "error image"
  327. return;
  328. }
  329.  
  330. if (e == Suffix::none) e = get_encoding(s);
  331.  
  332. switch(e) {
  333. case Suffix::jpg:
  334. p = new Fl_JPEG_Image(s.c_str());
  335. break;
  336. case Suffix::gif:
  337. p = new Fl_GIF_Image(s.c_str());
  338. break;
  339. // case Suffix::bmp:
  340. // p = new Fl_BMP_Image(s.c_str());
  341. // break;
  342. default: // Unsupported image encoding
  343. fn.set_label("unsupported file type \""+s+'\"');
  344. p = new Bad_image(30,20); // the "error image"
  345. }
  346. }
  347.  
  348. void Image::draw_lines() const
  349. {
  350. if (fn.label()!="") fn.draw_lines();
  351.  
  352. if (w&&h)
  353. p->draw(point(0).x,point(0).y,w,h,cx,cy);
  354. else
  355. p->draw(point(0).x,point(0).y);
  356. }
  357.  
  358. } // Graph
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement