Created
December 7, 2019 08:24
-
-
Save jucie/82b58ab48f8c0c99d522def5d480deb2 to your computer and use it in GitHub Desktop.
geomedian c++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Este programa le a imagem PNG de um mapa e encontra o ponto em que | |
// o territorio se divide igualmente entre Norte e Sul, Leste e Oeste. | |
// A lib PNG++ usa uma funcao que o Windows nao tem, entao quebramos o galho com uma macro. | |
// https://stackoverflow.com/questions/11718915/alternative-api-of-strerror-r-for-windows-os | |
#define strerror_r(errno,buf,len) strerror_s(buf,len,errno) | |
#include <png.hpp> // e' a biblioteca que sabe ler, gravar e manipular imagens em formato PNG. | |
// Esta e' a classe da lib PNG++ que representa uma imagem. Vamos chama-la apenas de Imagem. | |
typedef png::image< png::rgb_pixel > Imagem; | |
const png::rgb_pixel pontoPreto; // e' um pontinho na cor preta. | |
// compara um pixel com outro pra ver se a cor bate. Retorna true se bater. | |
bool operator==(const png::rgb_pixel& lhs, const png::rgb_pixel& rhs) { | |
return lhs.blue == rhs.blue && lhs.green == rhs.green && lhs.red == rhs.red; | |
} | |
// compara um pixel com outro pra ver se a cor bate. Retorna true se NAO bater. | |
bool operator!=(const png::rgb_pixel& lhs, const png::rgb_pixel& rhs) { | |
return !operator==(lhs, rhs); | |
} | |
// fazLinhaHorizontal traca uma linha da esquerda para a direita na posicao y. | |
void fazLinhaHorizontal(Imagem& img, size_t y) { | |
for (size_t x = 0; x < img.get_width(); x++) { // varre da esquerda para a direita | |
img.set_pixel(x, y, pontoPreto); // marca um pontinho | |
} | |
} | |
// fazLinhaVertical traca uma linha de cima para baixo na coluna x. | |
void fazLinhaVertical(Imagem& img, size_t x) { | |
for (size_t y = 0; y < img.get_height(); y++) { // varre de cima para baixo | |
img.set_pixel(x, y, pontoPreto); // marca um pontinho | |
} | |
} | |
// calculaArea retorna a quantidade de pixels dentro do territorio que nos interessa. | |
size_t calculaArea(Imagem& img) { | |
png::rgb_pixel fundo = img.get_pixel(0,0); // pega cor do cantinho | |
size_t cnt = 0; // vamos contar | |
for (size_t y = 0; y < img.get_height(); y++) { // varre de cima para baixo | |
for (size_t x = 0; x < img.get_width(); x++) { // varre da esquerda para a direita | |
if (img.get_pixel(x, y) != fundo) { // estamos dentro do territorio? | |
cnt++; // area que nos interessa tem mais um pixel | |
} | |
} | |
} | |
return cnt; // quantos pixels tem no territorio | |
} | |
// divideNorteSul faz uma linha horizontal dividindo o Norte do Sul. | |
// area indica em que posicao deve ser tracada a linha horizontal. | |
void divideNorteSul(Imagem& img, size_t area) { | |
png::rgb_pixel fundo = img.get_pixel(0,0); // pega cor do cantinho | |
size_t cnt = 0; // vamos contar | |
for (size_t y = 0; y < img.get_height(); y++) { // varre de cima para baixo | |
for (size_t x = 0; x < img.get_width(); x++) { // varre da esquerda para a direita | |
if (img.get_pixel(x, y) != fundo) { // estamos dentro do territorio? | |
cnt++; // area que nos interessa tem mais um pixel | |
if (cnt == area) { // chegamos na linha onde devemos marcar? | |
fazLinhaHorizontal(img, y); // entao marca essa linha | |
return; // e cai fora | |
} | |
} | |
} | |
} | |
} | |
// divideLesteOeste faz uma linha vertical dividindo o Leste do Oeste. | |
// area indica em que posicao deve ser tracada a linha vertical. | |
void divideLesteOeste(Imagem& img, size_t area) { | |
png::rgb_pixel fundo = img.get_pixel(0,0); // pega cor do cantinho | |
size_t cnt = 0; // vamos contar | |
for (size_t x = 0; x < img.get_width(); x++) { // varre da esquerda para a direita | |
for (size_t y = 0; y < img.get_height(); y++) { // varre de cima para baixo | |
if (img.get_pixel(x, y) != fundo) { // estamos dentro do territorio? | |
cnt++; // area que nos interessa tem mais um pixel | |
if (cnt == area) { // chegamos na coluna onde devemos marcar? | |
fazLinhaVertical(img, x); // entao marca essa coluna | |
return; // e cai fora | |
} | |
} | |
} | |
} | |
} | |
// fazACruz acha o ponto no mapa onde a area se divide igualmente entre Norte/Sul e Leste/Oeste. | |
void fazACruz(Imagem& img) { | |
size_t area = calculaArea(img); // primeiro obtemos a area total do territorio | |
size_t metade = area / 2; // vamos dividir essa area ao meio | |
divideNorteSul(img, metade); // tracamos uma linha dividindo entre Norte e Sul | |
divideLesteOeste(img, metade); // depois tracamos outra dividindo entre Leste e Oeste | |
} | |
int main() { | |
Imagem img("input.png"); // le a imagem original do arquivo de entrada | |
fazACruz(img); // marca a divisao | |
img.write("output.png"); // grava a imagem marcada no arquivo de saida | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment