sample.c 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763
  1. /*
  2. ************************************************************
  3. * MODULE: r.le.setup/sample.c *
  4. * Version 5.0beta Oct. 1, 2001 *
  5. * *
  6. * AUTHOR: W.L. Baker, University of Wyoming *
  7. * BAKERWL@UWYO.EDU *
  8. * *
  9. * PURPOSE: To set up sampling areas, which can can then *
  10. * be used to obtain data using the r.le.dist, *
  11. * r.le.patch, and r.le.pixel programs. The *
  12. * sample.c code queries the user for information *
  13. * needed to setup sampling units *
  14. * *
  15. * COPYRIGHT: (C) 2001 by W.L. Baker *
  16. * *
  17. * This program is free software under the GNU General *
  18. * Public License(>=v2). Read the file COPYING that comes *
  19. * with GRASS for details *
  20. * *
  21. ************************************************************/
  22. #include <stdlib.h>
  23. #include <grass/gis.h>
  24. #include <grass/vector.h>
  25. #include <grass/config.h>
  26. #include <grass/display.h>
  27. #include <grass/glocale.h>
  28. #include "setup.h"
  29. static int calc_unit_loc(double radius, int top, int bot, int left, int right,
  30. double ratio, int u_w, int u_l, int method,
  31. double intv, int num, int h_d, int v_d, double *ux,
  32. double *uy, int *sites, double startx, int starty,
  33. int fmask, double nx, double x, double y);
  34. static void draw_grid(int l, int t, int w_w, int w_l, int h_d, int v_d,
  35. int starty, int startx, double colratio,
  36. double rowratio);
  37. static void man_unit(int t, int b, int l, int r, char *n1, char *n2, char *n3,
  38. double *mx, int fmask);
  39. static void get_rd(int exp1, int exp2, int dx, int dy, int u_w, int u_l,
  40. int *l, int *t);
  41. static int overlap(int x1, int y1, int x2, int y2, int dx, int dy);
  42. static int calc_num(int w_w, int w_l, double ratio, int u_w, int u_l,
  43. int method, double intv, int startx, int starty, int size,
  44. int count);
  45. static void graph_unit(int t, int b, int l, int r, char *n1, char *n2,
  46. char *n3, double *mx, int fmask);
  47. int tag = 0;
  48. static RETSIGTYPE f(int);
  49. /* SAMPLING UNIT SETUP DRIVER */
  50. void sample(int t0, int b0, int l0, int r0, char *name, char *name1,
  51. char *name2, double *msc)
  52. {
  53. int btn, d, fmask;
  54. double tmp;
  55. /*
  56. IN
  57. name = name of raster map to be set up
  58. name1 = name of overlay vector map
  59. name2 = name of overlay site map
  60. msc[0]= cols of region/width of screen
  61. msc[1]= rows of region/height of screen
  62. t0 = top row of sampling frame
  63. b0 = bottom row of sampling frame
  64. l0 = left col of sampling frame
  65. r0 = right col of sampling frame
  66. */
  67. /* determine whether the user will use
  68. the keyboard or mouse to setup the
  69. sampling units */
  70. keyboard:
  71. fprintf(stderr, "\n\n HOW WILL YOU SPECIFY SAMPLING UNITS?\n");
  72. fprintf(stderr,
  73. "\n Use keyboard to enter sampling unit dimensions 1");
  74. fprintf(stderr,
  75. "\n Use mouse to draw sampling units 2\n");
  76. fprintf(stderr,
  77. "\n Which Number? ");
  78. numtrap(1, &tmp);
  79. d = (int)(tmp);
  80. if (d < 1 || d > 2) {
  81. fprintf(stderr, " You did not enter a 1 or 2, try again\n");
  82. goto keyboard;
  83. }
  84. if (d == 1 || d == 2) {
  85. /* return a value > 0 to fmask if there is
  86. a MASK present */
  87. fprintf(stderr,
  88. "\n If a MASK is not present (see r.mask) a beep may sound\n");
  89. fprintf(stderr,
  90. " and a WARNING may be printed that can be ignored.\n");
  91. fprintf(stderr,
  92. " If a MASK is present there will be no warning.\n");
  93. fmask = Rast_open_old("MASK", G_mapset());
  94. fprintf(stderr, "\n");
  95. /* call the routine to setup sampling
  96. units manually */
  97. if (d == 1)
  98. man_unit(t0, b0, l0, r0, name, name1, name2, msc, fmask);
  99. /* call the routine to setup sampling
  100. units graphically */
  101. else if (d == 2)
  102. graph_unit(t0, b0, l0, r0, name, name1, name2, msc, fmask);
  103. Rast_close(fmask);
  104. }
  105. /* if neither, then exit */
  106. else
  107. exit(0);
  108. return;
  109. }
  110. /* DEFINE SAMPLING UNITS MANUALLY */
  111. static void man_unit(int t, int b, int l, int r, char *n1, char *n2, char *n3,
  112. double *mx, int fmask)
  113. {
  114. int i, j, dx, dy, w_w, w_l, u_w, u_l,
  115. method, l0, t0, randflag = 0, unit_num, num = 0, scales,
  116. h_d = 1, v_d = 1, itmp, thick, sites, *row_buf, fr, k,
  117. count = 0, maxsize = 0, nx = 0, ny = 0, numx = 0, numy = 0,
  118. al = 0, ar = 0, at = 0, ab = 0, au_w = 0, au_l = 0;
  119. double *ux, *uy;
  120. FILE *fp;
  121. double dtmp, ratio, size, intv = 0.0, start[2], cnt = 0, radius = 0.0;
  122. char *sites_mapset;
  123. struct Cell_head wind;
  124. /* VARIABLES:
  125. COORDINATES IN THIS ROUTINE ARE IN CELLS
  126. t = top row of sampling frame
  127. b = bottom row of sampling frame
  128. l = left col of sampling frame
  129. r = right col of sampling frame
  130. n1 =
  131. n2 =
  132. n3 =
  133. start[0]= row of UL corner of starting pt for strata
  134. start[1]= col of UL corner of starting pt for strata
  135. mx[0] = cols of region/width of screen
  136. mx[1] = rows of region/height of screen
  137. */
  138. start[0] = 0.0;
  139. start[1] = 0.0;
  140. l = (int)((double)(l * mx[0]) + 0.5);
  141. r = (int)((double)(r * mx[0]) + 0.5);
  142. t = (int)((double)(t * mx[1]) + 0.5);
  143. b = (int)((double)(b * mx[1]) + 0.5);
  144. w_w = r - l;
  145. w_l = b - t;
  146. /* draw the sampling frame */
  147. R_open_driver();
  148. R_standard_color(D_translate_color("grey"));
  149. draw_box((int)(l / mx[0] + 0.5), (int)(t / mx[1] + 0.5),
  150. (int)(r / mx[0] + 0.5), (int)(b / mx[1] + 0.5), 1);
  151. R_close_driver();
  152. /* open the units file for output */
  153. fp = fopen0("r.le.para/units", "w");
  154. G_sleep_on_error(0);
  155. /* get the number of scales */
  156. do {
  157. fprintf(stderr,
  158. "\n How many different SCALES do you want (1-15)? ");
  159. numtrap(1, &dtmp);
  160. if (dtmp > 15 || dtmp < 1) {
  161. fprintf(stderr,
  162. "\n Too many (>15) or too few scales; try again");
  163. }
  164. }
  165. while (dtmp < 1 || dtmp > 15);
  166. fprintf(fp, "%10d # of scales\n", (scales = (int)dtmp));
  167. /* for each scale */
  168. for (i = 0; i < scales; i++) {
  169. for (;;) {
  170. G_system("clear");
  171. radius = 0.0;
  172. fprintf(stderr, "\n\n TYPE IN PARAMETERS FOR SCALE %d:\n",
  173. i + 1);
  174. /* get the distribution method */
  175. fprintf(stderr,
  176. "\n Choose method of sampling unit DISTRIBUTION \n");
  177. fprintf(stderr, " Random nonoverlapping 1\n");
  178. fprintf(stderr, " Systematic contiguous 2\n");
  179. fprintf(stderr, " Systematic noncontiguous 3\n");
  180. fprintf(stderr, " Stratified random 4\n");
  181. fprintf(stderr, " Centered over sites 5\n");
  182. fprintf(stderr, " Exit to setup option menu 6\n\n");
  183. do {
  184. fprintf(stderr, " Which Number? ");
  185. numtrap(1, &dtmp);
  186. if ((method = fabs(dtmp)) > 6 || method < 1) {
  187. fprintf(stderr,
  188. "\n Choice must between 1-5; try again");
  189. }
  190. }
  191. while (method > 6 || method < 1);
  192. if (method == 6)
  193. return;
  194. /* for stratified random distribution,
  195. determine the number of strata */
  196. if (method == 4) {
  197. getstrata:
  198. fprintf(stderr,
  199. "\n Number of strata along the x-axis? (1-60) ");
  200. numtrap(1, &dtmp);
  201. h_d = fabs(dtmp);
  202. fprintf(stderr,
  203. "\n Number of strata along the y-axis? (1-60) ");
  204. numtrap(1, &dtmp);
  205. v_d = fabs(dtmp);
  206. if (h_d < 1 || v_d < 1 || h_d > 60 || v_d > 60) {
  207. fprintf(stderr,
  208. "\n Number must be between 1-60; try again.");
  209. goto getstrata;
  210. }
  211. }
  212. /* for methods with strata */
  213. if (method == 2 || method == 3 || method == 4) {
  214. strata:
  215. fprintf(stderr,
  216. "\n Sampling frame row & col for upper left corner of");
  217. fprintf(stderr,
  218. " the strata?\n Rows are numbered down and columns");
  219. fprintf(stderr,
  220. " are numbered to the right\n Enter 1 1 to start in");
  221. fprintf(stderr, " upper left corner of sampling frame: ");
  222. numtrap(2, start);
  223. start[0] = start[0] - 1.0;
  224. start[1] = start[1] - 1.0;
  225. if (start[0] > w_l || start[0] < 0 ||
  226. start[1] > w_w || start[1] < 0) {
  227. fprintf(stderr,
  228. "\n The starting row and col you entered are outside");
  229. fprintf(stderr,
  230. " the sampling frame\n Try again\n");
  231. goto strata;
  232. }
  233. }
  234. if (method == 4) {
  235. /* call draw_grid with the left, top, width,
  236. length, the number of horizontal and
  237. vertical strata, and the starting row
  238. and col for the strata */
  239. draw_grid((int)(l / mx[0] + 0.5), (int)(t / mx[1] + 0.5),
  240. (int)(w_w / mx[0] + 0.5), (int)(w_l / mx[1] + 0.5),
  241. h_d, v_d, (int)(start[0] / mx[1] + 0.5),
  242. (int)(start[1] / mx[0] + 0.5), mx[0], mx[1]);
  243. if (!G_yes(" Are these strata OK? ", 1)) {
  244. if (G_yes("\n\n Refresh the screen? ", 1)) {
  245. paint_map(n1, n2, n3);
  246. R_open_driver();
  247. R_standard_color(D_translate_color("grey"));
  248. draw_box((int)(l / mx[0] + 0.5),
  249. (int)(t / mx[1] + 0.5),
  250. (int)(r / mx[0] + 0.5),
  251. (int)(b / mx[1] + 0.5), 1);
  252. R_close_driver();
  253. }
  254. goto getstrata;
  255. }
  256. }
  257. /* if sampling using circles */
  258. fprintf(stderr, "\n Do you want to sample using rectangles");
  259. if (!G_yes
  260. ("\n (including squares) (y) or circles (n)? ", 1)) {
  261. getradius:
  262. fprintf(stderr,
  263. "\n What radius do you want for the circles? Radius");
  264. fprintf(stderr,
  265. "\n is in pixels; add 0.5 pixels, for the center");
  266. fprintf(stderr,
  267. "\n pixel, to the number of pixels outside the");
  268. fprintf(stderr,
  269. "\n center pixel. Type a real number with one");
  270. fprintf(stderr,
  271. "\n decimal place ending in .5 (e.g., 4.5): ");
  272. numtrap(1, &radius);
  273. if (radius > 100.0) {
  274. fprintf(stderr,
  275. "\n Are you sure that you want such a large");
  276. if (!G_yes("\n radius (> 100 pixels)? ", 1))
  277. goto getradius;
  278. }
  279. ratio = 1.0;
  280. u_w = (int)(2 * radius);
  281. u_l = (int)(2 * radius);
  282. if (fmask > 0) {
  283. count = 0;
  284. row_buf = Rast_allocate_buf(CELL_TYPE);
  285. fr = Rast_open_old(n1, G_mapset());
  286. for (j = t; j < b; j++) {
  287. Rast_zero_buf(row_buf, CELL_TYPE);
  288. Rast_get_row(fr, row_buf, j, CELL_TYPE);
  289. for (k = l; k < r; k++) {
  290. if (*(row_buf + k))
  291. count++;
  292. }
  293. }
  294. G_free(row_buf);
  295. Rast_close(fr);
  296. cnt = (double)(count);
  297. if (cnt)
  298. cnt = sqrt(cnt);
  299. else
  300. cnt = 0;
  301. }
  302. else {
  303. count = (w_l - (int)(start[0])) * (w_w - (int)(start[1]));
  304. }
  305. }
  306. /* if sampling using rectangles/squares */
  307. else {
  308. /* get the width/length ratio */
  309. getratio:
  310. fprintf(stderr,
  311. "\n Sampling unit SHAPE (aspect ratio, #cols/#rows) "
  312. "expressed as real number"
  313. "\n (e.g., 10 cols/5 rows = 2.0) for sampling units "
  314. "of scale %d? ", i + 1);
  315. numtrap(1, &ratio);
  316. if (ratio < 0)
  317. ratio = -ratio;
  318. else if (ratio > 25.0)
  319. if (!G_yes
  320. ("\n Are you sure you want such a large ratio? ",
  321. 1))
  322. goto getratio;
  323. /* determine the recommended maximum size
  324. for sampling units */
  325. getsize:
  326. dtmp = (ratio > 1) ? 1 / ratio : ratio;
  327. dtmp /= (h_d > v_d) ? h_d * h_d : v_d * v_d;
  328. tryagain:
  329. if (method == 1) {
  330. if (fmask > 0) {
  331. count = 0;
  332. row_buf = Rast_allocate_buf(CELL_TYPE);
  333. fr = Rast_open_old(n1, G_mapset());
  334. for (j = t; j < b; j++) {
  335. Rast_zero_buf(row_buf, CELL_TYPE);
  336. Rast_get_row(fr, row_buf, j, CELL_TYPE);
  337. for (k = l; k < r; k++) {
  338. if (*(row_buf + k))
  339. count++;
  340. }
  341. }
  342. G_free(row_buf);
  343. Rast_close(fr);
  344. cnt = (double)(count);
  345. if (cnt)
  346. cnt = sqrt(cnt);
  347. else
  348. cnt = 0;
  349. maxsize =
  350. ((cnt * dtmp / 2) * (cnt * dtmp / 2) >
  351. 1.0 / dtmp) ? (cnt * dtmp / 2) * (cnt * dtmp /
  352. 2) : 1.0 /
  353. dtmp;
  354. fprintf(stderr,
  355. "\n Recommended maximum SIZE is %d in %d cell total",
  356. maxsize, count);
  357. fprintf(stderr, " area\n");
  358. }
  359. else {
  360. fprintf(stderr, "\n Recommended maximum SIZE is");
  361. fprintf(stderr, " %d in %d pixel total area\n",
  362. (int)((w_l - (int)(start[0])) * (w_w -
  363. (int)(start
  364. [1])) *
  365. dtmp / 2),
  366. (w_l - (int)(start[0])) * (w_w -
  367. (int)(start[1])));
  368. count =
  369. (w_l - (int)(start[0])) * (w_w - (int)(start[1]));
  370. maxsize =
  371. (int)((w_l - (int)(start[0])) * (w_w -
  372. (int)(start[1]))
  373. * dtmp / 2);
  374. }
  375. }
  376. else if (method == 2 || method == 3 || method == 5) {
  377. fprintf(stderr,
  378. "\n Recommended maximum SIZE is %d in %d pixel total",
  379. (int)((w_l - (int)(start[0])) * (w_w -
  380. (int)(start[1]))
  381. * dtmp / 2),
  382. (w_l - (int)(start[0])) * (w_w -
  383. (int)(start[1])));
  384. fprintf(stderr, " area\n");
  385. }
  386. else if (method == 4) {
  387. fprintf(stderr, "\n Recommended maximum SIZE is");
  388. fprintf(stderr, " %d in %d pixel individual",
  389. (int)(w_w * w_l * dtmp / 2),
  390. ((w_w - (int)(start[1])) / h_d) * ((w_l -
  391. (int)(start
  392. [0])) /
  393. v_d));
  394. fprintf(stderr, " stratum area\n");
  395. }
  396. /* get the unit size, display the calculated
  397. size, and ask if it is OK */
  398. fprintf(stderr,
  399. " What size (in pixels) for each sampling unit of scale %d? ",
  400. i + 1);
  401. numtrap(1, &size);
  402. thick = 1;
  403. if (size < 15 || ratio < 0.2 || ratio > 5)
  404. thick = 0;
  405. u_w = sqrt(size * ratio);
  406. u_l = sqrt(size / ratio);
  407. fprintf(stderr,
  408. "\n The nearest size is %d cells wide X %d cells high = %d",
  409. u_w, u_l, u_w * u_l);
  410. fprintf(stderr, " cells\n");
  411. if (!u_w || !u_l) {
  412. fprintf(stderr,
  413. "\n 0 cells wide or high is not acceptable; try again");
  414. goto tryagain;
  415. }
  416. if (!G_yes(" Is this SIZE OK? ", 1))
  417. goto getsize;
  418. }
  419. /* for syst. noncontig. distribution, get
  420. the interval between units */
  421. if (method == 3) {
  422. fprintf(stderr,
  423. "\n The interval, in pixels, between the units of scale");
  424. fprintf(stderr, " %d? ", i + 1);
  425. numtrap(1, &intv);
  426. }
  427. /* if the unit dimension + the interval
  428. is too large, print a warning and
  429. try getting another size */
  430. if (u_w + intv > w_w / h_d || u_l + intv > w_l / v_d) {
  431. fprintf(stderr,
  432. "\n Unit size too large for sampling frame; try again\n");
  433. if (radius)
  434. goto getradius;
  435. else
  436. goto getsize;
  437. }
  438. /* for stratified random distribution,
  439. the number of units is the same as
  440. the number of strata */
  441. if (method == 4)
  442. num = h_d * v_d;
  443. /* for the other distributions, calculate the
  444. maximum number of units, then get the
  445. number of units */
  446. else if (method == 1 || method == 2 || method == 3) {
  447. if (method == 1) {
  448. if (!
  449. (unit_num =
  450. calc_num(w_w, w_l, ratio, u_w, u_l, method, intv,
  451. (int)(start[1]), (int)(start[0]), u_w * u_l,
  452. count))) {
  453. fprintf(stderr,
  454. "\n Something wrong with sampling unit size, try again\n");
  455. if (radius)
  456. goto getradius;
  457. else
  458. goto getsize;
  459. }
  460. fprintf(stderr,
  461. "\n Maximum NUMBER of units in scale %d is %d\n",
  462. i + 1, unit_num);
  463. fprintf(stderr,
  464. " Usually 1/2 of this number can be successfully");
  465. fprintf(stderr,
  466. " distributed\n More than 1/2 can sometimes be");
  467. fprintf(stderr, " distributed\n");
  468. }
  469. else if (method == 2 || method == 3) {
  470. numx = floor((double)(w_w - start[1]) / (u_w + intv));
  471. numy = floor((double)(w_l - start[0]) / (u_l + intv));
  472. if (((w_w -
  473. (int)(start[1])) % (numx * (u_w + (int)(intv)))) >=
  474. u_w)
  475. numx++;
  476. if (((w_l -
  477. (int)(start[0])) % (numy * (u_l + (int)(intv)))) >=
  478. u_l)
  479. numy++;
  480. unit_num = numx * numy;
  481. fprintf(stderr,
  482. "\n Maximum NUMBER of units in scale %d is %d as %d",
  483. i + 1, unit_num, numy);
  484. fprintf(stderr, " rows with %d units per row", numx);
  485. }
  486. do {
  487. fprintf(stderr,
  488. "\n What NUMBER of sampling units do you want to try");
  489. fprintf(stderr, " to use? ");
  490. numtrap(1, &dtmp);
  491. if ((num = dtmp) > unit_num || num < 1) {
  492. fprintf(stderr,
  493. "\n %d is greater than the maximum number of",
  494. num);
  495. fprintf(stderr, " sampling units; try again\n");
  496. }
  497. else if (method == 2 || method == 3) {
  498. fprintf(stderr,
  499. "\n How many sampling units do you want per row? ");
  500. numtrap(1, &dtmp);
  501. if ((nx = dtmp) > num) {
  502. fprintf(stderr,
  503. "\n Number in each row > number requested; try");
  504. fprintf(stderr, " again\n");
  505. }
  506. else {
  507. if (nx > numx) {
  508. fprintf(stderr,
  509. "\n Can't fit %d units in each row, try",
  510. nx);
  511. fprintf(stderr, " again\n");
  512. }
  513. else {
  514. if (num % nx)
  515. ny = num / nx + 1;
  516. else
  517. ny = num / nx;
  518. if (ny > numy) {
  519. fprintf(stderr,
  520. "\n Can't fit the needed %d rows, try",
  521. ny);
  522. fprintf(stderr, " again\n");
  523. }
  524. }
  525. }
  526. }
  527. }
  528. while (num > unit_num || num < 1 || nx > num || nx > numx ||
  529. ny > numy);
  530. }
  531. /* dynamically allocate storage for arrays to
  532. store the upper left corner of sampling
  533. units */
  534. if (method != 5) {
  535. ux = G_calloc(num + 1, sizeof(double));
  536. uy = G_calloc(num + 1, sizeof(double));
  537. }
  538. else {
  539. ux = G_calloc(250, sizeof(double));
  540. uy = G_calloc(250, sizeof(double));
  541. }
  542. /* calculate the upper left corner of sampling
  543. units and store them in arrays ux and uy */
  544. if (!calc_unit_loc
  545. (radius, t, b, l, r, ratio, u_w, u_l, method, intv, num, h_d,
  546. v_d, ux, uy, &sites, (int)(start[1]), (int)(start[0]), fmask,
  547. nx, mx[0], mx[1]))
  548. goto last;
  549. signal(SIGINT, SIG_DFL);
  550. if (method == 5)
  551. num = sites;
  552. /* draw the sampling units on the
  553. screen */
  554. if (method == 2 || method == 3 || method == 5) {
  555. R_open_driver();
  556. R_standard_color(D_translate_color("red"));
  557. for (j = 0; j < num; j++) {
  558. if (radius) {
  559. draw_circle((int)((double)(ux[j]) / mx[0]),
  560. (int)((double)(uy[j]) / mx[1]),
  561. (int)((double)(ux[j] + u_w) / mx[0]),
  562. (int)((double)(uy[j] + u_l) / mx[1]), 3);
  563. }
  564. else {
  565. draw_box((int)((double)(ux[j]) / mx[0]),
  566. (int)((double)(uy[j]) / mx[1]),
  567. (int)((double)(ux[j] + u_w) / mx[0]),
  568. (int)((double)(uy[j] + u_l) / mx[1]), 1);
  569. }
  570. }
  571. R_close_driver();
  572. }
  573. if (G_yes("\n Is this set of sampling units OK? ", 1))
  574. break;
  575. last:
  576. signal(SIGINT, SIG_DFL);
  577. if (G_yes("\n Refresh the screen? ", 1)) {
  578. paint_map(n1, n2, n3);
  579. R_open_driver();
  580. R_standard_color(D_translate_color("grey"));
  581. draw_box((int)(l / mx[0]), (int)(t / mx[1]), (int)(r / mx[0]),
  582. (int)(b / mx[1]), 1);
  583. R_close_driver();
  584. }
  585. }
  586. /* save the sampling unit parameters
  587. in r.le.para/units file */
  588. fprintf(fp, "%10d # of units of scale %d.\n", num, (i + 1));
  589. fprintf(fp, "%10d%10d u_w, u_l of units in scale %d\n", u_w, u_l,
  590. (i + 1));
  591. fprintf(fp, "%10.1f radius of circles in scale %d\n",
  592. radius, (i + 1));
  593. for (j = 0; j < num; j++)
  594. fprintf(fp, "%10d%10d left, top of unit[%d]\n", (int)ux[j],
  595. (int)uy[j], j + 1);
  596. if (i < scales - 1 && G_yes("\n\n Refresh the screen? ", 1)) {
  597. paint_map(n1, n2, n3);
  598. R_open_driver();
  599. R_standard_color(D_translate_color("grey"));
  600. draw_box((int)(l / mx[0]), (int)(t / mx[1]), (int)(r / mx[0]),
  601. (int)(b / mx[1]), 1);
  602. R_close_driver();
  603. }
  604. }
  605. /* free dynamically allocated memory */
  606. G_free(ux);
  607. G_free(uy);
  608. fclose(fp);
  609. return;
  610. }
  611. /* FOR STRATIFIED RANDOM DISTRIBUTION, DRAW THE STRATA ON THE SCREEN */
  612. static void draw_grid(int l, int t, int w_w, int w_l, int h_d, int v_d,
  613. int starty, int startx, double colratio,
  614. double rowratio)
  615. {
  616. int j, k, l0, t0, itmp, dx, dy, initl, tmp;
  617. /* VARIABLES:
  618. k = the remainder after dividing the screen width/height
  619. by the number of strata
  620. dx = how many screen cols per stratum
  621. dy = how many screen rows per stratum
  622. l0 = left side of screen + dx
  623. t0 = top of screen + dy
  624. w_w = width of screen
  625. w_l = height of screen
  626. h_d = number of horizontal strata
  627. v_d = number of vertical strata
  628. */
  629. R_open_driver();
  630. R_standard_color(D_translate_color("orange"));
  631. if (startx > 0) {
  632. dx = (int)((double)((int)(colratio *
  633. ((int)
  634. ((double)(w_w - startx) /
  635. (double)(h_d)))) / colratio + 0.5));
  636. l0 = l + startx;
  637. }
  638. else {
  639. dx = (int)((double)((int)(colratio *
  640. ((int)((double)(w_w) / (double)(h_d)))) /
  641. colratio + 0.5));
  642. l0 = l;
  643. }
  644. if (starty > 0) {
  645. dy = (int)((double)((int)(rowratio *
  646. ((int)
  647. ((double)(w_l - starty) /
  648. (double)(v_d)))) / rowratio + 0.5));
  649. t0 = t + starty;
  650. }
  651. else {
  652. dy = (int)((double)((int)(rowratio *
  653. ((int)((double)(w_l) / (double)(v_d)))) /
  654. rowratio + 0.5));
  655. t0 = t;
  656. }
  657. initl = l0;
  658. /* draw the vertical strata */
  659. for (j = 1; j <= h_d - 1; j++) {
  660. l0 += dx;
  661. R_move_abs(l0, t0);
  662. R_cont_rel(0, w_l - starty);
  663. }
  664. /* draw the horizontal strata */
  665. for (j = 1; j <= v_d - 1; j++) {
  666. t0 += dy;
  667. R_move_abs(initl, t0);
  668. R_cont_rel(w_w - startx, 0);
  669. }
  670. R_close_driver();
  671. return;
  672. }
  673. /* CALCULATE THE COORDINATES OF THE TOP LEFT CORNER OF THE SAMPLING UNITS */
  674. static int calc_unit_loc(double radius, int top, int bot, int left, int right,
  675. double ratio, int u_w, int u_l, int method,
  676. double intv, int num, int h_d, int v_d, double *ux,
  677. double *uy, int *sites, double startx, int starty,
  678. int fmask, double nx, double x, double y)
  679. {
  680. char *sites_mapset, sites_file_name[GNAME_MAX], *cmd;
  681. struct Map_info Map;
  682. struct Cell_head region;
  683. double D_u_to_a_col(), D_u_to_a_row();
  684. int i, j, k, cnt = 0, w_w = right - left, w_l = bot - top, exp1, exp2,
  685. dx = w_w, dy = w_l, l, t, left1 = left, top1 = top, n, tmp,
  686. ulrow, ulcol, *row_buf, lap = 0;
  687. static struct line_pnts *Points;
  688. struct line_cats *Cats;
  689. int ltype;
  690. /* VARIABLES:
  691. UNITS FOR ALL DIMENSION VARIABLES IN THIS ROUTINE ARE IN PIXELS
  692. top = sampling frame top row in pixels
  693. bot = sampling frame bottom row in pixels
  694. left = sampling frame left in pixels
  695. right = sampling frame right in pixels
  696. left1 = col of left side of sampling frame or each stratum
  697. top1 = row of top side of sampling frame or each stratum
  698. l = random # cols to be added to left1
  699. r = random # rows to be added to top1
  700. ratio =
  701. u_w = sampling unit width in pixels
  702. u_l = sampling unit length in pixels
  703. method = method of sampling unit distribution (1-5)
  704. intv = interval between sampling units when method=3
  705. num = number of sampling units
  706. h_d = number of horizontal strata
  707. v_d = number of vertical strata
  708. ux =
  709. uy =
  710. sites =
  711. startx = col of UL corner starting pt for strata
  712. starty = row of UL corner starting pt for strata
  713. dx = number of cols per stratum
  714. dy = number of rows per stratum
  715. w_w = width of sampling frame in cols
  716. w_l = length of sampling frame in rows
  717. */
  718. /* if user hits Ctrl+C, abort this
  719. calculation */
  720. setjmp(jmp);
  721. if (tag) {
  722. tag = 0;
  723. return 0;
  724. }
  725. /* for syst. noncontig. distribution */
  726. if (method == 3) {
  727. u_w += intv;
  728. u_l += intv;
  729. }
  730. /* for stratified random distribution */
  731. if (method == 4) {
  732. dx = (int)((double)(w_w - startx) / (double)(h_d));
  733. dy = (int)((double)(w_l - starty) / (double)(v_d));
  734. }
  735. /* for syst. contig. and noncontig.
  736. distribution */
  737. else if (method == 2 || method == 3) {
  738. if (nx >= num)
  739. dx = (w_w - startx) - (num - 1) * u_w;
  740. else {
  741. dx = (w_w - startx) - (nx - 1) * u_w;
  742. dy = (w_l - starty) - (num / nx - 1) * u_l;
  743. }
  744. }
  745. if (10 > (exp1 = (int)pow(10.0, ceil(log10((double)(dx - u_w + 10))))))
  746. exp1 = 10;
  747. if (10 > (exp2 = (int)pow(10.0, ceil(log10((double)(dy - u_l + 10))))))
  748. exp2 = 10;
  749. /* for random nonoverlapping and stratified
  750. random */
  751. if (method == 1 || method == 4) {
  752. fprintf(stderr,
  753. "\n 'Ctrl+C' and choose fewer units if the requested number");
  754. fprintf(stderr, " is not reached\n");
  755. for (i = 0; i < num; i++) {
  756. /* if Cntl+C */
  757. if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  758. signal(SIGINT, f);
  759. /* for stratified random distribution */
  760. if (method == 4) {
  761. j = 0;
  762. if (n = i % h_d)
  763. left1 += dx;
  764. else {
  765. left1 = left + startx;
  766. if (i < h_d)
  767. top1 = top + starty;
  768. else
  769. top1 += dy;
  770. }
  771. get_rd(exp1, exp2, dx, dy, u_w, u_l, &l, &t);
  772. }
  773. /* for random nonoverlapping distribution */
  774. if (method == 1) {
  775. /* get random numbers */
  776. back:
  777. get_rd(exp1, exp2, dx, dy, u_w, u_l, &l, &t);
  778. if (left1 + l + u_w > right || top1 + t + u_l > bot ||
  779. left1 + l < left || top1 + t < top)
  780. goto back;
  781. /* if there is a mask, check to see that
  782. the unit will be within the mask area */
  783. if (fmask > 0) {
  784. row_buf = Rast_allocate_c_buf();
  785. Rast_get_c_row_nomask(fmask, row_buf, t + top1);
  786. if (!
  787. (*(row_buf + l + left1) &&
  788. *(row_buf + l + left1 + u_w - 1)))
  789. goto back;
  790. Rast_zero_c_buf(row_buf);
  791. Rast_get_c_row_nomask(fmask, row_buf, t + top1 + u_l - 1);
  792. if (!
  793. (*(row_buf + l + left1) &&
  794. *(row_buf + l + left1 + u_w - 1)))
  795. goto back;
  796. G_free(row_buf);
  797. }
  798. /* check for sampling unit overlap */
  799. lap = 0;
  800. for (j = 0; j < cnt; j++) {
  801. if (overlap
  802. (l + left1, t + top1, (int)ux[j], (int)uy[j], u_w,
  803. u_l))
  804. lap = 1;
  805. }
  806. if (lap)
  807. goto back;
  808. cnt++;
  809. }
  810. /* fill the array of upper left coordinates
  811. for the sampling units */
  812. *(ux + i) = l + left1;
  813. *(uy + i) = t + top1;
  814. /* draw the sampling units on the
  815. screen */
  816. R_open_driver();
  817. R_standard_color(D_translate_color("red"));
  818. if (radius)
  819. draw_circle((int)((double)(ux[i]) / x),
  820. (int)((double)(uy[i]) / y),
  821. (int)((double)(ux[i] + u_w) / x),
  822. (int)((double)(uy[i] + u_l) / y), 3);
  823. else
  824. draw_box((int)((double)(ux[i]) / x),
  825. (int)((double)(uy[i]) / y),
  826. (int)((double)(ux[i] + u_w) / x),
  827. (int)((double)(uy[i] + u_l) / y), 1);
  828. R_close_driver();
  829. fprintf(stderr, " Distributed unit %4d of %4d requested\r",
  830. i + 1, num);
  831. }
  832. }
  833. /* for syst. contig. & syst. noncontig. */
  834. else if (method == 2 || method == 3) {
  835. for (i = 0; i < num; i++) {
  836. *(ux + i) =
  837. left + startx + u_w * (i - nx * floor((double)i / nx));
  838. *(uy + i) = top + starty + u_l * floor((double)i / nx);
  839. }
  840. }
  841. /* for centered over sites */
  842. else if (method == 5) {
  843. sites_mapset =
  844. G_ask_vector_old(" Enter name of vector points map",
  845. sites_file_name);
  846. if (sites_mapset == NULL) {
  847. G_system("d.frame -e");
  848. exit(0);
  849. }
  850. Vect_open_old(&Map, sites_file_name, sites_mapset);
  851. /* fprintf(stderr, "\n Can't open vector points file %s\n", sites_file_name); */
  852. *sites = 0;
  853. i = 0;
  854. n = 0;
  855. Points = Vect_new_line_struct(); /* init line_pnts struct */
  856. Cats = Vect_new_cats_struct();
  857. while (1) {
  858. ltype = Vect_read_next_line(&Map, Points, Cats);
  859. if (ltype == -1)
  860. G_fatal_error(_("Cannot read vector"));
  861. if (ltype == -2)
  862. break; /* EOF */
  863. /* point features only. (GV_POINTS is pts AND centroids, GV_POINT is just pts) */
  864. if (!(ltype & GV_POINT))
  865. continue;
  866. ulcol = ((int)(D_u_to_a_col(Points->x[0]))) + 1 - u_w / 2;
  867. ulrow = ((int)(D_u_to_a_row(Points->y[0]))) + 1 - u_l / 2;
  868. if (ulcol <= left || ulrow <= top || ulcol + u_w - 1 > right ||
  869. ulrow + u_l - 1 > bot) {
  870. fprintf(stderr,
  871. " No sampling unit over site %d at east=%8.1f north=%8.1f\n",
  872. n + 1, Points->x[0], Points->y[0]);
  873. fprintf(stderr,
  874. " as it would extend outside the map\n");
  875. }
  876. else {
  877. *(ux + i) = ulcol - 1;
  878. *(uy + i) = ulrow - 1;
  879. i++;
  880. }
  881. n++;
  882. if (n > 250)
  883. G_fatal_error
  884. ("There are more than the maximum of 250 sites\n");
  885. }
  886. fprintf(stderr, " Total sites with sampling units = %d\n", i);
  887. *sites = i;
  888. cmd = G_malloc(100);
  889. sprintf(cmd, "d.vect %s color=black", sites_file_name);
  890. G_system(cmd);
  891. G_free(cmd);
  892. Vect_close(&Map);
  893. G_free(Points);
  894. G_free(Cats);
  895. }
  896. return 1;
  897. }
  898. /* FIND THE CORRECT RANDOM NUMBER */
  899. static void get_rd(int exp1, int exp2, int dx, int dy, int u_w, int u_l,
  900. int *l, int *t)
  901. {
  902. int rdl, rdt;
  903. do {
  904. rdl = rand();
  905. *l = rdl % exp1;
  906. rdt = rand();
  907. *t = rdt % exp2;
  908. }
  909. while (dx < *l + u_w || dy < *t + u_l);
  910. return;
  911. }
  912. /* */
  913. static RETSIGTYPE f(int sig)
  914. {
  915. tag = 1;
  916. longjmp(jmp, 1);
  917. return;
  918. }
  919. /* CHECK IF 2 SAMPLING UNITS OVERLAP */
  920. static int overlap(int x1, int y1, int x2, int y2, int dx, int dy)
  921. {
  922. if (x1 >= x2 + dx || x2 >= x1 + dx || y1 >= y2 + dy || y2 >= y1 + dy)
  923. return 0;
  924. else
  925. return 1;
  926. }
  927. /* CALCULATE MAXIMUM POSSIBLE NUMBER OF SAMPLING UNITS */
  928. static int calc_num(int w_w, int w_l, double ratio, int u_w, int u_l,
  929. int method, double intv, int startx, int starty, int size,
  930. int count)
  931. {
  932. int nx, ny, max;
  933. /* for random nonoverlapping */
  934. if (method == 1) {
  935. max = count / size;
  936. }
  937. /* for syst. contig. distribution */
  938. else if (method == 2) {
  939. nx = floor((double)(w_w - startx) / u_w);
  940. ny = floor((double)(w_l - starty) / u_l);
  941. max = nx * ny;
  942. }
  943. /* for syst. noncontig. distribution */
  944. else if (method == 3) {
  945. nx = floor((double)(w_w - startx) / (u_w + intv));
  946. ny = floor((double)(w_l - starty) / (u_l + intv));
  947. max = nx * ny;
  948. }
  949. return max;
  950. }
  951. /* USE THE MOUSE TO DEFINE SAMPLING
  952. UNITS GRAPHICALLY */
  953. static void graph_unit(int t, int b, int l, int r, char *n1, char *n2,
  954. char *n3, double *mx, int fmask)
  955. {
  956. int x0 = 0, y0 = 0, xp, yp, ux[250], uy[250], u_w, u_l, btn = 0, k = 0,
  957. w_w = 0, w_l = 0, *row_buf, at, ab, al, ar, circle = 0,
  958. tmpw, tmpl, au_w, au_l, lap = 0, l0 = 0, r0 = 0, t0 = 0, b0 = 0;
  959. FILE *fp;
  960. double tmp, radius = 0.0;
  961. register int i, j;
  962. /* VARIABLES:
  963. COORDINATES IN THIS ROUTINE ARE IN CELLS
  964. t = top row of sampling frame
  965. b = bottom row of sampling frame
  966. l = left col of sampling frame
  967. r = right col of sampling frame
  968. n1 =
  969. n2 =
  970. n3 =
  971. mx[0] = cols of region/width of screen
  972. mx[1] = rows of region/height of screen
  973. xp = mouse x location in screen coordinates (col)
  974. yp = mouse y location in screen coordinates (row)
  975. ar = mouse x location in map coordinates (col)
  976. al = mouse y location in map coordinates (row)
  977. */
  978. l0 = l;
  979. r0 = r;
  980. t0 = t;
  981. b0 = b;
  982. l = (int)((double)(l * mx[0]) + 0.5);
  983. r = (int)((double)(r * mx[0]) + 0.5);
  984. t = (int)((double)(t * mx[1]) + 0.5);
  985. b = (int)((double)(b * mx[1]) + 0.5);
  986. w_w = r - l;
  987. w_l = b - t;
  988. /* draw the sampling frame */
  989. R_open_driver();
  990. R_standard_color(D_translate_color("grey"));
  991. draw_box((int)(l / mx[0]), (int)(t / mx[1]), (int)(r / mx[0]),
  992. (int)(b / mx[1]), 1);
  993. R_close_driver();
  994. fp = fopen0("r.le.para/units", "w");
  995. G_sleep_on_error(0);
  996. /* get the number of scales */
  997. do {
  998. fprintf(stderr,
  999. "\n How many different SCALES do you want? (1-15) ");
  1000. numtrap(1, &tmp);
  1001. if (tmp < 1 || tmp > 15)
  1002. fprintf(stderr,
  1003. " Too many (>15) or too few scales, try again.\n");
  1004. }
  1005. while (tmp < 1 || tmp > 15);
  1006. fprintf(fp, "%10d # of scales\n", (int)(tmp));
  1007. /* for each scale */
  1008. for (i = 0; i < tmp; i++) {
  1009. G_system("clear");
  1010. radius = 0.0;
  1011. circle = 0;
  1012. /* if sampling using circles */
  1013. fprintf(stderr, "\n SCALE %d\n", i + 1);
  1014. fprintf(stderr, "\n Do you want to sample using rectangles");
  1015. if (!G_yes("\n (including squares) (y) or circles (n)? ", 1)) {
  1016. circle = 1;
  1017. fprintf(stderr,
  1018. "\n Draw a rectangular area to contain a standard circular");
  1019. fprintf(stderr,
  1020. "\n sampling unit of scale %d. First select upper left",
  1021. i + 1);
  1022. fprintf(stderr, "\n corner, then lower right:\n");
  1023. fprintf(stderr, " Left button: Check unit size\n");
  1024. fprintf(stderr,
  1025. " Middle button: Upper left corner of area here\n");
  1026. fprintf(stderr,
  1027. " Right button: Lower right corner of area here\n");
  1028. }
  1029. else {
  1030. fprintf(stderr,
  1031. "\n Draw a standard rectangular unit of scale %d.",
  1032. i + 1);
  1033. fprintf(stderr,
  1034. "\n First select upper left corner, then lower right:\n");
  1035. fprintf(stderr, " Left button: Check unit size\n");
  1036. fprintf(stderr,
  1037. " Middle button: Upper left corner of unit here\n");
  1038. fprintf(stderr,
  1039. " Right button: Lower right corner of unit here\n");
  1040. }
  1041. R_open_driver();
  1042. do {
  1043. back1:
  1044. R_get_location_with_box(x0, y0, &xp, &yp, &btn);
  1045. /* convert the upper left screen coordinate
  1046. (x0, y0) and the mouse position (xp, yp)
  1047. on the screen to the nearest row and
  1048. column; do the same for the sampling
  1049. unit width (u_w) and height (u_l);
  1050. then convert back */
  1051. ar = (int)((double)(xp) * mx[0] + 0.5);
  1052. xp = (int)((double)(ar) / mx[0] + 0.5);
  1053. al = (int)((double)(x0) * mx[0] + 0.5);
  1054. x0 = (int)((double)(al) / mx[0] + 0.5);
  1055. au_w = ar - al;
  1056. u_w = (int)((double)(au_w) / mx[0] + 0.5);
  1057. ab = (int)((double)(yp) * mx[1] + 0.5);
  1058. yp = (int)((double)(ab) / mx[1] + 0.5);
  1059. at = (int)((double)(y0) * mx[1] + 0.5);
  1060. y0 = (int)((double)(at) / mx[1] + 0.5);
  1061. au_l = ab - at;
  1062. u_l = (int)((double)(au_l) / mx[1] + 0.5);
  1063. /* left button, check the size of the rubber
  1064. box in array system */
  1065. if (btn == 1) {
  1066. if (ar > r || ab > b || ar < l || ab < t) {
  1067. fprintf(stderr,
  1068. "\n This point is not in the sampling frame; try again\n");
  1069. goto back1;
  1070. }
  1071. if (x0 < l || y0 < t) {
  1072. fprintf(stderr,
  1073. "\n Use the middle button to first put the upper left");
  1074. fprintf(stderr,
  1075. "\n corner inside the sampling frame\n");
  1076. goto back1;
  1077. }
  1078. if (ar <= al || ab <= at) {
  1079. fprintf(stderr,
  1080. "\n Please put the lower right corner down and to");
  1081. fprintf(stderr,
  1082. "\n the right of the upper left corner\n");
  1083. goto back1;
  1084. }
  1085. else {
  1086. fprintf(stderr,
  1087. "\n Unit would be %d columns wide by %d rows long\n",
  1088. abs(au_w), abs(au_l));
  1089. fprintf(stderr,
  1090. " Width/length would be %5.2f and size %d pixels\n",
  1091. (double)abs((au_w)) / (double)abs((au_l)),
  1092. abs(au_w) * abs(au_l));
  1093. }
  1094. }
  1095. /* mid button, move the start point of the
  1096. rubber box */
  1097. else if (btn == 2) {
  1098. if (ar > r || ab > b || ar < l || ab < t) {
  1099. fprintf(stderr,
  1100. "\n Point is not in the sampling frame; try again\n");
  1101. goto back1;
  1102. }
  1103. else {
  1104. R_move_abs(xp, yp);
  1105. x0 = xp;
  1106. y0 = yp;
  1107. }
  1108. }
  1109. /* right button, outline the unit */
  1110. else if (btn == 3) {
  1111. if (circle) {
  1112. if (u_w > u_l) {
  1113. al = al + ((ar - al) - (ab - at)) / 2;
  1114. ar = al + (ab - at);
  1115. x0 = (int)((double)(al) / mx[0] + 0.5);
  1116. xp = (int)((double)(ar) / mx[0] + 0.5);
  1117. au_w = ar - al;
  1118. u_w = u_l = (int)((double)(au_w) / mx[0] + 0.5);
  1119. }
  1120. if (u_l > u_w) {
  1121. at = at + ((ab - at) - (ar - al)) / 2;
  1122. ab = at + (ar - al);
  1123. y0 = (int)((double)(at) / mx[1] + 0.5);
  1124. yp = (int)((double)(ab) / mx[1] + 0.5);
  1125. au_l = ab - at;
  1126. u_w = u_l = (int)((double)(au_l) / mx[1] + 0.5);
  1127. }
  1128. }
  1129. if (ar > r || ab > b || al < l || at < t) {
  1130. fprintf(stderr,
  1131. "\n The unit extends outside the sampling frame or map;");
  1132. fprintf(stderr, "\n try again\n");
  1133. goto back1;
  1134. }
  1135. if (au_w > w_w || au_l > w_l) {
  1136. fprintf(stderr,
  1137. "\n The unit is too big for the sampling frame; ");
  1138. fprintf(stderr, "try again\n");
  1139. goto back1;
  1140. }
  1141. /* if there is a mask, check to see that
  1142. the unit will be within the mask area,
  1143. by checking to see whether the four
  1144. corners of the unit are in the mask */
  1145. if (fmask > 0) {
  1146. row_buf = Rast_allocate_c_buf();
  1147. Rast_get_c_row_nomask(fmask, row_buf, at);
  1148. if (!(*(row_buf + al) && *(row_buf + ar - 1))) {
  1149. fprintf(stderr,
  1150. "\n The unit would be outside the mask; ");
  1151. fprintf(stderr, "try again\n");
  1152. G_free(row_buf);
  1153. goto back1;
  1154. }
  1155. Rast_zero_c_buf(row_buf);
  1156. Rast_get_c_row_nomask(fmask, row_buf, ab - 1);
  1157. if (!(*(row_buf + al) && *(row_buf + ar - 1))) {
  1158. fprintf(stderr,
  1159. "\n The unit would be outside the mask; ");
  1160. fprintf(stderr, "try again\n");
  1161. G_free(row_buf);
  1162. goto back1;
  1163. }
  1164. G_free(row_buf);
  1165. }
  1166. if (xp - x0 > 0 && yp - y0 > 0) {
  1167. R_standard_color(D_translate_color("red"));
  1168. if (circle)
  1169. draw_circle(x0, y0, xp, yp, 3);
  1170. else
  1171. draw_box(x0, y0, xp, yp, 1);
  1172. G_system("clear");
  1173. if (circle) {
  1174. fprintf(stderr,
  1175. "\n\n The standard circular sampling unit has:\n");
  1176. fprintf(stderr, " radius = %f pixels\n",
  1177. (double)(ar - al) / 2.0);
  1178. }
  1179. else {
  1180. fprintf(stderr,
  1181. "\n\n The standard sampling unit has:\n");
  1182. fprintf(stderr, " columns=%d rows=%d\n",
  1183. abs(ar - al), abs(ab - at));
  1184. fprintf(stderr, " width/length ratio=%5.2f\n",
  1185. (double)abs(ar - al) / (double)abs(ab - at));
  1186. fprintf(stderr, " size=%d pixels\n",
  1187. abs(ar - al) * abs(ab - at));
  1188. }
  1189. k = 0;
  1190. ux[0] = al;
  1191. uy[0] = at;
  1192. }
  1193. else if (xp - x0 == 0 || yp - y0 == 0) {
  1194. fprintf(stderr,
  1195. "\n Unit has 0 rows and/or 0 columns; try again\n");
  1196. goto back1;
  1197. }
  1198. else {
  1199. fprintf(stderr,
  1200. "\n You did not put the lower right corner below");
  1201. fprintf(stderr,
  1202. "\n and to the right of the upper left corner. Please try again");
  1203. goto back1;
  1204. }
  1205. }
  1206. }
  1207. while (btn != 3);
  1208. R_close_driver();
  1209. /* use the size and shape of the
  1210. standard unit to outline more units
  1211. in that scale */
  1212. fprintf(stderr, "\n Outline more sampling units of scale %d?\n",
  1213. i + 1);
  1214. fprintf(stderr, " Left button: Exit\n");
  1215. fprintf(stderr, " Middle button: Check unit position\n");
  1216. fprintf(stderr,
  1217. " Right button: Lower right corner of next unit here\n");
  1218. R_open_driver();
  1219. /* if not the left button (to exit) */
  1220. back2:
  1221. while (btn != 1) {
  1222. R_get_location_with_box(xp - u_w, yp - u_l, &xp, &yp, &btn);
  1223. /* convert the left (x0), right (y0),
  1224. top (y0), bottom (yp) coordinates in
  1225. screen pixels to the nearest row and
  1226. column; do the same for the sampling
  1227. unit width (u_w) and height (u_l);
  1228. then convert back */
  1229. ar = (int)((double)(xp) * mx[0] + 0.5);
  1230. ab = (int)((double)(yp) * mx[1] + 0.5);
  1231. xp = (int)((double)(ar) / mx[0] + 0.5);
  1232. yp = (int)((double)(ab) / mx[1] + 0.5);
  1233. al = (int)((double)(xp - u_w) * mx[0] + 0.5);
  1234. at = (int)((double)(yp - u_l) * mx[0] + 0.5);
  1235. x0 = (int)((double)(al) / mx[0] + 0.5);
  1236. y0 = (int)((double)(at) / mx[1] + 0.5);
  1237. /* if right button, outline the unit */
  1238. if (btn == 3) {
  1239. if (ar > r || ab > b || al < l || at < t) {
  1240. fprintf(stderr,
  1241. "\n The unit would be outside the map; try again");
  1242. goto back2;
  1243. }
  1244. /* if there is a mask, check to see that
  1245. the unit will be within the mask area */
  1246. if (fmask > 0) {
  1247. row_buf = Rast_allocate_c_buf();
  1248. Rast_get_c_row_nomask(fmask, row_buf, at);
  1249. if (!(*(row_buf + al) && *(row_buf + ar - 1))) {
  1250. fprintf(stderr,
  1251. "\n The unit would be outside the mask; ");
  1252. fprintf(stderr, "try again");
  1253. G_free(row_buf);
  1254. goto back2;
  1255. }
  1256. Rast_zero_c_buf(row_buf);
  1257. Rast_get_c_row_nomask(fmask, row_buf, ab - 1);
  1258. if (!(*(row_buf + al) && *(row_buf + ar - 1))) {
  1259. fprintf(stderr,
  1260. "\n The unit would be outside the mask; ");
  1261. fprintf(stderr, "try again");
  1262. G_free(row_buf);
  1263. goto back2;
  1264. }
  1265. G_free(row_buf);
  1266. }
  1267. /* check for sampling unit overlap */
  1268. lap = 0;
  1269. for (j = 0; j < k + 1; j++) {
  1270. if (overlap(al, at, ux[j], uy[j], au_w, au_l)) {
  1271. fprintf(stderr,
  1272. "\n The unit would overlap a previously drawn ");
  1273. fprintf(stderr, "unit; try again");
  1274. lap = 1;
  1275. }
  1276. }
  1277. if (lap)
  1278. goto back2;
  1279. k++;
  1280. fprintf(stderr, "\n %d sampling units have been placed",
  1281. (k + 1));
  1282. ux[k] = al;
  1283. uy[k] = at;
  1284. R_standard_color(D_translate_color("red"));
  1285. if (circle)
  1286. draw_circle(x0, y0, xp, yp, 3);
  1287. else
  1288. draw_box(x0, y0, xp, yp, 1);
  1289. }
  1290. }
  1291. R_close_driver();
  1292. /* save the sampling units in the
  1293. r.le.para/units file */
  1294. if (circle)
  1295. radius = (double)(ar - al) / 2.0;
  1296. else
  1297. radius = 0.0;
  1298. fprintf(fp, "%10d # of units of scale %d\n", k + 1, i + 1);
  1299. fprintf(fp, "%10d%10d u_w, u_l of units in scale %d\n",
  1300. (int)(u_w * mx[0]), (int)(u_l * mx[1]), i + 1);
  1301. fprintf(fp, "%10.1f radius of circles in scale %d\n",
  1302. radius, (i + 1));
  1303. for (j = 0; j < k + 1; j++)
  1304. fprintf(fp, "%10d%10d left, top of unit[%d]\n", ux[j], uy[j],
  1305. j + 1);
  1306. if (i < tmp - 1 && G_yes("\n Refresh the screen? ", 1)) {
  1307. paint_map(n1, n2, n3);
  1308. R_open_driver();
  1309. R_standard_color(D_translate_color("red"));
  1310. R_close_driver();
  1311. }
  1312. }
  1313. fclose(fp);
  1314. return;
  1315. }
  1316. /* DRAW A RECTANGULAR BOX WITH THICKNESS OF "THICK" */
  1317. void draw_box(int x0, int y0, int xp, int yp, int thick)
  1318. {
  1319. int i;
  1320. /*PARAMETERS:
  1321. x0 = leftmost position
  1322. y0 = topmost position
  1323. xp = rightmost position
  1324. yp = bottommost position
  1325. thick = thickness
  1326. i = individual screen pixels
  1327. */
  1328. for (i = 0; i <= thick; i++) {
  1329. R_move_abs(x0 + i, y0 + i);
  1330. R_cont_abs(x0 + i, yp - i);
  1331. R_cont_abs(xp - i, yp - i);
  1332. R_cont_abs(xp - i, y0 + i);
  1333. R_cont_abs(x0 + i, y0 + i);
  1334. R_move_abs(x0 - i, y0 - i);
  1335. R_cont_abs(x0 - i, yp + i);
  1336. R_cont_abs(xp + i, yp + i);
  1337. R_cont_abs(xp + i, y0 - i);
  1338. R_cont_abs(x0 - i, y0 - i);
  1339. }
  1340. R_flush();
  1341. return;
  1342. }
  1343. /* DRAW A CIRCLE WITH THICKNESS OF "THICK" */
  1344. void draw_circle(int x0, int y0, int xp, int yp, int thick)
  1345. {
  1346. int i, j, xstart, ystart, x2, yr;
  1347. double ang, xinc, yinc;
  1348. /*PARAMETERS
  1349. x0 = leftmost position of enclosing square
  1350. y0 = topmost position of enclosing square
  1351. xp = rightmost position of enclosing square
  1352. yp = bottommost position of enclosing square
  1353. thick = thickness in screen pixels for drawing lines
  1354. i = index for incrementing process
  1355. j = individual screen pixels
  1356. x1 = x coordinate of point where
  1357. circle touches enclosing square
  1358. ang = angle in radians that is the
  1359. angle to be moved in connecting
  1360. a straight line segment to the
  1361. previous location
  1362. */
  1363. for (j = 0; j < thick; j++) {
  1364. xstart = x0 + (xp - x0) / 2;
  1365. ystart = y0 + j;
  1366. ang = 0.049087385;
  1367. R_move_abs(xstart, ystart);
  1368. for (i = 1; i < 129; i++) {
  1369. xinc = cos((double)i * ang / 2.0) * sin((double)i * ang / 2.0) *
  1370. (double)(yp - y0 - 2 * j);
  1371. yinc = sin((double)i * ang / 2.0) * sin((double)i * ang / 2.0) *
  1372. (double)(yp - y0 - 2 * j);
  1373. R_cont_abs(xstart + (int)xinc, ystart + (int)yinc);
  1374. }
  1375. }
  1376. R_flush();
  1377. return;
  1378. }
  1379. /* READ USER DIGITAL INPUT FROM THE SCREEN */
  1380. void numtrap(int n, double *a)
  1381. {
  1382. char num[31], *s;
  1383. int i = 0, j, k = 1, c;
  1384. while (i < n) {
  1385. s = num;
  1386. /* find the first period, minus sign,
  1387. or digit in the user input */
  1388. while ((c = getchar()) != '.' && c != '-' && !isdigit(c)) ;
  1389. /* if it is a decimal pt, then get
  1390. characters as long as they are
  1391. digits and append them to the
  1392. end of the num array */
  1393. if (c == '.') {
  1394. *s++ = c;
  1395. while ((c = getchar()) && isdigit(c) && k < 30) {
  1396. *s++ = c;
  1397. k++;
  1398. }
  1399. }
  1400. /* if it is not a period, but
  1401. is a minus sign or digit, then
  1402. get characters as long as they
  1403. are digits and append them to the
  1404. end of the num array. If a decimal
  1405. pt is found, then append this also
  1406. and keep getting digits */
  1407. else if (isdigit(c) || c == '-') {
  1408. *s++ = c;
  1409. while ((c = getchar()) && isdigit(c) && k < 30) {
  1410. *s++ = c;
  1411. k++;
  1412. }
  1413. if (c == '.') {
  1414. *s++ = c;
  1415. while ((c = getchar()) && isdigit(c) && k < 30) {
  1416. *s++ = c;
  1417. k++;
  1418. }
  1419. }
  1420. }
  1421. *s = '\0';
  1422. /* once the user's input has been
  1423. read, convert the digits of the num
  1424. array into a double and store it
  1425. in the i++ element of the "a" array */
  1426. *(a + i++) = atof(num);
  1427. /* keep getting characters as long as
  1428. they are not spaces, commas, tabs,
  1429. or end of line */
  1430. while (c != ' ' && c != ',' && c != '\t' && c != '\n')
  1431. c = getchar();
  1432. }
  1433. return;
  1434. }