Skip to content

Instantly share code, notes, and snippets.

@ivancea
Last active October 19, 2018 22:28
Show Gist options
  • Save ivancea/665f312d80e41a517911a6e3dfec2e99 to your computer and use it in GitHub Desktop.
Save ivancea/665f312d80e41a517911a6e3dfec2e99 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <vector>
#include <queue>
#include "Image.h"
using namespace std;
enum Direction {
UP,
RIGHT,
DOWN,
LEFT
};
struct Point {
int x;
int y;
Point(){}
Point(int _x, int _y) : x(_x), y(_y) {}
bool operator==(const Point& point){
return point.x == x && point.y == y;
}
bool operator!=(const Point& point){
return !operator==(point);
}
};
ostream& operator<<(ostream& os, const Point& point){
return os << "(" << point.x << ", " << point.y << ")";
}
bool isBuilding(const Image& image, Point position){
return position.x >= 0 && position.y >= 0
&& position.x < image.getX() && position.y < image.getY()
&& image.get(position.x, position.y) == sf::Color::White;
}
vector<Point> getPath(const Image& image, Point initialPosition, Direction initialDirection){
vector<Point> path;
path.push_back(initialPosition);
Direction currentDirection = initialDirection;
Point currentPosition = initialPosition;
do{
switch(currentDirection){
case UP:
if(isBuilding(image, Point{currentPosition.x, currentPosition.y - 1})){
currentPosition.y -= 1;
currentDirection = LEFT;
}else{
currentDirection = RIGHT;
}
break;
case RIGHT:
if(isBuilding(image, Point{currentPosition.x + 1, currentPosition.y})){
currentPosition.x += 1;
currentDirection = UP;
}else{
currentDirection = DOWN;
}
break;
case DOWN:
if(isBuilding(image, Point{currentPosition.x, currentPosition.y + 1})){
currentPosition.y += 1;
currentDirection = RIGHT;
}else{
currentDirection = LEFT;
}
break;
case LEFT:
if(isBuilding(image, Point{currentPosition.x - 1, currentPosition.y})){
currentPosition.x -= 1;
currentDirection = DOWN;
}else{
currentDirection = UP;
}
break;
}
if(path.back() != currentPosition){
path.push_back(currentPosition);
}
}while(currentPosition != initialPosition || currentDirection != initialDirection);
if(path.size() > 1){
path.pop_back();
}
return path;
}
void clearBuilding(Image& image, Point position){
queue<Point> toProcess;
toProcess.push(position);
do{
Point point = toProcess.front();
toProcess.pop();
if(isBuilding(image, point)){
image.set(point.x, point.y, sf::Color::Red);
toProcess.push(Point{point.x+1, point.y});
toProcess.push(Point{point.x-1, point.y});
toProcess.push(Point{point.x, point.y+1});
toProcess.push(Point{point.x, point.y-1});
}
}while(toProcess.size() > 0);
}
vector<Point> getBuilding(Image& image, Point position, Direction direction){
vector<Point> path = getPath(image, position, direction);
clearBuilding(image, position);
return path;
}
int main(int argc, char** argv){
if(argc != 2){
cout << "First argument: file path" << endl;
return -1;
}
Image image;
cout << "Loading file: " << argv[1] << endl;
image.loadFromBMP(argv[1]);
if(!image.isValid()){
cout << "ERROR: Couldn't load image" << endl;
return 1;
}
cout << "Processing buildings..." << endl;
for(int i=0; i<image.getX(); i++){
for(int j=0; j<image.getY(); j++){
if(image.get(i,j) == sf::Color::White){
vector<Point> building = getBuilding(image, Point{i, j}, UP);
cout << "BUILDING FOUND:" << endl;
for(Point point : building){
cout << point << endl;
}
cout << endl;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment