单像空间后方交会算法单元(SingleCross.pas)

unit SingleCross;
{-------------------------------------------------
             摄影测量单像空间会方交会算法单元
          == ◎◎◎   作者:陈明(龙在天)  ◎◎◎ ==
          == ◎◎◎   任课老师:  邓  非  ◎◎◎ ==
                  QQ:810492306
--------------------------------------------------}

interface
uses SysUtils,Matrice,PerlRegEx,Classes,Dialogs;

type KZPoint=record    //地面控制点坐标
  X:extended;
  Y:extended;
  Z:extended;
end;
type YXPoint=record   //影像点坐标
  X:extended;
  Y:extended;
end;
type IData=record     //三个输入不方便的角度
  ψ:extended;
  ω:extended;
  κ:extended;
end;

var m, f, x0, y0, Xs, Ys, Zs:extended; //m,f,x0,y0为内方位元素
    PointNum:integer;                             //控制点的个数
    LowLimit:extended;                            //精度控制
    a1, a2, a3, b1, b2, b3, c1, c2, c3:extended;  //R矩阵各值
    KZPs:array of KZPoint;         //用户输入的已知控制点
    YXPs:array of YXPoint;         //用户输入的已知像点
    F3:IData;                      //三个输入不方便的角度
    A,X,L:RCOMat;                  //平差矩阵, X=[dXs,dYs,dZs,dψ,dω,dκ]T;  A[2n,6], L[2n,1]

var splitStr:string=' *';           //正则表达式的分隔符

//===========================从文本文件中读取初始数据===========================
procedure DataFromText(filename:string);
//===========================初始化数据=========================================
procedure InitData;
//===========================计算R矩阵==========================================
procedure CalcR;
//===========================计算L矩阵==========================================
procedure CalcL;
//===========================计算A矩阵==========================================
procedure CalcA;
//===========================计算X矩阵==========================================
procedure CalcX;
//===========================循环计算直到误差够小===============================
procedure Calc;

implementation

uses Unit1;

//===========================从文本文件中读取初始数据===========================
procedure DataFromText(filename:string);
var f:TextFile;
    Reg:TPerlRegEx;
    s:string;
    List:TStrings;
    rows,i:integer;
begin
  Reg:=TPerlRegEx.Create(nil);
  List:=TStringList.Create;
  assignfile(f,filename);
  reset(f);
  s:='';   rows:=0;
  while not Eof(f) do
  begin
    Readln(f,s); s:=trim(s);                            //第一行
    while s='' do begin readln(f,s); s:=trim(s); end;  //处理空行
    rows:=rows+1;
  end;
  SetLength(KZPs,rows);
  SetLength(YXPs,rows);
  PointNum:=rows;
  Reset(f);
  for I := 0 to rows - 1 do
    begin
      Readln(f,s); s:=Trim(s);
      while s='' do begin readln(f,s); s:=trim(s); end;
      reg.Subject := UTF8string(s);
      reg.RegEx :=UTF8string(splitStr);
      reg.Split(list,MaxInt);
      KZPs[i].X:=StrToFloat(List[1]);
      //Form1.Memo1.Lines.Add(FloatToStr(Kzps[i].X));
      KZPs[i].Y:=StrToFloat(List[2]);
      //Form1.Memo1.Lines.Add(FloatToStr(Kzps[i].Y));
      KZPs[i].Z:=StrToFloat(List[3]);
      //Form1.Memo1.Lines.Add(FloatToStr(Kzps[i].Z));
      YXPs[i].X:=StrToFloat(List[4]) / 1000;
      //Form1.Memo1.Lines.Add(FloatToStr(Yxps[i].X));
      YXPs[i].Y:=StrToFloat(List[5]) / 1000;
      //Form1.Memo1.Lines.Add(FloatToStr(yxps[i].y));
      List.Clear;
    end;
  Reg.Free;
  List.Free;
  CloseFile(f);
end;

//===========================初始化数据=========================================
procedure InitData;
var tempX,tempY:extended;
  I: Integer;
