def deal_path(path_group, svg_width, svg_height): for element in path_group: d = element["d"] path = parse_path(d) print(parse_path(d)) print(path[0])
def __init__(self,name,forward_text_path,reverse_text_path,length): self.name = name+'.png' self.forward_text_path = forward_text_path self.reverse_text_path = reverse_text_path self.length = length forward_parsed_path = parse_path(forward_text_path) reverse_parsed_path = parse_path(reverse_text_path) self.forward_line_x, self.forward_line_y = zip(*[(p.real,p.imag) for p in (forward_parsed_path.point(i/self.length) for i in range(0,self.length+1))]) self.reverse_line_x, self.reverse_line_y = zip(*[(p.real,p.imag) for p in (reverse_parsed_path.point(i/self.length) for i in range(0,self.length+1))]) self.track_image = Image.open(self.name).convert('P') self.x_lim = self.track_image.size[0] self.y_lim = self.track_image.size[1]
def get_path(id): if (id == 1): # set of points for "8" svgpath = "m 185.34925,203.60654 q 0,30.14579 -23.58557,50.13885 -23.42937,19.99306 -59.04201,19.99306 -37.799387,0 -60.291583,-19.52447 -22.336,-19.52448 -22.336,-49.98266 0,-19.36828 11.246098,-34.98786 11.246098,-15.77578 31.707748,-24.99133 v -0.93717 Q 44.304437,133.31842 35.24508,121.44754 26.341919,109.57666 26.341919,91.770341 q 0,-26.240896 21.555021,-43.734826 21.555021,-17.49393 54.82473,-17.49393 34.83166,0 55.6057,16.712951 20.77405,16.712951 20.77405,42.485259 0,15.775775 -9.84034,31.082965 -9.84034,15.15099 -28.89622,23.74176 v 0.93718 q 21.86741,9.37175 33.4259,23.11698 11.55849,13.74523 11.55849,34.98786 z M 148.33084,90.052187 q 0,-16.712951 -12.96425,-26.553287 -12.80806,-9.996532 -32.80112,-9.996532 -19.68067,0 -32.33253,9.371749 -12.495664,9.371748 -12.495664,25.30372 0,11.246098 6.247832,19.524473 6.404028,8.12218 19.212084,14.52621 5.779245,2.81153 16.556755,7.34121 10.933703,4.52967 21.242633,7.49739 15.46338,-10.30892 21.39882,-21.39882 5.93544,-11.0899 5.93544,-25.616113 z m 4.84207,116.522073 q 0,-14.37002 -6.40403,-22.96079 -6.24783,-8.74696 -24.67893,-17.49393 -7.34121,-3.4363 -16.08817,-6.40402 -8.746966,-2.96772 -23.273175,-8.27838 -14.057623,7.65359 -22.648392,20.77404 -8.434574,13.12045 -8.434574,29.6772 0,21.08644 14.52621,34.83167 14.52621,13.74523 36.862211,13.74523 22.80459,0 36.39362,-11.71469 13.74523,-11.71468 13.74523,-32.17633 z" elif (id == 2): # set of points for "6" svgpath = """m 192.89809,187.54732 q 0,36.11694 -23.86582,59.02813 -23.70671,22.75208 -58.2326,22.75208 -17.501599,0 -31.821091,-5.40958 Q 64.659087,258.50836 53.68081,247.8483 39.99774,234.64254 32.519783,212.84509 q -7.318851,-21.79745 -7.318851,-52.5048 0,-31.50288 6.682429,-55.84602 6.841535,-24.343135 21.638344,-43.276685 14.00128,-17.978917 36.11694,-28.002562 22.115655,-10.182749 51.550175,-10.182749 9.38722,0 15.75144,0.795527 6.36422,0.795527 12.88754,2.863898 v 30.389144 h -1.59106 q -4.45495,-2.386582 -13.52396,-4.454953 -8.90991,-2.227477 -18.29713,-2.227477 -34.20767,0 -54.573173,21.479238 -20.365499,21.320133 -23.706714,57.755279 13.364859,-8.11437 26.252402,-12.25112 13.046648,-4.29584 30.070935,-4.29584 15.11502,0 26.57061,2.86389 11.6147,2.7048 23.70671,11.13739 14.00129,9.70543 21.00193,24.50224 7.15974,14.79681 7.15974,35.95783 z m -32.29841,1.27285 q 0,-14.79681 -4.45495,-24.50224 -4.29585,-9.70544 -14.31949,-16.86518 -7.31885,-5.09138 -16.22876,-6.68243 -8.90991,-1.59106 -18.61534,-1.59106 -13.523964,0 -25.138663,3.18211 -11.614699,3.18211 -23.865819,9.86454 -0.318211,3.50032 -0.477317,6.84154 -0.159105,3.18211 -0.159105,8.11437 0,25.13867 5.091375,39.77637 5.25048,14.4786 14.319491,22.91119 7.318852,7.00064 15.751441,10.34185 8.591697,3.18211 18.615337,3.18211 23.0703,0 36.27605,-14.00128 13.20575,-14.16038 13.20575,-40.57189 z""" elif (id == 3): # set of points for "9" svgpath = "m 194.00949,132.78458 q 0,32.35895 -7.46745,58.74395 -7.3015,26.38499 -22.23641,44.97064 -15.10084,18.91755 -37.83508,29.20603 -22.73424,10.28849 -53.433761,10.28849 -8.629055,0 -16.262449,-0.99566 -7.633394,-0.82971 -13.607355,-2.82103 v -31.69519 h 1.659433 q 4.812358,2.48916 13.607355,4.81236 8.794998,2.15727 19.581316,2.15727 36.673481,0 57.416401,-21.90453 20.90886,-22.07046 24.22773,-60.73526 -15.43273,9.29282 -29.04009,13.27546 -13.60735,3.98264 -29.70386,3.98264 -15.266786,0 -27.712538,-2.98698 -12.279808,-2.98698 -24.72556,-11.61603 -14.603015,-10.12255 -22.070466,-25.72122 -7.301508,-15.59868 -7.301508,-37.33726 0,-37.83508 24.891504,-61.56498 24.891503,-23.7299 60.735268,-23.7299 17.92188,0 33.18867,5.642074 15.26679,5.476131 26.71688,16.594336 14.10519,13.773298 21.73858,35.511877 7.63339,21.572637 7.63339,55.922913 z m -33.52055,-7.13557 q 0,-25.721216 -5.31019,-41.319892 -5.31019,-15.598675 -14.60302,-24.227729 -7.79933,-7.467451 -16.76027,-10.620375 -8.96095,-3.318867 -19.41538,-3.318867 -23.89584,0 -37.835082,14.934902 -13.773299,14.934902 -13.773299,41.983671 0,15.76462 4.480471,25.72122 4.48047,9.9566 15.100845,17.42405 7.467451,5.14424 16.428392,6.96962 8.960941,1.65943 19.913203,1.65943 12.94358,0 26.21905,-3.48481 13.27547,-3.48481 24.8915,-10.12254 0.16595,-3.48481 0.33189,-6.80368 0.33189,-3.48481 0.33189,-8.795 z" elif (id == 4): # set of points for "&" svgpath = "m 109.99677,74.649937 q 0,-12.730557 -7.63833,-19.966873 -7.50433,-7.370322 -19.296846,-7.370322 -12.328539,0 -20.100879,8.308363 -7.77234,8.174357 -7.77234,20.100879 0,10.050439 5.226229,17.822779 5.360234,7.772337 22.915002,18.358807 13.132574,-4.69021 19.832864,-13.668602 6.8343,-9.112398 6.8343,-23.585031 z M 135.99391,192.03907 71.939108,129.59234 q -4.154182,2.01009 -8.308364,5.36023 -4.154181,3.21614 -8.308363,8.84439 -3.752164,5.22623 -6.16427,12.59655 -2.412105,7.37032 -2.412105,16.61673 0,19.56485 11.390498,31.62538 11.524504,11.92652 32.563424,11.92652 12.462542,0 24.657082,-6.03026 12.32854,-6.16427 20.6369,-18.49281 z m 40.33576,-79.59948 v 12.86456 q 0,12.86456 -3.35014,28.94527 -3.35015,16.0807 -11.3905,30.68734 l 50.65421,49.31416 H 179.2778 L 148.59046,204.2336 q -15.41067,19.02884 -31.49138,26.66717 -16.0807,7.50433 -33.099445,7.50433 -27.873219,0 -46.366027,-16.21471 -18.358803,-16.34872 -18.358803,-42.74787 0,-12.32854 3.484152,-21.30693 3.484153,-8.9784 8.174358,-15.54468 4.690205,-6.29828 11.658509,-11.79252 6.968305,-5.62824 14.070616,-9.78243 -14.740645,-9.64842 -21.306932,-19.43085 -6.432281,-9.782423 -6.432281,-24.657074 0,-8.978392 3.484152,-17.018744 3.618158,-8.174357 10.720469,-14.87465 6.700293,-6.432281 17.420762,-10.452457 10.854474,-4.020176 23.853043,-4.020176 23.183017,0 37.521637,11.792516 14.33863,11.65851 14.33863,29.615295 0,5.896257 -1.60807,13.400586 -1.60807,7.370322 -5.49424,13.26658 -4.28819,6.566284 -12.19453,12.596554 -7.90635,6.03026 -20.5029,10.31845 l 49.71617,48.51012 q 1.87609,-5.36024 2.81413,-11.79252 0.93804,-6.43228 1.07204,-13.40058 0.26802,-7.50433 0.13401,-16.75074 0,-9.2464 0,-15.67868 z" path = parse_path(svgpath) # svg.path point method returns a complex number p, p.real and p.imag can pull the x, and y # # on 0.0 to 1.0 along path, represent percent of distance along path n = 1000 # number of line segments to draw # pts = [] # for i in range(0,n+1): # f = i/n # will go from 0.0 to 1.0 # complex_point = path.point(f) # path.point(t) returns point at 0.0 <= f <= 1.0 # pts.append((complex_point.real, complex_point.imag)) # list comprehension version or loop above pts = [((p.real - 100) / 200, (300 - p.imag) / 200) for p in (path.point(i / n) for i in range(0, n + 1))] return pts
def get_path_info(elem): """ Gets the attributes from a path element. :param elem: The element. :return: The path attributes. """ return parse_path(elem.getAttribute('d'))
def drawSVG(svgPaths): for x in range(len(svgPaths)): print(svgPaths[x]) path = parse_path(svgPaths[0]) # svg.path point method returns a complex number p, p.real and p.imag can pull the x, and y # # on 0.0 to 1.0 along path, represent percent of distance along path n = 999 # number of line segments to draw # pts = [] # for i in range(0,n+1): # f = i/n # will go from 0.0 to 1.0 # complex_point = path.point(f) # path.point(t) returns point at 0.0 <= f <= 1.0 # pts.append((complex_point.real, complex_point.imag)) # list comprehension version or loop above pts = [(p.real, p.imag) for p in (path.point(i / n) for i in range(0, n + 1))] pygame.init() # init pygame infoObject = pygame.display.Info() surface = pygame.display.set_mode( (infoObject.current_w, infoObject.current_h)) # get surface to draw on surface.fill(pygame.Color('white')) # set background to white pygame.draw.aalines(surface, pygame.Color('black'), False, pts) # False is no closing pygame.display.update() # copy surface to display while True: # loop to wait till window close for event in pygame.event.get(): if event.type == pygame.QUIT: exit()
def test(numberOfFiles): k = 0 while (k < numberOfFiles): linesOnlySegment = [] linesOnlySegmentsArray = [] f = open("onlyCurves" + str(k) + ".txt", "r") pathToFormString = f.readline() f.close() k = k + 1 currentPathObject = parse_path(pathToFormString) stringTestObject = str(currentPathObject[0]) if "Move" in stringTestObject: print("success") for l in range(len(currentPathObject) - 1): # print(currentPathObject[l]) linesOnlySegment.append(breakIntoLines(currentPathObject[l + 1])) linesOnlySegmentsArray.append(linesOnlySegment) print(linesOnlySegment) return 777
def parsePathObject(numberOfFiles): k = 0 while (k < numberOfFiles): linesOnlySegment = [] f = open("onlyCurves" + str(k) + ".txt", "r") pathToFormString = f.readline() f.close() currentPathObject = parse_path(pathToFormString) #I'm assuming that the first command I will always see is the Move command(I need to make this more robust/dynamic) for l in range(len(currentPathObject) - 1): # print(currentPathObject[l]) linesOnlySegment.append(breakIntoLines(currentPathObject[l + 1])) linesOnlySegmentsArray.append(linesOnlySegment) #seeing what each part of my array holds so that I can use that information to extract points # print(linesOnlySegmentsArray) # print(linesOnlySegmentsArray[0]) # if (k == 1): # print(linesOnlySegmentsArray[1][0]) # print(len(linesOnlySegment)) f = open("onlyLines" + str(k) + ".txt", "w") f.write(str(linesOnlySegment)) f.close() k = k + 1
def load_image(filename, n_div=4): root = ET.parse("{}.svg".format(filename)).getroot() viewbox = tuple(map(float, root.attrib["viewBox"].split())) all_lines = [] for line in root.findall("xmlns:line", SNS): x1 = float(line.attrib["x1"]) y1 = float(line.attrib["y1"]) x2 = float(line.attrib["x2"]) y2 = float(line.attrib["y2"]) sw = float(line.attrib["stroke-width"] if "stroke-width" in line.attrib else 1) x1, y1 = normalize(x1, y1, viewbox) x2, y2 = normalize(x2, y2, viewbox) all_lines.append((x1, y1, x2, y2, sw)) for polyline in root.findall("xmlns:polyline", SNS): points = [ normalize(*map(float, pt.split(',')), viewbox) for pt in polyline.attrib["points"].split() ] x1, y1 = points[0] sw = float(polyline.attrib["stroke-width"] if "stroke-width" in polyline.attrib else 1) for x2, y2 in points[1:]: all_lines.append((x1, y1, x2, y2, sw)) x1, y1 = x2, y2 for polygon in root.findall("xmlns:polygon", SNS): points = [ normalize(*map(float, pt.split(',')), viewbox) for pt in polygon.attrib["points"].split() ] points.append(points[0]) x1, y1 = points[0] sw = float(polygon.attrib["stroke-width"] if "stroke-width" in polygon.attrib else 1) for x2, y2 in points[1:]: all_lines.append((x1, y1, x2, y2, sw)) x1, y1 = x2, y2 for path in root.findall("xmlns:path", SNS): path_spec = parse_path(path.attrib["d"]) sw = float(path.attrib["stroke-width"] if "stroke-width" in path.attrib else 1) for segment in path_spec: if type(segment) is Line: x1, y1 = normalize(segment.start.real, segment.start.imag, viewbox) x2, y2 = normalize(segment.end.real, segment.end.imag, viewbox) all_lines.append((x1, y1, x2, y2, sw)) elif type(segment) is CubicBezier: points = [] for i in range(n_div + 1): t = i / n_div c = segment.point(t) x, y = normalize(c.real, c.imag, viewbox) points.append((x, y)) x1, y1 = points[0] for x2, y2 in points[1:]: all_lines.append((x1, y1, x2, y2, sw)) x1, y1 = x2, y2 return all_lines
def svg_path_to_polygons(path_data): """Return a list of polygons that collectively approximate the SVG path whose string is `path_data`. This handles just enough cases to parse the map files. Examples: >>> svg_path_to_polygons('m 10 20 30 40') [[(10.0, 20.0), (40.0, 60.0)]] >>> svg_path_to_polygons('m 10 20 30 40 z') [[(10.0, 20.0), (40.0, 60.0), (10.0, 20.0)]] >>> svg_path_to_polygons('m 10 20 30 40 z m 100 200 10 20') [[(10.0, 20.0), (40.0, 60.0), (10.0, 20.0)], [(110.0, 220.0), (120.0, 240.0)]] """ # `svg.path` treats the Move command as though it were Line. # Split the path data, in order to collect one Path per contour. path_strings = [s for s in path_data.split('m') if s] path_prefix = 'm' polygons = [] for path_string in path_strings: if path_string[0] not in 'M': path_string = path_prefix + path_string path = parse_path(path_string) polygons.append(path_to_points(path)) end_pt = path[-1].end path_prefix = 'M %f,%f m' % (end_pt.real, end_pt.imag) return polygons
def read_svg(self,content, **kwargs): """appends svg content to drawing :param content: string, either filename or svg content """ #from http://stackoverflow.com/questions/15857818/python-svg-parser from xml.dom import minidom try: doc = minidom.parse(content) # parseString also exists except IOError: doc = minidom.parseString(content.encode('utf-8')) trans=Trans() trans.f=-1 #flip y axis for path in doc.getElementsByTagName('path'): #find the color... dirty, but simply understandable color=path.getAttribute('fill') #assign filling color to default stroke color alpha=1 style=path.getAttribute('style') for s in style.split(';'): item=s.split(':') if item[0]=='opacity': alpha=float(item[1]) elif item[0]=='stroke': color=item[1] if not color or alpha==0 : #ignore picture frame continue # process the path d=path.getAttribute('d') from svg.path import parse_path e=Entity.from_svg(parse_path(d),color) e=trans*e self.append(e) doc.unlink() return self
def wo_wlines(all_path): line = [] for i in range(len(all_path)): clr = all_path[i].getAttribute('stroke') if clr == '#000': d = all_path[i].getAttribute('d') P = parse_path(d) points = [] if len(P) < 1: pass else: for j in range(len(P)): if isinstance(P[j], CubicBezier) or isinstance(P[j], Line): strt = P[j].start.real, P[j].start.imag ed = P[j].end.real, P[j].end.imag if j == 0: points.append(strt) points.append(ed) else: points.append(ed) else: print("What?! th is " + P[j]) points = rdp(points, epsilon=0.5) line.append(points) else: pass return line
def ReadSVG(filename): soup = bs4.BeautifulSoup(open(filename)) # Select the maximum length curve all_paths = soup.findAll('path') maxlength = len(str(all_paths[0])) maxidx = 0 for i in range(1, len(all_paths)): if maxlength < len(str(all_paths[i])): maxlength = len(str(all_paths[i])) maxidx = i maxpath = all_paths[maxidx] path_d = maxpath['d'] path1 = parse_path(path_d) X = np.empty((100, 3)) ctr = 0 for i in np.linspace(0, 1, 100): X[ctr, 0] = path1.point(i).real X[ctr, 1] = path1.point(i).imag X[ctr, 2] = 0.0 ctr += 1 attributes = [] isMultilevelUCF = False return X, attributes, isMultilevelUCF
def getXYCordsFromSVG(self, svgString): #path = os.path.join( os.path.dirname(__file__), "..", "calibration", "bull.svg") #svg_string = open(path,"r",encoding="utf8").read() dom = minidom.parseString(svgString) svgPaths = [ path.getAttribute('d') for path in dom.getElementsByTagName('path') ] points = [] for svgPath in svgPaths: data = parse_path(svgPath) for seg in data: if isinstance(seg, Arc) or isinstance( seg, QuadraticBezier) or isinstance(seg, CubicBezier): # everything except a straight line points.extend(self.pathToPoints(seg, 1, 10)) elif isinstance(seg, Line): # straight line so just calculate 1 poinet start and end points.extend(self.pathToPoints(seg, 1, 1)) else: # straight line move so just calculate 1 poinet start and end with pen up points.extend(self.pathToPoints(seg, 0, 1)) #xyCords = None # if formatAsString: # xyCords = '\n'.join(map(lambda x: "{},{},{}".format( # str(x[0]), str(x[1]), str(x[2])), points)) # else: # xyCords = points return points
def paintEvent_byVideo(self, result, da): filepath1 = "./src/demour/scripts1/img/{}.svg".format(result) # 1.读取xml文件 doc = minidom.parse(filepath1) # 2.查找path标签 paths = doc.getElementsByTagName('path') svgTag = doc.getElementsByTagName('svg') self.w = svgTag[0].getAttribute('width') self.h = svgTag[0].getAttribute('height') #print(self.w, self.h) pathsList = [] for path in paths: pathsList.append(path.getAttribute('d')) # 解析路径字符串 for path in pathsList: result = parse_path(path) # path 序列 可以通过for循环获取所有的元素 for ele in result: #print(type(ele).__name__) if type(ele).__name__ == 'Move': self.drawMove(ele, da) elif type(ele).__name__ == 'Line': self.drawLine(ele, da) elif type(ele).__name__ == 'CubicBezier': self.drawCubicBezier(ele, da) elif type(ele).__name__ == 'QuadraticBezier': self.drawQuadraticBezier(ele, da) elif type(ele).__name__ == 'Close': self.drawClose(ele, da) else: print('其他')
def read_svg(self, content, **kwargs): """appends svg content to drawing :param content: string, either filename or svg content """ #from http://stackoverflow.com/questions/15857818/python-svg-parser from xml.dom import minidom try: doc = minidom.parse(content) # parseString also exists except IOError: doc = minidom.parseString(content.encode('utf-8')) trans = Trans() trans.f = -1 #flip y axis for path in doc.getElementsByTagName('path'): #find the color... dirty, but simply understandable color = path.getAttribute( 'fill') #assign filling color to default stroke color alpha = 1 style = path.getAttribute('style') for s in style.split(';'): item = s.split(':') if item[0] == 'opacity': alpha = float(item[1]) elif item[0] == 'stroke': color = item[1] if not color or alpha == 0: #ignore picture frame continue # process the path d = path.getAttribute('d') from svg.path import parse_path e = Entity.from_svg(parse_path(d), color) e = trans * e self.append(e) doc.unlink() return self
def main(): # These are the svg 'd strings'. You can make your own by using whatever vector art tool you want svg_string = 'M273.47 457.43C358.61 457.43 414.39 409.24 440.79 312.87C329.9 382.84 274.13 382.84 273.47 312.87C272.81 242.9 216.7 242.9 105.15 312.87C132.21 409.24 188.32 457.43 273.47 457.43Z' hey_svg = 'M12.08 246.47C17.03 271.23 320.99 254.39 357.62 246.47C394.26 238.55 396.24 144.49 328.91 193.01C261.58 241.52 237.82 300.93 283.37 291.23C313.73 284.76 320.66 230.9 304.16 129.64C302.84 171.89 291.29 193.01 269.5 193.01C247.72 193.01 239.47 171.89 244.75 129.64C242.77 171.23 228.25 192.35 201.19 193.01C160.59 194 157.62 129.64 185.35 129.64C213.07 129.64 209.11 190.04 185.35 191.03C161.58 192.02 150.69 194.99 129.9 191.03C109.11 187.07 130.89 113.8 92.28 113.8C66.53 113.8 53 140.2 51.68 193.01C45.74 74.2 45.74 14.79 51.68 14.79C60.59 14.79 71.49 59.34 71.49 107.86C71.49 140.2 54.32 168.59 20 193.01C11.42 212.15 8.78 229.97 12.08 246.47Z' pi_svg = 'M 10.499686,177.03840 L 31.174931,178.56990 C 52.615925,154.32116 61.039171,82.595924 187.38789,96.634671 C 182.79339,403.95560 48.021426,436.37234 56.444675,499.41907 C 59.507674,535.15406 87.840417,557.10556 118.47041,558.38181 C 215.21014,555.06356 210.87089,424.63084 240.99038,95.868921 L 365.80760,95.868921 C 359.17110,211.75239 341.04836,327.63586 339.00636,441.22208 C 340.53786,516.77606 386.48285,557.10556 446.97708,557.61606 C 546.52456,560.93431 577.92030,444.79558 577.92030,395.27709 L 556.47931,395.27710 C 554.43731,436.11709 534.78306,465.47083 492.92207,467.25758 C 378.82535,468.78908 441.61683,266.63113 442.38258,97.400421 L 577.92030,98.166171 L 577.15455,11.636437 C 13.807491,8.9075799 85.312284,-2.1366151 10.499686,177.03840 z' path = parse_path(svg_string) # put the svg of your choice in this field window_width = 600 window_height = 600 frames_per_loop = 200 # higher means slower animation frames_per_second = 30 # higher means faster assuming your computer can take it depth = 100 # number of vectors, use lower if your computer needs but less accurate samples = 200 # how acurate the shape reading is, higher numbers is better but # takes longer to set up window = graphics(window_width, window_height, 'main') factors = generate_facts(path, depth, samples) #generates initail positions of vectors vectors = make_vector_list( factors) # makes the vectors from the given initials frame = 1 while True: # loops the animation if frame > frames_per_loop: frame = 0 frame += 1 window.clear() print_svg(window, path, frames_per_loop - 1) print_vectors(window, vectors.val, vectors.next, frame / frames_per_loop) window.update_frame(frames_per_second)
def initialize(svg_filename='Blank_US_Map.svg'): """Initialize the `states` global variable.""" with open(svg_filename, 'r') as svg: soup = BeautifulSoup(svg.read(), selfClosingTags=['defs']) paths = soup.findAll('path') global states states = {} for p in paths: state_name = p.get('id', None) path_string = p.get('d', None) if not state_name or not path_string: continue # `svg.path` treats the Move command as though it were Line. # Split the path data, in order to collect one Path per contour. path_strings = [s for s in path_string.split('m') if s] polygons = [] path_prefix = 'm' for path_string in path_strings: if path_string[0] not in 'M': path_string = path_prefix + path_string path = parse_path(path_string) polygons.append(path_to_points(path)) end_pt = path[-1].end end_pt = path[0].start path_prefix = 'M %f,%f m' % (end_pt.real, end_pt.imag) states[state_name] = polygons states = OrderedDict(sorted(states.items()))
def __init__(self, selected_element, extra_output_log): # The id is just an internal name for the element. Used currently for console output. self.id = selected_element.attrib['id'] # The path is the geometric boundary of an electrode. self.path = parse_path(selected_element.attrib['d']) # All Patches share a common overall scaling, while each has a translation transformation also associated with # its relative position in the trap. The combination of both is represented by the Patch's transform attribute. self.transform = get_matrix(parent_map[selected_element]) # Boolean flag indicating that the Patch has been matched with an electrode identity. self.matched = False # Extract the style element and grab the stroke information with a regular expression search. style = selected_element.attrib['style'] stroke_regex = r'stroke\s*:\s*#(?P<color>\w+)\s*;' stroke_match = re.search(stroke_regex, style) # The patch elements are either black ('000000') or blue ('0000ff') which indicates the height # of the electrode in the trap. Grab this information from the stroke info and set the height of the patch. self.color = stroke_match.group('color') # TODO: Figure out why the z value is set to -4.5. The svg is to scale, but I don't know what the scaling is. self.z = -4.5 if self.color == '0000ff' else 0.0 if PRINT_EXTRA_OUTPUT: print('Creating patch for', self.id) if LOG_EXTRA_OUTPUT: extra_output_log.write('Creating patch for ' + self.id + '\n')
def from_svg(self, svg_path): path = parse_path(svg_path) start = self.coords.complex_translate(path[0].start) end = self.coords.complex_translate(path[len(path) - 1].end) cb = None cbset = [] if isinstance(path[0], Move): path = [path[i] for i in range(1, len(path))] if isinstance(path[0], CubicBezier): # TODO: needs to account for multiple bezier in path points = [path[0].start, path[0].control1, path[0].control2, path[0].end] if not Curve.is_linear(points): cb = [self.coords.complex_translate(p) for p in points] if len(path) > 1: # set of curves/points for r in range(0, len(path)): cbset.append( ( self.coords.translate( path[r].start.real, path[r].start.imag ), self.coords.translate(path[r].end.real, path[r].end.imag), ) ) return Curve(start=start, end=end, cb=cb, cbset=cbset)
def convert_svg_path_to_mpl(path_string): parsed = parse_path(path_string) vertices = [] codes = [] i_to_list = lambda i: [i.real, i.imag] for part in parsed: if isinstance(part, Move): vertices.append(i_to_list(part.start)) codes.append(mPath.MOVETO) elif isinstance(part, CubicBezier): vertices.extend([ i_to_list(part.start), i_to_list(part.control1), i_to_list(part.control2), i_to_list(part.end) ]) codes.extend( [mPath.MOVETO, mPath.CURVE4, mPath.CURVE4, mPath.CURVE4]) elif isinstance(part, QuadraticBezier): raise Exception('QuadraticBezier not implemented.') elif isinstance(part, Arc): raise Exception('Arc not implemented.') else: raise Exception(f'{type(part)} not implemented.') if parsed.closed: vertices.append([np.nan, np.nan]) codes.append(mPath.CLOSEPOLY) path = mPath(np.array(vertices), np.array(codes, dtype=np.uint8)) return remove_redundant_movetos(path)
def get_angle_from_path(path_str, t1, t2): path = parse_path(path_str) p1 = path.point(t1) p2 = path.point(t2) angle = math.atan2(p2.imag - p1.imag, p2.real - p1.real) angle = math.degrees(angle) return angle
def computeLength(shape): if shape.tagName == 'path': path = parse_path(shape.getAttribute('d')); return path.length(); # this is by far is the program most costly instruction if shape.tagName == 'line': return hypot(float(shape.getAttribute('x2')) - float(shape.getAttribute('x1')), float(shape.getAttribute('y2')) - float(shape.getAttribute('y1'))); if shape.tagName == 'polyline': length = 0.0; points = _parsePoints(shape); px = py = None; for x,y in points: if px is not None: length += hypot(x-px, y-py); px, py = x, y; return length; if shape.tagName == 'polygon': length = 0.0; points = _parsePoints(shape); px = py = fx = fy = None; for x,y in points: if fx is None: fx, fy = x, y; if px is not None: length += hypot(x-px, y-py); px, py = x, y; length += hypot(fx-px, fy-py); return length; print("Unsupported shape \"%s\" will not be animated."%shape.tagName);
def addpathid(root, curr): if 'path' in curr.tag: if int(curr.attrib['structure_id']) == int(root['id']): #add/update path id attribute path_area = parse_path( curr.attrib["d"] ).area() slice_id = "p" + curr.getparent().getparent()[0].attrib["id"] if 'path_ids' in root: root['path_ids'].append(curr.attrib['id']) root['path_areas'].append(path_area) root['path_routes'].append(getpathroute(curr)) root['slice_ids'].append(slice_id) root['ave_area'] = sum([a for a in root['path_areas']]) / len(root['path_ids']) root['volume'] += path_area else: root['path_ids'] = [curr.attrib['id']] root['path_routes'] = [getpathroute(curr)] root['path_areas'] = [path_area] root['slice_ids'] = [slice_id] root['ave_area'] = path_area root['volume'] = path_area root['largest_area'] = max( enumerate(root['path_areas']), key=lambda x: x[1] ) for child in curr: addpathid(root, child)
def get_particle_bounding_box(particle): if particle.tag == '{http://www.w3.org/2000/svg}path': commands = particle.attrib['d'] steps = parse_path(commands) points = [] for step in steps: if hasattr(step, 'start'): points.append(step.start) if hasattr(step, 'end'): points.append(step.end) min_x = min((p.real for p in points)) min_y = min((p.imag for p in points)) max_x = min((p.real for p in points)) max_y = min((p.imag for p in points)) # simple offset if hasattr(particle, 'x'): min_x += float(particle['x']) min_y += float(particle['y']) max_x += float(particle['x']) max_y += float(particle['y']) else: # rect min_x = float(particle.attrib['x']) min_y = float(particle.attrib['y']) max_x = min_x + float(particle.attrib['width']) max_y = min_y + float(particle.attrib['height']) # finished the bounding box Box = namedtuple('Box', ['left', 'top', 'right', 'bottom']) return Box(min_x, min_y, max_x, max_y)
def loop(screen): clock = pg.time.Clock() cont = True pfad = parse_path( "M 8,30A 20,20 0,0,1 50,30A 20,20 0,0,1 90,30Q 90,60 50,90Q 10,60 10,30 z" ) vis.animSVG(screen, (255, 255, 255), pfad, (6, 6), (0, 0), 2, 3, FRAMERATE, clock) line = vis.animLine(screen, (255, 255, 255), (100, 100), (200, 300), 3, 1, 60, clock) while cont: for event in pg.event.get( ): #Wenn Fenster geschlossen --> Main Loop beenden if event.type == pg.QUIT: cont = False #Fenster clearen, mit schwarzem Hintergrund füllen #screen.fill((0, 0, 0)) #--ZEICHENVORGANG vis.drawSVG(screen, (255, 255, 255), pfad, (6, 6), (0, 0), 0.01, 2) pg.draw.rect(screen, (255, 255, 255), line) #Fenster updaten pg.display.flip() #max. 60fps clock.tick(FRAMERATE)
def draw_image(self, image_file): """ Draw the SVG file with some apporximation. """ self.initPygame() # Get path from SVG file self.filename = image_file.replace('/', '-').split('.')[0] doc = minidom.parse(image_file) path_strings = [path.getAttribute('d') for path in doc.getElementsByTagName('path')] doc.unlink() count = 0 for eachPath in path_strings: count += 1 p = parse_path(eachPath) pointList = [] for j in range(0, int(len(p)), 2): # Skip half object (lines, arcs...) eachObject = p[j] """Approximate the curve throught floating-point steps from 0 to 1""" for i in range(0, int(1.0/SVG_APPROX_STEP)): i = round(i * SVG_APPROX_STEP, 3) x = int(round(eachObject.point(i).real * SVG_SCALE + SHIFT_X/2, 3)) y = int(round(eachObject.point(i).imag * SVG_SCALE, 3)) print (i, x, y, flush=True) pointList.append((x, y)) pointList = [(point[0]+160, -point[1]+120) for point in pointList] self.generate_path(pointList) if count % 5 == 0: self.dipInk()
def main(): lines = [] while True: line = sys.stdin.readline() if line == '\n': break lines.append(line) path_strings = parse_svg("".join(lines)) # print >> sys.stderr, path_strings points = [] while True: line = sys.stdin.readline().strip() if not line: break x, y = line.split(',') points.append((float(x), float(y))) # print >> sys.stderr, points compound = parse_path(path_strings) # print >> sys.stderr, "compound", compound compound_segments = [((segment.start.real, segment.start.imag), (segment.end.real, segment.end.imag)) for segment in compound] # print >> sys.stderr, "segments", compound_segments for p in points: if point_in_poly(p, compound_segments): print "true" else: print "false"
def get_points(path): path = parse_path(path) points = [] for p in path: points.append([p.start.real, p.start.imag]) points.append([p.end.real, p.end.imag]) return points
def path_to_polygon(path): polygon = [] global max_x, max_y, min_x, min_y new_path = Path() for segment in parse_path(path): new_path.append(Line(segment.start, segment.end)) new_path.closed = True raw_path = new_path.d() # search for compound path bits and remove them path_bits = re.findall('M.+?[ZM]', raw_path) if len(path_bits) > 0: raw_path = path_bits[0] raw_path_size = len(re.findall(',', raw_path)) for bit in path_bits: bit_size = len(re.findall(',', bit)) if bit_size > raw_path_size: raw_path = bit raw_path_size = bit_size # convert to simple list of nodes nodes = re.findall('[ML]\s*(\d+\.*\d*,\d+\.*\d*)\s*', raw_path) for n in nodes: coords = n.split(',') if max_x < int(coords[0]): max_x = int(coords[0]) if max_y < int(coords[1]): max_y = int(coords[1]) if min_x > int(coords[0]): min_x = int(coords[0]) if min_y > int(coords[1]): min_y = int(coords[1]) polygon.append([int(coords[0]), int(coords[1])]) polygon.pop() return polygon
def parse_path(self, doc): l = [] for elem in doc.getElementsByTagName('path'): pd = elem.getAttribute('d') transform = self.extract_transform(elem) path = parse_path(pd) element_path = [] for e in path: if e.length() == 0: continue samples = self.points_to_steps(e.length()) sampled_path = [] for i in range(samples): x0, y0 = e.point(1 / samples * i).real, e.point( 1 / samples * i).imag x1, y1 = e.point(1 / samples * (i + 1)).real, e.point( 1 / samples * (i + 1)).imag x0, y0 = self.apply_transform(x0, y0, transform) x1, y1 = self.apply_transform(x1, y1, transform) x0, y0 = self.points_to_steps(x0), self.points_to_steps(y0) x1, y1 = self.points_to_steps(x1), self.points_to_steps(y1) sampled_path.append((x0, y0)) sampled_path.append((x1, y1)) element_path += sampled_path if len(element_path) > 0: l.append(element_path) return l
def from_svg_d(cls, geo_txt): """ Load from text as in d attribute of svg HTML tag. """ # parse path = parse_path(geo_txt) # split curves shape = [] for elem in path: if isinstance(elem, svg.path.path.Move): # start new curve curve = [] shape.append(curve) continue else: # add point to curve assert isinstance( elem, (svg.path.path.Line, svg.path.path.Close) ), (elem, type(elem)) point = Region._get_line_start(elem) curve = shape[-1] curve.append(point) # remove repeating point for curve in shape: if curve[-1] == curve[0]: curve.pop() # create data and object region_data = [shape] region = cls(region_data) return region
def Measurement(): str_S1 = '<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg ' + 'xmlns="http://www.w3.org/2000/svg" ' + 'xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="600" height="500" viewBox="-50 0 500 500" > ' str_S2 = '<path d = "' str_S3 = '" inkscape:connector-curvature="0" '+ 'style="fill:none;stroke:#000000;stroke-width:3" />' str_S4 = '</svg>' doc = minidom.parse('temp.svg') path_strings = [path.getAttribute('d') for path in doc.getElementsByTagName('path')] path1 = parse_path(path_strings[0]) path2 = parse_path(path_strings[1]) #print "Path1: "+str(path1) #print "Path2: "+str(path2) str_Text = gen_text(path1, path2) fin_svg = str(str_S1) + str ('\n') + str(str_S2) + str(path1.d()) + str ('\n') + str(str_S3) + str ('\n') + str(str_S2) + str(path2.d()) + str(str_S3) + str(str_Text) + str(str_S4) cursor = db.cursor() sql = "select count(*) from svg_table;" cursor.execute(sql) c = int(cursor.fetchone()[0]) i = c+1 sql = "insert into svg_table (id, svg) values( " + str(i) + ", '" + fin_svg + "');" cursor.execute(sql) comma = str(", ") str_sql = "INSERT INTO `rear_table`(`ID`, `SPointX`, `SPointY`, `LegOpenX`, `LegOpenY`, `LegOpenLen`, `OutseamX`, `OutseamY`, `OutseamCPX`, `OutseamCPY`, `OutseamLen`, `WaistX`, `WaistY`, `WaistLen`, `BackriseX`, `BackriseY`, `BackriseCPX`, `BackriseCPY`, `BackriseLen`, `InseamX`, `InseamY`, `InseamCPX`, `InseamCPY`, `InseamLen`) VALUES (" str_sql1 = str(i) + comma + str(path1[0].start.real) + comma + str(path1[0].start.imag) + comma + str(path1[0].end.real) + comma + str(path1[0].end.imag) + comma + str(path1[0].length()) + comma str_sql2 = str(path1[1].end.real) + comma + str(path1[1].end.imag) + comma + str(path1[1].control.real) + comma + str(path1[1].control.imag) + comma + str(path1[1].length()) + comma str_sql3 = str(path1[2].end.real) + comma + str(path1[2].end.imag) + comma + str(path1[2].length()) + comma str_sql4 = str(path1[3].end.real) + comma + str(path1[3].end.imag) + comma + str(path1[3].control.real) + comma + str(path1[3].control.imag) + comma + str(path1[3].length()) + comma str_sql5 = str(path1[4].end.real) + comma + str(path1[4].end.imag) + comma + str(path1[4].control.real) + comma + str(path1[4].control.imag) + comma + str(path1[4].length()) + str(');') sql = str_sql + str_sql1 + str_sql2+ str_sql3+ str_sql4+ str_sql5 #print "sql string = ",sql cursor.execute(sql) str_sql = "INSERT INTO `front_table`(`ID`, `SPointX`, `SPointY`, `LegOpenX`, `LegOpenY`, `LegOpenLen`, `OutseamX`, `OutseamY`, `OutseamCPX`, `OutseamCPY`, `OutseamLen`, `WaistX`, `WaistY`, `WaistLen`, `FrontriseX`, `FrontriseY`, `FrontriseCPX`, `FrontriseCPY`, `FrontriseLen`, `InseamX`, `InseamY`, `InseamCPX`, `InseamCPY`, `InseamLen`) VALUES (" str_sql1 = str(i) + comma + str(path2[0].start.real) + comma + str(path2[0].start.imag) + comma + str(path2[0].end.real) + comma + str(path2[0].end.imag) + comma + str(path2[0].length()) + comma str_sql2 = str(path2[1].end.real) + comma + str(path2[1].end.imag) + comma + str(path2[1].control.real) + comma + str(path2[1].control.imag) + comma + str(path2[1].length()) + comma str_sql3 = str(path2[2].end.real) + comma + str(path2[2].end.imag) + comma + str(path2[2].length()) + comma str_sql4 = str(path2[3].end.real) + comma + str(path2[3].end.imag) + comma + str(path2[3].control.real) + comma + str(path2[3].control.imag) + comma + str(path2[3].length()) + comma str_sql5 = str(path2[4].end.real) + comma + str(path2[4].end.imag) + comma + str(path2[4].control.real) + comma + str(path2[4].control.imag) + comma + str(path2[4].length()) + str(');') sql = str_sql + str_sql1 + str_sql2+ str_sql3+ str_sql4+ str_sql5 cursor.execute(sql) db.commit() print i
def build_lines(svgfile, line_length_threshold=10.0, min_points_per_path=1, max_points_per_path=3): # we don't draw lines less than line_length_threshold path_strings = get_path_strings(svgfile) lines = [] for path_string in path_strings: try: full_path = parse_path(path_string) except: import pdb pdb.set_trace() print "e" for i in range(len(full_path)): p = full_path[i] if type(p) != Line and type(p) != CubicBezier: print "encountered an element that is not just a line or bezier " print "type: ", type(p) print p else: x_start = p.start.real y_start = p.start.imag x_end = p.end.real y_end = p.end.imag line_length = np.sqrt((x_end - x_start) * (x_end - x_start) + (y_end - y_start) * (y_end - y_start)) # len_data.append(line_length) points = [] if type(p) == CubicBezier: x_con1 = p.control1.real y_con1 = p.control1.imag x_con2 = p.control2.real y_con2 = p.control2.imag n_points = int(line_length / line_length_threshold) + 1 n_points = max(n_points, min_points_per_path) n_points = min(n_points, max_points_per_path) points = cubicbezier(x_start, y_start, x_con1, y_con1, x_con2, y_con2, x_end, y_end, n_points) else: points = [(x_start, y_start), (x_end, y_end)] if i == 0: # only append the starting point for svg lines.append([points[0][0], points[0][1], 0, 0]) # put eoc to be zero for j in range(1, len(points)): eos = 0 if j == len(points) - 1 and i == len(full_path) - 1: eos = 1 lines.append([points[j][0], points[j][1], eos, 0]) # put eoc to be zero lines = np.array(lines, dtype=np.float32) # make it relative moves lines[1:, 0:2] -= lines[0:-1, 0:2] lines[-1, 3] = 1 # end of character lines[0] = [0, 0, 0, 0] # start at origin return lines[1:]
def load_image(filename): root = ET.parse("{}.svg".format(filename)).getroot() viewbox = tuple(map(float, root.attrib["viewBox"].split())) all_lines = [] for line in root.findall("xmlns:line", NS): x1 = float(line.attrib["x1"]) y1 = float(line.attrib["y1"]) x2 = float(line.attrib["x2"]) y2 = float(line.attrib["y2"]) x1, y1 = normalize(x1, y1, viewbox) x2, y2 = normalize(x2, y2, viewbox) all_lines.append((x1, y1, x2, y2)) for polyline in root.findall("xmlns:polyline", NS): points = [ normalize(*map(float, pt.split(',')), viewbox) for pt in polyline.attrib["points"].split() ] x1, y1 = points[0] for x2, y2 in points[1:]: all_lines.append((x1, y1, x2, y2)) x1, y1 = x2, y2 for polygon in root.findall("xmlns:polygon", NS): points = [ normalize(*map(float, pt.split(',')), viewbox) for pt in polygon.attrib["points"].split() ] points.append(points[0]) x1, y1 = points[0] for x2, y2 in points[1:]: all_lines.append((x1, y1, x2, y2)) x1, y1 = x2, y2 for path in root.findall("xmlns:path", NS): path_spec = parse_path(path.attrib["d"]) # TODO: is support for QuadraticBezier and Arc needed? for segment in path_spec: if type(segment) is Line: x1, y1 = normalize(segment.start.real, segment.start.imag, viewbox) x2, y2 = normalize(segment.end.real, segment.end.imag, viewbox) all_lines.append((x1, y1, x2, y2)) elif type(segment) is CubicBezier: length = segment.length() n_div = max( 2, int( math.ceil(length / (RESOLUTION * (viewbox[3] - viewbox[1]))))) points = [] for i in range(n_div + 1): t = i / n_div c = segment.point(t) x, y = normalize(c.real, c.imag, viewbox) points.append((x, y)) x1, y1 = points[0] for x2, y2 in points[1:]: all_lines.append((x1, y1, x2, y2)) x1, y1 = x2, y2 return all_lines
def parse_paths(root): paths = [] for el in root.findall(".//{http://www.w3.org/2000/svg}path[@d]"): if el.get("d") != "Z": path = parse_path(el.get("d")) paths.append(path) return paths
def path_delta_move(pat, delta): text = get_full_match(pat) match = pat.group(1) path = parse_path(match) for primitive in path: path_primitive_move(primitive, delta) new_d = path.d() return text.replace(match, new_d)
def pathify_svg(svgfile, max_line_len, scale): svgfile_name = svgfile.filename svgfile_data = svgfile.read() print("Converting SVG from " + svgfile_name + " max_line_len=" + str(max_line_len)) print("SVG Data: " + str(svgfile_data)) pathstr = "" svg_dom = minidom.parseString(svgfile_data) path_strings = [path.getAttribute('d') for path in svg_dom.getElementsByTagName('path')] for path_string in path_strings: path_data = parse_path(path_string) x = [] y = [] for line in path_data: start = ((line.start.real), (line.start.imag)) end = ((line.end.real), (line.end.imag)) x.append(start[0]) x.append(end[0]) y.append(start[1]) y.append(end[1]) xmax = max(x) xmin = min(x) ymax = max(y) ymin = min(y) shift_x = -(xmax+xmin)/2 shift_y = -(ymax+ymin)/2 scale_x = xmax-xmin scale_y = ymax-ymin if scale_x/MAX_WIDTH > scale_y/MAX_HEIGHT: scale_x = MAX_WIDTH/scale_x scale_y = scale_x else: scale_y = MAX_HEIGHT/scale_y scale_x = scale_y for index, item in enumerate(x): x[index] = mround((x[index]+shift_x)*scale_x*scale) y[index] = mround((y[index]+shift_y)*-scale_y*scale) # remove duplicates i = 0 while i < len(x)-1: if x[i] == x[i+1] and y[i] == y[i+1]: del x[i+1] del y[i+1] else: i += 1 for index, item in enumerate(x): code = '({},{}),'.format(x[index], y[index]) pathstr += code print("SVG Conversion Complete") return pathstr
def _getSVGPathsFromMinidom(self, pMinidom): paths = [] for path in pMinidom.getElementsByTagName("path"): dAttributeOfPath = path.getAttribute('d') parsedPath = parse_path(dAttributeOfPath) paths.append(self._castMinidomParsedPath(parsedPath)) if logger.isEnabledFor(logging.DEBUG): logger.debug("Parsed SVG paths are {}".format(paths)) return paths
def parse_svg(filepath): doc = minidom.parse(filepath) paths = [] ids = [] for path in doc.getElementsByTagName('path'): ids.append(path.getAttribute('id')) parsed_path = parse_path(path.getAttribute('d')) paths.append(parsed_path) return np.array(ids), np.array(paths)
def filter_svg(svg_doc, paths): svg_root = svg_doc.getElementsByTagName('svg')[0] # copy only the root node new_svg = svg_root.cloneNode(False) for element in svg_doc.getElementsByTagName('path'): parsed_path = parse_path(element.getAttribute('d')) if parsed_path in paths: element.setAttribute('class', 'highlight') new_svg.appendChild(element) return new_svg
def build_lines(svgfile, line_length_threshold=10.0, min_points_per_path=1, max_points_per_path=3): # we don't draw lines less than line_length_threshold path_strings = get_path_strings(svgfile) lines = [] for path_string in path_strings: try: full_path = parse_path(path_string) except: import pdb pdb.set_trace() print "e" for i in range(len(full_path)): p = full_path[i] if type(p) != Line and type(p) != CubicBezier: print "encountered an element that is not just a line or bezier " print "type: ", type(p) print p else: x_start = p.start.real y_start = p.start.imag x_end = p.end.real y_end = p.end.imag line_length = np.sqrt( (x_end - x_start) * (x_end - x_start) + (y_end - y_start) * (y_end - y_start)) # len_data.append(line_length) points = [] if type(p) == CubicBezier: x_con1 = p.control1.real y_con1 = p.control1.imag x_con2 = p.control2.real y_con2 = p.control2.imag n_points = int(line_length / line_length_threshold) + 1 n_points = max(n_points, min_points_per_path) n_points = min(n_points, max_points_per_path) points = cubicbezier(x_start, y_start, x_con1, y_con1, x_con2, y_con2, x_end, y_end, n_points) else: points = [(x_start, y_start), (x_end, y_end)] if i == 0: # only append the starting point for svg lines.append([points[0][0], points[0][1], 0, 0]) # put eoc to be zero for j in range(1, len(points)): eos = 0 if j == len(points) - 1 and i == len(full_path) - 1: eos = 1 lines.append([points[j][0], points[j][1], eos, 0]) # put eoc to be zero lines = np.array(lines, dtype=np.float32) # make it relative moves lines[1:, 0:2] -= lines[0:-1, 0:2] lines[-1, 3] = 1 # end of character lines[0] = [0, 0, 0, 0] # start at origin return lines[1:]
def svg_to_path(file_obj, file_type=None): def complex_to_float(values): return np.array([[i.real, i.imag] for i in values]) def load_line(svg_line): points = complex_to_float([svg_line.point(0.0), svg_line.point(1.0)]) if not starting: points[0] = vertices[-1] entities.append(Line(np.arange(2)+len(vertices))) vertices.extend(points) def load_arc(svg_arc): points = complex_to_float([svg_arc.start, svg_arc.point(.5), svg_arc.end]) if not starting: points[0] = vertices[-1] entities.append(Arc(np.arange(3)+len(vertices))) vertices.extend(points) def load_quadratic(svg_quadratic): points = complex_to_float([svg_quadratic.start, svg_quadratic.control, svg_quadratic.end]) if not starting: points[0] = vertices[-1] entities.append(Bezier(np.arange(3)+len(vertices))) vertices.extend(points) def load_cubic(svg_cubic): points = complex_to_float([svg_cubic.start, svg_cubic.control1, svg_cubic.control2, svg_cubic.end]) if not starting: points[0] = vertices[-1] entities.append(Bezier(np.arange(4)+len(vertices))) vertices.extend(points) # first, we grab all of the path strings from the xml file xml = parse_xml(file_obj.read()) paths = [p.attributes['d'].value for p in xml.getElementsByTagName('path')] entities = deque() vertices = deque() loaders = {'Arc' : load_arc, 'Line' : load_line, 'CubicBezier' : load_cubic, 'QuadraticBezier' : load_quadratic} for svg_string in paths: starting = True for svg_entity in parse_path(svg_string): loaders[svg_entity.__class__.__name__](svg_entity) #starting = False return {'entities' : np.array(entities), 'vertices' : np.array(vertices)}
def parse_paths(paths, min_edge_size): segments = [] index = 0 for path in paths: index += 1 print str(float(index) / len(paths) * 100) + ' %' if 'd' not in path.attributes.keys(): raise Exception, 'There is no attribute "d" in path element' svg_path = parse_path(path.attributes['d'].value) common_attributes = extract_attributes(path) segments.append(tuple([svg_path_to_segment_list(svg_path, min_edge_size), common_attributes])) return segments
def get_corners(self): transform = get_matrix( parent_map[self.element] ) corners = [] for p in parse_path( self.element.attrib['d']): coords = np.matrix([ [1,0,p.start.real],[0,1,p.start.imag],[0,0,1] ]) res = transform*coords if len(corners): dx = corners[-1][0] - res[0,2] dy = corners[-1][1] - res[1,2] if dx*dx + dy*dy < 0.01: continue corners.append( (res[0,2], res[1,2]) ) return corners
def simplify_points(path_d): path = parse_path(path_d) for bezier in path: if isinstance(bezier, CubicBezier): for attr in ('start', 'control1', 'control2', 'end'): setattr(bezier, attr, gfc(getattr(bezier, attr))) elif isinstance(bezier, Line): for attr in ('start', 'end'): setattr(bezier, attr, gfc(getattr(bezier, attr))) return path
def get_svg_path(wc): config = get_config() svgd = get_absolute_path(config.get('KWS', 'locations')) svgs = glob(os.path.join(svgd, '*.svg')) dids = [os.path.basename(x).replace('.svg', '') for x in svgs] svgp = svgs[dids.index(wc.doc_id)] dom = minidom.parse(svgp) path = None for element in dom.getElementsByTagName('path'): if element.getAttribute('id') == wc.id: path = parse_path(element.getAttribute('d')) return path
def get_path_from_svg(svg_path): n_pts = 100 all_coords = [] svg_image = minidom.parse(svg_path) path_strings = [path.getAttribute('d') for path in svg_image.getElementsByTagName('path')] for i in range(len(path_strings)): path_strings[i] = parse_path(str(path_strings[i])) svg_image.unlink() for current_path in path_strings: for element in current_path: all_coords.append(get_coords_from_shape(element)) return all_coords
async def draw(self, network, layout, viewport, scale): self._network = network self._layout = layout self._viewport = viewport[0] + viewport[1] self._scale = scale self.scale = scale self._resize() # TODO: actually draw the things for obj in layout.keys(): if isinstance(obj, Interlocking): l, t, r, b = self.transform(layout[obj][0]) + self.transform(layout[obj][1]) self._interlockings[obj] = QRect(l, t, r - l, b - t) elif isinstance(obj, Switch): self._switches[obj] = layout[obj] elif isinstance(obj, TrackSection): self._tracks[obj] = svgpath.parse_path(layout[obj]) for intg, bbox in self._interlockings.items(): wid = self._interlocking_widgets[intg] = InterlockingWidget(self.layout, self, bbox, intg) for track, path in self._tracks.items(): wid = self._track_widgets[track] = TrackWidget(self.layout, self, path, track) for switch, params in self._switches.items(): if switch in self._switch_widgets: continue direction, offset = params track = switch.track.section_with_offset(switch.position) wid = self._switch_widgets[switch] = SwitchWidget(self.layout, self, switch, \ self._track_widgets.get(track), direction, offset) if isinstance(switch.turnout, Switch): switch2 = switch.turnout direction, offset = self._switches[switch2] track = switch2.track.section_with_offset(switch2.position) wid2 = self._switch_widgets[switch2] = SwitchWidget(self.layout, self, switch2, \ self._track_widgets.get(track), direction, offset) wid.turnout_wid = wid2 elif isinstance(switch.turnout, Track): track2 = switch.turnout other_point = None if track2.up_next == switch: other_point = self._track_widgets[track2.sections[-1]].raw_path[0].start elif track2.down_next == switch: other_point = self._track_widgets[track2.sections[0]].raw_path[-1].end if not other_point: continue wid.turnout_point = self.transform((other_point.real, other_point.imag))
async def draw(self, network, layout, viewport, scale): self._viewport = viewport[0] + viewport[1] self._scale = scale self.scale = scale self._resize() # TODO: actually draw the things for obj in layout.keys(): if isinstance(obj, Switch): self._switches[obj] = layout[obj] elif isinstance(obj, TrackSection): self._tracks[obj] = svgpath.parse_path(layout[obj]) for track, path in self._tracks.items(): wid = self._track_widgets[track] = TrackWidget(self.layout, self, path, track)
def parse_element(element, objects, transform, min_length, min_area, directives): obj = {} transform = multiply_transforms(transform, parse_transform(element.get('transform'))) if element.tag == GROUP_TAG: for child in element: parse_element(child, objects, transform, min_length, min_area, directives) return if element.tag == PATH_TAG: if element.get(SODITYPE_ATTR) == 'arc': xy = float(element.get(CX_ATTR)) + float(element.get(CY_ATTR)) * 1j rx, ry = float(element.get(RX_ATTR)), float(element.get(RY_ATTR)) xy = transform_one(transform, xy) if transform: rx *= transform[0] ry *= transform[3] radius = (rx + ry) * .5 if max(rx, ry) / min(rx, ry) > 1.05: warn('Ellipse %s (%f, %f) will be approximated as a circle with ' 'radius %f.' % (element.get('id'), rx, ry, radius)) obj['circle'] = finalize_coords([xy]) obj['circle'].append(radius) else: path = svg.parse_path(element.get('d')) poly = list(transform_many(transform, path_to_polygon(path, min_length, min_area))) sort_poly(poly) obj['poly'] = finalize_coords(poly) if 'triangulate' in directives: obj['convex'] = [finalize_coords(x) for x in convexify(poly)] elif element.tag == RECT_TAG or element.tag == IMAGE_TAG: poly = transform_many(transform, rect_to_polygon(element, False)) obj['poly'] = finalize_coords(poly) if element.tag == RECT_TAG and 'triangulate' in directives: obj['convex'] = [obj['poly']] link = element.get(LINK_ATTR) desc = element.find(DESC_TAG) if link is not None: obj['subclass'] = link_to_subclass(link) if desc is not None: obj['script'] = desc.text if obj: objects.append(obj)
def get_path_from_svg(svg_path): step = 0.1 all_coords = [] svg_image = minidom.parse(svg_path) path_strings = [path.getAttribute('d') for path in svg_image.getElementsByTagName('path')] for i in range(len(path_strings)): path_strings[i] = parse_path(str(path_strings[i])) svg_image.unlink() for current_path in path_strings: for element in current_path: if type(element) is svg.path.path.CubicBezier: # all_coords.append(get_cubic_benzier(element, step)) pass if type(element) is svg.path.path.Line: all_coords.append(get_line(element, step)) return all_coords
def build_gcode(filename, desired_size): svg = ET.parse(filename) svg_tag = svg.getroot() paths = svg.findall('.//{http://www.w3.org/2000/svg}path') svg_paths = list(parse_path(path.attrib['d']) for path in paths) desired_size = desired_size try: size = float(svg_tag.attrib['width']) + float(svg_tag.attrib['height']) * 1j except Exception: zx, zy, x, y = svg_tag.attrib['viewBox'].split() size = float(x) + float(y) * 1j max_dimension = max(size.real, size.imag) scale = desired_size / max_dimension gcode = [preamble] + list(gcodify(svg_paths, scale + scale * 1j, -0.5 * size)) + [epilogue] return gcode
def geocode_depto(prov, dpto, envelope_func=find_bounding_box): """ Acá está la magia Para un departamento -dado por prov y dpto-, lo obtiene del mapa de referencia DEPARTAMENTOS_SHP. Interpreta los paths contenidos en el SVG correspondiente y calcula la transformación que permite georeferenciarlo. """ fname = "source_svgs/fracciones/%02d%03d.svg" % (prov, dpto) print >>sys.stderr, "Opening %s" % fname with open(fname, 'r') as f: tree = etree.parse(f) svg_width = int(xpath_svg(tree, "//svg:svg/@width")[0]) svg_height = int(xpath_svg(tree, "//svg:svg/@height")[0]) paths = xpath_svg(tree, "//svg:path[contains(@class, 'fraccion') and starts-with(@clave_unica, '%02d%03d')]" % (prov, dpto)) # points: # todos los vertices de todas las fracciones contenidas en el SVG points = set([ invert_y(line.start, svg_height) for path_def in [q.attrib['d'] for q in paths] for line in parse_path(path_def) ]) # svg_bounding_points: # puntos extremos de points svg_bounding_points = envelope_func(points) shp_points = shapefile_points(DEPARTAMENTOS_SHP, "PROV = '%02d' AND DEPTO = '%03d'" % (prov, dpto)) shp_bounding_points = envelope_func(shp_points) # tr: # transformacion estimada a partir de los conjuntos de # puntos extremos del SVG y del SHP tr = estimate_transform(svg_bounding_points, shp_bounding_points) # retorna: # tuple list [ (atributos_path, [ (line_start, line_end), ... ]), ... ] return svg_paths_points(paths, tr, svg_height)
def parse_svg(filename): #filename = "./piirros2.svg" doc = minidom.parse(filename) # parseString also exists path_strings = [path.getAttribute('d') for path in doc.getElementsByTagName('path')] pth = str(path_strings[0]) path1 = parse_path(pth) coord = [] for i in range(0, 501, 1): j = float(i) / 500 coord.append((path1.point(j).real, path1.point(j).imag)) #for pair in coord: #print pair return coord
def __init__(self, filename): root = ET.parse(filename).getroot() paths = [] for element in root.getchildren(): if str.endswith(element.tag, "path"): paths.append(parse_path(element.attrib["d"])) self.paths = [] for path in paths: a_path = aggdraw.Path() self.paths.append(a_path) for line in path: x1 = line.start.real y1 = line.start.imag x2 = line.end.real y2 = line.end.imag a_path.moveto(x1, y1) a_path.lineto(x2, y2)
def parse(filename): doc = minidom.parse(filename) svg = doc.getElementsByTagName('svg') if len(svg) == 0: print 'No SVG data found in file' return width = svg[0].getAttribute('width') height = svg[0].getAttribute('height') print width, height if width is "" or height is "": width = DRAWING_WIDTH height = DRAWING_HEIGHT # https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox viewbox = svg[0].getAttribute('viewBox') print 'VIEWBOX ' + viewbox if viewbox is not "": viewbox = viewbox.split() if len(viewbox) == 4: width = float(viewbox[2]) height = float(viewbox[3]) else: width = float(width) height = float(height) print width, height path_strings = [path.getAttribute('d') for path in doc.getElementsByTagName('path')] paths = [] for path_string in path_strings: paths.append(parse_path(path_string)) doc.unlink() x =[] for path in paths: pathList = [] #print "PATH START" for segment in path: temp = parseSegment(segment, width, height) # print temp pathList = pathList + temp #print "PATH END" x.append(pathList) return x
def load_file(self, filename): #read the svg doc as a DOM to extract the XML <path> element doc = xml.dom.minidom.parse(filename) # determine the ratio of each pixel to real world units svg = doc.getElementsByTagName('svg')[0] #get the units for this file height = svg.getAttribute('height') width = svg.getAttribute('width') if(height.find("in")!=-1): self.display_units = "in" elif(height.find("mm")!=-1): self.display_units = "mm" elif(height.find("cm")!=-1): self.display_units = "cm" elif(height.find("px")!=-1): self.display_units = "px" height = height.replace(self.display_units, "") width = width.replace(self.display_units, "") viewbox = svg.getAttribute('viewBox').rsplit(" ") self.unit = (float(width)/float(viewbox[2]) + float(height)/float(viewbox[3]))/2 self.plt.display_units = self.display_units # extract the path elements path_strings = [path.getAttribute('d') for path in doc.getElementsByTagName('path')] # iterate over each path that is found for path_string in path_strings: # break up each path shape into the individual lines (mM -> zZ) lines = re.split('z|Z', path_string) for line in lines: if(len(line)>2): line += self.delimiter item = parse_path(line) # convert the string to a path using svg.path library self.paths.append(item)