// PRE: coord_en_pixeles=false si se pasan posiciones en tiles. POST: camino posee pares de posiciones EN TILES que debe recorrer secuencialmente. Camino Calculador::obtenerCaminoMin(Escenario *esc, Coordenada coord_orig, Coordenada coord_dest, Coordenada coord_ceros, bool coord_en_pixeles) { Camino camino; Coordenada pos_tile_inicial, pos_tile_destino; try { if (coord_en_pixeles) { pos_tile_inicial = tileParaPixel(coord_orig, coord_ceros); pos_tile_destino = tileParaPixel(coord_dest, coord_ceros); } else { pos_tile_inicial = coord_orig; pos_tile_destino = coord_dest; } //if ((!esc->tileEsOcupable(pos_tile_destino)) || (pos_tile_inicial == pos_tile_destino)) if ((pos_tile_inicial == pos_tile_destino) || ((!esc->tileEsOcupable(pos_tile_destino)) && distEuclidiana(pos_tile_inicial, pos_tile_destino) < 2)) return camino; } catch ( FueraDeEscenario &e ) { return camino; } std::vector<Nodo*> visitados, vecinos; Nodo *tile_inicial = new Nodo(pos_tile_inicial, NULL, pos_tile_destino); Nodo nodoFinal; vecinos.push_back(tile_inicial); std::vector<Nodo*>::iterator it, pActualIt; Nodo *pActual; try { while (!vecinos.empty()) { bool encontrado = false; Coordenada c; pActualIt = vecinos.begin(); pActual = (*pActualIt); for (c.y = pActual->pos.y-1; c.y <= pActual->pos.y+1; c.y++) { for (c.x = pActual->pos.x-1; c.x <= pActual->pos.x+1; c.x++) { if ( (!pActual->padre || !pActual->padre->esTile(c)) && (!pActual->esTile(c)) ) { if (c == pos_tile_destino) { Nodo nodoAux(c, pActual, pos_tile_destino); if ((!encontrado) || nodoAux.f() < nodoFinal.f()) nodoFinal = nodoAux; encontrado = true; } else if (esc->tileEsOcupable(c) && std::find_if(visitados.begin(), visitados.end(), Nodo::CmpPointerXY(c)) == visitados.end()) { it = std::find_if(vecinos.begin(), vecinos.end(), Nodo::CmpPointerXY(c)); if (it == vecinos.end()) { std::vector<Nodo*>::iterator itV = std::lower_bound(vecinos.begin(), vecinos.end(), Nodo(c, pActual, pos_tile_destino), Nodo::CmpNodoVsPointerF()); vecinos.insert(itV, new Nodo(c, pActual, pos_tile_destino)); } else if ((*it)->guardarMenorG(pActual)) { Nodo *ppVecino = *it; vecinos.erase(it); it = std::lower_bound(vecinos.begin(), vecinos.end(), ppVecino, Nodo::CmpPointersF()); vecinos.insert(it, ppVecino); } } } } } if (encontrado) { pActual = nodoFinal.padre; throw DestinoEncontrado(); } visitados.push_back(pActual); pActualIt = std::find_if(vecinos.begin(), vecinos.end(), Nodo::CmpPointerXY(pActual->pos)); vecinos.erase(pActualIt); } } catch ( DestinoEncontrado &e ) { // pActual tiene ahora el último tile del camino, NO el destino. while (!pActual->esTile(tile_inicial)) { camino.agregar( pActual->pos ); pActual = pActual->padre; } camino.invertir(); if (esc->tileEsOcupable(pos_tile_destino)) camino.agregar( pos_tile_destino ); // Nuevo: En el caso de que se pueda hacer el camino entero hasta el lugar anterior porque el destino está ocupado, lo hará. } for (pActualIt = visitados.begin(); pActualIt < visitados.end(); ++pActualIt) delete *pActualIt; for (pActualIt = vecinos.begin(); pActualIt < vecinos.end(); ++pActualIt) delete *pActualIt; visitados.clear(); vecinos.clear(); return camino; }
bool operator()(const Nodo* l, const Nodo r) { return (l->f() < r.f()); }
bool operator()(const Nodo l, const Nodo* r) { return (l.f() < r->f()); }
bool operator< (const Nodo & r) const { return (this->f() < r.f()); }