Browse Source

new path2D function from pySLM

master
Jörg Kurlbaum 3 years ago
parent
commit
cc25701e4c
  1. 2
      freecad/LaserCladdingWorkbench/Resources/LaserCladding.qrc
  2. 351
      freecad/LaserCladdingWorkbench/Resources/icons/Laser_Workbench.svg
  3. 5
      freecad/LaserCladdingWorkbench/init_gui.py
  4. 9
      freecad/LaserCladdingWorkbench/pad.py
  5. 3
      freecad/LaserCladdingWorkbench/path.py
  6. 6
      freecad/LaserCladdingWorkbench/program.py
  7. 33
      freecad/LaserCladdingWorkbench/utils.py

2
freecad/LaserCladdingWorkbench/Resources/LaserCladding.qrc

@ -1,6 +1,6 @@
<RCC> <RCC>
<qresource> <qresource>
<file>icons/Laser_Workbench.svg</file> <file>icons/LaserWorkbench.svg</file>
<file>icons/LaserCreatePad.svg</file> <file>icons/LaserCreatePad.svg</file>
<file>icons/LaserCreateProg.svg</file> <file>icons/LaserCreateProg.svg</file>
<file>icons/LaserRecomputePad.svg</file> <file>icons/LaserRecomputePad.svg</file>

351
freecad/LaserCladdingWorkbench/Resources/icons/Laser_Workbench.svg

