1 /*
2 Copyright (c) 2005-2022 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 // Polygon overlay
18 //
19 // Don't want warnings about deprecated sscanf, getenv
20 #ifndef _CRT_SECURE_NO_DEPRECATE
21 #define _CRT_SECURE_NO_DEPRECATE
22 #endif
23 #define _MAIN_C_ 1
24
25 #include <cstring>
26
27 #include <iostream>
28 #include <iomanip>
29 #include <algorithm>
30
31 #include "oneapi/tbb/tick_count.h"
32
33 #include "pover_global.hpp"
34 #include "polyover.hpp"
35 #include "pover_video.hpp"
36 #include "polymain.hpp"
37
38 #if _DEBUG
39 const char *faceNames[] = { "North", "East", "South", "West" };
40 #endif
41
42 /**
43 **/
main(int argc,char * argv[])44 int main(int argc, char *argv[]) {
45 pover_video poly;
46 poly.threaded = true;
47 gVideo = &poly;
48
49 if (!initializeVideo(argc, argv)) {
50 return -1;
51 }
52
53 gIsGraphicalVersion = poly.graphic_display();
54 if (argc > 1) {
55 if (!ParseCmdLine(argc, argv)) {
56 if (gIsGraphicalVersion)
57 rt_sleep(10000);
58 // if graphical, we haven't opened the console window so all the error messages we
59 // so carefully wrote out disappeared into the ether. :(
60 return -1;
61 }
62 }
63
64 if (gCsvFilename != nullptr) {
65 #define BUFLEN 1000
66 std::string fname_buf = gCsvFilename;
67 fname_buf += ".csv";
68 gCsvFile.open(fname_buf.c_str());
69 }
70
71 // we have gMapXSize and gMapYSize determining the number of "squares"
72 // we have g_xwinsize and g_ywinsize the total size of the window
73 // we also have BORDER_SIZE the size of the border between maps
74 // we need to determine
75 // g_polyBoxSize -- the number of pixels on each size of each square
76
77 if (gIsGraphicalVersion) {
78 int xpixelsPerMap =
79 (g_xwinsize - 4 * BORDER_SIZE) / 3; // three maps, with borders between and outside
80 gMapXSize = xpixelsPerMap; // make the boxes one per pixel
81 gPolyXBoxSize = xpixelsPerMap / gMapXSize;
82 int ypixelsPerMap = (g_ywinsize - 2 * BORDER_SIZE); // one map vertically
83 gMapYSize = ypixelsPerMap; // one pixel per box, rather.
84
85 gPolyYBoxSize = ypixelsPerMap / gMapYSize;
86 if ((gPolyXBoxSize == 0) || (gPolyYBoxSize == 0)) {
87 std::cout << "The display window is not large enough to show the maps"
88 << "\n";
89 int minxSize = 4 * BORDER_SIZE + 3 * gMapXSize;
90 int minySize = 2 * BORDER_SIZE + gMapYSize;
91 std::cout << " Should be at least " << minxSize << " x " << minySize << "."
92 << "\n";
93 return -1;
94 }
95 map2XLoc = 2 * BORDER_SIZE + gMapXSize * gPolyXBoxSize;
96 maprXLoc = 3 * BORDER_SIZE + 2 * gMapXSize * gPolyXBoxSize;
97 }
98 else { // not gIsGraphicalVersion
99 // gMapXSize, gMapYSize, gNPolygons defined in pover_global.h
100 }
101
102 // create two polygon maps
103 SetRandomSeed(gMyRandomSeed); // for repeatability
104
105 gVideo->main_loop();
106
107 return 0;
108 }
109
Usage(int argc,char * argv[])110 void Usage(int argc, char *argv[]) {
111 char *cmdTail = strrchr(*argv, '\\');
112 if (cmdTail == nullptr) {
113 cmdTail = *argv;
114 }
115 else {
116 cmdTail++;
117 }
118 std::cout
119 << cmdTail
120 << " [threads[:threads2]] [--polys npolys] [--size nnnxnnn] [--seed nnn] [--csv filename] [--grainsize n] [--use_malloc]"
121 << "\n";
122 std::cout << "Create polygon maps and overlay them."
123 << "\n"
124 << "\n";
125 std::cout << "Parameters:"
126 << "\n";
127 std::cout << " threads[:threads2] - number of threads to run"
128 << "\n";
129 std::cout << " --polys npolys - number of polygons in each map"
130 << "\n";
131 std::cout << " --size nnnxnnn - size of each map (X x Y)"
132 << "\n";
133 std::cout << " --seed nnn - initial value of random number generator"
134 << "\n";
135 std::cout << " --csv filename - write timing data to CSV-format file"
136 << "\n";
137 std::cout << " --grainsize n - set grainsize to n"
138 << "\n";
139 std::cout << " --use_malloc - allocate polygons with malloc instead of scalable allocator"
140 << "\n";
141 std::cout << "\n";
142 std::cout << "npolys must be smaller than the size of the map"
143 << "\n";
144 std::cout << "\n";
145 std::exit(-1);
146 }
147
ParseCmdLine(int argc,char * argv[])148 bool ParseCmdLine(int argc, char *argv[]) {
149 bool error_found = false;
150 bool nPolysSpecified = false;
151 bool nMapSizeSpecified = false;
152 bool nSeedSpecified = false;
153 bool csvSpecified = false;
154 bool grainsizeSpecified = false;
155 bool mallocSpecified = false;
156 int origArgc = argc;
157 char **origArgv = argv;
158 unsigned int newnPolygons = gNPolygons;
159 unsigned int newSeed = gMyRandomSeed;
160 unsigned int newX = gMapXSize;
161 unsigned int newY = gMapYSize;
162 unsigned int newGrainSize = gGrainSize;
163 argc--;
164 argv++;
165 if (argc > 0 && isdigit((*argv)[0])) {
166 // first argument is one or two numbers, specifying how mny threads to run
167 char *end;
168 gThreadsHigh = gThreadsLow = (int)strtol(argv[0], &end, 0);
169 switch (*end) {
170 case ':': gThreadsHigh = (int)strtol(end + 1, nullptr, 0); break;
171 case '\0': break;
172 default:
173 std::cout << "Unexpected character in thread specifier: " << *end << "\n";
174 break;
175 }
176 if (gThreadsLow > gThreadsHigh) {
177 int t = gThreadsLow;
178 gThreadsLow = gThreadsHigh;
179 gThreadsHigh = t;
180 }
181 argv++;
182 argc--;
183 }
184 while (argc > 0) {
185 // format 1: --size nnnxnnn, where nnn in {0 .. 9}+ -- size of map in "squares"
186 if (!strncmp("--size", *argv, (std::size_t)6)) {
187 if (nMapSizeSpecified) {
188 std::cout << " Error: map size multiply specified"
189 << "\n";
190 error_found = true;
191 }
192 else {
193 argv++;
194 argc--;
195 if (argc == 0) {
196 error_found = true;
197 std::cout << " Error: --size must have a value"
198 << "\n";
199 }
200 if (strchr(*argv, 'x') != strrchr(*argv, 'x')) {
201 // more than one 'x'
202 std::cout << "Error: map size should be nnnxnnn (" << *argv << ")"
203 << "\n";
204 error_found = true;
205 }
206 else {
207 int rval;
208 rval = sscanf(*argv, "%ux%u", &newX, &newY);
209 if (rval != 2) {
210 std::cout << "Error parsing map size (format should be nnnxnnn (" << *argv
211 << ")"
212 << "\n";
213 error_found = true;
214 }
215 if (newX == 0 || newY == 0) {
216 std::cout << "Error: size of map should be greater than 0 (" << *argv << ")"
217 << "\n";
218 error_found = true;
219 }
220 }
221 }
222 argc--;
223 argv++;
224 }
225 // format 2: --seed nnn -- initial random number seed
226 else if (!strncmp("--seed", *argv, (std::size_t)6)) {
227 argv++;
228 argc--;
229 if (nSeedSpecified) {
230 std::cout << "Error: new seed multiply specified"
231 << "\n";
232 error_found = true;
233 }
234 else {
235 nSeedSpecified = true;
236 int rtval = sscanf(*argv, "%u", &newSeed);
237 if (rtval == 0) {
238 std::cout << "Error: --seed should be an unsigned number (instead of " << *argv
239 << ")"
240 << "\n";
241 error_found = true;
242 }
243 }
244 argv++;
245 argc--;
246 }
247 // format 3: --polys n[n] -- number of polygons in each map
248 else if (!strncmp("--polys", *argv, (std::size_t)7)) {
249 //unsigned int newnPolygons;
250 argv++;
251 argc--;
252 if (nPolysSpecified) {
253 std::cout << "Error: number of polygons multiply-specified"
254 << "\n";
255 error_found = true;
256 }
257 else {
258 int rtval = sscanf(*argv, "%u", &newnPolygons);
259 if (newnPolygons == 0) {
260 std::cout << "Error: number of polygons must be greater than 0 (" << *argv
261 << ")"
262 << "\n";
263 }
264 }
265 argv++;
266 argc--;
267 }
268 // format 4: --csv <fileroot> -- name of CSV output file ("xxx" for "xxx.csv")
269 else if (!strncmp("--csv", *argv, (std::size_t)5)) {
270 argv++;
271 argc--;
272 if (csvSpecified) {
273 std::cout << "Error: Multiple specification of CSV file"
274 << "\n";
275 error_found = true;
276 }
277 else {
278 gCsvFilename = *argv;
279 argv++;
280 argc--;
281 csvSpecified = true;
282 }
283 }
284 else if (!strncmp("--grainsize", *argv, (std::size_t)11)) {
285 argv++;
286 argc--;
287 if (grainsizeSpecified) {
288 std::cout << "Error: Multiple specification of grainsize"
289 << "\n";
290 error_found = true;
291 }
292 else {
293 int grval = sscanf(*argv, "%u", &newGrainSize);
294 grainsizeSpecified = true;
295 if (newGrainSize == 0) {
296 std::cout << "Error: grainsize must be greater than 0"
297 << "\n";
298 error_found = true;
299 }
300 }
301 argv++;
302 argc--;
303 }
304 else if (!strncmp("--use_malloc", *argv, (std::size_t)12)) {
305 argv++;
306 argc--;
307 if (mallocSpecified) {
308 std::cout << "Error: --use_malloc multiply-specified"
309 << "\n";
310 error_found = true;
311 }
312 else {
313 mallocSpecified = true;
314 gMBehavior = UseMalloc;
315 }
316 }
317 else {
318 std::cout << "Error: unrecognized argument: " << *argv << "\n";
319 error_found = true;
320 argv++;
321 argc--;
322 }
323 }
324 if (!error_found) {
325 if (newX * newY < newnPolygons) {
326 error_found = true;
327 std::cout
328 << "Error: map size should not be smaller than the number of polygons (gNPolygons = "
329 << newnPolygons << ", map size " << newX << "x" << newY << ")"
330 << "\n";
331 }
332 }
333 if (!error_found) {
334 gMapXSize = newX;
335 gMapYSize = newY;
336 gNPolygons = newnPolygons;
337 gMyRandomSeed = newSeed;
338 gGrainSize = (int)newGrainSize;
339 }
340 else {
341 Usage(origArgc, origArgv);
342 }
343 return !error_found;
344 }
345
346 // create a polygon map with at least gNPolygons polygons.
347 // Usually more than gNPolygons polygons will be generated, because the
348 // process of growing the polygons results in holes.
GenerateMap(Polygon_map_t ** newMap,int xSize,int ySize,int gNPolygons,colorcomp_t maxR,colorcomp_t maxG,colorcomp_t maxB)349 bool GenerateMap(Polygon_map_t **newMap,
350 int xSize,
351 int ySize,
352 int gNPolygons,
353 colorcomp_t maxR,
354 colorcomp_t maxG,
355 colorcomp_t maxB) {
356 bool error_found = false;
357 int *validPolys;
358 int *validSide;
359 int maxSides;
360 RPolygon *newPoly;
361
362 if (xSize <= 0) {
363 std::cout << "xSize (" << xSize << ") should be > 0."
364 << "\n";
365 error_found = true;
366 }
367 if (ySize <= 0) {
368 std::cout << "ySize (" << ySize << ") should be > 0."
369 << "\n";
370 error_found = true;
371 }
372 if (gNPolygons > (xSize * ySize)) {
373 std::cout << "gNPolygons (" << gNPolygons << ") should be less than " << (xSize * ySize)
374 << "\n";
375 error_found = true;
376 }
377 if (error_found)
378 return false;
379 // the whole map is [xSize x ySize] squares
380 // the way we create the map is to
381 // 1) pick nPolygon discrete squares on an [xSize x ySize] grid
382 // 2) while there are unused squares on the grid
383 // 3) pick a polygon with a side that has unused squares on a side
384 // 4) expand the polygon by 1 to occupy the unused squares
385 //
386 // Continue until every square on the grid is occupied by a polygon
387 int *tempMap;
388 tempMap = (int *)malloc(xSize * ySize * sizeof(int));
389 for (int i = 0; i < xSize; i++) {
390 for (int j = 0; j < ySize; j++) {
391 tempMap[i * ySize + j] = 0;
392 }
393 }
394
395 // *newMap = new vector<RPolygon>;
396 *newMap = new Polygon_map_t;
397 (*newMap)->reserve(gNPolygons + 1); // how much bigger does this need to be on average?
398 (*newMap)->push_back(RPolygon(0, 0, xSize - 1, ySize - 1));
399 for (int i = 0; i < gNPolygons; i++) {
400 int nX;
401 int nY;
402 do { // look for an empty square.
403 nX = NextRan(xSize);
404 nY = NextRan(ySize);
405 } while (tempMap[nX * ySize + nY] != 0);
406 int nR = (maxR * NextRan(1000)) / 999;
407 int nG = (maxG * NextRan(1000)) / 999;
408 int nB = (maxB * NextRan(1000)) / 999;
409 (*newMap)->push_back(RPolygon(nX, nY, nX, nY, nR, nG, nB));
410 tempMap[nX * ySize + nY] = i + 1; // index of this polygon + 1
411 }
412 // now have to grow polygons to fill the space.
413 validPolys = (int *)malloc(4 * gNPolygons * sizeof(int));
414 validSide = (int *)malloc(4 * gNPolygons * sizeof(int));
415 for (int i = 0; i < gNPolygons; i++) {
416 validPolys[4 * i] = validPolys[4 * i + 1] = validPolys[4 * i + 2] = validPolys[4 * i + 3] =
417 i + 1;
418 validSide[4 * i] = NORTH_SIDE;
419 validSide[4 * i + 1] = EAST_SIDE;
420 validSide[4 * i + 2] = SOUTH_SIDE;
421 validSide[4 * i + 3] = WEST_SIDE;
422 }
423 maxSides = 4 * gNPolygons;
424 while (maxSides > 0) {
425 int indx = NextRan(maxSides);
426 int polyIndx = validPolys[indx];
427 int checkSide = validSide[indx];
428 int xlow, xhigh, ylow, yhigh;
429 int xlnew, xhnew, ylnew, yhnew;
430 (**newMap)[polyIndx].get(&xlow, &ylow, &xhigh, &yhigh);
431 xlnew = xlow;
432 xhnew = xhigh;
433 ylnew = ylow;
434 yhnew = yhigh;
435 // can this polygon be expanded along the chosen side?
436 switch (checkSide) {
437 case NORTH_SIDE:
438 // y-1 from xlow to xhigh
439 ylow = yhigh = (ylow - 1);
440 ylnew--;
441 break;
442 case EAST_SIDE:
443 // x+1 from ylow to yhigh
444 xlow = xhigh = (xhigh + 1);
445 xhnew++;
446 break;
447 case SOUTH_SIDE:
448 // y+1 from xlow to xhigh
449 ylow = yhigh = (yhigh + 1);
450 yhnew++;
451 break;
452 case WEST_SIDE:
453 // x-1 from ylow to yhigh
454 xlow = xhigh = (xlow - 1);
455 xlnew--;
456 break;
457 }
458 bool okay_to_extend = !(((xlow < 0) || (xlow >= xSize)) || ((ylow < 0) || (ylow >= ySize)));
459 for (int i = xlow; (i <= xhigh) && okay_to_extend; i++) {
460 for (int j = ylow; (j <= yhigh) && okay_to_extend; j++) {
461 okay_to_extend = tempMap[i * ySize + j] == 0;
462 }
463 }
464 if (okay_to_extend) {
465 (**newMap)[polyIndx].set(xlnew, ylnew, xhnew, yhnew);
466 for (int i = xlow; i <= xhigh; i++) {
467 for (int j = ylow; j <= yhigh && okay_to_extend; j++) {
468 tempMap[i * ySize + j] = polyIndx;
469 }
470 }
471 }
472 else {
473 // once we cannot expand along a side, we will never be able to; remove from the list.
474 for (int i = indx + 1; i < maxSides; i++) {
475 validPolys[i - 1] = validPolys[i];
476 validSide[i - 1] = validSide[i];
477 }
478 maxSides--;
479 }
480 }
481
482 // Once no polygons can be grown, look for unused squares, and fill them with polygons.
483 for (int j = 0; j < ySize; j++) {
484 for (int i = 0; i < xSize; i++) {
485 if (tempMap[i * ySize + j] == 0) {
486 // try to grow in the x direction, then the y direction
487 int ilen = i;
488 int jlen = j;
489 while (ilen < (xSize - 1) && tempMap[(ilen + 1) * ySize + jlen] == 0) {
490 ilen++;
491 }
492 bool yok = true;
493 while (yok && jlen < (ySize - 1)) {
494 for (int k = i; k <= ilen && yok; k++) {
495 yok = (tempMap[k * ySize + jlen + 1] == 0);
496 }
497 if (yok) {
498 jlen++;
499 }
500 }
501
502 // create new polygon and push it on our list.
503 int nR = (maxR * NextRan(1000)) / 999;
504 int nG = (maxG * NextRan(1000)) / 999;
505 int nB = (maxB * NextRan(1000)) / 999;
506 (*newMap)->push_back(RPolygon(i, j, ilen, jlen, nR, nG, nB));
507 gNPolygons++;
508 for (int k = i; k <= ilen; k++) {
509 for (int l = j; l <= jlen; l++) {
510 tempMap[k * ySize + l] = gNPolygons;
511 }
512 }
513 }
514 }
515 }
516
517 #if _DEBUG
518 if (!gIsGraphicalVersion) {
519 std::cout << "\n"
520 << "Final Map:"
521 << "\n";
522 for (int j = 0; j < ySize; j++) {
523 std::cout << "Row " << std::setw(2) << j << ":";
524 for (int i = 0; i < xSize; i++) {
525 int it = tempMap[i * ySize + j];
526 if (it < 10) {
527 std::cout << std::setw(2) << it;
528 }
529 else {
530 char ct = (int)'a' + it - 10;
531 std::cout << " " << ct;
532 }
533 }
534 std::cout << "\n";
535 }
536 }
537 #endif // _DEBUG
538 free(tempMap);
539 free(validPolys);
540 free(validSide);
541 return true;
542 }
543
CheckPolygonMap(Polygon_map_t * checkMap)544 void CheckPolygonMap(Polygon_map_t *checkMap) {
545 #define indx(i, j) (i * gMapYSize + j)
546 #define rangeCheck(str, n, limit) \
547 if (((n) < 0) || ((n) >= limit)) { \
548 std::cout << "checkMap error: " << str << " out of range (" << n << ")" \
549 << "\n"; \
550 anError = true; \
551 }
552 #define xRangeCheck(str, n) rangeCheck(str, n, gMapXSize)
553 #define yRangeCheck(str, n) rangeCheck(str, n, gMapYSize)
554 // The first polygon is the whole map.
555 bool anError = false;
556 int *cArray;
557 if (checkMap->size() <= 0) {
558 std::cout << "checkMap error: no polygons in map"
559 << "\n";
560 return;
561 }
562 // mapXhigh and mapYhigh are inclusive, that is, if the map is 5x5, those values would be 4.
563 int mapXhigh, mapYhigh, mapLowX, mapLowY;
564 int gMapXSize, gMapYSize;
565 (*checkMap)[0].get(&mapLowX, &mapLowY, &mapXhigh, &mapYhigh);
566 if ((mapLowX != 0) || (mapLowY != 0)) {
567 std::cout << "checkMap error: map origin not (0,0) (X=" << mapLowX << ", Y=" << mapLowY
568 << ")"
569 << "\n";
570 anError = true;
571 }
572 if ((mapXhigh < 0) || (mapYhigh < 0)) {
573 std::cout << "checkMap error: no area in map (X=" << mapXhigh << ", Y=" << mapYhigh << ")"
574 << "\n";
575 anError = true;
576 }
577 if (anError)
578 return;
579 // bounds for array.
580 gMapXSize = mapXhigh + 1;
581 gMapYSize = mapYhigh + 1;
582 cArray = (int *)malloc(sizeof(int) * (gMapXSize * gMapYSize));
583
584 for (int i = 0; i < gMapXSize; i++) {
585 for (int j = 0; j < gMapYSize; j++) {
586 cArray[indx(i, j)] = 0;
587 }
588 }
589
590 int xlow, xhigh, ylow, yhigh;
591 for (int k = 1; k < int(checkMap->size()) && !anError; k++) {
592 (*checkMap)[k].get(&xlow, &ylow, &xhigh, &yhigh);
593 xRangeCheck("xlow", xlow);
594 yRangeCheck("ylow", ylow);
595 xRangeCheck("xhigh", xhigh);
596 yRangeCheck("yhigh", yhigh);
597 if (xlow > xhigh) {
598 std::cout << "checkMap error: xlow > xhigh (" << xlow << "," << xhigh << ")"
599 << "\n";
600 anError = true;
601 }
602 if (ylow > yhigh) {
603 std::cout << "checkMap error: ylow > yhigh (" << ylow << "," << yhigh << ")"
604 << "\n";
605 anError = true;
606 }
607 for (int i = xlow; i <= xhigh; i++) {
608 for (int j = ylow; j <= yhigh; j++) {
609 if (cArray[indx(i, j)] != 0) {
610 std::cout << "checkMap error: polygons " << cArray[indx(i, j)] << " and " << k
611 << " intersect"
612 << "\n";
613 anError = true;
614 }
615 cArray[indx(i, j)] = k;
616 }
617 }
618 }
619 for (int i = 0; i < gMapXSize; i++) {
620 for (int j = 0; j < gMapYSize; j++) {
621 if (cArray[indx(i, j)] == 0) {
622 std::cout << "checkMap error: block(" << i << ", " << j << ") not in any polygon"
623 << "\n";
624 anError = true;
625 }
626 }
627 }
628 free(cArray);
629 }
630
CompOnePolygon(RPolygon & p1,RPolygon & p2)631 bool CompOnePolygon(RPolygon &p1, RPolygon &p2) {
632 int xl1, xh1, yl1, yh1;
633 int xl2, xh2, yl2, yh2;
634 p1.get(&xl1, &yl1, &xh1, &yh1);
635 p2.get(&xl2, &yl2, &xh2, &yh2);
636 if (yl1 > yl2)
637 return true;
638 if (yl1 < yl2)
639 return false;
640 return (xl1 > xl2);
641 }
642
PolygonsEqual(RPolygon * p1,RPolygon * p2)643 bool PolygonsEqual(RPolygon *p1, RPolygon *p2) {
644 int xl1, xh1, yl1, yh1;
645 int xl2, xh2, yl2, yh2;
646 p1->get(&xl1, &yl1, &xh1, &yh1);
647 p2->get(&xl2, &yl2, &xh2, &yh2);
648 return ((xl1 == xl2) && (yl1 == yl2) && (xh1 == xh2) && (yh1 == yh2));
649 }
650
ComparePolygonMaps(Polygon_map_t * map1,Polygon_map_t * map2)651 bool ComparePolygonMaps(Polygon_map_t *map1, Polygon_map_t *map2) {
652 // create two new polygon maps, copy the pointers from the original to these.
653 // we have to skip the first polygon, which is the size of the whole map
654 Polygon_map_t *t1, *t2;
655 bool is_ok = true;
656 t1 = new Polygon_map_t;
657 t1->reserve(map1->size());
658 for (unsigned int i = 1; i < map1->size(); i++) {
659 t1->push_back(map1->at(i));
660 }
661 t2 = new Polygon_map_t;
662 t2->reserve(map2->size());
663 for (unsigned int i = 1; i < map2->size(); i++) {
664 t2->push_back(map2->at(i));
665 }
666 // sort the two created maps by (xlow, ylow)
667 sort(t1->begin(), t1->end());
668 sort(t2->begin(), t2->end());
669 // compare each element of both maps.
670 if (t1->size() != t2->size()) {
671 std::cout << "Error: maps not the same size ( " << int(t1->size()) << " vs "
672 << int(t2->size()) << ")."
673 << "\n";
674 }
675 int maxSize = (int)((t1->size() < t2->size()) ? t1->size() : t2->size());
676 for (int i = 0; i < maxSize; i++) {
677 if (!PolygonsEqual(&((*t1)[i]), &((*t2)[i]))) {
678 std::cout << "Error: polygons unequal (" << (*t1)[i] << " vs " << (*t2)[i] << "\n";
679 is_ok = false;
680 }
681 }
682 delete t1;
683 delete t2;
684 return is_ok;
685 }
686
SetRandomSeed(int newSeed)687 void SetRandomSeed(int newSeed) {
688 srand((unsigned)newSeed);
689 }
690
NextRan(int n)691 int NextRan(int n) {
692 // assert(n > 1);
693 // if we are given 1, we will just return 0
694 //assert(n < RAND_MAX);
695 int rrand = rand() << 15 | rand();
696 if (rrand < 0)
697 rrand = -rrand;
698 return rrand % n;
699 }
700
operator <<(std::ostream & s,const RPolygon & p)701 std::ostream &operator<<(std::ostream &s, const RPolygon &p) {
702 int xl, yl, xh, yh;
703 p.get(&xl, &yl, &xh, &yh);
704 return s << "[(" << xl << "," << yl << ")-(" << xh << "," << yh << ")] ";
705 }
706