/// <summary> /// Производит обновление соседей для всех учреждений, которые связаны /// с дорогой <paramref name="roadWithNeighbours"/>. /// Если у учерждений есть общая дорога, то значит они «соседствуют». Данная функция проверяет /// уже существующих соседей у всех учреждений дороги. /// Если у какого-либо учреждения еще нет соседей, то новая постройка сразу добавляется в качестве соседа. /// Если же соседи уже существуют, то сначала проверяется, находится ли сосед на той же дороге, что и /// новая постройка. Если нет, то постройка также добавляется в качестве соседа. /// Если существующие соседи находятся на той же дороге, что и новая постройка, то /// в таком случае проверяется местоположение новой постройки относительно постройки, у которой проверяем /// соседей, а также каждого из соседей. Если новая постройка находится «между» этими двумя объектами, то /// считаем, что уже существующий сосед перестал быть таковым, удаляем его из списка, и добавляем вместо него /// нашу новую постройку. /// </summary> /// <param name="roadWithNeighbours">Объект дороги, которая связана с <paramref name="newInstitution"/>, и /// у существующих учреждений на которой необходимо обновить соседей.</param> /// <param name="newInstitution">Новая постройка, одной из дорог /// которой является <paramref name="roadWithNeighbours"/></param> /// <param name="intersectPoint">Точка пересечения дороги <paramref name="roadWithNeighbours"/> с некой /// другой дорогой, вследствие чего был создан <paramref name="newInstitution"/></param> private void UpdateNeighbours(Road roadWithNeighbours, Institution newInstitution, Point2D intersectPoint) { // Если на данной дороге еще не было никаких учреждений, то необходимо инициализировать для неё их список. if (!_roadInstitutions.ContainsKey(roadWithNeighbours)) { _roadInstitutions[roadWithNeighbours] = new List <Institution>(); } foreach (Institution existedInstitution in _roadInstitutions[roadWithNeighbours]) { // Если у какой-либо из построек на дороге еще нет соседей, то можно сразу добавлять туда нашу новую. if (existedInstitution.Neighbours.Count == 0) { existedInstitution.AddNeighbour(newInstitution); newInstitution.AddNeighbour(existedInstitution); continue; } bool neighbourOnSameLineExists = false; // Так как функции ReplaceNeighbour и AddNeighbour меняют содержимое Neighbours, то // «ходим» по копии этого объекта. foreach (Institution neighbour in existedInstitution.Neighbours.ToList()) { // Игнорируем тех «соседей», которые находятся на другой дороге, и которые никак не мешают нам. if (neighbour.FirstRoad != roadWithNeighbours && neighbour.SecondRoad != roadWithNeighbours) { continue; } neighbourOnSameLineExists = true; // Если наша новая постройка находится между некой постройкой и её соседом (на одной дороге), то // значит мы «разорвали» соседство, и теперь сами являемся соседом той постройки. if (intersectPoint.IsBetweenTwoPointsOnSameLine(existedInstitution.Location, neighbour.Location)) { existedInstitution.ReplaceNeighbour(neighbour, newInstitution); newInstitution.AddNeighbour(existedInstitution); break; } } // Если нет никаких построек между нашей новой постройкой и той, которую обрабатываем в цикле foreach, // то считаем нас её соседом. if (!neighbourOnSameLineExists) { existedInstitution.AddNeighbour(newInstitution); newInstitution.AddNeighbour(existedInstitution); } } _roadInstitutions[roadWithNeighbours].Add(newInstitution); }