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()
示例#2
0
def create_svg_document_with_light(elements,
                                   size,
                                   viewbox=None,
                                   background_color="white",
                                   background_opacity=1.0):
    """Create the full SVG document, with a lighting filter.

    Resources:

    - https://www.w3.org/TR/SVG11/filters.html#LightSourceDefinitions
    - https://svgwrite.readthedocs.io/en/master/classes/filters.html
    - http://www.svgbasics.com/filters2.html
    - https://css-tricks.com/look-svg-light-source-filters/

    :param viewbox: (minx, miny, width, height)
    """
    # TODO work in progress
    # TODO have a look at how threejs is converted to SVG:
    # https://github.com/mrdoob/three.js/blob/master/examples/jsm/renderers/SVGRenderer.js
    dwg = Drawing("ase.svg", profile="full", size=size)

    light_filter = dwg.defs.add(Filter(size=("100%", "100%")))
    diffuse_lighting = light_filter.feDiffuseLighting(size=size,
                                                      surfaceScale=10,
                                                      diffuseConstant=1,
                                                      kernelUnitLength=1,
                                                      color="white")
    diffuse_lighting.fePointLight(source=(size[0], 0, 1000))
    light_filter.feComposite(operator="arithmetic", k1=1)

    root = Group(id="root", filter=light_filter.get_funciri())
    dwg.add(root)
    # if Color(background_color).web != "white":
    # apparently the best way, see: https://stackoverflow.com/a/11293812/5033292
    root.add(
        shapes.Rect(size=size,
                    fill=background_color,
                    fill_opacity=background_opacity))
    for element in elements:
        root.add(element)
    if viewbox:
        dwg.viewbox(*viewbox)
    return dwg
    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)
    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())
示例#5
0
def create_svg_document(elements,
                        size,
                        viewbox=None,
                        background_color="white",
                        background_opacity=1.0):
    """Create the full SVG document.

    :param viewbox: (minx, miny, width, height)
    """
    dwg = Drawing("ase.svg", profile="tiny", size=size)
    root = Group(id="root")
    dwg.add(root)
    # if Color(background_color).web != "white":
    # apparently the best way, see: https://stackoverflow.com/a/11293812/5033292
    root.add(
        shapes.Rect(size=size,
                    fill=background_color,
                    fill_opacity=background_opacity))
    for element in elements:
        root.add(element)
    if viewbox:
        dwg.viewbox(*viewbox)
    return dwg
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()
示例#7
0
	def visualize(self, trajectory, output_file):
		drawing = Drawing()
		
		
		
		# Определение параметров образов состояний аппарата
		machine_view_length, machine_view_width = self.__machine_view_size
		
		coordinates_scaling = machine_view_length / self.__machine_length
		
		machine_diameter = \
			((machine_view_length * 2.0) ** 2.0 + machine_view_width ** 2.0) \
				** 0.5
				
		machine_radius = machine_diameter / 2.0
		
		
		
		# Создание последовательности записываемых состояний аппарата
		def generate_states_sequence():
			spawn_time = 0.0
			
			for trajectory_time, state in trajectory:
				if trajectory_time >= spawn_time:
					spawn_time += self.__time_interval
					
					yield state
					
					
		states_sequence = generate_states_sequence()
		
		
		
		# Запись последовательности состояний аппарата
		is_view_box_initialized                = False
		view_box_minimal_x, view_box_minimal_y = 0.0, 0.0
		view_box_maximal_x, view_box_maximal_y = 0.0, 0.0
		
		
		for state in states_sequence:
			# Создание образа состояния аппарата
			state_view_angle  = - state.coordinates[2] / math.pi * 180.0
			state_view_center = \
				state.coordinates[0] * coordinates_scaling, \
					- state.coordinates[1] * coordinates_scaling
					
			state_view_position = \
				state_view_center[0], \
					state_view_center[1] - machine_view_width / 2.0
					
			state_view = \
				Rect(
					insert       = state_view_position,
					size         = self.__machine_view_size,
					fill         = rgb(255, 255, 255),
					stroke       = rgb(0, 0, 0),
					stroke_width = 1
				)
				
			state_view.rotate(
				state_view_angle,
				center = state_view_center
			)
			
			
			# Добавление образа состояния аппарата к образу траектории
			drawing.add(state_view)
			
			if is_view_box_initialized:
				view_box_minimal_x, view_box_minimal_y = \
					min(state_view_center[0], view_box_minimal_x), \
						min(state_view_center[1], view_box_minimal_y)
						
				view_box_maximal_x, view_box_maximal_y = \
					max(state_view_center[0], view_box_maximal_x), \
						max(state_view_center[1], view_box_maximal_y)
			else:
				is_view_box_initialized = True
				
				view_box_minimal_x, view_box_minimal_y = \
					state_view_center[0], \
						state_view_center[1]
						
				view_box_maximal_x, view_box_maximal_y = \
					state_view_center[0], \
						state_view_center[1]
						
						
						
		# Настройка отображения образа траектории
		drawing.viewbox(
			minx   = view_box_minimal_x - machine_radius,
			miny   = view_box_minimal_y - machine_radius,
			width  = view_box_maximal_x - view_box_minimal_x + machine_diameter,
			height = view_box_maximal_y - view_box_minimal_y + machine_diameter
		)
		
		
		
		# Запись образа траектории в файл
		try:
			drawing.write(output_file)
		except:
			raise Exception() #!!!!! Генерировать хорошие исключения
