Paint bucketing shapes mostly working
This commit is contained in:
parent
879a7c18a9
commit
664d0e67ac
|
|
@ -10,6 +10,7 @@ import math
|
||||||
import subprocess
|
import subprocess
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
def select_any(self):
|
def select_any(self):
|
||||||
svlgui.MODE = " "
|
svlgui.MODE = " "
|
||||||
|
|
@ -266,3 +267,27 @@ def pairwise(iterable):
|
||||||
a, b = tee(iterable)
|
a, b = tee(iterable)
|
||||||
next(b, None)
|
next(b, None)
|
||||||
return izip(a, b)
|
return izip(a, b)
|
||||||
|
|
||||||
|
def hittest(linelist,x,y):
|
||||||
|
hits = False
|
||||||
|
def IsOnLeft(a, b, c):
|
||||||
|
return Area2(a, b, c) > 0
|
||||||
|
def IsOnRight(a, b, c):
|
||||||
|
return Area2(a, b, c) < 0
|
||||||
|
def IsCollinear(a, b, c):
|
||||||
|
return Area2(a, b, c) == 0
|
||||||
|
# calculates the triangle's size (formed by the "anchor" segment and additional point)
|
||||||
|
def Area2(a, b, c):
|
||||||
|
return (b[0]-a[0])*(c[1]-a[1])-(c[0]-a[0])*(b[1]-a[1])
|
||||||
|
def intersects(a,b,c,d):
|
||||||
|
return not (IsOnLeft(a,b,c) != IsOnRight(a,b,d))
|
||||||
|
def ccw(a,b,c):
|
||||||
|
return (c[1]-a[1])*(b[0]-a[0]) > (b[1]-a[1])*(c[0]-a[0])
|
||||||
|
def intersect(a,b,c,d):
|
||||||
|
return ccw(a,c,d) != ccw(b,c,d) and ccw(a,b,c) != ccw(a,b,d)
|
||||||
|
for i in xrange(len(linelist)):
|
||||||
|
hits = hits != intersect([linelist[i-1].endpoint1.x,linelist[i-1].endpoint1.y],
|
||||||
|
[linelist[i].endpoint1.x,linelist[i].endpoint1.y],[x,y],[x,sys.maxint])
|
||||||
|
print hits, x, y
|
||||||
|
return hits
|
||||||
|
|
||||||
|
|
|
||||||
99
svlgui.py
99
svlgui.py
|
|
@ -2631,6 +2631,8 @@ class Group (object):
|
||||||
cr.pencolor = Color([0,0,1]).pygui
|
cr.pencolor = Color([0,0,1]).pygui
|
||||||
cr.stroke_rect([sorted([self.startx,self.cx])[0], sorted([self.starty,self.cy])[0], \
|
cr.stroke_rect([sorted([self.startx,self.cx])[0], sorted([self.starty,self.cy])[0], \
|
||||||
sorted([self.startx,self.cx])[1], sorted([self.starty,self.cy])[1]])
|
sorted([self.startx,self.cx])[1], sorted([self.starty,self.cy])[1]])
|
||||||
|
for i in self.fills:
|
||||||
|
i.draw(cr, rect=rect)
|
||||||
for i in self.lines:
|
for i in self.lines:
|
||||||
i.draw(cr, rect=rect)
|
i.draw(cr, rect=rect)
|
||||||
def add(self, *args):
|
def add(self, *args):
|
||||||
|
|
@ -2720,17 +2722,15 @@ class Group (object):
|
||||||
return
|
return
|
||||||
elif MODE=="b":
|
elif MODE=="b":
|
||||||
nlines = [i for i in self.lines]
|
nlines = [i for i in self.lines]
|
||||||
endsleft = True
|
# First, remove all line segments that have at least one free endpoit, not coincident with any other segment.
|
||||||
while endsleft:
|
# Do that repeatedly until no such segment remains.
|
||||||
endsleft = False
|
|
||||||
print nlines
|
|
||||||
for i in reversed(nlines):
|
for i in reversed(nlines):
|
||||||
if not (i.endpoint1 in [j.endpoint1 for j in nlines if not j==i]+[j.endpoint2 for j in nlines if not j==i]):
|
if not (i.endpoint1 in [j.endpoint1 for j in nlines if not j==i]+[j.endpoint2 for j in nlines if not j==i]):
|
||||||
nlines.remove(i)
|
nlines.remove(i)
|
||||||
endsleft = True
|
|
||||||
elif not (i.endpoint2 in [j.endpoint1 for j in nlines if not j==i]+[j.endpoint2 for j in nlines if not j==i]):
|
elif not (i.endpoint2 in [j.endpoint1 for j in nlines if not j==i]+[j.endpoint2 for j in nlines if not j==i]):
|
||||||
nlines.remove(i)
|
nlines.remove(i)
|
||||||
endsleft = True
|
|
||||||
|
# Find the closest segment to the point.
|
||||||
if nlines:
|
if nlines:
|
||||||
mindist = sys.maxint
|
mindist = sys.maxint
|
||||||
point = Point(x, y)
|
point = Point(x, y)
|
||||||
|
|
@ -2740,6 +2740,71 @@ class Group (object):
|
||||||
if d<mindist:
|
if d<mindist:
|
||||||
mindist = d
|
mindist = d
|
||||||
closestsegment = i
|
closestsegment = i
|
||||||
|
|
||||||
|
print closestsegment
|
||||||
|
|
||||||
|
# Go to the endpoint and turn right. Repeat until you hit the closest segment again.
|
||||||
|
if closestsegment:
|
||||||
|
# Grab angles to closest segments endpoints, go to the counterclockwise-most one
|
||||||
|
angle1 = misc_funcs.angle_to_point(point, closestsegment.endpoint1)
|
||||||
|
angle2 = misc_funcs.angle_to_point(point, closestsegment.endpoint2)
|
||||||
|
if (angle1<angle2 and angle2-angle1<180):
|
||||||
|
startpoint = closestsegment.endpoint2
|
||||||
|
sp = 2
|
||||||
|
else:
|
||||||
|
startpoint = closestsegment.endpoint1
|
||||||
|
sp = 1
|
||||||
|
linelist = [closestsegment]
|
||||||
|
while True:
|
||||||
|
# try:
|
||||||
|
nextline = max([[closestsegment.angle(i),i] for i in startpoint.lines if not i==closestsegment])[1]
|
||||||
|
# except:
|
||||||
|
# break
|
||||||
|
closestsegment = nextline
|
||||||
|
startpoint = [None,closestsegment.endpoint1,closestsegment.endpoint2][sp]
|
||||||
|
if not nextline in linelist:
|
||||||
|
linelist.append(nextline)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Check if the polygon encloses the given point. If it is not, then we've found an "island"
|
||||||
|
if misc_funcs.hittest(linelist,x,y):
|
||||||
|
f = Fill()
|
||||||
|
f.lines = linelist
|
||||||
|
print linelist
|
||||||
|
self.fills.append(f)
|
||||||
|
else:
|
||||||
|
print "No hit"
|
||||||
|
|
||||||
|
|
||||||
|
'''nlines = [i for i in self.lines]
|
||||||
|
endsleft = True
|
||||||
|
while endsleft:
|
||||||
|
endsleft = False
|
||||||
|
for i in reversed(nlines):
|
||||||
|
if not (i.endpoint1 in [j.endpoint1 for j in nlines if not j==i]+[j.endpoint2 for j in nlines if not j==i]):
|
||||||
|
nlines.remove(i)
|
||||||
|
endsleft = True
|
||||||
|
elif not (i.endpoint2 in [j.endpoint1 for j in nlines if not j==i]+[j.endpoint2 for j in nlines if not j==i]):
|
||||||
|
nlines.remove(i)
|
||||||
|
endsleft = True
|
||||||
|
print "2728",nlines
|
||||||
|
|
||||||
|
if nlines:
|
||||||
|
mindist = sys.maxint
|
||||||
|
point = Point(x, y)
|
||||||
|
closestsegment = None
|
||||||
|
|
||||||
|
for i in nlines:
|
||||||
|
d = misc_funcs.distToSegment(point,i.endpoint1,i.endpoint2)
|
||||||
|
if d<mindist:
|
||||||
|
mindist = d
|
||||||
|
closestsegment = i
|
||||||
|
|
||||||
|
f = Fill()
|
||||||
|
f.lines = nlines
|
||||||
|
self.fills.append(f)
|
||||||
|
|
||||||
if closestsegment:
|
if closestsegment:
|
||||||
# Then go to endpoint of closestsegment counterclockwise from point
|
# Then go to endpoint of closestsegment counterclockwise from point
|
||||||
angle1 = misc_funcs.angle_to_point(point, closestsegment.endpoint1)
|
angle1 = misc_funcs.angle_to_point(point, closestsegment.endpoint1)
|
||||||
|
|
@ -2764,7 +2829,7 @@ class Group (object):
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
print "*****",linelist
|
print "*****",linelist
|
||||||
# Continue until closestsegment is reached. I _think_ this is inevitable.
|
# Continue until closestsegment is reached. I _think_ this is inevitable.'''
|
||||||
|
|
||||||
self.selecting = True
|
self.selecting = True
|
||||||
else:
|
else:
|
||||||
|
|
@ -3097,6 +3162,26 @@ class Line(object):
|
||||||
tb+="cr.restore()\n"
|
tb+="cr.restore()\n"
|
||||||
jscommunicate(tb)
|
jscommunicate(tb)
|
||||||
|
|
||||||
|
class Fill(object):
|
||||||
|
"""Fills are Shapes without edges, built from Lines"""
|
||||||
|
def __init__(self):
|
||||||
|
super(Fill,self).__init__()
|
||||||
|
self.lines = []
|
||||||
|
self.fillcolor = FILLCOLOR
|
||||||
|
def draw(self, cr=None, transform=None, rect=None):
|
||||||
|
if SYSTEM=="osx":
|
||||||
|
if USING_GL:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
cr.gsave()
|
||||||
|
cr.newpath()
|
||||||
|
cr.fillcolor = self.fillcolor.pygui
|
||||||
|
cr.moveto(self.lines[0].endpoint2.x,self.lines[0].endpoint2.y)
|
||||||
|
for i in self.lines:
|
||||||
|
cr.lineto(i.endpoint1.x,i.endpoint1.y)
|
||||||
|
cr.fill()
|
||||||
|
cr.grestore()
|
||||||
|
|
||||||
def set_cursor(curs, widget=None):
|
def set_cursor(curs, widget=None):
|
||||||
if SYSTEM == "osx":
|
if SYSTEM == "osx":
|
||||||
cursdict = {"arrow":StdCursors.arrow, "ibeam":StdCursors.ibeam,
|
cursdict = {"arrow":StdCursors.arrow, "ibeam":StdCursors.ibeam,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue