/*
* Created on 23 juin 2005
*
* Olivier BEDEL
* Bassin Versant du Jaudy-Guindy-Bizien,
* Laboratoire RESO UMR ESO 6590 CNRS, Universitë de Rennes 2
*
*/
package org.openjump.core.ui.style.decoration;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import com.vividsolutions.jump.I18N;
import com.vividsolutions.jump.workbench.ui.GUIUtil;
import com.vividsolutions.jump.workbench.ui.Viewport;
import com.vividsolutions.jump.workbench.ui.images.IconLoader;
import com.vividsolutions.jump.workbench.ui.renderer.style.LineStringEndpointStyle;
/**
* @author Olivier
*
*/
public class ArrowLineStringMiddlepointStyle extends LineStringEndpointStyle {
private final static double SMALL_ANGLE = 10;
private final static double MEDIUM_ANGLE = 30;
private final static double MEDIUM_LENGTH = 10;
private final static double LARGE_LENGTH = 15;
private boolean filled;
private double finAngle;
protected double finLength;
public ArrowLineStringMiddlepointStyle(String name, boolean start, String iconFile,
double finAngle, double finLength, boolean filled) {
super(name, IconLoader.icon(iconFile), start);
this.finAngle = finAngle;
this.finLength = finLength;
this.filled = filled;
}
/**
* @param tail the tail of the whole arrow; just used to determine angle
* @param finLength required distance from the tip to each fin's tip
*/
private GeneralPath arrowhead(Point2D shaftTip, Point2D shaftTail,
double finLength, double finAngle) {
GeneralPath arrowhead = new GeneralPath();
Point2D finTip1 = fin(shaftTip, shaftTail, finLength, finAngle);
Point2D finTip2 = fin(shaftTip, shaftTail, finLength, -finAngle);
arrowhead.moveTo((float) finTip1.getX(), (float) finTip1.getY());
arrowhead.lineTo((float) shaftTip.getX(), (float) shaftTip.getY());
arrowhead.lineTo((float) finTip2.getX(), (float) finTip2.getY());
return arrowhead;
}
private Point2D fin(Point2D shaftTip, Point2D shaftTail, double length,
double angle) {
double shaftLength = shaftTip.distance(shaftTail);
Point2D finTail = shaftTip;
Point2D finTip = GUIUtil.add(GUIUtil.multiply(GUIUtil.subtract(
shaftTail, shaftTip), length / shaftLength), finTail);
AffineTransform affineTransform = new AffineTransform();
affineTransform.rotate((angle * Math.PI) / 180, finTail.getX(),
finTail.getY());
return affineTransform.transform(finTip, null);
}
protected void paint(Point2D terminal, Point2D next, Viewport viewport,
Graphics2D graphics) throws NoninvertibleTransformException {
if (terminal.equals(next)) {
return;
}
graphics.setColor(lineColorWithAlpha);
graphics.setStroke(stroke);
Point2D middle = new Point();
middle.setLocation((terminal.getX()+next.getX()) /2.0, (terminal.getY()+next.getY()) /2.0);
GeneralPath arrowhead = arrowhead(middle, next, finLength, finAngle);
if (filled) {
arrowhead.closePath();
graphics.fill(arrowhead);
}
//#fill isn't affected by line width, but #draw is. Therefore, draw even
//if we've already filled. [Jon Aquino]
graphics.draw(arrowhead);
}
public static class NarrowSolidMiddle extends ArrowLineStringMiddlepointStyle {
public NarrowSolidMiddle() {
super(I18N.get("ui.renderer.style.ArrowLineStringMiddlepointStyle.Middle-Arrow-Solid-Narrow"), false, "ArrowEndSolidNarrow.gif", //$NON-NLS-1$ //$NON-NLS-2$
SMALL_ANGLE, LARGE_LENGTH, true);
}
}
}