示例#8
0
def flatten_shape(i, all_paths, merge_paths):
    dwg = Drawing("merge_output%s.svg" % i, profile='tiny')

    def draw_line(start, end, offset=0.0):
        start += offset
        end += offset
        dwg.add(
            dwg.line(start=(start.real, start.imag),
                     end=(end.real, end.imag),
                     stroke_width=4,
                     stroke=rgb(255, 0, 0)))

    dwg.add(
        dwg.path(
            **{
                'd': all_paths[i].d(),
                'fill': "none",
                'stroke-width': 4,
                'stroke': rgb(0, 0, 0)
            }))
    dwg.add(
        dwg.path(
            **{
                'd': merge_paths[i].d(),
                'fill': "none",
                'stroke-width': 4,
                'stroke': rgb(255, 0, 0)
            }))
    bbox = calc_overall_bbox(all_paths[i])
    width, height = abs(bbox[1] - bbox[0]), abs(bbox[3] - bbox[2])
    margin = 40
    lower = min(bbox[2], bbox[3]) + height + margin
    left = min(bbox[0], bbox[1]) + margin

    def draw_marker(loc, col=rgb(255, 0, 0), offset=(left, lower)):
        dwg.add(
            dwg.circle(center=(loc.real + offset[0], loc.imag + offset[1]),
                       r=4,
                       fill=col))

    max_axis = max(width, height)
    num_lines = 10
    points = [merge_paths[i].point(j / num_lines)
              for j in range(num_lines)] + [merge_paths[i].point(1.0)]
    angles = [
        asin((points[j + 1].imag - points[j].imag) /
             abs(points[j + 1] - points[j])) for j in range(num_lines)
    ]

    ends = [max_axis * (sin(angle) + cos(angle) * 1j) for angle in angles]
    intersection_clips = []
    for j, end in enumerate(ends):
        end_point = end + points[j]
        intersections = other_paths[i].intersect(
            Line(start=points[j], end=end_point))

        for intersection in intersections[0]:
            intersection_point = intersection[1].point(intersection[2])
            target = merge_paths[i].length() * (
                1 - j / num_lines) + abs(intersection_point - points[j]) * 1j
            intersection_clips.append(
                PathClip(index=other_paths[i].index(intersection[1]),
                         t=intersection[2],
                         target=target))
            if j % 10 == 0:
                draw_line(points[j], intersection_point)
                draw_marker(intersection_point, rgb(0, 255, 0), (0, 0))
            break

    # make the flexed points by chopping the chunks of the other paths out, then
    # translating and rotating them such that their end points line up with the diff lines
    def transform_side(sides, targets, angle_offset=0):
        def angle(point1, point2):
            diff = point1 - point2
            if diff.real == 0:
                return 90.0
            return atan(diff.imag / diff.real) * 180.0 / pi

        # change this so that it has two targets
        transformed_side = Path(*sides)
        source_angle = angle(transformed_side.end, transformed_side.start) - \
                       angle(targets[0], targets[1])
        transformed_side = transformed_side.rotated(-source_angle +
                                                    angle_offset)
        source = transformed_side.end if angle_offset == 0 else transformed_side.start
        diff = targets[1] - source
        transformed_side = transformed_side.translated(diff)
        draw_marker(targets[0], rgb(0, 200, 200))
        draw_marker(targets[1], rgb(0, 255, 255))
        transformed_diff = abs(transformed_side.start - transformed_side.end)
        targets_diff = abs(targets[0] - targets[1])
        if transformed_diff < targets_diff:
            transformed_side.insert(
                0, Line(start=targets[0], end=transformed_side.start))
        elif transformed_diff > targets_diff:
            # pop elements off until the transformed diff is smaller
            while transformed_diff > targets_diff:
                transformed_side.pop(0)
                transformed_diff = abs(transformed_side.start -
                                       transformed_side.end)
            print("path", transformed_side)
            print("path is longer", transformed_diff - targets_diff)
        return transformed_side

    start_index = 0
    curr_t = 0
    flexed_path = []
    t_resolution = 0.01
    if intersection_clips[0].index > intersection_clips[-1].index or \
        (intersection_clips[0].index == intersection_clips[-1].index and
         intersection_clips[0].t > intersection_clips[-1].t):
        intersection_clips.reverse()
    # add the end of the shape to the intersection clips
    intersection_clips.append(
        PathClip(index=len(other_paths[i]) - 1,
                 t=1.0,
                 target=merge_paths[i].length()))
    last_target = 0
    for clip in intersection_clips:
        sides = []
        print("boundaries", start_index, clip.index, curr_t, clip.t)
        upper_t = clip.t if start_index == clip.index else 1.0
        while start_index <= clip.index and curr_t < upper_t:
            curr_seg = other_paths[i][start_index]
            while curr_t < upper_t:
                max_t = curr_t + t_resolution if curr_t + t_resolution < clip.t else clip.t
                sides.append(
                    Line(start=curr_seg.point(curr_t),
                         end=curr_seg.point(max_t)))
                curr_t += t_resolution
            curr_t = upper_t
            if start_index != clip.index:
                curr_t = 0.0
            if upper_t == 1.0:
                start_index += 1
                upper_t = clip.t if start_index == clip.index else 1.0
        if len(sides) != 0:
            flexed_path.append(
                transform_side(sides, [last_target, clip.target]))
        last_target = clip.target

    straight_path = [Line(start=0, end=merge_paths[i].length())]
    for p in flexed_path:
        p = p.translated(left + lower * 1j)
        dwg.add(
            dwg.path(d=p.d(),
                     fill="none",
                     stroke_width=4,
                     stroke=rgb(255, 0, 0)))

    transformed_path = flexed_path + straight_path
    transformed_path = Path(*transformed_path).translated(left + lower * 1j)
    dwg.add(
        dwg.path(d=transformed_path.d(),
                 fill="none",
                 stroke_width=4,
                 stroke=rgb(0, 0, 0)))
    bbox = calc_overall_bbox(list(all_paths[i]) + list(transformed_path))

    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()
    return flexed_path