@ -1,351 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2766"
height="64px"
width="64px"
sodipodi:docname="Laser_Workbench.svg"
inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1278"
inkscape:window-height="1417"
id="namedview975"
showgrid="false"
inkscape:zoom="8.5625"
inkscape:cx="32"
inkscape:cy="32"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2766" />
<defs
id="defs2768">
<linearGradient
id="linearGradient3787">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3789" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3791" />
</linearGradient>
<linearGradient
id="linearGradient3864">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868" />
</linearGradient>
<linearGradient
gradientTransform="matrix(1.0614931,0,0,1,-540.96941,-73.37642)"
y2="100.10708"
x2="609.54919"
y1="126.79625"
x1="581.26331"
gradientUnits="userSpaceOnUse"
id="linearGradient3181"
xlink:href="#linearGradient3864" />
<linearGradient
y2="92.711899"
x2="626.31323"
y1="92.711899"
x1="605.94659"
gradientTransform="matrix(-0.72140579,0.77867919,-0.73356972,-0.67961421,545.35072,-389.46656)"
gradientUnits="userSpaceOnUse"
id="linearGradient3184"
xlink:href="#linearGradient3864" />
<linearGradient
id="linearGradient3864-0">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866-6" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868-2" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3864-0"
id="linearGradient3217"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0614931,0,0,1,-643.22843,-82.445766)"
x1="605.94659"
y1="92.711899"
x2="626.31323"
y2="92.711899" />
<linearGradient
y2="92.711899"
x2="626.31323"
y1="92.711899"
x1="605.94659"
gradientTransform="matrix(1.1915091,0,0,1,-772.13265,-84.532596)"
gradientUnits="userSpaceOnUse"
id="linearGradient3184-4-0"
xlink:href="#linearGradient3864-0-2" />
<linearGradient
id="linearGradient3864-0-2">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866-6-8" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868-2-3" />
</linearGradient>
<linearGradient
y2="92.711899"
x2="626.31323"
y1="92.711899"
x1="605.94659"
gradientTransform="matrix(1.1915091,0,0,1,-772.13265,-84.532596)"
gradientUnits="userSpaceOnUse"
id="linearGradient3184-4-4"
xlink:href="#linearGradient3864-0-9" />
<linearGradient
id="linearGradient3864-0-9">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866-6-9" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868-2-4" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3864-0-9-5"
id="linearGradient4054-6"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0614931,0.54122665,0,1,-692.52246,-451.18305)"
x1="634.20868"
y1="91.597527"
x2="679.06909"
y2="102.88628" />
<linearGradient
id="linearGradient3864-0-9-5">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866-6-9-0" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868-2-4-0" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3864-0-9-5"
id="linearGradient4090"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0614931,0.54122665,0,1,-687.73118,-415.49631)"
x1="634.20868"
y1="91.597527"
x2="679.06909"
y2="102.88628" />
<linearGradient
xlink:href="#linearGradient3864-0-9-5-0"
id="linearGradient4090-6"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0614931,0.54122665,0,1,-687.73118,-415.49631)"
x1="634.20868"
y1="91.597527"
x2="679.06909"
y2="102.88628" />
<linearGradient
id="linearGradient3864-0-9-5-0">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866-6-9-0-2" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868-2-4-0-5" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3864-0-9-5-0"
id="linearGradient4124"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.80817481,0.4120665,0,0.76135663,-517.34974,-304.44262)"
x1="634.20868"
y1="91.597527"
x2="679.06909"
y2="102.88628" />
<linearGradient
xlink:href="#linearGradient3864-0-2-2"
id="linearGradient4018-2"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5385683,-0.86055196,0,0.96535888,-879.38043,517.26249)"
x1="635.40765"
y1="100.79263"
x2="672.73157"
y2="100.2725" />
<linearGradient
id="linearGradient3864-0-2-2">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866-6-8-9" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868-2-3-2" />
</linearGradient>
<linearGradient
y2="48.117603"
x2="709.04407"
y1="114.56509"
x1="663.32715"
gradientTransform="matrix(1.5385683,0.52247795,0,0.96535888,-912.7401,-396.04414)"
gradientUnits="userSpaceOnUse"
id="linearGradient4073-8"
xlink:href="#linearGradient3864-0-1" />
<linearGradient
id="linearGradient3864-0-1">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866-6-2" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868-2-47" />
</linearGradient>
<linearGradient
xlink:href="#linearGradient3864-0-9-6"
id="linearGradient4054-8"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.5385683,0.52247795,0,0.96535888,-912.7628,-417.24568)"
x1="634.20868"
y1="91.597527"
x2="679.06909"
y2="102.88628" />
<linearGradient
id="linearGradient3864-0-9-6">
<stop
style="stop-color:#0619c0;stop-opacity:1;"
offset="0"
id="stop3866-6-9-3" />
<stop
style="stop-color:#379cfb;stop-opacity:1;"
offset="1"
id="stop3868-2-4-7" />
</linearGradient>
</defs>
<g
id="layer1">
<path
id="rect3200-5-3"
d="M 33,35 5,49 33,59 59,45 z m 0,5 16,6 -16,8 -17,-6 z"
style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#0b1521;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
</g>
<metadata
id="metadata57">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license
rdf:resource="" />
<dc:date>Mon Oct 10 13:44:52 2011 +0000</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>[wmayer]</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier>FreeCAD/src/Mod/Draft/Resources/icons/Draft_2DShapeView.svg</dc:identifier>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:contributor>
<cc:Agent>
<dc:title>[agryson] Alexander Gryson</dc:title>
</cc:Agent>
</dc:contributor>
<dc:subject>
<rdf:Bag>
<rdf:li>box</rdf:li>
<rdf:li>plane</rdf:li>
<rdf:li>rectangle</rdf:li>
</rdf:Bag>
</dc:subject>
<dc:description>A box floating above a projection of its lower face</dc:description>
</cc:Work>
</rdf:RDF>
</metadata>
<path
style="fill:#ff0000;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 33.119982,5.9005474 V 43.968066"
id="path1011" />
<ellipse
style="fill:#ff1a00;fill-opacity:1;stroke:none;stroke-width:9.49383"
id="path1020"
cx="33.058163"
cy="44.76939"
rx="1.6904655"
ry="1.6950274" />
<path
style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 33.119982,43.968066 38.117245,40"
id="path1022" />
<path
style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 33.119982,43.968066 29.151916,38.970803"
id="path1022-3" />
<path
style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 33.119982,43.968066 -6.204197,-1.49202"
id="path1022-6"
inkscape:transform-center-x="2.4142336"
inkscape:transform-center-y="-0.3120438" />
<path
style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 33.119982,43.968066 -5.853996,2.539469"
id="path1022-5"
inkscape:transform-center-x="-2.177793"
inkscape:transform-center-y="2.5275147" />
<path
style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 33.316894,43.931615 5.935078,2.343723"
id="path1022-35"
inkscape:transform-center-x="-3.2044307"
inkscape:transform-center-y="1.9014819" />
<path
style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 33.119982,43.968066 6.311789,-0.937814"
id="path1022-62" />
</svg>

Before

Width:  |  Height:  |  Size: 11 KiB

5
freecad/LaserCladdingWorkbench/init_gui.py

