Last active
August 16, 2023 09:56
-
-
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 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] | |
// http://wsr.imagej.net/developer/macro/macros.html#toolsets | |
var obtusedAngles = false; | |
macro "Unused Tool - " {} | |
macro "X axis Registration Tool - C037T2d13-T9d13X" { | |
cmd = getArgument(); | |
} | |
macro "Y axis Registration Tool - C037T2d13|T9d13Y" { | |
cmd = getArgument(); | |
} | |
macro "circumcircle [f1]" { | |
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 [f2]" { | |
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 distance [f4]" { | |
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; | |
} | |
macro "Two-line angle option [f3]" { | |
Dialog.create("Set Two-line angle measurement"); | |
Dialog.addCheckbox("Obtuse angle", obtusedAngles); | |
Dialog.show(); | |
obtusedAngles = Dialog.getCheckbox(); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Installation
macros/toolsets
Usage
Circumradius
Angle between two lines
Distance between a line and a point