- made some optimizations in FlatCAMGerber.isolate() method

This commit is contained in:
Marius Stanciu 2019-11-25 17:55:54 +02:00
parent 2fe08cf990
commit b31d016b13
2 changed files with 107 additions and 97 deletions

View File

@ -1148,97 +1148,6 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
base_name = self.options["name"]
def generate_envelope(offset, invert, geometry=None, env_iso_type=2, follow=None, nr_passes=0):
# isolation_geometry produces an envelope that is going on the left of the geometry
# (the copper features). To leave the least amount of burrs on the features
# the tool needs to travel on the right side of the features (this is called conventional milling)
# the first pass is the one cutting all of the features, so it needs to be reversed
# the other passes overlap preceding ones and cut the left over copper. It is better for them
# to cut on the right side of the left over copper i.e on the left side of the features.
if follow:
geom = self.isolation_geometry(offset, geometry=geometry, follow=follow)
else:
try:
geom = self.isolation_geometry(offset, geometry=geometry, iso_type=env_iso_type, passes=nr_passes)
except Exception as e:
log.debug('FlatCAMGerber.isolate().generate_envelope() --> %s' % str(e))
return 'fail'
if invert:
try:
pl = []
for p in geom:
if p is not None:
if isinstance(p, Polygon):
pl.append(Polygon(p.exterior.coords[::-1], p.interiors))
elif isinstance(p, LinearRing):
pl.append(Polygon(p.coords[::-1]))
geom = MultiPolygon(pl)
except TypeError:
if isinstance(geom, Polygon) and geom is not None:
geom = Polygon(geom.exterior.coords[::-1], geom.interiors)
elif isinstance(geom, LinearRing) and geom is not None:
geom = Polygon(geom.coords[::-1])
else:
log.debug("FlatCAMGerber.isolate().generate_envelope() Error --> Unexpected Geometry %s" %
type(geom))
except Exception as e:
log.debug("FlatCAMGerber.isolate().generate_envelope() Error --> %s" % str(e))
return 'fail'
return geom
# if float(self.options["isotooldia"]) < 0:
# self.options["isotooldia"] = -self.options["isotooldia"]
def area_subtraction(geo):
new_geometry = []
name = self.ui.obj_combo.currentText()
subtractor_obj = self.app.collection.get_by_name(name)
sub_union = cascaded_union(subtractor_obj.solid_geometry)
try:
for geo_elem in geo:
if isinstance(geo_elem, Polygon):
for ring in self.poly2rings(geo_elem):
new_geo = ring.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo_elem, MultiPolygon):
for poly in geo_elem:
for ring in self.poly2rings(poly):
new_geo = ring.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo_elem, LineString):
new_geo = geo_elem.difference(sub_union)
if new_geo:
if not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo_elem, MultiLineString):
for line_elem in geo_elem:
new_geo = line_elem.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
except TypeError:
if isinstance(geo, Polygon):
for ring in self.poly2rings(geo):
new_geo = ring.difference(sub_union)
if new_geo:
if not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo, LineString):
new_geo = geo.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo, MultiLineString):
for line_elem in geo:
new_geo = line_elem.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
return new_geometry
if combine:
if outname is None:
if self.iso_type == 0:
@ -1260,8 +1169,8 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
# if milling type is climb then the move is counter-clockwise around features
mill_t = 1 if milling_type == 'cl' else 0
geom = generate_envelope(iso_offset, mill_t, geometry=work_geo, env_iso_type=iso_t, follow=follow,
nr_passes=i)
geom = self.generate_envelope(iso_offset, mill_t, geometry=work_geo, env_iso_type=iso_t,
follow=follow, nr_passes=i)
if geom == 'fail':
app_obj.inform.emit('[ERROR_NOTCL] %s' % _("Isolation geometry could not be generated."))
@ -1349,7 +1258,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
# ############################################################
if self.ui.except_cb.get_value():
self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo"))
geo_obj.solid_geometry = area_subtraction(geo_obj.solid_geometry)
geo_obj.solid_geometry = self.area_subtraction(geo_obj.solid_geometry)
# TODO: Do something if this is None. Offer changing name?
self.app.new_object("geometry", iso_name, iso_init, plot=plot)
@ -1386,8 +1295,9 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
# if milling type is climb then the move is counter-clockwise around features
mill_t = 1 if milling_type == 'cl' else 0
mill_t = 1 if milling_type == 'cl' else 0
geom = generate_envelope(offset, mill_t, geometry=work_geo, env_iso_type=iso_t, follow=follow,
nr_passes=i)
geom = self.generate_envelope(offset, mill_t, geometry=work_geo, env_iso_type=iso_t,
follow=follow,
nr_passes=i)
if geom == 'fail':
app_obj.inform.emit('[ERROR_NOTCL] %s' %
@ -1422,11 +1332,110 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
# ############################################################
if self.ui.except_cb.get_value():
self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo"))
geo_obj.solid_geometry = area_subtraction(geo_obj.solid_geometry)
geo_obj.solid_geometry = self.area_subtraction(geo_obj.solid_geometry)
# TODO: Do something if this is None. Offer changing name?
self.app.new_object("geometry", iso_name, iso_init, plot=plot)
def generate_envelope(self, offset, invert, geometry=None, env_iso_type=2, follow=None, nr_passes=0):
# isolation_geometry produces an envelope that is going on the left of the geometry
# (the copper features). To leave the least amount of burrs on the features
# the tool needs to travel on the right side of the features (this is called conventional milling)
# the first pass is the one cutting all of the features, so it needs to be reversed
# the other passes overlap preceding ones and cut the left over copper. It is better for them
# to cut on the right side of the left over copper i.e on the left side of the features.
if follow:
geom = self.isolation_geometry(offset, geometry=geometry, follow=follow)
else:
try:
geom = self.isolation_geometry(offset, geometry=geometry, iso_type=env_iso_type, passes=nr_passes)
except Exception as e:
log.debug('FlatCAMGerber.isolate().generate_envelope() --> %s' % str(e))
return 'fail'
if invert:
try:
pl = []
for p in geom:
if p is not None:
if isinstance(p, Polygon):
pl.append(Polygon(p.exterior.coords[::-1], p.interiors))
elif isinstance(p, LinearRing):
pl.append(Polygon(p.coords[::-1]))
geom = MultiPolygon(pl)
except TypeError:
if isinstance(geom, Polygon) and geom is not None:
geom = Polygon(geom.exterior.coords[::-1], geom.interiors)
elif isinstance(geom, LinearRing) and geom is not None:
geom = Polygon(geom.coords[::-1])
else:
log.debug("FlatCAMGerber.isolate().generate_envelope() Error --> Unexpected Geometry %s" %
type(geom))
except Exception as e:
log.debug("FlatCAMGerber.isolate().generate_envelope() Error --> %s" % str(e))
return 'fail'
return geom
def area_subtraction(self, geo, subtractor_geo=None):
"""
Subtracts the subtractor_geo (if present else self.solid_geometry) from the geo
:param geo: target geometry from which to subtract
:param subtractor_geo: geometry that acts as subtractor
:return:
"""
new_geometry = []
target_geo = geo
if subtractor_geo:
sub_union = cascaded_union(subtractor_geo)
else:
name = self.ui.obj_combo.currentText()
subtractor_obj = self.app.collection.get_by_name(name)
sub_union = cascaded_union(subtractor_obj.solid_geometry)
try:
for geo_elem in target_geo:
if isinstance(geo_elem, Polygon):
for ring in self.poly2rings(geo_elem):
new_geo = ring.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo_elem, MultiPolygon):
for poly in geo_elem:
for ring in self.poly2rings(poly):
new_geo = ring.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo_elem, LineString):
new_geo = geo_elem.difference(sub_union)
if new_geo:
if not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(geo_elem, MultiLineString):
for line_elem in geo_elem:
new_geo = line_elem.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
except TypeError:
if isinstance(target_geo, Polygon):
for ring in self.poly2rings(target_geo):
new_geo = ring.difference(sub_union)
if new_geo:
if not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(target_geo, LineString):
new_geo = target_geo.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
elif isinstance(target_geo, MultiLineString):
for line_elem in target_geo:
new_geo = line_elem.difference(sub_union)
if new_geo and not new_geo.is_empty:
new_geometry.append(new_geo)
return new_geometry
def on_plot_cb_click(self, *args):
if self.muted_ui:
return

View File

@ -13,6 +13,7 @@ CAD program, and create G-Code for Isolation routing.
- In Gerber isolation changed the UI
- in Gerber isolation added the option to selectively isolate only certain polygons
- made some optimizations in FlatCAMGerber.isolate() method
23.11.2019