void OrganismCellWorld::floodFillOrganism(unsigned int startCell, bool find) { static unsigned int floodId = 0; ++floodId; std::vector<unsigned int> open; std::vector<unsigned int> closed; open.push_back(startCell); unsigned int foundOrganism = 0; while (!open.empty()) { unsigned int index = open.back(); open.pop_back(); closed.push_back(index); auto& cell = cells[index]; cell.lastFlood = floodId; if (!cell.alive) continue; if (find) { // Found an organism if (cell.organism != 0) { // Hadn't found one yet, so store it if (foundOrganism == 0) { foundOrganism = cell.organism; } // Two organisms touching; pick the lower index else if (cell.organism < foundOrganism) { foundOrganism = cell.organism; } } } for (auto neighbor : getNeighborIndices(index)) { if (cells[neighbor].lastFlood == floodId) continue; open.push_back(neighbor); } } // New organism if nothing else was touching (or not trying to find an organism) if (foundOrganism == 0) { foundOrganism = nextOrgIndex; ++nextOrgIndex; } // Set the organism index of everything touching for (auto& index : closed) { cells[index].organism = foundOrganism; } }
Real BilinearInterpolation::sample(Real xcoord, Real ycoord) { // first find 4 neighboring points int lx = 0; // index of x coordinate of adjacent grid point to left of P int ux = 0; // index of x coordinate of adjacent grid point to right of P getNeighborIndices(_xAxis, xcoord, lx, ux); int ly = 0; // index of y coordinate of adjacent grid point below P int uy = 0; // index of y coordinate of adjacent grid point above P getNeighborIndices(_yAxis, ycoord, ly, uy); Real fQ11 = _zSurface(ly, lx); Real fQ21 = _zSurface(ly, ux); Real fQ12 = _zSurface(uy, lx); Real fQ22 = _zSurface(uy, ux); // if point exactly found on a node do not interpolate if ((lx == ux) && (ly == uy)) return fQ11; Real x = xcoord; Real y = ycoord; Real x1 = _xAxis[lx]; Real x2 = _xAxis[ux]; Real y1 = _yAxis[ly]; Real y2 = _yAxis[uy]; // if xcoord lies exactly on an xAxis node do linear interpolation if (lx == ux) return fQ11 + (fQ12 - fQ11) * (y - y1) / (y2 - y1); // if ycoord lies exactly on an yAxis node do linear interpolation if (ly == uy) return fQ11 + (fQ21 - fQ11) * (x - x1) / (x2 - x1); Real fxy = fQ11 * (x2 - x) * (y2 - y); fxy += fQ21 * (x - x1) * (y2 - y); fxy += fQ12 * (x2 - x) * (y - y1); fxy += fQ22 * (x - x1) * (y - y1); fxy /= ((x2 - x1) * (y2 - y1)); return fxy; }
void ContourTree::compute_ST(){ uint N = 1; for (uint i=0; i<dimension; ++i) N = N*size[i]; std::vector<uint> neighborIndices; std::vector<uint>::iterator neighborIndices_it; std::set<uint> mergingRegions; std::set<uint>::iterator mergingRegions_it; Leader* tmpLeader; Vertex* tmpVertex; Leader* deleteLeader; std::vector<Vertex*>::iterator vertex_it; for (uint i = 0; i < N; ++i) { getNeighborIndices(&neighborIndices, indices[i], size, dimension); for (neighborIndices_it = neighborIndices.begin(); neighborIndices_it != neighborIndices.end(); ++neighborIndices_it) if (elements[*neighborIndices_it]->ST_root) mergingRegions.insert(elements[*neighborIndices_it]->ST_root->leader->index); if (mergingRegions.size() == 1) { elements[*mergingRegions.begin()]->ST_parent = indices[i]; elements[indices[i]]->ST_root = elements[*mergingRegions.begin()]->ST_root; elements[*mergingRegions.begin()]->ST_root->leader->index = indices[i]; } else if ( mergingRegions.empty() ) { tmpLeader = new Leader; tmpVertex = new Vertex; tmpLeader->index = indices[i]; tmpVertex->leader = tmpLeader; tmpVertex->index = indices[i]; tmpVertex->childrenCount = 0; tmpLeader->vertices.push_back(tmpVertex); elements[indices[i]]->ST_root = tmpVertex; ST.push_back(tmpVertex); }else { tmpLeader = new Leader; tmpVertex = new Vertex; tmpLeader->index = indices[i]; tmpVertex->leader = tmpLeader; tmpVertex->index = indices[i]; tmpVertex->childrenCount = 0; tmpLeader->vertices.push_back(tmpVertex); elements[indices[i]]->ST_root = tmpVertex; tmpVertex->toVertex = NULL; ST.push_back(tmpVertex); for (mergingRegions_it = mergingRegions.begin(); mergingRegions_it != mergingRegions.end(); ++mergingRegions_it) { elements[*mergingRegions_it]->ST_parent = indices[i]; tmpVertex->childrenVertices.push_back(elements[*mergingRegions_it]->ST_root); (tmpVertex->childrenCount)++; deleteLeader = elements[*mergingRegions_it]->ST_root->leader; tmpLeader->vertices.insert(tmpLeader->vertices.end(),deleteLeader->vertices.begin(),deleteLeader->vertices.end() ); for (vertex_it = deleteLeader->vertices.begin(); vertex_it != deleteLeader->vertices.end(); ++vertex_it) (*vertex_it)->leader = tmpLeader; delete deleteLeader; elements[*mergingRegions_it]->ST_root->toVertex = elements[indices[i]]->ST_root; } } mergingRegions.clear(); neighborIndices.clear(); } }
void OrganismCellWorld::redistributeCells() { size_t indexPosCur = indexFromPos(static_cast<int>(posCursor.x), static_cast<int>(posCursor.y)); if (cells[indexPosCur].organism != 0) { playerOrganism = cells[indexPosCur].organism; } for (auto& cell : cells) { cell.attached = cell.organism == playerOrganism; } std::map<unsigned, std::vector<size_t>> born; std::map<unsigned, std::vector<size_t>> died; std::vector<size_t> changed; std::set<unsigned> organisms; for (size_t i = 0; i < cells.size(); ++i) { auto& cell = cells[i]; if (cell.nextAlive && !cell.alive) { born[cell.organism].push_back(i); organisms.insert(cell.organism); } else if (!cell.nextAlive && cell.alive) { died[cell.organism].push_back(i); organisms.insert(cell.organism); } } // DEBUG ADD/REMOVE FOOD if (engine->inputManager.getIntValue(4) > 0) toAdd += 100; else if (engine->inputManager.getIntValue(4) < 0) toRemove += 100; // Accumulate number of dead cells toRemove += decay; for (auto organism : organisms) { auto& orgBorn = born[organism]; auto& orgDied = died[organism]; // Shuffle the list of cells that died/were born std::random_shuffle(orgBorn.begin(), orgBorn.end()); std::random_shuffle(orgDied.begin(), orgDied.end()); auto bornIter = orgBorn.begin(); auto diedIter = orgDied.begin(); if (organism == playerOrganism) { // If we've accumulated enough decay, kill off some cells permanently while (toRemove > 1.f && diedIter != orgDied.end()) { cells[*diedIter].alive = false; changed.push_back(*diedIter); ++diedIter; toRemove -= 1.f; } // If we have cells to add then do so while (toAdd > 0 && bornIter != orgBorn.end()) { cells[*bornIter].alive = true; changed.push_back(*bornIter); ++bornIter; toAdd -= 1; } } else { // Kill cells randomly unsigned killRandom = rand() % 8; for (unsigned i = 0; i < killRandom && diedIter != orgDied.end(); ++i) { cells[*diedIter].alive = false; changed.push_back(*diedIter); ++diedIter; } } // Redistribute dead cells into born cells while (bornIter != orgBorn.end() && diedIter != orgDied.end()) { cells[*bornIter].alive = true; cells[*diedIter].alive = false; changed.push_back(*bornIter); changed.push_back(*diedIter); ++bornIter; ++diedIter; } } std::random_shuffle(changed.begin(), changed.end()); for (auto& index : changed) { cells[index].organism = 0; for (auto neighbor : getNeighborIndices(index)) { cells[neighbor].organism = 0; } } for (auto it = changed.begin(); it != changed.end(); ++it) { auto index = *it; auto& cell = cells[index]; // Newly-created; find nearby organisms if (cell.alive) { if (cell.organism == 0) floodFillOrganism(index, true); } // Newly-destroyed; neighbors may have split into new organisms else { for (auto neighborIndex : getNeighborIndices(index)) { auto& neighbor = cells[neighborIndex]; if (neighbor.alive && neighbor.organism == 0) floodFillOrganism(neighborIndex, false); } } } aliveCount = 0; for (auto& cell : cells) { if (cell.alive && cell.attached) ++aliveCount; } }