def fill(self, elt): VIPpattern = self.VairPattern() blazon.Ordinary.defs.append(VIPpattern) pattern = SVGdraw.SVGelement('pattern', attributes={ "width": "16", "height": "16", "patternUnits": "userSpaceOnUse", "patternContentUnits": "userSpaceOnUse", "id": "vair%04d" % blazon.Ordinary.id }) self.color = "vair%04d" % blazon.Ordinary.id blazon.Ordinary.id += 1 pattern.addElement( SVGdraw.rect(x="0", y="0", width="16", height="8", fill="url(#%s)" % VIPpattern.attributes["id"])) pattern.addElement( SVGdraw.rect(x="0", y="8", width="20", height="8", fill="url(#%s)" % VIPpattern.attributes["id"], transform="translate(-4,0)")) blazon.Ordinary.defs.append(pattern) elt.attributes["fill"] = "url(#%s)" % pattern.attributes["id"] return elt
def fill(self,elt): pattern=SVGdraw.SVGelement('pattern',attributes= {"height":"15","width":"15", "patternUnits":"userSpaceOnUse", "patternContentUnits":"userSpaceOnUse", "id":"ermine%04d"%blazon.Ordinary.id}) blazon.Ordinary.id+=1 pattern.addElement(self.color1.fill(SVGdraw.rect(x="0",y="0",width="15",height="15"))) pattern.addElement(self.color2.fill(SVGdraw.SVGelement('path', attributes={"d": "M1,5 c1,-1 1.5,-4 1.5,-4 c0,0 .5,3 1.5,4 l-1.5,1.5 z"}))) pattern.addElement(self.color2.fill(SVGdraw.circle(cx="1.5",cy="2", r=".5"))) pattern.addElement(self.color2.fill(SVGdraw.circle(cx="2.5",cy="1", r=".5"))) pattern.addElement(self.color2.fill(SVGdraw.circle(cx="3.5",cy="2", r=".5"))) pattern.addElement(self.color2.fill(SVGdraw.SVGelement('path', attributes={"d": "M8.5,12.5 c1,-1 1.5,-4 1.5,-4 c0,0 .5,3 1.5,4 l-1.5,1.5 z"}))) pattern.addElement(self.color2.fill(SVGdraw.circle(cx="9",cy="9.5", r=".5"))) pattern.addElement(self.color2.fill(SVGdraw.circle(cx="10",cy="8.5", r=".5"))) pattern.addElement(self.color2.fill(SVGdraw.circle(cx="11",cy="9.5", r=".5"))) blazon.Ordinary.defs.append(pattern) elt.attributes["fill"]="url(#%s)"%pattern.attributes["id"] return elt
def fill(self, elt): pattern = SVGdraw.SVGelement('pattern', attributes={ "height": "20", "width": "20", "patternUnits": "userSpaceOnUse", "patternContentUnits": "userSpaceOnUse", "id": "semy%04d" % blazon.Ordinary.id }) blazon.Ordinary.id += 1 # Just in case we try to countercharge it. It doesn't work anyway. self.colors = (self.background, self.charge.tincture) charge2 = copy.deepcopy(self.charge) self.charge.moveto((5, 15)) self.charge.scale(.1) charge2.moveto((15, 5)) charge2.scale(.1) #pattern.addElement(SVGdraw.rect(0,0,30,30,stroke="black", # stroke_width=".3",fill="none")) pattern.addElement(self.charge.finalizeSVG()) pattern.addElement(charge2.finalizeSVG()) blazon.Ordinary.defs.append(pattern) newelt = SVGdraw.group() elt = self.background.fill(elt) newelt.addElement(elt) newbase = SVGdraw.rect(x=-blazon.Ordinary.FESSPTX, y=-blazon.Ordinary.FESSPTY, width=blazon.Ordinary.WIDTH, height=blazon.Ordinary.HEIGHT, fill="url(#%s)" % pattern.attributes["id"]) newelt.addElement(newbase) return newelt
def build(self): (sx, sy) = self._srcchgset.position() h_offset = self._srcchgset.tag_offset(self._h) self._position = (sx + (self._srcchgset.extent()[0])/2, sy - (3*self._h)/2 + h_offset) x = self._position[0]+(self._w-self._tw)/2 y = self._position[1] r = UNIT/2 rect = SVG.rect(x,y,self._tw,self._h, self._srcchgset.strokecolor(), self._srcchgset.fillcolor(), self._srcchgset.strokewidth()) rect.attributes['rx'] = r rect.attributes['ry'] = r rect.attributes['opacity'] = str(self._opacity/100.0) text = SVG.text(self._position[0]+self._w/2, self._position[1]+self._h/2+UNIT/4, "%s" % self._title.encode('utf-8'), self._srcchgset.fontsize(), self._srcchgset.fontname()) txc = SvgColor('white') text.attributes['style'] = 'fill:%s; text-anchor: middle' % txc.rgb() name = self._title.encode('utf-8').replace('/','') g = SVG.group('grp%d' % self._revision, elements=[rect, text]) link = "%s/changeset/%d" % (self._parent.urlbase(), self._revision) self._link = SVG.link(link, elements=[g]) self._link.attributes['id'] = 'rev%d' % self._revision self._link.attributes['style'] = \ 'color: %s; background-color: %s' % \ (self._srcchgset.fillcolor(), self._srcchgset.strokecolor())
def fill(self,elt): pattern=SVGdraw.SVGelement('pattern',attributes= {"height":"20", "width":"20", "patternUnits": "userSpaceOnUse", "patternContentUnits": "userSpaceOnUse", "id": "semy%04d"%blazon.Ordinary.id}) blazon.Ordinary.id+=1 # Just in case we try to countercharge it. It doesn't work anyway. self.colors=(self.background,self.charge.tincture) charge2=copy.deepcopy(self.charge) self.charge.moveto((5,15)) self.charge.scale(.1) charge2.moveto((15,5)) charge2.scale(.1) #pattern.addElement(SVGdraw.rect(0,0,30,30,stroke="black", # stroke_width=".3",fill="none")) pattern.addElement(self.charge.finalizeSVG()) pattern.addElement(charge2.finalizeSVG()) blazon.Ordinary.defs.append(pattern) newelt=SVGdraw.group() elt=self.background.fill(elt) newelt.addElement(elt) newbase=SVGdraw.rect(x=-blazon.Ordinary.FESSPTX, y=-blazon.Ordinary.FESSPTY, width=blazon.Ordinary.WIDTH, height=blazon.Ordinary.HEIGHT, fill="url(#%s)"%pattern.attributes["id"]) newelt.addElement(newbase) return newelt
def fill(self, elt): pattern = SVGdraw.SVGelement('pattern', attributes={ "width": "8", "height": "16", "patternUnits": "userSpaceOnUse", "patternContentUnits": "userSpaceOnUse", "id": "counter-vair%04d" % blazon.Ordinary.id }) blazon.Ordinary.id += 1 pattern.addElement( self.color1.fill(SVGdraw.rect(x="0", y="0", width="8", height="18"))) pattern.addElement( self.color2.fill( SVGdraw.SVGelement( 'path', attributes={ "d": "M0,8 l2,-2 l0,-4 l2,-2 l2,2 l0,4 l2,2 l-2,2 l0,4 l-2,2 l-2,-2 l0,-4 z" }))) elt.attributes["fill"] = "url(#%s)" % pattern.attributes["id"] blazon.Ordinary.defs.append(pattern) return elt
def fill(self,elt): pattern=SVGdraw.SVGelement('pattern',attributes= {"height":"15","width":"15", "patternUnits":"userSpaceOnUse", "patternContentUnits":"userSpaceOnUse", "id":"ermine%04d"%blazon.Ordinary.id}) blazon.Ordinary.id+=1 pattern.addElement(self.color1.fill(SVGdraw.rect(x="0",y="0",width="15",height="15"))) pattern.addElement(self.color2.fill(SVGdraw.SVGelement('path', attributes={"d": "M1,5 c1,-1 1.5,-4 1.5,-4 c0,0 .5,3 1.5,4 l-1.5,1.5 z"}))) pattern.addElement(self.color2.fill(SVGdraw.circle(cx="1.5",cy="2", r=".5"))) pattern.addElement(self.color2.fill(SVGdraw.circle(cx="2.5",cy="1", r=".5"))) pattern.addElement(self.color2.fill(SVGdraw.circle(cx="3.5",cy="2", r=".5"))) pattern.addElement(self.color2.fill(SVGdraw.SVGelement('path', attributes={"d": "M8.5,12.5 c1,-1 1.5,-4 1.5,-4 c0,0 .5,3 1.5,4 l-1.5,1.5 z"}))) pattern.addElement(self.color2.fill(SVGdraw.circle(cx="9",cy="9.5", r=".5"))) pattern.addElement(self.color2.fill(SVGdraw.circle(cx="10",cy="8.5", r=".5"))) pattern.addElement(self.color2.fill(SVGdraw.circle(cx="11",cy="9.5", r=".5"))) blazon.Ordinary.defs.append(pattern) elt.attributes["fill"]="url(#%s)"%pattern.attributes["id"] return elt
def VairPattern(self): pattern = SVGdraw.SVGelement(type="pattern", attributes={ "patternContentUnits": "userSpaceOnUse", "height": "8", "id": "vair-in-pale%04d" % blazon.Ordinary.id, "patternUnits": "userSpaceOnUse", "width": "8" }) pattern.addElement( self.color1.fill(SVGdraw.rect(x="0", y="0", width="8", height="8"))) pattern.addElement( self.color2.fill( SVGdraw.SVGelement( type='path', attributes={ "d": "M0,8 l2,-2 l0,-4 l2,-2 l2,2 l0,4 l2,2 z" }))) self.color = "vair-in-pale%04d" % blazon.Ordinary.id blazon.Ordinary.id += 1 return pattern
def doGrid(self, canvas, rows, verticalOffset, partHeight, columns, horizontalOffset, partWidth, gridsize, lineColor, fillColor, penWidth): polySize = str(gridsize) + self.units for polyRow in range(0, rows): polyTop = verticalOffset + polyRow*partHeight polyTopStr = str(polyTop) + self.units #do stuff for hexagons rowcolumns = columns rowoffset = 0 if self.type == 'hex': if polyRow % 2 == 0: if (self.width-(horizontalOffset+self.rightMargin-.01)) >= (columns*partWidth + gridsize): rowcolumns = columns + 1 else: rowoffset = gridsize/2 + gridsize/4 for polyColumn in range(0, rowcolumns): polyLeft = horizontalOffset + polyColumn*partWidth polyLeft += rowoffset polyLeftStr = str(polyLeft) + self.units if self.type == 'hex': gridshape = hexagon(gridsize, polyLeft, polyTop, self.units, stroke=lineColor, fill=fillColor, stroke_width=penWidth) else: gridshape = SVGdraw.rect(polyLeftStr, polyTopStr, polySize, polySize, stroke=lineColor, fill=fillColor, stroke_width=penWidth) canvas.addElement(gridshape) return canvas
def fill(self, elt): pattern = SVGdraw.SVGelement('pattern', attributes={ "height": "20", "width": "20", "patternUnits": "userSpaceOnUse", "patternContentUnits": "userSpaceOnUse", "id": "fret%04d" % blazon.Ordinary.id }) blazon.Ordinary.id += 1 # Why do I need a background rectangle in the pattern??? # pattern.addElement(self.color1.fill(SVGdraw.rect(x="0",y="0",width="22", # height="22"))) group = SVGdraw.group() group.attributes["stroke"] = "#888888" group.attributes["stroke-width"] = ".1" rect1 = self.color2.fill( SVGdraw.rect(x="-2", y="-20", width="4", height="50")) rect1.attributes["transform"] = "translate(0,10) rotate(45)" rect2 = self.color2.fill( SVGdraw.rect(x="-2", y="-20", width="4", height="50")) rect2.attributes["transform"] = "translate(20,10) rotate(45)" rect3 = self.color2.fill( SVGdraw.rect(x="-2", y="-20", width="4", height="50")) rect3.attributes["transform"] = "translate(0,10) rotate(-45)" rect4 = self.color2.fill( SVGdraw.rect(x="-2", y="-20", width="4", height="50")) rect4.attributes["transform"] = "translate(20,10) rotate(-45)" for e in [rect1, rect2, rect3, rect4]: group.addElement(e) pattern.addElement(group) blazon.Ordinary.defs.append(pattern) elt = self.color1.fill(elt) newelt = SVGdraw.group() newelt.addElement(elt) newbase = SVGdraw.rect(x=-blazon.Ordinary.FESSPTX, y=-blazon.Ordinary.FESSPTY, width=blazon.Ordinary.WIDTH, height=blazon.Ordinary.HEIGHT, fill="url(#%s)" % pattern.attributes["id"]) newelt.addElement(newbase) return newelt
def fill(self,elt): pattern=SVGdraw.SVGelement('pattern',attributes= {"height":"20", "width":"20", "patternUnits":"userSpaceOnUse", "patternContentUnits":"userSpaceOnUse", "id": "maso%04d"%blazon.Ordinary.id}) blazon.Ordinary.id+=1 group=SVGdraw.group() group.addElement(self.color2.fill(SVGdraw.rect(x="0",y="9",width="20",height="2"))) group.addElement(self.color2.fill(SVGdraw.rect(x="0",y="10",width="1",height="10"))) group.addElement(self.color2.fill(SVGdraw.rect(x="19",y="10",width="1",height="10"))) group.addElement(self.color2.fill(SVGdraw.rect(x="9",y="0",width="2", height="10"))) group.addElement(self.color2.fill(SVGdraw.rect(x="0",y="0",width="20",height="1"))) group.addElement(self.color2.fill(SVGdraw.rect(x="0",y="19",width="20",height="1"))) pattern.addElement(group) blazon.Ordinary.defs.append(pattern) elt=self.color1.fill(elt) newelt=SVGdraw.group() newelt.addElement(elt) newbase=SVGdraw.rect(x=-blazon.Ordinary.FESSPTX, y=-blazon.Ordinary.FESSPTY, width=blazon.Ordinary.WIDTH, height=blazon.Ordinary.HEIGHT, fill="url(#%s)"%pattern.attributes["id"]) newelt.addElement(newbase) return newelt
def fill(self,elt): pattern=SVGdraw.SVGelement('pattern',attributes= {"height":"20", "width":"20", "patternUnits":"userSpaceOnUse", "patternContentUnits":"userSpaceOnUse", "id": "maso%04d"%blazon.Ordinary.id}) blazon.Ordinary.id+=1 group=SVGdraw.group() group.addElement(self.color2.fill(SVGdraw.rect(x="0",y="9",width="20",height="2"))) group.addElement(self.color2.fill(SVGdraw.rect(x="0",y="10",width="1",height="10"))) group.addElement(self.color2.fill(SVGdraw.rect(x="19",y="10",width="1",height="10"))) group.addElement(self.color2.fill(SVGdraw.rect(x="9",y="0",width="2", height="10"))) group.addElement(self.color2.fill(SVGdraw.rect(x="0",y="0",width="20",height="1"))) group.addElement(self.color2.fill(SVGdraw.rect(x="0",y="19",width="20",height="1"))) pattern.addElement(group) blazon.Ordinary.defs.append(pattern) elt=self.color1.fill(elt) newelt=SVGdraw.group() newelt.addElement(elt) newbase=SVGdraw.rect(x=-blazon.Ordinary.FESSPTX, y=-blazon.Ordinary.FESSPTY, width=blazon.Ordinary.WIDTH, height=blazon.Ordinary.HEIGHT, fill="url(#%s)"%pattern.attributes["id"]) newelt.addElement(newbase) return newelt
def fill(self,elt): VIPpattern=self.VairPattern() blazon.Ordinary.defs.append(VIPpattern) pattern=SVGdraw.SVGelement('pattern',attributes= {"width":"16", "height":"16", "patternUnits":"userSpaceOnUse", "patternContentUnits":"userSpaceOnUse", "id":"vair%04d"%blazon.Ordinary.id}) self.color="vair%04d"%blazon.Ordinary.id blazon.Ordinary.id+=1 pattern.addElement(SVGdraw.rect(x="0", y="0", width="16", height="8", fill="url(#%s)"%VIPpattern.attributes["id"])) pattern.addElement(SVGdraw.rect(x="0", y="8", width="20", height="8", fill="url(#%s)"%VIPpattern.attributes["id"], transform="translate(-4,0)")) blazon.Ordinary.defs.append(pattern) elt.attributes["fill"]="url(#%s)"%pattern.attributes["id"] return elt
def fill(self,elt): pattern=SVGdraw.SVGelement('pattern',attributes= {"height":"20", "width":"20", "patternUnits": "userSpaceOnUse", "patternContentUnits": "userSpaceOnUse", "id": "fret%04d"%blazon.Ordinary.id}) blazon.Ordinary.id+=1 # Why do I need a background rectangle in the pattern??? # pattern.addElement(self.color1.fill(SVGdraw.rect(x="0",y="0",width="22", # height="22"))) group=SVGdraw.group() group.attributes["stroke"]="#888888" group.attributes["stroke-width"]=".1" rect1=self.color2.fill(SVGdraw.rect(x="-2",y="-20", width="4",height="50")) rect1.attributes["transform"]="translate(0,10) rotate(45)" rect2=self.color2.fill(SVGdraw.rect(x="-2",y="-20", width="4",height="50")) rect2.attributes["transform"]="translate(20,10) rotate(45)" rect3=self.color2.fill(SVGdraw.rect(x="-2",y="-20", width="4",height="50")) rect3.attributes["transform"]="translate(0,10) rotate(-45)" rect4=self.color2.fill(SVGdraw.rect(x="-2",y="-20", width="4",height="50")) rect4.attributes["transform"]="translate(20,10) rotate(-45)" for e in [rect1,rect2,rect3,rect4]: group.addElement(e) pattern.addElement(group) blazon.Ordinary.defs.append(pattern) elt=self.color1.fill(elt) newelt=SVGdraw.group() newelt.addElement(elt) newbase=SVGdraw.rect(x=-blazon.Ordinary.FESSPTX, y=-blazon.Ordinary.FESSPTY, width=blazon.Ordinary.WIDTH, height=blazon.Ordinary.HEIGHT, fill="url(#%s)"%pattern.attributes["id"]) newelt.addElement(newbase) return newelt
def VairPattern(self): pattern=SVGdraw.SVGelement(type="pattern",attributes= {"patternContentUnits":"userSpaceOnUse", "height":"8", "id":"vair-in-pale%04d"%blazon.Ordinary.id, "patternUnits":"userSpaceOnUse", "width":"8"}) pattern.addElement(self.color1.fill(SVGdraw.rect(x="0", y="0", width="8", height="8"))) pattern.addElement(self.color2.fill(SVGdraw.SVGelement(type='path', attributes= {"d":"M0,8 l2,-2 l0,-4 l2,-2 l2,2 l0,4 l2,2 z"}))) self.color="vair-in-pale%04d"%blazon.Ordinary.id blazon.Ordinary.id+=1 return pattern
def writeScale( self ): """write scales.""" current_x = self.mScaleX current_y = self.mScaleY + self.mScaleHeight nboxes = len(self.mColourThresholds) # box size for legend in x-direction # subtract size of right-most axis label so that it takes the # same width as self.mDataWidth. box_size_x = math.ceil( (self.mDataWidth - (self.mScaleFontSize * len(self.mFormatNumberLegend % self.mColourThresholds[-1]))) / nboxes ) # change font size such that it labels will fit between tick-marks self.mScaleFontSize = min( self.mScaleFontSize, (box_size_x * self.mScaleNumTicks * 1.5) / len(self.mFormatNumberLegend % self.mColourThresholds[-1]) ) for x in range(nboxes): e = SVGdraw.rect( current_x, current_y, box_size_x, self.mScaleBoxSizeY, fill = "rgb(%i,%i,%i)" % self.mColours[x], stroke = "rgb(%i,%i,%i)" % self.mColours[x]) self.addElement(e) if x % self.mScaleNumTicks == 0: e = SVGdraw.line( current_x, current_y, current_x, current_y + self.mScaleBoxSizeY, stroke = "rgb(%i,%i,%i)" % BLACK, stroke_width = 5) self.addElement(e) e = SVGdraw.text( current_x, current_y - self.mScaleBoxSizeY, self.mFormatNumberLegend % self.mColourThresholds[x], self.mScaleFontSize, self.mScaleFont, stroke = "rgb(%i,%i,%i)" % BLACK, text_anchor = "start") self.addElement(e) current_x += box_size_x
def fill(self,elt): pattern=SVGdraw.SVGelement('pattern',attributes= {"width":"8", "height":"16", "patternUnits":"userSpaceOnUse", "patternContentUnits":"userSpaceOnUse", "id":"counter-vair%04d"%blazon.Ordinary.id}) blazon.Ordinary.id+=1 pattern.addElement(self.color1.fill(SVGdraw.rect(x="0", y="0", width="8", height="18"))) pattern.addElement(self.color2.fill(SVGdraw.SVGelement('path', attributes={"d": "M0,8 l2,-2 l0,-4 l2,-2 l2,2 l0,4 l2,2 l-2,2 l0,4 l-2,2 l-2,-2 l0,-4 z"}))) elt.attributes["fill"]="url(#%s)"%pattern.attributes["id"] blazon.Ordinary.defs.append(pattern) return elt
def build(self): spos = self._first.position()[1] epos = self._last.position()[1] if spos > epos: (self._first, self._last) = (self._last, self._first) sp = self._first.position('n') ep = self._last.position('s') r = UNIT / 2 w = self._first.extent()[0] + UNIT h = ep[1] - sp[1] + UNIT x = sp[0] - w / 2 y = sp[1] - UNIT / 2 self._widget = SVG.rect(x, y, w, h, self._fillcolor, self._strokecolor, self._parent.strokewidth()) self._widget.attributes['rx'] = r self._widget.attributes['ry'] = r self._widget.attributes['opacity'] = '0.5' self._extent = (w, h)
def build(self): self._position = self._parent.position() x = self._position[0] + (self._w - self._tw) / 2 y = self._position[1] r = UNIT / 2 rect = SVG.rect(x, y, self._tw, self._h, self._parent.fillcolor(), self._parent.strokecolor(), self._parent.strokewidth()) rect.attributes['rx'] = r rect.attributes['ry'] = r text = SVG.text(self._position[0] + +self._w / 2, self._position[1] + self._h / 2 + UNIT / 6, "/%s" % self._title.encode('utf-8'), self._parent.fontsize(), self._parent.fontname()) text.attributes['style'] = 'text-anchor: middle' name = self._title.encode('utf-8').replace('/', '') g = SVG.group('grp%s' % name, elements=[rect, text]) href = Href(self._parent.urlbase()) self._link = SVG.link(plink(href.browser(self._title)), elements=[g])
def doGrid(self, canvas, rows, verticalOffset, partHeight, columns, horizontalOffset, partWidth, gridsize, lineColor, fillColor, penWidth): polySize = str(gridsize) + self.units for polyRow in range(0, rows): polyTop = verticalOffset + polyRow * partHeight polyTopStr = str(polyTop) + self.units #do stuff for hexagons rowcolumns = columns rowoffset = 0 if self.type == 'hex': if polyRow % 2 == 0: if (self.width - (horizontalOffset + self.rightMargin - .01)) >= ( columns * partWidth + gridsize): rowcolumns = columns + 1 else: rowoffset = gridsize / 2 + gridsize / 4 for polyColumn in range(0, rowcolumns): polyLeft = horizontalOffset + polyColumn * partWidth polyLeft += rowoffset polyLeftStr = str(polyLeft) + self.units if self.type == 'hex': gridshape = hexagon(gridsize, polyLeft, polyTop, self.units, stroke=lineColor, fill=fillColor, stroke_width=penWidth) else: gridshape = SVGdraw.rect(polyLeftStr, polyTopStr, polySize, polySize, stroke=lineColor, fill=fillColor, stroke_width=penWidth) canvas.addElement(gridshape) return canvas
def getElements(self, x, y, map_node2height ): elements = [] for n in self.mTree.get_terminals(): t = self.mTree.node(n).data.taxon if t not in self.mMapId2Cluster: continue cluster = self.mMapId2Cluster[t] if cluster not in self.mMapCluster2Colour: self.mMapCluster2Colour[cluster] = COLOURS[len(self.mMapCluster2Colour) % len(COLOURS) ] colour = self.mMapCluster2Colour[cluster] elements.append( SVGdraw.rect( x, y + map_node2height[n] - self.mBoxWidth / 2, self.mBoxWidth, self.mBoxWidth, stroke = "rgb(%i,%i,%i)" % colour, fill = "rgb(%i,%i,%i)" % colour) ) return elements
def getElements( self, node_id, x, y ): e = [] colour = self.getColour( node_id, x, y ) if self.mPlotSymbol == "circle": e.append( SVGdraw.circle( x + self.mFontSize / 2, y, self.mFontSize/2, stroke = "rgb(%i,%i,%i)" % BLACK, fill = "rgb(%i,%i,%i)" % colour) ) elif self.mPlotSymbol == "square": e.append( SVGdraw.rect( x, y-self.mFontSize/2, self.mFontSize, self.mFontSize, stroke = "rgb(%i,%i,%i)" % BLACK, fill = "rgb(%i,%i,%i)" % colour) ) return e
def build(self): self._position = self._parent.position() x = self._position[0]+(self._w-self._tw)/2 y = self._position[1] r = UNIT/2 rect = SVG.rect(x,y,self._tw,self._h, self._parent.fillcolor(), self._parent.strokecolor(), self._parent.strokewidth()) rect.attributes['rx'] = r rect.attributes['ry'] = r text = SVG.text(self._position[0]++self._w/2, self._position[1]+self._h/2+UNIT/6, "/%s" % self._title.encode('utf-8'), self._parent.fontsize(), self._parent.fontname()) text.attributes['style'] = 'text-anchor: middle' name = self._title.encode('utf-8').replace('/','') g = SVG.group('grp%s' % name, elements=[rect, text]) href = Href(self._parent.urlbase()) self._link = SVG.link(plink(href.browser(self._title)), elements=[g])
def build(self): spos = self._first.position()[1] epos = self._last.position()[1] if spos > epos: (self._first, self._last) = (self._last, self._first) sp = self._first.position('n') ep = self._last.position('s') r = UNIT/2 w = self._first.extent()[0] + UNIT h = ep[1] - sp[1] + UNIT x = sp[0] - w/2 y = sp[1] - UNIT/2 self._widget = SVG.rect(x,y,w,h, self._fillcolor, self._strokecolor, self._parent.strokewidth()) self._widget.attributes['rx'] = r self._widget.attributes['ry'] = r self._widget.attributes['opacity'] = str(self._opacity/100.0) self._extent = (w,h)
def svgout(self,stroke_width=0.3,scale=20,circle_radius=0.3, startat=None,coloriter=None,crossings=True,circradius=None,circscale=1): # if circradius is some positive number, try to draw a circular(!) diagram # circscale is how much to scale the y-dimension by (how thick a circle) # try: # if type(SVGdraw)!=type(__builtins__): # raise Exception("SVGdraw not a module?") # return None # except NameError: # raise Exception("No SVGDraw found") # return None cols=['#000000', '#800000', '#808000', '#008080', '#000080', '#ff2000', '#ffff20', '#20ffff', '#0020ff', '#ff0080', '#ff8000', '#8000ff', '#80ff00'] if circradius: sz=(2*self.ymax*circscale+2+2*circradius) svg=SVGdraw.svg(width="%dpx"%(sz*scale), height="%dpx"%(sz*scale), viewBox=[-sz+self.xmodulus/2.0, -sz, 2*sz, 2*sz]) def transform(x,y): # Have to flip it over... r=self.ymax*circscale+circradius-y*circscale theta=2*math.pi*x/self.xmodulus-math.pi return [sz/2+r*math.cos(theta), sz/2+r*math.sin(theta)] else: svg=SVGdraw.svg(width="%dpx"%((self.xmodulus+2)*scale), height="%dpx"%((self.ymax+2)*scale), viewBox=[-1, -1, self.xmodulus+2, self.ymax+2]) def transform(x,y): return [x,y] defs=SVGdraw.defs(id="defs") plusmask=SVGdraw.SVGelement("mask", attributes={"id":"plusmask"}) minusmask=SVGdraw.SVGelement("mask", attributes={"id":"minusmask"}) if circradius: sz=1+2*self.ymax*circscale+2*circradius # Whatever, something big. r=SVGdraw.rect(x=-sz, y=-sz, width=sz*2,height=sz*2,fill='white') else: r=SVGdraw.rect(x=-1,y=-1,width=self.xmodulus+2,height=self.ymax+2, fill='white') plusmask.addElement(r) minusmask.addElement(r) defs.addElement(plusmask) defs.addElement(minusmask) svg.addElement(defs) maingroup=SVGdraw.group(id="main") # I've come to expect them this way up... maingroup.attributes['transform']='scale(1,-1) translate(0,%d)'% \ (-self.ymax) svg.addElement(maingroup) # Positive slopes and negative slopes. plus=SVGdraw.group(id="plus",mask="url(#plusmask)") minus=SVGdraw.group(id="minus",mask="url(#minusmask)") maingroup.addElement(plus) maingroup.addElement(minus) circgroup=SVGdraw.group(id="circgroup") maingroup.addElement(circgroup) strands=self.strands(self.pivots[0]) circuit=None if coloriter is None: if len(strands)>1: # Multistranded; color it by strand. def multicoloriter(): counter=0 lastcircuit=None while True: if circuit != lastcircuit: lastcircuit=circuit counter+=1 yield cols[counter%len(cols)] coloriter=multicoloriter() else: def singlecoloriter(): # for singlestranders! colcounter=0 colordiv=len(self.pivots)/6 while True: yield cols[int(colcounter/colordiv)%len(cols)] colcounter+=1 coloriter=singlecoloriter() for circuit in strands: # If there's a startat parameter, and it appears in this list, # slosh the list around so it's first if startat and startat in circuit: ind=circuit.index(startat) circuit=circuit[ind:]+circuit[0:ind] for i in range(0,len(circuit)): here=circuit[i] nxt=circuit[(i+1)%len(circuit)] col=coloriter.next() if type(col)==int: # let iterator generate indexes col=cols[col%len(cols)] if circradius: path=[here,nxt] else: path=self.pathbetween(here,nxt) pathstring="" for j in range(0,len(path),2): # Had hoped that transform() would have been enough, but we need # to go through all the intermediate lattice-points when doing # circular plots, to curve around in the right direction. if circradius: betweens=self.pointsbetween(path[j],path[j+1]) pathstring+=" M %f %f "%tuple(transform(path[j].x,path[j].y)) for k in range(0,len(betweens)): pathstring+=" L %f %f "% \ tuple(transform(betweens[k].x,betweens[k].y)) pathstring+="L %f %f "% \ tuple(transform(path[j+1].x, path[j+1].y)) else: pathstring+=" M %f %f L %f %f"% \ (tuple(transform(path[j].x,path[j].y)+ transform(path[j+1].x,path[j+1].y))) pathelt=SVGdraw.path(pathstring,stroke_width=stroke_width, stroke=col,fill="none") if self.slopebetween(here,nxt)>0: plus.addElement(pathelt) else: minus.addElement(pathelt) for i in self.pivots: cr=transform(i.x, i.y) c=SVGdraw.circle(cx=cr[0], cy=cr[1], r=circle_radius, fill='black') circgroup.addElement(c) if not circradius: # Mark the wraparound point. circgroup.addElement(SVGdraw.path("M 0 -1 l 0 %d M %d -1 l 0 %d"% \ (self.ymax+2,self.xmodulus, self.ymax+2), stroke='black', stroke_width=0.03)) # Somehow I want to *note* when a knot is single-strand or # multistrand. circgroup.addElement(SVGdraw.text(x=0.2,y=0, text=str(len(strands)), fill='#000408', font_size=1, font_family='sans-serif', transform='scale(1,-1)')) if crossings: # Try multistrand crossings? (not working right) # Need *ALL* the crossing points though. oncircuit=[] for circuit in strands: oncircuit.extend(self.oncircuit(circuit)) masked=set() over=0 masks=[minusmask,plusmask] # How about this? For each horizontal line _that has intersections on it_, # all crossings go in one direction, and that direction alternates. # # How do we find those lines? points=[] for circuit in strands: for i in range(0,len(circuit)): here=circuit[i] nxt=circuit[(i+1)%len(circuit)] points+=self.pointsbetween(here,nxt) heights=[] howmanyhits=dict() for p in points: howmanyhits[p]=howmanyhits.get(p,0)+1 howmanyhits=[(p,howmanyhits[p]) for p in howmanyhits.keys()] howmanyhits=filter((lambda x: x[1]>1), howmanyhits) heights=[x[0].y for x in howmanyhits] heights.sort() # No "sort unique" so just keep track of the last one we saw and skip it. # DOESN'T WORK EITHER BUT BETTER THAN BEFORE XXXXXX # (testing with python ./knots.py -l 18 17 6 32 6 37) Works with more # symmetrical designs. last=None for h in heights: if h==last: continue last=h mask=masks[over] over=1-over for x in range(0,self.xmodulus,2): p=Point((x if not h%2 else x+1),h,self) if p in self.pivots: continue # Skip pivot-points. tp1=transform(p.x-0.5, p.y-0.5) tp2=transform(p.x-0.5, p.y+0.5) tp3=transform(p.x+0.5, p.y+0.5) tp4=transform(p.x+0.5, p.y-0.5) tp=transform(p.x, p.y) if circradius: r=SVGdraw.circle(fill="black", cx=tp[0], cy=tp[1], r=0.6) else: angle=45 r=SVGdraw.polygon(fill="black", points=[tp1,tp2,tp3,tp4], transform="rotate(%f,%f,%f)"% \ (angle, tp[0], tp[1])) mask.addElement(r) # maingroup.addElement(r) # If it's on the edge, duplicate it on the other side # for ease of viewing. if p.x==0 and not circradius: mask.addElement(SVGdraw.rect(x=self.xmodulus-0.5, y=p.y-0.5, width=1, height=1, fill="#111", transform= "rotate(45,%d,%d)"% (self.xmodulus,p.y))) return svg
def toSVG(self): #modification du maximum en X : depend du nombre d'element global XMAX XMAX = len(self.infos)*(BAR_THICKNESS+SPACE) # creation du document doc=SVGdraw.drawing() svg=SVGdraw.svg(None, '100%','100%') # creation des patterns pour les axes et la grille axeX = SVGdraw.pattern(id="axeX",width="20",height="10",patternUnits="userSpaceOnUse") axeX.addElement(SVGdraw.path("M 0 0, L 0 10","none","black","0.25")) axeX.addElement(SVGdraw.path("M 10 10, V 5","none","lightgray","0.25")) axeY = SVGdraw.pattern(id="axeY",width="10",height="20",patternUnits="userSpaceOnUse") axeY.addElement(SVGdraw.path("M 0 0, L 10 0","none","black","0.25")) axeY.addElement(SVGdraw.path("M 5 10, L 10 10","none","lightgray","0.25")) grid = SVGdraw.pattern(id="grid",width="10",height="10",patternUnits="userSpaceOnUse") grid.addElement(SVGdraw.path("M 0 0, L 10 0, L 10 10,L 0 10, L 0 0","none","lightgray","0.25")) defs=SVGdraw.defs() defs.addElement(axeX) defs.addElement(axeY) defs.addElement(grid) svg.addElement(defs) group=SVGdraw.group(transform="translate(130,130) scale(1,-1)") # dessin de la grille de fond group.addElement(SVGdraw.rect(0,0,XMAX,YMAX,"url(#grid)","lightgray","0.25")) # dessin des axes group.addElement(SVGdraw.rect(0,-10,XMAX,10,"url(#axeX)")) group.addElement(SVGdraw.rect(-10,0,10,YMAX,"url(#axeY)")) group.addElement(SVGdraw.line(0,0,XMAX,0,"black",1)) group.addElement(SVGdraw.line(0,0,0,YMAX,"black",1)) # dessin des fleches des axes group.addElement(SVGdraw.polygon([[-3,YMAX],[3,YMAX],[0,YMAX+10]], "black","white")) group.addElement(SVGdraw.polygon([[XMAX,-3],[XMAX,3],[XMAX+10,0]], "black","white")) textgroup=SVGdraw.group(transform="scale(1,-1)") # graduations for y in range(0,YMAX+STEP,STEP): textgroup.addElement(SVGdraw.text(-STEP,y, str(y), 8, text_anchor="middle", transform="translate(0,%d)"%(-y*2))) textgroup.addElement(SVGdraw.text(0,YMAX+SPACE, r"%", 8, transform="translate(0,%d)"%(-(YMAX+SPACE)*2))) # ajout de la legende principale legendText = "Repertoire %s - taille %.02f ko"%(self.rootName,float(self.totalSize/1024.0)) textgroup.addElement(SVGdraw.text(XMAX,YMAX+3*SPACE, legendText,12, "verdana", text_anchor="end", fill="darkblue",transform="translate(0,%d)"%(-(YMAX+3*SPACE)*2))) group.addElement(textgroup) # tri des elements selon la taille occupee self.infos.sort(self.tupleCmp) xincr=0 #self.infos for (name,size) in self.infos: # calcul du pourcentage de place occupe pourcent = (100.0*float(size))/float(self.totalSize) height=int(pourcent*YMAX/100); # insertion du texte de l'emplacement sur le disque et de la taille occupee en Ko legendText = "%s (%### ###.02f ko)"%(name,float(size/1024.0)) legend = SVGdraw.text(xincr+BAR_THICKNESS/2, -10,legendText,8,"verdana",text_anchor="begin",fill="blue") legend.attributes["transform"]="scale(1,-1) translate(0,20) rotate(45,%d,-10)"%(xincr+BAR_THICKNESS/2) group.addElement(legend) #insertion de la barre representant le pourcentage group.addElement(SVGdraw.rect(xincr,0,BAR_THICKNESS, height,"green","black",opacity=0.5)) #insertion de la taille en pourcentage a gauche de la barre pourcentText=SVGdraw.text(xincr+BAR_THICKNESS/2, height+SPACE,"%02.01f%% "%pourcent,6, "arial", text_anchor="middle", fill="black") pourcentText.attributes["transform"]="scale(1,-1) translate(0,-%d)"%((height+SPACE)*2) group.addElement(pourcentText) # augmentation du l'abscisse en X xincr = xincr+BAR_THICKNESS+SPACE svg.addElement(group) doc.setSVG(svg) doc.toXml(self.svgURL)
def addDuplication( self, entries, map_gene2pos, height, url = None, with_separator=True, link_to_previous = False, quality2symbol = {}, quality2mask = {}): """add a dot in row/col.""" mi, ma = None, 0 pos = bisect.bisect( self.mColourThresholds, height ) master_colour = self.mColours[pos] chrs = {} points = [] if not link_to_previous: self.mPreviousPoints = {} ######################################################## ######################################################## ######################################################## ## convert gene list to a set of points ######################################################## for species, transcript, gene, quality in entries: chr, strand, first_res, last_res = map_gene2pos[gene] chrs[chr] = 1 pos1 = self.getPosition( chr, strand, first_res ) pos2 = self.getPosition( chr, strand, last_res ) a = min( pos1, pos2 ) b = max( pos1, pos2 ) if mi == None: mi = a else: mi = min(a, mi) ma = max(b, ma) points.append( (pos1, pos2, gene, quality, chr) ) ######################################################## ######################################################## ######################################################## ## decide whether we need to increment the radius ######################################################## cis = len(chrs) == 1 old_radius = self.mRadius is_overlap = False if cis: if not self.mLastChr: self.mLastChr = chr if chr != self.mLastChr: self.mRadius = self.mRadiusFallBack self.mLastMax = ma self.mPreviousMax = ma self.mLastChr = chr else: if self.mPreviousMax + self.mMinDistance > mi: ## overlap due to close proximitiy self.mRadius += self.mRadiusIncrement if with_separator: self.addSeparator() ## true overlap if self.mPreviousMax > mi: is_overlap = True elif self.mLastMax + self.mMinDistance > mi: pass else: self.mRadius = self.mRadiusFallBack self.mLastMax = max(self.mLastMax, ma) else: if self.mLastMax > mi: self.mRadius += self.mRadiusIncrement if with_separator: self.addSeparator() self.mPreviousMin = mi self.mPreviousMax = ma self.mPreviousCis = cis self.mRadiusMax = max(self.mRadius, self.mRadiusMax) ######################################################## ######################################################## ######################################################## ## draw points ######################################################## link_colour = master_colour link_rad_width = self.mLinkRadStrokeWidth link_arc_width = self.mLinkArcStrokeWidth new_points = {} for pos1, pos2, gene, quality, chr in points: angle = self.getAngle( (pos1 + pos2) / 2 ) x,y = self.getPosOnArc( angle, self.mRadius ) try: symbol = quality2symbol[quality] except KeyError: symbol = "rect" if quality in quality2mask: colour = self.mLinkColourSymbolMasked link_colour = self.mLinkColourMasked link_rad_width = self.mLinkStrokeWidthMasked link_arc_width = self.mLinkStrokeWidthMasked else: colour = master_colour if gene in self.mPreviousPoints: continue new_points[gene] = (x, y, angle, quality, chr) if symbol == "circle": ee = SVGdraw.circle( x, y, self.mLinkSymbolSize, fill = "rgb(%i,%i,%i)" % colour, stroke="black", stroke_width = self.mLinkStrokeWidthSymbol ) elif symbol == "rect": ee = SVGdraw.rect( x-self.mLinkSymbolSize/2, y-self.mLinkSymbolSize/2, self.mLinkSymbolSize, self.mLinkSymbolSize, fill = "rgb(%i,%i,%i)" % colour, stroke="black", stroke_width = self.mLinkStrokeWidthSymbol ) if url: e = SVGdraw.link( url % gene ) e.addElement( ee ) else: e = ee self.addWheelElement( e ) ######################################################## ######################################################## ######################################################## ## write all arcs in between old points and new points ## cis: circular arc ## trans: radial arc ######################################################## angles = [] for x1,y1,angle1,quality1,chr1 in new_points.values(): ## reduce clutter by not writing arc to the same angle for x2,y2,angle2,quality2,chr2 in self.mPreviousPoints.values(): for a in angles: if a - self.mAngleResolution < angle2 < a + self.mAngleResolution: break else: angles.append( angle2 ) d = SVGdraw.pathdata( x1, y1 ) if chr1 == chr2: d.relellarc( self.mRadius, self.mRadius, 0, 0, 1, x2-x1, y2-y1 ) link_width = link_rad_width else: d.relellarc( self.mRadius * 2, self.mRadius * 2, 0, 0, 0, x2-x1, y2-y1 ) link_width = link_arc_width e = SVGdraw.path( d, fill = "none", stroke = "rgb(%i,%i,%i)" % link_colour, stroke_width = link_width ) self.addWheelElement(e, self.mPlaneLinks) ## plot lines between new points new_genes = new_points.keys() for g1 in range(len(new_genes)-1): x1,y1,angle1,quality1,chr1 = new_points[new_genes[g1]] for g2 in range(g1+1, len(new_genes)): x2,y2,angle2,quality2,chr2 = new_points[new_genes[g2]] for a in angles: if a - self.mAngleResolution < angle2 < a + self.mAngleResolution: break else: angles.append( angle2 ) d = SVGdraw.pathdata( x1, y1 ) if chr1 == chr2: d.relellarc( self.mRadius, self.mRadius, 0, 0, 1, x2-x1, y2-y1 ) link_width = link_rad_width else: d.relellarc( self.mRadius * 2, self.mRadius * 2, 0, 0, 0, x2-x1, y2-y1 ) link_width = link_arc_width e = SVGdraw.path( d, fill = "none", stroke = "rgb(%i,%i,%i)" % link_colour, stroke_width = link_width ) self.addWheelElement(e, self.mPlaneLinks) ## add new points to old points for k, v in new_points.items(): self.mPreviousPoints[k] = v
def doGrid(self, canvas, rows, verticalOffset, partHeight, columns, horizontalOffset, partWidth, gridsize, lineColor, fillColor, penWidth): polySize = str(gridsize) + self.units group = SVGdraw.group() group.attributes['id'] = 'map' group.attributes['rows'] = rows group.attributes['columns'] = columns group.attributes['cells'] = rows * columns # for id index = 0 #print "%s COLUMNS" % columns #print "%s ROWS" % rows for polyRow in range(0, rows): polyTop = verticalOffset + polyRow*partHeight polyTopStr = str(polyTop) + self.units #do stuff for hexagons rowcolumns = columns rowoffset = 0 if self.type == 'hex' or self.type == 'hexpath': if polyRow % 2 == 0: if (self.width-(horizontalOffset+self.rightMargin-.01)) >= (columns*partWidth + gridsize): rowcolumns = columns + 1 else: rowoffset = gridsize/2 + gridsize/4 for polyColumn in range(0, rowcolumns): polyLeft = horizontalOffset + polyColumn*partWidth polyLeft += rowoffset polyLeftStr = str(polyLeft) + self.units if self.type == 'hex': gridshape = hexagon(gridsize, polyLeft, polyTop, self.units, stroke=lineColor, fill=fillColor, stroke_width=penWidth) elif self.type == 'hexpath': gridshape = hexpath(gridsize, polyLeft, polyTop, self.units, stroke=lineColor, fill=fillColor, stroke_width=penWidth) else: gridshape = SVGdraw.rect(polyLeftStr, polyTopStr, polySize, polySize, stroke=lineColor, fill=fillColor, stroke_width=penWidth) """ positions = { 'cell_NW': (index - rows), 'cell_N' : (index - rows * 2), 'cell_NE': (index - rows + 1), 'cell_SE': (index + rows), 'cell_S' : (index + rows * 2), 'cell_SW': (index + rows - 1) } """ gridshape.attributes['id'] = 'cell_' + str(index) neighbors_class = 'neighbors-' id = index - columns if id >= 0: #gridshape.attributes['cell_NW'] = "cell_" + str(id) neighbors_class += "cell_" + str(id) + '-' id = index - columns * 2 if id >= 0: #gridshape.attributes['cell_N'] = "cell_" + str(id) neighbors_class += "cell_" + str(id) + '-' id = index - columns + 1 if id >= 0: #gridshape.attributes['cell_NE'] = "cell_" + str(id) neighbors_class += "cell_" + str(id) + '-' id = index + columns - 1 if id <= rows * columns: #gridshape.attributes['cell_SE'] = "cell_" + str(id) neighbors_class += "cell_" + str(id) + '-' id = index + columns * 2 if id <= rows * columns: #gridshape.attributes['cell_S'] = "cell_" + str(id) neighbors_class += "cell_" + str(id) + '-' id = index + columns if id <= rows * columns: #gridshape.attributes['cell_SW'] = "cell_" + str(id) neighbors_class += "cell_" + str(id) + '-' gridshape.attributes['class'] = neighbors_class index = index + 1 group.addElement(gridshape) canvas.addElement(group) return canvas
def svgout(self, stroke_width=0.3, scale=20, circle_radius=0.3, startat=None, coloriter=None, crossings=True, circradius=None, circscale=1): # if circradius is some positive number, try to draw a circular(!) diagram # circscale is how much to scale the y-dimension by (how thick a circle) # try: # if type(SVGdraw)!=type(__builtins__): # raise Exception("SVGdraw not a module?") # return None # except NameError: # raise Exception("No SVGDraw found") # return None cols = [ '#000000', '#800000', '#808000', '#008080', '#000080', '#ff2000', '#ffff20', '#20ffff', '#0020ff', '#ff0080', '#ff8000', '#8000ff', '#80ff00' ] if circradius: sz = (2 * self.ymax * circscale + 2 + 2 * circradius) svg = SVGdraw.svg( width="%dpx" % (sz * scale), height="%dpx" % (sz * scale), viewBox=[-sz + self.xmodulus / 2.0, -sz, 2 * sz, 2 * sz]) def transform(x, y): # Have to flip it over... r = self.ymax * circscale + circradius - y * circscale theta = 2 * math.pi * x / self.xmodulus - math.pi return [ sz / 2 + r * math.cos(theta), sz / 2 + r * math.sin(theta) ] else: svg = SVGdraw.svg( width="%dpx" % ((self.xmodulus + 2) * scale), height="%dpx" % ((self.ymax + 2) * scale), viewBox=[-1, -1, self.xmodulus + 2, self.ymax + 2]) def transform(x, y): return [x, y] defs = SVGdraw.defs(id="defs") plusmask = SVGdraw.SVGelement("mask", attributes={"id": "plusmask"}) minusmask = SVGdraw.SVGelement("mask", attributes={"id": "minusmask"}) if circradius: sz = 1 + 2 * self.ymax * circscale + 2 * circradius # Whatever, something big. r = SVGdraw.rect(x=-sz, y=-sz, width=sz * 2, height=sz * 2, fill='white') else: r = SVGdraw.rect(x=-1, y=-1, width=self.xmodulus + 2, height=self.ymax + 2, fill='white') plusmask.addElement(r) minusmask.addElement(r) defs.addElement(plusmask) defs.addElement(minusmask) svg.addElement(defs) maingroup = SVGdraw.group(id="main") # I've come to expect them this way up... maingroup.attributes['transform']='scale(1,-1) translate(0,%d)'% \ (-self.ymax) svg.addElement(maingroup) # Positive slopes and negative slopes. plus = SVGdraw.group(id="plus", mask="url(#plusmask)") minus = SVGdraw.group(id="minus", mask="url(#minusmask)") maingroup.addElement(plus) maingroup.addElement(minus) circgroup = SVGdraw.group(id="circgroup") maingroup.addElement(circgroup) strands = self.strands(self.pivots[0]) circuit = None if coloriter is None: if len(strands) > 1: # Multistranded; color it by strand. def multicoloriter(): counter = 0 lastcircuit = None while True: if circuit != lastcircuit: lastcircuit = circuit counter += 1 yield cols[counter % len(cols)] coloriter = multicoloriter() else: def singlecoloriter(): # for singlestranders! colcounter = 0 colordiv = len(self.pivots) / 6 while True: yield cols[int(colcounter / colordiv) % len(cols)] colcounter += 1 coloriter = singlecoloriter() for circuit in strands: # If there's a startat parameter, and it appears in this list, # slosh the list around so it's first if startat and startat in circuit: ind = circuit.index(startat) circuit = circuit[ind:] + circuit[0:ind] for i in range(0, len(circuit)): here = circuit[i] nxt = circuit[(i + 1) % len(circuit)] col = coloriter.next() if type(col) == int: # let iterator generate indexes col = cols[col % len(cols)] if circradius: path = [here, nxt] else: path = self.pathbetween(here, nxt) pathstring = "" for j in range(0, len(path), 2): # Had hoped that transform() would have been enough, but we need # to go through all the intermediate lattice-points when doing # circular plots, to curve around in the right direction. if circradius: betweens = self.pointsbetween(path[j], path[j + 1]) pathstring += " M %f %f " % tuple( transform(path[j].x, path[j].y)) for k in range(0, len(betweens)): pathstring+=" L %f %f "% \ tuple(transform(betweens[k].x,betweens[k].y)) pathstring+="L %f %f "% \ tuple(transform(path[j+1].x, path[j+1].y)) else: pathstring+=" M %f %f L %f %f"% \ (tuple(transform(path[j].x,path[j].y)+ transform(path[j+1].x,path[j+1].y))) pathelt = SVGdraw.path(pathstring, stroke_width=stroke_width, stroke=col, fill="none") if self.slopebetween(here, nxt) > 0: plus.addElement(pathelt) else: minus.addElement(pathelt) for i in self.pivots: cr = transform(i.x, i.y) c = SVGdraw.circle(cx=cr[0], cy=cr[1], r=circle_radius, fill='black') circgroup.addElement(c) if not circradius: # Mark the wraparound point. circgroup.addElement(SVGdraw.path("M 0 -1 l 0 %d M %d -1 l 0 %d"% \ (self.ymax+2,self.xmodulus, self.ymax+2), stroke='black', stroke_width=0.03)) # Somehow I want to *note* when a knot is single-strand or # multistrand. circgroup.addElement( SVGdraw.text(x=0.2, y=0, text=str(len(strands)), fill='#000408', font_size=1, font_family='sans-serif', transform='scale(1,-1)')) if crossings: # Try multistrand crossings? (not working right) # Need *ALL* the crossing points though. oncircuit = [] for circuit in strands: oncircuit.extend(self.oncircuit(circuit)) masked = set() over = 0 masks = [minusmask, plusmask] # How about this? For each horizontal line _that has intersections on it_, # all crossings go in one direction, and that direction alternates. # # How do we find those lines? points = [] for circuit in strands: for i in range(0, len(circuit)): here = circuit[i] nxt = circuit[(i + 1) % len(circuit)] points += self.pointsbetween(here, nxt) heights = [] howmanyhits = dict() for p in points: howmanyhits[p] = howmanyhits.get(p, 0) + 1 howmanyhits = [(p, howmanyhits[p]) for p in howmanyhits.keys()] howmanyhits = filter((lambda x: x[1] > 1), howmanyhits) heights = [x[0].y for x in howmanyhits] heights.sort() # No "sort unique" so just keep track of the last one we saw and skip it. # DOESN'T WORK EITHER BUT BETTER THAN BEFORE XXXXXX # (testing with python ./knots.py -l 18 17 6 32 6 37) Works with more # symmetrical designs. last = None for h in heights: if h == last: continue last = h mask = masks[over] over = 1 - over for x in range(0, self.xmodulus, 2): p = Point((x if not h % 2 else x + 1), h, self) if p in self.pivots: continue # Skip pivot-points. tp1 = transform(p.x - 0.5, p.y - 0.5) tp2 = transform(p.x - 0.5, p.y + 0.5) tp3 = transform(p.x + 0.5, p.y + 0.5) tp4 = transform(p.x + 0.5, p.y - 0.5) tp = transform(p.x, p.y) if circradius: r = SVGdraw.circle(fill="black", cx=tp[0], cy=tp[1], r=0.6) else: angle = 45 r=SVGdraw.polygon(fill="black", points=[tp1,tp2,tp3,tp4], transform="rotate(%f,%f,%f)"% \ (angle, tp[0], tp[1])) mask.addElement(r) # maingroup.addElement(r) # If it's on the edge, duplicate it on the other side # for ease of viewing. if p.x == 0 and not circradius: mask.addElement( SVGdraw.rect(x=self.xmodulus - 0.5, y=p.y - 0.5, width=1, height=1, fill="#111", transform="rotate(45,%d,%d)" % (self.xmodulus, p.y))) return svg
def doGrid(self, canvas, rows, verticalOffset, partHeight, columns, horizontalOffset, partWidth, gridsize, lineColor, fillColor, penWidth): polySize = str(gridsize) + self.units polyCount = 0 thebes = SVGdraw.text(20, 20, "Thebes") canvas.addElement(thebes) name = SVGdraw.text(200, 20, "Map For " + self.name) canvas.addElement(name) warning = SVGdraw.text(500, 20, "NOT IN GAME") canvas.addElement(warning) for polyRow in range(0, rows): polyTop = verticalOffset + polyRow*partHeight polyTopStr = str(polyTop) + self.units #do stuff for hexagons rowcolumns = columns rowoffset = 0 if self.type == 'hex': if polyRow % 2 == 0: if (self.width-(horizontalOffset+self.rightMargin-.01)) >= (columns*partWidth + gridsize): rowcolumns = columns + 1 else: rowoffset = gridsize/2 + gridsize/4 for polyColumn in range(0, rowcolumns): polyLeft = horizontalOffset + polyColumn*partWidth polyLeft += rowoffset polyLeftStr = str(polyLeft) + self.units polyCount += 1 if self.type == 'hex': nodeID = 100 * polyColumn + polyRow if (nodeID in self.nodes) or (self.drawAll): gridshape = hexagon(gridsize, polyLeft, polyTop, self.units, stroke=lineColor, fill=fillColor, stroke_width=penWidth) if self.drawNumbers: if (polyRow < 10): polyRowStr = "0" + str(polyRow) else: polyRowStr = str(polyRow) gridtext = SVGdraw.text(90 * (polyLeft + partHeight - .10), 90 * (polyTop + partHeight - .15),str(polyColumn)+polyRowStr,font_size=11); canvas.addElement(gridtext) canvas.addElement(gridshape) if nodeID in self.nodes: if self.drawDesc: gridname = SVGdraw.text(90 * (polyLeft + partHeight - .16), 90 * (polyTop + partHeight + .13),self.nodes[nodeID]["name"],font_size=9); canvas.addElement(gridname) griddesc = SVGdraw.text(90 * (polyLeft + partHeight - .2), 90 * (polyTop + partHeight + .02),self.nodes[nodeID]["desc"],font_size=8); canvas.addElement(griddesc) else: gridname = SVGdraw.text(90 * (polyLeft + partHeight - .16), 90 * (polyTop + partHeight + .02),self.nodes[nodeID]["name"],font_size=12); canvas.addElement(gridname) else: gridshape = SVGdraw.rect(polyLeftStr, polyTopStr, polySize, polySize, stroke=lineColor, fill=fillColor, stroke_width=penWidth) canvas.addElement(gridshape) return canvas
def doGrid(self, canvas, rows, verticalOffset, partHeight, columns, horizontalOffset, partWidth, gridsize, lineColor, fillColor, penWidth): polySize = str(gridsize) + self.units group = SVGdraw.group() group.attributes['id'] = 'map' group.attributes['rows'] = rows group.attributes['columns'] = columns group.attributes['cells'] = rows * columns # for id index = 0 #print "%s rows, %s columns" % ( rows, columns ) for polyRow in range(0, rows): polyTop = verticalOffset + polyRow*partHeight polyTopStr = str(polyTop) + self.units #do stuff for hexagons rowcolumns = columns rowoffset = 0 if self.type == 'hex' or self.type == 'hexpath': if polyRow % 2 == 0: if (self.width-(horizontalOffset+self.rightMargin-.01)) >= (columns*partWidth + gridsize): rowcolumns = columns + 1 else: rowoffset = gridsize/2 + gridsize/4 for polyColumn in range(0, rowcolumns): polyLeft = horizontalOffset + polyColumn*partWidth polyLeft += rowoffset polyLeftStr = str(polyLeft) + self.units if self.type == 'hex': gridshape = hexagon(gridsize, polyLeft, polyTop, self.units, stroke=lineColor, fill=fillColor, stroke_width=penWidth) elif self.type == 'hexpath': gridshape = hexpath(gridsize, polyLeft, polyTop, self.units, stroke=lineColor, fill=fillColor, stroke_width=penWidth) else: gridshape = SVGdraw.rect(polyLeftStr, polyTopStr, polySize, polySize, stroke=lineColor, fill=fillColor, stroke_width=penWidth) """ positions = { 'cell_NW': (index - columns ), 'cell_N' : (index - columns * 2), 'cell_NE': (index - columns + 1), 'cell_SE': (index + columns ), 'cell_S' : (index + columns * 2), 'cell_SW': (index + columns - 1) } """ gridshape.attributes['id'] = 'cell_' + str(index) gridshape.attributes['row'] = str(polyRow) gridshape.attributes['col'] = str(polyColumn) neighbors_class = [ ] evenRow = (polyRow % 2 == 0) evenCol = (polyColumn % 2 == 0) id = -1 #print "i%s: polyRow=%s polyColumn=%s" % ( index, polyRow, polyColumn ) # North OK id = index - columns * 2 if id >= 0: neighbors_class.append( "N:cell_" + str(id) ) #gridshape.attributes['cell_N'] = "cell_" + str(id) # South OK id = index + columns * 2 if id <= rows * columns: #gridshape.attributes['cell_S'] = "cell_" + str(id) neighbors_class.append( "S:cell_" + str(id) ) # NorthWest OK if evenRow: if polyColumn > 0: id = (index - columns) - 1 else: id = (index - columns) if id >= 0: neighbors_class.append( "NW:cell_" + str(id) ) # NorthEst OK if polyColumn < columns: if evenRow: id = index - columns elif polyColumn < columns - 1: id = index - columns + 1 if id >= 0: neighbors_class.append( "NE:cell_" + str(id) ) #gridshape.attributes['cell_NW'] = "cell_" + str(id) # SouthEst OK if evenRow: id = index + columns else: if polyColumn < (columns - 1): id = index + columns + 1 if id <= rows * columns: neighbors_class.append( "SE:cell_" + str(id) ) #gridshape.attributes['cell_SE'] = "cell_" + str(id) # SouthWest if evenRow: if polyColumn > 0: id = index + columns - 1 else: id = index + columns if id <= rows * columns: neighbors_class.append( "SW:cell_" + str(id) ) #gridshape.attributes['cell_SW'] = "cell_" + str(id) if len(neighbors_class) > 0: gridshape.attributes['class'] = 'neighbors-' + '-'.join(neighbors_class) index = index + 1 group.addElement(gridshape) canvas.addElement(group) return canvas
def build(self): SvgBaseChangeset.build(self) (fgc, bgc) = (self._strokecolor, self._fillcolor) txc = self._textcolor if 'firstchangeset' in self._classes: (fgc, bgc) = (bgc, fgc) if 'lastchangeset' in self._classes: bgc = SvgColor('black') txc = SvgColor('white') widgets = [] if self._shape == 'circle': widgets.append(SVG.circle(self._position[0], self._position[1], self._radius, bgc, fgc, self._parent.strokewidth())) if self._enhance: (x,y) = self._position (d,hr) = (self._radius*SQRT3/2, self._radius/2) widgets.append(SVG.line(x-d,y-hr,x+d,y-hr, fgc, self._parent.strokewidth())) widgets.append(SVG.line(x-d,y+hr,x+d,y+hr, fgc, self._parent.strokewidth())) elif self._shape == 'square': r = UNIT/6 size = self._radius-r widgets.append(SVG.rect(self._position[0]-size, self._position[1]-size, 2*size, 2*size, bgc, fgc, self._parent.strokewidth())) outline.attributes['rx'] = r outline.attributes['ry'] = r elif self._shape == 'hexa': (x,y) = self._position (r,hr) = (self._radius, self._radius/2) pd = SVG.pathdata() pd.move(x,y-r) pd.line(x+r,y-hr) pd.line(x+r,y+hr) pd.line(x,y+r) pd.line(x-r,y+hr) pd.line(x-r,y-hr) pd.line(x,y-r) widgets.append(SVG.path(pd, bgc, fgc, self._parent.strokewidth())) else: raise AssertionError, \ "unsupported changeset shape (%d)" % self._revision title = SVG.text(self._position[0], self._position[1] + UNIT/6, str(self._revision), self._parent.fontsize(), self._parent.fontname()) title.attributes['style'] = 'fill:%s; text-anchor: middle' % txc.rgb() widgets.append(title) g = SVG.group('grp%d' % self._revision, elements=widgets) link = "%s/changeset/%d" % (self._parent.urlbase(), self._revision) self._link = SVG.link(link, elements=[g]) if self._revision: self._link.attributes['style'] = \ 'color: %s; background-color: %s' % \ (self._strokecolor, self._fillcolor) self._link.attributes['id'] = 'rev%d' % self._revision self._link.attributes['class'] = ' '.join(self._classes)