示例#9
0
         upper_sizes = [max(bbox[0], bbox[1]), abs(bbox[3] - bbox[2])]
     transform = "scale(1, {})".format(-1 if i == 0 else 1)
     group = dwg.add(dwg.g(transform=transform))
     for path in path_list:
         path = path.translated(-min(bbox[2], bbox[3]) * 1j)
         group.add(
             dwg.path(
                 **{
                     'd': path.d(),
                     'fill': "none",
                     'stroke-width': 4,
                     'stroke': rgb(0, 0, 0)
                 }))
 bbox = calc_overall_bbox(flexed_paths[1])
 dwg.viewbox(
     min(bbox[0], bbox[1]), -upper_sizes[1],
     abs(min(bbox[0], bbox[1]) - max(bbox[0], bbox[1], upper_sizes[0])),
     abs(bbox[3] - bbox[2]) + upper_sizes[1])
 dwg.save()
 # render the shapes selected
 dwg = Drawing("merge_output.svg", profile='tiny')
 for path in all_paths:
     dwg.add(
         dwg.path(
             **{
                 'd': path.d(),
                 'fill': "none",
                 'stroke-width': 4,
                 'stroke': rgb(0, 0, 0)
             }))
 dwg.add(
     dwg.path(
示例#10
0
文件: svg.py 项目: openalea/wlformat
def export_workflow(workflow, store, size=None):
    """Construct a SVG description for a workflow.

    Args:
        workflow (WorkflowDef)
        store (dict of uid, def): elements definitions
        size (int, int): size of drawing in pixels

    Returns:
        (str) - SVG description of workflow
    """
    # check that each node has a position
    for node in workflow['nodes']:
        if 'x' not in node or 'y' not in node:
            raise UserWarning("need to position workflow first")

    if size is None:
        size = (600, 600)

    # draw
    paper = Drawing("workflow.svg", size, id="repr")

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="bg_loaded")
    lg.add_stop_color(0, color='#8c8cff')
    lg.add_stop_color(1, color='#c8c8c8')
    paper.defs.add(lg)

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="bg_failed")
    lg.add_stop_color(0, color='#ff8cff')
    lg.add_stop_color(1, color='#c8c8c8')
    paper.defs.add(lg)

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="in_port")
    lg.add_stop_color(0, color='#3333ff')
    lg.add_stop_color(1, color='#2222ff')
    paper.defs.add(lg)

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="out_port")
    lg.add_stop_color(0, color='#ffff33')
    lg.add_stop_color(1, color='#9a9a00')
    paper.defs.add(lg)

    for i, link in enumerate(workflow['links']):
        draw_link(paper, workflow, store, link, i)

    bbs = []
    for i, node in enumerate(workflow['nodes']):
        bb = draw_node(paper, workflow, store, node, i)
        bbs.append(bb)

    # reformat whole drawing to fit screen
    xmin = min(bb[0] for bb in bbs) - draw_padding
    xmax = max(bb[2] for bb in bbs) + draw_padding
    ymin = min(bb[1] for bb in bbs) - draw_padding
    ymax = max(bb[3] for bb in bbs) + draw_padding

    w = float(size[0])
    h = float(size[1])
    xratio = (xmax - xmin) / w
    yratio = (ymax - ymin) / h
    if xratio > yratio:
        xsize = int(xratio * w)
        ysize = int(xratio * h)
        ymin -= (ysize - (ymax - ymin)) / 2
    else:
        xsize = int(yratio * w)
        ysize = int(yratio * h)
        xmin -= (xsize - (xmax - xmin)) / 2

    paper.viewbox(xmin, ymin, xsize, ysize)

    return paper.tostring(), (xmin, ymin, xsize, ysize)
