commit
64302c1b92
10 changed files with 935 additions and 0 deletions
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
# Workbench LaserCladding |
||||
import FreeCAD as App |
||||
|
||||
# add Import/Export types |
||||
#App.addExportType("Kuka KRL (*.src)", "exportKukaSrc") |
||||
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
import FreeCAD as App |
||||
|
||||
class LaserCladding (Workbench): |
||||
MenuText = "Laser Cladding" |
||||
ToolTip = "Create Simple Path on workpieces for Laser Cladding" |
||||
Icon = """""" |
||||
|
||||
def __init__(self): |
||||
__dirname__ = os.path.join(FreeCAD.getUserAppDataDir(), "Mod", "LaserCladding") |
||||
_tooltip = "The LaserCladding Workbench can create Paths for Robots" |
||||
self.__class__.Icon = os.path.join(__dirname__, |
||||
"Resources", "icons", |
||||
"Laser_Workbench.svg") |
||||
|
||||
def Initialize(self): |
||||
"""This function is executed when the workbench is first activated. |
||||
It is executed once in a FreeCAD session followed by the Activated function. |
||||
""" |
||||
import lasercladding |
||||
|
||||
self.list = ["CreateCladdingJob", "SelectBaseReference", "CreatePad"] # A list of command names created in the line above |
||||
self.appendToolbar("My Commands",self.list) # creates a new toolbar with your commands |
||||
self.appendMenu("LaserCladding",self.list) # creates a new menu |
||||
self.appendMenu(["LaserCladding","My submenu"],self.list) # appends a submenu to an existing menu |
||||
|
||||
def Activated(self): |
||||
"""This function is executed whenever the workbench is activated""" |
||||
#from importlib import reload |
||||
#reload(lccmd) |
||||
return |
||||
|
||||
def Deactivated(self): |
||||
"""This function is executed whenever the workbench is deactivated""" |
||||
return |
||||
|
||||
def ContextMenu(self, recipient): |
||||
"""This function is executed whenever the user right-clicks on screen""" |
||||
# "recipient" will be either "view" or "tree" |
||||
self.appendContextMenu("My commands",self.list) # add commands to the context menu |
||||
|
||||
def GetClassName(self): |
||||
# This function is mandatory if this is a full Python workbench |
||||
# This is not a template, the returned string should be exactly "Gui::PythonWorkbench" |
||||
return "Gui::PythonWorkbench" |
||||
|
||||
|
||||
Gui.addWorkbench(LaserCladding()) |
||||
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
<RCC> |
||||
<qresource> |
||||
<file>icons/Laser_Workbench.svg</file> |
||||
<!-- <file>ui/preferences-draft.ui</file> --> |
||||
</qresource> |
||||
</RCC> |
||||
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
# module lasercladding |
||||
|
||||
from .commands import * |
||||
from .path import * |
||||
from .job import * |
||||
from .kuka import * |
||||
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
import FreeCAD as App |
||||
import FreeCADGui as Gui |
||||
import Part |
||||
|
||||
|
||||
from .job import LaserJob, ViewProviderLaserJob |
||||
from .pad import LaserPad, create_laserpad |
||||
|
||||
class CreateCladdingJob(): |
||||
def Activated(self): |
||||
# Here your write what your ScriptCmd does... |
||||
App.Console.PrintMessage('Create Lasser Cladding Job') |
||||
a=App.ActiveDocument.addObject("App::FeaturePython","LaserJob") |
||||
LaserJob(a) |
||||
ViewProviderLaserJob(a.ViewObject) |
||||
|
||||
def GetResources(self): |
||||
return {'Pixmap' : 'path_to_an_icon/myicon.png', 'MenuText': 'Create Cladding Job', 'ToolTip': 'Add a Job to your Document'} |
||||
|
||||
|
||||
class SelectBaseReference(): |
||||
def Activated(self): |
||||
# Here your write what your ScriptCmd does... |
||||
App.Console.PrintMessage('Select Base reference!') |
||||
if not Gui.Selection.hasSelection(): |
||||
App.Console.PrintMessage('Select a Vertex') |
||||
return |
||||
# check length |
||||
selection = Gui.Selection.getSelectionEx() |
||||
# find first vertex |
||||
for s in selection: |
||||
if s.HasSubObjects: |
||||
for obj in s.SubObjects: |
||||
if isinstance(obj, Part.Vertex): |
||||
vertex = obj.copy() |
||||
laserjob_entry = App.ActiveDocument.getObject('LaserJob') |
||||
if laserjob_entry is None: |
||||
App.Console.PrintMessage('Create a LaserJob first') |
||||
return |
||||
laserjob_entry.base_reference = App.Vector((vertex.X, vertex.Y, vertex.Z)) |
||||
App.ActiveDocument.recompute() |
||||
|
||||
|
||||
def GetResources(self): |
||||
return {'Pixmap' : 'path_to_an_icon/myicon.png', 'MenuText': 'Select Base reference', 'ToolTip': 'Add a Job to your Document'} |
||||
|
||||
|
||||
class CreatePad(): |
||||
def Activated(self): |
||||
# Here your write what your ScriptCmd does... |
||||
App.Console.PrintMessage('Select some Face as reference') |
||||
if not Gui.Selection.hasSelection(): |
||||
App.Console.PrintMessage('Select a Face') |
||||
return |
||||
# check length |
||||
ref_face = (Gui.Selection.getSelection()[0], |
||||
Gui.Selection.getSelectionEx()[0].SubElementNames[0]) |
||||
#selection = Gui.Selection.getSelectionEx() |
||||
# find first vertex |
||||
#for s in selection: |
||||
# if s.HasSubObjects: |
||||
# for obj in s.SubObjects: |
||||
# if isinstance(obj, Part.Face): |
||||
# face = obj.copy() |
||||
create_laserpad(ref_face) |
||||
App.ActiveDocument.recompute() |
||||
|
||||
|
||||
def GetResources(self): |
||||
return {'Pixmap' : 'path_to_an_icon/myicon.png', 'MenuText': 'Select Base reference', 'ToolTip': 'Add a Job to your Document'} |
||||
|
||||
|
||||
|
||||
|
||||
Gui.addCommand('CreateCladdingJob', CreateCladdingJob()) |
||||
Gui.addCommand('SelectBaseReference', SelectBaseReference()) |
||||
Gui.addCommand('CreatePad', CreatePad()) |
||||
@ -0,0 +1,110 @@
@@ -0,0 +1,110 @@
|
||||
import FreeCAD as App |
||||
|
||||
|
||||
class LaserJob: |
||||
def __init__(self, obj): |
||||
'''Add some custom properties to our box feature''' |
||||
obj.addProperty("App::PropertyVector", "base_reference", "Reference", "Reference Point (teached)") |
||||
obj.base_reference = App.Vector(0,0,0) |
||||
|
||||
## to make addObject() available |
||||
obj.addExtension("App::GroupExtensionPython", None) |
||||
obj.Proxy = self |
||||
|
||||
def addObject(self, obj): |
||||
self.pads = [obj] |
||||
|
||||
def onChanged(self, fp, prop): |
||||
'''Do something when a property has changed''' |
||||
App.Console.PrintMessage("Change property: " + str(prop) + "\n") |
||||
|
||||
def execute(self, fp): |
||||
'''Do something when doing a recomputation, this method is mandatory''' |
||||
App.Console.PrintMessage("Recompute Python Box feature\n") |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ViewProviderLaserJob: |
||||
def __init__(self, obj): |
||||
'''Set this object to the proxy object of the actual view provider''' |
||||
obj.addProperty("App::PropertyColor","Color","Box","Color of the box").Color=(1.0,0.0,0.0) |
||||
|
||||
obj.addExtension("Gui::ViewProviderGroupExtensionPython", None) |
||||
|
||||
obj.Proxy = self |
||||
|
||||
def attach(self, obj): |
||||
'''Setup the scene sub-graph of the view provider, this method is mandatory''' |
||||
self.onChanged(obj,"Color") |
||||
|
||||
def updateData(self, fp, prop): |
||||
'''If a property of the handled feature has changed we have the chance to handle this here''' |
||||
# fp is the handled feature, prop is the name of the property that has changed |
||||
pass |
||||
|
||||
def getDisplayModes(self,obj): |
||||
'''Return a list of display modes.''' |
||||
modes=[] |
||||
modes.append("Shaded") |
||||
modes.append("Wireframe") |
||||
return modes |
||||
|
||||
def getDefaultDisplayMode(self): |
||||
'''Return the name of the default display mode. It must be defined in getDisplayModes.''' |
||||
return "Shaded" |
||||
|
||||
def setDisplayMode(self,mode): |
||||
'''Map the display mode defined in attach with those defined in getDisplayModes.\ |
||||
Since they have the same names nothing needs to be done. This method is optional''' |
||||
return mode |
||||
|
||||
def onChanged(self, vp, prop): |
||||
'''Here we can do something when a single property got changed''' |
||||
App.Console.PrintMessage("Change property: " + str(prop) + "\n") |
||||
#if prop == "Color": |
||||
# c = vp.getPropertyByName("Color") |
||||
# self.color.rgb.setValue(c[0],c[1],c[2]) |
||||
|
||||
def getIcon(self): |
||||
'''Return the icon in XPM format which will appear in the tree view. This method is\ |
||||
optional and if not defined a default icon is shown.''' |
||||
return """ |
||||
/* XPM */ |
||||
static const char * ViewProviderBox_xpm[] = { |
||||
"16 16 6 1", |
||||
" c None", |
||||
". c #141010", |
||||
"+ c #615BD2", |
||||
"@ c #C39D55", |
||||
"# c #000000", |
||||
"$ c #57C355", |
||||
" ........", |
||||
" ......++..+..", |
||||
" .@@@@.++..++.", |
||||
" .@@@@.++..++.", |
||||
" .@@ .++++++.", |
||||
" ..@@ .++..++.", |
||||
"###@@@@ .++..++.", |
||||
"##$.@@$#.++++++.", |
||||
"#$#$.$$$........", |
||||
"#$$####### ", |
||||
"#$$#$$$$$# ", |
||||
"#$$#$$$$$# ", |
||||
"#$$#$$$$$# ", |
||||
" #$#$$$$$# ", |
||||
" ##$$$$$# ", |
||||
" ####### "}; |
||||
""" |
||||
|
||||
def __getstate__(self): |
||||
'''When saving the document this object gets stored using Python's json module.\ |
||||
Since we have some un-serializable parts here -- the Coin stuff -- we must define this method\ |
||||
to return a tuple of all serializable objects or None.''' |
||||
return None |
||||
|
||||
def __setstate__(self,state): |
||||
'''When restoring the serialized object from document we have the chance to set some internals here.\ |
||||
Since no data were serialized nothing needs to be done here.''' |
||||
return None |
||||
@ -0,0 +1,149 @@
@@ -0,0 +1,149 @@
|
||||
import FreeCAD as App |
||||
import numpy as np |
||||
from . import kuka |
||||
|
||||
|
||||
class LaserPad: |
||||
def __init__(self, obj, face): |
||||
'''Add some custom properties to our box feature''' |
||||
obj.addProperty("App::PropertyEnumeration", "pathtype", "SlicingParameters", "Type of Path generation (slice, etc)") |
||||
obj.pathtype = ["sliced", "auto", "wire"] |
||||
|
||||
obj.addProperty("App::PropertyEnumeration", "slicedirection", "SlicingParameters", "When Slicing, which direction to use") |
||||
obj.slicedirection = ["xaxis", "yaxis", "zaxis", "custom"] |
||||
|
||||
obj.addProperty("App::PropertyLinkSub","ref_surface","SlicingParameters","reference_1") |
||||
obj.ref_surface = face |
||||
|
||||
obj.Proxy = self |
||||
|
||||
def onChanged(self, fp, prop): |
||||
'''Do something when a property has changed''' |
||||
App.Console.PrintMessage("Change property: " + str(prop) + "\n") |
||||
|
||||
def execute(self, fp): |
||||
'''Do something when doing a recomputation, this method is mandatory''' |
||||
App.Console.PrintMessage("Recompute LaserPad\n") |
||||
face = fp.ref_surface[0].getSubObject(fp.ref_surface[1])[0] |
||||
print(face) |
||||
|
||||
if fp.pathtype == "sliced": |
||||
xmin = face.BoundBox.XMin |
||||
xmax = face.BoundBox.XMax |
||||
ymin = face.BoundBox.YMin |
||||
ymax = face.BoundBox.YMax |
||||
slice_direction = App.Vector(0,0,0) |
||||
if fp.slicedirection == "xaxis": |
||||
slice_direction = App.Vector(1,0,0) |
||||
pmin, pmax = xmin, xmax |
||||
if fp.slicedirection == "yaxis": |
||||
slice_direction = App.Vector(0,1,0) |
||||
pmin, pmax = ymin, ymax |
||||
if fp.slicedirection == "zaxis": |
||||
slice_direction = App.Vector(0,0,1) |
||||
pmin, pmax = zmin, zmax |
||||
|
||||
slices = face.slices(slice_direction, [x for x in np.arange(pmin, pmax, 2)]) |
||||
|
||||
prog = kuka.Kuka_Prog() |
||||
for edge in slices.Edges: |
||||
poses = kuka.get_list_of_poses(face, edge, 10) |
||||
prog.append_poses(poses) |
||||
prog.draw_wire() |
||||
prog.save_prog("/home/jk/test_export_workbench") |
||||
|
||||
|
||||
### helper to create some object |
||||
def create_laserpad(face): |
||||
laserjob_entry = App.ActiveDocument.getObject('LaserJob') |
||||
if laserjob_entry is None: |
||||
App.Console.PrintMessage('Create a LaserJob first') |
||||
return |
||||
pad_obj = App.ActiveDocument.addObject("App::FeaturePython","LaserPad") |
||||
pad = LaserPad(pad_obj, face) |
||||
#a=laserjob_entry.addObbject(pad) |
||||
ViewProviderLaserPad(pad.ViewProvider) |
||||
return pad |
||||
|
||||
|
||||
class ViewProviderLaserPad: |
||||
def __init__(self, obj): |
||||
'''Set this object to the proxy object of the actual view provider''' |
||||
obj.addProperty("App::PropertyColor","Color","Box","Color of the box").Color=(1.0,0.0,0.0) |
||||
obj.Proxy = self |
||||
|
||||
def attach(self, obj): |
||||
'''Setup the scene sub-graph of the view provider, this method is mandatory''' |
||||
self.onChanged(obj,"Color") |
||||
|
||||
def updateData(self, fp, prop): |
||||
'''If a property of the handled feature has changed we have the chance to handle this here''' |
||||
# fp is the handled feature, prop is the name of the property that has changed |
||||
pass |
||||
|
||||
def getDisplayModes(self,obj): |
||||
'''Return a list of display modes.''' |
||||
modes=[] |
||||
modes.append("Shaded") |
||||
modes.append("Wireframe") |
||||
return modes |
||||
|
||||
def getDefaultDisplayMode(self): |
||||
'''Return the name of the default display mode. It must be defined in getDisplayModes.''' |
||||
return "Shaded" |
||||
|
||||
def setDisplayMode(self,mode): |
||||
'''Map the display mode defined in attach with those defined in getDisplayModes.\ |
||||
Since they have the same names nothing needs to be done. This method is optional''' |
||||
return mode |
||||
|
||||
def onChanged(self, vp, prop): |
||||
'''Here we can do something when a single property got changed''' |
||||
App.Console.PrintMessage("Change property: " + str(prop) + "\n") |
||||
#if prop == "Color": |
||||
# c = vp.getPropertyByName("Color") |
||||
# self.color.rgb.setValue(c[0],c[1],c[2]) |
||||
|
||||
def getIcon(self): |
||||
'''Return the icon in XPM format which will appear in the tree view. This method is\ |
||||
optional and if not defined a default icon is shown.''' |
||||
return """ |
||||
/* XPM */ |
||||
static const char * ViewProviderBox_xpm[] = { |
||||
"16 16 6 1", |
||||
" c None", |
||||
". c #141010", |
||||
"+ c #615BD2", |
||||
"@ c #C39D55", |
||||
"# c #000000", |
||||
"$ c #57C355", |
||||
" ........", |
||||
" ......++..+..", |
||||
" .@@@@.++..++.", |
||||
" .@@@@.++..++.", |
||||
" .@@ .++++++.", |
||||
" ..@@ .++..++.", |
||||
"###@@@@ .++..++.", |
||||
"##$.@@$#.++++++.", |
||||
"#$#$.$$$........", |
||||
"#$$####### ", |
||||
"#$$#$$$$$# ", |
||||
"#$$#$$$$$# ", |
||||
"#$$#$$$$$# ", |
||||
" #$#$$$$$# ", |
||||
" ##$$$$$# ", |
||||
" ####### "}; |
||||
""" |
||||
|
||||
def __getstate__(self): |
||||
'''When saving the document this object gets stored using Python's json module.\ |
||||
Since we have some un-serializable parts here -- the Coin stuff -- we must define this method\ |
||||
to return a tuple of all serializable objects or None.''' |
||||
return None |
||||
|
||||
def __setstate__(self,state): |
||||
'''When restoring the serialized object from document we have the chance to set some internals here.\ |
||||
Since no data were serialized nothing needs to be done here.''' |
||||
return None |
||||
|
||||
|
||||
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
import FreeCAD as App |
||||
|
||||
class LaserPath: |
||||
def __init__(self, obj): |
||||
'''Add some custom properties to our box feature''' |
||||
obj.addProperty("App::Property", "base_reference", "Reference", "Reference Point (teached)") |
||||
obj.base_reference = App.Vector(0,0,0) |
||||
obj.Proxy = self |
||||
|
||||
def onChanged(self, fp, prop): |
||||
'''Do something when a property has changed''' |
||||
App.Console.PrintMessage("Change property: " + str(prop) + "\n") |
||||
|
||||
def execute(self, fp): |
||||
'''Do something when doing a recomputation, this method is mandatory''' |
||||
App.Console.PrintMessage("Recompute Python Box feature\n") |
||||
Loading…
Reference in new issue