Example #1
0
	def intersect(self,b) :
		if b.__class__ == Line :
			return b.intersect(self)
		else : 
			# taken from http://paulbourke.net/geometry/2circle/
			if (self.st-b.st).l2()<1e-10 and (self.end-b.end).l2()<1e-10 : return [self.st,self.end]
			r0 = self.r 
			r1 = b.r
			P0 = self.c
			P1 = b.c
			d2 = (P0-P1).l2() 
			d = sqrt(d2)
			if d>r0+r1  or r0+r1<=0 or d2<(r0-r1)**2 :
				return []
			if d2==0 and r0==r1 :
				return self.check_intersection( b.check_intersection(
					[self.st, self.end, b.st, b.end] ) )
			if d == r0+r1  :
				return self.check_intersection( b.check_intersection(
								[P0 + (P1 - P0)*r0/(r0+r1)]  ) )
			else: 
				a = (r0**2 - r1**2 + d2)/(2.*d)
				P2 = P0 + a*(P1-P0)/d
				h = r0**2-a**2
				h = sqrt(h) if h>0 else 0. 
				return self.check_intersection(b.check_intersection( [
							P([P2.x+h*(P1.y-P0.y)/d, P2.y-h*(P1.x-P0.x)/d]),
							P([P2.x-h*(P1.y-P0.y)/d, P2.y+h*(P1.x-P0.x)/d]),
						] ))
Example #2
0
    def run(self):
        s = self.options.s.split(";")
        node = None

        if len(self.selected) > 0:
            node = self.selected.itervalues().next()
            if node.tag == '{http://www.w3.org/2000/svg}path':
                self.path = CSP(node)
            else:
                error("Select a path or select nothing to create new path!")

        try:
            self.p = self.path.items[-1].points[-1][1]
        except:
            self.path = CSP([[[
                P(self.view_center),
                P(self.view_center),
                P(self.view_center)
            ]]],
                            clean=False)
            self.p = self.path.items[-1].points[-1][1]

        self.last_command = None
        for a in s:
            self.parse_command(a)
            try:
                self.p = self.path.items[-1].points[-1][1]
            except:
                pass

        if node == None: self.path.draw(group=self.current_layer)
        else: node.set("d", self.path.to_string())
Example #3
0
 def arc_to_xyij(self, a, x, y, i, j):  # a=2|3 => a*2-5=-1|1
     end = P(x, y)
     st = self.p
     c = st + P(i, j)
     r1, r2 = (st - c).l2(), (c - end).l2()
     if abs(r1 - r2) > 1.e-6:  # check radiuses at the start/end of the arc
         r1, r2 = (st - c).mag(), (c - end).mag()
         subprocess.Popen([
             'zenity', '--warning', '--timeout=3', '--text',
             ('Arc from %s-%s was replaced by the line because of start and end raduises are not equal.\n'
              + 'r1=%s, r2=%s, st %s, end %s, center %s') %
             (st, end, r1, r2, st, end, c)
         ])
         self.line_to(x, y)
     elif r1 < 1e-6 or r2 < 1e-6:
         r1, r2 = (st - c).mag(), (c - end).mag()
         subprocess.Popen([
             'zenity', '--warning', '--timeout=3', '--text',
             ('Arc from %s-%s was replaced by the line because of radius too small.\n'
              + 'r1=%s, r2=%s, st %s, end %s, center %s') %
             (st, end, r1, r2, st, end, c)
         ])
         self.line_to(x, y)
     else:
         self.path.items.append(Arc(st, end, c, a * 2 - 5))
         self.p = P(x, y)
         print "Arc to (%s, %s)-(%s, %s)" % (x, y, i, j)
Example #4
0
    def get_arc_param(self, x, y, a, r, i, j, l):
        st = self.p
        c = None
        # asume not enought params use slope.
        if x != None or y != None:
            # using two points and slope.
            end = P(x if x != None else self.p.x, y if y != None else self.p.y)
            return self.arc_on_two_points_and_slope(self.p, end, self.slope)

        if a != None:
            if l != None:
                r = l / a / 2
            if r != None:
                c = self.p + self.slope.ccw() * r
            if i != None or j != None:
                c = P(i if i != None else self.p.x,
                      j if j != None else self.p.y)
            if c != None:
                end = (self.p - c).rotate(a) + c
                return self.arc_on_two_points_and_slope(
                    self.p, end, self.slope)

        if l != None:
            if i != None or j != None:
                c = P(i if i != None else self.p.x,
                      j if j != None else self.p.y)
                r = (self.p - c).mag()
            if r != None:
                a = l / r / 2
                return self.get_arc_param(None, None, a, r, None, None, None)

        error("To few parametersfor arc. Command: %s" % self.command)