示例#11
0
 def reset(self):
     self.stack = []
     self.points = []
     dwg = Drawing("canvas.svg", (self.width, self.height))
     dwg.viewbox(0, 0, self.width, self.height)
     self.stack.append(dwg)
示例#12
0
        end_index = \
        [i for i, l in enumerate(lines) if l.find('EMC') >= 0 and i > start_index][0]
        shape = "\n".join(lines[start_index:end_index])
        paths += parse_shape(shape, page_num, gstates)
    # all paths
    paths = sorted(list(set(paths)))
    vals = {'fill': 'none', 'stroke': rgb(0, 0, 0), 'stroke-width': 4}
    output_filename = "all_paths.svg"
    dwg = Drawing(output_filename, profile='tiny')
    overall_bbox = calc_overall_bbox(paths)
    print(overall_bbox)
    for path in paths:
        vals['d'] = path
        dwg.add(dwg.path(**vals))
    dwg.viewbox(overall_bbox[0], overall_bbox[2],
                abs(overall_bbox[1] - overall_bbox[0]),
                abs(overall_bbox[3] - overall_bbox[2]))
    dwg.save()

    # make svgs of all paths
    for i, ds in enumerate(paths):
        output_filename = "path%s.svg" % i
        dwg = Drawing(output_filename, profile='tiny')
        if isinstance(ds, list):
            for d in ds:
                vals['d'] = d,
                dwg.add(dwg.path(**vals))
        else:
            vals['d'] = ds
            shape = parse_path(ds)
            bbox = calc_overall_bbox(shape._segments)
示例#13
0
    def draw_pattern(self):
        self.output_filename = "{}/snake_tiling_m_{}_{}.svg".format(
            self.output_folder, self.dx, self.dy)
        dwg = Drawing(self.output_filename)
        # add background panel
        background_clippath = dwg.rect(insert=(self.pattern_viewbox[0],
                                               self.pattern_viewbox[1]),
                                       size=('100%', '100%'))
        background_panel = dwg.rect(insert=(self.pattern_viewbox[0],
                                            self.pattern_viewbox[1]),
                                    size=('101%', '101%'),
                                    fill='#3072a2')
        clip_path = dwg.defs.add(dwg.clipPath(id="background_panel"))
        clip_path.add(background_clippath)
        clipped_drawing = dwg.add(
            dwg.g(clip_path="url(#background_panel)", id="clippedpath"))
        clipped_drawing.add(background_panel)
        current_color = 0

        def add_pentagon(group, transform, current_color, draw_pent=True):
            pent_group = group.add(
                dwg.g(transform=format_transform(*transform)))
            if draw_pent:
                pent_group.add(
                    dwg.path(
                        **{
                            'd': self.new_pentagon().d(),
                            'fill': self.colors[current_color %
                                                len(self.colors)],
                            'stroke-width': 4,
                            'stroke': rgb(0, 0, 0)
                        }))
            return pent_group

        for y in range(self.num_down):
            transform = "translate({}, {})".format(0, self.rep_spacing * y)
            dgroup = clipped_drawing.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
                    diff = dx + self.column_offset.imag * 1j
                else:
                    diff = int(x / 2) * self.rep_spacing
                for i in range(4):
                    snake_bbox = calc_overall_bbox(self.tile_paths)
                    snake_width, snake_height = abs(snake_bbox[0] - snake_bbox[1]), \
                                                abs(snake_bbox[2] - snake_bbox[3])
                    pent_group = add_pentagon(
                        dgroup,
                        (self.transforms[i][0], self.transforms[i][1] + diff),
                        current_color,
                        draw_pent=False)
                    for i, path in enumerate(self.tile_paths):
                        stransform = 'translate({},{})'.format(
                            snake_width * self.dx, snake_height * self.dy)
                        pent_group.add(
                            dwg.path(
                                **{
                                    'd': path.d(),
                                    'style': self.tile_attributes[i].get(
                                        'style'),
                                    'id': self.tile_attributes[i]['id'],
                                    'transform': stransform
                                }))
                    current_color += 1

        dwg.viewbox(*self.pattern_viewbox)
        dwg.save()
