Graphics_utils.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. /* Graphics_utils.cpp
  2. *
  3. * Copyright (C) 1992-2011,2015 Paul Boersma
  4. *
  5. * This code is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This code is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. * See the GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <math.h>
  19. #include "GraphicsP.h"
  20. /***** UTILITIES: *****/
  21. /***** THESE ROUINTES OUTPUT TO CURRENT GRAPHICS BY CALLING PRIMITIVES. *****/
  22. /***** THE TWO UTILITIES "Graphics_grey" AND "Graphics_altitude" *****/
  23. /***** ARE IN DIFFERENT FILES BECAUSE THEY NEED LOCAL SUBROUTINES. *****/
  24. /********** Utility functions. **********/
  25. /********** Drawing into margins. **********/
  26. void Graphics_drawInnerBox (Graphics me) {
  27. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  28. int lineType = my lineType;
  29. double lineWidth = my lineWidth;
  30. Graphics_Colour colour = my colour;
  31. Graphics_setInner (me);
  32. Graphics_setWindow (me, 0.0, 1.0, 0.0, 1.0);
  33. Graphics_setLineType (me, Graphics_DRAWN);
  34. Graphics_setLineWidth (me, 2.0 * lineWidth);
  35. Graphics_setColour (me, Graphics_BLACK);
  36. Graphics_rectangle (me, 0.0, 1.0, 0.0, 1.0);
  37. Graphics_unsetInner (me);
  38. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  39. Graphics_setLineType (me, lineType);
  40. Graphics_setLineWidth (me, lineWidth);
  41. Graphics_setColour (me, colour);
  42. }
  43. void Graphics_textLeft (Graphics me, bool farr, conststring32 text) {
  44. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  45. int vert = farr ? Graphics_TOP : Graphics_BOTTOM;
  46. Graphics_Colour colour = my colour;
  47. Graphics_setColour (me, Graphics_BLACK);
  48. Graphics_setWindow (me, 0.0, 1.0, 0.0, 1.0);
  49. Graphics_setTextRotation (me, 90.0);
  50. Graphics_setTextAlignment (me, Graphics_CENTRE, vert);
  51. if (! farr) Graphics_setInner (me);
  52. Graphics_text (me, 0.0, 0.5, text);
  53. if (! farr) Graphics_unsetInner (me);
  54. Graphics_setTextRotation (me, 0.0);
  55. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  56. Graphics_setColour (me, colour);
  57. }
  58. void Graphics_textRight (Graphics me, bool farr, conststring32 text) {
  59. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  60. int vert = farr ? Graphics_TOP : Graphics_BOTTOM;
  61. Graphics_Colour colour = my colour;
  62. Graphics_setColour (me, Graphics_BLACK);
  63. Graphics_setTextAlignment (me, Graphics_CENTRE, vert);
  64. Graphics_setWindow (me, 0.0, 1.0, 0.0, 1.0);
  65. Graphics_setTextRotation (me, 270.0);
  66. if (! farr) Graphics_setInner (me);
  67. Graphics_text (me, 1.0, 0.5, text);
  68. if (! farr) Graphics_unsetInner (me);
  69. Graphics_setTextRotation (me, 0.0);
  70. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  71. Graphics_setColour (me, colour);
  72. }
  73. void Graphics_textBottom (Graphics me, bool farr, conststring32 text) {
  74. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  75. Graphics_Colour colour = my colour;
  76. Graphics_setColour (me, Graphics_BLACK);
  77. Graphics_setWindow (me, 0.0, 1.0, 0.0, 1.0);
  78. if (farr) {
  79. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_BOTTOM);
  80. Graphics_text (me, 0.5, 0.0, text);
  81. } else {
  82. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_TOP);
  83. Graphics_setInner (me);
  84. Graphics_text (me, 0.5, - my vertTick, text);
  85. Graphics_unsetInner (me);
  86. }
  87. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  88. Graphics_setColour (me, colour);
  89. }
  90. void Graphics_textTop (Graphics me, bool farr, conststring32 text) {
  91. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  92. Graphics_Colour colour = my colour;
  93. Graphics_setColour (me, Graphics_BLACK);
  94. Graphics_setWindow (me, 0.0, 1.0, 0.0, 1.0);
  95. if (farr) {
  96. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_TOP);
  97. Graphics_text (me, 0.5, 1.0, text);
  98. } else {
  99. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_BOTTOM);
  100. Graphics_setInner (me);
  101. Graphics_text (me, 0.5, 1.0 + my vertTick, text);
  102. Graphics_unsetInner (me);
  103. }
  104. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  105. Graphics_setColour (me, colour);
  106. }
  107. void Graphics_marksLeft (Graphics me, int numberOfMarks, bool haveNumbers, bool haveTicks, bool haveDottedLines) {
  108. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  109. int lineType = my lineType;
  110. double lineWidth = my lineWidth;
  111. Graphics_Colour colour = my colour;
  112. if (numberOfMarks < 2) return;
  113. Graphics_setColour (me, Graphics_BLACK);
  114. Graphics_setWindow (me, 0, 1, y1WC, y2WC);
  115. Graphics_setTextAlignment (me, Graphics_RIGHT, Graphics_HALF);
  116. Graphics_setInner (me);
  117. if (haveTicks) {
  118. Graphics_setLineType (me, Graphics_DRAWN);
  119. Graphics_setLineWidth (me, 2.0 * lineWidth);
  120. }
  121. for (int i = 1; i <= numberOfMarks; i ++) {
  122. double f = (i - 1.0) / (numberOfMarks - 1), yWC = y1WC + (y2WC - y1WC) * f;
  123. if (haveNumbers) Graphics_text (me, - my horTick, yWC, Melder_float (Melder_half (yWC)));
  124. if (haveTicks) Graphics_line (me, - my horTick, yWC, 0, yWC);
  125. }
  126. if (haveTicks) Graphics_setLineWidth (me, lineWidth);
  127. if (haveDottedLines && numberOfMarks > 2) {
  128. Graphics_setLineType (me, Graphics_DOTTED);
  129. Graphics_setLineWidth (me, 0.67 * lineWidth);
  130. for (int i = 2; i < numberOfMarks; i ++) {
  131. double f = (i - 1.0) / (numberOfMarks - 1), yWC = y1WC + (y2WC - y1WC) * f;
  132. Graphics_line (me, 0.0, yWC, 1.0, yWC);
  133. }
  134. Graphics_setLineWidth (me, lineWidth);
  135. }
  136. Graphics_unsetInner (me);
  137. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  138. Graphics_setLineType (me, lineType);
  139. Graphics_setColour (me, colour);
  140. }
  141. void Graphics_marksRight (Graphics me, int numberOfMarks, bool haveNumbers, bool haveTicks, bool haveDottedLines) {
  142. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  143. int lineType = my lineType;
  144. double lineWidth = my lineWidth;
  145. Graphics_Colour colour = my colour;
  146. if (numberOfMarks < 2) return;
  147. Graphics_setColour (me, Graphics_BLACK);
  148. Graphics_setWindow (me, 0, 1, y1WC, y2WC);
  149. Graphics_setTextAlignment (me, Graphics_LEFT, Graphics_HALF);
  150. Graphics_setInner (me);
  151. if (haveTicks) {
  152. Graphics_setLineType (me, Graphics_DRAWN);
  153. Graphics_setLineWidth (me, 2.0 * lineWidth);
  154. }
  155. for (int i = 1; i <= numberOfMarks; i ++) {
  156. double f = (i - 1.0) / (numberOfMarks - 1), yWC = y1WC + (y2WC - y1WC) * f;
  157. if (haveNumbers) Graphics_text (me, 1.0 + my horTick, yWC, Melder_float (Melder_half (yWC)));
  158. if (haveTicks) Graphics_line (me, 1.0, yWC, 1.0 + my horTick, yWC);
  159. }
  160. if (haveTicks) Graphics_setLineWidth (me, lineWidth);
  161. if (haveDottedLines && numberOfMarks > 2) {
  162. Graphics_setLineType (me, Graphics_DOTTED);
  163. Graphics_setLineWidth (me, 0.67 * lineWidth);
  164. for (int i = 2; i < numberOfMarks; i ++) {
  165. double f = (i - 1.0) / (numberOfMarks - 1), yWC = y1WC + (y2WC - y1WC) * f;
  166. Graphics_line (me, 0.0, yWC, 1.0, yWC);
  167. }
  168. Graphics_setLineWidth (me, lineWidth);
  169. }
  170. Graphics_unsetInner (me);
  171. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  172. Graphics_setLineType (me, lineType);
  173. Graphics_setColour (me, colour);
  174. }
  175. void Graphics_marksBottom (Graphics me, int numberOfMarks, bool haveNumbers, bool haveTicks, bool haveDottedLines) {
  176. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  177. int lineType = my lineType;
  178. double lineWidth = my lineWidth;
  179. Graphics_Colour colour = my colour;
  180. if (numberOfMarks < 2) return;
  181. Graphics_setColour (me, Graphics_BLACK);
  182. Graphics_setWindow (me, x1WC, x2WC, 0.0, 1.0);
  183. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_TOP);
  184. Graphics_setInner (me);
  185. if (haveTicks) {
  186. Graphics_setLineType (me, Graphics_DRAWN);
  187. Graphics_setLineWidth (me, 2.0 * lineWidth);
  188. }
  189. for (int i = 1; i <= numberOfMarks; i ++) {
  190. double f = (i - 1.0) / (numberOfMarks - 1), xWC = x1WC + (x2WC - x1WC) * f;
  191. if (haveNumbers) Graphics_text (me, xWC, - my vertTick, Melder_float (Melder_half (xWC)));
  192. if (haveTicks) Graphics_line (me, xWC, - my vertTick, xWC, 0);
  193. }
  194. if (haveTicks) Graphics_setLineWidth (me, lineWidth);
  195. if (haveDottedLines && numberOfMarks > 2) {
  196. Graphics_setLineType (me, Graphics_DOTTED);
  197. Graphics_setLineWidth (me, 0.67 * lineWidth);
  198. for (int i = 2; i < numberOfMarks; i ++)
  199. {
  200. double f = (i - 1.0) / (numberOfMarks - 1), xWC = x1WC + (x2WC - x1WC) * f;
  201. Graphics_line (me, xWC, 0.0, xWC, 1.0);
  202. }
  203. Graphics_setLineWidth (me, lineWidth);
  204. }
  205. Graphics_unsetInner (me);
  206. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  207. Graphics_setLineType (me, lineType);
  208. Graphics_setColour (me, colour);
  209. }
  210. void Graphics_marksTop (Graphics me, int numberOfMarks, bool haveNumbers, bool haveTicks, bool haveDottedLines) {
  211. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  212. int lineType = my lineType;
  213. double lineWidth = my lineWidth;
  214. Graphics_Colour colour = my colour;
  215. if (numberOfMarks < 2) return;
  216. Graphics_setColour (me, Graphics_BLACK);
  217. Graphics_setWindow (me, x1WC, x2WC, 0.0, 1.0);
  218. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_BOTTOM);
  219. Graphics_setInner (me);
  220. if (haveTicks) {
  221. Graphics_setLineType (me, Graphics_DRAWN);
  222. Graphics_setLineWidth (me, 2.0 * lineWidth);
  223. }
  224. for (int i = 1; i <= numberOfMarks; i ++) {
  225. double f = (i - 1.0) / (numberOfMarks - 1), xWC = x1WC + (x2WC - x1WC) * f;
  226. if (haveNumbers) Graphics_text (me, xWC, 1.0 + my vertTick, Melder_float (Melder_half (xWC)));
  227. if (haveTicks) Graphics_line (me, xWC, 1.0, xWC, 1.0 + my vertTick);
  228. }
  229. if (haveTicks) Graphics_setLineWidth (me, lineWidth);
  230. if (haveDottedLines && numberOfMarks > 2) {
  231. Graphics_setLineType (me, Graphics_DOTTED);
  232. Graphics_setLineWidth (me, 0.67 * lineWidth);
  233. for (int i = 2; i < numberOfMarks; i ++) {
  234. double f = (i - 1.0) / (numberOfMarks - 1), xWC = x1WC + (x2WC - x1WC) * f;
  235. Graphics_line (me, xWC, 0.0, xWC, 1.0);
  236. }
  237. Graphics_setLineWidth (me, lineWidth);
  238. }
  239. Graphics_unsetInner (me);
  240. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  241. Graphics_setLineType (me, lineType);
  242. Graphics_setColour (me, colour);
  243. }
  244. #define MAXNUM_MARKS_PER_DECADE 7
  245. static double decade_y [1 + MAXNUM_MARKS_PER_DECADE] [1 + MAXNUM_MARKS_PER_DECADE] = {
  246. { 0 },
  247. { 0, 10 },
  248. { 0, 10, 30 },
  249. { 0, 10, 20, 50 },
  250. { 0, 10, 20, 30, 50 },
  251. { 0, 10, 20, 30, 50, 70 },
  252. { 0, 10, 15, 20, 30, 50, 70 },
  253. { 0, 10, 15, 20, 30, 40, 50, 70 }
  254. };
  255. void Graphics_marksLeftLogarithmic (Graphics me, int numberOfMarksPerDecade, bool haveNumbers, bool haveTicks, bool haveDottedLines) {
  256. double x1 = my d_x1WC, x2 = my d_x2WC, y1 = my d_y1WC, y2 = my d_y2WC;
  257. int lineType = my lineType;
  258. double lineWidth = my lineWidth;
  259. Graphics_Colour colour = my colour;
  260. if (numberOfMarksPerDecade < 1) numberOfMarksPerDecade = 1;
  261. if (numberOfMarksPerDecade > MAXNUM_MARKS_PER_DECADE) numberOfMarksPerDecade = MAXNUM_MARKS_PER_DECADE;
  262. if (y1 > 300 || y2 > 300) return;
  263. double py1 = pow (10, y1 + ( y1 < y2 ? -1e-6 : 1e-6 ));
  264. double py2 = pow (10, y2 + ( y1 < y2 ? 1e-6 : -1e-6 ));
  265. Graphics_setColour (me, Graphics_BLACK);
  266. Graphics_setWindow (me, 0, 1, y1, y2);
  267. Graphics_setTextAlignment (me, Graphics_RIGHT, Graphics_HALF);
  268. Graphics_setInner (me);
  269. for (int i = 1; i <= numberOfMarksPerDecade; i ++) {
  270. double y = decade_y [numberOfMarksPerDecade] [i];
  271. while (y < (y1<y2?py1:py2)) y *= 10.0;
  272. while (y >= (y1<y2?py1:py2)) y /= 10.0;
  273. for (y *= 10.0; y <= (y1<y2?py2:py1); y *= 10.0) {
  274. if (haveNumbers) Graphics_text (me, - my horTick, log10 (y), Melder_float (Melder_half (y)));
  275. if (haveTicks) {
  276. Graphics_setLineWidth (me, 2.0 * lineWidth);
  277. Graphics_setLineType (me, Graphics_DRAWN);
  278. Graphics_line (me, - my horTick, log10 (y), 0, log10 (y));
  279. Graphics_setLineWidth (me, lineWidth);
  280. }
  281. if (haveDottedLines) {
  282. Graphics_setLineType (me, Graphics_DOTTED);
  283. Graphics_setLineWidth (me, 0.67 * lineWidth);
  284. Graphics_line (me, 0.0, log10 (y), 1.0, log10 (y));
  285. Graphics_setLineType (me, lineType);
  286. Graphics_setLineWidth (me, lineWidth);
  287. }
  288. }
  289. }
  290. Graphics_unsetInner (me);
  291. Graphics_setWindow (me, x1, x2, y1, y2);
  292. Graphics_setColour (me, colour);
  293. }
  294. void Graphics_marksRightLogarithmic (Graphics me, int numberOfMarksPerDecade, bool haveNumbers, bool haveTicks, bool haveDottedLines) {
  295. double x1 = my d_x1WC, x2 = my d_x2WC, y1 = my d_y1WC, y2 = my d_y2WC;
  296. int lineType = my lineType;
  297. double lineWidth = my lineWidth;
  298. Graphics_Colour colour = my colour;
  299. if (numberOfMarksPerDecade < 1) numberOfMarksPerDecade = 1;
  300. if (numberOfMarksPerDecade > MAXNUM_MARKS_PER_DECADE) numberOfMarksPerDecade = MAXNUM_MARKS_PER_DECADE;
  301. if (y1 > 300.0 || y2 > 300.0) return;
  302. double py1 = pow (10.0, y1 + ( y1 < y2 ? -1e-6 : 1e-6 ));
  303. double py2 = pow (10.0, y2 + ( y1 < y2 ? 1e-6 : -1e-6 ));
  304. Graphics_setColour (me, Graphics_BLACK);
  305. Graphics_setWindow (me, 0.0, 1.0, y1, y2);
  306. Graphics_setTextAlignment (me, Graphics_LEFT, Graphics_HALF);
  307. Graphics_setInner (me);
  308. for (int i = 1; i <= numberOfMarksPerDecade; i ++) {
  309. double y = decade_y [numberOfMarksPerDecade] [i];
  310. while (y < (y1<y2?py1:py2)) y *= 10.0;
  311. while (y >= (y1<y2?py1:py2)) y /= 10.0;
  312. for (y *= 10.0; y <= (y1<y2?py2:py1); y *= 10.0) {
  313. if (haveNumbers) Graphics_text (me, 1.0 + my horTick, log10 (y), Melder_float (Melder_half (y)));
  314. if (haveTicks) {
  315. Graphics_setLineWidth (me, 2.0 * lineWidth);
  316. Graphics_setLineType (me, Graphics_DRAWN);
  317. Graphics_line (me, 1.0, log10 (y), 1.0 + my horTick, log10 (y));
  318. Graphics_setLineWidth (me, lineWidth);
  319. }
  320. if (haveDottedLines) {
  321. Graphics_setLineType (me, Graphics_DOTTED);
  322. Graphics_setLineWidth (me, 0.67 * lineWidth);
  323. Graphics_line (me, 0.0, log10 (y), 1.0, log10 (y));
  324. Graphics_setLineType (me, lineType);
  325. Graphics_setLineWidth (me, lineWidth);
  326. }
  327. }
  328. }
  329. Graphics_unsetInner (me);
  330. Graphics_setWindow (me, x1, x2, y1, y2);
  331. Graphics_setColour (me, colour);
  332. }
  333. void Graphics_marksTopLogarithmic (Graphics me, int numberOfMarksPerDecade, bool haveNumbers, bool haveTicks, bool haveDottedLines) {
  334. double x1 = my d_x1WC, x2 = my d_x2WC, y1 = my d_y1WC, y2 = my d_y2WC;
  335. int lineType = my lineType;
  336. double lineWidth = my lineWidth;
  337. Graphics_Colour colour = my colour;
  338. if (numberOfMarksPerDecade < 1) numberOfMarksPerDecade = 1;
  339. if (numberOfMarksPerDecade > MAXNUM_MARKS_PER_DECADE) numberOfMarksPerDecade = MAXNUM_MARKS_PER_DECADE;
  340. if (x1 > 300.0 || x2 > 300.0) return;
  341. double px1 = pow (10.0, x1 + ( x1 < x2 ? -1e-6 : 1e-6 ));
  342. double px2 = pow (10.0, x2 + ( x1 < x2 ? 1e-6 : -1e-6 ));
  343. Graphics_setColour (me, Graphics_BLACK);
  344. Graphics_setWindow (me, x1, x2, 0.0, 1.0);
  345. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_BOTTOM);
  346. Graphics_setInner (me);
  347. for (int i = 1; i <= numberOfMarksPerDecade; i ++) {
  348. double x = decade_y [numberOfMarksPerDecade] [i];
  349. while (x < (x1<x2?px1:px2)) x *= 10.0;
  350. while (x >= (x1<x2?px1:px2)) x /= 10.0;
  351. for (x *= 10.0; x <= (x1<x2?px2:px1); x *= 10.0) {
  352. if (haveNumbers) Graphics_text (me, log10 (x), 1.0 + my vertTick, Melder_float (Melder_half (x)));
  353. if (haveTicks) {
  354. Graphics_setLineWidth (me, 2.0 * lineWidth);
  355. Graphics_setLineType (me, Graphics_DRAWN);
  356. Graphics_line (me, log10 (x), 1.0, log10 (x), 1.0 + my vertTick);
  357. Graphics_setLineWidth (me, lineWidth);
  358. }
  359. if (haveDottedLines) {
  360. Graphics_setLineType (me, Graphics_DOTTED);
  361. Graphics_setLineWidth (me, 0.67 * lineWidth);
  362. Graphics_line (me, log10 (x), 0.0, log10 (x), 1.0);
  363. Graphics_setLineType (me, lineType);
  364. Graphics_setLineWidth (me, lineWidth);
  365. }
  366. }
  367. }
  368. Graphics_unsetInner (me);
  369. Graphics_setWindow (me, x1, x2, y1, y2);
  370. Graphics_setColour (me, colour);
  371. }
  372. void Graphics_marksBottomLogarithmic (Graphics me, int numberOfMarksPerDecade, bool haveNumbers, bool haveTicks, bool haveDottedLines) {
  373. double x1 = my d_x1WC, x2 = my d_x2WC, y1 = my d_y1WC, y2 = my d_y2WC;
  374. int lineType = my lineType;
  375. double lineWidth = my lineWidth;
  376. Graphics_Colour colour = my colour;
  377. if (numberOfMarksPerDecade < 1) numberOfMarksPerDecade = 1;
  378. if (numberOfMarksPerDecade > MAXNUM_MARKS_PER_DECADE) numberOfMarksPerDecade = MAXNUM_MARKS_PER_DECADE;
  379. if (x1 > 300.0 || x2 > 300.0) return;
  380. double px1 = pow (10.0, x1 + ( x1 < x2 ? -1e-6 : 1e-6 ));
  381. double px2 = pow (10.0, x2 + ( x1 < x2 ? 1e-6 : -1e-6 ));
  382. Graphics_setColour (me, Graphics_BLACK);
  383. Graphics_setWindow (me, x1, x2, 0, 1);
  384. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_TOP);
  385. Graphics_setInner (me);
  386. for (int i = 1; i <= numberOfMarksPerDecade; i ++) {
  387. double x = decade_y [numberOfMarksPerDecade] [i];
  388. while (x < (x1<x2?px1:px2)) x *= 10.0;
  389. while (x >= (x1<x2?px1:px2)) x /= 10.0;
  390. for (x *= 10.0; x <= (x1<x2?px2:px1); x *= 10.0) {
  391. if (haveNumbers) Graphics_text (me, log10 (x), - my vertTick, Melder_float (Melder_half (x)));
  392. if (haveTicks) {
  393. Graphics_setLineWidth (me, 2.0 * lineWidth);
  394. Graphics_setLineType (me, Graphics_DRAWN);
  395. Graphics_line (me, log10 (x), - my vertTick, log10 (x), 0.0);
  396. Graphics_setLineWidth (me, lineWidth);
  397. }
  398. if (haveDottedLines) {
  399. Graphics_setLineType (me, Graphics_DOTTED);
  400. Graphics_setLineWidth (me, 0.67 * lineWidth);
  401. Graphics_line (me, log10 (x), 0.0, log10 (x), 1.0);
  402. Graphics_setLineType (me, lineType);
  403. Graphics_setLineWidth (me, lineWidth);
  404. }
  405. }
  406. }
  407. Graphics_unsetInner (me);
  408. Graphics_setWindow (me, x1, x2, y1, y2);
  409. Graphics_setColour (me, colour);
  410. }
  411. void Graphics_markLeft (Graphics me, double position, bool hasNumber, bool hasTick, bool hasDottedLine, conststring32 text /* cattable */) {
  412. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  413. int lineType = my lineType;
  414. double lineWidth = my lineWidth;
  415. Graphics_Colour colour = my colour;
  416. Graphics_setColour (me, Graphics_BLACK);
  417. Graphics_setWindow (me, 0.0, 1.0, y1WC, y2WC);
  418. Graphics_setTextAlignment (me, Graphics_RIGHT, Graphics_HALF);
  419. Graphics_setInner (me);
  420. if (hasNumber) Graphics_text (me, - my horTick, position, Melder_float (Melder_half (position)));
  421. if (hasTick) {
  422. Graphics_setLineType (me, Graphics_DRAWN);
  423. Graphics_setLineWidth (me, 2.0 * lineWidth);
  424. Graphics_line (me, - my horTick, position, 0.0, position);
  425. Graphics_setLineWidth (me, lineWidth);
  426. }
  427. if (hasDottedLine) {
  428. Graphics_setLineType (me, Graphics_DOTTED);
  429. Graphics_setLineWidth (me, 0.67 * lineWidth);
  430. Graphics_line (me, 0.0, position, 1.0, position);
  431. Graphics_setLineWidth (me, lineWidth);
  432. }
  433. if (text && text [0]) Graphics_text (me, - my horTick, position, text); // 'text' has to stay valid until here; no Graphics is allowed to use the cat buffer!
  434. Graphics_unsetInner (me);
  435. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  436. Graphics_setLineType (me, lineType);
  437. Graphics_setColour (me, colour);
  438. }
  439. void Graphics_markRight (Graphics me, double position, bool hasNumber, bool hasTick, bool hasDottedLine, conststring32 text /* cattable */) {
  440. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  441. int lineType = my lineType;
  442. double lineWidth = my lineWidth;
  443. Graphics_Colour colour = my colour;
  444. Graphics_setColour (me, Graphics_BLACK);
  445. Graphics_setWindow (me, 0.0, 1.0, y1WC, y2WC);
  446. Graphics_setTextAlignment (me, Graphics_LEFT, Graphics_HALF);
  447. Graphics_setInner (me);
  448. if (hasNumber) Graphics_text (me, 1.0 + my horTick, position, Melder_float (Melder_half (position)));
  449. if (hasTick) {
  450. Graphics_setLineType (me, Graphics_DRAWN);
  451. Graphics_setLineWidth (me, 2.0 * lineWidth);
  452. Graphics_line (me, 1.0, position, 1.0 + my horTick, position);
  453. Graphics_setLineWidth (me, lineWidth);
  454. }
  455. if (hasDottedLine) {
  456. Graphics_setLineType (me, Graphics_DOTTED);
  457. Graphics_setLineWidth (me, 0.67 * lineWidth);
  458. Graphics_line (me, 0.0, position, 1.0, position);
  459. Graphics_setLineWidth (me, lineWidth);
  460. }
  461. if (text && text [0]) Graphics_text (me, 1.0 + my horTick, position, text);
  462. Graphics_unsetInner (me);
  463. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  464. Graphics_setLineType (me, lineType);
  465. Graphics_setColour (me, colour);
  466. }
  467. void Graphics_markTop (Graphics me, double position, bool hasNumber, bool hasTick, bool hasDottedLine, conststring32 text /* cattable */) {
  468. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  469. int lineType = my lineType;
  470. double lineWidth = my lineWidth;
  471. Graphics_Colour colour = my colour;
  472. Graphics_setColour (me, Graphics_BLACK);
  473. Graphics_setWindow (me, x1WC, x2WC, 0.0, 1.0);
  474. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_BOTTOM);
  475. Graphics_setInner (me);
  476. if (hasNumber) Graphics_text (me, position, 1.0 + my vertTick, Melder_float (Melder_single (position)));
  477. if (hasTick) {
  478. Graphics_setLineType (me, Graphics_DRAWN);
  479. Graphics_setLineWidth (me, 2.0 * lineWidth);
  480. Graphics_line (me, position, 1.0, position, 1.0 + my vertTick);
  481. Graphics_setLineWidth (me, lineWidth);
  482. }
  483. if (hasDottedLine) {
  484. Graphics_setLineType (me, Graphics_DOTTED);
  485. Graphics_setLineWidth (me, 0.67 * lineWidth);
  486. Graphics_line (me, position, 0.0, position, 1.0);
  487. Graphics_setLineWidth (me, lineWidth);
  488. }
  489. if (text && text [0]) Graphics_text (me, position, 1.0 + my vertTick, text);
  490. Graphics_unsetInner (me);
  491. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  492. Graphics_setLineType (me, lineType);
  493. Graphics_setColour (me, colour);
  494. }
  495. void Graphics_markBottom (Graphics me, double position, bool hasNumber, bool hasTick, bool hasDottedLine, conststring32 text /* cattable */) {
  496. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  497. int lineType = my lineType;
  498. double lineWidth = my lineWidth;
  499. Graphics_Colour colour = my colour;
  500. Graphics_setColour (me, Graphics_BLACK);
  501. Graphics_setWindow (me, x1WC, x2WC, 0.0, 1.0);
  502. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_TOP);
  503. Graphics_setInner (me);
  504. if (hasNumber) Graphics_text (me, position, - my vertTick, Melder_float (Melder_single (position)));
  505. if (hasTick) {
  506. Graphics_setLineType (me, Graphics_DRAWN);
  507. Graphics_setLineWidth (me, 2.0 * lineWidth);
  508. Graphics_line (me, position, - my vertTick, position, 0.0);
  509. Graphics_setLineWidth (me, lineWidth);
  510. }
  511. if (hasDottedLine) {
  512. Graphics_setLineType (me, Graphics_DOTTED);
  513. Graphics_setLineWidth (me, 0.67 * lineWidth);
  514. Graphics_line (me, position, 0.0, position, 1.0);
  515. Graphics_setLineWidth (me, lineWidth);
  516. }
  517. if (text && text [0]) Graphics_text (me, position, - my vertTick, text);
  518. Graphics_unsetInner (me);
  519. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  520. Graphics_setLineType (me, lineType);
  521. Graphics_setColour (me, colour);
  522. }
  523. void Graphics_markLeftLogarithmic (Graphics me, double position, bool hasNumber, bool hasTick, bool hasDottedLine, conststring32 text /* cattable */) {
  524. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  525. int lineType = my lineType;
  526. double lineWidth = my lineWidth;
  527. Graphics_Colour colour = my colour;
  528. if (position <= 0.0) return;
  529. Graphics_setColour (me, Graphics_BLACK);
  530. Graphics_setWindow (me, 0, 1, y1WC, y2WC);
  531. Graphics_setTextAlignment (me, Graphics_RIGHT, Graphics_HALF);
  532. Graphics_setInner (me);
  533. if (hasNumber) Graphics_text (me, - my horTick, log10 (position), Melder_float (Melder_half (position)));
  534. if (hasTick) {
  535. Graphics_setLineType (me, Graphics_DRAWN);
  536. Graphics_setLineWidth (me, 2.0 * lineWidth);
  537. Graphics_line (me, - my horTick, log10 (position), 0.0, log10 (position));
  538. Graphics_setLineWidth (me, lineWidth);
  539. }
  540. if (hasDottedLine) {
  541. Graphics_setLineType (me, Graphics_DOTTED);
  542. Graphics_setLineWidth (me, 0.67 * lineWidth);
  543. Graphics_line (me, 0.0, log10 (position), 1.0, log10 (position));
  544. Graphics_setLineWidth (me, lineWidth);
  545. }
  546. if (text && text [0]) Graphics_text (me, - my horTick, log10 (position), text);
  547. Graphics_unsetInner (me);
  548. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  549. Graphics_setLineType (me, lineType);
  550. Graphics_setColour (me, colour);
  551. }
  552. void Graphics_markRightLogarithmic (Graphics me, double position, bool hasNumber, bool hasTick, bool hasDottedLine, conststring32 text /* cattable */) {
  553. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  554. int lineType = my lineType;
  555. double lineWidth = my lineWidth;
  556. Graphics_Colour colour = my colour;
  557. if (position <= 0.0) return;
  558. Graphics_setColour (me, Graphics_BLACK);
  559. Graphics_setWindow (me, 0.0, 1.0, y1WC, y2WC);
  560. Graphics_setTextAlignment (me, Graphics_LEFT, Graphics_HALF);
  561. Graphics_setInner (me);
  562. if (hasNumber) Graphics_text (me, 1.0 + my horTick, log10 (position), Melder_float (Melder_half (position)));
  563. if (hasTick) {
  564. Graphics_setLineType (me, Graphics_DRAWN);
  565. Graphics_setLineWidth (me, 2.0 * lineWidth);
  566. Graphics_line (me, 1.0, log10 (position), 1.0 + my horTick, log10 (position));
  567. Graphics_setLineWidth (me, lineWidth);
  568. }
  569. if (hasDottedLine) {
  570. Graphics_setLineType (me, Graphics_DOTTED);
  571. Graphics_setLineWidth (me, 0.67 * lineWidth);
  572. Graphics_line (me, 0.0, log10 (position), 1.0, log10 (position));
  573. Graphics_setLineWidth (me, lineWidth);
  574. }
  575. if (text && text [0]) Graphics_text (me, 1.0 + my horTick, log10 (position), text);
  576. Graphics_unsetInner (me);
  577. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  578. Graphics_setLineType (me, lineType);
  579. Graphics_setColour (me, colour);
  580. }
  581. void Graphics_markTopLogarithmic (Graphics me, double position, bool hasNumber, bool hasTick, bool hasDottedLine, conststring32 text /* cattable */) {
  582. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  583. int lineType = my lineType;
  584. double lineWidth = my lineWidth;
  585. Graphics_Colour colour = my colour;
  586. if (position <= 0.0) return;
  587. Graphics_setColour (me, Graphics_BLACK);
  588. Graphics_setWindow (me, x1WC, x2WC, 0.0, 1.0);
  589. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_BOTTOM);
  590. Graphics_setInner (me);
  591. if (hasNumber) Graphics_text (me, log10 (position), 1.0 + my vertTick, Melder_float (Melder_half (position)));
  592. if (hasTick) {
  593. Graphics_setLineType (me, Graphics_DRAWN);
  594. Graphics_setLineWidth (me, 2.0 * lineWidth);
  595. Graphics_line (me, log10 (position), 1.0, log10 (position), 1.0 + my vertTick);
  596. Graphics_setLineWidth (me, lineWidth);
  597. }
  598. if (hasDottedLine) {
  599. Graphics_setLineType (me, Graphics_DOTTED);
  600. Graphics_setLineWidth (me, 0.67 * lineWidth);
  601. Graphics_line (me, log10 (position), 0.0, log10 (position), 1.0);
  602. Graphics_setLineWidth (me, lineWidth);
  603. }
  604. if (text && text [0]) Graphics_text (me, log10 (position), 1.0 + my vertTick, text);
  605. Graphics_unsetInner (me);
  606. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  607. Graphics_setLineType (me, lineType);
  608. Graphics_setColour (me, colour);
  609. }
  610. void Graphics_markBottomLogarithmic (Graphics me, double position, bool hasNumber, bool hasTick, bool hasDottedLine, conststring32 text /* cattable */) {
  611. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  612. int lineType = my lineType;
  613. double lineWidth = my lineWidth;
  614. Graphics_Colour colour = my colour;
  615. if (position <= 0.0) return;
  616. Graphics_setColour (me, Graphics_BLACK);
  617. Graphics_setWindow (me, x1WC, x2WC, 0.0, 1.0);
  618. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_TOP);
  619. Graphics_setInner (me);
  620. if (hasNumber) Graphics_text (me, log10 (position), - my vertTick, Melder_float (Melder_half (position)));
  621. if (hasTick) {
  622. Graphics_setLineType (me, Graphics_DRAWN);
  623. Graphics_setLineWidth (me, 2.0 * lineWidth);
  624. Graphics_line (me, log10 (position), - my vertTick, log10 (position), 0.0);
  625. Graphics_setLineWidth (me, lineWidth);
  626. }
  627. if (hasDottedLine) {
  628. Graphics_setLineType (me, Graphics_DOTTED);
  629. Graphics_setLineWidth (me, 0.67 * lineWidth);
  630. Graphics_line (me, log10 (position), 0.0, log10 (position), 1.0);
  631. Graphics_setLineWidth (me, lineWidth);
  632. }
  633. if (text && text [0]) Graphics_text (me, log10 (position), - my vertTick, text);
  634. Graphics_unsetInner (me);
  635. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  636. Graphics_setLineType (me, lineType);
  637. Graphics_setColour (me, colour);
  638. }
  639. void Graphics_marksLeftEvery (Graphics me, double units, double distance, bool haveNumbers, bool haveTicks, bool haveDottedLines) {
  640. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  641. int lineType = my lineType;
  642. integer first, last;
  643. double lineWidth = my lineWidth;
  644. Graphics_Colour colour = my colour;
  645. distance *= units;
  646. first = Melder_iceiling (( y1WC < y2WC ? y1WC : y2WC ) / distance - 1e-5);
  647. last = Melder_ifloor (( y1WC < y2WC ? y2WC : y1WC ) / distance + 1e-5);
  648. Graphics_setColour (me, Graphics_BLACK);
  649. Graphics_setWindow (me, 0, 1, y1WC, y2WC);
  650. Graphics_setTextAlignment (me, Graphics_RIGHT, Graphics_HALF);
  651. Graphics_setInner (me);
  652. if (haveTicks) {
  653. Graphics_setLineType (me, Graphics_DRAWN);
  654. Graphics_setLineWidth (me, 2.0 * lineWidth);
  655. }
  656. for (integer i = first; i <= last; i ++) {
  657. double yWC = i * distance;
  658. if (haveNumbers) Graphics_text (me, - my horTick, yWC, Melder_float (Melder_half (yWC / units)));
  659. if (haveTicks) Graphics_line (me, - my horTick, yWC, 0.0, yWC);
  660. }
  661. if (haveTicks) Graphics_setLineWidth (me, lineWidth);
  662. if (haveDottedLines) {
  663. Graphics_setLineType (me, Graphics_DOTTED);
  664. Graphics_setLineWidth (me, 0.67 * lineWidth);
  665. for (integer i = first; i <= last; i ++) {
  666. double yWC = i * distance;
  667. Graphics_line (me, 0.0, yWC, 1.0, yWC);
  668. }
  669. Graphics_setLineWidth (me, lineWidth);
  670. }
  671. Graphics_unsetInner (me);
  672. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  673. Graphics_setLineType (me, lineType);
  674. Graphics_setColour (me, colour);
  675. }
  676. void Graphics_marksRightEvery (Graphics me, double units, double distance, bool haveNumbers, bool haveTicks, bool haveDottedLines) {
  677. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  678. int lineType = my lineType;
  679. integer first, last;
  680. double lineWidth = my lineWidth;
  681. Graphics_Colour colour = my colour;
  682. distance *= units;
  683. first = Melder_iceiling (( y1WC < y2WC ? y1WC : y2WC ) / distance - 1e-5);
  684. last = Melder_ifloor (( y1WC < y2WC ? y2WC : y1WC ) / distance + 1e-5);
  685. if (first > last) return;
  686. Graphics_setColour (me, Graphics_BLACK);
  687. Graphics_setWindow (me, 0, 1, y1WC, y2WC);
  688. Graphics_setTextAlignment (me, Graphics_LEFT, Graphics_HALF);
  689. Graphics_setInner (me);
  690. if (haveTicks) {
  691. Graphics_setLineType (me, Graphics_DRAWN);
  692. Graphics_setLineWidth (me, 2.0 * lineWidth);
  693. }
  694. for (integer i = first; i <= last; i ++) {
  695. double yWC = i * distance;
  696. if (haveNumbers) Graphics_text (me, 1.0 + my horTick, yWC, Melder_float (Melder_half (yWC / units)));
  697. if (haveTicks) Graphics_line (me, 1.0, yWC, 1.0 + my horTick, yWC);
  698. }
  699. if (haveTicks) Graphics_setLineWidth (me, lineWidth);
  700. if (haveDottedLines) {
  701. Graphics_setLineType (me, Graphics_DOTTED);
  702. Graphics_setLineWidth (me, 0.67 * lineWidth);
  703. for (integer i = first; i <= last; i ++) {
  704. double yWC = i * distance;
  705. Graphics_line (me, 0.0, yWC, 1.0, yWC);
  706. }
  707. Graphics_setLineWidth (me, lineWidth);
  708. }
  709. Graphics_unsetInner (me);
  710. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  711. Graphics_setLineType (me, lineType);
  712. Graphics_setColour (me, colour);
  713. }
  714. void Graphics_marksBottomEvery (Graphics me, double units, double distance, bool haveNumbers, bool haveTicks, bool haveDottedLines) {
  715. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  716. int lineType = my lineType;
  717. integer first, last;
  718. double lineWidth = my lineWidth;
  719. Graphics_Colour colour = my colour;
  720. distance *= units;
  721. first = Melder_iceiling (( x1WC < x2WC ? x1WC : x2WC ) / distance - 1e-5);
  722. last = Melder_ifloor (( x1WC < x2WC ? x2WC : x1WC ) / distance + 1e-5);
  723. Graphics_setColour (me, Graphics_BLACK);
  724. Graphics_setWindow (me, x1WC, x2WC, 0.0, 1.0);
  725. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_TOP);
  726. Graphics_setInner (me);
  727. if (haveTicks) {
  728. Graphics_setLineType (me, Graphics_DRAWN);
  729. Graphics_setLineWidth (me, 2.0 * lineWidth);
  730. }
  731. for (integer i = first; i <= last; i ++) {
  732. double xWC = i * distance;
  733. if (haveNumbers) Graphics_text (me, xWC, - my vertTick, Melder_float (Melder_half (xWC / units)));
  734. if (haveTicks) Graphics_line (me, xWC, - my vertTick, xWC, 0.0);
  735. }
  736. if (haveTicks) Graphics_setLineWidth (me, lineWidth);
  737. if (haveDottedLines) {
  738. Graphics_setLineType (me, Graphics_DOTTED);
  739. Graphics_setLineWidth (me, 0.67 * lineWidth);
  740. for (integer i = first; i <= last; i ++) {
  741. double xWC = i * distance;
  742. Graphics_line (me, xWC, 0.0, xWC, 1.0);
  743. }
  744. Graphics_setLineWidth (me, lineWidth);
  745. }
  746. Graphics_unsetInner (me);
  747. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  748. Graphics_setLineType (me, lineType);
  749. Graphics_setColour (me, colour);
  750. }
  751. void Graphics_marksTopEvery (Graphics me, double units, double distance, bool haveNumbers, bool haveTicks, bool haveDottedLines) {
  752. double x1WC = my d_x1WC, x2WC = my d_x2WC, y1WC = my d_y1WC, y2WC = my d_y2WC;
  753. int lineType = my lineType;
  754. integer first, last;
  755. double lineWidth = my lineWidth;
  756. Graphics_Colour colour = my colour;
  757. distance *= units;
  758. first = Melder_iceiling (( x1WC < x2WC ? x1WC : x2WC ) / distance - 1e-5);
  759. last = Melder_ifloor (( x1WC < x2WC ? x2WC : x1WC ) / distance + 1e-5);
  760. Graphics_setColour (me, Graphics_BLACK);
  761. Graphics_setWindow (me, x1WC, x2WC, 0.0, 1.0);
  762. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_BOTTOM);
  763. Graphics_setInner (me);
  764. if (haveTicks) {
  765. Graphics_setLineType (me, Graphics_DRAWN);
  766. Graphics_setLineWidth (me, 2.0 * lineWidth);
  767. }
  768. for (integer i = first; i <= last; i ++) {
  769. double xWC = i * distance;
  770. if (haveNumbers) Graphics_text (me, xWC, 1.0 + my vertTick, Melder_float (Melder_half (xWC / units)));
  771. if (haveTicks) Graphics_line (me, xWC, 1.0, xWC, 1.0 + my vertTick);
  772. }
  773. if (haveTicks) Graphics_setLineWidth (me, lineWidth);
  774. if (haveDottedLines) {
  775. Graphics_setLineType (me, Graphics_DOTTED);
  776. Graphics_setLineWidth (me, 0.67 * lineWidth);
  777. for (integer i = first; i <= last; i ++) {
  778. double xWC = i * distance;
  779. Graphics_line (me, xWC, 0.0, xWC, 1.0);
  780. }
  781. Graphics_setLineWidth (me, lineWidth);
  782. }
  783. Graphics_unsetInner (me);
  784. Graphics_setWindow (me, x1WC, x2WC, y1WC, y2WC);
  785. Graphics_setLineType (me, lineType);
  786. Graphics_setColour (me, colour);
  787. }
  788. void Graphics_mark (Graphics me, double x, double y, double size_mm, conststring32 markString /* cattable */) {
  789. int mark;
  790. if (! markString || ! markString [0]) mark = 0;
  791. else if (! markString [1]) {
  792. if (markString [0] == '+') mark = 1;
  793. else if (markString [0] == 'x') mark = 2;
  794. else if (markString [0] == 'o') mark = 3;
  795. else if (markString [0] == '.') mark = 0;
  796. else mark = -1;
  797. } else mark = -1;
  798. if (mark == -1) {
  799. int oldSize = my fontSize;
  800. int oldHorizontalAlignment = my horizontalTextAlignment;
  801. int oldVerticalAlignment = my verticalTextAlignment;
  802. Graphics_setFontSize (me, size_mm * 72.0 / 25.4);
  803. Graphics_setTextAlignment (me, Graphics_CENTRE, Graphics_HALF);
  804. Graphics_text (me, x, y, markString);
  805. Graphics_setFontSize (me, oldSize);
  806. Graphics_setTextAlignment (me, (kGraphics_horizontalAlignment) oldHorizontalAlignment, oldVerticalAlignment);
  807. } else if (mark == 0) {
  808. Graphics_fillCircle_mm (me, x, y, size_mm);
  809. } else if (mark == 1) {
  810. double dx = 0.5 * Graphics_dxMMtoWC (me, size_mm);
  811. double dy = 0.5 * Graphics_dyMMtoWC (me, size_mm);
  812. Graphics_line (me, x - dx, y, x + dx, y);
  813. Graphics_line (me, x, y - dy, x, y + dy);
  814. } else if (mark == 2) {
  815. double dx = 0.4 * Graphics_dxMMtoWC (me, size_mm);
  816. double dy = 0.4 * Graphics_dyMMtoWC (me, size_mm);
  817. Graphics_line (me, x - dx, y - dy, x + dx, y + dy);
  818. Graphics_line (me, x + dx, y - dy, x - dx, y + dy);
  819. } else {
  820. Graphics_circle_mm (me, x, y, size_mm);
  821. }
  822. }
  823. void Graphics_setTextRotation_vector (Graphics me, double dx, double dy) {
  824. double angle;
  825. if (dy == 0.0) {
  826. angle = dx >= 0.0 ? 0.0 : 180.0;
  827. } else if (dx == 0.0) {
  828. angle = dy > 0.0 ? 90.0 : 270.0;
  829. } else {
  830. double dxDC = dx * my scaleX, dyDC = my yIsZeroAtTheTop ? -dy * my scaleY : dy * my scaleY;
  831. angle = atan2 (dyDC, dxDC) * (180.0 / NUMpi);
  832. }
  833. Graphics_setTextRotation (me, angle);
  834. }
  835. /* End of file Graphics_utils.cpp */