c# - 如何将以下 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);
}
解决方案
如果您想复制您可以使用的确切行为,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);
但是,如果不理解为什么要这样做,我会非常犹豫是否只使用这样的解决方案。我会看看我是否能找到实现算法的描述,看看它是否与实现相匹配,或者寻找其他实现,看看它们是否使用相同类型的排序。