1 """Various particle line types."""
2
3 import pyx, math
4 from pyx import color
5
6 from diagrams import FeynDiagram
7 from points import Point
8 from deco import Arrow, Label
9 from utils import Visible, defunit
10
11
12
14 "Base class for all objects which connect points in Feynman diagrams"
15
17 self.p1 = point1
18 self.p2 = point2
19 self.styles = []
20 self.arcthrupoint = None
21 self.is3D = False
22 self.arrows = []
23 self.labels = []
24
25
26 FeynDiagram.currentDiagram.add(self)
27
28
29 - def addLabel(self, text, pos=0.5, displace=-0.25, angle = 0):
30 """Add a LaTeX label to this line, either via parameters or actually as
31 a TeXLable object."""
32 if FeynDiagram.options.DEBUG:
33 print "Adding label: " + text
34
35
36
37 self.labels.append(Label(text=text, line=self, pos=pos, displace=displace, angle=angle))
38 if FeynDiagram.options.DEBUG:
39 print "Labels = " + str(self.labels)
40 return self
41
42
44 self.labels = []
45 return self
46
47
49 """Get a new Point representing the point at the given fraction along
50 the fundamental line (i.e. no truncation or deformation).
51 TODO: Handle units properly."""
52 p = self.getPath()
53 x, y = p.at(p.begin() + frac * p.arclen())
54 return Point(x/defunit, y/defunit)
55
56
58
59 self.arrows = []
60 for i in arrows:
61 if i.__class__ == "deco.Arrow":
62 self.arrows.append(i)
63 else:
64 self.arrows.append(Arrow(pos = i))
65 return self
66
67
68 - def addArrow(self, position = 0.53, arrow = None):
69 """Add an arrow to the line at the specified position, which is a number
70 between 0 and 1, representing the fraction along the line at which the
71 arrow should be placed. The default arrow style can be overridden by
72 explicitly supplying an arrow object as the 'arrow' argument, in which
73 case the position argument will be ignored."""
74 if arrow:
75 self.arrows.append(arrow)
76 else:
77 self.arrows.append(Arrow(pos=position))
78 return self
79
80
82 """Remove all arrows from this line."""
83 self.arrows = []
84 return self
85
86
87 - def arcThru(self, arcpoint = None, x = None, y = None):
88 """Set the point through which this line will arc. Either pass a Point
89 or set x, y as floats."""
90 if arcpoint != None:
91 self.arcthrupoint = arcpoint
92 elif x != None and y != None:
93 self.arcthrupoint = Point(x, y)
94 else:
95 raise Exception("Tried to set an arcpoint with invalid arguments")
96 return self
97
98
100 """Make this line a straight line between start and end."""
101 self.arcthrupoint = None
102
103
104 - def bend(self, amount):
124
125
126 - def set3D(self, choice):
127 self.is3D = choice
128 return self
129
130
132 return self.styles
133
134
136 self.styles = stylelist
137 return self
138
139
141 self.styles.append(style)
142 return self
143
144
146 self.styles = self.styles + stylelist
147 return self
148
149
151 if self.arcthrupoint == None:
152
153 return pyx.path.path( pyx.path.moveto( *(self.p1.getXY()) ),
154 pyx.path.lineto( *(self.p2.getXY()) ) )
155 elif (self.p1.x() == self.p2.x() and self.p1.y() == self.p2.y()):
156
157
158
159 arccenter = self.p1.midpoint(self.arcthrupoint)
160 arcradius = self.p1.distance(self.arcthrupoint) / 2.0
161
162
163 cargs = (arccenter.x(), arccenter.y(), arcradius)
164 circle = pyx.path.circle(*cargs)
165 line = pyx.path.line( self.p1.x(), self.p1.y(), arccenter.x(), arccenter.y())
166 if FeynDiagram.options.VDEBUG:
167 FeynDiagram.currentCanvas.stroke(line, [color.rgb.green])
168 as, bs = circle.intersect(line)
169 subpaths = circle.split(as[0])
170 cpath = subpaths[0]
171 return cpath
172
173
174 arcangle1 = arccenter.arg(self.p1)
175 arcangle2 = arccenter.arg(self.p1) + 360
176 arcargs = (arccenter.x(), arccenter.y(), arcradius, arcangle1, arcangle2)
177 return pyx.path.path( pyx.path.arc(*arcargs) )
178
179 else:
180 n13, n23 = None, None
181
182 try:
183 n13 = (self.p1.y() - self.arcthrupoint.y()) / (self.p1.x() - self.arcthrupoint.x())
184 except ZeroDivisionError:
185 if FeynDiagram.options.DEBUG:
186 print "Grad 1 diverges"
187 n13 = 1e100
188
189 try:
190 n23 = (self.p2.y() - self.arcthrupoint.y()) / (self.p2.x() - self.arcthrupoint.x())
191 except ZeroDivisionError:
192 if FeynDiagram.options.DEBUG:
193 print "Grad 2 diverges"
194 n23 = 1e100
195
196
197
198 if n13 == n23:
199 return pyx.path.path( pyx.path.moveto(*(self.p1.getXY())),
200 pyx.path.lineto(*(self.p2.getXY())) )
201
202
203 m13, m23 = None, None
204 try:
205 m13 = -1.0 / n13
206 except ZeroDivisionError:
207 m13 = 1e100
208 try:
209 m23 = -1.0 / n23
210 except ZeroDivisionError:
211 m23 = 1e100
212 mid13 = self.p1.midpoint(self.arcthrupoint)
213 mid23 = self.p2.midpoint(self.arcthrupoint)
214
215
216 c13 = mid13.y() - m13 * mid13.x()
217 c23 = mid23.y() - m23 * mid23.x()
218
219
220 xcenter = - (c23 - c13) / (m23 - m13)
221 ycenter = m13 * xcenter + c13
222 arccenter = Point(xcenter, ycenter)
223
224
225 arcradius = arccenter.distance(self.arcthrupoint)
226 arcangle1 = arccenter.arg(self.p1)
227 arcangle2 = arccenter.arg(self.p2)
228 arcangle3 = arccenter.arg(self.arcthrupoint)
229 arcargs = (arccenter.x(), arccenter.y(), arcradius, arcangle1, arcangle2)
230
231 if FeynDiagram.options.DEBUG and arcangle1 == arcangle2:
232 print "Arc angles are the same - not drawing anything"
233
234
235 vec12 = [self.p2.x()-self.p1.x(), self.p2.y()-self.p1.y(), 0.0]
236 vec13 = [self.arcthrupoint.x()-self.p1.x(), self.arcthrupoint.y()-self.p1.y(), 0.0]
237 crossproductZcoord = vec12[0]*vec13[1] - vec12[1]*vec13[0]
238
239 if crossproductZcoord < 0:
240 return pyx.path.path( pyx.path.moveto(*(self.p1.getXY())),
241 pyx.path.arc(*arcargs))
242 else:
243 return pyx.path.path( pyx.path.moveto(*(self.p1.getXY())),
244 pyx.path.arcn(*arcargs))
245
246
248 """Find the subpath between the endpoints which isn't overshadowed by a blob of some kind"""
249 p1path = self.p1.getPath()
250 p2path = self.p2.getPath()
251 vispath = self.getPath()
252 if FeynDiagram.options.VDEBUG:
253 FeynDiagram.currentCanvas.stroke(vispath, [color.rgb.green])
254 if p1path:
255 as, bs = p1path.intersect(vispath)
256 for b in bs:
257 subpaths = vispath.split(b)
258 if len(subpaths) > 1:
259 if FeynDiagram.options.DEBUG:
260 print "Num subpaths 1 = %d" % len(subpaths)
261 subpaths.sort( lambda x, y : int(pyx.unit.tocm(x.arclen() - y.arclen())/math.fabs(pyx.unit.tocm(x.arclen() - y.arclen()))) )
262 vispath = subpaths[-1]
263 if FeynDiagram.options.VDEBUG:
264 FeynDiagram.currentCanvas.stroke(subpaths[0], [color.rgb.blue])
265 if FeynDiagram.options.VDEBUG:
266 for a in as:
267 ix, iy = p1path.at(a)
268 FeynDiagram.currentCanvas.fill(pyx.path.circle(ix, iy, 0.05), [color.rgb.green])
269 if p2path:
270 as, bs = p2path.intersect(vispath)
271 for b in bs:
272 subpaths = vispath.split(b)
273 if len(subpaths) > 1:
274 if FeynDiagram.options.DEBUG:
275 print "Num subpaths 2 = %d" % len(subpaths)
276 subpaths.sort( lambda x, y : int(pyx.unit.tocm(x.arclen() - y.arclen())/math.fabs(pyx.unit.tocm(x.arclen() - y.arclen()))) )
277 vispath = subpaths[-1]
278 if FeynDiagram.options.VDEBUG:
279 FeynDiagram.currentCanvas.stroke(subpaths[0], [color.rgb.red])
280 if FeynDiagram.options.VDEBUG:
281 for a in as:
282 ix, iy = p2path.at(a)
283 FeynDiagram.currentCanvas.fill(pyx.path.circle(ix, iy, 0.05), [color.rgb.blue])
284 if FeynDiagram.options.VDEBUG:
285 FeynDiagram.currentCanvas.stroke(vispath, [color.rgb.red])
286
287 return vispath
288
289
290 - def draw(self, canvas):
291 path = self.getVisiblePath()
292 styles = self.styles + self.arrows
293 if FeynDiagram.options.DEBUG:
294 print "Drawing " + str(self.__class__) + " with styles = " + str(styles)
295 print path
296 canvas.stroke(path, styles)
297 for l in self.labels:
298 l.draw(canvas)
299
300
302 pass
303
304
306 - def draw(self, canvas):
307 path = self.getVisiblePath()
308 styles = self.styles + [pyx.style.linestyle.dashed] + self.arrows
309
310 if FeynDiagram.options.DEBUG:
311 print "Drawing " + str(self.__class__) + " with styles = " + str(styles)
312 print path
313 canvas.stroke(path, styles)
314 for l in self.labels:
315 l.draw(canvas)
316
317
319 pass
320
321
322
323
325 """Base class for spring and sine-like lines"""
327 pass
328
330 pass
331
333 pass
334
337
338
339 -class Gluon(DecoratedLine):
340 """A line with a cycloid deformation"""
342 self.p1 = point1
343 self.p2 = point2
344 self.styles = []
345 self.arcthrupoint = None
346 self.is3D = False
347 self.arrows = []
348 self.labels = []
349 self.arcradius = pyx.unit.length(0.25)
350 self.elasticity = 1.3
351 self.inverted = False
352 self.linetype = "gluon"
353
354 FeynDiagram.currentDiagram.add(self)
355
356
358 self.inverted = not self.inverted
359 return self
360
361
363 return self.elasticity
364
365
367 self.elasticity = value
368 return self
369
370
384
385
386 - def draw(self, canvas):
387 styles = self.styles + self.arrows
388 if FeynDiagram.options.DEBUG:
389 print "Drawing " + str(self.__class__) + " with styles = " + str(styles)
390 canvas.stroke(self.getDeformedPath(), styles)
391 for l in self.labels:
392 l.draw(canvas)
393
394
395
397 """A line with a sinoid deformation"""
399 self.p1 = point1
400 self.p2 = point2
401 self.styles = []
402 self.arcthrupoint = None
403 self.is3D = False
404 self.arrows = []
405 self.labels = []
406 self.inverted = False
407 self.arcradius = pyx.unit.length(0.25)
408 self.linetype = "photon"
409
410 FeynDiagram.currentDiagram.add(self)
411
412
414 self.inverted = not self.inverted
415 return self
416
417
424
425
426 - def draw(self, canvas):
427 styles = self.styles + self.arrows
428 if FeynDiagram.options.DEBUG:
429 print "Drawing " + str(self.__class__) + " with styles = " + str(styles)
430 canvas.stroke(self.getDeformedPath(), styles)
431 for l in self.labels:
432 l.draw(canvas)
433
434
436 pass
437
438
439
440 NamedLine = {"photon" : Photon, "gluon" : Gluon, "fermion" : DecoratedLine}
441