Commit dd10fa15 authored by lode_leroy's avatar lode_leroy

Contour

git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@48 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent d530ae74
Currently it is not necessary to install the software,
simply unpack the distribution archive, and run "python pycam.py"
from the archive directory
DEPENDENCIES:
-------------
Windows:
--------
Python 2.5
PyOpenGL : http://pyopengl.sourceforge.net/
http://downloads.sourceforge.net/pyopengl/PyOpenGL-3.0.0.win32.exe
TOGL: http://downloads.sourceforge.net/togl/Togl2.0-8.4-Windows.zip
(just copy the directory Togl2.0 into Python25/tcl)
GLUT : http://www.cip.physik.uni-muenchen.de/~georg.hennig/downloads/glut-3.7.6-wheel_mingw.zip
Unix:
-----
Install PyOpenGL, Togl, Glut using your package manager.
Or compile from source:
http://downloads.sourceforge.net/pyopengl/PyOpenGL-3.0.0.tar.gz
In case Togl is not available or not working, I suggest to compile Togl yourself.
http://downloads.sourceforge.net/togl/Togl2.0-src.tar.gz
Install the source packages for tcl and tk using your package manager.
cd ~/Togl2.0
./configure --prefix=/usr --exec-prefix=/usr --enable-threads
make
make install
or, failing that, for download the sources for the same version of tcl and tk
as you have installed on your system:
(http://sourceforge.net/project/showfiles.php?group_id=10894&package_id=10452)
Togl only needs access to a few header files that are not part of the
binary distributions...
I unpacked the tcl and tk sources next to the Togl sources in my home directory, then
cd ~/tcl-8.5.5/unix;
./configure
cd ~/tk-8.5.5/unix;
./configure
cd ~/Togl2.0;
./configure --with-tcl=$HOME/tcl-8.5.5 --with-tk=$HOME/tk-8.5.5 \
--prefix=/usr --exec-prefix=/usr --enable-threads
make
make install
......@@ -19,6 +19,7 @@ Features:
** Linear
** ZigZag
** Polygon
** Contour (aka. waterline)
* Importers:
** STL
......@@ -30,23 +31,6 @@ Features:
** OpenGL
INSTALL:
PyOpenGL : http://pyopengl.sourceforge.net/
http://downloads.sourceforge.net/pyopengl/PyOpenGL-3.0.0b5.tar.gz
(requires TOGL)
TOGL: http://downloads.sourceforge.net/togl/Togl2.0-8.4-Windows.zip
(just copy Togl2.0 into Python25/tcl)
http://downloads.sourceforge.net/togl/Togl2.0-src.tar.gz
(download tcl-8.4-src.tgz and tk-8.4-src.tgz and compile and install togl)
(on windows, this also requires GLUT)
GLUT : http://www.cip.physik.uni-muenchen.de/~georg.hennig/downloads/glut-3.7.6-wheel_mingw.zip
RUNNING:
extract the archive and run "python pycam.py"
......@@ -57,12 +41,21 @@ USAGE:
as a practical approach, you would probably:
1) use the Cylindrical cutter with the PushCutter Pathgenerator and the Polygon PostProcessor to do the "rough" cutting
1) for "rough" cutting,
use the Cylindrical cutter
with the PushCutter Pathgenerator
and the Polygon PostProcessor in "x" or "y" mode
2) use the Toroidal cutter with the ContourCutter Pathgenerator to do the "semifinish" cutting.
(it's not yet implemented, so you can skip this one for now :-)
2) for "semifinish" cutting,
use the Cylindrical/Toroidal cutter
with the PushCutter Pathgenerator
and the Contour PostProcessor in "xy" mode
3) use the Spherical cutter with the DropCutter Pathgenerator and the ZigZag PostProcessor to do the "finish" cutting.
3) "finish" cutting
use the Spherical cutter
with the DropCutter Pathgenerator
and the ZigZag PostProcessor in "x" or "y" mode
TODO:
......@@ -78,12 +71,8 @@ TODO:
* Cutters
** FiletCutter
* PathGenerators
** ContourCutter
-> waterlevel tracer
* PathProcessors
** Traveling Salesman
** Traveling Salesman for Polygon PostProcessor
* Gui
** create something better than "SimpleGui"
......@@ -98,15 +87,13 @@ FEATURE REQUESTS:
* diagonal paths
* start at arbitrary corner
KNOWN BUGS:
* The combination of PushCutter with PolygonCutter sometimes cuts accross
the model in between lines
* The combination of PushCutter with ContourCutter sometimes cuts accross
the model in between lines in "x" or "y" mode
* The combination of PushCutter with ContourCutter sometimes gives erratic
toolpaths in "xy" mode
* The combination of PushCutter with PolygonCutter and ContourCutter
sometimes make tiny cuts accross the model in between lines
OPTIMIZATION:
......@@ -114,7 +101,7 @@ OPTIMIZATION:
* short-circuit the plane/triangle/line/edge/point/vertex tests,
so that when the result is known, no further intersections are calculated
* use kdtree
* use kdtree to speed up collision detection
* make Model have unique points
......
......@@ -16,11 +16,13 @@ def g(x):
def b(x):
return ((col[(x)%12]>> 0)&0xff)
def test_image(image):
def test_image(image, image2=None):
pe = PolygonExtractor(policy=PolygonExtractor.CONTOUR)
h = len(image)
w = len(image[0])
for dir in [0, 1]:
for dir in [1, 0, 1]:
if dir == 1 and image2:
image = image2
pe.new_direction(dir)
imax = 0
jmax = 0
......@@ -80,10 +82,10 @@ def test_image(image):
elif dir == 1:
path_list = pe.ver_path_list
else:
if hasattr(pe, "merge_path_list"):
path_list = pe.merge_path_list
else:
path_list = []
path_list = pe.merge_path_list
if not path_list:
continue
for curr_path in path_list:
for point in curr_path.points:
......@@ -211,132 +213,167 @@ if __name__ == "__main__":
if (test==0):
image = [
" ",
" ** ",
" **** ",
" ****** ",
" ****** ",
" **** ",
" ** ",
" ",
" ",
" ** ",
" **** ",
" ****** ",
" ****** ",
" **** ",
" ** ",
" ",
]
test_image(image)
if (test==1):
image = [
" ",
" ****** ",
" *** ***** ",
" ** ***** ",
" *** ",
" ",
" ",
" ****** ",
" *** ***** ",
" ** ***** ",
" *** ",
" ",
]
test_image(image)
if (test==2):
image = [
" ",
" *** ",
" ***** ** ",
" ***** *** ",
" ***** ",
" ",
" ",
" *** ",
" ***** ** ",
" ***** *** ",
" ***** ",
" ",
]
test_image(image)
if (test==3):
image = [
" ",
" ******* ",
" ********* ",
" *** *** *** ",
" ** *** ** ",
" ",
" ",
" ",
" ******* ",
" ********* ",
" *** *** *** ",
" ** *** ** ",
" ",
" ",
]
test_image(image)
if (test==4):
image = [
" ",
" ** *** ** ",
" *** *** *** ",
" ********* ",
" ******* ",
" ",
" ",
" ",
" ** *** ** ",
" *** *** *** ",
" ********* ",
" ******* ",
" ",
" ",
]
test_image(image)
if (test==5):
image = [
" ",
" ******* ",
" ********* ",
" *** *** *** ",
" ** *** ** ",
" *** *** *** ",
" ********* ",
" ******* ",
" ",
" ",
" ",
" ******* ",
" ********* ",
" *** *** *** ",
" ** *** ** ",
" *** *** *** ",
" ********* ",
" ******* ",
" ",
" ",
]
test_image(image)
if (test==6):
image = [
" ",
" ******* ",
" ********* ",
" *** *** *** ",
" ********* ",
" ******* ",
" ",
" ",
" ",
" ******* ",
" ********* ",
" *** *** *** ",
" ********* ",
" ******* ",
" ",
" ",
]
test_image(image)
if (test==7):
image = [
" ",
" *********** ",
" ***** ***** ",
" ** ***** ** ",
" *********** ",
" ",
" ",
" ",
" *********** ",
" ***** ***** ",
" ** ***** ** ",
" *********** ",
" ",
" ",
]
test_image(image)
if (test==8):
image = [
" ",
" *********** ",
" ** ** ",
" ** ***** ** ",
" ** *** *** ** ",
" ** ** ** ** ",
" ** *** *** ** ",
" ** ***** ** ",
" ** ** ",
" *********** ",
" ",
" ",
" ",
" *********** ",
" ** ** ",
" ** ***** ** ",
" ** *** *** ** ",
" ** ** ** ** ",
" ** *** *** ** ",
" ** ***** ** ",
" ** ** ",
" *********** ",
" ",
" ",
]
test_image(image)
if (test==9):
image = [
" ",
" ",
" *********** ",
" *********** ",
" *********** ",
" *********** ",
" ",
" ",
" *** ",
" ***** ",
" ********* ",
" *********** ",
" ",
" ",
]
image2 = [
" ",
" ",
" *********** ",
" *********** ",
" *********** ",
" *********** ",
" ",
" * ",
" *** ",
" ***** ",
" ********* ",
" *********** ",
" ",
" ",
]
test_image(image, image2 )
if (test==10):
image = [
" ",
" ******************** ",
" **************************** ",
" ************ ************ ",
" ***** ******** ********* ******* ",
" ************** ***** ****** ",
" ******************** ******* ",
" *********************** ",
" "
" ",
" ******************** ",
" **************************** ",
" ************ ************ ",
" ***** ******** ********* ******* ",
" ************** ***** ****** ",
" ******************** ******* ",
" *********************** ",
" "
]
test_image(image)
......
......@@ -5,24 +5,17 @@ from pycam.Geometry.Path import *
from pycam.Geometry.Point import *
DEBUG_POLYGONEXTRACTOR=False
DEBUG_POLYGONEXTRACTOR2=False
class PolygonExtractor:
CONTOUR=1
MONOTONE=2
def __init__(self, policy=MONOTONE):
self.policy = policy
self.hor_path_list = None
self.ver_path_list = None
self.merge_path_list = None
self.dx = 1
self.dy = 1
def append(self, p):
if (self.current_dir==0):
self.curr_line.append(p)
elif self.current_dir==1:
# store as flipped
self.curr_line.append(Point(p.y, p.x, p.z))
def new_direction(self, dir):
self.current_dir = dir
......@@ -30,17 +23,37 @@ class PolygonExtractor:
self.curr_path_list = []
self.prev_line = []
self.curr_line = []
if self.policy == PolygonExtractor.CONTOUR and dir == 1 and self.hor_path_list:
self.last_x = -INFINITE
self.delta_x = 0
self.convert_hor_path_list()
def end_direction(self):
if self.policy == PolygonExtractor.CONTOUR and self.hor_path_list:
self.process_virtual_hor_scanline(INFINITE)
self.new_scanline()
self.end_scanline()
if self.policy == PolygonExtractor.CONTOUR and self.hor_path_list:
for path in self.all_path_list:
i = 0
while i < len(path.points)-1:
if path.points[i].x > path.points[i+1].x:
if DEBUG_POLYGONEXTRACTOR2: print "drop point %d:" % path.points[i].id
path.points = path.points[:i] + path.points[i+1:]
if i>0:
i -= 1
else:
i += 1
if DEBUG_POLYGONEXTRACTOR: print "%d paths" % len(self.all_path_list)
for path in self.all_path_list:
if DEBUG_POLYGONEXTRACTOR: print "%d:" % path.id,
if DEBUG_POLYGONEXTRACTOR: print "%d ->" % path.top_join.id
for point in path.points:
if DEBUG_POLYGONEXTRACTOR: print "(%g,%g)" % (point.x, point.y),
if DEBUG_POLYGONEXTRACTOR: print "%d(%g,%g)" % (point.id, point.x, point.y),
if DEBUG_POLYGONEXTRACTOR: print "->%d" % path.bot_join.id
path_list = []
......@@ -74,33 +87,46 @@ class PolygonExtractor:
for path in path_list:
if DEBUG_POLYGONEXTRACTOR: print "path %d(w=%d): " % (path.id, path.winding),
for point in path.points:
if DEBUG_POLYGONEXTRACTOR: print "(%g,%g)" % (point.x, point.y),
if DEBUG_POLYGONEXTRACTOR: print "%d(%g,%g)" % (point.id, point.x, point.y),
if DEBUG_POLYGONEXTRACTOR: print
if self.current_dir==0:
self.hor_path_list = path_list
elif self.current_dir==1:
# flip back since we stored the points flipped (see add_point)
for path in path_list:
path.reverse()
for point in path.points:
(point.x,point.y) = (point.y,point.x)
self.ver_path_list = path_list
if self.policy == PolygonExtractor.CONTOUR and self.hor_path_list and self.ver_path_list:
self.merge_path_list = path_list
else:
self.ver_path_list = path_list
def finish(self):
if self.policy == PolygonExtractor.CONTOUR:
if self.hor_path_list and self.ver_path_list:
self.merge_path_lists()
pass
def new_scanline(self):
self.curr_line = []
def append(self, p):
self.curr_line.append(p)
def end_scanline(self):
if self.current_dir==0:
self.process_hor_scanline(self.curr_line)
elif self.current_dir==1:
if self.policy == PolygonExtractor.CONTOUR and self.hor_path_list:
next_x = 0
if len(self.curr_line)>0:
next_x = self.curr_line[0].x
self.delta_x = next_x - self.last_x
self.last_x = next_x
else:
next_x = self.last_x + self.delta_x
self.process_virtual_hor_scanline(next_x)
self.process_ver_scanline(self.curr_line)
def process_hor_scanline(self, scanline):
last = 0
inside = False
s = ""
for point in self.curr_line:
for point in scanline:
next = point.x
if inside:
s += "*" * int(next-last)
......@@ -121,12 +147,12 @@ class PolygonExtractor:
if DEBUG_POLYGONEXTRACTOR: print
if DEBUG_POLYGONEXTRACTOR: print "active points: ",
for point in self.curr_line:
for point in scanline:
if DEBUG_POLYGONEXTRACTOR: print "(%g,%g)" % (point.x, point.y),
if DEBUG_POLYGONEXTRACTOR: print
prev_point = Iterator(self.prev_line)
curr_point = Iterator(self.curr_line)
curr_point = Iterator(scanline)
curr_path = Iterator(self.curr_path_list)
winding = 0
......@@ -304,119 +330,337 @@ class PolygonExtractor:
if DEBUG_POLYGONEXTRACTOR: print "%d(%g,%g,w=%d)" % (path.id, path.points[-1].x, path.points[-1].y, path.winding),
if DEBUG_POLYGONEXTRACTOR: print
self.prev_line = self.curr_line
def merge_path_lists(self):
self.merge_path_list = []
# find matching path to merge with */
for s0 in self.hor_path_list:
if DEBUG_POLYGONEXTRACTOR: print "merging %d" % s0.id
if DEBUG_POLYGONEXTRACTOR: print "s0=", s0
#TODO: store/cache topmost point inside the path
# find top of path to merge
point_iter = Iterator(s0.points)
top0 = CyclicIterator(point_iter.seq, point_iter.ind)
min_x0 = top0.peek().x
min_y0 = top0.peek().y
while point_iter.remains()>0:
point = point_iter.peek()
if point and ((point.y<min_y0) or (point.y==min_y0 and point.x>min_x0)):
min_y0 = point.y
min_x0 = point.x
top0 = CyclicIterator(point_iter.seq, point_iter.ind)
point_iter.next()
if DEBUG_POLYGONEXTRACTOR: print "top0: x=", min_x0, "y=",min_y0, "p=",top0.peek().id
# find matching path to merge with
path_iter = Iterator(self.ver_path_list)
while path_iter.remains()>0:
s1 = path_iter.next()
if DEBUG_POLYGONEXTRACTOR: print "trying %d" % s1.id
if DEBUG_POLYGONEXTRACTOR: print "s1=", s1
min_d = -1
point_iter = Iterator(s1.points)
top1 = None
min_x1 = 0
min_y1 = 0
while point_iter.remains()>0:
point = point_iter.peek()
# check points in second quadrant # TODO: if none found: check other quadrants
if point.y<=min_y0 and point.x<=min_x0:
d = sqr(point.x-min_x0)+sqr(point.y-min_y0)
if (d<min_d or top1==None):
min_x1 = point.x
min_y1 = point.y
min_d = d
top1 = CyclicIterator(point_iter.seq, point_iter.ind)
point_iter.next()
if DEBUG_POLYGONEXTRACTOR: print "min_y0=%g min_y1=%g (d=%g)" % (min_y0, min_y1, min_d)
if min_d < 0:
continue
if DEBUG_POLYGONEXTRACTOR: print "top1: x=", min_x1, "y=",min_y1, "p=",top1.peek().id
if (min_y1 >= min_y0-self.dy) and (min_y1 <= min_y0+self.dy) and (min_x1 >= min_x0-self.dx) and (min_x1 <= min_x0+self.dx):
# we have a potential match
if DEBUG_POLYGONEXTRACTOR: print "matched %d" % s1.id
if DEBUG_POLYGONEXTRACTOR: print "i0=%d i1=%d" % (top0.peek().id, top1.peek().id)
if DEBUG_POLYGONEXTRACTOR: print "s1=", s1
total = len(s0.points) + len(s1.points)
p = Path()
p.winding = s0.winding
p0 = top0.next()
p1 = top1.next()
next_p0 = top0.peek()
next_p1 = top1.peek()
if p0.y == next_p0.y:
while (p1.y < p0.y) and (next_p1.y < p0.y) and (p0.x <= p1.x) and (p1.x <= next_p0.x):
p1 = top1.next()
next_p1 = top1.peek()
if DEBUG_POLYGONEXTRACTOR: print "top0=%d: (%g,%g)" % (p0.id, p0.x, p0.y)
if DEBUG_POLYGONEXTRACTOR: print "top1=%d: (%g,%g)" % (p1.id, p1.x, p1.y)
last = p0;
pathlen = 0
while pathlen < total:
next_p0 = top0.peek()
next_p1 = top1.peek()
pathlen = len(p.points)
if DEBUG_POLYGONEXTRACTOR: print "last=%d: (%g, %g)" % (last.id, last.x, last.y)
if DEBUG_POLYGONEXTRACTOR: print "p0: %d(%g,%g)\t" % (p0.id, p0.x, p0.y),
if DEBUG_POLYGONEXTRACTOR: print "next_p0: %d(%g,%g)" % (next_p0.id, next_p0.x, next_p0.y)
if DEBUG_POLYGONEXTRACTOR: print "p1: %d(%g,%g)\t" % (p1.id, p1.x, p1.y),
if DEBUG_POLYGONEXTRACTOR: print "next_p1: %d(%g,%g)" % (next_p1.id, next_p1.x, next_p1.y)
if DEBUG_POLYGONEXTRACTOR: print "|p1-last|=%g |p0-last|=%g" % (sqr(p1.x - last.x) + sqr(p1.y - last.y), sqr(p0.x - last.x) + sqr(p0.y - last.y))
if sqr(p1.x - last.x) + sqr(p1.y - last.y) < sqr(p0.x - last.x) + sqr(p0.y - last.y):
if DEBUG_POLYGONEXTRACTOR: print "0: p1=%d: (%g,%g)" % (p1.id, p1.x, p1.y)
p.append(p1)
last = p1
p1 = top1.next()
continue
else:
if DEBUG_POLYGONEXTRACTOR: print "1: p0=%d: (%g,%g)" % (p0.id, p0.x, p0.y)
p.append(p0)
last = p0
p0 = top0.next()
continue;
if pathlen == len(p):
if DEBUG_POLYGONEXTRACTOR: print "failed: size=%d total=%d" %(len(p), total)
p = None
break
if p:
self.merge_path_list.append(p)
if DEBUG_POLYGONEXTRACTOR: print "done: size=%d total=%d" % (len(p.points), total)
break
self.prev_line = scanline
def process_ver_scanline(self, scanline, next_x=-INFINITE):
last = 0
inside = False
s = ""
for point in scanline:
next = point.y
if inside:
s += "*" * int(next-last)
else:
s += " " * int(next-last)
last = next
inside = not inside
if DEBUG_POLYGONEXTRACTOR: print s
if DEBUG_POLYGONEXTRACTOR: print "active paths: ",
for path in self.curr_path_list:
if DEBUG_POLYGONEXTRACTOR: print "%d(%g,%g)" % (path.id, path.points[-1].x, path.points[-1].y),
if DEBUG_POLYGONEXTRACTOR: print
if DEBUG_POLYGONEXTRACTOR: print "prev points: ",
for point in self.prev_line:
if DEBUG_POLYGONEXTRACTOR: print "(%g,%g)" % (point.x, point.y),
if DEBUG_POLYGONEXTRACTOR: print
if DEBUG_POLYGONEXTRACTOR: print "active points: ",
for point in scanline:
if DEBUG_POLYGONEXTRACTOR: print "(%g,%g)" % (point.x, point.y),
if DEBUG_POLYGONEXTRACTOR: print
prev_point = Iterator(self.prev_line)
curr_point = Iterator(scanline)
curr_path = Iterator(self.curr_path_list)
winding = 0
while prev_point.remains()>0 or curr_point.remains()>0:
if DEBUG_POLYGONEXTRACTOR: print "num_prev=", prev_point.remains(), ", num_curr=",curr_point.remains()
if prev_point.remains()==0 and curr_point.remains()>=2:
c0 = curr_point.next()
c1 = curr_point.next()
# new path starts
p0 = Path()
p0.winding = winding+1
if DEBUG_POLYGONEXTRACTOR: print "new path %d(%g,%g)" % ( p0.id, c0.x, c0.y)
p0.append(c0)
self.curr_path_list.append(p0)
p1 = Path()
p1.winding = winding
if DEBUG_POLYGONEXTRACTOR: print "new path %d(%g,%g)" % (p1.id, c1.x, c1.y)
p1.append(c1)
self.curr_path_list.append(p1)
p0.top_join = p1
p1.top_join = p0
continue
if prev_point.remains()>=2 and curr_point.remains()==0:
#old path ends
p0 = curr_path.takeNext()
if DEBUG_POLYGONEXTRACTOR: print "end path %d" % p0.id
self.all_path_list.append(p0)
prev_point.next()
p1 = curr_path.takeNext()
if DEBUG_POLYGONEXTRACTOR: print "end path %d" % p1.id
self.all_path_list.append(p1)
prev_point.next()
p0.bot_join = p1
p1.bot_join = p0
continue
if prev_point.remains()>=2 and curr_point.remains()>=2:
p0 = prev_point.peek(0)
p1 = prev_point.peek(1)
c0 = curr_point.peek(0)
c1 = curr_point.peek(1)
if DEBUG_POLYGONEXTRACTOR: print "overlap test: p0=%g p1=%g" % (p0.x, p1.x)
if DEBUG_POLYGONEXTRACTOR: print "overlap test: c0=%g c1=%g" % (c0.x, c1.x)
if c1.y < p0.y:
# new segment is completely to the left
# new path starts
s0 = Path()
if DEBUG_POLYGONEXTRACTOR: print "new path %d(%g,%g) w=%d" % (s0.id, c0.x, c0.y, winding+1)
s0.append(c0)
curr_path.insert(s0)
s1 = Path()
s0.winding = winding+1
s1.winding = winding
if DEBUG_POLYGONEXTRACTOR: print "new path %d(%g,%g) w=%d" % (s1.id, c1.x, c1.y, winding)
s1.append(c1)
curr_path.insert(s1)
curr_point.next()
curr_point.next()
s0.top_join = s1
s1.top_join = s0
elif c0.y > p1.y:
# new segment is completely to the right
# old path ends
s0 = curr_path.takeNext()
if DEBUG_POLYGONEXTRACTOR: print "end path %d" % s0.id
self.all_path_list.append(s0)
prev_point.next()
s1 = curr_path.takeNext()
if DEBUG_POLYGONEXTRACTOR: print "end path %d" % s1.id
self.all_path_list.append(s1)
prev_point.next()
s0.bot_join = s1;
s1.bot_join = s0;
winding = s1.winding;
else:
# new segment is overlapping
left_path = curr_path.next()
right_path = curr_path.peek()
left_point = c0
right_point = c1
winding = left_path.winding
curr_point.next()
prev_point.next()
overlap_p = True
overlap_c = True
while overlap_c or overlap_p:
overlap_p = False
overlap_c = False
# check for path joins
if prev_point.remains()>=2:
p2 = prev_point.peek(1)
if DEBUG_POLYGONEXTRACTOR: print "join test: p0=%g p1=%g p2=%g" % (p0.x, p1.x, p2.x)
if DEBUG_POLYGONEXTRACTOR: print "join test: c0=%g c1=%g" % (c0.x, c1.x)
if p2.y <= c1.y:
overlap_p = True
if self.policy == PolygonExtractor.CONTOUR:
s0 = curr_path.takeNext()
s1 = curr_path.takeNext()
if curr_path.remains()>=1:
right_path = curr_path.peek()
self.all_path_list.append(s0)
self.all_path_list.append(s1);
if DEBUG_POLYGONEXTRACTOR: print "path %d joins %d" % (s0.id, s1.id)
s0.bot_join = s1;
s1.bot_join = s0;
elif self.policy == PolygonExtractor.MONOTONE:
s0 = curr_path.takeNext()
left_path.bot_join = s0
s0.bot_join = left_path
if DEBUG_POLYGONEXTRACTOR: print "path %d joins %d" % (left_path.id, s0.id)
curr_path.remove(left_path)
self.all_path_list.append(left_path)
self.all_path_list.append(s0)
s1 = curr_path.next()
left_path = s1
right_path = curr_path.peek()
prev_point.next()
prev_point.next()
winding = s1.winding
p0 = p2
if prev_point.remains()>=1:
p1 = prev_point.peek(0)
else:
overlap_p = False
# check for path splits
if curr_point.remains()>=2:
c2 = curr_point.peek(1)
if DEBUG_POLYGONEXTRACTOR: print "split test: p0=%g p1=%g" % (p0.x, p1.x)
if DEBUG_POLYGONEXTRACTOR: print "split test: c0=%g c1=%g c2=%g" % (c0.x, c1.x, c2.x)
if c2.y <= p1.y:
overlap_c = True
s0 = Path()
s1 = Path()
s0.winding=winding+1
s1.winding=winding
s0.top_join = s1
s1.top_join = s0
if DEBUG_POLYGONEXTRACTOR: print "region split into %d and %d (w=%d)" %(s0.id, s1.id, winding+1)
curr_point.next()
c0 = curr_point.next()
if self.policy == PolygonExtractor.CONTOUR:
s0.append(c1)
curr_path.insert(s0)
s1.append(c2)
curr_path.insert(s1)
elif self.policy == PolygonExtractor.MONOTONE:
s0.append(left_point)
s1.append(c1)
curr_path.insertBefore(s0)
curr_path.insertBefore(s1)
left_point = c2
if curr_point.remains()>=1:
c1 = curr_point.peek(0)
right_point = c1
else:
overlap_c = False
if DEBUG_POLYGONEXTRACTOR: print "add to path %d(%g,%g)" % (left_path.id, left_point.x, left_point.y)
left_path.append(left_point)
right_path.append(right_point)
if right_path == curr_path.peek():
curr_path.next()
if DEBUG_POLYGONEXTRACTOR: print "add to path %d(%g,%g)" % (right_path.id, right_point.x, right_point.y)
winding = right_path.winding;
prev_point.next()
curr_point.next()
if DEBUG_POLYGONEXTRACTOR: print "active paths: ",
for path in self.curr_path_list:
if DEBUG_POLYGONEXTRACTOR: print "%d(%g,%g,w=%d)" % (path.id, path.points[-1].x, path.points[-1].y, path.winding),
if DEBUG_POLYGONEXTRACTOR: print
self.prev_line = scanline
def convert_hor_path_list(self):
if DEBUG_POLYGONEXTRACTOR2: print "converting hor paths"
hor_path_list = []
for s in self.hor_path_list:
allsame = True
miny = s.points[0].y
maxy = s.points[0].y
for p in s.points:
if not p.x == s.points[0].x:
allsame=False
if p.y < miny:
miny = p.y
if p.y > maxy:
maxy = p.y
if allsame:
if DEBUG_POLYGONEXTRACTOR2: print "all same !"
s0 = Path()
for p in s.points:
if p.y == miny:
s0.append(p)
hor_path_list.append(s0)
s1 = Path()
for p in s.points:
if p.y == maxy:
s1.append(p)
hor_path_list.append(s1)
continue
prev = s.points[-1]
iter = CyclicIterator(s.points)
p = s.points[0]
next = iter.next()
while not (prev.x >= p.x and next.x > p.x):
p = next
next = iter.next()
count = 0
while count < len(s.points):
s0 = Path()
while next.x >= p.x:
s0.append(p)
p = next
next = iter.next()
count += 1
s0.append(p)
while len(s0.points)>1 and s0.points[0].x == s0.points[1].x:
s0.points = s0.points[1:]
while len(s0.points)>1 and s0.points[-2].x == s0.points[-1].x:
s0.points = s0.points[0:-1]
hor_path_list.append(s0)
s1 = Path()
while next.x <= p.x:
s1.append(p)
p = next
next = iter.next()
count += 1
s1.append(p)
s1.reverse()
while len(s1.points)>1 and s1.points[0].x == s1.points[1].x:
s1.points = s1.points[1:]
while len(s1.points)>1 and s1.points[-2].x == s1.points[-1].x:
s1.points = s1.points[0:-1]
hor_path_list.append(s1)
hor_path_list.sort(cmp=lambda a,b:cmp(a.points[0].x,b.points[0].x))
if DEBUG_POLYGONEXTRACTOR2:
print "ver_hor_path_list = ", hor_path_list
for s in hor_path_list:
print "s%d =" % s.id,
for point in s.points:
print point.id,
print
self.ver_hor_path_list = hor_path_list
self.act_hor_path_list = []
def process_virtual_hor_scanline(self, next_x):
if len(self.ver_hor_path_list)>0 and self.ver_hor_path_list[0].points[0].x < next_x:
next_x = self.ver_hor_path_list[0].points[0].x
if len(self.act_hor_path_list)>0 and self.act_hor_path_list[0].points[0].x < next_x:
next_x = self.act_hor_path_list[0].points[0].x
if DEBUG_POLYGONEXTRACTOR2:
print "ver_hor_path_list =", self.ver_hor_path_list
print "act_hor_path_list =", self.act_hor_path_list
print "next_x =", next_x
if len(self.ver_hor_path_list)>0 and self.ver_hor_path_list[0].points[0].x <= next_x:
while len(self.ver_hor_path_list)>0 and self.ver_hor_path_list[0].points[0].x <= next_x:
self.act_hor_path_list.append(self.ver_hor_path_list[0])
self.ver_hor_path_list = self.ver_hor_path_list[1:]
self.act_hor_path_list.sort(cmp=lambda a,b:cmp(a.points[0].x,b.points[0].x))
while len(self.act_hor_path_list)>0 and self.act_hor_path_list[0].points[0].x <= next_x:
scanline = []
i = 0
while i < len(self.act_hor_path_list):
s = self.act_hor_path_list[i]
if DEBUG_POLYGONEXTRACTOR2: print "s =",s
scanline.append(s.points[0])
if s.points[0].x <= next_x:
if len(s.points) <= 1:
if DEBUG_POLYGONEXTRACTOR2: print "remove list"
self.act_hor_path_list = self.act_hor_path_list[:i]+self.act_hor_path_list[i+1:]
hor_list_removed = True
continue
else:
if DEBUG_POLYGONEXTRACTOR2: print "remove point", s.points[0]
s.points = s.points[1:]
if len(s.points)> 0 and s.points[0].x == next_x:
repeat = True
i += 1
self.act_hor_path_list.sort(cmp=lambda a,b:cmp(a.points[0].x,b.points[0].x))
scanline.sort(cmp=lambda a,b:cmp(a.y,b.y))
if DEBUG_POLYGONEXTRACTOR2:
print "scanline =", scanline
print "ver_hor_path_list =", self.ver_hor_path_list
print "act_hor_path_list =", self.act_hor_path_list
self.process_ver_scanline(scanline)
......@@ -6,13 +6,16 @@ class ContourCutter:
self.paths = []
self.curr_path = None
self.scanline = None
self.pe = PolygonExtractor(PolygonExtractor.CONTOUR)
self.pe = None
self.points = []
def append(self, p):
self.points.append(p)
def new_direction(self, dir):
if self.pe == None:
self.pe = PolygonExtractor(PolygonExtractor.CONTOUR)
self.pe.new_direction(dir)
def end_direction(self):
......@@ -38,5 +41,5 @@ class ContourCutter:
self.paths = self.pe.ver_path_list
for p in self.paths:
p.append(p.points[0])
self.pe = None
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment