[Home] Restricted access for guests. The link to Java source code is disabled
Java source code of 'jhplot.jadraw.JaGlLoop'
/*
* Title: japlot.jaxodraw
* Description: Graphical user interface for drawing Feynman diagrams
* @author Daniele Binosi
* @author Lukas Theussl
Copyright (C) 2003-2006, Daniele Binosi and Lukas Theussl
See the file LICENSE in the source distribution home directory
for a full copy of the GPL (GNU General Public License).
This file is part of japlot.jaxodraw.
japlot.jaxodraw 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 2 of the License, or
(at your option) any later version.
japlot.jaxodraw 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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package jhplot.jadraw;
import java.awt.BasicStroke;
import java.awt.Dimension;
import org.freehep.graphics2d.VectorGraphics;
import java.awt.geom.Arc2D;
import java.awt.geom.FlatteningPathIterator;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
/**
* Gluon loop
*
*/
public class JaGlLoop extends JaLoopObject {
/**
*
*/
private static final long serialVersionUID = 1L;
/** Constructor: just calls super(). */
public JaGlLoop() {
super();
}
/** Returns an exact copy of this JaGlLoop.
* @return A copy of this JaGlLoop.
*/
public final JaObject copy() {
JaGlLoop temp = (JaGlLoop) copy(new JaGlLoop());
temp.setAmp(getAmp());
temp.setFreq(getFreq());
return temp;
}
/** Returns true if all serializable variables of this JaObject
* and those of the specified one are equal.
* @param comp A JaObject to compare with.
* @return True if the objects are equal, false otherwise.
*/
public final boolean isCopy(JaObject comp) {
boolean isCopy = false;
if (comp instanceof JaGlLoop) {
if (super.isCopy(comp)
&& (((JaGlLoop) comp).getAmp() == getAmp())
&& (((JaGlLoop) comp).getFreq() == getFreq())) {
isCopy = true;
}
}
return isCopy;
}
/** The method that draws this JaGlLoop.
* @param g2 The graphics context where the JaGlLoop has to be drawn.
* @param drawToScreen A boolean variable that indicates whether
* the drawing is done on the screen or somewhere else. This is used
* for exporting/printing, where the object handles should not be painted,
* even if they are visible on the screen.
*/
public final void jaxoDraw(VectorGraphics g2, boolean drawToScreen) {
g2.setColor(getColor());
g2.setStroke(new BasicStroke(getStroke()));
GeneralPath gp = getGeneralPath();
gp.reset();
float boh = 0.6f;
int angamp = 180;
if (getAmp() < 0) {
angamp = -180;
}
int a = Math.abs(getAmp());
int n;
float ts;
double length =
Math.sqrt(((double) getWidth() * (double) getWidth())
+ ((double) getHeight() * (double) getHeight()));
if (length < 5) {
length = 0;
}
length = 2 * length * Math.PI;
n = (int) (length / getFreq() / boh);
ts = (float) (length / boh / n);
Arc2D arc = new Arc2D.Float();
if (getDoubleLine()) {
for (int i = 0; i < n; i++) {
arc.setArc(i * ts * boh, (-a / 2) + getDLSeparation(), ts, a,
180, angamp, Arc2D.OPEN);
gp.append(arc, true);
arc.setArc(i * ts * boh, (-a / 2) - getDLSeparation(), ts, a,
180, angamp, Arc2D.OPEN);
gp.append(arc, false);
arc.setArc((i + 1) * ts * boh, (-a / 2) + getDLSeparation(),
ts * (1 - boh), a, 0, angamp, Arc2D.OPEN);
gp.append(arc, true);
arc.setArc((i + 1) * ts * boh, (-a / 2) - getDLSeparation(),
ts * (1 - boh), a, 0, angamp, Arc2D.OPEN);
gp.append(arc, false);
}
} else {
for (int i = 0; i < n; i++) {
arc.setArc(i * ts * boh, -a / 2, ts, a, 180, angamp, Arc2D.OPEN);
gp.append(arc, true);
arc.setArc((i + 1) * ts * boh, -a / 2, ts * (1 - boh), a, 0,
angamp, Arc2D.OPEN);
gp.append(arc, true);
}
}
gp = conformalGP(gp, length, 2 * Math.PI);
gp = transl(gp, 1 / Math.PI);
g2.draw(gp);
Rectangle2D bb = gp.getBounds2D();
double[] bbox =
{bb.getMinX(), bb.getMinY(), bb.getMaxX(), bb.getMaxY()};
setBoundingBox(bbox);
}
/** The LaTeX command that is necessary to draw this JaGlLoop
* using the axodraw.sty package.
* @param scale A scale factor to translate Java coordinates to
* LaTeX coordinates.
* @param canvasDim The current dimension of the canvas.
* @return The corresponding axodraw LaTeX command.
*/
public final String latexCommand(float scale, Dimension canvasDim) {
int canvasHeight = canvasDim.height;
Point2D center = getLaTexCenter(scale, canvasHeight);
float radius = getLaTexRadius(scale);
Point2D angles = getLaTexAngles();
float amplitude = getLaTexAmplitude(2.f * scale);
float windings = getLaTexWindingNumber(1.0f);
String command = "";
String base = "\\GlueArc";
if ((int) radius == 0) {
command = "%";
} else if (getDoubleLine()) {
float offSet = getDLSeparation() / scale;
String command1 =
base + "(" + D_FORMAT.format(center.getX()) + ","
+ D_FORMAT.format(center.getY()) + ")" + "("
+ D_FORMAT.format(radius + offSet) + ","
+ D_FORMAT.format(angles.getX()) + ","
+ D_FORMAT.format(angles.getY()) + ")" + "{"
+ D_FORMAT.format(amplitude) + "}" + "{"
+ D_FORMAT.format(windings) + "}";
String command2 =
base + "(" + D_FORMAT.format(center.getX()) + ","
+ D_FORMAT.format(center.getY()) + ")" + "("
+ D_FORMAT.format(radius - offSet) + ","
+ D_FORMAT.format(angles.getX()) + ","
+ D_FORMAT.format(angles.getY()) + ")" + "{"
+ D_FORMAT.format(amplitude) + "}" + "{"
+ D_FORMAT.format(windings) + "}";
command =
command1.concat(command2.concat("%%JaxoDrawID:DoubleLine"
+ "(" + D_FORMAT.format(getDLSeparation()) + ")"));
} else {
command =
base + "(" + D_FORMAT.format(center.getX()) + ","
+ D_FORMAT.format(center.getY()) + ")" + "("
+ D_FORMAT.format(radius) + ","
+ D_FORMAT.format(angles.getX()) + ","
+ D_FORMAT.format(angles.getY()) + ")" + "{"
+ D_FORMAT.format(amplitude) + "}" + "{"
+ D_FORMAT.format(windings) + "}";
}
return command;
}
/////////////////////////////////////////////////////////////////////////
//
// private auxiliary methods //
//
/////////////////////////////////////////////////////////////////////////
protected final Point2D getLaTexAngles() {
Point2D anglesPoint = new Point2D.Float();
int sAngle;
int eAngle;
int offset = 0;
if (getRelw() == 0) {
sAngle = 90;
}
sAngle =
(int) Math.round((
Math.atan2((float) getRelh(), (float) getRelw()) * 180.f
) / Math.PI);
if (((getRelw() <= 0) && (getRelh() > 0))
|| ((getRelw() >= 0) && (getRelh() < 0))) {
sAngle = -sAngle - offset;
eAngle = sAngle + 360;
anglesPoint.setLocation(sAngle, eAngle);
}
if (((getRelw() > 0) && (getRelh() >= 0))
|| ((getRelw() < 0) && (getRelh() <= 0))) {
sAngle = -sAngle + offset;
eAngle = sAngle + 360;
anglesPoint.setLocation(sAngle, eAngle);
}
return anglesPoint;
}
private float getLaTexAmplitude(float scaleFactor) {
float a = getAmp() / scaleFactor;
return a;
}
private float getLaTexWindingNumber(float scaleFactor) {
double length =
Math.sqrt(((double) getWidth() * (double) getWidth())
+ ((double) getHeight() * (double) getHeight()));
float n = (float) ((length * 2 * Math.PI) / getFreq() / 0.7f);
n = n / scaleFactor;
return n;
}
private Point2D conformal(float px, float py, double length, double angle) {
float nx =
(float) (
length / 2 * (
1
+ (
Math.exp((py * angle) / length) * Math.cos((
px * angle
) / length)
)
)
);
float ny =
(float) (
-length / 2 * Math.exp((py * angle) / length) * Math.sin((
-px * angle
) / length)
);
return new Point2D.Float(nx, ny);
}
private GeneralPath conformalGP(GeneralPath gpp, double length,
double angle) {
GeneralPath gp2 = new GeneralPath();
FlatteningPathIterator pi =
new FlatteningPathIterator(gpp.getPathIterator(null), 0.05);
float[] segm = new float[6];
int type;
float corr = (1.f - (20.f / (float) length));
gp2.moveTo(0.f, 0.f);
while (!pi.isDone()) {
type = pi.currentSegment(segm);
float px1 =
(float) conformal(segm[0], segm[1], length, angle).getX();
float py1 =
(float) conformal(segm[0], segm[1], length, angle).getY();
float px2 =
(float) conformal(segm[2], segm[3], length, angle).getX();
float py2 =
(float) conformal(segm[2], segm[3], length, angle).getY();
float px3 =
(float) conformal(segm[4], segm[5], length, angle).getX();
float py3 =
(float) conformal(segm[4], segm[5], length, angle).getY();
if (type == PathIterator.SEG_MOVETO) {
gp2.moveTo(px1, py1);
} else if (type == PathIterator.SEG_LINETO) {
gp2.lineTo(px1, py1);
} else if (type == PathIterator.SEG_QUADTO) {
px1 = (float) conformal(segm[0], corr * segm[1], length, angle)
.getX();
py1 = (float) conformal(segm[0], corr * segm[1], length, angle)
.getY();
gp2.quadTo(px1, py1, px2, py2);
} else if (type == PathIterator.SEG_CUBICTO) {
gp2.curveTo(px1, py1, px2, py2, px3, py3);
} else {
gp2.closePath();
}
pi.next();
}
return gp2;
}
}