[Android Apps and Games] Tamasaka:
Arrows in various shapes

This script draws arrows with current pencil. It has five parameters.

1. Size of arrow head.

2. Tip angle of arrow head in degrees.

3. Select shape of head from a line head, a barbed head or a delta head. Barbed head and delta head arrows are drawn with butt stroke cap.

4. Single head or double head.

5. Free or snap to grid.

If you skip setting the parameters, it works by default variables. When you need a simple tool for the specific shape arrow, you can modify the default variables and disable the parameters.

The snap-to-grid code was copied from the internal example.

/* Arrow (multi-shape) ver. 1.01 */
headsize = 4;
tipangle = 45;
headshape = 1;
heads = 1;
snap = 0;
if (LN.getNumberOfParameters() >= 1)
headsize = LN.getParameter(1); /* Head size, 2 ≤ Parameter(1) ≤ 8, 7 steps */
if (LN.getNumberOfParameters() >= 2)
tipangle = LN.getParameter(2); /* Tip angle (degree), 30 ≤ Parameter(2) ≤ 120, 7 steps */
if (LN.getNumberOfParameters() >= 3)
headshape = LN.getParameter(3); /* Head shape (0:line, 1:barbed, 2:delta), 0 ≤ Parameter(3) ≤ 2, 3 steps */
if (LN.getNumberOfParameters() >= 4)
heads = LN.getParameter(4); /* Heads (2:double), 1 ≤ Parameter(4) ≤ 2, 2 steps */
if (LN.getNumberOfParameters() >= 5)
snap = LN.getParameter(5); /* Snap to grid (1:on), 0 ≤ Parameter(5) ≤ 1, 2 steps */

strokewidth = LN.getStrokeWidth();
theta = tipangle * Math.PI / 360;
headlength = (headsize + 1) / 2 * strokewidth / Math.sqrt(Math.sin(theta));

x1 = LN.getX1();
y1 = LN.getY1();
x2 = LN.getX2();
y2 = LN.getY2();

if (snap) {
width = LN.getWidth();
scale = LN.getScale();
step = width / 150 + scale * width / 25;
x1 = (step / 2) + Math.floor((x1 - (step / 2)) / step + 0.5) * step;
y1 = (step / 2) + Math.floor((y1 - (step / 2)) / step + 0.5) * step;
x2 = (step / 2) + Math.floor((x2 - (step / 2)) / step + 0.5) * step;
y2 = (step / 2) + Math.floor((y2 - (step / 2)) / step + 0.5) * step;
}

direction = Math.atan2(y2 - y1, x2 - x1);
reverse = direction + Math.PI;
x21 = x2 + headlength * Math.cos(reverse + theta);
y21 = y2 + headlength * Math.sin(reverse + theta);
x22 = x2 + headlength * Math.cos(reverse - theta);
y22 = y2 + headlength * Math.sin(reverse - theta);
x11 = x1 + headlength * Math.cos(direction + theta);
y11 = y1 + headlength * Math.sin(direction + theta);
x12 = x1 + headlength * Math.cos(direction - theta);
y12 = y1 + headlength * Math.sin(direction - theta);
xmin = Math.min(Math.min(x1, Math.min(x11, x12)), Math.min(x2, Math.min(x21, x22)));
ymin = Math.min(Math.min(y1, Math.min(y11, y12)), Math.min(y2, Math.min(y21, y22)));
xmax = Math.max(Math.max(x1, Math.max(x11, x12)), Math.max(x2, Math.max(x21, x22)));
ymax = Math.max(Math.max(y1, Math.max(y11, y12)), Math.max(y2, Math.max(y21, y22)));

if (headshape >= 2) {
x2m = (x21 + x22) / 2;
y2m = (y21 + y22) / 2;
x1m = (x11 + x12) / 2;
y1m = (y11 + y12) / 2;
}
else if (headshape > 0) {
x2m = (x21 * 2 + x22 * 2 + x2) / 5;
y2m = (y21 * 2 + y22 * 2 + y2) / 5;
x1m = (x11 * 2 + x12 * 2 + x1) / 5;
y1m = (y11 * 2 + y12 * 2 + y1) / 5;
}

LN.setStrokeCap(headshape?1:0);
LN.setClip(xmin, ymin, xmax, ymax);
if (headshape ==0) {
LN.drawLine(x1, y1, x2, y2);
LN.drawLine (x2, y2, x21, y21);
LN.drawLine (x2, y2, x22, y22);
if (heads >= 2) {
LN.drawLine (x1, y1, x11, y11);
LN.drawLine (x1, y1, x12, y12);
}
}
else {
LN.drawFilledQuadrangle(x2, y2, x21, y21, x2m, y2m, x22, y22);
if (heads >= 2) {
LN.drawFilledQuadrangle(x1, y1, x11, y11, x1m, y1m, x12, y12);
LN.drawLine(x1m, y1m, x2m, y2m);
}
else
LN.drawLine(x1, y1, x2m, y2m);
}