def hex1(params, document): key = params["key"] d1 = params["d1"] k = params["k"] s = params["s"] h = params["h"] if h is None: h = 0.0 l = params["l"] name = params["name"] part = document.addObject("Part::Feature", name) # head a = s / math.tan(math.pi / 3.0) box1 = makeBox(a, s, k) box1.translate(Vector(-0.5 * a, -0.5 * s, 0)) box1.rotate(Vector(0, 0, 0), Vector(0, 0, 1), 30) box2 = makeBox(a, s, k) box2.translate(Vector(-0.5 * a, -0.5 * s, 0)) box2.rotate(Vector(0, 0, 0), Vector(0, 0, 1), 150) box3 = makeBox(a, s, k) box3.translate(Vector(-0.5 * a, -0.5 * s, 0)) box3.rotate(Vector(0, 0, 0), Vector(0, 0, 1), 270) head = box1.fuse(box2).fuse(box3) shaft_unthreaded = Part.makeCylinder(0.5 * d1, h + k) shaft_threaded = Part.makeCylinder(0.5 * d1, l - h) shaft_threaded.translate(Vector(0, 0, h + k)) part.Shape = head.fuse(shaft_unthreaded).fuse(shaft_threaded).removeSplitter()
def linesFromPoints(points, closed=False): lines = [] for i in range(0, len(points) - 1): lines.append(Part.makeLine(points[i], points[(i + 1) % len(points)])) if closed: lines.append(Part.makeLine(points[len(points) - 1], points[0])) return lines
def mainFrameCoeff(ship, draft): """ Calculate main frame coefficient. @param ship Selected ship instance @param draft Draft. @return Main frame coefficient """ cm = 0.0 maxY = 0.0 minY = 0.0 # We will take a duplicate of ship shape in order to place it shape = ship.Shape.copy() shape.translate(Vector(0.0,0.0,-draft)) x = 0.0 area = 0.0 # Now we need to know the x range of values bbox = shape.BoundBox xmin = bbox.XMin xmax = bbox.XMax # Create the box L = xmax - xmin B = bbox.YMax - bbox.YMin p = Vector(-1.5*L, -1.5*B, bbox.ZMin - 1.0) box = Part.makeBox(1.5*L + x, 3.0*B, - bbox.ZMin + 1.0, p) maxY = bbox.YMin minY = bbox.YMax # Compute common part with ship for s in shape.Solids: # Get solids intersection try: common = box.common(s) except: continue if common.Volume == 0.0: continue # Recompute object adding it to the scene, when we have # computed desired data we can remove it. try: Part.show(common) except: continue # Divide by faces and compute only section placed ones faces = common.Faces for f in faces: faceBounds = f.BoundBox # Orientation filter if faceBounds.XMax - faceBounds.XMin > 0.00001: continue # Place filter if abs(faceBounds.XMax - x) > 0.00001: continue # Valid face, compute area area = area + f.Area maxY = max(maxY, faceBounds.YMax) minY = min(minY, faceBounds.YMin) # Destroy last object generated App.ActiveDocument.removeObject(App.ActiveDocument.Objects[-1].Name) dy = maxY - minY if dy*draft > 0.0: cm = area / (dy*draft) return cm
def FilletFlange(innerdia = 10,filletdia = 5,filletthick=10): ff = Part.makeCylinder(innerdia/2 + filletdia/2,filletthick) fi = Part.makeCylinder(innerdia/2,filletthick+filletdia) fi.translate(Vector(0,0,-filletdia/2)) ff=ff.fuse(fi) ff=ff.fuse(ff.makeFillet(filletdia/2-0.01,[ff.Edges[3],ff.Edges[5]])) return ff
def makeRef(p1, p2, p3, border): p4 = p1 + (p3 - p2) lines = linesFromPoints([p1, p2, p3, p4], True) w = Part.Wire(lines) p = w.extrude(border) Part.show(p)
def getShapeFromMesh(mesh): import Part, MeshPart if mesh.isSolid() and (mesh.countComponents() == 1): # use the best method faces = [] for f in mesh.Facets: p=f.Points+[f.Points[0]] pts = [] for pp in p: pts.append(FreeCAD.Vector(pp[0],pp[1],pp[2])) faces.append(Part.Face(Part.makePolygon(pts))) shell = Part.makeShell(faces) solid = Part.Solid(shell) solid = solid.removeSplitter() return solid faces = [] segments = mesh.getPlanarSegments(0.001) # use rather strict tolerance here for i in segments: if len(i) > 0: wires = MeshPart.wireFromSegment(mesh, i) if wires: faces.append(makeFace(wires)) try: se = Part.makeShell(faces) except: return None else: try: solid = Part.Solid(se) except: return se else: return solid
def p_polyhedron_action(p) : '''polyhedron_action : polyhedron LPAREN points EQ OSQUARE points_list_3d ESQUARE COMMA faces EQ OSQUARE path_set ESQUARE COMMA keywordargument_list RPAREN SEMICOL | polyhedron LPAREN points EQ OSQUARE points_list_3d ESQUARE COMMA triangles EQ OSQUARE points_list_3d ESQUARE COMMA keywordargument_list RPAREN SEMICOL''' if printverbose: print("Polyhedron Points") v = [] for i in p[6] : if printverbose: print(i) v.append(FreeCAD.Vector(float(i[0]),float(i[1]),float(i[2]))) if printverbose: print(v) print ("Polyhedron "+p[9]) print (p[12]) faces_list = [] mypolyhed = doc.addObject('Part::Feature',p[1]) for i in p[12] : if printverbose: print(i) v2 = FreeCAD.Vector pp =[v2(v[k]) for k in i] # Add first point to end of list to close polygon pp.append(pp[0]) print(pp) w = Part.makePolygon(pp) f = Part.Face(w) #f = make_face(v[int(i[0])],v[int(i[1])],v[int(i[2])]) faces_list.append(f) shell=Part.makeShell(faces_list) solid=Part.Solid(shell).removeSplitter() if solid.Volume < 0: solid.reverse() mypolyhed.Shape=solid p[0] = [mypolyhed]
def execute(self, fp): edges = fp.Edges if edges < 3: edges = 3 length = fp.Length radius = fp.Radius height = fp.Height m=Base.Matrix() m.rotateZ(math.radians(360.0/edges)) # create polygon polygon = [] v=Base.Vector(length,0,0) for i in range(edges): polygon.append(v) v = m.multiply(v) polygon.append(v) wire = Part.makePolygon(polygon) # create circle circ=Part.makeCircle(radius) # Create the face with the polygon as outline and the circle as hole face=Part.Face([wire,Part.Wire(circ)]) # Extrude in z to create the final solid extrude=face.extrude(Base.Vector(0,0,height)) fp.Shape = extrude
def hex2(params, document): key = params["key"] d1 = params["d1"] k = params["k"] s = params["s"] b1 = params["b1"] b2 = params["b2"] b3 = params["b3"] l = params["l"] b = b3 if l < 125: b = b1 elif l < 200: b = b2 name = params["name"] part = document.addObject("Part::Feature", name) # head a = s / math.tan(math.pi / 3.0) box1 = makeBox(a, s, k) box1.translate(Vector(-0.5 * a, -0.5 * s, 0)) box1.rotate(Vector(0, 0, 0), Vector(0, 0, 1), 30) box2 = makeBox(a, s, k) box2.translate(Vector(-0.5 * a, -0.5 * s, 0)) box2.rotate(Vector(0, 0, 0), Vector(0, 0, 1), 150) box3 = makeBox(a, s, k) box3.translate(Vector(-0.5 * a, -0.5 * s, 0)) box3.rotate(Vector(0, 0, 0), Vector(0, 0, 1), 270) head = box1.fuse(box2).fuse(box3) shaft_unthreaded = Part.makeCylinder(0.5 * d1, l - b + k) shaft_threaded = Part.makeCylinder(0.5 * d1, b) shaft_threaded.translate(Vector(0, 0, l - b + k)) part.Shape = head.fuse(shaft_unthreaded).fuse(shaft_threaded).removeSplitter()
def areaOpShapes(self, obj): '''areaOpShapes(obj) ... return shapes representing the solids to be removed.''' PathLog.track() if obj.Base: PathLog.debug("base items exist. Processing...") removalshapes = [] for b in obj.Base: PathLog.debug("Base item: {}".format(b)) for sub in b[1]: if "Face" in sub: shape = Part.makeCompound([getattr(b[0].Shape, sub)]) else: edges = [getattr(b[0].Shape, sub) for sub in b[1]] shape = Part.makeFace(edges, 'Part::FaceMakerSimple') env = PathUtils.getEnvelope(self.baseobject.Shape, subshape=shape, depthparams=self.depthparams) obj.removalshape = env.cut(self.baseobject.Shape) removalshapes.append((obj.removalshape, False)) else: # process the job base object as a whole PathLog.debug("processing the whole job base object") env = PathUtils.getEnvelope(self.baseobject.Shape, subshape=None, depthparams=self.depthparams) obj.removalshape = env.cut(self.baseobject.Shape) removalshapes = [(obj.removalshape, False)] return removalshapes
def update(self, draft, trim, ship): """ Update free surface 3D view @param traft Draft. @param trim Trim in degrees. """ # Destroy old object if exist self.clean() # Set free surface bounds bbox = ship.Shape.BoundBox L = 1.5 * bbox.XLength B = 3.0 * bbox.YLength # Create plane x = - 0.5 * L y = - 0.5 * B point = Base.Vector(x,y,0.0) plane = Part.makePlane(L,B, point, Base.Vector(0,0,1)) # Set position plane.rotate(Base.Vector(0,0,0), Base.Vector(0,1,0), trim) plane.translate(Base.Vector(0,0,draft)) # Create the FreeCAD object Part.show(plane) objs = FreeCAD.ActiveDocument.Objects self.obj = objs[len(objs)-1] self.obj.Label = 'FreeSurface' # Set properties of object guiObj = FreeCADGui.ActiveDocument.getObject(self.obj.Name) guiObj.ShapeColor = (0.4,0.8,0.85) guiObj.Transparency = 50
def execute(self, part): data = iso_4014_1979_partial_hex_screw["sizes"][part.size] # the calculations are based on the ACII art picture above, # with the points starting from the far right point, # and ending with the same point to close the polygon y_distance = 0.5 * data["s_max"] angle = math.pi / 3 head_radius = y_distance / math.sin(angle) x_distance = math.cos(angle) * head_radius points = [ Vector(head_radius, 0, 0), Vector(x_distance, y_distance, 0), Vector(-x_distance, y_distance, 0), Vector(-head_radius, 0, 0), Vector(-x_distance, -y_distance, 0), Vector(x_distance, -y_distance, 0), Vector(head_radius, 0, 0), ] # create a polygon and transform it to a face too: hexagon = Part.Face(Part.makePolygon(points)) # just an integer won't work here, must use units: k = data["k_nom"] * Units.MilliMetre head = hexagon.extrude(Vector(0, 0, k)) shaft = Part.makeCylinder( 0.5 * data["ds_max"], part.length + k, Vector(0, 0, 0), Vector(0, 0, 1) ) part.Shape = head.fuse(shaft)
def makeSnapshotWithGui(): from PyQt4 import QtGui import FreeCADGui def getMainWindow(): toplevel = QtGui.qApp.topLevelWidgets() for i in toplevel: if i.metaObject().className() == "Gui::MainWindow": return i raise Exception("No main window found") mw=getMainWindow() mw.hide() #mw.showMinimized() # Create a test geometry and add it to the document obj=Part.makeCone(10,8,10) doc = FreeCAD.newDocument() Part.show(obj) # switch off animation so that the camera is moved to the final position immediately view = FreeCADGui.getDocument(doc.Name).activeView() view.setAnimationEnabled(False) view.viewAxometric() view.fitAll() view.saveImage('crystal.png',800,600,'Current') FreeCAD.closeDocument(doc.Name) # close the application QtGui.qApp.quit()
def servo(): """servo""" data = servo_data # approximate the servo body = Part.makeBox(data['x'], data['y'], data['z']) maintien1 = Part.makeBox(data['maintien x'], data['maintien y'], data['maintien z']) maintien1.translate(Vector(data['x'], 0, data['maintien offset z'])) maintien2 = Part.makeBox(data['maintien x'], data['maintien y'], data['maintien z']) maintien2.translate(Vector(-data['maintien x'], 0, data['maintien offset z'])) cylindre = Part.makeCylinder(data['cylindre r'], data['cylindre h']) cylindre.translate(Vector(data['cylindre offset x'], data['y'] / 2, data['cylindre offset z'])) taquet = Part.makeBox(data['taquet x'], data['taquet y'], data['taquet z']) taquet.translate(Vector(-data['taquet y'] / 2, -data['taquet y'] / 2, 0)) taquet.rotate(Vector(0, 0, 0), Vector(0, 0, 1), -90) taquet.translate(Vector(data['cylindre offset x'], data['y'] / 2, data['z'] + data['cylindre h'])) obj = body.fuse(maintien1) obj = obj.fuse(maintien2) obj = obj.fuse(cylindre) obj = obj.fuse(taquet) obj.translate(Vector(-data['x'] / 2, -data['y'] / 2, -data['z'] / 2)) return obj
def getArea(self,obj): "returns the horizontal area at the center of the space" import Part,DraftGeomUtils if not hasattr(obj.Shape,"CenterOfMass"): return 0 try: pl = Part.makePlane(1,1) pl.translate(obj.Shape.CenterOfMass) sh = obj.Shape.copy() cutplane,v1,v2 = ArchCommands.getCutVolume(pl,sh) e = sh.section(cutplane) e = Part.__sortEdges__(e.Edges) w = Part.Wire(e) f = Part.Face(w) except Part.OCCError: return 0 else: if hasattr(obj,"PerimeterLength"): if w.Length != obj.PerimeterLength.Value: obj.PerimeterLength = w.Length if hasattr(obj,"VerticalArea"): a = 0 for f in sh.Faces: ang = f.normalAt(0,0).getAngle(FreeCAD.Vector(0,0,1)) if (ang > 1.57) and (ang < 1.571): a += f.Area if a != obj.VerticalArea.Value: obj.VerticalArea = a #print "area of ",obj.Label," : ",f.Area return f.Area
def arma8ptos(fi,recubrN,sepFi,radDobl,pto1,pto2,pto3,pto4,pto5,pto6,pto7,pto8,gap1,gap2): recubrG=recubrN+float(fi)/1000/2.0 v=pto6.sub(pto2) recArmPlano=(v.Length-2*recubrG-int((v.Length-2.0*recubrG)/sepFi)*sepFi)/2.0 v1=GeomUtils.vectorUnitario(pto2,pto1) v2=GeomUtils.vectorUnitario(pto2,pto3) v3=GeomUtils.vectorUnitario(pto3,pto4) v4=GeomUtils.vectorUnitario(pto2,pto6) v5=GeomUtils.vectorUnitario(pto3,pto7) v6=GeomUtils.vectorUnitario(pto6,pto5) v7=GeomUtils.vectorUnitario(pto6,pto7) v8=GeomUtils.vectorUnitario(pto7,pto8) pto1a=pto1.add(GeomUtils.escalarPorVector(recArmPlano,v4)).add(GeomUtils.escalarPorVector(recubrG,v2)).add(GeomUtils.escalarPorVector(gap1,v1)) pto2a=pto2.add(GeomUtils.escalarPorVector(recArmPlano,v4)).add(GeomUtils.escalarPorVector(recubrG,v2)).add(GeomUtils.escalarPorVector(recubrG,v1)) pto3a=pto3.add(GeomUtils.escalarPorVector(recArmPlano,v5)).sub(GeomUtils.escalarPorVector(recubrG,v2)).add(GeomUtils.escalarPorVector(recubrG,v3)) pto4a=pto4.add(GeomUtils.escalarPorVector(recArmPlano,v5)).sub(GeomUtils.escalarPorVector(recubrG,v2)).add(GeomUtils.escalarPorVector(gap2,v3)) pto5a=pto5.sub(GeomUtils.escalarPorVector(recArmPlano,v4)).add(GeomUtils.escalarPorVector(recubrG,v7)).add(GeomUtils.escalarPorVector(gap1,v6)) pto6a=pto6.sub(GeomUtils.escalarPorVector(recArmPlano,v4)).add(GeomUtils.escalarPorVector(recubrG,v7)).add(GeomUtils.escalarPorVector(recubrG,v6)) pto7a=pto7.sub(GeomUtils.escalarPorVector(recArmPlano,v5)).sub(GeomUtils.escalarPorVector(recubrG,v7)).add(GeomUtils.escalarPorVector(recubrG,v8)) pto8a=pto8.sub(GeomUtils.escalarPorVector(recArmPlano,v5)).sub(GeomUtils.escalarPorVector(recubrG,v7)).add(GeomUtils.escalarPorVector(gap2,v8)) cara1=Part.Face(Part.makePolygon([pto1a,pto2a,pto6a,pto5a,pto1a])) cara2=Part.Face(Part.makePolygon([pto2a,pto6a,pto7a,pto3a,pto2a])) cara3=Part.Face(Part.makePolygon([pto3a,pto4a,pto8a,pto7a,pto3a])) arma=cara1.fuse(cara2.fuse(cara3)) armadura=arma.makeFillet(radDobl,arma.Edges) return armadura
def make_extrusion(self, name, points, invert_order): print 'make_extrusion', name, invert_order wires = [] for section in points: pts = [] if len(section) < 3: print "warning: cross section in make_extrusion() < 3 points" print "length:", len(section) continue if not invert_order: for pt in section: # print "%.2f %.2f %.2f" % (pt[0], pt[1], pt[2]) pts.append( Base.Vector(pt[0], pt[1], pt[2]) ) pt = section[0] pts.append( Base.Vector(pt[0], pt[1], pt[2]) ) else: for pt in section: # print "%.2f %.2f %.2f" % (pt[0], pt[1], pt[2]) pts.append( Base.Vector(pt[0], pt[1], pt[2]) ) pt = section[0] pts.append( Base.Vector(pt[0], pt[1], pt[2]) ) #pt = section[0] #Base.Vector(pt[0], pt[1], pt[2]) #for pt in reversed(section): # print "%.2f %.2f %.2f" % (pt[0], pt[1], pt[2]) #pts.append( Base.Vector(pt[0], pt[1], pt[2]) ) wire = Part.makePolygon(pts) wires.append(wire) loft = Part.makeLoft(wires, False) return loft
def gen_haus(le,wi,hiall,hi,ang,midx=0.7,wx=0.5,midy=0.5,wy=0): h=gen_haus0(le,wi,hiall,hi,midx,wx,midy,wy) print h Part.show(h) p=FreeCAD.ActiveDocument.ActiveObject p.Placement.Rotation.Angle=ang*math.pi/180 return p
def projectFace(self,face): "projects a single face on the WP" #print "VRM: projectFace start: ",len(face[0].Vertexes)," verts, ",len(face[0].Edges)," edges" wires = [] if not face[0].Wires: if DEBUG: print "Error: Unable to project face on the WP" return None norm = face[0].normalAt(0,0) for w in face[0].Wires: verts = [] edges = Part.__sortEdges__(w.Edges) #print len(edges)," edges after sorting" for e in edges: v = e.Vertexes[0].Point #print v v = self.wp.getLocalCoords(v) verts.append(v) verts.append(verts[0]) if len(verts) > 2: #print "new wire with ",len(verts) wires.append(Part.makePolygon(verts)) try: sh = ArchCommands.makeFace(wires) except: if DEBUG: print "Error: Unable to project face on the WP" return None else: # restoring flipped normals vnorm = self.wp.getLocalCoords(norm) if vnorm.getAngle(sh.normalAt(0,0)) > 1: sh.reverse() #print "VRM: projectFace end: ",len(sh.Vertexes)," verts" return [sh]+face[1:]
def make_surfaceShelves(self): # shelf for left work surface shelf_width = self.pos_support1[0]-self.pos_supportMini1[0]+self.thickness shelf_depth = self.depth - self.pos_support1[1] shelf_height = self.underside_height / 2. shelf = Part.makeBox(shelf_width, shelf_depth, self.thickness, self.pos_supportMini1 + Base.Vector(-self.thickness, 0, 0)) shelf = shelf.cut(self.parts_left['support1']) self.parts_left['shelf'] = shelf # shelf for right work surface shelf_width = self.pos_support3[0]-self.pos_supportMini2[0]+self.thickness shelf_depth = self.depth - self.pos_support3[1] shelf_height = self.underside_height / 2. shelf = Part.makeBox(shelf_width, shelf_depth, self.thickness, self.pos_supportMini2 + Base.Vector(-self.thickness, 0, 0)) shelf = shelf.cut(self.parts_right['support3']) self.parts_right['shelf'] = shelf
def __init__(self, doc, name='integ2'): self.data = { 'len lo': 20., # mm 'len hi': 100., # mm 'ext diameter': 36., # mm 'int diameter': 30., # mm } int_diam = self.data['int diameter'] ext_diam = self.data['ext diameter'] len_hi = self.data['len hi'] len_lo = self.data['len lo'] cone = Part.makeCone(int_diam / 2, ext_diam / 2, len_lo) trunk = Part.makeCylinder(ext_diam / 2, len_hi) trunk.translate(Vector(0, 0, len_lo)) comp = cone.fuse(trunk) cutter = Part.makeBox(ext_diam, ext_diam, len_hi + len_lo) cutter.translate(Vector(0, -ext_diam / 2, 0)) cutter.rotate(Vector(0, 0, 0), Vector(0, 0, 1), 180) comp = comp.common(cutter) MecaComponent.__init__(self, doc, comp, name, (1., 1., 0.))
def __init__(self, doc, tube, name='aero_clutch'): self.data = { 'len': 20., # mm 'width' : 15., # mm } data = self.data data['thick'] = tube['thick'] # mm data['ext diameter'] = tube['int diameter'] - tube['thick'] # mm data['int diameter'] = tube['int diameter'] - 3 * tube['thick'] # mm # rebuild a tube int_part = Part.makeCylinder(data['int diameter'] / 2, data['len']) ext_part = Part.makeCylinder(data['ext diameter'] / 2, data['len']) part = ext_part.cut(int_part) # cut the external shape shape = Part.makeBox(2 * data['ext diameter'], 2 * data['ext diameter'], data['len']) shape.translate(Vector(-data['ext diameter'], -data['ext diameter'], 0)) comp = part.common(shape) # cut the nerves nerv = Part.makeBox(data['ext diameter'] / 2 - 2 * data['thick'], 3., data['len'] / 2) nerv.translate(Vector(-data['ext diameter'] / 2 + data['thick'] / 2, -3. / 2, 0)) comp = comp.cut(nerv) MecaComponent.__init__(self, doc, comp, name, (1., 1., 0.))
def areaOpShapes(self, obj): '''areaOpShapes(obj) ... return top face''' # Facing is done either against base objects if obj.Base: PathLog.debug("obj.Base: {}".format(obj.Base)) faces = [] for b in obj.Base: for sub in b[1]: shape = getattr(b[0].Shape, sub) if isinstance(shape, Part.Face): faces.append(shape) else: PathLog.debug('The base subobject is not a face') return planeshape = Part.makeCompound(faces) PathLog.debug("Working on a collection of faces {}".format(faces)) # If no base object, do planing of top surface of entire model else: planeshape = self.baseobject.Shape PathLog.debug("Working on a shape {}".format(self.baseobject.Name)) # Find the correct shape depending on Boundary shape. PathLog.debug("Boundary Shape: {}".format(obj.BoundaryShape)) bb = planeshape.BoundBox if obj.BoundaryShape == 'Boundbox': bbperim = Part.makeBox(bb.XLength, bb.YLength, 1, FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin), FreeCAD.Vector(0, 0, 1)) env = PathUtils.getEnvelope(partshape=bbperim, depthparams=self.depthparams) elif obj.BoundaryShape == 'Stock': stock = PathUtils.findParentJob(obj).Stock.Shape env = stock else: env = PathUtils.getEnvelope(partshape=planeshape, depthparams=self.depthparams) return [(env, False)]
def makeSurfaceVolume(filename): import FreeCAD,Part f1=open(filename) coords=[] miny=1 for line in f1.readlines(): sline=line.strip() if sline and not sline.startswith('#'): ycoord=len(coords) lcoords=[] for xcoord, num in enumerate(sline.split()): fnum=float(num) lcoords.append(FreeCAD.Vector(float(xcoord),float(ycoord),fnum)) miny=min(fnum,miny) coords.append(lcoords) s=Part.BSplineSurface() s.interpolate(coords) plane=Part.makePlane(len(coords[0])-1,len(coords)-1,FreeCAD.Vector(0,0,miny-1)) l1=Part.makeLine(plane.Vertexes[0].Point,s.value(0,0)) l2=Part.makeLine(plane.Vertexes[1].Point,s.value(1,0)) l3=Part.makeLine(plane.Vertexes[2].Point,s.value(0,1)) l4=Part.makeLine(plane.Vertexes[3].Point,s.value(1,1)) f0=plane.Faces[0] f0.reverse() f1=Part.Face(Part.Wire([plane.Edges[0],l1.Edges[0],s.vIso(0).toShape(),l2.Edges[0]])) f2=Part.Face(Part.Wire([plane.Edges[1],l3.Edges[0],s.uIso(0).toShape(),l1.Edges[0]])) f3=Part.Face(Part.Wire([plane.Edges[2],l4.Edges[0],s.vIso(1).toShape(),l3.Edges[0]])) f4=Part.Face(Part.Wire([plane.Edges[3],l2.Edges[0],s.uIso(1).toShape(),l4.Edges[0]])) f5=s.toShape().Faces[0] solid=Part.Solid(Part.Shell([f0,f1,f2,f3,f4,f5])) return solid,(len(coords[0])-1)/2.0,(len(coords)-1)/2.0
def makeTube(outerRadius, innerRadius, height): outer_cylinder = Part.makeCylinder(outerRadius, height) shape = outer_cylinder if innerRadius > 0 and innerRadius < outerRadius: inner_cylinder = Part.makeCylinder(innerRadius, height) shape = outer_cylinder.cut(inner_cylinder) return shape
def ruled_surface(e1,e2): """ creates a ruled surface between 2 edges, with automatic orientation.""" # Automatic orientation # /src/Mod/Part/App/PartFeatures.cpp#171 p1 = e1.valueAt(e1.FirstParameter) p2 = e1.valueAt(e1.LastParameter) p3 = e2.valueAt(e2.FirstParameter) p4 = e2.valueAt(e2.LastParameter) if e1.Orientation == 'Reversed': p = p1 p1 = p2 p2 = p if e2.Orientation == 'Reversed': p = p3 p3 = p4 p4 = p v1 = p2 - p1 v2 = p3 - p1 n1 = v1.cross(v2) v3 = p3 - p4 v4 = p2 - p4 n2 = v3.cross(v4) if (n1.dot(n2) < 0): e = e2.copy() e.reverse() return(Part.makeRuledSurface(e1,e)) else: return(Part.makeRuledSurface(e1,e2))
def createGeometry(self,fp): if all((fp.Radius1,fp.Radius2,fp.FacesNumber,fp.Height)): import math import FreeCAD,Part #from draftlibs import fcgeo plm = fp.Placement wires=[] faces=[] for ir,r in enumerate((fp.Radius1,fp.Radius2)): angle = (math.pi*2)/fp.FacesNumber pts = [FreeCAD.Vector(r.Value,0,ir*fp.Height.Value)] for i in range(fp.FacesNumber-1): ang = (i+1)*angle pts.append(FreeCAD.Vector(r.Value*math.cos(ang),\ r.Value*math.sin(ang),ir*fp.Height.Value)) pts.append(pts[0]) shape = Part.makePolygon(pts) face = Part.Face(shape) if ir==1: #top face face.reverse() wires.append(shape) faces.append(face) #shellperi=Part.makeRuledSurface(*wires) shellperi=Part.makeLoft(wires) shell=Part.Shell(shellperi.Faces+faces) fp.Shape = Part.Solid(shell) fp.Placement = plm
def execute(self, obj): """Build the object""" #-- When length l is given, a vector with length = l and #-- orientation v is created if obj.l == 0: l = obj.v.Length else: l = obj.l.Value #-- Correct the length if (l < obj.arrow_l): arrow_l = l/2. else: arrow_l = obj.arrow_l.Value #--- Create the base vector base_vect = FreeCAD.Vector(obj.v) base_vect.Length = l - arrow_l #-- Build the object vectz = Part.makeCylinder(obj.d / 2.0, base_vect.Length, Vector(0,0,0), obj.v) base = Part.makeSphere(obj.d / 2.0) arrow = Part.makeCone(obj.d/2. + 2/3. * obj.d, 0.05, arrow_l, base_vect, base_vect) #-- Create the union of all the parts u = vectz.fuse(base) u = u.fuse(arrow) #-- Asign the shape obj.Shape = u
def makeSquareTool(s, m): # makes a cylinder with an inner square hole, used as cutting tool # create square face msq = Base.Matrix() msq.rotateZ(math.radians(90.0)) polygon = [] vsq = Base.Vector(s / 2.0, s / 2.0, -m * 0.1) for i in range(4): polygon.append(vsq) vsq = msq.multiply(vsq) polygon.append(vsq) square = Part.makePolygon(polygon) square = Part.Face(square) # create circle face circ = Part.makeCircle(s * 3.0, Base.Vector(0.0, 0.0, -m * 0.1)) circ = Part.Face(Part.Wire(circ)) # Create the face with the circle as outline and the square as hole face=circ.cut(square) # Extrude in z to create the final cutting tool exSquare = face.extrude(Base.Vector(0.0, 0.0, m * 1.2)) # Part.show(exHex) return exSquare
def __init__(self, doc, name='helix'): self.data = { 'len lo': 70., # mm 'len up': 120., # mm 'int diameter': 36., # mm 'thick': 1., # mm } len_lo = self.data['len lo'] # blocking thread (pas de vis de blocage) radius = self.data['int diameter'] / 2 helix = Part.makeHelix(4., 16., radius) p0 = (radius, 0, 0) p1 = (radius, 0, 3) p2 = (radius - 1, 0, 2) p3 = (radius - 1, 0, 1) e0 = Part.makeLine(p0, p1) e1 = Part.makeLine(p1, p2) e2 = Part.makeLine(p2, p3) e3 = Part.makeLine(p3, p0) section = Part.Wire([e0, e1, e2, e3]) helix = Part.Wire(helix).makePipeShell([section], 1, 1) helix.translate(Vector(0, 0, len_lo - 20)) helix = helix.fuse(helix) comp = helix MecaComponent.__init__(self, doc, comp, name, (1., 1., 0.))
def recompute(self): if self.bezcurve: for seg in self.bezcurve: self.sep.removeChild(seg) seg = None self.bezcurve = [] if (len(self.points) >= 2): if self.degree: poles = self.points[1:] segpoleslst = [ poles[x:x + self.degree] for x in range(0, len(poles), (self.degree or 1)) ] else: segpoleslst = [self.points] startpoint = self.points[0] for segpoles in segpoleslst: c = Part.BezierCurve() #last segment may have lower degree c.increase(len(segpoles)) c.setPoles([startpoint] + segpoles) c = c.toShape() startpoint = segpoles[-1] buf = c.writeInventor(2, 0.01) #fp=open("spline.iv","w") #fp.write(buf) #fp.close() try: ivin = coin.SoInput() ivin.setBuffer(buf) ivob = coin.SoDB.readAll(ivin) except: # workaround for pivy SoInput.setBuffer() bug import re buf = buf.replace("\n", "") pts = re.findall("point \[(.*?)\]", buf)[0] pts = pts.split(",") pc = [] for p in pts: v = p.strip().split() pc.append([float(v[0]), float(v[1]), float(v[2])]) coords = coin.SoCoordinate3() coords.point.setValues(0, len(pc), pc) line = coin.SoLineSet() line.numVertices.setValue(-1) bezcurveseg = coin.SoSeparator() bezcurveseg.addChild(coords) bezcurveseg.addChild(line) self.sep.addChild(bezcurveseg) else: if ivob and ivob.getNumChildren() > 1: bezcurveseg = ivob.getChild(1).getChild(0) bezcurveseg.removeChild(bezcurveseg.getChild(0)) bezcurveseg.removeChild(bezcurveseg.getChild(0)) self.sep.addChild(bezcurveseg) else: FreeCAD.Console.PrintWarning( "bezcurveTracker.recompute() failed to read-in Inventor string\n" ) self.bezcurve.append(bezcurveseg)
def update_object_from_edit_points(self, obj, node_idx, v, alt_edit_mode=0): if obj.FirstAngle == obj.LastAngle: # object is a circle if node_idx == 0: obj.Placement.Base = obj.Placement.multVec(v) elif node_idx == 1: obj.Radius = v.Length else: # obj is an arc if alt_edit_mode == 0: import Part if node_idx == 0: # center point p1 = self.getArcStart(obj) p2 = self.getArcEnd(obj) p0 = DraftVecUtils.project(v, self.getArcMid(obj)) obj.Radius = p1.sub(p0).Length obj.FirstAngle = -math.degrees( DraftVecUtils.angle(p1.sub(p0))) obj.LastAngle = -math.degrees( DraftVecUtils.angle(p2.sub(p0))) obj.Placement.Base = obj.Placement.multVec(p0) else: """ Edit arc by 3 points. """ v = obj.Placement.multVec(v) p1 = obj.Placement.multVec(self.getArcStart(obj)) p2 = obj.Placement.multVec(self.getArcMid(obj)) p3 = obj.Placement.multVec(self.getArcEnd(obj)) if node_idx == 1: # first point p1 = v elif node_idx == 3: # midpoint p2 = v elif node_idx == 2: # second point p3 = v arc = Part.ArcOfCircle(p1, p2, p3) import Part s = arc.toShape() # Part.show(s) DEBUG p0 = arc.Location obj.Placement.Base = p0 obj.Radius = arc.Radius delta = s.Vertexes[0].Point obj.FirstAngle = -math.degrees( DraftVecUtils.angle(p1.sub(p0))) delta = s.Vertexes[1].Point obj.LastAngle = -math.degrees( DraftVecUtils.angle(p3.sub(p0))) elif alt_edit_mode == 1: # edit arc by center radius FirstAngle LastAngle if node_idx == 0: obj.Placement.Base = obj.Placement.multVec(v) else: dangle = math.degrees(math.atan2(v[1], v[0])) if node_idx == 1: obj.FirstAngle = dangle elif node_idx == 2: obj.LastAngle = dangle elif node_idx == 3: obj.Radius = v.Length
def superWireReverse(debuglist,closed=False): '''superWireReverse(debuglist,[closed]): forces a wire between edges that don't necessarily have coincident endpoints. If closed=True, wire will always be closed. debuglist has a tuple for every edge.The first entry is the edge, the second is the flag 'does not nedd to be inverted' ''' #taken from draftlibs def median(v1,v2): vd = v2.sub(v1) vd.scale(.5,.5,.5) return v1.add(vd) try: from DraftGeomUtils import findMidpoint except ImportError: #workaround for Version 0.12 from draftlibs.fcgeo import findMidpoint #workaround for Version 0.12 import Part #edges = sortEdges(edgeslist) print debuglist newedges = [] for i in range(len(debuglist)): curr = debuglist[i] if i == 0: if closed: prev = debuglist[-1] else: prev = None else: prev = debuglist[i-1] if i == (len(debuglist)-1): if closed: nexte = debuglist[0] else: nexte = None else: nexte = debuglist[i+1] print i,prev,curr,nexte if prev: if curr[0].Vertexes[-1*(not curr[1])].Point == \ prev[0].Vertexes[-1*prev[1]].Point: p1 = curr[0].Vertexes[-1*(not curr[1])].Point else: p1 = median(curr[0].Vertexes[-1*(not curr[1])].Point,\ prev[0].Vertexes[-1*prev[1]].Point) else: p1 = curr[0].Vertexes[-1*(not curr[1])].Point if nexte: if curr[0].Vertexes[-1*curr[1]].Point == \ nexte[0].Vertexes[-1*(not nexte[1])].Point: p2 = nexte[0].Vertexes[-1*(not nexte[1])].Point else: p2 = median(curr[0].Vertexes[-1*(curr[1])].Point,\ nexte[0].Vertexes[-1*(not nexte[1])].Point) else: p2 = curr[0].Vertexes[-1*(curr[1])].Point if isinstance(curr[0].Curve,(Part.LineSegment, Part.Line)): print "line",p1,p2 newedges.append(Part.LineSegment(p1,p2).toShape()) elif isinstance(curr[0].Curve,Part.Circle): p3 = findMidpoint(curr[0]) print "arc",p1,p3,p2 newedges.append(Part.Arc(p1,p3,p2).toShape()) else: print "Cannot superWire edges that are not lines or arcs" return None print newedges return Part.Wire(newedges)
def getCurveSet(ent): result = [] if ent.is_a() in ["IfcGeometricCurveSet", "IfcGeometricSet"]: elts = ent.Elements elif ent.is_a() in [ "IfcLine", "IfcPolyline", "IfcCircle", "IfcTrimmedCurve", "IfcRectangleProfileDef" ]: elts = [ent] else: print("getCurveSet: unhandled entity: ", ent) return [] for el in elts: if el.is_a("IfcPolyline"): result.append(getPolyline(el)) elif el.is_a("IfcRectangleProfileDef"): result.append(getRectangle(el)) elif el.is_a("IfcLine"): result.append(getLine(el)) elif el.is_a("IfcCircle"): result.append(getCircle(el)) elif el.is_a("IfcTrimmedCurve"): base = el.BasisCurve t1 = el.Trim1[0].wrappedValue t2 = el.Trim2[0].wrappedValue if not el.SenseAgreement: t1, t2 = t2, t1 if base.is_a("IfcPolyline"): bc = getPolyline(base) result.append(bc) elif base.is_a("IfcCircle"): bc = getCircle(base) e = Part.ArcOfCircle(bc.Curve, math.radians(t1), math.radians(t2)).toShape() d = base.Position.RefDirection.DirectionRatios v = FreeCAD.Vector(d[0], d[1], d[2] if len(d) > 2 else 0) a = -DraftVecUtils.angle(v) e.rotate(bc.Curve.Center, FreeCAD.Vector(0, 0, 1), math.degrees(a)) result.append(e) elif el.is_a("IfcCompositeCurve"): for base in el.Segments: if base.ParentCurve.is_a("IfcPolyline"): bc = getPolyline(base.ParentCurve) result.append(bc) elif base.ParentCurve.is_a("IfcCircle"): bc = getCircle(base.ParentCurve) e = Part.ArcOfCircle(bc.Curve, math.radians(t1), math.radians(t2)).toShape() d = base.Position.RefDirection.DirectionRatios v = FreeCAD.Vector(d[0], d[1], d[2] if len(d) > 2 else 0) a = -DraftVecUtils.angle(v) e.rotate(bc.Curve.Center, FreeCAD.Vector(0, 0, 1), math.degrees(a)) result.append(e) elif el.is_a("IfcIndexedPolyCurve"): coords = el.Points.CoordList def index2points(segment): pts = [] for i in segment.wrappedValue: c = coords[i - 1] c = FreeCAD.Vector(c[0], c[1], c[2] if len(c) > 2 else 0) c.multiply(scaling) pts.append(c) return pts for s in el.Segments: if s.is_a("IfcLineIndex"): result.append(Part.makePolygon(index2points(s))) elif s.is_a("IfcArcIndex"): [p1, p2, p3] = index2points(s) result.append(Part.Arc(p1, p2, p3)) else: raise RuntimeError( "Illegal IfcIndexedPolyCurve segment") else: print("getCurveSet: unhandled element: ", el) return result
def getCircle(ent): c = ent.Position.Location.Coordinates c = FreeCAD.Vector(c[0], c[1], c[2] if len(c) > 2 else 0) c.multiply(scaling) r = ent.Radius * scaling return Part.makeCircle(r, c)
def getRectangle(ent): return Part.makePlane(ent.XDim, ent.YDim)
def createAnnotation(annotation, doc, ifcscale, preferences): """creates an annotation object""" anno = None if annotation.is_a("IfcGrid"): axes = [] uvwaxes = () if annotation.UAxes: uvwaxes = annotation.UAxes if annotation.VAxes: uvwaxes = uvwaxes + annotation.VAxes if annotation.WAxes: uvwaxes = uvwaxes + annotation.WAxes for axis in uvwaxes: if axis.AxisCurve: sh = get2DShape(axis.AxisCurve, ifcscale) if sh and (len(sh[0].Vertexes) == 2): # currently only straight axes are supported sh = sh[0] l = sh.Length pl = FreeCAD.Placement() pl.Base = sh.Vertexes[0].Point pl.Rotation = FreeCAD.Rotation( FreeCAD.Vector(0, 1, 0), sh.Vertexes[-1].Point.sub(sh.Vertexes[0].Point)) o = Arch.makeAxis(1, l) o.Length = l o.Placement = pl o.CustomNumber = axis.AxisTag axes.append(o) if axes: name = "Grid" grid_placement = None if annotation.Name: name = annotation.Name if six.PY2: name = name.encode("utf8") if annotation.ObjectPlacement: # https://forum.freecadweb.org/viewtopic.php?f=39&t=40027 grid_placement = getPlacement(annotation.ObjectPlacement, scaling=1) if preferences['PREFIX_NUMBERS']: name = "ID" + str(aid) + " " + name anno = Arch.makeAxisSystem(axes, name) if grid_placement: anno.Placement = grid_placement print(" axis") else: name = "Annotation" if annotation.Name: name = annotation.Name if six.PY2: name = name.encode("utf8") if "annotation" not in name.lower(): name = "Annotation " + name if preferences['PREFIX_NUMBERS']: name = "ID" + str(aid) + " " + name shapes2d = [] for rep in annotation.Representation.Representations: if rep.RepresentationIdentifier in [ "Annotation", "FootPrint", "Axis" ]: sh = get2DShape(rep, ifcscale) if sh in doc.Objects: # dirty hack: get2DShape might return an object directly if non-shape based (texts for ex) anno = sh else: shapes2d.extend(sh) if shapes2d: import Part sh = Part.makeCompound(shapes2d) #if preferences['DEBUG']: print(" shape") anno = doc.addObject("Part::Feature", name) anno.Shape = sh p = getPlacement(annotation.ObjectPlacement, ifcscale) if p: # and annotation.is_a("IfcAnnotation"): anno.Placement = p #else: #if preferences['DEBUG']: print(" no shape") return anno
def execute(self,obj): if self.clone(obj): return if not obj.Base: return if not obj.Base.Shape: return if not obj.Base.Shape.Wires: return if not obj.Diameter.Value: return if not obj.Amount: return father = obj.Host fathershape = None if not father: # support for old-style rebars if obj.InList: if hasattr(obj.InList[0],"Armatures"): if obj in obj.InList[0].Armatures: father = obj.InList[0] if father: if father.isDerivedFrom("Part::Feature"): fathershape = father.Shape wire = obj.Base.Shape.Wires[0] if hasattr(obj,"Rounding"): #print(obj.Rounding) if obj.Rounding: radius = obj.Rounding * obj.Diameter.Value import DraftGeomUtils wire = DraftGeomUtils.filletWire(wire,radius) bpoint, bvec = self.getBaseAndAxis(wire) if not bpoint: return axis = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0,0,-1)) if fathershape: size = (ArchCommands.projectToVector(fathershape.copy(),axis)).Length else: size = 1 if hasattr(obj,"Direction"): if not DraftVecUtils.isNull(obj.Direction): axis = FreeCAD.Vector(obj.Direction) axis.normalize() if fathershape: size = (ArchCommands.projectToVector(fathershape.copy(),axis)).Length else: size = 1 if hasattr(obj,"Distance"): if obj.Distance.Value: size = obj.Distance.Value #print(axis) #print(size) spacinglist = None if hasattr(obj, "CustomSpacing"): if obj.CustomSpacing: spacinglist = strprocessOfCustomSpacing(obj.CustomSpacing) influenceArea = sum(spacinglist) - spacinglist[0] / 2 - spacinglist[-1] / 2 if (obj.OffsetStart.Value + obj.OffsetEnd.Value) > size: return # all tests ok! pl = obj.Placement import Part circle = Part.makeCircle(obj.Diameter.Value/2,bpoint,bvec) circle = Part.Wire(circle) try: bar = wire.makePipeShell([circle],True,False,2) except Part.OCCError: print("Arch: error sweeping rebar profile along the base sketch") return # building final shape shapes = [] placementlist = [] if father: rot = father.Placement.Rotation else: rot = FreeCAD.Rotation() if obj.Amount == 1: barplacement = CalculatePlacement(obj.Amount, 1, size, axis, rot, obj.OffsetStart.Value, obj.OffsetEnd.Value) placementlist.append(barplacement) if hasattr(obj,"Spacing"): obj.Spacing = 0 else: if obj.OffsetStart.Value: baseoffset = DraftVecUtils.scaleTo(axis,obj.OffsetStart.Value) else: baseoffset = None interval = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value) interval = interval / (obj.Amount - 1) for i in range(obj.Amount): barplacement = CalculatePlacement(obj.Amount, i+1, size, axis, rot, obj.OffsetStart.Value, obj.OffsetEnd.Value) placementlist.append(barplacement) if hasattr(obj,"Spacing"): obj.Spacing = interval # Calculate placement of bars from custom spacing. if spacinglist: placementlist[:] = [] reqInfluenceArea = size - (obj.OffsetStart.Value + obj.OffsetEnd.Value) if influenceArea > reqInfluenceArea: return FreeCAD.Console.PrintError("Influence area of rebars is greater than "+ str(reqInfluenceArea) + ".\n") elif influenceArea < reqInfluenceArea: FreeCAD.Console.PrintWarning("Last span is greater that end offset.\n") for i in range(len(spacinglist)): if i == 0: barplacement = CustomSpacingPlacement(spacinglist, 1, axis, father.Placement.Rotation, obj.OffsetStart.Value, obj.OffsetEnd.Value) placementlist.append(barplacement) else: barplacement = CustomSpacingPlacement(spacinglist, i+1, axis, father.Placement.Rotation, obj.OffsetStart.Value, obj.OffsetEnd.Value) placementlist.append(barplacement) obj.Amount = len(spacinglist) obj.Spacing = 0 obj.PlacementList = placementlist for i in range(len(obj.PlacementList)): if i == 0: bar.Placement = obj.PlacementList[i] shapes.append(bar) else: bar = bar.copy() bar.Placement = obj.PlacementList[i] shapes.append(bar) if shapes: obj.Shape = Part.makeCompound(shapes) obj.Placement = pl
def Activated(self): document = App.ActiveDocument if not document: document = App.newDocument() box = Box.make() Part.show(box)
def positioning_test1(): """ test the place_plank function """ # test place_plank() #pp0 = test_plank() #Part.show(pp0) pp1 = place_plank(test_plank(), 20,4,2, 'i', 'xy', 300,0,0) Part.show(pp1) pp2 = place_plank(test_plank(), 20,4,2, 'x', 'xy', 300,30,0) Part.show(pp2) pp3 = place_plank(test_plank(), 20,4,2, 'y', 'xy', 300,60,0) Part.show(pp3) pp4 = place_plank(test_plank(), 20,4,2, 'z', 'xy', 300,90,0) Part.show(pp4) #pp4 = place_plank(test_plank(), 20,4,2, 'u', 'xy', 300,30,0) pp21 = place_plank(test_plank(), 20,4,2, 'i', 'xy', 350,0,0) Part.show(pp21) pp22 = place_plank(test_plank(), 20,4,2, 'i', 'xz', 350,30,0) Part.show(pp22) pp23 = place_plank(test_plank(), 20,4,2, 'i', 'yx', 350,60,0) Part.show(pp23) pp24 = place_plank(test_plank(), 20,4,2, 'i', 'yz', 350,90,0) Part.show(pp24) pp25 = place_plank(test_plank(), 20,4,2, 'i', 'zx', 350,120,0) Part.show(pp25) pp26 = place_plank(test_plank(), 20,4,2, 'i', 'zy', 350,150,0) Part.show(pp26) #pp27 = place_plank(test_plank(), 20,4,2, 'i', 'xx', 350,180,0) ##Part.show(pp1) r_test = 1 return(r_test)
def getCoG(self, fp, vol, roll=Units.parseQuantity("0 deg"), trim=Units.parseQuantity("0 deg")): """Return the fluid volume center of gravity, provided the volume of fluid inside the tank. The returned center of gravity is referred to the untransformed ship. Keyword arguments: fp -- Part::FeaturePython object affected. vol -- Volume of fluid. roll -- Ship roll angle. trim -- Ship trim angle. If the fluid volume is bigger than the total tank one, it will be conveniently clamped. """ # Change the units of the volume, and clamp the value if vol <= 0.0: return Vector() if vol >= fp.Shape.Volume: vol = 0.0 for solid in fp.Shape.Solids: vol += solid.Volume sCoG = solid.CenterOfMass cog.x = cog.x + sCoG.x * solid.Volume cog.y = cog.y + sCoG.y * solid.Volume cog.z = cog.z + sCoG.z * solid.Volume cog.x = cog.x / vol cog.y = cog.y / vol cog.z = cog.z / vol return cog # Get a first estimation of the level level = vol.Value / fp.Shape.Volume # Transform the tank shape current_placement = fp.Placement m = current_placement.toMatrix() m.rotateX(roll.getValueAs("rad")) m.rotateY(-trim.getValueAs("rad")) fp.Placement = Placement(m) # Iterate to find the fluid shape for i in range(COMMON_BOOLEAN_ITERATIONS): shape = self.getVolume(fp, level, return_shape=True) error = (vol.Value - shape.Volume) / fp.Shape.Volume if abs(error) < 0.01: break level += error # Get the center of gravity vol = 0.0 cog = Vector() if len(shape.Solids) > 0: for solid in shape.Solids: vol += solid.Volume sCoG = solid.CenterOfMass cog.x = cog.x + sCoG.x * solid.Volume cog.y = cog.y + sCoG.y * solid.Volume cog.z = cog.z + sCoG.z * solid.Volume cog.x = cog.x / vol cog.y = cog.y / vol cog.z = cog.z / vol # Untransform the object to retrieve the original position fp.Placement = current_placement p = Part.Point(cog) m = Matrix() m.rotateY(trim.getValueAs("rad")) m.rotateX(-roll.getValueAs("rad")) p.rotate(Placement(m)) return Vector(p.X, p.Y, p.Z)
def getVolume(self, fp, level, return_shape=False): """Return the fluid volume inside the tank, provided the filling level. Keyword arguments: fp -- Part::FeaturePython object affected. level -- Percentage of filling level (interval [0, 1]). return_shape -- False if the tool should return the fluid volume value, True if the tool should return the volume shape. """ if level <= 0.0: if return_shape: return Part.Vertex() return Units.Quantity(0.0, Units.Volume) if level >= 1.0: if return_shape: return fp.Shape.copy() return Units.Quantity(fp.Shape.Volume, Units.Volume) # Build up the cutting box bbox = fp.Shape.BoundBox dx = bbox.XMax - bbox.XMin dy = bbox.YMax - bbox.YMin dz = bbox.ZMax - bbox.ZMin box = App.ActiveDocument.addObject("Part::Box", "Box") length_format = USys.getLengthFormat() box.Placement = Placement( Vector(bbox.XMin - dx, bbox.YMin - dy, bbox.ZMin - dz), Rotation(App.Vector(0, 0, 1), 0)) box.Length = length_format.format(3.0 * dx) box.Width = length_format.format(3.0 * dy) box.Height = length_format.format((1.0 + level) * dz) # Create a new object on top of a copy of the tank shape Part.show(fp.Shape.copy()) tank = App.ActiveDocument.Objects[-1] # Compute the common boolean operation App.ActiveDocument.recompute() common = App.activeDocument().addObject("Part::MultiCommon", "TankVolHelper") common.Shapes = [tank, box] App.ActiveDocument.recompute() if len(common.Shape.Solids) == 0: # The common operation is failing, let's try moving a bit the free # surface msg = QtGui.QApplication.translate( "ship_console", "Tank volume operation failed. The tool is retrying that" " slightly moving the free surface position", None) App.Console.PrintWarning(msg + '\n') rand_bounds = 0.01 * dz i = 0 while len(common.Shape.Solids ) == 0 and i < COMMON_BOOLEAN_ITERATIONS: i += 1 box.Height = length_format.format( (1.0 + level) * dz + random.uniform(-random_bounds, random_bounds)) App.ActiveDocument.recompute() if return_shape: ret_value = common.Shape.copy() else: ret_value = Units.Quantity(common.Shape.Volume, Units.Volume) App.ActiveDocument.removeObject(common.Name) App.ActiveDocument.removeObject(tank.Name) App.ActiveDocument.removeObject(box.Name) App.ActiveDocument.recompute() return ret_value
def draw(self): try: Gui.getDocument(self.name) Gui.getDocument(self.name).resetEdit() App.getDocument(self.name).recompute() App.closeDocument(self.name) App.setActiveDocument("") App.ActiveDocument = None Gui.ActiveDocument = None except: pass #make document App.newDocument(self.name) App.setActiveDocument(self.name) App.ActiveDocument = App.getDocument(self.name) Gui.ActiveDocument = Gui.getDocument(self.name) #Make profile of angle and extrude it p1x = -gv.extruderMountPlateWidth / 2 p1y = 0 p2x = p1x p2y = gv.extruderDepth p3x = -p1x p3y = p2y p4x = p3x p4y = p1y #Make Sketch App.activeDocument().addObject('Sketcher::SketchObject', 'Sketch') App.activeDocument().Sketch.Placement = App.Placement( App.Vector(0.000000, 0.000000, 0.000000), App.Rotation(0.000000, 0.000000, 0.000000, 1.000000)) Gui.activeDocument().activeView().setCamera( '#Inventor V2.1 ascii \n OrthographicCamera {\n viewportMapping ADJUST_CAMERA \n position 0 0 87 \n orientation 0 0 1 0 \n nearDistance -112.88701 \n farDistance 287.28702 \n aspectRatio 1 \n focalDistance 87 \n height 143.52005 }' ) # Gui.activeDocument().setEdit('Sketch') App.ActiveDocument.Sketch.addGeometry( Part.Line(App.Vector(p1x, p1y, 0), App.Vector(p4x, p4y, 0))) App.ActiveDocument.Sketch.addGeometry( Part.Line(App.Vector(p4x, p4y, 0), App.Vector(p3x, p3y, 0))) App.ActiveDocument.Sketch.addGeometry( Part.Line(App.Vector(p3x, p3y, 0), App.Vector(p2x, p2y, 0))) App.ActiveDocument.Sketch.addGeometry( Part.Line(App.Vector(p2x, p2y, 0), App.Vector(p1x, p1y, 0))) App.ActiveDocument.Sketch.addConstraint( Sketcher.Constraint('Coincident', 0, 2, 1, 1)) App.ActiveDocument.Sketch.addConstraint( Sketcher.Constraint('Coincident', 1, 2, 2, 1)) App.ActiveDocument.Sketch.addConstraint( Sketcher.Constraint('Coincident', 2, 2, 3, 1)) App.ActiveDocument.Sketch.addConstraint( Sketcher.Constraint('Coincident', 3, 2, 0, 1)) App.ActiveDocument.Sketch.addConstraint( Sketcher.Constraint('Horizontal', 0)) App.ActiveDocument.Sketch.addConstraint( Sketcher.Constraint('Horizontal', 2)) App.ActiveDocument.Sketch.addConstraint( Sketcher.Constraint('Vertical', 1)) App.ActiveDocument.Sketch.addConstraint( Sketcher.Constraint('Vertical', 3)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch.addConstraint( Sketcher.Constraint('PointOnObject', 0, 1, -1)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch.addConstraint( Sketcher.Constraint('Symmetric', 0, 2, 0, 1, -1, 1)) App.ActiveDocument.recompute() #Add dimensions App.ActiveDocument.Sketch.addConstraint( Sketcher.Constraint('DistanceY', 1, gv.extruderDepth)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch.addConstraint( Sketcher.Constraint('DistanceX', 0, gv.extruderMountPlateWidth)) App.ActiveDocument.recompute() # Gui.getDocument(self.name).resetEdit() App.getDocument(self.name).recompute() #Pad extruderMountPlate App.activeDocument().addObject("PartDesign::Pad", "Pad") App.activeDocument().Pad.Sketch = App.activeDocument().Sketch App.activeDocument().Pad.Length = 10.0 App.ActiveDocument.recompute() Gui.activeDocument().hide("Sketch") App.ActiveDocument.Pad.Length = gv.extruderMountPlateThickness App.ActiveDocument.Pad.Reversed = 0 App.ActiveDocument.Pad.Midplane = 0 App.ActiveDocument.Pad.Length2 = 100.000000 App.ActiveDocument.Pad.Type = 0 App.ActiveDocument.Pad.UpToFace = None App.ActiveDocument.recompute() # Gui.activeDocument().resetEdit() #Make holes for mounting plate to angle #Sketch Points p1x = gv.extruderMountPlateWidth p1y = (gv.extruderMountAngleWidth + gv.extruderMountAngleThickness) / 2 p2x = -gv.xCarriageWidth / 2 + gv.xCarriageMountHoleHorizOffset p2y = p1y p3x = -p2x p3y = p1y p4x = -p1x p4y = p1y App.activeDocument().addObject('Sketcher::SketchObject', 'Sketch001') App.activeDocument().Sketch001.Support = uf.getFace( App.ActiveDocument.Pad, None, None, None, None, gv.extruderMountPlateThickness, 0) #(App.ActiveDocument.Pad,["Face6"]) App.activeDocument().recompute() # Gui.activeDocument().setEdit('Sketch001') # App.ActiveDocument.Sketch001.addExternal("Pad","Edge12") App.ActiveDocument.Sketch001.addExternal( "Pad", uf.getEdge(App.ActiveDocument.Pad, -gv.extruderMountPlateWidth / 2, 0, None, None, gv.extruderMountPlateThickness, 0)) App.ActiveDocument.Sketch001.addExternal( "Pad", uf.getEdge(App.ActiveDocument.Pad, gv.extruderMountPlateWidth / 2, 0, None, None, gv.extruderMountPlateThickness, 0)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addGeometry( Part.Line(App.Vector(p1x, p1y, 0), App.Vector(p2x, p2y, 0))) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('PointOnObject', 0, 1, -3)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('Horizontal', 0)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addGeometry( Part.Line(App.Vector(p2x, p2y, 0), App.Vector(p3x, p3y, 0))) App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('Coincident', 0, 2, 1, 1)) App.ActiveDocument.recompute() App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('Horizontal', 1)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addGeometry( Part.Line(App.Vector(p3x, p3y, 0), App.Vector(p4x, p4y, 0))) App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('Coincident', 1, 2, 2, 1)) App.ActiveDocument.recompute() App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('PointOnObject', 2, 2, -4)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('Horizontal', 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('Equal', 2, 0)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.toggleConstruction(0) App.ActiveDocument.Sketch001.toggleConstruction(1) App.ActiveDocument.Sketch001.toggleConstruction(2) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addGeometry( Part.Circle(App.Vector(p2x, p2y, 0), App.Vector(0, 0, 1), gv.mountToPrintedDia / 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('Coincident', 3, 3, 0, 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addGeometry( Part.Circle(App.Vector(p3x, p3y, 0), App.Vector(0, 0, 1), gv.mountToPrintedDia / 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('Coincident', 4, 3, 1, 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('Equal', 4, 3)) App.ActiveDocument.recompute() #Add dimensions App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('Radius', 4, gv.mountToPrintedDia / 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint( 'DistanceX', 0, 2, 0, 1, -(gv.extruderMountPlateWidth / 2 - gv.xCarriageWidth / 2 + gv.xCarriageMountHoleHorizOffset))) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint( 'DistanceY', -1, 1, 0, 2, (gv.extruderMountAngleWidth + gv.extruderMountAngleThickness) / 2)) App.ActiveDocument.recompute() # Gui.getDocument(self.name).resetEdit() App.getDocument(self.name).recompute() #Cut the holes App.activeDocument().addObject("PartDesign::Pocket", "Pocket") App.activeDocument().Pocket.Sketch = App.activeDocument().Sketch001 App.activeDocument().Pocket.Length = 5.0 App.ActiveDocument.recompute() Gui.activeDocument().hide("Sketch001") Gui.activeDocument().hide("Pad") # Gui.activeDocument().setEdit('Pocket') # Gui.ActiveDocument.Pocket.ShapeColor=Gui.ActiveDocument.Pad.ShapeColor # Gui.ActiveDocument.Pocket.LineColor=Gui.ActiveDocument.Pad.LineColor # Gui.ActiveDocument.Pocket.PointColor=Gui.ActiveDocument.Pad.PointColor App.ActiveDocument.Pocket.Length = 5.000000 App.ActiveDocument.Pocket.Type = 1 App.ActiveDocument.Pocket.UpToFace = None App.ActiveDocument.recompute() # Gui.activeDocument().resetEdit() #make holes for mounting the extruder #Sketch Points p1x = -gv.extruderMountPlateWidth / 2 p1y = gv.extruderDepth - gv.extruderEdgeToCenterLine p2x = -gv.extruderMountHoleSpacing / 2 p2y = p1y p3x = 0 p3y = p1y p4x = -p2x p4y = p1y p5x = -p1x p5y = p1y #Make Sketch App.activeDocument().addObject('Sketcher::SketchObject', 'Sketch002') App.activeDocument().Sketch002.Support = uf.getFace( App.ActiveDocument.Pocket, None, None, None, None, gv.extruderMountPlateThickness, 0) #(App.ActiveDocument.Pocket,["Face5"]) App.activeDocument().recompute() # Gui.activeDocument().setEdit('Sketch002') App.ActiveDocument.Sketch002.addExternal( "Pocket", uf.getEdge(App.ActiveDocument.Pocket, -gv.extruderMountPlateWidth / 2, 0, None, None, gv.extruderMountPlateThickness, 0)) App.ActiveDocument.Sketch002.addExternal( "Pocket", uf.getEdge(App.ActiveDocument.Pocket, gv.extruderMountPlateWidth / 2, 0, None, None, gv.extruderMountPlateThickness, 0)) App.ActiveDocument.Sketch002.addGeometry( Part.Line(App.Vector(p1x, p1y, 0), App.Vector(p2x, p2y, 0))) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('PointOnObject', 0, 1, -3)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Horizontal', 0)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addGeometry( Part.Line(App.Vector(p2x, p2y, 0), App.Vector(p3x, p3y, 0))) App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Coincident', 0, 2, 1, 1)) App.ActiveDocument.recompute() App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('PointOnObject', 1, 2, -2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Horizontal', 1)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addGeometry( Part.Line(App.Vector(p3x, p3y, 0), App.Vector(p4x, p4y, 0))) App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Coincident', 1, 2, 2, 1)) App.ActiveDocument.recompute() App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Horizontal', 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addGeometry( Part.Line(App.Vector(p4x, p4y, 0), App.Vector(p5x, p5y, 0))) App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Coincident', 2, 2, 3, 1)) App.ActiveDocument.recompute() App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('PointOnObject', 3, 2, -4)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Horizontal', 3)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Equal', 3, 0)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Equal', 2, 1)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.toggleConstruction(0) App.ActiveDocument.Sketch002.toggleConstruction(1) App.ActiveDocument.Sketch002.toggleConstruction(2) App.ActiveDocument.Sketch002.toggleConstruction(3) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addGeometry( Part.Circle(App.Vector(p2x, p2y, 0), App.Vector(0, 0, 1), gv.extruderMountHoleDia / 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Coincident', 4, 3, 0, 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addGeometry( Part.Circle(App.Vector(p4x, p4y, 0), App.Vector(0, 0, 1), gv.extruderMountHoleDia / 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Coincident', 5, 3, 2, 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addGeometry( Part.Circle(App.Vector(p3x, p3y, 0), App.Vector(0, 0, 1), gv.extruderFilamentHoleDia / 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Coincident', 6, 3, 1, 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Equal', 4, 5)) App.ActiveDocument.recompute() #Add Dimensions App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('DistanceX', 0, 2, 2, 2, gv.extruderMountHoleSpacing)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('DistanceY', 3, 2, -4, 2, gv.extruderEdgeToCenterLine)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Radius', 4, gv.extruderMountHoleDia / 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addConstraint( Sketcher.Constraint('Radius', 6, gv.extruderFilamentHoleDia / 2)) App.ActiveDocument.recompute() # Gui.getDocument(self.name).resetEdit() App.getDocument(self.name).recompute() #Cut holes through all App.activeDocument().addObject("PartDesign::Pocket", "Pocket001") App.activeDocument().Pocket001.Sketch = App.activeDocument().Sketch002 App.activeDocument().Pocket001.Length = 5.0 App.ActiveDocument.recompute() Gui.activeDocument().hide("Sketch002") Gui.activeDocument().hide("Pocket") # Gui.ActiveDocument.Pocket001.ShapeColor=Gui.ActiveDocument.Pocket.ShapeColor # Gui.ActiveDocument.Pocket001.LineColor=Gui.ActiveDocument.Pocket.LineColor # Gui.ActiveDocument.Pocket001.PointColor=Gui.ActiveDocument.Pocket.PointColor App.ActiveDocument.Pocket001.Length = 5.000000 App.ActiveDocument.Pocket001.Type = 1 App.ActiveDocument.Pocket001.UpToFace = None App.ActiveDocument.recompute() # Gui.activeDocument().resetEdit() #Cut holes for hot end mount if needed. if self.hotEndMountHoles: #Sketch Points p1x = -gv.hotEndMountHoleSpacing / 2 p1y = gv.extruderDepth - gv.extruderEdgeToCenterLine p2x = -p1x p2y = p1y #Make Sketch App.activeDocument().addObject('Sketcher::SketchObject', 'Sketch003') App.activeDocument().Sketch003.Support = uf.getFace( App.ActiveDocument.Pocket001, None, None, None, None, gv.extruderMountPlateThickness, 0) #(App.ActiveDocument.Pocket001,["Face5"]) App.activeDocument().recompute() # Gui.activeDocument().setEdit('Sketch003') App.ActiveDocument.Sketch003.addGeometry( Part.Line(App.Vector(p1x, p1y, 0), App.Vector(p2x, p2y, 0))) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Horizontal', 0)) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Symmetric', 0, 1, 0, 2, -2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.toggleConstruction(0) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addGeometry( Part.Circle(App.Vector(p1x, p1y, 0), App.Vector(0, 0, 1), gv.hotEndMountHoleDia / 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 1, 3, 0, 1)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addGeometry( Part.Circle(App.Vector(p2x, p2y, 0), App.Vector(0, 0, 1), gv.hotEndMountHoleDia / 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 2, 3, 0, 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Equal', 1, 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Radius', 2, gv.hotEndMountHoleDia / 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('DistanceX', 0, gv.hotEndMountHoleSpacing)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Distance', -1, 1, 0, p1y)) # Gui.getDocument(self.name).resetEdit() App.getDocument(self.name).recompute() #Cut hole Through All App.activeDocument().addObject("PartDesign::Pocket", "Pocket002") App.activeDocument().Pocket002.Sketch = App.activeDocument( ).Sketch003 App.activeDocument().Pocket002.Length = 5.0 App.ActiveDocument.recompute() Gui.activeDocument().hide("Sketch003") Gui.activeDocument().hide("Pocket001") # Gui.ActiveDocument.Pocket002.ShapeColor=Gui.ActiveDocument.Pocket001.ShapeColor # Gui.ActiveDocument.Pocket002.LineColor=Gui.ActiveDocument.Pocket001.LineColor # Gui.ActiveDocument.Pocket002.PointColor=Gui.ActiveDocument.Pocket001.PointColor App.ActiveDocument.Pocket002.Length = 5.000000 App.ActiveDocument.Pocket002.Type = 1 App.ActiveDocument.Pocket002.UpToFace = None App.ActiveDocument.recompute()
"""Creates a circuit for testing""" import Part as part import RecognitionSite as rs import GeneticCircuit as gc import Enzyme as enz import copy import unittest ##SETUP ##Create the parts part1 = part.Part(1, 1) site1 = rs.RecognitionSite('D', 1) part2 = part.Part(2, 1) site2 = rs.RecognitionSite('[', 1) part3 = part.Part(3, 1) site3 = rs.RecognitionSite('(', 1) part4 = part.Part(4,1) site4 = rs.RecognitionSite('[', -1) part5 = part.Part(5, 1) site5 = rs.RecognitionSite('(', 1) part6 = part.Part(6, 1) site6 = rs.RecognitionSite('D', -1) part7 = part.Part(7,1) ##Create the enzymes enzyme1 = enz.Enzyme('Ara') enzyme1.addSiteToRecognize('[') enzyme1.addSiteToRecognize('D') enzyme2 = enz.Enzyme('ATc')
def execute(self, obj): import Part # import OpenSCAD2Dgeom import os if obj.String and obj.FontFile: if obj.Placement: plm = obj.Placement ff8 = obj.FontFile.encode('utf8') # 1947 accents in filepath # TODO: change for Py3?? bytes? # Part.makeWireString uses FontFile as char* string if sys.version_info.major < 3: CharList = Part.makeWireString(obj.String, ff8, obj.Size, obj.Tracking) else: CharList = Part.makeWireString(obj.String, obj.FontFile, obj.Size, obj.Tracking) if len(CharList) == 0: App.Console.PrintWarning( translate("draft", "ShapeString: string has no wires") + "\n") return SSChars = [] # test a simple letter to know if we have a sticky font or not sticky = False if sys.version_info.major < 3: testWire = Part.makeWireString("L", ff8, obj.Size, obj.Tracking)[0][0] else: testWire = Part.makeWireString("L", obj.FontFile, obj.Size, obj.Tracking)[0][0] if testWire.isClosed: try: testFace = Part.Face(testWire) except Part.OCCError: sticky = True else: if not testFace.isValid(): sticky = True else: sticky = True for char in CharList: if sticky: for CWire in char: SSChars.append(CWire) else: CharFaces = [] for CWire in char: f = Part.Face(CWire) if f: CharFaces.append(f) # whitespace (ex: ' ') has no faces. This breaks OpenSCAD2Dgeom... if CharFaces: # s = OpenSCAD2Dgeom.Overlappingfaces(CharFaces).makeshape() # s = self.makeGlyph(CharFaces) s = self.makeFaces(char) SSChars.append(s) shape = Part.Compound(SSChars) obj.Shape = shape if plm: obj.Placement = plm obj.positionBySupport()
def onChanged(self, vobj, prop): if prop == "LineColor": l = vobj.LineColor self.mat.diffuseColor.setValue([l[0],l[1],l[2]]) elif prop == "DrawStyle": if vobj.DrawStyle == "Solid": self.linestyle.linePattern = 0xffff elif vobj.DrawStyle == "Dashed": self.linestyle.linePattern = 0xf00f elif vobj.DrawStyle == "Dotted": self.linestyle.linePattern = 0x0f0f else: self.linestyle.linePattern = 0xff88 elif prop == "LineWidth": self.linestyle.lineWidth = vobj.LineWidth elif prop in ["BubbleSize","BubblePosition","FontName","FontSize"]: if hasattr(self,"bubbleset"): if self.bubbles: self.bubbleset.removeChild(self.bubbles) self.bubbles = None if vobj.Object.Shape: if vobj.Object.Shape.Edges: self.bubbles = coin.SoSeparator() self.bubblestyle = coin.SoDrawStyle() self.bubblestyle.linePattern = 0xffff self.bubbles.addChild(self.bubblestyle) import Part,Draft self.bubbletexts = [] pos = ["Start"] if hasattr(vobj,"BubblePosition"): if vobj.BubblePosition == "Both": pos = ["Start","End"] else: pos = [vobj.BubblePosition] for i in range(len(vobj.Object.Shape.Edges)): for p in pos: verts = vobj.Object.Shape.Edges[i].Vertexes if p == "Start": p1 = verts[0].Point p2 = verts[1].Point else: p1 = verts[1].Point p2 = verts[0].Point dv = p2.sub(p1) dv.normalize() if hasattr(vobj.BubbleSize,"Value"): rad = vobj.BubbleSize.Value/2 else: rad = vobj.BubbleSize/2 center = p2.add(dv.scale(rad,rad,rad)) buf = Part.makeCircle(rad,center).writeInventor() try: cin = coin.SoInput() cin.setBuffer(buf) cob = coin.SoDB.readAll(cin) except: import re # workaround for pivy SoInput.setBuffer() bug buf = buf.replace("\n","") pts = re.findall("point \[(.*?)\]",buf)[0] pts = pts.split(",") pc = [] for p in pts: v = p.strip().split() pc.append([float(v[0]),float(v[1]),float(v[2])]) coords = coin.SoCoordinate3() coords.point.setValues(0,len(pc),pc) line = coin.SoLineSet() line.numVertices.setValue(-1) else: coords = cob.getChild(1).getChild(0).getChild(2) line = cob.getChild(1).getChild(0).getChild(3) self.bubbles.addChild(coords) self.bubbles.addChild(line) st = coin.SoSeparator() tr = coin.SoTransform() fs = rad*1.5 if hasattr(vobj,"FontSize"): fs = vobj.FontSize.Value tr.translation.setValue((center.x,center.y-fs/2.5,center.z)) fo = coin.SoFont() fn = Draft.getParam("textfont","Arial,Sans") if hasattr(vobj,"FontName"): if vobj.FontName: try: fn = str(vobj.FontName) except: pass fo.name = fn fo.size = fs tx = coin.SoAsciiText() tx.justification = coin.SoText2.CENTER self.bubbletexts.append(tx) st.addChild(tr) st.addChild(fo) st.addChild(tx) self.bubbles.addChild(st) self.bubbleset.addChild(self.bubbles) self.onChanged(vobj,"NumberingStyle") elif prop in ["NumberingStyle","StartNumber"]: if hasattr(self,"bubbletexts"): chars = "abcdefghijklmnopqrstuvwxyz" roman=(('M',1000),('CM',900),('D',500),('CD',400), ('C',100),('XC',90),('L',50),('XL',40), ('X',10),('IX',9),('V',5),('IV',4),('I',1)) num = 0 if hasattr(vobj,"StartNumber"): if vobj.StartNumber > 1: num = vobj.StartNumber-1 alt = False for t in self.bubbletexts: if hasattr(vobj,"NumberingStyle"): if vobj.NumberingStyle == "1,2,3": t.string = str(num+1) elif vobj.NumberingStyle == "01,02,03": t.string = str(num+1).zfill(2) elif vobj.NumberingStyle == "001,002,003": t.string = str(num+1).zfill(3) elif vobj.NumberingStyle == "A,B,C": result = "" base = num/26 if base: result += chars[base].upper() remainder = num % 26 result += chars[remainder].upper() t.string = result elif vobj.NumberingStyle == "a,b,c": result = "" base = num/26 if base: result += chars[base] remainder = num % 26 result += chars[remainder] t.string = result elif vobj.NumberingStyle == "I,II,III": result = "" n = num n += 1 for numeral, integer in roman: while n >= integer: result += numeral n -= integer t.string = result elif vobj.NumberingStyle == "L0,L1,L2": t.string = "L"+str(num) else: t.string = str(num+1) num += 1 if hasattr(vobj,"BubblePosition"): if vobj.BubblePosition == "Both": if not alt: num -= 1 alt = not alt
def getSVG(section, allOn=False, renderMode="Wireframe", showHidden=False, showFill=False, scale=1, linewidth=1, fontsize=1): """getSVG(section,[allOn,renderMode,showHidden,showFill,scale,linewidth,fontsize]) : returns an SVG fragment from an Arch section plane. If allOn is True, all cut objects are shown, regardless if they are visible or not. renderMode can be Wireframe (default) or Solid to use the Arch solid renderer. If showHidden is True, the hidden geometry above the section plane is shown in dashed line. If showFill is True, the cut areas get filled with a pattern""" if not section.Objects: return import DraftGeomUtils p = FreeCAD.Placement(section.Placement) direction = p.Rotation.multVec(FreeCAD.Vector(0, 0, 1)) objs = Draft.getGroupContents(section.Objects, walls=True, addgroups=True) if not allOn: objs = Draft.removeHidden(objs) # separate spaces spaces = [] nonspaces = [] for o in objs: if Draft.getType(o) == "Space": spaces.append(o) else: nonspaces.append(o) objs = nonspaces svg = '' fillpattern = '<pattern id="sectionfill" patternUnits="userSpaceOnUse" patternTransform="matrix(5,0,0,5,0,0)"' fillpattern += ' x="0" y="0" width="10" height="10">' fillpattern += '<g>' fillpattern += '<rect width="10" height="10" style="stroke:none; fill:#ffffff" /><path style="stroke:#000000; stroke-width:1" d="M0,0 l10,10" /></g></pattern>' # generating SVG if renderMode == "Solid": # render using the Arch Vector Renderer import ArchVRM, WorkingPlane wp = WorkingPlane.plane() wp.setFromPlacement(section.Placement) #wp.inverse() render = ArchVRM.Renderer() render.setWorkingPlane(wp) render.addObjects(objs) if showHidden: render.cut(section.Shape, showHidden) else: render.cut(section.Shape) svg += '<g transform="scale(1,-1)">\n' svg += render.getViewSVG(linewidth="LWPlaceholder") svg += fillpattern svg += render.getSectionSVG(linewidth="SWPlaceholder", fillpattern="sectionfill") if showHidden: svg += render.getHiddenSVG(linewidth="LWPlaceholder") svg += '</g>\n' # print render.info() else: # render using the Drawing module import Drawing, Part shapes = [] hshapes = [] sshapes = [] for o in objs: if o.isDerivedFrom("Part::Feature"): if o.Shape.isNull(): pass elif o.Shape.isValid(): if section.OnlySolids: shapes.extend(o.Shape.Solids) else: shapes.append(o.Shape) else: print section.Label, ": Skipping invalid object:", o.Label cutface, cutvolume, invcutvolume = ArchCommands.getCutVolume( section.Shape.copy(), shapes) if cutvolume: nsh = [] for sh in shapes: for sol in sh.Solids: if sol.Volume < 0: sol.reverse() c = sol.cut(cutvolume) s = sol.section(cutface) try: wires = DraftGeomUtils.findWires(s.Edges) for w in wires: f = Part.Face(w) sshapes.append(f) #s = Part.Wire(s.Edges) #s = Part.Face(s) except Part.OCCError: #print "ArchDrawingView: unable to get a face" sshapes.append(s) nsh.extend(c.Solids) #sshapes.append(s) if showHidden: c = sol.cut(invcutvolume) hshapes.append(c) shapes = nsh if shapes: baseshape = Part.makeCompound(shapes) svgf = Drawing.projectToSVG(baseshape, direction) if svgf: svgf = svgf.replace('stroke-width="0.35"', 'stroke-width="LWPlaceholder"') svgf = svgf.replace('stroke-width="1"', 'stroke-width="LWPlaceholder"') svgf = svgf.replace('stroke-width:0.01', 'stroke-width:LWPlaceholder') svg += svgf if hshapes: hshapes = Part.makeCompound(hshapes) svgh = Drawing.projectToSVG(hshapes, direction) if svgh: svgh = svgh.replace('stroke-width="0.35"', 'stroke-width="LWPlaceholder"') svgh = svgh.replace('stroke-width="1"', 'stroke-width="LWPlaceholder"') svgh = svgh.replace('stroke-width:0.01', 'stroke-width:LWPlaceholder') svgh = svgh.replace( 'fill="none"', 'fill="none"\nstroke-dasharray="DAPlaceholder"') svg += svgh if sshapes: svgs = "" if showFill: svgs += fillpattern svgs += '<g transform="rotate(180)">\n' for s in sshapes: if s.Edges: f = Draft.getSVG(s, direction=direction.negative(), linewidth=0, fillstyle="sectionfill", color=(0, 0, 0)) svgs += f svgs += "</g>\n" sshapes = Part.makeCompound(sshapes) svgs += Drawing.projectToSVG(sshapes, direction) if svgs: svgs = svgs.replace('stroke-width="0.35"', 'stroke-width="SWPlaceholder"') svgs = svgs.replace('stroke-width="1"', 'stroke-width="SWPlaceholder"') svgs = svgs.replace('stroke-width:0.01', 'stroke-width:SWPlaceholder') svgs = svgs.replace('stroke-width="0.35 px"', 'stroke-width="SWPlaceholder"') svgs = svgs.replace('stroke-width:0.35', 'stroke-width:SWPlaceholder') svg += svgs linewidth = linewidth / scale st = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Arch").GetFloat( "CutLineThickness", 2) da = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Arch").GetString( "archHiddenPattern", "30,10") da = da.replace(" ", "") svg = svg.replace('LWPlaceholder', str(linewidth) + 'px') svg = svg.replace('SWPlaceholder', str(linewidth * st) + 'px') svg = svg.replace('DAPlaceholder', str(da)) if spaces and round( direction.getAngle(FreeCAD.Vector(0, 0, 1)), Draft.precision()) in [0, round(math.pi, Draft.precision())]: svg += '<g transform="scale(1,-1)">' for s in spaces: svg += Draft.getSVG(s, scale=scale, fontsize=fontsize, direction=direction) svg += '</g>' # print "complete node:",svg return svg
def getDeviation(self): """returns a deviation vector that represents the base of the circle""" import Part c = Part.makeCircle(1, Vector(0, 0, 0), self.normal) return c.Vertexes[0].Point
def asEdge(self): return Part.Edge(self.asLine())
def export_mesh(filename, meshobj=None, isDiel=False, showNormals=False, folder=DEF_FOLDER): '''export mesh in FasterCap format as conductor or dielectric interface 'filename' is the name of the export file 'meshobj' must be a Mesh::Feature object 'isDiel' specifies if the mesh is a dielectric, so the function will add a reference point to each panel to indicate which is the external side (outside) 'showNormals' will add a compound object composed by a set of arrows showing the normal direction for each panel 'folder' is the folder in which 'filename' will be saved Example: mymeshGui = Gui.ActiveDocument.Mesh mymeshObj = mymeshGui.Object export_mesh("mymesh.txt", meshobj=mymeshObj, folder="C:/temp") ''' # if no valid mesh was passed if meshobj == None: return elif meshobj.TypeId != "Mesh::Feature": FreeCAD.Console.PrintMessage( "Error: 'meshobj' is not an object of type 'Mesh::Feature'") return if not os.path.isdir(folder): os.mkdir(folder) with open(folder + os.sep + filename, 'w') as fid: # write the preamble if isDiel == True: fid.write("0 dielectric definition file for mesh '" + meshobj.Label) else: fid.write("0 conductor definition file for mesh '" + meshobj.Label) fid.write("' created using FreeCAD's ElectroMagnetic workbench\n") fid.write( "* see http://www.freecad.org and http://www.fastfieldsolvers.com\n" ) fid.write("\n") # export facets arrows = [] condName = meshobj.Label.replace(" ", "_") for facet in meshobj.Mesh.Facets: if len(facet.Points) == 3: fid.write("T " + condName) elif len(facet.Points) == 4: fid.write("Q " + condName) else: FreeCAD.Console.PrintMessage( "Unforseen number of mesh facet points: " + len(facet.Points) + ", skipping facet") continue center = Vector(0.0, 0.0, 0.0) avgSideLen = 0.0 for j, point in enumerate(facet.Points): fid.write(" ") for i in range(3): fid.write(" " + str(point[i])) if isDiel == True or showNormals == True: # 'point' is a tuple, transform in vector center = center + Vector(point) # get side length side = Vector(facet.Points[(j + 1) % 3]) - Vector(point) avgSideLen += side.Length if isDiel == True or showNormals == True: # calculate the reference point # (there should be a better way to divide a vector by a scalar..) center.multiply(1.0 / len(facet.Points)) # and now move along the normal, proportional to the average facet dimension scaledNormal = Vector(facet.Normal) scaledNormal.multiply(avgSideLen / len(facet.Points)) refpoint = center + scaledNormal if isDiel == True: fid.write(" ") for i in range(3): fid.write(" " + str(refpoint[i])) fid.write("\n") if showNormals == True: arrows.append(make_arrow(center, refpoint)) if showNormals == True: # add the vector normals visualization to the view # Note: could also use Part.show(normals) but in this case we could # not give the (permanent) name to the object, only change the label afterwards normals = Part.makeCompound(arrows) normalobj = FreeCAD.ActiveDocument.addObject( "Part::Feature", "Normals") normalobj.Shape = normals fid.closed
def GetFace(self): self.edges.append(Part.makeLine(self.lastPoint, self.firstPoint)) w = Part.Wire(self.edges) return Part.Face(w)
def generateHob(baseRadius,addendumRadius,dedendumRadius,angularSeperation,\ clearance,filletRadius,sign,status): CLOSED = True OPEN = False FACE = True WIRE_FRAME = False PLACEMENT = None DELETE = True status.updateStatus("Setting precision to 0.001 mm") PRECISION = 0.001 status.updateStatus("Calculating range for involute function") addendumRadius *= 1.01 ratioAddendum = addendumRadius / baseRadius ratioDedendum = dedendumRadius / baseRadius t=numpy.arange(InvoluteProfile.calculateRange(ratioDedendum),\ InvoluteProfile.calculateRange(ratioAddendum),PRECISION) status.updateStatus("Defining involute curves") xInvLeft = baseRadius * (numpy.cos(-t - angularSeperation) - t * numpy.sin(-t - angularSeperation)) yInvLeft = baseRadius * (numpy.sin(-t - angularSeperation) + t * numpy.cos(-t - angularSeperation)) xInvRight = baseRadius * (numpy.cos(t + angularSeperation) + t * numpy.sin(t + angularSeperation)) yInvRight = baseRadius * (numpy.sin(t + angularSeperation) - t * numpy.cos(t + angularSeperation)) InvLeftVector = [] InvRightVector = [] status.updateStatus("Defining vectors for involute curves") for i in range(len(t)): InvLeftVector.append(FreeCAD.Vector(xInvLeft[i], yInvLeft[i], 0)) InvRightVector.append(FreeCAD.Vector(xInvRight[i], yInvRight[i], 0)) status.updateStatus("Drafting involute curves") InvLeft = Draft.makeBSpline(Part.makePolygon(InvLeftVector), OPEN, WIRE_FRAME) InvRight = Draft.makeBSpline(Part.makePolygon(InvRightVector), OPEN, WIRE_FRAME) status.updateStatus("Defining clearance lines") clearanceLeftX = FreeCAD.Vector(xInvLeft[0] - clearance + filletRadius, yInvLeft[0], 0) clearanceRightX = FreeCAD.Vector( xInvRight[0] - clearance + filletRadius, yInvRight[0], 0) status.updateStatus("Drafting clearance lines") lineLeft = Draft.makeLine(InvLeftVector[0], clearanceLeftX) lineRight = Draft.makeLine(InvRightVector[0], clearanceRightX) status.updateStatus("Defining root line") clearanceLeftY = FreeCAD.Vector(xInvLeft[0] - clearance, yInvLeft[0] + filletRadius, 0) clearanceRightY = FreeCAD.Vector(xInvRight[0] - clearance, yInvRight[0] - filletRadius, 0) status.updateStatus("Drafting root line") lineClearance = Draft.makeLine(clearanceLeftY, clearanceRightY) status.updateStatus("Defining fillet curves") filletLeftCenter = FreeCAD.Placement() filletRightCenter = FreeCAD.Placement() filletLeftCenter.move(FreeCAD.Vector(xInvLeft[0]-clearance+filletRadius,\ yInvLeft[0]+filletRadius,0)) filletRightCenter.move(FreeCAD.Vector(xInvRight[0]-clearance+filletRadius,\ yInvRight[0]-filletRadius,0)) startangle = 180 endangle = 270 status.updateStatus("Drafting fillet curves") filletLeft = Draft.makeCircle(filletRadius, filletLeftCenter, WIRE_FRAME, startangle, endangle) startangle = 90 endangle = 180 filletRight = Draft.makeCircle(filletRadius, filletRightCenter, WIRE_FRAME, startangle, endangle) radius = math.sqrt(xInvLeft[len(xInvLeft) - 1]**2 + yInvLeft[len(xInvLeft) - 1]**2) status.updateStatus("Defining addendum arc") arcAngle = sign * (math.atan( yInvLeft[len(xInvLeft) - 1] / xInvLeft[len(xInvLeft) - 1]) * 180 / math.pi) startangle = arcAngle endangle = -arcAngle status.updateStatus("Drafting addendum arc") arc = Draft.makeCircle(radius, PLACEMENT, WIRE_FRAME, startangle, endangle) status.updateStatus("Generating hob geometry") hobWire, deletedFeatures=Draft.upgrade([arc,lineRight,lineLeft,lineClearance,\ InvRight,InvLeft,filletRight,filletLeft],DELETE) status.updateStatus("Generating hob face") hobFace, deletedFeatures = Draft.upgrade(hobWire, DELETE) return hobFace[0]
#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 export_faces(filename, isDiel=False, name="", showNormals=False, folder=DEF_FOLDER): '''export faces in FasterCap format as conductor or dielectric interface The function operates on the selection. The selection can be a face, a compound or a solid. 'filename' is the name of the export file 'isDiel' specifies if the mesh is a dielectric, so the function will add a reference point to each panel to indicate which is the external side (outside) 'name' is the name of the conductor created in the file. If not specified, defaults to the label of the first element in the selection set 'showNormals' will add a compound object composed by a set of arrows showing the normal direction for each panel 'folder' is the folder in which 'filename' will be saved Example: export_faces("mymesh.txt", folder="C:/temp") ''' # get selection sel = FreeCADGui.Selection.getSelection() # if no valid mesh was passed if sel == None: return if name == "": condName = sel[0].Label.replace(" ", "_") else: condName = name # scan objects in selection and extract all faces faces = [] facets = [] for obj in sel: if obj.TypeId == "Mesh::Feature": facets.extend(obj.Mesh.Facets) else: if obj.Shape.ShapeType == "Face": faces.append(obj.Shape) elif obj.Shape.ShapeType == "Compound" or obj.Shape.ShapeType == "Solid": faces.extend(obj.Shape.Faces) # scan faces and find out which faces have more than 4 vertexes # TBD warning: should mesh also curve faces facesComplex = [x for x in faces if len(x.Vertexes) >= 5] facesSimple = [x for x in faces if len(x.Vertexes) < 5] # mesh complex faces doc = FreeCAD.ActiveDocument for face in facesComplex: mesh = doc.addObject("Mesh::Feature", "Mesh") mesh.Mesh = MeshPart.meshFromShape(Shape=face, Fineness=0, SecondOrder=0, Optimize=1, AllowQuad=0) facets.extend(mesh.Mesh.Facets) # now we have faces and facets. Uniform all panels = [] for face in facesSimple: sortEdges = DraftGeomUtils.sortEdges(face.Edges) # Point of a Vertex is a Vector, as well as Face.normalAt() points = [x.Vertexes[0].Point for x in sortEdges] panels.append([points, face.normalAt(0, 0)]) for facet in facets: points = [Vector(x) for x in facet.Points] panels.append([points, Vector(facet.Normal)]) if not os.path.isdir(folder): os.mkdir(folder) with open(folder + os.sep + filename, 'w') as fid: # write the preamble if isDiel == True: fid.write( "0 dielectric definition file for the following objects\n") else: fid.write( "0 conductor definition file for the following objects\n") for obj in sel: fid.write("* - " + obj.Label + "\n") fid.write("* created using FreeCAD's ElectroMagnetic workbench\n") fid.write( "* see http://www.freecad.org and http://www.fastfieldsolvers.com\n\n" ) arrows = [] # export faces for panel in panels: pointsNum = len(panel[0]) if pointsNum == 3: fid.write("T " + condName) elif pointsNum == 4: fid.write("Q " + condName) else: FreeCAD.Console.PrintMessage( "Unforseen number of panel vertexes: " + pointsNum + ", skipping panel") continue center = Vector(0.0, 0.0, 0.0) avgSideLen = 0.0 for j, vertex in enumerate(panel[0]): fid.write(" ") for i in range(3): fid.write(" " + str(vertex[i])) if isDiel == True or showNormals == True: # 'point' is a tuple, transform in vector center = center + vertex # get side length side = panel[0][(j + 1) % 3] - vertex avgSideLen += side.Length if isDiel == True or showNormals == True: # calculate the reference point # (there should be a better way to divide a vector by a scalar..) center.multiply(1.0 / pointsNum) # and now move along the normal, proportional to the average facet dimension scaledNormal = panel[1] scaledNormal.multiply(avgSideLen / pointsNum) refpoint = center + scaledNormal if isDiel == True: fid.write(" ") for i in range(3): fid.write(" " + str(refpoint[i])) fid.write("\n") if showNormals == True: arrows.append(make_arrow(center, refpoint)) fid.closed if showNormals == True: # add the vector normals visualization to the view # Note: could also use Part.show(normals) but in this case we could # not give the (permanent) name to the object, only change the label afterwards normals = Part.makeCompound(arrows) normalobj = FreeCAD.ActiveDocument.addObject("Part::Feature", "Normals") normalobj.Shape = normals
FreeCAD.newDocument(DOC_NAME) FreeCAD.setActiveDocument(DOC_NAME) DOC = FreeCAD.activeDocument() else: clear_doc() # EPS= tolerance to use to cut the parts EPS = 0.10 EPS_C = EPS * -0.5 # part_steel_box_tube_for_support_horizontal_generator h = 50 l = 50 L = 420 + 350 + 293 + 257 e = 3 part_steel_box_tube_for_support_horizontal_generator = Part.makeBox(L, h, l) # Cut part_steel_box_tube_for_support_horizontal_generator by box_1 box_1 = Part.makeBox(L, h - e*2, l - e*2) box_1_vector = FreeCAD.Vector(0, e, e) box_1.translate(box_1_vector) part_steel_box_tube_for_support_horizontal_generator = part_steel_box_tube_for_support_horizontal_generator.cut(box_1) Part.show(part_steel_box_tube_for_support_horizontal_generator) DOC.recompute() __objs__ = [] __objs__.append(FreeCAD.getDocument("part_steel_box_tube_for_support_horizontal_generator").getObject("Shape"))
def AddArc(self, x1, z1, x2, z2): midPoint = FreeCAD.Base.Vector(x1, 0, z1) endPoint = FreeCAD.Base.Vector(x2, 0, z2) self.edges.append( Part.Arc(self.lastPoint, midPoint, endPoint).toShape()) self.lastPoint = endPoint
def asLine(self): return Part.LineSegment(self.Start, self.End)
def makeUShapeRebar(f_cover, b_cover, r_cover, l_cover, diameter, t_cover, rounding, amount_spacing_check, amount_spacing_value, orientation="Bottom", structure=None, facename=None): """ makeUShapeRebar(FrontCover, BottomCover, RightCover, LeftCover, Diameter, Topcover, Rounding, AmountSpacingCheck, AmountSpacingValue, Orientation, Structure, Facename): Adds the U-Shape reinforcement bar to the selected structural object. It takes four different types of orientations as input i.e 'Bottom', 'Top', 'Right', 'Left'. """ if not structure and not facename: selected_obj = FreeCADGui.Selection.getSelectionEx()[0] structure = selected_obj.Object facename = selected_obj.SubElementNames[0] face = structure.Shape.Faces[getFaceNumber(facename) - 1] #StructurePRM = getTrueParametersOfStructure(structure) FacePRM = getParametersOfFace(structure, facename) if not FacePRM: FreeCAD.Console.PrintError( "Cannot identified shape or from which base object sturctural element is derived\n" ) return # Get points of U-Shape rebar points = getpointsOfUShapeRebar(FacePRM, r_cover, l_cover, b_cover, t_cover, orientation) import Part import Arch sketch = FreeCAD.activeDocument().addObject('Sketcher::SketchObject', 'Sketch') sketch.MapMode = "FlatFace" sketch.Support = [(structure, facename)] FreeCAD.ActiveDocument.recompute() sketch.addGeometry(Part.LineSegment(points[0], points[1]), False) sketch.addGeometry(Part.LineSegment(points[1], points[2]), False) import Sketcher sketch.addGeometry(Part.LineSegment(points[2], points[3]), False) if amount_spacing_check: rebar = Arch.makeRebar(structure, sketch, diameter, amount_spacing_value, f_cover) FreeCAD.ActiveDocument.recompute() else: size = (ArchCommands.projectToVector(structure.Shape.copy(), face.normalAt(0, 0))).Length rebar = Arch.makeRebar(structure, sketch, diameter, int((size - diameter) / amount_spacing_value), f_cover) rebar.Rounding = rounding # Adds properties to the rebar object rebar.ViewObject.addProperty( "App::PropertyString", "RebarShape", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Shape of rebar")).RebarShape = "UShapeRebar" rebar.ViewObject.setEditorMode("RebarShape", 2) rebar.addProperty( "App::PropertyDistance", "FrontCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Front cover of rebar")).FrontCover = f_cover rebar.setEditorMode("FrontCover", 2) rebar.addProperty( "App::PropertyDistance", "RightCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Right Side cover of rebar")).RightCover = r_cover rebar.setEditorMode("RightCover", 2) rebar.addProperty( "App::PropertyDistance", "LeftCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Left Side cover of rebar")).LeftCover = l_cover rebar.setEditorMode("LeftCover", 2) rebar.addProperty( "App::PropertyDistance", "BottomCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Bottom cover of rebar")).BottomCover = b_cover rebar.setEditorMode("BottomCover", 2) rebar.addProperty( "App::PropertyBool", "AmountCheck", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Amount radio button is checked")).AmountCheck rebar.setEditorMode("AmountCheck", 2) rebar.addProperty( "App::PropertyDistance", "TopCover", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Top cover of rebar")).TopCover = t_cover rebar.setEditorMode("TopCover", 2) rebar.addProperty( "App::PropertyDistance", "TrueSpacing", "RebarDialog", QT_TRANSLATE_NOOP( "App::Property", "Spacing between of rebars")).TrueSpacing = amount_spacing_value rebar.setEditorMode("TrueSpacing", 2) rebar.addProperty( "App::PropertyString", "Orientation", "RebarDialog", QT_TRANSLATE_NOOP("App::Property", "Shape of rebar")).Orientation = orientation rebar.setEditorMode("Orientation", 2) if amount_spacing_check: rebar.AmountCheck = True else: rebar.AmountCheck = False rebar.TrueSpacing = amount_spacing_value rebar.Label = "UShapeRebar" FreeCAD.ActiveDocument.recompute() return rebar
def getShape(self, obj): "computes a shape from a base shape and/or bounday faces" import Part shape = None faces = [] pl = obj.Placement #print("starting compute") # 1: if we have a base shape, we use it if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.Solids: shape = obj.Base.Shape.copy() shape = shape.removeSplitter() # 2: if not, add all bounding boxes of considered objects and build a first shape if shape: #print("got shape from base object") bb = shape.BoundBox else: bb = None for b in obj.Boundaries: if b[0].isDerivedFrom("Part::Feature"): if not bb: bb = b[0].Shape.BoundBox else: bb.add(b[0].Shape.BoundBox) if not bb: return shape = Part.makeBox(bb.XLength, bb.YLength, bb.ZLength, FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin)) #print("created shape from boundbox") # 3: identifying boundary faces goodfaces = [] for b in obj.Boundaries: if b[0].isDerivedFrom("Part::Feature"): for sub in b[1]: if "Face" in sub: fn = int(sub[4:]) - 1 faces.append(b[0].Shape.Faces[fn]) #print("adding face ",fn," of object ",b[0].Name) #print("total: ", len(faces), " faces") # 4: get cutvolumes from faces cutvolumes = [] for f in faces: f = f.copy() f.reverse() cutface, cutvolume, invcutvolume = ArchCommands.getCutVolume( f, shape) if cutvolume: #print("generated 1 cutvolume") cutvolumes.append(cutvolume.copy()) #Part.show(cutvolume) for v in cutvolumes: #print("cutting") shape = shape.cut(v) # 5: get the final shape if shape: if shape.Solids: #print("setting objects shape") shape = shape.Solids[0] obj.Shape = shape pl = pl.multiply(obj.Placement) obj.Placement = pl if hasattr(obj.Area, "Value"): a = self.getArea(obj) if obj.Area.Value != a: obj.Area = a return print("Arch: error computing space boundary")
def smoothChordCommands(self, bone, inChord, outChord, edge, wire, corner, smooth, color = None): if smooth == 0: PathLog.info(" No smoothing requested") return [ bone.lastCommand, outChord.g1Command() ] d = 'in' refPoint = inChord.Start if smooth == Smooth.Out: d = 'out' refPoint = outChord.End if DraftGeomUtils.areColinear(inChord.asEdge(), outChord.asEdge()): PathLog.info(" straight edge %s" % d) return [ outChord.g1Command() ] pivot = None pivotDistance = 0 PathLog.info("smooth: (%.2f, %.2f)-(%.2f, %.2f)" % (edge.Vertexes[0].Point.x, edge.Vertexes[0].Point.y, edge.Vertexes[1].Point.x, edge.Vertexes[1].Point.y)) for e in wire.Edges: self.dbg.append(e) if type(e.Curve) == Part.LineSegment or type(e.Curve) == Part.Line: PathLog.debug(" (%.2f, %.2f)-(%.2f, %.2f)" % (e.Vertexes[0].Point.x, e.Vertexes[0].Point.y, e.Vertexes[1].Point.x, e.Vertexes[1].Point.y)) else: PathLog.debug(" (%.2f, %.2f)^%.2f" % (e.Curve.Center.x, e.Curve.Center.y, e.Curve.Radius)) for pt in DraftGeomUtils.findIntersection(edge, e, True, findAll=True): if not PathGeom.pointsCoincide(pt, corner) and self.pointIsOnEdge(pt, e): #debugMarker(pt, "candidate-%d-%s" % (self.boneId, d), color, 0.05) PathLog.debug(" -> candidate") distance = (pt - refPoint).Length if not pivot or pivotDistance > distance: pivot = pt pivotDistance = distance else: PathLog.debug(" -> corner intersect") if pivot: #debugCircle(pivot, self.toolRadius, "pivot.%d-%s" % (self.boneId, d), color) pivotEdge = Part.Edge(Part.Circle(pivot, FreeCAD.Vector(0,0,1), self.toolRadius)) t1 = self.findPivotIntersection(pivot, pivotEdge, inChord.asEdge(), inChord.End, d, color) t2 = self.findPivotIntersection(pivot, pivotEdge, outChord.asEdge(), inChord.End, d, color) commands = [] if not PathGeom.pointsCoincide(t1, inChord.Start): PathLog.debug(" add lead in") commands.append(Chord(inChord.Start, t1).g1Command()) if bone.obj.Side == Side.Left: PathLog.debug(" add g3 command") commands.append(Chord(t1, t2).g3Command(pivot)) else: PathLog.debug(" add g2 command center=(%.2f, %.2f) -> from (%2f, %.2f) to (%.2f, %.2f" % (pivot.x, pivot.y, t1.x, t1.y, t2.x, t2.y)) commands.append(Chord(t1, t2).g2Command(pivot)) if not PathGeom.pointsCoincide(t2, outChord.End): PathLog.debug(" add lead out") commands.append(Chord(t2, outChord.End).g1Command()) #debugMarker(pivot, "pivot.%d-%s" % (self.boneId, d), color, 0.2) #debugMarker(t1, "pivot.%d-%s.in" % (self.boneId, d), color, 0.1) #debugMarker(t2, "pivot.%d-%s.out" % (self.boneId, d), color, 0.1) return commands PathLog.info(" no pivot found - straight command") return [ inChord.g1Command(), outChord.g1Command() ]