unit Cehui; {----------------------------------- == ◎◎◎ 作者:陈明(龙在天) ◎◎◎ == QQ:810492306 注:本程序约定写法-->60度20分30秒写为60.20.30 30.20.10为30度20分10秒 其它小数写法均为弧度值 各个函数的参数均以弧度值为实参 ------------------------------------} interface uses Math,SysUtils; type Point=record //点坐标的记录类型 x:single; y:single; end; //*****************前方交会的计算,根据AB两点的坐标和两个角求P点的坐标********** function FrontCross(A,B:Point;a_bear,b_bear:single):Point; //*****************测边交会的计算,已知A,B,ap长,bp长,求P。P点在A,B下侧则fm=1;在上侧则fm=-1,xx为AB测绘象限序号 function SidesCross(A,B:Point;ap,bp:single;fm,xx:integer):Point; //*****************将角度转换成弧度如60.30.20(60度30分20秒)化成弧度1.056******* function MyDegToRad(Deg:string):single; //*****************将弧度转换成角度,如3转换成171度53分14秒,171.53.14*********** function MyRadToDeg(Rad:single):string; //*****************奇进偶不进算法函数****************************************** function JustifyFloat(float1:single):integer; //*****************坐标正算函数,已知A,AB距离,AB坐标方位角,求B****************** function RCalCoordinate(A:Point;Sab:single;ab_bear:single):Point; //*****************坐标反算函数,已知A,B求AB方位角和Sab,xx为AB测绘象限序号****** function LCalCoordinate(A,B:Point;var ab_bear:single;xx:integer):single;//顺便返回 ab_bear //*****************将弧(角)度度化到0到2*Pi之间,纠正角度范围******************** function JustifyBear(bear:single):single;overload; function JustifyBear(bear:string):string;overload; //*****************余弦函数求角值,已知三边长a,b,c其中c为欲求角的对边*********** function YuXianFunc(a,b,c:single):single; //*****************已知A,B坐标求AB长度***************************************** function CalABLong(A,B:Point):single; //*****************由A,B两点坐标判断AB是在测绘坐标系中哪象限******************* function JudgeABXX(A,B:Point):integer; //*****************由A,B坐标计算AB的方位角,xx,象限,FW,方位******************** function CalAB_FWbear(A,B:Point):single; //*****************正弦函数求边长,已知a边和A,B角******************************* function ZhengXianFunc(a:single;a_bear,b_bear:single):single; //*****************将角度转换成秒值,如30.20.10转换成秒值********************** function CoordinateToSeconds(Deg:string):single; //*****************将秒值转换成角度值****************************************** function SecondsToCoordinate(Se:single):string; //*****************两个角(30.20.10的形式),加减法运算,1234分别为加减乘除******* function CoordinateAddAndSub(A,B:string;i:integer):string; //*****************小数转分数************************************************** function Fraction(decimal: double): string; implementation //================================小数转分数=================================== function Fraction(decimal: double): string; var intNumerator, intDenominator, intNegative: integer; // 声明整数变量为长整数 dblFraction, dblDecimal, dblAccuracy, dblinteger: Double; // 声明浮点数为双精度 temp:string; begin dblDecimal := decimal; //取得目标小数 if trunc(decimal) = decimal then // 如果是整数,则直转 result := floattostr(decimal) else begin if abs(decimal) > 1 then //如果小数大于1 如 10.24 ,进行拆解 begin dblinteger := trunc(decimal); //取出整数部分 dblDecimal := abs(frac(decimal)); //取出小数部分 end else dblDecimal := decimal; dblAccuracy := 0.01; //设置精度 intNumerator := 0; //初始分子为0 intDenominator := 1; //初始分母为1 intNegative := 1; //符号标记为正 if dblDecimal < 0 then intNegative := -1; //如果目标为负,设置负标志位 dblFraction := 0; //设置分数值为 0/1 while Abs(dblFraction - dblDecimal) > dblAccuracy do //如果当前没有达到精度要求就继续循环 begin if Abs(dblFraction) > Abs(dblDecimal) then //如果我们的分数大于目标 intDenominator := intDenominator + 1 //增加分母 else //否则 intNumerator := intNumerator + intNegative; //增加分子 dblFraction := intNumerator / intDenominator; //计算新的分数 end; // edit2.Text := inttostr(intNumerator) + '/' + inttostr(intDenominator); if abs(decimal) > 1 then //如果小数大于1 如 10.24 ,进行拆解 //结果:dblinteger为整数部分, intNumerator为分子,intDenominator为分母 begin if dblinteger<0 then //如果为负数 begin dblinteger := -dblinteger; temp := floattostr(dblinteger*intDenominator+intNumerator) + '/' + inttostr(intDenominator); //result := floattostr(dblinteger) + '又' + inttostr(intNumerator) + '/' + inttostr(intDenominator) result := '-'+temp; end else begin temp := floattostr(dblinteger*intDenominator+intNumerator) + '/' + inttostr(intDenominator); result :=temp; end; end else result := inttostr(intNumerator) + '/' + inttostr(intDenominator); end; end; //============================前方交会的计算(逆时针)=========================== function FrontCross(A,B:Point;a_bear,b_bear:single):Point; var P:Point; begin p.x:=(A.x*cot(b_bear)+B.x*cot(a_bear)+(B.y-A.y))/(cot(a_bear)+cot(b_bear)); p.y:=(A.y*cot(b_bear)+B.y*cot(a_bear)-(B.x-A.x))/(cot(a_bear)+cot(b_bear)); result:=P; end; //========================将角度转换成弧度如60.30.20(60度30分20秒)化成弧度1.056 function MyDegToRad(Deg:string):single; var sum:single; begin sum:=CoordinateToSeconds(Deg); result:=sum/(180*3600)*Pi; end; //=============================奇进偶不进算法函数============================== function JustifyFloat(float1:single):integer; var temp:integer; begin result:=0; temp:=trunc(float1*2); if float1<0 then temp:=trunc(-float1*2); //如果目标数为负数 if odd(temp) then //奇进偶不进 begin if (temp mod 4)=1 then result:=temp div 2 else if (temp mod 4)=3 then result:=(temp+1) div 2; end else begin result:=temp div 2; end; if float1<0 then result:=-result; end; //============================将弧度转换成角度,如3转换成171度53分14秒,171.53.14 function MyRadToDeg(Rad:single):string; var temp1,temp2,temp3:single; str1,str2,str3:string; begin temp1:=Rad/Pi*180; if Rad<0 then temp1:=-Rad/Pi*180; //如果为负数 str1:=IntToStr(Floor(temp1)); //取整 147 temp2:=Frac(temp1)*60; //Frac取小数部分, str2:=IntToStr(Floor(temp2)); //算分值 temp3:=Frac(temp2)*60; str3:=IntToStr(Round(temp3)); //Round四舍五入,算秒值 result:=str1+'.'+str2+'.'+str3; //度.分.秒 的形式输出 if Rad<0 then result:='-'+result; end; //========================坐标正算函数,已知A,AB距离,AB坐标方位角,求B=========== function RCalCoordinate(A:Point;Sab:single;ab_bear:single):Point; var B:Point; begin B.x:=A.x+Sab*Cos(ab_bear); B.y:=A.y+Sab*Sin(ab_bear); result:=B; end; //=======================坐标反算函数,已知A,B求AB方位角和Sab,xx为AB测绘象限序号 function LCalCoordinate(A,B:Point;var ab_bear:single;xx:integer):single; var Xab,Yab:single; //分别为X,Y坐标差 begin Xab:=B.x-A.x; Yab:=B.y-A.y; ab_bear:=Arctan(Yab/Xab); //改变参数ab_bear值并返回 if ab_bear<0 then ab_bear:=-ab_bear; //如果ab_bear小于0时 case xx of //转换为坐标方位角 1:ab_bear:=ab_bear; 2:ab_bear:=Pi-ab_bear; 3:ab_bear:=Pi+ab_bear; 4:ab_bear:=2*Pi-ab_bear; end; result:=Sqrt(Sqr(Xab)+Sqr(Yab)); end; //========测边交会的计算,已知A,B,ap长,bp长,求P。P点在A,B下侧则fm=1;在上侧则fm=-1,xx为AB测绘象限序号 function SidesCross(A,B:Point;ap,bp:single;fm,xx:integer):Point; var Sab:single; //AB边长 ab_bear:single; //AB方位角 ap_bear:single; //AP方位角 a_bear:single; //角A值(弧度) P:Point; begin Sab:=LCalCoordinate(A,B,ab_bear,xx); //坐标反算求出AB长和AB方位角 a_bear:=YuXianFunc(Sab,ap,bp); //余弦函数求A角 ap_bear:=JustifyBear(ab_bear+fm*a_bear); //算AP的方位角 P:=RCalCoordinate(A,ap,ap_bear); //坐标正算求出P点坐标 result:=P; end; //=======================将弧(角)度度化到0到2*Pi之间,纠正弧(角)度范围========== function JustifyBear(bear:single):single;overload; begin if bear<0 then repeat bear:=bear+2*Pi; until bear>=0; if bear>2*Pi then repeat bear:=bear-2*Pi; until bear<=2*Pi; result:=bear; end; function JustifyBear(bear:string):string;overload; var seconds:single; begin seconds:=CoordinateToSeconds(bear); if seconds<0 then repeat seconds:=seconds+360*3600; until seconds>=0; if seconds>360*3600 then repeat seconds:=seconds-360*3600; until seconds<360*3600; result:=SecondsToCoordinate(seconds); end; //======================余弦函数求角值,已知三边长a,b,c其中c为欲求角的对边====== function YuXianFunc(a,b,c:single):single; var bear:single; begin bear:=Arccos((Sqr(a)+Sqr(b)-Sqr(c))/(2*a*b)); result:=bear; end; //=======================已知A,B坐标求AB长度=================================== function CalABLong(A,B:Point):single; begin result:=Sqrt(Sqr(A.x-B.x)+Sqr(A.y-B.y)); end; //======================由A,B两点坐标判断AB是在测绘坐标系中哪象限============== function JudgeABXX(A,B:Point):integer; begin result:=1; if (B.x-A.x>0) and (B.y-A.y>0) then result:=1; if (B.x-A.x<0) and (B.y-A.y>0) then result:=2; if (B.x-A.x<0) and (B.y-A.y<0) then result:=3; if (B.x-A.x>0) and (B.y-A.y<0) then result:=4; end; //=======================由A,B坐标计算AB的方位角,xx,象限,FW,方位============== function CalAB_FWbear(A,B:Point):single; var ab_bear:single; xx:integer; begin xx:=JudgeABXX(A,B); LCalCoordinate(A,B,ab_bear,xx); result:=ab_bear; end; //======================正弦函数求边长,已知a边和A,B角========================== function ZhengXianFunc(a:single;a_bear,b_bear:single):single; begin result:=0; if sin(a_bear)<>0 then result:=a*sin(b_bear)/sin(a_bear); end; //======================将角度转换成秒值,如30.20.10转换成秒值================= function CoordinateToSeconds(Deg:string):single; var deg1,deg2:string; sum:single; temp:string; begin sum:=0; temp:=Deg; if copy(Deg,1,1)='-' then Deg:=Copy(Deg,2,Length(Deg)-1);//如果为负数则化为正的 if pos('.',Deg)=0 then begin sum:=StrToInt(Deg)*3600; end; if pos('.',Deg)<>0 then begin deg1:=copy(deg,pos('.',deg)+1,length(deg)-pos('.',deg)); //deg1=30.20 deg2:=copy(deg,1,pos('.',deg)-1); //deg2=60 sum:=StrToInt(deg2)*3600; //化成秒 if pos('.',deg1)=0 then begin sum:=sum+StrToInt(deg1)*60; end; if pos('.',deg1)<>0 then begin deg2:=copy(deg1,1,pos('.',deg1)-1); sum:=sum+StrToInt(deg2)*60; deg2:=copy(deg1,pos('.',deg1)+1,length(deg1)-pos('.',deg1)); sum:=sum+StrToFloat(deg2); end; end; result:=sum; if copy(temp,1,1)='-' then result:=-result; end; //=======================将秒值转换成角度值==================================== function SecondsToCoordinate(Se:single):string; var str1:string; temp:integer; o:single; begin if Se<0 then Se:=-Se; temp:=Trunc(Se); o:=se-Trunc(Se); //如果目标为负数 str1:=IntToStr(temp div 3600)+'.'; str1:=str1+IntToStr((temp mod 3600) div 60)+'.'; str1:=str1+FloatToStr((temp mod 60)+o); result:=str1; if se<0 then result:='-'+result; end; //========================两个角(30.20.10的形式),加减法运算,1234分别为加减乘除 function CoordinateAddAndSub(A,B:string;i:integer):string; var temp:single; temp1:single; begin case i of 1:begin //加法运算 temp:=CoordinateToSeconds(A)+CoordinateToSeconds(B); result:=SecondsToCoordinate(temp); end; 2:begin //减法运算 temp:=CoordinateToSeconds(A)-CoordinateToSeconds(B); result:=SecondsToCoordinate(temp); end; 3:begin //乘法运算 temp:=CoordinateToSeconds(A) * StrToInt(B); result:=SecondsToCoordinate(temp); end; 4:begin //除法运算 temp1:=CoordinateToSeconds(A) / StrToInt(B); temp:=JustifyFloat(temp1); //奇进偶不进 result:=SecondsToCoordinate(temp); end; end; end; end.