def arrow_trafos(path, properties): dir1, dir2 = arrow_vectors(path, properties.line_arrow1, properties.line_arrow2) width = properties.line_width if width < 1.0: width = 1.0 scale = Scale(width) t1 = t2 = None if dir1 is not None: t1 = Translation(path.Node(0))(Rotation(dir1.polar()[1]))(scale) if dir2 is not None: t2 = Translation(path.Node(-1))(Rotation(dir2.polar()[1]))(scale) return t1, t2
def Execute(self, device, rect): left, bottom, right, top = rect dy = self.spacing if dy > 0: device.SetFillColor(self.background) device.FillRectangle(left, top, right, bottom) device.PushTrafo() vx, vy = self.direction angle = atan2(vy, vx) center = rect.center() rot = Rotation(angle, center) left, bottom, right, top = rot(rect) device.Concat(rot) device.Translate(center) height = top - bottom width = right - left steps = int(height / dy + 1) y = height / 2 x = width / 2 device.SetLineColor(self.foreground) device.SetLineAttributes(self.width) drawline = device.DrawLineXY for i in range(steps): drawline(-x, y, +x, y) y = y - dy device.PopTrafo() else: device.SetFillColor(self.foreground) device.FillRectangle(left, bottom, right, top)
def Execute(self, device, rect): if device.has_axial_gradient: self.execute_axial_gradient(device, rect) return SetFillColor = device.SetFillColor FillRectangle = device.FillRectangle steps = device.gradient_steps colors = self.gradient.Sample(steps) SetFillColor(colors[0]) apply(device.FillRectangle, tuple(rect)) device.PushTrafo() vx, vy = self.direction angle = atan2(vy, vx) - pi / 2 center = rect.center() rot = Rotation(angle, center) left, bottom, right, top = rot(rect) device.Concat(rot) device.Translate(center) height = top - bottom miny = -height / 2 height = height * (1.0 - self.border) width = right - left dy = height / steps y = height / 2 x = width / 2 for i in range(steps): SetFillColor(colors[i]) FillRectangle(-x, y, +x, miny) y = y - dy device.PopTrafo()
def compute_trafo(self, state=0): sel = self.selection if sel in self.selTurn: # rotation vec = self.drag_cur - self.center angle = math.atan2(vec.y, vec.x) angle = angle - self.start_angle + 2 * math.pi if state & const.ConstraintMask: pi12 = math.pi / 12 angle = pi12 * int(angle / pi12 + 0.5) self.trafo = Rotation(angle, self.center) self.trafo_desc = (1, angle) elif sel in self.selShear: if sel in (2, 6): # horiz. shear height = self.drag_start.y - self.reference if height: ratio = self.off.x / height self.trafo = Trafo(1, 0, ratio, 1, -ratio * self.reference, 0) self.trafo_desc = (2, ratio) else: # vert. shear width = self.drag_start.x - self.reference if width: ratio = self.off.y / width self.trafo = Trafo(1, ratio, 0, 1, 0, -ratio * self.reference) self.trafo_desc = (3, ratio)
def read_text(self, line): args = tokenize(line, 12) # don't tokenize the text itself if len(args) != 13: # including the unparsed rest of the line raise SketchLoadError('Invalid text specification') sub_type, color, depth, pen_style, font, size, angle, flags, \ height, length, x, y, rest = args self.fill(color, None) self.font(font, size * 0.9, flags) if len(rest) > 2: #at least a space and a newline # read the actual text. This implementation may fail in # certain cases! string = rest[1:] while string[-5:] != '\\001\n': line = self.readline() if not line: raise SketchLoadError('Premature end of string') string = string + line globals = {'__builtins__': {}} try: # using eval here might be a security hole! string = eval('"""' + string[:-5] + '"""', globals) except: string = eval("'''" + string[:-5] + "'''", globals) else: raise SketchLoadError('Invalid text string') trafo = Translation(self.trafo(x, y))(Rotation(angle)) self.simple_text(string, trafo=trafo, halign=align[sub_type]) self.set_depth(depth)
def parse_transform(self, trafo_string): trafo = self.trafo #print trafo trafo_string = as_latin1(trafo_string) while trafo_string: #print trafo_string match = rx_trafo.match(trafo_string) if match: function = match.group(1) args = string.translate(match.group(2), commatospace) args = map(float, split(args)) trafo_string = trafo_string[match.end(0):] if function == 'matrix': trafo = trafo(apply(Trafo, tuple(args))) elif function == 'scale': trafo = trafo(Scale(args[0])) elif function == 'translate': dx, dy = args trafo = trafo(Translation(dx, dy)) elif function == 'rotate': trafo = trafo(Rotation(args[0] * degrees)) elif function == 'skewX': trafo = trafo(Trafo(1, 0, tan(args[0] * degrees), 1, 0, 0)) elif function == 'skewY': trafo = trafo(Trafo(1, tan(args[0] * degrees), 0, 1, 0, 0)) else: trafo_string = '' #print trafo self.trafo = trafo
def write_gradient(self, gradient, style): pattern, rect = gradient key = self.gradient_id(pattern) write = self.file.write #write('Bb\n') if pattern.is_AxialGradient: vx, vy = pattern.Direction() angle = atan2(vy, vx) - pi / 2 center = rect.center() rot = Rotation(angle, center) left, bottom, right, top = rot(rect) height = (top - bottom) * (1.0 - pattern.Border()) trafo = rot(Translation(center)) start = trafo(0, height / 2) write("1 %s %g %g %g %g 1 0 0 1 0 0 Bg\n" % (key[0], start.x, start.y, atan2(-vy, -vx) * 180.0 / pi, height)) elif pattern.is_RadialGradient: cx, cy = pattern.Center() cx = cx * rect.right + (1 - cx) * rect.left cy = cy * rect.top + (1 - cy) * rect.bottom radius = max(hypot(rect.left - cx, rect.top - cy), hypot(rect.right - cx, rect.top - cy), hypot(rect.right - cx, rect.bottom - cy), hypot(rect.left - cx, rect.bottom - cy)) radius = radius * (1.0 - pattern.Border()) write("0 0 0 0 Bh\n") write("1 %s %g %g 0 %g 1 0 0 1 0 0 Bg\n" % (key[0], cx, cy, radius))
def DragHandle(self, pa, pb, selection): try: inverse = self.trafo.inverse() except SingularMatrix: return pa, pb = map(inverse, (pa, pb)) r1, r2, n = self.r1, self.r2, self.n alpha = 2 * pi / n ra, beta = pa.polar() rot = Rotation(-beta) rb, gamma = rot(pb).polar() if selection <= n: if pa * pb < 0: self.r1 = 0 else: self.r1 = min(r2, r1 + rb - ra) else: n = n + int(2 * gamma / alpha) if n >= 1: self.n = n self.recompute()
def execute_axial_gradient(self, device, rect): vx, vy = self.direction angle = atan2(vy, vx) - pi / 2 center = rect.center() rot = Rotation(angle, center) left, bottom, right, top = rot(rect) height = (top - bottom) * (1.0 - self.border) trafo = rot(Translation(center)) device.AxialGradient(self.gradient, trafo(0, height / 2), trafo(0, -height / 2))
def DragHandle(self, pa, pb, selection): try: inverse = self.trafo.inverse() except SingularMatrix: return pa, pb = map(inverse, (pa, pb)) delta = pb - pa theta1 = self.theta1 theta2 = self.theta2 if theta2 < theta1: theta2 = theta2 + 360 p1 = Polar(self.l1, theta1 * pi / 180) p2 = Polar(self.l2, theta2 * pi / 180) p3 = Rotation(pi / 360 * (theta2 - theta1))(Polar( self.r, theta1 * pi / 180)) if selection == 1: p1 = p1 + delta self.l1, angle = p1.polar() if not self.shift_pressed: self.theta1 = angle * 180 / pi elif selection == 2: p2 = p2 + delta self.l2, angle = p2.polar() if not self.shift_pressed: self.theta2 = angle * 180 / pi elif selection == 3: self.theta1 = (0.5 * p1 + delta).polar()[1] * 180 / pi elif selection == 4: self.theta2 = (0.5 * p2 + delta).polar()[1] * 180 / pi elif selection == 5: p3 = p3 + delta l, angle = p3.polar() angle = angle * 180 / pi % 360 begin = self.theta1 % 360 end = self.theta2 % 360 if end < begin: end = end + 360 if angle >= begin and angle <= end: self.r = l else: self.r = 0 if self.control_pressed: if selection in (1, 3): self.theta1 = int(0.5 + self.theta1 / 5.) * 5 elif selection in (2, 4): self.theta2 = int(0.5 + self.theta2 / 5.) * 5 self.recompute()
def GetHandles(self): handles = [] theta1 = self.theta1 theta2 = self.theta2 if theta2 < theta1: theta2 = theta2 + 360 p1 = Polar(self.l1, theta1 * pi / 180) p2 = Polar(self.l2, theta2 * pi / 180) p3 = Rotation(pi / 360 * (theta2 - theta1))(Polar( self.r, theta1 * pi / 180)) for p in (p1, p2): handles.append(handle.MakeNodeHandle(self.trafo(p))) for p in (0.5 * p1, 0.5 * p2, p3): handles.append(handle.MakeControlHandle(self.trafo(p))) return handles
def axial_gradient(self, properties, rect): pattern = properties.fill_pattern vx, vy = pattern.Direction() angle = atan2(vy, vx) - pi / 2 center = rect.center() rot = Rotation(angle, center) left, bottom, right, top = rot(rect) trafo = rot(Translation(center)) image = PIL.Image.new('RGB', (1, 200)) border = int(round(100 * pattern.Border())) _sketch.fill_axial_gradient(image.im, pattern.Gradient().Colors(), 0, border, 0, 200 - border) self.pdf.saveState() apply(self.pdf.transform, trafo.coeff()) self.pdf.drawInlineImage(image, (left - right) / 2, (bottom - top) / 2, right - left, top - bottom) self.pdf.restoreState()
def read_ellipse(self, line): readline = self.readline tokenize = skread.tokenize_line args = tokenize(line) if len(args) != 19: raise SketchLoadError('Invalid Ellipse specification') sub_type, line_style, thickness, pen_color, fill_color, depth, \ pen_style, area_fill, style, direction, angle, \ cx, cy, rx, ry, sx, sy, ex, ey = args self.fill(fill_color, area_fill) self.line(pen_color, thickness, const.JoinMiter, const.CapButt, line_style, style) center = self.trafo(cx, cy) radius = self.trafo.DTransform(rx, ry) trafo = Trafo(radius.x, 0, 0, radius.y) trafo = Rotation(angle)(trafo) trafo = Translation(center)(trafo) apply(self.ellipse, trafo.coeff()) self.set_depth(depth)
def Execute(self, device, rect): if device.has_conical_gradient: self.execute_conical(device, rect) return steps = device.gradient_steps cx, cy = self.center left, bottom, right, top = rect cx = cx * right + (1 - cx) * left cy = cy * top + (1 - cy) * bottom vx, vy = self.direction angle = atan2(vy, vx) rot = Rotation(angle, cx, cy) radius = max(hypot(left - cx, top - cy), hypot(right - cx, top - cy), hypot(right - cx, bottom - cy), hypot(left - cx, bottom - cy)) + 10 device.PushTrafo() device.Concat(rot) device.Translate(cx, cy) device.Scale(radius) colors = self.gradient.Sample(steps) SetFillColor = device.SetFillColor FillPolygon = device.FillPolygon da = pi / steps points = [(1, 0)] for i in range(steps): a = da * (i + 1) x = cos(a) y = sin(a) points.insert(0, (x, y)) points.append((x, -y)) colors.reverse() SetFillColor(colors[0]) FillPolygon(points) points.insert(0, (0, 0)) for i in range(steps): SetFillColor(colors[i]) del points[1] del points[-1] FillPolygon(points) device.PopTrafo()
def recompute(self): r1 = self.r1 r2 = self.r2 theta1 = self.theta1 theta2 = self.theta2 if theta2 < theta1: theta2 = theta2+360 ring2 = Sketch.Ellipse(start_angle=theta1*pi/180, end_angle=theta2*pi/180, arc_type=0).Paths()[0] ring1 = ring2.Duplicate() ring2.Transform(Scale(r2)) ring1.Transform(Scale(r1)) new = Sketch.CreatePath() newpaths = [new] new.AppendLine(Polar(r1, theta1*pi/180.)) for i in range(ring2.len): segment = ring2.Segment(i) new.AppendSegment(*segment) new.AppendLine(Polar(r2, theta2*pi/180.)) new.AppendLine(Polar(r1, theta2*pi/180.)) ring1.Transform(Scale(-1,1)) ring1.Transform(Rotation((180+theta1+theta2)*pi/180.)) for i in range(ring1.len): s = ring1.Segment(i) new.AppendSegment(*s) for path in newpaths: path.Transform(self.trafo) if self.objects: self.objects[0].SetPaths(newpaths) else: obj = Sketch.PolyBezier(tuple(newpaths)) self.set_objects([obj])
def getStructBoxnode(inlabel, plist, vlist): global courfont global tarrw1, tarrw2, tarrw3 pvfnsz = 12 # font size for pointers/vars # here we'll also generate a dict of all graphic objects # global 'id' is not needed - it will be a part of a tuple, along with master group sbdict = {} ## pointers - horizontal yoff = 0 ypad = 2 lastcharpad = pvfnsz # so the arrow dont overlap with last char xoutermost = 0 # to get the longest arrow (so we use it to make arrows same length) point_tflist = [] # list of actual textfield objects tcount = 0 for iptxt in plist: textfld = SimpleText(Translation(0, yoff), iptxt) textfld.SetProperties(font=courfont, font_size=pvfnsz) textfld.update_rects() sbdict['ptf_' + str(tcount)] = textfld # add connector line tfbr = textfld.bounding_rect tfline = getQuickLine((tfbr.left, tfbr.bottom), (tfbr.right + lastcharpad, tfbr.bottom)) tfline.SetProperties(line_width=2.0, line_arrow1=tarrw1, line_arrow2=tarrw2) tfline.update_rects() sbdict['ptfl_' + str(tcount)] = tfline if tfbr.right + lastcharpad > xoutermost: xoutermost = tfbr.right + lastcharpad # group line and text tgrp = Group([tfline, textfld]) tgrp.update_rects() sbdict['ptfg_' + str(tcount)] = tgrp # add the group - not just textfld - to list here point_tflist.append(tgrp) # get height - calc next offset; yoff will go negative, but nvm (will group and move) # don't use tgrp's BB, its too high llx, lly, urx, ury = textfld.bounding_rect # /tgrp. /getTfBB(textfld) tfHeight = ury - lly yoff -= tfHeight + ypad tcount += 1 # done - now resize all the arrows according to xoutermost, # so they are same length # SetLine(i, x, y[, cont]) "Replace the ith segment by a line segment" # where the i-th segment is the node.. for tgrp in point_tflist: # loop (in a list) tfline = tgrp.objects[ 0] # access Group (sub)object - tfline is first [0] # get 2nd node (=segment 1) - in there, Point() is third in list ([2]) tmpep = tfline.paths[0].Segment(1)[2] # change 2nd node (=segment 1) of the (first) path (paths[0]) tfline.paths[0].SetLine(1, (xoutermost, tmpep.y)) tfline.update_rects() tgrp.update_rects() # finally, group all these point_group = Group(point_tflist) # accepts list directly point_group.update_rects() sbdict['ptg'] = point_group ## variables - vertical (so, rotate group afterwards) yoff = 0 ypad = 2 lastcharpad = 1 # pvfnsz /so the arrow dont overlap with last char xoutermost = 0 # to get the longest arrow (so we use it to make arrows same length) varbl_tflist = [] # list of actual textfield objects tcount = 0 havevars = len(vlist) # could be zero! for ivtxt in vlist: textfld = SimpleText(Translation(0, yoff), ivtxt) textfld.SetProperties(font=courfont, font_size=pvfnsz) textfld.update_rects() sbdict['vtf_' + str(tcount)] = textfld # add connector line tfbr = textfld.bounding_rect tfline = getQuickLine((tfbr.left, tfbr.bottom), (tfbr.right + lastcharpad, tfbr.bottom)) tfline.SetProperties(line_width=2.0, line_arrow1=tarrw1, line_arrow2=tarrw3) tfline.update_rects() sbdict['vtfl_' + str(tcount)] = tfline if tfbr.right + lastcharpad > xoutermost: xoutermost = tfbr.right + lastcharpad # group line and text tgrp = Group([tfline, textfld]) tgrp.update_rects() sbdict['vtfg_' + str(tcount)] = tgrp # add the group - not just textfld - to list here varbl_tflist.append(tgrp) # get height - calc next offset; yoff will go negative, but nvm (will group and move) llx, lly, urx, ury = textfld.bounding_rect # getTfBB(textfld) tfHeight = ury - lly yoff -= tfHeight + 2 tcount += 1 # done - now resize all the arrows according to xoutermost, # so they are same length # SetLine(i, x, y[, cont]) "Replace the ith segment by a line segment" # where the i-th segment is the node.. for tgrp in varbl_tflist: # loop (in a list) tfline = tgrp.objects[ 0] # access Group (sub)object - tfline is first [0] # get 2nd node (=segment 1) - in there, Point() is third in list ([2]) tmpep = tfline.paths[0].Segment(1)[2] # change 2nd node (=segment 1) of the (first) path (paths[0]) tfline.paths[0].SetLine(1, (xoutermost, tmpep.y)) tfline.update_rects() tgrp.update_rects() # finally, group all these varbl_group = Group(varbl_tflist) # accepts list directly varbl_group.update_rects() sbdict['vtg'] = varbl_group # rotate variable group # for repositioning - easiest to rotate around # upper-left corner (instead of center point) vgbr = varbl_group.bounding_rect varbl_g_cp = vgbr.center() # centerpoint varbl_g_ul = Point(vgbr.left, vgbr.top) # top (upper) left varbl_group.Transform(Rotation(radians(-90), varbl_g_ul)) varbl_group.update_rects() # must reassign variable for .bounding_rect # after transform and update_rects()!!: vgbr = varbl_group.bounding_rect vgbr_w = vgbr.right - vgbr.left vgbr_h = vgbr.top - vgbr.bottom # also, below needed for box & move calc: #~ point_group.update_rects() pgbr = point_group.bounding_rect pgbr_w = pgbr.right - pgbr.left pgbr_h = pgbr.top - pgbr.bottom # and note - groups seem to add some sort of padding, so align to intern lines instead (instead of group BB edges) # get first (moveto) Point of first tf's line (align to that, instead of pgbr) - needed for 'boxing' below: tfline = point_group[0].objects[0] tmpep = tfline.paths[0].Segment(0)[2] tmpep_v = Point(0, 0) if havevars != 0: tmpep_v = varbl_group[0].objects[0].paths[0].Segment(0)[2] xmoveadj = tmpep.x - pgbr.left # adjustment due to group padding ymoveadj = -(tmpep_v.y - vgbr.top) # only for moving varbl_group # move rotated varbl_group below left of point_group xmove = 0 # -vgbr_w # looks ok like this xmove += xmoveadj # adjust due to group padding ymove = -pgbr_h ymove += ymoveadj # adjust due to group padding varbl_group.Translate(Point(xmove, ymove)) varbl_group.update_rects() vgbr = varbl_group.bounding_rect ## add the box label lxpad = 10 # box label x padding tfld_label = SimpleText(Translation(0, 0), inlabel) tfld_label.SetProperties(font=courfont, font_size=16) tfld_label.update_rects() # reposition # on y: center align tfld_label with center of point_group cp_pg = pgbr.center() tlbr = tfld_label.bounding_rect cp_tl = tlbr.center() ymove = -(cp_tl.y - cp_pg.y) # on x: <NO>align right edge of tfld_label + pad with left edge of point_group</NO> # center in respect to expected boxwidth instead # calc expected boxwidth first tlbr = tfld_label.bounding_rect tlbr_w = tlbr.right - tlbr.left boxwidth = lxpad + tlbr_w + lxpad # only title text label width + padding varbl_width = vgbr.right - vgbr.left if boxwidth < lxpad + varbl_width + lxpad: boxwidth = lxpad + varbl_width + lxpad #~ xmove = -(tlbr.right + lxpad - pgbr.left) # title text left aligned w/ right edge xmove = -((tlbr.center().x - pgbr.left) + boxwidth / 2) xmove += xmoveadj # adjust due to group padding tfld_label.Translate(Point(xmove, ymove)) tfld_label.update_rects() tlbr = tfld_label.bounding_rect # must reassign variable (though we won't need it anymore) ## create a box for point/varbl_group # start at upper left point of point_group BB; # go downleft, to <NO>upper left point of varbl_group BB</NO> # .. note - groups seem to add some sort of padding, so align to intern lines: # go downleft, to upper edge of varbl_group, and ([left edge of tfld_label] - pad) # get first (moveto) Point of first tf's line (align to that, instead of pgbr) tfline = point_group[0].objects[0] tmpep = tfline.paths[0].Segment(0)[2] start_x = tmpep.x # pgbr.left start_y = pgbr.top off_x = -(boxwidth) # -vgbr_w off_y = -pgbr_h trec = Rectangle(trafo=Trafo(off_x, 0, 0, off_y, start_x, start_y)) trec.SetProperties( line_width=2.0, fill_pattern=SolidPattern(CreateRGBColor(0.7, 0.7, 0.9)), ) trec.update_rects() sbdict['box'] = trec # now group all these # grouping goes: 1st on bottom, 2nd on top of it, etc.. retgrp = Group([trec, tfld_label, point_group, varbl_group]) retgrp.update_rects() # move lower left corner of retgrp to 0,0 rgbr = retgrp.bounding_rect retgrp.Translate(Point(-rgbr.left, -rgbr.bottom)) retgrp.update_rects() return (retgrp, sbdict)
def insert_home(self): object = Autoshape('star') object.Transform(Rotation(-90 * pi / 180.)) object.SetData((10, 10, 10, 30)) self.main_window.PlaceObject(object)
def main(): import Sketch global doc global tbase_style Sketch.init_lib() draw_printable = 1 draw_visible = 0 embed_fonts = 0 eps_for = util.get_real_username() eps_date = util.current_date() eps_title = None rotate = 0 #doc = load.load_drawing('') # from mainwindow.py: self.SetDocument(Document(create_layer = 1)) doc = Document(create_layer = 1) # get font info first Graphics.font.read_font_dirs() # indicate start of coord system first # coord system:: + goes upward / rightward # from RectangleCreator: trafo = Trafo(off.x, 0, 0, off.y, end.x, end.y) # actually, there 'end' seems to correspond to start (llc: lower left corner of rectangle) - and 'off' to the length extended in each direction (i.e. width, height - but can be negative) ; so instead of 'end' - calling it 'start' start_x = 5 start_y = 5 off_x = -10 off_y = -10 trec = Rectangle(trafo = Trafo(off_x, 0, 0, off_y, start_x, start_y)) trec.update_rects() doc.Insert(trec) # from create_text.py textfld = SimpleText(Translation(50, 50), "xyzzy") textfld.SetProperties(fill_pattern = SolidPattern(StandardColors.green), font = GetFont('Courier-Bold'),#('Times-Bold'), font_size = 36) #copy textfld textfld2 = textfld.Duplicate() textfld2.SetProperties(fill_pattern = SolidPattern(StandardColors.blue)) # change color only # rotate textfld angleDeg = 45 angleRad = pi*(angleDeg/180.0) # ensure float op - could use math.radians instead textfld.Transform(Rotation(angleRad)) # Rotation(angle, center) textfld.update_rects() # probably a good idea # change textfld's text with the current width (that we see) # get bounding box of text a = textfld.properties llx, lly, urx, ury = a.font.TextBoundingBox(textfld.text, a.font_size) # calculate width - its of UNTRANSFORMED text twidth = urx - llx # insert this width as text in textbox now: #~ textfld.text = str(twidth) #~ textfld.update_rects() # probably a good idea - again # get textfield as bezier textbez = textfld.AsBezier() #~ print textbez # returns Sketch.Graphics.group.Group; subclass of EditableCompound # the bounding rectangle - from Compound (type is Rect): textbez_bRect = textbez.bounding_rect # calc width now t2width = textbez_bRect.right - textbez_bRect.left # insert this width as text in textbox now: textfld.text = str(t2width) textfld.update_rects() # probably a good idea - again #~ doc.Insert(textfld) # create a line # using create_spiral.py technique below (see syntax note #(A1)) tpath = CreatePath() # Note - apparently, the first appended point is "moveTo"; # .. the ubsequent ones being "LineTo" tp = Point(textbez_bRect.left,textbez_bRect.bottom) tpath.AppendLine(tp) # moveto tp = Point(textbez_bRect.left,textbez_bRect.top) tpath.AppendLine(tp) # lineto tp = Point(textbez_bRect.right,textbez_bRect.top) tpath.AppendLine(tp) # lineto tp = Point(textbez_bRect.right,textbez_bRect.bottom) tpath.AppendLine(tp) # lineto tline = PolyBezier((tpath,)) tline.AddStyle(tbase_style) # of Graphics.properties (also in compound, document) - seems to add a 'layer' if dynamic; else seems to 'replace' ?! #~ doc.Insert(tline) # group tline and textfld ... # footprints.py has Group(foot_prints = []) tgrp = Group([textfld, textfld2, tline]) tgrp.update_rects() doc.Insert(tgrp) # add a box.. around textfld2 # use radius1, radius2 != 0 AND 1 (logarithmic) to get RoundedRectangle (best between 0.0 and 1.0) tfbr = textfld2.bounding_rect start_x = tfbr.left start_y = tfbr.bottom off_x = tfbr.right - tfbr.left off_y = tfbr.top - tfbr.bottom twid = abs(off_x - start_x) thei = abs(off_y - start_y) radfact = 1.2*twid/thei tradius = 0.05 # if we want to specify a single one, then the actual look will depend on the dimesions of the rectangle - so must 'smooth' it with radfact... trec = Rectangle(trafo = Trafo(off_x, 0, 0, off_y, start_x, start_y), radius1 = tradius, radius2 = tradius*radfact) trec.update_rects() doc.Insert(trec) # add another box - any where start_x = 100.0 start_y = 100.0 off_x = 50.0 off_y = 50.0 trec2 = Rectangle(trafo = Trafo(off_x, 0, 0, off_y, start_x, start_y)) trec2.update_rects() doc.Insert(trec2) # try change props post insert - OK trec2.SetProperties(fill_pattern = SolidPattern(StandardColors.yellow), line_width = 2.0, line_pattern = SolidPattern(CreateRGBColor(0.5, 0.5, 0.7))) # try move the group as a whole (Translate - syntax: spread.py) # say, align the right edge of tline to left edge of trec2 (x direction) # NOTE: group does not define own .AsBezier(self); # but it has tgrp.bounding_rect (although python doesn't show it in dir(tgrp)) # also there is Rectangle.bounding_rect # NOTE though - it seems bounding_rect is somehow padded, with (at least) 10 units in each direction! (also, bounding rect of line will include the arrow) xmove = (trec2.bounding_rect.left+10)-(tline.bounding_rect.right-10) #~ print xmove, trec2.bounding_rect.left, tline.bounding_rect.right tgrp.Translate(Point(xmove, 0)) tgrp.update_rects() # add temporary line to indicate bounding boxes # and effect of padding (may cover the very first trec) tmpbr = trec2.bounding_rect doc.Insert( getQuickLine( (0,0), (trec2.bounding_rect.left+10, tline.bounding_rect.top-10) ) ) # end of draw - generate output file filename = '' psfile = 'vectorout.ps' sk2ps(filename, psfile, printable= draw_printable, visible = draw_visible, For = eps_for, CreationDate = eps_date, Title = eps_title, rotate = rotate, embed_fonts = embed_fonts)
def insert_triangle(self): object = Autoshape('star') object.SetData((10, 20, 3)) object.Transform(Rotation(-pi / 2)) self.main_window.PlaceObject(object)
def insert_toggle_dir(self, name, angle=0): object = Autoshape(name) object.Transform(Rotation(angle * pi / 180.)) object.ToggleDir() self.main_window.PlaceObject(object)
def CreatedObject(self): trafo = Translation(self.start) r, phi = (self.drag_cur - self.start).polar() if r: trafo = trafo(Rotation(phi)) return SimpleText(trafo=trafo, properties=DefaultTextProperties())