HOG2
Map2DEnvironment.cpp
Go to the documentation of this file.
1 /*
2  * Map2DEnvironment.cpp
3  * hog2
4  *
5  * Created by Nathan Sturtevant on 4/20/07.
6  * Copyright 2007 Nathan Sturtevant, University of Alberta. All rights reserved.
7  *
8  */
9 #include "Map2DEnvironment.h"
10 #include "FPUtil.h"
11 #include "SVGUtil.h"
12 #include <cstring>
13 #include <unordered_map>
14 #include "Graphics.h"
15 
16 using namespace Graphics;
17 
18 MapEnvironment::MapEnvironment(Map *_m, bool useOccupancy)
19 {
20  drawParams = kNoOptions;
21  DIAGONAL_COST = ROOT_TWO;
22  map = _m;
23  if (useOccupancy)
24  oi = new BaseMapOccupancyInterface(map);
25  else
26  oi = 0;
27  h = 0;
28  fourConnected = false;
29 }
30 
32 {
33  drawParams = kNoOptions;
34  map = me->map->Clone();
35  h = 0;
36  if (me->oi)
37  oi = new BaseMapOccupancyInterface(map);
38  else oi = 0;
39  DIAGONAL_COST = me->DIAGONAL_COST;
40  fourConnected = me->fourConnected;
41 }
42 
44 {
45 // delete map;
46  delete oi;
47 }
48 
50 {
51  return h;
52 }
53 
55 {
56  h = gh;
57 }
58 
59 void MapEnvironment::GetSuccessors(const xyLoc &loc, std::vector<xyLoc> &neighbors) const
60 {
61  neighbors.resize(0);
62  bool up=false, down=false;
63  //
64  if ((map->CanStep(loc.x, loc.y, loc.x, loc.y+1)))
65  {
66  down = true;
67  neighbors.push_back(xyLoc(loc.x, loc.y+1));
68  }
69  if ((map->CanStep(loc.x, loc.y, loc.x, loc.y-1)))
70  {
71  up = true;
72  neighbors.push_back(xyLoc(loc.x, loc.y-1));
73  }
74  if ((map->CanStep(loc.x, loc.y, loc.x-1, loc.y)))
75  {
76  if (!fourConnected && (up && (map->CanStep(loc.x, loc.y, loc.x-1, loc.y-1))))
77  neighbors.push_back(xyLoc(loc.x-1, loc.y-1));
78  if (!fourConnected && (down && (map->CanStep(loc.x, loc.y, loc.x-1, loc.y+1))))
79  neighbors.push_back(xyLoc(loc.x-1, loc.y+1));
80  neighbors.push_back(xyLoc(loc.x-1, loc.y));
81  }
82  if ((map->CanStep(loc.x, loc.y, loc.x+1, loc.y)))
83  {
84  if (!fourConnected && (up && (map->CanStep(loc.x, loc.y, loc.x+1, loc.y-1))))
85  neighbors.push_back(xyLoc(loc.x+1, loc.y-1));
86  if (!fourConnected && (down && (map->CanStep(loc.x, loc.y, loc.x+1, loc.y+1))))
87  neighbors.push_back(xyLoc(loc.x+1, loc.y+1));
88  neighbors.push_back(xyLoc(loc.x+1, loc.y));
89  }
90 }
91 
92 bool MapEnvironment::GetNextSuccessor(const xyLoc &currOpenNode, const xyLoc &goal,
93  xyLoc &next, double &currHCost, uint64_t &special,
94  bool &validMove)
95 {
96  if (fourConnected)
97  return GetNext4Successor(currOpenNode, goal, next, currHCost, special, validMove);
98  return GetNext8Successor(currOpenNode, goal, next, currHCost, special, validMove);
99 
100 }
101 
102 bool MapEnvironment::GetNext4Successor(const xyLoc &currOpenNode, const xyLoc &goal,
103  xyLoc &next, double &currHCost, uint64_t &special,
104  bool &validMove)
105 {
106  validMove = false;
107  if (special > 3)
108  return false;
109  // pass back next h-cost?
110  // 4 connected:
111  // case 2: above and right: Up, Right, Left, Down
112  // case 3: directly right: Right, Down, Up, Left
113  // case 4: below and right: Right, Down, Up, Left
114  // case 5: directly below: Down, Left, Right, Up
115  // case 6: below and left: Down, Left, Right, Up
116  // case 7: directly left: Left, Up, Down, Right
117  // case 8: above and left: Left, Up, Down, Right
118 
119  // 1,2. same y and different x (+/-)
120  // 3,4. same x and different y (+/-)
121  // 5,6,7,8. same x/y difference (+/-) combinations
122  int theEntry = 0;
123  const tDirection order[8][8] =
124  {
125  {kN, kE, kW, kS},
126  {kS, kE, kW, kN},
127  {kW, kN, kS, kE},
128  {kE, kN, kS, kW},
129 
130  {kN, kW, kE, kS},
131  {kW, kS, kN, kE},
132  {kN, kE, kW, kS},
133  {kS, kE, kW, kN},
134  };
135  const double hIncrease[8][8] =
136  {
137  {1.0, 0.0, 0.0, 0.0},
138  {1.0, 0.0, 0.0, 0.0},
139  {1.0, 0.0, 0.0, 0.0},
140  {1.0, 0.0, 0.0, 0.0},
141  {0.0, 1.0, 0.0, 0.0},
142  {0.0, 1.0, 0.0, 0.0},
143  {0.0, 1.0, 0.0, 0.0},
144  {0.0, 1.0, 0.0, 0.0},
145  };
146 
147  if (currOpenNode.x == goal.x && currOpenNode.y > goal.y)
148  { theEntry = 0; }
149  else if (currOpenNode.x == goal.x && currOpenNode.y < goal.y)
150  { theEntry = 1; }
151  else if (currOpenNode.x > goal.x && currOpenNode.y == goal.y)
152  { theEntry = 2; }
153  else if (currOpenNode.x < goal.x && currOpenNode.y == goal.y)
154  { theEntry = 3; }
155  else if (currOpenNode.x > goal.x && currOpenNode.y > goal.y)
156  { theEntry = 4; }
157  else if (currOpenNode.x > goal.x && currOpenNode.y < goal.y)
158  { theEntry = 5; }
159  else if (currOpenNode.x < goal.x && currOpenNode.y > goal.y)
160  { theEntry = 6; }
161  else if (currOpenNode.x < goal.x && currOpenNode.y < goal.y)
162  { theEntry = 7; }
163 
164 // std::cout << special << " h from " << currHCost << " to "
165 // << currHCost + hIncrease[theEntry][special] << std::endl;
166  switch (special) {
167  case 0:
168  next = currOpenNode;
169  currHCost += hIncrease[theEntry][special];
170  ApplyAction(next, order[theEntry][special]);
171  special++;
172  if (map->CanStep(currOpenNode.x, currOpenNode.y, next.x, next.y))
173  {
174  //std::cout << "Next successor of " << currOpenNode << " is " << next << std::endl;
175  validMove = true;
176  return true;
177  }
178  case 1:
179  next = currOpenNode;
180  currHCost += hIncrease[theEntry][special];
181  ApplyAction(next, order[theEntry][special]);
182  special++;
183  if (map->CanStep(currOpenNode.x, currOpenNode.y, next.x, next.y))
184  {
185  //std::cout << "Next successor of " << currOpenNode << " is " << next << std::endl;
186  validMove = true;
187  return true;
188  }
189  case 2:
190  next = currOpenNode;
191  currHCost += 1;
192  currHCost += hIncrease[theEntry][special];
193  ApplyAction(next, order[theEntry][special]);
194  special++;
195  if (map->CanStep(currOpenNode.x, currOpenNode.y, next.x, next.y))
196  {
197  //std::cout << "Next successor of " << currOpenNode << " is " << next << std::endl;
198  validMove = true;
199  return true;
200  }
201  case 3:
202  next = currOpenNode;
203  currHCost += hIncrease[theEntry][special];
204  ApplyAction(next, order[theEntry][special]);
205  special++;
206  if (map->CanStep(currOpenNode.x, currOpenNode.y, next.x, next.y))
207  {
208  //std::cout << "Next successor of " << currOpenNode << " is " << next << std::endl;
209  validMove = true;
210  return false;
211  }
212  default:
213  return false;
214  }
215 
216  return false;
217 }
218 
219 bool MapEnvironment::GetNext8Successor(const xyLoc &currOpenNode, const xyLoc &goal,
220  xyLoc &next, double &currHCost, uint64_t &special,
221  bool &validMove)
222 {
223  // in addition to the 16 obvious cases, when diagonal movess cross the
224  // diagonals we have separate cases. Thus, we don't implement this for now.
225 
226  // Diagonal movement when next to the goal could also be problematic, depending on the
227  // map representation
228  assert(false);
229 
230 // // it must be 1.5 for this code to be correct...
231 // assert(DIAGONAL_COST == 1.5);
232 // validMove = false;
233 // if (special > 7) // moves
234 // return false;
235 // // pass back next h-cost?
236 // // 4 connected:
237 // // case 2: above and right: Up, Right, Left, Down
238 // // case 3: directly right: Right, Down, Up, Left
239 // // case 4: below and right: Right, Down, Up, Left
240 // // case 5: directly below: Down, Left, Right, Up
241 // // case 6: below and left: Down, Left, Right, Up
242 // // case 7: directly left: Left, Up, Down, Right
243 // // case 8: above and left: Left, Up, Down, Right
244 //
245 // // 1,2. same y and different x (+/-)
246 // // 3,4. same x and different y (+/-)
247 // // 5,6,7,8. same x/y difference (+/-) combinations
248 // int theEntry = 0;
249 // const tDirection order[8][8] =
250 // {
251 // // directly above
252 // {kN, kNW, kNE, kE, kW, kS, kSE, kSW},
253 // // more above to the right
254 // {kN, kNE, kE, kNW, kW, kS, kSE, kSW},
255 // // diagonally right
256 // {kNE, kN, kE, kNW, kSE, kS, kW, kSW},
257 // // more right and above
258 // {kE, kNE, kN, kS, kSE, kW, kNW, kSW},
259 //
260 // {kE, kN, kS, kW},
261 //
262 // {kN, kW, kE, kS},
263 // {kW, kS, kN, kE},
264 // {kN, kE, kW, kS},
265 // {kS, kE, kW, kN},
266 // };
267 // const double hIncrease[8][8] =
268 // {
269 // // directly above
270 // {1.0, 0.0, 0.5, 0.0, 0.5, 1.0, 0.0, 0.0},
271 // // more above to the right
272 // {0.0, 0.5, 0.5, 0.5, 0.5, 0.0, 1.0, 0.0},
273 // // diagonally right
274 // {0.5, 0.0, 1.5, 0.0, 0.0, 0.0, 1.0, 0.0},
275 // // more right and above
276 // {0.0, 0.5, 0.5, 0.5, 0.5, 0.0, 1.0, 0.0},
277 // {0.0, 1.0, 0.0, 0.0},
278 // {0.0, 1.0, 0.0, 0.0},
279 // {0.0, 1.0, 0.0, 0.0},
280 // {0.0, 1.0, 0.0, 0.0},
281 // };
282 //
283 // if (currOpenNode.x == goal.x && currOpenNode.y > goal.y)
284 // { theEntry = 0; }
285 // else if (currOpenNode.x == goal.x && currOpenNode.y < goal.y)
286 // { theEntry = 1; }
287 // else if (currOpenNode.x > goal.x && currOpenNode.y == goal.y)
288 // { theEntry = 2; }
289 // else if (currOpenNode.x < goal.x && currOpenNode.y == goal.y)
290 // { theEntry = 3; }
291 // else if (currOpenNode.x > goal.x && currOpenNode.y > goal.y)
292 // { theEntry = 4; }
293 // else if (currOpenNode.x > goal.x && currOpenNode.y < goal.y)
294 // { theEntry = 5; }
295 // else if (currOpenNode.x < goal.x && currOpenNode.y > goal.y)
296 // { theEntry = 6; }
297 // else if (currOpenNode.x < goal.x && currOpenNode.y < goal.y)
298 // { theEntry = 7; }
299 //
300 // // std::cout << special << " h from " << currHCost << " to "
301 // // << currHCost + hIncrease[theEntry][special] << std::endl;
302 // switch (special) {
303 // case 0:
304 // next = currOpenNode;
305 // currHCost += hIncrease[theEntry][special];
306 // ApplyAction(next, order[theEntry][special]);
307 // special++;
308 // if (map->CanStep(currOpenNode.x, currOpenNode.y, next.x, next.y))
309 // {
310 // //std::cout << "Next successor of " << currOpenNode << " is " << next << std::endl;
311 // validMove = true;
312 // return true;
313 // }
314 // case 1:
315 // next = currOpenNode;
316 // currHCost += hIncrease[theEntry][special];
317 // ApplyAction(next, order[theEntry][special]);
318 // special++;
319 // if (map->CanStep(currOpenNode.x, currOpenNode.y, next.x, next.y))
320 // {
321 // //std::cout << "Next successor of " << currOpenNode << " is " << next << std::endl;
322 // validMove = true;
323 // return true;
324 // }
325 // case 2:
326 // next = currOpenNode;
327 // currHCost += 1;
328 // currHCost += hIncrease[theEntry][special];
329 // ApplyAction(next, order[theEntry][special]);
330 // special++;
331 // if (map->CanStep(currOpenNode.x, currOpenNode.y, next.x, next.y))
332 // {
333 // //std::cout << "Next successor of " << currOpenNode << " is " << next << std::endl;
334 // validMove = true;
335 // return true;
336 // }
337 // case 3:
338 // next = currOpenNode;
339 // currHCost += hIncrease[theEntry][special];
340 // ApplyAction(next, order[theEntry][special]);
341 // special++;
342 // if (map->CanStep(currOpenNode.x, currOpenNode.y, next.x, next.y))
343 // {
344 // //std::cout << "Next successor of " << currOpenNode << " is " << next << std::endl;
345 // validMove = true;
346 // return false;
347 // }
348 // default:
349 // return false;
350 // }
351 //
352 // return false;
353 }
354 
355 void MapEnvironment::GetActions(const xyLoc &loc, std::vector<tDirection> &actions) const // can agent go to diff loc?
356 {
357  bool up=false, down=false;
358  if ((map->CanStep(loc.x, loc.y, loc.x, loc.y+1)))
359  {
360  down = true;
361  actions.push_back(kS);
362  }
363  if ((map->CanStep(loc.x, loc.y, loc.x, loc.y-1)))
364  {
365  up = true;
366  actions.push_back(kN);
367  }
368  if ((map->CanStep(loc.x, loc.y, loc.x-1, loc.y))) // left
369  {
370  if (!fourConnected)
371  {
372  if ((up && (map->CanStep(loc.x, loc.y, loc.x-1, loc.y-1)))) // Can go up?
373  actions.push_back(kNW);
374  if ((down && (map->CanStep(loc.x, loc.y, loc.x-1, loc.y+1)))) // can go down?
375  actions.push_back(kSW);
376  }
377  actions.push_back(kW); //
378  }
379  if ((map->CanStep(loc.x, loc.y, loc.x+1, loc.y)))
380  {
381  if (!fourConnected)
382  {
383  if ((up && (map->CanStep(loc.x, loc.y, loc.x+1, loc.y-1))))
384  actions.push_back(kNE);
385  if ((down && (map->CanStep(loc.x, loc.y, loc.x+1, loc.y+1))))
386  actions.push_back(kSE);
387  }
388  actions.push_back(kE);
389  }
390 }
391 
392 tDirection MapEnvironment::GetAction(const xyLoc &s1, const xyLoc &s2) const
393 {
394  int result = kStay;
395  switch (s1.x-s2.x)
396  {
397  case -1: result = kE; break;
398  case 0: break;
399  case 1: result = kW; break;
400  default: return kTeleport;
401  }
402 
403  // Tack the vertical move onto it
404  // Notice the exploit of particular encoding of kStay, kE, etc. labels
405  switch (s1.y-s2.y)
406  {
407  case -1: result = result|kS; break;
408  case 0: break;
409  case 1: result = result|kN; break;
410  default: return kTeleport;
411  }
412  return (tDirection)result;
413 }
414 
416 {
417  switch (a)
418  {
419  case kN: a = kS; break;
420  case kNE: a = kSW; break;
421  case kE: a = kW; break;
422  case kSE: a = kNW; break;
423  case kS: a = kN; break;
424  case kSW: a = kNE; break;
425  case kW: a = kE; break;
426  case kNW: a = kSE; break;
427  default: break;
428  }
429  return true;
430 }
431 
433 {
434  //xyLoc old = s;
435  switch (dir)
436  {
437  case kN: s.y-=1; break;
438  case kS: s.y+=1; break;
439  case kE: s.x+=1; break;
440  case kW: s.x-=1; break;
441  case kNW: s.y-=1; s.x-=1; break;
442  case kSW: s.y+=1; s.x-=1; break;
443  case kNE: s.y-=1; s.x+=1; break;
444  case kSE: s.y+=1; s.x+=1; break;
445  default: break;
446  }
447 // if (map->CanStep(s.x, s.y, old.x, old.y) &&
448 // ((!oi) || (oi && !(oi->GetStateOccupied(s)))))
449 // {
450 // return;
451 // }
452 // s = old;
453 }
454 
455 double MapEnvironment::HCost(const xyLoc &l1, const xyLoc &l2) const
456 {
457  double h1, h2;
458  if (fourConnected)
459  {
460  h1 = abs(l1.x-l2.x)+abs(l1.y-l2.y);
461  }
462  else {
463  double a = ((l1.x>l2.x)?(l1.x-l2.x):(l2.x-l1.x));
464  double b = ((l1.y>l2.y)?(l1.y-l2.y):(l2.y-l1.y));
465  //return sqrt(a*a+b*b);
466  h1 = (a>b)?(b*DIAGONAL_COST+a-b):(a*DIAGONAL_COST+b-a);
467  }
468 
469  if (h == 0)
470  return h1;
471 
472  int n1 = map->GetNodeNum(l1.x, l1.y);
473  int n2 = map->GetNodeNum(l2.x, l2.y);
474  if ((n1 != -1) && (n2 != -1))
475  {
476  graphState nn1 = n1;
477  graphState nn2 = n2;
478  h2 = h->HCost(nn1, nn2);
479  }
480  else
481  h2 = 0;
482  return std::max(h1, h2);
483 }
484 
485 double MapEnvironment::GCost(const xyLoc &l, const tDirection &act) const
486 {
487  double multiplier = 1.0;
488 // if (map->GetTerrainType(l.x, l.y) == kSwamp)
489 // {
490 // multiplier = 3.0;
491 // }
492  switch (act)
493  {
494  case kN: return 1.0*multiplier;
495  case kS: return 1.0*multiplier;
496  case kE: return 1.0*multiplier;
497  case kW: return 1.0*multiplier;
498  case kNW: return DIAGONAL_COST*multiplier;
499  case kSW: return DIAGONAL_COST*multiplier;
500  case kNE: return DIAGONAL_COST*multiplier;
501  case kSE: return DIAGONAL_COST*multiplier;
502  default: return 0;
503  }
504  return 0;
505 }
506 
507 double MapEnvironment::GCost(const xyLoc &l1, const xyLoc &l2) const
508 {
509  double multiplier = 1.0;
510  if (map->GetTerrainType(l1.x, l1.y) == kSwamp)
511  {
512  multiplier = 3.0;
513  }
514  if (l1 == l2) return 0.0;
515  if (l1.x == l2.x) return 1.0*multiplier;
516  if (l1.y == l2.y) return 1.0*multiplier;
517  return DIAGONAL_COST*multiplier;
518 // double h = HCost(l1, l2);
519 // if (fgreater(h, DIAGONAL_COST))
520 // return DBL_MAX;
521 // return h;
522 }
523 
524 bool MapEnvironment::GoalTest(const xyLoc &node, const xyLoc &goal) const
525 {
526  return ((node.x == goal.x) && (node.y == goal.y));
527 }
528 
530 {
531  return map->GetMapWidth()*map->GetMapHeight();
532 }
533 
535 {
536  //return (((uint64_t)node.x)<<16)|node.y;
537  return node.y*map->GetMapWidth()+node.x;
538  // return (node.x<<16)|node.y;
539 }
540 
541 void MapEnvironment::GetStateFromHash(uint64_t parent, xyLoc &s) const
542 {
543  s.x = parent%map->GetMapWidth();
544  s.y = parent/map->GetMapWidth();
545 }
546 
548 {
549  return (uint32_t) act;
550 }
551 
553 {
554  //std::cout<<"drawing\n";
555  map->OpenGLDraw();
556  // Draw occupancy interface - occupied = white
557 // for (int i=0; i<map->GetMapWidth(); i++)
558 // for (int j=0; j<map->GetMapHeight(); j++)
559 // {
560 // xyLoc l;
561 // l.x = i;
562 // l.y = j;
563 // if (oi && oi->GetStateOccupied(l))
564 // {
565 // SetColor(1.0, 1.0, 1.0, 1.0);
566 // OpenGLDraw(l);//, 1.0, 1.0, 1.0);
567 // }
568 // }
569 }
570 
571 
572 
573 void MapEnvironment::OpenGLDraw(const xyLoc &l) const
574 {
575  GLdouble xx, yy, zz, rad;
576  map->GetOpenGLCoord(l.x, l.y, xx, yy, zz, rad);
577  GLfloat r, g, b, t;
578  GetColor(r, g, b, t);
579  glColor4f(r, g, b, t);
580  //glColor3f(0.5, 0.5, 0.5);
581  DrawSphere(xx, yy, zz, rad);
582 }
583 
584 void MapEnvironment::OpenGLDraw(const xyLoc &l1, const xyLoc &l2, float v) const
585 {
586  GLdouble xx, yy, zz, rad;
587  GLdouble xx2, yy2, zz2;
588 // map->GetOpenGLCoord((float)((1-v)*l1.x+v*l2.x),
589 // (float)((1-v)*l1.y+v*l2.y), xx, yy, zz, rad);
590 // printf("%f between (%d, %d) and (%d, %d)\n", v, l1.x, l1.y, l2.x, l2.y);
591  map->GetOpenGLCoord(l1.x, l1.y, xx, yy, zz, rad);
592  map->GetOpenGLCoord(l2.x, l2.y, xx2, yy2, zz2, rad);
593  // map->GetOpenGLCoord(perc*newState.x + (1-perc)*oldState.x, perc*newState.y + (1-perc)*oldState.y, xx, yy, zz, rad);
594  xx = (1-v)*xx+v*xx2;
595  yy = (1-v)*yy+v*yy2;
596  zz = (1-v)*zz+v*zz2;
597  GLfloat r, g, b, t;
598  GetColor(r, g, b, t);
599  glColor4f(r, g, b, t);
600  DrawSphere(xx, yy, zz, rad);
601 }
602 
603 //void MapEnvironment::OpenGLDraw(const xyLoc &l, GLfloat r, GLfloat g, GLfloat b) const
604 //{
605 // GLdouble xx, yy, zz, rad;
606 // map->GetOpenGLCoord(l.x, l.y, xx, yy, zz, rad);
607 // glColor3f(r,g,b);
608 // DrawSphere(xx, yy, zz, rad);
609 //}
610 
611 
612 void MapEnvironment::OpenGLDraw(const xyLoc& initial, const tDirection &dir) const
613 {
614 
615  xyLoc s = initial;
616  GLdouble xx, yy, zz, rad;
617  map->GetOpenGLCoord(s.x, s.y, xx, yy, zz, rad);
618 
619  glColor3f(0.5, 0.5, 0.5);
620  glBegin(GL_LINE_STRIP);
621  glVertex3f(xx, yy, zz-rad/2);
622 
623  switch (dir)
624  {
625  case kN: s.y-=1; break;
626  case kS: s.y+=1; break;
627  case kE: s.x+=1; break;
628  case kW: s.x-=1; break;
629  case kNW: s.y-=1; s.x-=1; break;
630  case kSW: s.y+=1; s.x-=1; break;
631  case kNE: s.y-=1; s.x+=1; break;
632  case kSE: s.y+=1; s.x+=1; break;
633  default: break;
634  }
635 
636 
637  map->GetOpenGLCoord(s.x, s.y, xx, yy, zz, rad);
638  glVertex3f(xx, yy, zz-rad/2);
639  glEnd();
640 
641 }
642 
643 void MapEnvironment::GLDrawLine(const xyLoc &a, const xyLoc &b) const
644 {
645  GLdouble xx1, yy1, zz1, rad;
646  GLdouble xx2, yy2, zz2;
647  map->GetOpenGLCoord(a.x, a.y, xx1, yy1, zz1, rad);
648  map->GetOpenGLCoord(b.x, b.y, xx2, yy2, zz2, rad);
649 
650  double angle = atan2(yy1-yy2, xx1-xx2);
651  double xoff = sin(2*PI-angle)*rad*0.1;
652  double yoff = cos(2*PI-angle)*rad*0.1;
653 
654 
655 
656  GLfloat rr, gg, bb, t;
657  GetColor(rr, gg, bb, t);
658  glColor4f(rr, gg, bb, t);
659 
660 
661  glBegin(GL_LINES);
662  glVertex3f(xx1, yy1, zz1-rad/2);
663  glVertex3f(xx2, yy2, zz2-rad/2);
664  glEnd();
665 
666 // glEnable(GL_BLEND);
667 // glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE);
668  //glEnable(GL_POLYGON_SMOOTH);
669 // glBegin(GL_TRIANGLE_STRIP);
670 // //glBegin(GL_QUADS);
671 // glVertex3f(xx1+xoff, yy1+yoff, zz1-rad/2);
672 // glVertex3f(xx2+xoff, yy2+yoff, zz2-rad/2);
673 // glVertex3f(xx1-xoff, yy1-yoff, zz1-rad/2);
674 // glVertex3f(xx2-xoff, yy2-yoff, zz2-rad/2);
675 // glEnd();
676 
677  // glDisable(GL_POLYGON_SMOOTH);
678  //
679 // glBegin(GL_LINES);
680 // glVertex3f(xx, yy, zz-rad/2);
681 // map->GetOpenGLCoord(b.x, b.y, xx, yy, zz, rad);
682 // glVertex3f(xx, yy, zz-rad/2);
683 // glEnd();
684 }
685 
686 void MapEnvironment::GLLabelState(const xyLoc &s, const char *str, double scale) const
687 {
688  glPushMatrix();
689 
690  GLdouble xx, yy, zz, rad;
691  map->GetOpenGLCoord(s.x, s.y, xx, yy, zz, rad);
692  GLfloat r, g, b, t;
693  GetColor(r, g, b, t);
694  glColor4f(r, g, b, t);
695 
696  glTranslatef(xx-rad, yy+rad/2, zz-2*rad);
697  glScalef(scale*rad/(300.0), scale*rad/300.0, 1);
698  glRotatef(180, 0.0, 0.0, 1.0);
699  glRotatef(180, 0.0, 1.0, 0.0);
700  //glTranslatef((float)x/width-0.5, (float)y/height-0.5, 0);
701  glDisable(GL_LIGHTING);
702  //for (int which = 0; which < strlen(str); which++)
703  // glutStrokeCharacter(GLUT_STROKE_ROMAN, str[which]);
704  glEnable(GL_LIGHTING);
705  //glTranslatef(-x/width+0.5, -y/height+0.5, 0);
706  glPopMatrix();
707 }
708 
709 void MapEnvironment::GLLabelState(const xyLoc &s, const char *str) const
710 {
711  glPushMatrix();
712 
713  GLdouble xx, yy, zz, rad;
714  map->GetOpenGLCoord(s.x, s.y, xx, yy, zz, rad);
715  GLfloat r, g, b, t;
716  GetColor(r, g, b, t);
717  glColor4f(r, g, b, t);
718 
719  glTranslatef(xx-rad, yy+rad/2, zz-rad);
720  glScalef(rad/(300.0), rad/300.0, 1);
721  glRotatef(180, 0.0, 0.0, 1.0);
722  glRotatef(180, 0.0, 1.0, 0.0);
723  //glTranslatef((float)x/width-0.5, (float)y/height-0.5, 0);
724  glDisable(GL_LIGHTING);
725  //for (int which = 0; which < strlen(str); which++)
726  // glutStrokeCharacter(GLUT_STROKE_ROMAN, str[which]);
727  glEnable(GL_LIGHTING);
728  //glTranslatef(-x/width+0.5, -y/height+0.5, 0);
729  glPopMatrix();
730 }
731 
733 {
734  std::string s;
735  // 10% margin on all sides of image
736  s = "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width = \""+std::to_string(10*map->GetMapWidth())+"\" height = \""+std::to_string(10*map->GetMapHeight())+"\" ";
737  s += "viewBox=\""+std::to_string(-map->GetMapWidth())+" "+std::to_string(-map->GetMapHeight())+" ";
738  s += std::to_string(12*map->GetMapWidth())+" "+std::to_string(12*map->GetMapHeight())+"\" ";
739  s += "preserveAspectRatio = \"none\" ";
740  s += ">\n";
741  return s;
742 }
743 
745 {
746  std::string s;
747  rgbColor black = {0.0, 0.0, 0.0};
748 
749  // draw tiles
750  for (int y = 0; y < map->GetMapHeight(); y++)
751  {
752  for (int x = 0; x < map->GetMapWidth(); x++)
753  {
754  bool draw = true;
755  if (map->GetTerrainType(x, y) == kGround)
756  {
757  rgbColor c = {0.0, 0.0, 0.0};
758 // rgbColor c = {0.9, 0.9, 0.9};
759  s += SVGDrawRect(x+1, y+1, 1, 1, c);
760  s += "\n";
761  }
762  else if (map->GetTerrainType(x, y) == kTrees)
763  {
764  rgbColor c = {0.0, 0.5, 0.0};
765  s += SVGDrawRect(x+1, y+1, 1, 1, c);
766  s += "\n";
767  }
768  else if (map->GetTerrainType(x, y) == kWater)
769  {
770  rgbColor c = {0.0, 0.0, 1.0};
771  s += SVGDrawRect(x+1, y+1, 1, 1, c);
772  s += "\n";
773  }
774  else if (map->GetTerrainType(x, y) == kSwamp)
775  {
776  rgbColor c = {0.0, 0.3, 1.0};
777  s += SVGDrawRect(x+1, y+1, 1, 1, c);
778  s += "\n";
779  }
780  else {
781 // rgbColor c = {0.0, 0.0, 0.0};
782  rgbColor c = {1.0, 1.0, 1.0};
783  s += SVGDrawRect(x+1, y+1, 1, 1, c);
784  s += "\n";
785  draw = false;
786  }
787  }
788  }
789 
790  // draw cell boundaries for open terrain
791  if (0)
792  for (int y = 0; y < map->GetMapHeight(); y++)
793  {
794  for (int x = 0; x < map->GetMapWidth(); x++)
795  {
796  // mark cells on map
797  if ((map->GetTerrainType(x, y)>>terrainBits) == (kGround>>terrainBits))
798  {
799  rgbColor c = {0.75, 0.75, 0.75};
800  s += ::SVGFrameRect(x+1, y+1, 1, 1, 1, c);
801  s += "\n";
802  }
803  }
804  }
805 
806  // draw lines between different terrain types
807  if (0)
808  for (int y = 0; y < map->GetMapHeight(); y++)
809  {
810  for (int x = 0; x < map->GetMapWidth(); x++)
811  {
812  bool draw = true;
813  if (map->GetTerrainType(x, y) == kGround)
814  {
815  if (x == map->GetMapWidth()-1)
816  s += ::SVGDrawLine(x+1+1, y+1, x+1+1, y+1+1, 1, black, false);
817  if (y == map->GetMapHeight()-1)
818  s += ::SVGDrawLine(x+1, y+1+1, x+1+1, y+1+1, 1, black, false);
819  }
820  else if (map->GetTerrainType(x, y) == kTrees)
821  {
822  if (x == map->GetMapWidth()-1)
823  s += ::SVGDrawLine(x+1+1, y+1, x+1+1, y+1+1, 1, black, false);
824  if (y == map->GetMapHeight()-1)
825  s += ::SVGDrawLine(x+1, y+1+1, x+1+1, y+1+1, 1, black, false);
826  }
827  else if (map->GetTerrainType(x, y) == kWater)
828  {
829  if (x == map->GetMapWidth()-1)
830  s += ::SVGDrawLine(x+1+1, y+1, x+1+1, y+1+1, 1, black, false);
831  if (y == map->GetMapHeight()-1)
832  s += ::SVGDrawLine(x+1, y+1+1, x+1+1, y+1+1, 1, black, false);
833  }
834  else if (map->GetTerrainType(x, y) == kSwamp)
835  {
836  }
837  else {
838  draw = false;
839  }
840 
841  if (draw)
842  {
843  SetColor(0.0, 0.0, 0.0);
844 
845  // Code does error checking, so this works with x == 0
846  if (map->GetTerrainType(x, y) != map->GetTerrainType(x-1, y))
847  {
848  SetColor(0.0, 0.0, 0.0);
849  s += ::SVGDrawLine(x+1, y+1, x+1, y+1+1, 1, black, false);
850  s += "\n";
851  }
852 
853  if (map->GetTerrainType(x, y) != map->GetTerrainType(x, y-1))
854  {
855  s += ::SVGDrawLine(x+1, y+1, x+1+1, y+1, 1, black, false);
856  s += "\n";
857  }
858 
859  if (map->GetTerrainType(x, y) != map->GetTerrainType(x+1, y))
860  {
861  s += ::SVGDrawLine(x+1+1, y+1, x+1+1, y+1+1, 1, black, false);
862  s += "\n";
863  }
864 
865  if (map->GetTerrainType(x, y) != map->GetTerrainType(x, y+1))
866  {
867  s += ::SVGDrawLine(x+1, y+1+1, x+1+1, y+1+1, 1, black, false);
868  s += "\n";
869  }
870  }
871 
872  }
873  }
874  s += "\n";
875 
876  return s;
877 }
878 
879 std::string MapEnvironment::SVGDraw(const xyLoc &l)
880 {
881  std::string s;
882  if (map->GetTerrainType(l.x, l.y) == kGround)
883  {
884  rgbColor c;// = {0.5, 0.5, 0};
885  GLfloat t;
886  GetColor(c.r, c.g, c.b, t);
887  s += SVGDrawRect(l.x+1, l.y+1, 1, 1, c);
888  //s += SVGDrawCircle(l.x+0.5+1, l.y+0.5+1, 0.5, c);
889  //stroke-width="1" stroke="pink" />
890  }
891  return s;
892 }
893 
894 std::string MapEnvironment::SVGFrameRect(int left, int top, int right, int bottom, int width)
895 {
896  std::string s;
897 
898  rgbColor c;// = {0.5, 0.5, 0};
899  GLfloat t;
900  GetColor(c.r, c.g, c.b, t);
901  s += ::SVGFrameRect(left+1, top+1, right-left+1, bottom-top+1, width, c);
902 
903  return s;
904 }
905 
906 std::string MapEnvironment::SVGLabelState(const xyLoc &l, const char *str, double scale) const
907 {
908  std::string s;
909  rgbColor c;// = {0.5, 0.5, 0};
910  GLfloat t;
911  GetColor(c.r, c.g, c.b, t);
912  s += SVGDrawText(l.x+1+0.3, l.y+1+1, str, c, scale);
913  return s;
914 // std::string s;
915 // s = "<text x=\"0\" y=\"15\" fill=\"black\">";
916 // s += str;
917 // s += "</text>";
918 // return s;
919 }
920 
921 std::string MapEnvironment::SVGLabelState(const xyLoc &l, const char *str, double scale, double xoff, double yoff) const
922 {
923  std::string s;
924  rgbColor c;// = {0.5, 0.5, 0};
925  GLfloat t;
926  GetColor(c.r, c.g, c.b, t);
927  s += SVGDrawText(l.x+0.5+1+xoff, l.y+0.5+1+1+yoff, str, c, scale);
928  return s;
929  // std::string s;
930  // s = "<text x=\"0\" y=\"15\" fill=\"black\">";
931  // s += str;
932  // s += "</text>";
933  // return s;
934 }
935 
936 std::string MapEnvironment::SVGDrawLine(const xyLoc &p1, const xyLoc &p2, int width) const
937 {
938  //<line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,255,255);stroke-width:1" />
939  //std::string s;
940  rgbColor c;// = {0.5, 0.5, 0};
941  GLfloat t;
942  GetColor(c.r, c.g, c.b, t);
943  return ::SVGDrawLine(p1.x+1, p1.y+1, p2.x+1, p2.y+1, width, c);
944 
945 // s = "<line x1 = \"" + std::to_string(p1.x) + "\" ";
946 // s += "y1 = \"" + std::to_string(p1.y) + "\" ";
947 // s += "x2 = \"" + std::to_string(p2.x) + "\" ";
948 // s += "y2 = \"" + std::to_string(p2.y) + "\" ";
949 // s += "style=\"stroke:"+SVGGetRGB(c)+";stroke-width:"+std::to_string(width)+"\" />";
950 // return s;
951 }
952 
953 void MapEnvironment::GetMaxRect(long terrain, int startx, int starty, int endx, int endy, std::vector<bool> &drawn, rect &r) const
954 {
955  while (true)
956  {
957  bool successx = true;
958  bool successy = true;
959 
960  if (endy+1 >= map->GetMapHeight() || endx+1 >= map->GetMapWidth())
961  break;
962  for (int x = startx; x < endx+1; x++)
963  {
964  if (map->GetTerrainType(x, endy+1) != terrain)// || drawn[endy*map->GetMapWidth()+x])
965  {
966  successx = false;
967  break;
968  }
969  }
970  for (int y = starty; y < endy+1; y++)
971  {
972  if (map->GetTerrainType(endx+1, y) != terrain)// || drawn[y*map->GetMapWidth()+endx])
973  {
974  successy = false;
975  break;
976  }
977  }
978  if (successx && successy)
979  {
980  if (map->GetTerrainType(endx+1, endy+1) != terrain)// || drawn[y*map->GetMapWidth()+endx])
981  successy = false;
982  }
983  if (successx)
984  endy++;
985  if (successy)
986  endx++;
987  if (!successx && !successy)
988  break;
989  }
990  GLdouble x1, x2, y1, y2, tmp, rad;
991  map->GetOpenGLCoord(startx, starty, x1, y1, tmp, rad);
992  map->GetOpenGLCoord(endx, endy, x2, y2, tmp, rad);
993  r = Graphics::rect(x1-rad, y1-rad, x2+rad, y2+rad);
994  for (int y = starty; y <= endy; y++)
995  {
996  for (int x = startx; x <= endx; x++)
997  {
998  drawn[y*map->GetMapWidth()+x] = true;
999  }
1000  }
1001 }
1002 
1003 void MapEnvironment::DrawSingleTerrain(long terrain, Graphics::Display &disp, std::vector<bool> &drawn) const
1004 {
1005  rgbColor groundColor = {0.9, 0.9, 0.9};
1006  rgbColor treeColor = {0.0, 0.5, 0.0};
1007  rgbColor waterColor = {0.0, 0.0, 1.0};
1008  rgbColor swampColor = {0.5, 0.7, 0.8};
1009  rgbColor grassColor = {0.5, 1.0, 0.6};
1010  rgbColor otherColor = Colors::black;
1011 
1012  for (int y = 0; y < map->GetMapHeight(); y++)
1013  {
1014  for (int x = 0; x < map->GetMapWidth(); x++)
1015  {
1016  if (map->GetTerrainType(x, y) != terrain)
1017  continue;
1018  rgbColor c;
1019  if (!drawn[y*map->GetMapWidth()+x])
1020  {
1021  switch (terrain)
1022  {
1023  case kGround: c = groundColor; break;
1024  case kTrees: c = treeColor; break;
1025  case kWater: c = waterColor; break;
1026  case kSwamp: c = swampColor; break;
1027  case kGrass: c = grassColor; break;
1028  default: c = otherColor; break;
1029  }
1030 
1031  rect r;
1032  GetMaxRect(terrain, x, y, x, y, drawn, r);
1033  disp.FillRect(r, c);
1034  }
1035  }
1036  }
1037 }
1038 
1040 {
1041 // kEfficientCells = 0x1,
1042 // kTerrainBorderLines = 0x2,
1043 // kCellBorderLines = 0x4
1044 
1045  rgbColor groundColor = {0.9, 0.9, 0.9};
1046  rgbColor treeColor = {0.0, 0.5, 0.0};
1047  rgbColor waterColor = {0.0, 0.0, 1.0};
1048  rgbColor swampColor = {0.5, 0.7, 0.8};
1049  rgbColor grassColor = {0.5, 1.0, 0.6};
1050  rgbColor otherColor = Colors::black;
1051 
1052  disp.FillRect({-1, -1, 1, 1}, Colors::black);
1053 
1054  // draw tiles
1055  if (drawParams&kEfficientCells)
1056  {
1057  long common;
1058  int g = 0, t = 0, w = 0, s = 0, o = 0;
1059  // get counts of all terrain to fill background color with most common terrain
1060  for (int y = 0; y < map->GetMapHeight(); y++)
1061  {
1062  for (int x = 0; x < map->GetMapWidth(); x++)
1063  {
1064  switch (map->GetTerrainType(x, y))
1065  {
1066  case kGround: g++; break;
1067  case kTrees: t++; break;
1068  case kWater: w++; break;
1069  case kSwamp: s++; break;
1070  default: o++; break;
1071  }
1072  }
1073  }
1074  rect r;
1075  GLdouble px, py, px1, py1, tmp, rad;
1076  map->GetOpenGLCoord(0, 0, px, py, tmp, rad);
1077  map->GetOpenGLCoord((int)map->GetMapWidth()-1, (int)map->GetMapHeight()-1, px1, py1, tmp, rad);
1078  r.left = px-rad;
1079  r.top = py-rad;
1080  r.right = px1+rad;
1081  r.bottom = py1+rad;
1082 
1083  if (g >= t && g >= w && g >= s && g >= o)
1084  {
1085  common = kGround;
1086  disp.FillRect(r, groundColor);
1087  }
1088  else if (t >= w && t >= s && t >= o)
1089  {
1090  common = kTrees;
1091  disp.FillRect(r, treeColor);
1092  }
1093  else if (w >= s && w >= o)
1094  {
1095  common = kWater;
1096  disp.FillRect(r, waterColor);
1097  }
1098  else if (s >= o)
1099  {
1100  common = kSwamp;
1101  disp.FillRect(r, swampColor);
1102  }
1103  else {
1104  common = kOutOfBounds;
1105  disp.FillRect(r, otherColor);
1106  }
1107 
1108  // Draw the rest of the map
1109  std::vector<bool> drawn(map->GetMapHeight()*map->GetMapWidth());
1110  if (common != kSwamp)
1111  DrawSingleTerrain(kSwamp, disp, drawn);
1112  if (common != kGround)
1113  DrawSingleTerrain(kGround, disp, drawn);
1114  if (common != kTrees)
1115  DrawSingleTerrain(kTrees, disp, drawn);
1116  if (common != kWater)
1117  DrawSingleTerrain(kWater, disp, drawn);
1118  if (common != kOutOfBounds)
1119  DrawSingleTerrain(kOutOfBounds, disp, drawn);
1120 
1121 
1122 
1123  }
1124  else {
1125  for (int y = 0; y < map->GetMapHeight(); y++)
1126  {
1127  for (int x = 0; x < map->GetMapWidth(); x++)
1128  {
1129  rect r;
1130  GLdouble px, py, t, rad;
1131  map->GetOpenGLCoord(x, y, px, py, t, rad);
1132  r.left = px-rad;
1133  r.top = py-rad;
1134  r.right = px+rad;
1135  r.bottom = py+rad;
1136 
1137  rgbColor c;
1138  bool draw = true;
1139 
1140  switch (map->GetTerrainType(x, y))
1141  {
1142  case kGround: c = groundColor; break;
1143  case kTrees: c = treeColor; break;
1144  case kWater: c = waterColor; break;
1145  case kSwamp: c = swampColor; break;
1146  case kGrass: c = grassColor; break;
1147  default: draw=false; break;
1148  }
1149  if (draw)
1150  {
1151  disp.FillRect(r, c);
1152  if (drawParams&kCellBorderLines)
1153  {
1154  disp.FrameRect(r, Colors::lightgray, rad/10.0);
1155  }
1156  }
1157  }
1158  }
1159  }
1160 
1161  // draw cell boundaries for open terrain
1162 // if (drawParams & kTerrainBorderLines)
1163 // {
1164 // for (int y = 0; y < map->GetMapHeight(); y++)
1165 // {
1166 // for (int x = 0; x < map->GetMapWidth(); x++)
1167 // {
1168 // // mark cells on map
1169 // if ((map->GetTerrainType(x, y)>>terrainBits) == (kGround>>terrainBits))
1170 // {
1171 // rgbColor c = {0.75, 0.75, 0.75};
1172 // rect r;
1173 // GLdouble px, py, t, rad;
1174 // map->GetOpenGLCoord(x, y, px, py, t, rad);
1175 // r.left = px-rad;
1176 // r.top = py-rad;
1177 // r.right = px+rad;
1178 // r.bottom = py+rad;
1179 // disp.FrameRect(r, c, 1);
1180 // }
1181 // }
1182 // }
1183 // }
1184 
1185  // draw lines between different terrain types
1186  if (drawParams & kTerrainBorderLines)
1187  {
1188  std::vector<std::pair<point, point>> lines;
1189  for (int y = 0; y < map->GetMapHeight(); y++)
1190  {
1191  for (int x = 0; x < map->GetMapWidth(); x++)
1192  {
1193  GLdouble px1, py1, t1, rad1;
1194  map->GetOpenGLCoord(x, y, px1, py1, t1, rad1);
1195  float px=static_cast<float>(px1);
1196  float py=static_cast<float>(py1);
1197  float t=static_cast<float>(t1);
1198  float rad=static_cast<float>(rad1);
1199 
1200  bool draw = true;
1201  if ((map->GetTerrainType(x, y) == kGround) ||
1202  (map->GetTerrainType(x, y) == kTrees) ||
1203  (map->GetTerrainType(x, y) == kWater))
1204  {
1205  if (x == map->GetMapWidth()-1)
1206  {
1207  point s = {px+rad, py-rad};
1208  point g = {px+rad, py+rad};
1209  //disp.DrawLine(s, g, 1, Colors::black);
1210  lines.push_back({s, g});
1211  }
1212  if (y == map->GetMapHeight()-1)
1213  {
1214  point s = {px-rad, py+rad};
1215  point g = {px+rad, py+rad};
1216  //disp.DrawLine(s, g, 1, Colors::black);
1217  lines.push_back({s, g});
1218  }
1219  }
1220  else if (map->GetTerrainType(x, y) == kSwamp)
1221  {
1222  }
1223  else {
1224  draw = false;
1225  }
1226 
1227  if (draw)
1228  {
1229  // Code does error checking, so this works with x == 0
1230  if (map->GetTerrainType(x, y) != map->GetTerrainType(x-1, y))
1231  {
1232  point s = {px-rad, py-rad};
1233  point g = {px-rad, py+rad};
1234  //disp.DrawLine(s, g, 1, Colors::black);
1235  lines.push_back({s, g});
1236  }
1237 
1238  if (map->GetTerrainType(x, y) != map->GetTerrainType(x, y-1))
1239  {
1240  point s = {px-rad, py-rad};
1241  point g = {px+rad, py-rad};
1242  //disp.DrawLine(s, g, 1, Colors::black);
1243  lines.push_back({s, g});
1244  }
1245 
1246  if (map->GetTerrainType(x, y) != map->GetTerrainType(x+1, y))
1247  {
1248  point s = {px+rad, py-rad};
1249  point g = {px+rad, py+rad};
1250  //disp.DrawLine(s, g, 1, Colors::black);
1251  lines.push_back({s, g});
1252  }
1253 
1254  if (map->GetTerrainType(x, y) != map->GetTerrainType(x, y+1))
1255  {
1256  point s = {px-rad, py+rad};
1257  point g = {px+rad, py+rad};
1258  //disp.DrawLine(s, g, 1, Colors::black);
1259  lines.push_back({s, g});
1260  }
1261  }
1262 
1263  }
1264  }
1265  std::vector<point> points;
1266  while (lines.size() > 0)
1267  {
1268  points.resize(0);
1269  // Inefficient n^2 algorithm for now
1270  points.push_back(lines.back().first);
1271  points.push_back(lines.back().second);
1272  lines.pop_back();
1273  bool found;
1274  do {
1275  found = false;
1276  for (int x = 0; x < lines.size(); x++)
1277  {
1278  if (lines[x].first == points.back())
1279  {
1280  points.push_back(lines[x].second);
1281  lines.erase(lines.begin()+x);
1282  found = true;
1283  break;
1284  }
1285  if (lines[x].second == points.back())
1286  {
1287  points.push_back(lines[x].first);
1288  lines.erase(lines.begin()+x);
1289  found = true;
1290  break;
1291  }
1292  }
1293  } while (found);
1294  disp.DrawLineSegments(points, 1, Colors::black);
1295  }
1296  }
1297 }
1298 
1299 void MapEnvironment::Draw(Graphics::Display &disp, const xyLoc &l) const
1300 {
1301  GLdouble px, py, t, rad;
1302  map->GetOpenGLCoord(l.x, l.y, px, py, t, rad);
1303 
1304  //if (map->GetTerrainType(l.x, l.y) == kGround)
1305  {
1306  rgbColor c;// = {0.5, 0.5, 0};
1307  GLfloat t;
1308  GetColor(c.r, c.g, c.b, t);
1309 
1310  rect r;
1311  r.left = px-rad;
1312  r.top = py-rad;
1313  r.right = px+rad;
1314  r.bottom = py+rad;
1315 
1316  //s += SVGDrawCircle(l.x+0.5+1, l.y+0.5+1, 0.5, c);
1317  disp.FillCircle(r, c);
1318  //stroke-width="1" stroke="pink" />
1319  }
1320 }
1321 
1322 void MapEnvironment::Draw(Graphics::Display &disp, const xyLoc &l1, const xyLoc &l2, float v) const
1323 {
1324  rect r1, r2;
1325  rgbColor c;// = {0.5, 0.5, 0};
1326  GLfloat t;
1327  GetColor(c.r, c.g, c.b, t);
1328  GLdouble rad;
1329  {
1330  GLdouble px, py, t;
1331  map->GetOpenGLCoord(l1.x, l1.y, px, py, t, rad);
1332 
1333  rect r;
1334  r.left = px-rad;
1335  r.top = py-rad;
1336  r.right = px+rad;
1337  r.bottom = py+rad;
1338  r1 = r;
1339  }
1340  {
1341  GLdouble px, py, t;
1342  map->GetOpenGLCoord(l2.x, l2.y, px, py, t, rad);
1343 
1344  rect r;
1345  r.left = px-rad;
1346  r.top = py-rad;
1347  r.right = px+rad;
1348  r.bottom = py+rad;
1349  r2 = r;
1350  }
1351  rect r;
1352  v = 1-v;
1353  r.left = v*r1.left+r2.left*(1-v);
1354  r.right = v*r1.right+r2.right*(1-v);
1355  r.top = v*r1.top+r2.top*(1-v);
1356  r.bottom = v*r1.bottom+r2.bottom*(1-v);
1357  disp.FillCircle(r, c);
1358 }
1359 
1360 
1362 {
1363  GLdouble px, py, t, rad;
1364  map->GetOpenGLCoord(l.x, l.y, px, py, t, rad);
1365  if (l.x < 0 || l.x >= map->GetMapWidth() || l.y < 0 || l.y >= map->GetMapHeight())
1366  return;
1367 
1368 // if (map->GetTerrainType(l.x, l.y) == kGround)
1369  {
1370  rgbColor c;// = {0.5, 0.5, 0};
1371  GLfloat t;
1372  GetColor(c.r, c.g, c.b, t);
1373 
1374  rect r;
1375  r.left = px-rad;
1376  r.top = py-rad;
1377  r.right = px+rad;
1378  r.bottom = py+rad;
1379 
1380  disp.FrameCircle({static_cast<float>(px), static_cast<float>(py)}, rad, c, rad);
1381 // disp.FrameCircle(r, c, 2);
1382  }
1383 }
1384 
1386 {
1387  GLdouble px, py, t, rad;
1388  map->GetOpenGLCoord(l.x, l.y, px, py, t, rad);
1389  return Graphics::point(px, py);
1390 }
1391 
1392 void MapEnvironment::DrawStateLabel(Graphics::Display &disp, const xyLoc &l, const char *txt) const
1393 {
1394  GLdouble px, py, t, rad;
1395  map->GetOpenGLCoord(l.x, l.y, px, py, t, rad);
1396 
1397  rgbColor c;
1398  {
1399  GLfloat t;
1400  GetColor(c.r, c.g, c.b, t);
1401  }
1402  disp.DrawText(txt, {static_cast<float>(px), static_cast<float>(py)}, c, rad);
1403 }
1404 
1405 void MapEnvironment::DrawStateLabel(Graphics::Display &disp, const xyLoc &l1, const xyLoc &l2, float v, const char *txt) const
1406 {
1407  Graphics::point p;
1408  GLdouble rad;
1409  {
1410  GLdouble px, py, t;
1411  map->GetOpenGLCoord(l1.x, l1.y, px, py, t, rad);
1412  p.x = px;
1413  p.y = py;
1414  }
1415  {
1416  GLdouble px, py, t, rad;
1417  map->GetOpenGLCoord(l2.x, l2.y, px, py, t, rad);
1418  p.x = (1-v)*p.x + (v)*px;
1419  p.y = (1-v)*p.y + (v)*py;
1420  }
1421  rgbColor c;
1422  {
1423  GLfloat t;
1424  GetColor(c.r, c.g, c.b, t);
1425  }
1426  disp.DrawText(txt, p, c, rad);
1427 }
1428 
1429 
1430 void MapEnvironment::DrawLine(Graphics::Display &disp, const xyLoc &a, const xyLoc &b, double width) const
1431 {
1432  GLdouble xx1, yy1, zz1, rad;
1433  GLdouble xx2, yy2, zz2;
1434  map->GetOpenGLCoord(a.x, a.y, xx1, yy1, zz1, rad);
1435  map->GetOpenGLCoord(b.x, b.y, xx2, yy2, zz2, rad);
1436 
1437  rgbColor c;// = {0.5, 0.5, 0};
1438  GLfloat t;
1439  GetColor(c.r, c.g, c.b, t);
1440 
1441  disp.DrawLine({static_cast<float>(xx1), static_cast<float>(yy1)},
1442  {static_cast<float>(xx2), static_cast<float>(yy2)}, width*rad*0.1, c);
1443 }
1444 
1445 void MapEnvironment::DrawArrow(Graphics::Display &disp, const xyLoc &a, const xyLoc &b, double width) const
1446 {
1447  GLdouble xx1, yy1, zz1, rad;
1448  GLdouble xx2, yy2, zz2;
1449  map->GetOpenGLCoord(a.x, a.y, xx1, yy1, zz1, rad);
1450  map->GetOpenGLCoord(b.x, b.y, xx2, yy2, zz2, rad);
1451 
1452  rgbColor c;// = {0.5, 0.5, 0};
1453  GLfloat t;
1454  GetColor(c.r, c.g, c.b, t);
1455 
1456  disp.DrawArrow({static_cast<float>(xx1), static_cast<float>(yy1)},
1457  {static_cast<float>(xx2), static_cast<float>(yy2)}, 0.1*rad*width, c);
1458 }
1459 
1460 
1461 //void MapEnvironment::OpenGLDraw(const xyLoc& initial, const tDirection &dir, GLfloat r, GLfloat g, GLfloat b) const
1462 //{
1463 // xyLoc s = initial;
1464 // GLdouble xx, yy, zz, rad;
1465 // map->GetOpenGLCoord(s.x, s.y, xx, yy, zz, rad);
1466 //
1467 // glColor3f(r,g,b);
1468 // glBegin(GL_LINE_STRIP);
1469 // glVertex3f(xx, yy, zz-rad/2);
1470 //
1471 //
1472 // switch (dir)
1473 // {
1474 // case kN: s.y-=1; break;
1475 // case kS: s.y+=1; break;
1476 // case kE: s.x+=1; break;
1477 // case kW: s.x-=1; break;
1478 // case kNW: s.y-=1; s.x-=1; break;
1479 // case kSW: s.y+=1; s.x-=1; break;
1480 // case kNE: s.y-=1; s.x+=1; break;
1481 // case kSE: s.y+=1; s.x+=1; break;
1482 // default: break;
1483 // }
1484 //
1485 //
1486 // map->GetOpenGLCoord(s.x, s.y, xx, yy, zz, rad);
1487 // glVertex3f(xx, yy, zz-rad/2);
1488 // glEnd();
1489 //}
1490 
1491 void MapEnvironment::GetNextState(const xyLoc &currents, tDirection dir, xyLoc &news) const
1492  {
1493  news = currents;
1494  switch (dir)
1495  {
1496  case kN: news.y-=1; break;
1497  case kS: news.y+=1; break;
1498  case kE: news.x+=1; break;
1499  case kW: news.x-=1; break;
1500  case kNW: news.y-=1; news.x-=1; break;
1501  case kSW: news.y+=1; news.x-=1; break;
1502  case kNE: news.y-=1; news.x+=1; break;
1503  case kSE: news.y+=1; news.x+=1; break;
1504  default: break;
1505  }
1506 }
1507 
1508 //double MapEnvironment::GetPathLength(std::vector<xyLoc> &neighbors)
1509 //{
1510 // double length = 0;
1511 // for (unsigned int x = 1; x < neighbors.size(); x++)
1512 // {
1513 // length += GCost(neighbors[x-1], neighbors[x]);
1514 // }
1515 // return length;
1516 //}
1517 
1518 
1519 /***********************************************************/
1520 /*
1521 AbsMapEnvironment::AbsMapEnvironment(MapAbstraction *_ma)
1522 :MapEnvironment(_ma->GetMap())
1523 {
1524  ma = _ma;
1525 
1526 }
1527 
1528 AbsMapEnvironment::~AbsMapEnvironment()
1529 {
1530  map = 0;
1531  //delete ma;
1532 }
1533 */
1534 /************************************************************/
1535 
1544 {
1545  mapWidth = m->GetMapWidth();
1546  mapHeight = m->GetMapHeight();
1547  bitvec.resize(mapWidth*mapHeight);// = new BitVector(mapWidth * mapHeight);
1548 
1549  //initialize the bitvector
1550 // for (int i=0; i<m->GetMapWidth(); i++)
1551 // for (int j=0; j<m->GetMapHeight(); j++)
1552 // bitvec->Set(CalculateIndex(i,j), false);
1553 }
1554 
1555 
1556 
1563 {
1564 // delete bitvec;
1565 // bitvec = 0;
1566 }
1567 
1577 {
1578  // Make sure the location is valid
1579  // unsigned, so must be greater than 0
1580  assert(/*(s.x>=0) &&*/ (s.x<mapWidth)/* && (s.y>=0)*/ && (s.y<mapHeight));
1581 // bitvec->Set(CalculateIndex(s.x,s.y), occupied);
1582  bitvec[CalculateIndex(s.x,s.y)] = occupied;
1583 }
1584 
1594 {
1595  // unsigned, so must be greater than 0
1596  assert(/*s.x>=0 &&*/ s.x<=mapWidth && /*s.y>=0 && */s.y<=mapHeight);
1597  //return bitvec->Get(CalculateIndex(s.x,s.y));
1598  return bitvec[CalculateIndex(s.x,s.y)];
1599 }
1600 
1612 //template <class state, class action>
1613 long BaseMapOccupancyInterface::CalculateIndex(uint16_t x, uint16_t y)
1614 {
1615  return (y * mapWidth) + x;
1616 }
1617 
1629 void BaseMapOccupancyInterface::MoveUnitOccupancy(const xyLoc &oldState, const xyLoc &newState)
1630 {
1631  SetStateOccupied(oldState, false);
1632  SetStateOccupied(newState, true);
1633 }
1634 
1636 {
1637  if (!(GetStateOccupied(l2)))
1638  {
1639  return true;
1640  }
1641  else
1642  {
1643  return false;
1644  }
1645 
1646 }
Graphics::Display::DrawLine
void DrawLine(point start, point end, float lineWidth, rgbColor c)
Definition: Graphics.cpp:184
Graphics::point
Definition: Graphics.h:32
loc::x
int x
Definition: MapGenerators.cpp:296
Graphics::point::y
float y
Definition: Graphics.h:36
MapEnvironment::SVGHeader
std::string SVGHeader()
Definition: Map2DEnvironment.cpp:732
Colors::GetColor
rgbColor GetColor(float v, float vmin, float vmax, int type)
Given min/max values, get a color from a color schema.
Definition: Colors.cpp:24
MapEnvironment::GoalTest
bool GoalTest(const xyLoc &node, const xyLoc &goal) const
Definition: Map2DEnvironment.cpp:524
MapEnvironment::DrawAlternate
void DrawAlternate(Graphics::Display &disp, const xyLoc &l) const
Definition: Map2DEnvironment.cpp:1361
MapEnvironment::InvertAction
virtual bool InvertAction(tDirection &a) const
Definition: Map2DEnvironment.cpp:415
rgbColor::b
float b
Definition: Colors.h:71
rgbColor
A color; r/g/b are between 0...1.
Definition: Colors.h:17
kSE
@ kSE
Definition: Map2DEnvironment.h:79
BaseMapOccupancyInterface::CalculateIndex
long CalculateIndex(uint16_t x, uint16_t y)
used to compute index into bitvector
Definition: Map2DEnvironment.cpp:1613
graphState
unsigned long graphState
Definition: GraphEnvironment.h:32
MapEnvironment::GetStateFromHash
void GetStateFromHash(uint64_t parent, xyLoc &s) const
Definition: Map2DEnvironment.cpp:541
terrainBits
const int terrainBits
Definition: Map.h:49
BaseMapOccupancyInterface::GetStateOccupied
virtual bool GetStateOccupied(const xyLoc &)
Returns the occupancy of a state.
Definition: Map2DEnvironment.cpp:1593
BaseMapOccupancyInterface
Definition: Map2DEnvironment.h:82
kTeleport
@ kTeleport
Definition: Map2DEnvironment.h:79
MapEnvironment::GetNext4Successor
bool GetNext4Successor(const xyLoc &currOpenNode, const xyLoc &goal, xyLoc &next, double &currHCost, uint64_t &special, bool &validMove)
Definition: Map2DEnvironment.cpp:102
loc::y
int y
Definition: MapGenerators.cpp:296
kTrees
@ kTrees
Definition: Map.h:59
MapEnvironment::SetGraphHeuristic
void SetGraphHeuristic(GraphHeuristic *h)
Definition: Map2DEnvironment.cpp:54
kOutOfBounds
@ kOutOfBounds
Definition: Map.h:52
xyLoc::y
uint16_t y
Definition: Map2DEnvironment.h:42
MapEnvironment::GetStateLoc
Graphics::point GetStateLoc(const xyLoc &l1)
Definition: Map2DEnvironment.cpp:1385
kW
@ kW
Definition: Map2DEnvironment.h:78
MapEnvironment::~MapEnvironment
virtual ~MapEnvironment()
Definition: Map2DEnvironment.cpp:43
SVGDrawText
std::string SVGDrawText(float x1, float y1, const char *txt, rgbColor c, double size, const char *typeface, SVG::svgAlignment align, SVG::svgBaseline base)
Definition: SVGUtil.cpp:227
Map::Clone
Map * Clone()
Definition: Map.h:159
MapEnvironment::oi
BaseMapOccupancyInterface * oi
Definition: Map2DEnvironment.h:222
MapEnvironment::SVGDraw
std::string SVGDraw()
Definition: Map2DEnvironment.cpp:744
SVGDrawRect
std::string SVGDrawRect(float x, float y, float width, float height, const char *gradient)
Definition: SVGUtil.cpp:74
Graphics::rect
Definition: Graphics.h:94
BaseMapOccupancyInterface::MoveUnitOccupancy
virtual void MoveUnitOccupancy(const xyLoc &, const xyLoc &)
Updates the occupancy interface when a unit moves.
Definition: Map2DEnvironment.cpp:1629
MapEnvironment::SVGLabelState
std::string SVGLabelState(const xyLoc &, const char *, double scale) const
Definition: Map2DEnvironment.cpp:906
FPUtil.h
DrawSphere
void DrawSphere(GLdouble _x, GLdouble _y, GLdouble _z, GLdouble tRadius)
Definition: GLUtil.cpp:433
xyLoc
Definition: Map2DEnvironment.h:37
width
int width
Definition: SFML_HOG.cpp:54
kNoOptions
@ kNoOptions
Definition: Map2DEnvironment.h:31
Map2DEnvironment.h
kCellBorderLines
@ kCellBorderLines
Definition: Map2DEnvironment.h:34
rgbColor::g
float g
Definition: Colors.h:71
MapEnvironment::GCost
virtual double GCost(const xyLoc &node1, const xyLoc &node2) const
Definition: Map2DEnvironment.cpp:507
MapEnvironment::SVGDrawLine
std::string SVGDrawLine(const xyLoc &x, const xyLoc &y, int width=1) const
Definition: Map2DEnvironment.cpp:936
kEfficientCells
@ kEfficientCells
Definition: Map2DEnvironment.h:32
MapEnvironment::OpenGLDraw
virtual void OpenGLDraw() const
Definition: Map2DEnvironment.cpp:552
MapEnvironment::Draw
void Draw(Graphics::Display &disp) const
Definition: Map2DEnvironment.cpp:1039
xyLoc::x
uint16_t x
Definition: Map2DEnvironment.h:41
MapEnvironment::map
Map * map
Definition: Map2DEnvironment.h:221
kStay
@ kStay
Definition: Map2DEnvironment.h:79
MapEnvironment::ApplyAction
virtual void ApplyAction(xyLoc &s, tDirection dir) const
Definition: Map2DEnvironment.cpp:432
kGround
@ kGround
Definition: Map.h:55
MapEnvironment::GetMaxRect
void GetMaxRect(long terrain, int x, int y, int endx, int endy, std::vector< bool > &drawn, Graphics::rect &r) const
Definition: Map2DEnvironment.cpp:953
Graphics::rect::top
float top
Definition: Graphics.h:100
kSwamp
@ kSwamp
Definition: Map.h:56
MapEnvironment
Definition: Map2DEnvironment.h:133
loc
Definition: MapGenerators.cpp:296
MapEnvironment::SVGFrameRect
std::string SVGFrameRect(int left, int top, int right, int bottom, int width=1)
Definition: Map2DEnvironment.cpp:894
kE
@ kE
Definition: Map2DEnvironment.h:78
Colors::black
const rgbColor black
Definition: Colors.h:119
SVGUtil.h
PI
static const double PI
Definition: GLUtil.h:66
Graphics::Display
Definition: Graphics.h:146
Graphics
Definition: Graphics.cpp:11
MapEnvironment::MapEnvironment
MapEnvironment(Map *m, bool useOccupancy=false)
Definition: Map2DEnvironment.cpp:18
ROOT_TWO
static const double ROOT_TWO
Definition: GLUtil.h:61
Graphics::rect::right
float right
Definition: Graphics.h:100
Map::GetMapWidth
long GetMapWidth() const
return the width of the map
Definition: Map.h:163
tDirection
tDirection
Definition: Map2DEnvironment.h:77
MapEnvironment::GetMaxHash
uint64_t GetMaxHash() const
Definition: Map2DEnvironment.cpp:529
MapEnvironment::GetGraphHeuristic
GraphHeuristic * GetGraphHeuristic()
Definition: Map2DEnvironment.cpp:49
MapEnvironment::DrawArrow
void DrawArrow(Graphics::Display &disp, const xyLoc &x, const xyLoc &y, double width=1.0) const
Definition: Map2DEnvironment.cpp:1445
Graphics::Display::FrameCircle
void FrameCircle(rect r, rgbColor c, float lineWidth)
Definition: Graphics.cpp:110
MapEnvironment::HCost
virtual double HCost(const xyLoc &) const
Heuristic value between node and the stored goal.
Definition: Map2DEnvironment.h:154
max
#define max(a, b)
Definition: MinimalSectorAbstraction.cpp:40
MapEnvironment::GetSuccessors
virtual void GetSuccessors(const xyLoc &nodeID, std::vector< xyLoc > &neighbors) const
Definition: Map2DEnvironment.cpp:59
Graphics.h
kN
@ kN
Definition: Map2DEnvironment.h:78
Graphics::Display::DrawArrow
void DrawArrow(point start, point end, float lineWidth, rgbColor c)
Definition: Graphics.cpp:193
rgbColor::r
float r
Definition: Colors.h:71
MapEnvironment::GetStateHash
uint64_t GetStateHash(const xyLoc &node) const
Definition: Map2DEnvironment.cpp:534
SVGDrawLine
std::string SVGDrawLine(float x1, float y1, float x2, float y2, float width, rgbColor c)
Definition: SVGUtil.cpp:192
MapEnvironment::GetActions
void GetActions(const xyLoc &nodeID, std::vector< tDirection > &actions) const
Definition: Map2DEnvironment.cpp:355
MapEnvironment::GLDrawLine
virtual void GLDrawLine(const xyLoc &x, const xyLoc &y) const
Definition: Map2DEnvironment.cpp:643
Graphics::point::x
float x
Definition: Graphics.h:36
kWater
@ kWater
Definition: Map.h:54
Graphics::Display::FillCircle
void FillCircle(rect r, rgbColor c)
Definition: Graphics.cpp:128
Graphics::Display::FrameRect
void FrameRect(rect r, rgbColor c, float lineWidth)
Definition: Graphics.cpp:73
MapEnvironment::DrawSingleTerrain
void DrawSingleTerrain(long terrain, Graphics::Display &disp, std::vector< bool > &drawn) const
Definition: Map2DEnvironment.cpp:1003
kS
@ kS
Definition: Map2DEnvironment.h:78
BaseMapOccupancyInterface::SetStateOccupied
virtual void SetStateOccupied(const xyLoc &, bool)
Sets the occupancy of a state.
Definition: Map2DEnvironment.cpp:1576
Map::GetMapHeight
long GetMapHeight() const
return the height of the map
Definition: Map.h:165
MapEnvironment::DrawLine
void DrawLine(Graphics::Display &disp, const xyLoc &x, const xyLoc &y, double width=1.0) const
Definition: Map2DEnvironment.cpp:1430
MapEnvironment::GetNextSuccessor
bool GetNextSuccessor(const xyLoc &currOpenNode, const xyLoc &goal, xyLoc &next, double &currHCost, uint64_t &special, bool &validMove)
Definition: Map2DEnvironment.cpp:92
kTerrainBorderLines
@ kTerrainBorderLines
Definition: Map2DEnvironment.h:33
MapEnvironment::DrawStateLabel
void DrawStateLabel(Graphics::Display &disp, const xyLoc &l1, const char *txt) const
Definition: Map2DEnvironment.cpp:1392
MapEnvironment::DIAGONAL_COST
double DIAGONAL_COST
Definition: Map2DEnvironment.h:223
Graphics::rect::left
float left
Definition: Graphics.h:100
Graphics::Display::DrawLineSegments
void DrawLineSegments(const std::vector< point > &points, float lineWidth, rgbColor c)
Definition: Graphics.cpp:230
kNE
@ kNE
Definition: Map2DEnvironment.h:78
py1
int py1
Definition: Sample.cpp:28
BaseMapOccupancyInterface::BaseMapOccupancyInterface
BaseMapOccupancyInterface(Map *m)
Constructor for the BaseMapOccupancyInterface.
Definition: Map2DEnvironment.cpp:1543
MapEnvironment::GetNextState
virtual void GetNextState(const xyLoc &currents, tDirection dir, xyLoc &news) const
Definition: Map2DEnvironment.cpp:1491
kGrass
@ kGrass
Definition: Map.h:57
Graphics::Display::DrawText
void DrawText(const char *text, point location, rgbColor c, float height, const char *typeface=0)
Definition: Graphics.cpp:221
MapEnvironment::GetNext8Successor
bool GetNext8Successor(const xyLoc &currOpenNode, const xyLoc &goal, xyLoc &next, double &currHCost, uint64_t &special, bool &validMove)
Definition: Map2DEnvironment.cpp:219
Colors::lightgray
const rgbColor lightgray
Definition: Colors.h:125
MapEnvironment::fourConnected
bool fourConnected
Definition: Map2DEnvironment.h:224
Graphics::rect::bottom
float bottom
Definition: Graphics.h:100
Graphics::Display::FillRect
void FillRect(rect r, rgbColor c)
Definition: Graphics.cpp:101
MapEnvironment::GetActionHash
uint64_t GetActionHash(tDirection act) const
Definition: Map2DEnvironment.cpp:547
kSW
@ kSW
Definition: Map2DEnvironment.h:79
BaseMapOccupancyInterface::~BaseMapOccupancyInterface
virtual ~BaseMapOccupancyInterface()
Destructor for the BaseMapOccupancyInterface.
Definition: Map2DEnvironment.cpp:1562
node
Nodes to be stored within a Graph.
Definition: Graph.h:170
MapEnvironment::GetAction
tDirection GetAction(const xyLoc &s1, const xyLoc &s2) const
Definition: Map2DEnvironment.cpp:392
MapEnvironment::GLLabelState
virtual void GLLabelState(const xyLoc &, const char *) const
Definition: Map2DEnvironment.cpp:709
Map
A tile-based representation of the world.
Definition: Map.h:142
SVGFrameRect
std::string SVGFrameRect(float x, float y, float width, float height, float border, rgbColor c)
Definition: SVGUtil.cpp:99
GraphHeuristic
Definition: GraphEnvironment.h:77
kNW
@ kNW
Definition: Map2DEnvironment.h:78
BaseMapOccupancyInterface::CanMove
virtual bool CanMove(const xyLoc &, const xyLoc &)
Definition: Map2DEnvironment.cpp:1635
px1
int px1
Definition: Sample.cpp:28