HOG2
MinimalSectorAbstraction.cpp
Go to the documentation of this file.
1 /*
2  * MinimalSectorAbstraction.cpp
3  *
4  * Copyright (c) 2007, Nathan Sturtevant
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * * Neither the name of the University of Alberta nor the
15  * names of its contributors may be used to endorse or promote products
16  * derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY NATHAN STURTEVANT ``AS IS'' AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
31 #include <queue>
32 #include "GenericAStar.h"
33 #include "Map2DEnvironment.h"
34 
35 //int sectorSize = 11;
36 
37 #define DIAG_MOVES
38 
39 #ifndef _MSC_VER
40 #define max(a, b) (((a)>(b))?(a):(b))
41 #endif
42 
53 :map(m)
54 {
55  sectorSize = theSectorSize;
58  int absSize = numXSectors*numYSectors;
59  printf("%d x sectors, %d y sectors\n", numXSectors, numYSectors);
60  sectors.resize(absSize);
62  optimizationIndex = (int)sectors.size();
63 }
64 
82 {
83  areas.clear();
85  for (int x = 0; x < numXSectors; x++)
86  {
87  for (int y = 0; y < numYSectors; y++)
88  {
89  int numRegions = GetSectorRegions(areas[y*numXSectors+x], x, y);
90  assert(numRegions < 256);
91  sectors[y*numXSectors+x].numRegions = numRegions;
92  }
93  }
94 
95  for (int x = 0; x < numXSectors; x++)
96  {
97  for (int y = 0; y < numYSectors; y++)
98  {
99  std::vector<tempEdgeData> edges;
100  GetEdges(areas, x, y, edges);
101  assert(edges.size() < 256);
102  sectors[y*numXSectors+x].numEdges = (uint8_t)edges.size();
104  }
105  }
106  printf("Total bytes used for abstraction: %d\n", (int)memory.size());
107  printf("Extra memory used: %d\n", (int)(sectors.size()*sizeof(sectorInfo)));
108  int nodes = 0, edges = 0;
109  for (unsigned int x = 0; x < sectors.size(); x++)
110  {
111  nodes += sectors[x].numRegions;
112  edges += sectors[x].numEdges;
113  }
114  printf("%d regions and %d edges\n", nodes, edges);
115  //OptimizeRegionLocations();
117 }
118 
132 void MinimalSectorAbstraction::GetEdges(std::vector<std::vector<int> > &areas,
133  int xSector, int ySector,
134  std::vector<tempEdgeData> &edges)
135 {
136  bool up = false, down = false, left = false, right = false;
137  if (ySector > 0) // up
138  {
139  up = true;
140  // get edge helper does the actual work of finding edges between adjacent sectors
141  GetEdgeHelper(areas[xSector + numXSectors*ySector], 0, 1,
142  areas[xSector + numXSectors*(ySector-1)], sectorSize*(sectorSize-1), 1,
143  edges, 0);
144  }
145  if (xSector > 0) // left
146  {
147  left = true;
148  GetEdgeHelper(areas[xSector + numXSectors*ySector], 0, sectorSize,
149  areas[(xSector-1) + numXSectors*ySector], sectorSize-1, sectorSize,
150  edges, 3);
151  }
152  if (ySector < numYSectors-1) // down
153  {
154  down = true;
155  GetEdgeHelper(areas[xSector + numXSectors*ySector], sectorSize*(sectorSize-1), 1,
156  areas[xSector + numXSectors*(ySector+1)], 0, 1,
157  edges, 2);
158  }
159  if (xSector < numXSectors-1) // right
160  {
161  right = true;
162  GetEdgeHelper(areas[xSector + numXSectors*ySector], sectorSize-1, sectorSize,
163  areas[(xSector+1) + numXSectors*ySector], 0, sectorSize,
164  edges, 1);
165  }
166 #ifdef DIAG_MOVES
167  // for diagonal moves, we directly check for diagonal moves -- all four points
168  // on the corner of the sector must be free to allow an edge to be created.
169  if (up && right)
170  {
171  if ((areas[xSector + numXSectors*(ySector)][sectorSize-1] != -1) && // current
172  (areas[xSector + numXSectors*(ySector-1)][sectorSize*sectorSize-1] != -1) && // up
173  (areas[xSector + 1 + numXSectors*(ySector-1)][sectorSize*(sectorSize-1)] != -1) && // up right
174  (areas[xSector + 1 + numXSectors*(ySector)][0] != -1)) // right
175  {
176  tempEdgeData ted;
177  ted.from = areas[xSector + numXSectors*(ySector)][sectorSize-1];
178  ted.to = areas[xSector + 1 + numXSectors*(ySector-1)][sectorSize*(sectorSize-1)];
179  ted.direction = 4;
180  edges.push_back(ted);
181  // printf("Adding diagonal edge between %d:(%d, %d) and %d:(%d, %d)\n",
182  // ted.from, xSector, ySector, ted.to, xSector+1, ySector-1);
183  }
184  }
185  if (up && left)
186  {
187  if ((areas[xSector + numXSectors*(ySector)][0] != -1) && // current
188  (areas[xSector + numXSectors*(ySector-1)][sectorSize*(sectorSize-1)] != -1) && // up
189  (areas[xSector - 1 + numXSectors*(ySector-1)][sectorSize*sectorSize-1] != -1) && // up left
190  (areas[xSector - 1 + numXSectors*(ySector)][sectorSize-1] != -1)) // left
191  {
192  tempEdgeData ted;
193  ted.from = areas[xSector + numXSectors*(ySector)][0];
194  ted.to = areas[xSector - 1 + numXSectors*(ySector-1)][sectorSize*sectorSize-1];
195  ted.direction = 7;
196  edges.push_back(ted);
197  // printf("Adding diagonal edge between %d:(%d, %d) and %d:(%d, %d)\n",
198  // ted.from, xSector, ySector, ted.to, xSector-1, ySector-1);
199  }
200  }
201  if (down && left)
202  {
203  if ((areas[xSector + numXSectors*(ySector)][sectorSize*(sectorSize-1)] != -1) && // current
204  (areas[xSector + numXSectors*(ySector+1)][0] != -1) && // down
205  (areas[xSector - 1 + numXSectors*(ySector+1)][sectorSize-1] != -1) && // down left
206  (areas[xSector - 1 + numXSectors*(ySector)][sectorSize*sectorSize-1] != -1)) // left
207  {
208  tempEdgeData ted;
209  ted.from = areas[xSector + numXSectors*(ySector)][sectorSize*(sectorSize-1)];
210  ted.to = areas[xSector - 1 + numXSectors*(ySector+1)][sectorSize-1];
211  ted.direction = 6;
212  edges.push_back(ted);
213  // printf("Adding diagonal edge between %d:(%d, %d) and %d:(%d, %d)\n",
214  // ted.from, xSector, ySector, ted.to, xSector-1, ySector+1);
215  }
216  }
217  if (down && right)
218  {
219  if ((areas[xSector + numXSectors*(ySector)][sectorSize*sectorSize-1] != -1) && // current
220  (areas[xSector + numXSectors*(ySector+1)][sectorSize-1] != -1) && // down
221  (areas[xSector + 1 + numXSectors*(ySector+1)][0] != -1) && // down right
222  (areas[xSector + 1 + numXSectors*(ySector)][sectorSize*(sectorSize-1)] != -1)) // right
223  {
224  tempEdgeData ted;
225  ted.from = areas[xSector + numXSectors*(ySector)][sectorSize*sectorSize-1];
226  ted.to = areas[xSector + 1 + numXSectors*(ySector+1)][0];
227  ted.direction = 5;
228  edges.push_back(ted);
229  // printf("Adding diagonal edge between %d:(%d, %d) and %d:(%d, %d)\n",
230  // ted.from, xSector, ySector, ted.to, xSector+1, ySector+1);
231  }
232  }
233 #endif
234 }
235 
258 void MinimalSectorAbstraction::GetEdgeHelper(std::vector<int> &startRegion,
259  int startIndex, int startOffset,
260  std::vector<int> &targetRegion,
261  int targetIndex, int targetOffset,
262  std::vector<tempEdgeData> &edges,
263  int direction)
264 {
265  int first = (int)edges.size();
266  int last = -1;
267  for (int x = 0; x < sectorSize; x++)
268  {
269  if ((startRegion[startIndex] != -1) &&
270  (targetRegion[targetIndex] != -1))
271  {
272  if ((last == -1) ||
273  (edges[edges.size()-1].from != startRegion[startIndex]) ||
274  (edges[edges.size()-1].to != targetRegion[targetIndex]))
275  {
276  bool here = false;
277  tempEdgeData ted;
278  ted.from = startRegion[startIndex];
279  ted.to = targetRegion[targetIndex];
280  ted.direction = direction;
281  for (unsigned int y = first; y < edges.size(); y++)
282  {
283  if (edges[y] == ted)
284  {
285  here = true;
286  break;
287  }
288  }
289  if (!here)
290  {
291  edges.push_back(ted);
292  last = (int)edges.size()-1;
293  }
294  }
295  }
296  startIndex += startOffset;
297  targetIndex += targetOffset;
298  }
299 }
300 
315  std::vector<int> &area,
316  std::vector<tempEdgeData> &edges)
317 {
318  // count number of edges for each region
319  std::vector<int> counts(si.numRegions);
320  for (unsigned int y = 0; y < counts.size(); y++)
321  {
322  for (unsigned int x = 0; x < edges.size(); x++)
323  if (edges[x].from == (int)y+1)
324  counts[y]++;
325  }
326 
327  // now we know the size needed to store this, and
328  // we can compute the rest of the abstraction info
329  assert(memory.size() < (1<<16));
330  si.memoryAddress = (uint16_t)memory.size();
331  int sum = 0;
332  for (int x = 0; x < si.numRegions; x++)
333  {
334  sum += counts[x];
335  // regions are numbered 0..n, but they are labelled 1..n+1
336  // inside the area information
337  memory.push_back(GetAbstractLocation(area, x+1));
338  memory.push_back(sum); // last edge of this parent
339  }
340  // printf("Sum is %d, total is %d\n", sum, si.numEdges);
341  assert(sum == si.numEdges);
342  // Add all the edges;
343  // this can be done faster, but I'm lazy
344  for (unsigned int y = 0; y < counts.size(); y++)
345  {
346  for (unsigned int x = 0; x < edges.size(); x++)
347  {
348  if (edges[x].from == (int)y+1)
349  memory.push_back(GetAbstractEdge(edges[x]));
350  }
351  }
352 }
353 
366 {
367 #ifdef DIAG_MOVES
368  return (data.direction<<5)|((data.to-1)&0x1F);
369 #else
370  return (data.direction<<6)|((data.to-1)&0x3F);
371 #endif
372 }
373 
386 uint8_t MinimalSectorAbstraction::GetAbstractLocation(std::vector<int> area, int value)
387 {
388  // too simple, finds any point
389  // for (unsigned int x = 0; x < area.size(); x++)
390  // {
391  // if (area[x] == value)
392  // {
393  // return x;
394  // }
395  // }
396  // assert(false);
397 
398  // find center of mass and get the point closest to it
399  int xaverage = 0;
400  int yaverage = 0;
401  int count = 0;
402  for (unsigned int x = 0; x < area.size(); x++)
403  {
404  if (area[x] == value)
405  {
406  count++;
407  xaverage+=x%sectorSize;
408  yaverage+=x/sectorSize;
409  }
410  }
411  assert(count != 0);
412  xaverage/=count;
413  yaverage/=count;
414  int best = sectorSize*sectorSize;
415  int index = -1;
416  for (unsigned int x = 0; x < area.size(); x++)
417  {
418  if (area[x] == value)
419  {
420  int score = ((x%sectorSize)-xaverage)*((x%sectorSize)-xaverage) +
421  (x/sectorSize - yaverage)*(x/sectorSize - yaverage);
422  if (score < best)
423  {
424  best = score;
425  index = x;
426  }
427  }
428  }
429  assert(index != -1);
430  return index;
431 }
432 
445 {
446  static bool draw = false;
447 
448  // this will draw the sectors for the map
449  GLdouble xx, yy, zz, rr;
450  glColor4f(0.5, 0.0, 0.0, 0.5);
451  map->GetOpenGLCoord(0, 0, xx, yy, zz, rr);
452 
453  // draw grid lines for sectors
454  glLineWidth(2);
455  glBegin(GL_LINES);
456  for (int y = 0; y <= numYSectors; y++)
457  {
458  glVertex3f(xx-rr, yy-rr+2*y*rr*sectorSize, zz-1*rr);
459  glVertex3f(xx+2*numXSectors*rr*sectorSize, yy-rr+2*y*sectorSize*rr, zz-1*rr);
460  }
461  for (int x = 0; x <= numXSectors; x++)
462  {
463  glVertex3f(xx-rr+2*x*rr*sectorSize, yy-rr, zz-1*rr);
464  glVertex3f(xx-rr+2*x*rr*sectorSize, yy-rr+2*numYSectors*rr*sectorSize, zz-1*rr);
465  }
466  glEnd();
467  glLineWidth(1);
468 
469  if (draw) printf("===BEGIN DRAW\n");
470  // now draw the abstraction itself
471  for (unsigned int x = 0; x < sectors.size(); x++)
472  {
473  for (unsigned int y = 0; y < sectors[x].numRegions; y++)
474  {
475  if (draw) printf("===DRAW SECTOR %d region %d\n", x, y);
476 
477  unsigned int loc1, loc2;
478  std::vector<tempEdgeData> neighbors;
479  GetNeighbors(x, y, neighbors);
480 
481  glBegin(GL_LINES);
482  GetXYLocation(x, y, loc1, loc2);
483  map->GetOpenGLCoord((int)loc1, (int)loc2, xx, yy, zz, rr);
484  for (unsigned int z = 0; z < neighbors.size(); z++)
485  {
486  // if the current sector is being optimized, change the color
487  if ((int)x == optimizationIndex)
488  glColor3f(1.0, 0.0, 0.0);
489  else
490  glColor4f(0.2, 0.8, 0.2, 1.00);
491 
492  if (draw) printf("Got edge from region %d to region %d (going dir %d)\n",
493  neighbors[z].from, neighbors[z].to, neighbors[z].direction);
494  if (draw) printf("Drawing from (%d, %d)\n", loc1, loc2);
495 
496  GLdouble xx2, yy2, zz2, rr2;
497  // only draw half of the directions, since edges are represented twice
498  switch (neighbors[z].direction)
499  {
500  case 0:
501  glVertex3f(xx, yy, zz-5.1*rr);
502  if ((int)x-numXSectors == optimizationIndex)
503  glColor3f(1.0, 0.0, 0.0);
504  else
505  glColor4f(0.2, 0.8, 0.2, 1.00);
506  GetXYLocation(x-numXSectors, neighbors[z].to, loc1, loc2);
507  map->GetOpenGLCoord((int)loc1, (int)loc2, xx2, yy2, zz2, rr2);
508  if (draw) printf("Drawing to (%d, %d)\n", loc1, loc2);
509  glVertex3f(xx2, yy2, zz2-5.1*rr2);
510  break;
511  case 1:
512  glVertex3f(xx, yy, zz-5.1*rr);
513  if ((int)x+1 == optimizationIndex)
514  glColor3f(1.0, 0.0, 0.0);
515  else
516  glColor4f(0.2, 0.8, 0.2, 1.00);
517  GetXYLocation(x+1, neighbors[z].to, loc1, loc2);
518  map->GetOpenGLCoord((int)loc1, (int)loc2, xx2, yy2, zz2, rr2);
519  if (draw) printf("Drawing to (%d, %d)\n", loc1, loc2);
520  glVertex3f(xx2, yy2, zz2-5.1*rr2);
521  break;
522  case 2:
523  case 3: break;
524  case 4:
525  glVertex3f(xx, yy, zz-5.1*rr);
526  if ((int)x-numXSectors+1 == optimizationIndex)
527  glColor3f(1.0, 0.0, 0.0);
528  else
529  glColor4f(0.2, 0.8, 0.2, 1.00);
530  GetXYLocation(x-numXSectors+1, neighbors[z].to, loc1, loc2);
531  map->GetOpenGLCoord((int)loc1, (int)loc2, xx2, yy2, zz2, rr2);
532  if (draw) printf("Drawing to (%d, %d)\n", loc1, loc2);
533  glVertex3f(xx2, yy2, zz2-5.1*rr2);
534  break;
535  case 5:
536  glVertex3f(xx, yy, zz-5.1*rr);
537  if ((int)x+numXSectors+1 == optimizationIndex)
538  glColor3f(1.0, 0.0, 0.0);
539  else
540  glColor4f(0.2, 0.8, 0.2, 1.00);
541  GetXYLocation(x+numXSectors+1, neighbors[z].to, loc1, loc2);
542  map->GetOpenGLCoord((int)loc1, (int)loc2, xx2, yy2, zz2, rr2);
543  if (draw) printf("Drawing to (%d, %d)\n", loc1, loc2);
544  glVertex3f(xx2, yy2, zz2-5.1*rr2);
545  break;
546  default:
547  break; // otherwise we draw all edges twice
548  }
549  }
550  glEnd();
551  }
552  }
553  draw = false;
554 }
555 
557 {
558  static bool draw = false;
559  static float lineScale = 0.5f;
560  // this will draw the sectors for the map
561  GLdouble xx, yy, zz, rr;
562 // glColor4f(0.5, 0.0, 0.0, 0.5);
563  map->GetOpenGLCoord(0, 0, xx, yy, zz, rr);
564 
565  // draw grid lines for sectors
566 // glLineWidth(2);
567 // glBegin(GL_LINES);
568  for (int y = 0; y <= numYSectors; y++)
569  {
570  display.DrawLine({static_cast<float>(xx-rr), static_cast<float>(yy-rr+2*y*rr*sectorSize), static_cast<float>(zz-1*rr)},
571  {static_cast<float>(xx+2*numXSectors*rr*sectorSize), static_cast<float>(yy-rr+2*y*sectorSize*rr), static_cast<float>(zz-1*rr)},
572  lineScale*rr, Colors::yellow);
573 // glVertex3f(xx-rr, yy-rr+2*y*rr*sectorSize, zz-1*rr);
574 // glVertex3f(xx+2*numXSectors*rr*sectorSize, yy-rr+2*y*sectorSize*rr, zz-1*rr);
575  }
576  for (int x = 0; x <= numXSectors; x++)
577  {
578  display.DrawLine({static_cast<float>(xx-rr+2*x*rr*sectorSize), static_cast<float>(yy-rr), static_cast<float>(zz-1*rr)},
579  {static_cast<float>(xx-rr+2*x*rr*sectorSize), static_cast<float>(yy-rr+2*numYSectors*rr*sectorSize), static_cast<float>(zz-1*rr)},
580  lineScale*rr, Colors::yellow);
581 // glVertex3f(xx-rr+2*x*rr*sectorSize, yy-rr, zz-1*rr);
582 // glVertex3f(xx-rr+2*x*rr*sectorSize, yy-rr+2*numYSectors*rr*sectorSize, zz-1*rr);
583  }
584 // glEnd();
585 // glLineWidth(1);
586 
587  rgbColor abstractionColor = Colors::bluegreen;
588 
589 // if (draw) printf("===BEGIN DRAW\n");
590  // now draw the abstraction itself
591  for (unsigned int x = 0; x < sectors.size(); x++)
592  {
593  for (unsigned int y = 0; y < sectors[x].numRegions; y++)
594  {
595 // if (draw) printf("===DRAW SECTOR %d region %d\n", x, y);
596 
597  unsigned int loc1, loc2;
598  std::vector<tempEdgeData> neighbors;
599  GetNeighbors(x, y, neighbors);
600 
601 // glBegin(GL_LINES);
602  GetXYLocation(x, y, loc1, loc2);
603  map->GetOpenGLCoord((int)loc1, (int)loc2, xx, yy, zz, rr);
604  for (unsigned int z = 0; z < neighbors.size(); z++)
605  {
606  GLdouble xx2, yy2, zz2, rr2;
607  // only draw half of the directions, since edges are represented twice
608  switch (neighbors[z].direction)
609  {
610  case 0:
611 // glVertex3f(xx, yy, zz-5.1*rr);
612  GetXYLocation(x-numXSectors, neighbors[z].to, loc1, loc2);
613  map->GetOpenGLCoord((int)loc1, (int)loc2, xx2, yy2, zz2, rr2);
614 // glVertex3f(xx2, yy2, zz2-5.1*rr2);
615  display.DrawLine({static_cast<float>(xx), static_cast<float>(yy), static_cast<float>(zz-5.1*rr)},
616  {static_cast<float>(xx2), static_cast<float>(yy2), static_cast<float>(zz2-5.1*rr2)}, lineScale*rr2, abstractionColor);
617  break;
618  case 1:
619 // glVertex3f(xx, yy, zz-5.1*rr);
620  GetXYLocation(x+1, neighbors[z].to, loc1, loc2);
621  map->GetOpenGLCoord((int)loc1, (int)loc2, xx2, yy2, zz2, rr2);
622 // glVertex3f(xx2, yy2, zz2-5.1*rr2);
623  display.DrawLine({static_cast<float>(xx), static_cast<float>(yy), static_cast<float>(zz-5.1*rr)},
624  {static_cast<float>(xx2), static_cast<float>(yy2), static_cast<float>(zz2-5.1*rr2)}, lineScale*rr2, abstractionColor);
625  break;
626  case 2:
627  case 3: break;
628  case 4:
629 // glVertex3f(xx, yy, zz-5.1*rr);
630  GetXYLocation(x-numXSectors+1, neighbors[z].to, loc1, loc2);
631  map->GetOpenGLCoord((int)loc1, (int)loc2, xx2, yy2, zz2, rr2);
632 // glVertex3f(xx2, yy2, zz2-5.1*rr2);
633  display.DrawLine({static_cast<float>(xx), static_cast<float>(yy), static_cast<float>(zz-5.1*rr)},
634  {static_cast<float>(xx2), static_cast<float>(yy2), static_cast<float>(zz2-5.1*rr2)}, lineScale*rr2, abstractionColor);
635  break;
636  case 5:
637 // glVertex3f(xx, yy, zz-5.1*rr);
638  GetXYLocation(x+numXSectors+1, neighbors[z].to, loc1, loc2);
639  map->GetOpenGLCoord((int)loc1, (int)loc2, xx2, yy2, zz2, rr2);
640 // glVertex3f(xx2, yy2, zz2-5.1*rr2);
641  display.DrawLine({static_cast<float>(xx), static_cast<float>(yy), static_cast<float>(zz-5.1*rr)},
642  {static_cast<float>(xx2), static_cast<float>(yy2), static_cast<float>(zz2-5.1*rr2)}, lineScale*rr2, abstractionColor);
643  break;
644  default:
645  break; // otherwise we draw all edges twice
646  }
647  }
648 // glEnd();
649  }
650  }
651 // draw = false;
652 }
653 
668  unsigned int region,
669  unsigned int &x,
670  unsigned int &y) const
671 {
672  uint8_t loc = memory[sectors[sector].memoryAddress+region*2];
673  x = loc%sectorSize;
674  y = loc/sectorSize;
675  x += (sector%numXSectors)*sectorSize;
676  y += ((int)sector/numXSectors)*sectorSize;
677 }
678 
691 void MinimalSectorAbstraction::GetNeighbors(unsigned int sector,
692  unsigned int region,
693  std::vector<tempEdgeData> &edges) const
694 {
695  edges.resize(0);
696  int sectorAddress = sectors[sector].memoryAddress;
697  int numRegions = sectors[sector].numRegions;
698  int numEdges, edgeStart;
699  if (region == 0)
700  {
701  edgeStart = 0;
702  numEdges = memory[sectorAddress+region*2+1];
703  }
704  else {
705  edgeStart = memory[sectorAddress+(region-1)*2+1];
706  numEdges = memory[sectorAddress+region*2+1]-edgeStart;
707  }
708  for (int x = edgeStart; x < edgeStart+numEdges; x++)
709  {
710  tempEdgeData ted;
711  ted.from = region;
712 #ifdef DIAG_MOVES
713  ted.direction = (memory[sectorAddress+2*numRegions+x]>>5)&0x7;
714  ted.to = memory[sectorAddress+2*numRegions+x]&0x1F;
715 #else
716  ted.direction = (memory[sectorAddress+2*numRegions+x]>>6)&0x3;
717  ted.to = memory[sectorAddress+2*numRegions+x]&0x3F;
718 #endif
719  edges.push_back(ted);
720  }
721 }
722 
736  int direction)
737 {
738  switch (direction) {
739  case 0: return sector-numXSectors; // up
740  case 1: return sector+1; // right
741  case 2: return sector+numXSectors; // down
742  case 3: return sector-1; // left
743 #ifdef DIAG_MOVES
744  case 4: return sector - numXSectors + 1; // up right
745  case 5: return sector + numXSectors + 1; // down right
746  case 6: return sector + numXSectors - 1;// down left
747  case 7: return sector - numXSectors - 1;// up left
748 #endif
749  }
750  assert(false);
751  return -1;
752 }
753 
766 {
767  if ((x < 0) || (y < 0))
768  return -1;
769  int xsector = x/sectorSize;
770  int ysector = y/sectorSize;
771  if ((xsector >= numXSectors) ||
772  (ysector >= numYSectors))
773  return -1;
774  return ysector*numXSectors+xsector;
775 }
776 
790 {
791  if (map->GetTerrainType(x, y) != kGround)
792  return -1;
793  int sector = GetSector(x, y);
794  if (sectors[sector].numRegions == 1) // only one region, we must be in region 0
795  return 0;
796 
797  std::vector<int> regions(sectors[sector].numRegions);
798  for (unsigned int t = 0; t < sectors[sector].numRegions; t++)
799  {
800  regions[t] = memory[sectors[sector].memoryAddress+t*2];
801  // printf("Region %d location %d\n", t, regions[t]);
802  }
803  return FindParentRegion(x%sectorSize+((y%sectorSize)*sectorSize), regions,
804  x-x%sectorSize, y-y%sectorSize);
805 }
806 
822  std::vector<int> &parents,
823  int mapXOffset, int mapYOffset)
824 {
825  int current = startLoc;
826  std::vector<int> stack;
827  std::queue<int> Q;
828  std::vector<int> markers(sectorSize*sectorSize);
829  markers[current] = 1;
830  // printf("Starting on %d\n", startLoc);
831  while (1)
832  {
833  for (unsigned int x = 0; x < parents.size(); x++)
834  if (current == parents[x])
835  return (int)x;
836 
837  if ((current+sectorSize < sectorSize*sectorSize) && (markers[current+sectorSize] == 0))
838  {
839  //stack.push_back(current+sectorSize);
840  Q.push(current+sectorSize);
841  markers[current+sectorSize] = 1;
842  }
843  if ((current-sectorSize >= 0) && (markers[current-sectorSize] == 0))
844  {
845  //stack.push_back(current-sectorSize);
846  Q.push(current-sectorSize);
847  markers[current-sectorSize] = 1;
848  }
849  if ((((current+1)%sectorSize) != 0) && (markers[current+1] == 0))
850  {
851  //stack.push_back(current+1);
852  Q.push(current+1);
853  markers[current+1] = 1;
854  }
855  if (((current%sectorSize) != 0) && (markers[current-1] == 0))
856  {
857  //stack.push_back(current-1);
858  Q.push(current-1);
859  markers[current-1] = 1;
860  }
861 
862  do {
863  // printf("Stack size: %d\n", Q.size());
864  assert(Q.size() != 0);
865  current = Q.front();
866  Q.pop();
867  // printf("Checking %d next\n", current);
868  } while ((markers[current] != 0) &&
869  (map->GetTerrainType(mapXOffset+current%sectorSize,
870  mapYOffset+current/sectorSize) != kGround));
871  }
872  return -1;
873 }
874 
889  int absXSector,
890  int absYSector)
891 {
892  area.resize(0);
893  area.resize(sectorSize*sectorSize);
894 
895  // initialize sector map to 0 for unsearched, -1 for unreachable
896  for (int x = 0; x < sectorSize; x++)
897  {
898  for (int y = 0; y < sectorSize; y++)
899  {
900  if (map->GetTerrainType(absXSector*sectorSize+x,
901  absYSector*sectorSize+y) != kGround)
902  {
903  area[y*sectorSize+x] = -1;
904  }
905  }
906  }
907 
908  int nextLabel = 1;
909  for (int x = 0; x < sectorSize; x++)
910  {
911  for (int y = 0; y < sectorSize; y++)
912  {
913  if (area[y*sectorSize+x] == 0)
914  {
915  LabelRegion(area, x, y, nextLabel);
916  nextLabel++;
917  }
918  }
919  }
920  return nextLabel-1;
921 }
922 
936 void MinimalSectorAbstraction::LabelRegion(std::vector<int> &area,
937  int x, int y, int label)
938 {
939  if ((y < 0) || (x < 0) || (y >= sectorSize) || (x >= sectorSize))
940  return;
941  if (area[y*sectorSize+x] != 0)
942  return;
943 
944  area[y*sectorSize+x] = label;
945  LabelRegion(area, x+1, y, label);
946  LabelRegion(area, x-1, y, label);
947  LabelRegion(area, x, y+1, label);
948  LabelRegion(area, x, y-1, label);
949 }
950 
963 {
964  regionError.resize(sectors.size());
965  optimizationIndex = 0;
966 }
967 
979 {
980  if (optimizationIndex >= (int)sectors.size())
981  return true;
982 //
983 // regionError[optimizationIndex].resize(sectors[optimizationIndex].numRegions);
984 // for (unsigned int y = 0; y < sectors[optimizationIndex].numRegions; y++)
985 // {
986 // unsigned int sx, sy;
987 // ResetAbstractCenter(optimizationIndex, y);
988 // GetXYLocation(optimizationIndex, y, sx, sy);
989 // GetRegionError(optimizationIndex, y, sx, sy, sectorSize*2+1);
990 // if (regionError[optimizationIndex][y] > sectorSize*1.5)
991 // MoveRegionCenter(optimizationIndex, y);
992 // }
993 //
994 // optimizationIndex++;
995  return false;
996 }
997 
1017 {
1018  uint8_t defaultCenter = GetAbstractLocation(areas[sector], region+1);
1019  memory[sectors[sector].memoryAddress+2*region] = defaultCenter;
1020 }
1021 
1031 {
1033  while (!PerformOneOptimizationStep());
1034 }
1035 
1049 {
1050  double error = regionError[sector][region];
1051  int best = -1;
1052  for (unsigned int x = 0; x < areas[sector].size(); x++)
1053  {
1054  if (areas[sector][x] == region+1)
1055  {
1056  int xoff = (sector%numXSectors)*sectorSize;
1057  int yoff = (sector/numXSectors)*sectorSize;
1058  double err = GetRegionError(sector, region, xoff+(x%sectorSize),
1059  yoff+x/sectorSize, error);
1060  if (fless(err, error))
1061  {
1062  error = err;
1063  best = x;
1064  }
1065  }
1066  }
1067  printf("For %d:%d, error improved to %f at offset %d\n", sector, region, error, best);
1068  if (best != -1)
1069  memory[sectors[sector].memoryAddress+2*region] = best;
1070 }
1071 
1094 double MinimalSectorAbstraction::GetRegionError(int fromSector, int fromRegion,
1095  int sx, int sy, double limit)
1096 {
1097 // GenericAStar gas;
1098 // std::vector<tempEdgeData> edges;
1099 // edges.resize(0);
1100 // GetNeighbors(fromSector, fromRegion, edges);
1101 // regionError[fromSector][fromRegion] = 0.0;
1102 // for (unsigned int z = 0; z < edges.size(); z++)
1103 // {
1104 // MapEnvironment env(map);
1105 // int toSector = GetAdjacentSector(fromSector, edges[z].direction);
1106 // int toRegion = edges[z].to;
1107 // unsigned int gx, gy;
1108 // GetXYLocation(toSector, toRegion, gx, gy);
1109 //
1110 // std::vector<uint32_t> thePath;
1111 // // compute the cost to travel between the given sector/region and a neighboring region
1112 // // We measure the cost as the number of nodes expanded over and above the optimal path
1113 // // length
1114 // gas.GetPath(&env, (gx<<16)|gy, (sx<<16)|sy, thePath);
1115 // assert(thePath.size() != 0);
1116 // regionError[fromSector][fromRegion] = max(regionError[fromSector][fromRegion],
1117 // gas.GetNodesExpanded()-thePath.size());
1118 // if (fgreater(regionError[fromSector][fromRegion], limit))
1119 // return regionError[fromSector][fromRegion];
1120 //
1121 // // now do it again the other way, because we could go either way along this edge
1122 // // and the costs can be highly assymetrical
1123 // thePath.resize(0);
1124 // gas.GetPath(&env, (sx<<16)|sy, (gx<<16)|gy, thePath);
1125 // assert(thePath.size() != 0);
1126 // regionError[fromSector][fromRegion] = max(regionError[fromSector][fromRegion],
1127 // gas.GetNodesExpanded()-thePath.size());
1128 // if (fgreater(regionError[fromSector][fromRegion], limit))
1129 // return regionError[fromSector][fromRegion];
1130 // }
1131 // return regionError[fromSector][fromRegion];
1132  assert(!"Commented out code here.");
1133  return 0;
1134 }
1135 
1147 {
1148  int defaultSectors = 0;
1149  for (unsigned int x = 0; x < sectors.size(); x++)
1150  {
1151  //std::vector<sectorInfo> sectors;
1152  if (sectors[x].numRegions != 1)
1153  continue;
1154 
1155  if (sectors[x].numEdges != 8)
1156  continue;
1157 
1158  std::vector<tempEdgeData> edges;
1159  std::vector<int> edgedir(8);
1160  GetNeighbors(x, 0, edges);
1161  for (unsigned int y = 0; y < edges.size(); y++)
1162  edgedir[edges[y].direction] = 1;
1163 
1164  // if there is one edge in each direction, this is a default sector
1165  int sum = 0;
1166  for (unsigned int y = 0; y < edgedir.size(); y++)
1167  sum += edgedir[y];
1168  if (sum == 8)
1169  defaultSectors++;
1170  }
1171  printf("%d default sectors would save %d bytes\n", defaultSectors, (8+2)*defaultSectors);
1172 }
tempEdgeData::direction
int direction
Definition: MinimalSectorAbstraction.h:73
Graphics::Display::DrawLine
void DrawLine(point start, point end, float lineWidth, rgbColor c)
Definition: Graphics.cpp:184
MinimalSectorAbstraction::GetSector
int GetSector(int x, int y)
MinimalSectorAbstraction::GetSector()
Definition: MinimalSectorAbstraction.cpp:765
rgbColor
A color; r/g/b are between 0...1.
Definition: Colors.h:17
tempEdgeData
Definition: MinimalSectorAbstraction.h:72
MinimalSectorAbstraction::regionError
std::vector< std::vector< double > > regionError
Definition: MinimalSectorAbstraction.h:144
MinimalSectorAbstraction::ComputePotentialMemorySavings
void ComputePotentialMemorySavings()
MinimalSectorAbstraction::ComputePotentialMemorySavings()
Definition: MinimalSectorAbstraction.cpp:1146
MinimalSectorAbstraction::OpenGLDraw
void OpenGLDraw()
MinimalSectorAbstraction::OpenGLDraw()
Definition: MinimalSectorAbstraction.cpp:444
MinimalSectorAbstraction::StoreSectorInMemory
void StoreSectorInMemory(sectorInfo &si, std::vector< int > &area, std::vector< tempEdgeData > &edges)
MinimalSectorAbstraction::StoreSectorInMemory()
Definition: MinimalSectorAbstraction.cpp:314
Map2DEnvironment.h
MinimalSectorAbstraction::GetEdges
void GetEdges(std::vector< std::vector< int > > &areas, int xSector, int ySector, std::vector< tempEdgeData > &edges)
MinimalSectorAbstraction::GetEdges()
Definition: MinimalSectorAbstraction.cpp:132
MinimalSectorAbstraction::numXSectors
int numXSectors
Definition: MinimalSectorAbstraction.h:141
MinimalSectorAbstraction::GetAbstractLocation
uint8_t GetAbstractLocation(std::vector< int > area, int value)
MinimalSectorAbstraction::GetAbstractLocation()
Definition: MinimalSectorAbstraction.cpp:386
MinimalSectorAbstraction.h
MinimalSectorAbstraction::numYSectors
int numYSectors
Definition: MinimalSectorAbstraction.h:141
MinimalSectorAbstraction::map
Map * map
Definition: MinimalSectorAbstraction.h:145
MinimalSectorAbstraction::InitializeOptimization
void InitializeOptimization()
MinimalSectorAbstraction::InitializeOptimization()
Definition: MinimalSectorAbstraction.cpp:962
MinimalSectorAbstraction::GetEdgeHelper
void GetEdgeHelper(std::vector< int > &startRegion, int startIndex, int startOffset, std::vector< int > &targetRegion, int tarGetIndex, int targetOffset, std::vector< tempEdgeData > &edges, int direction)
MinimalSectorAbstraction::GetEdgeHelper()
Definition: MinimalSectorAbstraction.cpp:258
kGround
@ kGround
Definition: Map.h:55
loc
Definition: MapGenerators.cpp:296
GenericAStar.h
MinimalSectorAbstraction::MinimalSectorAbstraction
MinimalSectorAbstraction(Map *map, int sectorSize)
MinimalSectorAbstraction::MinimalSectorAbstraction()
Definition: MinimalSectorAbstraction.cpp:52
Graphics::Display
Definition: Graphics.h:146
fless
bool fless(double a, double b)
Definition: FPUtil.h:28
MinimalSectorAbstraction::FindParentRegion
int FindParentRegion(int startLoc, std::vector< int > &parents, int mapXOffset, int mapYOffset)
MinimalSectorAbstraction::FindParentRegion()
Definition: MinimalSectorAbstraction.cpp:821
sectorInfo::memoryAddress
uint16_t memoryAddress
Definition: MinimalSectorAbstraction.h:69
sectorInfo
Definition: MinimalSectorAbstraction.h:66
Map::GetMapWidth
long GetMapWidth() const
return the width of the map
Definition: Map.h:163
MinimalSectorAbstraction::GetXYLocation
void GetXYLocation(unsigned int sector, unsigned int region, unsigned int &x, unsigned int &y) const
MinimalSectorAbstraction::GetXYLocation()
Definition: MinimalSectorAbstraction.cpp:667
MinimalSectorAbstraction::PerformOneOptimizationStep
bool PerformOneOptimizationStep()
MinimalSectorAbstraction::PerformOneOptimizationStep()
Definition: MinimalSectorAbstraction.cpp:978
tempEdgeData::to
int to
Definition: MinimalSectorAbstraction.h:73
MinimalSectorAbstraction::GetRegion
int GetRegion(int x, int y)
MinimalSectorAbstraction::GetRegion()
Definition: MinimalSectorAbstraction.cpp:789
Map::GetTerrainType
long GetTerrainType(long x, long y, tSplitSide split=kWholeTile) const
Get the terrain type of the (split) tile at x, y.
Definition: Map.cpp:1028
sectorInfo::numEdges
uint8_t numEdges
Definition: MinimalSectorAbstraction.h:68
MinimalSectorAbstraction::optimizationIndex
int optimizationIndex
Definition: MinimalSectorAbstraction.h:148
sectorInfo::numRegions
uint8_t numRegions
Definition: MinimalSectorAbstraction.h:67
tempEdgeData::from
int from
Definition: MinimalSectorAbstraction.h:73
MinimalSectorAbstraction::LabelRegion
void LabelRegion(std::vector< int > &area, int x, int y, int label)
MinimalSectorAbstraction::LabelRegion()
Definition: MinimalSectorAbstraction.cpp:936
MinimalSectorAbstraction::areas
std::vector< std::vector< int > > areas
Definition: MinimalSectorAbstraction.h:146
MinimalSectorAbstraction::MoveRegionCenter
void MoveRegionCenter(int sector, int region)
MinimalSectorAbstraction::MoveRegionCenter()
Definition: MinimalSectorAbstraction.cpp:1048
MinimalSectorAbstraction::GetSectorRegions
int GetSectorRegions(std::vector< int > &area, int absXSector, int absYSector)
MinimalSectorAbstraction::GetSectorRegions()
Definition: MinimalSectorAbstraction.cpp:888
MinimalSectorAbstraction::sectors
std::vector< sectorInfo > sectors
Definition: MinimalSectorAbstraction.h:142
Map::GetMapHeight
long GetMapHeight() const
return the height of the map
Definition: Map.h:165
Colors::yellow
const rgbColor yellow
Definition: Colors.h:148
MinimalSectorAbstraction::OptimizeRegionLocations
void OptimizeRegionLocations()
MinimalSectorAbstraction::OptimizeRegionLocations()
Definition: MinimalSectorAbstraction.cpp:1030
MinimalSectorAbstraction::memory
std::vector< uint8_t > memory
Definition: MinimalSectorAbstraction.h:143
MinimalSectorAbstraction::Draw
void Draw(Graphics::Display &display) const
Definition: MinimalSectorAbstraction.cpp:556
MinimalSectorAbstraction::GetAbstractEdge
uint8_t GetAbstractEdge(tempEdgeData &data)
MinimalSectorAbstraction::GetAbstractEdge()
Definition: MinimalSectorAbstraction.cpp:365
MinimalSectorAbstraction::GetAdjacentSector
int GetAdjacentSector(unsigned int sector, int direction)
MinimalSectorAbstraction::GetAdjacentSector()
Definition: MinimalSectorAbstraction.cpp:735
Map::GetOpenGLCoord
bool GetOpenGLCoord(int _x, int _y, GLdouble &x, GLdouble &y, GLdouble &z, GLdouble &radius) const
Get the openGL coordinates of a given tile.
Definition: Map.cpp:1826
MinimalSectorAbstraction::GetRegionError
double GetRegionError(int fromSector, int fromRegion, int sx, int sy, double limit)
MinimalSectorAbstraction::GetRegionError()
Definition: MinimalSectorAbstraction.cpp:1094
MinimalSectorAbstraction::ResetAbstractCenter
void ResetAbstractCenter(int sector, int region)
MinimalSectorAbstraction::ResetAbstractCenter()
Definition: MinimalSectorAbstraction.cpp:1016
MinimalSectorAbstraction::sectorSize
int sectorSize
Definition: MinimalSectorAbstraction.h:147
MinimalSectorAbstraction::GetNeighbors
void GetNeighbors(unsigned int sector, unsigned int region, std::vector< tempEdgeData > &edges) const
MinimalSectorAbstraction::GetNeighbors()
Definition: MinimalSectorAbstraction.cpp:691
MinimalSectorAbstraction::BuildAbstraction
void BuildAbstraction()
MinimalSectorAbstraction::BuildAbstraction()
Definition: MinimalSectorAbstraction.cpp:81
Map
A tile-based representation of the world.
Definition: Map.h:142
Colors::bluegreen
const rgbColor bluegreen
Definition: Colors.h:139