简体   繁体   English

实现2D线的相等性

[英]Implementing equality for 2d lines

I have simple class defining 2d line: 我有定义2d线的简单类:

public class Line {
    public double X1 { get; set; }
    public double Y1 { get; set; }
    public double X2 { get; set; }
    public double Y2 { get; set; }
}

My primary goal is to get different lines from List using .Distinct(). 我的主要目标是使用.Distinct()从List获得不同的行。 In my case two lines are equal if theirs coordinates are equal regardless direction (line 1,2 -> 3,4 equals to 3,4 -> 1,2). 在我的情况下,如果两条线的坐标相等,则无论方向如何(线1,2-> 3,4等于3,4-> 1,2)都相等。 I going to implement Equals like: 我将像这样实现Equals:

public override bool Equals(object obj) {
    if (obj as Line == null) { return false; }
    var second = (Line)obj;
    if (this.X1 != second.X1 && this.X1 != second.X2) { return false; }
    if (this.Y1 != second.Y1 && this.Y1 != second.Y2) { return false; }
    if (this.X2 != second.X2 && this.X2 != second.X1) { return false; }
    if (this.Y2 != second.Y2 && this.Y2 != second.Y1) { return false; }
    return true;
}

but I have no idea how to implement GetHashCode (as I understand it's necessary to make it in case of using Distinct()) 但我不知道如何实现GetHashCode(据我了解,在使用Distinct()的情况下有必要做到这一点)

This becomes a bit easier if you first define a Point , then define your Line in terms of 2 Point s. 如果首先定义一个Point ,然后以2 Point单位定义Line ,这会变得容易一些。

Now, to calculate a reliable (but unaffected by direction) hash of a Line , make sure you order your points consistently when calculating the hash. 现在,要计算Line的可靠(但不受方向影响)哈希,请确保在计算哈希时始终对点进行排序。

Putting this all together into a complete implementation (which also covers operator == and != ): 将所有这些放到一个完整的实现中(还包括运算符==!= ):

public class Point
{
    public double X { get; set; }
    public double Y { get; set; }

    protected bool Equals(Point other)
    {
        return X.Equals(other.X) && Y.Equals(other.Y);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((Point) obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return (X.GetHashCode()*397) + Y.GetHashCode();
        }
    }

    public static bool operator ==(Point left, Point right)
    {
        return Equals(left, right);
    }

    public static bool operator !=(Point left, Point right)
    {
        return !Equals(left, right);
    }
}

public class Line
{
    public Point Point1 { get; set; }
    public Point Point2 { get; set; }

    protected bool Equals(Line other)
    {
        return Equals(Point1, other.Point1) && Equals(Point2, other.Point2) 
             || Equals(Point1, other.Point2) && Equals(Point2, other.Point1);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((Line) obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            var orderedPoints =
                new[] {Point1, Point2}.OrderBy(p => p != null ? p.X : 0)
                                      .ThenBy(p => p != null ? p.Y : 0).ToList();
            var p1 = orderedPoints[0];
            var p2 = orderedPoints[1];
            return ((p1 != null ? p1.GetHashCode() : 0)*397) 
                   + (p2 != null ? p2.GetHashCode() : 0);
        }
    }

    public static bool operator ==(Line left, Line right)
    {
        return Equals(left, right);
    }

    public static bool operator !=(Line left, Line right)
    {
        return !Equals(left, right);
    }
}

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

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