PatchMap<1>* Cartographer::buildAdjacencyMap(const UnitType *uType, const Vec2i &pos, CardinalDir facing, Field f, int size) { PF_TRACE(); const Vec2i mapPos = pos + (OrdinalOffsets[odNorthWest] * size); const int sx = pos.x; const int sy = pos.y; Rectangle rect(mapPos.x, mapPos.y, uType->getSize() + 2 + size, uType->getSize() + 2 + size); PatchMap<1> *pMap = new PatchMap<1>(rect, 0); pMap->zeroMap(); PatchMap<1> tmpMap(rect, 0); tmpMap.zeroMap(); // mark cells occupied by unitType at pos (on tmpMap) Util::RectIterator rIter(pos, pos + Vec2i(uType->getSize() - 1)); while (rIter.more()) { Vec2i gpos = rIter.next(); if (!uType->hasCellMap() || uType->getCellMapCell(gpos.x - sx, gpos.y - sy, facing)) { tmpMap.setInfluence(gpos, 1); } } // mark goal cells on result map rIter = Util::RectIterator(mapPos, pos + Vec2i(uType->getSize())); while (rIter.more()) { Vec2i gpos = rIter.next(); if (tmpMap.getInfluence(gpos) || !masterMap->canOccupy(gpos, size, f)) { continue; // building or obstacle } Util::PerimeterIterator pIter(gpos - Vec2i(1), gpos + Vec2i(size)); while (pIter.more()) { if (tmpMap.getInfluence(pIter.next())) { pMap->setInfluence(gpos, 1); break; } } } return pMap; }
//---------------------------------------------------------------------------- unsigned int LayMap::search(int x,int y,layerType layer) // // Method of searching is very simple : this function is called recursively // for all still not visited points in the vicinity of (x,y),or other points // in universal feed or tries to change layer if there's a via. If all these // possibilities are already checked it returns 0. { unsigned int net; layoutMapType *m=&map[x-xMin][y-yMin]; if (m->visited & layer) // we've already been here ! return 0; if ( m->termNo ) switch (layer) { case DiffusionLayer: case PolyLayer: if (!(m->layers & Metal1Layer)&& !(m->layers & Metal2Layer)) return m->termNo; break; case Metal1Layer: if (!(m->layers & Metal2Layer)) return m->termNo; break; case Metal2Layer: return m->termNo; } m->visited |= layer; // mark that place // visiting points belonging to the same layer : if(layer != PolyLayer) // restricted feeds && metal segments { // we have only to check this neighbors // which have connection with our on // the same layer if(m->leftWay & layer && x > xMin) if ( net = search(x-1,y,layer) ) return net; if(m->upWay & layer && y < yMax) if ( net = search(x,y+1,layer) ) return net; if(m->rightWay & layer && x < xMax) if ( net = search(x+1,y,layer) ) return net; if(m->downWay & layer && y > yMin) if ( net = search(x,y-1,layer) ) return net; } else // for universal feed we have to // go to visit all of the points from the // list { ListIterator rIter( (List&)(*imageMap)[m->uniNo] ); int a = x / imageMap->cols , b = y / imageMap->rows; if (x<0) a--; if (y<0) b--; a*=imageMap->cols; b*=imageMap->rows; // now we have coordinates of left-bottom point // in cluster for(;(Item&)rIter != NOITEM;rIter++) { Point &p = (Point&)(Item&)rIter; if ( (x!= a+p.x || y!= b+p.y) && (net = search(a+p.x,b+p.y,layer))>0 ) return net; } } // if all points on this layer visited lets try go to the other if(m->layers & ViaLayer) // normal via exists if ( (layer & Metal1Layer) || (layer & Metal2Layer) ) { if( net = search(x,y,(m->layers & PolyLayer)>0 ? PolyLayer : DiffusionLayer)) return net; } else { if( net = search(x,y,(m->layers & Metal1Layer) ? Metal1Layer : Metal2Layer)) return net; } if((m->layers & MetalsViaLayer)>0) // via between two metals if ( (layer & Metal1Layer)>0 ) { if( net = search(x,y,Metal2Layer)) return net; } else { if( net = search(x,y,Metal1Layer)) return net; } // we cannot go further - must return return 0; }// LayMap::search //