Cehui.pas—待续

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.