Automatically forming parallel lines to below manually-drawn line?

#21

I think this is the source of the misunderstanding.
From a line, you can measure and extract its angle in a macro. Then apply the proper trigonometry to calculate displacement in x and in y, then adjust Herbie’s macro to loop not over x+w but over x+dx, y+dy.

Now you have the tools at hand to use Pythagoras, as your original question already hinted.

#22

It’s a question of figuring out the correct maths, and using the `drawLine()` and/or `Overlay.drawLine()` macro functions.

I assembled a macro tool for you that allows creating a line selection (first two clicks) and then creates a configurable number of parallel lines, up to a distance that’s defined by the third mouse click:

``````// Author: Jan Eglinger

var numberOfLines = 1;
var symmetric = false;

macro "Parallel Lines Tool - C00b-B11-L31a6-L2398-L158a" {
var leftButton = 16;
getCursorLoc(xStart, yStart, zStart, flagStart);
if (flagStart&leftButton==0) {
print("Not the left button. Stopping...");
return;
}
// drag mode
while (true) {
getCursorLoc(x, y, z, flags);
if (flags&leftButton==0) {
// if single point, then return immediately
if(xStart == x && yStart == y) {
return;
}
// go to parallel mode
// starting from line xStart, yStart, x, y
drawParallelLines(xStart, yStart, x, y);
print("Finished");
return;
}
makeLine(xStart, yStart, x, y);
wait(10);
}
makeOval(x-radius, y-radius, radius*2, radius*2);
}

macro "Parallel Lines Tool Options" {
Dialog.create("Parallel Lines Tool");
Dialog.addNumber("Number of Lines", numberOfLines);
Dialog.addCheckbox("Symmetric around first line?", symmetric);
Dialog.show();
numberOfLines = Dialog.getNumber();
symmetric = Dialog.getCheckbox();
}

function drawParallelLines(x1, y1, x2, y2) {
makeLine(x1, y1, x2, y2);
while (true) {
getCursorLoc(x, y, z, modifiers);
if (modifiers&leftButton!=0) {
return;
}
// get slope of line
dx = (x2-x1);
dy = (y2-y1);
ratio =  dx / dy;

// get length of line
length = sqrt(pow((x2-x1), 2) + pow((y2-y1), 2));

// get distance of x and y to line
dist = ((y2-y1)*x - (x2-x1)*y + x2*y1 - y2*x1) / length;
//print(dist);

ddy = sqrt(pow(dist,2) / (pow(ratio, 2) + 1)) * abs(dist)/dist * abs(dy)/dy;
Overlay.clear;
for (i = 0; i < numberOfLines; i++) {
z = 1 - i/numberOfLines;
Overlay.drawLine(x1+z*ddy, y1-z*ratio*ddy, x2+z*ddy, y2-z*ratio*ddy);
if (symmetric) {
Overlay.drawLine(x1-z*ddy, y1+z*ratio*ddy, x2-z*ddy, y2+z*ratio*ddy);
}
}
Overlay.show;
wait(10);
}
}
``````

To install the macro tool, paste the code into a Plugins > New > Text Window… and choose Macros > Install Macros Ctrl-I.

#23

And perhaps finally, as an alternative to Jan’s Macro Tool, here is a short ImageJ-macro:

Updated

``````// imagej-macro "parallels" (Herbie G., 02./03. July 2018)
requires( "1.52d" );
if (selectionType()!=5) exit("Line selection required.");
d = getNumber("Line spacing in pixel: ", 20);
hh = getHeight(); ww = getWidth();
getSelectionCoordinates(x, y);
if ((x[0]<x[1]&&y[0]>y[1]) || (x[0]>x[1]&&y[0]<y[1])) s=1; else s=-1;
getSelectionBounds(X, Y, w, h);
denom = sqrt(h*h+w*w);
a = h*d/denom;
b = w*d/denom;
x = X; y = Y;
do {
setSelectionLocation(x, y);
run("Add Selection...");
x += a; y += b*s;
} while ( x+w<ww && y+h<hh && y>0 );
x = X; y = Y;
x -= a; y -= b*s;
while ( x>0 && y+h<hh && y>0 ) {
setSelectionLocation(x, y);
run("Add Selection...");
x -= a; y -= b*s;
}
run("Select None");
exit();
``````

Paste the above macro code to an empty macro window (Plugins >> New >> Macro) and run it.

HTH

Herbie

#24

Thanks so very much for the macro @imagejan it works like a charm! It’s perfect, better than what she wanted! Really appreciate your help and time

#25

Thanks @Herbie for your macro it’s exactly what I was looking for! And thanks for your help throughout this thread. Appreciate it!

#26

Thanks @eljonco for your help!