//04.02.22, 9:48
//although the newest version is weibel_9.8,
// for this older version weibel_8.1 an additional macro 
// "Show Project Statistics"
// was desired.
var 
// --- user globals ---
margin = 100,//min Margin on all four sides
Zvalue = 165, // the grid constant, an integer
gridColor = "#800000",

swatterRadius = 80,
swatterColor = "#8066ff00",

// --- internal globals ---
frameLeft, frameRight, frameTop, frameBottom, frameWidth, frameHeight,
xPairs = 0, yLines = 0,
xPoints, yPoints,
nGridLines,
currentID = 0,
disty = Zvalue *sqrt(3)/2,//equilateral triangular network 
gridDone = false,
stampTime = 0,
firstTime = true,
;

macro "Grid [F1]"{
	prepare();
	size = Overlay.size;
	
	if (size > 2)
		Overlay.remove;
	else{		
		gridToManager();
		roiManager("Show All without labels");
		run("From ROI Manager");
	}
	if (size == nGridLines + 2 || size == 2)
		frameToOverlay();
	}
}

macro "Frame [F2]"{
	prepare();
	size = Overlay.size;
	if (size == nGridLines || size == 0){
		frameToOverlay();
	}
	else if (size == nGridLines + 2){
		Overlay.removeSelection(size - 1);
		Overlay.removeSelection(size - 2);
	}
	else 
		Overlay.remove;
}

macro "Frame and Grid [F3]"{
	prepare();
	size = Overlay.size;
	if (size == nGridLines + 2){
		Overlay.remove;
	}
	else {
		gridToManager();
		roiManager("Show All without labels");
		run("From ROI Manager");
		frameToOverlay();
	}
}

macro "-"{
}


function doSave(name){//not used
	fullPath = getDirectory("temp") + name + ".zip";
	roiManager("Save", fullPath);
}

function doLoad(name){//not used
	fullPath = getDirectory("temp") + name + ".zip";
	roiManager("Open", fullPath);
	run("From ROI Manager");
}

// calculate parameters for current image size
// sets "Require Command key for macros"
function prepare(){
	if (firstTime){
		run("Misc...", "require run");
		setOption("QueueMacros" , true);
		firstTime = false;
	}
	if(nImages == 0) exit;
	if (currentID == getImageID)
		return;
	currentID = getImageID;
	frameWidth = getWidth - 2 * margin;
	xPairs = floor(frameWidth/Zvalue/2);
	frameWidth = xPairs * Zvalue * 2;
	frameLeft = round((getWidth - frameWidth)/2);
	frameRight = getWidth - frameLeft;

	frameHeight = getHeight - 2 * margin;
	yLines = floor(frameHeight/disty);
	frameHeight = disty * yLines ;
	frameTop = round((getHeight - frameHeight)/2);
	frameBottom = getHeight - frameTop;
	if (xPairs < 1 || yLines < 1){ 
		currentID = 0;
		exit(" Image is too small");
	}
	//print(" KAN Weg ", " xPairs=", xPairs, " yLines=", yLines);
}

//adds gridlines to roiManager
function gridToManager(){
	prepare();
	xPoints = newArray(50000);
	yPoints = newArray(50000);
	
	gridDone = getImageID;
	pt = 0;
	offx = 0.25 * Zvalue;
	for (y = frameTop + 0.5 * disty; y < (frameTop + frameHeight); y += disty){
		for (pair = 0; pair < xPairs; pair++){
			x = frameLeft + offx + pair*2 * Zvalue;
			xPoints[pt] = round(x);
			xPoints[pt + 1] = round(x + Zvalue);
			yPoints[pt] = round(y);
			yPoints[pt + 1] = round(y);
			pt += 2;
		}
		if (offx < (0.5 * Zvalue)) 
			offx = 0.75 * Zvalue;
		else 
			offx = 0.25 * Zvalue;
	}
	nGridLines = pt/2;
	run("Select None");
	run("Show Overlay");
	xPoints = Array.trim(xPoints, pt);
	yPoints = Array.trim(yPoints, pt);
	cnt = roiManager("count");
	if (cnt > 0 && cnt == nGridLines) {

		roiManager("select", nGridLines-1);
		getSelectionCoordinates(xx, yy);
		lastXLine = xPoints[pt -2];
		lastXArr = xx[0];
		lastYLine = yPoints[pt -2];
		lastYArr = yy[0];
		if (lastXLine == lastXArr && lastYLine == lastYArr)
			return;
	}		
	roiManager("Reset");
	roiManager("Show None");
	//setBatchMode(true);
	time = getTime;
	thisID = getImageID;
	newImage("Untitled", "8-bit White", 2, 2, 1);
	wait(100);
	showStatus ("Creating " + nGridLines + " Lines");
	setBatchMode(true);
	for (jj = 0; jj < nGridLines; jj++){
		makeLine(xPoints[jj*2], yPoints[jj*2], xPoints[jj*2] + Zvalue, yPoints[jj*2]);
		roiManager("Add", gridColor);
		showProgress(jj/nGridLines);
	}
	setBatchMode(false);
	close;
	selectImage(thisID);
	//setBatchMode(false);
	showStatus ("" + nGridLines +  " Lines;  "  + (getTime - time)/1000 + "  sec. ");
	wait(500);
}

