diff options
Diffstat (limited to 'Build/source/utils/axodraw2/axodraw2-src/axohelp.c')
-rw-r--r-- | Build/source/utils/axodraw2/axodraw2-src/axohelp.c | 3807 |
1 files changed, 0 insertions, 3807 deletions
diff --git a/Build/source/utils/axodraw2/axodraw2-src/axohelp.c b/Build/source/utils/axodraw2/axodraw2-src/axohelp.c deleted file mode 100644 index 6f818d7eff2..00000000000 --- a/Build/source/utils/axodraw2/axodraw2-src/axohelp.c +++ /dev/null @@ -1,3807 +0,0 @@ -/* - - Need to do: - 1. Fix reporting of number of object to in-file number - 2. Or Don't require object 0 for ID line - - #[ License : - - (C) 2016-2019 by authors: - John Collins (jcc8 at psu dot edu) - Jos Vermaseren (t68 at nikhef dot nl) - - axohelp is free software: you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your option) - any later version. - - axohelp is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - details. - - For the GNU General Public License see <http://www.gnu.org/licenses/>. - - #] License : - #[ Commentary + Modifications : - - This file contains the source code of the axohelp program that is used - together with axopdf.sty and pdflatex. It is a conversion of the postscript - code of axodraw.sty. - - input file contains objects of the type - [number] axohelp input - the output contains objects: - \axo@setObject{label}% - {input data}% - {output} - There may be blank lines and commentary. - - #[ About folds : (this line starts with one blank and two tabs) - - The internals of the file have been organized in folds. - These are defined as a range of lines if which the first and last - lines have a special format. Each starts with any three characters - (may include tabs), then #[ for the start line and #] for the closing - line, then both lines need identical name fields, closed by a colon. - After the colon can be anything. When a fold is closed one should see - only the first line but with the #[ replaced by ## as in - ## About folds : (this line starts with one blank and two tabs) - Folds can be nested. - This fold concept comes originally from the occam compiler for the - transputer in the second half of the 1980's although there it was - implemented differently. It was taken over by the STedi editor in its - current form. The sources of this editor are available from the form - home site: http://www.nikhef.nl/~form - Some people have managed to emulate these folds in editors like emacs - and vim. - - #] About folds : - #] Commentary + Modifications : - #[ Includes : -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <math.h> -#include <string.h> -#include <ctype.h> - -/* - #] Includes : - #[ Defines : -*/ - -#define NAME "axohelp" -#define VERSIONDATE "2019 Aug 28" -#define VERSION 1 -#define SUBVERSION 3 - -#define COMMENTCHAR '%' -#define TERMCHAR ';' - -#define STROKING 0 -#define NONSTROKING 1 - -char **inputs; -long *inputsizes; -double **inargs; -long numinputs = 0; -long inputallocations = 0; -char *axohelp; -FILE *outfile; -char *inname, *outname; -int VerboseFlag = 0; -char outputbuffer[1000000]; -char *outpos; -long numobject; -char *nameobject; -int witharrow = 0; -int identification = 0; - -static int lastlinefeed = 1; -static double axolinewidth = 0.5; -static struct aRRow { - double stroke; - double width; - double length; - double inset; - double where; - double scale; - double aspect; - int type; /* 0: old style arrow; 1: Jaxodraw style arrow */ - int adjust; /* whether the line length should be adjusted */ -} arrow; -double linesep = 0; -int flip = 0; -int clockwise = 0; - -void CleanupOutput(char *str); -void send( char* str ); -void sendClean( char* str ); - -void ArrowHead(); -void GetArrow(double *); -void BezierArrow(double *); -void ArcSegment(double,double,double); -double *ReadArray(char *,int *,int *); -double *ReadTail(char *,int *); -double LengthBezier(double,double,double,double,double,double,double); - -double M_pi; -double torad; -#define COS(x) cos((x)*torad) -#define SIN(x) sin((x)*torad) -#define TAN(x) tan((x)*torad) - -typedef void (*TFUN)(double *); - -typedef struct { - char *name; - TFUN func; - int numargs; - int colortype; -} KEYWORD; - -double mod(double,int); - -void GluonHelp(double *,double); -void DoubleGluonHelp(double *,double,double,double,double); -void GluonCircHelp(double *); -void GluonArcHelp(double *,double,double); -void PhotonHelp(double *,double); -void PhotonArcHelp(double *,double,int); -void ZigZagHelp(double *,double); -void ZigZagArcHelp(double *); -double ComputeDash(double *,double,double); -double ComputeDashCirc(double *,double); - -void ArrowArc(double *); -void ArrowArcn(double *); -void ArrowDoubleArc(double *); -void ArrowLine(double *); -void ArrowDoubleLine(double *); -void AxoArc(double *); -void AxoBezier(double *); -void AxoGluon(double *); -void AxoGluonArc(double *); -void AxoGluonCirc(double *); -void AxoLine(double *); -void AxoPhoton(double *); -void AxoPhotonArc(double *); -void AxoZigZag(double *); -void AxoZigZagArc(double *); -void BezierCurve(double *); -void Boxc(double *); -void CArc(double *); -void DashArrowArc(double *); -void DashArrowArcn(double *); -void DashArrowLine(double *); -void DashArrowDoubleArc(double *); -void DashArrowDoubleLine(double *); -void DashBezier(double *); -void DashCArc(double *); -void DashDoubleArc(double *); -void DashDoubleBezier(double *); -void DashDoubleLine(double *); -void DashDoublePhoton(double *); -void DashDoublePhotonArc(double *); -void DashDoubleZigZag(double *); -void DashDoubleZigZagArc(double *); -void DashGluon(double *); -void DashGluonArc(double *); -void DashGluonCirc(double *); -void DashPhoton(double *); -void DashPhotonArc(double *); -void DashZigZag(double *); -void DashZigZagArc(double *); -void DashLine(double *); -void DoubleArc(double *); -void DoubleBezier(double *); -void DoubleLine(double *); -void DoublePhoton(double *); -void DoublePhotonArc(double *); -void DoubleZigZag(double *); -void DoubleZigZagArc(double *); -void EBox(double *); -void EBoxc(double *); -void ECirc(double *); -void ETri(double *); -void FBox(double *); -void FBoxc(double *); -void FOval(double *); -void FTri(double *); -void GluonArc(double *); -void GluonCirc(double *); -void Gluon(double *); -void Grid(double *); -void LinAxis(double *); -void Line(double *); -void LogAxis(double *); -void Oval(double *); -void Photon(double *); -void PhotonArc(double *); -void Rotate(double *); -void Vertex(double *); -void ZigZag(double *); -void ZigZagArc(double *); - -void Curve(double *,int); -void DashCurve(double *,int); -void Polygon(double *,int,int); - -void Inivars(void); - -KEYWORD commands[] = { - { "Line", Line, 4, STROKING } - ,{ "ArrowArc", ArrowArc, 7, STROKING } - ,{ "ArrowArcn", ArrowArcn, 7, STROKING } - ,{ "ArrowDoubleArc", ArrowDoubleArc, 8, STROKING } - ,{ "ArrowLine", ArrowLine, 6, STROKING } - ,{ "ArrowDoubleLine", ArrowDoubleLine, 7, STROKING } - ,{ "AxoArc", AxoArc, 17, STROKING } - ,{ "AxoBezier", AxoBezier, 19, STROKING } - ,{ "AxoGluon", AxoGluon, 8, STROKING } - ,{ "AxoGluonArc", AxoGluonArc, 10, STROKING } - ,{ "AxoGluonCirc", AxoGluonCirc, 8, STROKING } - ,{ "AxoLine", AxoLine, 15, STROKING } - ,{ "AxoPhoton", AxoPhoton, 8, STROKING } - ,{ "AxoPhotonArc", AxoPhotonArc, 10, STROKING } - ,{ "AxoZigZag", AxoZigZag, 8, STROKING } - ,{ "AxoZigZagArc", AxoZigZagArc, 10, STROKING } - ,{ "Bezier", BezierCurve, 8, STROKING } - ,{ "Boxc", Boxc, 4, STROKING } - ,{ "CArc", CArc, 5, STROKING } - ,{ "DashArrowArc", DashArrowArc, 8, STROKING } - ,{ "DashArrowArcn", DashArrowArcn, 8, STROKING } - ,{ "DashArrowDoubleArc", DashArrowDoubleArc, 9, STROKING } - ,{ "DashArrowDoubleLine",DashArrowDoubleLine,8, STROKING } - ,{ "DashArrowLine", DashArrowLine, 7, STROKING } - ,{ "DashBezier", DashBezier, 9, STROKING } - ,{ "DashCArc", DashCArc, 6, STROKING } - ,{ "DashDoubleArc", DashDoubleArc, 7, STROKING } - ,{ "DashDoubleBezier", DashDoubleBezier, 10, STROKING } - ,{ "DashDoubleLine", DashDoubleLine, 6, STROKING } - ,{ "DashDoublePhoton", DashDoublePhoton, 8, STROKING } - ,{ "DashDoublePhotonArc",DashDoublePhotonArc,10, STROKING } - ,{ "DashDoubleZigZag", DashDoubleZigZag, 8, STROKING } - ,{ "DashDoubleZigZagArc",DashDoubleZigZagArc,10, STROKING } - ,{ "DashGluon", DashGluon, 7, STROKING } - ,{ "DashGluonArc", DashGluonArc, 10, STROKING } - ,{ "DashGluonCirc", DashGluonCirc, 7, STROKING } - ,{ "DashLine", DashLine, 5, STROKING } - ,{ "DashPhoton", DashPhoton, 7, STROKING } - ,{ "DashPhotonArc", DashPhotonArc, 10, STROKING } - ,{ "DashZigZag", DashZigZag, 7, STROKING } - ,{ "DashZigZagArc", DashZigZagArc, 10, STROKING } - ,{ "DoubleArc", DoubleArc, 6, STROKING } - ,{ "DoubleBezier", DoubleBezier, 9, STROKING } - ,{ "DoubleLine", DoubleLine, 5, STROKING } - ,{ "DoublePhoton", DoublePhoton, 7, STROKING } - ,{ "DoublePhotonArc", DoublePhotonArc, 8, STROKING } - ,{ "DoubleZigZag", DoubleZigZag, 7, STROKING } - ,{ "DoubleZigZagArc", DoubleZigZagArc, 8, STROKING } - ,{ "EBox", EBox, 4, STROKING } - ,{ "FBox", FBox, 4, STROKING } - ,{ "FBoxc", FBoxc, 4, STROKING } - ,{ "ECirc", ECirc, 3, STROKING } - ,{ "ETri", ETri, 6, STROKING } - ,{ "FOval", FOval, 5, NONSTROKING } - ,{ "FTri", FTri, 6, NONSTROKING } - ,{ "GluonArc", GluonArc, 7, STROKING } - ,{ "GluonCirc", GluonCirc, 6, STROKING } - ,{ "Gluon", Gluon, 6, STROKING } - ,{ "Grid", Grid, 6, STROKING } - ,{ "LinAxis", LinAxis, 8, STROKING } - ,{ "LogAxis", LogAxis, 7, STROKING } - ,{ "Oval", Oval, 5, STROKING } - ,{ "Photon", Photon, 6, STROKING } - ,{ "PhotonArc", PhotonArc, 7, STROKING } - ,{ "Rotate", Rotate, 7, NONSTROKING } - ,{ "Vertex", Vertex, 3, NONSTROKING } - ,{ "ZigZag", ZigZag, 6, STROKING } - ,{ "ZigZagArc", ZigZagArc, 7, STROKING } -}; - -/* - #] Defines : - #[ SetDefaults : -*/ - -void SetDefaults() -{ - lastlinefeed = 1; - axolinewidth = 0.5; - linesep = 0; - flip = 0; - clockwise = 0; - witharrow = 0; -} - -/* - #] SetDefaults : - #[ mod : -*/ - -double mod( double x, int n ) { - /* Return x mod n, with positive returned value in range 0<=result<n. - (up to rounding error). - */ - x = fmod(x, n); - if (x >= n) { x -= n; } - if (x < 0) { x += n; } - return x; -} - -/* - #] mod : - #[ PDF utilities : - - These routines are included to make the program more readable and easier - to write. It also allows the easy use of the OutputString?? OLD name routine that - compactifies the output. -*/ - -#define Stroke send(" S") -#define CloseAndStroke send(" h S") -#define Fill send(" f") -#define CloseAndFill send(" h f") -#define SaveGraphicsState send(" q") -#define RestoreGraphicsState send(" Q") - -void Bezier(double x1,double y1,double x2,double y2,double x3,double y3) { - sprintf(outputbuffer,"\n %12.3f %12.3f %12.3f %12.3f %12.3f %12.3f c",x1,y1,x2,y2,x3,y3); - sendClean(outputbuffer); -} - -void LineTo(double x1,double y1) { - sprintf(outputbuffer,"\n %12.3f %12.3f l",x1,y1); - sendClean(outputbuffer); -} - -void MoveTo(double x1,double y1) { - sprintf(outputbuffer,"\n %12.3f %12.3f m",x1,y1); - sendClean(outputbuffer); -} - -void SetLineWidth(double w) { - sprintf(outputbuffer," %12.3f w",w); - sendClean(outputbuffer); -} - -void SetDashSize(double dashsize,double phase) { - if ( dashsize ) { - sprintf(outputbuffer," [%12.3f] %12.3f d",dashsize,phase); - sendClean(outputbuffer); - } - else send(" [] 0 d"); -} - -void SetTransferMatrix(double x11,double x12,double x21,double x22,double x,double y) -{ - if ( ( fabs(x11-1.) > 0.001 ) || ( fabs(x22-1.) > 0.001 ) - || ( fabs(x12) > 0.001 ) || ( fabs(x21) > 0.001 ) - || ( fabs(x) > 0.001 ) || ( fabs(y) > 0.001 ) ) { - sprintf(outputbuffer,"%12.3f %12.3f %12.3f %12.3f %12.3f %12.3f cm\n",x11,x12,x21,x22,x,y); - sendClean(outputbuffer); - } -} - -static double BzK; - -void BezierCircle(double r,char *action) -{ - char *outpos = outputbuffer; - outpos += - sprintf(outpos," %12.3f 0 m %12.3f %12.3f %12.3f %12.3f 0 %12.3f c\n",-r,-r,r*BzK,-r*BzK,r,r); - outpos += - sprintf(outpos," %12.3f %12.3f %12.3f %12.3f %12.3f 0 c\n",r*BzK,r,r,r*BzK,r); - outpos += - sprintf(outpos," %12.3f %12.3f %12.3f %12.3f 0 %12.3f c\n",r,-r*BzK,r*BzK,-r,-r); - outpos += - sprintf(outpos," %12.3f %12.3f %12.3f %12.3f %12.3f 0 c %s\n",-r*BzK,-r,-r,-r*BzK,-r,action); - sendClean(outputbuffer); -} - -void BezierOval(double w, double h, char *action) -{ - char *outpos = outputbuffer; - outpos += - sprintf(outpos," %12.3f 0 m %12.3f %12.3f %12.3f %12.3f 0 %12.3f c\n",-w,-w,h*BzK,-w*BzK,h,h); - outpos += - sprintf(outpos," %12.3f %12.3f %12.3f %12.3f %12.3f 0 c\n",w*BzK,h,w,h*BzK,w); - outpos += - sprintf(outpos," %12.3f %12.3f %12.3f %12.3f 0 %12.3f c\n",w,-h*BzK,w*BzK,-h,-h); - outpos += - sprintf(outpos," %12.3f %12.3f %12.3f %12.3f %12.3f 0 c %s\n",-w*BzK,-h,-w,-h*BzK,-w,action); - sendClean(outputbuffer); -} - -void SetGray(double grayscale,int par) -{ - if ( par == STROKING ) { - sprintf(outputbuffer," %12.3f G",grayscale); - } - else { - sprintf(outputbuffer," %12.3f g",grayscale); - } - sendClean(outputbuffer); -} - -void SetColor(double c, double m, double y, double k,int par) -{ - if ( par == STROKING ) { - sprintf(outputbuffer," %12.3f %12.3f %12.3f %12.3f K",c,m,y,k); - } - else { - sprintf(outputbuffer," %12.3f %12.3f %12.3f %12.3f k",c,m,y,k); - } - sendClean(outputbuffer); -} - -void SetBackgroundColor(int par) -{ - if ( par == STROKING ) { send(" 0 0 0 0 K"); } - else { send(" 0 0 0 0 k"); } -} - -void Rectangle(double x,double y,double w,double h) { - sprintf(outputbuffer,"\n %12.3f %12.3f %12.3f %12.3f re",x,y,w,h); - sendClean(outputbuffer); -} - -void Triangle(double x1,double y1,double x2,double y2,double x3,double y3) { - sprintf(outputbuffer,"\n %12.3f %12.3f m %12.3f %12.3f l %12.3f %12.3f l h",x1,y1,x2,y2,x3,y3); - sendClean(outputbuffer); -} - -/* - #] PDF utilities : - #[ Service routines : - #[ GetArrow : -*/ - -void GetArrow(double *args) -{ - witharrow = args[7]; - arrow.stroke = args[0]; - arrow.width = args[1]; - arrow.length = args[2]; - arrow.inset = args[3]; - arrow.scale = args[4]; - arrow.aspect = args[5]; - arrow.where = args[6]; - arrow.type = 1; - arrow.adjust = 0; - if ( args[8] ) flip = 1; - if ( witharrow ) { - if ( arrow.length == 0 && arrow.width == 0 ) { - arrow.width = (axolinewidth + 0.7*linesep + 1 ) * 1.2; - if (arrow.width < 2.5) arrow.width = 2.5; - arrow.length = 2*arrow.width*arrow.aspect; - } - else if ( arrow.width == 0 ) { - arrow.width = arrow.length/(2*arrow.aspect); - } - else if ( arrow.length == 0 ) { - arrow.length = 2*arrow.width*arrow.aspect; - } - arrow.width *= arrow.scale; - arrow.length *= arrow.scale; - if ( arrow.where > 1 ) { arrow.where = 1; arrow.adjust = 1; } - if ( arrow.where < 0 ) { arrow.where = 0; arrow.adjust = 1; } - } -} - -/* - #] GetArrow : - #[ ArrowHead : - - Places an arrowhead of a given size at 0 in the +x direction - The size: Full width is 2*size and full length is also 2*size. -*/ - -void ArrowHead() -/* - Jaxodraw style arrows -*/ -{ - int k; - double length; - SaveGraphicsState; - if ( flip ) length = -arrow.length; - else length = arrow.length; - SetDashSize(0,0); - if ( arrow.stroke ) { - SetLineWidth(arrow.stroke); - for (k = 1; k <= 2; k++ ) { - SaveGraphicsState; - MoveTo(length*0.5,0); - LineTo(-length*0.5,arrow.width); - LineTo(-length*0.5+length*arrow.inset,0); - LineTo(-length*0.5,-arrow.width); - if (k == 1) { - SetBackgroundColor(NONSTROKING); - send(" h f"); - } - else { - send(" s"); - } - RestoreGraphicsState; - } - } - else { - MoveTo(length*0.5,0); - LineTo(-length*0.5,arrow.width); - LineTo(-length*0.5+length*arrow.inset,0); - LineTo(-length*0.5,-arrow.width); - send(" h f"); - } - RestoreGraphicsState; -} - -/* - #] ArrowHead : - #[ BezierArrow : - - We compute the length of the curve. - Then we try to find the t value for which holds: - Length(t)/Length(1) = arrow.where -*/ - -void BezierArrow(double *args) -{ - double t,u,x,y,dx,dy,dr,len,tlen,tmin=0,tmax=1.0; - double x1=args[2]-args[0],x2=args[4]-args[0],x3=args[6]-args[0]; - double y1=args[3]-args[1],y2=args[5]-args[1],y3=args[7]-args[1]; - len = LengthBezier(x1,y1,x2,y2,x3,y3,1.0); - t = arrow.where; - tlen = LengthBezier(x1,y1,x2,y2,x3,y3,t); - while ( fabs(tlen/len-arrow.where) > 0.0001 ) { - if ( tlen/len > arrow.where ) { - tmax = t; - t = 0.5*(tmin+t); - } - else { - tmin = t; - t = 0.5*(tmax+t); - } - tlen = LengthBezier(x1,y1,x2,y2,x3,y3,t); - } - u = 1-t; - x = args[0]*u*u*u+(3*args[2]*u*u+(3*args[4]*u+args[6]*t)*t)*t; - y = args[1]*u*u*u+(3*args[3]*u*u+(3*args[5]*u+args[7]*t)*t)*t; - dx = 3*(-args[0]*u*u+args[2]*u*(1-3*t)+args[4]*t*(2-3*t)+args[6]*t*t); - dy = 3*(-args[1]*u*u+args[3]*u*(1-3*t)+args[5]*t*(2-3*t)+args[7]*t*t); - dr = sqrt(dx*dx+dy*dy); - SetTransferMatrix(1,0,0,1,x,y); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - ArrowHead(); -} - -/* - #] BezierArrow : - #[ ArcSegment : -*/ - -void ArcSegment(double r, double phi1, double dphi) -{ - double xphi, d, x, y, phia, phib, x1,y1,x2,y2,x3,y3; - int num, i; - - num = dphi/90.0001+1.; /* number of segments we should use. */ - xphi = dphi/num; /* arc size of each segment */ - d = 4.*TAN(xphi/4.)/3.; /* the magic distance for the control points */ - - x = r*COS(phi1); y = r*SIN(phi1); - MoveTo(x,y); - for ( i = 0; i < num; i++ ) { - phia = phi1+i*xphi; /* Start of segment */ - phib = phia+xphi; /* End of segment */ - x3 = r*COS(phib); y3 = r*SIN(phib); - x1 = x - y*d; y1 = y + x*d; - x2 = x3+y3*d; y2 = y3-x3*d; - - Bezier(x1,y1,x2,y2,x3,y3); - - x = x3; y = y3; - } -} - -/* - #] ArcSegment : - #[ ReadNumber : -*/ - -char *ReadNumber(char *s,double *num) -{ - double x3,minus = 1; - int x1,x2; - while ( *s == '+' || *s == '-' ) { - if ( *s == '-' ) minus = -minus; - s++; - } - x1 = x2 = 0; x3 = 1; - while ( *s <= '9' && *s >= '0' ) { x1 = 10*x1 + *s++ - '0'; } - if ( *s == 0 ) { *num = x1*minus; return(s); } - if ( *s == '.' ) { - s++; - while ( *s >= '0' && *s <= '9' ) { x2 = 10*x2 + *s++ - '0'; x3 *= 10; } - } - *num = minus*((double)x1 + x2/x3); - return(s); -} - -/* - #] ReadNumber : - #[ ReadArray : - - Reads a tail of floats of the type (x1,y1)(x2,y2),...,(xn,yn) or - (x1,y1)(x2,y2),...,(xn,yn) f1 ... fm - The floats may be written as integers. - Normally they are in the format ####.### - In num1 we return the number of coordinates encountered. - In num2 we return the number of extra floats encountered. - The array of the return value should be freed after it has been used. -*/ - -double *ReadArray(char *inbuf, int *num1, int *num2) -{ - int argsize = 0, newsize, num = 0, i; - double *args = 0, *newargs = 0, *extraargs, x, y; - char *s; - *num2 = 0; - s = inbuf; - while ( *s == ' ' || *s == '\t' || *s == '\n' ) s++; - if ( *s == '"' ) { - s++; - while ( *s == ' ' || *s == '\t' || *s == '\n' ) s++; - } - while ( *s == '(' ) { /* We need to read (x,y) */ - s++; - while ( *s == ' ' || *s == '\n' || *s == '\t' ) s++; - s = ReadNumber(s,&x); - while ( *s == ' ' ) s++; - if ( *s != ',' ) { - fprintf(stderr,"%s: Illegal format for array of numbers in object %ld of type %s in file %s\n" - ,axohelp,numobject,nameobject,inname); - free(args); - return(0); - } - s++; - while ( *s == ' ' || *s == '\n' || *s == '\t' ) s++; - s = ReadNumber(s,&y); - while ( *s == ' ' || *s == '\n' || *s == '\t' ) s++; - if ( *s != ')' ) { - fprintf(stderr,"%s: Illegal format for array of numbers in object %ld of type %s in file %s\n" - ,axohelp,numobject,nameobject,inname); - free(args); - return(0); - } - s++; - while ( *s == ' ' ) s++; - num += 2; - if ( num >= argsize ) { - if ( argsize == 0 ) newsize = 20; - else newsize = 2*argsize; - newargs = (double *)malloc(sizeof(double)*newsize); - if ( args == 0 ) { args = newargs; argsize = newsize; } - else { - for ( i = 0; i < argsize; i++ ) newargs[i] = args[i]; - free(args); - args = newargs; argsize = newsize; - } - } - args[num-2] = x; args[num-1] = y; - } - if ( *s == '"' ) s++; - while ( *s == ' ' || *s == '\t' || *s == '\n' ) s++; - *num1 = num/2; - - if ( *s ) { - if ( ( extraargs = ReadTail(s,num2) ) == 0 ) { - return(0); - } - if ( num+*num2 > argsize ) { - newargs = (double *)malloc(sizeof(double)*(num+*num2)); - for ( i = 0; i < num; i++ ) newargs[i] = args[i]; - free(args); - args = newargs; - argsize = num+*num2; - } - for ( i = 0; i < *num2; i++ ) args[num+i] = extraargs[i]; - free(extraargs); - } - return(args); -} - -/* - #] ReadArray : - #[ ReadTail : - - Reads a command tail that consists of floating point numbers in the - notation xxx.yyy or just as integers without even the decimal point. - The output array is allocated and should be returned in a well behaved - program. -*/ - -double *ReadTail(char *buff,int *number) -{ - char *s; - int num = 1, i; - double *outargs; - s = buff; - while ( *s ) { - if ( *s == ' ' || *s == '\t' || *s == '\n' ) { - num++; *s++ = 0; - while ( *s == ' ' || *s == '\t' || *s == '\n' ) *s++ = 0; - } - else s++; - } - outargs = (double *)malloc(num*sizeof(double)); - s = buff; - for ( i = 0; i < num; i++ ) { - while ( *s == 0 ) s++; - s = ReadNumber(s,outargs+i); - if ( *s == 'p' && s[1] == 't' ) s += 2; - if ( *s != 0 ) { - fprintf(stderr,"%s: Illegal format for number in command %ld (%s) in file %s.\n" - ,axohelp,numobject,nameobject,inname); - free(outargs); - return(0); - } - } - *number = num; - return(outargs); -} - -/* - #] ReadTail : - #[ DoCurve : - - Interpolation curve expressed as a Bezier curve. -*/ - -void DoCurve(double x0, double y0, double x1, double y1, - double x2, double y2, double x3, double y3) -{ - double xx1, yy1, xx2, yy2; - xx1 = (2*x1+x2)/3; - yy1 = ((y1-y0)/(x1-x0)*(x2-x0)+(y2-y0)/(x2-x0)*(x1-x0)+y1+2*y0)/3; - xx2 = (x1+2*x2)/3; - yy2 = ((y2-y3)/(x2-x3)*(x1-x3)+(y1-y3)/(x1-x3)*(x2-x3)+y2+2*y3)/3; - - Bezier(xx1,yy1,xx2,yy2,x2,y2); -} - -/* - #] DoCurve : - #[ LengthBezier : - - Routine computes the length of a Bezier curve. - Method: - x = x0*(1-t)^3+3*x1*t*(1-t)^2+3*x2*t^2*(1-t)+x3*t^3 - y = y0*(1-t)^3+3*y1*t*(1-t)^2+3*y2*t^2*(1-t)+y3*t^3 - We assume that x0=y0=0. (Hence call with x1-x0 etc) - --> dx/dt = 3*x1*(1-t)*(1-3*t)+3*x2*t*(2-3*t)+3*x3*t^2 - = 3*(x1+2*t*(x2-2*x1)+t^2*(x3-3*x2+3*x1)) - --> L = int_0^1 dt * sqrt(dx^2+dy^2) - We use ordinary Gaussian quadratures over the domain -1,...,+1 - - We have here quadratures for 8, 16 or 32 points. - For the moment we use the 16 point quadrature. It seems to work well. - The numbers were taken from Abramowitz and Stegun. -*/ - -typedef struct quad { - double x; - double w; -} QUAD; - -QUAD g8[4] = { - { 0.183434642495650, 0.362683783378362 } - ,{ 0.525532409916329, 0.313706645877887 } - ,{ 0.796666477413627, 0.222381034453374 } - ,{ 0.960289856497536, 0.101228536290376 } - }; -QUAD g16[8] = { - { 0.095012509837637440185, 0.189450610455068496285 } - ,{ 0.281603550779258913230, 0.182603415044923588867 } - ,{ 0.458016777657227386342, 0.169156519395002538189 } - ,{ 0.617876244402643748447, 0.149595988816576732081 } - ,{ 0.755404408355003033895, 0.124628971255533872052 } - ,{ 0.865631202387831743880, 0.095158511682492784810 } - ,{ 0.944575023073232576078, 0.062253523938647892863 } - ,{ 0.989400934991649932596, 0.027152459411754094852 } - }; -QUAD g32[16] = { - { 0.048307665687738316235, 0.096540088514727800567 } - ,{ 0.144471961582796493485, 0.095638720079274859419 } - ,{ 0.239287362252137074545, 0.093844399080804565639 } - ,{ 0.331868602282127649780, 0.091173878695763884713 } - ,{ 0.421351276130635345364, 0.087652093004403811143 } - ,{ 0.506899908932229390024, 0.083311924226946755222 } - ,{ 0.587715757240762329041, 0.078193895787070306472 } - ,{ 0.663044266930215200975, 0.072345794108848506225 } - ,{ 0.732182118740289680387, 0.065822222776361846838 } - ,{ 0.794483795967942406963, 0.058684093478535547145 } - ,{ 0.849367613732569970134, 0.050998059262376176196 } - ,{ 0.896321155766052123965, 0.042835898022226680657 } - ,{ 0.934906075937739689171, 0.034273862913021433103 } - ,{ 0.964762255587506430774, 0.025392065309262059456 } - ,{ 0.985611511545268335400, 0.016274394730905670605 } - ,{ 0.997263861849481563545, 0.007018610009470096600 } - }; - -double LengthBezier(double x1,double y1,double x2,double y2,double x3,double y3,double tmax) -{ - double xa = 3*x1, xb = 6*(x2-2*x1), xc = 3*(x3-3*x2+3*x1); - double ya = 3*y1, yb = 6*(y2-2*y1), yc = 3*(y3-3*y2+3*y1); - double t, sum = 0, dx, dy; - int j; - - for ( j = 0; j < 8; j++ ) { - t = 0.5*(1+g16[j].x)*tmax; - dx = xa+t*(xb+t*xc); - dy = ya+t*(yb+t*yc); - sum += 0.5*g16[j].w*sqrt(dx*dx+dy*dy); - t = 0.5*(1-g16[j].x)*tmax; - dx = xa+t*(xb+t*xc); - dy = ya+t*(yb+t*yc); - sum += 0.5*g16[j].w*sqrt(dx*dx+dy*dy); - } - return(sum*tmax); -} - -/* - #] LengthBezier : - #] Service routines : - #[ ScanForObjects : - - Routine reads the input buffer and sets up pointers to the commands. - Basically it is responsible for checking the input syntax and making - sure all commands will have the proper number of arguments. -*/ - -long ScanForObjects(char *buffer) -{ - char *s = buffer, *t; - if ( *s == COMMENTCHAR ) { while ( *s && *s != '\n' ) s++; } - while ( *s ) { /* here we are to look for a new command */ - if ( *s != '[' ) { /* for the case of the very first character */ - while ( *s && ( *s != '[' || ( *s == '[' && s[-1] == '\\' ) ) ) { - if ( *s == ' ' || *s == '\n' ) { - while ( *s == ' ' || *s == '\n' ) s++; /* Skip blank lines */ - } - else if ( *s == COMMENTCHAR && s[-1] != '\\' ) { - while ( *s && *s != '\n' ) s++; - } - else s++; - } - } - if ( *s == 0 ) break; -/* - if everything is correct we are now on a [ - a: look for matching ] in the same line. This defines the label. -*/ - t = s+1; - while ( *t && *t != ']' && *t != '\n' && ( *t != COMMENTCHAR || - ( *t == COMMENTCHAR && t[-1] != '\\' ) ) ) t++; - if ( *t == 0 ) { - fprintf(stderr,"%s: irregular end of file %s.\n",axohelp,inname); - return(-1); - } - else if ( *t == '\n' ) { - fprintf(stderr,"%s: a label in file %s should inside a single line.\n",axohelp,inname); - return(-1); - } - else if ( *t == COMMENTCHAR ) { - fprintf(stderr,"%s: illegal comment character inside a label in file %s.\n",axohelp,inname); - return(-1); - } - else if ( *t != ']' ) { - fprintf(stderr,"%s: internal error reading a label in file %s.\n",axohelp,inname); - return(-1); - } -/* - Store the address of this command -*/ - if ( numinputs >= inputallocations ) { /* we need more space */ - long newnum, i; - char **newadd; - if ( inputallocations == 0 ) { newnum = 100; } - else { newnum = 2*inputallocations; } - if ( ( newadd = (char **)malloc(newnum*sizeof(char *)) ) == 0 ) { - fprintf(stderr,"%s: memory error reading file %s\n",axohelp,inname); - return(-1); - } - for ( i = 0; i < inputallocations; i++ ) { newadd[i] = inputs[i]; } - if ( inputs != 0 ) free(inputs); - inputs = newadd; - inputallocations = newnum; - } - inputs[numinputs++] = s; -/* - Now scan for the first comment character. That is the end of the object. -*/ - while ( *t && ( *t != TERMCHAR || ( *t == TERMCHAR && t[-1] == '\\' ) ) - && *t != '[' ) t++; - if ( *t != '[' ) { - while ( t[-1] == ' ' || t[-1] == '\n' ) t--; - *t++ = 0; - } - s = t; - } - return(numinputs); -} - -/* - #] ScanForObjects : - #[ ReadInput : -*/ - -char *ReadInput(char *filename) -{ - FILE *finput; - long filesize, num; - char *buffer; - if ( ( finput = fopen(filename,"r") ) == 0 ) { - fprintf(stderr,"%s: Cannot open file %s\n",axohelp,filename); - exit(1); - } - if ( ( fseek(finput,0,SEEK_END) != 0 ) - || ( ( filesize = ftell(finput) ) < 0 ) - || ( fseek(finput,0,SEEK_SET) != 0 ) ) { - fprintf(stderr,"%s: File error in file %s\n",axohelp,filename); - exit(1); - } - if ( ( buffer = malloc((filesize+1)*sizeof(char)) ) == 0 ) { - fprintf(stderr,"%s: Error allocating %ld bytes of memory",axohelp,filesize+1); - exit(1); - } -/* - Assume character in file is 1 byte, which is true for all cases - we currently encounter. -*/ - num = fread( buffer, 1, filesize, finput ); - if ( ferror(finput) ) { - fprintf(stderr,"%s: Error reading file %s\n",axohelp,filename); - exit(1); - } -/* - By definition, fread reads ALL the items specified, or it gets to - end-of-file, or there is an error. - It returns the actual number of items successfully read, which - is less than the number given in the 3rd argument ONLY if a - read error or end-of-file is encountered. - We have already tested for an error. - But num could legitimately be less than filesize, because of - translation of CRLF to LF (on MSWindows with MSWindows text file). -*/ - buffer[num] = 0; - fclose(finput); - return(buffer); -} - -/* - #] ReadInput : - #[ CleanupOutput : -*/ - -void CleanupOutput(char *str) -{ - char *s, *t; - int period = 0; - s = t = str; - // Collapse multiple white space (' ' and '\n') to one. Remove trailing space. - while ( *s ) { - if ( *s == '\n' ) {*s = ' '; } - if ( (*s == ' ') && ( s[1] == ' ' || s[1] == '\n' || s[1] == 0 ) ) { s++;} - else { *t++ = *s++; } - } - *t = 0; - - // Optimize format of numbers: - s = t = str; - while ( *s ) { - if ( *s == '.' ) { period = 1; *t++ = *s++; } - else if ( isdigit(*s) ) { *t++ = *s++; } - else if ( period ) { - while ( t > str && t[-1] == '0' ) { t--; } - if ( t > str && t[-1] == '.' ) { - t--; - // Handle case that number is .000, not e.g. 9.000 - if (t > str && ! isdigit(t[-1]) ) { - *t++ = '0'; - } - } - period = 0; *t++ = *s++; - } - else { - period = 0; *t++ = *s++; - } - } - *t = 0; - - // Collapse '-0' to '0' - s = t = str; - while ( *s ) { - if ( *s == '-' && s[1] == '0' && s[2] == ' ' ) { s++; } - else *t++ = *s++; - } - *t = 0; -} - -/* - #] CleanupOutput : - #[ send : -*/ - -void send( char* str ) { - fprintf(outfile, "%s",str); -} - -/* - #] CleanupOutput : - #[ sendClean : -*/ - -void sendClean( char* str ) { - CleanupOutput(str); - send(str); -} - -/* - #] sendClean : - #[ DoOneObject : -*/ - -int DoOneObject(char *cinput) -{ - // Single point for exit, to ensure proper clean up. - int num, i, num1, num2, retcode; - char *s, *t; - double *argbuf = 0; - retcode = -1; - SetDefaults(); - - // Locate number of object: - s = cinput; while ( *s != '[' ) s++; - s++; t = s; while ( *t != ']' ) t++; - *t++ = 0; while ( *t == ' ' || *t == '\t' || *t == '\n' ) t++; - - fprintf(outfile,"\\axo@setObject{%s}%%\n{%s%c}%%\n{",s,t,TERMCHAR); - outpos = outputbuffer; - - nameobject = t; while ( *t != ' ' && *t != '\t' && *t != '\n' && *t ) t++; - *t++ = 0; while ( *t == ' ' || *t == '\t' || *t == '\n' ) t++; -/* - Now nameobject is the name of the command and t points at the first parameter. -*/ - - if ( *s == '0' && s[1] == 0 ) { -/* - The identification line. - In due time we might add more options here. -*/ - if ( strcmp(nameobject,"AxodrawWantsPDF") == 0 ) { - identification = 1; - fprintf(outfile,"Axohelp version %d.%d. PDF output.",VERSION,SUBVERSION); - goto SUCCESS; - } - else { - fprintf(stderr,"%s: Illegal request in identification string [0]: %s\n" - ,axohelp,nameobject); - goto EXIT; - } - } -/* - if ( identification == 0 ) { - fprintf(stderr,"%s: No identification string. Check versions.\n",axohelp); - goto EXIT; - } -*/ - - if ( ( strcmp(nameobject,"Curve") == 0 ) - || ( strcmp(nameobject,"Polygon") == 0 ) - || ( strcmp(nameobject,"FilledPolygon") == 0 ) ) { -/* - #[ Curve,Polygons : -*/ - if ( ( argbuf = ReadArray(t,&num1,&num2) ) == 0 ) - goto EXIT; - if ( num2-1 != 0 ) { - fprintf(stderr,"%s: Command %s should have no extra numbers in %s.\n", - axohelp,nameobject,inname); - goto EXIT; - } - else { -/* - First some 'fixed' operations to set the state right - 1: scale 2: linewidth 3: color - Then the function. - Finally the trailer and cleanup. -*/ - axolinewidth = argbuf[2*num1+num2-1]; - SetLineWidth(axolinewidth); - if ( strcmp(nameobject,"Curve") == 0 ) { - Curve(argbuf,num1); - } - else if ( strcmp(nameobject,"Polygon") == 0 ) { - Polygon(argbuf,num1,0); - } - else if ( strcmp(nameobject,"FilledPolygon") == 0 ) { - Polygon(argbuf,num1,1); - } - free(argbuf); - argbuf = 0; - } -/* - #] Curve,Polygons : -*/ - } - else if ( strcmp(nameobject,"DashCurve") == 0 ) { -/* - #[ DashCurve : -*/ - if ( ( argbuf = ReadArray(t,&num1,&num2) ) == 0 ) - goto EXIT; - if ( num2 != 2 ) { - fprintf(stderr,"%s: Command %s does not have two numbers after the coordinates\n in file %s.\n", - axohelp,nameobject,inname); - goto EXIT; - } - else { -/* - First some 'fixed' operations to set the state right - 1: scale 2: linewidth 3: color - Then the function. - Finally the trailer and cleanup. -*/ - axolinewidth = argbuf[2*num1+num2-1]; - SetLineWidth(axolinewidth); - DashCurve(argbuf,num1); - free(argbuf); - argbuf = 0; - } -/* - #] DashCurve : -*/ - } - else { -/* - #[ Regular command : -*/ - if ( ( argbuf = ReadTail(t,&num) ) == 0 ) - goto EXIT; - for ( i = 0; i < sizeof(commands)/sizeof(KEYWORD); i++ ) { - if ( strcmp(nameobject,commands[i].name) == 0 ) { - if ( num == commands[i].numargs+1 ) { -/* - First some 'fixed' operations to set the state right - 1: scale 2: linewidth 3: color - Then the function. - Finally the trailer and cleanup. -*/ - axolinewidth = argbuf[num-1]; - SetLineWidth(axolinewidth); - (*(commands[i].func))(argbuf); - free(argbuf); - argbuf = 0; - break; - } - else { - fprintf(stderr,"%s: Command %s should have %d(+1) arguments in %s.\n" - ,axohelp,nameobject,commands[i].numargs,inname); - goto EXIT; - } - } - } -/* - #] Regular command : -*/ - if ( i >= sizeof(commands)/sizeof(KEYWORD) ) { - fprintf(stderr,"%s: Command %s not recognized in file %s.\n", - axohelp,nameobject,inname); - goto EXIT; - } - } - SUCCESS: - retcode = 0; - EXIT: - if (argbuf) { free(argbuf); } - fprintf(outfile,"}\n"); - return(retcode); -} - -/* - #] DoOneObject : - #[ PrintHelp : -*/ - -void PrintHelp(char *name) -{ - fprintf(stderr,"This is %s v. %d.%d of %s\n", NAME, VERSION, SUBVERSION, VERSIONDATE); - fprintf(stderr,"Usage: %s [OPTION] filename\n",name); - fprintf(stderr,"Input will then be from filename.ax1, output to filename.ax2.\n"); - fprintf(stderr,"-h, --help : prints this help information and terminates.\n"); - fprintf(stderr,"-v, --version : prints version information and terminates.\n"); - fprintf(stderr,"-V : prints information about each function treated in stdout.\n"); - fprintf(stderr," (NOT CURRENTLY IMPLEMENTED)\n\n"); - fprintf(stderr,"Please report bugs to jcc8@psu.edu.\n"); - fprintf(stderr,"axodraw2 web page: https://ctan.org/pkg/axodraw2\n"); -} - -/* - #] PrintHelp : - #[ PrintHelpPrompt : -*/ - -void PrintHelpPrompt(char *name) -{ - fprintf(stderr,"Try '%s --help' for more information.\n", name); -} - -/* - #] PrintHelpPrompt : - #[ Inivars : -*/ - -void Inivars() -{ - M_pi = acos(-1.); - torad = M_pi/180.; - BzK = 4.*(sqrt(2.)-1.)/3.; -} - -/* - #] Inivars : - #[ main : -*/ - -int main(int argc,char **argv) -{ - char *s, *inbuffer; - int length, error = 0; - long num,i; - - Inivars(); - argc--; - axohelp = *argv++; - if ( argc <= 0 ) { - PrintHelp(axohelp); - return 1; - } - while ( (*argv)[0] == '-' ) { /* we have options */ - s = *argv; - if ( s[1] == '-' ) { - /* Double "--", treat as "-" */ - s++; - } - if ( ( strcmp(s,"-h") == 0) || ( strcmp(s,"-help") == 0 ) ) { - PrintHelp(axohelp); - return 0; - } - else if ( ( strcmp(s,"-v") == 0 ) || ( strcmp(s,"-version") == 0 ) ) { - fprintf(stderr, - "%s %d.%d\n(release date %s)\n" - "Copyright 2018 John Collins and Jos Vermaseren.\n" - "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\n" - "There is NO WARRANTY, to the extent permitted by law.\n", - axohelp, VERSION, SUBVERSION, VERSIONDATE); - return 0; - } - else if ( strcmp( s, "-V" ) == 0 ) { - VerboseFlag = 1; - } - else { - fprintf(stderr,"%s: Illegal option %s\n", axohelp, *argv); - PrintHelpPrompt(axohelp); - return 1; - } - argc--; argv++; - if ( argc <= 0 ) { - fprintf(stderr,"%s: Not enough arguments\n",axohelp); - PrintHelpPrompt(axohelp); - return 1; - } - } - if ( argc != 1 ) { - fprintf(stderr,"%s: Too many arguments\n",axohelp); - PrintHelpPrompt(axohelp); - return 1; - } -/* - The filename is now in s. We copy it to a separate string and - paste on the extension .ax1 (if needed), and construct the - name of the output file. -*/ - s = *argv; - length = strlen(s); - inname = strcpy(malloc((length+5)*sizeof(char)),s); - outname = strcpy(malloc((length+5)*sizeof(char)),s); - if ( (length > 4) && (strcmp(s+length-4, ".ax1") == 0) ) { - outname[length-1] = '2'; - } - else { - strcpy( inname+length, ".ax1" ); - strcpy( outname+length, ".ax2" ); - } - if ( ( inbuffer = ReadInput(inname) ) == 0 ) return(1); - if ( ( outfile = fopen(outname,"w") ) == 0 ) { - fprintf(stderr,"%s: Cannot create file %s\n",axohelp,outname); - exit(1); - } - num = ScanForObjects(inbuffer); - for ( i = 0; i < num; i++ ) { - numobject = i+1; - if ( DoOneObject(inputs[i]) < 0 ) { error++; } - } - fclose(outfile); - if ( error > 0 ) { - fprintf(stderr,"%s: %d objects in %s were not translated correctly.\n", - axohelp,error,inname); - return(1); - } - return(0); -} - -/* - #] main : - #[ routines : - #[ Line routines : - #[ Line : * - - Line(x1,y1)(x2,y2) -*/ - -void Line(double *args) -{ - MoveTo(args[0],args[1]); - LineTo(args[2],args[3]); - Stroke; -} - -/* - #] Line : - #[ DoubleLine : * - - DoubleLine(x1,y1)(x2,y2){sep} -*/ - -void DoubleLine(double *args) -{ - SaveGraphicsState; - if ( args[4] > 0 ) { - SetLineWidth(args[4]+axolinewidth); - Line(args); - SetLineWidth(args[4]-axolinewidth); - SetBackgroundColor(STROKING); - } - Line(args); - RestoreGraphicsState; -} - -/* - #] DoubleLine : - #[ DashLine : * - - DashLine(x1,y1)(x2,y2){dashsize} -*/ - -void DashLine(double *args) -{ - double dx = args[2]-args[0], dy = args[3]-args[1], dr = sqrt(dx*dx+dy*dy); - double dashsize = args[4]; - int num; - num = dr/dashsize; - if ( ( num%2 ) == 1 ) num++; - dashsize = dr/num; - SetDashSize(dashsize,dashsize/2); - Line(args); -} - -/* - #] DashLine : - #[ DashDoubleLine : * - - DashDoubleLine(x1,y1)(x2,y2){sep}{dashsize} -*/ - -void DashDoubleLine(double *args) -{ - double dx = args[2]-args[0], dy = args[3]-args[1], dr = sqrt(dx*dx+dy*dy); - double dashsize = args[5]; - int num; - num = dr/dashsize; - if ( ( num%2 ) == 1 ) num++; - dashsize = dr/num; - SetDashSize(dashsize,dashsize/2); - DoubleLine(args); -} - -/* - #] DashDoubleLine : - #[ ArrowLine : * - - ArrowLine(x1,y1)(x2,y2){size}{where} - - where: x of arrowhead is x1+where*(x2-x1). Same for y. - serves both ArrowLine and LongArrowLine -*/ - -void ArrowLine(double *args) -{ - double dx, dy, dr, where; - Line(args); - if ( arrow.type == 0 ) where = args[5]; - else where = arrow.where; - dx = args[2]-args[0]; - dy = args[3]-args[1]; - dr = sqrt(dx*dx+dy*dy); - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - SetTransferMatrix(1,0,0,1,dr*where,0); - if ( arrow.type == 0 ) arrow.width = args[4]; - ArrowHead(); -} - -/* - #] ArrowLine : - #[ ArrowDoubleLine : * - - ArrowDoubleLine(x1,y1)(x2,y2){sep}{size}{where} - - where: x of arrowhead is x1+where*(x2-x1). Same for y. - serves both ArrowLine and LongArrowLine -*/ - -void ArrowDoubleLine(double *args) -{ - double dx, dy, dr, where; - DoubleLine(args); - if ( arrow.type == 0 ) where = args[6]; - else where = arrow.where; - dx = args[2]-args[0]; - dy = args[3]-args[1]; - dr = sqrt(dx*dx+dy*dy); - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - SetTransferMatrix(1,0,0,1,dr*where,0); - if ( arrow.type == 0 ) arrow.width = args[5]+args[4]; - ArrowHead(); -} - -/* - #] ArrowDoubleLine : - #[ DashArrowLine : * - - DashArrowLine(x1,y1)(x2,y2){dashsize}{amplitude}{where} - - where: x of arrowhead is x1+where*(x2-x1). Same for y. - we re-adjust the position of the arrow to place it on a dash. -*/ - -void DashArrowLine(double *args) -{ - double dx = args[2]-args[0], dy = args[3]-args[1], dr = sqrt(dx*dx+dy*dy); - double dashsize = args[4], where; - int num, nw; - if ( arrow.type == 0 ) where = args[6]; - else where = arrow.where; - num = dr/dashsize; - if ( ( num%2 ) == 1 ) num++; - if ( num%4 != 0 && where > 0.499 && where < 0.501 ) num += 2; - dashsize = dr/num; - SetDashSize(dashsize,dashsize/2); - Line(args); - nw = where*(num/2)+0.5; - where = (2.0*nw)/num; - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - SetTransferMatrix(1,0,0,1,dr*where,0); - if ( arrow.type == 0 ) arrow.width = args[5]; - ArrowHead(); -} - -/* - #] DashArrowLine : - #[ DashArrowDoubleLine : * - - DashArrowDoubleLine(x1,y1)(x2,y2){sep}{dashsize}{amplitude}{where} - - where: x of arrowhead is x1+where*(x2-x1). Same for y. - we re-adjust the position of the arrow to place it on a dash. -*/ - -void DashArrowDoubleLine(double *args) -{ - double dx = args[2]-args[0], dy = args[3]-args[1], dr = sqrt(dx*dx+dy*dy); - double dashsize = args[5], where; - int num, nw; - if ( arrow.type == 0 ) where = args[7]; - else where = arrow.where; - num = dr/dashsize; - if ( ( num%2 ) == 1 ) num++; - if ( num%4 != 0 && where > 0.499 && where < 0.501 ) num += 2; - dashsize = dr/num; - SetDashSize(dashsize,dashsize/2); - DoubleLine(args); - nw = where*(num/2)+0.5; - where = (2.0*nw)/num; - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - SetTransferMatrix(1,0,0,1,dr*where,0); - if ( arrow.type == 0 ) arrow.width = args[6]+args[4]; - ArrowHead(); -} - -/* - #] DashArrowDoubleLine : - #] Line routines : - #[ Arc routines : - #[ CArc : * - - CArc(x1,y1)(r,phi1,phi2) - - The arc segment runs anticlockwise - - We divide the segment into a number of equal segments, each less - than 90 degrees. Then the control points are at distance - 4*tan(90/n)/3 from the endpoints, in which n=360/(phi2-phi1) - (note that if n=4 we get tan(22.5)=sqrt(2)-1). -*/ - -void CArc(double *args) -{ - double phi1 = args[3], phi2 = args[4], r = args[2]; - double dphi; - while ( phi2 < phi1 ) phi2 += 360; - dphi = phi2-phi1; - if ( dphi <= 0 ) { return; } - if ( dphi >= 360 ) { ECirc(args); return; } - SetTransferMatrix(1,0,0,1,args[0],args[1]); - ArcSegment(r,phi1,dphi); - Stroke; -} - -/* - #] CArc : - #[ DoubleArc : * - - DoubleArc(x1,y1)(r,phi1,phi2){sep} - - The arc segment runs anticlockwise - - We divide the segment into a number of equal segments, each less - than 90 degrees. Then the control points are at distance - 4*tan(90/n)/3 from the endpoints, in which n=360/(phi2-phi1) - (note that if n=4 we get tan(22.5)=sqrt(2)-1). -*/ - -void DoubleArc(double *args) -{ - double phi1 = args[3], phi2 = args[4], r = args[2]; - double dphi, sep = args[5]; - while ( phi2 < phi1 ) phi2 += 360; - dphi = phi2-phi1; - if ( dphi <= 0 ) { return; } - SetTransferMatrix(1,0,0,1,args[0],args[1]); - ArcSegment(r+sep/2,phi1,dphi); - Stroke; - ArcSegment(r-sep/2,phi1,dphi); - Stroke; -} - -/* - #] DoubleArc : - #[ DashCArc : * - - DashCArc(x1,y1)(r,phi1,phi2){dashsize} - - The arc segment runs anticlockwise -*/ - -void DashCArc(double *args) -{ - double arcsize = args[4]-args[3]; - double r = args[2], dr, dashsize = args[5]; - int num; - if ( arcsize <= 0 ) arcsize += 360; - if ( arcsize > 360 ) arcsize = 360; - dr = 2*M_pi*r*(arcsize/360); - num = dr/dashsize; - if ( (num%2) == 1 ) num++; - dashsize = dr/num; - SetDashSize(dashsize,dashsize/2); - CArc(args); -} - -/* - #] DashCArc : - #[ DashDoubleArc : * - - DashDoubleArc(x1,y1)(r,phi1,phi2){sep}{dashsize} - - The arc segment runs anticlockwise - The trouble here is to synchronize the two dash patterns. - This is done by a rescaling. We assume that the rescaling is - sufficiently small that the linewidth does not suffer from it. -*/ - -void DashDoubleArc(double *args) -{ - double phi1 = args[3], r = args[2]; - double arcsize = args[4]-args[3]; - double dr, dashsize = args[6], sep = args[5]; - int num; - linesep = sep; - SetTransferMatrix(1,0,0,1,args[0],args[1]); - if ( arcsize <= 0 ) arcsize += 360; - if ( arcsize > 360 ) arcsize = 360; - dr = 2*M_pi*r*(arcsize/360); - num = dr/dashsize; - if ( (num%2) == 1 ) num++; - dashsize = dr/num; - SetDashSize(dashsize,dashsize/2); - SaveGraphicsState; - SetTransferMatrix(1+0.5*sep/r,0,0,1+0.5*sep/r,0,0); - ArcSegment(r,phi1,arcsize); - Stroke; - RestoreGraphicsState; - SaveGraphicsState; - SetTransferMatrix(1-0.5*sep/r,0,0,1-0.5*sep/r,0,0); - ArcSegment(r,phi1,arcsize); - Stroke; - RestoreGraphicsState; -} - -/* - #] DashDoubleArc : - #[ ArrowArc : * - - ArrowArc(x1,y1)(r,phi1,phi2){amplitude}{where} - - where: phi of arrowhead is phi1+where*(phi2-phi1) - The arc segment runs anticlockwise - serves both ArrowArc and LongArrowArc and ... (Jaxodraw addition) -*/ - -void ArrowArc(double *args) -{ - double phi1 = args[3], phi2 = args[4], r = args[2]; - double dphi, x, y, phi; - if ( arrow.type == 0 ) { - arrow.width = args[5]; - arrow.where = args[6]; - } - - while ( phi2 < phi1 ) phi2 += 360; - dphi = phi2-phi1; - SetTransferMatrix(1,0,0,1,args[0],args[1]); - - if ( dphi <= 0 ) { return; } - ArcSegment(r,phi1,dphi); - Stroke; -/* - Now compute the position and angle of the arrowhead -*/ - phi = phi1 + arrow.where*dphi; - x = r*COS(phi); y = r*SIN(phi); - SetTransferMatrix(1,0,0,1,x,y); - SetTransferMatrix(COS(phi+90),SIN(phi+90),-SIN(phi+90),COS(phi+90),0,0); - ArrowHead(); -} - -/* - #] ArrowArc : - #[ ArrowDoubleArc : * - - ArrowDoubleArc(x1,y1)(r,phi1,phi2){sep}{amplitude}{where} - - where: phi of arrowhead is phi1+where*(phi2-phi1) - The arc segment runs anticlockwise - serves both ArrowArc and LongArrowArc and ... (Jaxodraw addition) -*/ - -void ArrowDoubleArc(double *args) -{ - double phi1 = args[3], phi2 = args[4], r = args[2]; - double dphi, x, y, phi; - linesep = args[5]; - while ( phi2 < phi1 ) phi2 += 360; - dphi = phi2-phi1; - if ( dphi <= 0 ) { return; } - SetTransferMatrix(1,0,0,1,args[0],args[1]); - ArcSegment(r+linesep/2,phi1,dphi); - Stroke; - ArcSegment(r-linesep/2,phi1,dphi); - Stroke; -/* - Now compute the position and angle of the arrowhead -*/ - if ( arrow.type == 0 ) { - arrow.width = args[6]; - arrow.where = args[7]; - } - phi = phi1 + arrow.where*dphi; - x = r*COS(phi); y = r*SIN(phi); - SetTransferMatrix(1,0,0,1,x,y); - SetTransferMatrix(COS(phi+90),SIN(phi+90),-SIN(phi+90),COS(phi+90),0,0); - ArrowHead(); -} - -/* - #] ArrowDoubleArc : - #[ DashArrowArc : + - - DashArrowArc(x1,y1)(r,phi1,phi2){dashsize}{amplitude}{where} - - where: phi of arrowhead is phi1+where*(phi2-phi1) - The arc segment runs anticlockwise -*/ - -void DashArrowArc(double *args) -{ - double dphi, x, y, phi, phi1 = args[3], phi2 = args[4]; - double r = args[2], dr, dashsize = args[5]; - int num; - if ( arrow.type == 0 ) { - arrow.width = args[6]; - arrow.where = args[7]; - } - - while ( phi2 < phi1 ) phi2 += 360; - dphi = phi2-phi1; - if ( dphi > 360 ) dphi = 360; - dr = 2*M_pi*r*(dphi/360); - num = dr/dashsize; - if ( (num%2) == 1 ) num++; - if ( num%4 != 0 && arrow.where > 0.499 && arrow.where < 0.501 ) num += 2; - dashsize = dr/num; - SetDashSize(dashsize,dashsize/2); - SetTransferMatrix(1,0,0,1,args[0],args[1]); - if ( dphi <= 0 ) { return; } - ArcSegment(r,phi1,dphi); - Stroke; -/* - Now compute the position and angle of the arrowhead -*/ - phi = phi1 + arrow.where*dphi; - x = r*COS(phi); y = r*SIN(phi); - SetTransferMatrix(1,0,0,1,x,y); - SetTransferMatrix(COS(phi+90),SIN(phi+90),-SIN(phi+90),COS(phi+90),0,0); - ArrowHead(); -} - -/* - #] DashArrowArc : - #[ DashArrowDoubleArc : + - - DashArrowDoubleArc(x1,y1)(r,phi1,phi2){sep}{dashsize}{amplitude}{where} - - where: phi of arrowhead is phi1+where*(phi2-phi1) - The arc segment runs anticlockwise -*/ - -void DashArrowDoubleArc(double *args) -{ - double dphi, x, y, phi, phi1 = args[3], phi2 = args[4]; - double r = args[2], dr, dashsize = args[6]; - int num; - linesep = args[5]; - if ( arrow.type == 0 ) { - arrow.width = args[7]; - arrow.where = args[8]; - } - - while ( phi2 < phi1 ) phi2 += 360; - dphi = phi2-phi1; - if ( dphi > 360 ) dphi = 360; - dr = 2*M_pi*r*(dphi/360); - num = dr/dashsize; - if ( (num%2) == 1 ) num++; - if ( num%4 != 0 && arrow.where > 0.499 && arrow.where < 0.501 ) num += 2; - dashsize = dr/num; - SetDashSize(dashsize,dashsize/2); - SetTransferMatrix(1,0,0,1,args[0],args[1]); - if ( dphi <= 0 ) { return; } - SaveGraphicsState; - SetTransferMatrix(1+0.5*linesep/r,0,0,1+0.5*linesep/r,0,0); - ArcSegment(r,phi1,dphi); - Stroke; - RestoreGraphicsState; - SaveGraphicsState; - SetTransferMatrix(1-0.5*linesep/r,0,0,1-0.5*linesep/r,0,0); - ArcSegment(r,phi1,dphi); - Stroke; - RestoreGraphicsState; -/* - Now compute the position and angle of the arrowhead -*/ - phi = phi1 + arrow.where*dphi; - x = r*COS(phi); y = r*SIN(phi); - SetTransferMatrix(1,0,0,1,x,y); - SetTransferMatrix(COS(phi+90),SIN(phi+90),-SIN(phi+90),COS(phi+90),0,0); - ArrowHead(); -} - -/* - #] DashArrowDoubleArc : - #[ ArrowArcn : + - - ArrowArcn(x1,y1)(r,phi1,phi2){amplitude}{where} - - where: phi of arrowhead is phi1+where*(phi2-phi1) - The arc segment runs clockwise -*/ - -void ArrowArcn(double *args) -{ - double newargs[7], a; - int i; - for ( i = 0; i < 7; i++ ) newargs[i] = args[i]; - newargs[6] = 1-newargs[6]; - a = newargs[3]; newargs[3] = newargs[4]; newargs[4] = a; - ArrowArc(newargs); -} - -/* - #] ArrowArcn : - #[ DashArrowArcn : + - - DashArrowArc(x1,y1)(r,phi1,phi2){amplitude}{where}{dashsize} - - where: phi of arrowhead is phi1+where*(phi2-phi1) - The arc segment runs clockwise -*/ - -void DashArrowArcn(double *args) -{ - double newargs[8], a; - int i; - for ( i = 0; i < 8; i++ ) newargs[i] = args[i]; - newargs[6] = 1-newargs[6]; - a = newargs[3]; newargs[3] = newargs[4]; newargs[4] = a; - DashArrowArc(newargs); -} - -/* - #] DashArrowArcn : - #] Arc routines : - #[ Circle routines : - #[ ECirc : + - - ECirc(x,y){radius} - Draws a circle -*/ - -void ECirc(double *args) -{ - SetTransferMatrix(1,0,0,1,args[0],args[1]); - BezierCircle(args[2],"S"); -} - -/* - #] ECirc : - #[ FOval : + - - FOval(x1,y1)(h,w) filled oval in default color - -*/ - -void FOval(double *args) -{ - SetTransferMatrix(1,0,0,1,args[0],args[1]); /* Move to center of oval */ - SetTransferMatrix(COS(args[4]),SIN(args[4]),-SIN(args[4]),COS(args[4]),0,0); - BezierOval(args[3],args[2],"f"); - BezierOval(args[3],args[2],"S"); -} - -/* - #] COval : - #[ Oval : + - - Oval(x1,y1)(h,w)(phi) - - One way would be with different scales in the x and y direction, - but that messes up the linewidth. - We need to describe quarter ovals with Bezier curves. The proper - parameters for the curves we can obtain from the circle with scaling. -*/ - -void Oval(double *args) -{ - SetTransferMatrix(1,0,0,1,args[0],args[1]); /* Move to center of oval */ - SetTransferMatrix(COS(args[4]),SIN(args[4]),-SIN(args[4]),COS(args[4]),0,0); - BezierOval(args[3],args[2],"S"); -} - -/* - #] Oval : - #] Circle routines : - #[ Box routines : - #[ EBox : * - - \EBox(#1,#2)(#3,#4) - - Draws a box with the left bottom at (x1,y1) and the right top - at (x2,y2). - Transparent interior. Current color for edge. -*/ - -void EBox(double *args) -{ - Rectangle(args[0],args[1],args[2]-args[0],args[3]-args[1]); - Stroke; -} - -/* - #] EBox : - #[ FBox : * - - \FBox(#1,#2)(#3,#4) - - Draws a filled box with the left bottom at (x1,y1) and - the right top at (x2,y2). - Current color. -*/ - -void FBox(double *args) -{ - Rectangle(args[0],args[1],args[2]-args[0],args[3]-args[1]); - Fill; -} - -/* - #] FBox : - #[ Boxc : * - - \Boxc(#1,#2)(#3,#4) - - Draws a transparent box with the center at (x1,y1). - The width and height are (3,4). Uses current color. -*/ - -void Boxc(double *args) -{ - Rectangle(args[0]-args[2]/2,args[1]-args[3]/2,args[2],args[3]); - Stroke; -} - -/* - #] Boxc : - #[ FBoxc : * - - \FBoxc(#1,#2)(#3,#4) - - Draws a filled box with the center at (x1,y1). - The width and height are (3,4). Uses current color. -*/ - -void FBoxc(double *args) -{ - Rectangle(args[0]-args[2]/2,args[1]-args[3]/2,args[2],args[3]); - Fill; -} - -/* - #] FBoxc : - #] Box routines : - #[ Triangle routines : - #[ ETri : * - - \ETri(#1,#2)(#3,#4)(#5,#6) - - Draws a triangle with the three corners. -*/ - -void ETri(double *args) -{ - Triangle(args[0],args[1],args[2],args[3],args[4],args[5]); - Stroke; -} - -/* - #] ETri : - #[ FTri : * - - \FTri(#1,#2)(#3,#4)(#5,#6) - - Draws a triangle with the three corners. -*/ - -void FTri(double *args) -{ - Triangle(args[0],args[1],args[2],args[3],args[4],args[5]); - Fill; -} - -/* - #] FTri : - #] Triangle routines : - #[ Particle routines : - #[ Vertex : + - - Vertex(x,y){radius} - Draws a filled circle -*/ - -void Vertex(double *args) -{ - SetTransferMatrix(1,0,0,1,args[0],args[1]); - BezierCircle(args[2],"f"); -} - -/* - #] Vertex : - #[ ComputeDash : -*/ - -double ComputeDash(double *args,double dr,double indash) -{ - int numwindings = args[5]+0.5, numdashes; - int numhalfwindings = 2*numwindings+2.1; - double onehalfwinding = dr/numhalfwindings; - double amp8 = fabs(args[4])*0.9; - double size = LengthBezier(-amp8,0, -amp8,2*args[4], onehalfwinding,2*args[4],1.0); - - numdashes = size/(2*indash); - if ( numdashes == 0 ) numdashes = 1; - if ( fabs(size-2*indash*numdashes) > fabs(size-2*indash*(numdashes+1)) ) - numdashes++; - return(size/(2*numdashes)); -} - -/* - #] ComputeDash : - #[ ComputeDashCirc : -*/ - -double ComputeDashCirc(double *args,double indash) -{ - int num = args[5]+0.5, numdashes; - double ampi = args[4], radius = args[2]; - double darc; - double dr,conv,inc; - double amp1,amp2,amp4,amp5,amp8; - double x0,x1,x2,x3,y0,y1,y2,y3,xx,size; - darc = 360.; - dr = darc*torad*radius; - conv = 1.0/radius; - inc = dr/(2*num); /* increment per half winding */ - amp8 = ampi*0.9; - amp1 = radius+ampi; - amp2 = radius-ampi; - amp4 = amp1/cos((inc+amp8)*conv); - amp5 = amp2/cos(amp8*conv); - if ( amp8 < 0 ) amp8 = -amp8; - xx = 2*inc; - x0 = amp1*cos(inc*conv); - y0 = amp1*sin(inc*conv); - x1 = amp4*cos((xx+amp8)*conv)-x0; - y1 = amp4*sin((xx+amp8)*conv)-y0; - x2 = amp5*cos((xx+amp8)*conv)-x0; - y2 = amp5*sin((xx+amp8)*conv)-y0; - x3 = amp2*cos(xx*conv)-x0; - y3 = amp2*sin(xx*conv)-y0; - size = LengthBezier(x1,y1,x2,y2,x3,y3,1.0); - numdashes = size/(2*indash); - if ( numdashes == 0 ) numdashes = 1; - if ( fabs(size-2*indash*numdashes) > fabs(size-2*indash*(numdashes+1)) ) - numdashes++; - return(size/(2*numdashes)); -} - -/* - #] ComputeDashCirc : - #[ ComputeDashPhotonArc : -*/ - -double ComputeDashPhotonArc(double *args,double darc,double dashsize,double *dashstart) -{ - int numdashes, numd; - double len1, len2, size, size2, ampli = args[5], radius = args[2]; - double cp = cos(darc); - double sp = sin(darc); - double cp2 = cos(darc/2.); - double sp2 = sin(darc/2.); - double beta = radius*darc/(M_pi*ampli); - double tt = (sp-cp*beta)/(cp+sp*beta); - double x2 = ((radius+ampli)*8*(beta*cp2-sp2)-(beta*(4+cp) - +(tt*cp*3.-sp*4.))*radius)/((beta-tt)*3.); - double x1 = ((radius+ampli)*8.*cp2-(1+cp)*radius)/3.-x2; - double y1 = (x1-radius)*beta; - double y2 = (x2-radius*cp)*tt+radius*sp; - double x3 = radius*cp; - double y3 = radius*sp; - len1 = LengthBezier(x1-radius,y1,x2-radius,y2,x3-radius,y3,1.0); - ampli = -ampli; - beta = radius*darc/(M_pi*ampli); - tt = (sp-cp*beta)/(cp+sp*beta); - x2 = ((radius+ampli)*8*(beta*cp2-sp2)-(beta*(4+cp) - +(tt*cp*3.-sp*4.))*radius)/((beta-tt)*3.); - x1 = ((radius+ampli)*8.*cp2-(1+cp)*radius)/3.-x2; - y1 = (x1-radius)*beta; - y2 = (x2-radius*cp)*tt+radius*sp; - x3 = radius*cp; - y3 = radius*sp; - len2 = LengthBezier(x1-radius,y1,x2-radius,y2,x3-radius,y3,1.0); - size = (len1+len2)/2; - size2 = len1/2; - numdashes = size/(2*dashsize); - if ( numdashes == 0 ) numdashes = 1; - if ( fabs(size-2*dashsize*numdashes) > fabs(size-2*dashsize*(numdashes+1)) ) - numdashes++; - dashsize = size/(2*numdashes); - numd = size2/(2*dashsize); - *dashstart = -(size2 - 2*numd*dashsize) + dashsize/2; - if ( *dashstart < 0 ) *dashstart += 2*dashsize; - return(dashsize); -} - -/* - #] ComputeDashPhotonArc : - #[ ComputeDashGluonArc : -*/ - -double ComputeDashGluonArc(double *args,double darc,double dashsize) -{ - int numdashes, num = args[6]; - double radius = args[2], ampi = args[5]; - double dr,conv,inc, size; - double amp1,amp2,amp4,amp5,amp8; - double x1,x2,x3,y1,y2,y3,xx,x3p,y3p; - dr = darc*torad*radius; - conv = 1.0/radius; - inc = dr/(2*num+2); /* increment per half winding */ - amp8 = ampi*0.9; - amp1 = radius+ampi; - amp2 = radius-ampi; - amp4 = amp1/cos((inc+amp8)*conv); - amp5 = amp2/cos(amp8*conv); - if ( amp8 < 0 ) amp8 = -amp8; - - xx = 2*inc; - x3p = amp2*cos(xx*conv); - y3p = amp2*sin(xx*conv); - x1 = amp5*cos((xx-amp8)*conv)-x3p; - y1 = amp5*sin((xx-amp8)*conv)-y3p; - x2 = amp4*cos((xx-amp8)*conv)-x3p; - y2 = amp4*sin((xx-amp8)*conv)-y3p; - x3 = amp1*cos((xx+inc)*conv)-x3p; - y3 = amp1*sin((xx+inc)*conv)-y3p; - size = LengthBezier(x1,y1,x2,y2,x3,y3,1.0); - - numdashes = size/(2*dashsize); - if ( numdashes == 0 ) numdashes = 1; - if ( fabs(size-2*dashsize*numdashes) > fabs(size-2*dashsize*(numdashes+1)) ) - numdashes++; - dashsize = size/(2*numdashes); - return(dashsize); -} - -/* - #] ComputeDashGluonArc : - #[ GluonHelp : - - We draw the gluon in two strokes. This is due to the possibility - of a dash pattern. We want the dashes to be nicely symmetric on - the central windings. That means that either the start and end need - a different size dashes, or we draw the start 'backwards'. - We have chosen for the last solution. -*/ - -void GluonHelp(double *args,double dr) -{ - int numwindings = args[5]+0.5; - int numhalfwindings = 2*numwindings+2.1; - double onehalfwinding = dr/numhalfwindings; - double amp8 = fabs(args[4])*0.9; - double xx = 2*onehalfwinding; - int i; - MoveTo(xx,-args[4]); - Bezier(xx+amp8,-args[4],xx+amp8,args[4],1.4*onehalfwinding,args[4]); - Bezier(0.5*onehalfwinding,args[4], - 0.1*onehalfwinding,args[4]*0.5,0,0); - Stroke; - MoveTo(xx,-args[4]); - for ( i = 0; i < numwindings-1; i++ ) { - Bezier(xx-amp8,-args[4], xx-amp8,args[4], xx+onehalfwinding,args[4]); - xx += 2*onehalfwinding; - Bezier(xx+amp8,args[4], xx+amp8,-args[4], xx,-args[4]); - } - Bezier(xx-amp8,-args[4], xx-amp8,args[4], xx+onehalfwinding*0.6,args[4]); - Bezier(dr-onehalfwinding*0.5,args[4], - dr-onehalfwinding*0.1,args[4]*0.5, - dr,0); - Stroke; -} - -/* - #] GluonHelp : - #[ GluonCircHelp : -*/ - -void GluonCircHelp(double *args) -{ - int num = args[5], i; - double ampi = args[4], radius = args[2]; - double darc; - double dr,conv,inc; - double amp1,amp2,amp4,amp5,amp8; - double x1,x2,x3,y1,y2,y3,xx; - darc = 360.; - dr = darc*torad*radius; - conv = 1.0/radius; - inc = dr/(2*num); /* increment per half winding */ - amp8 = ampi*0.9; - amp1 = radius+ampi; - amp2 = radius-ampi; - amp4 = amp1/cos((inc+amp8)*conv); - amp5 = amp2/cos(amp8*conv); - if ( amp8 < 0 ) amp8 = -amp8; - xx = 2*inc; - x3 = amp1*cos(inc*conv); - y3 = amp1*sin(inc*conv); - MoveTo(x3,y3); -/* - Now the loop -*/ - for ( i = 0; i < num; i++ ) { - x1 = amp4*cos((xx+amp8)*conv); - y1 = amp4*sin((xx+amp8)*conv); - x2 = amp5*cos((xx+amp8)*conv); - y2 = amp5*sin((xx+amp8)*conv); - x3 = amp2*cos(xx*conv); - y3 = amp2*sin(xx*conv); - Bezier(x1,y1,x2,y2,x3,y3); - x1 = amp5*cos((xx-amp8)*conv); - y1 = amp5*sin((xx-amp8)*conv); - x2 = amp4*cos((xx-amp8)*conv); - y2 = amp4*sin((xx-amp8)*conv); - x3 = amp1*cos((xx+inc)*conv); - y3 = amp1*sin((xx+inc)*conv); - Bezier(x1,y1,x2,y2,x3,y3); - xx += 2*inc; - } - Stroke; -} - -/* - #] GluonCircHelp : - #[ GluonArcHelp : -*/ - -void GluonArcHelp(double *args, double darc, double ampi) -{ - int num = args[6], i; - double radius = args[2]; - double dr,conv,inc; - double amp1,amp2,amp3,amp4,amp5,amp6,amp7,amp8; - double x1,x2,x3,y1,y2,y3,xx,x1p,y1p,x2p,y2p,x3p,y3p; - dr = darc*torad*radius; - conv = 1.0/radius; - inc = dr/(2*num+2); /* increment per half winding */ - amp8 = ampi*0.9; - amp1 = radius+ampi; - amp2 = radius-ampi; - amp3 = radius+ampi/2; - amp4 = amp1/cos((inc+amp8)*conv); - amp5 = amp2/cos(amp8*conv); - amp6 = amp1/cos((inc*0.6+amp8)*conv); - amp7 = amp1/cos(inc*0.9*conv); - if ( amp8 < 0 ) amp8 = -amp8; - xx = 2*inc; -/* - First the starting part. We draw it separately because there could - be a dashing pattern. This way the windings come out best. -*/ - x1 = amp3*cos(inc*0.1*conv); - y1 = amp3*sin(inc*0.1*conv); - x2 = amp7*cos(inc*0.5*conv); - y2 = amp7*sin(inc*0.5*conv); - x3 = amp1*cos(inc*1.4*conv); - y3 = amp1*sin(inc*1.4*conv); - x1p = amp6*cos((xx+amp8)*conv); - y1p = amp6*sin((xx+amp8)*conv); - x2p = amp5*cos((xx+amp8)*conv); - y2p = amp5*sin((xx+amp8)*conv); - x3p = amp2*cos(xx*conv); - y3p = amp2*sin(xx*conv); - MoveTo(x3p,y3p); - Bezier(x2p,y2p,x1p,y1p,x3,y3); - Bezier(x2,y2,x1,y1,radius,0); - Stroke; -/* - Now the loop -*/ - MoveTo(x3p,y3p); - for ( i = 1; i < num; i++ ) { - x1 = amp5*cos((xx-amp8)*conv); - y1 = amp5*sin((xx-amp8)*conv); - x2 = amp4*cos((xx-amp8)*conv); - y2 = amp4*sin((xx-amp8)*conv); - x3 = amp1*cos((xx+inc)*conv); - y3 = amp1*sin((xx+inc)*conv); - Bezier(x1,y1,x2,y2,x3,y3); - xx += 2*inc; - x1 = amp4*cos((xx+amp8)*conv); - y1 = amp4*sin((xx+amp8)*conv); - x2 = amp5*cos((xx+amp8)*conv); - y2 = amp5*sin((xx+amp8)*conv); - x3 = amp2*cos(xx*conv); - y3 = amp2*sin(xx*conv); - Bezier(x1,y1,x2,y2,x3,y3); - } -/* - And now the end point -*/ - x1 = amp5*cos((xx-amp8)*conv); - y1 = amp5*sin((xx-amp8)*conv); - x2 = amp6*cos((xx-amp8)*conv); - y2 = amp6*sin((xx-amp8)*conv); - x3 = amp1*cos((xx+inc*0.6)*conv); - y3 = amp1*sin((xx+inc*0.6)*conv); - Bezier(x1,y1,x2,y2,x3,y3); - x1 = amp7*cos((xx+inc*1.5)*conv); - y1 = amp7*sin((xx+inc*1.5)*conv); - x2 = amp3*cos((dr-inc*0.1)*conv); - y2 = amp3*sin((dr-inc*0.1)*conv); - x3 = radius*cos(dr*conv); - y3 = radius*sin(dr*conv); - - Bezier(x1,y1,x2,y2,x3,y3); - - Stroke; -} - -/* - #] GluonArcHelp : - #[ PhotonHelp : -*/ - -void PhotonHelp(double *args, double dr) -{ - int numhalfwindings = args[5]*2+0.5; - double onehalfwinding = dr/numhalfwindings; - double y = 4.*args[4]/3; - double x, xx; - int i; - MoveTo(0,0); -/* - Now loop over the half windings, alternating the sign of the y's -*/ - x = (4*onehalfwinding)/3/M_pi; xx = 0; - for ( i = 0; i < numhalfwindings; i++, y = -y ) { - Bezier(xx+x,y, xx+onehalfwinding-x,y, xx+onehalfwinding,0); - xx += onehalfwinding; - } - Stroke; -} -/* - #] PhotonHelp : - #[ PhotonArcHelp : -*/ - -void PhotonArcHelp(double *args,double arcend,int num) -{ - int i; - double ampli = args[5], radius = args[2]; - double cp,sp,cp2,sp2,cpi,spi; - double x1,x2,x3,y1,y2,y3,beta,tt; - - cp = cos(arcend); - sp = sin(arcend); - cp2 = cos(arcend/2.); - sp2 = sin(arcend/2.); - - MoveTo(radius,0); - for ( i = 0; i < num; i++, ampli = -ampli ) { - cpi = cos(i*arcend); - spi = sin(i*arcend); - beta = radius*arcend/(M_pi*ampli); - tt = (sp-cp*beta)/(cp+sp*beta); - x2 = ((radius+ampli)*8*(beta*cp2-sp2)-(beta*(4+cp) - +(tt*cp*3.-sp*4.))*radius)/((beta-tt)*3.); - x1 = ((radius+ampli)*8.*cp2-(1+cp)*radius)/3.-x2; - y1 = (x1-radius)*beta; - y2 = (x2-radius*cp)*tt+radius*sp; - x3 = radius*cp; - y3 = radius*sp; - Bezier(cpi*x1-spi*y1,cpi*y1+spi*x1, - cpi*x2-spi*y2,cpi*y2+spi*x2, - cpi*x3-spi*y3,cpi*y3+spi*x3); - } - Stroke; -} - -/* - #] PhotonArcHelp : - #[ ZigZagHelp : -*/ - -void ZigZagHelp(double *args, double dr) -{ - int numhalfwindings = args[5]*2+0.5; - double onehalfwinding = dr/numhalfwindings; - double x = onehalfwinding, y = args[4]; - int i; - MoveTo(0,0); -/* - Now loop over the half windings, alternating the sign of the y's -*/ - for ( i = 0; i < numhalfwindings; i++, y = -y ) { - LineTo(x-onehalfwinding/2.,y); LineTo(x,0); - x += onehalfwinding; - } - Stroke; -} - -/* - #] ZigZagHelp : - #[ ZigZagArcHelp : -*/ - -void ZigZagArcHelp(double *args) -{ - int num = 2*args[6]-0.5, i; - double amp = args[5], r = args[2]; - double arcstart = args[3], arcend = args[4], darc; - if ( arcend < arcstart ) arcend += 360.; - darc = (arcend-arcstart)/(num+1); - MoveTo(r*COS(arcstart),r*SIN(arcstart)); - arcstart += darc/2; - for ( i = 0; i <= num; i++, amp = -amp ) { - LineTo((r+amp)*COS(arcstart+darc*i),(r+amp)*SIN(arcstart+darc*i)); - } - LineTo(r*COS(arcend),r*SIN(arcend)); - Stroke; -} - -/* - #] ZigZagArcHelp : - #[ Gluon : * - - Gluon(x1,y1)(x2,y2){amplitude}{windings} - - Each half winding is one cubic Bezier curve. - In addition the end points are different Bezier curves. -*/ - -void Gluon(double *args) -{ - double dx = args[2] - args[0]; - double dy = args[3] - args[1]; - double dr = sqrt(dx*dx+dy*dy); - - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - GluonHelp(args,dr); -} - -/* - #] Gluon : - #[ DashGluon : * - - DashGluon(x1,y1)(x2,y2){amplitude}{windings}{dashsize} - - Each half winding is one cubic Bezier curve. - In addition the end points are different Bezier curves. -*/ - -void DashGluon(double *args) -{ - double dx = args[2] - args[0]; - double dy = args[3] - args[1]; - double dr = sqrt(dx*dx+dy*dy); - double dashsize; - - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - - dashsize = ComputeDash(args,dr,args[6]); - SetDashSize(dashsize,dashsize/2); - GluonHelp(args,dr); -} - -/* - #] DashGluon : - #[ GluonCirc : * - - GluonCirc(x1,y1)(r,phi){amplitude}{windings} - - Draws a gluon on a circle - x_center,y_center,radius,phase_angle,gluon_radius,num - in which num is the number of windings of the gluon. - Method: Same as GluonArc, but without special start and end -*/ - -void GluonCirc(double *args) -{ - int num = args[5]; - double arcstart = args[3]; - - SetTransferMatrix(1,0,0,1,args[0],args[1]); /* Move to center of circle */ - - arcstart += 360./(2*num); /* extra phase to make 0 angle more accessible */ - - SetTransferMatrix(COS(arcstart),SIN(arcstart) - ,-SIN(arcstart),COS(arcstart),0,0); - - GluonCircHelp(args); -} - -/* - #] GluonCirc : - #[ DashGluonCirc : * - - DashGluonCirc(x1,y1)(r,phi){amplitude}{windings}{dashsize} - - Draws a gluon on a circle - x_center,y_center,radius,phase_angle,gluon_radius,num - in which num is the number of windings of the gluon. - Method: Same as GluonArc, but without special start and end -*/ - -void DashGluonCirc(double *args) -{ - int num = args[5]; - double arcstart = args[3], dashsize; - - SetTransferMatrix(1,0,0,1,args[0],args[1]); /* Move to center of circle */ - - arcstart += 360./(2*num); /* extra phase to make 0 angle more accessible */ - - SetTransferMatrix(COS(arcstart),SIN(arcstart) - ,-SIN(arcstart),COS(arcstart),0,0); - - dashsize = ComputeDashCirc(args,args[6]); - - SetDashSize(dashsize,dashsize/2); - GluonCircHelp(args); -} - -/* - #] DashGluonCirc : - #[ GluonArc : * - - GluonArc(x1,y1)(r,phi1,phi2){amplitude}{windings} - - Draws a gluon on an arcsegment - x_center,y_center,radius,stat_angle,end_angle,gluon_radius,num - in which num is the number of windings of the gluon. - Method: - 1: compute length of arc. - 2: generate gluon in x and y as if the arc is a straight line - 3: x' = (radius+y)*cos(x*const) - y' = (radius+y)*sin(x*const) -*/ - -void GluonArc(double *args) -{ - double darc, arcstart = args[3],arcend = args[4], ampi = args[5]; -/* - When arcend comes before arcstart we have a problem. The solution is - to flip the order and change the sign on ampi -*/ - if ( arcend < arcstart ) { - darc = arcstart; arcstart = arcend; arcend = darc; ampi = -ampi; - } - - SetTransferMatrix(1,0,0,1,args[0],args[1]); /* Move to center of circle */ - - SetTransferMatrix(COS(arcstart),SIN(arcstart) - ,-SIN(arcstart),COS(arcstart),0,0); - darc = arcend-arcstart; - GluonArcHelp(args,darc,ampi); -} - -/* - #] GluonArc : - #[ DashGluonArc : * - - DashGluonArc(x1,y1)(r,phi1,phi2){amplitude}{windings}{dashsize} - - Draws a gluon on an arcsegment - x_center,y_center,radius,stat_angle,end_angle,gluon_radius,num - in which num is the number of windings of the gluon. - Method: - 1: compute length of arc. - 2: generate gluon in x and y as if the arc is a straight line - 3: x' = (radius+y)*cos(x*const) - y' = (radius+y)*sin(x*const) -*/ - -void DashGluonArc(double *args) -{ - double darc, arcstart = args[3],arcend = args[4], ampi = args[5]; - double dashsize = args[7]; -/* - When arcend comes before arcstart we have a problem. The solution is - to flip the order and change the sign on ampi -*/ - if ( arcend < arcstart ) { - darc = arcstart; arcstart = arcend; arcend = darc; ampi = -ampi; - } - - SetTransferMatrix(1,0,0,1,args[0],args[1]); /* Move to center of circle */ - - SetTransferMatrix(COS(arcstart),SIN(arcstart) - ,-SIN(arcstart),COS(arcstart),0,0); - darc = arcend-arcstart; - dashsize = ComputeDashGluonArc(args,darc,dashsize); - SetDashSize(dashsize,dashsize/2); - GluonArcHelp(args,darc,ampi); -} - -/* - #] DashGluonArc : - #[ Photon : * - - Photon(x1,y1)(x2,y2){amplitude}{windings} - - Each half winding is one cubic Bezier curve. -*/ - -void Photon(double *args) -{ - double dx = args[2] - args[0]; - double dy = args[3] - args[1]; - double dr = sqrt(dx*dx+dy*dy); - - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - - PhotonHelp(args,dr); -} - -/* - #] Photon : - #[ DoublePhoton : * - - DoublePhoton(x1,y1)(x2,y2){amplitude}{windings}{sep} - - Each half winding is one cubic Bezier curve. -*/ - -void DoublePhoton(double *args) -{ - double dx = args[2] - args[0]; - double dy = args[3] - args[1]; - double dr = sqrt(dx*dx+dy*dy); - linesep = args[6]; - - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - - SaveGraphicsState; - SetLineWidth(linesep+axolinewidth); - PhotonHelp(args,dr); - RestoreGraphicsState; - - SaveGraphicsState; - SetLineWidth(linesep-axolinewidth); - SetBackgroundColor(STROKING); - PhotonHelp(args,dr); - RestoreGraphicsState; -} - -/* - #] DoublePhoton : - #[ DashPhoton : * - - DashPhoton(x1,y1)(x2,y2){amplitude}{windings}{dashsize} - - Each half winding is one cubic Bezier curve. -*/ - -void DashPhoton(double *args) -{ - double dx = args[2] - args[0]; - double dy = args[3] - args[1]; - double dr = sqrt(dx*dx+dy*dy); - int numdashes, numhalfwindings = args[5]*2+0.5; - double x, y, size; - double dashsize = args[6], onehalfwinding = dr/numhalfwindings; - x = (4*onehalfwinding)/3/M_pi; y = 4.*args[4]/3; - size = 0.5*LengthBezier(x,y, onehalfwinding-x,y, onehalfwinding,0,1.0); - numdashes = size/(2*args[6]); - if ( numdashes == 0 ) numdashes = 1; - if ( fabs(size-2*dashsize*numdashes) > fabs(size-2*dashsize*(numdashes+1)) ) - numdashes++; - dashsize = size/(2*numdashes); - - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - - SetDashSize(dashsize,dashsize/2); - PhotonHelp(args,dr); -} - -/* - #] DashPhoton : - #[ DashDoublePhoton : * - - DashDoublePhoton(x1,y1)(x2,y2){amplitude}{windings}{sep}{dashsize} - - Each half winding is one cubic Bezier curve. -*/ - -void DashDoublePhoton(double *args) -{ - double dx = args[2] - args[0]; - double dy = args[3] - args[1]; - double dr = sqrt(dx*dx+dy*dy); - int numdashes, numhalfwindings = args[5]*2+0.5; - double x, y, size; - double dashsize = args[7], onehalfwinding = dr/numhalfwindings; - x = (4*onehalfwinding)/3/M_pi; y = 4.*args[4]/3; - size = 0.5*LengthBezier(x,y, onehalfwinding-x,y, onehalfwinding,0,1.0); - numdashes = size/(2*args[6]); - if ( numdashes == 0 ) numdashes = 1; - if ( fabs(size-2*dashsize*numdashes) > fabs(size-2*dashsize*(numdashes+1)) ) - numdashes++; - dashsize = size/(2*numdashes); - - linesep = args[6]; - - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - SetDashSize(dashsize,dashsize/2); - - SaveGraphicsState; - SetLineWidth(linesep+axolinewidth); - PhotonHelp(args,dr); - RestoreGraphicsState; - -/* SetDashSize(0,0); */ - SaveGraphicsState; - SetLineWidth(linesep-axolinewidth); - SetBackgroundColor(STROKING); - PhotonHelp(args,dr); - RestoreGraphicsState; -} - -/* - #] DashDoublePhoton : - #[ PhotonArc : * - - PhotonArc(x1,y1)(r,phi1,phi2){amplitude}{windings} - - This routine follows the Postscript routine closely, except for that - we do not put a transfer matrix inside the loop. The corresponding - moveto messes up the path. One would have to put stroking operations - in there each time. -*/ - -void PhotonArc(double *args) -{ - double arcstart = args[3],arcend = args[4]; - int num = 2*args[6]+0.5; - - if ( arcend < arcstart ) arcend += 360.; - - SetTransferMatrix(1,0,0,1,args[0],args[1]); /* Move to center of circle */ - - arcend = torad*(arcend-arcstart)/num; - - SetTransferMatrix(COS(arcstart),SIN(arcstart) - ,-SIN(arcstart),COS(arcstart),0,0); - - PhotonArcHelp(args,arcend,num); -} - -/* - #] PhotonArc : - #[ DoublePhotonArc : * - - DoublePhotonArc(x1,y1)(r,phi1,phi2){amplitude}{windings}{sep} -*/ - -void DoublePhotonArc(double *args) -{ - double arcstart = args[3],arcend = args[4]; - int num = 2*args[6]+0.5; - linesep = args[7]; - - if ( arcend < arcstart ) arcend += 360.; - - SetTransferMatrix(1,0,0,1,args[0],args[1]); /* Move to center of circle */ - - arcend = torad*(arcend-arcstart)/num; - - SetTransferMatrix(COS(arcstart),SIN(arcstart) - ,-SIN(arcstart),COS(arcstart),0,0); - - SaveGraphicsState; - SetLineWidth(linesep+axolinewidth); - PhotonArcHelp(args,arcend,num); - RestoreGraphicsState; - - SaveGraphicsState; - SetLineWidth(linesep-axolinewidth); - SetBackgroundColor(STROKING); - PhotonArcHelp(args,arcend,num); - RestoreGraphicsState; -} - -/* - #] DoublePhotonArc : - #[ DashPhotonArc : * - - DashPhotonArc(x1,y1)(r,phi1,phi2){amplitude}{windings}{dashsize} -*/ - -void DashPhotonArc(double *args) -{ - double arcstart = args[3],arcend = args[4]; - double dashsize = args[7], dashstart; - int num = 2*args[6]+0.5; - - if ( arcend < arcstart ) arcend += 360.; - - SetTransferMatrix(1,0,0,1,args[0],args[1]); /* Move to center of circle */ - - arcend = torad*(arcend-arcstart)/num; - - SetTransferMatrix(COS(arcstart),SIN(arcstart) - ,-SIN(arcstart),COS(arcstart),0,0); - - dashsize = ComputeDashPhotonArc(args,arcend,dashsize,&dashstart); - SetDashSize(dashsize,dashstart); - PhotonArcHelp(args,arcend,num); -} - -/* - #] DashPhotonArc : - #[ DashDoublePhotonArc : * - - DashDoublePhotonArc(x1,y1)(r,phi1,phi2){amplitude}{windings}{sep}{dashsize} -*/ - -void DashDoublePhotonArc(double *args) -{ - double arcstart = args[3],arcend = args[4]; - double dashsize = args[8], dashstart; - int num = 2*args[6]+0.5; - linesep = args[7]; - - if ( arcend < arcstart ) arcend += 360.; - - SetTransferMatrix(1,0,0,1,args[0],args[1]); /* Move to center of circle */ - - arcend = torad*(arcend-arcstart)/num; - - SetTransferMatrix(COS(arcstart),SIN(arcstart) - ,-SIN(arcstart),COS(arcstart),0,0); - dashsize = ComputeDashPhotonArc(args,arcend,dashsize,&dashstart); - - SaveGraphicsState; - SetDashSize(dashsize,dashstart); - SetLineWidth(linesep+axolinewidth); - PhotonArcHelp(args,arcend,num); - RestoreGraphicsState; - - SaveGraphicsState; - SetDashSize(0,0); - SetLineWidth(linesep-axolinewidth); - SetBackgroundColor(STROKING); - PhotonArcHelp(args,arcend,num); - RestoreGraphicsState; -} - -/* - #] DashDoublePhotonArc : - #[ ZigZag : * - - ZigZag(x1,y1)(x2,y2){amplitude}{windings} - - We draw each half winding as two straight lines. - This can be done better! -*/ - -void ZigZag(double *args) -{ - double dx = args[2] - args[0]; - double dy = args[3] - args[1]; - double dr = sqrt(dx*dx+dy*dy); - - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - ZigZagHelp(args,dr); -} - -/* - #] ZigZag : - #[ DoubleZigZag : * - - DoubleZigZag(x1,y1)(x2,y2){amplitude}{windings}{sep} - - We draw each half winding as two straight lines. - This can be done better! -*/ - -void DoubleZigZag(double *args) -{ - double dx = args[2] - args[0]; - double dy = args[3] - args[1]; - double dr = sqrt(dx*dx+dy*dy); - linesep = args[6]; - - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - - SaveGraphicsState; - SetLineWidth(linesep+axolinewidth); - ZigZagHelp(args,dr); - RestoreGraphicsState; - - SaveGraphicsState; - SetLineWidth(linesep-axolinewidth); - SetBackgroundColor(STROKING); - ZigZagHelp(args,dr); - RestoreGraphicsState; -} - -/* - #] DoubleZigZag : - #[ DashZigZag : * - - DashZigZag(x1,y1)(x2,y2){amplitude}{windings}{dashsize} - - We should recalculate the size of the dashes. Otherwise the points - of the teeth can become messy. -*/ - -void DashZigZag(double *args) -{ - double dx = args[2] - args[0]; - double dy = args[3] - args[1]; - double dr = sqrt(dx*dx+dy*dy); - double dashsize = args[6]; - int n = args[5]*2+0.5; - double size = dr/(n*2); - - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - - size = sqrt(size*size+args[4]*args[4]); - n = size/(2*dashsize); /* number of complete dash patterns rounded down */ -/* - Now test what is closer to dash: size/n or size/(n+1) -*/ - if ( n == 0 ) n = 1; - if ( fabs(size-2*dashsize*n) > fabs(size-2*dashsize*(n+1)) ) n++; - dashsize = size/(2*n); - - SetDashSize(dashsize,dashsize/2); - ZigZagHelp(args,dr); -} - -/* - #] DashZigZag : - #[ DashDoubleZigZag : * - - DashDoubleZigZag(x1,y1)(x2,y2){amplitude}{windings}{sep}{dashsize} - - We draw each half winding as two straight lines. - This can be done better! -*/ - -void DashDoubleZigZag(double *args) -{ - double dx = args[2] - args[0]; - double dy = args[3] - args[1]; - double dr = sqrt(dx*dx+dy*dy); - double dashsize = args[7]; - int n = args[5]*2+0.5; - double size = dr/(n*2); - linesep = args[6]; - - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - - size = sqrt(size*size+args[4]*args[4]); - n = size/(2*dashsize); /* number of complete dash patterns rounded down */ -/* - Now test what is closer to dash: size/n or size/(n+1) -*/ - if ( n == 0 ) n = 1; - if ( fabs(size-2*dashsize*n) > fabs(size-2*dashsize*(n+1)) ) n++; - dashsize = size/(2*n); - - SetDashSize(dashsize,dashsize/2); - - SaveGraphicsState; - SetLineWidth(linesep+axolinewidth); - ZigZagHelp(args,dr); - RestoreGraphicsState; - - SetDashSize(0,0); - - SaveGraphicsState; - SetLineWidth(linesep-axolinewidth); - SetBackgroundColor(STROKING); - ZigZagHelp(args,dr); - RestoreGraphicsState; -} - -/* - #] DashDoubleZigZag : - #[ ZigZagArc : * - - ZigZagArc(x1,y1)(r,phi1,phi2){amplitude}{windings} -*/ - -void ZigZagArc(double *args) -{ - SetTransferMatrix(1,0,0,1,args[0],args[1]); /* Move to center of circle */ - ZigZagArcHelp(args); -} - -/* - #] ZigZagArc : - #[ DoubleZigZagArc : * - - DoubleZigZagArc(x1,y1)(r,phi1,phi2){amplitude}{windings}{sep} -*/ - -void DoubleZigZagArc(double *args) -{ - SetTransferMatrix(1,0,0,1,args[0],args[1]); /* Move to center of circle */ - linesep = args[7]; - - SaveGraphicsState; - SetLineWidth(linesep+axolinewidth); - ZigZagArcHelp(args); - RestoreGraphicsState; - - SaveGraphicsState; - SetLineWidth(linesep-axolinewidth); - SetBackgroundColor(STROKING); - ZigZagArcHelp(args); - RestoreGraphicsState; -} - -/* - #] DoubleZigZagArc : - #[ DashZigZagArc : * - - DashZigZagArc(x1,y1)(r,phi1,phi2){amplitude}{windings}{dashsize} -*/ - -void DashZigZagArc(double *args) -{ - double dashsize = args[7], dashstart; - SetTransferMatrix(1,0,0,1,args[0],args[1]); /* Move to center of circle */ - { - int num = 2*args[6]-0.5, numdashes; - double amp = args[5], r = args[2], size, size2; - double arcstart = args[3], arcend = args[4], darc; - if ( arcend < arcstart ) arcend += 360.; - darc = (arcend-arcstart)/(num+1); - size = sqrt(0.5*(amp*amp+r*r-(r*r-amp*amp)*COS(darc))); - size2 = sqrt(amp*amp+2*(amp+r)*r*(1-COS(darc/2))); - numdashes = size/(2*dashsize); - if ( numdashes == 0 ) numdashes = 1; - if ( fabs(size-2*dashsize*numdashes) > fabs(size-2*dashsize*(numdashes+1)) ) - numdashes++; - dashsize = size/(2*numdashes); - num = size2/(2*dashsize); - dashstart = -(size2 - 2*num*dashsize) + dashsize/2; - if ( dashstart < 0 ) dashstart += 2*dashsize; - } - SetDashSize(dashsize,dashstart); - ZigZagArcHelp(args); -} - -/* - #] DashZigZagArc : - #[ DashDoubleZigZagArc : * - - DashDoubleZigZagArc(x1,y1)(r,phi1,phi2){amplitude}{windings}{sep}{dashsize} -*/ - -void DashDoubleZigZagArc(double *args) -{ - double dashsize = args[8], dashstart; - SetTransferMatrix(1,0,0,1,args[0],args[1]); /* Move to center of circle */ - linesep = args[7]; - { - int num = 2*args[6]-0.5, numdashes; - double amp = args[5], r = args[2], size, size2; - double arcstart = args[3], arcend = args[4], darc; - if ( arcend < arcstart ) arcend += 360.; - darc = (arcend-arcstart)/(num+1); - size = sqrt(0.5*(amp*amp+r*r-(r*r-amp*amp)*COS(darc))); - size2 = sqrt(amp*amp+2*(amp+r)*r*(1-COS(darc/2))); - numdashes = size/(2*dashsize); - if ( numdashes == 0 ) numdashes = 1; - if ( fabs(size-2*dashsize*numdashes) > fabs(size-2*dashsize*(numdashes+1)) ) - numdashes++; - dashsize = size/(2*numdashes); - num = size2/(2*dashsize); - dashstart = -(size2 - 2*num*dashsize) + dashsize/2; - if ( dashstart < 0 ) dashstart += 2*dashsize; - } - - SaveGraphicsState; - SetDashSize(dashsize,dashstart); - SetLineWidth(linesep+axolinewidth); - ZigZagArcHelp(args); - RestoreGraphicsState; - - SaveGraphicsState; - SetDashSize(0,0); - SetLineWidth(linesep-axolinewidth); - SetBackgroundColor(STROKING); - ZigZagArcHelp(args); - RestoreGraphicsState; -} - -/* - #] DashDoubleZigZagArc : - #] Particle routines : - #[ Drawing routines : - #[ Polygon : -*/ - -void Polygon(double *args,int num,int type) -{ - int i; - MoveTo(args[0],args[1]); - args += 2; - for ( i = 1; i < num; i++, args += 2 ) { - LineTo(args[0],args[1]); - } - if ( type == 0 ) { CloseAndStroke; } - else if ( type == 1 ) { CloseAndFill; } -} - -/* - #] Polygon : - #[ Curve : + - - Curve{(x1,y1),...,(xn,yn)} - - num is the number of pairs in points. -*/ - -void Curve(double *points,int num) -{ - int i, ss; - double x0,y0,x1,y1,x2,y2,x3,y3; - - if ( num < 2 ) return; - if ( num == 2 ) { Line(points); return; } - - ss = 2*num; - - x1 = points[0]; y1 = points[1]; - x2 = points[2]; y2 = points[3]; - x3 = points[4]; y3 = points[5]; - x0 = 2*x1-x2; - y0 = 2*((y3-y2)/(x3-x2)-(y2-y1)/(x2-x1))*((x2-x1)*(x2-x1)/(x3-x1))+2*y1-y2; - - MoveTo(x1,y1); - DoCurve(x0,y0,x1,y1,x2,y2,x3,y3); - - for ( i = 0; i < ss-6; i += 2 ) { - DoCurve(points[i ],points[i+1],points[i+2],points[i+3], - points[i+4],points[i+5],points[i+6],points[i+7]); - } - if ( ss > 6 ) { - x0 = points[ss-6]; y0 = points[ss-5]; - x1 = points[ss-4]; y1 = points[ss-3]; - x2 = points[ss-2]; y2 = points[ss-1]; - x3 = 2*x2-x1; - y3 = 2*((y2-y1)/(x2-x1)-(y1-y0)/(x1-x0))*((x2-x1)*(x2-x1)/(x2-x0))+2*y2-y1; - - DoCurve(x0,y0,x1,y1,x2,y2,x3,y3); - } - Stroke; -} - -/* - #] Curve : - #[ DashCurve : + - - DashCurve{(x1,y1),...,(xn,yn)}{dashsize} -*/ - -void DashCurve(double *args,int num1) -{ - double dashsize = args[2*num1]; - if ( num1 == 2 ) { - DashLine(args); - } - else if ( num1 > 2 ) { - SetDashSize(dashsize,dashsize/2); - Curve(args,num1); - } -} - -/* - #] DashCurve : - #[ LogAxis : - - Draws a line with logarithmic hash marks along it. - LogAxis(x1,y1)(x2,y2)(num_logs,hashsize,offset,width) - The line is from (x1,y1) to (x2,y2) and the marks are on the left side - when hashsize is positive, and right when it is negative. - num_logs is the number of orders of magnitude and offset is the number - at which one starts at (x1,y1) (like if offset=2 we start at 2) - When offset is 0 we start at 1. Width is the linewidth. -*/ - -void LogAxis(double *args) -{ - double dx = args[2]-args[0], dy = args[3]-args[1], dr = sqrt(dx*dx+dy*dy); - double width = args[7], size, nlogs = args[4], hashsize = args[5]; - double offset = args[6], x; - int i, j; - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - MoveTo(0,0); LineTo(dr,0); Stroke; -/* - Now compute the hash marks. -*/ - size = dr/nlogs; - if ( offset <= 0 ) { offset = 0; } - else { offset = mod( log10(offset), 1 ); } -/* - Big hash marks -*/ - for ( i = 0; i <= nlogs+1; i++ ) { - x = (i-offset)*size; - if ( x >= -0.001 && x <= dr+0.001 ) { - MoveTo(x,0); - LineTo(x,hashsize*1.2); - Stroke; - } - } -/* - Little hash marks -*/ - SetLineWidth(0.6*width); - for ( i = 0; i <= nlogs; i++ ) { - for ( j = 2; j < 10; j++ ) { - x = (i-offset+log10(j))*size; - if ( x >= -0.001 && x <= dr+0.001 ) { - MoveTo(x,0); LineTo(x,hashsize*0.8); Stroke; - } - } - } -} - -/* - #] LogAxis : - #[ LinAxis : - - Draws a line with linear hash marks along it. - LinAxis(x1,y1)(x2,y2)(num_decs,per_dec,hashsize,offset,width) - The line is from (x1,y1) to (x2,y2) and the marks are on the left side - when hashsize is positive, and right when it is negative. - num_decs is the number of accented marks, per_dec the number of - divisions between them and offset is the number - at which one starts at (x1,y1) (like if offset=2 we start at the second - small mark) Width is the linewidth. -*/ - -void LinAxis(double *args) -{ - double width = args[8], hashsize = args[6], x; - double dx = args[2]-args[0], dy = args[3]-args[1], dr = sqrt(dx*dx+dy*dy); - double num_decs = args[4], per_dec = args[5], size, size2; - double offset = args[7]; - int i, j, numperdec = per_dec+0.5; - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(dx/dr,dy/dr,-dy/dr,dx/dr,0,0); - MoveTo(0,0); LineTo(dr,0); Stroke; - size = dr/num_decs; - if ( numperdec > 1 ) { size2 = size / numperdec; } - else { size2 = size; numperdec = 1; } - offset = mod( offset, numperdec ); -/* - In geometric calculations of positions of hash marks, note that offset can - be between 0 and numperdec, and that within rounding error, numperdec is - allowed. Also allow for positions of hash marks that if calculated exactly - are in range, but because of rounding error are slightly outside. -*/ -/* - Big hash marks: -*/ - for ( i = 0; i <= num_decs+1; i++ ) { - x = i*size - offset*size2; - if ( ( x > -0.001) && ( x < dr+0.001 ) ) { - MoveTo(x,0); LineTo(x,hashsize*1.2); Stroke; - } - } -/* - Little hash marks. -*/ - SetLineWidth(0.6*width); - for ( i = 0; i <= num_decs; i++ ) { - for ( j = 1; j < numperdec; j++ ) { - x = i*size + (j - offset)*size2; - if ( ( x > -0.001) && ( x < dr+0.001 ) ) { - MoveTo(x,0); LineTo(x,hashsize*0.8); Stroke; - } - } - } -} - -/* - #] LinAxis : - #[ BezierCurve : - - Draws a Bezier curve. Starts at (x1,y1). - The control points are (x2,y2),(x3,y3),(x4,y4) -*/ - -void BezierCurve(double *args) -{ - MoveTo(args[0],args[1]); - Bezier(args[2],args[3],args[4],args[5],args[6],args[7]); - Stroke; - if ( witharrow ) BezierArrow(args); -} - -/* - #] BezierCurve : - #[ DoubleBezier : - - Draws a Bezier curve. Starts at (x1,y1). - The control points are (x2,y2),(x3,y3),(x4,y4) -*/ - -void DoubleBezier(double *args) -{ - linesep = args[8]; - SaveGraphicsState; - SetLineWidth(linesep+axolinewidth); - MoveTo(args[0],args[1]); - Bezier(args[2],args[3],args[4],args[5],args[6],args[7]); - Stroke; - RestoreGraphicsState; - SaveGraphicsState; - SetLineWidth(linesep-axolinewidth); - SetBackgroundColor(STROKING); - MoveTo(args[0],args[1]); - Bezier(args[2],args[3],args[4],args[5],args[6],args[7]); - Stroke; - RestoreGraphicsState; - if ( witharrow ) BezierArrow(args); -} - -/* - #] DoubleBezier : - #[ DashBezier : - - Draws a Bezier curve. Starts at (x1,y1). - The control points are (x2,y2),(x3,y3),(x4,y4) -*/ - -void DashBezier(double *args) -{ - int numdashes; - double size, dashsize = args[8]; - size = LengthBezier(args[2]-args[0],args[3]-args[1] - ,args[4]-args[0],args[5]-args[1],args[6]-args[0],args[7]-args[1],1.0); - - numdashes = size/(2*dashsize); - if ( numdashes == 0 ) numdashes = 1; - if ( fabs(size-2*dashsize*numdashes) > fabs(size-2*dashsize*(numdashes+1)) ) - numdashes++; - dashsize = (size/(2*numdashes)); - - SetDashSize(dashsize,dashsize/2); - MoveTo(args[0],args[1]); - Bezier(args[2],args[3],args[4],args[5],args[6],args[7]); - Stroke; - if ( witharrow ) BezierArrow(args); -} - -/* - #] DashBezier : - #[ DashDoubleBezier : - - Draws a Bezier curve. Starts at (x1,y1). - The control points are (x2,y2),(x3,y3),(x4,y4) -*/ - -void DashDoubleBezier(double *args) -{ - int numdashes; - double size, dashsize = args[9]; - size = LengthBezier(args[2]-args[0],args[3]-args[1] - ,args[4]-args[0],args[5]-args[1],args[6]-args[0],args[7]-args[1],1.0); - - numdashes = size/(2*dashsize); - if ( numdashes == 0 ) numdashes = 1; - if ( fabs(size-2*dashsize*numdashes) > fabs(size-2*dashsize*(numdashes+1)) ) - numdashes++; - dashsize = (size/(2*numdashes)); - - SetDashSize(dashsize,dashsize/2); - linesep = args[8]; - SaveGraphicsState; - SetLineWidth(linesep+axolinewidth); - MoveTo(args[0],args[1]); - Bezier(args[2],args[3],args[4],args[5],args[6],args[7]); - Stroke; - RestoreGraphicsState; - SaveGraphicsState; - SetLineWidth(linesep-axolinewidth); - SetBackgroundColor(STROKING); - MoveTo(args[0],args[1]); - Bezier(args[2],args[3],args[4],args[5],args[6],args[7]); - Stroke; - RestoreGraphicsState; - if ( witharrow ) BezierArrow(args); -} - -/* - #] DashDoubleBezier : - #] Drawing routines : - #[ Wrapper routines : - #[ AxoArc : - - Draws arc centered at (#1,#2), radius #3, starting and ending - angles #4, #5. - Double, dashing, arrow, flip, clockwise -*/ - -void AxoArc(double *args) -{ - double dashsize = args[6]; - linesep = args[5]; - GetArrow(args+7); - if ( args[16] ) { /* If clockwise: reverse the angles and the arrow */ - double e; - clockwise = 1; /* In principle not needed */ - flip = 1-flip; - arrow.where = 1-arrow.where; - e = args[3]; args[3] = args[4]; args[4] = e; - } - - if ( witharrow ) { - if ( arrow.where > 1 ) arrow.where = 1; - if ( arrow.where < 0 ) arrow.where = 0; - if ( dashsize > 0 ) { - if ( linesep > 0 ) { - DashArrowDoubleArc(args); - } - else { - args[5] = args[6]; - DashArrowArc(args); - } - } - else { - if ( linesep > 0 ) { - ArrowDoubleArc(args); - } - else { - ArrowArc(args); - } - } - } - else { - if ( dashsize > 0 ) { - if ( linesep > 0 ) { - DashDoubleArc(args); - } - else { - args[5] = args[6]; - DashCArc(args); - } - } - else { - if ( linesep > 0 ) { - DoubleArc(args); - } - else { - CArc(args); - } - } - } -} - -/* - #] AxoArc : - #[ AxoBezier : -*/ - -void AxoBezier(double *args) -{ - linesep = args[8]; - GetArrow(args+10); - if ( witharrow ) { - if ( arrow.where > 1 ) arrow.where = 1; - if ( arrow.where < 0 ) arrow.where = 0; - } - if ( args[9] ) { /* dashes */ - if ( args[8] ) { /* double */ - DashDoubleBezier(args); - } - else { - args[8] = args[9]; - DashBezier(args); - } - } - else { - if ( args[8] ) { /* double */ - DoubleBezier(args); - } - else { - BezierCurve(args); /* The name Bezier was already taken */ - } - } -} - -/* - #] AxoBezier : - #[ AxoGluon : -*/ - -void AxoGluon(double *args) -{ - SetLineWidth(axolinewidth + args[6]); - if ( args[7] ) { /* dashes */ - args[6] = args[7]; - DashGluon(args); - } - else { - Gluon(args); - } -} - -/* - #] AxoGluon : - #[ AxoGluonArc : -*/ - -void AxoGluonArc(double *args) -{ - SetLineWidth(axolinewidth + args[7]); - if ( args[9] ) { /* Clockwise */ - double a = args[3]; args[3] = args[4]; args[4] = a; - } - if ( args[8] ) { /* Dashes */ - args[7] = args[8]; - DashGluonArc(args); - } - else { - GluonArc(args); - } -} - -/* - #] AxoGluonArc : - #[ AxoGluonCirc : -*/ - -void AxoGluonCirc(double *args) -{ - SetLineWidth(axolinewidth + args[6]); - if ( args[7] ) { /* dashes */ - args[6] = args[7]; - DashGluonCirc(args); - } - else { - GluonCirc(args); - } -} - -/* - #] AxoGluonCirc : - #[ AxoLine : - - AxoLine(x1,y1)(x2,y2){sep}{dashsize}{stroke width length inset}{where} - - Generic switchyard to the various routines for compatibility - with Jaxodraw and axodraw4j - - Note: because the specific routines can be called either in the - direct way or by means of the generic routine, they have to know - what arrow to use. This is regulated by arrow.type. 0=old arrows. -*/ - -void AxoLine(double *args) -{ - linesep = args[4]; - GetArrow(args+6); - if ( witharrow ) { - if ( arrow.where > 1 ) arrow.where = 1; - if ( arrow.where < 0 ) arrow.where = 0; - if ( args[5] == 0 ) { - if ( linesep == 0 ) ArrowLine(args); - else { ArrowDoubleLine(args); } - } - else { - if ( linesep == 0 ) { - args[4] = args[5]; - DashArrowLine(args); - } - else { DashArrowDoubleLine(args); } - } - } - else { - if ( args[5] == 0 ) { /* No dashing */ - if ( linesep == 0 ) Line(args); - else DoubleLine(args); - } - else { - if ( linesep == 0 ) { - args[4] = args[5]; DashLine(args); - } - else DashDoubleLine(args); - } - } -} - -/* - #] AxoLine : - #[ AxoPhoton : -*/ - -void AxoPhoton(double *args) -{ - if ( args[7] ) { /* dashes */ - if ( args[6] ) { /* double */ - DashDoublePhoton(args); - } - else { - args[6] = args[7]; - DashPhoton(args); - } - } - else { - if ( args[6] ) { /* double */ - DoublePhoton(args); - } - else { - Photon(args); - } - } -} - -/* - #] AxoPhoton : - #[ AxoPhotonArc : -*/ - -void AxoPhotonArc(double *args) -{ - if ( args[9] ) { /* Clockwise */ - int num = 2*args[6]+0.5; - double a = args[3]; args[3] = args[4]; args[4] = a; - if ( ( num & 1 ) == 0 ) args[5] = -args[5]; - } - if ( args[8] ) { /* dash */ - if ( args[7] ) { /* double */ - DashDoublePhotonArc(args); - } - else { - args[7] = args[8]; - DashPhotonArc(args); - } - } - else { - if ( args[7] ) { /* double */ - DoublePhotonArc(args); - } - else { - PhotonArc(args); - } - } -} - -/* - #] AxoPhotonArc : - #[ AxoZigZag : -*/ - -void AxoZigZag(double *args) -{ - if ( args[7] ) { /* dashes */ - if ( args[6] ) { /* double */ - DashDoubleZigZag(args); - } - else { - args[6] = args[7]; - DashZigZag(args); - } - } - else { - if ( args[6] ) { /* double */ - DoubleZigZag(args); - } - else { - ZigZag(args); - } - } -} - -/* - #] AxoZigZag : - #[ AxoZigZagArc : -*/ - -void AxoZigZagArc(double *args) -{ - if ( args[9] ) { /* Clockwise */ - int num = 2*args[6]+0.5; - double a = args[3]; args[3] = args[4]; args[4] = a; - if ( ( num & 1 ) == 0 ) args[5] = -args[5]; - } - if ( args[8] ) { /* dash */ - if ( args[7] ) { /* double */ - DashDoubleZigZagArc(args); - } - else { - args[7] = args[8]; - DashZigZagArc(args); - } - } - else { - if ( args[7] ) { /* double */ - DoubleZigZagArc(args); - } - else { - ZigZagArc(args); - } - } -} - -/* - #] AxoZigZagArc : - #] Wrapper routines : - #[ Various routines : - #[ Rotate : + - - Rotate: x y angle hmode vmode textwidth textheight - Note, the textwidth/textheight have been scaled already; -*/ - -void Rotate(double *args) -{ - double textheight = args[6]*args[4]/2/65536.; - double textwidth = args[5]*args[3]/2/65536.; - SetTransferMatrix(1,0,0,1,args[0],args[1]); - SetTransferMatrix(COS(args[2]),SIN(args[2]),-SIN(args[2]),COS(args[2]),0,0); - SetTransferMatrix(1,0,0,1,-textwidth,textheight); -} - -/* - #] Rotate : - #[ Grid : - - Makes a coordinate grid in the indicated color. - (x0,y0)(incx,incy)(nx,ny){color}{linewidth} -*/ - -void Grid(double *args) -{ - int i, nx = args[4]+0.01, ny = args[5]+0.01; - double maxx = args[2]*args[4]; - double maxy = args[3]*args[5]; - SetTransferMatrix(1,0,0,1,args[0],args[1]); - for ( i = 0; i <= nx; i++ ) { - MoveTo(i*args[2],0); - LineTo(i*args[2],maxy); - Stroke; - } - for ( i = 0; i <= ny; i++ ) { - MoveTo(0,i*args[3]); - LineTo(maxx,i*args[3]); - Stroke; - } -} - -/* - #] Grid : - #] Various routines : - #] routines : -*/ |