@ -9,8 +9,9 @@ import os
class LaserCladding (Gui.Workbench): class LaserCladding (Gui.Workbench):
MenuText = "Laser Cladding" MenuText = "Laser Cladding"
ToolTip = "Create Simple Paths on workpieces for Laser Cladding" ToolTip = "Create Simple Paths on workpieces for Laser Cladding"
Icon = ":/icons/Laser_Workbench.svg" Icon = os.path.join(App.getUserAppDataDir(),
"Mod", "fc_lasercladding_wb","freecad", "LaserCladdingWorkbench",
"Resources", "icons", "LaserWorkbench.svg")
def __init__(self): def __init__(self):
pass pass

9
freecad/LaserCladdingWorkbench/pad.py

@ -64,6 +64,9 @@ class LaserPad:
myHatcher.hatchSortMethod = hatching.AlternateSort() myHatcher.hatchSortMethod = hatching.AlternateSort()
polygon_coords = get_coords_from_shape(face) polygon_coords = get_coords_from_shape(face)
print("===== coords from shape ======")
print("{}", polygon_coords)
print("===== ======")
layer = myHatcher.hatch(polygon_coords) layer = myHatcher.hatch(polygon_coords)
contours_geoms = layer.getContourGeometry() contours_geoms = layer.getContourGeometry()
@ -97,7 +100,8 @@ class LaserPad:
def onChanged(self, fp, prop): def onChanged(self, fp, prop):
'''Do something when a property has changed''' '''Do something when a property has changed'''
App.Console.PrintMessage("Change property: " + str(prop) + "\n") # App.Console.PrintMessage("Change property: " + str(prop) + "\n")
pass
def execute(self, fp): def execute(self, fp):
App.Console.PrintMessage("Recompute LaserPad\n") App.Console.PrintMessage("Recompute LaserPad\n")
@ -149,10 +153,11 @@ class ViewProviderLaserPad:
def onChanged(self, vp, prop): def onChanged(self, vp, prop):
'''Here we can do something when a single property got changed''' '''Here we can do something when a single property got changed'''
App.Console.PrintMessage("Change property: " + str(prop) + "\n") # App.Console.PrintMessage("Change property: " + str(prop) + "\n")
# if prop == "Color": # if prop == "Color":
# c = vp.getPropertyByName("Color") # c = vp.getPropertyByName("Color")
# self.color.rgb.setValue(c[0],c[1],c[2]) # self.color.rgb.setValue(c[0],c[1],c[2])
pass
def getIcon(self): def getIcon(self):
'''Return the icon in XPM format which will appear in the tree view. This method is\ '''Return the icon in XPM format which will appear in the tree view. This method is\

3
freecad/LaserCladdingWorkbench/path.py

@ -11,7 +11,8 @@ class LaserPath:
def onChanged(self, fp, prop): def onChanged(self, fp, prop):
'''Do something when a property has changed''' '''Do something when a property has changed'''
App.Console.PrintMessage("Change property: " + str(prop) + "\n") #App.Console.PrintMessage("Change property: " + str(prop) + "\n")
pass
def execute(self, fp): def execute(self, fp):
App.Console.PrintMessage("Recompute LaserPath\n") App.Console.PrintMessage("Recompute LaserPath\n")

6
freecad/LaserCladdingWorkbench/program.py

@ -54,7 +54,8 @@ class LaserProgram:
def onChanged(self, fp, prop): def onChanged(self, fp, prop):
'''Do something when a property has changed''' '''Do something when a property has changed'''
App.Console.PrintMessage("Change property: " + str(prop) + "\n") #App.Console.PrintMessage("Change property: " + str(prop) + "\n")
pass
def execute(self, fp): def execute(self, fp):
'''Do something when doing a recomputation, this method is mandatory''' '''Do something when doing a recomputation, this method is mandatory'''
@ -95,10 +96,11 @@ class ViewProviderLaserProgram:
def onChanged(self, vp, prop): def onChanged(self, vp, prop):
'''Here we can do something when a single property got changed''' '''Here we can do something when a single property got changed'''
App.Console.PrintMessage("Change property: " + str(prop) + "\n") # App.Console.PrintMessage("Change property: " + str(prop) + "\n")
#if prop == "Color": #if prop == "Color":
# c = vp.getPropertyByName("Color") # c = vp.getPropertyByName("Color")
# self.color.rgb.setValue(c[0],c[1],c[2]) # self.color.rgb.setValue(c[0],c[1],c[2])
pass
def getIcon(self): def getIcon(self):
'''Return the icon in XPM format which will appear in the tree view. This method is\ '''Return the icon in XPM format which will appear in the tree view. This method is\

