public void PointD_DistanceReturns2ForToPointsPlacedVertically() { PointD p1 = new PointD(3, 4); PointD p2 = new PointD(3, 6); Assert.AreEqual(2, p1.Distance(p2)); }
public void PointD_DistanceReturns5ForToInclinedPoints() { PointD p1 = new PointD(0, 0); PointD p2 = new PointD(4, 3); Assert.AreEqual(5, p1.Distance(p2)); }
private void ChangeSunDiskData(PointD ptCurrMousePosition) { if (ptMouseDown != ptCurrMousePosition) // not just click { switch (currMouseActionRegime) { case MouseActionsRegime.Nothing: break; case MouseActionsRegime.DrawingSunDisk: sunDiskPositionAndSize = new RoundData(ptMouseDown.X, ptMouseDown.Y, ptMouseDown.Distance(ptCurrMousePosition)); break; case MouseActionsRegime.MovingSunDisk: sunDiskPositionAndSize.DCenterX = sunDiskPositionAndSizeBeforeMovingResizing.DCenterX + (ptCurrMousePosition.X - ptMouseDown.X); sunDiskPositionAndSize.DCenterY = sunDiskPositionAndSizeBeforeMovingResizing.DCenterY + (ptCurrMousePosition.Y - ptMouseDown.Y); break; case MouseActionsRegime.ResizingSunDisk: sunDiskPositionAndSize.DRadius = ptCurrMousePosition.Distance(sunDiskPositionAndSize.pointDCircleCenter()); break; default: break; } } }
public void PointD_DistanceReturns1ForToPointsPlacedHorizontally() { PointD p1 = new PointD(3, 4); PointD p2 = new PointD(4, 4); Assert.AreEqual(1, p1.Distance(p2)); }
private void Fire(ScannedRobotEvent e, double absoluteBearing) { absoluteBearing = MyBot.HeadingRadians + e.BearingRadians; //Finding the heading and heading change. double enemyHeading = e.HeadingRadians; double enemyHeadingChange = enemyHeading - _oldEnemyHeading; _oldEnemyHeading = enemyHeading; // Circular Targeting http://robowiki.net/wiki/Circular_Targeting /*This method of targeting is know as circular targeting; you assume your enemy will * keep moving with the same speed and turn rate that he is using at fire time.The * base code comes from the wiki. */ double deltaTime = 0; double predictedX = MyBot.X + e.Distance * Math.Sin(absoluteBearing); double predictedY = MyBot.Y + e.Distance * Math.Cos(absoluteBearing); PointD point = new PointD(MyBot.X, MyBot.Y); while ((++deltaTime) * _bulletSpeed < point.Distance(predictedX, predictedY)) { //Add the movement we think our enemy will make to our enemy's current X and Y predictedX += Math.Sin(enemyHeading) * e.Velocity; predictedY += Math.Cos(enemyHeading) * e.Velocity; //Find our enemy's heading changes. enemyHeading += enemyHeadingChange; //If our predicted coordinates are outside the walls, put them 18 distance units away from the walls as we know //that that is the closest they can get to the wall (Bots are non-rotating 36*36 squares). predictedX = Math.Max(Math.Min(predictedX, MyBot.BattleFieldWidth - 18), 18); predictedY = Math.Max(Math.Min(predictedY, MyBot.BattleFieldHeight - 18), 18); } //Find the bearing of our predicted coordinates from us. double aim = Utils.NormalAbsoluteAngle(Math.Atan2(predictedX - MyBot.X, predictedY - MyBot.Y)); var bullerPower = 400 / e.Distance; //Aim and fire. MyBot.SetTurnGunRightRadians(Utils.NormalRelativeAngle(aim - MyBot.GunHeadingRadians)); MyBot.SetFire(bullerPower); MyBot.SetTurnRadarRightRadians(Utils.NormalRelativeAngle(absoluteBearing - MyBot.RadarHeadingRadians) * 2); }
/// <summary> /// Determines whether the testing point is inside the circle. /// </summary> /// <param name="pt">The testing point.</param> /// <param name="theCircle">The circle.</param> /// <returns>System.Int32: /// -1 => pt is outside the circle /// 0 => pt is at the circle margin /// 1 => pt is inside the circle /// default (for empty circle data) is outside /// </returns> public static int IsPointInsideCircle(this PointD pt, RoundData theCircle, double marginDetectorPrecision = 2.0d) { if (theCircle.IsNull) { return(-1); // default is outside } if (PointD.Distance(pt, theCircle.pointDCircleCenter()) < theCircle.DRadius) { return(1); } if (Math.Abs(PointD.Distance(pt, theCircle.pointDCircleCenter()) - theCircle.DRadius) <= marginDetectorPrecision) { return(0); } return(-1); }
private static int FindNextClosest(List <PathDefWithClosed> Paths) { QuadTreeNode Root = new QuadTreeNode(); PolyLineSet.Bounds B = new PolyLineSet.Bounds(); for (int i = 0; i < Paths.Count; i++) { if (Paths[i].Closed == false) { B.FitPoint(Paths[i].Vertices.First()); B.FitPoint(Paths[i].Vertices.Last()); } } Root.xstart = B.TopLeft.X - 10; Root.xend = B.BottomRight.X + 10; Root.ystart = B.TopLeft.Y - 10; Root.yend = B.BottomRight.Y + 10; for (int i = 0; i < Paths.Count; i++) { if (Paths[i].Closed == false) { Root.Insert(new SegmentEndContainer() { PathID = i, Point = Paths[i].Vertices.First(), Side = SideEnum.Start }, 5); Root.Insert(new SegmentEndContainer() { PathID = i, Point = Paths[i].Vertices.Last(), Side = SideEnum.End }, 5); } } RectangleF R = new RectangleF(); R.Width = 3; R.Height = 3; for (int i = 0; i < Paths.Count; i++) { var P = Paths[i]; if (P.Closed == false) { var PF = P.Vertices[0]; var PF2 = P.Vertices[1]; var PathDir = PF - PF2;// MathHelpers.Difference(PF, PF2); PathDir.Normalize(); R.X = (float)(P.Vertices.First().X - 1.5); R.Y = (float)(P.Vertices.First().Y - 1.5); int startmatch = -1; int endmatch = -1; double closestdistance = B.Width() + B.Height(); Root.CallBackInside(R, delegate(QuadTreeItem QI) { var S = QI as SegmentEndContainer; if (S.PathID == i) { return(true); } if (P.Width != Paths[S.PathID].Width) { return(true); } PointD Dir2; if (S.Side == SideEnum.Start) { var S2 = Paths[S.PathID].Vertices[1]; Dir2 = S2 - S.Point; Dir2.Normalize(); } else { var S2 = Paths[S.PathID].Vertices[Paths[S.PathID].Vertices.Count() - 2]; Dir2 = S2 - S.Point; Dir2.Normalize(); } double dotted = Dir2.Dot(PathDir); var D = PointD.Distance(S.Point, PF); if (D < 1.0) { // D -= dotted * 3.0; if (D < closestdistance) { closestdistance = D; if (S.Side == SideEnum.Start) { startmatch = S.PathID; } else { endmatch = S.PathID; } } } return(true); }); if (startmatch > -1 || endmatch > -1) { if (endmatch > -1) { if (closestdistance > 0) { Paths[endmatch].Vertices.Remove(Paths[endmatch].Vertices.Last()); } Paths[endmatch].Vertices.AddRange(Paths[i].Vertices); if (Paths[endmatch].Vertices.First() == Paths[endmatch].Vertices.Last()) { Console.WriteLine("closed path with {0} points during stage 4a", Paths[endmatch].Vertices.Count()); Paths[endmatch].Closed = true; } Paths.Remove(Paths[i]); // Console.WriteLine(" 4a"); return(1); } if (startmatch > -1) { Paths[i].Vertices.Reverse(); if (closestdistance > 0) { Paths[i].Vertices.Remove(Paths[i].Vertices.Last()); } Paths[i].Vertices.AddRange(Paths[startmatch].Vertices); if (Paths[i].Vertices.First() == Paths[i].Vertices.Last()) { Console.WriteLine("closed path with {0} points during stage 4b", Paths[i].Vertices.Count()); Paths[i].Closed = true; } Paths.Remove(Paths[startmatch]); //Console.WriteLine(" 4b"); return(1); } } PF = P.Vertices.Last(); R.X = (float)(P.Vertices.First().X - 1.5); R.Y = (float)(P.Vertices.First().Y - 1.5); startmatch = -1; endmatch = -1; closestdistance = B.Width() + B.Height(); Root.CallBackInside(R, delegate(QuadTreeItem QI) { var S = QI as SegmentEndContainer; if (S.PathID == i) { return(true); } if (P.Width != Paths[S.PathID].Width) { return(true); } var D = PointD.Distance(S.Point, PF); if (D < 1.0 && D < closestdistance) { closestdistance = D; if (S.Side == SideEnum.Start) { startmatch = S.PathID; } else { endmatch = S.PathID; } } return(true); }); if (startmatch > -1 || endmatch > -1) { if (endmatch > -1) { Paths[i].Vertices.Reverse(); if (closestdistance > 0) { Paths[endmatch].Vertices.Remove(Paths[endmatch].Vertices.Last()); } Paths[endmatch].Vertices.AddRange(Paths[i].Vertices); if (Paths[endmatch].Vertices.First() == Paths[endmatch].Vertices.Last()) { Console.WriteLine("closed path with {0} points during stage 4c", Paths[endmatch].Vertices.Count()); Paths[endmatch].Closed = true; } Paths.Remove(Paths[i]); // Console.WriteLine(" 4c"); return(1); } if (startmatch > -1) { if (closestdistance > 0) { Paths[i].Vertices.Remove(Paths[i].Vertices.Last()); } Paths[i].Vertices.AddRange(Paths[startmatch].Vertices); if (Paths[i].Vertices.First() == Paths[i].Vertices.Last()) { Console.WriteLine("closed path with {0} points during stage 4d", Paths[i].Vertices.Count()); Paths[i].Closed = true; } Paths.Remove(Paths[startmatch]); // Console.WriteLine(" 4d"); return(1); } } } } return(0); }
private static List <PathDefWithClosed> StripOverlaps(List <PathDefWithClosed> Paths) { List <PathDefWithClosed> Res = new List <PathDefWithClosed>(); QuadTreeNode Root = new QuadTreeNode(); PolyLineSet.Bounds B = new PolyLineSet.Bounds(); for (int i = 0; i < Paths.Count; i++) { if (Paths[i].Closed == false) { foreach (var a in Paths[i].Vertices) { B.FitPoint(a); } } else { Res.Add(Paths[i]); } } Root.xstart = B.TopLeft.X - 10; Root.xend = B.BottomRight.X + 10; Root.ystart = B.TopLeft.Y - 10; Root.yend = B.BottomRight.Y + 10; RectangleF QueryRect = new RectangleF(); QueryRect.Width = 3; QueryRect.Height = 3; List <PathDefWithClosed> ToDelete = new List <PathDefWithClosed>(); for (int i = 0; i < Paths.Count; i++) { if (Paths[i].Closed == false) { int nearcount = 0; foreach (var a in Paths[i].Vertices) { QueryRect.X = (float)a.X - 1.5f; QueryRect.Y = (float)a.Y - 1.5f; Root.CallBackInside(QueryRect, delegate(QuadTreeItem QI) { var S = QI as SegmentEndContainer; if (S.Point == a) { nearcount++; } else { if (PointD.Distance(a, S.Point) < 0.001) { nearcount++; } } return(true); } ); } int max = Math.Max(4, (Paths[i].Vertices.Count * 50) / 100); if (nearcount <= max) { foreach (var a in Paths[i].Vertices) { Root.Insert(new SegmentEndContainer() { PathID = i, Point = a, Side = SideEnum.Start }, 8); } Res.Add(Paths[i]); } else { Res.Add(Paths[i]); Console.WriteLine("{4}: {0} out of {1}/{2}/{3}", nearcount, max, Paths[i].Vertices.Count, (Paths[i].Vertices.Count * 90) / 100, i); Console.WriteLine("{0}: skipped!", i); } } } return(Res); }
private static int FindNextClosest(List <PathDefWithClosed> Paths) { QuadTreeNode Root = new QuadTreeNode(); Bounds B = new Bounds(); for (int i = 0; i < Paths.Count; i++) { if (Paths[i].Closed == false) { B.FitPoint(Paths[i].Points.First()); B.FitPoint(Paths[i].Points.Last()); } } Root.xstart = B.TopLeft.X - 10; Root.xend = B.BottomRight.X + 10; Root.ystart = B.TopLeft.Y - 10; Root.yend = B.BottomRight.Y + 10; for (int i = 0; i < Paths.Count; i++) { if (Paths[i].Closed == false) { Root.Insert(new SegmentEndContainer() { PathID = i, Point = Paths[i].Points.First(), Side = SideEnum.Start }, 4); Root.Insert(new SegmentEndContainer() { PathID = i, Point = Paths[i].Points.Last(), Side = SideEnum.End }, 4); } } RectangleF R = new RectangleF(); R.Width = 30; R.Height = 30; for (int i = 0; i < Paths.Count; i++) { var P = Paths[i]; if (P.Closed == false) { var PF = P.Points.First(); R.X = (float)(P.Points.First().X - 15); R.Y = (float)(P.Points.First().Y - 15); int startmatch = -1; int endmatch = -1; double closestdistance = B.Width() + B.Height(); Root.CallBackInside(R, delegate(QuadTreeItem QI) { var S = QI as SegmentEndContainer; if (S.PathID == i) { return(true); } var D = PointD.Distance(S.Point, PF); if (D < 1.0 && D < closestdistance) { closestdistance = D; if (S.Side == SideEnum.Start) { startmatch = S.PathID; } else { endmatch = S.PathID; } } return(true); }); if (startmatch > -1 || endmatch > -1) { if (endmatch > -1) { Paths[endmatch].Points.Remove(Paths[endmatch].Points.Last()); Paths[endmatch].Points.AddRange(Paths[i].Points); if (Paths[endmatch].Points.First() == Paths[endmatch].Points.Last()) { // Console.WriteLine("closed path with {0} points during stage 4a", Paths[endmatch].Points.Count()); Paths[endmatch].Closed = true; } Paths.Remove(Paths[i]); // Console.WriteLine(" 4a"); return(1); } if (startmatch > -1) { Paths[i].Points.Reverse(); Paths[i].Points.Remove(Paths[i].Points.Last()); Paths[i].Points.AddRange(Paths[startmatch].Points); if (Paths[i].Points.First() == Paths[i].Points.Last()) { // Console.WriteLine("closed path with {0} points during stage 4b", Paths[i].Points.Count()); Paths[i].Closed = true; } Paths.Remove(Paths[startmatch]); //Console.WriteLine(" 4b"); return(1); } } PF = P.Points.Last(); R.X = (float)(P.Points.First().X - 0.5); R.Y = (float)(P.Points.First().Y - 0.5); startmatch = -1; endmatch = -1; closestdistance = B.Width() + B.Height(); Root.CallBackInside(R, delegate(QuadTreeItem QI) { var S = QI as SegmentEndContainer; if (S.PathID == i) { return(true); } var D = PointD.Distance(S.Point, PF); if (D < 1.0 && D < closestdistance) { closestdistance = D; if (S.Side == SideEnum.Start) { startmatch = S.PathID; } else { endmatch = S.PathID; } } return(true); }); if (startmatch > -1 || endmatch > -1) { if (endmatch > -1) { Paths[i].Points.Reverse(); Paths[endmatch].Points.Remove(Paths[endmatch].Points.Last()); Paths[endmatch].Points.AddRange(Paths[i].Points); if (Paths[endmatch].Points.First() == Paths[endmatch].Points.Last()) { // Console.WriteLine("closed path with {0} points during stage 4c", Paths[endmatch].Points.Count()); Paths[endmatch].Closed = true; } Paths.Remove(Paths[i]); // Console.WriteLine(" 4c"); return(1); } if (startmatch > -1) { Paths[i].Points.Remove(Paths[i].Points.Last()); Paths[i].Points.AddRange(Paths[startmatch].Points); if (Paths[i].Points.First() == Paths[i].Points.Last()) { // Console.WriteLine("closed path with {0} points during stage 4d", Paths[i].Points.Count()); Paths[i].Closed = true; } Paths.Remove(Paths[startmatch]); // Console.WriteLine(" 4d"); return(1); } } } } return(0); }
protected unsafe void eraseSmooth(ImageSurface surf, Context g, PointD start, PointD end) { int rad = (int)(BrushWidth / 2.0) + 1; //Premultiply with alpha value byte bk_col_a = (byte)(PintaCore.Palette.SecondaryColor.A * 255.0); byte bk_col_r = (byte)(PintaCore.Palette.SecondaryColor.R * bk_col_a); byte bk_col_g = (byte)(PintaCore.Palette.SecondaryColor.G * bk_col_a); byte bk_col_b = (byte)(PintaCore.Palette.SecondaryColor.B * bk_col_a); int num_steps = (int)start.Distance(end) / rad + 1; //Initialize lookup table when first used (to prevent slower startup of the application) initLookupTable(); for (int step = 0; step < num_steps; step++) { PointD pt = Utility.Lerp(start, end, (float)step / num_steps); int x = (int)pt.X, y = (int)pt.Y; Gdk.Rectangle surface_rect = new Gdk.Rectangle(0, 0, surf.Width, surf.Height); Gdk.Rectangle brush_rect = new Gdk.Rectangle(x - rad, y - rad, 2 * rad, 2 * rad); Gdk.Rectangle dest_rect = Gdk.Rectangle.Intersect(surface_rect, brush_rect); if ((dest_rect.Width > 0) && (dest_rect.Height > 0)) { //Allow Clipping through a temporary surface using (ImageSurface tmp_surface = copySurfacePart(surf, dest_rect)) { for (int iy = dest_rect.Top; iy < dest_rect.Bottom; iy++) { ColorBgra *srcRowPtr = tmp_surface.GetRowAddressUnchecked(iy - dest_rect.Top); int dy = ((iy - y) * LUT_Resolution) / rad; if (dy < 0) { dy = -dy; } byte[] lut_factor_row = lut_factor [dy]; for (int ix = dest_rect.Left; ix < dest_rect.Right; ix++) { ColorBgra col = *srcRowPtr; int dx = ((ix - x) * LUT_Resolution) / rad; if (dx < 0) { dx = -dx; } int force = lut_factor_row [dx]; //Note: premultiplied alpha is used! if (mouse_button == 3) { col.A = (byte)((col.A * force + bk_col_a * (255 - force)) / 255); col.R = (byte)((col.R * force + bk_col_r * (255 - force)) / 255); col.G = (byte)((col.G * force + bk_col_g * (255 - force)) / 255); col.B = (byte)((col.B * force + bk_col_b * (255 - force)) / 255); } else { col.A = (byte)(col.A * force / 255); col.R = (byte)(col.R * force / 255); col.G = (byte)(col.G * force / 255); col.B = (byte)(col.B * force / 255); } *srcRowPtr = col; srcRowPtr++; } } //Draw the final result on the surface pasteSurfacePart(g, tmp_surface, dest_rect); } } } }
/// <summary> /// Calculates the given index's segment end point data. /// </summary> /// <param name="currentIndex">The index of the ControlPoint to calculate the segment end point data of.</param> /// <param name="nextIndex">The index of the next ControlPoint.</param> /// <param name="lineEndPoint">The end point of the line prior to the given ControlPoint's index.</param> /// <param name="cornerEndPoint">The end point of the rounded corner at the given ControlPoint's index.</param> private void calculateSegmentEndPoints(int currentIndex, out int nextIndex, out PointD lineEndPoint, out PointD cornerEndPoint) { //Determine the positions of the current, next, and double next ControlPoints. nextIndex = currentIndex + 1; if (nextIndex >= ControlPoints.Count) { nextIndex = 0; } int doubleNextIndex = nextIndex + 1; if (doubleNextIndex >= ControlPoints.Count) { doubleNextIndex = 0; } PointD currentPosition = ControlPoints[currentIndex].Position; PointD nextPosition = ControlPoints[nextIndex].Position; PointD doubleNextPosition = ControlPoints[doubleNextIndex].Position; //Calculate the distance between the current and next point and the next and double next point. double currentDistance = currentPosition.Distance(nextPosition); double nextDistance = nextPosition.Distance(doubleNextPosition); //Calculate the smaller of the two distances. double minDistance = Math.Min(currentDistance, nextDistance); //The radius value used can change between ControlPoints depending on their proximity to each other. double currentRadius = Radius; //Reduce the radius according to the distance between adjacent ControlPoints if necessary. if (currentRadius > minDistance / 2d) { currentRadius = minDistance / 2d; } //Calculate the current offset ratio, which is the ratio of the radius to the distance between the current and next points. double currentOffsetRatio; //Prevent a divide by 0 error. if (currentDistance <= 0d) { currentOffsetRatio = 0d; } else { currentOffsetRatio = currentRadius / currentDistance; if (currentOffsetRatio > 1d) { currentOffsetRatio = 1d; } } //Calculate the next offset ratio, which is the ratio of the radius to the distance between the next and double next points. double nextOffsetRatio; //Prevent a divide by 0 error. if (nextDistance <= 0d) { nextOffsetRatio = 0d; } else { nextOffsetRatio = currentRadius / nextDistance; if (nextOffsetRatio > 1d) { nextOffsetRatio = 1d; } } //Calculate the end point of the straight line before the rounded corner. lineEndPoint = new PointD(nextPosition.X - (nextPosition.X - currentPosition.X) * currentOffsetRatio, nextPosition.Y - (nextPosition.Y - currentPosition.Y) * currentOffsetRatio); //Calculate the end point of the rounded corner after the straight line. cornerEndPoint = new PointD(nextPosition.X + (doubleNextPosition.X - nextPosition.X) * nextOffsetRatio, nextPosition.Y + (doubleNextPosition.Y - nextPosition.Y) * nextOffsetRatio); }
/// <summary> /// Gets the local minimums distribution. /// </summary> /// <param name="dmFieldData">The dm field data.</param> /// <param name="dimensionNumber">The dimension number: /// 1 - rows (angle) /// 2 - columns (distance) /// </param> /// <returns>DenseMatrix.</returns> //public static DenseMatrix GetLocalMinimumsDistribution(DenseMatrix dmFieldData, PointD sunCenterPoint, PointD imageCenterPoint, double imageRadius, int imageHeight, double imageCircleCropFactor = 0.9d, int dimensionNumber = 1) public static List <Point3D> GetLocalMinimumsDistribution(DenseMatrix dmFieldData, RoundData sunDiskData, RoundData imageRoundData, int imageHeight, double imageCircleCropFactor = 0.9d) { // DenseMatrix dmFieldminimumsData = DenseMatrix.Create(dmFieldData.RowCount, dmFieldData.ColumnCount, 0.0d); List <Point3D> lRetPoints = new List <Point3D>(); double imageRadius = imageRoundData.DRadius; PointD imageCenterPoint = imageRoundData.pointDCircleCenter(); PointPolar imageCenterPointRelatedToSunCenter = new PointPolar(imageCenterPoint - sunDiskData.pointDCircleCenter(), true); double distanceSunCenterToImageCenter = PointD.Distance(imageCenterPoint, sunDiskData.pointDCircleCenter()); #region // obsolete //if (dimensionNumber == 1) //{ #endregion // obsolete for (int i = 0; i < dmFieldData.RowCount; i++) { bool itsTheCropCase = false; //если направлени на кроп кадра - то не берем в расмотрение double currentAngle = ((double)i / (double)(dmFieldData.RowCount - 1)) * 2.0d * Math.PI; LineDescription2D line, lineMargin; if (currentAngle < Math.PI) { //верхняя половина, смотрим направление на y=0.0d line = new LineDescription2D(sunDiskData.pointDCircleCenter(), new Vector2D(Math.Cos(currentAngle), -Math.Sin(currentAngle))); lineMargin = new LineDescription2D(new PointD(0.0d, 0.0d), new Vector2D(1.0d, 0.0d)); } else { line = new LineDescription2D(sunDiskData.pointDCircleCenter(), new Vector2D(Math.Cos(currentAngle), Math.Sin(currentAngle))); lineMargin = new LineDescription2D(new PointD(0.0d, imageHeight), new Vector2D(1.0d, 0.0d)); } PointD crossPointD = LineDescription2D.CrossPoint(line, lineMargin); if (crossPointD.Distance(imageCenterPoint) < imageRadius) { itsTheCropCase = true; } #region // obsolete //double yMargin = 0.0d; //double xMargin = sunCenterPoint.X + (yMargin - sunCenterPoint.Y) / Math.Tan(currentAngle); //double dx = xMargin - imageCenterPoint.X; //double dy = yMargin - imageCenterPoint.Y; //if (Math.Sqrt(dx * dx + dy * dy) < imageRadius) itsTheCropCase = true; #endregion // obsolete #region //obsolete //else //{ // //нижняя половина, смотрим направление на y=imageHeight // double yMargin = (double)imageHeight; // double xMargin = sunCenterPoint.X + (yMargin - sunCenterPoint.Y) / Math.Tan(currentAngle); // double dx = xMargin - imageCenterPoint.X; // double dy = yMargin - imageCenterPoint.Y; // if (Math.Sqrt(dx * dx + dy * dy) < imageRadius) itsTheCropCase = true; //} #endregion //obsolete //Если слишком близко к краю изображения - тоже исключаем. Минимум должен лежать не ближе, например, 1/15 //DenseMatrix dmSlicedDataMatrix = (DenseMatrix)dmFieldData.SubMatrix(i, 1, 0, dmFieldData.ColumnCount); DenseVector dvRowDataVector = (DenseVector)dmFieldData.EnumerateRows().ElementAt(i); #region // debug plotting //dvRowDataVector.SaveVectorDataAsImagePlot( // "D:\\_gulevlab\\SkyImagesAnalysis_appData\\patent-samples\\result.2015-03-24\\img-2014-09-20T16-03-58devID1\\dvRowDataVector-plot-image-" + // i.ToString("D03") + "-step1.png"); #endregion // debug plotting dvRowDataVector.MapIndexedInplace((idx, x) => ((x == 0.0d) || (idx < sunDiskData.DRadius * 1.5d)) ? (1.0d) : (x)); #region // debug plotting //dvRowDataVector.SaveVectorDataAsImagePlot( // "D:\\_gulevlab\\SkyImagesAnalysis_appData\\patent-samples\\result.2015-03-24\\img-2014-09-20T16-03-58devID1\\dvRowDataVector-plot-image-" + // i.ToString("D03") + "-step2.png"); #endregion // debug plotting double phiFromImageCenterToDirection = imageCenterPointRelatedToSunCenter.Phi - currentAngle; double distanceToImageMargin = distanceSunCenterToImageCenter * Math.Cos(phiFromImageCenterToDirection) + Math.Sqrt(imageRadius * imageRadius - distanceSunCenterToImageCenter * distanceSunCenterToImageCenter * Math.Sin(phiFromImageCenterToDirection) * Math.Sin(phiFromImageCenterToDirection)); dvRowDataVector.MapIndexedInplace( (idx, x) => ((double)idx / distanceToImageMargin >= imageCircleCropFactor) ? (1.0d) : (x)); #region // debug plotting //dvRowDataVector.SaveVectorDataAsImagePlot( // "D:\\_gulevlab\\SkyImagesAnalysis_appData\\patent-samples\\result.2015-03-24\\img-2014-09-20T16-03-58devID1\\dvRowDataVector-plot-image-" + // i.ToString("D03") + "-step3.png"); #endregion // debug plotting double minValue = dvRowDataVector.Minimum(); int minValueIndex = dvRowDataVector.MinimumIndex(); //if (!itsTheCropCase) dmFieldminimumsData[i, minValueIndex] = minValue; if ((!itsTheCropCase) && ((double)minValueIndex > sunDiskData.DRadius)) { lRetPoints.Add(new Point3D(currentAngle, minValueIndex, minValue)); } else { continue; } } #region // obsolete //} //else if (dimensionNumber == 2) //{ // for (int i = 0; i < dmFieldData.ColumnCount; i++) // { // DenseMatrix dmSlicedDataMatrix = (DenseMatrix)dmFieldData.SubMatrix(0, dmFieldData.RowCount, i, 1); // DenseVector dvSlicedDataVector = DenseVector.OfEnumerable(dmSlicedDataMatrix.Values); // dvSlicedDataVector.MapInplace(new Func<double, double>(x => (x == 0.0d) ? (1.0d) : (x))); // double minValue = dvSlicedDataVector.Minimum(); // int minValueIndex = dvSlicedDataVector.MinimumIndex(); // dmFieldminimumsData[minValueIndex, i] = minValue; // } //} #endregion // obsolete //return dmFieldminimumsData; return(lRetPoints); }
/// <summary> /// Cartesians to polar. /// </summary> /// <param name="dmData">input densematrix data.</param> /// <param name="centerPoint">The center point of new polar system - in old cartesian coordinate system.</param> /// <param name="dmMask">The mask matrix.</param> /// <param name="angleGridNodesCount">The angle grid nodes count.</param> /// <returns>MathNet.Numerics.LinearAlgebra.Double.DenseMatrix.</returns> /// todo: регулировать размер сетки для свертки по гауссу public static DenseMatrix CartesianToPolar(DenseMatrix dmData, PointD centerPoint, DenseMatrix dmMask, int angleGridNodesCount = 144) { double angleValueDiff = 2 * Math.PI / (angleGridNodesCount - 1); DenseMatrix dmDistances = DenseMatrix.Create(dmData.RowCount, dmData.ColumnCount, (r, c) => centerPoint.Distance(new PointD(c, r))); dmDistances = (DenseMatrix)dmDistances.PointwiseMultiply(dmMask); double maxDistance = dmDistances.Values.Maximum(); int distanceNodesCount = Convert.ToInt32(maxDistance) + 1; DenseMatrix dmCountOfElementsSummedToThePolarPointValue = DenseMatrix.Create(angleGridNodesCount, distanceNodesCount, 0.0d); DenseMatrix dmAngles = DenseMatrix.Create(dmData.RowCount, dmData.ColumnCount, (row, column) => { double dx = (double)column - centerPoint.X; double dy = (double)row - centerPoint.Y; double r = dmDistances[row, column]; if (r == 0.0d) { return(0.0d); } double cosPhi = dx / r; double phi = Math.Acos(cosPhi); if (dy > 0) { phi = 2.0d * Math.PI - phi; } return(phi); }); dmAngles = (DenseMatrix)dmAngles.PointwiseMultiply(dmMask); DenseMatrix dmOutData = DenseMatrix.Create(angleGridNodesCount, distanceNodesCount, 0.0d); //Vector2D vCenterPoint = new Vector2D(centerPoint); //DenseMatrix dmSmoothed = dmData.Conv2(StandardConvolutionKernels.gauss, 7); //int cartesianRowCount = dmSmoothed.RowCount; //int cartesianColCount = dmSmoothed.ColumnCount; //DenseMatrix dmOutData = DenseMatrix.Create(angleGridNodesCount, distanceNodesCount, (row, col) => //{ // PointPolar ptPolCurrPoint = new PointPolar((double) col, (double) row*angleValueDiff); // PointD ptdCurrPoint = (ptPolCurrPoint.PointD() + vCenterPoint).ToPointD(); // int cartesianRow = Convert.ToInt32(ptdCurrPoint.Y); // int cartesianCol = Convert.ToInt32(ptdCurrPoint.X); // if ((cartesianRow < 0) || (cartesianRow >= cartesianRowCount) || (cartesianCol < 0) || // (cartesianCol >= cartesianColCount)) // { // return 0.0d; // } // else // return dmSmoothed[cartesianRow, cartesianCol]; //}); for (int cartesianRow = 0; cartesianRow < dmData.RowCount; cartesianRow++) { for (int cartesianCol = 0; cartesianCol < dmData.ColumnCount; cartesianCol++) { double currAngle = dmAngles[cartesianRow, cartesianCol]; double currDistance = dmDistances[cartesianRow, cartesianCol]; if (dmMask[cartesianRow, cartesianCol] == 0.0d) { continue; } int angleRow = Convert.ToInt32(currAngle / angleValueDiff); int distanceCol = Convert.ToInt32(currDistance); dmOutData[angleRow, distanceCol] += dmData[cartesianRow, cartesianCol]; if (dmMask[cartesianRow, cartesianCol] > 0.0d) { dmCountOfElementsSummedToThePolarPointValue[angleRow, distanceCol] += 1.0d; } } } dmCountOfElementsSummedToThePolarPointValue.MapInplace(x => (x == 0.0d) ? (0.0d) : (1.0d / x)); dmOutData = (DenseMatrix)dmOutData.PointwiseMultiply(dmCountOfElementsSummedToThePolarPointValue); dmOutData.MapInplace(x => (x == 0.0d) ? (1.0d) : (x)); //сгладим foreach (Tuple <int, MathNet.Numerics.LinearAlgebra.Vector <double> > tplRowVectorAndIndex in dmOutData.EnumerateRowsIndexed()) { DenseVector currVector = (DenseVector)tplRowVectorAndIndex.Item2; DenseVector currVectorSmoothed = currVector.Conv(StandardConvolutionKernels.gauss, 5); // и восстановим краевые значения for (int i = 0; i < 5; i++) { currVectorSmoothed[i] = currVector[i]; currVectorSmoothed[currVectorSmoothed.Count - i - 1] = currVector[currVector.Count - i - 1]; } dmOutData.SetRow(tplRowVectorAndIndex.Item1, currVectorSmoothed.ToArray()); } return(dmOutData); }