00001 #include "mundoqt.h"
00002 #include "main-window.h"
00003
00004 #include <QColor>
00005 #include <QBrush>
00006 #include <QPainter>
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <QFileDialog>
00010 #include <QtDebug>
00011
00012 #define RAIO_SELECAO 10
00013 #define RAIO_PAREDE (GROSSURA_PAREDE * 2)
00014
00015 #define COR_MORTE Qt::cyan
00016 #define COR_NASCIMENTO QColor(percorre->biota.genes.cor_cabeca[0],percorre->biota.genes.cor_cabeca[1],percorre->biota.genes.cor_cabeca[2])
00017 #define IDADE_COR 5
00018
00019
00020
00021 MundoQT::MundoQT(QWidget *parent, Qt::WFlags f) : QWidget(parent, f), Mundo()
00022 {
00023 parede_selecionada = NULL;
00024 mutex = NULL;
00025
00026 offsetx = 0;
00027 offsety = 0;
00028 zm = 0.5f;
00029 executando = true;
00030 fixar = false;
00031 autoSelec = false;
00032
00033 QString simvidaConfig = QDir::homePath() + QDir::separator() + ".simvida";
00034
00035
00036 QFile file(simvidaConfig);
00037
00038 if (!file.open(QIODevice::ReadOnly))
00039 {
00040 qDebug() << tr("Creating new Simvida configuration file");
00041
00042
00043 propriedades.tamanho_x = TAMANHO_X;
00044 propriedades.tamanho_y = TAMANHO_Y;
00045 propriedades.energia_grao = ENERGIA_GRAO;
00046 propriedades.teto_energetico = TETO_ENERGETICO;
00047 propriedades.probabilidade_mutacao = PROBABILIDADE_MUTACAO;
00048 propriedades.intensidade_mutacao = INTENSIDADE_MUTACAO;
00049
00050 file.open(QIODevice::WriteOnly);
00051 FILE *arq = fdopen(file.handle(), "w");
00052
00053 fprintf(arq, "%d\n%d\n%d\n%d\n%d\n%d\n",
00054 TAMANHO_X, TAMANHO_Y, ENERGIA_GRAO,
00055 TETO_ENERGETICO, PROBABILIDADE_MUTACAO, INTENSIDADE_MUTACAO);
00056
00057 fclose(arq);
00058 }
00059 else
00060 {
00061
00062 FILE *arq = fdopen(file.handle(), "r");
00063 fscanf(arq, "%d\n%d\n%d\n%d\n%d\n%d\n",
00064 &(propriedades.tamanho_x), &(propriedades.tamanho_y),
00065 &(propriedades.energia_grao),
00066 &(propriedades.teto_energetico), &(propriedades.probabilidade_mutacao),
00067 &(propriedades.intensidade_mutacao));
00068
00069 fclose(arq);
00070 }
00071
00072 file.close();
00073
00074 reiniciar();
00075 }
00076
00077
00078
00079 MundoQT::~MundoQT()
00080 {
00081
00082 }
00083
00084
00085
00086 void MundoQT::paintEvent(QPaintEvent *event)
00087 {
00088
00089
00090 QPainter painter(this);
00091 painter.setRenderHint(QPainter::Antialiasing, false);
00092 painter.setRenderHint(QPainter::SmoothPixmapTransform, false);
00093
00094 int dx = width()/2;
00095 int dy = height()/2;
00096
00097
00098 QBrush brush(QColor(200, 220, 255));
00099 painter.setBrush(brush);
00100
00101
00102 painter.drawRect(event->rect());
00103
00104
00105 QPen pen;
00106 pen.setColor(Qt::black);
00107 pen.setWidth((int)(zm*GROSSURA_PAREDE*2)+1);
00108 painter.setPen(pen);
00109
00110
00111 brush.setColor(Qt::white);
00112 painter.setBrush(brush);
00113 painter.drawRect(
00114 (int)(-offsetx*zm+dx),(int)(-offsety*zm+dy),
00115 (int)(propriedades.tamanho_x*zm), (int)(propriedades.tamanho_y*zm));
00116
00117
00118 mutex->lock();
00119 brush.setColor(Qt::black);
00120 painter.setBrush(brush);
00121 for (struct NohParede *percorre = nohCabecaParedes.proximo;
00122 percorre != NULL;
00123 percorre = percorre->proximo)
00124 {
00125 painter.drawLine(
00126 (int)((percorre->inicio.X-offsetx)*zm+dx),
00127 (int)((percorre->inicio.Y-offsety)*zm+dy),
00128 (int)((percorre->fim.X-offsetx)*zm+dx),
00129 (int)((percorre->fim.Y-offsety)*zm+dy));
00130
00131 painter.drawEllipse(
00132 (int)(((percorre->inicio.X - RAIO_PAREDE)-offsetx)*zm+dx),
00133 (int)(((percorre->inicio.Y - RAIO_PAREDE)-offsety)*zm+dy),
00134 (int)(RAIO_PAREDE*2.0f*zm),(int)(RAIO_PAREDE*2.0f*zm));
00135
00136 painter.drawEllipse(
00137 (int)(((percorre->fim.X - RAIO_PAREDE)-offsetx)*zm+dx),
00138 (int)(((percorre->fim.Y - RAIO_PAREDE)-offsety)*zm+dy),
00139 (int)(RAIO_PAREDE*2.0f*zm),(int)(RAIO_PAREDE*2.0f*zm));
00140 }
00141 mutex->unlock();
00142
00143
00144 pen.setColor(Qt::black);
00145 pen.setWidth((int)(zm+1));
00146 painter.setPen(pen);
00147
00148
00149 mutex->lock();
00150 brush.setColor(Qt::cyan);
00151 painter.setBrush(brush);
00152 for (struct NohGrao *percorre = nohCabecaGraos.proximo;
00153 percorre != NULL;
00154 percorre = percorre->proximo)
00155 {
00156
00157 if (percorre->posicao.X > (signed int)propriedades.tamanho_x ||
00158 percorre->posicao.Y > (signed int)propriedades.tamanho_y)
00159 percorre->posicao =
00160 Vetor<float>(rand() % propriedades.tamanho_x, rand() % propriedades.tamanho_y);
00161
00162
00163 if (
00164 ((percorre->posicao.X + RAIO_GRAO)-offsetx)*zm+dx >= event->rect().x() &&
00165 ((percorre->posicao.X - RAIO_GRAO)-offsetx)*zm+dy <= event->rect().x()+ event->rect().width() &&
00166 ((percorre->posicao.Y + RAIO_GRAO)-offsety)*zm+dx >= event->rect().y() &&
00167 ((percorre->posicao.Y - RAIO_GRAO)-offsety)*zm+dy <= event->rect().y() + event->rect().height())
00168 {
00169 if (percorre == grao_selecionado)
00170 {
00171 pen.setWidth((int)(zm+3));
00172 painter.setPen(pen);
00173 }
00174
00175 painter.drawEllipse(
00176 (int)(((percorre->posicao.X - RAIO_GRAO)-offsetx)*zm+dx),
00177 (int)(((percorre->posicao.Y - RAIO_GRAO)-offsety)*zm+dy),
00178 (int)(RAIO_GRAO*2.0f*zm), (int)(RAIO_GRAO*2.0f*zm));
00179
00180 if (percorre == grao_selecionado)
00181 {
00182 pen.setWidth((int)(zm+1));
00183 painter.setPen(pen);
00184 }
00185 }
00186 }
00187 mutex->unlock();
00188
00189
00190 mutex->lock();
00191 for (struct NohBiota *percorre = nohCabecaBiotas.proximo;
00192 percorre != NULL;
00193 percorre = percorre->proximo)
00194 if (
00195 ((percorre->biota.estado.posicao.X + (percorre->biota.genes.massa_cabeca * FATOR_PERCEPCAO_GRAOS))-offsetx)*zm+dx >= event->rect().x() &&
00196 ((percorre->biota.estado.posicao.Y + (percorre->biota.genes.massa_cabeca * FATOR_PERCEPCAO_GRAOS))-offsety)*zm+dy >= event->rect().y() &&
00197 ((percorre->biota.estado.posicao.X - (percorre->biota.genes.massa_cabeca * FATOR_PERCEPCAO_GRAOS))-offsetx)*zm+dx <= event->rect().x()+ event->rect().width() &&
00198 ((percorre->biota.estado.posicao.Y - (percorre->biota.genes.massa_cabeca * FATOR_PERCEPCAO_GRAOS))-offsety)*zm+dy <= event->rect().y() + event->rect().height())
00199 {
00200
00201 pen.setColor(
00202 (percorre->biota.estado.energia <= 1)? COR_MORTE :
00203 (percorre->biota.estado.idade <= IDADE_COR-1)? COR_NASCIMENTO :
00204 QColor(0,
00205 (int)(((float)percorre->biota.estado.energia/(float)percorre->biota.genes.limiar_reproducao)*255.0f) % 255,
00206 (int)(((float)percorre->biota.estado.energia/(float)percorre->biota.genes.limiar_reproducao)*255.0f) % 255 ));
00207 painter.setPen(pen);
00208
00209
00210 brush.setColor(
00211 (percorre->biota.estado.energia <= 1)? COR_MORTE :
00212 (percorre->biota.estado.idade <= IDADE_COR)? COR_NASCIMENTO :
00213 QColor(percorre->biota.genes.cor_cabeca[0],percorre->biota.genes.cor_cabeca[1],percorre->biota.genes.cor_cabeca[2]));
00214 painter.setBrush(brush);
00215
00216 painter.drawEllipse(
00217 (int)(((percorre->biota.estado.posicao.X - percorre->biota.genes.massa_cabeca)-offsetx)*zm+dx),
00218 (int)(((percorre->biota.estado.posicao.Y - percorre->biota.genes.massa_cabeca)-offsety)*zm+dy),
00219 (int)(percorre->biota.genes.massa_cabeca*2.0f*zm), (int)(percorre->biota.genes.massa_cabeca*2.0f*zm));
00220
00221
00222 painter.drawLine(
00223 (int)((percorre->biota.estado.posicao.X-offsetx)*zm+dx),
00224 (int)((percorre->biota.estado.posicao.Y-offsety)*zm+dy),
00225 (int)(((percorre->biota.estado.posicao.X +
00226 (cos(percorre->biota.estado.angulo) * percorre->biota.genes.massa_cabeca))-offsetx)*zm+dx),
00227 (int)(((percorre->biota.estado.posicao.Y +
00228 (sin(percorre->biota.estado.angulo) * percorre->biota.genes.massa_cabeca))-offsety)*zm+dy));
00229
00230
00231 pen.setStyle(Qt::NoPen); painter.setPen(pen);
00232 brush.setColor(Qt::white); painter.setBrush(brush);
00233 painter.drawEllipse(
00234 (int)((((percorre->biota.estado.posicao.X + (percorre->biota.genes.massa_cabeca/2.0f)) - (percorre->biota.genes.massa_cabeca/6.0f))-offsetx)*zm+dx),
00235 (int)((((percorre->biota.estado.posicao.Y - (percorre->biota.genes.massa_cabeca/2.0f)) - (percorre->biota.genes.massa_cabeca/6.0f))-offsety)*zm+dy),
00236 (int)((percorre->biota.genes.massa_cabeca/3.0f)*zm), (int)((percorre->biota.genes.massa_cabeca/3.0f)*zm));
00237 painter.drawEllipse(
00238 (int)((((percorre->biota.estado.posicao.X + (percorre->biota.genes.massa_cabeca*0.3f)) - (percorre->biota.genes.massa_cabeca/4.0f))-offsetx)*zm+dx),
00239 (int)((((percorre->biota.estado.posicao.Y - (percorre->biota.genes.massa_cabeca*0.3f)) - (percorre->biota.genes.massa_cabeca/4.0f))-offsety)*zm+dy),
00240 (int)((percorre->biota.genes.massa_cabeca/2.0f)*zm), (int)((percorre->biota.genes.massa_cabeca/2.0f)*zm));
00241 pen.setStyle(Qt::SolidLine); painter.setPen(pen);
00242
00243
00244 for (unsigned int c = 0; c < percorre->biota.numero_segmentos; c++)
00245 {
00246
00247 painter.drawLine(
00248 (int)(((cos(percorre->biota.genes.segmentos[c].angulo+percorre->biota.estado.angulo)*
00249 percorre->biota.genes.massa_cabeca + percorre->biota.estado.posicao.X)-offsetx) * zm+dx),
00250 (int)(((sin(percorre->biota.genes.segmentos[c].angulo+percorre->biota.estado.angulo)*
00251 percorre->biota.genes.massa_cabeca + percorre->biota.estado.posicao.Y)-offsety) * zm+dy),
00252 (int)(((cos(percorre->biota.genes.segmentos[c].angulo+(sin(percorre->biota.estado.posicaoSegmentos[c])*
00253 (percorre->biota.genes.segmentos[c].arco/1.0f))+percorre->biota.estado.angulo)*
00254 (percorre->biota.genes.massa_cabeca+percorre->biota.genes.segmentos[c].comprimento+percorre->biota.genes.segmentos[c].massa)+
00255 percorre->biota.estado.posicao.X)-offsetx) *zm+dx),
00256 (int)(((sin(percorre->biota.genes.segmentos[c].angulo+(sin(percorre->biota.estado.posicaoSegmentos[c])*
00257 (percorre->biota.genes.segmentos[c].arco/1.0f))+percorre->biota.estado.angulo)*
00258 (percorre->biota.genes.massa_cabeca+percorre->biota.genes.segmentos[c].comprimento+percorre->biota.genes.segmentos[c].massa)+
00259 percorre->biota.estado.posicao.Y)-offsety) *zm+dy));
00260
00261
00262 brush.setColor(
00263 (percorre->biota.estado.energia <= 1)? COR_MORTE :
00264 (percorre->biota.estado.idade <= IDADE_COR)? COR_NASCIMENTO :
00265 QColor(percorre->biota.genes.segmentos[c].cor[0],percorre->biota.genes.segmentos[c].cor[1],percorre->biota.genes.segmentos[c].cor[2]));
00266 painter.setBrush(brush);
00267
00268 painter.drawEllipse(
00269 (int)((((cos(percorre->biota.genes.segmentos[c].angulo+(sin(percorre->biota.estado.posicaoSegmentos[c])*
00270 (percorre->biota.genes.segmentos[c].arco/1.0f))+percorre->biota.estado.angulo)*
00271 (percorre->biota.genes.massa_cabeca+percorre->biota.genes.segmentos[c].comprimento+percorre->biota.genes.segmentos[c].massa)+
00272 percorre->biota.estado.posicao.X) - percorre->biota.genes.segmentos[c].massa)-offsetx)*zm+dx),
00273 (int)((((sin(percorre->biota.genes.segmentos[c].angulo+(sin(percorre->biota.estado.posicaoSegmentos[c])*
00274 (percorre->biota.genes.segmentos[c].arco/1.0f))+percorre->biota.estado.angulo)*
00275 (percorre->biota.genes.massa_cabeca+percorre->biota.genes.segmentos[c].comprimento+percorre->biota.genes.segmentos[c].massa)+
00276 percorre->biota.estado.posicao.Y) - percorre->biota.genes.segmentos[c].massa)-offsety)*zm+dy),
00277 (int)(percorre->biota.genes.segmentos[c].massa*2.0f*zm), (int)(percorre->biota.genes.segmentos[c].massa*2.0f*zm));
00278 }
00279
00280 if (percorre == selecionado)
00281 {
00282 brush.setStyle(Qt::NoBrush); painter.setBrush(brush);
00283
00284 pen.setColor(Qt::yellow); painter.setPen(pen);
00285 painter.drawEllipse(
00286 (int)(((percorre->biota.estado.posicao.X - (percorre->biota.genes.massa_cabeca * FATOR_PERCEPCAO_GRAOS))-offsetx)*zm+dx),
00287 (int)(((percorre->biota.estado.posicao.Y - (percorre->biota.genes.massa_cabeca * FATOR_PERCEPCAO_GRAOS))-offsety)*zm+dy),
00288 (int)((percorre->biota.genes.massa_cabeca * FATOR_PERCEPCAO_GRAOS)*2.0f*zm),
00289 (int)((percorre->biota.genes.massa_cabeca * FATOR_PERCEPCAO_GRAOS)*2.0f*zm));
00290
00291 pen.setColor(Qt::green); painter.setPen(pen);
00292 painter.drawEllipse(
00293 (int)(((percorre->biota.estado.posicao.X - percorre->biota.genes.massa_cabeca - RAIO_SELECAO)-offsetx)*zm+dx),
00294 (int)(((percorre->biota.estado.posicao.Y - percorre->biota.genes.massa_cabeca - RAIO_SELECAO)-offsety)*zm+dy),
00295 (int)((percorre->biota.genes.massa_cabeca + RAIO_SELECAO)*2.0f*zm),
00296 (int)((percorre->biota.genes.massa_cabeca + RAIO_SELECAO)*2.0f*zm));
00297
00298 brush.setStyle(Qt::SolidPattern); painter.setBrush(brush);
00299 }
00300 }
00301 mutex->unlock();
00302 }
00303
00304
00305
00306 void MundoQT::mouseDoubleClickEvent ( QMouseEvent * event )
00307 {
00308
00309 lastPos = Vetor<float>(event->x(), event->y());
00310
00311 if (event->button() == Qt::LeftButton)
00312 {
00313
00314 mutex->lock();
00315
00316
00317 if (selecionarGrao((Vetor<float>(event->x(), event->y()) - (Vetor<float>(width(),height())/2.0f))/zm + Vetor<float>(offsetx, offsety)))
00318
00319 removerGrao();
00320 else
00321 novoGrao();
00322
00323
00324 mutex->unlock();
00325
00326
00327 if (!executando)
00328 repaint();
00329 }
00330 }
00331
00332
00333
00334 void MundoQT::mouseMoveEvent ( QMouseEvent * event )
00335 {
00336 if ((event->buttons() & Qt::MidButton) != 0)
00337 {
00338
00339 offsetx += (lastPos.X - event->x()) / zm;
00340 offsety += (lastPos.Y - event->y()) / zm;
00341
00342
00343 if (offsetx < 0)
00344 offsetx = 0;
00345 else if (offsetx > propriedades.tamanho_x)
00346 offsetx = propriedades.tamanho_x;
00347 if (offsety < 0)
00348 offsety = 0;
00349 else if (offsety > propriedades.tamanho_y)
00350 offsety = propriedades.tamanho_y;
00351
00352
00353
00354 emit changeHorizontalBar((int)offsetx);
00355 emit changeVerticalBar((int)offsety);
00356
00357
00358 if (!executando)
00359 repaint();
00360 }
00361 else if ((event->buttons() & Qt::LeftButton) != 0)
00362 {
00363 if (selecionado != NULL)
00364 {
00365
00366 selecionado->biota.estado.posicao =
00367 ((Vetor<float>(event->x(), event->y()) - (Vetor<float>(width(),height())/2.0f))/zm + Vetor<float>(offsetx, offsety));
00368
00369
00370 if (!executando)
00371 repaint();
00372 }
00373 else if (grao_selecionado != NULL)
00374 {
00375
00376 posicionarGrao
00377 ((Vetor<float>(event->x(), event->y()) - (Vetor<float>(width(),height())/2.0f))/zm + Vetor<float>(offsetx, offsety));
00378
00379
00380 if (!executando)
00381 repaint();
00382 }
00383 else if (parede_selecionada != NULL)
00384 {
00385
00386 posicionarParede(Vetor<float>(event->x(), event->y()));
00387
00388
00389 if (!executando)
00390 repaint();
00391 }
00392 }
00393
00394
00395 lastPos = Vetor<float>(event->x(), event->y());
00396 }
00397
00398
00399
00400 void MundoQT::mousePressEvent ( QMouseEvent * event )
00401 {
00402
00403 lastPos = Vetor<float>(event->x(), event->y());
00404
00405
00406 if (event->button() != Qt::MidButton) {
00407
00408 Vetor<float> pos = (Vetor<float>(event->x(), event->y()) - (Vetor<float>(width(),height())/2.0f))/zm + Vetor<float>(offsetx, offsety);
00409
00410 if (!selecionarBiota(pos))
00411 selecionado = NULL;
00412 if (!selecionarGrao(pos))
00413 grao_selecionado = NULL;
00414 if (!selecionarParede((Vetor<float>(event->x(), event->y()))))
00415 parede_selecionada = NULL;
00416
00417
00418 if (!executando)
00419 repaint();
00420
00421 if (event->button() == Qt::RightButton) {
00422 if (selecionado)
00423 {
00424 info->setBiota(selecionado->biota);
00425 info->move(event->globalPos());
00426 menuBiota->exec(event->globalPos());
00427 }
00428 else if (grao_selecionado)
00429 menuGrao->exec(event->globalPos());
00430 else if (parede_selecionada)
00431 menuParede->exec(event->globalPos());
00432 else if (pos.X > 0 && pos.Y > 0 && pos.X < propriedades.tamanho_x && pos.Y < propriedades.tamanho_y)
00433 menuVoid->exec(event->globalPos());
00434 }
00435
00436 mudaBarraStatus();
00437 }
00438 }
00439
00440
00441
00442 void MundoQT::wheelEvent ( QWheelEvent * event )
00443 {
00444 if (event->delta() > 0 && zm > 0.1f)
00445 {
00446 zm = (zm * 0.9f) - 0.001f;
00447
00448 if (!executando)
00449 repaint();
00450 }
00451 else if (event->delta() < 0 && zm < 4.0f)
00452 {
00453 zm = (zm * 1.1f) + 0.001f;
00454
00455 if (!executando)
00456 repaint();
00457 }
00458 }
00459
00460
00461
00462 void MundoQT::mouseReleaseEvent ( QMouseEvent * event )
00463 {
00464 if (selecionado && executando)
00465 {
00466 selecionado->biota.acelerar(Vetor<float>(event->x(), event->y()) - lastPos);
00467 }
00468 }
00469
00470
00471
00472 void MundoQT::offsetxChanged(int vx)
00473 {
00474 offsetx = vx;
00475
00476
00477 if (!executando)
00478 repaint();
00479 }
00480
00481
00482
00483 void MundoQT::offsetyChanged(int vy)
00484 {
00485 offsety = vy;
00486
00487
00488 if (!executando)
00489 repaint();
00490 }
00491
00492
00493
00494 void MundoQT::setMutex(QMutex *m)
00495 {
00496 mutex = m;
00497 }
00498
00499
00500
00501
00502 QMutex* MundoQT::getMutex()
00503 {
00504 return mutex;
00505 }
00506
00507
00508
00509 void MundoQT::atualizar()
00510 {
00511 static int deadCry = 50;
00512
00513 mutex->lock();
00514 Mundo::atualizar();
00515
00516 if (selecionado && fixar)
00517 {
00518 offsetx = selecionado->biota.estado.posicao.X;
00519 offsety = selecionado->biota.estado.posicao.Y;
00520
00521
00522 emit changeHorizontalBar((int)offsetx);
00523 emit changeVerticalBar((int)offsety);
00524 }
00525 mutex->unlock();
00526
00527 if (!selecionado && autoSelec)
00528 {
00529 if (deadCry >= 50)
00530 {
00531 deadCry = 0;
00532 maisVelho();
00533 }
00534 else
00535 deadCry++;
00536 }
00537
00538 mudaBarraStatus();
00539 }
00540
00541
00542
00543
00544
00545 void MundoQT::estatistica()
00546 {
00547
00548
00549
00550 struct NohLineage
00551 {
00552 unsigned int lineage;
00553 unsigned int quantidade;
00554 int cor[3];
00555 struct NohLineage *proximo;
00556 };
00557
00558 struct NohLineage cabecaLineage;
00559
00560 cabecaLineage.proximo = NULL;
00561
00562
00563 float numero_segmentos = 0;
00564 float massa_cabeca = 0;
00565 float limiar_reproducao = 0;
00566 float distribuicao_energetica = 0;
00567 float idade = 0;
00568 float energia = 0;
00569 float geracao = 0;
00570 float filhos = 0;
00571
00572
00573 unsigned int max_numero_segmentos = 0;
00574 int max_massa_cabeca = 0;
00575 int max_limiar_reproducao = 0;
00576 float max_distribuicao_energetica = 0;
00577 unsigned int max_idade = 0;
00578 float max_energia = 0;
00579 unsigned int max_geracao = 0;
00580 unsigned int max_filhos = 0;
00581
00582
00583 mutex->lock();
00584 for (struct NohBiota *percorre = nohCabecaBiotas.proximo;
00585 percorre != NULL;
00586 percorre = percorre->proximo)
00587 {
00588
00589 numero_segmentos += percorre->biota.numero_segmentos;
00590 massa_cabeca += percorre->biota.genes.massa_cabeca;
00591 limiar_reproducao += percorre->biota.genes.limiar_reproducao;
00592 distribuicao_energetica += percorre->biota.genes.distribuicao_energia;
00593 idade += percorre->biota.estado.idade;
00594 energia += percorre->biota.estado.energia;
00595 geracao += percorre->biota.estado.geracao;
00596 filhos += percorre->biota.estado.filhos;
00597
00598
00599 if (percorre->biota.numero_segmentos > max_numero_segmentos)
00600 max_numero_segmentos = percorre->biota.numero_segmentos;
00601 if (percorre->biota.genes.massa_cabeca > max_massa_cabeca)
00602 max_massa_cabeca = percorre->biota.genes.massa_cabeca;
00603 if (percorre->biota.genes.limiar_reproducao > max_limiar_reproducao)
00604 max_limiar_reproducao = percorre->biota.genes.limiar_reproducao;
00605 if (percorre->biota.genes.distribuicao_energia > max_distribuicao_energetica)
00606 max_distribuicao_energetica = percorre->biota.genes.distribuicao_energia;
00607 if (percorre->biota.estado.idade > max_idade)
00608 max_idade = percorre->biota.estado.idade;
00609 if (percorre->biota.estado.energia > max_energia)
00610 max_energia = percorre->biota.estado.energia;
00611 if (percorre->biota.estado.geracao > max_geracao)
00612 max_geracao = percorre->biota.estado.geracao;
00613 if (percorre->biota.estado.filhos > max_filhos)
00614 max_filhos = percorre->biota.estado.filhos;
00615
00616
00617 struct NohLineage *percorre_lin;
00618 for (percorre_lin = &cabecaLineage;
00619 percorre_lin->proximo != NULL &&
00620 percorre_lin->proximo->lineage > percorre->biota.lineage;
00621 percorre_lin = percorre_lin->proximo)
00622 ;
00623
00624
00625 if (percorre_lin->proximo != NULL && (percorre_lin->proximo->lineage == percorre->biota.lineage))
00626 {
00627 percorre_lin->proximo->quantidade++;
00628 percorre_lin->proximo->cor[0] += percorre->biota.genes.cor_cabeca[0];
00629 percorre_lin->proximo->cor[1] += percorre->biota.genes.cor_cabeca[1];
00630 percorre_lin->proximo->cor[2] += percorre->biota.genes.cor_cabeca[2];
00631 }
00632 else
00633 {
00634
00635 struct NohLineage *novo = new NohLineage;
00636
00637 novo->lineage = percorre->biota.lineage;
00638 novo->proximo = percorre_lin->proximo;
00639 novo->quantidade = 1;
00640 novo->cor[0] = percorre->biota.genes.cor_cabeca[0];
00641 novo->cor[1] = percorre->biota.genes.cor_cabeca[1];
00642 novo->cor[2] = percorre->biota.genes.cor_cabeca[2];
00643
00644 percorre_lin->proximo = novo;
00645 }
00646 }
00647 mutex->unlock();
00648
00649
00650 if (estatisticas.numero_biotas > 0)
00651 {
00652 numero_segmentos /= estatisticas.numero_biotas;
00653 massa_cabeca /= estatisticas.numero_biotas;
00654 limiar_reproducao /= estatisticas.numero_biotas;
00655 distribuicao_energetica /= estatisticas.numero_biotas;
00656
00657 idade /= estatisticas.numero_biotas;
00658 energia /= estatisticas.numero_biotas;
00659 geracao /= estatisticas.numero_biotas;
00660 filhos /= estatisticas.numero_biotas;
00661 }
00662
00663
00664 QPainter painterE(stat->imgEspecies->imagem);
00665 int altura = 0;
00666
00667
00668
00669 struct NohLineage *percorre_lin = cabecaLineage.proximo;
00670 while (percorre_lin != NULL)
00671 {
00672
00673 painterE.setPen(QPen(QColor(
00674 percorre_lin->cor[0]/percorre_lin->quantidade,
00675 percorre_lin->cor[1]/percorre_lin->quantidade,
00676 percorre_lin->cor[2]/percorre_lin->quantidade)));
00677
00678 painterE.drawLine(
00679 stat->imgEspecies->imagem->width()-1,
00680 stat->imgEspecies->imagem->height() -
00681 (int)(altura * stat->imgEspecies->imagem->height() / (float)estatisticas.numero_biotas),
00682 stat->imgEspecies->imagem->width()-1,
00683 stat->imgEspecies->imagem->height() -
00684 (int)((altura + percorre_lin->quantidade) * stat->imgEspecies->imagem->height() / (float)estatisticas.numero_biotas));
00685
00686 altura += percorre_lin->quantidade;
00687
00688
00689 struct NohLineage *remove = percorre_lin;
00690 percorre_lin = percorre_lin->proximo;
00691 delete remove;
00692 }
00693
00694 painterE.drawImage(-1,0,*(stat->imgEspecies->imagem));
00695
00696
00697 static int max_numero_biotas_graos = 0;
00698 static int lastGraoY = -1;
00699 static int lastBiotaY = -1;
00700
00701
00702 if (estatisticas.numero_biotas > (unsigned int)max_numero_biotas_graos)
00703 max_numero_biotas_graos = estatisticas.numero_biotas;
00704 if (estatisticas.numero_graos > (unsigned int)max_numero_biotas_graos)
00705 max_numero_biotas_graos = estatisticas.numero_graos;
00706
00707
00708 int biotaY = stat->imgBiotasGraos->height() -
00709 (int)(estatisticas.numero_biotas * stat->imgBiotasGraos->height() / (float)max_numero_biotas_graos);
00710
00711 int graoY = stat->imgBiotasGraos->height() -
00712 (int)(estatisticas.numero_graos * stat->imgBiotasGraos->height() / (float)max_numero_biotas_graos);
00713
00714
00715 QPainter painterBG(stat->imgBiotasGraos->imagem);
00716 painterBG.setPen(QPen(Qt::white));
00717 painterBG.drawLine(stat->imgBiotasGraos->width()-1, 0, stat->imgBiotasGraos->width()-1, stat->imgBiotasGraos->height());
00718
00719
00720 painterBG.setPen(QPen(Qt::red));
00721 painterBG.drawLine(stat->imgBiotasGraos->width()-2, (lastBiotaY == -1)? biotaY : lastBiotaY, stat->imgBiotasGraos->width()-1, biotaY);
00722 painterBG.setPen(QPen(Qt::blue));
00723 painterBG.drawLine(stat->imgBiotasGraos->width()-2, (lastGraoY == -1)? graoY : lastGraoY, stat->imgBiotasGraos->width()-1, graoY);
00724
00725
00726 painterBG.drawImage(-1,0,*(stat->imgBiotasGraos->imagem));
00727
00728 lastBiotaY = biotaY;
00729 lastGraoY = graoY;
00730
00731 if (stat->isVisible())
00732 {
00733
00734
00735 stat->labelEnergia->setText(QVariant(energia).toString() + tr(" wens"));
00736 stat->labelSegmentos->setText(QVariant(numero_segmentos).toString());
00737 stat->labelCabeca->setText(QVariant(massa_cabeca).toString());
00738 stat->labelLimiar->setText(QVariant(limiar_reproducao).toString() + tr(" wens"));
00739 stat->labelDistribuicao->setText(QVariant(distribuicao_energetica*100).toString() + tr(" %"));
00740 stat->labelGeracao->setText(QVariant(geracao).toString());
00741 stat->labelIdade->setText(QVariant(idade).toString());
00742 stat->labelFilhos->setText(QVariant(filhos).toString());
00743
00744 stat->labelEnergia_2->setText(QVariant(max_energia).toString() + tr(" wens"));
00745 stat->labelSegmentos_2->setText(QVariant(max_numero_segmentos).toString());
00746 stat->labelCabeca_2->setText(QVariant(max_massa_cabeca).toString());
00747 stat->labelLimiar_2->setText(QVariant(max_limiar_reproducao).toString() + tr(" wens"));
00748 stat->labelDistribuicao_2->setText(QVariant(max_distribuicao_energetica*100).toString() + tr(" %"));
00749 stat->labelGeracao_2->setText(QVariant(max_geracao).toString());
00750 stat->labelIdade_2->setText(QVariant(max_idade).toString());
00751 stat->labelFilhos_2->setText(QVariant(max_filhos).toString());
00752
00753 stat->labelGraosxBiotas->setText(QVariant((float)estatisticas.numero_graos/(float)estatisticas.numero_biotas).toString());
00754
00755
00756 stat->imgEspecies->repaint();
00757 stat->imgBiotasGraos->repaint();
00758 }
00759 }
00760
00761
00762
00763 void MundoQT::mudaBarraStatus()
00764 {
00765 if (selecionado)
00766 emit estadoModificado(
00767 tr("Age") + ": " + QVariant(selecionado->biota.estado.idade).toString() +
00768 ", " + tr("Generation") + ": " + QVariant((int)selecionado->biota.estado.geracao).toString() +
00769 ", " + tr("Energy") + ": " + QVariant((int)selecionado->biota.estado.energia).toString() +
00770 ", " + tr("Offsprings") + ": " + QVariant((int)selecionado->biota.estado.filhos).toString());
00771 else if (grao_selecionado)
00772 emit estadoModificado(
00773 ", " + tr("Grain energy") + ": " + QVariant(propriedades.energia_grao).toString());
00774 else
00775 emit estadoModificado(
00776 QVariant((int)estatisticas.ciclos).toString() + " " + tr("Cicles") + ", " +
00777 QVariant((int)estatisticas.numero_biotas).toString() + + " " + tr("Biots") + ", " +
00778 QVariant((int)estatisticas.numero_graos).toString() + + " " + tr("Grains") + ".");
00779 }
00780
00781
00782
00783 void MundoQT::limpar()
00784 {
00785
00786
00787
00788 if (mutex != NULL)
00789 mutex->lock();
00790
00791 Mundo::destroy();
00792
00793
00794 if (mutex != NULL)
00795 mutex->unlock();
00796
00797
00798 if (!executando && mutex != NULL)
00799 repaint();
00800
00801 mudaBarraStatus();
00802 }
00803
00804
00805
00806 void MundoQT::reiniciar()
00807 {
00808 limpar();
00809
00810
00811 if (mutex != NULL)
00812 mutex->lock();
00813
00814
00815 int inicial = rand() % 2+((propriedades.tamanho_x*propriedades.tamanho_y)/250000);
00816 for (int c = 0; c < inicial; c++)
00817 inserirBiota(Biota((Mundo*)this));
00818
00819
00820 if (mutex != NULL)
00821 mutex->unlock();
00822
00823 selecionado = NULL;
00824
00825
00826 if (!executando)
00827 repaint();
00828
00829 mudaBarraStatus();
00830 }
00831
00832
00833
00834 void MundoQT::posicionarParede(Vetor<float> pos)
00835 {
00836 if (pontaSelecionada == PONTA_INICIO)
00837 parede_selecionada->inicio = (pos - (Vetor<float>(width(),height())/2.0f))/zm + Vetor<float>(offsetx, offsety);
00838 else if (pontaSelecionada == PONTA_FIM)
00839 parede_selecionada->fim = (pos - (Vetor<float>(width(),height())/2.0f))/zm + Vetor<float>(offsetx, offsety);
00840 else
00841 {
00842 Vetor<float> posicao = (pos - (Vetor<float>(width(),height())/2.0f))/zm + Vetor<float>(offsetx, offsety);
00843
00844 parede_selecionada->inicio += posicao - ancora_parede;
00845 parede_selecionada->fim += posicao - ancora_parede;
00846 ancora_parede = posicao;
00847 }
00848 }
00849
00850
00851
00852
00853 bool MundoQT::selecionarParede(Vetor<float> pos)
00854 {
00855 Vetor<float> posicao = (pos - (Vetor<float>(width(),height())/2.0f))/zm + Vetor<float>(offsetx, offsety);
00856
00857
00858 for (struct NohParede *percorre = nohCabecaParedes.proximo;
00859 percorre != NULL;
00860 percorre = percorre->proximo)
00861 {
00862 if (posicao.distancia(percorre->inicio) <= DISTANCIA_SELECAO_PAREDE)
00863 {
00864 parede_selecionada = percorre;
00865 pontaSelecionada = PONTA_INICIO;
00866 return true;
00867 }
00868 if (posicao.distancia(percorre->fim) <= DISTANCIA_SELECAO_PAREDE)
00869 {
00870 parede_selecionada = percorre;
00871 pontaSelecionada = PONTA_FIM;
00872 return true;
00873 }
00874
00875 Vetor<float> u = posicao - percorre->inicio;
00876 Vetor<float> v = percorre->fim - percorre->inicio;
00877 Vetor<float> proj = (v.modulo() == 0)? posicao : (
00878 (v / v.modulo ()) *
00879 (((u.X * v.X)+(u.Y * v.Y)) / v.modulo()) );
00880
00881 proj += percorre->inicio;
00882
00883
00884 if (proj.X > percorre->inicio.X && proj.X > percorre->fim.X)
00885 proj = (percorre->inicio.X > percorre->fim.X)? percorre->inicio : percorre->fim;
00886 else if (proj.X < percorre->inicio.X && proj.X < percorre->fim.X)
00887 proj = (percorre->inicio.X < percorre->fim.X)? percorre->inicio : percorre->fim;
00888 else if (proj.Y > percorre->inicio.Y && proj.Y > percorre->fim.Y)
00889 proj = (percorre->inicio.Y > percorre->fim.Y)? percorre->inicio : percorre->fim;
00890 else if (proj.Y < percorre->inicio.Y && proj.Y < percorre->fim.Y)
00891 proj = (percorre->inicio.Y < percorre->fim.Y)? percorre->inicio : percorre->fim;
00892
00893
00894 if (posicao.distancia(proj) <=
00895 GROSSURA_PAREDE)
00896 {
00897 parede_selecionada = percorre;
00898 pontaSelecionada = MEIO;
00899 ancora_parede = proj;
00900 return true;
00901 }
00902 }
00903 return false;
00904 }
00905
00906
00907
00908 void MundoQT::novaParede()
00909 {
00910 mutex->lock();
00911 struct NohParede *novaParede = new struct NohParede;
00912
00913 novaParede->inicio = (lastPos - (Vetor<float>(width(),height())/2.0f))/zm + Vetor<float>(offsetx, offsety);
00914 novaParede->fim = (lastPos - (Vetor<float>(width(),height())/2.0f))/zm + Vetor<float>(offsetx, offsety);
00915 novaParede->proximo = nohCabecaParedes.proximo;
00916 nohCabecaParedes.proximo = novaParede;
00917
00918 parede_selecionada = novaParede;
00919 pontaSelecionada = PONTA_FIM;
00920 mutex->unlock();
00921
00922
00923 if (!executando)
00924 repaint();
00925 }
00926
00927
00928
00929 void MundoQT::removerParede()
00930 {
00931 mutex->lock();
00932
00933 for (struct NohParede *percorre = &nohCabecaParedes;
00934 percorre->proximo != NULL;
00935 percorre = percorre->proximo)
00936 if (percorre->proximo == parede_selecionada)
00937 {
00938 struct NohParede *remover = percorre->proximo;
00939 percorre->proximo = percorre->proximo->proximo;
00940 delete remover;
00941 parede_selecionada = NULL;
00942
00943 break;
00944 }
00945 mutex->unlock();
00946
00947
00948 if (!executando)
00949 repaint();
00950 }
00951
00952
00953
00954 void MundoQT::novoGrao()
00955 {
00956
00957 mutex->lock();
00958 inserirGrao((lastPos - (Vetor<float>(width(),height())/2.0f))/zm + Vetor<float>(offsetx, offsety));
00959 mutex->unlock();
00960
00961
00962 if (!executando)
00963 repaint();
00964 }
00965
00966
00967
00968 void MundoQT::removerGrao()
00969 {
00970 removerGraoSelecionado();
00971 }
00972
00973
00974
00975 void MundoQT::salvarBiota()
00976 {
00977 bool was_executando = executando;
00978 if (executando)
00979 MainWindow::getInstance()->startStop();
00980
00981 QString fileName = QFileDialog::getSaveFileName(this, tr("Save Biot"),QDir::homePath(),tr("Biot") + "(*.xml)");
00982
00983 if (!fileName.isNull())
00984 {
00985 FILE *arq;
00986 arq = fopen(fileName.toAscii().data(), "w");
00987
00988 selecionado->biota.salvar(arq);
00989 fclose(arq);
00990 }
00991
00992 if (was_executando)
00993 MainWindow::getInstance()->startStop();
00994 }
00995
00996
00997
00998 void MundoQT::abrirBiota()
00999 {
01000 QString fileName = QFileDialog::getOpenFileName(this, tr("Open Biot"),QDir::homePath(),tr("Biot") + "(*.xml)");
01001
01002 if (fileName.isNull())
01003 return;
01004
01005 FILE *arq;
01006 arq = fopen(fileName.toAscii().data(), "r");
01007
01008 mutex->lock();
01009 Biota biota = Biota((Mundo*)this, ((lastPos-Vetor<float>(width()/2,height()/2))/zm) + Vetor<float>(offsetx, offsety), arq);
01010 inserirBiota(biota);
01011 mutex->unlock();
01012
01013 fclose(arq);
01014
01015
01016 if (!executando)
01017 repaint();
01018 }
01019
01020
01021
01022 void MundoQT::novoBiota()
01023 {
01024 mutex->lock();
01025
01026 Biota biota((Mundo*)this);
01027 biota.estado.posicao = ((lastPos - Vetor<float>(width()/2,height()/2))/zm) + Vetor<float>(offsetx, offsety);
01028
01029 inserirBiota(biota);
01030
01031 mutex->unlock();
01032
01033
01034 if (!executando)
01035 repaint();
01036 }
01037
01038
01039
01040 void MundoQT::removerBiota()
01041 {
01042 mutex->lock();
01043
01044
01045 struct NohBiota *percorre;
01046 for (percorre = &nohCabecaBiotas;
01047 percorre->proximo != selecionado;
01048 percorre = percorre->proximo);
01049
01050
01051 struct NohBiota *remover = percorre->proximo;
01052 percorre->proximo = percorre->proximo->proximo;
01053
01054 selecionado = NULL;
01055
01056 remover->biota.destroy();
01057 delete remover;
01058
01059 estatisticas.numero_biotas--;
01060
01061 mutex->unlock();
01062
01063
01064 if (!executando)
01065 repaint();
01066 }
01067
01068
01069
01070 void MundoQT::mutacaoBiota()
01071 {
01072 mutex->lock();
01073 selecionado->biota.mutacao();
01074 mutex->unlock();
01075
01076
01077 if (!executando)
01078 repaint();
01079 }
01080
01081
01082
01083 void MundoQT::setMenuBiota(QMenu *m)
01084 {
01085 menuBiota = m;
01086 }
01087
01088
01089
01090 void MundoQT::setMenuGrao(QMenu *m)
01091 {
01092 menuGrao = m;
01093 }
01094
01095
01096
01097 void MundoQT::setMenuVoid(QMenu *m)
01098 {
01099 menuVoid = m;
01100 }
01101
01102
01103
01104 void MundoQT::setMenuParede(QMenu *m)
01105 {
01106 menuParede = m;
01107 }
01108
01109
01110
01111 void MundoQT::maisVelho()
01112 {
01113 NohBiota *maximo = NULL;
01114
01115
01116 mutex->lock();
01117 for (struct NohBiota *percorre = nohCabecaBiotas.proximo;
01118 percorre != NULL;
01119 percorre = percorre->proximo)
01120 {
01121 if (maximo == NULL || percorre->biota.estado.idade > maximo->biota.estado.idade)
01122 maximo = percorre;
01123 }
01124 mutex->unlock();
01125
01126 selecionado = maximo;
01127
01128
01129 offsetx = selecionado->biota.estado.posicao.X;
01130 offsety = selecionado->biota.estado.posicao.Y;
01131
01132
01133 emit changeHorizontalBar((int)offsetx);
01134 emit changeVerticalBar((int)offsety);
01135 mudaBarraStatus();
01136 }
01137
01138
01139
01140 void MundoQT::maisEnergia()
01141 {
01142 NohBiota *maximo = NULL;
01143
01144
01145 mutex->lock();
01146 for (struct NohBiota *percorre = nohCabecaBiotas.proximo;
01147 percorre != NULL;
01148 percorre = percorre->proximo)
01149 {
01150 if (maximo == NULL || percorre->biota.estado.energia > maximo->biota.estado.energia)
01151 maximo = percorre;
01152 }
01153 mutex->unlock();
01154
01155 selecionado = maximo;
01156
01157
01158 offsetx = selecionado->biota.estado.posicao.X;
01159 offsety = selecionado->biota.estado.posicao.Y;
01160
01161
01162 emit changeHorizontalBar((int)offsetx);
01163 emit changeVerticalBar((int)offsety);
01164 mudaBarraStatus();
01165 }
01166
01167
01168
01169 void MundoQT::geracaoMaisNova()
01170 {
01171 NohBiota *maximo = NULL;
01172
01173
01174 mutex->lock();
01175 for (struct NohBiota *percorre = nohCabecaBiotas.proximo;
01176 percorre != NULL;
01177 percorre = percorre->proximo)
01178 {
01179 if (maximo == NULL || percorre->biota.estado.geracao > maximo->biota.estado.geracao)
01180 maximo = percorre;
01181 }
01182 mutex->unlock();
01183
01184 selecionado = maximo;
01185
01186
01187 offsetx = selecionado->biota.estado.posicao.X;
01188 offsety = selecionado->biota.estado.posicao.Y;
01189
01190
01191 emit changeHorizontalBar((int)offsetx);
01192 emit changeVerticalBar((int)offsety);
01193 mudaBarraStatus();
01194 }
01195
01196
01197
01198 void MundoQT::geracaoMaisAntiga()
01199 {
01200 NohBiota *maximo = NULL;
01201
01202
01203 mutex->lock();
01204 for (struct NohBiota *percorre = nohCabecaBiotas.proximo;
01205 percorre != NULL;
01206 percorre = percorre->proximo)
01207 {
01208 if (maximo == NULL || percorre->biota.estado.geracao < maximo->biota.estado.geracao)
01209 maximo = percorre;
01210 }
01211 mutex->unlock();
01212
01213 selecionado = maximo;
01214
01215
01216 offsetx = selecionado->biota.estado.posicao.X;
01217 offsety = selecionado->biota.estado.posicao.Y;
01218
01219
01220 emit changeHorizontalBar((int)offsetx);
01221 emit changeVerticalBar((int)offsety);
01222 mudaBarraStatus();
01223 }
01224
01225
01226
01227
01228 void MundoQT::maisFilhos()
01229 {
01230 NohBiota *maximo = NULL;
01231
01232
01233 mutex->lock();
01234 for (struct NohBiota *percorre = nohCabecaBiotas.proximo;
01235 percorre != NULL;
01236 percorre = percorre->proximo)
01237 {
01238 if (maximo == NULL || percorre->biota.estado.filhos > maximo->biota.estado.filhos)
01239 maximo = percorre;
01240 }
01241 mutex->unlock();
01242
01243 selecionado = maximo;
01244
01245
01246 offsetx = selecionado->biota.estado.posicao.X;
01247 offsety = selecionado->biota.estado.posicao.Y;
01248
01249
01250 emit changeHorizontalBar((int)offsetx);
01251 emit changeVerticalBar((int)offsety);
01252 mudaBarraStatus();
01253 }
01254
01255
01256
01257 void MundoQT::abrirSimulacao()
01258 {
01259 QString fileName = QFileDialog::getOpenFileName(this, tr("Open Simulation"),QDir::homePath(),tr("Simulation") + "(*.xml)");
01260
01261 if (fileName.isNull())
01262 return;
01263
01264 FILE *arq;
01265 arq = fopen(fileName.toAscii().data(), "r");
01266
01267 mutex->lock();
01268 Mundo::abrirMundo(arq);
01269 mutex->unlock();
01270
01271 fclose(arq);
01272
01273
01274 if (!executando)
01275 repaint();
01276 }
01277
01278
01279
01280 void MundoQT::salvarSimulacao()
01281 {
01282 QString fileName = QFileDialog::getSaveFileName(this, tr("Save Simulation"),QDir::homePath(),tr("Simulation") + "(*.xml)");
01283
01284 if (fileName.isNull())
01285 return;
01286
01287 FILE *arq;
01288 arq = fopen(fileName.toAscii().data(), "w");
01289
01290 Mundo::salvarMundo(arq);
01291 fclose(arq);
01292 }
01293
01294