- Geometry Editor: modified the intersection (if the selected shapes don't intersects preserve them) and substract functions (delete all shapes that were used in the process)

- work in the ToolSilk
This commit is contained in:
Marius Stanciu
2019-04-25 16:26:31 +03:00
committed by Marius
parent ae8111bf59
commit c2334bd747
4 changed files with 129 additions and 62 deletions

View File

@@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing.
================================================= =================================================
25.04.2019
- Geometry Editor: modified the intersection (if the selected shapes don't intersects preserve them) and substract functions (delete all shapes that were used in the process)
- work in the ToolSilk
24.04.2019 24.04.2019
- PDF import tool: working in making the PDF layer rendering multithreaded in itself (one layer rendered on each worker) - PDF import tool: working in making the PDF layer rendering multithreaded in itself (one layer rendered on each worker)

View File

@@ -18,7 +18,7 @@ from FlatCAMTool import FlatCAMTool
from flatcamGUI.ObjectUI import LengthEntry, RadioSet from flatcamGUI.ObjectUI import LengthEntry, RadioSet
from shapely.geometry import LineString, LinearRing, MultiLineString from shapely.geometry import LineString, LinearRing, MultiLineString
from shapely.ops import cascaded_union from shapely.ops import cascaded_union, unary_union
import shapely.affinity as affinity import shapely.affinity as affinity
from numpy import arctan2, Inf, array, sqrt, sign, dot from numpy import arctan2, Inf, array, sqrt, sign, dot
@@ -3117,31 +3117,6 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.tool_shape.clear(update=True) self.tool_shape.clear(update=True)
self.tool_shape.redraw() self.tool_shape.redraw()
def cutpath(self):
selected = self.get_selected()
tools = selected[1:]
toolgeo = cascaded_union([shp.geo for shp in tools])
target = selected[0]
if type(target.geo) == Polygon:
for ring in poly2rings(target.geo):
self.add_shape(DrawToolShape(ring.difference(toolgeo)))
self.delete_shape(target)
elif type(target.geo) == LineString or type(target.geo) == LinearRing:
self.add_shape(DrawToolShape(target.geo.difference(toolgeo)))
self.delete_shape(target)
elif type(target.geo) == MultiLineString:
try:
for linestring in target.geo:
self.add_shape(DrawToolShape(linestring.difference(toolgeo)))
except:
self.app.log.warning("Current LinearString does not intersect the target")
self.delete_shape(target)
else:
self.app.log.warning("Not implemented. Object type: %s" % str(type(target.geo)))
self.replot()
def toolbar_tool_toggle(self, key): def toolbar_tool_toggle(self, key):
self.options[key] = self.sender().isChecked() self.options[key] = self.sender().isChecked()
if self.options[key] == True: if self.options[key] == True:
@@ -3781,7 +3756,7 @@ class FlatCAMGeoEditor(QtCore.QObject):
:return: None. :return: None.
""" """
results = cascaded_union([t.geo for t in self.get_selected()]) results = unary_union([t.geo for t in self.get_selected()])
# Delete originals. # Delete originals.
for_deletion = [s for s in self.get_selected()] for_deletion = [s for s in self.get_selected()]
@@ -3795,9 +3770,9 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.replot() self.replot()
def intersection(self): def intersection_2(self):
""" """
Makes intersectino of selected polygons. Original polygons are deleted. Makes intersection of selected polygons. Original polygons are deleted.
:return: None :return: None
""" """
@@ -3827,11 +3802,67 @@ class FlatCAMGeoEditor(QtCore.QObject):
self.replot() self.replot()
def intersection(self):
"""
Makes intersection of selected polygons. Original polygons are deleted.
:return: None
"""
shapes = self.get_selected()
results = []
intact = []
try:
intersector = shapes[0].geo
except Exception as e:
log.debug("FlatCAMGeoEditor.intersection() --> %s" % str(e))
self.app.inform.emit(_("[WARNING_NOTCL] A selection of at least 2 geo items is required to do Intersection."))
self.select_tool('select')
return
for shape in shapes[1:]:
if intersector.intersects(shape.geo):
results.append(intersector.intersection(shape.geo))
else:
intact.append(shape)
if len(results) != 0:
# Delete originals.
for_deletion = [s for s in self.get_selected()]
for shape in for_deletion:
if shape not in intact:
self.delete_shape(shape)
for geo in results:
self.add_shape(DrawToolShape(geo))
# Selected geometry is now gone!
self.selected = []
self.replot()
def subtract(self): def subtract(self):
selected = self.get_selected() selected = self.get_selected()
try: try:
tools = selected[1:] tools = selected[1:]
toolgeo = cascaded_union([shp.geo for shp in tools]) toolgeo = unary_union([shp.geo for shp in tools])
result = selected[0].geo.difference(toolgeo)
for_deletion = [s for s in self.get_selected()]
for shape in for_deletion:
self.delete_shape(shape)
self.add_shape(DrawToolShape(result))
self.replot()
except Exception as e:
log.debug(str(e))
def subtract_2(self):
selected = self.get_selected()
try:
tools = selected[1:]
toolgeo = unary_union([shp.geo for shp in tools])
result = selected[0].geo.difference(toolgeo) result = selected[0].geo.difference(toolgeo)
self.delete_shape(selected[0]) self.delete_shape(selected[0])
@@ -3841,6 +3872,30 @@ class FlatCAMGeoEditor(QtCore.QObject):
except Exception as e: except Exception as e:
log.debug(str(e)) log.debug(str(e))
def cutpath(self):
selected = self.get_selected()
tools = selected[1:]
toolgeo = unary_union([shp.geo for shp in tools])
target = selected[0]
if type(target.geo) == Polygon:
for ring in poly2rings(target.geo):
self.add_shape(DrawToolShape(ring.difference(toolgeo)))
elif type(target.geo) == LineString or type(target.geo) == LinearRing:
self.add_shape(DrawToolShape(target.geo.difference(toolgeo)))
elif type(target.geo) == MultiLineString:
try:
for linestring in target.geo:
self.add_shape(DrawToolShape(linestring.difference(toolgeo)))
except:
self.app.log.warning("Current LinearString does not intersect the target")
else:
self.app.log.warning("Not implemented. Object type: %s" % str(type(target.geo)))
return
self.delete_shape(target)
self.replot()
def buffer(self, buf_distance, join_style): def buffer(self, buf_distance, join_style):
selected = self.get_selected() selected = self.get_selected()

View File

@@ -18,6 +18,7 @@ import numpy as np
import zlib import zlib
import re import re
import time
import gettext import gettext
import FlatCAMTranslation as fcTranslate import FlatCAMTranslation as fcTranslate
@@ -201,8 +202,11 @@ class ToolPDF(FlatCAMTool):
self.pdf_decompressed[short_name] = '' self.pdf_decompressed[short_name] = ''
# removal from list is done in a multithreaded way therefore not always the removal can be done # removal from list is done in a multithreaded way therefore not always the removal can be done
# try to remove until it's done
try: try:
self.parsing_promises.remove(short_name) while True:
self.parsing_promises.remove(short_name)
time.sleep(0.1)
except: except:
pass pass
self.app.inform.emit(_("[success] Opened: %s") % filename) self.app.inform.emit(_("[success] Opened: %s") % filename)
@@ -1057,7 +1061,7 @@ class ToolPDF(FlatCAMTool):
# with the final point P3. Intermediate values of t generate intermediate points along the curve. # with the final point P3. Intermediate values of t generate intermediate points along the curve.
# The curve does not, in general, pass through the two control points P1 and P2 # The curve does not, in general, pass through the two control points P1 and P2
:return: LineString geometry :return: A list of point coordinates tuples (x, y)
""" """
# here we store the geometric points # here we store the geometric points

View File

@@ -173,46 +173,48 @@ class ToolSilk(FlatCAMTool):
ap_size = self.silk_obj.apertures[apid]['size'] ap_size = self.silk_obj.apertures[apid]['size']
geo_list = self.silk_obj.apertures[apid]['solid_geometry'] geo_list = self.silk_obj.apertures[apid]['solid_geometry']
self.app.worker_task.emit({'fcn': self.aperture_intersection, self.app.worker_task.emit({'fcn': self.aperture_intersection,
'params': [apid, ap_size, geo_list]}) 'params': [apid, geo_list]})
def aperture_intersection(self, aperture_id, aperture_size, geo_list): def aperture_intersection(self, apid, geo_list):
self.promises.append(aperture_id) self.promises.append(apid)
new_solid_geometry = [] new_solid_geometry = []
for g in geo_list:
print(g.exterior.wkt)
with self.app.proc_container.new(_("Parsing aperture %s geometry ..." % str(aperture_id))): with self.app.proc_container.new(_("Parsing aperture %s geometry ..." % str(apid))):
for geo_silk in geo_list: for geo_silk in geo_list:
for sm_ap in self.sm_obj.apertures: if geo_silk.exterior.intersects(self.solder_union.exterior):
for key in self.sm_obj.apertures[sm_ap]: print("yes")
if key == 'solid_geometry': new_geo = geo_silk.exterior.difference(self.solder_union.exterior)
if geo_silk.intersects(self.solder_union): # if the resulting geometry is not empty add it to the new_apertures solid_geometry
new_geo = geo_silk.symmetric_difference(self.solder_union) try:
# if the resulting geometry is not empty add it to the new_apertures solid_geometry for g in new_geo:
if type(new_geo) == MultiPolygon: new_solid_geometry.append(g)
for g in new_geo: except TypeError:
new_solid_geometry.append(g) new_solid_geometry.append(new_geo)
else:
new_solid_geometry.append(new_geo)
else: else:
new_solid_geometry.append(geo_silk) print("no")
new_solid_geometry.append(geo_silk)
try: if new_solid_geometry:
while not self.new_apertures[aperture_id]['solid_geometry']: try:
self.new_apertures[aperture_id]['solid_geometry'] = new_solid_geometry while not self.new_apertures[apid]['solid_geometry']:
time.sleep(0.1) self.new_apertures[apid]['solid_geometry'] = new_solid_geometry
except: time.sleep(0.1)
pass except:
pass
try: try:
while True: while True:
# removal from list is done in a multithreaded way therefore not always the removal can be done # removal from list is done in a multithreaded way therefore not always the removal can be done
# so we keep trying until it's done # so we keep trying until it's done
self.promises.remove(aperture_id) self.promises.remove(apid)
time.sleep(0.1) time.sleep(0.1)
except: except:
pass pass
def periodic_check(self, check_period): def periodic_check(self, check_period, reset=False):
""" """
This function starts an QTimer and it will periodically check if intersections are done This function starts an QTimer and it will periodically check if intersections are done
@@ -227,11 +229,12 @@ class ToolSilk(FlatCAMTool):
except: except:
pass pass
self.check_thread.setInterval(check_period) if reset:
try: self.check_thread.setInterval(check_period)
self.check_thread.timeout.disconnect(self.periodic_check_handler) try:
except: self.check_thread.timeout.disconnect(self.periodic_check_handler)
pass except:
pass
self.check_thread.timeout.connect(self.periodic_check_handler) self.check_thread.timeout.connect(self.periodic_check_handler)
self.check_thread.start(QtCore.QThread.HighPriority) self.check_thread.start(QtCore.QThread.HighPriority)