///////////////////////////////////////////////////////////////////////////////////////////////// // // // Wildtrack Project - Lowland Tapir // // // // Authors: // Amendments: Cross hair mod by JP + point 26 adjusted // // Name: Sky Date: Apr 10 Office: JMP Cary JMP Version: 11 // // 1) Embedded crosshair function into Wildtrack JSL to improve accuracy of landmark points // // 2) Improve the funcatioality of the "New Picture" button to speed up process of collecting // // landmark points from images // // 3) Calculate specific areas of the foot (using area of polygons): // // Area of polygon = 1/2 ( x1(y2 − yn) + xn(y1 − yn−1) + x2(y3 − y1) + x3(y4 − y2) + ...) // // 4) Increase font size // // 5) Add Explorer functionality for saving images and table for the buttons "Save As", // // "Save Table" and "New Picture" // // // ///////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////// // // // Instructions for Operation // // // // 1. Run this script. The result will be a window with buttons and an empty graph // // // // 2. Drag a rhino spoor picture into the graph. On the Mac, you can just drag in a // // jpeg file from the Finder. On Windows the only format that seems to work well // // is BMP, so you may have to convert the JPEG to BMP before you drag it in. // // The one application that holds a BMP picture that seems to drag well right // // into the JMP graphics frame is Microsoft Word. Others don't work so well, // // and the only thing that seems to work with those is to copy and paste into // // the area below the frame, then use the fat-plus cursor to select, then drag // // it into the frame. Soon we will provide a "Paste" right-click command in // // the Graphics frame to make this work. // // // // 3. If the graph is not the right size, then shift-drag from the corner to make // // it the right size. IMPORTANT: the graph must be square, which you can double-check // // by right-clicking in the graph but not on the picture and doing the Size/Scale // // submenu command 'FrameSize' and verifying the coordinates are the same for horiz // // and vert. // // // // 4. Click and Enter into the edit fields. Currently there are three edit fields, // // labeled: Rhino, Track, Location. // // // // 5. Click the landmark points in, in the order prompted by the message in the lower left. // // If you click a point by mistake, you can click 'Delete Last Point' and click again. // // Also, if the points do not line up perfectly, you can carefully click on a point and // // drag it to a better position. You may wish to drag it away to get a better look at the // // picture, then drag it back in. The messsage will say "Done" when all landmark points // // are in. // // // // 6. Click 'Derived Points'. Now all the derived points will be shown with red labels. // // If they don't look right, you can click "Clear Derived" to remove them, and refine // // the original landmark points by dragging them. Then click "Derived Points" again. // // // // 7. When you are happy with the points, now you can add them to a data table. // // If you don't already have the data table open, click 'Open' to open an old // // data table, or 'New' to start a new table. Then to add the new row, click // // the 'Append Row' button. // // // // 8. Periodically, click Save or use save in the File menu to make sure the new // // data makes it to disk. // // // // 9. For the next picture, click the 'New Picture' button to clear the landmarks, // // right-click in the picture and do the "Delete" command. Then go to step 2. // // // ///////////////////////////////////////////////////////////////////////////////////////////////// namesdefaulttohere(1); // Instruction Image //instructionImagePath = "C:\Users\JMP\Desktop\script images\am tiger footprint temp c.jpg"; instructionImagePath ="C:\Users\skyal\AppData\Local\SAS\JMP\Addins\com.sas.fitv1b\lowland tapir footprint b.jpg"; // Initial Point Set // xx and yy are the placed markers in the graph // xxd and yyd are the properly numbered points that include derived points // xxa and yya are after normalizing the data to centimeters getPictSize = function({pseg}, //Joseph ammend 14-01-15 /*{i=0,tmp,blob=chartoblob(pseg<xx[2]&yy[1]yy[2]),-1,1)*angl, 0 ) ); xx = []; yy = []; xxd = []; yyd = []; // xx=[144,138,362,686,314,666,232,350,608,736,238,670,354,448]; // yy=[682,214,676,636,586,514,546,490,442,452,368,314,146,170]; // Labels beside landmark points pointLabel = {"Scale1","Scale2", // rule "1","2","3","4","5" ,"6","7","8","9","10","11","12","13","14","15",// placed "D16","D17","D18","D19","D20","D21","D22"}; // derived numberOfLandmarksAndRules = 17; numberOfDerivedPoints = 7; LandmarkCircleColor = "white"; LandmarkTextColor = "white"; DerivedCircleColor = "yellow"; DerivedTextColor = "yellow"; // Labels for prompting promptLabel = {"on ruler ","on ruler ", "Landmark 1=Highest point of front toe ", "Landmark 2=Highest point of toe 4 ", "Landmark 3=Highest point of toe 2 ", "Landmark 4=Intersection of L2-5 with left edge of front toe ", "Landmark 5=Intersection of L2-5 with right edge of front toe ", "Landmark 6=Most lateral point of left toe ", "Landmark 7=Most lateral point of right toe ", "Landmark 8=Intersection of L6-7 with left edge of front toe ", "Landmark 9=Intersection of L6-7 with right edge of front toe ", "Landmark 10=Most medial point of left toe ", "Landmark 11=Most medial point of right toe ", "Landmark 12=Lowest point of left toe ", "Landmark 13=Lowest point of right toe ", "Landmark 14=Lowest point of heel ", "Landmark 15=Centre point of heel ", "","","","","","","","","","","","","","","" }; nLabel = nItems(pointLabel); scaleFactor = 10; depth = 0; // Normalization of Data CalcNormalize = expr( np = nrow(xx); //--rescale to centimeters, distance between 1 and 2 is 10 cm scale = scaleFactor/sqrt((yy[2]-yy[1])^2+(xx[2]-xx[1])^2); xxa = xxd*scale; yya = yyd*scale; //--center on 32nd point xxa = xxa-xxa[19]; yya = yya-yya[19]; ); // function to calculate the intersection of two lines // see http://astronomy.swin.edu.au/~pbourke/geometry/lineline2d/ CalcIntersection = function({p1x,p1y,p2x,p2y,p3x,p3y,p4x,p4y}, tempDenom= (p4y-p3y)*(p2x-p1x)-(p4x-p3x)*(p2y-p1y); tempNumerA = (p4x-p3x)*(p1y-p3y)-(p4y-p3y)*(p1x-p3x); tempNumerB = (p2x-p1x)*(p1y-p3y)-(p2y-p1y)*(p1x-p3x); result = if (tempDenom==0, {0,0}, uA = tempNumerA / tempDenom; uB = tempNumerB / tempDenom; evalList({ p1x+uA*(p2x-p1x), p1y+uA*(p2y-p1y)})); ); // test: CalcIntersection(1,0,0,1,0,0,1,1); should be {.5,.5} // function to calculate distance between two points calcDist = function({x1,y1,x2,y2}, sqrt((x2-x1)^2+(y2-y1)^2); ); // function to calculate the angle between three points CalcAngle = function({x1,y1,x2,y2,x3,y3}, L12 = calcDist(x1,y1,x2,y2); L13 = calcDist(x1,y1,x3,y3); L23 = calcDist(x2,y2,x3,y3); abs(arcCosine((L12^2+L23^2-L13^2)/(2*L12*L23)))*360/(2*pi()); ); // test: CalcAngle(0,0,1,0,0,1); // should be 45 degrees CalcAngleIntersection = function({p1x,p1y,p2x,p2y,p3x,p3y,p4x,p4y}, {tx0,ty0} = CalcIntersection(p1x,p1y,p2x,p2y,p3x,p3y,p4x,p4y); CalcAngle(p1x,p1y,tx0,ty0,p4x,p4y); ); // The data on the graph is in xx and yy // Here we reorganize those points into the numbered points, // deriving new points into the vectors xxd and yyd DerivePoints = expr( // Adjust for depth, if necessary if (depth > 0.0, depthFactor = (19.469172 + 0.7021119 * depth) / 20; // Don't adjust first two points xx1 = xx[1]; yy1 = yy[1]; xx2 = xx[2]; yy2 = yy[2]; xx -= 500; yy -= 500; xx *= depthFactor; yy *= depthFactor; xx += 500; yy += 500; xx[1] = xx1; yy[1] = yy1; xx[2] = xx2; yy[2] = yy2; ); nrx = nrow(xx); if (nrow(xx)<15 | nrow(yy)<15,print("NEED MORE POINTS",nrow(xx),nrow(yy))); xxx = xx[3::nrow(xx),0]; yyy = yy[3::nrow(yy),0]; xxd = j(22,1,0); xxd[1] = xxx[1]; xxd[2] = xxx[2]; xxd[3] = xxx[3]; xxd[4] = xxx[4]; xxd[5] = xxx[5]; xxd[6] = xxx[6]; xxd[7] = xxx[7]; xxd[8] = xxx[8]; xxd[9] = xxx[9]; xxd[10] = xxx[10]; xxd[11] = xxx[11]; xxd[12] = xxx[12]; xxd[13] = xxx[13]; xxd[14] = xxx[14]; xxd[15] = xxx[15]; yyd = j(22,1,0); yyd[1] = yyy[1]; yyd[2] = yyy[2]; yyd[3] = yyy[3]; yyd[4] = yyy[4]; yyd[5] = yyy[5]; yyd[6] = yyy[6]; yyd[7] = yyy[7]; yyd[8] = yyy[8]; yyd[9] = yyy[9]; yyd[10] = yyy[10]; yyd[11] = yyy[11]; yyd[12] = yyy[12]; yyd[13] = yyy[13]; yyd[14] = yyy[14]; yyd[15] = yyy[15]; temp = (yyd[2]-yyd[ 3])/(xxd[2]-xxd[ 3]); xTemp = xxd[1] + 1; yTemp = yyd[1] + 1*temp; {xxd[16],yyd[16]} = CalcIntersection(xxd[ 1],yyd[ 1],xTemp ,yTemp ,xxd[15],yyd[15],xxd[ 2],yyd[ 2]); temp = (yyd[2]-yyd[ 3])/(xxd[2]-xxd[ 3]); xTemp = xxd[1] + 1; yTemp = yyd[1] + 1*temp; {xxd[17],yyd[17]} = CalcIntersection(xxd[1],yyd[1],xTemp ,yTemp ,xxd[15],yyd[15],xxd[3],yyd[3]); {xxd[18],yyd[18]} = CalcIntersection(xxd[ 2],yyd[ 2],xxd[ 3],yyd[ 3],xxd[15],yyd[15],xxd[ 1],yyd[ 1]); {xxd[19],yyd[19]} = CalcIntersection(xxd[10],yyd[10],xxd[11],yyd[11],xxd[15],yyd[15],xxd[ 1],yyd[ 1]); {xxd[20],yyd[20]} = CalcIntersection(xxd[12],yyd[12],xxd[10],yyd[10],xxd[15],yyd[15],xxd[ 2],yyd[ 2]); {xxd[21],yyd[21]} = CalcIntersection(xxd[13],yyd[13],xxd[11],yyd[11],xxd[15],yyd[15],xxd[ 3],yyd[ 3]); {xxd[22],yyd[22]} = CalcIntersection(xxd[12],yyd[12],xxd[13],yyd[13],xxd[15],yyd[15],xxd[ 1],yyd[ 1]); ); // Here are all the numeric column names for the output data table colList = { "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "X10", "X11", "X12", "X13", "X14", "X15", "X16", "X17", "X18", "X19", "X20", "X21", "X22", "Y1", "Y2", "Y3", "Y4", "Y5", "Y6", "Y7", "Y8", "Y9", "Y10", "Y11", "Y12", "Y13", "Y14", "Y15", "Y16", "Y17", "Y18", "Y19", "Y20", "Y21", "Y22", "V1" , "V2" , "V3" , "V4" , "V5" , "V6" , "V7" , "V8" , "V9" , "V10", "V11", "V12", "V13", "V14", "V15", "V16", "V17", "V18", "V19", "V20", "V21", "V22", "V23", "V24", "V25", "V26", "V27", "V28", "V29", "V30", "V31", "V32", "V33", "V34", "V35", "V36", "V37", "V38", "V39", "V40", "V41", "V42", "V43", "V44", "V45", "V46", "V47", "V48", "V49", "V50", "V51", "V52", "V53", "V54", "V55", "V56", "V57", "V58", "V59", "V60", "V61", "V62", "V63", "V64", "V65", "V66", "V67", "V68", "V69", "V70", "V71", "V72", "V73", "V74", "V75", "V76", "V77","V78", "V79","V80", "V81", "V82", "V83", "V84", "V85", "V86", "V87", "V88", "V89", "V90","V91", "Area1","Area2","Area3","Area4","Area5","Area6" }; // add all the column names to the output table addAllColumns = expr( idCol = dtD< 1000 |xPos < 0 |yPos > 1000 |yPos < 0, xPos = 500; yPos = 500); ); savepic=EXPR( selectedDir = PickDirectory(); result = dialog(vList("Enter Path",pathName=EditText(selectedDir||"track1.jpg",width(400)),Button("OK"))); path = result["pathName"]; wind[FrameBox(1)]<