private void ChainDeeper(Node firstNode, Node secondNode) { ElementsChain chain = new ElementsChain(); chain.AddNode(firstNode); // Добавляем текущую ноду в цепь chain.AddNode(secondNode); // Добавляем предыдущую ноду в цепь Node currentNode = secondNode; Node prevNode = firstNode; while (currentNode.Connections.Count < 3) { if (currentNode.Connections.Count < 2) // Тупик { return; } Node nextNode = currentNode.Connections.Keys.FirstOrDefault(i => i != prevNode); prevNode = currentNode; // Переходим на следующую currentNode = nextNode; chain.AddNode(currentNode); // Записываем ноду в цепь } if (Chains.FirstOrDefault(i => i.Nodes.First() == chain.Nodes.Last() && i.Nodes.Last() == chain.Nodes.First()) == null) // Проверка на существующий путь { Chains.Add(chain); // Добавляем цепь в список цепей } }
public int SameDirected(ElementsChain chain) { var left = Nodes.Skip(1).TakeWhile(i => i != chain.Nodes.First()).ToArray(); var right = Nodes.Skip(left.Length + 1).ToArray(); var rotated = right.Concat(left).ToArray(); return(rotated[1] == chain.Nodes[1] ? 1 : rotated.Last() == chain.Nodes[1] ? -1 : 0); }
public void Update() { ResetNodesState(); // Сброс состояния нод, присвоение им номеров foreach (Connector connector in Connectors) { if (connector.NodeA.Connections.Count == 1 && connector.NodeB.Connections.Count > 1 || connector.NodeA.Connections.Count > 1 && connector.NodeB.Connections.Count == 1) { throw new WrongSchemeException("Unconnected pin found!"); } } ContoursSearch(); // Получаем список замкнутых контуров if (Contours.Count < 1) { return; } if (Contours.Count == 1) { if (Contours.First().Connectors.Count(i => i is Battery) != 1) { throw new WrongSchemeException("Check layout! Wrong batteries amount!"); } Battery bat = Contours.First().Connectors.First(i => i is Battery) as Battery; ElementsChain batChain = new ElementsChain(new Node[] { bat.NodeA, bat.NodeB }); double amp = bat.Eds / Contours.First().Connectors.Sum(i => i.Resistance) * Contours.First().SameDirected(batChain); Contours.First().RunElectricCurrent(amp); return; } ChainsSerach(); // Получаем список цепей UpdateChainNumbers(); Rule1Count = Nodes.Count(i => i.Connections.Count > 2) - 1; // Количество уравнений по первому правилу int matrixSize = Chains.Count; // Размер матрицы (количество неизвестных) CountMatrix = new double[matrixSize, matrixSize]; // Матрица для левой части уравнений resultVector = new double[matrixSize]; // Вектор для правой части уравнений for (int i = 0; i < matrixSize; i++) // Уравнение { for (int j = 0; j < matrixSize; j++) // Неизвестная { if (i < Rule1Count) // Первое правило { Node curNode = Nodes // Следующая по списку нода с >2 ног .Where(nd => nd.Connections.Count > 2) .ElementAt(i); CountMatrix[i, j] = Chains[j].GetCurrentDirection(curNode); } else // Второе правило { // Если контур включает в себя хотябы один коннектор из цепочки, то он включает в себя всю цепочку if (Contours[i - Rule1Count].Connectors.Contains(Chains[j].Connectors.First())) { CountMatrix[i, j] = Chains[j].GetResistance() * Contours[i - Rule1Count].SameDirected(Chains[j]); } } } resultVector[i] = i < Rule1Count ? 0 : Contours[i - Rule1Count].GetEds(); // Результирующий вектор (0 или сумма ЭДС) } KramerCounter kc = new KramerCounter(CountMatrix, resultVector); // Крамер double[] xv = kc.Answer; for (int i = 0; i < xv.Length; i++) { Chains[i].RunElectricCurrent(-xv[i]); } Fire("Quations", "DisplayMatrix"); }