简体   繁体   English

如何从起点到终点产生坐标对?

[英]How to yield coordinate pairs from a start point to an end point?

I want to create coordinate pairs that demonstrates a path between two points. 我想创建坐标对,以演示两个点之间的路径。 First if it is available the function should make a diagonal path then the remaining coordinates should be either vertical or horizontal. 首先,如果该功能可用,则该功能应绘制一条对角线路径,然后其余坐标应为垂直或水平。

I calculated the absolute X and Y values between two points. 我计算了两点之间的绝对X和Y值。 Then if X or Y is greater than zero, the function decreases it and yields the result. 然后,如果X或Y大于零,则函数将其减小并产生结果。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var start = new Point(10, 10);
            var end = new Point(5, 3);
            var coordinates = new List<Point>(Coordinates(start, end));
            foreach (var coord in coordinates)
            {
                Console.WriteLine("[" + coord.X + ", " + coord.Y + "]");
            }
            Console.ReadKey();
        }

        public static IEnumerable<Point> Coordinates(Point start, Point end)
        {
            var difX = Math.Abs(end.X - start.X + 1);
            var difY = Math.Abs(end.Y - start.Y + 1);
            var iterations = (difX > difY) ? difX : difY;
            for (var i = 0; i < iterations; i++)
            {
                if (difX > 0)
                {
                    difX--;
                }

                if (difY > 0)
                {
                    difY--;
                }
                yield return new Point(end.X - difX, end.Y - difY);
            }
        }
    }

    internal struct Point
    {
        public double X { get; set; }
        public double Y { get; set; }

        public Point(double x, double y)
        {
            X = x;
            Y = y;
        }
    }
}

The problem here is if the start point is farther to the origin than the end point this doesn't work. 这里的问题是,如果起点比起点比终点更远,则不起作用。

  // Start point (10, 10), end point (5, 3)
  // Actual results: 
  [2, -2]
  [3, -1]
  [4, 0]
  [5, 1]
  [5, 2]
  [5, 3]

  // Desired: 
  [10, 10]
  [9, 9]
  [8, 8]
  [7, 7]
  [6, 6]
  [5, 5]
  [5, 4]
  [5, 3]

  // If I reverse start and end points the result is as expected:
  [5, 3]
  [6, 4]
  [7, 5]
  [8, 6]
  [9, 7]
  [10, 8]
  [10, 9]
  [10, 10]

You Math.Abs when working out how much you need to step, which loses the direction of your stepping and all your paths can only thus proceed in a positive direction. 您的Math.Abs​​在计算出需要走多少步时会失去步速的方向,因此您的所有路径只能朝积极的方向前进。 Instead keep the stepping as positive or negative: 而是保持步进为正或负:

    public static IEnumerable<Point> Coordinates(Point start, Point end)
    {
        int difX = end.X - start.X;
        int difY = end.Y - start.Y;
        var iterations = (difX > difY) ? difX : difY;

        //reduce the stepping to either +1 or -1 for each 
        difX = difX/Math.Abs(difX);
        difY = difY/Math.Abs(difY);

        //start off one behind, because we'll increment in the loop
        int newX = start.X - difX; 
        int newY = start.Y - difY;

        //now when you loop, only apply the stepping if you didnt already reach the end
        for (var i = 0; i < iterations; i++)
        {
            //only move if we didn't reach the end
            if(newX != end.X) 
              newX += difX;
            if(newY != end.Y)
              newY += difY;

            yield return new Point(newX, newY);
        }
    }

DISCLAIMER: Untested! 免责声明:未经测试!

This is how I would approach this: 这就是我的处理方式:

public static IEnumerable<Point> Coordinates(Point start, Point end)
{
    double dirX = start.X < end.X ? +1 : -1;
    double dirY = start.Y < end.Y ? +1 : -1;

    double x = start.X;
    double y = start.Y;

    do
    {
        if (!coordsEqual(x, end.X)) x = x+dirX;
        if (!coordsEqual(y, end.Y)) x = y+dirY;
        yield return new Point(x,y);
    }while( !shouldStop(x,y,end) );
}

static bool shouldStop( double x, double y, Point target )
{
    // Basically x == end.X && y == end.Y , just considering floating point issues.
    return coordsEqual( x, target.X ) && coordsEqual( y, target.Y );
}

static bool coordsEqual( double d1, double d2 )
{
    // TODO
}

Mind that I left some work to do. 介意我还要做一些工作。 Checking equality on doubles has quite some pitfalls, so I left it up to you to learn about them. 检查双打是否相等有很多陷阱,所以我留给您学习它们。

BTW: You seem to only use integer values. 顺便说一句:您似乎只使用整数值。 Checking equality is much easier if you use int instead of double . 如果使用int而不是double则检查相等性要容易得多。

A simple loop while checking if we reach end point or not: 检查我们是否达到end时的一个简单循环:

Code: 码:

public static IEnumerable<Point> Coordinates(Point start, Point end) {
  int dx = Math.Sign(end.X - start.X);
  int dy = Math.Sign(end.Y - start.Y);
  int steps = Math.Max(Math.Abs(end.X - start.X), Math.Abs(end.Y - start.Y)) + 1; 

  int x = start.X;
  int y = start.Y;

  for (int i = 1; i <= steps; ++i) {
    yield return new Point(x, y);

    x = x == end.X ? end.X : x + dx;
    y = y == end.Y ? end.Y : y + dy;
  }
}

Demo: 演示:

Console.WriteLine(string.Join(Environment.NewLine, 
  Coordinates(new Point(10, 10), new Point(5, 3))));

Console.WriteLine();

Console.WriteLine(string.Join(Environment.NewLine, 
  Coordinates(new Point(5, 3), new Point(10, 10))));

Outcome: 结果:

{X=10,Y=10} 
{X=9,Y=9}
{X=8,Y=8}
{X=7,Y=7}
{X=6,Y=6}
{X=5,Y=5}
{X=5,Y=4}
{X=5,Y=3}

{X=5,Y=3} 
{X=6,Y=4}
{X=7,Y=5}
{X=8,Y=6}
{X=9,Y=7}
{X=10,Y=8}
{X=10,Y=9}
{X=10,Y=10}   

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM