Bitwise operators in Python

share on google plus share on facebook share on twitter share on linkedin share via email

Python has logical operators (like ‘and’) and bitwise operators (like ‘&’). Bitwise operators are not that common in Python code, but they can be extremely useful in some cases. For example, in RhinoPython they are used to work with geometry type filters.

The geometry types in the rhinoscripsyntax package are defined in the selection module and can be accessed like this:

1.import rhinoscriptsyntax as rs
2. 
3.print rs.filter.point    # prints 1
4.print rs.filter.curve    # prints 4
5.print rs.filter.surface  # prints 8

The entire list of values can be found on GitHub, but i will copy the code here for simplicity:

01.class filter:
02.    allobjects = 0
03.    point = 1
04.    pointcloud = 2
05.    curve = 4
06.    surface = 8
07.    polysurface = 16
08.    mesh = 32
09.    light = 256
10.    annotation = 512
11.    instance = 4096
12.    textdot = 8192
13.    grip = 16384
14.    detail = 32768
15.    hatch = 65536
16.    morph = 13072
17.    cage = 134217728
18.    phantom = 268435456
19.    clippingplane = 536870912
20.    extrusion = 1073741824

Notice that the values correspond to powers of 2. Therefore they each correspond to a different digit in the binary system:

1.print bin(rs.filter.point)    # prints '0b1'
2.print bin(rs.filter.curve)    # prints '0b100'
3.print bin(rs.filter.surface)  # prints '0b1000'

This is where bitwise operators come in. Bitwise operators compare corresponding digits in two binary numbers and return a result in binary form accordingly.

Bitwise ‘and’ (&) returns a binary number with 1 at digits where both of the corresponding digits of the operands are 1:

1.print 0 & 1    # prints 0 (0000), since 0000 'and' 0001 => 0000
2.print 2 & 3    # prints 2 (0010), since 0010 'and' 0011 => 0010
3.print 2 & 7    # prints 2 (0010), since 0010 'and' 0111 => 0010
4.print 15 & 10  # prints 10 (1010), since 1111 'and' 1010 => 1010 

Bitwise ‘or’ (|) returns a binary number with 1 at digits where at least one of the digits of the operands was 1:

1.print 0 & 1    # prints 1 (0001), since 0000 'and' 0001 => 0001
2.print 2 & 3    # prints 3 (0011), since 0010 'and' 0011 => 0011
3.print 2 & 7    # prints 7 (0111), since 0010 'and' 0111 => 0111
4.print 15 & 10  # prints 15 (1111), since 1111 'and' 1010 => 1111 

Getting back to the example of geometry filters in rhinoscriptsyntax, this snippet returns the guids of both points and curves:

1.guids = rs.ObjectsByType(rs.filter.point | rs.filter.curve)

What happens in the background is the following. The result of the combined filter is:

1.filter = rs.filter.point | rs.filter.curve
2.print filter  # prints 5 (0101), since 0001 'or' 0100 => 0101

Comparing this combined filter with the filter values of the different geometry types using bitwise ‘and’ the function can figure out which types to include in the result:

01.include_points   = False
02.include_curves   = False
03.include_surfaces = False
04. 
05.if filter & rs.filter.point:
06.    include_points = True
07. 
08.if filter & rs.filter.curve:
09.    include_curves = True
10. 
11.if filter & rs.filter.surface:
12.    include_surfaces = True
13. 
14.print include_points    # prints True
15.print include_curves    # prints True
16.print include_surfaces  # prints False

Leave a response

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>