首页 > 解决方案 > 如何将以下 C++ 代码转换为 C#

问题描述

1.    sort(arr1.begin(), arr1.end(), [](Point2f lhs, Point2f rhs) { return lhs.x<rhs.x; } );
2.    sort(arr1.begin(), arr1.begin()+2, [](Point2f lhs, Point2f rhs) { return lhs.y<rhs.y; });
3.    sort(arr1.begin()+2, arr1.end(), [](Point2f lhs, Point2f rhs) { return lhs.y<rhs.y; });

我正在尝试对一组点 ( top-left --> bottom-left --> top-right --> bottom-right) 进行排序。我想将以上内容转换为 C#,但我不确定如何完成以上内容。到目前为止,我已经完成了以下工作:

var sortedArr1 = arr1.OrderBy(r => r.X).ThenBy(r=>r.Y).ToList();

我相信它完成了陈述 1 和 2,但没有解决最后一个陈述。

[编辑] 根据下面的评论,我从源代码中添加了一个片段。

 public List<Point2d> DetectCorners(Mat src)
    {
        var lines = src.HoughLines(1, Cv2.PI / 180, 50, 0, 0);
        Mat labels = new Mat();
        Mat centers = new Mat();
        List<Point2f> data = new List<Point2f>();
        for (uint i = 0; i < lines.Length; i++)
        {
            float rho = lines[i].Rho;
            float theta = lines[i].Theta;
            float x = rho * (float)Math.Cos(theta);
            float y = rho * (float)Math.Sin(theta);
            data.Add(new Point2f(x, y));
        }

        Cv2.Kmeans(InputArray.Create(data), 4, labels,
            new TermCriteria(CriteriaType.Eps & CriteriaType.Count, 10, 1.0), 5, KMeansFlags.PpCenters, centers);
        List<Point2f> fourPoints = new List<Point2f>();
        List<Point2f> xyPoints = new List<Point2f>();
        for (int i = 0; i < 4; i++)
        {
            float x = centers.At<float>(i, 0);
            float y = centers.At<float>(i, 1);
            float rho = (float)Math.Sqrt(x * x + y * y);
            float theta = (float)Math.Atan2(y, x);

            xyPoints.Add(new Point2f(x, y));
            fourPoints.Add(new Point2f(rho, theta));
        }
        
        var sortedXyPoints = xyPoints.OrderBy(r => Math.Abs(r.Y / r.X)).ToArray();
        List<Point2d> ans = new List<Point2d>();
        for (uint i = 0; i < 2; i++)
        {
            float x0 = sortedXyPoints[i].X;
            float y0 = sortedXyPoints[i].Y;
            for (uint j = 2; j < 4; j++)
            {
                float x1 = sortedXyPoints[j].X;
                float y1 = sortedXyPoints[j].Y;
                float x = (y0 * (x1 * x1 + y1 * y1) - y1 * (x0 * x0 + y0 * y0)) / (y0 * x1 - x0 * y1);
                float y = (x0 * (x1 * x1 + y1 * y1) - x1 * (x0 * x0 + y0 * y0)) / (y1 * x0 - x1 * y0);
                ans.Add(new Point2d(x, y));
            }
        }
        // order of points (top-left, bottom-left, top-right, bottom-right)
        var sortedAns = ans.OrderBy(r => r.X).ThenBy(r=>r.Y).ToArray();
        //TODO: convert sort(arr1.begin()+2, arr1.end(), [](Point2f lhs, Point2f rhs) { return lhs.y<rhs.y; }); to c#
        return new List<Point2d>(sortedAns);
    }

标签: c#c++

解决方案


如果您想复制您可以使用的确切行为,Array.Sort或者List.Sort需要一个范围的开始和长度来排序。您将需要实现一个IComparer<T>而不是使用委托,但是制作一个采用委托来比较对象属性的实现是相当简单的。这应该让您复制确切的行为:

public class KeyComparer<T, TKey> : IComparer<T> where TKey : IComparable<TKey>
{
    private readonly Func<T, TKey> selector;
    public KeyComparer(Func<T, TKey> selector) => this.selector = selector;
    public int Compare(T x, T y) => selector(x).CompareTo(selector(y));
}
...
var xComparer = new KeyComparer<Point, float>(p => p.X);
var yComparer = new KeyComparer<Point, float>(p => p.Y);

myList.Sort(xComparer);
myList.Sort(0, 2, yComparer);
myList.Sort(2, myList.Length -2, yComparer);

但是,如果不理解为什么要这样做,我会非常犹豫是否只使用这样的解决方案。我会看看我是否能找到实现算法的描述,看看它是否与实现相匹配,或者寻找其他实现,看看它们是否使用相同类型的排序。


推荐阅读