//adds frame to Overlay
function frameToOverlay() {

		makeSelection("polyline", newArray(frameLeft,frameRight,frameRight), newArray(frameTop,frameTop,getHeight));
		run("Add Selection...", "stroke=green width=2");
		
		makeSelection("polyline", newArray(frameRight,frameLeft,frameLeft), newArray(frameBottom,frameBottom,0));
		run("Add Selection...", "stroke=red width=2");
		run("Select None");

	}
	run("Show Overlay");
}


macro "Switch to YV [1]"{
	ojSwitchToItem("YV");
}
macro "Switch to YV-YG [2]"{
	ojSwitchToItem("YV-YG");
}
macro "Switch to YG [3]"{
	ojSwitchToItem("YG");
}


macro "Switch to YV-P [6]"{
	ojSwitchToItem("YV-P");
}
macro "Switch to YV-YG-P [7]"{
	ojSwitchToItem("YV-YG-P");
}
macro "Switch to YG-P [8]"{
	ojSwitchToItem("YG-P");
}

macro "-"{
}


macro "Only Show Grid Items [y]"{
	ojSetItemVisible("*", false);
	ojSetItemVisible("YV", true);
	ojSetItemVisible("YV-YG", true);
	ojSetItemVisible("YG", true);
}

macro "Only Show Profile Items [p]"{
	ojSetItemVisible("*", false);
	ojSetItemVisible("YV-P", true);
	ojSetItemVisible("YV-YG-P", true);
	ojSetItemVisible("YG-P", true);
}


macro "Set all visible [t]"{
	ojSetItemVisible("*", true);
}

macro "-"{
}

macro "Start Swatter [s]"{
	if (selectionType == 1){
		run("Select None");
		exit;
	}
	if (gridDone != getImageID)
		exit("Please re-create the grid");
	ojSetTool(0);
	setTool("brush");
	call("ij.gui.Toolbar.setBrushSize", swatterRadius * 2); 
	getCursorLoc(x, y, z, modifiers);
	
	
	makeOval(x - swatterRadius, y-swatterRadius, swatterRadius * 2, swatterRadius * 2);
	run("Properties... ", "name=[] stroke=magenta width=1 fill=" + swatterColor);
}

macro "Mark Swatter [m]"{
	if (getTime - stampTime < 9000) return;
	if (gridDone != getImageID)
		exit("Please re-create the grid");
	if (selectionType != 1 && selectionType != 9){//must be oval or brush
		exit("No Swatter area found");
	}
	stampTime = getTime;
	iName = "" + ojActiveItemName();
	if (iName == "0"){
		ojShowTools();
		exit("No item type is selected in ObjectJ Tools	");
	}
	if (ojImageLink() == 0)
		exit("Image is not linked");
	ojUpdateMarkers(false);
	for (pt = 0; pt < xPoints.length; pt++){
		if (selectionContains(xPoints[pt], yPoints[pt])){
			showProgress(pt/xPoints.length);
			x = xPoints[pt];
			y = yPoints[pt];
			if (isFree(x, y, Zvalue/2)){
				ojSwitchToItem(ojActiveItemName());
				ojSetMarker(xPoints[pt], yPoints[pt]);
			}
		}
	}
	ojUpdateMarkers(true);
	stampTime = 0;
}