begin
  tempX:=0; tempY:=0;
  F3.ψ :=0;
  F3.ω :=0;
  F3.κ :=0;
  for I := 0 to PointNum - 1 do
    begin
      tempX:=tempX+KZPs[i].X;
      tempY:=tempX+KZPs[i].Y;
    end;
  Zs:=m*f;
  Xs:=tempX / PointNum;
  Ys:=tempY / PointNum;
end;

//===========================计算R矩阵==========================================
procedure CalcR;
begin
  a1:=Cos(F3.ψ)*Cos(F3.κ)-Sin(F3.ψ)*Sin(F3.ω)*Sin(F3.κ);
  a2:=-Cos(F3.ψ)*Sin(f3.κ)-Sin(f3.ψ)*Sin(f3.ω)*Cos(f3.κ);
  a3:=-Sin(f3.ψ)*Cos(f3.ω);
  b1:=Cos(f3.ω)*Sin(f3.κ);
  b2:=Cos(f3.ω)*Cos(f3.κ);
  b3:=-Sin(f3.ω);
  c1:=Sin(f3.ψ)*Cos(f3.κ)+Cos(f3.ψ)*Sin(f3.ω)*Sin(f3.κ);
  c2:=-Sin(f3.ψ)*Sin(f3.κ)+Cos(f3.ψ)*Sin(f3.ω)*Cos(f3.κ);
  c3:=Cos(f3.ψ)*Cos(f3.ω);
end;

//===========================计算L矩阵==========================================
procedure CalcL;
var JSx, JSy:extended;    //近似值
    I: Integer;
begin
  SetLength(L,2*PointNum,1);      //L[2n,1]
  for I := 0 to PointNum - 1 do
    begin
      JSx:=x0/1000-f*( (a1*(KZPs[i].X-Xs) + b1*(KZPs[i].Y-Ys) + c1*(KZPs[i].Z-Zs) ) / ( a3*(KZPs[i].X-Xs) + b3*(KZPs[i].Y-Ys) + c3*(KZPs[i].Z-Zs) ) );
      JSy:=y0/1000-f*( (a2*(KZPs[i].X-Xs) + b2*(KZPs[i].Y-Ys) + c2*(KZPs[i].Z-Zs) ) / ( a3*(KZPs[i].X-Xs) + b3*(KZPs[i].Y-Ys) + c3*(KZPs[i].Z-Zs) ) );
      L[2*i,0]:=YXPs[i].X-JSx;
      L[2*i+1,0]:=YXPs[i].Y-JSy;
    end;
end;

//===========================计算A矩阵==========================================
procedure CalcA;
var a11, a12, a13, a21, a22, a23, a14, a15, a16, a24, a25, a26,Z1:extended;
    i:integer;
begin
  SetLength(A,2*PointNum,6);      //A[2n,6]
  for I := 0 to PointNum - 1 do
    begin
      Z1:=a3*(KZPs[i].X-Xs) + b3*(KZPs[i].Y-Ys) + c3*(KZPs[i].Z-Zs);
      a11:=(a1*f+a3*YXPs[i].X) / Z1;
      a12:=(b1*f+b3*YXPs[i].X) / Z1;
      a13:=(c1*f+c3*YXPs[i].X) / Z1;
      a21:=(a2*f+a3*YXPs[i].Y) / Z1;
      a22:=(b2*f+b3*YXPs[i].Y) / Z1;
      a23:=(c2*f+c3*YXPs[i].Y) / Z1;
      a14:=YXPs[i].Y*Sin(f3.ω)-( (YXPs[i].X*(YXPs[i].X*Cos(f3.κ)-YXPs[i].Y*Sin(f3.κ)))/f+f*Cos(f3.κ) )*Cos(f3.ω);
      a15:=-f*Sin(f3.κ)-YXPs[i].X*(YXPs[i].X*Sin(f3.κ)+YXPs[i].Y*Cos(f3.κ)) / f;
      a16:=YXPs[i].Y;
      a24:=-YXPs[i].X*Sin(f3.ω)-( (YXPs[i].X*(YXPs[i].X*Cos(f3.κ)-YXPs[i].Y*Sin(f3.κ)))/f-f*Sin(f3.κ) )*Cos(f3.ω);
      a25:=-f*Cos(f3.κ)-YXPs[i].Y*(YXPs[i].X*Sin(f3.κ)+YXPs[i].Y*Cos(f3.κ)) / f;
      a26:=-YXPs[i].X;

      A[2*i,0]:=a11;
      A[2*i,1]:=a12;
      A[2*i,2]:=a13;
      A[2*i,3]:=a14;
      A[2*i,4]:=a15;
      A[2*i,5]:=a16;
      A[2*i+1,0]:=a21;
      A[2*i+1,1]:=a22;
      A[2*i+1,2]:=a23;
      A[2*i+1,3]:=a24;
      A[2*i+1,4]:=a25;
      A[2*i+1,5]:=a26;
    end;
