计算距离A的给定距离的AB线上的点

我会非常疯狂地计算沿着给定线AB的点,在距离A的给定距离处,以便我可以“绘制”两个给定点之间的线。 一开始听起来很简单,但我似乎无法做到这一点。 更糟糕的是,我不明白我哪里出错了。 几何(和一般的数学)不是我强大的套件。

我已经阅读了类似的问题,并在那里有答案。 事实上,我直接从Mads Elvheim的回答中解除了我对CalculatePoint函数的当前实现: 给定一个起点和终点以及一个距离,计算沿线的一个点 (加上后面的注释中的修正 – 如果我理解正确的话)因为我的独立尝试解决问题让我无处可去,除了头等舱快递票务frusterpationland。

这是我的更新代码(请参阅EDIT备注post的底部):

using System; using System.Drawing; using System.Windows.Forms; namespace DrawLines { public class MainForm : Form { // ===================================================================== // Here's the part I'm having trouble with. I don't really understand // how this is suposed to work, so I can't seem to get it right! // --------------------------------------------------------------------- // A "local indirector" - Just so I don't have go down and edit the // actual call everytime this bluddy thing changes names. private Point CalculatePoint(Point a, Point b, int distance) { return CalculatePoint_ByAgentFire(a, b, distance); } #region CalculatePoint_ByAgentFire //AgentFire: Better approach (you can rename the struct if you need): struct Vector2 { public readonly double X; public readonly double Y; public Vector2(double x, double y) { this.X = x; this.Y = y; } public static Vector2 operator -(Vector2 a, Vector2 b) { return new Vector2(bX - aX, bY - aY); } public static Vector2 operator *(Vector2 a, double d) { return new Vector2(aX * d, aY * d); } public override string ToString() { return string.Format("[{0}, {1}]", X, Y); } } // For getting the midpoint you just need to do the (a - b) * d action: //static void Main(string[] args) //{ // Vector2 a = new Vector2(1, 1); // Vector2 b = new Vector2(3, 1); // float distance = 0.5f; // From 0.0 to 1.0. // Vector2 c = (a - b) * distance; // Console.WriteLine(c); //} private Point CalculatePoint_ByAgentFire(Point a, Point b, int distance) { var vA = new Vector2(aX, aY); var vB = new Vector2(bX, bY); double lengthOfHypotenuse = LengthOfHypotenuseAsDouble(a,b); double portionOfDistanceFromAtoB = distance / lengthOfHypotenuse; var vC = (vA - vB) * portionOfDistanceFromAtoB; Console.WriteLine("vC="+vC); return new Point((int)(vC.X+0.5), (int)(vC.Y+0.5)); } // Returns the length of the hypotenuse rounded to an integer, using // Pythagoras' Theorem for right angle triangles: The length of the // hypotenuse equals the sum of the square of the other two sides. // Ergo: h = Sqrt(a*a + b*b) private double LengthOfHypotenuseAsDouble(Point a, Point b) { double aSq = Math.Pow(Math.Abs(aX - bX), 2); // horizontal length squared double bSq = Math.Pow(Math.Abs(bY - bY), 2); // vertical length squared return Math.Sqrt(aSq + bSq); // length of the hypotenuse } #endregion //dbaseman: I thought something looked strange about the formula ... the question //you linked was how to get the point at a distance after B, whereas you want the //distance after A. This should give you the right answer, the start point plus //distance in the vector direction. // // Didn't work as per: http://sofzh.miximages.com/c%23/DrawLinesAB-broken_zps069161e9.jpg.html // private Point CalculatePoint_ByDbaseman(Point a, Point b, int distance) { // a. calculate the vector from a to b: double vectorX = bX - aX; double vectorY = bY - aY; // b. calculate the length: double magnitude = Math.Sqrt(vectorX * vectorX + vectorY * vectorY); // c. normalize the vector to unit length: vectorX /= magnitude; vectorY /= magnitude; // d. calculate and Draw the new vector, which is x1y1 + vxvy * (mag + distance). return new Point( (int)((double)aX + vectorX * distance) // x = col , (int)((double)aY + vectorY * distance) // y = row ); } // MBo: Try to remove 'magnitude' term in the parentheses both for X and for Y expressions. // // Didn't work as per: http://sofzh.miximages.com/c%23/DrawLinesAB-broken_zps069161e9.jpg.html // //private Point CalculatePoint_ByMBo(Point a, Point b, int distance) { // // a. calculate the vector from a to b: // double vectorX = bX - aX; // double vectorY = bY - aY; // // b. calculate the length: // double magnitude = Math.Sqrt(vectorX * vectorX + vectorY * vectorY); // // c. normalize the vector to unit length: // vectorX /= magnitude; // vectorY /= magnitude; // // d. calculate and Draw the new vector, which is x1y1 + vxvy * (mag + distance). // return new Point( // (int)( ((double)aX + vectorX * distance) + 0.5 ) // , (int)( ((double)aX + vectorX * distance) + 0.5 ) // ); //} // Didn't work //private Point CalculatePoint_ByUser1556110(Point a, Point b, int distance) { // Double magnitude = Math.Sqrt(Math.Pow(bY - aY, 2) + Math.Pow(bX - aX, 2)); // return new Point( // (int)(aX + distance * (bX - aX) / magnitude + 0.5) // , (int)(aY + distance * (bY - aY) / magnitude + 0.5) // ); //} // didn't work //private static Point CalculatePoint_ByCadairIdris(Point a, Point b, int distance) { // // a. calculate the vector from a to b: // double vectorX = bX - aX; // double vectorY = bY - aY; // // b. calculate the proportion of hypotenuse // double factor = distance / Math.Sqrt(vectorX*vectorX + vectorY*vectorY); // // c. factor the lengths // vectorX *= factor; // vectorY *= factor; // // d. calculate and Draw the new vector, // return new Point((int)(aX + vectorX), (int)(aY + vectorY)); //} // Returns a point along the line AB at the given distance from A // based on Mads Elvheim's answer to: // https://stackoverflow.com/questions/1800138/given-a-start-and-end-point-and-a-distance-calculate-a-point-along-a-line private Point MyCalculatePoint(Point a, Point b, int distance) { // a. calculate the vector from o to g: double vectorX = bX - aX; double vectorY = bY - aY; // b. calculate the length: double magnitude = Math.Sqrt(vectorX * vectorX + vectorY * vectorY); // c. normalize the vector to unit length: vectorX /= magnitude; vectorY /= magnitude; // d. calculate and Draw the new vector, which is x1y1 + vxvy * (mag + distance). return new Point( (int)(((double)aX + vectorX * (magnitude + distance)) + 0.5) // x = col , (int)(((double)aY + vectorY * (magnitude + distance)) + 0.5) // y = row ); } // ===================================================================== private const int CELL_SIZE = 4; // width and height of each "cell" in the bitmap. private readonly Bitmap _bitmap; // to draw on (displayed in picBox1). private readonly Graphics _graphics; // to draw with. // actual points on _theLineString are painted red. private static readonly SolidBrush _thePointBrush = new SolidBrush(Color.Red); // ... and are labeled in Red, Courier New, 12 point, Bold private static readonly SolidBrush _theLabelBrush = new SolidBrush(Color.Red); private static readonly Font _theLabelFont = new Font("Courier New", 12, FontStyle.Bold); // the interveening calculated cells on the lines between actaul points are painted Black. private static readonly SolidBrush _theLineBrush = new SolidBrush(Color.Black); // the points in my line-string. private static readonly Point[] _theLineString = new Point[] { // x, y new Point(170, 85), // A new Point( 85, 70), // B //new Point(209, 66), // C //new Point( 98, 120), // D //new Point(158, 19), // E //new Point( 2, 61), // F //new Point( 42, 177), // G //new Point(191, 146), // H //new Point( 25, 128), // I //new Point( 95, 24) // J }; public MainForm() { InitializeComponent(); // initialise "the graphics system". _bitmap = new Bitmap(picBox1.Width, picBox1.Height); _graphics = Graphics.FromImage(_bitmap); picBox1.Image = _bitmap; } #region actual drawing on the Grpahics private void DrawCell(int x, int y, Brush brush) { _graphics.FillRectangle( brush , x * CELL_SIZE, y * CELL_SIZE // x, y , CELL_SIZE, CELL_SIZE // width, heigth ); } private void DrawLabel(int x, int y, char c) { string s = c.ToString(); _graphics.DrawString( s, _theLabelFont, _theLabelBrush , x * CELL_SIZE + 5 // x , y * CELL_SIZE - 8 // y ); } // ... there should be no mention of _graphics or CELL_SIZE below here ... #endregion #region draw points on form load private void MainForm_Load(object sender, EventArgs e) { DrawPoints(); } // draws and labels each point in _theLineString private void DrawPoints() { char c = 'A'; // label text, as a char so we can increment it for each point. foreach ( Point p in _theLineString ) { DrawCell(pX, pY, _thePointBrush); DrawLabel(pX, pY, c++); } } #endregion #region DrawLines on button click private void btnDrawLines_Click(object sender, EventArgs e) { DrawLinesBetweenPointsInTheString(); } // Draws "the lines" between the points in _theLineString. private void DrawLinesBetweenPointsInTheString() { int n = _theLineString.Length - 1; // one less line-segment than points for ( int i = 0; i < n; ++i ) Draw(_theLineString[i], _theLineString[i + 1]); picBox1.Invalidate(); // tell the graphics system that the picture box needs to be repainted. } // Draws all the cells along the line from Point "a" to Point "b". private void Draw(Point a, Point b) { int maxDistance = LengthOfHypotenuse(a, b); for ( int distance = 1; distance < maxDistance; ++distance ) { var point = CalculatePoint(a, b, distance); DrawCell(point.X, point.X, _theLineBrush); } } // Returns the length of the hypotenuse rounded to an integer, using // Pythagoras' Theorem for right angle triangles: The length of the // hypotenuse equals the sum of the square of the other two sides. // Ergo: h = Sqrt(a*a + b*b) private int LengthOfHypotenuse(Point a, Point b) { double aSq = Math.Pow(Math.Abs(aX - bX), 2); // horizontal length squared double bSq = Math.Pow(Math.Abs(bY - bY), 2); // vertical length squared return (int)(Math.Sqrt(aSq + bSq) + 0.5); // length of the hypotenuse } #endregion #region Windows Form Designer generated code ///  /// Required method for Designer support - do not modify /// the contents of this method with the code editor. ///  private void InitializeComponent() { this.picBox1 = new System.Windows.Forms.PictureBox(); this.btnDrawLines = new System.Windows.Forms.Button(); ((System.ComponentModel.ISupportInitialize)(this.picBox1)).BeginInit(); this.SuspendLayout(); // // picBox1 // this.picBox1.Dock = System.Windows.Forms.DockStyle.Fill; this.picBox1.Location = new System.Drawing.Point(0, 0); this.picBox1.Name = "picBox1"; this.picBox1.Size = new System.Drawing.Size(1000, 719); this.picBox1.TabIndex = 0; this.picBox1.TabStop = false; // // btnDrawLines // this.btnDrawLines.Location = new System.Drawing.Point(23, 24); this.btnDrawLines.Name = "btnDrawLines"; this.btnDrawLines.Size = new System.Drawing.Size(77, 23); this.btnDrawLines.TabIndex = 1; this.btnDrawLines.Text = "Draw Lines"; this.btnDrawLines.UseVisualStyleBackColor = true; this.btnDrawLines.Click += new System.EventHandler(this.btnDrawLines_Click); // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(1000, 719); this.Controls.Add(this.btnDrawLines); this.Controls.Add(this.picBox1); this.Location = new System.Drawing.Point(10, 10); this.MinimumSize = new System.Drawing.Size(1016, 755); this.Name = "MainForm"; this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; this.Text = "Draw Lines on a Matrix."; this.Load += new System.EventHandler(this.MainForm_Load); ((System.ComponentModel.ISupportInitialize)(this.picBox1)).EndInit(); this.ResumeLayout(false); } private System.Windows.Forms.PictureBox picBox1; private System.Windows.Forms.Button btnDrawLines; #endregion } } 

对不起,如果它有点长,但这是从我的真实项目中挖掘的SSCCE ,这是运行MazeOfBolton的A *最短路线算法的实现 ……即迷宫跑者。

我实际想要做的是在迷宫(矩阵)中围绕两个给定点(原点和目标)预先计算“围栏”(即缓冲的MBR ),使得“围栏”内的所有点都在给定的范围内距离“两点之间的直线”的距离,以便快速消除远离目标的数十万条可能的路径。

请注意,这个编程挑战在几年前已经结束,因此这里的“竞争性plagerism”没有问题。 不,这不是功课,事实上我是一名专业的程序员……我只是在这里度过了我的舒适区,即使是相对简单的几何形状。 叹。

所以…请任何人都可以给我任何指示,以帮助我正确地获得CalculatePoint函数: 计算距离A的给定距离的AB线上的点?

提前感谢您的慷慨……即使在阅读这篇文章时也是如此。

干杯。 基思。


编辑:我刚刚更新了发布的源代码,因为:

(1)我刚刚意识到它不是自包含的。 我忘记了单独的MainForm。 Designer .cs文件,我已将其附加到已发布代码的底部。

(2)最新版本包括我到目前为止所尝试的内容,并附有一张照片,链接到每张故障的图片……并且它们都是一样的。 伊? WTF?

我想我的问题可能在其他地方,就像其他人以前错过的一些时髦的窗体设置,因为我忘了发布设计师生成的代码……除了everythingelse(在我的实际项目中)描绘了我期望它的确切位置,那么为什么计算出的点应该是不同的。 我不知道!?!?!? 我非常沮丧,而且我变得暴躁,所以我想我会留下这一天;-)

去表明我们经常低估了让计算机做多少努力所做的事情……甚至只画一条简单的线条…它甚至不是曲线,更不用说一个大圆圈或横向的墨卡托或任何东西想要…只是一个简单的蓝线!?!?!? 😉

非常感谢所有发帖的人!

再次干杯。 基思。

计算向量AB

首先定义从A点(1,-1)到B点(2,4)的矢量,从B中减去A.矢量将是Vab(1,5)。

计算AB的长度

使用毕达哥拉斯定理计算向量AB的长度。

 |Vab| = SQRT(1²+5²) 

长度为(圆形)5.1

计算单位矢量

将矢量除以其长度以获得单位矢量(长度为1的矢量)。

 V1(1/5.1,5/5.1) = V1(0.2, 0.98) 

计算长度为4的向量

现在将V1乘以你想要的长度,例如4,得到Vt。

 Vt(0.2*4,0.98*4) = Vt(0.8,3.92) 

计算目标点

将向量Vt添加到A点以获得点T(目标)。

 T = A + Vt = T(1.8,2.92) 

编辑:回答你的编辑

LengthOfHypotenuse方法看起来应该是这样的

  • 修正了计算bSq时的错误
  • 并删除了冗余的Math.Abs​​调用,因为2的pow为始终为正
  • 删除了0.5的添加,不知道为什么你需要那个
  • 你应该至少使用一个浮点作为返回值(双倍或小数也可以)

     //You should work with Vector2 class instead of Point and use their Length property private double LengthOfHypotenuse(Point a, Point b) { double aSq = Math.Pow(aX - bX, 2); // horizontal length squared double bSq = Math.Pow(aY - bY, 2); // vertical length squared return Math.Sqrt(aSq + bSq); // length of the hypotenuse } 

Draw(Point a,Point b)方法应如下所示:

  • 更正了DrawCell()调用

     private void Draw(Point a, Point b) { double maxDistance = LengthOfHypotenuse(a, b); for (int distance = 0; distance < maxDistance; ++distance) { var point = CalculatePoint(new Vector2(a), new Vector2(b), distance); DrawCell(point.X, point.Y, _theLineBrush); } } 

您的CalculatePoint(点a,点b,int距离)方法:

  • 将一些计算移到Vector2类中

     private Point CalculatePoint(Vector2 a, Vector2 b, int distance) { Vector2 vectorAB = a - b; return a + vectorAB.UnitVector * distance; } 

我已经为你扩展了Vector类,以添加缺少的运算符(为AgentFire提供的信用)

  //AgentFire: Better approach (you can rename the struct if you need): struct Vector2 { public readonly double X; public readonly double Y; public Vector2(Point p) : this(pX,pY) { } public Vector2(double x, double y) { this.X = x; this.Y = y; } public static Vector2 operator -(Vector2 a, Vector2 b) { return new Vector2(bX - aX, bY - aY); } public static Vector2 operator +(Vector2 a, Vector2 b) { return new Vector2(bX + aX, bY + aY); } public static Vector2 operator *(Vector2 a, double d) { return new Vector2(aX * d, aY * d); } public static Vector2 operator /(Vector2 a, double d) { return new Vector2(aX / d, aY / d); } public static implicit operator Point(Vector2 a) { return new Point((int)aX, (int)aY); } public Vector2 UnitVector { get { return this / Length; } } public double Length { get { double aSq = Math.Pow(X, 2); double bSq = Math.Pow(Y, 2); return Math.Sqrt(aSq + bSq); } } public override string ToString() { return string.Format("[{0}, {1}]", X, Y); } } 

更好的方法(如果需要,可以重命名结构):

 struct Vector2 { public readonly float X; public readonly float Y; public Vector2(float x, float y) { this.X = x; this.Y = y; } public static Vector2 operator -(Vector2 a, Vector2 b) { return new Vector2(bX - aX, bY - aY); } public static Vector2 operator +(Vector2 a, Vector2 b) { return new Vector2(aX + bX, aY + bY); } public static Vector2 operator *(Vector2 a, float d) { return new Vector2(aX * d, aY * d); } public override string ToString() { return string.Format("[{0}, {1}]", X, Y); } } 

要获得中点,您只需要执行(a - b) * d + a动作:

 class Program { static void Main(string[] args) { Vector2 a = new Vector2(1, 1); Vector2 b = new Vector2(3, 1); float distance = 0.5f; // From 0.0 to 1.0. Vector2 c = (a - b) * distance + a; Console.WriteLine(c); } } 

这会给你一点:

50%

output:\> [2, 1]

之后你需要的是for(the distance; up to one ; d += step)0.01.0并绘制你的像素。

  private static Point CalculatePoint(Point a, Point b, int distance) { // a. calculate the vector from o to g: double vectorX = bX - aX; double vectorY = bY - aY; // b. calculate the proportion of hypotenuse double factor = distance / Math.Sqrt(vectorX * vectorX + vectorY * vectorY); // c. factor the lengths vectorX *= factor; vectorY *= factor; // d. calculate and Draw the new vector, return new Point((int)(aX + vectorX), (int)(aY + vectorY)); } 

尝试删除X和Y表达式括号中的“幅度”项:

 (int)( ((double)aX + vectorX * distance) + 0.5 ) 
 private Point CalculatePoint(Point a, Point b, int distance) { Point newPoint = new Point(10,10); Double Magnitude = Math.Sqrt(Math.Pow((bY - aY),2) + Math.Pow((bX - aX),2)); newPoint.X = (int)(aX + (distance * ((bX - aX)/magnitude))); newPoint.Y = (int)(aY + (distance * ((bY - aY)/magnitude))); return newPoint; } 

好的伙计们,我发现了我的主要错误。 这是一个经典的Doh! 我的Draw方法是在pX,p绘画。 X

所以,我终于得到了一些有用的东西。 请注意,我并不是说这是一个“好的解决方案”,或“唯一可行的解​​决方案”我只是说它做了我想做的事情;-)

这是我更新的工作代码:(这次完整且自包含;-)

 using System; using System.Drawing; using System.Windows.Forms; using System.Diagnostics; namespace DrawLines { public class MainForm : Form { #region constants and readonly attributes private const int CELL_SIZE = 4; // width and height of each "cell" in the bitmap. private readonly Bitmap _myBitmap; // to draw on (displayed in picBox1). private readonly Graphics _myGraphics; // to draw with. // actual points on _theLineString are painted red. private static readonly SolidBrush _thePointBrush = new SolidBrush(Color.Red); // ... and are labeled in /*Bold*/ Black, 16 point Courier New private static readonly SolidBrush _theLabelBrush = new SolidBrush(Color.Black); private static readonly Font _theLabelFont = new Font("Courier New", 16); //, FontStyle.Bold); // the interveening calculated cells on the lines between actaul points are painted Silver. private static readonly SolidBrush _theLineBrush = new SolidBrush(Color.Silver); // the points in my line-string. private static readonly Point[] _thePoints = new Point[] { // x, yci new Point(170, 85), // A 0 new Point( 85, 70), // B 1 new Point(209, 66), // C 2 new Point( 98, 120), // D 3 new Point(158, 19), // E 4 new Point( 2, 61), // F 5 new Point( 42, 177), // G 6 new Point(191, 146), // H 7 new Point( 25, 128), // I 8 new Point( 95, 24) // J 9 }; #endregion public MainForm() { InitializeComponent(); // initialise "the graphics system". _myBitmap = new Bitmap(picBox1.Width, picBox1.Height); _myGraphics = Graphics.FromImage(_myBitmap); picBox1.Image = _myBitmap; } #region DrawPoints upon MainForm_Load private void MainForm_Load(object sender, EventArgs e) { DrawPoints(); } // draws and labels each point in _theLineString private void DrawPoints() { char c = 'A'; // label text, as a char so we can increment it for each point. foreach ( Point p in _thePoints ) { DrawCell(pX, pY, _thePointBrush); DrawLabel(pX, pY, c++); } } #endregion #region DrawLines on button click // ===================================================================== // Here's the interesting bit. DrawLine was called Draw // Draws a line from A to B, by using X-values to calculate the Y values. private void DrawLine(Point a, Point b) { if ( aY > bY ) // A is below B Swap(ref a, ref b); // make A the topmost point (ergo sort by Y) Debug.Assert(aY < bY, "A is still below B!"); var left = Math.Min(aX, bX); var right = Math.Max(aX, bX); int width = right - left; Debug.Assert(width >= 0, "width is negative!"); var top = aY; var bottom = bY; int height = bottom - top; Debug.Assert(height >= 0, "height is negative!"); if ( width > height ) { // use given X values to calculate the Y values, // otherwise it "skips" some X's double slope = (double)height / (double)width; Debug.Assert(slope >= 0, "slope is negative!"); if (aX <= bX) // a is left-of b, so draw left-to-right. for ( int x=1; x= 0, "slope is negative!"); if (aX <= bX) { // a is left-of b, so draw left-to-right. (FG) for ( int y=1; y /// Required method for Designer support - do not modify /// the contents of this method with the code editor. ///  private void InitializeComponent() { this.picBox1 = new System.Windows.Forms.PictureBox(); this.btnDrawLines = new System.Windows.Forms.Button(); ((System.ComponentModel.ISupportInitialize)(this.picBox1)).BeginInit(); this.SuspendLayout(); // // picBox1 // this.picBox1.Dock = System.Windows.Forms.DockStyle.Fill; this.picBox1.Location = new System.Drawing.Point(0, 0); this.picBox1.Name = "picBox1"; this.picBox1.Size = new System.Drawing.Size(1000, 719); this.picBox1.TabIndex = 0; this.picBox1.TabStop = false; // // btnDrawLines // this.btnDrawLines.Location = new System.Drawing.Point(23, 24); this.btnDrawLines.Name = "btnDrawLines"; this.btnDrawLines.Size = new System.Drawing.Size(77, 23); this.btnDrawLines.TabIndex = 1; this.btnDrawLines.Text = "Draw Lines"; this.btnDrawLines.UseVisualStyleBackColor = true; this.btnDrawLines.Click += new System.EventHandler(this.btnDrawLines_Click); // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(1000, 719); this.Controls.Add(this.btnDrawLines); this.Controls.Add(this.picBox1); this.Location = new System.Drawing.Point(10, 10); this.MinimumSize = new System.Drawing.Size(1016, 755); this.Name = "MainForm"; this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; this.Text = "Draw Lines on a Matrix."; this.Load += new System.EventHandler(this.MainForm_Load); ((System.ComponentModel.ISupportInitialize)(this.picBox1)).EndInit(); this.ResumeLayout(false); } private System.Windows.Forms.PictureBox picBox1; private System.Windows.Forms.Button btnDrawLines; #endregion } } 

编辑 – 更新上面的代码:此版本绘制“实线”。 之前发布的版本在几乎垂直的行中跳过了单元格,所以在这些情况下我反转算法来计算X值(而不是Y值)…现在我可以用它来设置(和绘制)“实心栅栏”围绕“航行区”;-)

这是正确结果的更新图片。

DrawLiness_solid_success.png

再次感谢所有帮助过的人…并且你确实提供了帮助;-)

干杯。 基思。