void PointGrid::getPointsInRange(const geometry_msgs::Point& lower_left, const geometry_msgs::Point& upper_right, vector< list<geometry_msgs::Point32>* >& points){
    points.clear();

    //compute the other corners of the box so we can get cells indicies for them
    geometry_msgs::Point upper_left, lower_right;
    upper_left.x = lower_left.x;
    upper_left.y = upper_right.y;
    lower_right.x = upper_right.x;
    lower_right.y = lower_left.y;

    //get the grid coordinates of the cells matching the corners of the range
    unsigned int gx, gy;

    //if the grid coordinates are outside the bounds of the grid... return
    if(!gridCoords(lower_left, gx, gy))
      return;
    //get the associated index
    unsigned int lower_left_index = gridIndex(gx, gy);

    if(!gridCoords(lower_right, gx, gy))
      return;
    unsigned int lower_right_index = gridIndex(gx, gy);

    if(!gridCoords(upper_left, gx, gy))
      return;
    unsigned int upper_left_index = gridIndex(gx, gy);

    //compute x_steps and y_steps
    unsigned int x_steps = lower_right_index - lower_left_index + 1;
    unsigned int y_steps = (upper_left_index - lower_left_index) / width_ + 1;
    /*
     * (0, 0) ---------------------- (width, 0)
     *  |                               |
     *  |                               |
     *  |                               |
     *  |                               |
     *  |                               |
     * (0, height) ----------------- (width, height)
     */
    //get an iterator
    vector< list<geometry_msgs::Point32> >::iterator cell_iterator = cells_.begin() + lower_left_index;
    //printf("Index: %d, Width: %d, x_steps: %d, y_steps: %d\n", lower_left_index, width_, x_steps, y_steps);
    for(unsigned int i = 0; i < y_steps; ++i){
      for(unsigned int j = 0; j < x_steps; ++j){
        list<geometry_msgs::Point32>& cell = *cell_iterator;
        //if the cell contains any points... we need to push them back to our list
        if(!cell.empty()){
          points.push_back(&cell);
        }
        if(j < x_steps - 1)
          cell_iterator++; //move a cell in the x direction
      }
      cell_iterator += width_ - (x_steps - 1); //move down a row
    }
  }
  void PointGrid::insert(geometry_msgs::Point32 pt){
    //get the grid coordinates of the point
    unsigned int gx, gy;

    //if the grid coordinates are outside the bounds of the grid... return
    if(!gridCoords(pt, gx, gy))
      return;

    //if the point is too close to its nearest neighbor... return
    if(nearestNeighborDistance(pt) < sq_min_separation_)
      return;

    //get the associated index
    unsigned int pt_index = gridIndex(gx, gy);

    //insert the point into the grid at the correct location
    cells_[pt_index].push_back(pt);
    //printf("Index: %d, size: %d\n", pt_index, cells_[pt_index].size());
  }
  double PointGrid::nearestNeighborDistance(geometry_msgs::Point32& pt){
    //get the grid coordinates of the point
    unsigned int gx, gy;

    gridCoords(pt, gx, gy);

    //get the bounds of the grid cell in world coords
    geometry_msgs::Point lower_left, upper_right;
    getCellBounds(gx, gy, lower_left, upper_right);

    //now we need to check what cells could contain the nearest neighbor
    geometry_msgs::Point32 check_point;
    double sq_dist = DBL_MAX;
    double neighbor_sq_dist = DBL_MAX;
    
    //left
    if(gx > 0){
      check_point.x = lower_left.x;
      check_point.y = pt.y;
      sq_dist = sq_distance(pt, check_point);
      if(sq_dist < sq_min_separation_)
        neighbor_sq_dist = min(neighbor_sq_dist, getNearestInCell(pt, gx - 1, gy));
    }

    //upper left
    if(gx > 0 && gy < height_ - 1){
      check_point.x = lower_left.x;
      check_point.y = upper_right.y;
      sq_dist = sq_distance(pt, check_point);
      if(sq_dist < sq_min_separation_)
        neighbor_sq_dist = min(neighbor_sq_dist, getNearestInCell(pt, gx - 1, gy + 1));
    }

    //top
    if(gy < height_ - 1){
      check_point.x = pt.x;
      check_point.y = upper_right.y;
      sq_dist = sq_distance(pt, check_point);
      if(sq_dist < sq_min_separation_)
        neighbor_sq_dist = min(neighbor_sq_dist, getNearestInCell(pt, gx, gy + 1));
    }

    //upper right
    if(gx < width_ - 1 && gy < height_ - 1){
      check_point.x = upper_right.x;
      check_point.y = upper_right.y;
      sq_dist = sq_distance(pt, check_point);
      if(sq_dist < sq_min_separation_)
        neighbor_sq_dist = min(neighbor_sq_dist, getNearestInCell(pt, gx + 1, gy + 1));
    }

    //right
    if(gx < width_ - 1){
      check_point.x = upper_right.x;
      check_point.y = pt.y;
      sq_dist = sq_distance(pt, check_point);
      if(sq_dist < sq_min_separation_)
        neighbor_sq_dist = min(neighbor_sq_dist, getNearestInCell(pt, gx + 1, gy));
    }

    //lower right
    if(gx < width_ - 1 && gy > 0){
      check_point.x = upper_right.x;
      check_point.y = lower_left.y;
      sq_dist = sq_distance(pt, check_point);
      if(sq_dist < sq_min_separation_)
        neighbor_sq_dist = min(neighbor_sq_dist, getNearestInCell(pt, gx + 1, gy - 1));
    }

    //bottom
    if(gy > 0){
      check_point.x = pt.x;
      check_point.y = lower_left.y;
      sq_dist = sq_distance(pt, check_point);
      if(sq_dist < sq_min_separation_)
        neighbor_sq_dist = min(neighbor_sq_dist, getNearestInCell(pt, gx, gy - 1));
    }

    //lower left
    if(gx > 0 && gy > 0){
      check_point.x = lower_left.x;
      check_point.y = lower_left.y;
      sq_dist = sq_distance(pt, check_point);
      if(sq_dist < sq_min_separation_)
        neighbor_sq_dist = min(neighbor_sq_dist, getNearestInCell(pt, gx - 1, gy - 1));
    }

    //we must also check within the cell we're in for a nearest neighbor
    neighbor_sq_dist = min(neighbor_sq_dist, getNearestInCell(pt, gx, gy));

    return neighbor_sq_dist;
  }
