public override void OnScannedRobot(ScannedRobotEvent e) { double absoluteBearing = HeadingRadians + e.BearingRadians; PointF myLocation = new PointF((float)X, (float)Y); PointF predictedLocation = projectMotion(myLocation, absoluteBearing, e.Distance); double predictedHeading; double enemyTurnRate = -Utils.NormalRelativeAngle(expectedHeading - (predictedHeading = expectedHeading = e.HeadingRadians)); double bulletPower = Math.Min(e.Distance < 250 ? 500 / e.Distance : 200 / e.Distance, 3); int time = 0; while ((time++) * (20 - (3 * bulletPower)) < myLocation.Distance(predictedLocation) - 18) { predictedHeading += (enemyTurnRate / 3); predictedLocation = projectMotion(predictedLocation, predictedHeading, e.Velocity); if (!new RectangleF(18, 18, 764, 564).Contains(predictedLocation)) { break; } } double maxValue = Double.MinValue; double angle = 0; do { double value = Math.Abs(Math.Cos(Utils.NormalRelativeAngle(absoluteBearing - angle))) * e.Distance / 150; PointF testedLocation = projectMotion(myLocation, angle, 8); value -= testedLocation.Distance(predictedLocation); value -= testedLocation.Distance(new PointF(400, 300)) / 3; if (!new RectangleF(30, 30, 740, 540).Contains(testedLocation)) { value -= 10000; } if (value > maxValue) { maxValue = value; double turnAngle = angle - HeadingRadians; SetAhead(Math.Cos(turnAngle) > 0 ? 100 : -100); SetTurnRightRadians(Math.Tan(turnAngle)); } } while ((angle += 0.01) < Math.PI * 2); MaxVelocity = (Math.Abs(TurnRemaining) < 30 ? 8 : 8 - Math.Abs(TurnRemaining / 30)); double gunTurn = Utils.NormalRelativeAngle(Math.Atan2(predictedLocation.X - myLocation.X, predictedLocation.Y - myLocation.Y) - GunHeadingRadians); SetTurnGunRightRadians(gunTurn); if ((Math.Abs(gunTurn) < Math.PI / 9) && (GunHeat == 0.0)) { SetFire(bulletPower); } SetTurnRadarRightRadians(2 * Utils.NormalRelativeAngle(absoluteBearing - RadarHeadingRadians)); }
private void Flocking(IEnumerable <BoidBehaviour> boids) { if (boids.Count() == 1) { Direction.X += 1; Direction.Y += 1; } foreach (BoidBehaviour boid in boids) { float distance = Position.Distance(boid.Position); if (boid != this && !boid.Predator) { if (distance < Space) { // Create space. Direction.X += (Position.X - boid.Position.X) * 0.01f; Direction.Y += (Position.Y - boid.Position.Y) * 0.01f; } else if (distance < Sight) { // Flock together. Direction.X += (boid.Position.X - Position.X) * 0.001f; Direction.Y += (boid.Position.Y - Position.Y) * 0.001f; } if (distance < Sight) { // Align movement. Direction.X += boid.Direction.X * 0.001f; Direction.Y += boid.Direction.Y * 0.001f; } } if (boid.Predator && distance < Sight) { // Avoid hunters. Direction.X += Position.X - boid.Position.X * 0.2f; Direction.Y += Position.Y - boid.Position.Y * 0.2f; } if (this.Avoid.HasValue && this.Position.Distance(this.Avoid.Value) < Sight) { // Avoid hunters. Direction.X += Position.X - this.Avoid.Value.X * 1.0f; Direction.Y += Position.Y - this.Avoid.Value.Y * 1.0f; } } }
public static double FindDistanceAlongSpine(PointF[] spine, PointF point) { if (spine == null || spine.Length <= 1) { return(-1); } double minDist = double.MaxValue; PointF bestPoint = PointF.Empty; PointF[] closestPoints = new PointF[2]; double totalDist = 0; for (int i = 1; i < spine.Length; i++) { PointF previousPoint = spine[i - 1]; PointF currentPoint = spine[i]; PointF closestPoint; double currentMinDist = MathExtension.MinDistanceFromLineToPoint(previousPoint, currentPoint, point, out closestPoint); if (currentMinDist < minDist) { minDist = currentMinDist; bestPoint = closestPoint; closestPoints[0] = previousPoint; closestPoints[1] = currentPoint; } } for (int i = 1; i < spine.Length; i++) { PointF previousPoint = spine[i - 1]; PointF currentPoint = spine[i]; if (previousPoint == closestPoints[0]) { //We're on the line totalDist += previousPoint.Distance(bestPoint); break; } else { //Not on this line totalDist += previousPoint.Distance(currentPoint); } } return(totalDist); }
public static PointF GetDistancePointFromBase(PointF[] spine, double distance, PointF offset = new PointF()) { if (spine == null || spine.Length <= 1) { return(PointF.Empty); } //double targetDistance = 0; if (!offset.IsEmpty) { } double distanceCounter = 0; for (int i = 1; i < spine.Length; i++) { PointF previousPoint = spine[i - 1]; PointF currentPoint = spine[i]; distanceCounter += previousPoint.Distance(currentPoint); if (distanceCounter > distance) { //The point is somewhere along this line Vector dir = new Vector(currentPoint.X - previousPoint.X, currentPoint.Y - previousPoint.Y); dir.Normalize(); dir *= distance; return(new PointF((float)(previousPoint.X + dir.X), (float)(previousPoint.Y + dir.Y))); } } return(PointF.Empty); }
public static PointF Mid(this PointF p, PointF other) { var distance = p.Distance(other); var direction = (other.Sub(p)).Normalize(); return(p.Add(direction.Scale(distance / 2))); }
public void DistanceTest() { var p = new PointF(1, 1); var c = new PointF(5, 4); var distance = p.Distance(c); Assert.AreEqual(distance, 5); }
public void DistanceTest(double x1, double y1, double x2, double y2) { Assert.AreEqual(x2.Hypot2(y2), MathTool.Distance(x1, y1, x2, y2), 0.000000001d); var p1 = new PointF((float)x1, (float)y1); var p2 = new PointF((float)x2, (float)y2); Assert.AreEqual(x2.Hypot2(y2), p1.Distance(p2), 0.000000001d); }
public double GetDistance() { GenericPointViewModel genericPoint1 = CanvasChildren[0]; GenericPointViewModel genericPoint2 = CanvasChildren[1]; PointF relativePoint1 = new PointF((float)genericPoint1.XRatio * Image.Width, (float)genericPoint1.YRatio * Image.Height); PointF relativePoint2 = new PointF((float)genericPoint2.XRatio * Image.Width, (float)genericPoint2.YRatio * Image.Height); double dist = relativePoint1.Distance(relativePoint2); return(dist); }
public double GetTrackLength(PointF[] track) { double dist = 0; int length = track.Length; for (int i = 1; i < length; i++) { PointF p1 = track[i - 1]; PointF p2 = track[i]; dist += p1.Distance(p2); } return(dist); }
private float[] GetEuclideanDistance(IRadialGradient gradient, PointF center, RectangleF rect) { var points = gradient.Stretch.IsCorner() ? GetCornerPoints(rect) : GetSidePoints(center, rect); var distances = new float[points.Length]; for (var i = 0; i < distances.Length; i++) { distances[i] = center.Distance(points[i]); } return(distances); }
public static PointF NearestPointFFromList(PointF srcPointF, List <PointF> listOfPointFs) { KeyValuePair <double, int> smallestDistance = new KeyValuePair <double, int>(); for (int i = 0; i < listOfPointFs.Count; i++) { double distance = srcPointF.Distance(listOfPointFs[i]); if (i == 0) { smallestDistance = new KeyValuePair <double, int>(distance, i); } else { if (distance < smallestDistance.Key) { smallestDistance = new KeyValuePair <double, int>(distance, i); } } } return(listOfPointFs[smallestDistance.Value]); }
public static bool GetPerpendicularLineDistanceFromBase(PointF[] spine, double distance, out PointF intersection, out Vector direction, PointF offset = new PointF()) { intersection = PointF.Empty; direction = new Vector(); if (spine == null || spine.Length <= 1) { return(false); } double distanceCounter = 0; for (int i = 1; i < spine.Length; i++) { PointF previousPoint = spine[i - 1]; PointF currentPoint = spine[i]; double currentSegmentDistance = previousPoint.Distance(currentPoint); distanceCounter += currentSegmentDistance; if (distanceCounter > distance) { //The point is somewhere along this line distanceCounter -= currentSegmentDistance; double delta = distance - distanceCounter; Vector dir = new Vector(currentPoint.X - previousPoint.X, currentPoint.Y - previousPoint.Y); dir.Normalize(); dir *= delta; intersection = new PointF((float)(previousPoint.X + dir.X), (float)(previousPoint.Y + dir.Y)); //Create perpendicular Vector direction = new Vector(dir.Y, -dir.X); return(true); } } return(false); }
protected override void OnTouchDown(Touch t) { if (t == Touch || _another != null) { return; } if (!Touch.Down) { Touch = t; OnTouchDown(t); return; } _pinching = true; _another = t; _startSpan = PointF.Distance(Touch.Current, _another.Current); _startZoom = Camera.Zoom; _dragging = false; }
protected override void OnDrag(Touch t) { if (_dragging) { var content = _scrollPane.Content(); var c = content.Camera; c.Scroll.Offset(PointF.Diff(_lastPos, t.Current).InvScale(c.Zoom)); if (c.Scroll.X + Width > content.Width) { c.Scroll.X = content.Width - Width; } if (c.Scroll.X < 0) { c.Scroll.X = 0; } if (c.Scroll.Y + Height > content.Height) { c.Scroll.Y = content.Height - Height; } if (c.Scroll.Y < 0) { c.Scroll.Y = 0; } _lastPos.Set(t.Current); } else if (PointF.Distance(t.Current, t.Start) > _dragThreshold) { _dragging = true; _lastPos.Set(t.Current); } }
protected override void OnDrag(Touch t) { Camera.Target = null; if (_pinching) { var curSpan = PointF.Distance(Touch.Current, _another.Current); Camera.ZoomTo(GameMath.Gate(PixelScene.minZoom, _startZoom * curSpan / _startSpan, PixelScene.maxZoom)); } else { if (!_dragging && PointF.Distance(t.Current, t.Start) > _dragThreshold) { _dragging = true; _lastPos.Set(t.Current); } else if (_dragging) { Camera.Scroll.Offset(PointF.Diff(_lastPos, t.Current).InvScale(Camera.Zoom)); _lastPos.Set(t.Current); } } }
public void Draw(Graphics g) { var BackgroundBrush = CSMABackgroundBrush; switch (Type) { case DomainType.CSMA: { BackgroundBrush = CSMABackgroundBrush; break; } case DomainType.IEEE81211: { BackgroundBrush = IEEE81211BackgroundBrush; break; } case DomainType.LTE: { BackgroundBrush = LTEBackgroundBrush; break; } case DomainType.Wimax: { BackgroundBrush = WimaxBackgroundBrush; break; } } if (Nodes.Count == 0) { if (Radius > 0) { g.FillEllipse(BackgroundBrush, new Rectangle((int)(X - Radius), (int)(Y - Radius), (int)(Radius * 2), (int)(Radius * 2))); } } else { if (DisplayProperties.RenderDomain) { var nodeRadius = 0.0d; foreach (var node in Nodes) { var dist = Position.Distance(node.Position); if (dist > nodeRadius) { nodeRadius = dist; } } g.FillEllipse(BackgroundBrush, new Rectangle((int)(X - nodeRadius), (int)(Y - nodeRadius), (int)(nodeRadius * 2), (int)(nodeRadius * 2))); } } if (DisplayProperties.RenderDomainText) { var textWidth = (int)g.MeasureString(Text, SystemFonts.DefaultFont).Width; var textHeight = (int)g.MeasureString(Text, SystemFonts.DefaultFont).Height; var diameter = textWidth > textHeight ? textWidth : textHeight; if (diameter < 35) { diameter = 35; } g.FillEllipse(BackgroundBrush, new Rectangle((int)(X - diameter / 2), (int)(Y - diameter / 2), diameter, diameter)); g.DrawString(Text, SystemFonts.DefaultFont, Brushes.Black, new Point((int)(X - textWidth / 2), (int)(Y - textHeight / 2))); } }
public LineSet(int id, LineContainer container, IEnumerable <Dot> dots) { ID = id; this.dots = dots.ToArray(); //if(dots.Last().NextConnectDot) foreach (var item in this.dots) { item.LineSet = this; item.PointChanged += DotPointChanged; } List <Dot> pl = new List <Dot>(); Dot first, prev; prev = first = this.dots.First(); PointF firstP, prevP = prev.Point; firstP = first.Point; float minX, maxX, minY, maxY; minX = maxX = firstP.X; minY = maxY = firstP.Y; //PointF first = dots.First().Point; //PointF prev = first; int counter = 0; int length = this.dots.Length; dotDistances = new float[length]; dotRectangles = new RectangleF[length]; lines = new Line[length]; Line line; foreach (var item in this.dots.Skip(1)) { PointF currentP = item.Point; //dotRectangles[counter] = currentP.GetRectangleFromTwoPoint(prevP); dotDistances[counter] = (float)currentP.Distance(prevP); line = new Line(prev, item, this, container); lines[counter] = line; dotRectangles[counter] = line.RectangleF; prev = item; prevP = prev.Point; counter++; float x = currentP.X, y = currentP.Y; if (x < minX) { minX = x; } else if (x > maxX) { maxX = x; } if (y < minY) { minY = y; } else if (y > maxY) { maxY = y; } } dotDistances[counter] = (float)firstP.Distance(prevP); line = new Line(prev, first, this, container); lines[counter] = line; dotRectangles[counter] = line.RectangleF; RectangleF = new RectangleF(minX, minY, maxX - minX, maxY - minY); Color = ColorCollections[ID % ColorCollections.Length]; }
public Bitmap GetImage(int width, int height, Font font, float offsetX, float offsetY, float scale) { Bitmap bmp = new Bitmap(width, height); Graphics g = Graphics.FromImage(bmp); float minX = float.PositiveInfinity, minY = float.PositiveInfinity, maxX = float.NegativeInfinity, maxY = float.NegativeInfinity; foreach (Node n in Nodes) { minX = Math.Min(minX, n.Location.X); minY = Math.Min(minY, n.Location.Y); maxX = Math.Max(maxX, n.Location.X); maxY = Math.Max(maxY, n.Location.Y); } if (!fixCamera) { float s = scale; scale = 1f; origin = new PointF((minX + maxX) * 30 * scale / 2, (minY + maxY) * 30 * scale / 2); scale = Math.Min(width / 2 / (maxX * 30 * scale - origin.X), height / 2 / (maxY * 30 * scale - origin.Y)) * 0.9f; scale *= s; RefScale = scale; origin = new PointF((minX + maxX) * 30 * scale / 2, (minY + maxY) * 30 * scale / 2); } else { scale = RefScale; } if (Math.Abs((minX + maxX) * 30 * scale / 2) > 10000f || Math.Abs((minY + maxY) * 30 * scale / 2) > 10000f) { Recenter(); minX = float.PositiveInfinity; minY = float.PositiveInfinity; maxX = float.NegativeInfinity; maxY = float.NegativeInfinity; foreach (Node n in Nodes) { minX = Math.Min(minX, n.Location.X); minY = Math.Min(minY, n.Location.Y); maxX = Math.Max(maxX, n.Location.X); maxY = Math.Max(maxY, n.Location.Y); } if (!fixCamera) { float s = scale; scale = 1f; origin = new PointF((minX + maxX) * 30 * scale / 2, (minY + maxY) * 30 * scale / 2); scale = Math.Min(width / 2 / (maxX * 30 * scale - origin.X), height / 2 / (maxY * 30 * scale - origin.Y)) * 0.9f; scale *= s; RefScale = scale; origin = new PointF((minX + maxX) * 30 * scale / 2, (minY + maxY) * 30 * scale / 2); } } g.TranslateTransform(width / 2 + offsetX - origin.X, height / 2 + offsetY - origin.Y); bool found = false; foreach (Node n in Nodes) { if (simpleMode && n.Type != Elements.Hydrogen || !simpleMode) { if (found || Selected != null && Selected.Locked) { g.DrawString(n.Type.ToDString(), font, Brushes.Black, n.Location.X * 30 * scale, n.Location.Y * 30 * scale, new StringFormat() { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center }); } else if (Cursor.Distance(n.Location.Scale(30f * scale).Add(new PointF(width / 2 + offsetX, height / 2 + offsetY)).Subtract(origin)) < 10f) { found = true; Selected = n; } } g.DrawString(n.Type.ToDString(), font, n == Selected ? Brushes.Silver : Brushes.Black, n.Location.X * 30 * scale, n.Location.Y * 30 * scale, new StringFormat() { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center }); } if ((Selected == null || !Selected.Locked) && !found) { Selected = null; } foreach (Bond b in Bonds) { PointF Dir21 = b.Node2.Location.Subtract(b.Node1.Location).Normalize(); PointF gap = Dir21.Scale(10); if (simpleMode && b.Node1.Type != Elements.Hydrogen && b.Node2.Type != Elements.Hydrogen || !simpleMode) { if (b.Type == BondType.Single || b.Type == BondType.Triple) { g.DrawLine(Pens.Black, gap.X + b.Node1.Location.X * 30 * scale, gap.Y + b.Node1.Location.Y * 30 * scale, -gap.X + b.Node2.Location.X * 30 * scale, -gap.Y + b.Node2.Location.Y * 30 * scale); } if (b.Type == BondType.Triple) { double angle = Math.Atan2(Dir21.Y, Dir21.X); PointF lateral = new PointF((float)Math.Cos(angle + Math.PI / 2), (float)Math.Sin(angle + Math.PI / 2)).Scale(4); g.DrawLine(Pens.Black, lateral.X + gap.X + b.Node1.Location.X * 30 * scale, lateral.Y + gap.Y + b.Node1.Location.Y * 30 * scale, lateral.X - gap.X + b.Node2.Location.X * 30 * scale, lateral.Y - gap.Y + b.Node2.Location.Y * 30 * scale); g.DrawLine(Pens.Black, -lateral.X + gap.X + b.Node1.Location.X * 30 * scale, -lateral.Y + gap.Y + b.Node1.Location.Y * 30 * scale, -lateral.X - gap.X + b.Node2.Location.X * 30 * scale, -lateral.Y - gap.Y + b.Node2.Location.Y * 30 * scale); } if (b.Type == BondType.Double) { double angle = Math.Atan2(Dir21.Y, Dir21.X); PointF lateral = new PointF((float)Math.Cos(angle + Math.PI / 2), (float)Math.Sin(angle + Math.PI / 2)).Scale(2); g.DrawLine(Pens.Black, lateral.X + gap.X + b.Node1.Location.X * 30 * scale, lateral.Y + gap.Y + b.Node1.Location.Y * 30 * scale, lateral.X - gap.X + b.Node2.Location.X * 30 * scale, lateral.Y - gap.Y + b.Node2.Location.Y * 30 * scale); g.DrawLine(Pens.Black, -lateral.X + gap.X + b.Node1.Location.X * 30 * scale, -lateral.Y + gap.Y + b.Node1.Location.Y * 30 * scale, -lateral.X - gap.X + b.Node2.Location.X * 30 * scale, -lateral.Y - gap.Y + b.Node2.Location.Y * 30 * scale); } } } for (int i = 0; i < 10; i++) { Tick(); } return(bmp); }
/* * This method looks at all the directions we could go, then rates them based on how close they will take us * to simulated bullets fired with both linear and head-on targeting generated by the waves we have logged. * It is the core of our movement. */ public void chooseDirection(PointF enemyLocation, Operations operations, AdvancedRobot robot) { MovementWave w; //This for loop rates each angle individually double bestRating = Double.PositiveInfinity; for (double moveAngle = 0; moveAngle < Math.PI * 2; moveAngle += Math.PI / 16D) { double rating = 0; //Movepoint is position we would be at if we were to move one robot-length in the given direction. PointF movePoint = project(new PointF((float)robot.X, (float)robot.Y), 36, moveAngle); /* * This loop will iterate through each wave and add a risk for the simulated bullets on each one * to the total risk for this angle. */ for (int i = 0; i < moveWaves.Count; i++) { w = moveWaves[i]; //This part will remove waves that have passed our robot, so we no longer keep taking into account old ones if (new PointF((float)robot.X, (float)robot.Y).Distance(w.origin) < (robot.Time - w.startTime) * w.speed + w.speed) { moveWaves.Remove(w); } else { /* * This adds two risks for each wave: one based on the distance from where a head-on targeting * bullet would be, and one for where a linear targeting bullet would be. */ rating += 1D / Math.Pow( movePoint.Distance(project(w.origin, movePoint.Distance(w.origin), w.angle)), 2); rating += 1D / Math.Pow( movePoint.Distance(project(w.origin, movePoint.Distance(w.origin), w.angle + w.latVel)), 2); } } //This adds a risk associated with being to close to the other robot if there are no waves. if (moveWaves.Count == 0) { rating = 1D / Math.Pow(movePoint.Distance(enemyLocation), 2); } //This part tells us to go in the direction if it is better than the previous best option and is reachable. if (rating < bestRating && new RectangleF(50, 50, (float)(robot.BattleFieldWidth - 100), (float)(robot.BattleFieldHeight - 100)).Contains( movePoint)) { bestRating = rating; /* * These next three lines are a very codesize-efficient way to * choose the best direction for moving to a point. */ int pointDir; operations.Ahead = 1000 * (pointDir = (Math.Abs(moveAngle - robot.HeadingRadians) < Math.PI / 2 ? 1 : -1)); operations.TurnRightRadians = Utils.NormalRelativeAngle(moveAngle + (pointDir == -1 ? Math.PI : 0) - robot.HeadingRadians); } } }
public static bool Equivalent(this PointF a, PointF b, float epsilon = 0.01f) => a.Distance(b) < epsilon;
public Operations HandleScanedRobot(AdvancedRobot robot, ScannedRobotEvent e, ScannedRobotEvent previousScaned, Operations operations, BattleEvents battleEvents) { var newOperations = operations.Clone(); double absoluteBearing = robot.HeadingRadians + e.BearingRadians; PointF myLocation = new PointF((float)robot.X, (float)robot.Y); PointF predictedLocation = projectMotion(myLocation, absoluteBearing, e.Distance); double predictedHeading; double enemyTurnRate = -Utils.NormalRelativeAngle(expectedHeading - (predictedHeading = expectedHeading = e.HeadingRadians)); double bulletPower = Math.Min(e.Distance < 250 ? 500 / e.Distance : 200 / e.Distance, 3); int time = 0; while ((time++) * (20 - (3 * bulletPower)) < myLocation.Distance(predictedLocation) - 18) { predictedHeading += (enemyTurnRate / 3); predictedLocation = projectMotion(predictedLocation, predictedHeading, e.Velocity); if (!new RectangleF(18, 18, 764, 564).Contains(predictedLocation)) { break; } } double maxValue = Double.MinValue; double angle = 0; do { double value = Math.Abs(Math.Cos(Utils.NormalRelativeAngle(absoluteBearing - angle))) * e.Distance / 150; PointF testedLocation = projectMotion(myLocation, angle, 8); value -= testedLocation.Distance(predictedLocation); value -= testedLocation.Distance(new PointF(400, 300)) / 3; if (!new RectangleF(30, 30, 740, 540).Contains(testedLocation)) { value -= 10000; } if (value > maxValue) { maxValue = value; double turnAngle = angle - robot.HeadingRadians; if (headingEnemy) { newOperations.Ahead = (Math.Cos(turnAngle) > 0 ? 100 : -100); newOperations.TurnRightRadians = (Math.Tan(turnAngle)); } else { var absoluteBearingMedkit = lastMedicalKitEvent.BearingRadians + robot.HeadingRadians; double turn = absoluteBearingMedkit + Math.PI / 2; turn -= Math.Max(0.5, (1 / lastMedicalKitEvent.Distance) * 100) * newOperations.Direction; newOperations.TurnRightRadians = Utils.NormalRelativeAngle(turn - robot.HeadingRadians); newOperations.Ahead = (Math.Cos(turn) > 0 ? 100 : -100); } } } while ((angle += 0.01) < Math.PI * 2); robot.MaxVelocity = (Math.Abs(robot.TurnRemaining) < 30 ? 8 : 8 - Math.Abs(robot.TurnRemaining / 30)); double gunTurn = Utils.NormalRelativeAngle(Math.Atan2(predictedLocation.X - myLocation.X, predictedLocation.Y - myLocation.Y) - robot.GunHeadingRadians); newOperations.TurnGunRightRadians = (gunTurn); if ((Math.Abs(gunTurn) < Math.PI / 9) && (robot.GunHeat == 0.0)) { newOperations.BulletPower = (bulletPower); } newOperations.TurnRadarRightRadians = (2 * Utils.NormalRelativeAngle(absoluteBearing - robot.RadarHeadingRadians)); return(newOperations); }
public static List <Point> FindBoundingContourPoints(IEnumerable <Point> contours, PointF[] boundingPoints) { if (boundingPoints.Length != 2) { return(null); } List <Point> contourPoints = contours.ToList(); List <Point> actualContourPointsList = new List <Point>(); foreach (Point point in contourPoints) { if (!actualContourPointsList.Contains(point)) { actualContourPointsList.Add(point); } else { break; } } PointF firstPoint = boundingPoints[0]; PointF lastPoint = boundingPoints[1]; int firstIndex = -1; int lastIndex = -1; double p1Dist = 10000; double p2Dist = 10000; //Loop through all the points and find the closest points to the bounds for (int i = 0; i < actualContourPointsList.Count; i++) { double dist1 = firstPoint.Distance(actualContourPointsList[i]); double dist2 = lastPoint.Distance(actualContourPointsList[i]); if (dist1 < p1Dist) { p1Dist = dist1; //closestFirstPoint = contourPoints[i]; firstIndex = i; } if (dist2 < p2Dist) { p2Dist = dist2; //closestLastPoint = contourPoints[i]; lastIndex = i; } } List <Point> result = new List <Point>(); //Return all the points that lie between first index and last index int start = firstIndex <= lastIndex ? firstIndex : lastIndex; int end = lastIndex >= firstIndex ? lastIndex : firstIndex; for (int j = start; j <= end; j++) { result.Add(actualContourPointsList[j]); } return(result); }
private double GetBestGapDistance(RBSK rbsk, Action <double> progressCallBack = null) { //Caluclate gap distnace if it hasn't been set //Auto Find the gap distance //Scan from 20 - 300, the range which gives us consistent results is the right one int start = 20; int end = 300; int interval = 1; Video.SetFrame(0); Image <Gray, Byte> firstFrame = Video.GetGrayFrameImage(); Dictionary <int, PointF> nosePoints = new Dictionary <int, PointF>(); for (int i = start; i <= end; i += interval) { using (Image <Gray, Byte> filteredImage = firstFrame.SmoothMedian(5)) using (Image <Gray, Byte> binaryImage = filteredImage.ThresholdBinary(new Gray(30), new Gray(255))) { rbsk.Settings.GapDistance = i; Point[] temp = null; PointF[] mousePoints = RBSKService.RBSKParallel(binaryImage, rbsk, ref temp); if (mousePoints != null) { //We've found a set of points for this gap distance, store it nosePoints.Add(i, mousePoints[2]); } } double progressValue = ((i - start) / ((double)end - start)) * 100; if (progressCallBack != null) { progressCallBack(progressValue); } } const double threshold = 20; PointF? previousPoint = null; List <int> currentSelection = new List <int>(); int bestCounter = 0; double bestDistanceSoFar = -1; foreach (KeyValuePair <int, PointF> kvp in nosePoints) { PointF currentPoint = kvp.Value; //Do we have a value? if (previousPoint.HasValue) { //Is the previous point within the threshold distance of the current point if (currentPoint.Distance(previousPoint.Value) < threshold) { currentSelection.Add(kvp.Key); previousPoint = currentPoint; } else { //We're not within the threshold, compare the current list to see if it's the best if (currentSelection.Count > bestCounter) { bestCounter = currentSelection.Count; bestDistanceSoFar = currentSelection.Average(); } currentSelection.Clear(); previousPoint = null; } } else { previousPoint = currentPoint; } } if (currentSelection.Count > bestCounter) { bestDistanceSoFar = currentSelection.Average(); } if (bestDistanceSoFar == -1) { bestDistanceSoFar = 100; } return(bestDistanceSoFar); }
private LineSegment2D[] FindSpine(LineSegment2D[] lines, RotatedRect rotatedRectangle, Image <Gray, Byte> img, PointF headPoint, PointF tailPoint) { //LineSegment2DF[] initialLines = new LineSegment2DF[2]; //if (!rotatedRectangle.Size.IsEmpty) //{ // //Use one of the smaller boundries from rotatedRect for initial detection // PointF[] vertices = rotatedRectangle.GetVertices(); // PointF p1 = vertices[0]; // PointF p2 = vertices[1]; // PointF p3 = vertices[2]; // PointF p4 = vertices[3]; // //PointF p1 = new PointF(rotatedRectangle.Left, rotatedRectangle.Top); // //PointF p2 = new PointF(rotatedRectangle.Left, rotatedRectangle.Bottom); // //PointF p3 = new PointF(rotatedRectangle.Right, rotatedRectangle.Bottom); // //PointF p4 = new PointF(rotatedRectangle.Right, rotatedRectangle.Top); // if (p2.DistanceSquared(p1) < p2.DistanceSquared(p3)) // { // //p1 and p2 are paired, p3 and p4 are paired // initialLines[0] = new LineSegment2DF(p1, p2); // initialLines[1] = new LineSegment2DF(p3, p4); // } // else // { // //p2 and p3 are paired, p1 and p4 are paired // initialLines[0] = new LineSegment2DF(p2, p3); // initialLines[1] = new LineSegment2DF(p1, p4); // } //} //else //{ // //Use one of the image sides for intial detection // initialLines[1] = new LineSegment2DF(new PointF(0, 0), new PointF(0, img.Height - 1)); // initialLines[0] = new LineSegment2DF(new PointF(img.Width - 1, 0), new PointF(img.Width - 1, img.Height - 1)); // //initialLines[0] = new LineSegment2DF(new PointF(0, 0), new PointF(img.Width - 1, 0)); // //initialLines[1] = new LineSegment2DF(new PointF(0 - 1, img.Height-1), new PointF(img.Width - 1, img.Height - 1)); //} //Find closest line segment to initial line double minDistance = double.MaxValue; LineSegment2D?targetLine = null; foreach (LineSegment2D line in lines) { //double minDistance1 = MathExtension.MinDistanceFromLineToPoint(initialLines[0].P1, initialLines[0].P2, line.P1); //double minDistance2 = MathExtension.MinDistanceFromLineToPoint(initialLines[0].P1, initialLines[0].P2, line.P2); double minDistance1 = headPoint.DistanceSquared(line.P1); double minDistance2 = headPoint.DistanceSquared(line.P2); double currentDist = minDistance1 < minDistance2 ? minDistance1 : minDistance2; if (currentDist < minDistance) { minDistance = currentDist; targetLine = line; } } List <LineSegment2D> previousLines = new List <LineSegment2D>(); //We have our target line, try to traverse to the other side LineSegment2D?nextLine = null; if (targetLine.HasValue) { previousLines.Add(targetLine.Value); } do { GetValue(lines, tailPoint, previousLines.ToArray(), targetLine, ref nextLine); if (nextLine.HasValue) { targetLine = nextLine; previousLines.Add(nextLine.Value); } }while (nextLine.HasValue); if (previousLines.Count == 0) { return(null); } double minDistanceFromEnd1 = tailPoint.Distance(previousLines.Last().P1); //MathExtension.MinDistanceFromLineToPoint(initialLines[1].P1, initialLines[1].P2, previousLines.Last().P1)); double minDistanceFromEnd2 = tailPoint.Distance(previousLines.Last().P2); //MathExtension.MinDistanceFromLineToPoint(initialLines[1].P1, initialLines[1].P2, previousLines.Last().P2); if (minDistanceFromEnd1 < 30 || minDistanceFromEnd2 < 30) { //Made it! return(previousLines.ToArray()); } minDistance = double.MaxValue; targetLine = null; foreach (var line in lines) { double minDistance1 = tailPoint.Distance(line.P1); //MathExtension.MinDistanceFromLineToPoint(initialLines[1].P1, initialLines[1].P2, line.P1)); double minDistance2 = tailPoint.Distance(line.P2); //MathExtension.MinDistanceFromLineToPoint(initialLines[1].P1, initialLines[1].P2, line.P2)); double currentDist = minDistance1 < minDistance2 ? minDistance1 : minDistance2; if (currentDist < minDistance) { minDistance = currentDist; targetLine = line; } } List <LineSegment2D> previousLines2 = new List <LineSegment2D>(); //We have our target line, try to traverse to the other side nextLine = null; if (targetLine.HasValue) { previousLines2.Add(targetLine.Value); } do { GetValue(lines, headPoint, previousLines2.ToArray(), targetLine, ref nextLine); if (nextLine.HasValue) { targetLine = nextLine; previousLines2.Add(nextLine.Value); } }while (nextLine.HasValue); previousLines2.Reverse(); previousLines.AddRange(previousLines2); return(previousLines.ToArray()); }
public Meteor(Hex.OffsetCoordinates meteorCoordinates, int health, int damage, HexagonNeighborDirection movementDirection) : base(Player.None, health, ObjectType.Meteor, 1) { this.MovementDirection = movementDirection; this.ObjectCoordinates = meteorCoordinates; this.CollisionDamage = damage; int meteorRadius = 15; //TODO: make meteor size dependent on it's damage this.ObjectAppearance = new List <DrawableShape> { new Ellipse(new Point(-meteorRadius, -meteorRadius), Colors.DarkGray, new Size(2 * meteorRadius, 2 * meteorRadius)), }; var darkSpots = new List <Ellipse>(); Random rand = new Random(); int minSpotRadius = meteorRadius / 7; int maxSpotRadius = meteorRadius / 5; for (int i = 0; i < 20; i++) { var spotRadius = rand.Next(minSpotRadius, maxSpotRadius + 1); var r = rand.Next(spotRadius, meteorRadius - spotRadius); var phi = 2 * Math.PI * rand.NextDouble(); int x = (int)(r * Math.Cos(phi)) - spotRadius; int y = (int)(r * Math.Sin(phi)) - spotRadius; var spotCenter = new PointF(x + spotRadius, y + spotRadius); if (!darkSpots.Any(existingSpot => spotCenter.Distance(existingSpot.Origin + existingSpot.Size / 2) < spotRadius + existingSpot.Size.Width)) { darkSpots.Add(new Ellipse(new Point(x, y), Colors.DimGray, new Size(2 * spotRadius, 2 * spotRadius))); } } this.ObjectAppearance.AddRange(darkSpots); var flameSweepsOnMeteor = new Dictionary <Color, double> { { Colors.Orange, 2 * Math.PI / 3 }, { Colors.Red, Math.PI / 4 } }; var flameSpanAngle = Math.PI / 4; foreach (var flameSweep in flameSweepsOnMeteor) { float flameBaseLengthHalf = meteorRadius * (float)Math.Sin(flameSweep.Value / 2); float flameHeight = flameBaseLengthHalf / (float)Math.Tan(flameSpanAngle / 2); float flameTipOffset = meteorRadius * (float)Math.Cos(flameSweep.Value / 2) + flameHeight; // arcSpanAngle = 180 - 2 * (90 - flameSpanAngle/2) = 180 - 180 + 2 * flameSpanAngle/2 = flameSpanAngle float arcRadius = flameHeight / (float)Math.Sin(flameSpanAngle); var pathComponents = new List <DrawableShape> { new Arc(new Point(-meteorRadius, -meteorRadius), new SizeF(2 * meteorRadius, 2 * meteorRadius), 180 - (float)(flameSweep.Value.ToDegrees() / 2), (float)flameSweep.Value.ToDegrees()), new Arc(new PointF(-flameTipOffset - arcRadius, -2 * arcRadius), new SizeF(2 * arcRadius, 2 * arcRadius), 90 - (float)flameSpanAngle.ToDegrees(), (float)flameSpanAngle.ToDegrees()), new Arc(new PointF(-flameTipOffset - arcRadius, 0), new SizeF(2 * arcRadius, 2 * arcRadius), -90, (float)flameSpanAngle.ToDegrees()) }; this.ObjectAppearance.Add(new Path(new Point(0, 0), flameSweep.Key, pathComponents)); } }
public List <List <PointF> > FindKeyPoints(Point[] points, int numberOfSlides, bool removeDuplicates = true) { //Stopwatch sw = new Stopwatch(); //sw.Start(); //Point[] allPoints = points.ToArray(); List <List <PointF> > result = new List <List <PointF> >(); if (points.Length <= 1) { return(result); } int listCounter = 0; for (int i = 0; i <= numberOfSlides; i++) { result.Add(new List <PointF>()); } List <PointF> visitedPoints = new List <PointF>(); PointF currentPoint = points[0]; if (removeDuplicates) { visitedPoints.Add(currentPoint); } double distanceCounter = 0; double offset = Settings.GapDistance / numberOfSlides; result[listCounter].Add(currentPoint); listCounter++; if (listCounter > numberOfSlides) { listCounter = 0; } int pointCounter = 0; int targetLimit = Settings.NumberOfPoints + 1; int limitCounter = 0; int?targetList = null; while (true) { Point targetPoint = points[pointCounter]; double dist = currentPoint.Distance(targetPoint); if (distanceCounter + dist >= offset) { StraightLine line = new StraightLine(currentPoint, targetPoint); double addOn = offset - distanceCounter; PointF keyPoint = line.DistanceFromStartFloat(addOn); result[listCounter].Add(keyPoint); if (listCounter == targetList) { limitCounter++; if (limitCounter == targetLimit) { break; } } listCounter++; if (listCounter > numberOfSlides) { listCounter = 0; } currentPoint = keyPoint; distanceCounter = 0; } else { distanceCounter += dist; currentPoint = points[pointCounter]; pointCounter++; if (pointCounter == points.Length) { targetList = listCounter; pointCounter -= points.Length; } if (removeDuplicates) { if (visitedPoints.Contains(points[pointCounter])) { break; } else { visitedPoints.Add(points[pointCounter]); } } } } //sw.Stop(); //Console.WriteLine("FindKeyPoints: " + sw.ElapsedMilliseconds); return(result); }
private Dictionary <int, ISingleFrameResult> GenerateDictionary() { //const int SecondBinaryThresold = 10; const double movementDelta = 15; Services.RBSK.RBSK rbsk = MouseService.GetStandardMouseRules(); if (GapDistance <= 0) { GapDistance = GetBestGapDistance(rbsk); } rbsk.Settings.GapDistance = GapDistance; rbsk.Settings.BinaryThreshold = ThresholdValue; Dictionary <int, ISingleFrameResult> results = new Dictionary <int, ISingleFrameResult>(); Video.Reset(); int counter = 0; int frameCount = Video.FrameCount; while (true) { if (Paused) { continue; } if (Cancelled) { break; } using (Image <Bgr, byte> frame = Video.GetFrameImage()) { if (frame == null) { break; } if (Roi != Rectangle.Empty) { frame.ROI = Roi; } double waist, waistArea, waistArea2, waistArea3, waistArea4; PointF centroid; //if (counter == 500) //{ // frame.ROI = new Rectangle(0,0,1,1); //} PointF[] headPoints = ProcessFrame(frame, rbsk, out waist, out waistArea, out waistArea2, out waistArea3, out waistArea4, out centroid, true); if (Roi != Rectangle.Empty) { centroid.X += Roi.X; centroid.Y += Roi.Y; if (headPoints != null) { headPoints[0].X += Roi.X; headPoints[0].Y += Roi.Y; headPoints[1].X += Roi.X; headPoints[1].Y += Roi.Y; headPoints[2].X += Roi.X; headPoints[2].Y += Roi.Y; headPoints[3].X += Roi.X; headPoints[3].Y += Roi.Y; headPoints[4].X += Roi.X; headPoints[4].Y += Roi.Y; } } //Console.WriteLine(waist + " " + waistArea); //if (headPoints != null) //{ // foreach (var point in headPoints) // { // frame.Draw(new CircleF(point, 2), new Bgr(Color.Yellow), 2); // } //} //ImageViewer.Show(frame); ISingleFrameResult frameResult = ModelResolver.Resolve <ISingleFrameResult>(); frameResult.HeadPoints = headPoints; frameResult.CentroidSize = waist; frameResult.PelvicArea = waistArea; frameResult.PelvicArea2 = waistArea2; frameResult.PelvicArea3 = waistArea3; frameResult.PelvicArea4 = waistArea4; frameResult.Centroid = centroid; results.Add(counter, frameResult); counter++; if (ProgressUpdates != null) { ProgressUpdates(this, new RBSKVideoUpdateEvent((double)counter / frameCount)); } } } if (Cancelled) { return(results); } //Find the most confident run of head detections List <List <HeadPointHolder> > confidentPoints = new List <List <HeadPointHolder> >(); PointF lastPoint = PointF.Empty; List <HeadPointHolder> currentList = new List <HeadPointHolder>(); double currentTotalMovement = 0; for (int i = 0; i < results.Count; i++) { PointF[] headPoints = results[i].HeadPoints; if (headPoints == null) { //No head found, use alternative methods if (currentList.Count > 0) { confidentPoints.Add(currentList); } currentList = new List <HeadPointHolder>(); lastPoint = PointF.Empty; currentTotalMovement = 0; //Console.WriteLine("Head points are null " + i); continue; } //Check against expected position PointF currentPoint = headPoints[2]; if (lastPoint.IsEmpty) { lastPoint = currentPoint; currentList.Add(new HeadPointHolder(i, currentPoint, currentTotalMovement)); continue; } double distance = lastPoint.Distance(currentPoint); if (distance < movementDelta) { //Acceptable currentTotalMovement += distance; currentList.Add(new HeadPointHolder(i, currentPoint, currentTotalMovement)); lastPoint = currentPoint; } else { if (currentList.Count > 0) { confidentPoints.Add(currentList); } currentList = new List <HeadPointHolder>(); lastPoint = PointF.Empty; currentTotalMovement = 0; //Console.WriteLine("Outside of range " + i); } } if (currentList.Count > 0) { confidentPoints.Add(currentList); } if (confidentPoints.Count == 0) { return(results); } //Find longest list with highest total movement List <HeadPointHolder> bestList = confidentPoints[0]; //double currentMaxTraverse = bestList.Last().TotalDelta; foreach (List <HeadPointHolder> list in confidentPoints) { //double currentTotalDelta = list.Last().TotalDelta; if (list.Count > bestList.Count) { //currentMaxTraverse = currentTotalDelta; bestList = list; } } //We now have a confident set of headpoints int minIndex = bestList.Select(x => x.FrameNumber).Min(); int maxIndex = bestList.Select(x => x.FrameNumber).Max(); minIndex--; while (minIndex >= 0) { //Traverse backwards PointF[] lastPoints = results[minIndex + 1].HeadPoints; if (lastPoints != null) { lastPoint = lastPoints[2]; } else { lastPoint = new PointF(-100, -100); } PointF[] headPoints = results[minIndex].HeadPoints; if (headPoints == null) { //No head found, use alternative methods int previousThreshold = rbsk.Settings.BinaryThreshold; rbsk.Settings.BinaryThreshold = ThresholdValue2; Video.SetFrame(minIndex); PointF[] headPoints2 = null; using (Image <Bgr, byte> frame = Video.GetFrameImage()) { if (frame == null) { break; } if (Roi != Rectangle.Empty) { frame.ROI = Roi; } headPoints2 = ProcessFrame(frame, rbsk, lastPoint, movementDelta); } rbsk.Settings.BinaryThreshold = previousThreshold; if (headPoints2 != null) { //We've got a good location //double temp = results[minIndex].CentroidSize; results[minIndex].HeadPoints = headPoints2; //results[minIndex].CentroidSize = temp; //results[minIndex] = new Tuple<PointF[], double>(headPoints2, temp); } else { for (int i = 0; i <= minIndex; i++) { if (results.ContainsKey(i)) { //double temp = results[i].Item2; //results[i] = new Tuple<PointF[], double>(null, temp); results[i].HeadPoints = null; } } break; } minIndex--; continue; } //Check against expected position PointF currentPoint = headPoints[2]; if (lastPoint.Distance(currentPoint) < movementDelta) { //Good point } else { //Wrong point, search for another rbsk that falls within range //if (minIndex == 17 || minIndex == 16) //{ // Console.WriteLine(""); //} Video.SetFrame(minIndex); PointF[] headPoints2 = null; using (Image <Bgr, byte> frame = Video.GetFrameImage()) { if (frame == null) { break; } if (Roi != Rectangle.Empty) { frame.ROI = Roi; } headPoints2 = ProcessFrame(frame, rbsk, lastPoint, movementDelta); } if (headPoints2 != null) { //We've got a good location //double temp = results[maxIndex].Item2; //results[minIndex] = new Tuple<PointF[], double>(headPoints2, temp); results[minIndex].HeadPoints = headPoints2; } else { //No other rbsk falls within range, use alternative methods //Console.WriteLine("Need to use alternative methods"); for (int i = 0; i <= minIndex; i++) { if (results.ContainsKey(i)) { //double temp = results[i].Item2; //results[i] = new Tuple<PointF[], double>(null, temp); results[i].HeadPoints = null; } } break; } } minIndex--; } maxIndex++; while (maxIndex < results.Count) { //Traverse backwards PointF[] lastPoints = results[maxIndex - 1].HeadPoints; if (lastPoints != null) { lastPoint = lastPoints[2]; } else { lastPoint = new PointF(-100, -100); } PointF[] headPoints = results[maxIndex].HeadPoints; if (headPoints == null) { //No head found, use alternative methods int previousThreshold = rbsk.Settings.BinaryThreshold; rbsk.Settings.BinaryThreshold = ThresholdValue2; Video.SetFrame(maxIndex); PointF[] headPoints2 = null; using (Image <Bgr, byte> frame = Video.GetFrameImage()) { if (frame == null) { break; } if (Roi != Rectangle.Empty) { frame.ROI = Roi; } headPoints2 = ProcessFrame(frame, rbsk, lastPoint, movementDelta); } rbsk.Settings.BinaryThreshold = previousThreshold; if (headPoints2 != null) { //We've got a good location //double temp = results[maxIndex].Item2; //results[maxIndex] = new Tuple<PointF[], double>(headPoints2, temp); results[maxIndex].HeadPoints = headPoints2; } else { int max = results.Keys.Max(); for (int i = maxIndex; i <= max; i++) { if (results.ContainsKey(i)) { //double temp = results[i].Item2; //results[i] = new Tuple<PointF[], double>(null, temp); results[i].HeadPoints = null; } } break; } maxIndex++; continue; } //Check against expected position PointF currentPoint = headPoints[2]; if (lastPoint.Distance(currentPoint) < movementDelta) { //Good point } else { //Wrong point, search for another rbsk that falls within range Video.SetFrame(maxIndex); PointF[] headPoints2 = null; using (Image <Bgr, byte> frame = Video.GetFrameImage()) { if (frame == null) { break; } if (Roi != Rectangle.Empty) { frame.ROI = Roi; } headPoints2 = ProcessFrame(frame, rbsk, lastPoint, movementDelta); } if (headPoints2 != null) { //We've got a good location //double temp = results[maxIndex].Item2; //results[maxIndex] = new Tuple<PointF[], double>(headPoints2, temp); results[maxIndex].HeadPoints = headPoints2; } else { //No other rbsk falls within range, use alternative methods //Console.WriteLine("Need to use alternative methods"); int max = results.Keys.Max(); for (int i = maxIndex; i <= max; i++) { if (results.ContainsKey(i)) { //double temp = results[i].Item2; //results[i] = new Tuple<PointF[], double>(null, temp); results[i].HeadPoints = null; } } break; } } maxIndex++; } return(results); }
private void EditorWindow_MouseMove(object sender, MouseEventArgs e) { StatusBar.Message($"X: {e.X} , Y: {e.Y}"); if (ActiveCommand != DrawCommands.Noun && clickCount >= 1) { //delta_Y = p2.Sub(e.Location); var offsetPoint = new PointF(offsetX, offsetY).Scale(Zoom); p2 = (new PointF(e.X, e.Y).Sub(offsetPoint)).Scale(1 / Zoom); switch (ActiveCommand) { case DrawCommands.Line: #region Line tempShape = new GLine(p1, p2); #endregion break; case DrawCommands.Circle: #region Circle tempShape = new GCircle(p1, p1.Distance(p2)); Debug.WriteLine($"x:{p1.X},Y:{p1.Y},R:{p1.Distance(p2)}"); Debug.WriteLine($"offsetX:{offsetX},OffsetY:{ offsetY}"); #endregion break; case DrawCommands.Rectangle: #region Rectangle tempShape = new GRectangle(p1, p2); #endregion break; case DrawCommands.PolyLine: #region PolyLine tempShape = tempPolyLine; if (clickCount == 1) { if (tempPolyLine == null) { tempPolyLine = new GPolyLine(); tempPolyLine.Lines.Add(new GLine(p1, p2)); } else { tempPolyLine.Lines.LastOrDefault().EndPoint = p2; } } else if (clickCount == 2) { //check end line position to exit or continue drawing. var prevLine = tempPolyLine.Lines.LastOrDefault(); tempPolyLine.Lines.Add(new GLine(prevLine.EndPoint, p2)); if (p2.Distance(tempPolyLine.Lines.FirstOrDefault().StartPoint) < Setup.Snap) { GeometryEngine.AddShape(tempShape); clickCount = 0; tempShape = null; tempPolyLine = null; // ActiveCommand = DrawCommands.Noun; } else { clickCount--; } } #endregion break; case DrawCommands.Curve: #region Curve if (clickCount == 1) { tempShape = new GLine(p1, p2); } else if (clickCount == 2) { if (tempShape is GCurve) { ((GCurve)tempShape).Center = p2; } else { var l = (GLine)tempShape; tempShape = new GCurve(l.StartPoint, p2, l.EndPoint); } } else if (clickCount == 3) { ((GCurve)tempShape).Center = p2; GeometryEngine.AddShape(tempShape); clickCount = 0; } #endregion break; case DrawCommands.Parabola: #region Parabola if (clickCount == 1) { tempShape = new GLine(p1, p2); } else if (clickCount == 2) { if (tempShape is GParabola) { ((GParabola)tempShape).Points[2] = p2; } else { var l = (GLine)tempShape; tempShape = new GParabola(l.StartPoint, l.EndPoint, p2); } } else if (clickCount == 3) { ((GParabola)tempShape).Points[2] = p2; GeometryEngine.AddShape(tempShape); clickCount = 0; } #endregion break; case DrawCommands.Clear: break; case DrawCommands.Noun: break; default: break; } EditorWindow.Invalidate(); } else if (clickCount == 0) { MouseEventArgs mouse = e as MouseEventArgs; if (mouse.Button == MouseButtons.Left) { Point mousePosNow = mouse.Location; int deltaX = mousePosNow.X - mouseDown.X; // the distance the mouse has been moved since mouse was pressed int deltaY = mousePosNow.Y - mouseDown.Y; offsetX = (int)(startx + (deltaX / Zoom)); // calculate new offset of image based on the current zoom factor offsetY = (int)(starty + (deltaY / Zoom)); EditorWindow.Invalidate(); } } }
public List <PointF> FindKeyPoints(Point[] points, float offset = 0, bool removeDuplicates = true) { //Stopwatch sw = new Stopwatch(); //sw.Start(); //Point[] allPoints = points.ToArray(); List <PointF> result = new List <PointF>(); List <PointF> visitedPoints = new List <PointF>(); PointF currentPoint = points[0]; if (removeDuplicates) { visitedPoints.Add(currentPoint); } double distanceCounter = 0; if (offset == 0) { result.Add(currentPoint); } else { distanceCounter += offset; } int pointCounter = 1; while (true) { Point targetPoint = points[pointCounter]; double dist = currentPoint.Distance(targetPoint); if (distanceCounter + dist >= Settings.GapDistance) { StraightLine line = new StraightLine(currentPoint, targetPoint); double addOn = Settings.GapDistance - distanceCounter; PointF keyPoint = line.DistanceFromStart(addOn); result.Add(keyPoint); currentPoint = keyPoint; distanceCounter = 0; } else { distanceCounter += dist; currentPoint = points[pointCounter]; pointCounter++; if (pointCounter == points.Length) { break; } if (removeDuplicates) { if (visitedPoints.Contains(points[pointCounter])) { break; } else { visitedPoints.Add(points[pointCounter]); } } } } //sw.Stop(); //Console.WriteLine("FindKeyPoints: " + sw.ElapsedMilliseconds); return(result); }
public void FindTail(Point[] mouseContour, PointF[] spine, Image <Bgr, Byte> drawImage, double width, PointF centroid, out List <Point> bodyPoints, out double waistLength, out double pelvicArea, out double pelvicArea2) { //Generate graph for both sides of spine List <Tuple <PointF, double> > r1Distances = new List <Tuple <PointF, double> >(); List <Tuple <PointF, double> > r2Distances = new List <Tuple <PointF, double> >(); double halfWidth = width / 2; double quarterWidth = halfWidth / 2; //Console.WriteLine("Quarter Width: " + quarterWidth); //bool bodyStarted1 = false, bodyStarted2 = false; //bool bodyEnded1 = false, bodyEnded2 = false; PointF r1BodyStart = PointF.Empty, r1BodyEnd = PointF.Empty, r2BodyStart = PointF.Empty, r2BodyEnd = PointF.Empty; for (int i = 1; i < spine.Length; i++) { LineSegment2DF line = new LineSegment2DF(spine[i - 1], spine[i]); //Create direction vector Vector lineDirection = new Vector(line.P2.X - line.P1.X, line.P2.Y - line.P1.Y); lineDirection.Normalize(); //Create vector perpendicular to spine Vector r1 = new Vector(lineDirection.Y, -lineDirection.X); Vector r2 = new Vector(-lineDirection.Y, lineDirection.X); //Get starting point Vector startingPoint = new Vector(line.P1.X, line.P1.Y); //We have our vectors for this part of the spine, iterate over spine length by 1 double length = line.Length; for (int spinePos = 0; spinePos < length; spinePos++) { Vector p = startingPoint + (spinePos * lineDirection); Vector test = p + (r1 * 300); Vector test2 = p + (r2 * 300); PointF start = new PointF((float)p.X, (float)p.Y); PointF p1 = new PointF((float)test.X, (float)test.Y); PointF p2 = new PointF((float)test2.X, (float)test2.Y); PointF intersect1 = MathExtension.PolygonLineIntersectionPoint(start, p1, mouseContour); PointF intersect2 = MathExtension.PolygonLineIntersectionPoint(start, p2, mouseContour); if (!intersect1.IsEmpty) { double distance = intersect1.Distance(start); r1Distances.Add(new Tuple <PointF, double>(intersect1, distance)); } if (!intersect2.IsEmpty) { double distance = intersect2.Distance(start); r2Distances.Add(new Tuple <PointF, double>(intersect2, distance)); } } } //Iterate forwards to find body start, backwards to find body end int r1Count = r1Distances.Count; for (int i = 0; i < r1Count; i++) { Tuple <PointF, double> currentItem = r1Distances.ElementAt(i); if (currentItem.Item2 > quarterWidth) { r1BodyStart = currentItem.Item1; break; } } for (int i = r1Count - 1; i >= 0; i--) { Tuple <PointF, double> currentItem = r1Distances.ElementAt(i); if (currentItem.Item2 > quarterWidth) { r1BodyEnd = currentItem.Item1; break; } } int r2Count = r2Distances.Count; for (int i = 0; i < r2Count; i++) { Tuple <PointF, double> currentItem = r2Distances.ElementAt(i); if (currentItem.Item2 > quarterWidth) { r2BodyStart = currentItem.Item1; break; } } for (int i = r2Count - 1; i >= 0; i--) { Tuple <PointF, double> currentItem = r2Distances.ElementAt(i); if (currentItem.Item2 > quarterWidth) { r2BodyEnd = currentItem.Item1; break; } } if (r1BodyStart.IsEmpty || r1BodyEnd.IsEmpty || r2BodyStart.IsEmpty || r2BodyEnd.IsEmpty) { bodyPoints = null; waistLength = -1; pelvicArea = -1; pelvicArea2 = -1; return; } Point[] alternateSegment1 = MathExtension.GetSegmentOfPolygon(mouseContour, r1BodyStart, r2BodyStart); Point[] alternateSegment2 = MathExtension.GetSegmentOfPolygon(mouseContour, r1BodyEnd, r2BodyEnd); if (alternateSegment1 == null || alternateSegment1.Length == 0 || alternateSegment2 == null || alternateSegment2.Length == 0) { bodyPoints = null; waistLength = -1; pelvicArea = -1; pelvicArea2 = -1; return; } for (int i = 1; i < alternateSegment1.Length; i++) { LineSegment2D line = new LineSegment2D(alternateSegment1[i - 1], alternateSegment1[i]); drawImage.Draw(line, new Bgr(Color.Green), 2); } for (int i = 1; i < alternateSegment2.Length; i++) { LineSegment2D line = new LineSegment2D(alternateSegment2[i - 1], alternateSegment2[i]); drawImage.Draw(line, new Bgr(Color.Red), 2); } Point[] bodySegment1 = MathExtension.GetSegmentOfPolygon(mouseContour, r1BodyStart, r1BodyEnd); Point[] bodySegment2 = MathExtension.GetSegmentOfPolygon(mouseContour, r2BodyStart, r2BodyEnd); if (bodySegment1 == null || bodySegment2 == null || bodySegment1.Length == 0 || bodySegment2.Length == 0) { bodyPoints = null; waistLength = -1; pelvicArea = -1; pelvicArea2 = -1; return; } double d1 = alternateSegment2[0].DistanceSquared(bodySegment2[0]); double d2 = alternateSegment2[0].DistanceSquared(bodySegment2.Last()); double d3 = alternateSegment2[0].DistanceSquared(bodySegment1[0]); double d4 = alternateSegment2[0].DistanceSquared(bodySegment1.Last()); Point[] noTailPoints = null; if (d1 < d2 && d1 < d3 && d1 < d4) { Point[] p1 = bodySegment2.Reverse().ToArray(); Point[] p2 = alternateSegment2; Point[] p3 = null; double f1 = alternateSegment2.Last().DistanceSquared(bodySegment1[0]); double f2 = alternateSegment2.Last().DistanceSquared(bodySegment1.Last()); if (f1 < f2) { p3 = bodySegment1; } else { p3 = bodySegment1.Reverse().ToArray(); } noTailPoints = p1.Concat(p2).Concat(p3).ToArray(); } else if (d2 < d3 && d2 < d4) { Point[] p1 = bodySegment2; Point[] p2 = alternateSegment2; Point[] p3 = null; double f1 = alternateSegment2.Last().DistanceSquared(bodySegment1[0]); double f2 = alternateSegment2.Last().DistanceSquared(bodySegment1.Last()); if (f1 < f2) { p3 = bodySegment1; } else { p3 = bodySegment1.Reverse().ToArray(); } noTailPoints = p1.Concat(p2).Concat(p3).ToArray(); } else if (d3 < d4) { Point[] p1 = bodySegment1; Point[] p2 = alternateSegment2; Point[] p3 = null; double f1 = alternateSegment2.Last().DistanceSquared(bodySegment2[0]); double f2 = alternateSegment2.Last().DistanceSquared(bodySegment2.Last()); if (f1 < f2) { p3 = bodySegment2; } else { p3 = bodySegment2.Reverse().ToArray(); } noTailPoints = p1.Concat(p2).Concat(p3).ToArray(); } else { Point[] p1 = bodySegment1; Point[] p2 = alternateSegment2; Point[] p3 = null; double f1 = alternateSegment2.Last().DistanceSquared(bodySegment2[0]); double f2 = alternateSegment2.Last().DistanceSquared(bodySegment2.Last()); if (f1 < f2) { p3 = bodySegment2; } else { p3 = bodySegment2.Reverse().ToArray(); } noTailPoints = p1.Concat(p2).Concat(p3).ToArray(); } RotatedRect rotatedRect = CvInvoke.MinAreaRect(noTailPoints.Select(x => new PointF(x.X, x.Y)).ToArray()); //bodyPoints = new List<Point>(noTailPoints); //PointF lastTail = alternateSegment1[0]; //PointF[] allBody = bodySegment1.Concat(bodySegment2.Reverse()).Select(x => new PointF(x.X, x.Y)).ToArray(); //Point[] allBody = mouseContour; double spineDistance1 = SpineExtension.FindDistanceAlongSpine(spine, centroid); double spineDistance2 = SpineExtension.FindDistanceAlongSpine(spine, alternateSegment1[0]); double halfWayDistance = (spineDistance1 + spineDistance2) / 2d; //Console.WriteLine("Spine Distance from point: " + spineDistance1); //spineDistance1 += 50; PointF intersection; Vector targetDirection2; PointF intersection2; Vector targetDirection3; PointF intersection3; Vector targetDirection4; bool result = SpineExtension.GetPerpendicularLineDistanceFromBase(spine, spineDistance1, out intersection, out targetDirection2); bool result2 = SpineExtension.GetPerpendicularLineDistanceFromBase(spine, halfWayDistance, out intersection2, out targetDirection3); bool result3 = SpineExtension.GetPerpendicularLineDistanceFromBase(spine, spineDistance2, out intersection3, out targetDirection4); PointF[] temp = rotatedRect.GetVertices(); bool widthShorter = temp[1].DistanceSquared(temp[0]) < temp[1].DistanceSquared(temp[2]); Vector targetDirection; if (widthShorter) { targetDirection = new Vector(temp[1].X - temp[0].X, temp[1].Y - temp[0].Y); } else { targetDirection = new Vector(temp[1].X - temp[2].X, temp[1].Y - temp[2].Y); } if (!result) { //Console.WriteLine("Unable to get perpendiular length"); bodyPoints = null; waistLength = -1; pelvicArea = -1; pelvicArea2 = -1; return; } PointF i1 = new PointF(intersection.X + (float)(targetDirection.X * 100), intersection.Y + (float)(targetDirection.Y * 100)); PointF i2 = new PointF(intersection.X + (float)(targetDirection.X * -100), intersection.Y + (float)(targetDirection.Y * -100)); PointF i3 = new PointF(intersection2.X + (float)(targetDirection.X * 100), intersection2.Y + (float)(targetDirection.Y * 100)); PointF i4 = new PointF(intersection2.X + (float)(targetDirection.X * -100), intersection2.Y + (float)(targetDirection.Y * -100)); PointF i5 = new PointF(intersection3.X + (float)(targetDirection.X * 100), intersection3.Y + (float)(targetDirection.Y * 100)); PointF i6 = new PointF(intersection3.X + (float)(targetDirection.X * -100), intersection3.Y + (float)(targetDirection.Y * -100)); PointF bodyI1 = MathExtension.PolygonLineIntersectionPoint(intersection, i1, mouseContour); PointF bodyI2 = MathExtension.PolygonLineIntersectionPoint(intersection, i2, mouseContour); PointF bodyI3 = MathExtension.PolygonLineIntersectionPoint(intersection2, i3, mouseContour); PointF bodyI4 = MathExtension.PolygonLineIntersectionPoint(intersection2, i4, mouseContour); PointF bodyI5 = MathExtension.PolygonLineIntersectionPoint(intersection3, i5, mouseContour); PointF bodyI6 = MathExtension.PolygonLineIntersectionPoint(intersection3, i6, mouseContour); //drawImage.Draw(new CircleF(bodyI1, 4), new Bgr(Color.Red), 3); //drawImage.Draw(new CircleF(bodyI2, 4), new Bgr(Color.Red), 3); //drawImage.Draw(new CircleF(bodyI3, 4), new Bgr(Color.Red), 3); //drawImage.Draw(new CircleF(bodyI4, 4), new Bgr(Color.Red), 3); //drawImage.Draw(new CircleF(bodyI5, 4), new Bgr(Color.Red), 3); //drawImage.Draw(new CircleF(bodyI6, 4), new Bgr(Color.Red), 3); //drawImage.Draw(new LineSegment2DF(bodyI3, bodyI4), new Bgr(Color.Yellow), 3); //drawImage.Draw(new LineSegment2DF(bodyI5, bodyI6), new Bgr(Color.Red), 3); drawImage.Draw(new LineSegment2DF(bodyI1, bodyI2), new Bgr(Color.MediumPurple), 3); //drawImage.Draw(new LineSegment2DF(bodyI3, bodyI4), new Bgr(Color.MediumPurple), 3); waistLength = bodyI1.Distance(bodyI2); //Console.WriteLine("Waist Length = " + waistLength); //List<Point> tempBodyPoints = new List<Point>(); //double r1BodyStartToTail = r1BodyStart.DistanceSquared(alternateSegment1[0]); //double r1BodyEndToTail = r1BodyEnd.DistanceSquared(alternateSegment1[0]); //bool startCloser = r1BodyStartToTail < r1BodyEndToTail; //if (!r1BodyStart.IsEmpty && !r1BodyEnd.IsEmpty) //{ // //Find segment from mouse contour // Point[] bodySegment = MathExtension.GetSegmentOfPolygon(mouseContour, r1BodyStart, r1BodyEnd); // //tempBodyPoints.AddRange(bodySegment); // ////PointF midPoint = r1BodyStart.MidPoint(r1BodyEnd); // //Point[] newBodySegment; // //if (startCloser) // //{ // // newBodySegment = MathExtension.GetSegmentOfPolygon(mouseContour, bodyI3, bodyI5); // //} // //else // //{ // // newBodySegment = MathExtension.GetSegmentOfPolygon(mouseContour, bodyI5, bodyI3); // //} // //tempBodyPoints.AddRange(newBodySegment); // //for (int i = 1; i < bodySegment.Length; i++) // //{ // // LineSegment2D line = new LineSegment2D(bodySegment[i - 1], bodySegment[i]); // // drawImage.Draw(line, new Bgr(Color.Cyan), 2); // //} //} //if (!r2BodyStart.IsEmpty && !r2BodyEnd.IsEmpty) //{ // //Find segment from mouse contour // Point[] bodySegment = MathExtension.GetSegmentOfPolygon(mouseContour, r2BodyStart, r2BodyEnd); // //tempBodyPoints.AddRange(bodySegment.Reverse()); // ////PointF midPoint = r2BodyStart.MidPoint(r2BodyEnd); // //Point[] newBodySegment; // //if (startCloser) // //{ // // newBodySegment = MathExtension.GetSegmentOfPolygon(mouseContour, bodyI4, bodyI6); // //} // //else // //{ // // newBodySegment = MathExtension.GetSegmentOfPolygon(mouseContour, bodyI6, bodyI4); // //} // //tempBodyPoints.AddRange(newBodySegment.Reverse()); // //for (int i = 1; i < bodySegment.Length; i++) // //{ // // LineSegment2D line = new LineSegment2D(bodySegment[i - 1], bodySegment[i]); // // drawImage.Draw(line, new Bgr(Color.Cyan), 2); // //} //} Point[] bodySegment3 = MathExtension.GetSegmentOfPolygon(mouseContour, r1BodyStart, r1BodyEnd); Point[] bodySegment4 = MathExtension.GetSegmentOfPolygon(mouseContour, r2BodyStart, r2BodyEnd); var bodyPoints2 = new List <Point>(bodySegment3.Concat(bodySegment4.Reverse())); PointF[] bodyPoints2F = bodyPoints2.Select(x => x.ToPointF()).ToArray(); Point[] squareBodyPoints = new Point[] { bodyI3.ToPoint(), bodyI4.ToPoint(), bodyI6.ToPoint(), bodyI5.ToPoint() }; //PointF[] tempBodyPointsF = tempBodyPoints.Select(x => x.ToPointF()).ToArray(); if (bodyPoints2F != null && bodyPoints2F.Length > 0) { var rect1 = CvInvoke.MinAreaRect(bodyPoints2F); rect1.Angle += 90; //CvInvoke.Ellipse(drawImage, rect1, new MCvScalar(0, 0, 255), 3); } pelvicArea = -1; pelvicArea2 = -1; if (squareBodyPoints != null && squareBodyPoints.Length > 0) { var rect2 = CvInvoke.MinAreaRect(squareBodyPoints.Select(x => x.ToPointF()).ToArray()); rect2.Angle += 90; //CvInvoke.Ellipse(drawImage, rect2, new MCvScalar(0, 255, 255), 3); pelvicArea = MathExtension.PolygonArea(squareBodyPoints); //Console.WriteLine("Pelvic Area tail: " + pelvicArea + " - " + (rect2.Size.Height * rect2.Size.Width)); pelvicArea2 = rect2.Size.Height * rect2.Size.Width; } //Ellipse fittedEllipse = PointCollection.EllipseLeastSquareFitting(bodyPoints2F); //CvInvoke.Ellipse(drawImage, fittedEllipse.RotatedRect, new MCvScalar(0, 0, 255), 3); //fittedEllipse = PointCollection.EllipseLeastSquareFitting(tempBodyPointsF); //CvInvoke.Ellipse(drawImage, fittedEllipse.RotatedRect, new MCvScalar(0, 0, 255), 3); //drawImage.DrawPolyline(rect1.GetVertices().Select(x => x.ToPoint()).ToArray(), true, new Bgr(Color.Orange), 4); //drawImage.DrawPolyline(rect2.GetVertices().Select(x => x.ToPoint()).ToArray(), true, new Bgr(Color.Orange), 4); //drawImage.DrawPolyline(fittedEllipse.RotatedRect.GetVertices().Select(x => x.ToPoint()).ToArray(), true, new Bgr(Color.Cyan), 4); bodyPoints = bodyPoints2; //pelvicArea = MathExtension.PolygonArea(squareBodyPoints); //bodyPoints = new List<Point>(new Point[] { bodyI3.ToPoint(), bodyI4.ToPoint(), bodyI6.ToPoint(), bodyI5.ToPoint() }); //bodyPoints = tempBodyPoints; //StringBuilder s1 = new StringBuilder(); //StringBuilder s2 = new StringBuilder(); //foreach (double dist in r1Distances) //{ // s1.Append(dist + ","); //} //foreach (double dist in r2Distances) //{ // s2.Append(dist + ","); //} //System.IO.File.WriteAllText(@"D:\PhD\r1test.txt", s1.ToString()); //System.IO.File.WriteAllText(@"D:\PhD\r2test.txt", s2.ToString()); }