Added OS-X installation instructions to manual.

This commit is contained in:
jpcaram 2014-12-27 15:12:49 -05:00
parent 6fae5258db
commit a0d6d1a6a9
5 changed files with 141 additions and 61 deletions

View File

@ -2419,16 +2419,18 @@ class App(QtCore.QObject):
try:
f = open(filename, 'w')
except IOError:
App.log.error("[error] Failed to open file for saving:", filename)
App.log.error("[error] Failed to open file for saving: %s", filename)
return
# Write
try:
json.dump(d, f, default=to_dict)
except:
App.log.error("[error] File open but failed to write:", filename)
f.close()
return
json.dump(d, f, default=to_dict)
# try:
# json.dump(d, f, default=to_dict)
# except Exception, e:
# print str(e)
# App.log.error("[error] File open but failed to write: %s", filename)
# f.close()
# return
f.close()

View File

@ -800,7 +800,6 @@ class FlatCAMDraw(QtCore.QObject):
self.shape_buffer.remove(shape)
# Add the new utility shape
#self.shape_buffer.append(geo)
self.add_shape(geo)
# Efficient plotting for fast animation
@ -811,13 +810,12 @@ class FlatCAMDraw(QtCore.QObject):
self.axes.draw_artist(el)
#self.canvas.canvas.blit(self.axes.bbox)
#self.replot()
# Pointer (snapped)
elements = self.axes.plot(x, y, 'bo', animated=True)
for el in elements:
self.axes.draw_artist(el)
elements = self.axes.plot(x, y, 'bo', animated=True)
for el in elements:
self.axes.draw_artist(el)
self.canvas.canvas.blit(self.axes.bbox)
self.canvas.canvas.blit(self.axes.bbox)
def on_canvas_key(self, event):
"""
@ -905,7 +903,7 @@ class FlatCAMDraw(QtCore.QObject):
def plot_shape(self, geometry=None, linespec='b-', linewidth=1, animated=False):
"""
Plots a geometric object or list of objects without rendeting. Plotted objects
Plots a geometric object or list of objects without rendering. Plotted objects
are returned as a list. This allows for efficient/animated rendering.
:param geometry: Geometry to be plotted (Any Shapely.geom kind or list of such)
@ -971,7 +969,6 @@ class FlatCAMDraw(QtCore.QObject):
:type shape: DrawToolShape
:return: None
"""
print "add_shape()"
# List of DrawToolShape?
if isinstance(shape, list):

108
camlib.py
View File

@ -154,26 +154,31 @@ class Geometry(object):
if reset:
self.flat_geometry = []
## If iterable, expand recursively.
try:
for geo in geometry:
self.flatten_to_paths(geometry=geo, reset=False)
## Not iterable, do the actual indexing and add.
except TypeError:
if type(geometry) == Polygon:
g = geometry.exterior
self.flat_geometry.append(g)
self.flat_geometry_rtree.insert(len(self.flat_geometry)-1, g.coords[0])
self.flat_geometry_rtree.insert(len(self.flat_geometry)-1, g.coords[-1])
## Add first and last points of the path to the index.
self.flat_geometry_rtree.insert(len(self.flat_geometry) - 1, g.coords[0])
self.flat_geometry_rtree.insert(len(self.flat_geometry) - 1, g.coords[-1])
for interior in geometry.interiors:
g = interior
self.flat_geometry.append(g)
self.flat_geometry_rtree.insert(len(self.flat_geometry)-1, g.coords[0])
self.flat_geometry_rtree.insert(len(self.flat_geometry)-1, g.coords[-1])
self.flat_geometry_rtree.insert(len(self.flat_geometry) - 1, g.coords[0])
self.flat_geometry_rtree.insert(len(self.flat_geometry) - 1, g.coords[-1])
else:
g = geometry
self.flat_geometry.append(g)
self.flat_geometry_rtree.insert(len(self.flat_geometry)-1, g.coords[0])
self.flat_geometry_rtree.insert(len(self.flat_geometry)-1, g.coords[-1])
self.flat_geometry_rtree.insert(len(self.flat_geometry) - 1, g.coords[0])
self.flat_geometry_rtree.insert(len(self.flat_geometry) - 1, g.coords[-1])
return self.flat_geometry, self.flat_geometry_rtree
@ -258,17 +263,18 @@ class Geometry(object):
:return:
"""
# Estimate good seedpoint if not provided.
if seedpoint is None:
seedpoint = polygon.representative_point()
# Current buffer radius
radius = tooldia/2*(1-overlap)
radius = tooldia / 2 * (1 - overlap)
# The toolpaths
geoms = [Point(seedpoint).buffer(radius).exterior]
geoms = []
# Path margin
path_margin = polygon.buffer(-tooldia/2)
path_margin = polygon.buffer(-tooldia / 2)
# Grow from seed until outside the box.
while 1:
@ -281,12 +287,12 @@ class Geometry(object):
else:
geoms.append(path)
radius += tooldia*(1-overlap)
radius += tooldia * (1 - overlap)
# Clean edges
outer_edges = [x.exterior for x in autolist(polygon.buffer(-tooldia/2))]
outer_edges = [x.exterior for x in autolist(polygon.buffer(-tooldia / 2))]
inner_edges = []
for x in autolist(polygon.buffer(-tooldia/2)): # Over resulting polygons
for x in autolist(polygon.buffer(-tooldia / 2)): # Over resulting polygons
for y in x.interiors: # Over interiors of each polygon
inner_edges.append(y)
geoms += outer_edges + inner_edges
@ -2198,6 +2204,11 @@ class CNCjob(Geometry):
"""
Generates G-Code from a Geometry object. Stores in ``self.gcode``.
Algorithm description:
----------------------
Follow geometry paths in the order they are being read. No attempt
to optimize.
:param geometry: Geometry defining the toolpath
:type geometry: Geometry
:param append: Wether to append to self.gcode or re-write it.
@ -2259,14 +2270,21 @@ class CNCjob(Geometry):
"""
Second algorithm to generate from Geometry.
ALgorithm description:
----------------------
Uses RTree to find the nearest path to follow.
:param geometry:
:param append:
:param tooldia:
:param tolerance:
:return:
:return: None
"""
assert isinstance(geometry, Geometry)
flat_geometry, rtindex = geometry.flatten_to_paths()
## Flatten the geometry and get rtree index
flat_geometry, rti = geometry.flatten_to_paths()
log.debug("%d paths" % len(flat_geometry))
if tooldia is not None:
self.tooldia = tooldia
@ -2285,24 +2303,28 @@ class CNCjob(Geometry):
self.gcode += "M03\n" # Spindle start
self.gcode += self.pausecode + "\n"
# Iterate over geometry and run individual methods
# depending on type
# for geo in flat_geometry:
#
# if type(geo) == LineString or type(geo) == LinearRing:
# self.gcode += self.linear2gcode(geo, tolerance=tolerance)
# continue
#
# if type(geo) == Point:
# self.gcode += self.point2gcode(geo)
# continue
#
# log.warning("G-code generation not implemented for %s" % (str(type(geo))))
hits = list(rtindex.nearest((0, 0), 1))
## Iterate over geometry paths getting the nearest each time.
path_count = 0
current_pt = (0, 0)
hits = list(rti.nearest(current_pt, 1))
while len(hits) > 0:
path_count += 1
print "Current: ", "(%.3f, %.3f)" % current_pt
geo = flat_geometry[hits[0]]
# Determine which end of the path is closest.
distance2start = distance(current_pt, geo.coords[0])
distance2stop = distance(current_pt, geo.coords[-1])
print " Path index =", hits[0]
print " Start: ", "(%.3f, %.3f)" % geo.coords[0], " D(Start): %.3f" % distance2start
print " Stop : ", "(%.3f, %.3f)" % geo.coords[-1], " D(Stop): %.3f" % distance2stop
# Reverse if end is closest.
if distance2start > distance2stop:
print " Reversing!"
geo.coords = list(geo.coords)[::-1]
# G-code
if type(geo) == LineString or type(geo) == LinearRing:
self.gcode += self.linear2gcode(geo, tolerance=tolerance)
elif type(geo) == Point:
@ -2310,12 +2332,13 @@ class CNCjob(Geometry):
else:
log.warning("G-code generation not implemented for %s" % (str(type(geo))))
start_pt = geo.coords[0]
stop_pt = geo.coords[-1]
rtindex.delete(hits[0], start_pt)
rtindex.delete(hits[0], stop_pt)
hits = list(rtindex.nearest(stop_pt, 1))
# Delete from index, update current location and continue.
rti.delete(hits[0], geo.coords[0])
rti.delete(hits[0], geo.coords[-1])
current_pt = geo.coords[-1]
hits = list(rti.nearest(current_pt, 1))
log.debug("%s paths traced." % path_count)
# Finish
self.gcode += "G00 Z%.4f\n" % self.z_move # Stop cutting
@ -2518,6 +2541,8 @@ class CNCjob(Geometry):
:param tool_tolerance: Tolerance when drawing the toolshape.
:return: None
"""
path_num = 0
if tooldia is None:
tooldia = self.tooldia
@ -2531,7 +2556,11 @@ class CNCjob(Geometry):
axes.plot(x, y, linespec, color=linecolor)
else:
for geo in self.gcode_parsed:
poly = geo['geom'].buffer(tooldia/2.0).simplify(tool_tolerance)
path_num += 1
axes.annotate(str(path_num), xy=geo['geom'].coords[0],
xycoords='data')
poly = geo['geom'].buffer(tooldia / 2.0).simplify(tool_tolerance)
patch = PolygonPatch(poly, facecolor=color[geo['kind'][0]][0],
edgecolor=color[geo['kind'][0]][1],
alpha=alpha[geo['kind'][0]], zorder=2)
@ -2812,7 +2841,10 @@ def find_polygon(poly_set, point):
def to_dict(obj):
"""
Makes a Shapely geometry object into serializeable form.
Makes the following types into serializable form:
* ApertureMacro
* BaseGeometry
:param obj: Shapely geometry.
:type obj: BaseGeometry
@ -3149,3 +3181,7 @@ def three_point_circle(p1, p2, p3):
radius = norm(center - p1)
return center, radius, T[0]
def distance(pt1, pt2):
return sqrt((pt1[0] - pt2[0]) ** 2 + (pt1[1] - pt2[1]) ** 2)

View File

@ -7,7 +7,8 @@ Drawing
* [DONE] Arcs
* [DONE] Subtract Shapes
* [DONE] Selected objects must be kept onlist to preserve order.
* Polygon to outline
* [DONE] Cut Path
* Polygon to outline
* Force perpendicular
* Un-group (Union creates group)
* Group (But not union)

View File

@ -4,16 +4,27 @@ Installation
Windows Installer
-----------------
Download the installer from the repository_ and run it in your machine. It includes everything you need.
Download the installer from the repository_ and run it in your machine.
It includes everything you need.
.. _repository: https://bitbucket.org/jpcgt/flatcam/downloads
Ubuntu
------
FlatCAM should work on most Linux distributions but Ubuntu has been chosen as the test platform.
FlatCAM should work on most Linux distributions but Ubuntu has been
chosen as the test platform.
There are several dependencies required to run FlatCAM. These are
listed in the following section. Before attempting a manual installation,
try running the provided setup script ``setup_ubuntu.sh`` that will
download and install required packages.
OS-X
----
See manual instructions below.
There are several dependencies required to run FlatCAM. These are listed in the following section. Before attempting a manual installation, try running the provided setup script ``setup_ubuntu.sh`` that will download and install required packages.
Manual Installation
-------------------
@ -26,6 +37,9 @@ Requirements
* Matplotlib 1.3.1
* Numpy 1.8
* `Shapely 1.3`_
* GEOS
* RTree
* SpatialIndex
.. _Shapely 1.3: https://pypi.python.org/pypi/Shapely
@ -34,9 +48,14 @@ These packages might have their own dependencies.
Linux
~~~~~
Under Linux, most modern package installers like **yum** or **apt-get** will attempt to locate and install the whole tree of dependencies for a specified package automatically. Refer to the provided setup script ``setup_ubuntu.sh`` for the names and installation order.
Under Linux, most modern package installers like **yum** or **apt-get**
will attempt to locate and install the whole tree of dependencies for a
specified package automatically. Refer to the provided setup script
``setup_ubuntu.sh`` for the names and installation order.
Once the dependencies are installed, download the latest .zip release (or the latest source, although it is not garanteed to work), unpack it, change into the created folder and run::
Once the dependencies are installed, download the latest .zip release
(or the latest source, although it is not garanteed to work), unpack it,
change into the created folder and run::
Python FlatCAM.py
@ -44,11 +63,36 @@ Once the dependencies are installed, download the latest .zip release (or the la
Windows
~~~~~~~
An easy way to get the requirements in your system is to install WinPython_. This is a standalone distribution of Python which includes all of FlatCAM's dependencies, except for Shapely.
An easy way to get the requirements in your system is to install WinPython_.
This is a standalone distribution of Python which includes all of FlatCAM's
dependencies, except for Shapely.
.. _WinPython: http://winpython.sourceforge.net/
Once the dependencies are installed, download the latest .zip release (or the latest source, although it is not garanteed to work), unpack it, change into the created folder and run::
Once the dependencies are installed, download the latest .zip
release (or the latest source, although it is not garanteed to work),
unpack it, change into the created folder and run::
Python FlatCAM.py
python FlatCAM.py
OS-X
~~~~
Start by installing binary packages: pyqt, geos, spatialindex.
One way to do this is using Homebrew_::
brew install name_of_package
.. _Homebrew: http://brew.sh
Now you can install all Python packages (numpy, matplotlib, rtree, scipy,
shapely, simplejson) using pip::
pip install name_of_package
Finally, download the latest FlatCAM .zip package or source code. Change into
its directory and launch it by running::
python FlatCAM.py