//check if position is already occupied by a marker
function isFree(xx, yy, tolerance){
	img = ojImageLink();
	if (img == 0)
		return false;
	for (obj = ojFirstObject(img); obj <= ojLastObject(img); obj++){
		ojSelectObject(obj);
		dd = sqrt(pow(ojXPos(1) - xx, 2)  + pow(ojYPos(1) - yy, 2));
		if (dd < tolerance) return false;
	}
	return true;
}
		
		
macro "Swatter color"{
	rd = parseInt(substring(swatterColor, 3,5), 16);
	gn = parseInt(substring(swatterColor, 5,7), 16);
	bl = parseInt(substring(swatterColor, 7,9), 16);
	print(rd, gn, bl);
	setForegroundColor(rd, gn, bl);
	run("Color Picker...");
	wait(333);
	waitForUser("- Select window 'CP',\n- choose swatter color, \n- then click 'OK'");
	color2 = getValue("color.foreground");
 	color2 = substring(toHex(0x1000000 + color2), 1);
	transp = minOf(255, 2.56 * getNumber("%Transparency:", 50));
	transp = substring(toHex(0x100 + transp), 1);
	swatterColor = "#" + transp + color2;
	showMessage("Swatter Color is: " + swatterColor);
	selectWindow("CP");
	run("Close");
}


macro "Kill objects in roi"{
	arr = newArray(ojNObjects());
	index = 0;
	img = ojImageLink();
	if (img == 0) exit("front window is  not linked");
	for (obj = ojFirstObject(img); obj <= ojLastObject(img); obj++){
		ojSelectObject(obj);
		if (ojZPos(1) == getSliceNumber && selectionContains(ojXPos(1), ojYPos(1)))
			arr[index++] = obj;
	}
	for (jj = index-1; jj >= 0; jj--)
		ojDeleteObject(arr[jj]);
}

// Shows table with collective results.
// With an image in front and Grid-only active,
// you can verify the number of its grid lines via:
// Image>Overlay>List Elements
 
macro "Show Project Statistics"{
	ojRecalculate();
	titles = split( " YV YV-YG YG NegGrid Extra YV-P YV-YG-P YG-P", " ");
	sumPoints = 0;
	sumAreaScaled = 0;
	print("\\Clear");
	selectWindow("Log");
	for(img = 1; img <= ojNImages(); img++){
		ww = ojGetImageValue(img, "width");
		hh = ojGetImageValue(img, "height");
		pxWidth = ojGetVoxelSize(img, "x");
		xPairs = floor((ww - 2 * margin)/Zvalue/2);
		frameWidth = xPairs * Zvalue * 2;//even Integer
		frameLeft = round((ww - frameWidth)/2);
		frameRight = ww - frameLeft;
		frameHeight1 = hh - 2 * margin;
		yLines = floor(frameHeight1/disty);
		frameHeight2 = disty * yLines ;
	
		frameTop = round((hh - frameHeight2)/2);
		frameBottom = hh - frameTop;
		area1 = frameWidth * frameHeight2;
		nPoints = xPairs * yLines * 2;
		areaScaled = area1 * pxWidth * pxWidth;
		print("Img=", img, " nGridPoints=", nPoints, " areaScaled=", areaScaled, " name=", ojGetImageName(img)); 
		sumPoints += nPoints;
		sumAreaScaled += areaScaled;
			//area2 = Zvalue*Zvalue * nPoints * sqrt(3)/2; 
			//print("area1=",  area1, " area2=", area2); 
	}
	run("Clear Results");
	//setResult("No_Pictures", 0, ojNImages());
	setResult("Sum_Grid_Points", 0, sumPoints);
	setResult("Sum_Field_Area", 0, sumAreaScaled);
	for(col = 0; col < titles.length; col++){
		title = titles[col];
		sum = ojGetStatistics(title, "sum");
		//title = replace(title, "-", "_");//optional if underscore desired
		setResult(title, 0, sum);
	}
	setOption("ShowRowNumbers", false);
	updateResults;
	selectWindow("Results");
}
