AnyAngleAlgorithm::AnyAngleAlgorithm(const std::vector<bool> &bits, int width, int height)
{
    // Read the height and width of the map.
    width_ = width + 2; // Add +2 for the frame of obstacles.
    height_ = height + 2;

    unblocked_cells_.clear();

    // Generate the cells with the padding.
    cells_ = new Cell*[width_];
    for (unsigned int x = 0; x < width_; x++) {
        cells_[x] = new Cell[height_];
    }

    // Make unblocked cells traversable.
    int num_traversable = 0;
    for (unsigned int x = 0; x < width_ - 2; x++) {
        for (unsigned int y = 0; y < height_ - 2; y++) {
            if (bits[y * width + x]) {
                cells_[x + 1][y + 1].is_traversable = true;
                unblocked_cells_.push_back(xyLoc(x,y));
            }
        }
    }

#ifdef ANY_ANGLE_VERBOSE
    std::cout << "Traversable cells: " << num_traversable << std::endl;
#endif

    Initialize();
}
AnyAngleAlgorithm::AnyAngleAlgorithm(const MapEnvironment *env)
{
    // Read the height and width of the map.
    Map* map = env->GetMap();
    width_ = map->GetMapWidth() + 2; // Add +2 for the frame of obstacles.
    height_ = map->GetMapHeight() + 2;

    unblocked_cells_.clear();

    // Generate the cells with the padding.
    cells_ = new Cell*[width_];
    for (unsigned int x = 0; x < width_; x++) {
        cells_[x] = new Cell[height_];
    }

    // Make unblocked cells traversable.
    int num_traversable = 0;
    for (unsigned int x = 0; x < width_ - 2; x++) {
        for (unsigned int y = 0; y < height_ - 2; y++) {
            if (map->GetTerrainType(x, y) == kGround) {
                cells_[x+1][y+1].is_traversable = true;
                num_traversable++;
                unblocked_cells_.push_back(xyLoc(x,y));
            }
        }
    }

#ifdef ANY_ANGLE_VERBOSE
    std::cout << "Traversable cells: " << num_traversable << std::endl;
#endif

    Initialize();
}
Esempio n. 3
0
cost QuickBucket::GetPath(xyLoc & s, xyLoc & g, std::vector<xyLoc> & path)
{
	search++;
	theHeap.clear();
	bucketsInUse = 0;	
	
	#ifdef BUCKET_STATISTICS
		int openSize = 1;
	#endif
		
	// Succesor buckets
	int id[6];	// 0: 0, 1: 2C-D, 2: 2D-2C, 3: 
	
	id[0] = GetBucketId(abCost(0,0));	// Get the bucket for the start state
	GenerateBucket(id[0]);
	buckets[id[0]].contents.push_back(bucketElement(s, 8));	// Insert the start state to the bucket, mark its parent as 8 = no parent
	
	buckets[id[0]].open = true;
	AddToOpen(abCost(0,0));					// Insert the bucket into the open list
	
	theMap[s.x][s.y].open = true;	// Set the start state as open
	theMap[s.x][s.y].generated = search;
	
	theMap[g.x][g.y].open = true;	// Also, set the goal state as open, but do not put it in the buckets yet	
	theMap[g.x][g.y].generated = search;
	
	abCost currCost;
	
	while (theMap[g.x][g.y].open && !theHeap.empty())
	{	
		// Select a bucket to expand
		currCost = theHeap[0];
		PopMin();
	
		#ifdef BUCKET_STATISTICS
			bucketExpansions++;			
		#endif 
		
		// Get the bucket and its successor buckets	
		id[0] = GetBucketId(currCost);
		buckets[id[0]].open = false;
	
		for (int i = 1; i < 6; i++)
		{
			id[i] = GetBucketId(abCost(currCost.a + A[i], currCost.b + B[i]));
		}
		GenerateBucket(id[5]+4);	// make sure we generate all the buckets with just one call
				
		// Expand all the contents of the bucket
		while (!buckets[id[0]].contents.empty())
		{
			bucketElement elem = buckets[id[0]].contents.back();
			buckets[id[0]].contents.pop_back();
			#ifdef BUCKET_STATISTICS			
				openSize--;
			#endif									
			if (theMap[elem.loc.x][elem.loc.y].open)
			{
				#ifdef BUCKET_STATISTICS
					elementExpansions++;
				#endif
				
				theMap[elem.loc.x][elem.loc.y].open = false;
				theMap[elem.loc.x][elem.loc.y].parent = elem.parent;
				
				//unsigned char neighbors = theMap[elem.loc.x][elem.loc.y].neighbors;
				unsigned char neighbors = theMap[elem.loc.x][elem.loc.y].neighbors & parentMask[elem.parent];
				
				unsigned char currNeighbor = 1;
				int baseCase = GetBaseCase(elem.loc, g);
						
				for (int d = 0; d < 8; d++)	// look at 8 directions
				{
					if (currNeighbor & neighbors)	// if there is a potential successor in a direction
					{
						xyLoc succ = xyLoc(elem.loc.x + X[d], elem.loc.y + Y[d]);
						
						// generate it if necessary
						if (theMap[succ.x][succ.y].generated != search)
						{
							theMap[succ.x][succ.y].generated = search;
							theMap[succ.x][succ.y].open = true;
						}
						
						// if it was not already expanded
						if (theMap[succ.x][succ.y].open)
						{
							buckets[id[cases[baseCase]]].contents.push_back(bucketElement(succ, (d+4)&7));
							#ifdef BUCKET_STATISTICS
								openSize++;
								if (openSize > maxOpenSize)
									maxOpenSize = openSize;
							#endif
						}
					}
					baseCase++;
					currNeighbor = (currNeighbor << 1);
				}
			}
			#ifdef BUCKET_STATISTICS
				else
					alreadyExpanded++;
			#endif
		}
		
		// Bucket expanded, try to add new buckets to the open list
		for (int i = 1; i < 6; i++)
		{
			if (!buckets[id[i]].open && !buckets[id[i]].contents.empty())	// if it is not already open and it contains at least one element
			{
				buckets[id[i]].open = true;
				AddToOpen(abCost(currCost.a + A[i], currCost.b + B[i]));
			}
		}
		
		#ifdef BUCKET_MEMORY_OPTIMIZATION
			std::vector<bucketElement>().swap(buckets[id[0]].contents);	// Free the memory for that bucket
			buckets[id[0]].contents.reserve(DEFAULT_BUCKET_SIZE);	// Allow it to have 256 elements so that we don't reallocate too often
		#endif
	}

	if (!theMap[g.x][g.y].open)
	{
		path.clear();
		xyLoc loc = g;
		while (loc.x != s.x || loc.y != s.y)
		{
			path.push_back(loc);
			int parent = theMap[loc.x][loc.y].parent;
			loc.x += X[parent];
			loc.y += Y[parent];
		}
		path.push_back(loc);
		std::reverse(path.begin(), path.end());
		return HCost(s,g) + currCost.GetCost();
	}
	
	return 0;//HCost(s,g);
}