def _svg_dimension(obj, plane, scale, linewidth, fontsize, stroke, pointratio, techdraw, rotation): """Return the SVG representation of a linear dimension.""" if not App.GuiUp: _wrn("'{}': SVG can only be generated " "in GUI mode".format(obj.Label)) return "" if not hasattr(obj.ViewObject, "Proxy") or not obj.ViewObject.Proxy: _err("'{}': doesn't have Proxy, " "SVG cannot be generated".format(obj.Label)) return "" vobj = obj.ViewObject prx = vobj.Proxy if not hasattr(prx, "p1"): _err("'{}': doesn't have points, " "SVG cannot be generated".format(obj.Label)) return "" ts = len(prx.string) * vobj.FontSize.Value / 4.0 rm = (prx.p3 - prx.p2).Length/2.0 - ts _diff32 = prx.p3 - prx.p2 _diff23 = prx.p2 - prx.p3 _v32 = DraftVecUtils.scaleTo(_diff32, rm) _v23 = DraftVecUtils.scaleTo(_diff23, rm) p2a = get_proj(prx.p2 + _v32, plane) p2b = get_proj(prx.p3 + _v23, plane) p1 = get_proj(prx.p1, plane) p2 = get_proj(prx.p2, plane) p3 = get_proj(prx.p3, plane) p4 = get_proj(prx.p4, plane) tbase = get_proj(prx.tbase, plane) r = prx.textpos.rotation.getValue().getValue() _rv = App.Rotation(r[0], r[1], r[2], r[3]) rv = _rv.multVec(App.Vector(1, 0, 0)) angle = -DraftVecUtils.angle(get_proj(rv, plane)) # angle = -DraftVecUtils.angle(p3.sub(p2)) svg = '' nolines = False if hasattr(vobj, "ShowLine"): if not vobj.ShowLine: nolines = True # drawing lines if not nolines: svg += '<path ' if vobj.DisplayMode == "2D": tangle = angle if tangle > math.pi/2: tangle = tangle-math.pi # elif (tangle <= -math.pi/2) or (tangle > math.pi/2): # tangle = tangle + math.pi if rotation != 0: # print("dim: tangle:", tangle, # " rot: ", rotation, # " text: ", prx.string) if abs(tangle + math.radians(rotation)) < 0.0001: tangle += math.pi _v = App.Vector(0, 2.0/scale, 0) _rot = DraftVecUtils.rotate(_v, tangle) tbase = tbase + _rot if not nolines: svg += 'd="M ' + str(p1.x) + ' ' + str(p1.y) + ' ' svg += 'L ' + str(p2.x) + ' ' + str(p2.y) + ' ' svg += 'L ' + str(p3.x) + ' ' + str(p3.y) + ' ' svg += 'L ' + str(p4.x) + ' ' + str(p4.y) + '" ' else: tangle = 0 if rotation != 0: tangle = -math.radians(rotation) tbase = tbase + App.Vector(0, -2.0/scale, 0) if not nolines: svg += 'd="M ' + str(p1.x) + ' ' + str(p1.y) + ' ' svg += 'L ' + str(p2.x) + ' ' + str(p2.y) + ' ' svg += 'L ' + str(p2a.x) + ' ' + str(p2a.y) + ' ' svg += 'M ' + str(p2b.x) + ' ' + str(p2b.y) + ' ' svg += 'L ' + str(p3.x) + ' ' + str(p3.y) + ' ' svg += 'L ' + str(p4.x) + ' ' + str(p4.y) + '" ' if not nolines: svg += 'fill="none" stroke="' svg += stroke + '" ' svg += 'stroke-width="' + str(linewidth) + ' px" ' svg += 'style="stroke-width:' + str(linewidth) svg += ';stroke-miterlimit:4;stroke-dasharray:none" ' svg += 'freecad:basepoint1="'+str(p1.x)+' '+str(p1.y)+'" ' svg += 'freecad:basepoint2="'+str(p4.x)+' '+str(p4.y)+'" ' svg += 'freecad:dimpoint="'+str(p2.x)+' '+str(p2.y)+'"' svg += '/>\n' # drawing dimension and extension lines overshoots if hasattr(vobj, "DimOvershoot") and vobj.DimOvershoot.Value: shootsize = vobj.DimOvershoot.Value/pointratio svg += get_overshoot(p2, shootsize, stroke, linewidth, angle) svg += get_overshoot(p3, shootsize, stroke, linewidth, angle + math.pi) if hasattr(vobj, "ExtOvershoot") and vobj.ExtOvershoot.Value: shootsize = vobj.ExtOvershoot.Value/pointratio shootangle = -DraftVecUtils.angle(p1 - p2) svg += get_overshoot(p2, shootsize, stroke, linewidth, shootangle) svg += get_overshoot(p3, shootsize, stroke, linewidth, shootangle) # drawing arrows if hasattr(vobj, "ArrowType"): arrowsize = vobj.ArrowSize.Value/pointratio if hasattr(vobj, "FlipArrows"): if vobj.FlipArrows: angle = angle + math.pi svg += get_arrow(obj, vobj.ArrowType, p2, arrowsize, stroke, linewidth, angle) svg += get_arrow(obj, vobj.ArrowType, p3, arrowsize, stroke, linewidth, angle + math.pi) # drawing text svg += svgtext.get_text(plane, techdraw, stroke, fontsize, vobj.FontName, tangle, tbase, prx.string) return svg
def CreateFromTemplate(job, template): if template.get('version') and 1 == int(template['version']): stockType = template.get('create') if stockType: placement = None posX = template.get('posX') posY = template.get('posY') posZ = template.get('posZ') rotX = template.get('rotX') rotY = template.get('rotY') rotZ = template.get('rotZ') rotW = template.get('rotW') if posX is not None and posY is not None and posZ is not None and rotX is not None and rotY is not None and rotZ is not None and rotW is not None: pos = FreeCAD.Vector(float(posX), float(posY), float(posZ)) rot = FreeCAD.Rotation(float(rotX), float(rotY), float(rotZ), float(rotW)) placement = FreeCAD.Placement(pos, rot) elif posX is not None or posY is not None or posZ is not None or rotX is not None or rotY is not None or rotZ is not None or rotW is not None: PathLog.warning( translate( 'PathStock', 'Corrupted or incomplete placement information in template - ignoring' )) if stockType == StockType.FromBase: xneg = template.get('xneg') xpos = template.get('xpos') yneg = template.get('yneg') ypos = template.get('ypos') zneg = template.get('zneg') zpos = template.get('zpos') neg = None pos = None if xneg is not None and xpos is not None and yneg is not None and ypos is not None and zneg is not None and zpos is not None: neg = FreeCAD.Vector( FreeCAD.Units.Quantity(xneg).Value, FreeCAD.Units.Quantity(yneg).Value, FreeCAD.Units.Quantity(zneg).Value) pos = FreeCAD.Vector( FreeCAD.Units.Quantity(xpos).Value, FreeCAD.Units.Quantity(ypos).Value, FreeCAD.Units.Quantity(zpos).Value) elif xneg is not None or xpos is not None or yneg is not None or ypos is not None or zneg is not None or zpos is not None: PathLog.error( translate( 'PathStock', 'Corrupted or incomplete specification for creating stock from base - ignoring extent' )) return CreateFromBase(job, neg, pos, placement) if stockType == StockType.CreateBox: PathLog.track(' create box') length = template.get('length') width = template.get('width') height = template.get('height') extent = None if length is not None and width is not None and height is not None: PathLog.track(' have extent') extent = FreeCAD.Vector( FreeCAD.Units.Quantity(length).Value, FreeCAD.Units.Quantity(width).Value, FreeCAD.Units.Quantity(height).Value) elif length is not None or width is not None or height is not None: PathLog.error( translate( 'PathStock', 'Corrupted or incomplete size for creating a stock box - ignoring size' )) else: PathLog.track( " take placement (%s) and extent (%s) from model" % (placement, extent)) return CreateBox(job, extent, placement) if stockType == StockType.CreateCylinder: radius = template.get('radius') height = template.get('height') if radius is not None and height is not None: pass elif radius is not None or height is not None: radius = None height = None PathLog.error( translate( 'PathStock', 'Corrupted or incomplete size for creating a stock cylinder - ignoring size' )) return CreateCylinder(job, radius, height, placement) PathLog.error( translate('PathStock', 'Unsupported stock type named {}').format(stockType)) else: PathLog.error( translate('PathStock', 'Unsupported PathStock template version {}').format( template.get('version'))) return None
EPS_C = EPS * (-0.5) cote_maximal = 2 + 8 + 8 + 8 + 86 + 8 + 8 + 8 + 2 hauteur_maximal = 2 # part_support_laser_cutting part_support_laser_cutting = Part.makeCylinder(cote_maximal/2, hauteur_maximal) # holes for fixing the electrodes degre = 180 for i in range(int(360/degre)): hole = Part.makeCylinder(4, hauteur_maximal) radius = 50/2 - 4 - 4 alpha=(i*degre*math.pi)/180 hole_vector = FreeCAD.Vector(radius*math.cos(alpha), radius*math.sin(alpha), 0) hole.translate(hole_vector) part_support_laser_cutting = part_support_laser_cutting.cut(hole) # holes for reducing the cost degre = 15 for i in range(int(360/degre)): hole = Part.makeCylinder(4, hauteur_maximal) radius = 86/2 + 8 + 4 alpha=(i*degre*math.pi)/180 hole_vector = FreeCAD.Vector(radius*math.cos(alpha), radius*math.sin(alpha), 0) hole.translate(hole_vector) part_support_laser_cutting = part_support_laser_cutting.cut(hole) Part.show(part_support_laser_cutting)
def settarget4(self): '''rotate neighbors''' print "settarget 4" dok = self.helperDok() pl = len(self.points) self.dial.setMaximum(pl - 1) pos = self.dial.value() if pos == 0: lpos = pl - 1 else: lpos = pos - 1 if pos == pl - 1: rpos = 0 else: rpos = pos + 1 # print ('pl,pos,lpos,rpos',pl,pos,lpos,rpos) t = self.points[pos] t1 = self.points[pos - 1] t2 = self.points[pos + 1] dt1 = t1 - t dt2 = t2 - t print(dt1, dt2) # rotation p2 = FreeCAD.Placement() #p2.Rotation=FreeCAD.Rotation(FreeCAD.Vector(0,0,1),za).multiply(FreeCAD.Rotation(FreeCAD.Vector(0,1,0),ya).multiply(FreeCAD.Rotation(FreeCAD.Vector(1,0,0),xa))) ef = self.ef kr = ef.mouseWheel * FreeCAD.ParamGet( 'User parameter:Plugins/nurbs').GetFloat("MoveWheelStep", 1) p2.Rotation = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), kr) print(t1, t2) ph = FreeCAD.Placement() ph.Base = dt1 drt1 = p2.multiply(ph).Base t1 = t + drt1 ph = FreeCAD.Placement() ph.Base = dt2 drt2 = p2.multiply(ph).Base t2 = t + drt2 print(t1, t2) print "kilo" self.target(dok, coordlist=[t1, t, t2]) # try: dok.Sphere # except: # s=dok.addObject("Part::Sphere","Sphere") # s.Radius=10000000 # s.ViewObject.Selectable=False # s.ViewObject.ShapeColor=(1.,1.,1.) # s.ViewObject.DisplayMode = u"Shaded" # s.ViewObject.DisplayMode = u"Shaded" # create or get traget curve try: bb = dok.TargetCurve bax = dok.TargetExtra except: bb = dok.addObject('Part::Feature', 'TargetCurve') bax = dok.addObject('Part::Feature', 'TargetExtra') bax.ViewObject.LineColor = (1.0, 1.0, 0.0) pp = self.points pp2 = pp[:pos - 1] + [t1, t, t2] + pp[pos + 2:] print("lnes", len(pp), len(pp2)) # bspline curve bs = dok.BSpline.Shape.Edge1.Curve.copy() bs.setPole(pos, FreeCAD.Vector(t1)) bs.setPole(pos + 1, FreeCAD.Vector(t)) bs.setPole(pos + 2, FreeCAD.Vector(t2)) dok.BSpline.Shape = bs.toShape() sss = bs.toShape() # pole polygon pol = Part.makePolygon(pp2 + [pp2[0]]) # bb.Shape=pol pp3 = [] ppax = [] print "wwww" if self.source == 'Backbone': xV = FreeCAD.Vector(100, 0, 0) yV = FreeCAD.Vector(0, 100, 0) zV = FreeCAD.Vector(0, 0, 141) source = self.getsource() needle = source.InList[0] curvea, bba, scaler, twister = needle.Proxy.Model() for i, p in enumerate(pp2): # print (i,twister[i],scaler[i]) [xa, ya, za] = twister[i] if pos == i: xa += self.rotx ya += self.roty za += self.rotz if pos == i: xa = self.rotx ya = self.roty za = self.rotz p2 = FreeCAD.Placement() p2.Rotation = FreeCAD.Rotation(FreeCAD.Vector( 0, 0, 1), za).multiply( FreeCAD.Rotation(FreeCAD.Vector(0, 1, 0), ya).multiply( FreeCAD.Rotation(FreeCAD.Vector(1, 0, 0), xa))) ph = FreeCAD.Placement() ph.Base = xV xR = p2.multiply(ph).Base ph = FreeCAD.Placement() ph.Base = yV yR = p2.multiply(ph).Base ph = FreeCAD.Placement() ph.Base = zV zR = p2.multiply(ph).Base p = FreeCAD.Vector(p) if 1: pp = Part.makePolygon([p, p + xR, p + xR + yR, p]) ps = Part.Face(pp) ppax.append(ps) pp = Part.makePolygon([p, p + yR, p + xR + yR, p]) ppax.append(Part.Face(pp)) pp = Part.makePolygon([p, p + zR, p + xR + yR, p]) ppax.append(Part.Face(pp)) # all together bb.Shape = Part.Compound([pol]) if ppax <> []: bax.Shape = Part.Compound(ppax + [bs.toShape(), sss]) dok.recompute() bb.ViewObject.LineColor = (1.0, 0.6, .0) bb.ViewObject.LineWidth = 1 bb.ViewObject.PointColor = (.8, 0.4, .0) bb.ViewObject.PointSize = 8 bax.ViewObject.Selectable = False col = [] for i in range(len(bax.Shape.Faces)): tt = i % 3 if tt == 0: col.append((1., 0., 0.)) elif tt == 1: col.append((0., 1., 0.)) else: col.append((0., 0., 1.)) bax.ViewObject.DiffuseColor = col
def addLine(start, angle, length): result = App.Vector(start.x + length * math.cos(angle), start.y + length * math.sin(angle), start.z) return result
def execute(self, obj): "creates the structure shape" import Part, DraftGeomUtils if self.clone(obj): return normal, length, width, height = self.getDefaultValues(obj) # creating base shape pl = obj.Placement base = None if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.isNull(): return if not obj.Base.Shape.isValid(): if not obj.Base.Shape.Solids: # let pass invalid objects if they have solids... return if hasattr(obj, "Tool"): if obj.Tool: try: base = obj.Tool.Shape.copy().makePipe( obj.Base.Shape.copy()) except Part.OCCError: FreeCAD.Console.PrintError( translate( "Arch", "Error: The base shape couldn't be extruded along this tool object" )) return if not base: if not height: return if obj.Normal == Vector(0, 0, 0): if len(obj.Base.Shape.Faces) > 0: normal = obj.Base.Shape.Faces[0].normalAt(.5, .5) else: normal = DraftGeomUtils.getNormal(obj.Base.Shape) if not normal: normal = FreeCAD.Vector(0, 0, 1) #p = FreeCAD.Placement(obj.Base.Placement) #normal = p.Rotation.multVec(normal) else: normal = Vector(obj.Normal) normal = normal.multiply(height) base = obj.Base.Shape.copy() if base.Solids: pass elif base.Faces: base = base.extrude(normal) elif (len(base.Wires) == 1): if base.Wires[0].isClosed(): try: base = Part.Face(base.Wires[0]) base = base.extrude(normal) except Part.OCCError: FreeCAD.Console.PrintError( obj.Label + " : " + str( translate( "Arch", "Unable to extrude the base shape\n" ))) return elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids and ( not sh.isNull()): base = sh else: FreeCAD.Console.PrintWarning( str( translate( "Arch", "This mesh is an invalid solid"))) obj.Base.ViewObject.show() else: base = self.getProfiles(obj) if base: if length > height: normal = normal.multiply(length) else: normal = normal.multiply(height) base = Part.Face(base[0]) base = base.extrude(normal) base = self.processSubShapes(obj, base, pl) self.applyShape(obj, base, pl)
def update(self): mode = self.imode print("focus", focus()) ef = self.ef print("val,x,y,k", ef.mouseWheel, ef.posx, ef.posy, ef.key) #hilfsfenster hd = self.helperDok() # move-mode if mode == 0 or mode == -1: try: bb = App.activeDocument().BSpline pos = self.dial.value() try: t = hd.Target.Shape.Vertex1.Point except: t = FreeCAD.Vector() print("Target", t) pp = bb.Shape.Edge1.Curve.getPoles() points = pp if pos > 0: pp2 = pp[:pos] + [t] + pp[pos + 1:] else: pp2 = [t] + pp[pos + 1:] bs = bb.Shape.Edge1.Curve.copy() bs.setPole(pos + 1, FreeCAD.Vector(t)) bb.Shape = bs.toShape() points = pp2 except: print "ExCEPT - need to create helper BSpline" src = self.getsource() points = src.Shape.Edge1.Curve.getPoles() mybsc = App.activeDocument().addObject('Part::Feature', 'BSpline') mybsc.Shape = src.Shape mybsc.ViewObject.Selectable = False Gui.activeDocument().activeView().viewAxonometric() Gui.SendMsgToActiveView("ViewFit") bb = App.activeDocument().ActiveObject Gui.Selection.addSelection(bb) self.points = points self.setcursor() #reset diff self.ef.mouseWheel = 0 self.settarget() return if mode == 1: bb = App.activeDocument().BSpline pos = self.dial.value() # try: # t=hd.Target.Shape.Point # except: # t=FreeCAD.Vector() t1 = hd.Target.Shape.Vertex1.Point t = hd.Target.Shape.Vertex2.Point t2 = hd.Target.Shape.Vertex3.Point pp = bb.Shape.Edge1.Curve.getPoles() points = pp [pi1, pi, pi2] = liposs(points, pos - 1, pos + 1) pp2 = pp pp2[pi1] = t1 pp2[pi2] = t2 pp2[pi] = t print("len pp, pp2", len(pp), len(pp2)) bs = bb.Shape.Edge1.Curve.copy() bs.setPole(pi1 + 1, FreeCAD.Vector(t1)) bs.setPole(pi + 1, FreeCAD.Vector(t)) bs.setPole(pi2 + 1, FreeCAD.Vector(t2)) bb = hd.TargetCurve bb.Shape = bs.toShape() points = pp2 Gui.Selection.addSelection(bb) self.points = points self.setcursor() #reset diff self.ef.mouseWheel = 0 self.settarget() return #----------------------- elif mode == 2: faktor = self.dials.value() self.dials.setValue(0) print("sharpen.", faktor) pos = self.dial.value() dok = self.helperDok() pp = self.points t1 = pp[pos - 1] * (1 - 0.01 * faktor) + pp[pos] * 0.01 * faktor if pos == len(pp) - 1: t2 = pp[0] * (1 - 0.01 * faktor) + pp[pos] * 0.01 * faktor else: t2 = pp[pos + 1] * (1 - 0.01 * faktor) + pp[pos] * 0.01 * faktor if pos == len(pp) - 1: pp2 = pp[1:pos - 1] + [t1, pp[pos], t2] # +pp[pos+2:] elif pos > 0: pp2 = pp[:pos - 1] + [t1, pp[pos], t2] + pp[pos + 2:] else: pp2 = [t1, pp[pos], t2] + pp[2:-1] bb = dok.TargetCurve # bspline curve bs = dok.BSpline.Shape.Edge1.Curve.copy() if pos == 0: posa = len(pp) else: posa = pos bs.setPole(posa, FreeCAD.Vector(t1)) if pos == len(pp) - 1: posb = 1 else: posb = pos + 2 bs.setPole(posb, FreeCAD.Vector(t2)) dok.BSpline.Shape = bs.toShape() pol = Part.makePolygon(pp2 + [pp2[0]]) bb.Shape = Part.Compound([pol]) points = pp2 elif mode == 4: print "rotate NEIOGHJHGJH" #----------------------- elif mode == 3: # colinear neighbors faktor = self.dials.value() #faktor= 100 self.dials.setValue(0) print("update sharpen.", faktor) pos = self.dial.value() dok = self.helperDok() pp = self.points if pos == len(pp) - 1: t2 = pp[pos] + (pp[0] - pp[pos - 1]) * (1 - 0.01 * faktor) t1 = pp[pos] - (pp[0] - pp[pos - 1]) * (1 - 0.01 * faktor) else: t2 = pp[pos] + (pp[pos + 1] - pp[pos - 1]) * (1 - 0.01 * faktor) t1 = pp[pos] - (pp[pos + 1] - pp[pos - 1]) * (1 - 0.01 * faktor) # if pos==len(pp)-1: # t2=pp[0]*(1-0.01*faktor)+pp[pos]*0.01*faktor # else: # t2=pp[pos]+(pp[pos+1]-pp[pos-1])*(1-0.01*faktor) # t1=pp[pos]-(pp[pos+1]-pp[pos-1])*(1-0.01*faktor) if pos == len(pp) - 1: pp2 = pp[1:pos - 1] + [t1, pp[pos], t2] # +pp[pos+2:] elif pos > 0: pp2 = pp[:pos - 1] + [t1, pp[pos], t2] + pp[pos + 2:] else: pp2 = [t1, pp[pos], t2] + pp[2:-1] bb = dok.TargetCurve # bspline curve bs = dok.BSpline.Shape.Edge1.Curve.copy() if pos == 0: posa = len(pp) else: posa = pos bs.setPole(posa, FreeCAD.Vector(t1)) if pos == len(pp) - 1: posb = 1 else: posb = pos + 2 bs.setPole(posb, FreeCAD.Vector(t2)) dok.BSpline.Shape = bs.toShape() pol = Part.makePolygon(pp2 + [pp2[0]]) bb.Shape = Part.Compound([pol]) points = pp2 #---------------------- Gui.Selection.addSelection(bb) self.points = points self.setcursor() #reset diff self.ef.mouseWheel = 0 self.settarget() return else: print "!!!!!!!!!!!!!! no imp for this mode!!"
def getCutVolume(cutplane, shapes): """getCutVolume(cutplane,shapes): returns a cut face and a cut volume from the given shapes and the given cutting plane""" import Part placement = FreeCAD.Placement(cutplane.Placement) # building boundbox bb = shapes[0].BoundBox for sh in shapes[1:]: bb.add(sh.BoundBox) bb.enlarge(1) um = vm = wm = 0 ax = placement.Rotation.multVec(FreeCAD.Vector(0, 0, 1)) u = placement.Rotation.multVec(FreeCAD.Vector(1, 0, 0)) v = placement.Rotation.multVec(FreeCAD.Vector(0, 1, 0)) if not bb.isCutPlane(placement.Base, ax): FreeCAD.Console.PrintMessage( str(translate("Arch", "No objects are cut by the plane"))) return None, None, None else: corners = [ FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin), FreeCAD.Vector(bb.XMin, bb.YMax, bb.ZMin), FreeCAD.Vector(bb.XMax, bb.YMin, bb.ZMin), FreeCAD.Vector(bb.XMax, bb.YMax, bb.ZMin), FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMax), FreeCAD.Vector(bb.XMin, bb.YMax, bb.ZMax), FreeCAD.Vector(bb.XMax, bb.YMin, bb.ZMax), FreeCAD.Vector(bb.XMax, bb.YMax, bb.ZMax) ] for c in corners: dv = c.sub(placement.Base) um1 = DraftVecUtils.project(dv, u).Length um = max(um, um1) vm1 = DraftVecUtils.project(dv, v).Length vm = max(vm, vm1) wm1 = DraftVecUtils.project(dv, ax).Length wm = max(wm, wm1) p1 = FreeCAD.Vector(-um, vm, 0) p2 = FreeCAD.Vector(um, vm, 0) p3 = FreeCAD.Vector(um, -vm, 0) p4 = FreeCAD.Vector(-um, -vm, 0) cutface = Part.makePolygon([p1, p2, p3, p4, p1]) cutface = Part.Face(cutface) cutface.Placement = placement cutnormal = DraftVecUtils.scaleTo(ax, wm) cutvolume = cutface.extrude(cutnormal) cutnormal = DraftVecUtils.neg(cutnormal) invcutvolume = cutface.extrude(cutnormal) return cutface, cutvolume, invcutvolume
def computeAreas(self,obj): if not obj.Shape: return if obj.Shape.isNull(): return if not obj.Shape.isValid(): return if not obj.Shape.Faces: return if not hasattr(obj,"Perimeter"): # check we have a latest version site return if not obj.Terrain: return # compute area fset = [] for f in obj.Shape.Faces: if f.normalAt(0,0).getAngle(FreeCAD.Vector(0,0,1)) < 1.5707: fset.append(f) if fset: import Drawing,Part pset = [] for f in fset: try: pf = Part.Face(Part.Wire(Drawing.project(f,FreeCAD.Vector(0,0,1))[0].Edges)) except Part.OCCError: # error in computing the area. Better set it to zero than show a wrong value if obj.ProjectedArea.Value != 0: print("Error computing areas for ",obj.Label) obj.ProjectedArea = 0 else: pset.append(pf) if pset: self.flatarea = pset.pop() for f in pset: self.flatarea = self.flatarea.fuse(f) self.flatarea = self.flatarea.removeSplitter() if obj.ProjectedArea.Value != self.flatarea.Area: obj.ProjectedArea = self.flatarea.Area # compute perimeter lut = {} for e in obj.Shape.Edges: lut.setdefault(e.hashCode(),[]).append(e) l = 0 for e in lut.values(): if len(e) == 1: # keep only border edges l += e[0].Length if l: if obj.Perimeter.Value != l: obj.Perimeter = l # compute volumes if obj.Terrain.Shape.Solids: shapesolid = obj.Terrain.Shape.copy() else: shapesolid = obj.Terrain.Shape.extrude(obj.ExtrusionVector) addvol = 0 subvol = 0 for sub in obj.Subtractions: subvol += sub.Shape.common(shapesolid).Volume for sub in obj.Additions: addvol += sub.Shape.cut(shapesolid).Volume if obj.SubtractionVolume.Value != subvol: obj.SubtractionVolume = subvol if obj.AdditionVolume.Value != addvol: obj.AdditionVolume = addvol
def execute(self, obj): PathLog.track() output = "" if obj.Comment != "": output += '(' + str(obj.Comment) + ')\n' toolLoad = obj.ToolController if toolLoad is None or toolLoad.ToolNumber == 0: FreeCAD.Console.PrintError( "No Tool Controller is selected. We need a tool to build a Path." ) return else: self.vertFeed = toolLoad.VertFeed.Value self.horizFeed = toolLoad.HorizFeed.Value self.vertRapid = toolLoad.VertRapid.Value self.horizRapid = toolLoad.HorizRapid.Value tool = toolLoad.Proxy.getTool(toolLoad) if not tool or tool.Diameter == 0: FreeCAD.Console.PrintError( "No Tool found or diameter is zero. We need a tool to build a Path." ) return else: self.radius = tool.Diameter / 2 if not obj.Base: parentJob = PathUtils.findParentJob(obj) if parentJob is None: return baseobject = parentJob.Base if baseobject is None: return holes = self.findHoles(obj, baseobject.Shape) for hole in holes: self.addDrillableLocation(obj, baseobject, hole[0]) locations = [] output = "(Begin Drilling)\n" if obj.Base: for loc in obj.Base: #print loc for sub in loc[1]: #locations.append(self._findDrillingVector(loc)) if "Face" in sub or "Edge" in sub: s = getattr(loc[0].Shape, sub) else: s = loc[0].Shape if s.ShapeType in ['Wire', 'Edge']: X = s.Edges[0].Curve.Center.x Y = s.Edges[0].Curve.Center.y Z = s.Edges[0].Curve.Center.z elif s.ShapeType in ['Vertex']: X = s.Point.x Y = s.Point.y Z = s.Point.z elif s.ShapeType in ['Face']: #if abs(s.normalAt(0, 0).z) == 1: # horizontal face X = s.CenterOfMass.x Y = s.CenterOfMass.y Z = s.CenterOfMass.z locations.append(FreeCAD.Vector(X, Y, Z)) output += "G90 G98\n" # rapid to clearance height output += "G0 Z" + str( obj.ClearanceHeight.Value) + "F " + PathUtils.fmt( self.vertRapid) + "\n" # rapid to first hole location, with spindle still retracted: p0 = locations[0] output += "G0 X" + fmt(p0.x) + " Y" + fmt( p0.y) + "F " + PathUtils.fmt(self.horizRapid) + "\n" # move tool to clearance plane output += "G0 Z" + fmt( obj.ClearanceHeight.Value) + "F " + PathUtils.fmt( self.vertRapid) + "\n" pword = "" qword = "" if obj.PeckDepth.Value > 0: cmd = "G83" qword = " Q" + fmt(obj.PeckDepth.Value) elif obj.DwellTime > 0: cmd = "G82" pword = " P" + fmt(obj.DwellTime) else: cmd = "G81" for p in locations: output += cmd + \ " X" + fmt(p.x) + \ " Y" + fmt(p.y) + \ " Z" + fmt(obj.FinalDepth.Value) + qword + pword + \ " R" + str(obj.RetractHeight.Value) + \ " F" + str(self.vertFeed) + "\n" \ output += "G80\n" if obj.Active: path = Path.Path(output) obj.Path = path obj.ViewObject.Visibility = True else: path = Path.Path("(inactive operation)") obj.Path = path obj.ViewObject.Visibility = False
def generateConstraintAreas(self, doc, layerNumber, grp, layerName, layerColor, layerTransparent): typeL = PCBconf.softLayers[self.databaseType][layerNumber]['ltype'] for i in self.wersjaFormatu.getConstraintAreas(layerNumber): ser = doc.addObject('Sketcher::SketchObject', "Sketch_{0}".format(layerName)) ser.ViewObject.Visibility = False # if i[0] == 'rect': try: height = i[5] except: height = 0 x1 = i[1] y1 = i[2] x2 = i[3] y2 = i[2] x3 = i[3] y3 = i[4] x4 = i[1] y4 = i[4] try: if i[6] != 0: xs = (i[1] + i[3]) / 2. ys = (i[2] + i[4]) / 2. mat = mathFunctions() (x1, y1) = mat.obrocPunkt2([x1, y1], [xs, ys], i[6]) (x2, y2) = mat.obrocPunkt2([x2, y2], [xs, ys], i[6]) (x3, y3) = mat.obrocPunkt2([x3, y3], [xs, ys], i[6]) (x4, y4) = mat.obrocPunkt2([x4, y4], [xs, ys], i[6]) except: pass ser.addGeometry( Part.LineSegment(FreeCAD.Vector(x1, y1, 0), FreeCAD.Vector(x2, y2, 0))) ser.addGeometry( Part.LineSegment(FreeCAD.Vector(x2, y2, 0), FreeCAD.Vector(x3, y3, 0))) ser.addGeometry( Part.LineSegment(FreeCAD.Vector(x3, y3, 0), FreeCAD.Vector(x4, y4, 0))) ser.addGeometry( Part.LineSegment(FreeCAD.Vector(x4, y4, 0), FreeCAD.Vector(x1, y1, 0))) elif i[0] == 'circle': try: try: height = i[5] except: height = 0 if i[4] == 0: ser.addGeometry( Part.Circle(FreeCAD.Vector(i[1], i[2], 0), FreeCAD.Vector(0, 0, 1), i[3]), False) else: ser.addGeometry( Part.Circle(FreeCAD.Vector(i[1], i[2], 0), FreeCAD.Vector(0, 0, 1), i[3] + i[4] / 2)) ser.addGeometry( Part.Circle(FreeCAD.Vector(i[1], i[2], 0), FreeCAD.Vector(0, 0, 1), i[3] - i[4] / 2)) except Exception as e: FreeCAD.Console.PrintWarning("3. {0}\n".format(e)) elif i[0] == 'polygon': try: height = i[2] except: height = 0 for j in i[1]: if j[0] == 'Line': ser.addGeometry( Part.LineSegment(FreeCAD.Vector(j[1], j[2], 0), FreeCAD.Vector(j[3], j[4], 0))) elif j[0] == 'Arc3P': x1 = j[1] y1 = j[2] x2 = j[3] y2 = j[4] [x3, y3] = self.arcMidPoint([x2, y2], [x1, y1], j[5]) arc = Part.ArcOfCircle(FreeCAD.Vector(x1, y1, 0.0), FreeCAD.Vector(x3, y3, 0.0), FreeCAD.Vector(x2, y2, 0.0)) ser.addGeometry(arc) # #FreeCAD.ActiveDocument.recompute() ser.recompute() createConstraintArea(ser, typeL, height) self.updateView()
def startElement(self, tag, attributes): if tag == "wall": name = attributes["id"] p1 = FreeCAD.Vector( float(attributes["xStart"]) * 10, float(attributes["yStart"]) * 10, 0) p2 = FreeCAD.Vector( float(attributes["xEnd"]) * 10, float(attributes["yEnd"]) * 10, 0) height = float(attributes["height"]) * 10 thickness = float(attributes["thickness"]) * 10 if DEBUG: print "Creating wall: ", name line = Draft.makeLine(p1, p2) if self.makeIndividualWalls: wall = Arch.makeWall(baseobj=line, width=thickness, height=height, name=name) wall.Label = name else: self.lines.setdefault(str(thickness) + ";" + str(height), []).append(line) elif tag == "pieceOfFurniture": name = attributes["name"] data = self.z.read(attributes["model"]) th, tf = tempfile.mkstemp(suffix=".obj") f = pyopen(tf, "wb") f.write(data) f.close() os.close(th) m = Mesh.read(tf) fx = (float(attributes["width"]) / 100) / m.BoundBox.XLength fy = (float(attributes["height"]) / 100) / m.BoundBox.YLength fz = (float(attributes["depth"]) / 100) / m.BoundBox.ZLength mat = FreeCAD.Matrix() mat.scale(1000 * fx, 1000 * fy, 1000 * fz) mat.rotateX(math.pi / 2) mat.rotateZ(math.pi) if DEBUG: print "Creating furniture: ", name if "angle" in attributes.keys(): mat.rotateZ(float(attributes["angle"])) m.transform(mat) os.remove(tf) p = m.BoundBox.Center.negative() p = p.add( FreeCAD.Vector( float(attributes["x"]) * 10, float(attributes["y"]) * 10, 0)) p = p.add( FreeCAD.Vector(0, 0, m.BoundBox.Center.z - m.BoundBox.ZMin)) m.Placement.Base = p obj = FreeCAD.ActiveDocument.addObject("Mesh::Feature", name) obj.Mesh = m self.furniture.append(obj) elif tag == "doorOrWindow": name = attributes["name"] data = self.z.read(attributes["model"]) th, tf = tempfile.mkstemp(suffix=".obj") f = pyopen(tf, "wb") f.write(data) f.close() os.close(th) m = Mesh.read(tf) fx = (float(attributes["width"]) / 100) / m.BoundBox.XLength fy = (float(attributes["height"]) / 100) / m.BoundBox.YLength fz = (float(attributes["depth"]) / 100) / m.BoundBox.ZLength mat = FreeCAD.Matrix() mat.scale(1000 * fx, 1000 * fy, 1000 * fz) mat.rotateX(math.pi / 2) m.transform(mat) b = m.BoundBox v1 = FreeCAD.Vector(b.XMin, b.YMin - 500, b.ZMin) v2 = FreeCAD.Vector(b.XMax, b.YMin - 500, b.ZMin) v3 = FreeCAD.Vector(b.XMax, b.YMax + 500, b.ZMin) v4 = FreeCAD.Vector(b.XMin, b.YMax + 500, b.ZMin) sub = Part.makePolygon([v1, v2, v3, v4, v1]) sub = Part.Face(sub) sub = sub.extrude(FreeCAD.Vector(0, 0, b.ZLength)) os.remove(tf) shape = Arch.getShapeFromMesh(m) if not shape: shape = Part.Shape() shape.makeShapeFromMesh(m.Topology, 0.100000) shape = shape.removeSplitter() if shape: if DEBUG: print "Creating window: ", name if "angle" in attributes.keys(): shape.rotate(shape.BoundBox.Center, FreeCAD.Vector(0, 0, 1), math.degrees(float(attributes["angle"]))) sub.rotate(shape.BoundBox.Center, FreeCAD.Vector(0, 0, 1), math.degrees(float(attributes["angle"]))) p = shape.BoundBox.Center.negative() p = p.add( FreeCAD.Vector( float(attributes["x"]) * 10, float(attributes["y"]) * 10, 0)) p = p.add( FreeCAD.Vector( 0, 0, shape.BoundBox.Center.z - shape.BoundBox.ZMin)) if "elevation" in attributes.keys(): p = p.add( FreeCAD.Vector(0, 0, float(attributes["elevation"]) * 10)) shape.translate(p) sub.translate(p) obj = FreeCAD.ActiveDocument.addObject("Part::Feature", name + "_body") obj.Shape = shape subobj = FreeCAD.ActiveDocument.addObject( "Part::Feature", name + "_sub") subobj.Shape = sub if FreeCAD.GuiUp: subobj.ViewObject.hide() win = Arch.makeWindow(baseobj=obj, name=name) win.Label = name win.Subvolume = subobj self.windows.append(win) else: print("importSH3D: Error creating shape for door/window " + name)
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 get_svg(obj, scale=1, linewidth=0.35, fontsize=12, fillstyle="shape color", direction=None, linestyle=None, color=None, linespacing=None, techdraw=False, rotation=0, fillspaces=False, override=True): """Return a string containing an SVG representation of the object. Paramaeters ----------- scale: float, optional It defaults to 1. It allows scaling line widths down, so they are resolution-independent. linewidth: float, optional It defaults to 0.35. fontsize: float, optional It defaults to 12, which is interpreted as `pt` unit (points). It is used if the given object contains any text. fillstyle: str, optional It defaults to 'shape color'. direction: Base::Vector3, optional It defaults to `None`. It is an arbitrary projection vector or a `WorkingPlane.Plane` instance. linestyle: optional It defaults to `None`. color: optional It defaults to `None`. linespacing: float, optional It defaults to `None`. techdraw: bool, optional It defaults to `False`. If it is `True`, it sets some options for generating SVG strings for displaying inside TechDraw. rotation: float, optional It defaults to 0. fillspaces: bool, optional It defaults to `False`. override: bool, optional It defaults to `True`. """ # If this is a group, recursively call this function to gather # all the SVG strings from the contents of the group if hasattr(obj, "isDerivedFrom"): if (obj.isDerivedFrom("App::DocumentObjectGroup") or utils.get_type(obj) == "Layer"): svg = "" for child in obj.Group: svg += get_svg(child, scale, linewidth, fontsize, fillstyle, direction, linestyle, color, linespacing, techdraw, rotation, fillspaces, override) return svg pathdata = [] svg = "" linewidth = float(linewidth)/scale if not override: if hasattr(obj, "ViewObject") and hasattr(obj.ViewObject, "LineWidth"): if hasattr(obj.ViewObject.LineWidth, "Value"): lw = obj.ViewObject.LineWidth.Value else: lw = obj.ViewObject.LineWidth linewidth = lw * linewidth fontsize = (float(fontsize)/scale)/2 if linespacing: linespacing = float(linespacing)/scale else: linespacing = 0.5 # print(obj.Label, "line spacing", linespacing, "scale", scale) # The number of times the dots are smaller than the arrow size pointratio = 0.75 plane = None if direction: if isinstance(direction, App.Vector): if direction != App.Vector(0, 0, 0): plane = WorkingPlane.plane() plane.alignToPointAndAxis_SVG(App.Vector(0, 0, 0), direction.negative().negative(), 0) else: raise ValueError("'direction' cannot be: Vector(0, 0, 0)") elif isinstance(direction, WorkingPlane.plane): plane = direction stroke = "#000000" if color and override: if "#" in color: stroke = color else: stroke = utils.get_rgb(color) elif App.GuiUp: # find print color pc = get_print_color(obj) if pc: stroke = utils.get_rgb(pc) # get line color elif hasattr(obj, "ViewObject"): if hasattr(obj.ViewObject, "LineColor"): stroke = utils.get_rgb(obj.ViewObject.LineColor) elif hasattr(obj.ViewObject, "TextColor"): stroke = utils.get_rgb(obj.ViewObject.TextColor) lstyle = "none" if override: lstyle = get_line_style(linestyle, scale) else: if hasattr(obj, "ViewObject") and hasattr(obj.ViewObject, "DrawStyle"): lstyle = get_line_style(obj.ViewObject.DrawStyle, scale) if not obj: pass elif isinstance(obj, Part.Shape): svg = _svg_shape(svg, obj, plane, fillstyle, pathdata, stroke, linewidth, lstyle) elif utils.get_type(obj) in ["Dimension", "LinearDimension"]: svg = _svg_dimension(obj, plane, scale, linewidth, fontsize, stroke, pointratio, techdraw, rotation) elif utils.get_type(obj) == "AngularDimension": if not App.GuiUp: _wrn("Export of dimensions to SVG is only available in GUI mode") if App.GuiUp: if obj.ViewObject.Proxy: if hasattr(obj.ViewObject.Proxy, "circle"): prx = obj.ViewObject.Proxy # drawing arc fill = "none" if obj.ViewObject.DisplayMode == "2D": svg += get_path(obj, plane, fill, pathdata, stroke, linewidth, lstyle, fill_opacity=None, edges=[prx.circle]) else: if hasattr(prx, "circle1"): svg += get_path(obj, plane, fill, pathdata, stroke, linewidth, lstyle, fill_opacity=None, edges=[prx.circle1]) svg += get_path(obj, plane, fill, pathdata, stroke, linewidth, lstyle, fill_opacity=None, edges=[prx.circle2]) else: svg += get_path(obj, plane, fill, pathdata, stroke, linewidth, lstyle, fill_opacity=None, edges=[prx.circle]) # drawing arrows if hasattr(obj.ViewObject, "ArrowType"): p2 = get_proj(prx.p2, plane) p3 = get_proj(prx.p3, plane) arrowsize = obj.ViewObject.ArrowSize.Value/pointratio arrowlength = 4*obj.ViewObject.ArrowSize.Value _v1a = prx.circle.valueAt(prx.circle.FirstParameter + arrowlength) _v1b = prx.circle.valueAt(prx.circle.FirstParameter) _v2a = prx.circle.valueAt(prx.circle.LastParameter - arrowlength) _v2b = prx.circle.valueAt(prx.circle.LastParameter) u1 = get_proj(_v1a - _v1b, plane) u2 = get_proj(_v2a - _v2b, plane) angle1 = -DraftVecUtils.angle(u1) angle2 = -DraftVecUtils.angle(u2) if hasattr(obj.ViewObject, "FlipArrows"): if obj.ViewObject.FlipArrows: angle1 = angle1 + math.pi angle2 = angle2 + math.pi svg += get_arrow(obj, obj.ViewObject.ArrowType, p2, arrowsize, stroke, linewidth, angle1) svg += get_arrow(obj, obj.ViewObject.ArrowType, p3, arrowsize, stroke, linewidth, angle2) # drawing text if obj.ViewObject.DisplayMode == "2D": _diff = (prx.circle.LastParameter - prx.circle.FirstParameter) t = prx.circle.tangentAt(prx.circle.FirstParameter + _diff/2.0) t = get_proj(t, plane) tangle = DraftVecUtils.angle(t) if (tangle <= -math.pi/2) or (tangle > math.pi/2): tangle = tangle + math.pi _diff = (prx.circle.LastParameter - prx.circle.FirstParameter) _va = prx.circle.valueAt(prx.circle.FirstParameter + _diff/2.0) tbase = get_proj(_va, plane) _v = App.Vector(0, 2.0/scale, 0) tbase = tbase + DraftVecUtils.rotate(_v, tangle) # print(tbase) else: tangle = 0 tbase = get_proj(prx.tbase, plane) svg += svgtext.get_text(plane, techdraw, stroke, fontsize, obj.ViewObject.FontName, tangle, tbase, prx.string) elif utils.get_type(obj) == "Label": if getattr(obj.ViewObject, "Line", True): # Some Labels may have no Line property # Draw multisegment line proj_points = list(map(lambda x: get_proj(x, plane), obj.Points)) path_dir_list = [format_point(proj_points[0], action='M')] path_dir_list += map(format_point, proj_points[1:]) path_dir_str = " ".join(path_dir_list) svg_path = '<path ' svg_path += 'fill="none" ' svg_path += 'stroke="{}" '.format(stroke) svg_path += 'stroke-width="{}" '.format(linewidth) svg_path += 'd="{}"'.format(path_dir_str) svg_path += '/>' svg += svg_path # Draw arrow. # We are different here from 3D view # if Line is set to 'off', no arrow is drawn if hasattr(obj.ViewObject, "ArrowType") and len(obj.Points) >= 2: last_segment = App.Vector(obj.Points[-1] - obj.Points[-2]) _v = get_proj(last_segment, plane) angle = -DraftVecUtils.angle(_v) + math.pi svg += get_arrow(obj, obj.ViewObject.ArrowType, proj_points[-1], obj.ViewObject.ArrowSize.Value/pointratio, stroke, linewidth, angle) if not App.GuiUp: _wrn("Export of texts to SVG is only available in GUI mode") # print text if App.GuiUp: fontname = obj.ViewObject.TextFont position = get_proj(obj.Placement.Base, plane) rotation = obj.Placement.Rotation justification = obj.ViewObject.TextAlignment text = obj.Text svg += svgtext.get_text(plane, techdraw, stroke, fontsize, fontname, rotation, position, text, linespacing, justification) elif utils.get_type(obj) in ["Annotation", "DraftText", "Text"]: # returns an svg representation of a document annotation if not App.GuiUp: _wrn("Export of texts to SVG is only available in GUI mode") if App.GuiUp: n = obj.ViewObject.FontName if utils.get_type(obj) == "Annotation": p = get_proj(obj.Position, plane) r = obj.ViewObject.Rotation.getValueAs("rad") t = obj.LabelText else: # DraftText (old) or Text (new, 0.19) p = get_proj(obj.Placement.Base, plane) r = obj.Placement.Rotation t = obj.Text j = obj.ViewObject.Justification svg += svgtext.get_text(plane, techdraw, stroke, fontsize, n, r, p, t, linespacing, j) elif utils.get_type(obj) == "Axis": # returns the SVG representation of an Arch Axis system if not App.GuiUp: _wrn("Export of axes to SVG is only available in GUI mode") if App.GuiUp: vobj = obj.ViewObject lorig = lstyle fill = 'none' rad = vobj.BubbleSize.Value/2 n = 0 for e in obj.Shape.Edges: lstyle = lorig svg += get_path(obj, plane, fill, pathdata, stroke, linewidth, lstyle, fill_opacity=None, edges=[e]) lstyle = "none" pos = ["Start"] if hasattr(vobj, "BubblePosition"): if vobj.BubblePosition == "Both": pos = ["Start", "End"] else: pos = [vobj.BubblePosition] for p in pos: if p == "Start": p1 = e.Vertexes[0].Point p2 = e.Vertexes[1].Point else: p1 = e.Vertexes[1].Point p2 = e.Vertexes[0].Point dv = p2.sub(p1) dv.normalize() center = p2.add(dv.scale(rad, rad, rad)) svg += get_circle(plane, fill, stroke, linewidth, lstyle, Part.makeCircle(rad, center)) if (hasattr(vobj.Proxy, "bubbletexts") and len(vobj.Proxy.bubbletexts) >= n): bubb = vobj.Proxy.bubbletexts svg += '<text ' svg += 'fill="{}" '.format(stroke) svg += 'font-size="{}" '.format(rad) svg += 'style="text-anchor:middle;' svg += 'text-align:center;' svg += 'font-family: sans;" ' svg += 'transform="' svg += 'translate({},{}) '.format(center.x + rad/4.0, center.y - rad/3.0) svg += 'scale(1,-1)"> ' svg += '<tspan>' svg += bubb[n].string.getValues()[0] svg += '</tspan>\n' svg += '</text>\n' n += 1 lstyle = lorig elif utils.get_type(obj) == "Pipe": fill = stroke if obj.Base and obj.Diameter: svg += get_path(obj, plane, fill, pathdata, stroke, linewidth, lstyle, fill_opacity=None, edges=obj.Base.Shape.Edges) for f in obj.Shape.Faces: if len(f.Edges) == 1: if isinstance(f.Edges[0].Curve, Part.Circle): svg += get_circle(plane, fill, stroke, linewidth, lstyle, f.Edges[0]) elif utils.get_type(obj) == "Rebar": fill = "none" basewire = obj.Base.Shape.Wires[0].copy() # Not applying rounding because the results are not correct # if hasattr(obj, "Rounding") and obj.Rounding: # basewire = DraftGeomUtils.filletWire( # basewire, obj.Rounding * obj.Diameter.Value # ) wires = [] for placement in obj.PlacementList: wire = basewire.copy() wire.Placement = placement.multiply(basewire.Placement) wires.append(wire) svg += get_path(obj, plane, fill, pathdata, stroke, linewidth, lstyle, fill_opacity=None, wires=wires) elif utils.get_type(obj) == "PipeConnector": pass elif utils.get_type(obj) == "Space": fill_opacity = 1 # returns an SVG fragment for the text of a space if not App.GuiUp: _wrn("Export of spaces to SVG is only available in GUI mode") if App.GuiUp: vobj = obj.ViewObject if fillspaces and hasattr(obj, "Proxy"): if not hasattr(obj.Proxy, "face"): obj.Proxy.getArea(obj, notouch=True) if hasattr(obj.Proxy, "face"): # setting fill if App.GuiUp: fill = utils.get_rgb(vobj.ShapeColor, testbw=False) fill_opacity = 1 - vobj.Transparency / 100.0 else: fill = "#888888" svg += get_path(obj, plane, fill, pathdata, stroke, linewidth, lstyle, fill_opacity=fill_opacity, wires=[obj.Proxy.face.OuterWire]) c = utils.get_rgb(vobj.TextColor) n = vobj.FontName a = 0 if rotation != 0: a = math.radians(rotation) t1 = vobj.Proxy.text1.string.getValues() t2 = vobj.Proxy.text2.string.getValues() scale = vobj.FirstLine.Value/vobj.FontSize.Value f1 = fontsize * scale if round(plane.axis.getAngle(App.Vector(0,0,1)),2) not in [0,3.14]: # if not in XY view, place the label at center p2 = obj.Shape.CenterOfMass else: _v = vobj.Proxy.coords.translation.getValue().getValue() p2 = obj.Placement.multVec(App.Vector(_v)) _h = vobj.Proxy.header.translation.getValue().getValue() lspc = App.Vector(_h) p1 = p2 + lspc j = vobj.TextAlign t3 = svgtext.get_text(plane, techdraw, c, f1, n, a, get_proj(p1, plane), t1, linespacing, j, flip=True) svg += t3 if t2: ofs = App.Vector(0, -lspc.Length, 0) if a: Z = App.Vector(0, 0, 1) ofs = App.Rotation(Z, -rotation).multVec(ofs) t4 = svgtext.get_text(plane, techdraw, c, fontsize, n, a, get_proj(p1, plane).add(ofs), t2, linespacing, j, flip=True) svg += t4 elif hasattr(obj, 'Shape'): # In the past we tested for a Part Feature # elif obj.isDerivedFrom('Part::Feature'): # # however, this doesn't work for App::Links; instead we # test for a 'Shape'. All Part::Features should have a Shape, # and App::Links can have one as well. if obj.Shape.isNull(): return '' fill_opacity = 1 # setting fill if obj.Shape.Faces: if App.GuiUp: try: m = obj.ViewObject.DisplayMode except AttributeError: m = None vobj = obj.ViewObject if m != "Wireframe": if fillstyle == "shape color": fill = utils.get_rgb(vobj.ShapeColor, testbw=False) fill_opacity = 1 - vobj.Transparency / 100.0 elif fillstyle in ("none",None): fill = "none" else: fill = 'url(#'+fillstyle+')' svg += get_pattern(fillstyle) else: fill = "none" else: fill = "#888888" else: fill = 'none' if len(obj.Shape.Vertexes) > 1: wiredEdges = [] if obj.Shape.Faces: for i, f in enumerate(obj.Shape.Faces): # place outer wire first wires = [f.OuterWire] wires.extend([w for w in f.Wires if w.hashCode() != f.OuterWire.hashCode()]) svg += get_path(obj, plane, fill, pathdata, stroke, linewidth, lstyle, fill_opacity=fill_opacity, wires=f.Wires, pathname='%s_f%04d' % (obj.Name, i)) wiredEdges.extend(f.Edges) else: for i, w in enumerate(obj.Shape.Wires): svg += get_path(obj, plane, fill, pathdata, stroke, linewidth, lstyle, fill_opacity=fill_opacity, edges=w.Edges, pathname='%s_w%04d' % (obj.Name, i)) wiredEdges.extend(w.Edges) if len(wiredEdges) != len(obj.Shape.Edges): for i, e in enumerate(obj.Shape.Edges): if DraftGeomUtils.findEdge(e, wiredEdges) is None: svg += get_path(obj, plane, fill, pathdata, stroke, linewidth, lstyle, fill_opacity=fill_opacity, edges=[e], pathname='%s_nwe%04d' % (obj.Name, i)) else: # closed circle or spline if obj.Shape.Edges: if isinstance(obj.Shape.Edges[0].Curve, Part.Circle): svg = get_circle(plane, fill, stroke, linewidth, lstyle, obj.Shape.Edges[0]) else: svg = get_path(obj, plane, fill, pathdata, stroke, linewidth, lstyle, fill_opacity=fill_opacity, edges=obj.Shape.Edges) if (App.GuiUp and hasattr(obj.ViewObject, "EndArrow") and obj.ViewObject.EndArrow and hasattr(obj.ViewObject, "ArrowType") and len(obj.Shape.Vertexes) > 1): p1 = get_proj(obj.Shape.Vertexes[-1].Point, plane) p2 = get_proj(obj.Shape.Vertexes[-2].Point, plane) angle = -DraftVecUtils.angle(p2 - p1) arrowsize = obj.ViewObject.ArrowSize.Value/pointratio svg += get_arrow(obj, obj.ViewObject.ArrowType, p1, arrowsize, stroke, linewidth, angle) # techdraw expects bottom-to-top coordinates if techdraw: svg = '<g transform ="scale(1,-1)">\n ' + svg + '</g>\n' return svg
def draw(self): #helper Variables #Make the coresponding xRodClamp 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) App.ActiveDocument = App.getDocument(self.name) #Make clamp body #Sketch points p1x = -gv.zEndstopSupportWidth / 2 p1y = 0 p2x = -gv.zEndstopSupportWidth / 2 p2y = gv.zEndStopClampLength p3x = gv.zEndstopSupportWidth / 2 p3y = gv.zEndStopClampLength p4x = gv.zEndstopSupportWidth / 2 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('Symmetric', 0, 2, 0, 1, -1, 1)) App.ActiveDocument.recompute() #add dimensions App.ActiveDocument.Sketch.addConstraint( Sketcher.Constraint('DistanceY', 1, gv.zEndStopClampLength)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch.addConstraint( Sketcher.Constraint('DistanceX', 2, -gv.zEndstopSupportWidth)) App.ActiveDocument.recompute() # Gui.getDocument(self.name).resetEdit() App.getDocument(self.name).recompute() #pad rod support 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.zRodDiaL / 2 + gv.zEndstopBodyThickness - gv.clampGap / 2 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 cut out for rod #sketch points p1x = 0 p1y = gv.zRodDiaL / 2 + gv.zEndstopBodyThickness #Make Sketch #make sketch App.activeDocument().addObject('Sketcher::SketchObject', 'Sketch001') App.activeDocument().Sketch001.Support = uf.getFace( App.ActiveDocument.Pad, None, None, 0, 0, None, None) App.activeDocument().recompute() # Gui.activeDocument().setEdit('Sketch001') App.ActiveDocument.Sketch001.addExternal( "Pad", uf.getEdge( App.ActiveDocument.Pad, 0, 0, 0, 0, gv.zRodDiaL / 2 + gv.zEndstopBodyThickness - gv.clampGap / 2, 0)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addGeometry( Part.Circle(App.Vector(p1x, p1y, 0), App.Vector(0, 0, 1), gv.zRodDiaL / 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('PointOnObject', 0, 3, -2)) App.ActiveDocument.recompute() #add dimensions App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('Distance', 0, 3, -3, gv.clampGap / 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch001.addConstraint( Sketcher.Constraint('Radius', 0, gv.zRodDiaL / 2)) App.ActiveDocument.recompute() Gui.getDocument(self.name).resetEdit() App.getDocument(self.name).recompute() #Cut through all 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.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() #cut Right clamp hole #Sketch points p1x = gv.zRodDiaL / 2 + gv.printedToPrintedDia / 2 p1y = gv.printedToPrintedDia / 2 + gv.mountToPrintedPadding #Make Sketch App.activeDocument().addObject('Sketcher::SketchObject', 'Sketch002') App.activeDocument().Sketch002.Support = uf.getFace( App.ActiveDocument.Pocket, 0, 1, None, None, gv.zRodDiaL / 2 + gv.zEndstopBodyThickness - gv.clampGap / 2, 0) App.activeDocument().recompute() App.activeDocument().recompute() # Gui.activeDocument().setEdit('Sketch002') App.ActiveDocument.Sketch002.addExternal( "Pocket", uf.getEdge( App.ActiveDocument.Pocket, gv.zEndstopSupportWidth / 2, 0, gv.zEndStopClampLength / 2, 0, gv.zRodDiaL / 2 + gv.zEndstopBodyThickness - gv.clampGap / 2, 0)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch002.addGeometry( Part.Circle(App.Vector(p1x, p1y, 0), App.Vector(0, 0, 1), gv.printedToPrintedDia / 2)) App.ActiveDocument.recompute() # App.ActiveDocument.Sketch002.addConstraint(Sketcher.Constraint('Distance',0,3,-3,p1y)) App.ActiveDocument.recompute() # App.ActiveDocument.Sketch002.addConstraint(Sketcher.Constraint('DistanceY',-1,1,0,3,p1y)) App.ActiveDocument.recompute() # App.ActiveDocument.Sketch002.addConstraint(Sketcher.Constraint('Radius',0,gv.printedToPrintedDia/2)) App.ActiveDocument.recompute() Gui.getDocument(self.name).resetEdit() App.getDocument(self.name).recompute() #Cut clamp hole 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() #Mirror clamp hole App.activeDocument().addObject("PartDesign::Mirrored", "Mirrored") App.ActiveDocument.recompute() App.activeDocument().Mirrored.Originals = [ App.activeDocument().Pocket001, ] App.activeDocument().Mirrored.MirrorPlane = ( App.activeDocument().Sketch002, ["V_Axis"]) Gui.activeDocument().Pocket001.Visibility = False # Gui.activeDocument().setEdit('Mirrored') # Gui.ActiveDocument.Mirrored.ShapeColor=Gui.ActiveDocument.Pocket001.ShapeColor # Gui.ActiveDocument.Mirrored.DisplayMode=Gui.ActiveDocument.Pocket001.DisplayMode App.ActiveDocument.Mirrored.Originals = [ App.ActiveDocument.Pocket001, ] App.ActiveDocument.Mirrored.MirrorPlane = ( App.ActiveDocument.Sketch002, ["V_Axis"]) App.ActiveDocument.recompute() # Gui.activeDocument().resetEdit() #Make channel for contact #Sketch Points p1x = -gv.zEndstopSupportWidth / 2 p1y = -(2 * gv.mountToPrintedPadding + gv.printedToPrintedDia + 2 * gv.xEndstopChannelWidth + gv.zEndstopJogWidth) p2x = p1x p2y = -(2 * gv.mountToPrintedPadding + gv.printedToPrintedDia + gv.zEndstopJogWidth) p3x = -gv.zEndstopJogWidth p3y = p2y p4x = 0 p4y = -(2 * gv.mountToPrintedPadding + gv.printedToPrintedDia) p5x = -p3x p5y = p2y p6x = -p1x p6y = p2y p7x = p6x p7y = p1y p8x = p5x - (gv.xEndstopChannelWidth * math.tan(math.pi / 8)) p8y = p1y p9x = p8x - math.pow(2, 0.5) * gv.xEndstopChannelWidth * math.tan( math.pi / 8) p9y = p1y + math.pow(2, 0.5) * gv.xEndstopChannelWidth * math.tan( math.pi / 8) p10x = p4x p10y = p1y + gv.zEndstopJogWidth - math.pow( 2, 0.5) * gv.xEndstopChannelWidth * math.tan(math.pi / 8) p11x = p3x + ( gv.xEndstopChannelWidth * math.tan(math.pi / 8)) + math.pow( 2, 0.5) * gv.xEndstopChannelWidth * math.tan(math.pi / 8) p11y = p9y p12x = p3x + (gv.xEndstopChannelWidth * math.tan(math.pi / 8)) p12y = p1y #Make Sketch App.activeDocument().addObject('Sketcher::SketchObject', 'Sketch003') App.activeDocument().Sketch003.Support = uf.getFace( App.ActiveDocument.Mirrored, 0, 0, None, None, 0, 0) App.activeDocument().recompute() App.activeDocument().recompute() # Gui.activeDocument().setEdit('Sketch003') App.ActiveDocument.Sketch003.addExternal( "Mirrored", uf.getEdge(App.ActiveDocument.Mirrored, -gv.zEndstopSupportWidth / 2, 0, gv.zEndStopClampLength / 2, 0, 0, 0)) App.ActiveDocument.Sketch003.addExternal( "Mirrored", uf.getEdge(App.ActiveDocument.Mirrored, gv.zEndstopSupportWidth / 2, 0, gv.zEndStopClampLength / 2, 0, 0, 0)) App.ActiveDocument.recompute() 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('PointOnObject', 0, 1, -3)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Vertical', 0)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addGeometry( Part.Line(App.Vector(p2x, p2y, 0), App.Vector(p3x, p3y, 0))) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 0, 2, 1, 1)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Horizontal', 1)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addGeometry( Part.Line(App.Vector(p3x, p3y, 0), App.Vector(p4x, p4y, 0))) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 1, 2, 2, 1)) App.ActiveDocument.recompute() App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addGeometry( Part.Line(App.Vector(p4x, p4y, 0), App.Vector(p5x, p5y, 0))) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 2, 2, 3, 1)) App.ActiveDocument.recompute() App.ActiveDocument.recompute() App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addGeometry( Part.Line(App.Vector(p5x, p5y, 0), App.Vector(p6x, p6y, 0))) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 3, 2, 4, 1)) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Horizontal', 4)) App.ActiveDocument.recompute() App.ActiveDocument.recompute() App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addGeometry( Part.Line(App.Vector(p6x, p6y, 0), App.Vector(p7x, p7y, 0))) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 4, 2, 5, 1)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('PointOnObject', 4, 2, -4)) App.ActiveDocument.recompute() App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addGeometry( Part.Line(App.Vector(p7x, p7y, 0), App.Vector(p8x, p8y, 0))) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 5, 2, 6, 1)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('PointOnObject', 5, 2, -4)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addGeometry( Part.Line(App.Vector(p8x, p8y, 0), App.Vector(p9x, p9y, 0))) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 6, 2, 7, 1)) App.ActiveDocument.recompute() App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addGeometry( Part.Line(App.Vector(p9x, p9y, 0), App.Vector(p10x, p10y, 0))) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 7, 2, 8, 1)) App.ActiveDocument.recompute() App.ActiveDocument.recompute() # App.ActiveDocument.Sketch003.addConstraint(Sketcher.Constraint('PointOnObject',8,2,-3)) App.ActiveDocument.recompute() # App.ActiveDocument.Sketch003.addConstraint(Sketcher.Constraint('Horizontal',8)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addGeometry( Part.Line(App.Vector(p10x, p10y, 0), App.Vector(p11x, p11y, 0))) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 8, 2, 9, 1)) App.ActiveDocument.recompute() # App.ActiveDocument.Sketch003.addConstraint(Sketcher.Constraint('Vertical',9)) App.ActiveDocument.recompute() # App.ActiveDocument.Sketch003.addConstraint(Sketcher.Constraint('PointOnObject',3,2,-4)) App.ActiveDocument.Sketch003.addGeometry( Part.Line(App.Vector(p11x, p11y, 0), App.Vector(p12x, p12y, 0))) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 9, 2, 10, 1)) App.ActiveDocument.recompute() # App.ActiveDocument.Sketch003.addConstraint(Sketcher.Constraint('PointOnObject',10,2,7)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addGeometry( Part.Line(App.Vector(p12x, p12y, 0), App.Vector(p1x, p1y, 0))) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addGeometry( Part.Line(App.Vector(p3x, p3y, 0), App.Vector(p11x, p11y, 0))) App.ActiveDocument.Sketch003.addGeometry( Part.Line(App.Vector(p5x, p5y, 0), App.Vector(p9x, p9y, 0))) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 10, 2, 11, 1)) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 11, 2, 0, 1)) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Horizontal', 6)) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Horizontal', 11)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('PointOnObject', 2, 2, -2)) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('PointOnObject', 8, 2, -2)) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Parallel', 9, 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Parallel', 3, 8)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.toggleConstruction(13) App.ActiveDocument.Sketch003.toggleConstruction(12) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Equal', 0, 12)) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Equal', 12, 13)) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Equal', 13, 5)) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Perpendicular', 2, 3)) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 12, 2, 9, 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 12, 1, 1, 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 3, 2, 13, 1)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Coincident', 13, 2, 7, 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Perpendicular', 12, 2)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Perpendicular', 13, 3)) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Parallel', 10, 9)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('Parallel', 7, 8)) App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('PointOnObject', 6, 2, 11)) #add dimensions App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('DistanceY', 5, -gv.xEndstopChannelWidth)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('DistanceY', 3, 2, 2, 2, gv.zEndstopJogWidth)) App.ActiveDocument.recompute() App.ActiveDocument.Sketch003.addConstraint( Sketcher.Constraint('DistanceY', -1, 1, 2, 2, -9.963388)) App.ActiveDocument.recompute() Gui.getDocument('zEndstop').resetEdit() App.getDocument('zEndstop').recompute() #Cut top channel 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("Mirrored") Gui.activeDocument().setEdit('Pocket002') Gui.ActiveDocument.Pocket002.ShapeColor = Gui.ActiveDocument.Mirrored.ShapeColor Gui.ActiveDocument.Pocket002.LineColor = Gui.ActiveDocument.Mirrored.LineColor Gui.ActiveDocument.Pocket002.PointColor = Gui.ActiveDocument.Mirrored.PointColor App.ActiveDocument.Pocket002.Length = 3.000000 App.ActiveDocument.Pocket002.Type = 0 App.ActiveDocument.Pocket002.UpToFace = None App.ActiveDocument.recompute() Gui.activeDocument().resetEdit() #Use a linear pattern to add other channel App.activeDocument().addObject("PartDesign::LinearPattern", "LinearPattern") App.ActiveDocument.recompute() App.activeDocument().LinearPattern.Originals = [ App.activeDocument().Pocket002, ] App.activeDocument().LinearPattern.Direction = ( App.activeDocument().Sketch003, ["H_Axis"]) App.activeDocument().LinearPattern.Length = 100 App.activeDocument().LinearPattern.Occurrences = 2 Gui.activeDocument().Pocket002.Visibility = False Gui.activeDocument().setEdit('LinearPattern') Gui.ActiveDocument.LinearPattern.ShapeColor = Gui.ActiveDocument.Pocket002.ShapeColor Gui.ActiveDocument.LinearPattern.DisplayMode = Gui.ActiveDocument.Pocket002.DisplayMode App.ActiveDocument.LinearPattern.Originals = [ App.ActiveDocument.Pocket002, ] App.ActiveDocument.LinearPattern.Direction = ( App.ActiveDocument.Sketch003, ["V_Axis"]) App.ActiveDocument.LinearPattern.Reversed = 1 App.ActiveDocument.LinearPattern.Length = 3.500000 App.ActiveDocument.LinearPattern.Occurrences = 2 App.ActiveDocument.recompute() Gui.activeDocument().resetEdit()
def makeSolarDiagram(longitude,latitude,scale=1,complete=False): """makeSolarDiagram(longitude,latitude,[scale,complete]): returns a solar diagram as a pivy node. If complete is True, the 12 months are drawn""" from subprocess import call py3_failed = call(["python3", "-c", "import Pysolar"]) if py3_failed: try: import Pysolar except: print("Pysolar is not installed. Unable to generate solar diagrams") return None else: from subprocess import check_output from pivy import coin if not scale: return None def toNode(shape): "builds a pivy node from a simple linear shape" from pivy import coin buf = shape.writeInventor(2,0.01) 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) item = coin.SoSeparator() item.addChild(coords) item.addChild(line) return item circles = [] sunpaths = [] hourpaths = [] circlepos = [] hourpos = [] # build the base circle + number positions import Part for i in range(1,9): circles.append(Part.makeCircle(scale*(i/8.0))) for ad in range(0,360,15): a = math.radians(ad) p1 = FreeCAD.Vector(math.cos(a)*scale,math.sin(a)*scale,0) p2 = FreeCAD.Vector(math.cos(a)*scale*0.125,math.sin(a)*scale*0.125,0) p3 = FreeCAD.Vector(math.cos(a)*scale*1.08,math.sin(a)*scale*1.08,0) circles.append(Part.LineSegment(p1,p2).toShape()) circlepos.append((ad,p3)) # build the sun curves at solstices and equinoxe year = datetime.datetime.now().year hpts = [ [] for i in range(24) ] m = [(6,21),(7,21),(8,21),(9,21),(10,21),(11,21),(12,21)] if complete: m.extend([(1,21),(2,21),(3,21),(4,21),(5,21)]) for i,d in enumerate(m): pts = [] for h in range(24): if not py3_failed: dt = "datetime.datetime(%s, %s, %s, %s)" % (year, d[0], d[1], h) alt_call = "python3 -c 'import datetime,Pysolar; print (Pysolar.solar.get_altitude_fast(%s, %s, %s))'" % (latitude, longitude, dt) alt = math.radians(float(check_output(alt_call, shell=True).strip())) az_call = "python3 -c 'import datetime,Pysolar; print (Pysolar.solar.get_azimuth(%s, %s, %s))'" % (latitude, longitude, dt) az = float(re.search('.+$', check_output(az_call, shell=True)).group(0)) else: dt = datetime.datetime(year,d[0],d[1],h) alt = math.radians(Pysolar.solar.GetAltitudeFast(latitude,longitude,dt)) az = Pysolar.solar.GetAzimuth(latitude,longitude,dt) az = -90 + az # pysolar's zero is south if az < 0: az = 360 + az az = math.radians(az) zc = math.sin(alt)*scale ic = math.cos(alt)*scale xc = math.cos(az)*ic yc = math.sin(az)*ic p = FreeCAD.Vector(xc,yc,zc) pts.append(p) hpts[h].append(p) if i in [0,6]: ep = FreeCAD.Vector(p) ep.multiply(1.08) if ep.z >= 0: if h == 12: if i == 0: h = "SUMMER" else: h = "WINTER" if latitude < 0: if h == "SUMMER": h = "WINTER" else: h = "SUMMER" hourpos.append((h,ep)) if i < 7: sunpaths.append(Part.makePolygon(pts)) for h in hpts: if complete: h.append(h[0]) hourpaths.append(Part.makePolygon(h)) # cut underground lines sz = 2.1*scale cube = Part.makeBox(sz,sz,sz) cube.translate(FreeCAD.Vector(-sz/2,-sz/2,-sz)) sunpaths = [sp.cut(cube) for sp in sunpaths] hourpaths = [hp.cut(cube) for hp in hourpaths] # build nodes ts = 0.005*scale # text scale mastersep = coin.SoSeparator() circlesep = coin.SoSeparator() numsep = coin.SoSeparator() pathsep = coin.SoSeparator() hoursep = coin.SoSeparator() hournumsep = coin.SoSeparator() mastersep.addChild(circlesep) mastersep.addChild(numsep) mastersep.addChild(pathsep) mastersep.addChild(hoursep) for item in circles: circlesep.addChild(toNode(item)) for item in sunpaths: for w in item.Edges: pathsep.addChild(toNode(w)) for item in hourpaths: for w in item.Edges: hoursep.addChild(toNode(w)) for p in circlepos: text = coin.SoText2() s = p[0]-90 s = -s if s > 360: s = s - 360 if s < 0: s = 360 + s if s == 0: s = "N" elif s == 90: s = "E" elif s == 180: s = "S" elif s == 270: s = "W" else: s = str(s) text.string = s text.justification = coin.SoText2.CENTER coords = coin.SoTransform() coords.translation.setValue([p[1].x,p[1].y,p[1].z]) coords.scaleFactor.setValue([ts,ts,ts]) item = coin.SoSeparator() item.addChild(coords) item.addChild(text) numsep.addChild(item) for p in hourpos: text = coin.SoText2() s = str(p[0]) text.string = s text.justification = coin.SoText2.CENTER coords = coin.SoTransform() coords.translation.setValue([p[1].x,p[1].y,p[1].z]) coords.scaleFactor.setValue([ts,ts,ts]) item = coin.SoSeparator() item.addChild(coords) item.addChild(text) numsep.addChild(item) return mastersep
def test02(self): '''Verify bones are correctly generated for a Profile.''' doc = FreeCAD.newDocument("TestDressupDogbone") # This is a real world test to make sure none of the tool chain broke box0 = doc.addObject('Part::Box', 'Box') box0.Width = 100 box0.Length = 100 box0.Height = 10 box1 = doc.addObject('Part::Box', 'Box') box1.Width = 50 box1.Length = 50 box1.Height = 20 box1.Placement = FreeCAD.Placement( FreeCAD.Vector(25, 25, -5), FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0)) doc.recompute() cut = doc.addObject('Part::Cut', 'Cut') cut.Base = box0 cut.Tool = box1 doc.recompute() for i in range(11): face = "Face%d" % (i + 1) f = cut.Shape.getElement(face) if f.Surface.Axis == FreeCAD.Vector( 0, 0, 1) and f.Orientation == 'Forward': break PathJob.Create('Job', [cut], None) profile = PathProfileFaces.Create('Profile Faces') profile.Base = (cut, face) profile.StepDown = 5 # set start and final depth in order to eliminate effects of stock (and its default values) profile.setExpression('StartDepth', None) profile.StartDepth = 10 profile.setExpression('FinalDepth', None) profile.FinalDepth = 0 profile.processHoles = True profile.processPerimeter = True doc.recompute() dogbone = PathDressupDogbone.Create(profile) doc.recompute() dog = dogbone.Proxy locs = sorted([bone[1] for bone in dog.bones], key=lambda xy: xy[0] * 1000 + xy[1]) def formatBoneLoc(pt): return "(%.2f, %.2f)" % (pt[0], pt[1]) # Make sure we get 8 bones, 2 in each corner (different heights) # with start point changes it passes back over the same spot multiple times, so just make sure they are in the right locations # self.assertEqual(len(locs), 8) self.assertEqual("(27.50, 27.50)", formatBoneLoc(locs[0])) self.assertEqual("(27.50, 27.50)", formatBoneLoc(locs[1])) self.assertEqual("(27.50, 72.50)", formatBoneLoc(locs[2])) self.assertEqual("(27.50, 72.50)", formatBoneLoc(locs[3])) self.assertEqual("(72.50, 27.50)", formatBoneLoc(locs[4])) self.assertEqual("(72.50, 27.50)", formatBoneLoc(locs[5])) self.assertEqual("(72.50, 72.50)", formatBoneLoc(locs[6])) self.assertEqual("(72.50, 72.50)", formatBoneLoc(locs[7])) FreeCAD.closeDocument("TestDressupDogbone")
def fcvec(x): if len(x) == 2: return (App.Vector(x[0], x[1], 0)) else: return (App.Vector(x[0], x[1], x[2]))
def isDrillable(obj, candidate, tooldiameter=None, includePartials=False): """ Checks candidates to see if they can be drilled. Candidates can be either faces - circular or cylindrical or circular edges. The tooldiameter can be optionally passed. if passed, the check will return False for any holes smaller than the tooldiameter. obj=Shape candidate = Face or Edge tooldiameter=float """ PathLog.track('obj: {} candidate: {} tooldiameter {}'.format( obj, candidate, tooldiameter)) drillable = False try: if candidate.ShapeType == 'Face': face = candidate # eliminate flat faces if (round(face.ParameterRange[0], 8) == 0.0) and (round( face.ParameterRange[1], 8) == round(math.pi * 2, 8)): for edge in face.Edges: # Find seam edge and check if aligned to Z axis. if (isinstance(edge.Curve, Part.Line)): PathLog.debug("candidate is a circle") v0 = edge.Vertexes[0].Point v1 = edge.Vertexes[1].Point #check if the cylinder seam is vertically aligned. Eliminate tilted holes if (numpy.isclose(v1.sub(v0).x, 0, rtol=1e-05, atol=1e-06)) and \ (numpy.isclose(v1.sub(v0).y, 0, rtol=1e-05, atol=1e-06)): drillable = True # vector of top center lsp = Vector(face.BoundBox.Center.x, face.BoundBox.Center.y, face.BoundBox.ZMax) # vector of bottom center lep = Vector(face.BoundBox.Center.x, face.BoundBox.Center.y, face.BoundBox.ZMin) # check if the cylindrical 'lids' are inside the base # object. This eliminates extruded circles but allows # actual holes. if obj.isInside(lsp, 1e-6, False) or obj.isInside( lep, 1e-6, False): PathLog.track( "inside check failed. lsp: {} lep: {}". format(lsp, lep)) drillable = False # eliminate elliptical holes elif not hasattr(face.Surface, "Radius"): PathLog.debug( "candidate face has no radius attribute") drillable = False else: if tooldiameter is not None: drillable = face.Surface.Radius >= tooldiameter / 2 else: drillable = True elif type(face.Surface) == Part.Plane and PathGeom.pointsCoincide( face.Surface.Axis, FreeCAD.Vector(0, 0, 1)): if len(face.Edges) == 1 and type( face.Edges[0].Curve) == Part.Circle: center = face.Edges[0].Curve.Center if obj.isInside(center, 1e-6, False): if tooldiameter is not None: drillable = face.Edges[ 0].Curve.Radius >= tooldiameter / 2 else: drillable = True else: for edge in candidate.Edges: if isinstance(edge.Curve, Part.Circle) and (includePartials or edge.isClosed()): PathLog.debug("candidate is a circle or ellipse") if not hasattr(edge.Curve, "Radius"): PathLog.debug("No radius. Ellipse.") drillable = False else: PathLog.debug("Has Radius, Circle") if tooldiameter is not None: drillable = edge.Curve.Radius >= tooldiameter / 2 if not drillable: FreeCAD.Console.PrintMessage( "Found a drillable hole with diameter: {}: " "too small for the current tool with " "diameter: {}".format( edge.Curve.Radius * 2, tooldiameter)) else: drillable = True PathLog.debug("candidate is drillable: {}".format(drillable)) except Exception as ex: PathLog.warning( translate("PathUtils", "Issue determine drillability: {}").format(ex)) return drillable
def mirror(objlist, p1, p2): """Create a mirror object from the provided list and line. It creates a `Part::Mirroring` object from the given `objlist` using a plane that is defined by the two given points `p1` and `p2`, and either - the Draft working plane normal, or - the negative normal provided by the camera direction if the working plane normal does not exist and the graphical interface is available. If neither of these two is available, it uses as normal the +Z vector. Parameters ---------- objlist: single object or a list of objects A single object or a list of objects. p1: Base::Vector3 Point 1 of the mirror plane. It is also used as the `Placement.Base` of the resulting object. p2: Base::Vector3 Point 1 of the mirror plane. Returns ------- None If the operation fails. list List of `Part::Mirroring` objects, or a single one depending on the input `objlist`. To Do ----- Implement a mirror tool specific to the workbench that does not just use `Part::Mirroring`. It should create a derived object, that is, it should work similar to `Draft.offset`. """ utils.print_header('mirror', "Create mirror") if not objlist: _err(translate("draft", "No object given")) return if p1 == p2: _err(translate("draft", "The two points are coincident")) return if not isinstance(objlist, list): objlist = [objlist] if hasattr(App, "DraftWorkingPlane"): norm = App.DraftWorkingPlane.getNormal() elif App.GuiUp: norm = Gui.ActiveDocument.ActiveView.getViewDirection().negative() else: norm = App.Vector(0, 0, 1) pnorm = p2.sub(p1).cross(norm).normalize() result = [] for obj in objlist: mir = App.ActiveDocument.addObject("Part::Mirroring", "mirror") mir.Label = obj.Label + " (" + translate("draft", "mirrored") + ") " mir.Source = obj mir.Base = p1 mir.Normal = pnorm gui_utils.format_object(mir, obj) result.append(mir) if len(result) == 1: result = result[0] gui_utils.select(result) return result
def settarget(self): '''set the target depending on the mouse wheel roll and mode key''' if self.imode == 3: print "SET IMODE 3" ef = self.ef self.dials.setValue(min(ef.mouseWheel, 99)) self.setsharp3(min(ef.mouseWheel, 99)) #return if self.imode == 4: print "SET IMODE 4" self.settarget4() return dok = self.helperDok() pl = len(self.points) self.dial.setMaximum(pl - 1) pos = self.dial.value() if pos == 0: lpos = pl - 1 else: lpos = pos - 1 if pos == pl - 1: rpos = 0 else: rpos = pos + 1 # print ('pl,pos,lpos,rpos',pl,pos,lpos,rpos) if self.imode <> 3: diff = FreeCAD.Vector() ef = self.ef if ef.key in ['x', 'y', 'z']: kx, ky, kz = 0, 0, 0 if ef.key == 'x': kx = ef.mouseWheel * FreeCAD.ParamGet( 'User parameter:Plugins/nurbs').GetFloat( "MoveWheelStep", 1) if ef.key == 'y': ky = ef.mouseWheel * FreeCAD.ParamGet( 'User parameter:Plugins/nurbs').GetFloat( "MoveWheelStep", 1) if ef.key == 'z': kz = ef.mouseWheel * FreeCAD.ParamGet( 'User parameter:Plugins/nurbs').GetFloat( "MoveWheelStep", 1) #changed point diff = FreeCAD.Vector(kx, ky, kz) t = self.points[pos] + diff elif ef.key == 't': a = FreeCAD.Vector(self.points[lpos]) - FreeCAD.Vector( self.points[rpos]) a.normalize() diff = a.multiply( ef.mouseWheel * FreeCAD.ParamGet('User parameter:Plugins/nurbs').GetFloat( "MoveWheelStep", 1)) t = self.points[pos] + diff elif ef.key == 'n' or ef.key == 'b': a = FreeCAD.Vector(self.points[lpos]) - FreeCAD.Vector( self.points[rpos]) b = FreeCAD.Vector(self.points[lpos]) - FreeCAD.Vector( self.points[pos]) c = a.cross(b) if ef.key == 'n': d = c.cross(a) else: d = c d.normalize() diff = d.multiply( ef.mouseWheel * FreeCAD.ParamGet('User parameter:Plugins/nurbs').GetFloat( "MoveWheelStep", 1)) t = self.points[pos] + diff elif ef.key == 'r': d = FreeCAD.Vector(self.points[pos][0], self.points[pos][1], 0).normalize() diff = d.multiply( ef.mouseWheel * FreeCAD.ParamGet('User parameter:Plugins/nurbs').GetFloat( "MoveWheelStep", 1)) t = self.points[pos] + diff else: print("mode not implemented ", ef.key) t = self.points[pos] #self.target(dok, t) print("settarget cc imode", self.imode) print("diff", diff) if self.imode == 1: self.target(dok, coordlist=[ self.points[pos - 1] + diff, t, self.points[pos + 1] + diff ]) else: self.target(dok, coordlist=[t]) # try: dok.Sphere # except: # s=dok.addObject("Part::Sphere","Sphere") # s.Radius=10000000 # s.ViewObject.Selectable=False # s.ViewObject.ShapeColor=(1.,1.,1.) # s.ViewObject.DisplayMode = u"Shaded" # s.ViewObject.DisplayMode = u"Shaded" # create or get traget curve pp = self.points if pos > 0: pp2 = pp[:pos] + [t] + pp[pos + 1:] else: pp2 = [t] + pp[pos + 1:] # bspline curve bs = dok.BSpline.Shape.Edge1.Curve.copy() bs.setPole(pos + 1, FreeCAD.Vector(t)) if self.imode == 1: bs.setPole(pos, self.points[pos - 1] + diff) bs.setPole(pos + 2, self.points[pos + 1] + diff) dok.BSpline.Shape = bs.toShape() pol = Part.makePolygon(pp2 + [pp2[0]]) else: pp2 = self.points # pole polygon pol = Part.makePolygon(pp2 + [pp2[0]]) # bb.Shape=pol bs = dok.BSpline.Shape.Edge1.Curve.copy() try: bb = dok.TargetCurve bax = dok.TargetExtra except: bb = dok.addObject('Part::Feature', 'TargetCurve') bax = dok.addObject('Part::Feature', 'TargetExtra') bax.ViewObject.LineColor = (1.0, 1.0, 0.0) pp3 = [] ppax = [] if self.source == 'Backbone': print "recompute Backbone #########################################" xV = FreeCAD.Vector(100, 0, 0) yV = FreeCAD.Vector(0, 100, 0) zV = FreeCAD.Vector(0, 0, 141) source = self.getsource() needle = source.InList[0] curvea, bba, scaler, twister = needle.Proxy.Model() for i, p in enumerate(pp2): # print (i,twister[i],scaler[i]) [xa, ya, za] = twister[i] if pos == i: xa += self.rotx ya += self.roty za += self.rotz if pos == i: xa = self.rotx ya = self.roty za = self.rotz p2 = FreeCAD.Placement() p2.Rotation = FreeCAD.Rotation(FreeCAD.Vector( 0, 0, 1), za).multiply( FreeCAD.Rotation(FreeCAD.Vector(0, 1, 0), ya).multiply( FreeCAD.Rotation(FreeCAD.Vector(1, 0, 0), xa))) ph = FreeCAD.Placement() ph.Base = xV xR = p2.multiply(ph).Base ph = FreeCAD.Placement() ph.Base = yV yR = p2.multiply(ph).Base ph = FreeCAD.Placement() ph.Base = zV zR = p2.multiply(ph).Base p = FreeCAD.Vector(p) if 1: pp = Part.makePolygon([p, p + xR, p + xR + yR, p]) ps = Part.Face(pp) ppax.append(ps) pp = Part.makePolygon([p, p + yR, p + xR + yR, p]) ppax.append(Part.Face(pp)) pp = Part.makePolygon([p, p + zR, p + xR + yR, p]) ppax.append(Part.Face(pp)) # all together bb.Shape = Part.Compound([pol]) if ppax <> []: bax.Shape = Part.Compound(ppax + [bs.toShape()]) dok.recompute() bb.ViewObject.LineColor = (1.0, 0.6, .0) bb.ViewObject.LineWidth = 1 bb.ViewObject.PointColor = (.8, 0.4, .0) bb.ViewObject.PointSize = 8 bax.ViewObject.Selectable = False col = [] for i in range(len(bax.Shape.Faces)): tt = i % 3 if tt == 0: col.append((1., 0., 0.)) elif tt == 1: col.append((0., 1., 0.)) else: col.append((0., 0., 1.)) # bax.ViewObject.DiffuseColor=col bax.ViewObject.LineColor = (1.0, 0.0, 0.0)
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 # transformer transformer = Part.makeBox(65.4, 50.8, 87.4776) # ferroxcube_1 ferroxcube_1 = Part.makeBox(28, 16, 87.4776) ferroxcube_1_vector = FreeCAD.Vector(18.7, 17.4, 0) ferroxcube_1.translate(ferroxcube_1_vector) # cut transformer with ferroxcube_1 transformer = transformer.cut(ferroxcube_1) # coil coil = Part.makeBox(65.4, 50.8, 33.3248) # ferroxcube_2 ferroxcube_2 = Part.makeBox(32, 20, 33.3248) ferroxcube_2_vector = FreeCAD.Vector(16.7, 15.4, 0) ferroxcube_2.translate(ferroxcube_2_vector) # cut coil with ferroxcube_2 coil = coil.cut(ferroxcube_2)
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 testWall(self): App.Console.PrintLog('Checking Arch Wall...\n') l = Draft.makeLine(App.Vector(0, 0, 0), App.Vector(-2, 0, 0)) w = Arch.makeWall(l) self.failUnless(w, "Arch Wall failed")
def execute(self, obj): if len(obj.InList) != 1: return if Draft.getType(obj.InList[0]) != "Structure": return if not obj.InList[0].Shape: 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.InList[0] 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(obj) if not bpoint: return axis = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0, 0, -1)) size = (ArchCommands.projectToVector(father.Shape.copy(), axis)).Length if hasattr(obj, "Direction"): if not DraftVecUtils.isNull(obj.Direction): axis = FreeCAD.Vector(obj.Direction) #.normalize() # don't normalize so the vector can also be used to determine the distance size = axis.Length #print axis #print size 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: print "Arch: error sweeping rebar profile along the base sketch" return # building final shape shapes = [] if obj.Amount == 1: offset = DraftVecUtils.scaleTo(axis, size / 2) bar.translate(offset) shapes.append(bar) 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) vinterval = DraftVecUtils.scaleTo(axis, interval) for i in range(obj.Amount): if i == 0: if baseoffset: bar.translate(baseoffset) shapes.append(bar) else: bar = bar.copy() bar.translate(vinterval) shapes.append(bar) if hasattr(obj, "Spacing"): obj.Spacing = interval if shapes: obj.Shape = Part.makeCompound(shapes) obj.Placement = pl
def testWallMultiMatAlign(self): App.Console.PrintLog( 'Checking Arch Wall with MultiMaterial and 3 alignments...\n') matA = Arch.makeMaterial() matB = Arch.makeMaterial() matMulti = Arch.makeMultiMaterial() matMulti.Materials = [matA, matB] matMulti.Thicknesses = [100, 200] # total width different from default 200 pts = [ App.Vector(0, 0, 0), App.Vector(1000, 0, 0), App.Vector(1000, 1000, 0), App.Vector(2000, 1000, 0) ] # wall based on wire: wire = Draft.makeWire(pts) wallWire = Arch.makeWall(wire) wallWire.Material = matMulti # wall based on sketch: sketch = App.activeDocument().addObject('Sketcher::SketchObject', 'Sketch') sketch.addGeometry([ Part.LineSegment(pts[0], pts[1]), Part.LineSegment(pts[1], pts[2]), Part.LineSegment(pts[2], pts[3]) ]) wallSketch = Arch.makeWall(sketch) wallSketch.Material = matMulti alignLst = ["Left", "Center", "Right"] checkLst = [[App.Vector(0, -300, 0), App.Vector(2000, 1000, 0)], [App.Vector(0, -150, 0), App.Vector(2000, 1150, 0)], [App.Vector(0, 0, 0), App.Vector(2000, 1300, 0)]] for i in range(3): wallWire.Align = alignLst[i] wallSketch.Align = alignLst[i] App.ActiveDocument.recompute() for box in [wallWire.Shape.BoundBox, wallSketch.Shape.BoundBox]: ptMin = App.Vector(box.XMin, box.YMin, 0) self.failUnless( ptMin.isEqual(checkLst[i][0], 1e-8), "Arch Wall with MultiMaterial and 3 alignments failed") ptMax = App.Vector(box.XMax, box.YMax, 0) self.failUnless( ptMax.isEqual(checkLst[i][1], 1e-8), "Arch Wall with MultiMaterial and 3 alignments failed")
def getpointsOfUShapeRebar( FacePRM: Tuple[Tuple[float, float], Tuple[float, float]], r_cover: float, l_cover: float, b_cover: float, t_cover: float, orientation: Literal["Bottom", "Top", "Left", "Right"], diameter: float, face_normal: FreeCAD.Vector, ) -> List[FreeCAD.Vector]: """getpointsOfUShapeRebar(FacePRM, RightCover, LeftCover, BottomCover, TopCover, Orientation, Diameter, FaceNormal): Return points of the UShape rebar in the form of array for sketch. It takes four different orientations input i.e. 'Bottom', 'Top', 'Left', 'Right'. """ center_x = FacePRM[1][0] center_y = FacePRM[1][1] # When Left/Rear Face of structure is selected if round(face_normal[0]) == -1 or round(face_normal[1]) == 1: center_x = -center_x # When Bottom Face of structure is selected elif round(face_normal[2]) == -1: center_y = -center_y if orientation == "Bottom": l_cover += diameter / 2 r_cover += diameter / 2 b_cover += diameter / 2 x1 = center_x - FacePRM[0][0] / 2 + l_cover y1 = center_y + FacePRM[0][1] / 2 - t_cover x2 = center_x - FacePRM[0][0] / 2 + l_cover y2 = center_y - FacePRM[0][1] / 2 + b_cover x3 = center_x + FacePRM[0][0] / 2 - r_cover y3 = center_y - FacePRM[0][1] / 2 + b_cover x4 = center_x + FacePRM[0][0] / 2 - r_cover y4 = center_y + FacePRM[0][1] / 2 - t_cover elif orientation == "Top": l_cover += diameter / 2 r_cover += diameter / 2 t_cover += diameter / 2 x1 = center_x - FacePRM[0][0] / 2 + l_cover y1 = center_y - FacePRM[0][1] / 2 + b_cover x2 = center_x - FacePRM[0][0] / 2 + l_cover y2 = center_y + FacePRM[0][1] / 2 - t_cover x3 = center_x + FacePRM[0][0] / 2 - r_cover y3 = center_y + FacePRM[0][1] / 2 - t_cover x4 = center_x + FacePRM[0][0] / 2 - r_cover y4 = center_y - FacePRM[0][1] / 2 + b_cover elif orientation == "Left": l_cover += diameter / 2 t_cover += diameter / 2 b_cover += diameter / 2 x1 = center_x + FacePRM[0][0] / 2 - r_cover y1 = center_y + FacePRM[0][1] / 2 - t_cover x2 = center_x - FacePRM[0][0] / 2 + l_cover y2 = center_y + FacePRM[0][1] / 2 - t_cover x3 = center_x - FacePRM[0][0] / 2 + l_cover y3 = center_y - FacePRM[0][1] / 2 + b_cover x4 = center_x + FacePRM[0][0] / 2 - r_cover y4 = center_y - FacePRM[0][1] / 2 + b_cover elif orientation == "Right": r_cover += diameter / 2 t_cover += diameter / 2 b_cover += diameter / 2 x1 = center_x - FacePRM[0][0] / 2 + l_cover y1 = center_y + FacePRM[0][1] / 2 - t_cover x2 = center_x + FacePRM[0][0] / 2 - r_cover y2 = center_y + FacePRM[0][1] / 2 - t_cover x3 = center_x + FacePRM[0][0] / 2 - r_cover y3 = center_y - FacePRM[0][1] / 2 + b_cover x4 = center_x - FacePRM[0][0] / 2 + l_cover y4 = center_y - FacePRM[0][1] / 2 + b_cover else: FreeCAD.Console.PrintError(f"Invalid orientation: {orientation}\n") return [] return [ FreeCAD.Vector(x1, y1, 0), FreeCAD.Vector(x2, y2, 0), FreeCAD.Vector(x3, y3, 0), FreeCAD.Vector(x4, y4, 0), ]
def testFrame(self): App.Console.PrintLog('Checking Arch Frame...\n') l = Draft.makeLine(App.Vector(0, 0, 0), App.Vector(-2, 0, 0)) p = Draft.makeRectangle(length=.5, height=.5) f = Arch.makeFrame(l, p) self.failUnless(f, "Arch Frame failed")
class Camera: """A camera for rendering. This object allows to record camera settings from the Coin camera, and to reuse them for rendering. Camera Orientation is defined by a Rotation Axis and a Rotation Angle, applied to 'default camera'. Default camera looks from (0,0,1) towards the origin (target is (0,0,-1), and the up direction is (0,1,0). For more information, see Coin documentation, Camera section. <https://developer.openinventor.com/UserGuides/Oiv9/Inventor_Mentor/Cameras_and_Lights/Cameras.html> """ # Enumeration of allowed values for ViewportMapping parameter (see Coin # documentation) # Nota: Keep following tuple in original order, as relationship between # values and indexes matters and is used for reverse transcoding VIEWPORTMAPPINGENUM = ("CROP_VIEWPORT_FILL_FRAME", "CROP_VIEWPORT_LINE_FRAME", "CROP_VIEWPORT_NO_FRAME", "ADJUST_CAMERA", "LEAVE_ALONE") Prop = namedtuple('Prop', ['Type', 'Group', 'Doc', 'Default']) # FeaturePython object properties PROPERTIES = { "Projection": Prop( "App::PropertyEnumeration", "Camera", QT_TRANSLATE_NOOP("Render", "Type of projection: Perspective/Orthographic"), ("Perspective", "Orthographic")), "Placement": Prop("App::PropertyPlacement", "", QT_TRANSLATE_NOOP("Render", "Placement of camera"), App.Placement(App.Vector(0, 0, 0), App.Vector(0, 0, 1), 0)), "ViewportMapping": Prop("App::PropertyEnumeration", "Camera", QT_TRANSLATE_NOOP("Render", "(See Coin documentation)"), VIEWPORTMAPPINGENUM), "AspectRatio": Prop("App::PropertyFloat", "Camera", QT_TRANSLATE_NOOP("Render", "Ratio width/height of the camera."), 1.0), "NearDistance": Prop("App::PropertyDistance", "Camera", QT_TRANSLATE_NOOP("Render", "Near distance, for clipping"), 0.0), "FarDistance": Prop("App::PropertyDistance", "Camera", QT_TRANSLATE_NOOP("Render", "Far distance, for clipping"), 200.0), "FocalDistance": Prop("App::PropertyDistance", "Camera", QT_TRANSLATE_NOOP("Render", "Focal distance"), 100.0), "Height": Prop("App::PropertyLength", "Camera", QT_TRANSLATE_NOOP("Render", "Height, for orthographic camera"), 5.0), "HeightAngle": Prop( "App::PropertyAngle", "Camera", QT_TRANSLATE_NOOP("Render", "Height angle, for perspective camera"), 60), } # ~FeaturePython object properties _fpos = dict() # FeaturePython objects @classmethod def set_properties(cls, fpo): """Set underlying FeaturePython object's properties""" for name in cls.PROPERTIES.keys() - set(fpo.PropertiesList): spec = cls.PROPERTIES[name] prop = fpo.addProperty(spec.Type, name, spec.Group, spec.Doc, 0) setattr(prop, name, spec.Default) def __init__(self, fpo): """Camera Initializer Arguments --------- fpo: a FeaturePython object created with FreeCAD.addObject """ self.type = "Camera" fpo.Proxy = self self.fpo = fpo self.set_properties(fpo) @property def fpo(self): """Underlying FeaturePython object getter""" return self._fpos[id(self)] @fpo.setter def fpo(self, new_fpo): """Underlying FeaturePython object setter""" self._fpos[id(self)] = new_fpo @staticmethod def create(document=None): """Create a Camera object in a document Factory method to create a new camera object. The camera is created into the active document (default). Optionally, it is possible to specify a target document, in that case the camera is created in the given document. If Gui is up, the camera is initialized to current active camera; otherwise it is set to DEFAULT_CAMERA_STRING. This method also create the FeaturePython and the ViewProviderCamera related objects. Params: document: the document where to create camera (optional) Returns: The newly created Camera object, the FeaturePython object and the ViewProviderCamera object""" doc = document if document else App.ActiveDocument fpo = doc.addObject("App::FeaturePython", "Camera") cam = Camera(fpo) viewp = ViewProviderCamera(fpo.ViewObject) if App.GuiUp: viewp.set_camera_from_gui() else: set_cam_from_coin_string(fpo, DEFAULT_CAMERA_STRING) App.ActiveDocument.recompute() return cam, fpo, viewp def onDocumentRestored(self, fpo): """Callback triggered when document is restored""" self.type = "Camera" fpo.Proxy = self self.fpo = fpo self.set_properties(fpo) def execute(self, fpo): # pylint: disable=no-self-use """Callback triggered on document recomputation (mandatory). It mainly draws the camera graphical representation""" def point_at(self, point): """Make camera point at a given target point Parameters: ----------- point -- point to point at (must have x, y, z properties) """ fpo = self.fpo current_target = fpo.Placement.Rotation.multVec(App.Vector(0, 0, -1)) base = fpo.Placement.Base new_target = App.Vector(point.x - base.x, point.y - base.y, point.z - base.z) axis = current_target.cross(new_target) if not axis.Length: # Don't try to rotate if axis is a null vector... return angle = degrees(new_target.getAngle(current_target)) rotation = App.Rotation(axis, angle) fpo.Placement.Rotation = rotation.multiply(fpo.Placement.Rotation)
def areaOpShapes(self, obj): '''areaOpShapes(obj) ... return top face''' # Facing is done either against base objects holeShape = None PathLog.debug('depthparams: {}'.format([i for i in self.depthparams])) if obj.Base: PathLog.debug("obj.Base: {}".format(obj.Base)) faces = [] holes = [] holeEnvs = [] oneBase = [obj.Base[0][0], True] sub0 = getattr(obj.Base[0][0].Shape, obj.Base[0][1][0]) minHeight = sub0.BoundBox.ZMax for b in obj.Base: for sub in b[1]: shape = getattr(b[0].Shape, sub) if isinstance(shape, Part.Face): faces.append(shape) if shape.BoundBox.ZMin < minHeight: minHeight = shape.BoundBox.ZMin # Limit to one model base per operation if oneBase[0] is not b[0]: oneBase[1] = False if numpy.isclose(abs(shape.normalAt(0, 0).z), 1): # horizontal face # Analyze internal closed wires to determine if raised or a recess for wire in shape.Wires[1:]: if obj.ExcludeRaisedAreas: ip = self.isPocket(b[0], shape, wire) if ip is False: holes.append((b[0].Shape, wire)) else: holes.append((b[0].Shape, wire)) else: PathLog.warning('The base subobject, "{0}," is not a face. Ignoring "{0}."'.format(sub)) if obj.ExcludeRaisedAreas and len(holes) > 0: for shape, wire in holes: f = Part.makeFace(wire, 'Part::FaceMakerSimple') env = PathUtils.getEnvelope(shape, subshape=f, depthparams=self.depthparams) holeEnvs.append(env) holeShape = Part.makeCompound(holeEnvs) PathLog.debug("Working on a collection of faces {}".format(faces)) planeshape = Part.makeCompound(faces) # If no base object, do planing of top surface of entire model else: planeshape = Part.makeCompound([base.Shape for base in self.model]) PathLog.debug("Working on a shape {}".format(obj.Label)) # Find the correct shape depending on Boundary shape. PathLog.debug("Boundary Shape: {}".format(obj.BoundaryShape)) bb = planeshape.BoundBox # Apply offset for clearing edges offset = 0 if obj.ClearEdges: offset = self.radius + 0.1 bb.XMin = bb.XMin - offset bb.YMin = bb.YMin - offset bb.XMax = bb.XMax + offset bb.YMax = bb.YMax + offset 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) if obj.ExcludeRaisedAreas and oneBase[1]: includedFaces = self.getAllIncludedFaces(oneBase[0], env, faceZ=minHeight) if len(includedFaces) > 0: includedShape = Part.makeCompound(includedFaces) includedEnv = PathUtils.getEnvelope(oneBase[0].Shape, subshape=includedShape, depthparams=self.depthparams) env = env.cut(includedEnv) elif obj.BoundaryShape == 'Stock': stock = PathUtils.findParentJob(obj).Stock.Shape env = stock if obj.ExcludeRaisedAreas and oneBase[1]: includedFaces = self.getAllIncludedFaces(oneBase[0], stock, faceZ=minHeight) if len(includedFaces) > 0: stockEnv = PathUtils.getEnvelope(partshape=stock, depthparams=self.depthparams) includedShape = Part.makeCompound(includedFaces) includedEnv = PathUtils.getEnvelope(oneBase[0].Shape, subshape=includedShape, depthparams=self.depthparams) env = stockEnv.cut(includedEnv) elif obj.BoundaryShape == 'Perimeter': if obj.ClearEdges: psZMin = planeshape.BoundBox.ZMin ofstShape = PathUtils.getOffsetArea(planeshape, self.radius * 1.25, plane=planeshape) ofstShape.translate(FreeCAD.Vector(0.0, 0.0, psZMin - ofstShape.BoundBox.ZMin)) env = PathUtils.getEnvelope(partshape=ofstShape, depthparams=self.depthparams) else: env = PathUtils.getEnvelope(partshape=planeshape, depthparams=self.depthparams) elif obj.BoundaryShape == 'Face Region': import PathScripts.PathSurfaceSupport as PathSurfaceSupport baseShape = oneBase[0].Shape psZMin = planeshape.BoundBox.ZMin ofstShape = PathUtils.getOffsetArea(planeshape, self.tool.Diameter * 1.1, plane=planeshape) ofstShape.translate(FreeCAD.Vector(0.0, 0.0, psZMin - ofstShape.BoundBox.ZMin)) custDepthparams = self._customDepthParams(obj, obj.StartDepth.Value + 0.1, obj.FinalDepth.Value - 0.1) # only an envelope ofstShapeEnv = PathUtils.getEnvelope(partshape=ofstShape, depthparams=custDepthparams) env = ofstShapeEnv.cut(baseShape) if holeShape: PathLog.debug("Processing holes and face ...") holeEnv = PathUtils.getEnvelope(partshape=holeShape, depthparams=self.depthparams) newEnv = env.cut(holeEnv) tup = newEnv, False, 'pathMillFace', 0.0, 'X', obj.StartDepth.Value, obj.FinalDepth.Value else: PathLog.debug("Processing solid face ...") tup = env, False, 'pathMillFace', 0.0, 'X', obj.StartDepth.Value, obj.FinalDepth.Value return [tup]