Skip to content

Instantly share code, notes, and snippets.

@steveroush
Last active November 18, 2023 03:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steveroush/412d9c5479ba8f5c30239e4963338b82 to your computer and use it in GitHub Desktop.
Save steveroush/412d9c5479ba8f5c30239e4963338b82 to your computer and use it in GitHub Desktop.
Graphviz post-processor to customize edges
#!/bin/sh
cat <<QUitquIT
# This is a shell archive.
#
# to execute this file, type: sh alter_archive.sh
#
# On Linux/UNIX/MacOS(?) systems it is an executable program that will create
# a subdirectory (named alter.d) in the currect directory and then
# install multiple (text) files in that directory.
# This shell archive and all contents are humanly readable - no binary files.
#
# Windows OS users will have to manually cut this file up and create any files
# that are desired. Sorry.
#
# To proceed, type "y" at the prompt.
#
QUitquIT
read -p "Type y to proceed " ans
if [ "$ans" != "y" ];then echo "exiting";exit;fi
if [ -d "alter.d" ];then
if [ -w "alter.d" ];then echo "directory alter.d exists and is writable";
else echo "directory alter.d exists but is NOT writable\nExiting"; exit; fi
else
mkdir "alter.d" ;
if [ -d "alter.d" ];then
if [ -w "alter.d" ];then echo "directory alter.d has been created and is writable";
else echo "directory alter.d has been created but is NOT writable\nExiting"; exit;
fi
fi
fi
echo writing alter.d/alterSimpleEdge.gvpr
cat >alter.d/alterSimpleEdge.gvpr <<'STopstOP'
/***********************************************************************
replace edge spline
"edgeType" (required):
- "curve" - "regular", symmetric, curve
- "straight" - two points define a line
- "ortho2" (2 connected sides of a rectangle == one horizontal segment and one vertical segment ) (newer feature)
- "ortho3" (3 sides of a rectangle) (was called "ortho")
"edgeOffset" (optional):
- offset from straight line (does not apply to "straight" or "ortho2")
- default: 50% of port-to-port distance
- units defined by trailing character(s):
- default: points
- "pt" - points
- "in" - inches
- "%" - percent of port-to-port distance
"edgeDirection (required):"
- "cw" (clockwise) or "ccw" (counter-clockwise)
- from tail to head
- does not apply to "straight"
- default is "cw" ???????
command line:
dot myfile.gv | gvpr -cf alterSimpleEdge.gvpr | neato -n2 -Tpng >myfile.png
Future:
- allow repositioning of arrowhead & arrowtail, using n,s,e,w,nw,ne,sw,se ports
(not very interesting, this can be done via the source graph (not applicilbe to some node shapes)
- allow repositioning of arrowhead & arrowtail, using new port definitions (1-12 clock positions, degrees (1-359/360), or % along node side 17% fron .ne to .se)
(not applicilbe to some node shapes)
************************************************************************/
BEGIN{
float Offset; // distance, in points
float Percent; // fraction of point-to-point (port-to-port) distance
float di, Distance;
float deltaX, deltaY;
float newX[], newY[];
float oldX[], oldY[], arrowSize[];
float dx, dy;
float tail2headDeltaX, tail2headDeltaY;
int i, cnt, n, v, goodDirection;
int arrowStart, arrowEnd, nextToarrowStart, nextToarrowEnd;
int splineStart, splineEnd;
int arrow[], clockWise;
string ptStr, outStr;
string aPoint, whichWay, point[int];
string rslt, MSG;
string numstr="?([+-])@(+([0-9])?(.*([0-9]))|\.+([0-9]))";
graph_t Root;
//////////////////////////////////////////////////////////////
void doErr(string errString) {
print("// Error: ", errString);
printf(2,"Error: %s\n", errString);
}
//////////////////////////////////////////////////////////////
void doMsg(string errString) {
print("// Note: ", errString);
//printf(2,"Note: %s\n", errString);
}
/////////////////////////////////////////////////////////////
float Max(float f1, float f2) {
float fx;
if (f1>f2) fx=f1;
else fx=f2;
return fx;
}
/////////////////////////////////////////////////////////////
float abs(float f1) {
float fx;
if (f1<0) fx=-f1;
else fx=f1;
return fx;
}
/////////////////////////////////////////////////////////////
string mkPoint(float thisX, float thisY) {
rslt=(string)thisX + "," + (string)thisY + " ";
print("// mkPoint rslt: ", rslt);
return rslt;
}
//////////////////////////////////////////////////////////////
// compute distance in points - always positive value
float distance(float x1,float y1,float x2,float y2) {
di=sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
//print("// DISTANCE: ", di, " ", x1," ", y1," ", x2," ", y2);
return di; // /72.; // convert points to inches !!
}
//////////////////////////////////////////////////////////////
string pointAlongLine(float x1, float y1, float x2, float y2, float percent, int direction) {
float newx, newy;
dx=x1-x2;
dy=y1-y2;
if (direction==1) {
newx=x1-(dx*percent);
newy=y1-(dy*percent);
} else {
newx=x1+(dx*percent);
newy=y1+(dy*percent);
}
print ("// pointAlongLine new point: ", direction," -- ", x1,",", y1," ", x2, ",", y2," -- ", newx, ",", newy);
rslt=(string)newx + "," + (string)newy;
print("// pointAlongLine rslt: ", rslt);
return rslt;
}
//////////////////////////////////////////////////////////////
string rightAnglePoint(float x1, float y1, float x2, float y2, float percent, int direction) {
// calculate a point on a line 90 degrees from midpoint of the given line
rslt=pointAlongLine(x1, y1, (x1+y1-y2), (y1-x1+x2), percent, direction);
print("// 90 rslt: ", rslt);
return rslt;
}
//////////////////////////////////////////////////////////////
string reposition(float x1, float y1, float x2, float y2, float aSize) {
float tmpX, tmpY, dist;
print("// reposition: ", x1,",",y1," ",x2,",",y2);
dist=distance(x1,y1,x2,y2);
tmpX=x1+((x2-x1)*(aSize/dist));
tmpY=y1+((y2-y1)*(aSize/dist));
print("// reposition: ", x1,",",y1," ",x2,",",y2, " == ", tmpX, " ", tmpY);
return (string)tmpX + "," + (string)tmpY;
}
////////////////////////////////////////////////////////////////////
// point1 & point2: - newX[2],newY[2] & newX[3],newY[3] - "outer spline points"
// port (point) - where the arrowhead lands
// aSize - arrowhead length
// perc - a percentage ?????? (starting w/ .67)
// MAYBE % of way from newX[2],newY[2] to newX[3],newY[3]
//
string arrowheadCalc(float p1X, float p1Y, float p2X, float p2Y, float portX, float portY, float aSize, float perc) {
float partialX, partialY, ahX, ahY, dX, dY, d, ahP;
string retS;
print("// arrowheadCalc: ", p1X,",",p1Y," ",p2X,",",p2Y);
partialX=p1X+((p2X-p1X)*perc);
partialY=p1Y+((p2Y-p1Y)*perc);
print("// arrowheadCalc: ", p1X, ",", p1Y," ",p2X,",",p2Y, " == ", partialX,",",partialY);
d=distance(portX, portY, partialX, partialY);
ahP=aSize/d; // some fraction
dX=partialX-portX;
dY=partialY-portY;
ahX=portX+(ahP*dX);
ahY=portY+(ahP*dY);
retS=(string)ahX + "," + (string)ahY;
print("// arrowheadCalc: ", retS);
return retS;
}
//////////////////////////////////////////////////////////////////
// straight (spline) line requires 4 points
// given 1st & last points of line,
// create spline w/ 3 points
// do NOT add 1st point, it already exists
string lineSegment3Points(float x1, float y1, float x2, float y2) {
//float pnewX[1], pnewY[1], pnewX[2], pnewY[2];
print("// lineSegment3Points called with >>", x1, ",", y1, " ",x2,",",y2,"<<");
rslt=" " + (string)(x1+(.33*(x2-x1))) + "," + (string)(y1+(.33*(y2-y1)));
rslt+=" " + (string)(x1+(.67*(x2-x1))) + "," + (string)(y1+(.67*(y2-y1))) + " ";
// now add point #2 (last point)
rslt+=(string)x2 + "," + (string)y2 + " ";
print("// lineSegment3Points returning >>", rslt,"<<");
return rslt;
}
///////////////////////////////////////////////////////////////////////////
string ortho2CalcDirection(string D) {
string ret1, ret2;
MSG="ortho2 DIRECTION tail2headDeltaX " + (string)tail2headDeltaX + " "+ (string)tail2headDeltaY;
doMsg(MSG);
if (tail2headDeltaX>0 && tail2headDeltaY>0) { // upper right quadrant
ret1="NE";
ret2="EN";
} else if (tail2headDeltaX<0 && tail2headDeltaY>0) { // upper left quadrant
ret1="WN";
ret2="NW";
} else if (tail2headDeltaX>0 && tail2headDeltaY<0) { // lower right quadrant
ret1="ES";
ret2="SE";
} else { // lower left quadrant
ret1="SW";
ret2="WS";
}
MSG="ortho2 DIRECTION before " + D + " "+ ret1;
doMsg(MSG);
if (D=="ccw") {
ret1=ret2;
MSG="ortho2 DIRECTION after " + D + " " + ret1;
doMsg(MSG);
}
MSG="ortho2 RETURNING " + ret1;
doMsg(MSG);
return ret1;
} ///////////////////////////////////////////////////////////////////////////
string ortho3CalcDirection(string D) {
string ret1, ret2;
MSG="DIRECTION tail2headDeltaX " + (string)tail2headDeltaX + " "+ (string)tail2headDeltaY;
doMsg(MSG);
if (abs(tail2headDeltaX)>=abs(tail2headDeltaY)) { // primarily east/west
if (tail2headDeltaX>=0) { // primarily east
ret1="nes";
ret2="sen";
} else { // primarily west
ret1="swn";
ret2="nws";
}
} else { // primarily north/south
if (tail2headDeltaY>=0) { // primarily north
ret1="wne";
ret2="enw";
} else { // primarily south
ret1="esw";
ret2="wse";
}
}
MSG="DIRECTION before " + D + " "+ ret1;
doMsg(MSG);
if (D=="ccw") {
ret1=ret2;
MSG="DIRECTION after " + D + " " + ret1;
doMsg(MSG);
}
return ret1;
}
//////////////////////////////////////////////////////////////////////////////
void debugDir(string D) {
print("// debug ",D," ",arrowStart, " ",oldX[arrowStart], " ",oldY[arrowStart]);
print("// ",D," ",arrowEnd, " ",oldX[arrowEnd], " ",oldY[arrowEnd]);
print("// ",D," ",arrowSize["s"], " ",arrowSize["e"]);
}
}
////////////////////// end of BEGIN ////////////////////////////////////////
BEG_G{
Root=$G;
}
//////////////////////////////////////////////////////////////
E{
int DIR, hasType, hasOffset, hasDirection;
string useDirection;
print("/////////////////////////////////////////////////////////");
if (!hasAttr($,"edgeType") || $.edgeType=="") {
print("// edgeType not set for ", $.name,", skipping this edge");
continue;
}
//////////// check attributes
if (hasAttr($,"edgeType") && $.edgeType=="(ortho2|ortho3|curved|straight)") {
hasType=1;
} else {
MSG="Edge " + $.name + ", has bad value for edgeType (" + $.edgeType + ")";
doErr(MSG);
hasType=0;
}
if (hasAttr($,"edgeOffset") && $.edgeOffset!="") { // optional
hasOffset=1;
} else {
hasOffset=0;
}
if (hasAttr($,"edgeDirection") && $.edgeDirection!="") { // required
hasDirection=1;
} else {
hasDirection=0;
}
//////////////////////////////////////////////////////
unset(newX);
unset(newY);
$.oldPos=$.pos;
// remove pos for all edge labels, let neato set correct pos
if (hasAttr($,"lp") && $.lp!="")
$.lp="";
if (hasAttr($,"xlp") && $.xlp!="")
$.xlp="";
if (hasAttr($,"head_lp") && $.head_lp!="")
$.head_lp="";
if (hasAttr($,"tail_lp") && $.tail_lp!="")
$.tail_lp="";
// there is a bug in dot (dot output format only), sometimes it messes up the pos value
// it produces pos="s,... instead of pos="e,...
// OR
// it produces pos="e,... instead of pos="s,...
if (!hasAttr($,"dir") || $.dir=="" || $.dir=="forward")
DIR=1;
else
switch($.dir) {
case "forward":
DIR=1;
break;
case "back":
DIR=2;
break;
case "both":
DIR=3;
break;
case "none":
DIR=4;
break;
default:
MSG="Edge " + $.name + ", bad value for dir (" + $.dir + ")";
doErr(MSG);
break;
}
print("// DIR: ",DIR);
Offset=.5; // default to 50% of point-to-point distance
if ($.edgeType!="" && $.edgeType!="(straight|ortho2|ortho3|curved)") {
MSG="Edge " + $.name + ", bad value for edgeType (" + $.edgeType + ")";
doErr(MSG);
continue;
}
print("// edge: ", $.name," >", $.pos, "<< ");
cnt=tokens($.pos, point);
// initialize these four points
arrowStart=0;
nextToarrowStart=arrowStart+1;
arrowEnd=cnt-1;
nextToarrowEnd=arrowEnd-1;
arrow["s"]=0;
arrow["e"]=0;
/****************************************************
now we try to "fix" the dot pos bug (see above)
do we need to check ""both"" ?????????
*****************************************************/
if ((point[0]=="s,*" && DIR==1) || (point[0]=="e,*" && DIR==2)) {
string ts[];
int ti;
for (ti=1; ti<cnt; ti++) {
ts[ti]=point[cnt-ti];
}
for (ti=1; ti<cnt; ti++) {
point[ti]=ts[ti];
print("// ti: ", ti," point: ", point[ti]);
}
print("// before: >",point[0]);
if (point[0]=="s,*" && DIR==1)
point[0]="e," + substr(point[0],2);
else
point[0]="s," + substr(point[0],2);
print("// after: >",point[0]);
print("//FIXED backwards arrowhead");
} // no else ??? HELP
for (i=0; i<cnt; i++) {
print("// ",i," ",point[i]);
ptStr=point[i];
// arrowheads?
if (point[i]=="[se]*") {
print("// arrowhead : ",point[i]);
ptStr=substr(point[i],2);
if (point[i]=="s*") {
arrowStart=i;
nextToarrowStart=arrowStart+1;
print("// START: ",arrowStart," arrowEnd: ", arrowEnd);
arrow["s"]=1;
} else if (point[i]=="e*") {
arrowEnd=i;
nextToarrowEnd=cnt-1;
if (arrowStart==arrowEnd) { // i.e. there is no starting arrow
arrowStart++;
nextToarrowStart=arrowStart+1;
}
if (nextToarrowStart==i)
nextToarrowStart++;
print("// END: ", arrowEnd, " START: ",arrowStart);
arrow["e"]=1;
}
}
// do we need trimmed version of point later on ??
// yes, we will have to adjust the arrowheads, too
oldX[i]=xOf(ptStr);
oldY[i]=yOf(ptStr);
print("// ",i," ",point[i], " ", oldX[i], " ", oldY[i]);
} // end of loop across pos points
//////////////////////////////////////////////////////////////////////
// tail-to-head
tail2headDeltaX=(float)oldX[arrowEnd] - (float)oldX[arrowStart]; // delta X
tail2headDeltaY=(float)oldY[arrowEnd] - (float)oldY[arrowStart]; // delta Y
print("// tail2headDeltaX: ", tail2headDeltaX, " tail2headDeltaY: ", tail2headDeltaY);
////////////////////////////////////////////////////////////////
// get arrowhead sizes (if arrowheads specified)
arrowSize["s"]=0.;
arrowSize["e"]=0.;
whichWay="s";
if (arrow[whichWay]) {
// need arrowhead length/distance
// therefore, need "next" point
// whichWay is point[????????]
arrowSize[whichWay]=distance(oldX[arrowStart], oldY[arrowStart], oldX[nextToarrowStart], oldY[nextToarrowStart]);
print("// arrow ", whichWay, " ", arrowSize[whichWay]);
}
whichWay="e";
if (arrow[whichWay]) {
// need arrowhead length/distance
// therefore, need "previous" point
// whichWay is point[cnt-1]
arrowSize[whichWay]=distance(oldX[arrowEnd], oldY[arrowEnd], oldX[nextToarrowEnd], oldY[nextToarrowEnd]);
print("// arrow ", whichWay, " ", arrowSize[whichWay]);
}
////////////////////////////////////////////////////////////////
print("// ArrowStart: ", arrowStart," nextToarrowStart: ", nextToarrowStart, " nextToarrowEnd: ", nextToarrowEnd, " arrowEnd: ", arrowEnd);
deltaX=oldX[arrowStart] - oldX[arrowEnd];
deltaY=oldY[arrowStart] - oldY[arrowEnd];
Distance=distance(oldX[arrowStart], oldY[arrowStart], oldX[arrowEnd], oldY[arrowEnd]);
print("// DISTANCE: ", Distance);
if (hasOffset) {
doMsg("OFFSET >" + $.edgeOffset +"<");
Percent=-1;
Offset=-1;
//////////////////////////////////////////////////////////
// add fractional value (9 to 1)
if ($.edgeOffset==numstr+ "%") { // "(+([0-9])\%)") {
Percent=.01*(float)sub($.edgeOffset,"%");
Offset=Percent*Distance;
doMsg("PERCENT: " + (string) Percent + " " + (string)Offset + " %%% ");
} else if ($.edgeOffset==numstr) { // points "+([0-9])") {
Offset=(float)$.edgeOffset;
Percent=Offset/Distance;
doMsg("PT (default): "+(string)Offset+" pt " + "Percent: " + (string) Percent);
} else if ($.edgeOffset==numstr + "pt") { // points, explicitly "(+([0-9])pt)") {
Offset=(float)sub($.edgeOffset,"pt");
Percent=Offset/Distance;
doMsg("PT: " + (string)Offset + " pt " + "Percent: " + (string) Percent);
} else if ($.edgeOffset==numstr + "in") { // inches, explicitly "(*([0-9]?(.)+([0-9])in)") {
// convert inches to points
Offset=((float)sub($.edgeOffset,"in"))*72.;
Percent=Offset/Distance;
doMsg("IN : "+(string)Offset+" in " + "Percent: " + (string) Percent);
} else {
MSG="Edge " + $.name + ", has bad value for offset (" + $.edgeOffset + "). Must be number optionally followed by \"%|in|pt\".";
doErr(MSG);
continue;
}
} else {
print("// setting edgeOffset to default of 36 points (.5 inches)");
Offset=36;
Percent=Offset/Distance;
}
print("// FINAL Percent: ", Percent," Offset: ", Offset);
clockWise=1; // default to clockwise from tail to head
goodDirection=0;
useDirection="";
useDirection="SKIPskipSKIP";
if (hasAttr($,"edgeDirection") && $.edgeDirection!="" && hasAttr($,"edgeType") && $.edgeType=="(ortho2|ortho3|curved)") {
print("// EDGE DIRECTION: ", $.edgeDirection);
goodDirection=1;
}
if ($.edgeType=="ortho3" && $.edgeDirection=="(cw|ccw)")
useDirection=ortho3CalcDirection($.edgeDirection);
else
useDirection=$.edgeDirection;
if ($.edgeType=="ortho2" && $.edgeDirection=="(cw|ccw)")
useDirection=ortho2CalcDirection($.edgeDirection);
if ($.edgeType=="straight" && useDirection!="") {
MSG="Edge " + $.name + ", edgeType==" + $.edgeType + ", ignoring value for direction (" + $.edgeDirection + ")";
doErr(MSG);
}
//$.label=useDirection; //// TEMPORARY
switch(useDirection) {
case "cw":
clockWise=1;
break;
case "ccw":
clockWise=0;
break;
///////////////////// ortho2 cases ////////////////////////////////////
case "EN": // east then north
newX[1]=oldX[arrowStart] + arrowSize["s"];
newY[1]=oldY[arrowStart];
newX[2]=newX[1]+tail2headDeltaX - arrowSize["s"];
newY[2]=newY[1];
newX[3]=newX[2];
newY[3]=oldY[arrowEnd] - arrowSize["e"];
debugDir($.edgeDirection);
break;
case "ES": // east then south
newX[1]=oldX[arrowStart]+arrowSize["s"];
newY[1]=oldY[arrowStart];
newX[2]=newX[1]+tail2headDeltaX - arrowSize["s"];
newY[2]=newY[1];
newX[3]=newX[2];
newY[3]=oldY[arrowEnd] + arrowSize["e"];
debugDir($.edgeDirection);
break;
case "WN": // west then north
newX[1]=oldX[arrowStart]-arrowSize["s"];
newY[1]=oldY[arrowStart];
newX[2]=newX[1]+tail2headDeltaX + arrowSize["s"];
newY[2]=newY[1];
newX[3]=newX[2];
newY[3]=oldY[arrowEnd] - arrowSize["e"];
debugDir($.edgeDirection);
break;
case "WS": // west then south
newX[1]=oldX[arrowStart]-arrowSize["s"];
newY[1]=oldY[arrowStart];
newX[2]=newX[1]+tail2headDeltaX + arrowSize["s"];
newY[2]=newY[1];
newX[3]=newX[2];
newY[3]=oldY[arrowEnd] + arrowSize["e"];
debugDir($.edgeDirection);
break;
case "NE": // north then east
newX[1]=oldX[arrowStart];
newY[1]=oldY[arrowStart]+arrowSize["s"];
newX[2]=newX[1];
newY[2]=newY[1]+tail2headDeltaY - arrowSize["s"];
newX[3]=oldX[arrowEnd]-arrowSize["e"];
newY[3]=newY[2];
debugDir($.edgeDirection);
break;
case "NW": // north then west
newX[1]=oldX[arrowStart];
newY[1]=oldY[arrowStart]+arrowSize["s"];
newX[2]=newX[1];
newY[2]=newY[1]+tail2headDeltaY - arrowSize["s"];
newX[3]=oldX[arrowEnd]+arrowSize["e"];
newY[3]=newY[2];
debugDir($.edgeDirection);
break;
case "SE": // south then east // bugs at head ???
newX[1]=oldX[arrowStart];
newY[1]=oldY[arrowStart]-arrowSize["s"];
newX[2]=newX[1];
newY[2]=newY[1]+tail2headDeltaY + arrowSize["s"];
newX[3]=oldX[arrowEnd]-arrowSize["e"];
newY[3]=newY[2];
debugDir($.edgeDirection);
break;
case "SW": // south then west
newX[1]=oldX[arrowStart];
newY[1]=oldY[arrowStart]-arrowSize["s"];
newX[2]=newX[1];
newY[2]=newY[1]+tail2headDeltaY + arrowSize["s"];
newX[3]=oldX[arrowEnd]+arrowSize["e"];
newY[3]=newY[2];
debugDir($.edgeDirection);
break;
///////////////////// ortho3 cases ////////////////////////////////////
case "nes": // primarily east
newX[1]=oldX[arrowStart];
newY[1]=oldY[arrowStart]+arrowSize["s"];
newX[2]=oldX[arrowStart];
newY[2]=MAX(oldY[arrowStart],oldY[arrowEnd]) + Offset;
newX[3]=oldX[arrowEnd];
newY[3]=newY[2];
newX[4]=newX[3];
newY[4]=oldY[arrowEnd] + arrowSize["e"];
debugDir($.edgeDirection);
break;
case "sen": // primarily east
newX[1]=oldX[arrowStart];
newY[1]=oldY[arrowStart]-arrowSize["s"];
newX[2]=oldX[arrowStart];
newY[2]=MIN(oldY[arrowStart],oldY[arrowEnd]) - Offset;
newX[3]=oldX[arrowEnd];
newY[3]=newY[2];
newX[4]=newX[3];
newY[4]=oldY[arrowEnd] - arrowSize["e"];
debugDir($.edgeDirection);
break;
case "nws": // primarily west
newX[1]=oldX[arrowStart];
newY[1]=oldY[arrowStart]+arrowSize["s"];
newX[2]=oldX[arrowStart];
newY[2]=MAX(oldY[arrowStart],oldY[arrowEnd]) + Offset;
newX[3]=oldX[arrowEnd];
newY[3]=newY[2];
newX[4]=newX[3];
newY[4]=oldY[arrowEnd] +arrowSize["e"];
debugDir($.edgeDirection);
break;
case "swn": // primarily west
newX[1]=oldX[arrowStart];
newY[1]=oldY[arrowStart]-arrowSize["s"];
newX[2]=oldX[arrowStart];
newY[2]=MIN(oldY[arrowStart],oldY[arrowEnd]) - Offset;
newX[3]=oldX[arrowEnd];
newY[3]=newY[2];
newX[4]=newX[3];
newY[4]=oldY[arrowEnd] - arrowSize["e"];
debugDir($.edgeDirection);
break;
case "enw": // primarily north
newX[1]=oldX[arrowStart]+arrowSize["s"];
newY[1]=oldY[arrowStart];
newX[2]=MAX(oldX[arrowStart],oldX[arrowEnd]) + Offset;
newY[2]=oldY[arrowStart];
newX[3]=newX[2];
newY[3]=oldY[arrowEnd];
newX[4]=oldX[arrowEnd] +arrowSize["e"];
newY[4]=newY[3];
debugDir($.edgeDirection);
break;
case "esw": // primarily south
newX[1]=oldX[arrowStart]+arrowSize["s"];
newY[1]=oldY[arrowStart];
newX[2]=MAX(oldX[arrowStart],oldX[arrowEnd]) + Offset;
newY[2]=oldY[arrowStart];
newX[3]=newX[2];
newY[3]=oldY[arrowEnd];
newX[4]=oldX[arrowEnd] + arrowSize["e"];
newY[4]=newY[3];
debugDir($.edgeDirection);
break;
case "wne": // primarily north
newX[1]=oldX[arrowStart] - arrowSize["s"];
newY[1]=oldY[arrowStart];
newX[2]=MIN(oldX[arrowStart],oldX[arrowEnd]) - Offset;
newY[2]=oldY[arrowStart];
newX[3]=newX[2];
newY[3]=oldY[arrowEnd];
newX[4]=oldX[arrowEnd] - arrowSize["e"];
newY[4]=newY[3];
debugDir($.edgeDirection);
break;
case "wse": // primarily south
newX[1]=oldX[arrowStart] - arrowSize["s"];
newY[1]=oldY[arrowStart];
newX[2]=MIN(oldX[arrowStart],oldX[arrowEnd]) - Offset;
newY[2]=oldY[arrowStart];
newX[3]=newX[2];
newY[3]=oldY[arrowEnd];
newX[4]=oldX[arrowEnd] - arrowSize["e"];
newY[4]=newY[3];
debugDir($.edgeDirection);
break;
case "SKIPskipSKIP": // do nothing
break;
default:
goodDirection=0;
MSG="Edge " + $.name + ", bad value for direction (" + $.edgeDirection + ")";
doErr(MSG);
break;
}
print("/////////// edgeType: ", $.edgeType);
if ($.edgeType=="straight") {
string tmpS;
tmpS=reposition(oldX[arrowStart], oldY[arrowStart], oldX[arrowEnd], oldY[arrowEnd], arrowSize["s"]);
newX[1]=xOf(tmpS);
newY[1]=yOf(tmpS);
newX[2]=newX[1];
newY[2]=newY[1];
tmpS=reposition(oldX[arrowEnd], oldY[arrowEnd], oldX[arrowStart], oldY[arrowStart], arrowSize["e"]);
newX[3]=xOf(tmpS);
newY[3]=yOf(tmpS);
newX[4]=newX[3];
newY[4]=newY[3];
} else if ($.edgeType=="curved") {
string newArrowhead;
// need to re-think newX[2]/newY[2] + newX[3]/newY[3]
// given arrowsizes & a calculated angle
newX[1]=oldX[arrowStart];
newY[1]=oldY[arrowStart];
newX[4]=oldX[arrowEnd];
newY[4]=oldY[arrowEnd];
aPoint=rightAnglePoint(oldX[arrowStart], oldY[arrowStart], oldX[arrowEnd], oldY[arrowEnd], Percent, clockWise);
print("// aPoint: ", aPoint);
newX[2]=xOf(aPoint);
newY[2]=yOf(aPoint);
print("// newX[2]/newY[2] :", newX[2],",",newY[2]);
deltaX=newX[2]-oldX[arrowStart];
deltaY=newY[2]-oldY[arrowStart];
newX[3]=deltaX+oldX[arrowEnd];
newY[3]=deltaY+oldY[arrowEnd];
print("// newX[3]/newY[3] :", newX[3],",",newY[3]);
if (point[arrowStart]=="s*") {
newArrowhead=arrowheadCalc(newX[2], newY[2], newX[3], newY[3], oldX[arrowStart], oldY[arrowStart], arrowSize["s"], .09);
newX[1]=xOf(newArrowhead);
newY[1]=yOf(newArrowhead);
print("// NEW START: ", newArrowhead);
}
if (point[arrowEnd]=="e*") {
newArrowhead=arrowheadCalc(newX[3], newY[3], newX[2], newY[2], oldX[arrowEnd], oldY[arrowEnd], arrowSize["e"], .09);
newX[4]=xOf(newArrowhead);
newY[4]=yOf(newArrowhead);
print("// NEW END: ", newArrowhead);
}
print ("// cnt, start, end ",cnt," ",arrowStart," ",arrowEnd);
}
/***************** finally, draw some edges **************************/
outStr="";
if (point[arrowStart]=="s*")
outStr+=point[arrowStart] + " ";
if (point[arrowEnd]=="e*")
outStr+=point[arrowEnd] + " ";
outStr+=" ";
if ($.edgeType=="straight") { // straight line
// 4 points (after any arrowheads)
// CHANGE to loop through X[] & Y[] values ??
outStr+=(string)newX[1] +"," + (string)newY[1] + " ";
outStr+=(string)newX[2] +"," + (string)newY[2] + " ";
outStr+=(string)newX[3] +"," + (string)newY[3] + " ";
outStr+=(string)newX[4] +"," + (string)newY[4] + " ";
print("// straight outStr >", outStr, "<");
$.pos=outStr;
} else if ($.edgeType=="(ortho2|ortho3)") { // ortho* layout
print("// ORTHO2 or ORTHO3");
// 1st point (after arrowheads)
outStr+=(string)newX[1] +"," + (string)newY[1] + " ";
// add rest of points (3 points) of each line segment
for (newX[i]) {
print("// ORTHO2/3 ", i);
if (i+1 in newX) {
print("// ORTHO2/3 ", i, " ", i+1);
outStr+=lineSegment3Points(newX[i],newY[i], newX[i+1], newY[i+1]);
outStr+=" ";
}
}
/***************************************************************
// add 3 points of 2nd line segment
outStr+=lineSegment3Points(newX[2], newY[2], newX[3], newY[3]);
outStr+=" ";
// add 3 points of 3rd (last) line segment
outStr+=lineSegment3Points(newX[3], newY[3], newX[4], newY[4]);
***********************************************************/
print("// B outStr >", outStr, "<");
$.pos=outStr;
} else if ($.edgeType=="curved") {
print("// CURVED");
// arrowheads first (duped from ortho3, clean it up)
print("// Ac outStr >", outStr, "<");
// loop through X[] & Y[] values
outStr+=mkPoint(newX[1], newY[1]);
outStr+=mkPoint(newX[2], newY[2]);
outStr+=mkPoint(newX[3], newY[3]);
outStr+=mkPoint(newX[4], newY[4]);
print("// B outStr >", outStr, "<");
$.pos=outStr;
}
}
STopstOP
echo writing alter.d/alterTest1.gv
cat >alter.d/alterTest1.gv <<'STopstOP'
digraph S{
//rankdir=LR
edge [edgeType=ortho3 edgeOffset="24"]
subgraph clusterAAn { ///// NORTH
label="cw + 24pt"
{rank=sink
AA1n[height=2]
AA6n[height=2]
edge [dir=forward edgeDirection=cw penwidth=3 color=blue]
AA1n:n -> AA2n:n
AA3n:se -> AA4n:sw [xlabel=XLABEL1 edgeDirection=ccw]
AA5n:n -> AA6n:n
AA1n:n -> AA4n:n
AA1n:n -> AA6n:n [xlabel=XLABEL2]
}
}
subgraph clusterAAs { //// SOUTH
label="ccw - 24pt"
{rank=sink
AA1s[height=2]
AA6s[height=2]
edge [dir=forward edgeDirection=ccw style=dotted color=purple]
AA1s:s -> AA2s:s
AA3s:se -> AA4s:sw [label=LABEL1]
AA5s:s -> AA6s:s
AA1s:s -> AA4s:s [label=LABEL2]
AA1s:s -> AA6s:s
{edge[style=invis edgeType="" edgeDirection=""] AA1s->AA2s->AA3s->AA4s->AA5s->AA6s }
}
}
edge [edgeOffset="37"]
edge [dir=forward edgeDirection=cw style=dashed color=red ]
AA5n:n ->AA1s:s
AA1n -> AA5s
}
STopstOP
echo writing alter.d/alterTest2.gv
cat >alter.d/alterTest2.gv <<'STopstOP'
digraph S{
edge [edgeType=ortho3]
edge[ edgeOffset="33%"]
subgraph clusterBBn { //// NORTH
label="cw + 33%"
{rank=source
BB1n[height=2]
BB6n[height=2]
edge [dir=forward edgeDirection=cw style=bold color=cyan]
BB1n:n -> BB2n:n [color=green]
BB3n:se -> BB4n:sw
BB5n:n -> BB6n:n
BB1n:n -> BB4n:n [color=blue]
BB1n:n -> BB6n:n
{edge[style=invis edgeType="" edgeDirection=""] BB1n->BB2n->BB3n->BB4n->BB5n->BB6n }
}
}
subgraph clusterBBs { //// SOUTH
label="ccw + 33%"
{rank=source
BB1s[height=2]
BB6s[height=2]
edge [dir=forward edgeDirection=ccw penwidth=4 style=tapered color=red]
BB1s:s -> BB2s:s
BB3s:se -> BB4s:sw
BB5s:s -> BB6s:s
BB1s:s -> BB4s:s
BB1s:s -> BB6s:s [color=brown edgeOffset="77" ]
{edge[style=invis edgeType="" edgeDirection=""] BB1s->BB2s->BB3s->BB4s->BB5s->BB6s }
}
}
edge [edgeOffset="77"]
edge [dir=forward edgeDirection=cw style=dashed color=green ]
BB5n:n -> BB1s:s
BB1n -> BB5s
}
STopstOP
echo writing alter.d/alterTest20.gv
cat >alter.d/alterTest20.gv <<'STopstOP'
digraph S{
rankdir=LR
nodesep=1.0
edge [edgeType=ortho3]
node [shape=rect] //record]
A [shape=record label="{<p1>123|<p2>45 54|<p3>a e i o u}"]
CDE [shape=record label="<p1>C|<p2>D|<p3>E"]
edge [edgeDirection=cw edgeOffset="44"]
A:p1:n -> CDE:p2:n
"struct1" [ shape =record, label = "a|b|<p1>c" ];
"struct2" [ shape =record, label = "a|{<p1>b1|b2}|c" ];
struct1:p1 -> struct2:p1 [xlabel=XLABEL]
{ edge [edgeType=curved]
Ax [shape=record label="{<p1>123|<p2>45 54|<p3>a e i o u}"]
CDEx [shape=record label="<p1>C|<p2>D|<p3>E"]
edge [edgeDirection=ccw edgeOffset="44"]
Ax:p1 -> CDEx:p2
"struct1x" [ shape =record, label = "a|b|<p1>c" ];
"struct2x" [ shape =record, label = "a|{<p1>b1|b2}|c" ];
struct1x:p1 -> struct2x:p1 [label=LABEL]
}
a1:n -> a2:n [ edgeDirection=cw edgeOffset="24"]
a3:se -> a4:sw [ edgeDirection=ccw edgeOffset="24"]
a5:s -> a6:s [ edgeDirection=ccw edgeOffset="24"]
a7:s -> a8:s [ edgeDirection=ccw edgeOffset="24"]
edge [edgeType=curved]
SS1:n -> SS2:n [edgeDirection=cw edgeOffset="24" color=red]
SS3:se -> SS4:sw [dir=back edgeDirection=ccw edgeOffset="24"]
// 3 edges from same two nodes but different ports
SS5:e -> SS6:w [dir=both edgeDirection=ccw edgeOffset="24"]
SS5:se -> SS6:sw [dir=both edgeDirection=ccw edgeOffset="40"]
SS5:s -> SS6:s [dir=both edgeDirection=ccw edgeOffset="60"]
edge [edgeType=curved]
YY1:n -> YY2:n [ edgeDirection=cw edgeOffset="24"]
YY3:se -> YY4:sw [dir=back edgeDirection=ccw edgeOffset="24"]
// 3 edges from same two nodes and same ports
YY5:s -> YY6:s -> YY7:s [dir=both edgeDirection=ccw edgeOffset="24"]
YY5:s -> YY6:s [dir=both edgeDirection=ccw edgeOffset="34"]
edge [dir=both edgeDirection=ccw edgeOffset="64"]
YY5:s -> YY6:s -> YY7:s
YY7:s -> YY8:s [dir=both edgeDirection=ccw edgeOffset="24"]
YY2:n -> YY2:e [ edgeDirection=cw edgeOffset="34"]
YY2:e -> YY2:s [ edgeDirection=cw edgeOffset="34"]
YY2:s -> YY2:n [ edgeDirection=cw edgeOffset="64"]
SS4:e -> SS2:e [constraint=false edgeDirection=cw edgeOffset="44" color=green]
SS1:se -> SS4:nw [constraint=false edgeDirection=cw edgeOffset="24" color=yellow]
SS1:se -> SS4:nw [constraint=false edgeDirection=ccw edgeOffset="24" color=teal]
edge [edgeType=straight color=purple]
SS1:e -> SS2:nw
SS1:s -> SS3:ne
}
STopstOP
echo writing alter.d/alterTest21.gv
cat >alter.d/alterTest21.gv <<'STopstOP'
digraph S{
//rankdir=LR
nodesep=.6
edge [edgeType=ortho3 color=green]
subgraph clustera{
a1:c -> a2:n [ edgeDirection=ccw edgeOffset="24" tailclip=false]
a3:sw -> a4:sw [ edgeDirection=ccw edgeOffset="44"]
a5:c -> a6:c [ edgeDirection=cw edgeOffset="24" tailclip=false headclip=false]
a7:s -> a8:s [ edgeDirection=cw edgeOffset="54"]
a8:s -> a7:s [edgeType=curved edgeDirection=cw edgeOffset="24"]
a7:n -> a8:n [edgeType=curved edgeDirection=cw edgeOffset="24"]
}
subgraph clusterS{
{rank=min //source
edge [edgeType=curved]
SS1:n -> SS2:n [edgeDirection=cw edgeOffset="24" label=OKOK color=red]
SS3:se -> SS4:sw [dir=back edgeDirection=ccw edgeOffset="24"]
// 3 edges from same two nodes but different ports
SS5:e -> SS6:w [dir=both edgeDirection=ccw edgeOffset="24"]
SS5:se -> SS6:sw [dir=both edgeDirection=ccw edgeOffset="40" label=lmnop]
SS5:s -> SS6:s [dir=both edgeDirection=ccw edgeOffset="60"]
SS4:e -> SS2:e [constraint=false edgeDirection=cw edgeOffset="44" label=popcorn color=purple]
SS1:se -> SS4:nw [constraint=false edgeDirection=cw edgeOffset="24" color=green]
SS1:se -> SS4:nw [constraint=false edgeDirection=ccw edgeOffset="24" color=teal]
edge [edgeType=straight dir=forward style=dashed color=purple ]
SS1:se -> SS2:nw
SS1:s -> SS3:ne
}
}
subgraph clusterY{
{XXXrank=sink
edge [edgeType=curved penwidth=3 color=red]
YY1:n -> YY2:n [ edgeDirection=cw edgeOffset="24"]
YY3:c -> YY4:c [dir=back edgeDirection=ccw edgeOffset="24" tailclip=false headclip=false]
// 3 edges from same two nodes and same ports
YY5:s -> YY6:s [dir=both edgeDirection=ccw edgeOffset="34"]
edge [dir=both edgeDirection=ccw edgeOffset="64"]
YY5:w -> YY6:w -> YY7:w
YY7:e -> YY8:e [dir=both edgeDirection=cw edgeOffset="24"]
YY2:n -> YY2:e [ edgeDirection=cw edgeOffset="34" color=red]
YY2:e -> YY2:s [ edgeDirection=cw edgeOffset="34" style=dotted]
YY2:s -> YY2:n [ edgeDirection=cw edgeOffset="64" color=blue]
}
}
SS5 -> a7 [edgeType=""]
a4 -> YY5 [edgeType=""]
}
STopstOP
echo writing alter.d/alterTest22.gv
cat >alter.d/alterTest22.gv <<'STopstOP'
digraph S{
rankdir=LR
nodesep=1.0
edge [edgeType=curved ]
node [shape=record]
A [shape=record label="{<p1>123|<p2>45 54|<p3>a e i o u}"]
CDE [shape=record label="<p1>C|<p2>D|<p3>E"]
A:p1:n -> CDE:p2
A:p2:c -> CDE:p2
A:p3:s -> CDE:p2 [edgeDirection=ccw]
struct1 [ shape =record, label = "<p1>a|<p2>b|<p3>c" ];
struct2 [ shape =record, label = "a|{<p1>b1|b2}|c" ];
struct1:p1:n -> struct2:p1
struct1:p1:n -> struct2:p1 [edgeDirection=ccw]
edge[edgeDirection=ccw]
struct1:p1:w -> struct1:p2:w
struct1:p2:w -> struct1:p3:w
struct1:p1:w -> struct1:p3:w [edgeOffset="54"]
///////////////////////////////////////////////////////////////////
edge [edgeType=ortho3 edgeDirection=cw]
A1 [shape=record label="{<p1>123|<p2>45 54|<p3>a e i o u}"]
B1 [shape=record label="{<p1>C|<p2>D|<p3>E}"]
A1:p1:n -> B1:p2:n
A1:p2:n -> B1:p2:n
A1:p3:s -> B1:p2:s [edgeDirection=ccw]
S1 [ shape =record, label = "<p1>a|<p2>b|<p3>c" ];
S2 [ shape =record, label = "<p0>a|{<p1>b1|b2}|c" ];
S1:p1:n -> S2:p0:n
S1:p1:n -> S2:p0:n [edgeType=curved]
edge[edgeDirection=ccw]
S1:p1:w -> S1:p2:w
S1:p2:w -> S1:p3:w
// old struct node
edge[edgeDirection=ccw]
struct1:p1:w -> struct1:p2:w
struct1:p2:w -> struct1:p3:w
node [shape=rect]
edge [edgeType=straight color=green style=dashed]
{ rank=same
r:s -> s [dir=both]
r:s -> t [dir=back]
r:s -> u [dir=none]
r:s -> v [dir=forward]
}
t:e -> E [dir=both]
t:e -> F [dir=back]
t:e -> G [dir=none]
t:e -> H [dir=forward]
}
STopstOP
echo writing alter.d/alterTest3.gv
cat >alter.d/alterTest3.gv <<'STopstOP'
digraph S {
rankdir=LR
subgraph clusterAAn { ///// WEST
label="cw + 38pt"
edge [edgeType=ortho3 edgeOffset="38" color=purple style=bold]
edge [dir=forward edgeDirection=cw ]
{rank=same
AA1w[height=2]
AA6w[height=2]
AA1w:w -> AA2w:w [label=a301]
AA3w:sw -> AA4w:sw
AA5w:w -> AA6w:w [label=a302]
}
}
subgraph clusterAAe { //// EAST
label="ccw - 38pt"
{rank=same
AA1e[height=2]
AA6e[height=2]
edge [edgeType=ortho3 edgeOffset="38" color=green style=bold]
edge [dir=forward edgeDirection=ccw penwidth=5 style=tapered]
AA1e:e -> AA2e:e [label=bb3aa]
AA3e:ne -> AA4e:e
AA5e:e -> AA6e:e [label=b3bb]
AA1e:e -> AA4e:e
AA1e:e -> AA6e:e [label=b3cc]
}
}
AA5w -> AA5e [style=invis]
}
STopstOP
echo writing alter.d/alterTest32.gv
cat >alter.d/alterTest32.gv <<'STopstOP'
digraph S{
ranksep=1.1
nodesep=1.1
subgraph cluster1 { //// counter clockwise
label="clock-wise"
{rank=same
a1 [group=1] a2 [group=2] a3 [group=3]
a1 -> a2 -> a3 -> a4 -> a5 -> a6 [style=invis]
}
{rank=same
b1 [group=1] b2 [group=2] b3 [group=3]
b1 -> b2 -> b3 -> b4 -> b5 -> b6[style=invis]
}
{rank=same
c1 [group=1] c2 [group=2] c3 [group=3] c4 [group=4] c5 [group=5]
c1 -> c2 -> c3 -> c4 -> c5 -> c6 [style=invis]
}
{rank=same
d1 [group=1] d2 [group=2] d3 [group=3]
d1 -> d2 -> d3 -> d4 -> d5 -> d6 [style=invis]
}
{rank=same
e1 [group=1] e2 [group=2] e3 [group=3]
e1 -> e2 -> e3 -> e4 -> e5 -> e6 [style=invis]
}
{rank=same
f1 [group=1] f2 [group=2] f3 [group=3]
f1 -> f2 -> f3 -> f4 -> f5 -> f6 [style=invis]
}
a1 ->b1->c1->d1->e1->f1 [style=invis]
a2 ->b2->c2->d2->e2->f2 [style=invis]
a3 ->b3->c3->d3->e3->f3 [style=invis]
a4 ->b4->c4->d4->e4->f4 [style=invis]
a5 ->b5->c5->d5->e5->f5 [style=invis]
a6 ->b6->c6->d6->e6->f6 [style=invis]
edge [edgeType=ortho2]
edge [dir=forward edgeDirection=cw style=bold color=cyan]
edge [dir=both arrowtail=diamond arrowhead=normal] // temporary ???
a1 -> b2 [label="\E" color=green]
c2 -> d3 [dir=both arrowtail=dot color=red]
//edge[dir=back]
d3 -> a1 [color=blue]
b2 -> a3 [color=cyan]
b2 -> a1
b4 -> a5 [color=blue]
a5 -> b4 [color=lime]
c5->b3
c4->d3
c1->b2 [dir=both arrowtail=diamond color=red]
c4->d5
a5->b6
d1 -> e2 [color=blue dir=none]
e2 -> d1 [color=lime dir=none]
f3 -> e4 [color=brown dir=none]
e4 -> f3 [color=orange dir=none]
}
}
STopstOP
echo writing alter.d/alterTest33.gv
cat >alter.d/alterTest33.gv <<'STopstOP'
digraph S{
ranksep=1.1
nodesep=1.1
subgraph cluster1 { //// counter clockwise
label="counter clock wise"
{rank=same
a1 [group=1] a2 [group=2] a3 [group=3]
a1 -> a2 -> a3 -> a4 -> a5 -> a6 [style=invis]
}
{rank=same
b1 [group=1] b2 [group=2] b3 [group=3]
b1 -> b2 -> b3 -> b4 -> b5 -> b6[style=invis]
}
{rank=same
c1 [group=1] c2 [group=2] c3 [group=3] c4 [group=4] c5 [group=5]
c1 -> c2 -> c3 -> c4 -> c5 -> c6 [style=invis]
}
{rank=same
d1 [group=1] d2 [group=2] d3 [group=3]
d1 -> d2 -> d3 -> d4 -> d5 -> d6 [style=invis]
}
{rank=same
e1 [group=1] e2 [group=2] e3 [group=3]
e1 -> e2 -> e3 -> e4 -> e5 -> e6 [style=invis]
}
{rank=same
f1 [group=1] f2 [group=2] f3 [group=3]
f1 -> f2 -> f3 -> f4 -> f5 -> f6 [style=invis]
}
a1 ->b1->c1->d1->e1->f1 [style=invis]
a2 ->b2->c2->d2->e2->f2 [style=invis]
a3 ->b3->c3->d3->e3->f3 [style=invis]
a4 ->b4->c4->d4->e4->f4 [style=invis]
a5 ->b5->c5->d5->e5->f5 [style=invis]
a6 ->b6->c6->d6->e6->f6 [style=invis]
edge [edgeType=ortho2]
edge [dir=forward edgeDirection=ccw edgeOffset=99]
edge [style=bold color=cyan]
edge [dir=both arrowtail=diamond arrowhead=normal] // temporary ???
a1 -> b2 [label="\E" color=green]
c2 -> d3 [dir=both arrowtail=dot color=red]
//edge[dir=back]
d3 -> a1 [color=blue]
b2 -> a3 [color=cyan]
b2 -> a1
b4 -> a5 [color=blue]
a5 -> b4 [color=lime]
c5->b3
c4->d3
c1->b2 [dir=both arrowtail=diamond color=red]
c4->d5
a5->b6
d1 -> e2 [color=blue dir=none]
e2 -> d1 [color=lime dir=none]
f3 -> e4 [color=brown dir=none]
e4 -> f3 [color=orange dir=none]
}
}
STopstOP
echo writing alter.d/alterTest35.gv
cat >alter.d/alterTest35.gv <<'STopstOP'
digraph S{
ranksep=1.1
nodesep=1.1
subgraph cluster1 { //// counter clockwise
label="ortho3 clock-wise"
{rank=same
a1 [group=1] a2 [group=2] a3 [group=3]
a1 -> a2 -> a3 -> a4 -> a5 -> a6 [style=invis]
}
{rank=same
b1 [group=1] b2 [group=2] b3 [group=3]
b1 -> b2 -> b3 -> b4 -> b5 -> b6[style=invis]
}
{rank=same
c1 [group=1] c2 [group=2] c3 [group=3] c4 [group=4] c5 [group=5]
c1 -> c2 -> c3 -> c4 -> c5 -> c6 [style=invis]
}
{rank=same
d1 [group=1] d2 [group=2] d3 [group=3]
d1 -> d2 -> d3 -> d4 -> d5 -> d6 [style=invis]
}
{rank=same
e1 [group=1] e2 [group=2] e3 [group=3]
e1 -> e2 -> e3 -> e4 -> e5 -> e6 [style=invis]
}
{rank=same
f1 [group=1] f2 [group=2] f3 [group=3]
f1 -> f2 -> f3 -> f4 -> f5 -> f6 [style=invis]
}
a1 ->b1->c1->d1->e1->f1 [style=invis]
a2 ->b2->c2->d2->e2->f2 [style=invis]
a3 ->b3->c3->d3->e3->f3 [style=invis]
a4 ->b4->c4->d4->e4->f4 [style=invis]
a5 ->b5->c5->d5->e5->f5 [style=invis]
a6 ->b6->c6->d6->e6->f6 [style=invis]
edge [edgeType=ortho3]
edge [dir=forward edgeDirection=cw style=bold color=cyan]
edge [dir=both arrowtail=diamond arrowhead=normal] // temporary ???
a1 -> b1 [color=green]
c1 -> c2 [dir=both arrowtail=dot color=red]
//edge[dir=back]
b2 -> a3 [color=cyan]
b4 -> a5 [color=blue]
a5 -> b4 [color=lime]
c5->b3
c4->d3
c1->b2 [dir=both arrowtail=diamond color=red]
c4->d5
a5->b6
d1 -> e2 [color=blue dir=none]
e2 -> d1 [color=lime dir=none]
f3 -> e4 [color=brown dir=none]
e4 -> f3 [color=orange dir=none]
}
}
STopstOP
echo writing alter.d/alterTest36.gv
cat >alter.d/alterTest36.gv <<'STopstOP'
digraph S{
ranksep=1.1
nodesep=1.1
subgraph cluster1 { //// counter clockwise
label="ortho3 counter-clock-wise"
{rank=same
a1 [group=1] a2 [group=2] a3 [group=3]
a1 -> a2 -> a3 -> a4 -> a5 -> a6 [style=invis]
}
{rank=same
b1 [group=1] b2 [group=2] b3 [group=3]
b1 -> b2 -> b3 -> b4 -> b5 -> b6[style=invis]
}
{rank=same
c1 [group=1] c2 [group=2] c3 [group=3] c4 [group=4] c5 [group=5]
c1 -> c2 -> c3 -> c4 -> c5 -> c6 [style=invis]
}
{rank=same
d1 [group=1] d2 [group=2] d3 [group=3]
d1 -> d2 -> d3 -> d4 -> d5 -> d6 [style=invis]
}
{rank=same
e1 [group=1] e2 [group=2] e3 [group=3]
e1 -> e2 -> e3 -> e4 -> e5 -> e6 [style=invis]
}
{rank=same
f1 [group=1] f2 [group=2] f3 [group=3]
f1 -> f2 -> f3 -> f4 -> f5 -> f6 [style=invis]
}
a1 ->b1->c1->d1->e1->f1 [style=invis]
a2 ->b2->c2->d2->e2->f2 [style=invis]
a3 ->b3->c3->d3->e3->f3 [style=invis]
a4 ->b4->c4->d4->e4->f4 [style=invis]
a5 ->b5->c5->d5->e5->f5 [style=invis]
a6 ->b6->c6->d6->e6->f6 [style=invis]
edge [edgeType=ortho3 ]
edge [dir=forward edgeDirection=ccw edgeOffset=99]
edge [style=bold color=cyan]
edge [dir=both arrowtail=diamond arrowhead=normal] // temporary ???
a1 -> b1 [color=green]
c1 -> c2 [dir=both arrowtail=dot color=red]
//edge[dir=back]
b2 -> a3 [color=cyan]
b4 -> a5 [color=blue]
a5 -> b4 [color=lime]
c5->b3
c4->d3
c1->b2 [dir=both arrowtail=diamond color=red]
c4->d5
a5->b6
d1 -> e2 [color=blue dir=none]
e2 -> d1 [color=lime dir=none]
f3 -> e4 [color=brown dir=none]
e4 -> f3 [color=orange dir=none]
}
}
STopstOP
echo writing alter.d/alterTest4.gv
cat >alter.d/alterTest4.gv <<'STopstOP'
digraph S{
rankdir=LR
edge [edgeType=ortho3]
edge[ edgeOffset="45%"]
subgraph clusterBBn {
label="ccw + 45%"
{rank=source
BB1n[height=2]
BB6n[height=2]
edge [dir=forward edgeDirection=ccw ]
BB1n:n -> BB2n:n [label=a123]
BB3n:se -> BB4n:sw
BB5n:n -> BB6n:n
BB1n:n -> BB4n:n [label=a12]
BB1n:n -> BB6n:n [label=a13]
{edge[style=invis edgeType="" edgeDirection=""] BB1n->BB2n->BB3n->BB4n->BB5n->BB6n }
}
}
subgraph clusterBBs {
label="cw + 45%"
{rank=source
BB1s[height=2]
BB6s[height=2]
edge [dir=forward edgeDirection=cw color=red]
BB1s:s -> BB2s:s [label=a23]
BB3s:se -> BB4s:sw
BB5s:s -> BB6s:s [label=a2a3]
BB1s:s -> BB4s:s
BB1s:s -> BB6s:s [label=a333]
{edge[style=invis edgeType="" edgeDirection=""] BB1s->BB2s->BB3s->BB4s->BB5s->BB6s }
}
}
}
STopstOP
@steveroush
Copy link
Author

Modest code clean-up plus bug fixes.
alterTest21

@steveroush
Copy link
Author

Modest code clean-up, changed "ortho" to "ortho3" (edge consists of 3 line segments) and added "ortho2" (edge consists of 2 line segments)
alterTest33

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment