private int getFEnumber(List <MyNode> nodes, MyPoint CenterPoint, FESearchSpace space, int currentModel) { int numberFE = 0; double radius = Mathematics.FindDist(new MyPoint(nodes[0].X, nodes[0].Y, MyPoint.PointType.IsAreaNode), CenterPoint); foreach (MyNode thisnode in nodes) { MyFiniteElement thisFE = this.parent.currentFullModel.FiniteElementModels[currentModel].FiniteElements.Find( FE => (FE.Nodes[0].X == thisnode.X && FE.Nodes[0].Y == thisnode.Y) || (FE.Nodes[1].X == thisnode.X && FE.Nodes[1].Y == thisnode.Y) || (FE.Nodes[2].X == thisnode.X && FE.Nodes[2].Y == thisnode.Y)); foreach (MyNode FEnode in thisFE.Nodes) { if (space == FESearchSpace.outside) { if (Mathematics.FindDist(new MyPoint(FEnode.X, FEnode.Y, MyPoint.PointType.IsAreaNode), CenterPoint) > radius) { numberFE++; } } else if (space == FESearchSpace.inside) { if (Mathematics.FindDist(new MyPoint(FEnode.X, FEnode.Y, MyPoint.PointType.IsAreaNode), CenterPoint) < radius) { numberFE++; } } } } return(numberFE); }
private List <MyFiniteElement> GetTriangulation(List <MyNode> nodes, int correspondingArea = 0) { List <MyFiniteElement> elements = new List <MyFiniteElement>(); if (ddlTriangulationMethod.SelectedIndex == 0) { List <DelaunayTriangulator.Vertex> points = nodes.ConvertAll(n => new DelaunayTriangulator.Vertex((float)n.X, (float)n.Y)); DelaunayTriangulator.Triangulator worker = new DelaunayTriangulator.Triangulator(); List <DelaunayTriangulator.Triad> triads = worker.Triangulation(points); foreach (DelaunayTriangulator.Triad triad in triads) { MyNode n1 = nodes[triad.a]; MyNode n2 = nodes[triad.b]; MyNode n3 = nodes[triad.c]; // НЕ Приввязываем узлы - возможно этот КЭ не пройдет дальнейший проверки, а привязка останется // коллапс будет ещё какой :) MyFiniteElement rElemt = new MyFiniteElement(0, 0, new MyNode[] { n1, n2, n3 }, correspondingArea - 1, false); // Этот алгоритм иногда генерирует элементы из узлов, лежащих на одной прямой. Почему - уже не успею разобраться :) // Скорее всего, проблема в относительной неточности координат точек модели: где-нибудь на геометрической проверке вываливается. // В общем, такие элементы игнорируем. double[] angles = Mathematics.getFEangles(rElemt); bool badAngles = false; if (angles.Any(a => a.Equal(0))) { badAngles = true; } if (angles.Any(a => double.IsNaN(a))) { badAngles = true; } else if (angles.Any(a => Math.Abs(a) < 0.01)) { badAngles = true; } if (!badAngles) { elements.Add(rElemt); } } } else { List <DelauneyPaulBourke.Geometry.Point> points = nodes.ConvertAll(n => new DelauneyPaulBourke.Geometry.Point(n.X, n.Y, 0)); List <Triangle> triads = DelauneyPaulBourke.Delauney.Triangulate(points); foreach (Triangle triad in triads) { MyNode n1 = nodes[triad.p1]; MyNode n2 = nodes[triad.p2]; MyNode n3 = nodes[triad.p3]; // НЕ Приввязываем узлы - возможно этот КЭ не пройдет дальнейший проверки, а привязка останется // коллапс будет ещё какой :) elements.Add(new MyFiniteElement(0, 0, new MyNode[] { n1, n2, n3 }, correspondingArea - 1, false)); } } return(elements); }
private int getFEnumber(List <MyNode> nodes, LineAngleType angleType, FESearchSpace space, int currentModel) { int numberFE = 0; foreach (MyNode thisnode in nodes) { MyFiniteElement thisFE = this.parent.currentFullModel.FiniteElementModels[currentModel].FiniteElements.Find( FE => (FE.Nodes[0].X == thisnode.X && FE.Nodes[0].Y == thisnode.Y) || (FE.Nodes[1].X == thisnode.X && FE.Nodes[1].Y == thisnode.Y) || (FE.Nodes[2].X == thisnode.X && FE.Nodes[2].Y == thisnode.Y)); foreach (MyNode FEnode in thisFE.Nodes) { if (angleType == LineAngleType.right_up) { if (space == FESearchSpace.up) { if ((FEnode.X < thisnode.X && FEnode.Y <= thisnode.Y) || (FEnode.X < thisnode.X && FEnode.Y >= thisnode.Y)) { numberFE++; } } else if (space == FESearchSpace.down) { if ((FEnode.Y < thisnode.Y && FEnode.X <= thisnode.X) || (FEnode.Y < thisnode.Y && FEnode.X >= thisnode.X)) { numberFE++; } } } else if (angleType == LineAngleType.left_up) { if (space == FESearchSpace.up) { if ((FEnode.Y > thisnode.Y && FEnode.X <= thisnode.X) || (FEnode.Y > thisnode.Y && FEnode.X >= thisnode.X)) { numberFE++; } } else if (space == FESearchSpace.down) { if ((FEnode.X < thisnode.X && FEnode.Y <= thisnode.X) || (FEnode.X < thisnode.X && FEnode.Y >= thisnode.X)) { numberFE++; } } } } } return(numberFE); }
public static double[] getFEangles(MyFiniteElement fe) { double[] angles = new double[3]; double a, b, c; // Стороны треугольника a = FindDist(fe.Nodes[0], fe.Nodes[1]); b = FindDist(fe.Nodes[1], fe.Nodes[2]); c = FindDist(fe.Nodes[2], fe.Nodes[0]); angles[0] = CosineLaw(a, b, c); angles[1] = CosineLaw(b, c, a); angles[2] = CosineLaw(c, a, b); return(angles); }
public static void DefineArea(this MyFiniteElement elem, IEnumerable <MyArea> areas) { double x = elem.Nodes.Sum(n => n.X) / 3; double y = elem.Nodes.Sum(n => n.Y) / 3; foreach (MyArea area in areas) { if (Mathematics.ContainsPoint(area.Nodes, x, y)) { elem.areaId = area.Id - 1; break; } } if (elem.areaId < 0) { int i = 0; i++; } }
private void constructionArea_MouseMove(object sender, MouseEventArgs e) { mouseAboveArea = true; MyPoint clickPoint = visualizer.getClickPoint(e.X, e.Y); if (mouseXcord.Equal(clickPoint.X) && mouseYcord.Equal(clickPoint.Y)) { return; } mouseXcord = clickPoint.X; mouseYcord = clickPoint.Y; if (e.Button == MouseButtons.Left) { // кусочек, который отвечает за перетаскивание области построения if (!this.mouseAboveEditedPoint && !this.mouseAboveEditedNode && this.currentFullModel.geometryModel.editedPoint == null) { this.mouseMoved = true; visualizer.MoveBy((e.X - mouseX), (e.Y - mouseY), showGrid.Checked); mouseX = e.X; mouseY = e.Y; } // кусочек, который отвечает за перетаскивание точки в режиме редактирования точки if (this.editPointsControl != null && this.editPointsControl.IsHandleCreated && this.mouseAboveEditedPoint) { if (this.currentFullModel.geometryModel.editedPoint != null) { if (currentFullModel.geometryModel.editedPoint.IsCenterOfArc) { MessageBox.Show("Изменение центра дуги невозможно!"); this.mouseAboveEditedPoint = false; } else { MyPoint ePoint = currentFullModel.geometryModel.editedPoint; if (currentFullModel.geometryModel.editedPoint.IsStartOfArc || currentFullModel.geometryModel.editedPoint.IsEndOfArc) { MyArc[] incidentArcs = currentFullModel.geometryModel.Arcs.Where(a => a.StartPoint == currentFullModel.geometryModel.editedPoint || a.EndPoint == currentFullModel.geometryModel.editedPoint).ToArray(); if (incidentArcs.Length > 0) { MyPoint commonCenter; commonCenter = incidentArcs[0].CenterPoint; double R = Mathematics.FindDist(currentFullModel.geometryModel.editedPoint, commonCenter); double x; double y; double angle = Math.Atan2(clickPoint.Y - commonCenter.Y, clickPoint.X - commonCenter.X); x = commonCenter.X + R * Math.Cos(angle); y = commonCenter.Y + R * Math.Sin(angle); bool PointFits = true; foreach (MyArc arc in incidentArcs) { MyArc testArc; if (arc.EndPoint == currentFullModel.geometryModel.editedPoint) { testArc = new MyArc(0, arc.Clockwise, arc.StartPoint, new MyPoint(x, y, MyPoint.PointType.IsGeometryPoint), arc.CenterPoint); } else { testArc = new MyArc(0, arc.Clockwise, new MyPoint(x, y, MyPoint.PointType.IsGeometryPoint), arc.EndPoint, arc.CenterPoint); } if (!TestArc(testArc)) { PointFits = false; break; } } if (PointFits) { currentFullModel.geometryModel.editedPoint.X = x; currentFullModel.geometryModel.editedPoint.Y = y; } } else { currentFullModel.geometryModel.editedPoint.X = clickPoint.Y; currentFullModel.geometryModel.editedPoint.Y = clickPoint.Y; } } else { currentFullModel.geometryModel.editedPoint.X = clickPoint.X; currentFullModel.geometryModel.editedPoint.Y = clickPoint.Y; } if (currentFullModel.geometryModel.editedPoint.NodeReference != null) // точка может и не иметь ссылки на узел - если это центральная точка дуги, например { currentFullModel.geometryModel.editedPoint.NodeReference.X = this.currentFullModel.geometryModel.editedPoint.X; currentFullModel.geometryModel.editedPoint.NodeReference.Y = this.currentFullModel.geometryModel.editedPoint.Y; } // отображаем id, x и y точки this.editPointsControl.number.Text = this.currentFullModel.geometryModel.editedPoint.Id.ToString(); this.editPointsControl.x.Text = Mathematics.floor(this.currentFullModel.geometryModel.editedPoint.X, Mathematics.accuracy_medium).ToString(); this.editPointsControl.y.Text = Mathematics.floor(this.currentFullModel.geometryModel.editedPoint.Y, Mathematics.accuracy_medium).ToString(); ReDrawAll(true); } } } // кусочек, который отвечает за перетаскивание узла зоны в режиме редактирования узлов зоны if (this.editNodesControl != null && this.editNodesControl.IsHandleCreated && this.mouseAboveEditedNode) { if (this.currentFullModel.geometryModel.editedNode != null) { this.currentFullModel.geometryModel.editedNode.X = clickPoint.X; this.currentFullModel.geometryModel.editedNode.Y = clickPoint.Y; if (currentFullModel.geometryModel.editedNode.PointReference != null) // точка может и не иметь ссылки на узел - если это центральная точка дуги, например { if (!(currentFullModel.geometryModel.editedNode.PointReference.IsCenterOfArc || currentFullModel.geometryModel.editedNode.PointReference.IsStartOfArc || currentFullModel.geometryModel.editedNode.PointReference.IsEndOfArc)) { currentFullModel.geometryModel.editedNode.PointReference.X = this.currentFullModel.geometryModel.editedNode.X; currentFullModel.geometryModel.editedNode.PointReference.Y = this.currentFullModel.geometryModel.editedNode.Y; } } // отображаем id, x и y точки this.editNodesControl.number.Text = this.currentFullModel.geometryModel.editedNode.Id.ToString(); this.editNodesControl.x.Text = Mathematics.floor(this.currentFullModel.geometryModel.editedNode.X, Mathematics.accuracy_medium).ToString(); this.editNodesControl.y.Text = Mathematics.floor(this.currentFullModel.geometryModel.editedNode.Y, Mathematics.accuracy_medium).ToString(); ReDrawAll(true); } } } else { // подсвечиваем точки и линии MyPoint nearestPoint; if ((nearestPoint = currentFullModel.geometryModel.Points.Find(p => Math.Abs(clickPoint.X - p.X) < (double)visualizer.pointLocality && Math.Abs(clickPoint.Y - p.Y) < (double)visualizer.pointLocality)) != null) { hoveredPoint = nearestPoint; mouseXcord = nearestPoint.X; mouseYcord = nearestPoint.Y; ReDrawAll(true); } else { if (hoveredPoint != null) { hoveredPoint = null; ReDrawAll(true); } } if (creatingCircle) // если мы в режиме рисования окружности { if (this.currentFullModel.geometryModel.centerOfCircle != null) { double x1, y1; if (hoveredPoint == null) { x1 = clickPoint.X; y1 = clickPoint.Y; } else { x1 = hoveredPoint.X; y1 = hoveredPoint.Y; } double radius = Mathematics.FindDist(x1, y1, currentFullModel.geometryModel.centerOfCircle.X, currentFullModel.geometryModel.centerOfCircle.Y); if (this.addCirclesControl != null) { this.addCirclesControl.radius.Text = Mathematics.floor(radius, Mathematics.accuracy_medium).ToString(); } currentFullModel.geometryModel.tempCircle = new MyCircle(this.currentFullModel.geometryModel.NumOfCircles + 1, this.currentFullModel.geometryModel.centerOfCircle, radius); ReDrawAll(true); } } if (activeControl is GridAnalysis) { MyFiniteElementModel model = currentFullModel.FiniteElementModels.Find(m => m.ModelName == currentFullModel.currentGridName); MyFiniteElement elem = model.FiniteElements.Find(el => Mathematics.ContainsPoint(el.Nodes.ToArray(), clickPoint)); if (elem != null) { elemInfoTooltip.ToolTipTitle = "Элемент №" + elem.Id.ToString(); StringBuilder tooltipText = new StringBuilder(); tooltipText.AppendLine("Площадь: " + Mathematics.floor(Mathematics.GeronLaw(elem.Nodes), 0.01)); double[] angles = Mathematics.getFEangles(elem); for (int i = 0; i < 3; i++) { tooltipText.AppendLine("Угол " + (i + 1).ToString() + ": " + angles[i].ToString("###.##")); } elemInfoTooltip.Show(tooltipText.ToString(), constructionArea, new Point(e.X, e.Y)); } else { elemInfoTooltip.Hide(constructionArea); } } } this.textBox1.Text = Mathematics.floor(mouseXcord, Mathematics.accuracy_medium).ToString(); this.textBox2.Text = Mathematics.floor(mouseYcord, Mathematics.accuracy_medium).ToString(); }
private void okButton_Click(object sender, EventArgs e) { List <string> lineStrings = new List <string>(this.notMoveLines.Text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList <string>()); List <MyLine> fixedLines = new List <MyLine>(); foreach (string str in lineStrings) { int idx; if (!int.TryParse(str, out idx)) { MessageBox.Show("Неверно заданы линии!"); return; } MyLine line = (MyLine)parent.currentFullModel.geometryModel.StraightLines.Find(l => l.Id == idx) ?? (MyLine)parent.currentFullModel.geometryModel.Arcs.Find(a => a.Id == idx); if (line == null) { MessageBox.Show("Не найдена линия с номером " + idx.ToString()); return; } fixedLines.Add(line); } parent.precision = parent.DefinePrecision(); if (parent.currentFullModel.geometryModel.Areas.Count != 0) { errorMessage1.Visible = false; errorBadGridName.Visible = false; // создаем новый объект "конечно-элементная модель" и добавляем его в список конечно-элементных моделей. foreach (MyFiniteElementModel model in parent.currentFullModel.FiniteElementModels) // проверяем, нет ли модели с таким именем { if (model.ModelName == gridName.Text) { errorBadGridName.Visible = true; return; } } this.Hide(); parent.StartProgress("Выполняется оптимизация"); // создаем для новой КЭ модели id int id = parent.currentFullModel.IdCandidate; currentModel = (MyFiniteElementModel)Util.getObjectCopy(currentModel); currentModel.ModelName = gridName.Text; currentModel.Id = id; currentModel.restoreArraysForOldMethods(parent.currentFullModel.geometryModel); int[] notMove = new int[currentModel.INOUT.Count]; notMove.Initialize(); if (notMoveLines.TextLength != 0) { foreach (MyLine fixedLine in fixedLines) { List <MyNode> tempNodes = new List <MyNode>(); if (fixedLine is MyStraightLine) { findNodesAtStraightLine(tempNodes, (MyStraightLine)fixedLine); foreach (MyNode node in tempNodes) { node.Type = NodeType.Fixed; notMove[node.Id] = 1; } } else { findNodesAtArc(tempNodes, (MyArc)fixedLine); foreach (MyNode node in tempNodes) { node.Type = NodeType.Fixed; notMove[node.Id] = 1; //currentModel.INOUT[node.Id] = 1; } } } } Regularization(currentModel.NRC, parent.currentFullModel.geometryModel.Areas.Count, currentModel, notMove); currentModel.FiniteElements.Clear(); currentModel.Nodes.Clear(); for (int i = 1; i <= currentModel.NP; i++) // MAXNP - число узлов { currentModel.Nodes.Add(new MyNode(currentModel.CORD[2 * (i - 1) + 1], currentModel.CORD[2 * (i - 1) + 2], i)); } for (int temp = 1; temp <= currentModel.NE; temp++) { int numOfFE = currentModel.FiniteElements.Count; int numOfNodes = currentModel.Nodes.Count; List <MyNode> tempNodes = new List <MyNode>(); double X1 = currentModel.CORD[2 * (currentModel.NOP[3 * (temp - 1) + 1] - 1) + 1]; double Y1 = currentModel.CORD[2 * (currentModel.NOP[3 * (temp - 1) + 1] - 1) + 2]; double X2 = currentModel.CORD[2 * (currentModel.NOP[3 * (temp - 1) + 2] - 1) + 1]; double Y2 = currentModel.CORD[2 * (currentModel.NOP[3 * (temp - 1) + 2] - 1) + 2]; double X3 = currentModel.CORD[2 * (currentModel.NOP[3 * (temp - 1) + 3] - 1) + 1]; double Y3 = currentModel.CORD[2 * (currentModel.NOP[3 * (temp - 1) + 3] - 1) + 2]; foreach (MyNode node in currentModel.Nodes) { if (Math.Abs(node.X - X1) <= 0.001 && Math.Abs(node.Y - Y1) <= 0.001) { tempNodes.Add(node); } if (Math.Abs(node.X - X2) <= 0.001 && Math.Abs(node.Y - Y2) <= 0.001) { tempNodes.Add(node); } if (Math.Abs(node.X - X3) <= 0.001 && Math.Abs(node.Y - Y3) <= 0.001) { tempNodes.Add(node); } } MyFiniteElement elem = new MyFiniteElement(numOfFE + 1, 0, tempNodes); elem.DefineArea(parent.currentFullModel.geometryModel.Areas); currentModel.FiniteElements.Add(elem); tempNodes.Clear(); } parent.EndProgress(); parent.ModelCreated(currentModel); Close(); } else { errorMessage1.Visible = true; } }
// чтение вариантов сетки из файла (Рапперт) public void ReadRuppertVariants(string file) { string[] lines = File.ReadAllLines(file, Encoding.Default); int NRC = Convert.ToInt32(lines[0]); int countOfZones = Convert.ToInt32(lines[1]); int CountOfBasePoints = Convert.ToInt32(lines[2]); int j = 3; // создаем для новой сетки id MyFiniteElementModel model = new MyFiniteElementModel(currentModel.Id, currentModel.ModelName, MyFiniteElementModel.GridType.Ruppert); int cur = parent.GetCurrentModelIndex(); model.INOUT = parent.currentFullModel.FiniteElementModels[cur].INOUT; model.NP = Convert.ToInt32(lines[j++]); // число узлов в варианте сетки model.CORD.Add(0.0); for (int n = 1; n <= model.NP; n++) { int Number = Convert.ToInt32(lines[j++]); double X = Convert.ToDouble(lines[j++].Replace(".", ",")); double Y = Convert.ToDouble(lines[j++].Replace(".", ",")); //int SeNum = Convert.ToInt32(slines[j++]); //int ZoneNum = Convert.ToInt32(slines[j++]); //string s = slines[j++]; //s = slines[j++]; j += 9; model.Nodes.Add(new MyNode(X, Y, Number)); model.CORD.Add(X); model.CORD.Add(Y); } model.NE = Convert.ToInt32(lines[j++]); // число КЭ в варианте сетки for (int e = 1; e <= model.NE; e++) { int Number = Convert.ToInt32(lines[j++]); int Node1 = Convert.ToInt32(lines[j++]); int Node2 = Convert.ToInt32(lines[j++]); int Node3 = Convert.ToInt32(lines[j++]); int Material = Convert.ToInt32(lines[j++]); List <MyNode> nodes = new List <MyNode>(); nodes = model.Nodes.FindAll(n => n.Id == Node1 || n.Id == Node2 || n.Id == Node3); MyFiniteElement elem = new MyFiniteElement(Number, Material, nodes); elem.DefineArea(parent.currentFullModel.geometryModel.Areas); model.FiniteElements.Add(elem); nodes.Clear(); } model.NOP.Add(0); for (int i = 0; i < model.NE; i++) { int n1 = model.FiniteElements[i].Nodes[0].Id; int n2 = model.FiniteElements[i].Nodes[1].Id; int n3 = model.FiniteElements[i].Nodes[2].Id; model.NOP.Add(n1); model.NOP.Add(n2); model.NOP.Add(n3); } File.Delete(Path.GetDirectoryName(this.parent.FullProjectFileName) + "\\grid.Ralg"); parent.ModelCreated(model); }