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
def __init__(self, point0, point1, boundingbox=False): self.p0 = Vector(*point0) self.p1 = Vector(*point1) self.test_boundingbox = boundingbox
def Center(self): """ The center of a vertex is itself! """ return Vector(self.toTuple())
def dist(tShape): return tShape.Center().sub(Vector(*self.pnt)).Length
def _center_of_mass(shape): Properties = GProp_GProps() brepgprop_VolumeProperties(shape, Properties) return Vector(Properties.CentreOfMass())
def __init__(self, selectorString): self.axes = { 'X': Vector(1, 0, 0), 'Y': Vector(0, 1, 0), 'Z': Vector(0, 0, 1), 'XY': Vector(1, 1, 0), 'YZ': Vector(0, 1, 1), 'XZ': Vector(1, 0, 1) } self.namedViews = { 'front': (Vector(0, 0, 1), True), 'back': (Vector(0, 0, 1), False), 'left': (Vector(1, 0, 0), False), 'right': (Vector(1, 0, 0), True), 'top': (Vector(0, 1, 0), True), 'bottom': (Vector(0, 1, 0), False) } self.operatorMinMax = {'>': True, '<': False, '+': True, '-': False} self.operator = { '+': DirectionSelector, '-': DirectionSelector, '#': PerpendicularDirSelector, '|': ParallelDirSelector } self.selectorString = selectorString parsing_result = _grammar.parseString(selectorString) self.mySelector = self._chooseSelector(parsing_result)
def Center(self): """ The center of a vertex is itself! """ return Vector(self.wrapped.Point)
def makeBox(cls, length, width, height, pnt=Vector(0, 0, 0), dir=Vector(0, 0, 1)): """ makeBox(length,width,height,[pnt,dir]) -- Make a box located\nin pnt with the d imensions (length,width,height)\nBy default pnt=Vector(0,0,0) and dir=Vector(0,0,1)' """ return Shape.cast(FreeCADPart.makeBox(length, width, height, pnt.wrapped, dir.wrapped))
def Center(self): try: return Vector(self.wrapped.CenterOfMass) except: pass
def add_part(self, part, filename=None, name=None, origin=None, parent_idx=0): """ Adds the given ``part`` to ``self.gltf_dict``. :param part: part to add to gltf export :type part: :class:`Part <cqparts.Part>` :param filename: name of binary file to store buffer, if ``None``, binary data is embedded in the *buffer's 'uri'* :type filename: :class:`str` :param name: name given to exported mesh (optional) :type name: :class:`str` :param parent_idx: index of parent node (everything is added to a hierarchy) :type parent_idx: :class:`int` :return: information about additions to the gltf dict :rtype: :class:`dict` **Return Format:** The returned :class:`dict` is an account of what objects were added to the gltf dict, and the index they may be referenced:: <return format> = { 'buffers': [(<index>, <object>), ... ], 'bufferViews': [(<index>, <object>), ... ], 'accessors': [(<index>, <object>), ... ], 'materials': [(<index>, <object>), ... ], 'meshes': [(<index>, <object>), ... ], 'nodes': [(<index>, <object>), ... ], } .. note:: The format of the returned :class:`dict` **looks similar** to the gltf format, but it **is not**. """ info = defaultdict(list) log.debug("gltf export: %r", part) # ----- Adding to: buffers with measure_time(log, 'buffers'): buff = self.part_buffer(part) self.scene_min = _list3_min(self.scene_min, (Vector(buff.vert_min) + part.world_coords.origin).toTuple()) self.scene_max = _list3_max(self.scene_max, (Vector(buff.vert_max) + part.world_coords.origin).toTuple()) buffer_index = len(self.gltf_dict['buffers']) buffer_dict = { "byteLength": len(buff), } if filename: # write file with open(filename, 'wb') as fh: for chunk in buff.buffer_iter(): fh.write(chunk) buffer_dict['uri'] = os.path.basename(filename) else: # embed buffer data in URI buffer_dict['uri'] = "data:{mimetype};base64,{data}".format( mimetype="application/octet-stream", data=base64.b64encode(buff.read()).decode('ascii'), ) self.gltf_dict['buffers'].append(buffer_dict) info['buffers'].append((buffer_index, buffer_dict)) # ----- Adding: bufferViews with measure_time(log, 'bufferViews'): bufferView_index = len(self.gltf_dict['bufferViews']) # vertices view view = { "buffer": buffer_index, "byteOffset": buff.vert_offset, "byteLength": buff.vert_len, "byteStride": 12, "target": WebGL.ARRAY_BUFFER, } self.gltf_dict['bufferViews'].append(view) bufferView_index_vertices = bufferView_index info['bufferViews'].append((bufferView_index_vertices, view)) # indices view view = { "buffer": buffer_index, "byteOffset": buff.idx_offset, "byteLength": buff.idx_len, "target": WebGL.ELEMENT_ARRAY_BUFFER, } self.gltf_dict['bufferViews'].append(view) bufferView_index_indices = bufferView_index + 1 info['bufferViews'].append((bufferView_index_indices, view)) # ----- Adding: accessors with measure_time(log, 'accessors'): accessor_index = len(self.gltf_dict['accessors']) # vertices accessor accessor = { "bufferView": bufferView_index_vertices, "byteOffset": 0, "componentType": WebGL.FLOAT, "count": buff.vert_size, "min": [v - 0.1 for v in buff.vert_min], "max": [v + 0.1 for v in buff.vert_max], "type": "VEC3", } self.gltf_dict['accessors'].append(accessor) accessor_index_vertices = accessor_index info['accessors'].append((accessor_index_vertices, accessor)) # indices accessor accessor = { "bufferView": bufferView_index_indices, "byteOffset": 0, "componentType": buff.idx_type, "count": buff.idx_size, "type": "SCALAR", } self.gltf_dict['accessors'].append(accessor) accessor_index_indices = accessor_index + 1 info['accessors'].append((accessor_index_indices, accessor)) # ----- Adding: materials with measure_time(log, 'materials'): material_index = len(self.gltf_dict['materials']) material = part._render.gltf_material self.gltf_dict['materials'].append(material) info['materials'].append((material_index, material)) # ----- Adding: meshes with measure_time(log, 'meshes'): mesh_index = len(self.gltf_dict['meshes']) mesh = { "primitives": [{ "attributes": { "POSITION": accessor_index_vertices, }, "indices": accessor_index_indices, "mode": WebGL.TRIANGLES, "material": material_index, }], } if name: mesh['name'] = name self.gltf_dict['meshes'].append(mesh) info['meshes'].append((mesh_index, mesh)) # ----- Adding: nodes with measure_time(log, 'nodes'): node_index = len(self.gltf_dict['nodes']) node = { "mesh": mesh_index, } if name: node['name'] = name if origin: node.update(self.coordsys_dict(part.world_coords - origin)) self.gltf_dict['nodes'].append(node) info['nodes'].append((node_index, node)) # Appending child index to its parent's children list parent_node = self.gltf_dict['nodes'][parent_idx] parent_node['children'] = parent_node.get('children', []) + [node_index] return info
#You run this example by typing the following in the FreeCAD python console, making sure to change #the path to this example, and the name of the example appropriately. #import sys #sys.path.append('/home/user/Downloads/cadquery/examples/FreeCAD') #import Ex015_Rotated_Workplanes #If you need to reload the part after making a change, you can use the following lines within the FreeCAD console. #reload(Ex015_Rotated_Workplanes) #You'll need to delete the original shape that was created, and the new shape should be named sequentially (Shape001, etc). #You can also tie these blocks of code to macros, buttons, and keybindings in FreeCAD for quicker access. #You can get a more information on this example at http://parametricparts.com/docs/examples.html#an-extruded-prismatic-solid import cadquery from cadquery import Vector import Part #Create a rotated workplane and put holes in each corner of a rectangle on that workplane, producing angled holes in the face result = cadquery.Workplane("front").box(4.0,4.0,0.25).faces(">Z").workplane() \ .transformed(offset=Vector(0,-1.5,1.0),rotate=Vector(60,0,0)) \ .rect(1.5,1.5,forConstruction=True).vertices().hole(0.25) #Get a cadquery solid object solid = result.val() #Use the wrapped property of a cadquery primitive to get a FreeCAD solid Part.show(solid.wrapped) #Would like to zoom to fit the part here, but FreeCAD doesn't seem to have that scripting functionality
def __init__(self,parseResults): #define all token to object mappings self.axes = { 'X': Vector(1,0,0), 'Y': Vector(0,1,0), 'Z': Vector(0,0,1), 'XY': Vector(1,1,0), 'YZ': Vector(0,1,1), 'XZ': Vector(1,0,1) } self.namedViews = { 'front' : (Vector(0,0,1),True), 'back' : (Vector(0,0,1),False), 'left' : (Vector(1,0,0),False), 'right' : (Vector(1,0,0),True), 'top' : (Vector(0,1,0),True), 'bottom': (Vector(0,1,0),False) } self.operatorMinMax = { '>' : True, '<' : False, '+' : True, '-' : False } self.operator = { '+' : DirectionSelector, '-' : DirectionSelector, '#' : PerpendicularDirSelector, '|' : ParallelDirSelector} self.parseResults = parseResults self.mySelector = self._chooseSelector(parseResults)
def makePlane(cls, length, width, basePnt=(0, 0, 0), dir=(0, 0, 1)): basePnt = Vector(basePnt) dir = Vector(dir) return Face( FreeCADPart.makePlane(length, width, basePnt.wrapped, dir.wrapped))