示例#14
0
文件: svg.py 项目: openalea/wlformat
def export_workflow(workflow, store, size=None):
    """Construct a SVG description for a workflow.

    Args:
        workflow (WorkflowDef)
        store (dict of uid, def): elements definitions
        size (int, int): size of drawing in pixels

    Returns:
        (str) - SVG description of workflow
    """
    # check that each node has a position
    for node in workflow['nodes']:
        if 'x' not in node or 'y' not in node:
            raise UserWarning("need to position workflow first")

    if size is None:
        size = (600, 600)

    # draw
    paper = Drawing("workflow.svg", size, id="repr")

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="bg_loaded")
    lg.add_stop_color(0, color='#8c8cff')
    lg.add_stop_color(1, color='#c8c8c8')
    paper.defs.add(lg)

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="bg_failed")
    lg.add_stop_color(0, color='#ff8cff')
    lg.add_stop_color(1, color='#c8c8c8')
    paper.defs.add(lg)

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="in_port")
    lg.add_stop_color(0, color='#3333ff')
    lg.add_stop_color(1, color='#2222ff')
    paper.defs.add(lg)

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="out_port")
    lg.add_stop_color(0, color='#ffff33')
    lg.add_stop_color(1, color='#9a9a00')
    paper.defs.add(lg)

    for i, link in enumerate(workflow['links']):
        draw_link(paper, workflow, store, link, i)

    bbs = []
    for i, node in enumerate(workflow['nodes']):
        bb = draw_node(paper, workflow, store, node, i)
        bbs.append(bb)

    # reformat whole drawing to fit screen
    xmin = min(bb[0] for bb in bbs) - draw_padding
    xmax = max(bb[2] for bb in bbs) + draw_padding
    ymin = min(bb[1] for bb in bbs) - draw_padding
    ymax = max(bb[3] for bb in bbs) + draw_padding

    w = float(size[0])
    h = float(size[1])
    xratio = (xmax - xmin) / w
    yratio = (ymax - ymin) / h
    if xratio > yratio:
        xsize = int(xratio * w)
        ysize = int(xratio * h)
        ymin -= (ysize - (ymax - ymin)) / 2
    else:
        xsize = int(yratio * w)
        ysize = int(yratio * h)
        xmin -= (xsize - (xmax - xmin)) / 2

    paper.viewbox(xmin, ymin, xsize, ysize)

    return paper.tostring(), (xmin, ymin, xsize, ysize)
