Merge pull request #95 from hyOzd/add-boxselector

Added 3d box selector with an option to use the bounding box for selection.
This commit is contained in:
Jeremy Wright 2015-06-20 23:11:04 -04:00
commit 645e3cd6f7
2 changed files with 140 additions and 1 deletions

View File

@ -70,6 +70,49 @@ class NearestToPointSelector(Selector):
return [ min(objectList,key=dist) ]
class BoxSelector(Selector):
"""
Selects objects inside the 3D box defined by 2 points.
If `boundingbox` is True only the objects that have their bounding
box inside the given box is selected. Otherwise only center point
of the object is tested.
Applicability: all types of shapes
Example::
CQ(aCube).edges(BoxSelector((0,1,0), (1,2,1))
"""
def __init__(self, point0, point1, boundingbox=False):
self.p0 = Vector(*point0)
self.p1 = Vector(*point1)
self.test_boundingbox = boundingbox
def filter(self, objectList):
result = []
x0, y0, z0 = self.p0.toTuple()
x1, y1, z1 = self.p1.toTuple()
def isInsideBox(p):
# using XOR for checking if x/y/z is in between regardless
# of order of x/y/z0 and x/y/z1
return ((p.x < x0) ^ (p.x < x1)) and \
((p.y < y0) ^ (p.y < y1)) and \
((p.z < z0) ^ (p.z < z1))
for o in objectList:
if self.test_boundingbox:
bb = o.BoundingBox()
if isInsideBox(Vector(bb.xmin, bb.ymin, bb.zmin)) and \
isInsideBox(Vector(bb.xmax, bb.ymax, bb.zmax)):
result.append(o)
else:
if isInsideBox(o.Center()):
result.append(o)
return result
class BaseDirSelector(Selector):
"""

View File

@ -178,6 +178,102 @@ class TestCQSelectors(BaseTest):
s = c.solids(selectors.NearestToPointSelector(t)).vals()
self.assertEqual(1,len(s))
def testBox(self):
c = CQ(makeUnitCube())
# test vertice selection
test_data_vertices = [
# box point0, box point1, selected vertice
((0.9, 0.9, 0.9), (1.1, 1.1, 1.1), (1.0, 1.0, 1.0)),
((-0.1, 0.9, 0.9), (0.9, 1.1, 1.1), (0.0, 1.0, 1.0)),
((-0.1, -0.1, 0.9), (0.1, 0.1, 1.1), (0.0, 0.0, 1.0)),
((-0.1, -0.1, -0.1), (0.1, 0.1, 0.1), (0.0, 0.0, 0.0)),
((0.9, -0.1, -0.1), (1.1, 0.1, 0.1), (1.0, 0.0, 0.0)),
((0.9, 0.9, -0.1), (1.1, 1.1, 0.1), (1.0, 1.0, 0.0)),
((-0.1, 0.9, -0.1), (0.1, 1.1, 0.1), (0.0, 1.0, 0.0)),
((0.9, -0.1, 0.9), (1.1, 0.1, 1.1), (1.0, 0.0, 1.0))
]
for d in test_data_vertices:
vl = c.vertices(selectors.BoxSelector(d[0], d[1])).vals()
self.assertEqual(1, len(vl))
v = vl[0]
self.assertTupleAlmostEquals(d[2], (v.X, v.Y, v.Z), 3)
# this time box points are swapped
vl = c.vertices(selectors.BoxSelector(d[1], d[0])).vals()
self.assertEqual(1, len(vl))
v = vl[0]
self.assertTupleAlmostEquals(d[2], (v.X, v.Y, v.Z), 3)
# test multiple vertices selection
vl = c.vertices(selectors.BoxSelector((-0.1, -0.1, 0.9),(0.1, 1.1, 1.1))).vals()
self.assertEqual(2, len(vl))
vl = c.vertices(selectors.BoxSelector((-0.1, -0.1, -0.1),(0.1, 1.1, 1.1))).vals()
self.assertEqual(4, len(vl))
# test edge selection
test_data_edges = [
# box point0, box point1, edge center
((0.4, -0.1, -0.1), (0.6, 0.1, 0.1), (0.5, 0.0, 0.0)),
((-0.1, -0.1, 0.4), (0.1, 0.1, 0.6), (0.0, 0.0, 0.5)),
((0.9, 0.9, 0.4), (1.1, 1.1, 0.6), (1.0, 1.0, 0.5)),
((0.4, 0.9, 0.9), (0.6, 1.1, 1.1,), (0.5, 1.0, 1.0))
]
for d in test_data_edges:
el = c.edges(selectors.BoxSelector(d[0], d[1])).vals()
self.assertEqual(1, len(el))
ec = el[0].Center()
self.assertTupleAlmostEquals(d[2], (ec.x, ec.y, ec.z), 3)
# test again by swapping box points
el = c.edges(selectors.BoxSelector(d[1], d[0])).vals()
self.assertEqual(1, len(el))
ec = el[0].Center()
self.assertTupleAlmostEquals(d[2], (ec.x, ec.y, ec.z), 3)
# test multiple edge selection
el = c.edges(selectors.BoxSelector((-0.1, -0.1, -0.1), (0.6, 0.1, 0.6))).vals()
self.assertEqual(2, len(el))
el = c.edges(selectors.BoxSelector((-0.1, -0.1, -0.1), (1.1, 0.1, 0.6))).vals()
self.assertEqual(3, len(el))
# test face selection
test_data_faces = [
# box point0, box point1, face center
((0.4, -0.1, 0.4), (0.6, 0.1, 0.6), (0.5, 0.0, 0.5)),
((0.9, 0.4, 0.4), (1.1, 0.6, 0.6), (1.0, 0.5, 0.5)),
((0.4, 0.4, 0.9), (0.6, 0.6, 1.1), (0.5, 0.5, 1.0)),
((0.4, 0.4, -0.1), (0.6, 0.6, 0.1), (0.5, 0.5, 0.0))
]
for d in test_data_faces:
fl = c.faces(selectors.BoxSelector(d[0], d[1])).vals()
self.assertEqual(1, len(fl))
fc = fl[0].Center()
self.assertTupleAlmostEquals(d[2], (fc.x, fc.y, fc.z), 3)
# test again by swapping box points
fl = c.faces(selectors.BoxSelector(d[1], d[0])).vals()
self.assertEqual(1, len(fl))
fc = fl[0].Center()
self.assertTupleAlmostEquals(d[2], (fc.x, fc.y, fc.z), 3)
# test multiple face selection
fl = c.faces(selectors.BoxSelector((0.4, 0.4, 0.4), (0.6, 1.1, 1.1))).vals()
self.assertEqual(2, len(fl))
fl = c.faces(selectors.BoxSelector((0.4, 0.4, 0.4), (1.1, 1.1, 1.1))).vals()
self.assertEqual(3, len(fl))
# test boundingbox option
el = c.edges(selectors.BoxSelector((-0.1, -0.1, -0.1), (1.1, 0.1, 0.6), True)).vals()
self.assertEqual(1, len(el))
fl = c.faces(selectors.BoxSelector((0.4, 0.4, 0.4), (1.1, 1.1, 1.1), True)).vals()
self.assertEqual(0, len(fl))
fl = c.faces(selectors.BoxSelector((-0.1, 0.4, -0.1), (1.1, 1.1, 1.1), True)).vals()
self.assertEqual(1, len(fl))
def testFaceCount(self):
c = CQ(makeUnitCube())
self.assertEqual( 6, c.faces().size() )
@ -194,4 +290,4 @@ class TestCQSelectors(BaseTest):
self.assertEqual(1,v2.size() ) #another way
#make sure the vertex is the right one
self.assertTupleAlmostEquals((0.0,0.0,1.0),v2.val().toTuple() ,3)
self.assertTupleAlmostEquals((0.0,0.0,1.0),v2.val().toTuple() ,3)