end;

//===========================计算X矩阵==========================================
procedure CalcX;
var AT,ATA,ATA1,ATA1AT:RCOMat;
    det:extended;
begin
  InitMat(2*PointNum);
  SetLength(AT,6,2*PointNum);
  TransMat(A,AT,2*PointNum,6);        //AT=A的转置
  SetLength(ATA,6,6);
  InitMat(6);
  MatMatR(AT,A,2*PointNum,6,ATA);     //ATA[6,6]=AT*A
  SetLength(ATA1,6,6);
  InitMat(6);
  InvMat(ATA,ATA1,det);               //ATA1=ATA的逆
  SetLength(ATA1AT,6,2*PointNum);
  InitMat(6);
  MatMatR(ATA1,AT,6,2*PointNum,ATA1AT);//ATA1AT[6,2*n]=ATA1*AT
  SetLength(X,6,1);
  InitMat(6);
  MatMatR(ATA1AT,L,2*PointNum,1,X);    //最后求得X
end;

//===========================循环计算直到误差够小===============================
procedure Calc;
var rs:string;
    times:integer;
begin
  times:=0;
  repeat
    CalcR;
    CalcL;
    CalcA;
    CalcX;
    Xs:=Xs+X[0,0]; Ys:=Ys+X[1,0]; Zs:=Zs+X[2,0];
    f3.ψ:=f3.ψ+X[3,0]; f3.ω:=f3.ω+X[4,0]; f3.κ:=f3.κ+X[5,0];
    times:=times+1;
    Form1.Memo1.Lines.Add('第'+IntToStr(times)+'次迭代============');
    Form1.Memo1.Lines.Add('Xs='+FloatToStr(Xs)+';Ys='+FloatToStr(Ys)+';Zs='+FloatToStr(Zs)+';');
    Form1.Memo1.Lines.Add('ψ='+FloatToStr(f3.ψ)+';ω='+FloatToStr(f3.ω)+';κ='+FloatToStr(f3.κ)+';');
    Form1.Memo1.Lines.Add('dXs='+FloatToStr(X[0,0])+';dYs='+FloatToStr(X[1,0])+';dZs='+FloatToStr(X[2,0])+';dψ='+FloatToStr(X[3,0])+';dω='+FloatToStr(X[4,0])+';dκ='+FloatToStr(X[5,0]));
    Form1.Memo1.Lines.Add('');
  until (abs(X[0,0])<LowLimit) and (abs(X[1,0])<LowLimit) and (abs(X[2,0])<LowLimit) and (abs(X[3,0])<LowLimit) and (abs(X[4,0])<LowLimit) and (abs(X[5,0])<LowLimit);
  rs:=rs+FloatToStr(Xs)+' '+FloatToStr(Ys)+' '+FloatToStr(Zs)+#13#10;
  rs:=rs+FloatToStr(f3.ψ)+' '+FloatToStr(f3.ω)+FloatToStr(f3.κ)+#13#10;
  rs:=rs+IntToStr(times);
  ShowMessage(rs);
end;

end.

用法说明:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form1.Position:=poScreenCenter;
  DataFromText('data.txt');
  m:=50000; f:=0.0281359; x0:=0; y0:=0; LowLimit:=0.000029;
  InitData;
  Calc;
end;