Example #5
0
 def close(self):
     if not self.points[0][1].near(self.points[-1][1]):
         self.points[-1][2].__init__(self.points[-1][1])
         self.points[0][0].__init__(self.points[0][1])
         self.points.append([
             P(self.points[0][1]),
             P(self.points[0][1]),
             P(self.points[0][2])
         ])
Example #6
0
    def draw(self,
             group=None,
             style=None,
             layer=None,
             transform=None,
             num=0,
             reverse_angle=None,
             color=None,
             width=None):
        layer, group, transform, reverse_angle = gcodetools.get_preview_group(
            layer, group, transform)
        st = P(gcodetools.transform(self.st.to_list(), layer, True))
        c = P(gcodetools.transform(self.c.to_list(), layer, True))
        a = self.a * reverse_angle
        r = (st - c)
        a_st = ((st - c).angle() - pi / 2) % (pi * 2) + pi / 2
        r = r.mag()
        if a > 0:
            a_end = a_st + a
            reverse = False
        else:
            a_end = a_st
            a_st = a_st + a
            reverse = True

        attr = {
            'style':
            get_style("biarc",
                      i=num,
                      name=style,
                      reverse=reverse,
                      width=width,
                      color=color),
            inkex.addNS('cx', 'sodipodi'):
            str(c.x),
            inkex.addNS('cy', 'sodipodi'):
            str(c.y),
            inkex.addNS('rx', 'sodipodi'):
            str(r),
            inkex.addNS('ry', 'sodipodi'):
            str(r),
            inkex.addNS('start', 'sodipodi'):
            str(a_st),
            inkex.addNS('end', 'sodipodi'):
            str(a_end),
            inkex.addNS('open', 'sodipodi'):
            'true',
            inkex.addNS('type', 'sodipodi'):
            'arc',
            "gcodetools":
            "Preview %s" % self,
        }
        if transform != []:
            attr["transform"] = transform
        inkex.etree.SubElement(group, inkex.addNS('path', 'svg'), attr)
Example #7
0
	def __init__(self,st,end):
		#debugger.add_debugger_to_class(self.__class__)
		if st.__class__ == P :  st = st.to_list()
		if end.__class__ == P :	end = end.to_list()
		self.st = P(st)
		self.end = P(end)
		self.l = self.length() 
		if self.l != 0 :
			self.n = ((self.end-self.st)/self.l).ccw()
		else: 
			self.n = [0,1]
Example #8
0
	def intersect(self,b, false_intersection = False) :
		if b.__class__ == Line :
			if self.l < 10e-8 or b.l < 10e-8 : return []
			v1 = self.end - self.st
			v2 = b.end - b.st
			x = v1.x*v2.y - v2.x*v1.y 
			if x == 0 :
				# lines are parallel
				res = []

				if (self.st.x-b.st.x)*v1.y - (self.st.y-b.st.y)*v1.x  == 0:
					# lines are the same
					if v1.x != 0 :
						if 0<=(self.st.x-b.st.x)/v2.x<=1 :  res.append(self.st)
						if 0<=(self.end.x-b.st.x)/v2.x<=1 :  res.append(self.end)
						if 0<=(b.st.x-self.st.x)/v1.x<=1 :  res.append(b.st)
						if 0<=(b.end.x-b.st.x)/v1.x<=1 :  res.append(b.end)
					else :
						if 0<=(self.st.y-b.st.y)/v2.y<=1 :  res.append(self.st)
						if 0<=(self.end.y-b.st.y)/v2.y<=1 :  res.append(self.end)
						if 0<=(b.st.y-self.st.y)/v1.y<=1 :  res.append(b.st)
						if 0<=(b.end.y-b.st.y)/v1.y<=1 :  res.append(b.end)
				return res
			else :
				t1 = ( v2.x*(self.st.y-b.st.y) - v2.y*(self.st.x-b.st.x) ) / x
				t2 = ( v1.x*(self.st.y-b.st.y) - v1.y*(self.st.x-b.st.x) ) / x
				
				if 0<=t1<=1 and 0<=t2<=1 or false_intersection : return [ self.st+v1*t1 ]	
				else : return []					
		else: 
			# taken from http://mathworld.wolfram.com/Circle-LineIntersection.html
			x1 = self.st.x - b.c.x
			x2 = self.end.x - b.c.x
			y1 = self.st.y - b.c.y
			y2 = self.end.y - b.c.y
			dx = x2-x1
			dy = y2-y1
			D = x1*y2-x2*y1
			dr = dx*dx+dy*dy
			descr = b.r**2*dr-D*D
			if descr<0 : return []
			if descr==0 : return self.check_intersection(b.check_intersection([ P([D*dy/dr+b.c.x,-D*dx/dr+b.c.y]) ]))
			sign = -1. if dy<0 else 1.
			descr = sqrt(descr)
			points = [
						 P( [ (D*dy+sign*dx*descr)/dr+b.c.x, (-D*dx+abs(dy)*descr)/dr+b.c.y ] ), 
						 P( [ (D*dy-sign*dx*descr)/dr+b.c.x, (-D*dx-abs(dy)*descr)/dr+b.c.y ] )
					]
			if false_intersection :
				return points
			else: 
				return self.check_intersection(b.check_intersection( points ))