示例#15
0
文件: svg.py 项目: openalea/wlformat
def export_node(node, store, size=None):
    """Construct a SVG description for a workflow node.

    Args:
        node (NodeDef)
        store (dict of uid, def): elements definitions
        size (int, int): size of drawing in pixels

    Returns:
        (str) - SVG description of workflow node
    """
    pfs = port_font_size

    # node size
    pr = port_radius
    pspace = pr * 9
    nw = compute_node_width(node, node['name'], pspace)
    nh = label_font_size + 2 * pr + 2 * pfs + 2 + (2 * node_padding)

    # draw
    if size is None:
        size = (600, 600)

    paper = Drawing("workflow_node.svg", size, id="repr")

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="in_port")
    lg.add_stop_color(0, color='#3333ff')
    lg.add_stop_color(1, color='#2222ff')
    paper.defs.add(lg)

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="out_port")
    lg.add_stop_color(0, color='#ffff33')
    lg.add_stop_color(1, color='#9a9a00')
    paper.defs.add(lg)

    # body
    g = paper.add(paper.g())

    # background
    lg = paper.linearGradient((0.5, 0), (0.5, 1.))
    lg.add_stop_color(0, color='#8c8cff')
    lg.add_stop_color(1, color='#c8c8c8')
    paper.defs.add(lg)

    bg = paper.rect((-nw / 2, -nh / 2), (nw, nh),
                    rx=node_padding, ry=node_padding,
                    stroke_width=1)
    bg.stroke('#808080')
    bg.fill(lg)
    g.add(bg)

    # label
    style = ('font-size: %dpx; font-family: %s; '
             'text-anchor: middle' % (label_font_size, label_font))
    frag = paper.tspan(node['name'], dy=[label_font_size // 3])
    label = paper.text("", style=style, fill='#000000')
    label.add(frag)
    g.add(label)

    # ports
    port_style = ('font-size: %dpx; ' % pfs +
                  'font-family: %s; ' % label_font)
    onstyle = port_style + 'text-anchor: end'
    instyle = port_style + 'text-anchor: start'
    istyle = port_style + 'text-anchor: middle'
    nb = len(node['inputs'])
    py = -nh / 2
    for i, pdef in enumerate(node['inputs']):
        px = i * pspace - pspace * (nb - 1) / 2
        pg = g.add(paper.g())
        pg.translate(px, py)
        idef = store.get(pdef['interface'], None)
        if idef is not None and 'url' in idef:
            link = pg.add(paper.a(href=idef['url'], target='_top'))
        else:
            link = pg

        port = paper.circle((0, 0), pr, stroke='#000000', stroke_width=1)
        port.fill("url(#in_port)")
        link.add(port)
        # port name
        frag = paper.tspan(pdef['name'], dy=[-2 * pr])
        label = paper.text("", style=instyle, fill='#000000')
        label.rotate(-45)
        label.add(frag)
        pg.add(label)
        # port interface
        if idef is None:
            itxt = pdef['interface']
        else:
            itxt = idef['name']
        if len(itxt) > 10:
            itxt = itxt[:7] + "..."
        frag = paper.tspan(itxt, dy=[pr + pfs])
        label = paper.text("", style=istyle, fill='#000000')
        label.add(frag)
        link.add(label)

    nb = len(node['outputs'])
    py = nh / 2
    for i, pdef in enumerate(node['outputs']):
        px = i * pspace - pspace * (nb - 1) / 2
        pg = g.add(paper.g())
        pg.translate(px, py)
        idef = store.get(pdef['interface'], None)
        if idef is not None and 'url' in idef:
            link = pg.add(paper.a(href=idef['url'], target='_top'))
        else:
            link = pg

        port = paper.circle((0, 0), pr, stroke='#000000', stroke_width=1)
        port.fill("url(#out_port)")
        link.add(port)
        # port name
        frag = paper.tspan(pdef['name'], dy=[2 * pr + pfs // 2])
        label = paper.text("", style=onstyle, fill='#000000')
        label.rotate(-45)
        label.add(frag)
        pg.add(label)
        # port interface
        if idef is None:
            itxt = pdef['interface']
        else:
            itxt = idef['name']
        if len(itxt) > 10:
            itxt = itxt[:7] + "..."
        frag = paper.tspan(itxt, dy=[- pr - 2])
        label = paper.text("", style=istyle, fill='#000000')
        label.add(frag)
        link.add(label)

    # reformat whole drawing to fit screen
    xmin = - nw / 2 - draw_padding / 10.
    xmax = + nw / 2 + draw_padding / 10.
    if len(node['inputs']) == 0:
        inames_extend = 0
    else:
        inames = [(len(pdef['name']), pdef['name']) for pdef in node['inputs']]
        inames_extend = string_size(sorted(inames)[-1][1], pfs) * 0.7 + pfs
    ymin = - nh / 2 - pr - inames_extend - draw_padding / 10.
    if len(node['outputs']) == 0:
        onames_extend = 0
    else:
        onames = [(len(pdef['name']), pdef['name']) for pdef in node['outputs']]
        onames_extend = string_size(sorted(onames)[-1][1], pfs) * 0.7 + pfs
    ymax = + nh / 2 + pr + onames_extend + draw_padding / 10.

    w = float(size[0])
    h = float(size[1])
    ratio = max((xmax - xmin) / w, (ymax - ymin) / h)
    xsize = ratio * w
    ysize = ratio * h

    bb = (xmin * xsize / (xmax - xmin),
          ymin * ysize / (ymax - ymin),
          xsize,
          ysize)

    paper.viewbox(*bb)
    return paper.tostring(), bb
示例#16
0
文件: svg.py 项目: openalea/wlformat
def export_node(node, store, size=None):
    """Construct a SVG description for a workflow node.

    Args:
        node (NodeDef)
        store (dict of uid, def): elements definitions
        size (int, int): size of drawing in pixels

    Returns:
        (str) - SVG description of workflow node
    """
    pfs = port_font_size

    # node size
    pr = port_radius
    pspace = pr * 9
    nw = compute_node_width(node, node['name'], pspace)
    nh = label_font_size + 2 * pr + 2 * pfs + 2 + (2 * node_padding)

    # draw
    if size is None:
        size = (600, 600)

    paper = Drawing("workflow_node.svg", size, id="repr")

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="in_port")
    lg.add_stop_color(0, color='#3333ff')
    lg.add_stop_color(1, color='#2222ff')
    paper.defs.add(lg)

    lg = paper.linearGradient((0.5, 0), (0.5, 1.), id="out_port")
    lg.add_stop_color(0, color='#ffff33')
    lg.add_stop_color(1, color='#9a9a00')
    paper.defs.add(lg)

    # body
    g = paper.add(paper.g())

    # background
    lg = paper.linearGradient((0.5, 0), (0.5, 1.))
    lg.add_stop_color(0, color='#8c8cff')
    lg.add_stop_color(1, color='#c8c8c8')
    paper.defs.add(lg)

    bg = paper.rect((-nw / 2, -nh / 2), (nw, nh),
                    rx=node_padding,
                    ry=node_padding,
                    stroke_width=1)
    bg.stroke('#808080')
    bg.fill(lg)
    g.add(bg)

    # label
    style = ('font-size: %dpx; font-family: %s; '
             'text-anchor: middle' % (label_font_size, label_font))
    frag = paper.tspan(node['name'], dy=[label_font_size // 3])
    label = paper.text("", style=style, fill='#000000')
    label.add(frag)
    g.add(label)

    # ports
    port_style = ('font-size: %dpx; ' % pfs + 'font-family: %s; ' % label_font)
    onstyle = port_style + 'text-anchor: end'
    instyle = port_style + 'text-anchor: start'
    istyle = port_style + 'text-anchor: middle'
    nb = len(node['inputs'])
    py = -nh / 2
    for i, pdef in enumerate(node['inputs']):
        px = i * pspace - pspace * (nb - 1) / 2
        pg = g.add(paper.g())
        pg.translate(px, py)
        idef = store.get(pdef['interface'], None)
        if idef is not None and 'url' in idef:
            link = pg.add(paper.a(href=idef['url'], target='_top'))
        else:
            link = pg

        port = paper.circle((0, 0), pr, stroke='#000000', stroke_width=1)
        port.fill("url(#in_port)")
        link.add(port)
        # port name
        frag = paper.tspan(pdef['name'], dy=[-2 * pr])
        label = paper.text("", style=instyle, fill='#000000')
        label.rotate(-45)
        label.add(frag)
        pg.add(label)
        # port interface
        if idef is None:
            itxt = pdef['interface']
        else:
            itxt = idef['name']
        if len(itxt) > 10:
            itxt = itxt[:7] + "..."
        frag = paper.tspan(itxt, dy=[pr + pfs])
        label = paper.text("", style=istyle, fill='#000000')
        label.add(frag)
        link.add(label)

    nb = len(node['outputs'])
    py = nh / 2
    for i, pdef in enumerate(node['outputs']):
        px = i * pspace - pspace * (nb - 1) / 2
        pg = g.add(paper.g())
        pg.translate(px, py)
        idef = store.get(pdef['interface'], None)
        if idef is not None and 'url' in idef:
            link = pg.add(paper.a(href=idef['url'], target='_top'))
        else:
            link = pg

        port = paper.circle((0, 0), pr, stroke='#000000', stroke_width=1)
        port.fill("url(#out_port)")
        link.add(port)
        # port name
        frag = paper.tspan(pdef['name'], dy=[2 * pr + pfs // 2])
        label = paper.text("", style=onstyle, fill='#000000')
        label.rotate(-45)
        label.add(frag)
        pg.add(label)
        # port interface
        if idef is None:
            itxt = pdef['interface']
        else:
            itxt = idef['name']
        if len(itxt) > 10:
            itxt = itxt[:7] + "..."
        frag = paper.tspan(itxt, dy=[-pr - 2])
        label = paper.text("", style=istyle, fill='#000000')
        label.add(frag)
        link.add(label)

    # reformat whole drawing to fit screen
    xmin = -nw / 2 - draw_padding / 10.
    xmax = +nw / 2 + draw_padding / 10.
    if len(node['inputs']) == 0:
        inames_extend = 0
    else:
        inames = [(len(pdef['name']), pdef['name']) for pdef in node['inputs']]
        inames_extend = string_size(sorted(inames)[-1][1], pfs) * 0.7 + pfs
    ymin = -nh / 2 - pr - inames_extend - draw_padding / 10.
    if len(node['outputs']) == 0:
        onames_extend = 0
    else:
        onames = [(len(pdef['name']), pdef['name'])
                  for pdef in node['outputs']]
        onames_extend = string_size(sorted(onames)[-1][1], pfs) * 0.7 + pfs
    ymax = +nh / 2 + pr + onames_extend + draw_padding / 10.

    w = float(size[0])
    h = float(size[1])
    ratio = max((xmax - xmin) / w, (ymax - ymin) / h)
    xsize = ratio * w
    ysize = ratio * h

    bb = (xmin * xsize / (xmax - xmin), ymin * ysize / (ymax - ymin), xsize,
          ysize)

    paper.viewbox(*bb)
    return paper.tostring(), bb
示例#17
0
class DrawTemplateSVG(object):
    def __init__(self,
                 tmax,
                 grid,
                 darea=DrawArea,
                 symbols=SymbolAssets,
                 m3d=Matrix3D):
        self._off = (2.2, 2.5)
        size = 100
        self._size = (size, size * 1.9)

        self._matrix3d = m3d(tmax[0], self._size, self._off, grid)
        self._area = darea(self._off, self._size, tmax[0], tmax[1],
                           grid).area()
        self.dwg = Drawing('graph.svg', size=self._area, id="graph")

        viewp = self.fixOneLineRoot(grid)
        self.dwg.viewbox(*viewp)

        self._symbols = symbols(self.dwg)

        self.setup()

    # When you have only one or two items, we need  to fix the grid area
    def fixOneLineRoot(self, grid):
        key_min = min(grid.keys())
        rootSize = len(grid[key_min])
        size = len(grid)

        area = [0, 0, *self._area]

        if key_min <= 1 and rootSize <= 2:
            ajy = self._size[0] * 1.8
            ajx = self._size[0] * 0.5

            area[1] = 0 - ajx
            area[3] = self._area[1] + ajy

            if size <= 1:
                area[0] = 0 - ajx

        return area

    def setup(self):
        self.setup_brightness()
        self.setup_marker()

    def setup_brightness(self):
        self._symbols.brightness()
        self._symbols.brightness("darker", 0.4)

    def setup_marker(self):
        s = self._size[0] / 8

        opts = {'insert': (152, 3), 'size': (s, s)}

        self._symbols.asset_marker('markers.arrow', opts)

    def boundary_box(self, pos, node):
        opts = {'id': node.get('_id')}

        symbol = self._symbols.asset('boundaries_box.front',
                                     'default boundaries', (pos[0], pos[1]),
                                     self._size, opts)
        self.add(symbol)

    def draw_label(self, pos, node):
        text = HelperDrawLabel(self._size, self._matrix3d) \
            .label_by_node(pos, node)

        symbol = self._symbols.text(*text)
        self.add(symbol)

    def draw_app(self, item):
        cad1 = [item[x] for x in range(2)]
        node = item[3]

        pos = self._matrix3d.rotateNodeXY(item)()

        self.draw_root(item)
        self.draw_grid_size(cad1, item[2])
        self.grid_box(pos)
        self.draw_execute(pos, node)
        self.boundary_box(pos, node)
        self.draw_label(pos, node)
        self.draw_tooltips(node)

    def draw_execute(self, pos, node):
        hDrawApp = HelperDrawApplication(self._size)
        hDrawApp.execute(pos, node)

        pSymb = hDrawApp.get_apps()

        for symb in pSymb:
            symbol = self._symbols.asset(*symb)
            self.add(symbol)

    def draw_tooltips(self, node):
        _id = "tool-" + node.get('_id')
        g = self._symbols.create_group(_id)

        hDrawTooltips = HelperDrawTooltips(self._size, self._off)
        hDrawTooltips.execute(node)

        ltxt = hDrawTooltips.get_text()

        symbol = self._symbols.multiline(ltxt, (0, 0))
        g.add(symbol)

    def grid_box(self, pos, opts={'fill-opacity': '0.4'}):
        symbol = self._symbols.asset('grid.base', 'default', pos, self._size,
                                     opts)
        self.add(symbol)

    def draw_grid_size(self, cad1, size):
        cad2 = (cad1[0], cad1[1] + size - 1)

        points = HelperDrawBasePolyline(self._size, self._matrix3d) \
            .create_polyline_by_pos(cad1, cad2)

        symbol = self._symbols.polyline(points, {
            'fill': '#ccc',
            'fill-opacity': 0.2
        })
        self.add(symbol)

    def draw_root(self, item):
        root = item[3].get('root')
        if root:
            nitem = (item[0] - 1, item[1], item[2], item[3])
            pos = self._matrix3d.rotateNodeXY(nitem)()

            symbol = self._symbols.asset('grid.entry', 'default', pos,
                                         self._size)

            self.draw_connect(nitem, item)
            self.add(symbol)

    def add(self, symbol):
        self.dwg.add(symbol)

    def save(self):
        return self.dwg.tostring()

    def draw_connect(self, node1, node2, details=None):
        id = "%s-%s" % (node1[0], node2[0])
        g = self.dwg.g(id=id)

        d = HelperDrawConnector(self._size, self._off,
                                self._matrix3d).connect(node1, node2)

        symbol = self._symbols.conn(d)
        g.add(symbol)

        cls = " conn-%s" % node1[3].get('_id')
        symbol = self._symbols.conn_holder(d, cls)
        g.add(symbol)

        symbol = self._symbols.text(details, (0, 0), {'display': 'none'})
        g.add(symbol)

        self.add(g)