/*
	This heading must remain intact at all times.
	Copyright (c) 2010 Mark Mason.

	File:	Q-Cogo-Cogo.js
	Use:	To provide coordinate geometry operations for Q-Cogo, <http://www.q-cogo.com/>.
	Ver:	1.2 (Beta)

	Created by Mark Mason. Latest version available from <http://www.q-cogo.com/>.



	This file is part of Q-Cogo.
	
	Q-Cogo is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.
	
	Q-Cogo is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with Q-Cogo.  If not, see <http://www.gnu.org/licenses/>.
*/

function Solver(){var T=qG('SolverTitle');if(T.innerHTML=='Triangle')SolveTriangle();else if(T.innerHTML=='Curve')SolveCurve();}
function SolveTriangle(){var A=qG('SolverA').value,B=qG('SolverB').value;var C=qG('SolverC').value,a=qG('Solveraa').value;var b=qG('Solverbb').value,c=qG('Solvercc').value;var valCheck=[A,B,C,a,b,c];var ValNames=['A','B','C','a','b','c'];var Side=0,Ang=0,Entered='';for(var v=0;v<6;v++){Ang=((valCheck[v]&&v<=2)?Ang+1:Ang);Side=((valCheck[v]&&v>2)?Side+1:Side);Entered+=((valCheck[v])?ValNames[v]+', ':'');}
Entered=Entered.substring(0,Entered.length-2);if(Side+Ang!=3){alert('Enter three values to solve triangle (leave remaining values blank)');return;}
if(Side==0){alert('Enter the length of at least one side');return;}
A=((A)?ParseDMS(A,1,0):0);B=((B)?ParseDMS(B,1,0):0);C=((C)?ParseDMS(C,1,0):0);a=((a)?ParseDecimal(a,1,1):0);b=((b)?ParseDecimal(b,1,1):0);c=((c)?ParseDecimal(c,1,1):0);if(A=='X'||B=='X'||C=='X'||a=='X'||b=='X'||c=='X')return
if(A+B+C>=Math.PI){alert('Angles must add to less than 180\u00B0!');return;}
if(A<0||B<0||C<0||a<0||b<0||c<0){alert('All values must be positive!');return;}
if(a&&b&&c){A=AngleCos(a,b,c);B=AngleCos(b,a,c);C=AngleCos(c,a,b);}
else if(a&&C&&b){c=SideCos(C,a,b);A=AngleCos(a,b,c);B=AngleCos(b,a,c);}
else if(b&&A&&c){a=SideCos(A,b,c);B=AngleCos(b,a,c);C=AngleCos(c,a,b);}
else if(c&&B&&a){b=SideCos(B,a,c);A=AngleCos(a,b,c);C=AngleCos(c,a,b);}
else if(a&&b&&A){B=AngleSin(A,b,a);C=Math.PI-A-B;c=SideSin(C,B,b);var a2=a,b2=b,A2=A,B2=Math.PI-AngleSin(A2,b2,a2),C2=Math.PI-A2-B2,c2=SideSin(C2,B2,b2);}
else if(a&&b&&B){A=AngleSin(B,a,b);C=Math.PI-A-B;c=SideSin(C,B,b);var a2=a,b2=b,B2=B,A2=Math.PI-AngleSin(B2,a2,b2),C2=Math.PI-A2-B2,c2=SideSin(C2,B2,b2);}
else if(b&&c&&B){C=AngleSin(B,c,b);A=Math.PI-B-C;a=SideSin(A,B,b);var b2=b,c2=c,B2=B,C2=Math.PI-AngleSin(B2,c2,b2),A2=Math.PI-B2-C2,a2=SideSin(A2,B2,b2);}
else if(b&&c&&C){B=AngleSin(C,b,c);A=Math.PI-B-C;a=SideSin(A,B,b);var b2=b,c2=c,C2=C,B2=Math.PI-AngleSin(C2,b2,c2),A2=Math.PI-B2-C2,a2=SideSin(A2,B2,b2);}
else if(c&&a&&C){A=AngleSin(C,a,c);B=Math.PI-A-C;b=SideSin(B,A,a);var c2=c,a2=a,C2=C,A2=Math.PI-AngleSin(C2,a2,c2),B2=Math.PI-A2-C2,b2=SideSin(B2,A2,a2);}
else if(c&&a&&A){C=AngleSin(A,c,a);B=Math.PI-A-C;b=SideSin(B,A,a);var c2=c,a2=a,A2=A,C2=Math.PI-AngleSin(A2,c2,a2),B2=Math.PI-A2-C2,b2=SideSin(B2,A2,a2);}
else if(A&&c&&B){C=Math.PI-A-B;a=SideSin(A,C,c);b=SideSin(B,C,c);}
else if(B&&a&&C){A=Math.PI-B-C;b=SideSin(B,A,a);c=SideSin(C,A,a);}
else if(C&&b&&A){B=Math.PI-A-C;c=SideSin(C,B,b);a=SideSin(A,B,b);}
else if(A&&B&&a){C=Math.PI-A-B;b=SideSin(B,A,a);c=SideSin(C,B,b);}
else if(A&&B&&b){C=Math.PI-A-B;a=SideSin(A,B,b);c=SideSin(C,B,b);}
else if(B&&C&&b){A=Math.PI-B-C;a=SideSin(A,B,b);c=SideSin(C,B,b);}
else if(B&&C&&c){A=Math.PI-B-C;a=SideSin(A,C,c);b=SideSin(B,C,c);}
else if(C&&A&&c){B=Math.PI-A-C;a=SideSin(A,C,c);b=SideSin(B,C,c);}
else if(C&&A&&a){B=Math.PI-A-C;b=SideSin(B,A,a);c=SideSin(C,B,b);}
var TriOK=1;var TL1=[a,b,c,A,B,C];for(var i=0;i<6;i++)TriOK=((typeof TL1[i]=="undefined"||isNaN(TL1[i])||TL1[i]<=0)?0:TriOK);if(!TriOK){alert('Impossible triangle!');return;}
var ADisp=FormatDMS(A+'',0),BDisp=FormatDMS(B+'',0),CDisp=FormatDMS(C+'',0);var aDisp=FormatDecimal(a+'',0,1),bDisp=FormatDecimal(b+'',0,1),cDisp=FormatDecimal(c+'',0,1);var ArDisp=FormatArea((c*Math.sin(B)*a/2)+'',1);var PtList=new Array(7);PtList[0]=['B',0,0,0,'B'];PtList[1]=['C',0,a,0,'C'];PtList[2]=['A',c*Math.sin(B),c*Math.cos(B),0,'A'];PtList[3]=['a',0,a/2,0,'a'];PtList[4]=['b',c*Math.sin(B)/2,(c*Math.cos(B)+a)/2,0,'b'];PtList[5]=['c',c*Math.sin(B)/2,c*Math.cos(B)/2,0,'c'];PtList[6]=[0];var TwoSols=1,AreSame=0;var TL2=[a2,b2,c2,A2,B2,C2];var Results2='',TwoText='';for(var i=0;i<6;i++){TwoSols=((typeof TL2[i]=="undefined"||isNaN(TL2[i])||TL2[i]<=0)?0:TwoSols);AreSame+=((i<=2&&Round(Math.abs(TL2[i]-TL1[i]),parseInt(qG('DPrecision').value))==0)?1:0);}
if(TwoSols&&AreSame<3){var A2Disp=FormatDMS(A2+'',0),B2Disp=FormatDMS(B2+'',0),C2Disp=FormatDMS(C2+'',0);var a2Disp=FormatDecimal(a2+'',0,1),b2Disp=FormatDecimal(b2+'',0,1),c2Disp=FormatDecimal(c2+'',0,1);var Ar2Disp=FormatArea((c2*Math.sin(B2)*a2/2)+'',1);PtList[6]=['B',0,1.3*a,0,'B'];PtList[7]=['C',0,1.3*a+a2,0,'C'];PtList[8]=['A',c2*Math.sin(B2),1.3*a+c2*Math.cos(B2),0,'A'];PtList[9]=['a',0,1.3*a+a2/2,0,'a'];PtList[10]=['b',c2*Math.sin(B2)/2,1.3*a+(c2*Math.cos(B2)+a2)/2,0,'b'];PtList[11]=['c',c2*Math.sin(B2)/2,1.3*a+c2*Math.cos(B2)/2,0,'c'];PtList[12]=[0];Results2+='\n       A:        '+A2Disp+'       a: '+a2Disp+'\n';Results2+='       B:        '+B2Disp+'       b: '+b2Disp+'\n';Results2+='       C:        '+C2Disp+'       c: '+c2Disp+'\n';Results2+='       Area: '+Ar2Disp+'\n';TwoText='- Two Solutions ';}
qG('SolverCanvasSt').value='SketchTriangle('+JsonMat(PtList,2)+', \'PointsCanvas\')';ZoomSketch(0,0,0);SketchTriangle(PtList,'PointsCanvas');var Results='Triangle '+TwoText+'(Entered '+Entered+'):\n';Results+='\n       A:        '+ADisp+'       a: '+aDisp+'\n';Results+='       B:        '+BDisp+'       b: '+bDisp+'\n';Results+='       C:        '+CDisp+'       c: '+cDisp+'\n';Results+='       Area: '+ArDisp+'\n';Results+=Results2;OutputCogo(Results,'SolverLog');}
function SideCos(A,b,c){return Math.sqrt(Math.pow(b,2)+Math.pow(c,2)-2*b*c*Math.cos(A));}
function AngleCos(a,b,c){return Math.acos((Math.pow(b,2)+Math.pow(c,2)-Math.pow(a,2))/(2*b*c));}
function SideSin(A,B,b){return b*Math.sin(A)/Math.sin(B);}
function AngleSin(B,a,b){return Math.asin(a*Math.sin(B)/b);}
function SolveCurve(){var R=qG('SolverRad').value,D=qG('SolverDelta').value;var T=qG('SolverTang').value,L=qG('SolverLen').value;var C=qG('SolverChord').value;var valCheck=[R,T,L,C],vals=['Radius','Tangent','Length','Chord'],NoEntered=0;for(var i=0;i<valCheck.length;i++){if(valCheck[i]){NoEntered++;var Entered=vals[i];}}
if(!D||NoEntered!=1){alert('Enter Delta and one other value (leave remaining values blank)');return;}
D=ParseDMS(D,1,0);R=((R)?ParseDecimal(R,1,1):0);T=((T)?ParseDecimal(T,1,1):0);L=((L)?ParseDecimal(L,1,1):0);C=((C)?ParseDecimal(C,1,1):0);if(R=='X'||D=='X'||T=='X'||L=='X'||C=='X')return;if(R<0||D<0||T<0||L<0||C<0){alert('All values must be positive!');return;}
if(D>=2*Math.PI||D<=0){alert('Delta must be between 0 and 360\u00B0!');return;}
if(R){T=R*Math.tan(D/2);L=R*D;C=2*R*Math.sin(D/2);}
else if(T){R=T/Math.tan(D/2);L=R*D;C=2*R*Math.sin(D/2);}
else if(L){R=L/D;T=R*Math.tan(D/2);C=2*R*Math.sin(D/2);}
else if(C){R=C/(2*Math.sin(D/2));T=R*Math.tan(D/2);L=R*D;}
var M=R*(1-Math.cos(D/2)),E=R*(1/Math.cos(D/2)-1),Sec=Math.pow(R,2)*D/2,Seg=Math.pow(R,2)*(D-Math.sin(D))/2;var CrvOK=1,Crv=[R,D,T,L,C,M];D=Math.abs(D);R=Math.abs(R);T=Math.abs(T);L=Math.abs(L);C=Math.abs(C);M=Math.abs(M);E=Math.abs(E);for(var i=0;i<6;i++)CrvOK=((typeof Crv[i]=="undefined"||isNaN(Crv[i])||Crv[i]==0)?0:CrvOK);if(!CrvOK){alert('Impossible curve!');return;}
var RDisp=FormatDecimal(R+'',0,1),DDisp=FormatDMS(D+'',0),TDisp=FormatDecimal(T+'',0,1);var LDisp=FormatDecimal(L+'',0,1),CDisp=FormatDecimal(C+'',0,1),MDisp=FormatDecimal(M+'',0,1);var EDisp=FormatDecimal(E+'',0,1),SecDisp=FormatArea(Sec+'',1),SegDisp=FormatArea(Seg+'',1);if(Round(D,7)==Round(Math.PI,7)){TDisp='       N/A';EDisp='       N/A';for(var i=0;i<qG('DPrecision').value-1;i++){TDisp+=' ';EDisp+=' ';}}
var PtList=new Array(11);PtList[0]=['D',0,0,0,'D'];PtList[1]=['BC',R*Math.cos(-1*D/2),R*Math.sin(-1*D/2),0,'BC'];PtList[2]=['EC',R*Math.cos(D/2),R*Math.sin(D/2),0,'EC'];var tBrg1=((D<Math.PI)?Math.PI/2-D/2:3*Math.PI/2-D/2);var tBrg2=((D<Math.PI)?D/2-Math.PI/2:D/2-3*Math.PI/2);PtList[3]=['PI',T*Math.cos(tBrg1)+PtList[1][1],T*Math.sin(tBrg1)+PtList[1][2],0,'PI'];PtList[4]=['C',PtList[1][1],PtList[1][2]+C/2,0,'C'];PtList[5]=['L',R,0,0,'L'];PtList[6]=['T',T/2*Math.cos(tBrg1)+PtList[1][1],T/2*Math.sin(tBrg1)+PtList[1][2],0,'T'];PtList[7]=['T',T/2*Math.cos(tBrg2)+PtList[2][1],T/2*Math.sin(tBrg2)+PtList[2][2],0,'T'];PtList[8]=['R',R/2*Math.cos(-1*D/2),R/2*Math.sin(-1*D/2),0,'R'];PtList[9]=['R',R/2*Math.cos(D/2),R/2*Math.sin(D/2),0,'R'];PtList[10]=[0];qG('SolverCanvasSt').value='SketchCurve('+JsonMat(PtList,2)+', \'PointsCanvas\')';ZoomSketch(0,0,0);SketchCurve(PtList,'PointsCanvas');var Results='Curve (Entered Delta and '+Entered+'):\n';Results+='\n       Radius:  '+RDisp+'       Delta:       '+DDisp+'\n';Results+='       Tangent: '+TDisp+'       Length:  '+LDisp+'\n';Results+='       Chord:   '+CDisp+'\n';Results+='       Mid-Ord: '+MDisp+'       Sector:  '+SecDisp+'\n';Results+='       Ext:     '+EDisp+'       Segment: '+SegDisp+'\n';OutputCogo(Results,'SolverLog');}
function Area(){var PtList=qG('AreaPts').value;if(!CheckBlank(PtList,' list of points bounding the area'))return;if(!(PtList=GetPointList(PtList,1,1)))return;if(PtList.length<3){alert('Enter at least three points bounding the area');return;}
PtList[PtList.length]=PtList[0];var Total=0,intAng=-2,intTest=0,radChk=0;for(var i=0;i<PtList.length-1;i++){if(PtList[i][0].search(/\*/)>=0&&PtList[i+1][0].search(/\*/)>=0){radChk=1;break;}}
if((PtList[0][0].search(/\*/)>=0&&PtList[PtList.length-2][0].search(/\*/)>=0)||radChk){alert('Radial points must be separated by at least one non-radial point');return;}
for(i=0;i<PtList.length-1;i++){var indexM=((i==0)?PtList.length-2:i-1);if(PtList[i][0].search(/\*/)>=0){var radC=Math.abs(PtPtInverse(0,PtList[i][0].replace(/\*/g,''),PtList[i+1][0])[0]-PtPtInverse(0,PtList[i][0].replace(/\*/g,''),PtList[indexM][0])[0]);if(Round(radC,parseInt(qG('DPrecision').value))>Math.pow(10,-1*parseInt(qG('DPrecision').value))){alert('Distances from radial point "'+PtList[i][0].replace(/\*/g,'')+'" to BC and EC are unequal!');return;}}
else{var indexP=i+1;indexP=((PtList[indexP][0].search(/\*/)>=0)?indexP+1:indexP);indexP=((indexP>PtList.length-1)?1:indexP);Total+=parseFloat(PtList[i][1])*parseFloat(PtList[indexP][2]);Total-=parseFloat(PtList[indexP][1])*parseFloat(PtList[i][2]);intAng+=1;indexM=((PtList[indexM][0].search(/\*/)>=0)?indexM-1:indexM);indexM=((indexM<0)?PtList.length-2:indexM);intTest+=(PtPtInverse(0,PtList[i][0],PtList[indexM][0])[2]-PtPtInverse(0,PtList[i][0],PtList[indexP][0])[2]+2*Math.PI)%(2*Math.PI);}}
Total=Math.abs(Total/2);var CW=((parseInt(intAng*Math.PI)!=parseInt(intTest))?-1:1);for(i=0;i<PtList.length-1;i++){if(PtList[i][0].search(/\*/)>=0){indexM=((i==0)?PtList.length-2:i-1);var R=PtPtInverse(0,PtList[i][0].replace(/\*/g,''),PtList[indexM][0])[0];var Theta=(PtPtInverse(0,PtList[i][0].replace(/\*/g,''),PtList[indexM][0])[2]-PtPtInverse(0,PtList[i][0].replace(/\*/g,''),PtList[i+1][0])[2]+2*Math.PI)%(2*Math.PI);Theta=((Theta>Math.PI)?2*Math.PI-Theta:Theta);var segArea=Math.pow(R,2.0)*(Theta-Math.sin(Theta))/2;var LR=PtLineInverse(0,PtList[i][0].replace(/\*/g,''),PtList[indexM][0],PtList[i+1][0])[0];LR=((LR.search(/right/i)>=0)?1:-1);segArea=((PtList[i][0].search(/\*/)==0)?Math.PI*Math.pow(R,2.0)-segArea:segArea);LR*=((PtList[i][0].search(/\*/)==0)?-1:1);Total+=CW*LR*segArea;}}
Total=Math.abs(Total);PtList.splice(PtList.length-1,1);qG('AreaCanvasSt').value='SketchArea('+JsonMat(PtList,2)+', \'PointsCanvas\')';ZoomSketch(0,0,0);SketchArea(PtList,'PointsCanvas');var PtString=FormatPtList(PtList,0);var Results='By Perimeter: '+PtString+'\n';Results+='\n       Area: '+FormatArea(Total+'',1)+'\n';OutputCogo(Results,'AreaLog');}
function Transform(){var PtList=qG('TransPts').value,AboutPt=qG('TransAbout').value;var SF=qG('TransSF').value,NShift=qG('TransN').value;var EShift=qG('TransE').value,ZShift=qG('TransZ').value;var Rot=qG('TransHA').value;if(!CheckBlank(PtList,' list of points to transform'))return;if(!SF&&!NShift&&!EShift&&!ZShift&&!Rot){alert('Enter at least one transformation parameter');return;}
if(!AboutPt&&(SF||Rot)){alert('Enter a point to transform about');return;}
AboutPt=FormatString(AboutPt,1,0);if(!(PtList=GetPointList(PtList,1,0))||!(AboutPt=GetPointList(AboutPt,0,0)))return;Rot=((Rot)?ParseDMS(Rot,1,0):0);NShift=((NShift)?ParseDecimal(NShift,1,1):0);EShift=((EShift)?ParseDecimal(EShift,1,1):0);ZShift=((ZShift)?ParseDecimal(ZShift,1,1):0);SF=((SF)?ParseDecimal(SF,1,0):0);if(SF=='X'||NShift=='X'||EShift=='X'||ZShift=='X'||Rot=='X')return;var Ymax=-1e15,Xmax=-1e15,Ymin=1e15,Xmin=1e15;for(var h=0;h<PtList.length;h++){if(parseFloat(PtList[h][1])>Ymax){Ymax=parseFloat(PtList[h][1]);}
if(parseFloat(PtList[h][1])<Ymin){Ymin=parseFloat(PtList[h][1]);}
if(parseFloat(PtList[h][2])>Xmax){Xmax=parseFloat(PtList[h][2]);}
if(parseFloat(PtList[h][2])<Xmin){Xmin=parseFloat(PtList[h][2]);}}
for(var g=0;g<2;g++){PtList[PtList.length]=['NW_Extents',Ymax,Xmin,0,'NW_Extents'];PtList[PtList.length]=['NE_Extents',Ymax,Xmax,0,'NE_Extents'];PtList[PtList.length]=['SW_Extents',Ymin,Xmin,0,'SW_Extents'];PtList[PtList.length]=['SE_Extents',Ymin,Xmax,0,'SE_Extents'];}
var dN=0;var dE=0;if(SF){for(var f=0;f<PtList.length-4;f++){dN=(parseFloat(PtList[f][1])-parseFloat(AboutPt[1]))*parseFloat(SF);dE=(parseFloat(PtList[f][2])-parseFloat(AboutPt[2]))*parseFloat(SF);PtList[f][1]=parseFloat(AboutPt[1])+dN;PtList[f][2]=parseFloat(AboutPt[2])+dE;}}
else SF='1';if(Rot){for(var d=0;d<PtList.length-4;d++){var DN1=parseFloat(PtList[d][1])-parseFloat(AboutPt[1]);var DE1=parseFloat(PtList[d][2])-parseFloat(AboutPt[2]);var DistAtoD=Math.sqrt(Math.pow(DN1,2)+Math.pow(DE1,2));var AzAtoD=Math.atan2(DE1,DN1);if(AzAtoD<0)AzAtoD=AzAtoD+2*Math.PI;AzAtoD+=Rot;dN=DistAtoD*Math.cos(AzAtoD);dE=DistAtoD*Math.sin(AzAtoD);PtList[d][1]=parseFloat(AboutPt[1])+dN;PtList[d][2]=parseFloat(AboutPt[2])+dE;}}
else Rot='0';if(NShift){for(var i=0;i<PtList.length-4;i++)PtList[i][1]=(parseFloat(PtList[i][1])+NShift)+'';}
else NShift='0';if(EShift){for(var j=0;j<PtList.length-4;j++)PtList[j][2]=(parseFloat(PtList[j][2])+EShift)+'';}
else EShift='0';if(ZShift){for(var k=0;k<PtList.length-4;k++)PtList[k][3]=(parseFloat(PtList[k][3])+ZShift)+'';}
else ZShift='0';var SFDisp=FormatDecimal(SF,1,0);var NShiftDisp=FormatDecimal(NShift,0,1);var EShiftDisp=FormatDecimal(EShift,0,1);var ZShiftDisp=FormatDecimal(ZShift,0,1);var RotDisp=FormatDMS(Rot,0);var Plural=((PtList.length>9)?'s':'');var Message=PtList.length-8+' point'+Plural+' will be edited!\n\n';Message+='     +N:  \t\t'+NShiftDisp.replace(/\s+/g,'')+'\n';Message+='     +E:  \t\t'+EShiftDisp.replace(/\s+/g,'')+'\n';Message+='     +Z:  \t\t'+ZShiftDisp.replace(/\s+/g,'')+'\n';Message+='     SF:  \t\t'+SFDisp.replace(/\s+/g,'')+'\n';Message+='     Rot:  \t\t'+RotDisp.replace(/\s+/g,'')+'\n\n';Message+='Edit point'+Plural+'?';check=confirm(Message);if(check==1){var ptMt=ParsePoints();for(var l=0;l<PtList.length;l++){for(var m=0;m<ptMt.length;m++){if(ptMt[m][0]==PtList[l][0]){ptMt[m]=PtList[l];}}}
lP=ptMt.length-2;OutputPoints(ptMt,lP);ClearSort();PtList[PtList.length]=[0];qG('TransformCanvasSt').value='SketchTransform('+JsonMat(PtList,2)+', \'PointsCanvas\')';ZoomSketch(0,0,0);SketchTransform(PtList,'PointsCanvas');PtList.splice(PtList.length-9,9);var PtString=FormatPtList(PtList,1);var Results='Transformed: '+PtString+'\n';if(AboutPt[0]){Results+='About:       '+AboutPt[0]+'\n';}
Results+='\n       +N:  '+NShiftDisp+'       SF:  '+SFDisp+'\n';Results+='       +E:  '+EShiftDisp+'       Rot:     '+RotDisp+'\n';Results+='       +Z:  '+ZShiftDisp+'\n';OutputCogo(Results,'TransformLog');}}
function Inverse(){var T=qG('InvType').innerHTML;if(T=='Point')PtPtInverse(1,0,0);else if(T=='Line')PtLineInverse(1,0,0,0);}
function PtLineInverse(Output,PtPt,StartPt,EndPt){if(!PtPt||!StartPt||!EndPt){PtPt=qG('InvPtPt').value;StartPt=qG('FromPt').value;EndPt=qG('ToPt').value;}
if(!CheckBlank(PtPt,' point to inverse from')||!CheckBlank(StartPt,' point at the start of line')||!CheckBlank(EndPt,' point at the end of line'))return;PtPt=FormatString(PtPt,1,0);StartPt=FormatString(StartPt,1,0);EndPt=FormatString(EndPt,1,0);if(!(PtPt=GetPointList(PtPt,0,0))||!(StartPt=GetPointList(StartPt,0,0))||!(EndPt=GetPointList(EndPt,0,0))||SamePoint(PtPt[0],StartPt[0],'From and start')||SamePoint(PtPt[0],EndPt[0],'From and end')||SamePoint(StartPt[0],EndPt[0],'Start and end')||SameCoords(PtPt,StartPt,'From and start')||SameCoords(PtPt,EndPt,'From and end')||SameCoords(StartPt,EndPt,'Start and end'))return;var Az1=PtPtInverse(0,StartPt[0],EndPt[0])[2],Az2=Az1+Math.PI/2;var Np=BrgBrg(0,0,StartPt,Az1,PtPt,Az2,'','')[0],Ep=BrgBrg(0,0,StartPt,Az1,PtPt,Az2,'','')[1];var Station=Math.sqrt(Math.pow(Np-StartPt[1],2)+Math.pow(Ep-StartPt[2],2));var Az4=Math.atan2(Ep-StartPt[2],Np-StartPt[1]);Az4=((Az4<0)?Az4+2*Math.PI:Az4);Station*=((Round(Az4,1)!=Round(Az1,1))?-1:1);var Zp=parseFloat(StartPt[3])+Station*(EndPt[3]-StartPt[3])/PtPtInverse(0,StartPt[0],EndPt[0])[0];var DN=Np-PtPt[1],DE=Ep-PtPt[2],DZ=Zp-PtPt[3];var HD=Math.sqrt(Math.pow(DN,2)+Math.pow(DE,2)),SD=Math.sqrt(Math.pow(HD,2)+Math.pow(DZ,2));var Az=Math.atan2(DE,DN);Az=((Az<0)?Az+2*Math.PI:Az);var AzDiff=(PtPtInverse(0,StartPt[0],PtPt[0])[2]-Az1+2*Math.PI)%(2*Math.PI);var LR=((AzDiff>0&&AzDiff<Math.PI)?'RIGHT of line':(AzDiff>Math.PI&&AzDiff<2*Math.PI)?'LEFT of line':'ON LINE');Az=((LR=='ON LINE')?0:Az);if(Output){var ptMt=new Array(5);ptMt[0]=StartPt;ptMt[1]=EndPt;ptMt[2]=PtPt;ptMt[3]=['Calc_Pt',Np,Ep,Zp,'Calc_Pt'];ptMt[4]=[0];var HD1=Math.sqrt(Math.pow(EndPt[1]-StartPt[1],2)+Math.pow(EndPt[2]-StartPt[2],2));var HD2=Math.sqrt(Math.pow(EndPt[1]-Np,2)+Math.pow(EndPt[2]-Ep,2));var MaxHD=Math.max(Station,HD1,HD2);var Line=((MaxHD==Station)?[0,3]:(MaxHD==HD1)?[0,1]:[1,3]);qG('InverseCanvasSt').value='SketchPtLine('+JsonMat(ptMt,2)+', \'PointsCanvas\','+JsonMat(Line,1)+')';ZoomSketch(0,0,0);SketchPtLine(ptMt,'PointsCanvas',Line);var StationDisp=FormatStn(Station+''),HDDisp=FormatDecimal(HD+'',0,1);var SDDisp=FormatDecimal(SD+'',0,1),dNDisp=FormatDecimal(DN+'',0,1);var dEDisp=FormatDecimal(DE+'',0,1),dZDisp=FormatDecimal(DZ+'',0,1);var AzDisp=FormatDMS(Az+'',0),GradeDisp=FormatGrade(DZ,HD);var Results=PtPt[0]+'('+PtPt[4]+') to Line '+StartPt[0]+'('+StartPt[4]+') --> '+EndPt[0]+'('+EndPt[4]+'): \n\n';Results+=LR+', Stn:  '+StationDisp+'\n\n';Results+='       HD: '+HDDisp+'       Az:     '+AzDisp+'\n';if(qG('InvDim').innerHTML=='3D')Results+='       SD: '+SDDisp+'       Grd: '+GradeDisp+'\n';Results+='       dN: '+dNDisp+'       dE: '+dEDisp+'\n';if(qG('InvDim').innerHTML=='3D')Results+='       dZ: '+dZDisp+'\n';OutputCogo(Results,'InverseLog');}
else return[LR,HD,SD,Az];}
function PtPtInverse(Output,FromPt,ToPt){if(!FromPt||!ToPt){FromPt=qG('FromPt').value;ToPt=qG('ToPt').value;}
if(!CheckBlank(FromPt,' point to inverse from')||!CheckBlank(ToPt,' point to inverse to'))return;if(typeof(FromPt)!='object'){FromPt=FormatString(FromPt,1,0);ToPt=FormatString(ToPt,1,0);if(!(FromPt=GetPointList(FromPt,0,0))||!(ToPt=GetPointList(ToPt,0,0))||(Output&&SamePoint(FromPt[0],ToPt[0],'From and to')))return;}
var DN=parseFloat(ToPt[1])-parseFloat(FromPt[1]),DE=parseFloat(ToPt[2])-parseFloat(FromPt[2]);var DZ=parseFloat(ToPt[3])-parseFloat(FromPt[3]);var HD=Math.sqrt(Math.pow(DN,2)+Math.pow(DE,2)),SD=Math.sqrt(Math.pow(HD,2)+Math.pow(DZ,2)),Az=Math.atan2(DE,DN);Az=((Az<0)?Az+2*Math.PI:Az);var HDDisp=FormatDecimal(HD+'',0,1),SDDisp=FormatDecimal(SD+'',0,1);var dNDisp=FormatDecimal(DN+'',0,1),dEDisp=FormatDecimal(DE+'',0,1);var dZDisp=FormatDecimal(DZ+'',0,1),AzDisp=FormatDMS(Az+'',0);var GradeDisp=FormatGrade(DZ,HD);if(Output){var ptMt=new Array(3);ptMt[0]=FromPt;ptMt[1]=ToPt;ptMt[2]=[0];qG('InverseCanvasSt').value='SketchPtPt('+JsonMat(ptMt,2)+', \'PointsCanvas\')';ZoomSketch(0,0,0);SketchPtPt(ptMt,'PointsCanvas');var Results=FromPt[0]+'('+FromPt[4]+') to '+ToPt[0]+'('+ToPt[4]+'): \n\n';Results+='       HD: '+HDDisp+'       Az:     '+AzDisp+'\n';if(qG('InvDim').innerHTML=='3D')Results+='       SD: '+SDDisp+'       Grd: '+GradeDisp+'\n';Results+='       dN: '+dNDisp+'       dE: '+dEDisp+'\n';if(qG('InvDim').innerHTML=='3D')Results+='       dZ: '+dZDisp+'\n';OutputCogo(Results,'InverseLog');}
else return[HD,SD,Az];}
function Intersect(Store){var FromPt=qG('IntFrom').value,ValueFrom=qG('IntValueFrom').value,ToPt=qG('IntTo').value;var ValueTo=qG('IntValueTo').value,Pt=qG('IntPt').value,Desc=qG('IntDesc').value;var Title=qG('IntTitle');if(!CheckBlank(FromPt,' point to intersect from')||!CheckBlank(ToPt,' point to intersect to'))return;FromPt=FormatString(FromPt,1,0);ToPt=FormatString(ToPt,1,0);if(!(FromPt=GetPointList(FromPt,0,0))||!(ToPt=GetPointList(ToPt,0,0))||SamePoint(FromPt[0],ToPt[0],'From and to')||SameCoords(FromPt,ToPt,'From and to'))return;if(Title.innerHTML=='Brg-Brg')BrgBrg(1,Store,FromPt,ValueFrom,ToPt,ValueTo,Pt,Desc);else if(Title.innerHTML=='Brg-Dist')BrgDist(Store,FromPt,ValueFrom,ToPt,ValueTo,Pt,Desc);else if(Title.innerHTML=='Dist-Dist')DistDist(Store,FromPt,ValueFrom,ToPt,ValueTo,Pt,Desc);}
function BrgBrg(Output,Store,FromPt,AzFrom,ToPt,AzTo,Pt,Desc){if(Output){if(!CheckBlank(AzFrom,' "from" azimuth')||!CheckBlank(AzTo,' "to" azimuth')||(Store==1&&(!CheckBlank(Pt,' point name')||!CheckBlank(Desc,' point description'))))return;AzFrom=ParseDMS(AzFrom,1,1);if(AzFrom!='X')AzTo=ParseDMS(AzTo,1,1);else return;}
if(AzTo!='X'){if(Round(AzFrom,7)==Round(AzTo,7)||Round(AzFrom-Math.PI,7)==Round(AzTo,7)||Round(AzFrom,7)==Round(AzTo-Math.PI,7)){alert('Azimuths do not intersect!');return;}
var AzAB=PtPtInverse(0,FromPt[0],ToPt[0])[2];var A=AzFrom-AzAB;var B=AzAB+Math.PI-AzTo;var P=Math.PI-A-B;var AP=PtPtInverse(0,FromPt[0],ToPt[0])[0]*Math.sin(B)/Math.sin(P);var Yp=parseFloat(FromPt[1])+AP*Math.cos(AzFrom);var Xp=parseFloat(FromPt[2])+AP*Math.sin(AzFrom);AzFrom=FormatDMS(AzFrom+'',0);AzTo=FormatDMS(AzTo+'',0);var N=FormatDecimal(Yp+'',0,1);var E=FormatDecimal(Xp+'',0,1);var Np=Yp+'',Ep=Xp+'',Zp=0+'';if(Output){var ptMt=new Array(3);ptMt[0]=FromPt;ptMt[1]=ToPt;ptMt[2]=['Calc_Pt',Np,Ep,Zp,'Calc_Pt'];ptMt[3]=[0];var Results='Brg-Brg from '+FromPt[0]+'('+FromPt[4]+') to '+ToPt[0]+'('+ToPt[4]+'):\n\n';Results+='       From Az: '+AzFrom+'        To Az: '+AzTo+'\n\n';if(Store==0)Results+='Calculated Point (NOT STORED):\n\n';else if(Store==1&&CheckPoint(Pt)){Pt=FormatString(Pt,1,0);Desc=FormatString(Desc,1,0);ptMt[2]=[Pt,Np,Ep,Zp,Desc];Results+='STORED '+Pt+'('+Desc+'):\n\n'
AddPoint(Pt,Np,Ep,Zp,Desc);qG('IntPt').value='';}
else return;Results+='       N:  '+N+'\n       E:  '+E+'\n';OutputCogo(Results,'IntersectLog');qG('IntersectCanvasSt').value='SketchBrgBrg('+JsonMat(ptMt,2)+', \'PointsCanvas\')';ZoomSketch(0,0,0);SketchBrgBrg(ptMt,'PointsCanvas');}
else return[Yp,Xp];}}
function BrgDist(Store,FromPt,AzFrom,ToPt,DistTo,Pt,Desc){if(!CheckBlank(AzFrom,' "from" azimuth')||!CheckBlank(DistTo,' "to" distance')||(Store==1&&(!CheckBlank(Pt,' point name')||!CheckBlank(Desc,' point description')))){return;}
AzFrom=ParseDMS(AzFrom,1,1);DistTo=ParseDecimal(DistTo,1,1);if(AzFrom!='X'&&DistTo!='X'){var Ya=parseFloat(FromPt[1]);var Xa=parseFloat(FromPt[2]);var Yb=parseFloat(ToPt[1]);var Xb=parseFloat(ToPt[2]);var AzAB=Math.atan2(Xb-Xa,Yb-Ya);if(AzAB<0){AzAB=AzAB+2*Math.PI;}
var A=AzFrom-AzAB;var AB=Math.sqrt(Math.pow(Ya-Yb,2)+Math.pow(Xa-Xb,2));var AP1=(2*(AB)*Math.cos(A)+Math.sqrt(Math.pow(2*AB*Math.cos(A),2)-4*(Math.pow(AB,2)-Math.pow(DistTo,2))))/2;var AP2=(2*(AB)*Math.cos(A)-Math.sqrt(Math.pow(2*AB*Math.cos(A),2)-4*(Math.pow(AB,2)-Math.pow(DistTo,2))))/2;var Xp1=Xa+AP1*Math.sin(AzFrom);var Yp1=Ya+AP1*Math.cos(AzFrom);var Xp2=Xa+AP2*Math.sin(AzFrom);var Yp2=Ya+AP2*Math.cos(AzFrom);if(isNaN(Xp1)||isNaN(Yp1)||isNaN(Xp2)||isNaN(Yp2)){alert('Azimuth and distance do not intersect!');return;}
var ptMt=new Array(5);ptMt[0]=FromPt;ptMt[1]=ToPt;ptMt[2]=['Sol_1',Yp1,Xp1,0,'Sol_1'];ptMt[3]=['Sol_2',Yp2,Xp2,0,'Sol_2'];ptMt[4]=[0];var HD1=Math.sqrt(Math.pow(Ya-Yp1,2)+Math.pow(Xa-Xp1,2));var HD2=Math.sqrt(Math.pow(Ya-Yp2,2)+Math.pow(Xa-Xp2,2));var HD3=Math.sqrt(Math.pow(Yp1-Yp2,2)+Math.pow(Xp1-Xp2,2));var MaxHD=Math.max(HD1,HD2,HD3);var Line=((MaxHD==HD1)?[0,2]:(MaxHD==HD2)?[0,3]:[2,3]);ZoomSketch(0,0,0);SketchBrgDist(ptMt,'PointsCanvas',1,Line);var N=FormatDecimal(Yp1,0,1);N=N.replace(/\s+/g,'');var E=FormatDecimal(Xp1,0,1);E=E.replace(/\s+/g,'');Message='Solution 1:\n\n';Message+='     N:  \t\t'+N+'\n';Message+='     E:  \t\t'+E+'\n\n';Message+='Accept this point?';var check1=confirm(Message);if(!check1){var N=FormatDecimal(Yp2,0,1);N=N.replace(/\s+/g,'');var E=FormatDecimal(Xp2,0,1);E=E.replace(/\s+/g,'');Message='Solution 2:\n\n';Message+='     N:  \t\t'+N+'\n';Message+='     E:  \t\t'+E+'\n\n';Message+='Accept this point?';var check2=confirm(Message);}
if(check1){var Xp=Xp1,Yp=Yp1;}
else if(check2){var Xp=Xp2,Yp=Yp2;}
else{alert('No solution chosen!');qG('PointsCanvas').innerHTML='';qG('PointsControl').innerHTML='';eval(qG('IntersectCanvasSt').value);return;}
AzFrom=FormatDMS(AzFrom+'',0);DistTo=FormatDecimal(DistTo+'',0,1);var N=FormatDecimal(Yp+'',0,1);var E=FormatDecimal(Xp+'',0,1);var Np=Yp+'',Ep=Xp+'',Zp=0+'';FromPt=GetPointList(FromPt[0],0,0);ToPt=GetPointList(ToPt[0],0,0);ptMt=new Array(4);ptMt[0]=FromPt;ptMt[1]=ToPt;ptMt[2]=['Calc_Pt',Np,Ep,Zp,'Calc_Pt'];ptMt[3]=[0];var Results='Brg-Dist from '+FromPt[0]+'('+FromPt[4]+') to '+ToPt[0]+'('+ToPt[4]+'):\n\n';Results+='       From Az: '+AzFrom+'        To Dist: '+DistTo+'\n\n';if(Store==0)Results+='Calculated Point (NOT STORED):\n\n';else if(Store==1&&CheckPoint(Pt)){Pt=FormatString(Pt,1,0);Desc=FormatString(Desc,1,0);Results+='STORED '+Pt+'('+Desc+'):\n\n';ptMt[2]=[Pt,Yp,Xp,0,Pt];AddPoint(Pt,Np,Ep,Zp,Desc);qG('IntPt').value='';}
else return;Results+='       N:  '+N+'\n       E:  '+E+'\n';OutputCogo(Results,'IntersectLog');qG('IntersectCanvasSt').value='SketchBrgDist('+JsonMat(ptMt,2)+', \'PointsCanvas\', 0, \'\')';ZoomSketch(0,0,0);SketchBrgDist(ptMt,'PointsCanvas',0,'');}}
function DistDist(Store,FromPt,DistFrom,ToPt,DistTo,Pt,Desc){if(!CheckBlank(DistFrom,' "from" distance')||!CheckBlank(DistTo,' "to" distance')||(Store==1&&(!CheckBlank(Pt,' point name')||!CheckBlank(Desc,' point description'))))return;DistFrom=ParseDecimal(DistFrom,1,1);DistTo=ParseDecimal(DistTo,1,1);if(DistFrom!='X'&&DistTo!='X'){var AB=PtPtInverse(0,FromPt[0],ToPt[0])[0];var AzAB=PtPtInverse(0,FromPt[0],ToPt[0])[2];var A=Math.acos((Math.pow(AB,2)+Math.pow(DistFrom,2)-Math.pow(DistTo,2))/(2*AB*DistFrom));var Xp1=parseFloat(FromPt[2])+DistFrom*Math.sin(AzAB+A);var Yp1=parseFloat(FromPt[1])+DistFrom*Math.cos(AzAB+A);var Xp2=parseFloat(FromPt[2])+DistFrom*Math.sin(AzAB-A);var Yp2=parseFloat(FromPt[1])+DistFrom*Math.cos(AzAB-A);if(isNaN(Xp1)||isNaN(Yp1)||isNaN(Xp2)||isNaN(Yp2)){alert('Distances do not intersect!');return;}
var ptMt=new Array(5);ptMt[0]=FromPt;ptMt[1]=ToPt;ptMt[2]=['Sol_1',Yp1,Xp1,0,'Sol_1'];ptMt[3]=['Sol_2',Yp2,Xp2,0,'Sol_2'];ptMt[4]=[0];ZoomSketch(0,0,0);SketchDistDist(ptMt,'PointsCanvas',1);var N=FormatDecimal(Yp1,0,1);N=N.replace(/\s+/g,'');var E=FormatDecimal(Xp1,0,1);E=E.replace(/\s+/g,'');Message='Solution 1:\n\n';Message+='     N:  \t\t'+N+'\n';Message+='     E:  \t\t'+E+'\n\n';Message+='Accept this point?';var check1=confirm(Message);if(!check1){var N=FormatDecimal(Yp2,0,1);N=N.replace(/\s+/g,'');var E=FormatDecimal(Xp2,0,1);E=E.replace(/\s+/g,'');Message='Solution 2:\n\n';Message+='     N:  \t\t'+N+'\n';Message+='     E:  \t\t'+E+'\n\n';Message+='Accept this point?';var check2=confirm(Message);}
if(check1){var Xp=Xp1;var Yp=Yp1;}
else if(check2){var Xp=Xp2;var Yp=Yp2;}
else{alert('No solution chosen!');qG('PointsCanvas').innerHTML='';qG('PointsControl').innerHTML='';eval(qG('IntersectCanvasSt').value);return;}
DistFrom=FormatDecimal(DistFrom+'',0,1);DistTo=FormatDecimal(DistTo+'',0,1);var N=FormatDecimal(Yp+'',0,1);var E=FormatDecimal(Xp+'',0,1);var Np=Yp+'';var Ep=Xp+'';var Zp=0+'';FromPt=GetPointList(FromPt[0],0,0);ToPt=GetPointList(ToPt[0],0,0);ptMt=new Array(4);ptMt[0]=FromPt;ptMt[1]=ToPt;ptMt[2]=['Calc_Pt',Np,Ep,Zp,'Calc_Pt'];ptMt[3]=[0];var Results='Dist-Dist from '+FromPt[0]+'('+FromPt[4]+') to '+ToPt[0]+'('+ToPt[4]+'):\n\n';Results+='       From Dist: '+DistFrom+'        To Dist: '+DistTo+'\n\n';if(Store==0)Results+='Calculated Point (NOT STORED):\n\n';else if(Store==1&&CheckPoint(Pt)){Pt=FormatString(Pt,1,0);Desc=FormatString(Desc,1,0);Results+='STORED '+Pt+'('+Desc+'):\n\n';ptMt[2]=[Pt,Yp,Xp,0,Pt];AddPoint(Pt,Np,Ep,Zp,Desc);qG('IntPt').value='';}
else return;Results+='       N:  '+N+'\n       E:  '+E+'\n';OutputCogo(Results,'IntersectLog');qG('IntersectCanvasSt').value='SketchDistDist('+JsonMat(ptMt,2)+', \'PointsCanvas\', 0)';ZoomSketch(0,0,0);SketchDistDist(ptMt,'PointsCanvas',0);}}
function Traverse(Store,Increment){var FromPt=qG('TravFrom').value;var BSPt=qG('TravBS').value;var Ang=qG('TravAng').value;var Dist=qG('TravDist').value;var ZA=qG('TravZA').value;var Pt=qG('TravPt').value;var Desc=qG('TravDesc').value;var Dim=qG('TravDim').innerHTML;var Type=qG('TravType').innerHTML;var HI=parseFloat(qG('HI').value);var HT=parseFloat(qG('HT').value);var AngBlankError='n azimuth';var BSRecord='';var HIHTRecord='';var AngRecord='        Az:     ';if(Type=='Angle'){if(!CheckBlank(BSPt,' backsight point'))return;BSPt=FormatString(BSPt,1,0);if(!(BSPt=GetPointList(BSPt,0,0)))return;AngBlankError=' horizontal angle';BSRecord=' BS '+BSPt[0]+'('+BSPt[4]+')';AngRecord='        HA:     ';}
if(Dim=='2D'&&(!CheckBlank(FromPt,' point to traverse from')||!CheckBlank(Ang,AngBlankError)||!CheckBlank(Dist,' horizontal distance')||(Store==1&&(!CheckBlank(Pt,' point name')||!CheckBlank(Desc,' point description'))))){return;}
else if(Dim=='3D'&&(!CheckBlank(FromPt,' point to traverse from')||!CheckBlank(Ang,AngBlankError)||!CheckBlank(Dist,' slope distance')||!CheckBlank(ZA,' zenith angle')||(Store==1&&(!CheckBlank(Pt,' point name')||!CheckBlank(Desc,' point description'))))){return;}
FromPt=FormatString(FromPt,1,0);if(!(FromPt=GetPointList(FromPt,0,0))||(Type=='Angle'&&SamePoint(FromPt[0],BSPt[0],'From and BS'))){return;}
Ang=((Type=='Angle')?ParseDMS(Ang,1,0):ParseDMS(Ang,1,1));ZA=((Dim=='3D')?ParseDMS(ZA,1,0):Math.PI/2);Dist=ParseDecimal(Dist,1,1);if(Ang!='X'&&Dist!='X'&&((Dim=='2D')||(Dim=='3D'&&ZA!='X'))){Ang2=Ang;if(Type=='Angle'){Ang=Ang+PtPtInverse(0,FromPt[0],BSPt[0])[2];}
if(Dim=='3D'){HIdisp=FormatDecimal(HI+'',0,1);HIdisp=HIdisp.replace(/\s+/g,'');HTdisp=FormatDecimal(HT+'',0,1);HTdisp=HTdisp.replace(/\s+/g,'');HIHTRecord=' [HI='+HIdisp+', HT='+HTdisp+']';}
else{HI=0;HT=0;}
ZA=((Dim=='3D'&&ZA>Math.PI)?Math.PI*2-ZA:ZA);HD=Math.sin(ZA)*Dist;VD=Math.cos(ZA)*Dist+HI-HT;var Np=HD*Math.cos(Ang)+parseFloat(FromPt[1]);var Ep=HD*Math.sin(Ang)+parseFloat(FromPt[2]);var Zp=VD+parseFloat(FromPt[3]);Ang=FormatDMS(Ang2+'',0);ZA=FormatDMS(ZA+'',0);Dist=FormatDecimal(Dist+'',0,1);var N=FormatDecimal(Np+'',0,1);var E=FormatDecimal(Ep+'',0,1);var Z=FormatDecimal(Zp+'',0,1);Np=Np+'';Ep=Ep+'';Zp=Zp+'';var ZAline='';var Zline='';var distLabel='HD:';if(Dim=='3D'){var Spacer='           ';for(var j=0;j<Dist.length;j++){Spacer+=' ';}
ZAline=Spacer+'        ZA:     '+ZA+'\n';Zline='       Z:  '+Z+'\n';distLabel='SD:';}
var Results=Dim+' by '+Type+' from '+FromPt[0]+'('+FromPt[4]+')'+BSRecord+HIHTRecord+':\n\n';Results+='       '+distLabel+' '+Dist+AngRecord+Ang+'\n';Results+=ZAline;if(Store==0){Results+='\nCalculated Point (NOT STORED):\n\n';Pt='Calc_Pt';Desc='Calc_Pt';}
else if(Store==1&&CheckPoint(Pt)){Pt=FormatString(Pt,1,0);Desc=FormatString(Desc,1,0);Results+='\nSTORED '+Pt+'('+Desc+'):\n\n'
AddPoint(Pt,Np,Ep,Zp,Desc);if(Increment){qG('TravBS').value=qG('TravFrom').value;qG('TravFrom').value=Pt;}
qG('TravPt').value='';}
else return;Results+='       N:  '+N+'\n       E:  '+E+'\n'+Zline;if(Type=='Azimuth'){var ptMt=new Array(3);ptMt[0]=FromPt;ptMt[1]=[Pt,Np,Ep,Zp,Desc];ptMt[2]=[0];}
else{var ptMt=new Array(3);ptMt[0]=BSPt;ptMt[1]=FromPt;ptMt[2]=[Pt,Np,Ep,Zp,Desc];ptMt[3]=[0];}
qG('TraverseCanvasSt').value='SketchPtPt('+JsonMat(ptMt,2)+', \'PointsCanvas\')';ZoomSketch(0,0,0);SketchPtPt(ptMt,'PointsCanvas');OutputCogo(Results,'TraverseLog');}}
