Skip to content
This repository has been archived by the owner on Feb 9, 2021. It is now read-only.

Commit

Permalink
Merge pull request #147 from adam-urbanczyk/master
Browse files Browse the repository at this point in the history
DirectionNthSelector  --> selects Nth face/wire normal/parallel to given direction
  • Loading branch information
dcowden committed Jun 8, 2016
2 parents a54a819 + 9df0e39 commit 0ef569a
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 4 deletions.
57 changes: 54 additions & 3 deletions cadquery/selectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,15 +306,66 @@ def distance(tShape):
# pnt = tShape.Center()
#return pnt.dot(self.vector)

# import OrderedDict
from collections import OrderedDict
#make and distance to object dict
objectDict = {distance(el) : el for el in objectList}
#transform it into an ordered dict
objectDict = OrderedDict(sorted(objectDict.items(),
key=lambda x: x[0]))

# find out the max/min distance
if self.directionMax:
d = max(map(distance, objectList))
d = objectDict.keys()[-1]
else:
d = min(map(distance, objectList))

d = objectDict.keys()[0]
# return all objects at the max/min distance (within a tolerance)
return filter(lambda o: abs(d - distance(o)) < self.TOLERANCE, objectList)

class DirectionNthSelector(ParallelDirSelector):
"""
Selects nth object parallel (or normal) to the specified direction
Used for faces and edges
Applicability:
Linear Edges
Planar Faces
"""
def __init__(self, vector, n, directionMax=True, tolerance=0.0001):
self.direction = vector
self.max = max
self.directionMax = directionMax
self.TOLERANCE = tolerance
if directionMax:
self.N = n #do we want indexing from 0 or from 1?
else:
self.N = -n

def filter(self,objectList):
#select first the objects that are normal/parallel to a given dir
objectList = super(DirectionNthSelector,self).filter(objectList)

def distance(tShape):
return tShape.Center().dot(self.direction)
#if tShape.ShapeType == 'Vertex':
# pnt = tShape.Point
#else:
# pnt = tShape.Center()
#return pnt.dot(self.vector)

#make and distance to object dict
objectDict = {distance(el) : el for el in objectList}
#calculate how many digits of precision do we need
digits = int(1/self.TOLERANCE)
# create a rounded distance to original distance mapping (implicitly perfroms unique operation)
dist_round_dist = {round(d,digits) : d for d in objectDict.keys()}
# choose the Nth unique rounded distance
nth_d = dist_round_dist[sorted(dist_round_dist.keys())[self.N]]

# map back to original objects and return
return [objectDict[d] for d in objectDict.keys() if abs(d-nth_d) < self.TOLERANCE]

class BinarySelector(Selector):
"""
Base class for selectors that operates with two other
Expand Down
24 changes: 23 additions & 1 deletion tests/TestCQSelectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,29 @@ def testMinDistance(self):
# test the case of multiple objects at the same distance
el = c.edges("<Z").vals()
self.assertEqual(4, len(el))


def testNthDistance(self):
c = Workplane('XY').pushPoints([(-2,0),(2,0)]).box(1,1,1)

#2nd face
val = c.faces(selectors.DirectionNthSelector(Vector(1,0,0),1)).val()
self.assertAlmostEqual(val.Center().x,-1.5)

#2nd face with inversed selection vector
val = c.faces(selectors.DirectionNthSelector(Vector(-1,0,0),1)).val()
self.assertAlmostEqual(val.Center().x,1.5)

#2nd last face
val = c.faces(selectors.DirectionNthSelector(Vector(1,0,0),-2)).val()
self.assertAlmostEqual(val.Center().x,1.5)

#Last face
val = c.faces(selectors.DirectionNthSelector(Vector(1,0,0),-1)).val()
self.assertAlmostEqual(val.Center().x,2.5)

#check if the selected face if normal to the specified Vector
self.assertAlmostEqual(val.normalAt().cross(Vector(1,0,0)).Length,0.0)

def testNearestTo(self):
c = CQ(makeUnitCube())

Expand Down

0 comments on commit 0ef569a

Please sign in to comment.