Example #9
0
	def bounds(self) : 
		# first get bounds of start/end 
		x1,y1, x2,y2 =  ( min(self.st.x,self.end.x),min(self.st.y,self.end.y),
						  max(self.st.x,self.end.x),max(self.st.y,self.end.y) )
		# Then check 0,pi/2,pi and 2pi angles. 
		if self.point_Gde_angle(self.c+P(0,self.r)) :
			y2 = max(y2, self.c.y+self.r)
		if self.point_inside_angle(self.c+P(0,-self.r)) :
			y1 = min(y1, self.c.y-self.r)
		if self.point_inside_angle(self.c+P(-self.r,0)) :
			x1 = min(x1, self.c.x-self.r)
		if self.point_inside_angle(self.c+P(self.r,0)) :
			x2 = max(x2, self.c.x+self.r)
		return x1,y1, x2,y2
Example #10
0
	def __init__(self,st,end,c,a,r=None) :
		# a - arc's angle, it's not defining actual angle before now, but defines direction so it's value does not mather matters only the sign.
		if st.__class__ == P :  st = st.to_list()
		if end.__class__ == P : end = end.to_list()
		if c.__class__ == P :   c = c.to_list()
		self.st = P(st)
		self.end = P(end)
		self.c = P(c)
		if r == None : self.r = (P(st)-P(c)).mag()
		else: self.r = r
		self.a = ( (self.st-self.c).angle() - (self.end-self.c).angle() ) % pi2
		if a>0 : self.a -= pi2
		self.a *= -1.
		self.cp = (self.st-self.c).rot(self.a/2)+self.c # central point of an arc
		self.l = self.length()
Example #11
0
    def arc_to_xyr(self, a, x, y, r, in_out=0):
        end = P(x, y)
        st = self.p
        c1 = (st + end) / 2

        if (st - end).l2() < 1.e-10:
            subprocess.Popen([
                'zenity', '--warning', '--timeout=3', '--text',
                ('Arc from %s-%s was replaced by the line because of start/end point are the same.\n'
                 + 'r=%s, st %s, end %s.') % (r, st, end)
            ])
            self.line_to(x, y)
            return

        b = r**2 - (st - end).l2() / 4.
        if b < 0:
            subprocess.Popen([
                'zenity', '--warning', '--timeout=3', '--text',
                ('Arc from %s-%s was replaced by the line because of given radius to small.\n'
                 + 'r=%s, st %s, end %s. Should be at least r=%s') %
                (st, end, r, st, end, sqrt((st - end).l2() / 4.))
            ])
            self.line_to(x, y)
            return
        n = (end - st).unit()
        n = n.cw() if a == 2 else n.ccw()
        c = c1 + n * sqrt(b)
        c = c - st
        if in_out > 0:
            a = 5 - a  # swap direction 2,3 -> 3,2
        self.arc_to_xyij(a, x, y, c.x, c.y)
Example #12
0
 def copy(self, st=None, end=None):
     res = CSPsubpath()
     if st == None: st = 0
     if end == None: end = len(self.points) - 1
     for i in range(st, end + 1):
         cp_ = []
         for point in self.points[i]:
             cp_.append(P(point.x, point.y))
         res.points.append(cp_)
     return res
Example #13
0
 def to_csp(self):
     # Taken from cubicsuperpath's ArcToCsp
     O = self.c
     sectors = int(abs(self.a) * 2 / pi) + 1
     da = self.a / sectors
     v = 4 * tan(da / 4) / 3
     angle = (self.st - self.c).angle()
     cspsubpath = CSPsubpath()
     for i in range(sectors + 1):
         c, s = cos(angle) * self.r, sin(angle) * self.r
         v1 = P([O.x + c - (-v) * s, O.y + s + (-v) * c])
         pt = P([O.x + c, O.y + s])
         v2 = P([O.x + c - v * s, O.y + s + v * c])
         cspsubpath.points.append([v1, pt, v2])
         angle += da
     cspsubpath.points[0][0] = cspsubpath.points[0][1].copy()
     cspsubpath.points[-1][2] = cspsubpath.points[-1][1].copy()
     csp = CSP()
     csp.items.append(cspsubpath)
     return csp
