def drawcurve(counter, pos, window): if counter == 1: pygame.draw.circle(window, (0, 255, 0), pos[0], 5) if counter == 2: line = shapely.geometry.LineString([pos[0], pos[1]]) pygame.draw.line(window, (255, 0, 0), pos[0], pos[1]) if counter == 3: pygame.draw.line(window, (255, 0, 0), pos[0], pos[1]) pygame.draw.circle(window, (0, 255, 0), pos[2], 5) if counter == 0: pygame.draw.line(window, (255, 0, 0), pos[0], pos[1]) pygame.draw.line(window, (255, 0, 0), pos[2], pos[3]) rect_lol, kosmos1, kosmos2 = LLuk(pos).get_pygame_arc() pygame.draw.arc(window, (255, 255, 0), rect_lol, kosmos1, kosmos2) lines.append(Line(srumpy(pos[0]), srumpy(pos[1]))) lines.append(Line(srumpy(pos[2]), srumpy(pos[3]))) print(kosmos2 - kosmos1) if (is_right_to(kosmos1, kosmos2)): lines.append( Arc(srumpy(pos[1]), srumpy((intergreat_len, intergreat_len)), 0, False, False, srumpy(pos[2]))) else: lines.append( Arc(srumpy(pos[1]), srumpy((intergreat_len, intergreat_len)), 0, False, True, srumpy(pos[2]))) srodes.append(srumpy(pos[0])) stroke_widths.append(2) srodes.append(srumpy(pos[3])) stroke_widths.append(2) return "kcc" return ""
def get_svg_arc(self): if (self.is_right_to(self.azimuth1, self.azimuth2)): return Arc(srumpy(self.arc_start), srumpy((self.arc_radius, self.arc_radius)), 0, False, False, srumpy(self.arc_end)) else: return Arc(srumpy(self.arc_start), srumpy((self.arc_radius, self.arc_radius)), 0, False, True, srumpy(self.arc_end))
def flip_path(upside_down_path): path = [] _, _, min_y, max_y = upside_down_path.bbox() offset = max_y + min_y for segment in upside_down_path._segments: if type(segment) is Line: path.append( Line(complex(segment.start.real, -segment.start.imag + offset), complex(segment.end.real, -segment.end.imag + offset))) elif type(segment) is Arc: path.append( Arc(complex(segment.start.real, -segment.start.imag + offset), segment.radius, abs(180 - segment.rotation), segment.large_arc, not segment.sweep, complex(segment.end.real, -segment.end.imag + offset))) elif type(segment) is QuadraticBezier: path.append( QuadraticBezier( complex(segment.start.real, -segment.start.imag + offset), complex(segment.control.real, -segment.control.imag + offset), complex(segment.end.real, -segment.end.imag + offset))) else: raise ValueError(f"Unknown type: {type(segment)}") return Path(*path)
def transform_seg(seg): if isinstance(seg, (Line, QuadraticBezier, CubicBezier)): return seg.__class__( *[transformed_points[point] for point in seg.bpoints()]) elif isinstance(seg, Arc): new_start = transformed_points[seg.start] new_end = transformed_points[seg.end] new_raidus = transformed_radii[seg.radius] new_rotation = seg.rotation + random.uniform( -rotation_amplitude, rotation_amplitude) return Arc(new_start, new_raidus, new_rotation, seg.large_arc, seg.sweep, new_end, seg.autoscale_radius)
def add_circle(input_file, output_file): """ Adds a circle around the base icon. This will have the effect to invert the mask. """ paths, attributes, svg_attributes = svg2paths2(input_file) if len(paths) > 1: raise NotImplementedError("Can't handle more than one path for now") path = paths[0] # Scale path down new_path = scale_path_to_bbox(path, (6, 6, 42, 42)) # Add circle new_path.append(Arc(24 + 2j, 22 + 22j, 180, 0, 1, 24 + 46j)) new_path.append(Arc(24 + 46j, 22 + 22j, 180, 0, 1, 24 + 2j)) wsvg( [new_path], attributes=attributes, svg_attributes=svg_attributes, filename=output_file, )
def __init__(self, obliquity=23.4443291, radius_capricorn=100, plate_parameters=None): self.obliquity = obliquity self._obliquityRadians = math.radians(obliquity) self._obliquityRadiansArgument = math.radians( (90 - self.obliquity) / 2) self.RadiusCapricorn = radius_capricorn self.plate_parameters = self.climata self.plate_altitudes = list(range(0, 90, 10)) self.plate_azimuths = list(range(10, 90, 10)) self.tropic_arcs() self.plates(plate_parameters=plate_parameters) # Parameters for layout of graduated limb. self.short_tick_angles = list(range(0, 361, 1)) self.long_tick_angles = list(range(0, 375, 15)) self.short_tick = 5 self.long_tick = 15 self.ticks = { "inner_radius": self.RadiusCapricorn, "center_radius": self.RadiusCapricorn + self.short_tick, "outer_radius": self.RadiusCapricorn + self.long_tick, "short_tick_angles": self.short_tick_angles, "long_tick_angles": self.long_tick_angles, } # Ecliptic self.RadiusEcliptic = (self.RadiusCapricorn + self.RadiusCancer) / 2.0 self.yEclipticCenter = (self.RadiusCapricorn - self.RadiusCancer) / 2.0 self.xEclipticCenter = 0.0 self.ecliptic_pole = self.RadiusEquator * math.tan( self._obliquityRadiansArgument / 2.0) self.ecliptic_center = self.RadiusEquator * math.tan( self._obliquityRadiansArgument) self.ecliptic = { "cx": self.xEclipticCenter, "cy": self.yEclipticCenter, "r": self.RadiusEcliptic, "width": 5, } self.ecliptic_path = Path( Arc( start=complex(0, self.ecliptic["cy"] + self.ecliptic["r"]), radius=(complex(self.ecliptic["r"], self.ecliptic["r"])), rotation=0.0, large_arc=True, sweep=False, end=complex(0, self.ecliptic["cy"] - self.ecliptic["r"]), ), Arc( start=complex(0, self.ecliptic["cy"] - self.ecliptic["r"]), radius=(complex(self.ecliptic["r"], self.ecliptic["r"])), rotation=0.0, large_arc=True, sweep=False, end=complex(0, self.ecliptic["cy"] + self.ecliptic["r"]), ), )
def main(): plate_parameters = {"Hawaiian Islands": 21.3069} astrolabe = Astrolabe(plate_parameters=plate_parameters) plate = astrolabe.plates["Hawaiian Islands"] background_color = "#a3262a;" stroke_color = "#f5ac27;" background_color = "grey;" stroke_color = "#f5ac27;" graph_color = "navy;" background_color = "white;" graph_color = "white;" # Morrison Blue stroke_color = "#f5ac27;" graph_color = "#596581;" background_color = "#051633" # In order to place parts of the figure in Inkscape layers, need the attributes below. # This will cause errors, of course, in other renderers unless the inkscape namespace # (xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape") is included. # Use Inkscape extensions to svg to place different parts of astrolabe into their own layer. inkscape_attributes = { identifier: 'inkscape:label="{}" inkscape:groupmode="layer"'.format(identifier) for identifier in identifiers } animation_parameters = { "from": "0", "to": "175", "begin": "0s", "dur": "3s" } ecliptic = { "cx": astrolabe.xEclipticCenter, "cy": astrolabe.yEclipticCenter, "r": astrolabe.RadiusEcliptic, "width": 5, } # ecliptic_center = astrolabe.RadiusEquator * math.tan( # astrolabe._obliquityRadiansArgument # ) outer_radius = ecliptic["r"] inner_radius = outer_radius - ecliptic["width"] top_middle_outer = { "x": (ecliptic["cx"]), "y": (ecliptic["cy"] + outer_radius) } bottom_middle_outer = { "x": (ecliptic["cx"]), "y": (ecliptic["cy"] - outer_radius) } top_middle_inner = { "x": (ecliptic["cx"]), "y": (ecliptic["cy"] + inner_radius) } bottom_middle_inner = { "x": (ecliptic["cx"]), "y": (ecliptic["cy"] - inner_radius) } aries_first_point = astrolabe.ecliptic_division(180) aries_first_point_angle = math.degrees( math.atan2(aries_first_point["y2"], aries_first_point["x2"])) ecliptic_divisions = [] for angle in list(range(0, 361, 30)): ecliptic_divisions.append(astrolabe.ecliptic_division(angle)) ecliptic_divisions_fine = [] for angle in list(range(0, 361, 10)): ecliptic_divisions_fine.append(astrolabe.ecliptic_division(angle)) ecliptic_divisions_extra_fine = [] for angle in list(range(0, 361, 2)): ecliptic_divisions_extra_fine.append( astrolabe.ecliptic_division(angle)) seasonal_arcs = [] month_names = [ "jan", "feb", "mar", "apr", "may", "june", "july", "aug", "sept", "oct", "nov", "dec", ] seasonal_names = [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12" ] seasonal_names = [ "pisces", "aquarius", "capricorn", "sagittarius", "scorpio", "libra", "virgo", "leo", "cancer", "gemini", "taurus", "aries", ] # seasonal_names = [ # "雨水", # "大寒", # "冬至", # "小雪", # "霜降", # "秋分", # "处暑", # "大暑", # "夏至", # "小满", # "谷雨", # "春分", # ] angle = 0 for n, division in enumerate(ecliptic_divisions[0:12]): tag = "season" + str(angle) angle += 30 next_division = ecliptic_divisions[(n + 1) % 12] sarc = Path( Arc( start=complex(division["x2"], division["y2"]), radius=complex(ecliptic["r"], ecliptic["r"]), rotation=0.0, large_arc=True, sweep=False, end=complex(next_division["x2"], next_division["y2"]), )) seasonal_arcs.append({ "tag": tag, "name": seasonal_names[n], "r": ecliptic["r"], "start_x": division["x2"], "start_y": division["y2"], "end_x": next_division["x2"], "end_y": next_division["y2"], "reversed": sarc.reversed().d(), }) stars = [ { "name": "aldebaran", "r": 0.7467, "theta": 68.98 }, { "name": "altair", "r": 0.8561, "theta": 297.69542 }, { "name": "arcturus", "r": 0.7109, "theta": 213.91500 }, { "name": "capella", "r": 0.4040, "theta": 79.17208 }, { "name": "sirius", "r": 1.3099, "theta": 101.28708 }, { "name": "procyon", "r": 0.9127, "theta": 114.82542 }, { "name": "deneb", "r": 0.4114, "theta": 310.35750 }, { "name": "castor", "r": 0.5556, "theta": 113.64958 }, { "name": "regulus", "r": 0.8103, "theta": 152.09250 }, { "name": "vega", "r": 0.4793, "theta": 279.23417 }, { "name": "betelgeuse", "r": 0.8784, "theta": 88.79292 }, { "name": "rigel", "r": 1.1463, "theta": 78.63417 }, { "name": "bellatrix", "r": 0.8949, "theta": 81.28250 }, { "name": "antares", "r": 1.5870, "theta": 247.35167 }, { "name": "spica", "r": 1.2096, "theta": 201.29792 }, ] for star in stars: star["cx"] = (astrolabe.RadiusEquator * star["r"] * math.cos(math.radians(star["theta"]))) star["cy"] = (astrolabe.RadiusEquator * star["r"] * math.sin(math.radians(star["theta"]))) print(astrolabe.obliquity) with open("calendrical_tools/astrolabe_template.svg.j2") as fp: template_text = fp.read() template = Template(template_text) svg = template.render( place_name=plate["location"], latitude=plate["latitude"], RCapricorn=astrolabe.RadiusCapricorn, REquator=astrolabe.RadiusEquator, RCancer=astrolabe.RadiusCancer, horiz=plate["horizon"], almucantar_coords=plate["almucantars"], almucantar_center=plate["almucantar_center"], azimuth_coords=plate["azimuths"], prime_vertical=plate["prime_vertical"], ticks=astrolabe.ticks, ecliptic=ecliptic, ecliptic_divisions=ecliptic_divisions, ecliptic_divisions_fine=ecliptic_divisions_fine, ecliptic_divisions_extra_fine=ecliptic_divisions_extra_fine, aries_first_point=aries_first_point, aries_first_point_angle=astrolabe.obliquity, top_middle_outer=top_middle_outer, bottom_middle_outer=bottom_middle_outer, outer_radius=outer_radius, inner_radius=inner_radius, top_middle_inner=top_middle_inner, bottom_middle_inner=bottom_middle_inner, # ecliptic_center=ecliptic_center, ecliptic_pole=astrolabe.ecliptic_pole, seasonal_arcs=seasonal_arcs, stars=stars, stroke_color=stroke_color, background_color=background_color, graph_color=graph_color, inkscape=inkscape_attributes, animation=animation_parameters, moons=[ (44.142706092611434, 214.41520455448494), (-64.29833725607341, 244.05007530120906), (19.338217263234128, 274.11533327404277), (17.224801417675735, 304.36003467896535), (-64.16194195841945, 334.4763799297398), (-25.561893428663097, 4.203505420431007), ], suns=[ 214.41713740391424, 244.05065884583018, 274.1147430450437, 304.35973321930214, 334.47736243435793, 4.204523538166541, ], ) with open("astrolabe_generated.svg", "w") as fp: fp.write(svg) import jinja2 # Seems like overkill, but adds "include_file" function to jinja2 # environment in order to include raw svg into an html template. @jinja2.contextfunction def include_file(ctx, name): env = ctx.environment return jinja2.Markup(env.loader.get_source(env, name)[0]) loader = jinja2.PackageLoader(__name__, ".") env = jinja2.Environment(loader=loader) env.globals["include_file"] = include_file
def parse_path(pathdef, current_pos=0j, tree_element=None): # In the SVG specs, initial movetos are absolute, even if # specified as 'm'. This is the default behavior here as well. # But if you pass in a current_pos variable, the initial moveto # will be relative to that current_pos. This is useful. elements = list(_tokenize_path(pathdef)) # Reverse for easy use of .pop() elements.reverse() if tree_element is None: segments = Path() else: segments = Path(tree_element=tree_element) start_pos = None command = None while elements: if elements[-1] in COMMANDS: # New command. last_command = command # Used by S and T command = elements.pop() absolute = command in UPPERCASE command = command.upper() else: # If this element starts with numbers, it is an implicit command # and we don't change the command. Check that it's allowed: if command is None: raise ValueError( "Unallowed implicit command in %s, position %s" % (pathdef, len(pathdef.split()) - len(elements))) if command == 'M': # Moveto command. x = elements.pop() y = elements.pop() pos = float(x) + float(y) * 1j if absolute: current_pos = pos else: current_pos += pos # when M is called, reset start_pos # This behavior of Z is defined in svg spec: # http://www.w3.org/TR/SVG/paths.html#PathDataClosePathCommand start_pos = current_pos # Implicit moveto commands are treated as lineto commands. # So we set command to lineto here, in case there are # further implicit commands after this moveto. command = 'L' elif command == 'Z': # Close path if not (current_pos == start_pos): segments.append(Line(current_pos, start_pos)) segments.closed = True current_pos = start_pos command = None elif command == 'L': x = elements.pop() y = elements.pop() pos = float(x) + float(y) * 1j if not absolute: pos += current_pos segments.append(Line(current_pos, pos)) current_pos = pos elif command == 'H': x = elements.pop() pos = float(x) + current_pos.imag * 1j if not absolute: pos += current_pos.real segments.append(Line(current_pos, pos)) current_pos = pos elif command == 'V': y = elements.pop() pos = current_pos.real + float(y) * 1j if not absolute: pos += current_pos.imag * 1j segments.append(Line(current_pos, pos)) current_pos = pos elif command == 'C': control1 = float(elements.pop()) + float(elements.pop()) * 1j control2 = float(elements.pop()) + float(elements.pop()) * 1j end = float(elements.pop()) + float(elements.pop()) * 1j if not absolute: control1 += current_pos control2 += current_pos end += current_pos segments.append(CubicBezier(current_pos, control1, control2, end)) current_pos = end elif command == 'S': # Smooth curve. First control point is the "reflection" of # the second control point in the previous path. if last_command not in 'CS': # If there is no previous command or if the previous command # was not an C, c, S or s, assume the first control point is # coincident with the current point. control1 = current_pos else: # The first control point is assumed to be the reflection of # the second control point on the previous command relative # to the current point. control1 = current_pos + current_pos - segments[-1].control2 control2 = float(elements.pop()) + float(elements.pop()) * 1j end = float(elements.pop()) + float(elements.pop()) * 1j if not absolute: control2 += current_pos end += current_pos segments.append(CubicBezier(current_pos, control1, control2, end)) current_pos = end elif command == 'Q': control = float(elements.pop()) + float(elements.pop()) * 1j end = float(elements.pop()) + float(elements.pop()) * 1j if not absolute: control += current_pos end += current_pos segments.append(QuadraticBezier(current_pos, control, end)) current_pos = end elif command == 'T': # Smooth curve. Control point is the "reflection" of # the second control point in the previous path. if last_command not in 'QT': # If there is no previous command or if the previous command # was not an Q, q, T or t, assume the first control point is # coincident with the current point. control = current_pos else: # The control point is assumed to be the reflection of # the control point on the previous command relative # to the current point. control = current_pos + current_pos - segments[-1].control end = float(elements.pop()) + float(elements.pop()) * 1j if not absolute: end += current_pos segments.append(QuadraticBezier(current_pos, control, end)) current_pos = end elif command == 'A': radius = float(elements.pop()) + float(elements.pop()) * 1j rotation = float(elements.pop()) arc = float(elements.pop()) sweep = float(elements.pop()) end = float(elements.pop()) + float(elements.pop()) * 1j if not absolute: end += current_pos segments.append(Arc(current_pos, radius, rotation, arc, sweep, end)) current_pos = end return segments
def renderLabel(self, inString): dwg = svgwrite.Drawing() # SVG drawing in memory strIdx = 0 # Used to iterate over inString xOffset = 100 # Cumulative character placement offset yOffset = 0 # Cumulative character placement offset charSizeX = 8 # Character size constant charSizeY = 8 # Character size constant baseline = 170 # Y value of text baseline glyphBounds = [ ] # List of boundingBox objects to track rendered character size finalSegments = [] # List of output paths escaped = False # Track whether the current character was preceded by a '\' lineover = False # Track whether the current character needs to be lined over lineoverList = [] # If we can't find the typeface that the user requested, we have to quit try: face = Face( os.path.dirname(os.path.abspath(__file__)) + '/typeface/' + self.fontName + '.ttf') face.set_char_size(charSizeX, charSizeY, 200, 200) except Exception as e: print(e) print("WARN: No Typeface found with the name " + self.fontName + ".ttf") sys.exit(0) # quit Python # If the typeface that the user requested exists, but there's no position table for it, we'll continue with a warning try: table = __import__( 'KiBuzzard.KiBuzzard.buzzard.typeface.' + self.fontName, globals(), locals(), ['glyphPos']) glyphPos = table.glyphPos spaceDistance = table.spaceDistance except: glyphPos = 0 spaceDistance = 60 print( "WARN: No Position Table found for this typeface. Composition will be haphazard at best." ) # If there's lineover text, drop the text down to make room for the line dropBaseline = False a = False x = 0 while x < len(inString): if x > 0 and inString[x] == '\\': a = True if x != len(inString) - 1: x += 1 if inString[x] == '!' and not a: dropBaseline = True a = False x += 1 if dropBaseline: baseline = 190 # Draw and compose the glyph portion of the tag for charIdx in range(len(inString)): # Check whether this character is a space if inString[charIdx] == ' ': glyphBounds.append(boundingBox(0, 0, 0, 0)) xOffset += spaceDistance continue # Check whether this character is a backslash that isn't escaped # and isn't the first character (denoting a backslash-shaped tag) if inString[charIdx] == '\\' and charIdx > 0 and not escaped: glyphBounds.append(boundingBox(0, 0, 0, 0)) escaped = True continue # If this is a non-escaped '!' mark the beginning of lineover if inString[charIdx] == '!' and not escaped: glyphBounds.append(boundingBox(0, 0, 0, 0)) lineover = True # If we've hit the end of the string but not the end of the lineover # go ahead and finish it out if charIdx == len(inString) - 1 and len(lineoverList) > 0: linePaths = [] linePaths.append( Line(start=complex(lineoverList[0], 10), end=complex(xOffset, 10))) linePaths.append( Line(start=complex(xOffset, 10), end=complex(xOffset, 30))) linePaths.append( Line(start=complex(xOffset, 30), end=complex(lineoverList[0], 30))) linePaths.append( Line(start=complex(lineoverList[0], 30), end=complex(lineoverList[0], 10))) linepath = Path(*linePaths) linepath = elPath(linepath.d()) finalSegments.append(linepath) lineover = False lineoverList.clear() continue # All special cases end in 'continue' so if we've gotten here we can clear our flags if escaped: escaped = False face.load_char( inString[charIdx]) # Load character curves from font outline = face.glyph.outline # Save character curves to var y = [t[1] for t in outline.points] # flip the points outline_points = [(p[0], max(y) - p[1]) for p in outline.points] start, end = 0, 0 paths = [] box = 0 yOffset = 0 for i in range(len(outline.contours)): end = outline.contours[i] points = outline_points[start:end + 1] points.append(points[0]) tags = outline.tags[start:end + 1] tags.append(tags[0]) segments = [ [ points[0], ], ] box = boundingBox(points[0][0], points[0][1], points[0][0], points[0][1]) for j in range(1, len(points)): if not tags[j]: # if this point is off-path if tags[j - 1]: # and the last point was on-path segments[-1].append( points[j]) # toss this point onto the segment elif not tags[j - 1]: # and the last point was off-path # get center point of two newPoint = ((points[j][0] + points[j - 1][0]) / 2.0, (points[j][1] + points[j - 1][1]) / 2.0) segments[-1].append( newPoint ) # toss this new point onto the segment segments.append( [ newPoint, points[j], ] ) # and start a new segment with the new point and this one elif tags[j]: # if this point is on-path segments[-1].append( points[j]) # toss this point onto the segment if j < (len(points) - 1): segments.append( [ points[j], ] ) # and start a new segment with this point if we're not at the end for segment in segments: if len(segment) == 2: paths.append( Line(start=tuple_to_imag(segment[0]), end=tuple_to_imag(segment[1]))) elif len(segment) == 3: paths.append( QuadraticBezier(start=tuple_to_imag(segment[0]), control=tuple_to_imag(segment[1]), end=tuple_to_imag(segment[2]))) start = end + 1 # Derive bounding box of character for segment in paths: i = 0 while i < 10: point = segment.point(0.1 * i) if point.real > box.xMax: box.xMax = point.real if point.imag > box.yMax: box.yMax = point.imag if point.real < box.xMin: box.xMin = point.real if point.imag < box.yMin: box.yMin = point.imag i += 1 glyphBounds.append(box) path = Path(*paths) if glyphPos != 0: try: xOffset += glyphPos[inString[charIdx]].real yOffset = glyphPos[inString[charIdx]].imag except: pass if lineover and len(lineoverList) == 0: lineoverList.append(xOffset) lineover = False if (lineover and len(lineoverList) > 0): linePaths = [] linePaths.append( Line(start=complex(lineoverList[0], 10), end=complex(xOffset, 10))) linePaths.append( Line(start=complex(xOffset, 10), end=complex(xOffset, 30))) linePaths.append( Line(start=complex(xOffset, 30), end=complex(lineoverList[0], 30))) linePaths.append( Line(start=complex(lineoverList[0], 30), end=complex(lineoverList[0], 10))) linepath = Path(*linePaths) linepath = elPath(linepath.d()) finalSegments.append(linepath) lineover = False lineoverList.clear() pathTransform = Matrix.translate(xOffset, baseline + yOffset - box.yMax) path = elPath(path.d()) * pathTransform path = elPath(path.d()) finalSegments.append(path) xOffset += 30 if glyphPos != 0: try: xOffset -= glyphPos[inString[charIdx]].real except: pass xOffset += (glyphBounds[charIdx].xMax - glyphBounds[charIdx].xMin) strIdx += 1 if self.leftCap == '' and self.rightCap == '': for i in range(len(finalSegments)): svgObj = dwg.add(dwg.path(finalSegments[i].d())) svgObj['fill'] = "#000000" else: #draw the outline of the label as a filled shape and #subtract each latter from it tagPaths = [] if self.rightCap == 'round': tagPaths.append( Line(start=complex(100, 0), end=complex(xOffset, 0))) tagPaths.append( Arc(start=complex(xOffset, 0), radius=complex(100, 100), rotation=180, large_arc=1, sweep=1, end=complex(xOffset, 200))) elif self.rightCap == 'square': tagPaths.append( Line(start=complex(100, 0), end=complex(xOffset, 0))) tagPaths.append( Line(start=complex(xOffset, 0), end=complex(xOffset + 50, 0))) tagPaths.append( Line(start=complex(xOffset + 50, 0), end=complex(xOffset + 50, 200))) tagPaths.append( Line(start=complex(xOffset + 50, 200), end=complex(xOffset, 200))) elif self.rightCap == 'pointer': tagPaths.append( Line(start=complex(100, 0), end=complex(xOffset, 0))) tagPaths.append( Line(start=complex(xOffset, 0), end=complex(xOffset + 50, 0))) tagPaths.append( Line(start=complex(xOffset + 50, 0), end=complex(xOffset + 100, 100))) tagPaths.append( Line(start=complex(xOffset + 100, 100), end=complex(xOffset + 50, 200))) tagPaths.append( Line(start=complex(xOffset + 50, 200), end=complex(xOffset, 200))) elif self.rightCap == 'flagtail': tagPaths.append( Line(start=complex(100, 0), end=complex(xOffset, 0))) tagPaths.append( Line(start=complex(xOffset, 0), end=complex(xOffset + 100, 0))) tagPaths.append( Line(start=complex(xOffset + 100, 0), end=complex(xOffset + 50, 100))) tagPaths.append( Line(start=complex(xOffset + 50, 100), end=complex(xOffset + 100, 200))) tagPaths.append( Line(start=complex(xOffset + 100, 200), end=complex(xOffset, 200))) elif self.rightCap == 'fslash': tagPaths.append( Line(start=complex(100, 0), end=complex(xOffset, 0))) tagPaths.append( Line(start=complex(xOffset, 0), end=complex(xOffset + 50, 0))) tagPaths.append( Line(start=complex(xOffset + 50, 0), end=complex(xOffset, 200))) elif self.rightCap == 'bslash': tagPaths.append( Line(start=complex(100, 0), end=complex(xOffset, 0))) tagPaths.append( Line(start=complex(xOffset, 0), end=complex(xOffset + 50, 200))) tagPaths.append( Line(start=complex(xOffset + 50, 200), end=complex(xOffset, 200))) elif self.rightCap == '' and self.leftCap != '': tagPaths.append( Line(start=complex(100, 0), end=complex(xOffset, 0))) tagPaths.append( Line(start=complex(xOffset, 0), end=complex(xOffset, 200))) if self.leftCap == 'round': tagPaths.append( Line(start=complex(xOffset, 200), end=complex(100, 200))) tagPaths.append( Arc(start=complex(100, 200), radius=complex(100, 100), rotation=180, large_arc=0, sweep=1, end=complex(100, 0))) elif self.leftCap == 'square': tagPaths.append( Line(start=complex(xOffset, 200), end=complex(100, 200))) tagPaths.append( Line(start=complex(100, 200), end=complex(50, 200))) tagPaths.append( Line(start=complex(50, 200), end=complex(50, 0))) tagPaths.append(Line(start=complex(50, 0), end=complex(100, 0))) elif self.leftCap == 'pointer': tagPaths.append( Line(start=complex(xOffset, 200), end=complex(100, 200))) tagPaths.append( Line(start=complex(100, 200), end=complex(50, 200))) tagPaths.append( Line(start=complex(50, 200), end=complex(0, 100))) tagPaths.append(Line(start=complex(0, 100), end=complex(50, 0))) tagPaths.append(Line(start=complex(50, 0), end=complex(100, 0))) elif self.leftCap == 'flagtail': tagPaths.append( Line(start=complex(xOffset, 200), end=complex(100, 200))) tagPaths.append( Line(start=complex(100, 200), end=complex(0, 200))) tagPaths.append( Line(start=complex(0, 200), end=complex(50, 100))) tagPaths.append(Line(start=complex(50, 100), end=complex(0, 0))) tagPaths.append(Line(start=complex(0, 0), end=complex(100, 0))) elif self.leftCap == 'fslash': tagPaths.append( Line(start=complex(xOffset, 200), end=complex(100, 200))) tagPaths.append( Line(start=complex(100, 200), end=complex(50, 200))) tagPaths.append( Line(start=complex(50, 200), end=complex(100, 0))) elif self.leftCap == 'bslash': tagPaths.append( Line(start=complex(xOffset, 200), end=complex(100, 200))) tagPaths.append( Line(start=complex(100, 200), end=complex(50, 0))) tagPaths.append(Line(start=complex(50, 0), end=complex(100, 0))) elif self.leftCap == '' and self.rightCap != '': tagPaths.append( Line(start=complex(xOffset, 200), end=complex(100, 200))) tagPaths.append( Line(start=complex(100, 200), end=complex(100, 0))) path = Path(*tagPaths) for i in range(len(finalSegments)): path = elPath(path.d() + " " + finalSegments[i].reverse()) tagObj = dwg.add(dwg.path(path.d())) tagObj['fill'] = "#000000" dwg['width'] = xOffset + 100 dwg['height'] = 250 #dwg.saveas('out.svg') print('create svg') return dwg