Hi Frank,
The __hash__ overload feature is available on the subversion repository
(rev.202). Just svn update and rebuild the solution. You can notice now
that the __hash__() and id() methods return different results. This
point is important: whenever you create a pythonOCC object (for instance
a Standard_Transient), you actually create *2* different objects: the
OpenCascade object and the Python proxy to this object. This can be
shown with the 'print' expression (see example below):
- the __hash__() method returns the memory location of the OpenCascade
object.
- the id() method returns the memory location of the python proxy.
Python 2.5.2 |EPD Py25 4.1.30101| (r252:60911, Dec 19 2008, 13:49:12)
[MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from OCC.Standard import *
>>> a = Standard_Transient()
>>> print a
<OCC.Standard.Standard_Transient; proxy of <Swig Object of type
'Standard_Transient *' at 0x00E0F1E0> >
>>> a.__hash__()
20841077
>>> id(a)
14703088
Best Regards,
Thomas
Frank Conradie a écrit :
By the way, I have a related question, which may be more appropriate for
the OCC forums, since I know it is an OCC issue and not specific to
pythonocc. But maybe you OCC-gurus can help me out ;-)
Why is it that TopExp_Explorer sometimes returns the same shapes
multiple times, e.g. in my code I'm using ShapeFix to turn a complex
shell with internal faces into a COMPSOLID with multiple SOLIDs that
share these internal faces, but for some reason the same SOLIDs get
returned multiple times by TopExp_Explorer. E.g. say my COMPSOLID
consists of two SOLIDs, these two solids get returned by the explorer 4
times each (S1, S2, S1, S2, etc.)! Yet another reason why we need the
__hash__ to work properly for shapes, as every time the same SOLID is
returned it has a different id, i.e. id(1st S1) != id(2nd S1), but
S1.HashCode() == S2.HashCode().
Cheers,
Frank
Thomas Paviot wrote:
Hello Franck,
It's really a good idea to map the Hash() OpenCascade method and the
python __hash__(). I read a few posts on the __hash__() topic. A good
one is, for instance:
http://mail.python.org/pipermail/python-dev/2003-September/037923.html .
It's said that 'object.__hash__() returns id(obj) by default'. I
tested that a little:
a = object()
a.__hash__()
10093672
id(a)
10093672
But, if __hash__ is overloaded, then __hash() and id() returns 2
different integers.
This is then my proposition:
- *for each* pythonOCC object that is managed by Handle_* (and thus,
for which the HashCode() method is available), overload the __hash__
method as Frank said. It can be done within SWIG with two or three
more lines in the SWIG_generator.py script.
- for other pythonOCC objects, leave the default __hash__ method (thus
equivalent to id() )
Thomas
Frank Conradie a écrit :
Hi Jelle
My particular need was to hash TopoDS_Shape objects properly. I'm not
sure if this is a good permanent solution, but this works for me, for
shapes at least:
def shape_hash(self):
return self.HashCode(sys.maxint)
TopoDS.TopoDS_Shape.__hash__ = shape_hash
Now I can use shapes in a Python set and as keys in a Python dict -
which also means that your Topology.Topo class works properly now (if
topo_item in topo_set)!
I can't help thinking there must be a more general way to incorporate
this into the SWIG wrapper for *all* OCC classes, but I don't know
enough about swig yet to know for sure.
Cheers,
Frank
jelle feringa wrote:
In order to use pythonocc objects in sets and as dict keys, they
must hash to the underlying OCC object. In fact, your Topo class
uses a set internally that does not work because of this very
fact, because set checks for set membership via hash, and thus,
two of the same objects that get explored will hash to different
values and thus be passed back twice.
Hi Frank,
This is really interesting, thanks so much for explaining.
Actually, now I recall what I messed up. I looped through a list of
some topology, lets say vertices and checked for their id ->
id(vertex).
That did work, however as you point out hash != id.
I think overloading the hash with comparing id()'s could work.
Hope this makes sense.
A lot, thanks for your advice here.
I suppose I could overwrite __hash__ the same way you guys
initially got past the == issue.
What do you think of overloading hash with id?
I'll check tomorrow morning, would be great if this is a stable fix,
it sure could be useful.
Thanks,
-jelle
------------------------------------------------------------------------
_______________________________________________
Pythonocc-users mailing list
Pythonocc-users@gna.org
https://mail.gna.org/listinfo/pythonocc-users
_______________________________________________
Pythonocc-users mailing list
Pythonocc-users@gna.org
https://mail.gna.org/listinfo/pythonocc-users
_______________________________________________
Pythonocc-users mailing list
Pythonocc-users@gna.org
https://mail.gna.org/listinfo/pythonocc-users