For a very quick (to calculate) hash with the desired properties on clockwise/counter clockwise independence you would not want to be dependent on finding a well defined ordering of the points.
This limits your hash combining operations to ones which commute. Therefore we wish to keep any and all data which is independent of orientation separate during the combining operations.
Here is a simple solution:
Assuming a combine function int -> int -> int which is associative
any of the following will do to start with:
public static int combine(int h, int x)
{
return h * 31 + x;
}
public static int combine(int h, int x)
{
return h ^ x;
}
Then we can do the following:
public override int GetHashCode()
{
int x = 0;
int y = 0;
uint h = 0;
foreach (var point p in polgon)
{
x = combine(x, p.X);
y = combine(y, p.Y);
h++;
}
// simplified, unrolled Murmur2 hash for end stage
const uint m = 0x5bd1e995;
const int r = 24;
uint h = count;
uint k = ReinterpretInt32ToUInt32(x);
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
k = ReinterpretInt32ToUInt32(y);
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
// avalanche
h ^= h >> 13;
h *= m;
h ^= h >> 15;
return ReinterpretUInt32ToInt32(h);
}
Relying on this to make the code above easy
public unsafe uint ReinterpretInt32ToUInt32(int i)
{
return *((uint*) (void*) &i);
}
public unsafe int ReinterpretUInt32ToInt32(uint u)
{
return *((int*) (void*) &u);
}
This will not be the best hash in terms of collision avoidance but should be very fast to calculate and you may find it sufficient for your needs.