C# 按 Z 数之间的较大距离拆分坐标数组

C# Split array of coordinates by higher distance between Z numbers

我正在制作用于测量的线圈 spring 激光扫描仪,只有激光扫描到那个 spring 时才会给我值。所以我有 X、Z 点数组,例如:"10,5; 11,6; 12,7; 11,8; 10,9; 10,15; 11,16; 12,17; 11,18; 10,19" 等。我希望你能理解它——这是它的图片

如何将数组拆分为 "big space in Z coord" -- 如何将 spring "tops" 拆分? (我不知道如何调用 it:D)我只需要那些最高的 X 直径点(比如 12,7;12,17)。

编辑:我会尝试解释更多。 我有 X,Z 点数组(X 是长度,Z 是高度)。它看起来像这样:{[10,5], [11,6], [12,7], [11,8], [10,9], [10,15], [11,16], [12 ,17], [11,18], [10,19]}。逗号分隔 X 和 Z 坐标(如图像)。我需要检测这些点组之间的差距 - 在 [10,9] 和 [10,15] 之间,所以我可以计算 spring 有多少个线程 - 并只获得那些最高的 X 点 - [12 ,7] 和 [12,17]。 我的想法是遍历该数组并检查之前的 Z 是否低于 xx,但我无法管理下一步该做什么。 我仍在学习 C#,大部分时间我都在谷歌上搜索和尝试,但为此我什至不知道尝试什么以及如何尝试:/

使用字符串拆分很简单。要获得差距,请查看点的斜率以分隔周期。下面的代码是完成拆分的一种方法。你不能像你这样的例子重新排序点,这可能不会给出正确的结果。看起来你的图片和点列表是相反的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace ConsoleApplication1
{
    enum State
    {
        UNKNOWN,
        POSITIVE,
        NEGATIVE
    }
    class Program
    {
        static void Main(string[] args)
        {
            string input = "10,5; 11,6; 12,7; 11,8; 10,9; 10,15; 11,16; 12,17; 11,18; 10,19";
            string[] splitSemicolon = input.Split(new char[] { ';' });
            Point[] points = splitSemicolon.Select(x => x.Split(new char[] { ',' })).Select(x => new Point(int.Parse(x.FirstOrDefault()), int.Parse(x.LastOrDefault()))).ToArray();            

            State state = State.UNKNOWN;
            List<Cycle> cycles = new List<Cycle>();
            Cycle newCycle = null;
            for (int i = 1; i < points.Length; i++)
            {
                double slope = 0;
                if (points[i].X == points[i - 1].X)
                {
                    slope = points[i].Y - points[i - 1].Y;
                }
                else
                {
                    slope = (points[i].Y - points[i - 1].Y) / (points[i].X - points[i - 1].X);
                }
                switch (state)
                {
                    case State.UNKNOWN:
                        newCycle = new Cycle();
                        cycles.Add(newCycle);
                        if (slope < 0)
                        {
                            newCycle.negativeSlope = new List<Point> { points[0], points[1] };
                            state = State.NEGATIVE;
                        }
                        else
                        {
                            newCycle.positiveSlope = new List<Point> { points[0], points[1] };
                            state = State.POSITIVE;
                        }
                        break;

                    case State.POSITIVE :
                        if (slope > 0)
                        {
                            newCycle.positiveSlope.Add(points[i]);
                        }
                        else
                        {
                            newCycle = new Cycle();
                            cycles.Add(newCycle);
                            newCycle.negativeSlope = new List<Point>() { points[i] };
                            state = State.NEGATIVE;
                        }
                        break;
                    case State.NEGATIVE:
                        if (slope > 0)
                        {
                            newCycle.positiveSlope = new List<Point>() { points[i] };
                            state = State.POSITIVE;
                        }
                        else
                        {
                            newCycle.negativeSlope.Add(points[i]);
                        }
                        break;
                }
            }

        }
    }
    public class Cycle
    {
        public List<Point> negativeSlope { get; set; }
        public List<Point> positiveSlope { get; set; }
    }
}

给出一个 XZ class 赞

public class XZ
{
    public int X { get; set; }
    public int Z { get; set; }

    public XZ(int x, int z)
    {
        X = x;
        Z = z;
    }

    public override string ToString()
    {
        return $"X = {X}, Z = {Z}";
    }
}

我们可以定义一个:

static IEnumerable<XZ[]> SplitByZGap(IEnumerable<XZ> points, int gap)
{
    var group = new List<XZ>();

    bool first = true;
    int lastZ = 0;

    foreach (var point in points)
    {
        if (first)
        {
            first = false;
        }
        else if (Math.Abs(point.Z - lastZ) >= gap)
        {
            var group2 = group.ToArray();
            group.Clear();
            yield return group2;
        }

        lastZ = point.Z;
        group.Add(point);
    }

    {
        var group2 = group.ToArray();
        group.Clear();
        yield return group2;
    }
}

这会将 XZ 个点的集合拆分 "gap"(Z 轴上的距离)

我们可以定义一些数据,例如:

var points = new[]
{
    new XZ(10,5),
    new XZ(11,6),
    new XZ(12,7),
    new XZ(11,8),
    new XZ(10,9),
    new XZ(10,15),
    new XZ(11,16),
    new XZ(12,17),
    new XZ(11,18),
    new XZ(10,26),
};

(请注意,我已将最后一个 z 坐标从 19 更改为 26)

然后:

var res = SplitByZGap(points, 6).ToArray();