33
freecad/LaserCladdingWorkbench/utils.py

@ -4,6 +4,7 @@ import FreeCADGui as Gui
import numpy as np import numpy as np
import math import math
import Part import Part
import shapely
from shapely.geometry import Polygon, Point from shapely.geometry import Polygon, Point
from pyslm import hatching as hatching from pyslm import hatching as hatching
from pyslm.geometry.geometry import LayerGeometryType from pyslm.geometry.geometry import LayerGeometryType
@ -33,24 +34,27 @@ def map_wire(wire, surface):
return Part.Wire(mapped_edges) return Part.Wire(mapped_edges)
def path2DToPathList(shapes: List[Polygon]) -> List[np.ndarray]:
def path2DToPathList(shapes: List[shapely.geometry.polygon.Polygon]) -> List[np.ndarray]:
""" """
Returns the list of paths and coordinates from a cross-section (i.e. Trimesh Path2D). This is required to be Returns the list of paths and coordinates from a cross-section (i.e. :class:`Trimesh.path.Path2D` objects).
done for performing boolean operations and offsetting with the internal PyClipper package. This is required to be done for performing boolean operations and offsetting with the internal PyClipper package.
:param shapes: A list of :class:`shapely.geometry.Polygon` representing a cross-section or container of
closed polygons :param shapes: A list of Shapely Polygons representing a cross-section or container of
closed polygons
:return: A list of paths (Numpy Coordinate Arrays) describing fully closed and oriented paths. :return: A list of paths (Numpy Coordinate Arrays) describing fully closed and oriented paths.
""" """
paths = [] paths = []
for poly in shapes: for poly in shapes:
coords = np.array(poly.exterior.coords) coords = np.array(poly.exterior.coords)
paths.append(coords)
for path in poly.interiors:
coords = np.array(path.coords)
paths.append(coords) paths.append(coords)
for path in poly.interiors:
coords = np.array(path.coords)
paths.append(coords)
return paths return paths
@ -100,7 +104,7 @@ def tuple_is_equal(t1, t2):
def get_polygon_from_subshape(subshape): def get_polygon_from_subshape(subshape):
# print("START NEW POLYGON") # print("START NEW POLYGON")
polygon = [] polygon = []
for edge in Part.__sortEdges__(subshape.Edges): for edge in subshape.Edges: # Part.__sortEdges__(subshape.Edges):
poly_points = [] poly_points = []
if type(edge.Curve) in [Part.Ellipse, Part.BSplineCurve, Part.Circle]: if type(edge.Curve) in [Part.Ellipse, Part.BSplineCurve, Part.Circle]:
n = math.floor(edge.Length/2.3) n = math.floor(edge.Length/2.3)
@ -131,6 +135,7 @@ def get_coords_from_shape(face):
tmp = get_polygon_from_subshape(inner_wire) tmp = get_polygon_from_subshape(inner_wire)
inner_polys.append(tmp) inner_polys.append(tmp)
poly = Polygon(outerpoly, holes=inner_polys) poly = Polygon(outerpoly, holes=inner_polys)
print("Polygon: ", poly)
return path2DToPathList([poly]) return path2DToPathList([poly])
@ -153,8 +158,8 @@ def create_contour_lines(geoms):
for geom in geoms: for geom in geoms:
if geom.type() == LayerGeometryType.Polygon: if geom.type() == LayerGeometryType.Polygon:
# print("Contour with {} coords".format(len(geom.coords))) # print("Contour with {} coords".format(len(geom.coords)))
coords = rdp.rdp(geom.coords, epsilon=0.3, algo="iter", return_mask=False) #coords = rdp.rdp(geom.coords, epsilon=0.3, algo="iter", return_mask=False)
# print("Simplfied Poly:", len(coords)) #print("Simplfied Poly:", len(coords))
pp = Part.makePolygon([App.Vector(x,y,0) for (x,y) in coords]) pp = Part.makePolygon([App.Vector(x,y,0) for (x,y) in geom.coords])
contours.append(pp) contours.append(pp)
return contours return contours

Loading…
Cancel
Save