protected override void OnMouseDown(MouseButtonEventArgs e) { base.OnMouseDown(e); Vector3 point = new Vector3(0, 0, 0); Glu.UnProject(new Vector3(e.X, e.Y, 0.0f), ref point); Vector2 point2 = new Vector2(point.X, point.Y); if (e.Button == MouseButton.Left) { if (Vector2.Distance(start, point2) < selectionRadius) { dragMode = DragMode.Start; start = point2; } else if (Vector2.Distance(end, point2) < selectionRadius) { dragMode = DragMode.End; end = point2; } } else if (e.Button == MouseButton.Right) { pathSet = false; OnResize(); } }
private bool FindTrasingData(Segment l, ref TracingData data) { var intersections = new Dictionary <Vector2, int>(); var inDistances = new Dictionary <float, Vector2>(); var outDistances = new Dictionary <float, Vector2>(); for (var i = 0; i < Segments.Length; i++) { var segment = Segments[i]; var intersectPoint = new Vector2(); var isIntersects = Vector2.SegmentToSegmentIntersection(l.Start, l.End, segment.Start, segment.End, ref intersectPoint); if (!isIntersects) { continue; } intersections[intersectPoint] = i; inDistances[Vector2.Distance(intersectPoint, l.Start)] = intersectPoint; outDistances[Vector2.Distance(intersectPoint, l.End)] = intersectPoint; } if (intersections.Count == 0) { return(false); } data.InPoint = inDistances[inDistances.Keys.Min()]; data.OutPoint = outDistances[outDistances.Keys.Min()]; data.InSegmentIndex = intersections[data.InPoint]; data.OutSegmentIndex = intersections[data.OutPoint]; return(true); }
protected override void OnMouseMove(MouseMoveEventArgs e) { base.OnMouseMove(e); if (dragMode != DragMode.Start && dragMode != DragMode.End) { return; } Vector3 point = new Vector3(0, 0, 0); Glu.UnProject(new Vector3(e.X, e.Y, 0.0f), ref point); Vector2 point2 = new Vector2(point.X, point.Y); if (dragMode == DragMode.Start) { start = point2; } else { end = point2; } settings.StartAndEnd = new[] { start, end }; }
public IEnumerable <Vector2> GetPath(Vector2 start, Vector2 end) { var result = new List <Vector2>(); movedSegments = new List <Segment>(); // 1. Старт result.Add(start); Vector2 obstacleEnd = start; while (obstacleEnd != Vector2.zero) { // 2. Сразу проверяем можем ли построить путь без пересечений List <Vector2> intersectPoints = findIntersectPoints3(obstacleEnd, end, segments); if (intersectPoints.Count == 0) { result.Add(end); return(result); } // Вычисляем два пути: по часовой и против часовой стрелки PathDistance byEnd = calcPathByEnd(obstacleEnd, intersectPoints, start, end); PathDistance byStart = calcPathByStart(obstacleEnd, intersectPoints, start, end); PathDistance shortestDistance = byEnd.distance < byStart.distance ? byEnd : byStart; result.AddRange(shortestDistance.points); obstacleEnd = shortestDistance.obstacleEnd; } result.Add(end); return(result); }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); Size = settings.Size; if (settings.Location.X != int.MinValue && settings.Location.Y != int.MinValue) { Location = new Point(settings.Location.X, settings.Location.Y); } if (settings.StartAndEnd != null) { start = settings.StartAndEnd[0]; end = settings.StartAndEnd[1]; pathSet = true; } GL.ClearColor(0.7f, 0.7f, 0.7f, 0.0f); GL.Disable(EnableCap.DepthTest); if (!File.Exists(settings.CurrentFile)) { settings.CurrentFile = null; LoadFile(settings.NextFile); } else { LoadFile(settings.CurrentFile); } }
public PathDistance calcPathByStart(Vector2 obstacleEnd, List <Vector2> intersectPoints, Vector2 start, Vector2 end) { // Находим ближайшую точку пересечения и ее сегмент, запоминаем Vector2 intersectNearestPoint = findNearestPoint(obstacleEnd, intersectPoints); Segment nearestSegment = findNearestSegment(intersectNearestPoint); // Проверяем можем ли с вершины обстакла дойти до финиша if (findIntersectPoints2(nearestSegment.start, end, segments) == 0) { PathDistance path1 = new PathDistance(); path1.addPoint(intersectNearestPoint); path1.accDistance(Vector2.Distance(start, intersectNearestPoint)); // Выбираем Начало отрезка и запоминаем path1.addPoint(nearestSegment.start); path1.accDistance(Vector2.Distance(intersectNearestPoint, nearestSegment.start)); path1.obstacleEnd = Vector2.zero; return(path1); } PathDistance path = new PathDistance(); path.addPoint(intersectNearestPoint); path.accDistance(Vector2.Distance(start, intersectNearestPoint)); // Выбираем Начало отрезка и запоминаем path.addPoint(nearestSegment.start); path.accDistance(Vector2.Distance(intersectNearestPoint, nearestSegment.start)); // Если не можем, ищем обстакл на котором располагается ближайший сегмент Obstacle obstacle = findObstacleBySegment(nearestSegment); // Идем по сегментам обстакла, пока не будем пересекать сами себя и не будем пересекать уже пройденные обстаклы, // или не построем путь из вершина до финиша while (!(findIntersectPoints2(nearestSegment.start, end, obstacle.segments) == 0 && findIntersectPoints2(nearestSegment.start, end, movedSegments.ToArray()) == 0)) { nearestSegment = obstacle.getNextSegmentByCounterClockWise(nearestSegment); // Нашли следующий сегмент обстакла, проверяем можем ли дойти до финиша без пересечений if (findIntersectPoints2(nearestSegment.start, end, segments) == 0) { path.addPoint(nearestSegment.start); path.accDistance(Vector2.Distance(nearestSegment.end, nearestSegment.start)); path.obstacleEnd = Vector2.zero; return(path); } // Не можем - запоминаем конец обстакла path.addPoint(nearestSegment.start); path.accDistance(Vector2.Distance(nearestSegment.end, nearestSegment.start)); } path.obstacleEnd = nearestSegment.start; movedSegments.AddRange(obstacle.segments.ToList()); return(path); }
private void OnResize() { GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height); InternalBox box = obstaclesCollection.Bounds; settings.Size = new Size(Bounds.Width, Bounds.Height); // теперь отскейлим box так, чтобы сохранить пропорции // также добавим ещё процентов 20 по сторонам float coeffW = (float)Width / Height; float coeffM = box.W / box.H; float halfW, halfH; if (coeffW < coeffM) { halfW = box.W / 2; halfH = box.W / coeffW / 2; } else { halfH = box.H / 2; halfW = box.H * coeffW / 2; } Vector2 center = box.Center; // если пути нет, проставим его ровно посереднине слева направо if (!pathSet) { start = new Vector2(center.x - halfW * 1.1f, center.y); end = new Vector2(center.x + halfW * 1.1f, center.y); pathSet = true; settings.StartAndEnd = new[] { start, end }; } // И надбавим 20% чтобы было откуда и куда строить путь halfW *= 1.2f; halfH *= 1.2f; Matrix4 projection = Matrix4.CreateOrthographicOffCenter(center.x - halfW, center.x + halfW, center.y - halfH, center.y + halfH, -10, 10); GL.MatrixMode(MatrixMode.Projection); GL.LoadMatrix(ref projection); Vector3 point = new Vector3(0, 0, 0); Glu.UnProject(new Vector3(0, 0, 0), ref point); Vector2 pointA = new Vector2(point.X, point.Y); Glu.UnProject(new Vector3(20, 0, 0), ref point); Vector2 pointB = new Vector2(point.X, point.Y); selectionRadius = Vector2.Distance(pointA, pointB); }
private Vector2 step1(Vector2 start, Vector2 end, List <Vector2> result, bool v) { var intersectPoints = findIntersectPoints(start, end); Vector2 nearestPoint = findNearestPoint(start, intersectPoints); result.Add(nearestPoint); Vector2 nearestPeak = findNearestPeak(nearestPoint, v); result.Add(nearestPeak); return(nearestPeak); }
public IEnumerable <Vector2> GetPath(Vector2 start, Vector2 end) { var path = new List <Vector2> { start }; var startEnd = new Segment(start, end); foreach (var obstacle in Obstacles) { obstacle.WayAround(startEnd).ForEach(p => path.Add(p)); } path.Add(end); return(path); }
private List <Vector2> findIntersectPoints3(Vector2 start, Vector2 end, Segment[] segments) { var result = new List <Vector2>(); foreach (Segment segment in segments) { Vector2 res = Vector2.zero; if (Vector2.SegmentToSegmentIntersection(segment.start, segment.end, start, end, ref res)) { result.Add(res); } } return(result); }
private int findIntersectPoints2(Vector2 start, Vector2 end, Segment[] segments) { int count = 0; foreach (Segment segment in segments) { Vector2 res = Vector2.zero; if (Vector2.SegmentToSegmentIntersection(segment.start, segment.end, start, end, ref res)) { count++; } } return(count); }
private Segment findNearestSegment(Vector2 intersectNearestPoint) { var result = new Segment(); foreach (Segment segment in segments) { float diff = Vector2.Distance(segment.start, intersectNearestPoint) + Vector2.Distance(segment.end, intersectNearestPoint) - Vector2.Distance(segment.start, segment.end); if (diff < 0.01) { result = segment; break; } } return(result); }
private IEnumerable <Vector2> findIntersectPoints(Vector2 startPath, Vector2 endPath) { var result = new List <Vector2>(); for (int i = 0; i < obstacles.Length; i++) { for (int j = 0; j < obstacles[i].Length; j++) { Vector2 v1; Vector2 v2; if (j == obstacles[i].Length - 1) { v1 = new Vector2(obstacles[i][j].x, obstacles[i][j].y); v2 = new Vector2(obstacles[i][0].x, obstacles[i][0].y); } else { v1 = new Vector2(obstacles[i][j].x, obstacles[i][j].y); v2 = new Vector2(obstacles[i][j + 1].x, obstacles[i][j + 1].y); } Vector2 v3 = new Vector2(startPath.x, startPath.y); Vector2 v4 = new Vector2(endPath.x, endPath.y); Vector2 res = new Vector2(); // Console.WriteLine("obstacle segment = " + v1 + " - " + v2); // Console.WriteLine("path segment = " + v3 + " - " + v4); var segmentToSegmentIntersection = Vector2.SegmentToSegmentIntersection(v1, v2, v3, v4, ref res); // Console.WriteLine("intersect res = " + segmentToSegmentIntersection); // Console.WriteLine("intersect point = " + v4); // Console.WriteLine(); if (segmentToSegmentIntersection) { result.Add(res); } } } return(result); }
public IEnumerable <Vector2> GetPath(Vector2 start, Vector2 end) { var result = new List <Vector2>(); result.Add(start); //printObstacle(); Vector2 nearestPeak1 = step1(start, end, result, false); Vector2 nearestPeak2 = step1(nearestPeak1, end, result, false); Vector2 nearestPeak3 = step1(nearestPeak2, end, result, true); Vector2 nearestPeak4 = step1(nearestPeak3, end, result, true); Vector2 nearestPeak5 = step1(nearestPeak4, end, result, true); // Vector2 nearestPeak6 = step1(nearestPeak5, end, result, true); // Vector2 nearestPeak7 = step1(nearestPeak6, end, result, true); // Vector2 nearestPeak8 = step1(nearestPeak7, end, result, true); return(result); }
private void createSegmentsAndObstacles(Vector2[][] sourceObstacles) { int segmentsLength = 0; for (int i = 0; i < sourceObstacles.Length; i++) { segmentsLength += sourceObstacles[i].Length; } obstacles = new Obstacle[sourceObstacles.Length]; segments = new Segment[segmentsLength]; int k = 0; for (int i = 0; i < sourceObstacles.Length; i++) { Segment[] segmentsForObstacle = new Segment[sourceObstacles[i].Length]; for (int j = 0; j < sourceObstacles[i].Length; j++) { Vector2 endS = Vector2.zero; Vector2 startS = Vector2.zero; if (j == sourceObstacles[i].Length - 1) { startS = sourceObstacles[i][j]; endS = sourceObstacles[i][0]; } else { startS = sourceObstacles[i][j]; endS = sourceObstacles[i][j + 1]; } var segment = new Segment(startS, endS); segments[k] = segment; segmentToObstacleIndex.Add(segment, i); segmentsForObstacle[j] = segment; k++; } obstacles[i] = new Obstacle(segmentsForObstacle); } }
public List <Vector2> WayAround(Segment l) { var td = new TracingData(); if (!FindTrasingData(l, ref td)) { return(new List <Vector2>()); } var toEndPath = new List <Vector2>(); var toEndPathLen = 0.0; toEndPath.Add(td.InPoint); for (var i = td.InSegmentIndex; i != td.OutSegmentIndex; i = (i + 1) % Segments.Length) { var newP = Segments[i].End; toEndPathLen += Vector2.Distance(toEndPath.Last(), newP); toEndPath.Add(newP); } toEndPathLen += Vector2.Distance(toEndPath.Last(), td.OutPoint); toEndPath.Add(td.OutPoint); var toStartPath = new List <Vector2>(); var toStartPathLen = 0.0; toStartPath.Add(td.InPoint); for (var i = td.InSegmentIndex; i != td.OutSegmentIndex; i = i == 0 ? Segments.Length - 1 : i - 1) { var newP = Segments[i].Start; toStartPathLen += Vector2.Distance(toStartPath.Last(), newP); toStartPath.Add(newP); } toStartPathLen += Vector2.Distance(toStartPath.Last(), td.OutPoint); toStartPath.Add(td.OutPoint); return(toStartPathLen < toEndPathLen ? toStartPath : toEndPath); }
private static double Length(IEnumerable <Vector2> path) { double res = 0; bool first = true; Vector2 prev = Vector2.zero; foreach (Vector2 vertex in path) { if (first) { first = false; prev = vertex; continue; } res += Vector2.Distance(prev, vertex); prev = vertex; } return(res); }
private Vector2 findNearestPeak(Vector2 nearestPoint, bool v) { Vector2 res = new Vector2(); for (int i = 0; i < obstacles.Length; i++) { for (int j = 0; j < obstacles[i].Length; j++) { Vector2 v1; Vector2 v2; if (j == obstacles[i].Length - 1) { v1 = new Vector2(obstacles[i][j].x, obstacles[i][j].y); v2 = new Vector2(obstacles[i][0].x, obstacles[i][0].y); } else { v1 = new Vector2(obstacles[i][j].x, obstacles[i][j].y); v2 = new Vector2(obstacles[i][j + 1].x, obstacles[i][j + 1].y); } Vector2 part1 = new Vector2(); Vector2 part2 = new Vector2(); float diff = Vector2.Distance(v1, nearestPoint) + Vector2.Distance(v2, nearestPoint) - Vector2.Distance(v1, v2); Vector2 peak = v ? v1 : v2; if (diff < 0.1) { res = peak; break; } } } return(res); }
private Vector2 findNearestPoint(Vector2 startPath, IEnumerable <Vector2> intersectPoints) { Vector2 res = new Vector2(); float minDistance = 0; foreach (Vector2 point in intersectPoints) { var distance = Vector2.Distance(startPath, point); if (minDistance == 0) { minDistance = distance; res = point; } if (distance < minDistance) { res = point; } } // Console.WriteLine("nearestPoint = " + res); return(res); }
private Vector2 findNearestPoint(Vector2 start, IEnumerable <Vector2> intersectPoints) { Vector2 res = new Vector2(); float minDistance = 0; foreach (Vector2 point in intersectPoints) { var distance = Vector2.Distance(start, point); if (minDistance == 0) { minDistance = distance; res = point; } if (distance < minDistance) { minDistance = distance; res = point; } } return(res); }
public Segment(Vector2 start, Vector2 end) { Start = start; End = end; }
private void SaveStatistics() { const float barrierSuccessRate = 0.96f; StringBuilder sb = new StringBuilder( "<!DOCTYPE html><meta charset=\"UTF-8\"><html><head><style>table { width:100%;}table, th, td { border: 1px solid black; border-collapse: collapse;}th, td { padding: 15px; text-align: left;}table#t01 tr:nth-child(even) { background-color: #eee;}table#t01 tr:nth-child(odd) { background-color: #fff;}table#t01 th { background-color: black; color: white;}</style></head><body><h2>Рекорды</h2><table>"); // тут табличка // Сначала хэдера sb.Append("<tr>"); sb.Append("<th>User</th>"); sb.Append("<th>Total</th>"); sb.Append("<th>Total duration</th>"); sb.Append("<th>Total length</th>"); // Имена файлов HashSet <string> files = new HashSet <string>(); foreach (var val in statistics) { files.Add(val.file); } HashSet <string> users = new HashSet <string>(); foreach (var val in statistics) { users.Add(val.user); } foreach (var file in files) { sb.Append("<th colspan=\"4\" style=\"text-align:center\">" + file + "</th>"); } sb.Append("</tr>"); // Вторая строка - средние значение sb.Append("<tr>"); sb.Append("<td>-</td>"); sb.Append("<td>-</td>"); sb.Append("<td>-</td>"); sb.Append("<td>-</td>"); for (int i = 0; i < files.Count; i++) { sb.Append("<td>Success</td>"); sb.Append("<td>Duration</td>"); sb.Append("<td>Length</td>"); sb.Append("<td>Points</td>"); } sb.Append("</tr>"); // Построим интервалы, за попадание в которые будем давать баллы. Для этого просто получим min и max значения // Интервалы строим на базе значений людей, которые выдали // Интервалы раздельны по файлам и по типу - длительность и длина Dictionary <string, Vector2> durationIntervals = new Dictionary <string, Vector2>(); Dictionary <string, Vector2> lengthIntervals = new Dictionary <string, Vector2>(); foreach (var file in files) { var fileStatistics = statistics.FindAll(p => p.file == file); float minDuration = (float)fileStatistics.Min(p => p.statistics.successRate <= barrierSuccessRate ? double.MaxValue : p.statistics.duration); float maxDuration = (float)fileStatistics.Max(p => p.statistics.successRate <= barrierSuccessRate ? double.MinValue : p.statistics.duration); float minLength = (float)fileStatistics.Min(p => p.statistics.successRate <= barrierSuccessRate ? double.MaxValue : p.statistics.length); float maxLength = (float)fileStatistics.Max(p => p.statistics.successRate <= barrierSuccessRate ? double.MinValue : p.statistics.length); durationIntervals[file] = new Vector2(minDuration, maxDuration); lengthIntervals[file] = new Vector2(minLength, maxLength); } // Теперь по фамилиям и файлам получим очки List <Tuple <string, string, int> > durationScore = new List <Tuple <string, string, int> >(); List <Tuple <string, string, int> > lengthScore = new List <Tuple <string, string, int> >(); foreach (string user in users) { foreach (var file in files) { Statistics stat = statistics.Find(p => p.user == user && p.file == file).statistics; if (stat.successRate <= barrierSuccessRate) { durationScore.Add(new Tuple <string, string, int>(user, file, 0)); lengthScore.Add(new Tuple <string, string, int>(user, file, 0)); } else { // Интервал по файлу Vector2 durationInterval = durationIntervals[file]; if (durationInterval.x == durationInterval.y) { durationScore.Add(new Tuple <string, string, int>(user, file, 10)); } else { float t = (float)((stat.duration - durationInterval.x) / (durationInterval.y - durationInterval.x)); durationScore.Add(new Tuple <string, string, int>(user, file, 10 - (int)(t * 10))); } Vector2 lengthInterval = lengthIntervals[file]; if (lengthInterval.x == lengthInterval.y) { lengthScore.Add(new Tuple <string, string, int>(user, file, 10)); } else { float t = (float)((stat.length - lengthInterval.x) / (lengthInterval.y - lengthInterval.x)); lengthScore.Add(new Tuple <string, string, int>(user, file, 10 - (int)(t * 10))); } } } } Dictionary <string, int> totalScores = new Dictionary <string, int>(); Dictionary <string, int> totalDuration = new Dictionary <string, int>(); Dictionary <string, int> totalLength = new Dictionary <string, int>(); foreach (string user in users) { // Находим все файлы по данному юзеру var userDurationScores = durationScore.FindAll(p => p.Item1 == user); var userLengthScores = lengthScore.FindAll(p => p.Item1 == user); totalDuration[user] = userDurationScores.Sum(p => p.Item3); totalLength[user] = userLengthScores.Sum(p => p.Item3); totalScores[user] = userDurationScores.Sum(p => p.Item3) + userLengthScores.Sum(p => p.Item3); } // А дальше - по фамилиям foreach (string user in users) { sb.Append("<tr>"); sb.Append("<td>" + user + "</td>"); // Тотал sb.Append("<td>" + totalScores[user] + "</td>"); // Тотал длительность sb.Append("<td>" + totalDuration[user] + "</td>"); // Тотал дистанция sb.Append("<td>" + totalLength[user] + "</td>"); foreach (var file in files) { Statistics stat = statistics.Find(p => p.user == user && p.file == file).statistics; // if (stat.successRate <= barrierSuccessRate) // sb.Append("<td style=\"color: red;font-weight: bold;\">" + string.Format("{0:0.00}", stat.successRate) + "</td>"); // else // sb.Append("<td>" + string.Format("{0:0.00}", stat.successRate) + "</td>"); if (stat.successRate <= barrierSuccessRate) { sb.Append("<td style=\"color: red;font-weight: bold;\">" + stat.SuccessRateForHtml() + "</td>"); } else { sb.Append("<td>" + stat.SuccessRateForHtml() + "</td>"); } // если stat.successRate == 1 мы должны найти среди таких молодцев лучший показатель var fileStatistics = statistics.FindAll(p => p.file == file); if (stat.successRate > barrierSuccessRate) { var minDuration = fileStatistics.Min(p => p.statistics.successRate <= barrierSuccessRate ? double.MaxValue : p.statistics.duration); var minLength = fileStatistics.Min(p => p.statistics.successRate <= barrierSuccessRate ? double.MaxValue : p.statistics.length); var minPoints = fileStatistics.Min(p => p.statistics.successRate <= barrierSuccessRate ? double.MaxValue : p.statistics.points); sb.Append((minDuration == stat.duration ? "<td style=\"color: green;font-weight: bold;\">" : "<td>") + string.Format("{0:0.000}", stat.duration) + "</td>"); sb.Append((minLength == stat.length ? "<td style=\"color: green;font-weight: bold;\">" : "<td>") + string.Format("{0:0.000}", stat.length) + "</td>"); sb.Append((minPoints == stat.points ? "<td style=\"color: green;font-weight: bold;\">" : "<td>") + string.Format("{0:0.000}", stat.points) + "</td>"); } else { sb.Append("<td>" + string.Format("{0:0.000}", stat.duration) + "</td>"); sb.Append("<td>" + string.Format("{0:0.000}", stat.length) + "</td>"); sb.Append("<td>" + string.Format("{0:0.000}", stat.points) + "</td>"); } } sb.Append("</tr>"); } sb.Append("</table></body></html>"); File.WriteAllText("records.html", sb.ToString()); }
public Obstacles(string file, InternalObstaclesCollection collection) { this.file = file; this.collection = collection; const int totalNumberOfPoints = 100; int numberOfRandomPoints = collection.areasA != null && collection.areasB != null ? (int)(totalNumberOfPoints * 0.2f) : totalNumberOfPoints; const int numberOfAreaPoints = (int)(totalNumberOfPoints * 0.8f); List <Vector2> testPoints = new List <Vector2>(); int pos = 0; // Для каждого набора точек сгенерим список случайных конечных и начальных точек // Если на карте заданы areaA и areaB, мы сгенерим кучку точек в пределах этих area if (collection.areasA != null && collection.areasB != null) { do { InternalBox[] startAreas; InternalBox[] endAreas; if (Mathematics.Random.Range(0, 2) == 0) { startAreas = collection.areasA; endAreas = collection.areasB; } else { startAreas = collection.areasA; endAreas = collection.areasB; } InternalBox startArea = startAreas[Mathematics.Random.Range(0, startAreas.Length)]; InternalBox endArea = endAreas[Mathematics.Random.Range(0, endAreas.Length)]; Vector2 startPoint = new Vector2(Mathematics.Random.Range(startArea.LeftBottom.x, startArea.RightTop.x), Mathematics.Random.Range(startArea.LeftBottom.y, startArea.RightTop.y)); Vector2 endPoint = new Vector2(Mathematics.Random.Range(endArea.LeftBottom.x, endArea.RightTop.x), Mathematics.Random.Range(endArea.LeftBottom.y, endArea.RightTop.y)); if (collection.Contains(startPoint) || collection.Contains(endPoint)) { continue; } testPoints.Add(startPoint); testPoints.Add(endPoint); pos += 2; } while (pos <= numberOfAreaPoints); } InternalBox box = collection.Bounds; Vector2 min = box.LeftBottom - new Vector2(box.W * 0.1f, box.H * 0.1f); Vector2 max = box.RightTop + new Vector2(box.W * 0.1f, box.H * 0.1f); pos = 0; do { Vector2 randomPoint = new Vector2(Mathematics.Random.Range(min.x, max.x), Mathematics.Random.Range(min.y, max.y)); if (collection.Contains(randomPoint)) { continue; } testPoints.Add(randomPoint); pos++; } while (pos != numberOfRandomPoints); points = testPoints.ToArray(); }
public void TestMain() { Console.WriteLine("Started"); IMap[] maps = new IMap[Game.pathFinders.Length]; Array.Copy(Game.pathFinders, maps, maps.Length); // Чтобы как-то не дай Бог никакой зависимости от порядка запуска не допустить, рандомизируем. Random rnd = new Random(); maps = maps.OrderBy(x => rnd.Next()).ToArray(); // Предзагрузим все файлы string[] files = Directory.EnumerateFiles(InternalSettings.SettingsDir, "*.*", SearchOption.TopDirectoryOnly) .Where(s => s.EndsWith(".txt") || s.EndsWith(".svg")).ToArray(); fileToObstacles = new Obstacles[files.Length]; for (int i = 0; i < files.Length; i++) { fileToObstacles[i] = new Obstacles(files[i], new InternalObstaclesCollection(files[i])); } Vector2 temp1 = Vector2.zero; Vector2 temp2 = Vector2.zero; // Ну и запустим банальные тестики, просто на нахождение пути for (int i = 0; i < maps.Length; i++) { Console.WriteLine("Map: " + maps[i].GetType().Namespace); for (int j = 0; j < fileToObstacles.Length; j++) { Obstacles obstacle = fileToObstacles[j]; int pairsCount = obstacle.points.Length / 2; List <double> durations = new List <double>(); List <double> lengths = new List <double>(); List <int> pointCounts = new List <int>(); // bool[] successes = new bool[pairsCount]; IMap map = maps[i]; bool initFail = false; bool intialized = false; AbortableBackgroundWorker backgroundWorker = new AbortableBackgroundWorker(); backgroundWorker.DoWork += delegate { stopwatch.Restart(); try { map.Init(obstacle.collection.Data); intialized = true; } catch (Exception) { initFail = true; } stopwatch.Stop(); }; backgroundWorker.RunWorkerAsync(); workerStopwatch.Restart(); // здесь мы одновременно ждём результата и считаем время while (true) { if (intialized || initFail) { break; } if (workerStopwatch.ElapsedMilliseconds > 10000) { backgroundWorker.Abort(); backgroundWorker.Dispose(); // Console.WriteLine("Init aborted"); initFail = true; break; } Thread.Sleep(100); } workerStopwatch.Stop(); int failsException = 0; int failsTimeout = 0; int failsPath = 0; if (!initFail) { for (int k = 0; k < obstacle.points.Length; k += 2) { bool fail = false; // Увы, но наши досточтимые калеги не смогли написать алгоритмы не уходящие в вечный цикл, или не перебирающие миллионы объектов // Поэтому будем снимать поиски, отрабатывающие дольше секунды IEnumerable <Vector2> path = null; Vector2 a = obstacle.points[k]; Vector2 b = obstacle.points[k + 1]; backgroundWorker = new AbortableBackgroundWorker(); backgroundWorker.DoWork += delegate { stopwatch.Restart(); try { path = map.GetPath(a, b); } catch (ThreadAbortException) { fail = true; } catch (Exception) { failsException++; fail = true; } stopwatch.Stop(); }; backgroundWorker.RunWorkerAsync(); workerStopwatch.Restart(); // здесь мы одновременно ждём результата и считаем время while (true) { if (path != null || fail) { break; } if (workerStopwatch.ElapsedMilliseconds > 1000) { backgroundWorker.Abort(); backgroundWorker.Dispose(); // Console.WriteLine("GetPath aborted"); failsTimeout++; fail = true; break; } Thread.Sleep(100); } workerStopwatch.Stop(); // Console.WriteLine("Time elapsed (ms): {0}", stopwatch.Elapsed.TotalMilliseconds); if (!fail && path.Count() < 2) { failsPath++; fail = true; } // Здесь мы должны отвалидировать адекватность пути и если он невалидный, отметить это if (!fail && (path.First() != obstacle.points[k] || path.Last() != obstacle.points[k + 1])) { failsPath++; fail = true; } if (!fail && obstacle.collection.Intersects(path, ref temp1, ref temp2)) { failsPath++; fail = true; } if (!fail) { durations.Add(stopwatch.Elapsed.TotalMilliseconds); pointCounts.Add(path.Count()); lengths.Add(Length(path)); } // successes[l] = !fail; } } var stats = new Statistics( initFail ? 0 : 1 - (float)(failsPath + failsTimeout + failsException) / pairsCount, durations.Count == 0 ? 0 : durations.Average(), lengths.Count == 0 ? 0 : lengths.Average(), pointCounts.Count == 0 ? 0 : pointCounts.Average(), initFail ? 0 : pairsCount, failsException, failsTimeout, failsPath ); Console.WriteLine("File: " + obstacle.file + stats.ToString()); statistics.Add(new UserFileStatistics(maps[i].GetType().Namespace.Replace("PathFinder.", ""), obstacle.file, stats)); } } SaveStatistics(); Console.WriteLine("Test finsihed."); }
public Segment(Vector2 start, Vector2 end) { this.start = start; this.end = end; }
public void addPoint(Vector2 point) { points.Add(point); }
protected override void OnRenderFrame(FrameEventArgs e) { base.OnRenderFrame(e); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); Matrix4 modelview = Matrix4.LookAt(Vector3.UnitZ, Vector3.Zero, Vector3.UnitY); GL.MatrixMode(MatrixMode.Modelview); GL.LoadMatrix(ref modelview); GL.Hint(HintTarget.LineSmoothHint, HintMode.Nicest); // tr.Draw(); obstaclesCollection.Draw(); if (obstaclesCollection.Initialized && !obstaclesCollection.Contains(start) && !obstaclesCollection.Contains(end)) { // stopwatch.Restart(); IEnumerable <Vector2> path = map.GetPath(start, end); // stopwatch.Stop(); // Console.WriteLine("Time elapsed (ms): {0}", stopwatch.Elapsed.TotalMilliseconds); // Сами линии пути { GL.Color3(0.5f, 1.0f, 0.5f); GL.LineWidth(3); GL.Begin(PrimitiveType.LineStrip); foreach (Vector2 vertex in path) { GL.Vertex3(vertex.x, vertex.y, 0.0f); } GL.End(); } // Точки на линии пути { GL.Color3(1.0f, 1.0f, 0.5f); GL.PointSize(6); GL.Begin(PrimitiveType.Points); foreach (Vector2 vertex in path) { GL.Vertex3(vertex.x, vertex.y, 0.0f); } GL.End(); } Vector2 badSegmentStart = Vector2.zero; Vector2 badSegmentEnd = Vector2.zero; if (obstaclesCollection.Intersects(path, ref badSegmentStart, ref badSegmentEnd)) { // Console.WriteLine("Intersection"); GL.Color3(1f, 0.0f, 0.0f); GL.LineWidth(3); GL.Begin(PrimitiveType.Lines); GL.Vertex3(badSegmentStart.x, badSegmentStart.y, 0.0f); GL.Vertex3(badSegmentEnd.x, badSegmentEnd.y, 0.0f); GL.End(); } } // Яркими точечками - начало и конец GL.PointSize(12); GL.Color3(1.0f, 0.5f, 0.5f); GL.Begin(PrimitiveType.Points); GL.Vertex3(start.x, start.y, 0.0f); GL.End(); GL.Color3(0.5f, 0.5f, 1.0f); GL.Begin(PrimitiveType.Points); GL.Vertex3(end.x, end.y, 0.0f); GL.End(); SwapBuffers(); }