Example #14
0
    def point_d2(self, p):
        pa = [
            P(self.x1, self.y1),
            P(self.x2, self.y1),
            P(self.x2, self.y2),
            P(self.x1, self.y2)
        ]
        mind = 1e100
        maxd = 0.
        for pl in pa:
            l = (p - pl).l2()
            if l > maxd: maxd = l

        if self.point_inside(p): mind = 0
        else:
            for i in range(len(pa)):
                l = Line(pa[i - 1], pa[i]).point_d2(p)
                if l < mind: mind = l

        return mind, maxd
Example #15
0
	def point_inside_angle(self,p,y=None) :  # TODO need to be done faster! 
		if y!=None : p = P(p,y)
		if (p-self.c).l2() != self.r**2 :  # p is not on the arc, lets move it there
			p = self.c+(p-self.c).unit()*self.r
		warn( (self.cp-self.c).dot(p-self.c),self.r**2, (self.cp-self.c).dot(p-self.c)/self.r**2)
		try:
			abs(  acos( (self.cp-self.c).dot(p-self.c) /self.r**2  )  )  <  abs(self.a/2)
		except :

			return True	 
		return abs(  acos( (self.cp-self.c).dot(p-self.c) /self.r**2  )  )  <  abs(self.a/2) 
Example #16
0
    def point(self, i, t):
        sp1, sp2 = self.cp_to_list(i), self.cp_to_list(i + 1)
        ax, bx, cx, dx = sp1[1][0], sp1[2][0], sp2[0][0], sp2[1][0]
        ay, by, cy, dy = sp1[1][1], sp1[2][1], sp2[0][1], sp2[1][1]

        x1, y1 = ax + (bx - ax) * t, ay + (by - ay) * t
        x2, y2 = bx + (cx - bx) * t, by + (cy - by) * t
        x3, y3 = cx + (dx - cx) * t, cy + (dy - cy) * t

        x4, y4 = x1 + (x2 - x1) * t, y1 + (y2 - y1) * t
        x5, y5 = x2 + (x3 - x2) * t, y2 + (y3 - y2) * t

        x, y = x4 + (x5 - x4) * t, y4 + (y5 - y4) * t
        return P(x, y)
Example #17
0
 def split(self, i, t=.5):
     sp1, sp2 = self.cp_to_list(i), self.cp_to_list(i + 1)
     [x1, y1], [x2, y2], [x3, y3], [x4, y4] = sp1[1], sp1[2], sp2[0], sp2[1]
     x12 = x1 + (x2 - x1) * t
     y12 = y1 + (y2 - y1) * t
     x23 = x2 + (x3 - x2) * t
     y23 = y2 + (y3 - y2) * t
     x34 = x3 + (x4 - x3) * t
     y34 = y3 + (y4 - y3) * t
     x1223 = x12 + (x23 - x12) * t
     y1223 = y12 + (y23 - y12) * t
     x2334 = x23 + (x34 - x23) * t
     y2334 = y23 + (y34 - y23) * t
     x = x1223 + (x2334 - x1223) * t
     y = y1223 + (y2334 - y1223) * t
     return [[P(sp1[0]), P(sp1[1]), P(x12, y12)],
             [P(x1223, y1223), P(x, y),
              P(x2334, y2334)], [P(x34, y34),
                                 P(sp2[1]),
                                 P(sp2[2])]]
Example #18
0
 def slope(self, j, t):
     cp1, cp2 = self.get_segment(j)
     if self.zerro_segment(j): return P(1., 0.)
     ax, ay, bx, by, cx, cy, dx, dy = self.parameterize_segment(j)
     slope = P(3 * ax * t * t + 2 * bx * t + cx,
               3 * ay * t * t + 2 * by * t + cy)
     if slope.l2(
     ) > 1e-9:  #LT changed this from 1e-20, which caused problems, same further
         return slope.unit()
     # appears than slope len = 0  (can be at start/end point if control point equals endpoint)
     if t == 0:  # starting point
         slope = cp2[0] - cp1[1]
         if slope.l2() > 1e-9:
             return slope.unit()
     if t == 1:
         slope = cp2[1] - cp1[2]
         if slope.l2() > 1e-9:
             return slope.unit()
     # probably segment straight
     slope = cp2[1] - cp1[1]
     if slope.l2() > 1e-9:
         return slope.unit()
     # probably something went wrong
     return P(1., 0.)