Example #4
0
File: Main.cpp Project: 222464/Ants
int main() {
	Ptr<CTinyJS> js = make<CTinyJS>();

	registerFunctions(js.get());
	registerMathFunctions(js.get());
	registerStringFunctions(js.get());

	//Add print function.
	js->addNative("function print(str)", js::funcs::print, 0);

	//Create console object.
	js->executeSafe("var console = {log: print};console.log('Console created.');");

	sf::RenderWindow window;
	window.create(sf::VideoMode(1280, 800), "ALife");

	//window.setVerticalSyncEnabled(true);
	window.setFramerateLimit(60);

	sf::Clock clock;

	float dt = 0.017f;

	ants::World world;

	std::shared_ptr<sf::Texture> gridTexture = std::make_shared<sf::Texture>();

	gridTexture->loadFromFile("resources/grid.png");

	std::vector<sf::Color> colors(4);
	colors[0] = sf::Color::Cyan;
	colors[1] = sf::Color::Red;
	colors[2] = sf::Color::Magenta;
	colors[3] = sf::Color::Green;

	world.create(128, 128, colors, gridTexture);

	for (int i = 0; i < 5; i++) {
		std::uniform_int_distribution<int> nestDistX(1, world.getWidth() - 2);
		std::uniform_int_distribution<int> nestDistY(1, world.getHeight() - 2);

		sf::Vector2i pos = sf::Vector2i(nestDistX(world._generator), nestDistY(world._generator));

		for (int dx = -1; dx <= 1; dx++)
		for (int dy = -1; dy <= 1; dy++) {
			Ptr<ants::Nest> nest = make<ants::Nest>();

			world.add(nest, sf::Vector2i(pos.x + dx, pos.y + dy));
		}

		for (int i = 0; i < 50; i++) {
			Ptr<ants::TestAnt> testAnt = make<ants::TestAnt>();

			world.add(testAnt, pos);
		}
	}

	for (int i = 0; i < 8; i++) {
		std::uniform_int_distribution<int> foodDistX(1, world.getWidth() - 2);
		std::uniform_int_distribution<int> foodDistY(1, world.getHeight() - 2);

		sf::Vector2i pos = sf::Vector2i(foodDistX(world._generator), foodDistY(world._generator));

		for (int dx = -1; dx <= 1; dx++)
		for (int dy = -1; dy <= 1; dy++) {
			Ptr<ants::Food> food = make<ants::Food>();

			world.add(food, sf::Vector2i(pos.x + dx, pos.y + dy));
		}
	}

	Ptr<ants::JSAnt> jsAnt = std::make_shared<ants::JSAnt>(js, "js/ant.js");

	world.add(jsAnt, sf::Vector2i(32, 32));

	sf::View view;
	sf::View newView;

	view.setSize(sf::Vector2f(static_cast<float>(window.getSize().x), static_cast<float>(window.getSize().y)));
	view.setCenter(sf::Vector2f(world.getWidth() * 0.5f * world.getCellWidth(), world.getHeight() * 0.5f * world.getCellHeight()));

	newView = view;

	float zoomRate = 0.2f;

	float viewInterpolateRate = 20.0f;

	sf::Vector2i prevMousePos = sf::Mouse::getPosition();

	float updateTimer = 0.0f;
	const float updateTime = 0.1f;

	bool quit = false;
	
	do {
		sf::Event windowEvent;

		while (window.pollEvent(windowEvent)) {
			switch (windowEvent.type)
			{
			case sf::Event::Closed:
				quit = true;

				break;

			case sf::Event::MouseWheelMoved:
				int dWheel = windowEvent.mouseWheel.delta;

				newView = view;

				window.setView(newView);

				sf::Vector2f mouseZoomDelta0 = window.mapPixelToCoords(sf::Mouse::getPosition(window));

				newView.setSize(view.getSize() + newView.getSize() * (-zoomRate * dWheel));

				window.setView(newView);

				sf::Vector2f mouseZoomDelta1 = window.mapPixelToCoords(sf::Mouse::getPosition(window));

				window.setView(view);

				newView.setCenter(view.getCenter() + mouseZoomDelta0 - mouseZoomDelta1);

				break;
			}
		}

		view.setCenter(view.getCenter() + (newView.getCenter() - view.getCenter()) * viewInterpolateRate * dt);
		view.setSize(view.getSize() + (newView.getSize() - view.getSize()) * viewInterpolateRate * dt);

		if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
			sf::Vector2i dPos = sf::Mouse::getPosition() - prevMousePos;

			view.setCenter(view.getCenter() - sf::Vector2f(dPos.x * (view.getSize().x / window.getSize().x), dPos.y * (view.getSize().x / window.getSize().x)));

			newView.setCenter(view.getCenter());
		}

		if (sf::Mouse::isButtonPressed(sf::Mouse::Right)) {
			sf::Vector2f mouseCoords = window.mapPixelToCoords(sf::Mouse::getPosition(window));

			sf::Vector2i gridCoords(mouseCoords.x / world.getCellWidth(), mouseCoords.y / world.getCellHeight());

			if (gridCoords.x >= 0 && gridCoords.y >= 0 && gridCoords.x < world.getWidth() && gridCoords.y < world.getHeight()) {
				bool hasObstacle = false;
				
				for (std::set<int>::const_iterator cit = world.getCell(gridCoords)._occupantIds.begin(); cit != world.getCell(gridCoords)._occupantIds.end(); cit++) {
					if (world.getGridObject(*cit)->getName() == "obstacle") {
						hasObstacle = true;

						break;
					}
				}

				if (!hasObstacle) {
					Ptr<ants::Obstacle> obstacle = make<ants::Obstacle>();

					world.add(obstacle, gridCoords);
				}
			}
		}

		prevMousePos = sf::Mouse::getPosition();

		window.clear();

		window.setView(view);

		updateTimer += dt;

		if (updateTimer > updateTime) {
			world.update();
			updateTimer -= updateTime;
		}

		world.render(window);

		window.display();

		dt = clock.getElapsedTime().asSeconds();

		clock.restart();
	} while (!quit);

	return 0;
}