Help on GetHashCode() method. Same value returns for different objects?

Hello,

I came up with a situation such that when I run a scipt in GHPython, I get the same integer value from GetHashCode() method when I loop through a list of different lines defined as input to GHPython component. My intention is to creat a dictionary with hash codes as keys and the geometry itself as the value.

Shouldn’t hash codes be unique for different items during the session?

Thanks.

They are unique if lines are unique, ie, if end points of different lines are different.

line.GetHashCode() = line.From.GetHashCode() ^ line.To.GetHashCode().

Are you sure that you don´t have duplicated lines?

The API says “not unique” (?). Permuting the XYZ values of Point3d produces the same hashcode too.

image

I am totally sure that the lines are different. Strangely, I am providing same line to different inputs (x and y for instance) of GHPython component, and it gives different hash codes even the line is not different. Actually that happens when I don’t provide type hint. When type hint is provided it returns the same hash code. Is there any other way of getting a unique id to different objects?

The GetHashCode() method of line produces the hashcode as:
line.From.X.GetHashCode() ^ line.From.Y.GetHashCode() ^ … etc.

So basically you can swap the x,y,z values of each point of your line and all will have the same hashcode. Also for example (0,0,0) and (1,0,1) have the same hashcode.

I don’t know much about this, maybe this is helpful?

I don’t know any other method to obtain unique id for objects in the code other than GetHashCode. Do you know another method to achieve @dsonntag ?

I would try the implementation from the link, using all 6 fields of the line object (2 points x 3 coordinates).

Thank you for your guidance however I should not generate myself the hash code, or other id, since I should be able to find it out later by searching, and it should belong to the object. If assigning the value generated would be possible that could work. But as far as I know hash code could not be set?

Well, not sure what is happening here because I am not familiar with python. I just know about how .Net works, and I guess in general how compiled code works. There are two types of things, objects and structs. Objects are referenced types, this means that have a specific location in memory, structs are value types, this means that two variables assigned with same value will have different locations in memory. Lines are structures in Rhino. Not sure if this has something to do here, but the point is what do you mean with different objects, geometrically o by reference in memory? In a C sharp comp. even without setting the input type hint, I get what I expect, same value for same geometry. As GH clone the data in parameters, you never will be able to check if they have the same memory location, bc cloning means create a new instance, ie, a new memory location. If you do the following, do you get a different behaviour? the code is just A = x.GetHashCode();

Hmm, check the real type of the input data when you do not set the type hint. Are they Rhino.Geometry.Line or GH_Line¿ maybe you are getting GH_Line and its GetHashCode() is not using the geometry value, just the default value. In that case you need to cast the input to the expected data type.

When I don’t provide type hint below is what I get, same input, different hashcodes.

could you do print x.GetType() or its equivalent in py¿

When type hint is set as line, same hashcodes as below:

x, and y -> type hint: line
z, and u -> type hint: no type hint
v, and w -> type hint: ghdoc Object when geometry (rhinoscriptsyntax)

When I run below code (x is a list of 20 lines), since some of hashcodes are the same, generated dictionary overwrites the existing keys and ends up with less items as shown below:

input lines (x) are as below:

When I add a check in the code as below, I could correct this issue but that generated hash code won’t belong to the line. Any ideas how to avoid? Thanks.

Ok I think I find it. You are using reference lines in rhino, rather than internalized lines in gh, right?. Check the type with no type hint for referenced and no referenced lines, for the first case you get LineCurve, for the second you get Line. As LineCurve inherits from Curve, it doesn’t have a custom GetHashCode() as Line have. So, you have two options, or use no type hint and avoid referenced geometry, or cast your geometry to your controlled types as Line. But just be aware that for other geometries, GetHashCode() will not give you an unique number, you have to do it yourself with your own functions.

Hi Dani,

Right, the lines I showed in the previous post were referenced from Rhino as you said. But there are others internalized in gh as well.

I think, I got the point from your explanation. For line objects, the options you suggested are both ok, I’ll either define no type hint or cast objects as lines. Thank you very much for this detailed answer.

Lastly, if I undestand you correctly, you said in your last sentence that setting Hash Code is possible? Since I don’t know how, I’d glad if you could help me on how to do it, since setting them by my own function would be the safest way, right?

I don’t know your problem, which geometry or data you will use, so I don’t know. But is easy to do, at least in c# bc all things has this method. This hash code is just an integer. Take the data that defines the geometry, create integer with them (if they are basic types as points or doubles, call its GetHashCode() method) and do the power with them (is better do the power, A^B rather than A+B for example, because if you do B+A you will get the same value, but no for B^A).

1 Like

Ok, thank you @Dani_Abalde. I’ll look for a way to do it in python.