/* @method DistanceList @discussion Allocate storage for an n-unit unitList. @throws KII_bad_alloc */ DistanceList::DistanceList(const FLOAT xlocs[], const FLOAT ylocs[], const VectorMatrix& radii) : unitList(NULL), numUnits(radii.Size()), numOverlap(0) { // Since this is a symmetric array, there's no need to store // information for unit n (all that information is already in the // lists for units 1..n-1 if ((unitList = new ListItem[numUnits-1]) == NULL) throw KII_bad_alloc("Failed allocating memory for DistanceList."); // Fill the lists. For unit i, we need only store information for // connections to units i+1..n, as earlier units already have the // information for their connections with i. FLOAT tempDist, tempDist2, tempDelta, deltaX, deltaY; for (int u1=0; u1<numUnits-1; u1++) { unitList[u1].radius = radii[u1]; for (int u2=u1+1; u2<numUnits; u2++) { deltaX = xlocs[u1]-xlocs[u2]; deltaY = ylocs[u1]-ylocs[u2]; tempDist2 = deltaX*deltaX + deltaY*deltaY; tempDist = sqrt(tempDist2); tempDelta = tempDist - (radii[u1]+radii[u2]); if (tempDelta < 0.0) { unitList[u1].overlapping.push_back(SublistItem(u2, radii[u2], tempDist, tempDist2, tempDelta)); numOverlap++; } else { unitList[u1].nonOverlapping.push_back(SublistItem(u2, radii[u2], tempDist, tempDist2, tempDelta)); } } } }
/* @method Update @discussion Update the DistanceList information based on the given new radii. @param radii unit connectivity radii must have same number of elements as numUnits @throws KII_invalid_argument */ void DistanceList::Update(const VectorMatrix& radii) { if (radii.Size() != numUnits) throw KII_invalid_argument("Wrong number of elements in radii for distance update."); #ifdef DEBUG2 cerr << "Updating DistanceList with radii " << radii << endl; #endif FLOAT tempDelta; SublistItem tempItem; list<SublistItem>::iterator u2iter; // Iterate through all units for (int u1=0; u1<numUnits-1; u1++) { #ifdef DEBUG2 cerr << u1 << ", "; #endif // Update unit connection radius unitList[u1].radius = radii[u1]; // Iterate over all overlapping and non-overlapping other units // First, overlapping: u2iter = unitList[u1].overlapping.begin(); while (u2iter != unitList[u1].overlapping.end()) { // Compute and update other unit's information u2iter->radius = radii[u2iter->otherUnit]; tempDelta = u2iter->dist - (unitList[u1].radius+u2iter->radius); u2iter->Delta = tempDelta; // Move it if non-overlapping, if necessary (Delta>=0). If the // move occurs, the iterator will point to the next item. If // not, then the iterator must be advanced explicitly. if (tempDelta >= 0) { tempItem = *u2iter; u2iter = unitList[u1].overlapping.erase(u2iter); unitList[u1].nonOverlapping.push_back(tempItem); numOverlap--; } else u2iter++; } // Then, non-overlapping: u2iter = unitList[u1].nonOverlapping.begin(); while (u2iter != unitList[u1].nonOverlapping.end()) { // Compute and update other unit's information u2iter->radius = radii[u2iter->otherUnit]; tempDelta = u2iter->dist - (unitList[u1].radius+u2iter->radius); u2iter->Delta = tempDelta; // Move it if overlapping, if necessary (Delta<0). If the // move occurs, the iterator will point to the next item. If // not, then the iterator must be advanced explicitly. if (tempDelta < 0) { tempItem = *u2iter; u2iter = unitList[u1].nonOverlapping.erase(u2iter); unitList[u1].overlapping.push_back(tempItem); numOverlap++; #ifdef DLDEBUG cerr << "\tDL::Update(): overlap of " << u1 << " and " << tempItem.otherUnit << " with radii " << unitList[u1].radius << " and " << tempItem.radius << ", respectively" << endl; #endif } else u2iter++; } } // end for (int u1-0; ...) #ifdef DEBUG2 cerr << "done." << endl;; #endif }