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 fracpoint(self, frac): """ Get a new Point representing the point at the given fraction along the fundamental line (i.e. no truncation or deformation). TODO: Handle units properly. """ p = self.getPath() ## no truncation or deformation x, y = p.at(p.begin() + frac * p.arclen()) return Point(x/defunit, y/defunit)
def arcThru(self, arcpoint = None, x = None, y = None): """Set the point through which this line will arc. Either pass a Point or set x, y as floats.""" if arcpoint is not None: self.arcthrupoint = arcpoint elif x is not None and y is not None: self.arcthrupoint = Point(x, y) else: raise Exception("Tried to set an arcpoint with invalid arguments") return self
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))
bCOLOR = [BLUE] tCOLOR = [RED] dCOLOR = [RED] ZCOLOR = [RED] pCOLOR = [FORESTGREEN] eCOLOR = [BLUE] gCOLOR = [VIOLET] #------------------------------------------------------------------------- # tZq production (5FS) - WWZ vertex fd = FeynDiagram() # l1 = Label('Lowest Order', x=0, y=2) pntIn = [] pntOut = [] pntIn.append(Point(-3, +1.5)) pntIn.append(Point(-3, -1.5)) pntOut.append(Point(+3, +1.5)) pntOut.append(Point(+3, -1.5)) vtx = [] vtx.append(Vertex(0, +1.5, mark=CIRCLE, fill=[RED])) vtx.append(Vertex(0, -1.5, mark=CIRCLE, fill=[RED])) # Add Z boson on various lines vtx.append(Vertex(0.5, 0.0, mark=CIRCLE, fill=[RED])) pntOut.append(Point(+3, 0.0)) draw_fermion(pntIn[0], vtx[0], uCOLOR, r'\Pqu', displacement=+0.2) draw_fermion(vtx[0], pntOut[0], dCOLOR, r'\Pqd', displacement=+0.2) draw_boson(vtx[2], vtx[0], pCOLOR, r'\PW')