snippetpythonMinor
Convert points into an octree
Viewed 0 times
convertpointsintooctree
Problem
I set about doing it as a challenge (and it's still far from finished) but I hit lots of problems. The main one that caused most of them was it can't deal with even numbers (it can be (1,1),(1,-1),(-1,1),(-1,-1), but nothing with a 0), so I had to multiply everything by 2 and add 1, which caused such a headache later on (which I won't bother going into as it should hopefully be fixed by now).
I don't know how they're normally coded anyway, so I just made it up as I went along until I had something that worked. Anyway, is the way I've done it alright, or is it not so good?
It calculates which path the points should take from the highest depth (eg.
If you want to try out the code on a larger grid, scroll down a bit and there's a line to uncomment where it'll download a grid of 400k points (be warned, it took 70 seconds to process for me). Here's a picture of it in 3d, where I deleted a corner so you can see how it works.
```
#import pymel.core as pm
import math
from operator import itemgetter
minDepthLevel = 0
class EditError( Exception ):
pass
def editDictionary( dictionaryName, listOfValues, canOverwriteKeys=True ):
reducedDictionary = dictionaryName
for i in listOfValues[:-2]:
if type( reducedDictionary ) != dict and canOverwriteKeys:
reducedDictionary = {}
try:
if reducedDictionary.get( i, None ) == None:
canOverwriteKeys = True
raise EditError()
elif type( reducedDictionary[i] ) != dict:
raise EditError()
except EditError:
reducedDictionary[i] = {}
except:
print "Something went wrong"
return
I don't know how they're normally coded anyway, so I just made it up as I went along until I had something that worked. Anyway, is the way I've done it alright, or is it not so good?
It calculates which path the points should take from the highest depth (eg.
9 = 16-8+4-2-1 or +1,-1,+1,-1,-1 ), and put them into the dictionary based on those values. If an entire branch (8 coordinates) gets filled, and all the blocks have the same ID, it'll go up a level, and set the branch to that ID to save space. Likewise, if there's nothing in it, it'll be set to False.If you want to try out the code on a larger grid, scroll down a bit and there's a line to uncomment where it'll download a grid of 400k points (be warned, it took 70 seconds to process for me). Here's a picture of it in 3d, where I deleted a corner so you can see how it works.
```
#import pymel.core as pm
import math
from operator import itemgetter
minDepthLevel = 0
class EditError( Exception ):
pass
def editDictionary( dictionaryName, listOfValues, canOverwriteKeys=True ):
reducedDictionary = dictionaryName
for i in listOfValues[:-2]:
if type( reducedDictionary ) != dict and canOverwriteKeys:
reducedDictionary = {}
try:
if reducedDictionary.get( i, None ) == None:
canOverwriteKeys = True
raise EditError()
elif type( reducedDictionary[i] ) != dict:
raise EditError()
except EditError:
reducedDictionary[i] = {}
except:
print "Something went wrong"
return
Solution
General comment
Python has a style guide called PEP 8. You are free to follow it or not but if except if you have a good reason, it's probably better to try to stick to it. Among other things, the naming convention is not followed.
You'll find tools to check your code (
From Idioms and Anti-Idioms in Python
Because except: catches all exceptions, including SystemExit,
KeyboardInterrupt, and GeneratorExit (which is not an error and should
not normally be caught by user code), using a bare except: is almost
never a good idea.
I'll let you think about it and catch only the relevant exceptions.
You can rewrite :
Also, if I were you, I'd define a function like :
(The naming kind of sucks because I have no idea what these functions are supposed to be).
Python has a style guide called PEP 8. You are free to follow it or not but if except if you have a good reason, it's probably better to try to stick to it. Among other things, the naming convention is not followed.
You'll find tools to check your code (
pep8) but also to fix it ([autopep8]3). You'll also find various other tools to check your code quality : pylint, pychecker, pyflakes, etc.
In roundToMultiple`From Idioms and Anti-Idioms in Python
Because except: catches all exceptions, including SystemExit,
KeyboardInterrupt, and GeneratorExit (which is not an error and should
not normally be caught by user code), using a bare except: is almost
never a good idea.
I'll let you think about it and catch only the relevant exceptions.
You can rewrite :
if closestPower > maxPower:
maxPower = closestPower
maxPower = max(closestPower, maxPower)Also, if I were you, I'd define a function like :
def roundToMultiple( multiple, i):
maxPower = 0
if i:
try:
return int( math.ceil( math.log( abs( i ), multiple ) ) )
except:
pass
return 0
def max_power( multiple, *args ):
return max(roundToMultiple(multiple, i) for i in args)(The naming kind of sucks because I have no idea what these functions are supposed to be).
Code Snippets
if closestPower > maxPower:
maxPower = closestPower
maxPower = max(closestPower, maxPower)def roundToMultiple( multiple, i):
maxPower = 0
if i:
try:
return int( math.ceil( math.log( abs( i ), multiple ) ) )
except:
pass
return 0
def max_power( multiple, *args ):
return max(roundToMultiple(multiple, i) for i in args)Context
StackExchange Code Review Q#83959, answer score: 2
Revisions (0)
No revisions yet.