diff --git a/FlatCAM.py b/FlatCAM.py
index 3a10da4d..2f82859e 100644
--- a/FlatCAM.py
+++ b/FlatCAM.py
@@ -25,6 +25,7 @@ from camlib import *
import sys
import urllib
import copy
+import random
########################################
@@ -980,10 +981,17 @@ class App:
:rtype: None
"""
- # Check for existing name
+ ### Check for existing name
if name in self.stuff:
- self.info("Rename " + name + " in project first.")
- return None
+ ## Create a new name
+ # Ends with number?
+ match = re.search(r'(.*[^\d])?(\d+)$', name)
+ if match: # Yes: Increment the number!
+ base = match.group(1) or ''
+ num = int(match.group(2))
+ name = base + str(num + 1)
+ else: # No: add a number!
+ name += "_1"
# Create object
classdict = {
@@ -2690,26 +2698,76 @@ class App:
return
+class BaseDraw:
+ def __init__(self, plotcanvas, name=None):
+ """
+
+ :param plotcanvas: The PlotCanvas where the drawing tool will operate.
+ :type plotcanvas: PlotCanvas
+ """
+
+ self.plotcanvas = plotcanvas
+
+ # Must have unique axes
+ charset = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890"
+ self.name = name or [random.choice(charset) for i in range(20)]
+ self.axes = self.plotcanvas.new_axes(self.name)
+
+
+class DrawingObject(BaseDraw):
+ def __init__(self, plotcanvas, name=None):
+ """
+ Possible objects are:
+
+ * Point
+ * Line
+ * Rectangle
+ * Circle
+ * Polygon
+ """
+
+ BaseDraw.__init__(self, plotcanvas)
+ self.properties = {}
+
+ def plot(self):
+ return
+
+ def update_plot(self):
+ self.axes.cla()
+ self.plot()
+ self.plotcanvas.auto_adjust_axes()
+
+
+class DrawingPoint(DrawingObject):
+ def __init__(self, plotcanvas, name=None, coord=None):
+ DrawingObject.__init__(self, plotcanvas)
+
+ self.properties.update({
+ "coordinate": coord
+ })
+
+ def plot(self):
+ x, y = self.properties["coordinate"]
+ self.axes.plot(x, y, 'o')
+
+
class Measurement:
def __init__(self, container, axes, click_subscibers, move_subscribers, update=None):
self.update = update
self.container = container
self.frame = None
self.label = None
- self.axes = axes
self.click_subscribers = click_subscibers
self.move_subscribers = move_subscribers
self.point1 = None
self.point2 = None
self.active = False
- # self.at = None # AnchoredText object on plot
def toggle_active(self, *args):
if self.active: # Deactivate
self.active = False
self.move_subscribers.pop("meas")
self.click_subscribers.pop("meas")
- # self.at.remove()
self.container.remove(self.frame)
if self.update is not None:
self.update()
@@ -2726,34 +2784,24 @@ class Measurement:
align.set(0, 0.5, 0, 0)
align.set_padding(4, 4, 4, 4)
self.label = Gtk.Label()
- self.label.set_label("Measuring tool...")
- align.add(self.label)
+ self.label.set_label("Click on a reference point...")
+ abox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 10)
+ abox.pack_start(Gtk.Image.new_from_file('share/measure16.png'), False, False, 0)
+ abox.pack_start(self.label, False, False, 0)
+ align.add(abox)
self.frame.add(align)
- self.frame.set_size_request(200, 30)
- self.frame.set_hexpand(True)
self.container.pack_end(self.frame, False, True, 1)
self.frame.show_all()
- align.show_all()
- self.label.show_all()
- self.container.queue_draw()
return True
def on_move(self, event):
- # try:
- # self.at.remove()
- # except:
- # pass
if self.point1 is None:
- # self.at = AnchoredText("Click on a reference point...")
self.label.set_label("Click on a reference point...")
else:
dx = event.xdata - self.point1[0]
dy = event.ydata - self.point1[1]
d = sqrt(dx**2 + dy**2)
- # self.at = AnchoredText("D = %.4f\nD(x) = %.4f\nD(y) = %.4f" % (d, dx, dy),
- # loc=2, prop={'size': 14}, frameon=False)
self.label.set_label("D = %.4f D(x) = %.4f D(y) = %.4f" % (d, dx, dy))
- # self.axes.add_artist(self.at)
if self.update is not None:
self.update()
diff --git a/FlatCAM.ui b/FlatCAM.ui
index ef716d78..9d2f8647 100644
--- a/FlatCAM.ui
+++ b/FlatCAM.ui
@@ -57,6 +57,21 @@ THE SOFTWARE.
+
+
+
-
-
-
+
False
@@ -2552,397 +2943,6 @@ this object.
-
- False
-
-
- True
- True
- never
- in
-
-
- True
- False
-
-
- True
- False
- 5
- 5
- 5
- 5
- vertical
-
-
- True
- False
-
-
- True
- False
- share/cnc32.png
-
-
- False
- True
- 0
-
-
-
-
- True
- False
- 3
- CNC Job Object
-
-
-
-
-
- True
- True
- 1
-
-
-
-
- False
- True
- 0
-
-
-
-
- True
- False
-
-
- True
- False
- 3
- Name:
-
-
- False
- True
- 0
-
-
-
-
- True
- True
- ●
- True
-
-
- False
- True
- 1
-
-
-
-
- False
- True
- 1
-
-
-
-
- True
- False
- 5
- 0
- 3
- Plot Options:
-
-
-
-
-
- False
- True
- 2
-
-
-
-
- Plot
- True
- True
- False
- 0
- True
- True
-
-
-
- False
- True
- 3
-
-
-
-
-
-
-
-
-
-
- True
- False
- 3
- 3
- 3
-
-
- True
- False
- 1
- Tool diam:
-
-
- False
- True
- 0
-
-
-
-
- True
- True
- ●
- True
-
-
-
- False
- True
- 1
-
-
-
-
- False
- True
- 6
-
-
-
-
- Update Plot
- True
- True
- True
-
-
-
-
- False
- True
- 7
-
-
-
-
- True
- False
- 3
- 0
- 3
- Export G-Code:
-
-
-
-
-
- False
- True
- 8
-
-
-
-
- Export
- True
- True
- True
-
-
-
-
- False
- True
- 9
-
-
-
-
- True
- False
- 3
- 0
- 3
- Scale:
-
-
-
-
-
- False
- True
- 10
-
-
-
-
- True
- False
- 3
- 3
- 3
-
-
- True
- False
- 1
- Factor:
-
-
- False
- True
- 0
-
-
-
-
- True
- True
- ●
- 1.0
- True
-
-
- False
- True
- 1
-
-
-
-
- False
- True
- 11
-
-
-
-
- Scale
- True
- True
- True
-
-
-
-
- False
- True
- 12
-
-
-
-
- True
- False
- 3
- 0
- 3
- Offset:
-
-
-
-
-
- False
- True
- 13
-
-
-
-
- True
- False
- 3
- 3
- 3
-
-
- True
- False
- 1
- Offset Vector:
-
-
- False
- True
- 0
-
-
-
-
- True
- True
- ●
- (0.0, 0.0)
- True
-
-
- False
- True
- 1
-
-
-
-
- False
- True
- 14
-
-
-
-
- Offset
- True
- True
- True
-
-
-
-
- False
- True
- 15
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
600
400
@@ -4331,7 +4331,7 @@ to overlap each pass.
True
False
- 4
+ 5
<b>Excellon Objects</b>
True
@@ -4707,7 +4707,7 @@ to overlap each pass.
True
False
- 4
+ 5
<b>Geometry Objects</b>
True
@@ -4813,6 +4813,7 @@ to overlap each pass.
True
False
+ 5
<b>CNC Job Objects</b>
True
diff --git a/camlib.py b/camlib.py
index 478e507c..76c5e403 100644
--- a/camlib.py
+++ b/camlib.py
@@ -818,23 +818,21 @@ class Gerber (Geometry):
self.flash_geometry.append(obround)
continue
- if aperture['type'] == 'P': #Regular polygon
+ if aperture['type'] == 'P': # Regular polygon
loc = flash['loc']
diam = aperture['diam']
nVertices = aperture['nVertices']
points = []
- for i in range(0,nVertices):
+ for i in range(0, nVertices):
x = loc[0] + diam * (cos(2 * pi * i / nVertices))
y = loc[1] + diam * (sin(2 * pi * i / nVertices))
- points.append((x,y))
+ points.append((x, y))
ply = Polygon(points)
if 'rotation' in aperture:
ply = affinity.rotate(ply, aperture['rotation'])
self.flash_geometry.append(ply)
continue
-
-
print "WARNING: Aperture type %s not implemented" % (aperture['type'])
def create_geometry(self):
@@ -1433,12 +1431,12 @@ class CNCjob(Geometry):
# Current path: temporary storage until tool is
# lifted or lowered.
- path = []
+ path = [(0, 0)]
# Process every instruction
for gobj in gobjs:
- # Changing height:
+ ## Changing height
if 'Z' in gobj:
if ('X' in gobj or 'Y' in gobj) and gobj['Z'] != current['Z']:
print "WARNING: Non-orthogonal motion: From", current
@@ -1490,6 +1488,13 @@ class CNCjob(Geometry):
for code in gobj:
current[code] = gobj[code]
+ # There might not be a change in height at the
+ # end, therefore, see here too if there is
+ # a final path.
+ if len(path) > 1:
+ geometry.append({"geom": LineString(path),
+ "kind": kind})
+
self.gcode_parsed = geometry
return geometry