Example #19
0
    def get_line_xy(self, x, y, a, l):
        x1, y1 = self.p.x, self.p.y
        #warn((x,y,a,l))
        if x == None:
            if y != None:
                if a != None:
                    a = tan(a)
                    if abs(a) > 16331778728300000:
                        return P(x1, y)
                    if a == 0:
                        error("Bad param a=0 for y defined line. Command: %s" %
                              self.command)
                    return x1 + (y - y1) / a, y
                elif l != None:
                    try:
                        x = sqrt(l**2 - (y - y1)**2)
                    except:
                        error("Bad params, l to small. Command: %s" %
                              self.command)
                    return P(x, y)
                else:
                    return P(x1, y)

            else:
                if a != None and l != None:
                    return self.p + P(cos(a), sin(a)) * l
        else:
            if y != None:
                return P(x, y)
            else:
                if a != None:
                    a = tan(a)
                    if abs(a) > 16331778728300000:
                        error(
                            "Bad param a=pi/2 for x defined line. Command: %s"
                            % self.command)
                    else:
                        return x, a * (x - x1) + y1

                elif l != None:
                    try:
                        y = sqrt(l**2 - (x - x1)**2)
                    except:
                        error("Bad params, l to small. Command: %s" %
                              self.command)
                else:
                    return P(x, y1)

        error("""Bad params for the line. Command: %s\n
					x = %s,
					y = %s,
					a = %s,
					l = %s
				""" % (self.command, x, y, a, l))
Example #20
0
    def parse_command(self, command):
        if command.strip() == "": return
        self.command = command
        r = re.match(
            "\s*([almhvALMHV]?)\s*((\s*[alxyrijdALXYRIJD]\s*\-?[\d\.]+)*)\s*",
            command)
        if not r:
            error("Cannot parse command: \"%s\"" % command)

        r = re.match("\s*([almhvALMHV])\s*([alxyrijdALXYRIJD].*)", command)
        if r:
            warn(r.groups())
            t, command = r.groups()
        else:
            t = self.last_command

        # parse the parameters
        x, y, a, l, r, i, j = None, None, None, None, None, None, None
        try:
            self.slope = self.path.slope(-1, -1, 1)
        except:
            self.slope = P(1., 0.)
        for p in re.findall("([alxyrijALXYRIJ])\s*(\-?\d*\.?\d*)", command):
            #warn(p)
            p = list(p)
            if p[0] == "A": a = -float(p[1]) / 180 * pi
            elif p[0] == "a": a = self.slope.angle() - float(p[1]) / 180 * pi
            else: p[1] = float(p[1]) * self.options.units
            if p[0] == "x": x = self.p.x + p[1]
            elif p[0] == "X": x = p[1]
            elif p[0] == "y": y = self.p.y - p[1]
            elif p[0] == "Y": y = -p[1]
            elif p[0] == "i": i = self.p.x + p[1]
            elif p[0] == "I": I = p[1]
            elif p[0] == "j": j = self.p.y - p[1]
            elif p[0] == "J": J = -p[1]
            elif p[0] in ("r", "R"): r = p[1]
            elif p[0] in ("d", "D"): r = p[1] / 2
            elif p[0] in ("l", "L"): l = p[1]

        # exec command
        if t in ("l", "L"): self.draw_line(x, y, a, l)
        if t in ("a", "A"): self.draw_arc(x, y, a, r, i, j, l)
        if t in ("m", "M"): self.move_to(x, y, a, l)
        self.last_command = t
Example #21
0
	def p(self) : 
		return P(self.x,self.y)
Example #22
0
 def from_list(self, subpath):
     self.points = []
     for cp in subpath:
         self.points.append([P(cp[0]), P(cp[1]), P(cp[2])])
Example #23
0
 def draw_start(self, x, y):
     self.st = P(x, y)
     self.p = P(x, y)
     self.path = LineArc()
Example #24
0
 def line_to(self, x, y):
     self.path.items.append(Line(self.p, [x, y]))
     self.p = P(x, y)
     print "Line to (%s, %s)" % (x, y)
Example #25
0
	def get_t_at_point(self, p, y=None) :
		if y!=None : p = P(p,y)
		if not self.point_inside_angle(p) : return -1.
		return abs( acos( (self.st-self.c).dot((p-self.c))/(self.r**2) )/pi ) # consuming all arcs les than 180 deg