示例#1
0
def save_pie_chart(filename, all_angles, step_size, colors):

    #  create the drawing surface
    svg_drawing = Drawing(filename=filename,
                          size=(SVG_SIZE, SVG_SIZE),
                          debug=True)

    start_x = SVG_SIZE // 2
    start_y = SVG_SIZE // 2
    radius = SVG_SIZE // 2

    radians0 = all_angles[-1]
    for i in range(len(all_angles)):
        radians1 = all_angles[i]
        dx0 = radius * (math.sin(radians0))
        dy0 = radius * (math.cos(radians0))
        dx1 = radius * (math.sin(radians1))
        dy1 = radius * (math.cos(radians1))

        m0 = round(dy0, 9)
        n0 = round(-dx0, 9)
        m1 = round(-dy0 + dy1, 9)
        n1 = round(dx0 - dx1, 9)

        w = svg_drawing.path(
            d="M {0},{1} l {2},{3} a {4},{4} 0 0,0 {5},{6} z".format(
                start_x, start_y, m0, n0, radius, m1, n1),
            fill=colors[i],
            stroke="none",
        )
        svg_drawing.add(w)
        radians0 = radians1

    svg_drawing.save()
示例#2
0
def main():
    args = parser.parse_args()
    if not any([args.i, args.m]):
        print('Please, provide some integers or a text message to encode.\n')
        parser.print_help()
        quit(1)

    ints = args.i
    message = args.m

    ints_output_file = args.o or '-'.join([str(i) for i in ints]) + '.svg'
    message_output_file = args.o or validate_filename(message) + '.svg'

    if ints:
        d = Drawing(filename=ints_output_file,
                    profile='tiny',
                    size=(f'{10 + len(ints)*35}px', '70px'))
        d.add(draw_numbers(*ints))
        d.save()
    if message:
        d = Drawing(filename=message_output_file,
                    profile='tiny',
                    size=(f'{10 + len(message)*35}px', '70px'))
        d.add(encode_message(message))
        d.save()
