From 875b64a63939a8ed769b0ea74631c53244710865 Mon Sep 17 00:00:00 2001 From: adam-urbanczyk Date: Mon, 23 May 2016 22:01:05 +0200 Subject: [PATCH 1/5] Started working on nth selector Implementing using ordered dict --- cadquery/selectors.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/cadquery/selectors.py b/cadquery/selectors.py index be07d7b..246db30 100644 --- a/cadquery/selectors.py +++ b/cadquery/selectors.py @@ -306,12 +306,20 @@ 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) From 1ac5937f963c95b58857013512ff8ed1b6b8c82b Mon Sep 17 00:00:00 2001 From: adam-urbanczyk Date: Thu, 2 Jun 2016 21:49:15 +0200 Subject: [PATCH 2/5] Preliminary implementation of Nth selector Not yet tested --- cadquery/selectors.py | 58 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/cadquery/selectors.py b/cadquery/selectors.py index 246db30..81a7ba2 100644 --- a/cadquery/selectors.py +++ b/cadquery/selectors.py @@ -323,6 +323,64 @@ def distance(tShape): # return all objects at the max/min distance (within a tolerance) return filter(lambda o: abs(d - distance(o)) < self.TOLERANCE, objectList) +class DirectionNthSelector(Selector): + """ + Selects objects closest or farthest in the specified direction + Used for faces, points, and edges + + Applicability: + All object types. for a vertex, its point is used. for all other kinds + of objects, the center of mass of the object is used. + + You can use the string shortcuts >(X|Y|Z) or <(X|Y|Z) if you want to + select based on a cardinal direction. + + For example this:: + + CQ(aCube).faces ( DirectionMinMaxSelector((0,0,1),True ) + + Means to select the face having the center of mass farthest in the positive z direction, + and is the same as: + + CQ(aCube).faces( ">Z" ) + + Future Enhancements: + provide a nicer way to select in arbitrary directions. IE, a bit more code could + allow '>(0,0,1)' to work. + + """ + def __init__(self, vector, n, directionMax=True, tolerance=0.0001): + self.vector = vector + self.max = max + self.directionMax = directionMax + self.TOLERANCE = tolerance + if directionMax: + self.N = n + else: + self.N = -n + + def filter(self,objectList): + + def distance(tShape): + return tShape.Center().dot(self.vector) + #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 From 788bc58244dac82201282c72c447633c71e9de9e Mon Sep 17 00:00:00 2001 From: adam-urbanczyk Date: Sun, 5 Jun 2016 16:54:03 +0200 Subject: [PATCH 3/5] DirectionNthSelector inherits from ParallelDirSelector DirectionNthSelector will only consider objects parallel | normal to the specified direction --- cadquery/selectors.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cadquery/selectors.py b/cadquery/selectors.py index 81a7ba2..0fe1f76 100644 --- a/cadquery/selectors.py +++ b/cadquery/selectors.py @@ -323,7 +323,7 @@ def distance(tShape): # return all objects at the max/min distance (within a tolerance) return filter(lambda o: abs(d - distance(o)) < self.TOLERANCE, objectList) -class DirectionNthSelector(Selector): +class DirectionNthSelector(ParallelDirSelector): """ Selects objects closest or farthest in the specified direction Used for faces, points, and edges @@ -350,19 +350,21 @@ class DirectionNthSelector(Selector): """ def __init__(self, vector, n, directionMax=True, tolerance=0.0001): - self.vector = vector + self.direction = vector self.max = max self.directionMax = directionMax self.TOLERANCE = tolerance if directionMax: - self.N = n + 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.vector) + return tShape.Center().dot(self.direction) #if tShape.ShapeType == 'Vertex': # pnt = tShape.Point #else: From 6678d3f5468031585d3b5ddd2be8e30fd786e9e0 Mon Sep 17 00:00:00 2001 From: adam-urbanczyk Date: Sun, 5 Jun 2016 16:54:29 +0200 Subject: [PATCH 4/5] Implemented test-case for DirectionNthSelector --- tests/TestCQSelectors.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/TestCQSelectors.py b/tests/TestCQSelectors.py index f90e14b..7843b12 100644 --- a/tests/TestCQSelectors.py +++ b/tests/TestCQSelectors.py @@ -166,7 +166,25 @@ def testMinDistance(self): # test the case of multiple objects at the same distance el = c.edges(" Date: Sun, 5 Jun 2016 21:26:26 +0200 Subject: [PATCH 5/5] Updated docstring for DirectionNthSelector and extended the related test-case --- cadquery/selectors.py | 25 ++++--------------------- tests/TestCQSelectors.py | 6 +++++- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/cadquery/selectors.py b/cadquery/selectors.py index 0fe1f76..14fdce2 100644 --- a/cadquery/selectors.py +++ b/cadquery/selectors.py @@ -325,29 +325,12 @@ def distance(tShape): class DirectionNthSelector(ParallelDirSelector): """ - Selects objects closest or farthest in the specified direction - Used for faces, points, and edges + Selects nth object parallel (or normal) to the specified direction + Used for faces and edges Applicability: - All object types. for a vertex, its point is used. for all other kinds - of objects, the center of mass of the object is used. - - You can use the string shortcuts >(X|Y|Z) or <(X|Y|Z) if you want to - select based on a cardinal direction. - - For example this:: - - CQ(aCube).faces ( DirectionMinMaxSelector((0,0,1),True ) - - Means to select the face having the center of mass farthest in the positive z direction, - and is the same as: - - CQ(aCube).faces( ">Z" ) - - Future Enhancements: - provide a nicer way to select in arbitrary directions. IE, a bit more code could - allow '>(0,0,1)' to work. - + Linear Edges + Planar Faces """ def __init__(self, vector, n, directionMax=True, tolerance=0.0001): self.direction = vector diff --git a/tests/TestCQSelectors.py b/tests/TestCQSelectors.py index 7843b12..05f9314 100644 --- a/tests/TestCQSelectors.py +++ b/tests/TestCQSelectors.py @@ -174,6 +174,10 @@ def testNthDistance(self): 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) @@ -182,7 +186,7 @@ def testNthDistance(self): 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 given Vector + #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):