def draw(self, canvas): """Draw the line on the supplied canvas.""" styles = self.styles + self.arrows if config.getOptions().DEBUG: print("Drawing " + str(self.__class__) + " with styles = " + str(styles)) mypath = [self.getVisiblePath(), self.getDeformedPath(+1), self.getDeformedPath(-1)] if self.inverted: mypath = mypath[::-1] if config.getOptions().DRAFT or not self.is3D: for i in range(3): canvas.stroke(mypath[i], styles) else: ass, bs = mypath[0].intersect(mypath[1]) ass, cs = mypath[0].intersect(mypath[2]) ps = [ass[:], bs[:], cs[:]] for i in range(3): params = [] for a in range(len(ps[i])): ## TODO: better endpoint cut vetoing if (a%3)!=i: params.append(ps[i][a] - self.skipsize3D) params.append(ps[i][a] + self.skipsize3D) pathbits = mypath[i].split(params) on = True for pathbit in pathbits: if on: canvas.stroke(pathbit, styles) on = not on for l in self.labels: l.draw(canvas)
def draw(self, canvas): """Draw the line on the supplied canvas.""" styles = self.styles + self.arrows if config.getOptions().DEBUG: print("Drawing " + str(self.__class__) + " with styles = " + str(styles)) mypath = self.getDeformedPath() if config.getOptions().DRAFT or not self.is3D: canvas.stroke(mypath, styles) else: para = pyx.deformer.parallel(0.001) ass, bs, cs = para.normpath_selfintersections(mypath.normpath(), epsilon=0.01) coil_params = [] for b in bs: coil_params.append(b[self.parity3D] - self.skipsize3D) coil_params.append(b[self.parity3D] + self.skipsize3D) pathbits = mypath.split(coil_params) on = True for pathbit in pathbits: if on: canvas.stroke(pathbit, styles) on = not on ## Labels for l in self.labels: l.draw(canvas)
def draw(self, canvas): """Draw the line on the supplied canvas.""" styles = self.styles + self.arrows if config.getOptions().DEBUG: print "Drawing " + str(self.__class__) + " with styles = " + str(styles) mypath = self.getDeformedPath() if config.getOptions().DRAFT or not self.is3D: canvas.stroke(mypath, styles) else: para = pyx.deformer.parallel(0.001) ass, bs, cs = para.normpath_selfintersections(mypath.normpath(), epsilon=0.01) coil_params = [] for b in bs: coil_params.append(b[self.parity3D] - self.skipsize3D) coil_params.append(b[self.parity3D] + self.skipsize3D) pathbits = mypath.split(coil_params) on = True for pathbit in pathbits: if on: canvas.stroke(pathbit, styles) on = not on ## Labels for l in self.labels: l.draw(canvas)
def draw(self, canvas): """Draw the line on the supplied canvas.""" styles = self.styles + self.arrows if config.getOptions().DEBUG: print "Drawing " + str(self.__class__) + " with styles = " + str(styles) mypath = [self.getVisiblePath(), self.getDeformedPath(+1), self.getDeformedPath(-1)] if self.inverted: mypath = mypath[::-1] if config.getOptions().DRAFT or not self.is3D: for i in range(3): canvas.stroke(mypath[i], styles) else: ass, bs = mypath[0].intersect(mypath[1]) ass, cs = mypath[0].intersect(mypath[2]) ps = [ass[:], bs[:], cs[:]] for i in range(3): params = [] for a in range(len(ps[i])): ## TODO: better endpoint cut vetoing if (a%3)!=i: params.append(ps[i][a] - self.skipsize3D) params.append(ps[i][a] + self.skipsize3D) pathbits = mypath[i].split(params) on = True for pathbit in pathbits: if on: canvas.stroke(pathbit, styles) on = not on for l in self.labels: l.draw(canvas)
def bend(self, amount): """Bend the line to the right by a given distance.""" if amount == 0: self.arcthrupoint = None return self middle = self.p1.midpoint(self.p2) nx = (middle.y() - self.p1.y()) / abs(self.p1.distance(middle)) ny = (self.p1.x() - middle.x()) / abs(self.p1.distance(middle)) vx = middle.x() - self.p1.x() vy = middle.y() - self.p1.y() if (vx * ny - vy * nx) > 0: nx *= -1 ny *= -1 arcpoint = Point(middle.x() + amount * nx, middle.y() + amount * ny) if config.getOptions().VDEBUG: FeynDiagram.currenDiagram.currentCanvas.stroke( pyx.path.line(middle.x(), middle.y(), arcpoint.x(), arcpoint.y()), [color.rgb.blue]) self.arcThru(arcpoint) if config.getOptions().DEBUG: print(self.getVisiblePath()) if config.getOptions().VDEBUG: FeynDiagram.currenDiagram.currentCanvas.stroke( self.getVisiblePath(), [color.rgb.blue]) return self
def addLabel(self, text, displace=0.3, angle = 0): """Add a LaTeX label to this point, either via parameters or actually as a PointLable object.""" if config.getOptions().DEBUG: print "Adding label: " + text self.labels.append(PointLabel(text=text, point=self, displace=displace, angle=angle)) if config.getOptions().DEBUG: print "Labels = " + str(self.labels) return self
def addLabel(self, text, displace=-0.15, angle = 0, size=pyx.text.size.normalsize, halign=CENTER, valign=None): """Add a label.""" if config.getOptions().DEBUG: print("Adding label: " + text) self.labels.append(PointLabel(text=text, point=self, displace=displace, angle=angle, size=size, halign=halign, valign=valign)) if config.getOptions().DEBUG: print("Labels = " + str(self.labels)) return self
def draw(self, canvas): """Draw the line on the supplied canvas.""" styles = self.styles + self.arrows if config.getOptions().DEBUG: print("Drawing " + str(self.__class__) + " with styles = " + str(styles)) mypath1 = self.getVisiblePath() mypath2 = self.getDeformedPath() if config.getOptions().DRAFT or not self.is3D: canvas.stroke(mypath1, styles) canvas.stroke(mypath2, styles) else: ass, bs = mypath1.intersect(mypath2) params1, params2 = [], [] parity1 = True if self.parity3D == 0: parity1 = False for a in ass: if parity1: params1.append(a - self.skipsize3D) params1.append(a + self.skipsize3D) parity1 = not parity1 pathbits1 = mypath1.split(params1) on = True for pathbit in pathbits1: if on: canvas.stroke(pathbit, styles) on = not on parity2 = False if self.parity3D == 0: parity2 = True for b in bs: if parity2: params2.append(b - self.skipsize3D) params2.append(b + self.skipsize3D) parity2 = not parity2 para = pyx.deformer.parallel(0.001) sas, sbs, scs = para.normpath_selfintersections(mypath2.normpath(), epsilon=0.01) coil_params = [] for b in sbs: coil_params.append(b[self.parity3D] - self.skipsize3D) coil_params.append(b[self.parity3D] + self.skipsize3D) params2 += coil_params params2.sort() pathbits2 = mypath2.split(params2) on = True for pathbit in pathbits2: if on: canvas.stroke(pathbit, styles) on = not on for l in self.labels: l.draw(canvas)
def addLabel(self, text, displace=-0.15, angle = 0): """Add a label.""" if config.getOptions().DEBUG: print "Adding label: " + text self.labels.append(PointLabel(text=text, point=self, displace=displace, angle=angle)) if config.getOptions().DEBUG: print "Labels = " + str(self.labels) return self
def draw(self, canvas): """Draw the line on the supplied canvas.""" styles = self.styles + self.arrows if config.getOptions().DEBUG: print "Drawing " + str(self.__class__) + " with styles = " + str(styles) mypath1 = self.getVisiblePath() mypath2 = self.getDeformedPath() if config.getOptions().DRAFT or not self.is3D: canvas.stroke(mypath1, styles) canvas.stroke(mypath2, styles) else: ass, bs = mypath1.intersect(mypath2) params1, params2 = [], [] parity1 = True if self.parity3D == 0: parity1 = False for a in ass: if parity1: params1.append(a - self.skipsize3D) params1.append(a + self.skipsize3D) parity1 = not parity1 pathbits1 = mypath1.split(params1) on = True for pathbit in pathbits1: if on: canvas.stroke(pathbit, styles) on = not on parity2 = False if self.parity3D == 0: parity2 = True for b in bs: if parity2: params2.append(b - self.skipsize3D) params2.append(b + self.skipsize3D) parity2 = not parity2 para = pyx.deformer.parallel(0.001) sas, sbs, scs = para.normpath_selfintersections(mypath2.normpath(), epsilon=0.01) coil_params = [] for b in sbs: coil_params.append(b[self.parity3D] - self.skipsize3D) coil_params.append(b[self.parity3D] + self.skipsize3D) params2 += coil_params params2.sort() pathbits2 = mypath2.split(params2) on = True for pathbit in pathbits2: if on: canvas.stroke(pathbit, styles) on = not on for l in self.labels: l.draw(canvas)
def addLabel(self, text, pos=0.5, displace=-0.25, angle = 0, size=pyx.text.size.normalsize, halign=CENTER, valign=None, **kwargs): """Add a LaTeX label to this line, either via parameters or actually as a TeXLabel object.""" if config.getOptions().DEBUG: print("Adding label: " + text) #if text.__class__ == "Label": # self.labels.append(label) #else: self.labels.append(LineLabel(text=text, line=self, pos=pos, displace=displace, angle=angle, size=size, halign=halign, valign=valign)) if config.getOptions().DEBUG: print("Labels = " + str(self.labels)) return self
def addLabel(self, text, pos=0.5, displace=-0.25, angle = 0, size=pyx.text.size.normalsize): """Add a LaTeX label to this line, either via parameters or actually as a TeXLable object.""" if config.getOptions().DEBUG: print "Adding label: " + text #if text.__class__ == "Label": # self.labels.append(label) #else: self.labels.append(LineLabel(text=text, line=self, pos=pos, displace=displace, angle=angle, size=size)) if config.getOptions().DEBUG: print "Labels = " + str(self.labels) return self
def draw(self, canvas): """Draw this arrow on the supplied canvas.""" p = self.line.getPath() posparam = p.begin() + self.pos * p.arclen() x, y = self.line.fracpoint(self.pos).getXY() arrx, arry = self.line.fracpoint(self.pos+self.length/2./p.arclen()).getXY() endx, endy = self.line.fracpoint(self.pos-self.length/2./p.arclen()).getXY() ## Calculate the displacement from the line displacement = self.displace intrinsicwidth = pyx.unit.length(0.1) if hasattr(self.line, "arcradius"): intrinsicwidth = self.line.arcradius if displacement > 0: displacement += intrinsicwidth else: displacement -= intrinsicwidth if config.getOptions().DEBUG: print "Displacement = ", displacement ## Position the arrow on the right hand side of lines tangent = p.tangent(posparam, displacement) normal = tangent.transformed(pyx.trafo.rotate(90, x, y)) nx, ny = normal.atend() nxcm, nycm = pyx.unit.tocm(nx - x), pyx.unit.tocm(ny - y) vx, vy = p.atbegin() vxcm, vycm = pyx.unit.tocm(x - vx), pyx.unit.tocm(y - vy) ## If the arrow is on the left, flip it by 180 degrees if (vxcm * nycm - vycm * nxcm) > 0: normal = normal.transformed(pyx.trafo.rotate(180, x, y)) nx, ny = normal.atend() if displacement < 0: normal = normal.transformed(pyx.trafo.rotate(180, x, y)) nx, ny = normal.atend() if config.getOptions().VDEBUG: FeynDiagram.currentCanvas.stroke(normal) ## Displace the arrow by this normal vector endx, endy = endx + (nx-x), endy + (ny-y) arrx, arry = arrx + (nx-x), arry + (ny-y) if self.sense<0.: arrx, arry, endx, endy = endx, endy, arrx, arry linepath = pyx.deco.decoratedpath( pyx.path.path(pyx.path.moveto(endx,endy), pyx.path.lineto(arrx,arry))) styles = [pyx.deco.earrow(size=self.size, angle=self.angle, constriction=self.constriction)] canvas.stroke(linepath.path,styles)
def draw(self, canvas): """Draw the line on the supplied canvas.""" styles = self.styles + self.arrows if config.getOptions().DEBUG: print("Drawing " + str(self.__class__) + " with styles = " + str(styles)) mypath1 = self.getDeformedPath(+1) mypath2 = self.getDeformedPath(-1) if self.inverted: mypathtmp = mypath1 mypath1 = mypath2 mypath2 = mypathtmp if config.getOptions().DRAFT or not self.is3D: canvas.stroke(mypath1, styles) canvas.stroke(mypath2, styles) else: ass, bs = mypath1.intersect(mypath2) params1, params2 = [], [] parity1 = True if self.parity3D == 0: parity1 = False for a in ass[1:]: ## TODO: better endpoint cut vetoing if parity1: params1.append(a - self.skipsize3D) params1.append(a + self.skipsize3D) parity1 = not parity1 pathbits1 = mypath1.split(params1) on = True for pathbit in pathbits1: if on: canvas.stroke(pathbit, styles) on = not on parity2 = False if self.parity3D == 0: parity2 = True for b in bs[1:]: ## TODO: better endpoint cut vetoing if parity2: params2.append(b - self.skipsize3D) params2.append(b + self.skipsize3D) parity2 = not parity2 pathbits2 = mypath2.split(params2) on = True for pathbit in pathbits2: if on: canvas.stroke(pathbit, styles) on = not on for l in self.labels: l.draw(canvas)
def draw(self, canvas): """Draw the line on the supplied canvas.""" styles = self.styles + self.arrows if config.getOptions().DEBUG: print "Drawing " + str(self.__class__) + " with styles = " + str(styles) mypath1 = self.getDeformedPath(+1) mypath2 = self.getDeformedPath(-1) if self.inverted: mypathtmp = mypath1 mypath1 = mypath2 mypath2 = mypathtmp if config.getOptions().DRAFT or not self.is3D: canvas.stroke(mypath1, styles) canvas.stroke(mypath2, styles) else: ass, bs = mypath1.intersect(mypath2) params1, params2 = [], [] parity1 = True if self.parity3D == 0: parity1 = False for a in ass[1:]: ## TODO: better endpoint cut vetoing if parity1: params1.append(a - self.skipsize3D) params1.append(a + self.skipsize3D) parity1 = not parity1 pathbits1 = mypath1.split(params1) on = True for pathbit in pathbits1: if on: canvas.stroke(pathbit, styles) on = not on parity2 = False if self.parity3D == 0: parity2 = True for b in bs[1:]: ## TODO: better endpoint cut vetoing if parity2: params2.append(b - self.skipsize3D) params2.append(b + self.skipsize3D) parity2 = not parity2 pathbits2 = mypath2.split(params2) on = True for pathbit in pathbits2: if on: canvas.stroke(pathbit, styles) on = not on for l in self.labels: l.draw(canvas)
def draw(self, canvas): """Draw this label on the supplied canvas.""" p = self.line.getPath() #x, y = self.line.fracPoint(self.pos).getXY() posparam = p.begin() + self.pos * p.arclen() x, y = p.at(posparam) ## Calculate the displacement from the line displacement = self.displace intrinsicwidth = pyx.unit.length(0.1) if hasattr(self.line, "arcradius"): intrinsicwidth = self.line.arcradius if displacement > 0: displacement += intrinsicwidth else: displacement -= intrinsicwidth if config.getOptions().DEBUG: print("Displacement = ", displacement) ## Position the label on the right hand side of lines tangent = p.tangent(posparam, displacement) normal = tangent.transformed(pyx.trafo.rotate(90, x, y)) nx, ny = normal.atend() nxcm, nycm = pyx.unit.tocm(nx - x), pyx.unit.tocm(ny - y) vx, vy = p.atbegin() vxcm, vycm = pyx.unit.tocm(x - vx), pyx.unit.tocm(y - vy) ## If the label is on the left, flip it by 180 degrees if (vxcm * nycm - vycm * nxcm) > 0: normal = normal.transformed(pyx.trafo.rotate(180, x, y)) nx, ny = normal.atend() if displacement < 0: normal = normal.transformed(pyx.trafo.rotate(180, x, y)) nx, ny = normal.atend() if config.getOptions().VDEBUG: FeynDiagram.currentDiagram.currentCanvas.stroke(normal) ## Displace the label by this normal vector x, y = nx, ny textattrs = pyx.attr.mergeattrs( [pyx.text.halign.center, pyx.text.vshift.mathaxis, self.size] + self.textattrs) t = pyx.text.defaulttexrunner.text(x, y, self.text, textattrs) #t.linealign(self.displace, # math.cos(self.angle * math.pi/180), # math.sin(self.angle * math.pi/180)) canvas.insert(t)
def draw(self, canvas): """Draw this label on the supplied canvas.""" p = self.line.getPath() #x, y = self.line.fracPoint(self.pos).getXY() posparam = p.begin() + self.pos * p.arclen() x, y = p.at(posparam) ## Calculate the displacement from the line displacement = self.displace intrinsicwidth = pyx.unit.length(0.1) if hasattr(self.line, "arcradius"): intrinsicwidth = self.line.arcradius if displacement > 0: displacement += intrinsicwidth else: displacement -= intrinsicwidth if config.getOptions().DEBUG: print "Displacement = ", displacement ## Position the label on the right hand side of lines tangent = p.tangent(posparam, displacement) normal = tangent.transformed(pyx.trafo.rotate(90, x, y)) nx, ny = normal.atend() nxcm, nycm = pyx.unit.tocm(nx - x), pyx.unit.tocm(ny - y) vx, vy = p.atbegin() vxcm, vycm = pyx.unit.tocm(x - vx), pyx.unit.tocm(y - vy) ## If the label is on the left, flip it by 180 degrees if (vxcm * nycm - vycm * nxcm) > 0: normal = normal.transformed(pyx.trafo.rotate(180, x, y)) nx, ny = normal.atend() if displacement < 0: normal = normal.transformed(pyx.trafo.rotate(180, x, y)) nx, ny = normal.atend() if config.getOptions().VDEBUG: FeynDiagram.currentDiagram.currentCanvas.stroke(normal) ## Displace the label by this normal vector x, y = nx, ny textattrs = pyx.attr.mergeattrs([pyx.text.halign.center, pyx.text.vshift.mathaxis, self.size] + self.textattrs) t = pyx.text.defaulttexrunner.text(x, y, self.text, textattrs) #t.linealign(self.displace, # math.cos(self.angle * math.pi/180), # math.sin(self.angle * math.pi/180)) canvas.insert(t)
def add(self, *objs): """Add an object to the diagram.""" for obj in objs: if config.getOptions().DEBUG: print "#objs = %d" % len(self.__objs) offset = 0 if obj.__dict__.has_key("layeroffset"): #print "offset =", obj.layeroffset offset = obj.layeroffset self.highestautolayer += 1 obj.setDepth(self.highestautolayer + offset) if config.getOptions().DEBUG: print "Object %s layer = %d + %d = %d" % \ (obj.__class__, self.highestautolayer, offset, self.highestautolayer + offset) self.__objs.append(obj)
def getDeformedPath(self): """Get the path with the decorative deformation.""" intwindings = int(self.frequency * pyx.unit.tocm(self.getVisiblePath().arclen()) / pyx.unit.tocm(self.arcradius)) intwindings += self.extras sign = 1 if self.inverted: sign = -1 vispath = self.getVisiblePath() curveradii = vispath.curveradius([i/10.0 for i in range(0,11)]) mincurveradius = None for curveradius in curveradii: try: curveradius = abs(curveradius/pyx.unit.m) #if config.getOptions().DEBUG: # print self.__class__, "- curve radius = ", curveradius if (mincurveradius is None or curveradius < mincurveradius): mincurveradius = curveradius except: pass numhloopcurves = 5 if mincurveradius is not None: numhloopcurves += int(0.1/mincurveradius) if config.getOptions().DEBUG: print(self.__class__, "- min curvature radius = ", mincurveradius, "->", numhloopcurves, "curves/hloop") defo = pyx.deformer.cycloid(self.arcradius, intwindings, curvesperhloop=numhloopcurves, skipfirst=0.0, skiplast=0.0, turnangle=0, sign=sign) return defo.deform(vispath)
def add(self, *objs): """Add an object to the diagram.""" for obj in objs: if config.getOptions().DEBUG: print("#objs = %d" % len(self.__objs)) offset = 0 if "layeroffset" in obj.__dict__: #print "offset =", obj.layeroffset offset = obj.layeroffset self.highestautolayer += 1 obj.setDepth(self.highestautolayer + offset) if config.getOptions().DEBUG: print("Object %s layer = %d + %d = %d" % \ (obj.__class__, self.highestautolayer, offset, self.highestautolayer + offset)) self.__objs.append(obj)
def getDeformedPath(self): """Get the path with the decorative deformation.""" intwindings = int(pyx.unit.tocm(self.getVisiblePath().arclen()) / pyx.unit.tocm(self.arcradius)) sign = 1 if self.inverted: sign = -1 vispath = self.getVisiblePath() curveradii = vispath.curveradius([i/10.0 for i in range(0,11)]) mincurveradius = None for curveradius in curveradii: try: curveradius = abs(mincurveradius/pyx.unit.m) #if config.getOptions().DEBUG: # print self.__class__, "- curvature radius = ", curveradius if (mincurveradius is None or curveradius < mincurveradius): mincurveradius = curveradius except: pass ## Use curvature info to increase number of curve sections numhloopcurves = 5 if mincurveradius is not None: numhloopcurves += int(0.1/mincurveradius) if config.getOptions().DEBUG: print self.__class__, "- min curve radius = ", mincurveradius, "->", numhloopcurves, "curves/hloop" defo = pyx.deformer.cycloid(self.arcradius, intwindings, curvesperhloop=numhloopcurves, skipfirst=0.0, skiplast=0.0, turnangle=0, sign=sign) return defo.deform(vispath)
def draw(self, canvas): """Draw the line on the supplied canvas.""" styles = self.styles + self.arrows if config.getOptions().DEBUG: print "Drawing " + str(self.__class__) + " with styles = " + str(styles) canvas.stroke(self.getDeformedPath(), styles) for l in self.labels: l.draw(canvas)
def draw(self, canvas): """Draw the line on the supplied canvas.""" styles = self.styles + self.arrows if config.getOptions().DEBUG: print("Drawing " + str(self.__class__) + " with styles = " + str(styles)) canvas.stroke(self.getDeformedPath(), styles) for l in self.labels: l.draw(canvas)
def __cmp__(self, other): """Compare with another visible class, just using layers.""" if other is None: return -1 if config.getOptions().DEBUG: print "Comparing visible classes: ", self.__class__, "->", self.getDepth(), "vs.", other.__class__, "->", other.getDepth() else: return cmp(self.getDepth(), other.getDepth())
def addLabel(self, text, displace=0.3, angle=0, size=pyx.text.size.normalsize): """Add a LaTeX label to this point, either via parameters or actually as a PointLable object.""" if config.getOptions().DEBUG: print("Adding label: " + text) self.labels.append( PointLabel(text=text, point=self, displace=displace, angle=angle, size=size)) if config.getOptions().DEBUG: print("Labels = " + str(self.labels)) return self
def draw(self, canvas): """Drwa this line on the given canvas.""" path = self.getVisiblePath() styles = self.styles + self.arrows if config.getOptions().DEBUG: print("Drawing " + str(self.__class__) + " with styles = " + str(styles)) print(path) canvas.stroke(path, styles) for l in self.labels: l.draw(canvas)
def draw(self, canvas): """Drwa this line on the given canvas.""" path = self.getVisiblePath() styles = self.styles + self.arrows if config.getOptions().DEBUG: print "Drawing " + str(self.__class__) + " with styles = " + str(styles) print path canvas.stroke(path, styles) for l in self.labels: l.draw(canvas)
def draw(self, canvas): """Draw this scalar line on the given canvas.""" path = self.getVisiblePath() styles = self.styles + [self.linestyle] + self.arrows ## TODO: call base class method? if config.getOptions().DEBUG: print("Drawing " + str(self.__class__) + " with styles = " + str(styles)) print(path) canvas.stroke(path, styles) for l in self.labels: l.draw(canvas)
def __cmp__(self, other): """Compare with another visible class, just using layers.""" if other is None: return -1 if config.getOptions().DEBUG: print("Comparing visible classes: ", \ self.__class__, "->", self.getDepth(), "vs.", \ other.__class__, "->", other.getDepth()) else: return cmp(self.getDepth(), other.getDepth())
def draw(self, canvas): """Draw this scalar line on the given canvas.""" path = self.getVisiblePath() styles = self.styles + [pyx.style.linestyle.dotted] + self.arrows ## TODO: call base class method? if config.getOptions().DEBUG: print "Drawing " + str(self.__class__) + " with styles = " + str(styles) print path canvas.stroke(path, styles) for l in self.labels: l.draw(canvas)
def drawToCanvas(self): """Draw the components of this diagram in a well-defined order.""" if config.getOptions().DEBUG: print("Final #objs = %d" % len(self.__objs)) if config.getOptions().VDEBUG: print("Running in visual debug mode") ## Sort drawing objects by layer drawingobjs = self.__objs try: drawingobjs.sort() except: pass ## Draw each object for obj in drawingobjs: if config.getOptions().DEBUG: print("Depth = ", obj.getDepth()) obj.draw(self.currentCanvas) return self.currentCanvas
def draw(self, canvas): """Draw this label on the supplied canvas.""" if config.getOptions().VDEBUG: canvas.fill(pyx.path.circle(self.point.getX(), self.point.getY(), 0.05), [pyx.color.rgb.green]) x = self.point.getX() + self.displace * math.cos(math.radians(self.angle)) y = self.point.getY() + self.displace * math.sin(math.radians(self.angle)) textattrs = pyx.attr.mergeattrs([pyx.text.halign.center, pyx.text.vshift.mathaxis, self.size] + self.textattrs) t = pyx.text.defaulttexrunner.text(x, y, self.text, textattrs) canvas.insert(t)
def bend(self, amount): """Bend the line to the right by a given distance.""" middle = self.p1.midpoint(self.p2) nx = (middle.y() - self.p1.y()) / abs(self.p1.distance(middle)) ny = (self.p1.x() - middle.x()) / abs(self.p1.distance(middle)) vx = middle.x() - self.p1.x() vy = middle.y() - self.p1.y() if (vx * ny - vy * nx) > 0: nx *= -1 ny *= -1 arcpoint = Point(middle.x() + amount * nx, middle.y() + amount * ny) if config.getOptions().VDEBUG: FeynDiagram.currenDiagram.currentCanvas.stroke( pyx.path.line(middle.x(), middle.y(), arcpoint.x(), arcpoint.y()), [color.rgb.blue] ) self.arcThru(arcpoint) if config.getOptions().DEBUG: print self.getVisiblePath() if config.getOptions().VDEBUG: FeynDiagram.currenDiagram.currentCanvas.stroke(self.getVisiblePath(), [color.rgb.blue]) return self
def drawToCanvas(self): """Draw the components of this diagram in a well-defined order.""" if config.getOptions().DEBUG: print "Final #objs = %d" % len(self.__objs) if config.getOptions().VDEBUG: print "Running in visual debug mode" ## Sort drawing objects by layer drawingobjs = self.__objs try: drawingobjs.sort() except: pass ## Draw each object for obj in drawingobjs: if config.getOptions().DEBUG: print "Depth = ", obj.getDepth() obj.draw(self.currentCanvas) return self.currentCanvas
def getVisiblePath(self): """Find the subpath between the endpoints which isn't overshadowed by a blob of some kind""" p1path = self.p1.getPath() p2path = self.p2.getPath() vispath = self.getPath() if config.getOptions().VDEBUG: FeynDiagram.currenDiagram.currentCanvas.stroke(vispath, [color.rgb.green]) if p1path: ass, bs = p1path.intersect(vispath) for b in bs: subpaths = vispath.split(b) if len(subpaths) > 1: if config.getOptions().DEBUG: print "Num subpaths 1 = %d" % len(subpaths) subpaths.sort( lambda x, y : int(pyx.unit.tocm(x.arclen() - y.arclen()) / math.fabs(pyx.unit.tocm(x.arclen() - y.arclen()))) ) vispath = subpaths[-1] if config.getOptions().VDEBUG: FeynDiagram.currenDiagram.currentCanvas.stroke(subpaths[0], [color.rgb.blue]) if config.getOptions().VDEBUG: for a in ass: ix, iy = p1path.at(a) FeynDiagram.currenDiagram.currentCanvas.fill(pyx.path.circle(ix, iy, 0.05), [color.rgb.green]) if p2path: ass, bs = p2path.intersect(vispath) for b in bs: subpaths = vispath.split(b) if len(subpaths) > 1: if config.getOptions().DEBUG: print "Num subpaths 2 = %d" % len(subpaths) subpaths.sort( lambda x, y : int(pyx.unit.tocm(x.arclen() - y.arclen()) / math.fabs(pyx.unit.tocm(x.arclen() - y.arclen()))) ) vispath = subpaths[-1] if config.getOptions().VDEBUG: FeynDiagram.currenDiagram.currentCanvas.stroke(subpaths[0], [color.rgb.red]) if config.getOptions().VDEBUG: for a in ass: ix, iy = p2path.at(a) FeynDiagram.currenDiagram.currentCanvas.fill(pyx.path.circle(ix, iy, 0.05), [color.rgb.blue]) if config.getOptions().VDEBUG: FeynDiagram.currenDiagram.currentCanvas.stroke(vispath, [color.rgb.red]) #return pyx.path.circle(-2,-1,0.2) return vispath
def draw(self, canvas): """Draw this label on the supplied canvas.""" if config.getOptions().VDEBUG: canvas.fill( pyx.path.circle(self.point.getX(), self.point.getY(), 0.05), [pyx.color.rgb.green]) x = self.point.getX() + self.displace * math.cos( math.radians(self.angle)) y = self.point.getY() + self.displace * math.sin( math.radians(self.angle)) textattrs = pyx.attr.mergeattrs([pyx.text.vshift.mathaxis, self.size] + self.textattrs) t = pyx.text.defaulttexrunner.text(x, y, self.text, textattrs) canvas.insert(t)
def getVisiblePath(self): """Find the subpath between the endpoints which isn't overshadowed by a blob of some kind""" p1path = self.p1.getPath() p2path = self.p2.getPath() vispath = self.getPath() if config.getOptions().VDEBUG: FeynDiagram.currenDiagram.currentCanvas.stroke( vispath, [color.rgb.green]) if p1path: ass, bs = p1path.intersect(vispath) for b in bs: subpaths = vispath.split(b) if len(subpaths) > 1: if config.getOptions().DEBUG: print("Num subpaths 1 = %d" % len(subpaths)) subpaths.sort(key=lambda x: pyx.unit.tocm(x.arclen())) vispath = subpaths[-1] if config.getOptions().VDEBUG: FeynDiagram.currenDiagram.currentCanvas.stroke( subpaths[0], [color.rgb.blue]) if config.getOptions().VDEBUG: for a in ass: ix, iy = p1path.at(a) FeynDiagram.currenDiagram.currentCanvas.fill( pyx.path.circle(ix, iy, 0.05), [color.rgb.green]) if p2path: ass, bs = p2path.intersect(vispath) for b in bs: subpaths = vispath.split(b) if len(subpaths) > 1: if config.getOptions().DEBUG: print("Num subpaths 2 = %d" % len(subpaths)) subpaths.sort(key=lambda x: pyx.unit.tocm(x.arclen())) vispath = subpaths[-1] if config.getOptions().VDEBUG: FeynDiagram.currenDiagram.currentCanvas.stroke( subpaths[0], [color.rgb.red]) if config.getOptions().VDEBUG: for a in ass: ix, iy = p2path.at(a) FeynDiagram.currenDiagram.currentCanvas.fill( pyx.path.circle(ix, iy, 0.05), [color.rgb.blue]) if config.getOptions().VDEBUG: FeynDiagram.currenDiagram.currentCanvas.stroke( vispath, [color.rgb.red]) #return pyx.path.circle(-2,-1,0.2) return vispath
def getDeformedPath(self): """Get the path with the decorative deformation.""" needwindings = 1.2 * \ pyx.unit.tocm(self.getVisiblePath().arclen()) / \ pyx.unit.tocm(self.arcradius) ## Get the whole number of windings and make sure that it's odd so we ## don't get a weird double-back thing intwindings = int(needwindings) if intwindings % 2 == 0: intwindings -= 1 deficit = needwindings - intwindings sign = 1 if self.inverted: sign = -1 ## Get list of curvature radii in the visible path vispath = self.getVisiblePath() curveradii = vispath.curveradius([i / 10.0 for i in range(0, 11)]) mincurveradius = None ## Find the maximum curvature (set None if straight line) for curveradius in curveradii: try: curveradius = abs(curvature / pyx.unit.m) #if config.getOptions().DEBUG: # print self.__class__, "- curvature radius = ", curveradius if (mincurveradius is None or curveradius < mincurveradius): mincurveradius = curveradius except: pass ## Use curvature info to increase number of curve sections numhloopcurves = 10 if mincurveradius is not None: numhloopcurves += int(0.2 / mincurveradius) if config.getOptions().DEBUG: print(self.__class__, "- min curve radius = ", mincurveradius, "->", numhloopcurves, "curves/hloop") defo = pyx.deformer.cycloid(self.arcradius, intwindings, curvesperhloop=numhloopcurves, skipfirst=0.0, skiplast=0.0, sign=sign) return defo.deform(vispath)
def getDeformedPath(self): """Get the path with the decorative deformation.""" needwindings = 1.2 * \ pyx.unit.tocm(self.getVisiblePath().arclen()) / \ pyx.unit.tocm(self.arcradius) ## Get the whole number of windings and make sure that it's odd so we ## don't get a weird double-back thing intwindings = int(needwindings) if intwindings % 2 == 0: intwindings -= 1 deficit = needwindings - intwindings sign = 1 if self.inverted: sign = -1 ## Get list of curvature radii in the visible path vispath = self.getVisiblePath() curveradii = vispath.curveradius([i/10.0 for i in range(0,11)]) mincurveradius = None ## Find the maximum curvature (set None if straight line) for curveradius in curveradii: try: curveradius = abs(curvature/pyx.unit.m) #if config.getOptions().DEBUG: # print self.__class__, "- curvature radius = ", curveradius if (mincurveradius is None or curveradius < mincurveradius): mincurveradius = curveradius except: pass ## Use curvature info to increase number of curve sections numhloopcurves = 10 if mincurveradius is not None: numhloopcurves += int(0.2/mincurveradius) if config.getOptions().DEBUG: print self.__class__, "- min curve radius = ", mincurveradius, "->", numhloopcurves, "curves/hloop" defo = pyx.deformer.cycloid(self.arcradius, intwindings, curvesperhloop=numhloopcurves, skipfirst=0.0, skiplast=0.0, sign=sign) return defo.deform(vispath)
def getPath(self): """Get the path taken by this line.""" if self.arcthrupoint is None: ## This is a simple straight line return pyx.path.path( pyx.path.moveto( *(self.p1.getXY()) ), pyx.path.lineto( *(self.p2.getXY()) ) ) elif (self.p1.x() == self.p2.x() and self.p1.y() == self.p2.y()): ## This is a tadpole-type loop and needs special care; ## We shall assume that the arcthrupoint is meant to be ## the antipode of the basepoint arccenter = self.p1.midpoint(self.arcthrupoint) arcradius = self.p1.distance(self.arcthrupoint) / 2.0 ## TODO Why does a circle work and an arc doesn't? cargs = (arccenter.x(), arccenter.y(), arcradius) circle = pyx.path.circle(*cargs) line = pyx.path.line( self.p1.x(), self.p1.y(), arccenter.x(), arccenter.y()) if config.getOptions().VDEBUG: FeynDiagram.currenDiagram.currentCanvas.stroke(line, [color.rgb.green]) ass, bs = circle.intersect(line) subpaths = circle.split(ass[0]) cpath = subpaths[0] return cpath ## or, with an arc... arcangle1 = arccenter.arg(self.p1) arcangle2 = arccenter.arg(self.p1) + 360 arcargs = (arccenter.x(), arccenter.y(), arcradius, arcangle1, arcangle2) return pyx.path.path( pyx.path.arc(*arcargs) ) else: n13, n23 = None, None ## Work out line gradients try: n13 = (self.p1.y() - self.arcthrupoint.y()) / (self.p1.x() - self.arcthrupoint.x()) except ZeroDivisionError: if config.getOptions().DEBUG: print "Grad 1 diverges" n13 = 1e100 try: n23 = (self.p2.y() - self.arcthrupoint.y()) / (self.p2.x() - self.arcthrupoint.x()) except ZeroDivisionError: if config.getOptions().DEBUG: print "Grad 2 diverges" n23 = 1e100 ## If gradients match, ## then we have a straight line, so bypass the complexity if n13 == n23: return pyx.path.path( pyx.path.moveto(*(self.p1.getXY())), pyx.path.lineto(*(self.p2.getXY())) ) ## Otherwise work out conjugate gradients and midpoints m13, m23 = None, None try: m13 = -1.0 / n13 except ZeroDivisionError: m13 = 1e100 try: m23 = -1.0 / n23 except ZeroDivisionError: m23 = 1e100 mid13 = self.p1.midpoint(self.arcthrupoint) mid23 = self.p2.midpoint(self.arcthrupoint) ## Line y-intercepts c13 = mid13.y() - m13 * mid13.x() c23 = mid23.y() - m23 * mid23.x() ## Find the centre of the arc xcenter = - (c23 - c13) / (m23 - m13) ycenter = m13 * xcenter + c13 arccenter = Point(xcenter, ycenter) ## Get the angles required for drawing the arc arcradius = arccenter.distance(self.arcthrupoint) arcangle1 = arccenter.arg(self.p1) arcangle2 = arccenter.arg(self.p2) arcangle3 = arccenter.arg(self.arcthrupoint) arcargs = (arccenter.x(), arccenter.y(), arcradius, arcangle1, arcangle2) if config.getOptions().DEBUG and arcangle1 == arcangle2: print "Arc angles are the same - not drawing anything" ## Calculate cross product to determine direction of arc vec12 = [self.p2.x()-self.p1.x(), self.p2.y()-self.p1.y(), 0.0] vec13 = [self.arcthrupoint.x()-self.p1.x(), self.arcthrupoint.y()-self.p1.y(), 0.0] crossproductZcoord = vec12[0]*vec13[1] - vec12[1]*vec13[0] if crossproductZcoord < 0: return pyx.path.path( pyx.path.moveto(*(self.p1.getXY())), pyx.path.arc(*arcargs)) else: return pyx.path.path( pyx.path.moveto(*(self.p1.getXY())), pyx.path.arcn(*arcargs))
def draw(self, canvas): """Draw this arrow on the supplied canvas.""" p = self.line.getPath() x, y = self.line.fracpoint(self.pos).getXY() posparam = p.begin() + self.pos * p.arclen() arrx, arry = self.line.fracpoint(self.pos+self.length/2./p.arclen()).getXY() endx, endy = self.line.fracpoint(self.pos-self.length/2./p.arclen()).getXY() ## Calculate the displacement from the line displacement = self.displace intrinsicwidth = pyx.unit.length(0.1) if hasattr(self.line, "arcradius"): intrinsicwidth = self.line.arcradius if displacement > 0: displacement += intrinsicwidth else: displacement -= intrinsicwidth if config.getOptions().DEBUG: print "Displacement = ", displacement ## Position the arrow on the right hand side of lines tangent = p.tangent(posparam, displacement) normal = tangent.transformed(pyx.trafo.rotate(90, x, y)) nx, ny = normal.atend() nxcm, nycm = pyx.unit.tocm(nx - x), pyx.unit.tocm(ny - y) vx, vy = p.atbegin() vxcm, vycm = pyx.unit.tocm(x - vx), pyx.unit.tocm(y - vy) ## If the arrow is on the left, flip it by 180 degrees if (vxcm * nycm - vycm * nxcm) > 0: normal = normal.transformed(pyx.trafo.rotate(180, x, y)) nx, ny = normal.atend() if displacement < 0: normal = normal.transformed(pyx.trafo.rotate(180, x, y)) nx, ny = normal.atend() if config.getOptions().VDEBUG: FeynDiagram.currentDiagram.currentCanvas.stroke(normal) ## Displace the arrow by this normal vector endx, endy = endx + (nx-x), endy + (ny-y) arrx, arry = arrx + (nx-x), arry + (ny-y) if self.sense<0.: arrx, arry, endx, endy = endx, endy, arrx, arry if not self.curved: linepath = pyx.path.path(pyx.path.moveto(endx,endy), pyx.path.lineto(arrx,arry)) if self.rotation: rotx, roty = 0.5*(endx+arrx), 0.5*(endy+arry) linepath = linepath.transformed(pyx.trafo.rotate(self.rotation, rotx, roty)) styles = [pyx.deco.earrow(size=self.size, angle=self.angle, constriction=self.constriction)] # Allow us to add colouring etc. to the line styles.extend(self.getCustomStyles()) dist = self.stemsep n = self.stems if n>1: # helicity style arrow arrowtopath = linepath.split(0.8*linepath.arclen())[0] constrictionlen = self.size * self.constriction * \ math.cos(self.angle*math.pi/360.0) arrowpath = pyx.deco._arrowhead(arrowtopath, linepath.arclen(), 1, self.size, 45, constrictionlen) canvas.fill(arrowpath, self.getCustomStyles()) path = pyx.deformer.parallel(-(n+1)/2. * dist).deform(arrowtopath) defo = pyx.deformer.parallel(dist) for m in range(n): path = defo.deform(path) canvas.stroke(path, self.getCustomStyles()) else: # ordinary (momentum) arrow canvas.stroke(linepath, styles) else: # curved arrow (always momentum-style) curvepiece = self.line.getPath().split([ (self.pos*p.arclen()-self.length/2.), (self.pos*p.arclen()+self.length/2.)]) arrpiece = curvepiece[1] if self.sense<0: arrpiece = arrpiece.reversed() linepath = pyx.deco.decoratedpath(pyx.deformer.parallel(displacement).deform(arrpiece)) styles = [pyx.deco.earrow(size=self.size, angle=self.angle, constriction=self.constriction)] # Allow us to add colouring etc. to the line styles.extend(self.getCustomStyles()) canvas.stroke(linepath.path,styles)
def draw(self, canvas): """Draw this arrow on the supplied canvas.""" p = self.line.getPath() posparam = p.begin() + self.pos * p.arclen() x, y = self.line.fracpoint(self.pos).getXY() arrx, arry = self.line.fracpoint(self.pos + self.length / 2. / p.arclen()).getXY() endx, endy = self.line.fracpoint(self.pos - self.length / 2. / p.arclen()).getXY() ## Calculate the displacement from the line displacement = self.displace intrinsicwidth = pyx.unit.length(0.1) if hasattr(self.line, "arcradius"): intrinsicwidth = self.line.arcradius if displacement > 0: displacement += intrinsicwidth else: displacement -= intrinsicwidth if config.getOptions().DEBUG: print("Displacement = ", displacement) ## Position the arrow on the right hand side of lines tangent = p.tangent(posparam, displacement) normal = tangent.transformed(pyx.trafo.rotate(90, x, y)) nx, ny = normal.atend() nxcm, nycm = pyx.unit.tocm(nx - x), pyx.unit.tocm(ny - y) vx, vy = p.atbegin() vxcm, vycm = pyx.unit.tocm(x - vx), pyx.unit.tocm(y - vy) ## If the arrow is on the left, flip it by 180 degrees if (vxcm * nycm - vycm * nxcm) > 0: normal = normal.transformed(pyx.trafo.rotate(180, x, y)) nx, ny = normal.atend() if displacement < 0: normal = normal.transformed(pyx.trafo.rotate(180, x, y)) nx, ny = normal.atend() if config.getOptions().VDEBUG: FeynDiagram.currentDiagram.currentCanvas.stroke(normal) ## Displace the arrow by this normal vector endx, endy = endx + (nx - x), endy + (ny - y) arrx, arry = arrx + (nx - x), arry + (ny - y) if self.sense < 0.: arrx, arry, endx, endy = endx, endy, arrx, arry if not self.curved: linepath = pyx.path.path(pyx.path.moveto(endx, endy), pyx.path.lineto(arrx, arry)) styles = [ pyx.deco.earrow(size=self.size, angle=self.angle, constriction=self.constriction) ] dist = self.stemsep n = self.stems if n > 1: # helicity style arrow arrowtopath = linepath.split(0.8 * linepath.arclen())[0] constrictionlen = self.size * self.constriction * \ math.cos(self.angle*math.pi/360.0) arrowpath = getarrowpath(arrowtopath, linepath.arclen(), 1, self.size, 45, self.constriction, constrictionlen) canvas.fill(arrowpath) path = pyx.deformer.parallel(-(n + 1) / 2. * dist).deform(arrowtopath) defo = pyx.deformer.parallel(dist) for m in range(n): path = defo.deform(path) canvas.stroke(path, []) else: # ordinary (momentum) arrow canvas.stroke(linepath, styles) else: # curved arrow (always momentum-style) curvepiece = self.line.getPath().split([ (self.pos * p.arclen() - self.length / 2.), (self.pos * p.arclen() + self.length / 2.) ]) arrpiece = curvepiece[1] if self.sense < 0: arrpiece = arrpiece.reversed() linepath = pyx.deco.decoratedpath( pyx.deformer.parallel(displacement).deform(arrpiece)) styles = [ pyx.deco.earrow(size=self.size, angle=self.angle, constriction=self.constriction) ] canvas.stroke(linepath.path, styles)
def getPath(self): """Get the path taken by this line.""" if self.arcthrupoint is None: ## This is a simple straight line return pyx.path.path( pyx.path.moveto( *(self.p1.getXY()) ), pyx.path.lineto( *(self.p2.getXY()) ) ) elif (self.p1.x() == self.p2.x() and self.p1.y() == self.p2.y()): ## This is a tadpole-type loop and needs special care; ## We shall assume that the arcthrupoint is meant to be ## the antipode of the basepoint arccenter = self.p1.midpoint(self.arcthrupoint) arcradius = self.p1.distance(self.arcthrupoint) / 2.0 ## TODO Why does a circle work and an arc doesn't? cargs = (arccenter.x(), arccenter.y(), arcradius) circle = pyx.path.circle(*cargs) line = pyx.path.line( self.p1.x(), self.p1.y(), arccenter.x(), arccenter.y()) if config.getOptions().VDEBUG: FeynDiagram.currenDiagram.currentCanvas.stroke(line, [color.rgb.green]) ass, bs = circle.intersect(line) subpaths = circle.split(ass[0]) cpath = subpaths[0] return cpath ## or, with an arc... arcangle1 = arccenter.arg(self.p1) arcangle2 = arccenter.arg(self.p1) + 360 arcargs = (arccenter.x(), arccenter.y(), arcradius, arcangle1, arcangle2) return pyx.path.path( pyx.path.arc(*arcargs) ) else: n13, n23 = None, None ## Work out line gradients try: n13 = (self.p1.y() - self.arcthrupoint.y()) / (self.p1.x() - self.arcthrupoint.x()) except ZeroDivisionError: if config.getOptions().DEBUG: print("Grad 1 diverges") n13 = 1e100 try: n23 = (self.p2.y() - self.arcthrupoint.y()) / (self.p2.x() - self.arcthrupoint.x()) except ZeroDivisionError: if config.getOptions().DEBUG: print("Grad 2 diverges") n23 = 1e100 ## If gradients match, ## then we have a straight line, so bypass the complexity if n13 == n23: return pyx.path.path( pyx.path.moveto(*(self.p1.getXY())), pyx.path.lineto(*(self.p2.getXY())) ) ## Otherwise work out conjugate gradients and midpoints m13, m23 = None, None try: m13 = -1.0 / n13 except ZeroDivisionError: m13 = 1e100 try: m23 = -1.0 / n23 except ZeroDivisionError: m23 = 1e100 mid13 = self.p1.midpoint(self.arcthrupoint) mid23 = self.p2.midpoint(self.arcthrupoint) ## Line y-intercepts c13 = mid13.y() - m13 * mid13.x() c23 = mid23.y() - m23 * mid23.x() ## Find the centre of the arc xcenter = - (c23 - c13) / (m23 - m13) ycenter = m13 * xcenter + c13 arccenter = Point(xcenter, ycenter) ## Get the angles required for drawing the arc arcradius = arccenter.distance(self.arcthrupoint) arcangle1 = arccenter.arg(self.p1) arcangle2 = arccenter.arg(self.p2) arcangle3 = arccenter.arg(self.arcthrupoint) arcargs = (arccenter.x(), arccenter.y(), arcradius, arcangle1, arcangle2) if config.getOptions().DEBUG and arcangle1 == arcangle2: print("Arc angles are the same - not drawing anything") ## Calculate cross product to determine direction of arc vec12 = [self.p2.x()-self.p1.x(), self.p2.y()-self.p1.y(), 0.0] vec13 = [self.arcthrupoint.x()-self.p1.x(), self.arcthrupoint.y()-self.p1.y(), 0.0] crossproductZcoord = vec12[0]*vec13[1] - vec12[1]*vec13[0] if crossproductZcoord < 0: return pyx.path.path( pyx.path.moveto(*(self.p1.getXY())), pyx.path.arc(*arcargs)) else: return pyx.path.path( pyx.path.moveto(*(self.p1.getXY())), pyx.path.arcn(*arcargs))