示例#3
0
    def draw(self, start=0, end=None, ext='svg', name=None):
        if end is None:
            end = os.path.getsize(self.source_path)
        if name is None:
            name = self.source_path.name
        name = f"{name}.{ext}"

        if ext == 'svg':
            from svgwrite        import Drawing
            from svgwrite.shapes import Rect
            dwg = Drawing(name, profile='tiny')

        elif ext == 'dxf':
            from dxfwrite import DXFEngine as dxf
            dwg = dxf.drawing(name)

        with open(self.source_path, 'rb') as source_file:
            for i, bit in enumerate(bits(source_file, start, end)):
                if bit == self.invert:
                    x = (i // self.height) * self.scale
                    y = (-i % self.height) * self.scale

                    params = {
                        'insert': (x, y),
                        'size': (self.scale, self.scale)
                    }
                    if ext == 'dxf':
                        rect = DxfRect(**params).to_face3d()
                    else:
                        rect = Rect(**params)
                    dwg.add(rect)
        dwg.save()
示例#4
0
文件: write.py 项目: i5anoff/gridfont
class Writer():
    def __init__(self, fontfn, outfn, size, pad=0, sw=0.2, nl=10):
        self.pos = (pad, pad)
        self.sw = sw
        self.pad = pad
        self.nl = nl
        self.xdst = 1
        self.dwg = Drawing(str(outfn), size=size, profile='tiny', debug=False)
        with open(str(fontfn), 'r') as f:
            self.symbols = load(f)['symbols']

    def newline(self):
        self.pos = (self.pad, self.pos[1] + self.nl)

    def write(self, phrase):
        for s in phrase:
            if s in self.symbols:
                o = self.symbols[s]
                gw = o['w']
                paths = o['paths']
                for path in paths:
                    self.dwg.add(
                        self.dwg.path(d=tosvgpath(
                            list(shift_path(path, self.pos))),
                                      stroke=black,
                                      fill='none',
                                      stroke_width=self.sw))
                self.pos = _rel_move(self.pos, (gw + self.xdst, 0))
            else:
                print('symbol not found: {:s}'.format(s))
        self.dwg.save(pretty=True, indent=2)
示例#5
0
def test_jump_reduction():
    paths = []
    rect_width = 100
    rect_height = rect_width / 2
    for i in range(3):
        y_offset = rect_width*i*1j
        corners = [rect_height, rect_width+rect_height,
                   rect_width+rect_height + rect_height*1j,
                   rect_height*1j+ rect_height]
        corners = [c+y_offset for c in corners]
        lines = [Line(start=corners[j], end=corners[(j+1) % len(corners)])
                 for j in range(len(corners))]
        _path = Path(*lines)
        _path = _path.rotated(i*20)
        paths += list(_path)

    max_y = max([p.start.imag for p in paths]+[p.end.imag for p in paths])
    max_x = max([p.start.real for p in paths]+[p.end.real for p in paths])
    filename = "test_jump_reduction.svg"
    viewbox = [0, -rect_height, max_x+2*rect_height, max_y+2*rect_height]
    dwg = Drawing(filename, width="10cm",
                  viewBox=" ".join([str(b) for b in viewbox]))
    dwg.add(dwg.path(d=Path(*paths).d()))
    dwg.save()
    dig = Digitizer()
    dig.filecontents = open(filename, "r").read()
    dig.svg_to_pattern()
    pattern_to_svg(dig.pattern, join(filename + ".svg"))
示例#6
0
def slice_file(image_position_patient_array,
               image_orientation_patient,
               output_path=None,
               input_path=None):
    print("Status: Loading File.")

    model = STLModel(input_path)
    stats = model.stats()

    print(stats)

    print("Status: Calculating Slices")

    v1 = Point3D(image_orientation_patient[0][0],
                 image_orientation_patient[0][1],
                 image_orientation_patient[0][2])
    v2 = Point3D(image_orientation_patient[1][0],
                 image_orientation_patient[1][1],
                 image_orientation_patient[1][2])
    org = Point3D(0, 0, 0)

    for i, slice_loc in enumerate(image_position_patient_array):
        slice_loc = Point3D(slice_loc[0], slice_loc[1], slice_loc[2])

        dwg = Drawing(output_path + str(i) + '.svg', profile='tiny')
        plane = Plane(v1 + slice_loc, v2 + slice_loc, org + slice_loc)
        x_axis = Line(org + slice_loc, v1 + slice_loc)
        y_axis = Line(org + slice_loc, v2 + slice_loc)
        pairs = model.slice_at_plane(plane, x_axis, y_axis)
        for pair in pairs:
            dwg.add(dwg.line(pair[0], pair[1], stroke=rgb(0, 0, 0, "%")))
        dwg.save()

    print("Status: Finished Outputting Slices")
示例#7
0
def raster_to_vector(image, path):
    drawing = Drawing(path, profile='tiny')
    width, height = image.size
    pixels = image.load()

    start_x = start_y = 0
    last_pixel = pixels[0, 0]
    for close_y in range(height):
        for close_x in range(width):
            pixel = pixels[close_x, close_y]
            # If pixel has different color
            if pixel != last_pixel:
                color = _RGB.format(*last_pixel)
                _add_rectangles(drawing, width, color,
                                start_x, start_y,
                                close_x, close_y)
                # Reset values
                last_pixel = pixel
                start_x = close_x
                start_y = close_y

    _add_rectangles(drawing, width, color,
                    start_x, start_y,
                    close_x, close_y)
    # Save constructed SVG
    try:
        drawing.save()
    except FileNotFoundError:
        makedirs(dirname(path))
        drawing.save()
示例#8
0
def raster_to_vector(image, path):
    drawing = Drawing(path, profile='tiny')
    width, height = image.size
    pixels = image.load()

    start_x = start_y = 0
    last_pixel = pixels[0, 0]
    for close_y in range(height):
        for close_x in range(width):
            pixel = pixels[close_x, close_y]
            # If pixel has different color
            if pixel != last_pixel:
                color = _RGB.format(*last_pixel)
                _add_rectangles(drawing, width, color, start_x, start_y,
                                close_x, close_y)
                # Reset values
                last_pixel = pixel
                start_x = close_x
                start_y = close_y

    _add_rectangles(drawing, width, color, start_x, start_y, close_x, close_y)
    # Save constructed SVG
    try:
        drawing.save()
    except FileNotFoundError:
        makedirs(dirname(path))
        drawing.save()
示例#9
0
def save_radial_tree_plot(filename, root_list, step_size):
    
    #  define some params
    white = "rgb(255, 255, 255)"
    black = "rgb(0, 0, 0)"

    #  create the drawing surface
    svg_drawing = Drawing(
        filename=filename,
        size=(SVG_SIZE, SVG_SIZE),
        debug=True)
    

    #  create defs, in this case, just a single gradient
    rad_grad = svg_drawing.radialGradient(("50%", "50%"), "100%", ("50%", "50%"), id="rad_grad")
    rad_grad.add_stop_color("0%", black, 255)
    rad_grad.add_stop_color("100%", white, 255)
    svg_drawing.defs.add(rad_grad)
    
    tree_plot = svg_drawing.mask(
        id='treeplot',
        style='stroke: black; stroke-width: 3; fill: none; stroke-linecap: round; stroke-opacity: 0.5;')  
    
    tree_plot.add(svg_drawing.rect( (0, 0), (SVG_SIZE, SVG_SIZE) ).fill(white))

    for root in root_list:
        draw_radial_tree_node(svg_drawing, tree_plot, root, rad_grad, step_size)    
    
    base_rect = svg_drawing.rect( (0, 0), (SVG_SIZE, SVG_SIZE), mask="url(#treeplot)").fill(black)
    svg_drawing.add(base_rect)  
    svg_drawing.add(tree_plot)

    svg_drawing.save()  
def generate_frame(i, j, k):
    filename = str(i)+str(j)+str(k)+".svg"
    dwg = Drawing(filename, size=(300, 300))
    dwg.add(dwg.text('i = %d, j = %d, k %d' % (i, j, k), insert=(0.5, 20),
                     fill='red'))
    dwg.add(dwg.line((0, 0), (10, 0), stroke=rgb(10, 10, 16, '%')))
    dwg.save()
    pixel_width = 300
    return convert(pixel_width, filename)
示例#11
0
def test_scale():
    scale = shape.scale(0.5)
    xml = ElementTree.tostring(scale.get_svg().get_xml()).decode()
    assert xml == ('<path d="M 50.000, 50.000 L 60.000, 70.000 '
                   'L 80.000, 50.000 Z" />')
    drawing_scale = Drawing(dirname.joinpath('scale.svg'),
                            size=(200, 200),
                            stroke='black',
                            stroke_width=1)
    drawing_scale.add(scale.get_svg())
    drawing_scale.save()
示例#12
0
def test_translate():
    translate = shape.translate(-50, -50)
    xml = ElementTree.tostring(translate.get_svg().get_xml()).decode()
    assert xml == ('<path d="M 50.000, 50.000 L 70.000, 90.000 '
                   'L 110.000, 50.000 Z" />')
    drawing_translate = Drawing(dirname.joinpath('translate.svg'),
                                size=(200, 200),
                                stroke='black',
                                stroke_width=1)
    drawing_translate.add(translate.get_svg())
    drawing_translate.save()
示例#13
0
def test_flip():
    flip = shape.flip(90)
    xml = ElementTree.tostring(flip.get_svg().get_xml()).decode()
    assert xml == ('<path d="M 80.000, 100.000 L 60.000, 140.000 '
                   'L 20.000, 100.000 Z" />')
    drawing_flip = Drawing(dirname.joinpath('flip.svg'),
                           size=(200, 200),
                           stroke='black',
                           stroke_width=1)
    drawing_flip.add(flip.get_svg())
    drawing_flip.save()
示例#14
0
def slice_file(f=None, resolution=0.1):
    print("Status: Loading File.")

    model = STLModel(f)
    scale = 10
    stats = model.stats()

    sub_vertex = Vector3(stats['extents']['x']['lower'],
                         stats['extents']['y']['lower'],
                         stats['extents']['z']['lower'])
    add_vertex = Vector3(0.5, 0.5, 0.5)

    model.xmin = model.xmax = None
    model.ymin = model.ymax = None
    model.zmin = model.zmax = None

    print("Status: Scaling Triangles.")

    for triangle in model.triangles:
        triangle.vertices[0] -= sub_vertex
        triangle.vertices[1] -= sub_vertex
        triangle.vertices[2] -= sub_vertex

        # The lines above have no effect on the normal.

        triangle.vertices[0] = (triangle.vertices[0] * scale) + add_vertex
        triangle.vertices[1] = (triangle.vertices[1] * scale) + add_vertex
        triangle.vertices[2] = (triangle.vertices[2] * scale) + add_vertex

        # Recalculate the triangle normal

        u = model.triangles[0].vertices[1] - model.triangles[0].vertices[0]
        v = model.triangles[0].vertices[2] - model.triangles[0].vertices[0]

        triangle.n = Normal((u.y * v.z) - (u.z * v.y),
                            (u.z * v.x) - (u.x * v.z),
                            (u.x * v.y) - (u.y * v.x))
        model.update_extents(triangle)

    print("Status: Calculating Slices")

    interval = scale * resolution
    stats = model.stats()
    print(stats)

    for targetz in range(0, int(stats['extents']['z']['upper']),
                         int(interval)):
        dwg = Drawing('outputs/svg/' + str(targetz) + '.svg', profile='tiny')
        pairs = model.slice_at_z(targetz)
        for pair in pairs:
            dwg.add(dwg.line(pair[0], pair[1], stroke=rgb(0, 0, 0, "%")))
        dwg.save()

    print("Status: Finished Outputting Slices")
示例#15
0
 def save(self):
     """Saves the illustration into :attr:`output_filename`."""
     drawing = Drawing(self.output_filename,
                       size=self.size,
                       stroke=self.stroke,
                       stroke_width=self.stroke_width,
                       font_size=self.font_size,
                       font_family=self.font_family)
     for region in self._regions:
         drawing.add(region.get_svg())
     drawing.save(pretty=True)
示例#16
0
class Builder(object):
    def __init__(self,
                 name,
                 commits,
                 configuration,
                 deltax=50.0,
                 width=700.0,
                 y=40.0,
                 sep=20.0,
                 image_size=40.0):
        self.commits = commits
        self.authors = AuthorList()
        self.initial_last_dates(configuration)
        self.position_function()
        height = y + sep + (self.max_elements + 1) * (image_size + sep)
        self.dwg = Drawing(name, size=(width + 2 * deltax, height))

        self.deltax = deltax
        self.width = width
        self.y = y
        self.sep = sep
        self.image_size = image_size

    def initial_last_dates(self, configuration):
        self.initial = self.commits[0]["date"]
        self.last = self.commits[-1]["date"]
        self.max_elements = 0

        for date_tuple, elements in configuration.items():
            date = datetime(*date_tuple).replace(tzinfo=timezone.utc)
            self.last = max(self.last, date)
            self.initial = min(self.initial, date)
            self.max_elements = max(self.max_elements, len(elements))

    def position_function(self):
        size = self.last.timestamp() - self.initial.timestamp()

        def position(date, y, deltax=0, deltay=0):
            return (self.deltax +
                    (date.timestamp() - self.initial.timestamp()) / size *
                    self.width + deltax, y + deltay)

        self.position = position

    def add(self, element):
        for xml in element.draw(self):
            self.dwg.add(xml)

    def save(self):
        self.dwg.save()
示例#17
0
 def draw_single_pentagon(self):
     pentagon = self.new_pentagon()
     dwg = Drawing("{}/single_pentagon.svg".format(self.output_folder),
                   profile='tiny')
     dwg.add(
         dwg.path(
             **{
                 'd': pentagon.d(),
                 'fill': "none",
                 'stroke-width': 4,
                 'stroke': rgb(0, 0, 0)
             }))
     dwg.viewbox(self.pent_x, self.pent_y, self.pent_width,
                 self.pent_height)
     dwg.save()
示例#18
0
def save_radial_tree_plot(filename, root_list):
    svg_drawing = Drawing(filename=filename,
                          size=(SVG_SIZE, SVG_SIZE),
                          debug=True)

    tree_plot = svg_drawing.add(
        svg_drawing.
        g(id='treeplot',
          style=
          'stroke: black; stroke-width: 1; fill: none; stroke-linecap: round;')
    )

    for root in root_list:
        draw_radial_tree_node(svg_drawing, tree_plot, root)

    svg_drawing.save()
示例#19
0
def draw():
	drawing = Drawing(drawing_file_name, drawing_size)
	
	
	first_circle_view = \
		Circle(
			center       = first_circle_center,
			r            = first_circle_radius,
			fill_opacity = 0,
			stroke       = rgb(0, 0, 0),
			stroke_width = 1
		)
		
	first_circle_center_view = \
		Circle(
			center       = first_circle_center,
			r            = 3,
			fill         = rgb(0, 0, 0),
			stroke_width = 0
		)
		
	drawing.add(first_circle_view)
	drawing.add(first_circle_center_view)
	
	
	second_circle_view = \
		Circle(
			center       = second_circle_center,
			r            = second_circle_radius,
			fill_opacity = 0,
			stroke       = rgb(0, 0, 0),
			stroke_width = 1
		)
		
	second_circle_center_view = \
		Circle(
			center       = second_circle_center,
			r            = 3,
			fill         = rgb(0, 0, 0),
			stroke_width = 0
		)
		
	drawing.add(second_circle_view)
	drawing.add(second_circle_center_view)
	
	
	drawing.save()
示例#20
0
def draw_paths(fn, bbox, paths, pad=(0, 0), sw=0.1):
    w, h = bbox
    sx, sy = pad
    dwg = Drawing(str(fn),
                  size=(w + 2 * sx, h + 2 * sy),
                  profile='tiny',
                  debug=False)

    bbox_path = tosvgpath(_box(bbox), pad, closed=True)
    dwg.add(dwg.path(d=bbox_path, stroke=accent, stroke_width=sw, fill='none'))

    for path in paths:
        dwg.add(
            dwg.path(d=tosvgpath(path, pad),
                     stroke=black,
                     fill='none',
                     stroke_width=sw))
    dwg.save(pretty=True, indent=2)
示例#21
0
class Writer():
  def __init__(self, fontfn, outfn, size, pad=0, sw=0.2, nl=10, xdst=1):
    self.pos = (pad, pad)
    self.sw = sw
    self.pad = pad
    self.nl = nl
    self.xdst = xdst
    self.dwg = Drawing(str(outfn), size=size, profile='tiny', debug=False)
    with open(str(fontfn), 'r') as f:
      self.symbols = load(f)['symbols']

  def newline(self):
    self.pos = (self.pad, self.pos[1] + self.nl)

  def scale(self, s):
    for o in self.symbols.values():
      w = o['w']
      h = o['h']
      new_paths = []
      for path in o['paths']:
        new_path = []
        for x, y in path:
          new_path.append((s*(x-w*0.5)+w*0.5*s, s*(y-h*0.5)+h*0.5*s))
        new_paths.append(new_path)
      o.update({'w': w*s, 'h': h*s, 'paths': new_paths})
    return self

  def write(self, phrase):
    for s in phrase:
      if s in self.symbols:
        o = self.symbols[s]
        gw = o['w']
        paths = o['paths']
        for path in paths:
          self.dwg.add(
              self.dwg.path(
                  d=tosvgpath(list(shift_path(path, self.pos))),
                  stroke=black,
                  fill='none',
                  stroke_width=self.sw))
        self.pos = _rel_move(self.pos, (gw + self.xdst, 0))
      else:
        print('symbol not found: {:s}'.format(s))
    self.dwg.save(pretty=True, indent=2)
示例#22
0
 def draw_diagram(self) -> None:
     n_countries: int = self.model.rowCount()
     if n_countries > 0:
         style: SvgStyle = self.svg_style
         delta_angle: float = 2.0*math.pi/n_countries
         max_value: float = max(self.model.values)
         dwg = Drawing(self.temp_svg_file.fileName(), profile='tiny', viewBox='-250 -250 500 500')
         for idx, v in enumerate(self.model.values):
             x: float = style.line_length * v/max_value * math.sin(idx * delta_angle)
             y: float = -style.line_length * v/max_value * math.cos(idx * delta_angle)
             dwg.add(shapes.Line(start=(0, 0), end=(x, y),
                                 stroke=style.line_color, stroke_width=style.line_width))
             radius: float = style.circle_rad
             if style.circle_rad_normalization:
                 radius *= v/max_value
             dwg.add(shapes.Circle(center=(x, y), r=radius,
                                   stroke=style.circle_stroke_color, stroke_width=style.circle_stroke_width,
                                   fill=style.circle_fill_color))
         dwg.save(pretty=True)
         self.load_svg(self.temp_svg_file.fileName())
示例#23
0
def export_svg_svgwrite(fn, paths, w, h, line_width=0.1):

  from svgwrite import Drawing
  w_str = "{}pt".format(w)
  h_str = "{}pt".format(h)

  dwg = Drawing(filename = fn,
                size = (w_str, h_str),
                viewBox=("0 0 {} {}".format(w,h)))

  for path in paths:
    if(len(path) > 1):
      str_list = []
      str_list.append("M {},{}".format(path[0,0],path[0,1]))
      for e in path[1:]:
        str_list.append(" L {},{}".format(e[0],e[1]))
      s = ''.join(str_list)
      dwg.add(dwg.path(s).stroke(color="rgb(0%,0%,0%)",width=line_width).fill("none"))

  dwg.save()
示例#24
0
    def generate_tiling(self):
        dwg = Drawing("{}/tiling2.svg".format(self.output_folder),
                      profile="tiny")

        current_color = 0
        row_spacing = self.pent_height * 2 + self.bottom_length

        for y in range(self.num_down):
            transform = "translate({}, {})".format(0, self.rep_spacing * y)
            dgroup = dwg.add(dwg.g(transform=transform))
            for x in range(self.num_across):
                # if x is odd, point 1 of pent 1 needs to be attached to point 3 of pent 2
                if x % 2 == 1:
                    dx = int(
                        x / 2
                    ) * self.rep_spacing + self.pent_width * 2 + self.column_offset.real
                    transform = "translate({}, {})".format(
                        dx, self.column_offset.imag)
                else:
                    transform = "translate({}, {})".format(
                        int(x / 2) * self.rep_spacing, 0)
                group = dgroup.add(dwg.g(transform=transform))
                for pent in self.cairo_group:
                    group.add(
                        dwg.path(
                            **{
                                'd':
                                pent.d(),
                                'fill':
                                self._colors[current_color %
                                             len(self._colors)],
                                'stroke-width':
                                4,
                                'stroke':
                                rgb(0, 0, 0)
                            }))
                    current_color += 1

        dwg.viewbox(*self.pattern_viewbox)
        dwg.save(pretty=True)
示例#25
0
def export_svg_svgwrite(fn, paths, w, h, line_width=0.1):

    from svgwrite import Drawing
    w_str = "{}pt".format(w)
    h_str = "{}pt".format(h)

    dwg = Drawing(filename=fn,
                  size=(w_str, h_str),
                  viewBox=("0 0 {} {}".format(w, h)))

    for path in paths:
        if (len(path) > 1):
            str_list = []
            str_list.append("M {},{}".format(path[0, 0], path[0, 1]))
            for e in path[1:]:
                str_list.append(" L {},{}".format(e[0], e[1]))
            s = ''.join(str_list)
            dwg.add(
                dwg.path(s).stroke(color="rgb(0%,0%,0%)",
                                   width=line_width).fill("none"))

    dwg.save()
示例#26
0
def save_pie_chart(filename, root_list, step_size):

    #  create the drawing surface
    svg_drawing = Drawing(filename=filename,
                          size=(SVG_SIZE, SVG_SIZE),
                          debug=True)

    start_x = SVG_SIZE // 2
    start_y = SVG_SIZE // 2
    radius = SVG_SIZE // 2

    all_angles = []
    for node in root_list:
        all_angles += node.pie_angle
    all_angles = sorted(all_angles)

    radians0 = all_angles[-1]
    for i in range(len(all_angles)):
        radians1 = all_angles[i]
        dx0 = radius * (math.sin(radians0))
        dy0 = radius * (math.cos(radians0))
        dx1 = radius * (math.sin(radians1))
        dy1 = radius * (math.cos(radians1))

        m0 = dy0
        n0 = -dx0
        m1 = -dy0 + dy1
        n1 = dx0 - dx1

        w = svg_drawing.path(
            d="M {0},{1} l {2},{3} a {4},{4} 0 0,0 {5},{6} z".format(
                start_x, start_y, m0, n0, radius, m1, n1),
            fill=colors[i],
            stroke="none",
        )
        svg_drawing.add(w)
        radians0 = radians1

    svg_drawing.save()
示例#27
0
class Builder(object):
    
    def __init__(self, name, commits, configuration, deltax=50.0, width=700.0, y=40.0, sep=20.0, image_size=40.0):
        self.commits = commits
        self.authors = AuthorList()
        self.initial_last_dates(configuration)
        self.position_function()
        height = y + sep + (self.max_elements + 1) * (image_size + sep)
        self.dwg = Drawing(name, size=(width + 2 * deltax, height))
        
        self.deltax = deltax
        self.width = width
        self.y = y
        self.sep = sep
        self.image_size = image_size
        
    def initial_last_dates(self, configuration):
        self.initial = self.commits[0]["date"]
        self.last = self.commits[-1]["date"]
        self.max_elements = 0

        for date_tuple, elements in configuration.items():
            date = datetime(*date_tuple).replace(tzinfo=timezone.utc)
            self.last = max(self.last, date)
            self.initial = min(self.initial, date)
            self.max_elements = max(self.max_elements, len(elements))
            
    def position_function(self):
        size = self.last.timestamp() - self.initial.timestamp()
        def position(date, y, deltax=0, deltay=0):
            return (self.deltax + (date.timestamp() - self.initial.timestamp()) / size * self.width + deltax, y + deltay)
        self.position = position
        
    def add(self, element):
        for xml in element.draw(self):
            self.dwg.add(xml)
            
    def save(self):
        self.dwg.save()
示例#28
0
    def draw_path_clip(self):
        path_filename = "{}/path_clip_{}.svg".format(
            self.output_folder,
            basename(self.filename).replace(".svg", ""))
        dwg = Drawing(path_filename)
        image_bbox = calc_overall_bbox(self.tile_paths)

        dx = self.pent_x - min(image_bbox[0], image_bbox[1])
        dy = self.pent_y - min(image_bbox[2], image_bbox[3])
        dwg.add(
            dwg.path(
                **{
                    "d": self.new_pentagon().d(),
                    "fill": "none",
                    'stroke-width': 4,
                    'stroke': rgb(0, 0, 0)
                }))
        neg_transform = "translate({}, {})".format(-dx, -dy)
        transform = "translate({}, {})".format(dx, dy)
        clip_path = dwg.defs.add(
            dwg.clipPath(id="pent_path", transform=neg_transform))
        clip_path.add(dwg.path(d=self.new_pentagon().d()))
        group = dwg.add(
            dwg.g(clip_path="url(#pent_path)",
                  transform=transform,
                  id="clippedpath"))
        for i, path in enumerate(self.tile_paths):
            group.add(
                dwg.path(d=path.d(),
                         style=self.tile_attributes[i].get('style'),
                         id=self.tile_attributes[i]['id']))
        dwg.add(dwg.use("#clippedpath", transform="transform(100, 100)"))

        dwg.viewbox(self.pent_x, self.pent_y, self.pent_width,
                    self.pent_height)
        dwg.save()
        xml = xml.dom.minidom.parse(path_filename)
        open(path_filename, "w").write(xml.toprettyxml())
示例#29
0
def make_x(wall: Wall, svg: Drawing):
    rngx = np.arange(2, 146 - 2, 0.25)

    waves = Polygon.Polygon()

    w2 = 0.85

    for y in np.arange(80, 100 + 120, 5.0):
        points = []
        for x in rngx:
            fxy = f(x + wall.x0, y / 1.66)
            points.append((x + wall.x0, y + fxy + w2))

        for x in reversed(rngx):
            fxy = f(x + wall.x0, y / 1.66)
            points.append((x + wall.x0, y + fxy - w2))

        p = Polygon.Polygon(points)
        waves += wall.window & p

    svg.save()

    waves &= wall.window
    wall.result = wall.wall - wall.window + waves
示例#30
0
def make_y(wall: Wall, svg: Drawing):
    rngy = np.arange(wall.y0 - 2, wall.y1 + 2, 0.25)

    waves = Polygon.Polygon()

    w2 = 0.85

    for x in np.arange(wall.x0 - 20, wall.x1 + 20, 6.0):
        points = []
        for y in rngy:
            fxy = f(x, y / 1.66)
            points.append((x + fxy - w2, y))

        for y in reversed(rngy):
            fxy = f(x, y / 1.66)
            points.append((x + fxy + w2, y))

        p = Polygon.Polygon(points)
        waves += wall.window & p

    svg.save()

    waves &= wall.window
    wall.result = wall.wall - wall.window + waves
示例#31
0
# Phys vs scaling indicator
scaled_regions = [
    (1, (2, 5)),
    (1, (7, 8)),
    (1, (11, 22)),
    (1, (24, 26)),
    (2, (2, 5)),
    (2, (7, 8)),
    (2, (11, 22)),
    (2, (24, 26)),
    (4, (2, 5)),
    (4, (7, 8)),
    (4, (11, 22)),
    (4, (24, 26)),
    (5, (2, 5)),
    (5, (7, 8)),
    (5, (11, 22)),
    (5, (24, 26)),
    (3, (17, 19)),
]

for region in scaled_regions:
    x_line = vertical_locs[region[0]]
    start = base_y + region[1][0] * delta_y - 5
    end = base_y + region[1][1] * delta_y - 5
    line = dwg.line(start=(x_line, start), end=(x_line, end))
    v_lines_scaled.add(line)

dwg.save()

print('done')
示例#32
0
 def export(self):
     dwg = Drawing(self.name, width=W, height=H)
     for r in self.rects:
         dwg.add(dwg.rect(insert=(r.x, r.y), size=(r.w, r.h), fill='black'))
     dwg.save()
def flatten_scene(pScene):
    lNode = pScene.GetRootNode()

    if not lNode:
        return

    for i in range(lNode.GetChildCount()):

        lChildNode = lNode.GetChild(i)
        if lChildNode.GetNodeAttribute() is None:
            continue
        lAttributeType = (lChildNode.GetNodeAttribute().GetAttributeType())
        if lAttributeType != FbxNodeAttribute.eMesh:
            continue
        lMesh = lChildNode.GetNodeAttribute()
        projected_points = {}
        control_points = lMesh.GetControlPoints()
        start_point = 0
        poly_paths = []
        for polygon_num in range(lMesh.GetPolygonCount()):
            corners = []
            for corner in range(3):
                corners.append(lMesh.GetPolygonVertex(polygon_num, corner))
            # first, check if any of the control points are already projected
            flattened = []
            for j, corner in enumerate(corners):
                if corner in projected_points:
                    flattened.append(projected_points[corner])
                    continue
                target_corner = corners[j - 1]
                current_vec = control_points[corner]
                target_vec = control_points[target_corner]
                angle = acos(
                    current_vec.DotProduct(target_vec) /
                    (current_vec.Length() * target_vec.Length()))
                length = current_vec.Distance(target_vec)
                # find where the last point was. If it doesn't exist, use the start point
                start_corner = projected_points[target_corner] \
                    if target_corner in projected_points else start_point
                flattened_corner = start_corner + length * (cos(angle) +
                                                            1j * sin(angle))
                projected_points[corner] = flattened_corner
                start_point = flattened_corner
                flattened.append(flattened_corner)
            poly_paths.append(
                Path(*[
                    Line(start=flattened[j], end=flattened[j - 1])
                    for j in range(3)
                ]))

        dwg = Drawing("mesh{}.svg".format(i), profile='tiny')
        for poly_path in poly_paths:
            dwg.add(
                dwg.path(
                    **{
                        'd': poly_path.d(),
                        'fill': "none",
                        'stroke-width': 4,
                        'stroke': rgb(0, 0, 0)
                    }))
        bbox = calc_overall_bbox(poly_paths)
        width, height = abs(bbox[1] - bbox[0]), abs(bbox[3] - bbox[2])
        dwg.viewbox(min(bbox[0], bbox[1]), min(bbox[2], bbox[3]), width,
                    height)
        dwg.save()
def diode_svg_frame(illuminated, num_across=9, num_down=8, frame=0, single_route=-1):
    filename = "diode{:03d}.svg".format(frame)
    led_symbol = "resources/Symbol_LED.svg"
    image_width = 600
    image_height = 400
    right_margin = 30
    bottom_margin = 30
    dwg = Drawing(filename,
                  size=(image_width+right_margin, image_height+bottom_margin),
                  style="background-color:white")
    # create a white background rectangle
    dwg.add(dwg.rect(size=(image_width+right_margin, image_height+bottom_margin),
                     insert=(0, 0), fill="white"))

    LED_dimensions = [106.0, 71.0]
    LED_points = [[35, 68], [35, 31], [66, 50]]
    LED_entries = [[4, 50], [103, 50]]
    aspect_ratio = LED_dimensions[1]/LED_dimensions[0]
    new_width = image_width/num_across
    new_height = new_width*aspect_ratio
    LED_scale = 0.75
    LED_offsets = [new_width*LED_scale/2, new_height*LED_scale]
    junction_radius = 0.8
    elements = []
    for i in range(0, num_across):
        x_pos = new_width*(num_across-i-1)
        if illuminated[1] >= illuminated[0]:
            incoming_wire = illuminated[1] + 1
        else:
            incoming_wire = illuminated[1]
        if i == incoming_wire:
            connection = "+"
            text_fill = "red"
        elif i == illuminated[0]:
            connection = "-"
            text_fill = "black"
        else:
            connection = "NC"
            text_fill = "gray"
        wire_label = "{} {}".format(i+1, connection)
        # the input wire title
        dwg.add(dwg.text(wire_label, insert=(x_pos+new_width-10, 10),
                             fill=text_fill))
        for j in range(0, num_down):
            y_pos = (image_height/num_down)*j
            position = [x_pos+LED_offsets[0], y_pos+LED_offsets[1]]
            scale = [LED_scale*new_width/LED_dimensions[0],
                     LED_scale*new_height/LED_dimensions[1]]
            # the led svg
            dwg.add(dwg.image(led_symbol, insert=position,
                              size=(new_width*LED_scale, new_height*LED_scale)))
            if i == illuminated[0] and j == illuminated[1] and single_route == -1:
                points = []
                for point in LED_points:
                    points.append(transform_point(point, scale, position))
                # the illuminated svg box
                dwg.add(dwg.polygon(points=points, fill="yellow"))
                line_fill = "green"
                stroke_width = 1
                insert_pos = -1
            else:
                line_fill = "black"
                insert_pos = 0
                stroke_width = 0.5
            # for each LED, we want to generate a line going from the input
            # to its output
            entry_point = transform_point(LED_entries[0], scale, position)
            if i > j:
                incoming_line_points = [[new_width*(num_across-j)-LED_offsets[0], 0],
                                    [new_width*(num_across-j)-LED_offsets[0], y_pos+20],
                                    [entry_point[0], y_pos+20], entry_point]
            elif j > i:
                incoming_line_points = [
                    [new_width * (num_across - j - 1) - LED_offsets[0], 0],
                    [new_width * (num_across - j - 1) - LED_offsets[0],
                     entry_point[1] + LED_offsets[1]],
                    [entry_point[0], entry_point[1]+LED_offsets[1]], entry_point]
            elif i == j:
                incoming_line_points = [
                    [new_width * (num_across - j - 1) - LED_offsets[0], 0],
                    [new_width * (num_across - j - 1) - LED_offsets[0], entry_point[1]], entry_point]
            else:
                incoming_line_points = []
            elements.insert(insert_pos,
                            make_junction_line(dwg, incoming_line_points,
                                               junction_radius, line_fill,
                                               stroke_width))
            # outgoing line
            exit_point = transform_point(LED_entries[1], scale, position)
            outgoing_line_points = [exit_point,
                                    [x_pos+new_width-LED_offsets[0],
                                     exit_point[1]],
                                    [x_pos+new_width-LED_offsets[0], 0]]
            elements.insert(insert_pos,
                            make_junction_line(dwg, outgoing_line_points,
                                               junction_radius, line_fill,
                                               stroke_width))
            route_points = [[new_width * (num_across - j - 1) - LED_offsets[0],
                             0]]
            for point in range(0, single_route+1):
                if point < i:
                    route_points.append([new_width * (num_across - j - 1) - LED_offsets[0], 0])

            # now create the network
            nodes = []
            for i in range(0, num_across):
                for j in range(0, num_down):
                    nodes.append(entry_point)
                    nodes.append(exit_point)
    # flatten the elements structure
    elements = sum(elements, [])
    print(elements)
    # the lines should be drawn last so that they are layered on top of all
    # other elements
    #for element in elements:
    #    dwg.add(element)
    dwg.save()
    return convert(image_width, filename)
示例#35
0
def disvg(paths=None, colors=None,
          filename=os_path.join(getcwd(), 'disvg_output.svg'),
          stroke_widths=None, nodes=None, node_colors=None, node_radii=None,
          openinbrowser=True, timestamp=False,
          margin_size=0.1, mindim=600, dimensions=None,
          viewbox=None, text=None, text_path=None, font_size=None,
          attributes=None, svg_attributes=None, svgwrite_debug=False, paths2Drawing=False):
    """Takes in a list of paths and creates an SVG file containing said paths.
    REQUIRED INPUTS:
        :param paths - a list of paths

    OPTIONAL INPUT:
        :param colors - specifies the path stroke color.  By default all paths
        will be black (#000000).  This paramater can be input in a few ways
        1) a list of strings that will be input into the path elements stroke
            attribute (so anything that is understood by the svg viewer).
        2) a string of single character colors -- e.g. setting colors='rrr' is
            equivalent to setting colors=['red', 'red', 'red'] (see the
            'color_dict' dictionary above for a list of possibilities).
        3) a list of rgb 3-tuples -- e.g. colors = [(255, 0, 0), ...].

        :param filename - the desired location/filename of the SVG file
        created (by default the SVG will be stored in the current working
        directory and named 'disvg_output.svg').

        :param stroke_widths - a list of stroke_widths to use for paths
        (default is 0.5% of the SVG's width or length)

        :param nodes - a list of points to draw as filled-in circles

        :param node_colors - a list of colors to use for the nodes (by default
        nodes will be red)

        :param node_radii - a list of radii to use for the nodes (by default
        nodes will be radius will be 1 percent of the svg's width/length)

        :param text - string or list of strings to be displayed

        :param text_path - if text is a list, then this should be a list of
        path (or path segments of the same length.  Note: the path must be
        long enough to display the text or the text will be cropped by the svg
        viewer.

        :param font_size - a single float of list of floats.

        :param openinbrowser -  Set to True to automatically open the created
        SVG in the user's default web browser.

        :param timestamp - if True, then the a timestamp will be appended to
        the output SVG's filename.  This will fix issues with rapidly opening
        multiple SVGs in your browser.

        :param margin_size - The min margin (empty area framing the collection
        of paths) size used for creating the canvas and background of the SVG.

        :param mindim - The minimum dimension (height or width) of the output
        SVG (default is 600).

        :param dimensions - The (x,y) display dimensions of the output SVG.
        I.e. this specifies the `width` and `height` SVG attributes. Note that 
        these also can be used to specify units other than pixels. Using this 
        will override the `mindim` parameter.

        :param viewbox - This specifies the coordinated system used in the svg.
        The SVG `viewBox` attribute works together with the the `height` and 
        `width` attrinutes.  Using these three attributes allows for shifting 
        and scaling of the SVG canvas without changing the any values other 
        than those in `viewBox`, `height`, and `width`.  `viewbox` should be 
        input as a 4-tuple, (min_x, min_y, width, height), or a string 
        "min_x min_y width height".  Using this will override the `mindim` 
        parameter.

        :param attributes - a list of dictionaries of attributes for the input
        paths.  Note: This will override any other conflicting settings.

        :param svg_attributes - a dictionary of attributes for output svg.
        
        :param svgwrite_debug - This parameter turns on/off `svgwrite`'s 
        debugging mode.  By default svgwrite_debug=False.  This increases 
        speed and also prevents `svgwrite` from raising of an error when not 
        all `svg_attributes` key-value pairs are understood.
        
        :param paths2Drawing - If true, an `svgwrite.Drawing` object is 
        returned and no file is written.  This `Drawing` can later be saved 
        using the `svgwrite.Drawing.save()` method.

    NOTES:
        * The `svg_attributes` parameter will override any other conflicting 
        settings.

        * Any `extra` parameters that `svgwrite.Drawing()` accepts can be 
        controlled by passing them in through `svg_attributes`.

        * The unit of length here is assumed to be pixels in all variables.

        * If this function is used multiple times in quick succession to
        display multiple SVGs (all using the default filename), the
        svgviewer/browser will likely fail to load some of the SVGs in time.
        To fix this, use the timestamp attribute, or give the files unique
        names, or use a pause command (e.g. time.sleep(1)) between uses.
    """


    _default_relative_node_radius = 5e-3
    _default_relative_stroke_width = 1e-3
    _default_path_color = '#000000'  # black
    _default_node_color = '#ff0000'  # red
    _default_font_size = 12


    # append directory to filename (if not included)
    if os_path.dirname(filename) == '':
        filename = os_path.join(getcwd(), filename)

    # append time stamp to filename
    if timestamp:
        fbname, fext = os_path.splitext(filename)
        dirname = os_path.dirname(filename)
        tstamp = str(time()).replace('.', '')
        stfilename = os_path.split(fbname)[1] + '_' + tstamp + fext
        filename = os_path.join(dirname, stfilename)

    # check paths and colors are set
    if isinstance(paths, Path) or is_path_segment(paths):
        paths = [paths]
    if paths:
        if not colors:
            colors = [_default_path_color] * len(paths)
        else:
            assert len(colors) == len(paths)
            if isinstance(colors, str):
                colors = str2colorlist(colors,
                                       default_color=_default_path_color)
            elif isinstance(colors, list):
                for idx, c in enumerate(colors):
                    if is3tuple(c):
                        colors[idx] = "rgb" + str(c)

    # check nodes and nodes_colors are set (node_radii are set later)
    if nodes:
        if not node_colors:
            node_colors = [_default_node_color] * len(nodes)
        else:
            assert len(node_colors) == len(nodes)
            if isinstance(node_colors, str):
                node_colors = str2colorlist(node_colors,
                                            default_color=_default_node_color)
            elif isinstance(node_colors, list):
                for idx, c in enumerate(node_colors):
                    if is3tuple(c):
                        node_colors[idx] = "rgb" + str(c)

    # set up the viewBox and display dimensions of the output SVG
    # along the way, set stroke_widths and node_radii if not provided
    assert paths or nodes
    stuff2bound = []
    if viewbox:
        if not isinstance(viewbox, str):
            viewbox = '%s %s %s %s' % viewbox
        if dimensions is None:
            dimensions = viewbox.split(' ')[2:4]
    elif dimensions:
        dimensions = tuple(map(str, dimensions))
        def strip_units(s):
            return re.search(r'\d*\.?\d*', s.strip()).group()
        viewbox = '0 0 %s %s' % tuple(map(strip_units, dimensions))
    else:
        if paths:
            stuff2bound += paths
        if nodes:
            stuff2bound += nodes
        if text_path:
            stuff2bound += text_path
        xmin, xmax, ymin, ymax = big_bounding_box(stuff2bound)
        dx = xmax - xmin
        dy = ymax - ymin

        if dx == 0:
            dx = 1
        if dy == 0:
            dy = 1

        # determine stroke_widths to use (if not provided) and max_stroke_width
        if paths:
            if not stroke_widths:
                sw = max(dx, dy) * _default_relative_stroke_width
                stroke_widths = [sw]*len(paths)
                max_stroke_width = sw
            else:
                assert len(paths) == len(stroke_widths)
                max_stroke_width = max(stroke_widths)
        else:
            max_stroke_width = 0

        # determine node_radii to use (if not provided) and max_node_diameter
        if nodes:
            if not node_radii:
                r = max(dx, dy) * _default_relative_node_radius
                node_radii = [r]*len(nodes)
                max_node_diameter = 2*r
            else:
                assert len(nodes) == len(node_radii)
                max_node_diameter = 2*max(node_radii)
        else:
            max_node_diameter = 0

        extra_space_for_style = max(max_stroke_width, max_node_diameter)
        xmin -= margin_size*dx + extra_space_for_style/2
        ymin -= margin_size*dy + extra_space_for_style/2
        dx += 2*margin_size*dx + extra_space_for_style
        dy += 2*margin_size*dy + extra_space_for_style
        viewbox = "%s %s %s %s" % (xmin, ymin, dx, dy)

        if dx > dy:
            szx = str(mindim) + 'px'
            szy = str(int(ceil(mindim * dy / dx))) + 'px'
        else:
            szx = str(int(ceil(mindim * dx / dy))) + 'px'
            szy = str(mindim) + 'px'
        dimensions = szx, szy

    # Create an SVG file
    if svg_attributes is not None:
        dimensions = (svg_attributes.get("width", dimensions[0]),
                      svg_attributes.get("height", dimensions[1]))
        debug = svg_attributes.get("debug", svgwrite_debug)
        dwg = Drawing(filename=filename, size=dimensions, debug=debug,
                      **svg_attributes)
    else:
        dwg = Drawing(filename=filename, size=dimensions, debug=svgwrite_debug,
                      viewBox=viewbox)

    # add paths
    if paths:
        for i, p in enumerate(paths):
            if isinstance(p, Path):
                ps = p.d()
            elif is_path_segment(p):
                ps = Path(p).d()
            else:  # assume this path, p, was input as a Path d-string
                ps = p

            if attributes:
                good_attribs = {'d': ps}
                for key in attributes[i]:
                    val = attributes[i][key]
                    if key != 'd':
                        try:
                            dwg.path(ps, **{key: val})
                            good_attribs.update({key: val})
                        except Exception as e:
                            warn(str(e))

                dwg.add(dwg.path(**good_attribs))
            else:
                dwg.add(dwg.path(ps, stroke=colors[i],
                                 stroke_width=str(stroke_widths[i]),
                                 fill='none'))

    # add nodes (filled in circles)
    if nodes:
        for i_pt, pt in enumerate([(z.real, z.imag) for z in nodes]):
            dwg.add(dwg.circle(pt, node_radii[i_pt], fill=node_colors[i_pt]))

    # add texts
    if text:
        assert isinstance(text, str) or (isinstance(text, list) and
                                         isinstance(text_path, list) and
                                         len(text_path) == len(text))
        if isinstance(text, str):
            text = [text]
            if not font_size:
                font_size = [_default_font_size]
            if not text_path:
                pos = complex(xmin + margin_size*dx, ymin + margin_size*dy)
                text_path = [Line(pos, pos + 1).d()]
        else:
            if font_size:
                if isinstance(font_size, list):
                    assert len(font_size) == len(text)
                else:
                    font_size = [font_size] * len(text)
            else:
                font_size = [_default_font_size] * len(text)
        for idx, s in enumerate(text):
            p = text_path[idx]
            if isinstance(p, Path):
                ps = p.d()
            elif is_path_segment(p):
                ps = Path(p).d()
            else:  # assume this path, p, was input as a Path d-string
                ps = p

            # paragraph = dwg.add(dwg.g(font_size=font_size[idx]))
            # paragraph.add(dwg.textPath(ps, s))
            pathid = 'tp' + str(idx)
            dwg.defs.add(dwg.path(d=ps, id=pathid))
            txter = dwg.add(dwg.text('', font_size=font_size[idx]))
            txter.add(txt.TextPath('#'+pathid, s))

    if paths2Drawing:
        return dwg
      
    # save svg
    if not os_path.exists(os_path.dirname(filename)):
        makedirs(os_path.dirname(filename))
    dwg.save()

    # re-open the svg, make the xml pretty, and save it again
    xmlstring = md_xml_parse(filename).toprettyxml()
    with open(filename, 'w') as f:
        f.write(xmlstring)

    # try to open in web browser
    if openinbrowser:
        try:
            open_in_browser(filename)
        except:
            print("Failed to open output SVG in browser.  SVG saved to:")
            print(filename)
示例#36
0
    def process(self):
        """
		This takes a 4CAT results file as input, and outputs a plain text file
		containing all post bodies as one continuous string, sanitized.
		"""

        link_regex = re.compile(r"https?://[^\s]+")
        delete_regex = re.compile(r"[^a-zA-Z)(.,\n -]")

        # settings
        strip_urls = self.parameters.get("strip-urls",
                                         self.options["strip-urls"]["default"])
        strip_symbols = self.parameters.get(
            "strip-symbols", self.options["strip-symbols"]["default"])
        sides = self.parameters.get("sides", self.options["sides"]["default"])
        self.align = self.parameters.get("align",
                                         self.options["align"]["default"])
        window = convert_to_int(
            self.parameters.get("window", self.options["window"]["default"]),
            5) + 1
        query = self.parameters.get("query", self.options["query"]["default"])
        self.limit = convert_to_int(
            self.parameters.get("limit", self.options["limit"]["default"]),
            100)

        left_branches = []
        right_branches = []

        # do some validation
        if not query.strip() or re.sub(r"\s", "", query) != query:
            self.dataset.update_status(
                "Invalid query for word tree generation. Query cannot be empty or contain whitespace."
            )
            self.dataset.finish(0)
            return

        window = min(window, self.options["window"]["max"] + 1)
        window = max(1, window)

        # find matching posts
        processed = 0
        for post in self.iterate_csv_items(self.source_file):
            processed += 1
            if processed % 500 == 0:
                self.dataset.update_status(
                    "Processing and tokenising post %i" % processed)
            body = post["body"]

            if strip_urls:
                body = link_regex.sub("", body)

            if strip_symbols:
                body = delete_regex.sub("", body)

            body = word_tokenize(body)
            positions = [
                i for i, x in enumerate(body) if x.lower() == query.lower()
            ]

            # get lists of tokens for both the left and right side of the tree
            # on the left side, all lists end with the query, on the right side,
            # they start with the query
            for position in positions:
                right_branches.append(body[position:position + window])
                left_branches.append(body[max(0, position - window):position +
                                          1])

        # Some settings for rendering the tree later
        self.step = self.fontsize * 0.6  # approximately the width of a monospace char
        self.gap = (7 * self.step)  # space for lines between nodes
        width = 1  # will be updated later

        # invert the left side of the tree (because that's the way we want the
        # branching to work for that side)
        # we'll visually invert the nodes in the tree again later
        left_branches = [list(reversed(branch)) for branch in left_branches]

        # first create vertical slices of tokens per level
        self.dataset.update_status("Generating token tree from posts")
        levels_right = [{} for i in range(0, window)]
        levels_left = [{} for i in range(0, window)]
        tokens_left = []
        tokens_right = []

        # for each "level" (each branching point representing a level), turn
        # tokens into nodes, record the max amount of occurences for any
        # token in that level, and keep track of what nodes are in which level.
        # The latter is needed because a token may occur multiple times, at
        # different points in the graph. Do this for both the left and right
        # side of the tree.
        for i in range(0, window):
            for branch in right_branches:
                if i >= len(branch):
                    continue

                token = branch[i].lower()
                if token not in levels_right[i]:
                    parent = levels_right[i - 1][branch[
                        i - 1].lower()] if i > 0 else None
                    levels_right[i][token] = Node(token,
                                                  parent=parent,
                                                  occurrences=1,
                                                  is_top_root=(parent is None))
                    tokens_right.append(levels_right[i][token])
                else:
                    levels_right[i][token].occurrences += 1

                occurrences = levels_right[i][token].occurrences
                self.max_occurrences[i] = max(
                    occurrences, self.max_occurrences[i]
                ) if i in self.max_occurrences else occurrences

            for branch in left_branches:
                if i >= len(branch):
                    continue

                token = branch[i].lower()
                if token not in levels_left[i]:
                    parent = levels_left[i - 1][branch[
                        i - 1].lower()] if i > 0 else None
                    levels_left[i][token] = Node(token,
                                                 parent=parent,
                                                 occurrences=1,
                                                 is_top_root=(parent is None))
                    tokens_left.append(levels_left[i][token])
                else:
                    levels_left[i][token].occurrences += 1

                occurrences = levels_left[i][token].occurrences
                self.max_occurrences[i] = max(
                    occurrences, self.max_occurrences[i]
                ) if i in self.max_occurrences else occurrences

        # nodes that have no siblings can be merged with their parents, else
        # the graph becomes unnecessarily large with lots of single-word nodes
        # connected to single-word nodes. additionally, we want the nodes with
        # the most branches to be sorted to the top, and then only retain the
        # most interesting (i.e. most-occurring) branches
        self.dataset.update_status("Merging and sorting tree nodes")
        for token in tokens_left:
            self.merge_upwards(token)
            self.sort_node(token)
            self.limit_subtree(token)

        for token in tokens_right:
            self.merge_upwards(token)
            self.sort_node(token)
            self.limit_subtree(token)

        # somewhat annoyingly, anytree does not simply delete nodes detached
        # from the tree in the previous steps, but makes them root nodes. We
        # don't need these root nodes (we only need the original root), so the
        # next step is to remove all root nodes that are not the main root.
        # We cannot modify a list in-place, so make a new list with the
        # relevant nodes
        level_sizes = {}
        filtered_tokens_right = []
        for token in tokens_right:
            if token.is_root and not token.is_top_root:
                continue

            filtered_tokens_right.append(token)

        filtered_tokens_left = []
        for token in tokens_left:
            if token.is_root and not token.is_top_root:
                continue

            filtered_tokens_left.append(token)

        # now we know which nodes are left, and can therefore determine how
        # large the canvas needs to be - this is based on the max number of
        # branches found on any level of the tree, in other words, the number
        # of "terminal nodes"
        height_left = self.whitespace * self.fontsize * max([
            self.max_breadth(node)
            for node in filtered_tokens_left if node.is_top_root
        ])
        height_right = self.whitespace * self.fontsize * max([
            self.max_breadth(node)
            for node in filtered_tokens_right if node.is_top_root
        ])
        height = max(height_left, height_right)

        canvas = Drawing(str(self.dataset.get_results_path()),
                         size=(width, height),
                         style="font-family:monospace;font-size:%ipx" %
                         self.fontsize)

        # the nodes on the left side of the graph now have the wrong word order,
        # because we reversed them earlier to generate the correct tree
        # hierarchy - now reverse the node labels so they are proper language
        # again
        for token in tokens_left:
            self.invert_node_labels(token)

        wrapper = SVG(overflow="visible")

        self.dataset.update_status("Rendering tree to SVG file")
        if sides != "right":
            wrapper = self.render(wrapper, [
                token for token in filtered_tokens_left
                if token.is_root and token.children
            ],
                                  height=height,
                                  side=self.SIDE_LEFT)

        if sides != "left":
            wrapper = self.render(wrapper, [
                token for token in filtered_tokens_right
                if token.is_root and token.children
            ],
                                  height=height,
                                  side=self.SIDE_RIGHT)

        # things may have been rendered outside the canvas, in which case we
        # need to readjust the SVG properties
        wrapper.update({"x": 0 if self.x_min >= 0 else self.x_min * -1})
        canvas.update({"width": (self.x_max - self.x_min)})

        canvas.add(wrapper)
        canvas.save(pretty=True)

        self.dataset.update_status("Finished")
        self.dataset.finish(len(tokens_left) + len(tokens_right))
示例#37
0
def disvg(paths=None,
          colors=None,
          filename=None,
          stroke_widths=None,
          nodes=None,
          node_colors=None,
          node_radii=None,
          openinbrowser=True,
          timestamp=None,
          margin_size=0.1,
          mindim=600,
          dimensions=None,
          viewbox=None,
          text=None,
          text_path=None,
          font_size=None,
          attributes=None,
          svg_attributes=None,
          svgwrite_debug=False,
          paths2Drawing=False,
          baseunit='px'):
    """Creates (and optionally displays) an SVG file.

    REQUIRED INPUTS:
        :param paths - a list of paths

    OPTIONAL INPUT:
        :param colors - specifies the path stroke color.  By default all paths
        will be black (#000000).  This paramater can be input in a few ways
        1) a list of strings that will be input into the path elements stroke
            attribute (so anything that is understood by the svg viewer).
        2) a string of single character colors -- e.g. setting colors='rrr' is
            equivalent to setting colors=['red', 'red', 'red'] (see the
            'color_dict' dictionary above for a list of possibilities).
        3) a list of rgb 3-tuples -- e.g. colors = [(255, 0, 0), ...].

        :param filename - the desired location/filename of the SVG file
        created (by default the SVG will be named 'disvg_output.svg' or
        'disvg_output_<timestamp>.svg' and stored in the temporary
        directory returned by `tempfile.gettempdir()`.  See `timestamp`
        for information on the timestamp.

        :param stroke_widths - a list of stroke_widths to use for paths
        (default is 0.5% of the SVG's width or length)

        :param nodes - a list of points to draw as filled-in circles

        :param node_colors - a list of colors to use for the nodes (by default
        nodes will be red)

        :param node_radii - a list of radii to use for the nodes (by default
        nodes will be radius will be 1 percent of the svg's width/length)

        :param text - string or list of strings to be displayed

        :param text_path - if text is a list, then this should be a list of
        path (or path segments of the same length.  Note: the path must be
        long enough to display the text or the text will be cropped by the svg
        viewer.

        :param font_size - a single float of list of floats.

        :param openinbrowser -  Set to True to automatically open the created
        SVG in the user's default web browser.

        :param timestamp - if true, then the a timestamp will be
        appended to the output SVG's filename.  This is meant as a
        workaround for issues related to rapidly opening multiple
        SVGs in your browser using `disvg`. This defaults to true if
        `filename is None` and false otherwise.

        :param margin_size - The min margin (empty area framing the collection
        of paths) size used for creating the canvas and background of the SVG.

        :param mindim - The minimum dimension (height or width) of the output
        SVG (default is 600).

        :param dimensions - The (x,y) display dimensions of the output SVG.
        I.e. this specifies the `width` and `height` SVG attributes. Note that 
        these also can be used to specify units other than pixels. Using this 
        will override the `mindim` parameter.

        :param viewbox - This specifies the coordinated system used in the svg.
        The SVG `viewBox` attribute works together with the the `height` and 
        `width` attrinutes.  Using these three attributes allows for shifting 
        and scaling of the SVG canvas without changing the any values other 
        than those in `viewBox`, `height`, and `width`.  `viewbox` should be 
        input as a 4-tuple, (min_x, min_y, width, height), or a string 
        "min_x min_y width height".  Using this will override the `mindim` 
        parameter.

        :param attributes - a list of dictionaries of attributes for the input
        paths.  Note: This will override any other conflicting settings.

        :param svg_attributes - a dictionary of attributes for output svg.
        
        :param svgwrite_debug - This parameter turns on/off `svgwrite`'s 
        debugging mode.  By default svgwrite_debug=False.  This increases 
        speed and also prevents `svgwrite` from raising of an error when not 
        all `svg_attributes` key-value pairs are understood.
        
        :param paths2Drawing - If true, an `svgwrite.Drawing` object is 
        returned and no file is written.  This `Drawing` can later be saved 
        using the `svgwrite.Drawing.save()` method.

    NOTES:
        * The `svg_attributes` parameter will override any other conflicting 
        settings.

        * Any `extra` parameters that `svgwrite.Drawing()` accepts can be 
        controlled by passing them in through `svg_attributes`.

        * The unit of length here is assumed to be pixels in all variables.

        * If this function is used multiple times in quick succession to
        display multiple SVGs (all using the default filename), the
        svgviewer/browser will likely fail to load some of the SVGs in time.
        To fix this, use the timestamp attribute, or give the files unique
        names, or use a pause command (e.g. time.sleep(1)) between uses.

    SEE ALSO:
        * document.py
    """

    _default_relative_node_radius = 5e-3
    _default_relative_stroke_width = 1e-3
    _default_path_color = '#000000'  # black
    _default_node_color = '#ff0000'  # red
    _default_font_size = 12

    if filename is None:
        timestamp = True if timestamp is None else timestamp
        filename = os_path.join(gettempdir(), 'disvg_output.svg')

    dirname = os_path.abspath(os_path.dirname(filename))
    if not os_path.exists(dirname):
        makedirs(dirname)

    # append time stamp to filename
    if timestamp:
        fbname, fext = os_path.splitext(filename)
        tstamp = str(time()).replace('.', '')
        stfilename = os_path.split(fbname)[1] + '_' + tstamp + fext
        filename = os_path.join(dirname, stfilename)

    # check paths and colors are set
    if isinstance(paths, Path) or is_path_segment(paths):
        paths = [paths]
    if paths:
        if not colors:
            colors = [_default_path_color] * len(paths)
        else:
            assert len(colors) == len(paths)
            if isinstance(colors, str):
                colors = str2colorlist(colors,
                                       default_color=_default_path_color)
            elif isinstance(colors, list):
                for idx, c in enumerate(colors):
                    if is3tuple(c):
                        colors[idx] = "rgb" + str(c)

    # check nodes and nodes_colors are set (node_radii are set later)
    if nodes:
        if not node_colors:
            node_colors = [_default_node_color] * len(nodes)
        else:
            assert len(node_colors) == len(nodes)
            if isinstance(node_colors, str):
                node_colors = str2colorlist(node_colors,
                                            default_color=_default_node_color)
            elif isinstance(node_colors, list):
                for idx, c in enumerate(node_colors):
                    if is3tuple(c):
                        node_colors[idx] = "rgb" + str(c)

    # set up the viewBox and display dimensions of the output SVG
    # along the way, set stroke_widths and node_radii if not provided
    assert paths or nodes
    stuff2bound = []
    if viewbox:
        if not isinstance(viewbox, str):
            viewbox = '%s %s %s %s' % viewbox
        if dimensions is None:
            dimensions = viewbox.split(' ')[2:4]
    elif dimensions:
        dimensions = tuple(map(str, dimensions))

        def strip_units(s):
            return re.search(r'\d*\.?\d*', s.strip()).group()

        viewbox = '0 0 %s %s' % tuple(map(strip_units, dimensions))
    else:
        if paths:
            stuff2bound += paths
        if nodes:
            stuff2bound += nodes
        if text_path:
            stuff2bound += text_path
        xmin, xmax, ymin, ymax = big_bounding_box(stuff2bound)
        dx = xmax - xmin
        dy = ymax - ymin

        if dx == 0:
            dx = 1
        if dy == 0:
            dy = 1

        # determine stroke_widths to use (if not provided) and max_stroke_width
        if paths:
            if not stroke_widths:
                sw = max(dx, dy) * _default_relative_stroke_width
                stroke_widths = [sw] * len(paths)
                max_stroke_width = sw
            else:
                assert len(paths) == len(stroke_widths)
                max_stroke_width = max(stroke_widths)
        else:
            max_stroke_width = 0

        # determine node_radii to use (if not provided) and max_node_diameter
        if nodes:
            if not node_radii:
                r = max(dx, dy) * _default_relative_node_radius
                node_radii = [r] * len(nodes)
                max_node_diameter = 2 * r
            else:
                assert len(nodes) == len(node_radii)
                max_node_diameter = 2 * max(node_radii)
        else:
            max_node_diameter = 0

        extra_space_for_style = max(max_stroke_width, max_node_diameter)
        xmin -= margin_size * dx + extra_space_for_style / 2
        ymin -= margin_size * dy + extra_space_for_style / 2
        dx += 2 * margin_size * dx + extra_space_for_style
        dy += 2 * margin_size * dy + extra_space_for_style
        viewbox = "%s %s %s %s" % (xmin, ymin, dx, dy)

        if mindim is None:
            szx = "{}{}".format(dx, baseunit)
            szy = "{}{}".format(dy, baseunit)
        else:
            if dx > dy:
                szx = str(mindim) + baseunit
                szy = str(int(ceil(mindim * dy / dx))) + baseunit
            else:
                szx = str(int(ceil(mindim * dx / dy))) + baseunit
                szy = str(mindim) + baseunit
        dimensions = szx, szy

    # Create an SVG file
    if svg_attributes is not None:
        dimensions = (svg_attributes.get("width", dimensions[0]),
                      svg_attributes.get("height", dimensions[1]))
        debug = svg_attributes.get("debug", svgwrite_debug)
        dwg = Drawing(filename=filename,
                      size=dimensions,
                      debug=debug,
                      **svg_attributes)
    else:
        dwg = Drawing(filename=filename,
                      size=dimensions,
                      debug=svgwrite_debug,
                      viewBox=viewbox)

    # add paths
    if paths:
        for i, p in enumerate(paths):
            if isinstance(p, Path):
                ps = p.d()
            elif is_path_segment(p):
                ps = Path(p).d()
            else:  # assume this path, p, was input as a Path d-string
                ps = p

            if attributes:
                good_attribs = {'d': ps}
                for key in attributes[i]:
                    val = attributes[i][key]
                    if key != 'd':
                        try:
                            dwg.path(ps, **{key: val})
                            good_attribs.update({key: val})
                        except Exception as e:
                            warn(str(e))

                dwg.add(dwg.path(**good_attribs))
            else:
                dwg.add(
                    dwg.path(ps,
                             stroke=colors[i],
                             stroke_width=str(stroke_widths[i]),
                             fill='none'))

    # add nodes (filled in circles)
    if nodes:
        for i_pt, pt in enumerate([(z.real, z.imag) for z in nodes]):
            dwg.add(dwg.circle(pt, node_radii[i_pt], fill=node_colors[i_pt]))

    # add texts
    if text:
        assert isinstance(text, str) or (isinstance(text, list) and isinstance(
            text_path, list) and len(text_path) == len(text))
        if isinstance(text, str):
            text = [text]
            if not font_size:
                font_size = [_default_font_size]
            if not text_path:
                pos = complex(xmin + margin_size * dx, ymin + margin_size * dy)
                text_path = [Line(pos, pos + 1).d()]
        else:
            if font_size:
                if isinstance(font_size, list):
                    assert len(font_size) == len(text)
                else:
                    font_size = [font_size] * len(text)
            else:
                font_size = [_default_font_size] * len(text)
        for idx, s in enumerate(text):
            p = text_path[idx]
            if isinstance(p, Path):
                ps = p.d()
            elif is_path_segment(p):
                ps = Path(p).d()
            else:  # assume this path, p, was input as a Path d-string
                ps = p

            # paragraph = dwg.add(dwg.g(font_size=font_size[idx]))
            # paragraph.add(dwg.textPath(ps, s))
            pathid = 'tp' + str(idx)
            dwg.defs.add(dwg.path(d=ps, id=pathid))
            txter = dwg.add(dwg.text('', font_size=font_size[idx]))
            txter.add(txt.TextPath('#' + pathid, s))

    if paths2Drawing:
        return dwg

    dwg.save()

    # re-open the svg, make the xml pretty, and save it again
    xmlstring = md_xml_parse(filename).toprettyxml()
    with open(filename, 'w') as f:
        f.write(xmlstring)

    # try to open in web browser
    if openinbrowser:
        try:
            open_in_browser(filename)
        except:
            print("Failed to open output SVG in browser.  SVG saved to:")
            print(filename)
            if end > start:
                ar_l = 10
            else:
                ar_l = -10

            ar_h = 7.5
            pts = ((end-ar_l, y_mid+ar_h), (end, y_mid), (end-ar_l, y_mid-ar_h))
            arrow = dwg.polyline(pts)
            h_lines.add(arrow)

    y += delta_y


# Phys vs scaling indicator
scaled_regions = [(0, (7, 9)),
                  (1, (2, 11)),
                  (1, (13, 14)),
                  (2, (2, 11)),
                  (2, (13, 14)),
                  ]

for region in scaled_regions:
    x_line = vertical_locs[region[0]]
    start = base_y + region[1][0] * delta_y - 5
    end = base_y + region[1][1] * delta_y - 5
    line = dwg.line(start=(x_line, start), end=(x_line, end))
    v_lines_scaled.add(line)

dwg.save()

print('done')