Automatically forming parallel lines to below manually-drawn line?

Tags: #<Tag:0x00007fa30469bf50> #<Tag:0x00007fa30469be10> #<Tag:0x00007fa30469bca8> #<Tag:0x00007fa30469bac8> #<Tag:0x00007fa30469b898> #<Tag:0x00007fa30469b668>


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.


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...");
    // drag mode
    while (true) {
        getCursorLoc(x, y, z, flags);
        if (flags&leftButton==0) {
            // if single point, then return immediately
            if(xStart == x && yStart == y) {
            // go to parallel mode
            // starting from line xStart, yStart, x, y
            drawParallelLines(xStart, yStart, x, y);
        makeLine(xStart, yStart, x, y);
    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);;
	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) {
        // 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;

        ddy = sqrt(pow(dist,2) / (pow(ratio, 2) + 1)) * abs(dist)/dist * abs(dy)/dy;
        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);

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


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


// 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");

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




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 :slight_smile:


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


Thanks @eljonco for your help!