Last active
February 26, 2026 10:24
-
-
Save nodtem66/d1cab427c98b5309c8a76642c6ba7c2a to your computer and use it in GitHub Desktop.
ImageJ Toolset for measuring (1) circumradius, (2) angle between two lines, and (3) distance between line and point.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Measurement tools | |
| // author [email protected] | |
| // Update: 26-02-2026 Add icons and a help text | |
| // http://wsr.imagej.net/developer/macro/macros.html#toolsets | |
| var obtusedAngles = false; | |
| macro "Basic Measurement Help Action Tool - C059T3e16?" { | |
| helpTitle = "Basic Measurement Help"; | |
| helpMessage = "Commands (Short key):\n" + | |
| "1. Circumcircle: Draw three points -> Press [f1]\n" + | |
| "2. Two-line Angle: Draw four points -> Press [f2] -> Click image\n" + | |
| " Double-click option: Obtuse angle = returning angle > 90\n" + | |
| "3. Two-line Distance: Draw four points -> Press [f3]\n"; | |
| showMessage(helpTitle, helpMessage); | |
| } | |
| macro "Circumcircle Action Tool [f1] - Cc00O11ee" { | |
| requires("1.30k"); | |
| if (selectionType() == -1) { | |
| exit("[circumcircle]: Please select three points!"); | |
| } | |
| getSelectionCoordinates(x, y); | |
| if (x.length != 3){ | |
| exit("Calculation requires only three points"); | |
| } | |
| //-- Get pixel data | |
| getPixelSize(unit, pw, ph, pd); | |
| //-- First calculate the perimeter of the triangle | |
| d1=sqrt((x[0]-x[1])*(x[0]-x[1])*pw*pw+(y[0]-y[1])*(y[0]-y[1])*ph*ph); | |
| d2=sqrt((x[1]-x[2])*(x[1]-x[2])*pw*pw+(y[1]-y[2])*(y[1]-y[2])*ph*ph); | |
| d3=sqrt((x[2]-x[0])*(x[2]-x[0])*pw*pw+(y[2]-y[0])*(y[2]-y[0])*ph*ph); | |
| //-- Half the perimeter | |
| s=0.5*(d1+d2+d3); | |
| //-- Area of circumcircle | |
| a=sqrt(s*(s-d1)*(s-d2)*(s*d3)); | |
| //-- Circumradius | |
| r=(d1*d2*d3)/sqrt((d1+d2+d3)*(d2+d3-d1)*(d3+d1-d2)*(d1+d2-d3)); | |
| //-- Menger curvature is the inverse of the radius of the circle | |
| mc=1/r; | |
| //-- Centroid coordinates (from https://en.wikipedia.org/wiki/Circumscribed_circle#Cartesian_coordinates_2) | |
| D=2*abs(x[0]*(y[1]-y[2]) + x[1]*(y[2]-y[0]) + x[2]*(y[0]-y[1])); | |
| cenX=abs((x[0]*x[0]+y[0]*y[0]) * (y[1]-y[2]) + (x[1]*x[1]+y[1]*y[1]) * (y[2]-y[0]) + (x[2]*x[2]+y[2]*y[2]) * (y[0]-y[1]))/D; | |
| cenY=abs((x[0]*x[0]+y[0]*y[0]) * (x[2]-x[1]) + (x[1]*x[1]+y[1]*y[1]) * (x[0]-x[2]) + (x[2]*x[2]+y[2]*y[2]) * (x[1]-x[0]))/D; | |
| //-- report | |
| //print("a: "+x[0]+","+y[0]); | |
| //print("b: "+x[1]+","+y[1]); | |
| //print("c: "+x[2]+","+y[2]); | |
| //print("Area of circumcircle: "+a); | |
| //print("Radius: "+r); | |
| //print("Menger Curvature: "+mc); | |
| //print("Circumcentre: "+cenX+","+cenY); | |
| row = Table.size; | |
| Table.set("Area", row, a); | |
| Table.set("Radius", row, r); | |
| Table.set("Menger Curvature", row, mc); | |
| Table.set("Centre X", row, cenX); | |
| Table.set("Centre Y", row, cenY); | |
| Table.update; | |
| //-- Create an overlay | |
| //-- Triangle | |
| makePolygon(x[0],y[0],x[1],y[1],x[2],y[2]); | |
| Overlay.addSelection("cyan"); | |
| //-- Circumcentre | |
| makeLine(cenX-5,cenY,cenX+5,cenY); | |
| Overlay.addSelection("magenta"); | |
| makeLine(cenX,cenY-5,cenX,cenY+5); | |
| Overlay.addSelection("magenta"); | |
| //-- Circumcircle | |
| run("Specify...", "width="+(r*2/pw)+" height="+(r*2/ph)+" x="+cenX+" y="+cenY+" oval centered"); | |
| Overlay.addSelection("red"); | |
| run("Select None"); | |
| } | |
| macro "Two Line Angle Tool [f2] - C000L28d8L28ca" { | |
| requires("1.30k"); | |
| if (selectionType() == -1) { | |
| exit("[Two-lines Angle]: Please select four points!"); | |
| } | |
| getSelectionCoordinates(x, y); | |
| if (x.length != 4) { | |
| exit("[Two-lines Angle]: Please select four points!"); | |
| } | |
| m1 = (y[1]-y[0])/(x[1]-x[0]+1e-16); | |
| m2 = (y[3]-y[2])/(x[3]-x[2]+1e-16); | |
| theta_deg = 0; | |
| if (abs(m1*m2 + 1) < 1e-9) { | |
| theta_deg = 90.0; | |
| } else { | |
| tan_theta = abs((m1 - m2)/(1+m1*m2)); | |
| theta_deg = atan2(tan_theta, 1.0) * 180.0 / PI; | |
| } | |
| if (obtusedAngles) { | |
| theta_deg = 180 - theta_deg; | |
| } | |
| makeLine(x[0],y[0],x[1],y[1]); | |
| Overlay.addSelection("red"); | |
| makeLine(x[2],y[2],x[3],y[3]); | |
| Overlay.addSelection("red"); | |
| mid1 = newArray((x[0]+x[1])/2, (y[0]+y[1])/2); | |
| mid2 = newArray((x[2]+x[3])/2, (y[2]+y[3])/2); | |
| makeSelection("polyline", newArray(mid1[0], mid2[0]), newArray(mid1[1], mid2[1])); | |
| setForegroundColor(0, 255, 255); | |
| run("Dotted Line", "line=1 dash=6,6"); | |
| run("Select None"); | |
| Table.set("Line angle", Table.size, theta_deg); | |
| Table.update; | |
| } | |
| macro "Two Line Angle Tool [f2] Options" { | |
| Dialog.create("Set Two-line angle measurement"); | |
| Dialog.addCheckbox("Obtuse angle", obtusedAngles); | |
| Dialog.show(); | |
| obtusedAngles = Dialog.getCheckbox(); | |
| } | |
| macro "Two Line Distance Action Tool [f3] - C000L25d5L2ad5" { | |
| requires("1.30k"); | |
| if (selectionType() == -1) { | |
| exit("[Two-lines distance]: Please select three points!"); | |
| } | |
| getSelectionCoordinates(x, y); | |
| if (x.length != 3) { | |
| exit("[Two-lines distance]: Please select three points!"); | |
| } | |
| a = y[0] - y[1]; | |
| b = x[1] - x[0]; | |
| c = (x[0]-x[1])*y[0] + (y[1]-y[0])*x[0]; | |
| ab2 = a*a + b*b; | |
| xc = (b*(b*x[2] - a*y[2]) - a*c) / ab2; | |
| yc = (a*(-b*x[2] + a*y[2])-b*c) / ab2; | |
| //-- Get pixel data | |
| getPixelSize(unit, pw, ph, pd); | |
| d = abs( (x[1]-x[0])*(y[0]-y[2]) - (x[0]-x[2])*(y[1]-y[0]) ) / sqrt(ab2) * pw; | |
| makeLine(x[0],y[0],x[1],y[1]); | |
| Overlay.addSelection("red"); | |
| makeSelection("polyline", newArray(xc, x[2]), newArray(yc, y[2])); | |
| setForegroundColor(0, 255, 255); | |
| run("Dotted Line", "line=1 dash=6,6"); | |
| run("Select None"); | |
| Table.set("Line Distance", Table.size, d); | |
| Table.update; | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Installation
macros/toolsetsUsage
Circumradius
Angle between two lines
Distance between a line and a point