Reputation: 954
I have a problem. I want to compare 2 coordinates with each other, but the coordinates doesn't have to be exactly the same. It's allowed to have a maximum difference of 0,1. So I created this code:
public class HexagonRegistryList
{
public int HexagonNum { get; set; }
public float x1 { get; set; }
public float y1 { get; set; }
public float x2 { get; set; }
public float y2 { get; set; }
public float x3 { get; set; }
public float y3 { get; set; }
public float x4 { get; set; }
public float y4 { get; set; }
public float x5 { get; set; }
public float y5 { get; set; }
public float x6 { get; set; }
public float y6 { get; set; }
public int ShapeNum { get; set; }
public HexagonRegistryList()
{
this.AdjacentShapeNumbers = new List<int>();
}
public List<int> AdjacentShapeNumbers { get; set; }
public IEnumerable<(float x, float y)> GetPoints()
{
yield return (x1, y1);
yield return (x2, y2);
yield return (x3, y3);
yield return (x4, y4);
yield return (x5, y5);
yield return (x6, y6);
}
public struct PointComparer : IEqualityComparer<(float x, float y)>
{
public bool Equals((float x, float y) p1, (float x, float y) p2)
{
return Math.Abs(p1.x - p2.x) < 0.1f && Math.Abs(p1.y - p2.y) < 0.1f;
}
public int GetHashCode((float x, float y) obj)
{
return obj.GetHashCode();
}
}
public bool IsAdjacentTo(HexagonRegistryList other)
{
//var isAdjacentTo = GetPoints().Intersect(other.GetPoints()).Count() >= 2;
var isAdjacentTo = GetPoints().Intersect(other.GetPoints(), new PointComparer()).Count() >= 2;
if (isAdjacentTo)
{
if (other.ShapeNum != 0)
{
AdjacentShapeNumbers.Add(other.ShapeNum);
}
}
return isAdjacentTo;
}
}
Now when it gets at this line: var isAdjacentTo = GetPoints().Intersect(other.GetPoints(), new PointComparer()).Count() >= 2;
It returns false, what is supposed to be true. Here are the coordinates:
x1 = 607.5
y1 = 935.3075
x2 = 607.5
y2 = 935.3074
As you can see the y coordinates have a difference of 0.0001, but that shouldn't be a problem with my code. But for some reason it says that these coordinates don't match!
I am comparing hexagon sides with each other, so here is the main call I do:
var sharedEdges = hexagons.GetPairs().Where(t => hexagon.IsAdjacentTo(hexagons[i]));
I am also using this class for the comparing:
public static class EnumerableExtensions
{
public static IEnumerable<(T first, T second)> GetPairs<T>(this IEnumerable<T> list)
{
return list.SelectMany((value, index) => list.Skip(index + 1),
(first, second) => (first, second));
}
}
hexagons is a List and hexagon is just 1 hexagon in the list.
What am I doing wrong?
Upvotes: 1
Views: 882
Reputation: 1500665
I suspect the problem is that Intersect
is effectively building a hash set to compare for equality. Your two "nearly equal" coordinates won't have the same hash code, so it won't even call Equals
. You could implement GetHashCode
by always returning 0, but fundamentally you've still got a big problem: your equality comparer can't implement IEqualityComparer<T>
as intended. An equality comparer should obey these rules for Equals
:
Equals(x, x)
should return true - that's fineEquals(x, y)
should return Equals(y, x)
- that's fine tooEquals(x, y)
and Equals(y, z)
return true, then Equals(x, z)
should return true too - and that's not fine.If you have three points, say:
a
and b
are close, and b
and c
are close, but a
and c
are not closeAsking for proximity isn't the same as asking for equality - and you want the former.
I realize this answer doesn't show you what you should do - but it's showing you where you're going wrong. I think you'll need to change your approach entirely. It's not entirely clear to me what you want to achieve in your method, but you might want to consider finding the distances between points instead of treating them as equal.
Upvotes: 6