public ComponentLinear(ComponentNode start, ComponentNode end, RodModel model) : base() { node1 = start; node2 = end; state = ComponentState.csNormal; Model = model; Section = Model.CrossSections[0]; }
public void RecoursiveMove(List <ComponentNode> nodes, ComponentNode src, ComponentNode tgt, float dx, float dy) { int srci = nodes.IndexOf(src); int tgti = nodes.IndexOf(tgt); // Теперь пробуем изменить расстояние между src и tgt // Изменим координату tgt float newx, newy; if (dx == float.MaxValue) { newx = tgt.Location.X; } else { newx = src.Location.X + dx; } if (dy == float.MaxValue) { newy = tgt.Location.Y; } else { newy = src.Location.Y + dy; } tgt.MoveTo(new IssoPoint2D() { X = newx, Y = newy }); // Теперь пересчитаем координаты всех точек, связаных с tgt for (int x = 0; x < nodes.Count; x++) { float sdx = ndX[tgti, x]; float sdy = ndY[tgti, x]; if (sdx == float.MaxValue) { sdx = nodes[x].Location.X - tgt.Location.X; } if (sdy == float.MaxValue) { sdy = nodes[x].Location.Y - tgt.Location.Y; } if ((x != tgti) && (x != srci)) { if ((nodes[x].Location.X - tgt.Location.X == sdx) && (nodes[x].Location.Y - tgt.Location.Y == sdy)) { continue; } else { RecoursiveMove(nodes, tgt, nodes[x], sdx, sdy); } } } }
public ComponentLinear SplitAt(IssoPoint2D pt) { ComponentNode node = new ComponentNode(pt); ComponentLinear lin = new ComponentLinear(node, node2, Model); node2 = node; return(lin); }
public ComponentLoad(ComponentTypes LoadType, float value, ComponentNode node) { Type = LoadType; this.node = node; Value = value; Direction = 90; isOrthogonal = false; isReverse = false; }
public IssoBinding(IssoBindingType t, ComponentNode source, ComponentNode target, float dist) { Type = t; this.source = source; this.target = target; Value = dist; LinePlace = new IssoPoint2D() { X = source.Location.X, Y = source.Location.Y }; }
public void Block(ComponentNode n) { int i = getNodeIndex(n) * 3; bool X = n.DisallowedDisplacements.Contains(NodeDisplacement.X); bool Y = n.DisallowedDisplacements.Contains(NodeDisplacement.Y); bool R = n.DisallowedDisplacements.Contains(NodeDisplacement.Rotation); for (int row = 0; row < Nodes.Count * 3; row++) { if (X) { GlobalMatrix[row, i] = 0; } if (Y) { GlobalMatrix[row, i + 1] = 0; } if (R) { GlobalMatrix[row, i + 2] = 0; } } for (int col = 0; col < Nodes.Count * 3; col++) { if (X) { GlobalMatrix[i, col] = 0; } if (Y) { GlobalMatrix[i + 1, col] = 0; } if (R) { GlobalMatrix[i + 2, col] = 0; } } if (X) { GlobalMatrix[i, i] = 1; } if (Y) { GlobalMatrix[i + 1, i + 1] = 1; } if (R) { GlobalMatrix[i + 2, i + 2] = 1; } }
internal ComponentNode UpdateNodeLocation(ComponentNode FixedNode) { ComponentNode node; if (Source == FixedNode) { node = Target; } else { node = Source; } float x = node.Location.X; float y = node.Location.Y; switch (Type) { case IssoBindingType.Horizontal: { node.MoveTo(new IssoPoint2D() { X = FixedNode.Location.X + DimSign * Size, Y = node.Location.Y }); break; } case IssoBindingType.Vertical: { node.MoveTo(new IssoPoint2D() { X = node.Location.X, Y = FixedNode.Location.Y + DimSign * Size }); break; } } if ((node.Location.X != x) || (node.Location.Y != y)) { return(node); } else { return(null); } }
internal bool NodeSingle(ComponentNode n2) { int cnt = 0; for (int i = 0; i < CompsList.Count; i++) { if (CompsList[i].CompType == ComponentTypes.ctLinear) { ComponentLinear l = (ComponentLinear)CompsList[i]; if ((l.StartNode == n2) || (l.EndNode == n2)) { cnt++; } } } return(cnt == 1); }
private List <IssoBinding> FindBindings(ComponentNode node, IssoBinding Except) { List <IssoBinding> result = new List <IssoBinding>(); for (int i = 0; i < CompsList.Count; i++) { if ((Except != CompsList[i]) && (CompsList[i].CompType == ComponentTypes.ctBinding)) { IssoBinding b = (IssoBinding)CompsList[i]; if ((node == b.Source) || (node == b.Target)) { result.Add(b); } } } return(result); }
public void Load(Stream stream, ObservableCollection <ComponentBasic> DestinationList) { XmlDocument doc = new XmlDocument(); stream.Seek(0, SeekOrigin.Begin); doc.Load(stream); DestinationList.Clear(); for (int i = 0; i < doc.DocumentElement.ChildNodes.Count; i++) { XmlNode n = doc.DocumentElement.ChildNodes[i]; if (n.Name == "x:Nodes") { for (int j = 0; j < n.ChildNodes.Count; j++) { XmlNode node = n.ChildNodes[j]; float x = float.Parse(GetAttrValue(node.Attributes["x:X"], "0")); float y = float.Parse(GetAttrValue(node.Attributes["x:Y"], "0")); bool dx = bool.Parse(GetAttrValue(node.Attributes["x:DX"], "false")); bool dy = bool.Parse(GetAttrValue(node.Attributes["x:DY"], "false")); bool r = bool.Parse(GetAttrValue(node.Attributes["x:Rotation"], "false")); ComponentNode cn = new ComponentNode(new IssoPoint2D() { X = x, Y = y }); if (dx) { cn.DisallowedDisplacements.Add(NodeDisplacement.X); } if (dy) { cn.DisallowedDisplacements.Add(NodeDisplacement.Y); } if (r) { cn.DisallowedDisplacements.Add(NodeDisplacement.Rotation); } DestinationList.Add(cn); } } List <ComponentNode> modelNodes = ModelNodes2(DestinationList); if (n.Name == "x:Beams") { for (int j = 0; j < n.ChildNodes.Count; j++) { XmlNode beam = n.ChildNodes[j]; int sn = int.Parse(GetAttrValue(beam.Attributes["x:StartNode"], "0")); int en = int.Parse(GetAttrValue(beam.Attributes["x:EndNode"], "0")); ComponentLinear cl = new ComponentLinear(modelNodes[sn], modelNodes[en], this); DestinationList.Add(cl); } } if (n.Name == "x:Forces") { for (int j = 0; j < n.ChildNodes.Count; j++) { XmlNode force = n.ChildNodes[j]; int ni = int.Parse(GetAttrValue(force.Attributes["x:Node"], "0")); float d = float.Parse(GetAttrValue(force.Attributes["x:Direction"], "0")); float v = float.Parse(GetAttrValue(force.Attributes["x:Value"], "0")); ComponentLoad cl = new ComponentLoad(ComponentTypes.ctForce, v, modelNodes[ni]); cl.Direction = d; DestinationList.Add(cl); } } List <ComponentLinear> modelBeams = ModelBeams2(DestinationList); if (n.Name == "x:DistributedLoads") { for (int j = 0; j < n.ChildNodes.Count; j++) { XmlNode load = n.ChildNodes[j]; int li = int.Parse(GetAttrValue(load.Attributes["x:Beam"], "0")); float d = float.Parse(GetAttrValue(load.Attributes["x:Direction"], "0")); float v = float.Parse(GetAttrValue(load.Attributes["x:Value"], "0")); ComponentLoad cl = new ComponentLoad(ComponentTypes.ctDistributedLoad, v, modelBeams[li]); cl.Direction = d; DestinationList.Add(cl); } } } }
internal void CalculateStatic() { // Статический расчёт! // 0. Разбиваем модель на элементы: // Незагруженные распределённой нагрузкой стержни берём целиком, // в противном случае - делим стержень на несколько элементов // 1. Создаём список узлов Nodes.Clear(); for (int i = 0; i < CompsList.Count; i++) { if (CompsList[i].CompType == ComponentTypes.ctNode) { Nodes.Add((ComponentNode)CompsList[i]); } } // В соответствии с количеством узлов создаём матрицу жёсткости системы и заполняем её нулями // Для каждого узла - три возможных перемещения // 0 - горизонтальное // 1 - вертикальное // 2 - поворот GlobalMatrix = new double[Nodes.Count * 3, Nodes.Count * 3]; for (int i = 0; i < Nodes.Count; i++) { for (int j = 0; j < Nodes.Count; j++) { GlobalMatrix[i, j] = 0; } } // 2. Создаём балочные элементы и заполняем глобальную матрицу Rods.Clear(); for (int i = 0; i < CompsList.Count; i++) { if (CompsList[i].CompType == ComponentTypes.ctLinear) { ComponentNode n1 = ((ComponentLinear)CompsList[i]).StartNode; ComponentNode n2 = ((ComponentLinear)CompsList[i]).EndNode; int n1i = getNodeIndex(n1); int n2i = getNodeIndex(n2); ElementBeam b = new ElementBeam((ComponentLinear)CompsList[i], this); Rods.Add(b); // Встраиваем матрицу жёсткости элемента в глобальную матрицу жёсткости for (int row = 0; row < 6; row++) { for (int col = 0; col < 6; col++) { int r, c; if (row < 3) { r = n1i * 3 + row; } else { r = n2i * 3 + row - 3; } if (col < 3) { c = n1i * 3 + col; } else { c = n2i * 3 + col - 3; } GlobalMatrix[r, c] += b.ExtMatrix[row, col]; } } } } // 3. Создаём вектор узловых сил. Loads = new double[Nodes.Count * 3]; for (int i = 0; i < Loads.Length; i++) { Loads[i] = 0; } for (int i = 0; i < CompsList.Count; i++) { if (CompsList[i].CompType == ComponentTypes.ctForce) { ComponentLoad load = (ComponentLoad)CompsList[i]; ComponentNode n = load.AppNodes[0]; // Сила приложена к узлу, её нужно разложить на // две составляющие в глобальной системе координат // - горизонтальную и вертикальную // Поскольку в одном узле может быть несколько сил - // складываем их double force = load.Value; double cosa = Math.Cos(load.Direction / 180 * Math.PI); double sina = Math.Sin(load.Direction / 180 * Math.PI); double forceX = force * cosa; double forceY = force * sina; int ind = getNodeIndex(n) * 3; // При этом, если в узле есть связь, запрещающая перемещения по указанному направлению, то // соответствующую часть силы обнуляем if (ind > -1) { // Сила по X if (!n.DisallowedDisplacements.Contains(NodeDisplacement.X)) { Loads[ind] += forceX; } // Сила по Y if (!n.DisallowedDisplacements.Contains(NodeDisplacement.Y)) { Loads[ind + 1] += forceY; } } } if (CompsList[i].CompType == ComponentTypes.ctDistributedLoad) { // Распределённую нагрузку приводим к узловой ComponentLoad load = (ComponentLoad)CompsList[i]; ComponentLinear lc = load.Beam; // Найдём элемент, созданный на основе компонента lc и сообщим ему, // что на нём лежит нагрузка load ElementBeam beam = Rods.Find(b => b.Linear == lc); if (beam != null) { beam.CalcEquivalentlReactions(load); int ind = getNodeIndex(lc.StartNode) * 3; if (ind > -1) { // Сила по X if (!lc.StartNode.DisallowedDisplacements.Contains(NodeDisplacement.X)) { Loads[ind] += beam.Rx1g; } // Сила по Y if (!lc.StartNode.DisallowedDisplacements.Contains(NodeDisplacement.Y)) { Loads[ind + 1] += beam.Ry1g; } // Момент if (!lc.StartNode.DisallowedDisplacements.Contains(NodeDisplacement.Rotation)) { Loads[ind + 2] += beam.M1g; } } ind = getNodeIndex(lc.EndNode) * 3; if (ind > -1) { // Сила по X if (!lc.EndNode.DisallowedDisplacements.Contains(NodeDisplacement.X)) { Loads[ind] += beam.Rx2g; } // Сила по Y if (!lc.EndNode.DisallowedDisplacements.Contains(NodeDisplacement.Y)) { Loads[ind + 1] += beam.Ry2g; } // Момент if (!lc.EndNode.DisallowedDisplacements.Contains(NodeDisplacement.Rotation)) { Loads[ind + 2] += beam.M2g; } } } } } // 4. Применяем ограничения for (int i = 0; i < CompsList.Count; i++) { if (CompsList[i].CompType == ComponentTypes.ctNode) { Block((ComponentNode)CompsList[i]); } } // 5. Получаем перемещения узлов в глобальной системе координат double[,] GlobalInverted = StarMath.inverse(GlobalMatrix); Displacements = StarMath.multiply(GlobalInverted, Loads); // "Подчистим" перемещения от сверхмалых значений CleanupDisplacements(); // Определим значения реакций в узлах - они же внутренние усилия for (int i = 0; i < Rods.Count; i++) { Rods[i].CalculateForces(); } }
internal int getNodeIndex(ComponentNode n) { return(Nodes.FindIndex(x => x == n)); }
internal bool PreprocessBindingChange(IssoBinding b, float newDX, float newDY) { // Фактически модель - это система точек на плоскости // Между некоторыми из них установлены связи в виде размеров // Когда меняется значение отдельного размера или добавляется новый, // требуется преобразовать координаты точек (сдвинуть линейно по вертикали или горизонтали) // Точки, которые не связаны никакими ограничениями, из рассмотрения исключаются List <IssoBinding> bin = Bindings; List <ComponentNode> nodes = ModelNodes; int nodecnt = ModelNodes.Count; ndX = new float[nodecnt, nodecnt]; ndY = new float[nodecnt, nodecnt]; for (int y = 0; y < nodecnt; y++) { for (int x = 0; x < nodecnt; x++) { ndX[x, y] = float.MaxValue; ndY[x, y] = float.MaxValue; if (x == y) { ndX[x, y] = 0; ndY[x, y] = 0; } } } for (int i = 0; i < bin.Count; i++) { // Пропускаем устанавливаемую связь if (b == bin[i]) { continue; } ComponentNode nd1 = bin[i].Source; ComponentNode nd2 = bin[i].Target; int nd1i = nodes.IndexOf(nd1); int nd2i = nodes.IndexOf(nd2); switch (bin[i].Type) { case IssoBindingType.Horizontal: { ndX[nd1i, nd2i] = Math.Sign(nd2.Location.X - nd1.Location.X) * bin[i].Value; ndX[nd2i, nd1i] = -ndX[nd1i, nd2i]; break; } case IssoBindingType.Vertical: { ndY[nd1i, nd2i] = Math.Sign(nd2.Location.Y - nd1.Location.Y) * bin[i].Value; ndY[nd2i, nd1i] = -ndY[nd1i, nd2i]; break; } } } // Теперь пробуем изменить расстояние между src и tgt if (LocationFixed(b.Type, nodes.IndexOf(b.Source), nodes.IndexOf(b.Target), new List <int>())) { return(false); } else { RecoursiveMove(nodes, b.Source, b.Target, newDX, newDY); return(true); } }