unit PedroRattachement;

interface

uses
	Classes, Topo, Divers, Contnrs, ComCtrls, SysUtils, Dialogs, Grades, PedroApi,
  Controls, Windows;
  
type
	TRattacheType=(rtRelevement,rtMultilateration,rtIntersection);
  TRattacheTolerance=(rtOrdinaire,rtPrecision);

  TXYZPointEx=record
  	X,Y,Z,AV,Distance,DZ,ZErr:double;
    Num:string;
  end;
  
  TRattache=class(TPersistent)
  private
    FY: double;
    FData: double;
    FX: double;
    FZ: double;
    FnVisees: integer;
    FPoint: string;
    FrtType: TRattacheType;
    FAV: double;
    Tab:array[4..11] of double;
  public
  	procedure Init(Num:string;aX,aY,aZ,aData:double;anVisees:integer=1;aAngleVertical:double=100);overload;
    procedure Init(aRattacheType:TRattacheType;Num:string;aX,aY,aZ,aData:double;anVisees:integer=1;aAngleVertical:double=100);overload;
    procedure LoadFrom(t:TRattache);

    constructor Create;overload;
    constructor Create(aRattacheType:TRattacheType;Num:string;aX,aY,aZ,aData:double;anVisees:integer=1);overload;
  
  	property RattacheType:TRattacheType read FrtType write FrtType;
    property Point:string read FPoint write FPoint;
    property X:double read FX write FX;
    property Y:double read FY write FY;
    property Z:double read FZ write FZ;
    property Data:double read FData write FData;
    property nVisees:integer read FnVisees write FnVisees;
    property AngleVertical:double read FAV write FAV;
  end;

	TPedroRattachement=class(TComponent)
  private
  	FList:TObjectList;
    FResult1: TPedroXYZPoint;
    FResult2: TPedroXYZPoint;
    FPtRecherche: string;
    FrtPrecision: TRattacheTolerance;
    FAutoOpen: boolean;
    FRmq: double;
    FTolRmq: double;
    FEmq: double;
    FTolEmq: double;
    FDelete: boolean;
    FFileName:string;
    FCalculAlti:boolean;
    function GetVisee(Index: integer): TRattache;
    procedure SetVisee(Index: integer; const Value: TRattache);
    procedure setPtRecherche(const Value: string);
  protected
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy;override;
    procedure Clear;
    procedure Display(aListView:TListView);
    function Add(Rattache:TRattache):integer;
    function NewRattache:TRattache;
    function Delete(Index:integer):boolean;
    function Count:integer;overload;
    function Count(aRattacheType:TRattacheType):integer;overload;
    procedure Test;
    procedure Calcul(Fichier:string);
    function GetAtIndex(Index:integer;aRattacheType:TRattacheType):TRattache;

    property Visees[Index:integer]:TRattache read GetVisee write SetVisee;
    property PtFinal:TPedroXYZPoint read FResult1;
    property PtFinal2:TPedroXYZPoint read FResult2;
    property Emq:double read FEmq;
    property Rmq:double read FRmq;
    property TolEmq:double read FTolEmq;
    property TolRmq:double read FTolRmq;
  published
    property PointRecherche:string read FPtRecherche write setPtRecherche;
    property Precision:TRattacheTolerance read FrtPrecision write FrtPrecision;
    property AutoOpen:boolean read FAutoOpen write FAutoOpen;
    property DeleteFileOnDestroy:boolean read FDelete write FDelete;
    property CalculAlti:boolean read FCalculAlti write FCalculAlti;
  end;

procedure Register;
  
implementation

{ TRattache }

constructor TRattache.Create;
begin
	inherited;
	FnVisees:=1;
end;

constructor TRattache.Create(aRattacheType: TRattacheType; Num: string; aX,
  aY, aZ, aData: double; anVisees: integer);
begin
  Create;
  self.FrtType:=aRattacheType;
  Init(Num,aX,aY,aZ,aData,anVisees);
end;

procedure TRattache.Init(Num: string; aX, aY, aZ, aData: double;
  anVisees: integer;aAngleVertical:double);
begin
	FPoint:=Num;
	FX:=aX;
  FY:=aY;
  FZ:=aZ;
  FData:=aData;
  nVisees:=anVisees;
  FAV:=aAngleVertical;
end;

procedure TRattache.Init(aRattacheType: TRattacheType; Num: string; aX, aY,
  aZ, aData: double; anVisees: integer;aAngleVertical:double);
begin
	FrtType:=aRattacheType;
  Init(Num,aX,aY,aZ,aData,anVisees,aAngleVertical);
end;

procedure TRattache.LoadFrom(t: TRattache);
begin
	FPoint:=t.FPoint;
	FX:=t.FX;
	FY:=t.FY;
	FZ:=t.FZ;
	FData:=t.FData;
	FnVisees:=t.FnVisees;
  FAV:=t.FAV;
end;

{ TPedroRattachement }

function TPedroRattachement.Add(Rattache: TRattache): integer;
begin
	result:=FList.Add(Rattache);
end;

procedure TPedroRattachement.Clear;
begin
  FList.Clear;
end;

function TPedroRattachement.Count: integer;
begin
	result:=FList.Count;
end;

constructor TPedroRattachement.Create(AOwner: TComponent);
begin
	inherited Create(AOwner);
  Flist:=TObjectList.Create(true);
  FResult1.X:=0;
  FResult1.Y:=0;
  FResult1.Z:=0;
  FResult2.X:=0;
  FResult2.Y:=0;
  FResult2.Z:=0;
  FFileName:='';
end;

function TPedroRattachement.Delete(Index: integer):boolean;
begin
	result:=false;
	if (FList.Count>0) and (Index>=0) and (Index<FList.Count) then
  begin
	  Flist.Delete(Index);
    result:=true;
  end;
end;

destructor TPedroRattachement.Destroy;
begin
	FList.Clear;
  FList.Destroy;
  if (FDelete) and (fileexists(FFileName)) then SysUtils.DeleteFile(ffilename);
  inherited;
end;

procedure TPedroRattachement.Display(aListView: TListView);
var i:integer;
		t:trattache;
    tl:tlistitem;
begin
	aListView.Clear;
  if FList.Count>0 then
  for i:=0 to FList.Count-1 do
  begin
  	t:=(flist.Items[i]) as TRattache;
    tl:=aListView.Items.Add;
    tl.Caption:=t.FPoint;
    if aListView.SmallImages<>nil then
    tl.SubItems.Add(realtostr(t.FX,4));
    tl.SubItems.Add(realtostr(t.FY,4));
    tl.SubItems.Add(realtostr(t.FZ,4));
    case t.FrtType of
    	rtRelevement:begin
      							 tl.ImageIndex:=0;
								     tl.SubItems.Add('Az='+realtostr(t.Data,5)+' gon');
      						 end;
    	rtMultilateration:begin
      							 tl.ImageIndex:=1;
								     tl.SubItems.Add('D='+realtostr(t.Data,5)+' m');
      						 end;
    	rtIntersection:begin
      							 tl.ImageIndex:=2;
								     tl.SubItems.Add('G='+realtostr(t.Data,5)+' gon');
      						 end;
    end;
    tl.SubItems.Add(inttostr(t.FnVisees));
    tl.SubItems.Add(realtostr(t.FAV,5));
  end;
end;

function TPedroRattachement.GetVisee(Index: integer): TRattache;
begin
	result:=(FList.Items[Index]) as TRattache;
end;

function TPedroRattachement.NewRattache: TRattache;
var t:trattache;
begin
	t:=trattache.Create;
  FList.Add(t);
  result:=t;
end;

procedure TPedroRattachement.setPtRecherche(const Value: string);
begin
	if Value<>FPtRecherche then
  begin
	  FPtRecherche := Value;
    FResult1.Num:=Value;
    FResult2.Num:=Value;
  end;
end;

procedure TPedroRattachement.SetVisee(Index: integer;
  const Value: TRattache);
var t:trattache;
begin
	t:=GetVisee(Index);
  t.LoadFrom(Value);
end;

function TPedroRattachement.Count(aRattacheType: TRattacheType): integer;
var i:integer;
begin
	result:=0;
	if FList.Count>0 then
  for i:=0 to FList.Count-1 do
 	if GetVisee(i).FrtType=aRattacheType then inc(result);
end;

procedure TPedroRattachement.Test;
begin
	Clear;
	newrattache.Init(rtRelevement,'R1', 80546.8200, 57468.7900, 1182.1230, 0.0000, 1, 98.2930);
	newrattache.Init(rtRelevement,'R2', 83695.7100, 58247.3900, 0, 85.5349);
	newrattache.Init(rtRelevement,'R3', 84729.4300, 55546.1200, 0, 156.7302);
	newrattache.Init(rtRelevement,'R4', 79465.3900, 53480.4500, 0, 304.1589);

  newrattache.Init(rtIntersection,'I1', 83695.7100, 58247.3900, 0, 171.6918+64.1521, 3);
  newrattache.Init(rtIntersection,'I2', 84713.5300, 53893.5800, 0, 86.5488+254.8788, 3);
  newrattache.Init(rtIntersection,'I3', 79465.3900, 53480.4500, 493.6810, 326.7314+127.7331, 3, 111.0220);

	newrattache.Init(rtMultilateration,'M1', 80708.4300, 54887.7800, 0, 1739.1090);
	newrattache.Init(rtMultilateration,'M2', 84729.4300, 55546.1200, 1627.398, 2575.1600, 1, 87.6200);
	newrattache.Init(rtMultilateration,'M3', 82102.1400, 54080.6900, 0, 1750.6900);
end;

function TPedroRattachement.GetAtIndex(Index: integer;
  aRattacheType: TRattacheType): TRattache;
var i,cpt:integer;
		t:trattache;
begin
	result:=nil;
	cpt:=-1;
  i:=0;
  while (i<FList.Count) and (cpt<Index) do
  begin
  	t:=GetVisee(i);
    if t.FrtType=aRattacheType then inc(cpt);
    inc(i);
  end;
  if cpt=index then result:=getvisee(i-1);
end;

procedure TPedroRattachement.Calcul(Fichier:string);
var m0,m1,t,ma,m,stok:tpedroxyzpoint;
    i,j,ns,cpt,cptpts,cptrelev,cptinter,cptmulti:integer;
    fich,phr:string;
    g:textfile;
    tpts,Final:tstringlist;
    yop,ok:boolean;
    a,b,ca,alpha,g1,g2,xa,ya,xb,yb,hab,oh,hm,ah,gt,ga,gb,rr,g0a,g0,cc,ck,bc,dy,dv:double;
    cosi,sini,aai,abi,aki,bbi,bki,aam,abm,akm,bbm,bkm,aar,abr,acr,akr,bbr,bcr,bkr,ckr,aa,ab,ac,ak,bb,bk,det,detx,dety,detv,dx:double;
    tra,tra1,tra2,tra3,tra4:trattache;
    ni,nr,nm,nv:integer;
    FAlti:TList;
    h:^TXYZPointEx;
begin
  cpt:=0;
  FFileName:=fichier;
  fich:=fichier;
  if fileexists(fich) then SysUtils.DeleteFile(fich);

  ni:=Count(rtintersection);
  nr:=count(rtRelevement);
  nm:=count(rtMultilateration);
  ok:=false;
  if (nr=0) and (nm=0) and (ni=0) then
  messagedlg('Données inexistantes...',mtwarning,[mbok],0) else
  if (nr<3) and (nm<2) and ((ni<1) or (nr<2)) and ((ni<1) or (nm<1)) then
  messagedlg('Données insuffisantes...',mtwarning,[mbok],0) else
  begin
    nv:=0;
    for i:=0 to ni-1 do nv:=nv+GetAtIndex(i,rtIntersection).FnVisees;


    Final:=tstringlist.Create;

    Final.Add('                                                                RATTACHEMENT');
    Final.Add('');
    Final.Add('Fichier :'+fichier);
    Final.Add('Date : '+dateit);
    Final.Add('');
    Final.Add('-------------------------------------------------------------------------------------------------------------------------------------');
    Final.Add('');
    Final.Add('Nombre de visées de relèvement : '+inttostr(nr));
    if nr>0 then
    begin
      for i:=0 to nr-1 do
      begin
      	tra:=getatindex(i,rtrelevement);
      	Final.Add('Point : '+tra.FPoint+' , X= '+realtostr(tra.FX,4)+'m , Y= '+realtostr(tra.FY,4)+'m , Azimut= '+realtostr(tra.FData,5)+'gon');
      end;
      Final.Add('');
    end;
    Final.Add('Nombre de visées de multilatération : '+inttostr(nm));
    if nm>0 then
    begin
      for i:=0 to nm-1 do 
    	begin
      	tra:=getatindex(i,rtmultilateration);
      	Final.Add('Point : '+tra.FPoint+' , X= '+realtostr(tra.FX,4)+'m , Y= '+realtostr(tra.FY,4)+'m , Distanceance= '+realtostr(tra.FData,4)+'m');
      end;
      Final.Add('');
    end;
    Final.Add('Nombre de visées d''intersection : '+inttostr(ni));
    if ni>0 then
    begin
      for i:=0 to ni-1 do
      begin
      	tra:=getatindex(i,rtintersection);
      	Final.Add('Point : '+tra.FPoint+' , X= '+realtostr(tra.FX,4)+'m , Y= '+realtostr(tra.FY,4)+'m , Gisementement= '+realtostr(tra.FData,4)+'gon , Nb de visées:'+inttostr(tra.FnVisees));
      end;
      Final.Add('');
    end;
    Final.Add('');
    Final.Add('** Calul du point approché **');
    Final.Add('-------------------------------------------');

    if ni>=2 then
    begin
    	tra1:=getatindex(0,rtintersection);
    	tra2:=getatindex(1,rtintersection);
      m0:=intersection(tra1.FX,tra1.FY,tra1.FData,tra2.FX,tra2.FY,tra2.FData);
      Final.Add('1 seule solution pour M0 à partir de 2 visées d''intersection :');
      Final.Add('Calculée avec les points '+tra1.FPoint+' et '+tra1.FPoint);
      Final.Add('');
      Final.Add(' Station '+FPtRecherche+' temporaire');
      Final.Add('    X= '+realtostr(m0.X,4));
      Final.Add('    Y= '+realtostr(m0.Y,4));
      Final.Add('');
      ns:=1;
    end else
    if nr>=3 then
    begin
    	tra1:=getatindex(0,rtrelevement);
    	tra2:=getatindex(1,rtrelevement);
    	tra3:=getatindex(2,rtrelevement);
      a:=tra2.FData-tra1.FData;
      b:=tra3.FData-tra2.FData;
      
      g1:=ArctanG(((tra1.FX-tra2.FX)*CotanG(a)-(tra1.FX-tra3.FX)*CotanG(a+b)+tra2.FY-tra3.FY)/((tra1.FY-tra2.FY)*CotanG(a)-(tra1.FY-tra3.FY)*CotanG(a+b)-(tra2.FX-tra3.FX)));
      g2:=g1+a;
      m0.Y:=tra1.FY+(tra1.FX-tra2.FX-(tra1.FY-tra2.FY)*TanG(g2))/(TanG(g2)-TanG(g1));
      m0.X:=tra1.FX+TanG(g1)*(m0.Y-tra1.FY);
      Final.Add('1 seule solution pour M0 à partir de 3 visées de relèvement :');
      Final.Add('Calculée avec les points '+tra1.FPoint+', '+tra2.FPoint+' et '+tra3.FPoint);
      Final.Add('');
      Final.Add(' Station '+FPtRecherche+' temporaire');
      Final.Add('    X= '+realtostr(m0.X,4));
      Final.Add('    Y= '+realtostr(m0.Y,4));
      Final.Add('');
      ns:=1;
    end else
    if nm>=2 then
    begin
    	tra1:=getatindex(0,rtmultilateration);
    	tra2:=getatindex(1,rtmultilateration);
      
      a:=Distance(tra1.FX,tra1.FY,tra2.FX,tra2.FY);
      b:=Gisement(tra1.FX,tra1.FY,tra2.FX,tra2.FY);
      ca:=(Sqr(tra1.FData)+Sqr(a)-Sqr(tra2.FData))/2/tra1.FData/a;
      alpha:=ArcCosG(ca);
      if alpha<0 then alpha:=alpha+200;
      m0.X:=tra1.FX+tra1.FData*SinG(b+alpha);
      m0.Y:=tra1.FY+tra1.FData*CosG(b+alpha);
      m1.X:=tra1.FX+tra1.FData*SinG(b-alpha);
      m1.Y:=tra1.FY+tra1.FData*CosG(b-alpha);
      Final.Add('2 solutions pour M0 à partir de 2 visées de multilatération :');
      Final.Add('Calculées avec les points '+tra1.FPoint+' et '+tra2.FPoint);
      Final.Add('');
      Final.Add('* M0 (1ère solution)');
      Final.Add('    X= '+realtostr(m0.X,4));
      Final.Add('    Y= '+realtostr(m0.Y,4));
      Final.Add('');
      Final.Add('* M0 (2ème solution)');
      Final.Add('    X= '+realtostr(m1.X,4));
      Final.Add('    Y= '+realtostr(m1.Y,4));
      Final.Add('');
      ns:=2;
    end else
    if (ni>=1) or (nr>2) then
    begin
    	tra:=getatindex(0,rtintersection);
      
      tra1:=getatindex(0,rtrelevement);
      tra2:=getatindex(1,rtrelevement);
      xa:=tra.FX;
      ya:=tra.FY;

      xb:=0;
      yb:=0;

      if (tra1.FX=tra.FX) and (tra1.Y=tra.FY) then
      begin
        xb:=tra2.FX;
        yb:=tra2.FY;
        hab:=tra2.FData-tra2.FData;
      end;
      if (tra2.FX=tra.FX) and (tra2.Y=tra.FY) then
      begin
        xb:=tra1.FX;
        yb:=tra1.FY;
        hab:=tra1.FData-tra2.FData;
      end;
      m0:=intersection(xa,ya,tra.FData,xb,yb,tra.FData+hab);
      Final.Add('1 seule solution pour M0 (1 intersection et 2 relèvements) :');
      Final.Add('Calculée avec les points '+tra1.FPoint+', '+tra2.FPoint+' et '+tra.FPoint);
      Final.Add('');
      Final.Add(' Station '+FPtRecherche+' temporaire');
      Final.Add('    X= '+realtostr(m0.X,4));
      Final.Add('    Y= '+realtostr(m0.Y,4));
      Final.Add('');
      ns:=1;
    end else
    if (ni>=1) or (nm>=1) then
    begin
    	tra1:=getatindex(0,rtintersection);
      tra2:=getatindex(0,rtmultilateration);
      if (tra1.FX<>tra2.FX) or (tra1.FY<>tra2.FY) then
      begin
        xa:=tra1.FX;
        ya:=tra1.FY;
        xb:=tra2.FX;
        yb:=tra2.FY;
        a:=Distance(xa,ya,xb,yb);
        b:=Gisement(xa,ya,xb,yb);
        alpha:=b-(tra1.FData);
        ah:=a*CosG(alpha);
        oh:=a*SinG(alpha);
        if oh>tra2.FData then
        begin
          messagedlg('Pas d''intersection...',mtwarning,[mbok],0);
          exit;
        end;
        hm:=sqrt(sqr(tra2.FData)-sqr(oh));
        m0.X:=tra1.FX+(ah-hm)*SinG(tra1.FData);
        m0.Y:=tra1.FY+(ah-hm)*CosG(tra1.FData);
        m1.X:=tra1.FX+(ah+hm)*SinG(tra1.FData);
        m1.Y:=tra1.FY+(ah+hm)*CosG(tra1.FData);
      end else
      begin
        m0.X:=tra1.FX+tra2.FData*SinG(tra1.FData);
        m0.Y:=tra1.FY+tra2.FData*CosG(tra1.FData);
        m1.X:=tra1.FX-tra2.FData*SinG(tra1.FData);
        m1.Y:=tra1.FY-tra2.FData*CosG(tra1.FData);
      end;
      Final.Add('2 solutions pour M0 (1 intersection et 1 multilatération) :');
      Final.Add('Calculées avec les points '+tra1.FPoint+' et '+tra2.FPoint);
      Final.Add('');
      Final.Add(' Station '+FPtRecherche+' temporaire (1ère solution)');
      Final.Add('    X= '+realtostr(m0.X,4));
      Final.Add('    Y= '+realtostr(m0.Y,4));
      Final.Add('');
      Final.Add(' Station '+FPtRecherche+' temporaire (2ème solution)');
      Final.Add('    X= '+realtostr(m1.X,4));
      Final.Add('    Y= '+realtostr(m1.Y,4));
      Final.Add('');
      ns:=2;
    end else
    if (nr>=2) or (nm>=1) then
    begin
      messagedlg('Pas assez de données...',mtwarning,[mbok],0);
      exit;
    end else
    begin
    	tra1:=getatindex(0,rtrelevement);
    	tra2:=getatindex(1,rtrelevement);
      tra:=getatindex(0,rtmultilateration);
      xa:=tra1.FX;
      ya:=tra1.FY;
      xb:=tra2.FX;
      yb:=tra2.FY;
      b:=Gisement(xa,ya,xb,yb);
      gt:=b+(tra2.FData-tra1.FData);
      xb:=(xa+xb)/2;
      yb:=(ya+yb)/2;
      gb:=b+100;
      ga:=gt-100;
      t:=intersection(xa,ya,ga,xb,yb,gb);
      rr:=sqrt(sqr(xa-t.X)+sqr(ya-t.Y));
      xa:=tra.FX;
      ya:=tra.FY;
      xb:=t.X;
      yb:=t.Y;
      a:=Distance(xa,ya,xb,yb);
      b:=Gisement(xa,ya,xb,yb);
      ca:=(sqr(tra.FData)+sqr(a)-sqr(rr))/2/tra.FData/a;
      alpha:=arcCosG(ca);
      if alpha<0 then alpha:=alpha+200;
      m0.X:=tra.FX+tra.FData*SinG(b+alpha);
      m0.Y:=tra.FY+tra.FData*CosG(b+alpha);
      m0.X:=tra.FX+tra.FData*SinG(b-alpha);
      m0.Y:=tra.FY+tra.FData*CosG(b-alpha);
      Final.Add('2 solutions pour M0 (1 mesure de Distanceance et 2 de relèvement) :');
      Final.Add('Calculées avec les points '+tra1.FPoint+' , '+tra2.FPoint+' et '+tra.FPoint);
      Final.Add('');
      Final.Add(' Station '+FPtRecherche+' temporaire (1ère solution)');
      Final.Add('    X= '+realtostr(m0.X,4));
      Final.Add('    Y= '+realtostr(m0.Y,4));
      Final.Add('');
      Final.Add(' Station '+FPtRecherche+' temporaire (2ème solution)');
      Final.Add('    X= '+realtostr(m1.X,4));
      Final.Add('    Y= '+realtostr(m1.Y,4));
      Final.Add('');
      ns:=2;
    end;

    Final.Add('** Résultats **');
    Final.Add('---------------------');
    if ns=1 then
    begin
      Final.Add('Solution unique');
      Final.Add('');
    end else
    begin
      Final.Add('Deux solutions');
      Final.Add('');
    end;

    {Ligne 499 : Organisation des calculs suivant le nombre de solutions}

    Ftolemq:=(sqrt(2*(nr+ni+nm)-3)+2.58)/sqrt(2*(nr+ni+nm));
    if FrtPrecision=rtOrdinaire then
    begin
      ftolemq:=tolemq*1.7;
      ftolrmq:=12;
    end else
    begin
      ftolemq:=tolemq*0.7;
      ftolrmq:=2.5;
    end;

    for i:=1 to ns do
    begin
      if i=1 then
      begin
        ma.X:=m0.X;
        ma.Y:=m0.Y;
      end else
      begin
        ma.X:=m1.X;
        ma.Y:=m1.Y;
      end;
      xb:=ma.X;
      yb:=ma.Y;

      if nr>=2 then
      begin
        for j:=0 to nr-1 do
        begin
        	tra:=getatindex(j,rtrelevement);
          xa:=tra.FX;
          ya:=tra.FY;
          tra.Tab[5]:=Gisement(xa,ya,xb,yb);
          tra.Tab[6]:=Distance(xa,ya,xb,yb);
        end;
       	tra:=getatindex(0,rtrelevement);
        g0a:=tra.Tab[5]+200-tra.FData;
        if g0a<0 then g0a:=g0a+400 else
        if g0a>=400 then g0a:=g0a-400;
        for j:=0 to nr-1 do
        begin
        	tra:=getatindex(j,rtrelevement);
          a:=g0a-200+tra.FData;
          if a>=400 then a:=a-400 else if a<0 then a:=a+400;
          tra.Tab[4]:=a;
          tra.Tab[7]:=10000*(tra.Tab[4]-tra.Tab[5]);
        end;
      end;

      {Ligne 630}
      if nm>=1 then
      for j:=0 to nm-1 do
      begin
      	tra:=getatindex(j,rtmultilateration);
        xa:=tra.FX;
        ya:=tra.FY;
        a:=Distance(xa,ya,xb,yb);
        b:=Gisement(xa,ya,xb,yb);
        tra.Tab[4]:=b;
        tra.Tab[5]:=a;
        tra.Tab[6]:=1000*(tra.FData-a);
      end;

      {Ligne 650}
      if ni>=1 then
      for j:=0 to ni-1 do
      begin
      	tra:=getatindex(j,rtintersection);
        xa:=tra.FX;
        ya:=tra.FY;
        a:=Distance(xa,ya,xb,yb);
        b:=Gisement(xa,ya,xb,yb);
        tra.Tab[8]:=b;
        tra.Tab[9]:=a;
        tra.Tab[7]:=tra.FData;
        if tra.Tab[7]>400 then tra.Tab[7]:=tra.Tab[7]-400;
        tra.Tab[10]:=10000*(tra.Tab[7]-tra.Tab[8]);
      end;

      {Ligne 700 : Calcul du poids des visées}
      for j:=0 to nm-1 do getatindex(j,rtmultilateration).Tab[7]:=1;
      for j:=0 to nr-1 do getatindex(j,rtrelevement).Tab[8]:=1;
      for j:=0 to ni-1 do
      begin
      	tra:=getatindex(j,rtintersection);
        tra.Tab[11]:=tra.FnVisees;
      end;

      if (ni>=1) and (nm>=1) then
      begin
      	for j:=0 to ni-1 do
        begin
        	tra:=getatindex(j,rtintersection);
        	if FrtPrecision=rtOrdinaire then tra.Tab[11]:=tra.FnVisees/4 else
          	tra.Tab[11]:=tra.FnVisees;
        end;
        for j:=0 to nm-1 do getatindex(j,rtmultilateration).Tab[7]:=1;
      end;

      {Ligne 720}
      if (nr>=2) and (nm>=1) then
      begin
        for j:=0 to nr-1 do getatindex(j,rtrelevement).Tab[8]:=1;
        for j:=0 to nm-1 do
        begin
        	tra:=getatindex(j,rtmultilateration);
        	if FrtPrecision=rtOrdinaire then tra.Tab[7]:=4/(nr-1) else
          	tra.Tab[7]:=1/(nr-1);
        end;
      end;

      {Ligne 750}
      if (ni>=1) and (nr>=2) then
      begin
        for j:=0 to nr-1 do getatindex(j,rtrelevement).Tab[8]:=1;
        for j:=0 to ni-1 do
        begin
        	tra:=getatindex(j,rtintersection);
        	tra.Tab[11]:=tra.FnVisees/(nr-1);
        end;
      end;

      {Ligne 770 : Début de la résolution des moindres carrés}
      aai:=0;
      abi:=0;
      aki:=0;
      bbi:=0;
      bki:=0;
      for j:=0 to ni-1 do
      begin
      	tra:=getatindex(j,rtintersection);
        cosi:=CosG(tra.Tab[8]);
        sini:=SinG(tra.Tab[8]);
        aai:=aai+tra.Tab[11]*sqr(cosi/tra.Tab[9]);
        abi:=abi+tra.Tab[11]*sini*cosi/sqr(tra.Tab[9]);
        aki:=aki+tra.Tab[11]*tra.Tab[10]*cosi/tra.Tab[9];
        bbi:=bbi+tra.Tab[11]*sqr(sini/tra.Tab[9]);
        bki:=bki+tra.Tab[11]*tra.Tab[10]*sini/tra.Tab[9];
      end;

      {Ligne 780}
      aam:=0;
      abm:=0;
      akm:=0;
      bbm:=0;
      bkm:=0;
      for j:=0 to nm-1 do
      begin
      	tra:=getatindex(j,rtmultilateration);
        cosi:=CosG(tra.Tab[4]);
        sini:=SinG(tra.Tab[4]);
        aam:=aam+tra.Tab[7]*sqr(sini/tra.Tab[5]);
        abm:=abm+tra.Tab[7]*sini*cosi/sqr(tra.Tab[5]);
        akm:=akm+tra.Tab[7]*tra.Tab[6]*sini/sqr(tra.Tab[5]);
        bbm:=bbm+tra.Tab[7]*sqr(cosi/tra.Tab[5]);
        bkm:=bkm+tra.Tab[7]*tra.Tab[6]*cosi/sqr(tra.Tab[5])
      end;

      {Ligne 792}
      aar:=0;
      abr:=0;
      acr:=0;
      akr:=0;
      bbr:=0;
      bcr:=0;
      bkr:=0;
      ckr:=0;
      for j:=0 to nr-1 do
      begin
      	tra:=getatindex(j,rtrelevement);
        cosi:=CosG(tra.Tab[5]);
        sini:=SinG(tra.Tab[5]);
        aar:=aar+tra.Tab[8]*sqr(cosi/tra.Tab[6]);
        abr:=abr+tra.Tab[8]*sini*cosi/sqr(tra.Tab[6]);
        acr:=acr+cosi/tra.Tab[6];

        akr:=akr+tra.Tab[8]*tra.Tab[7]*cosi/tra.Tab[6];

        bbr:=bbr+tra.Tab[8]*sqr(sini/tra.Tab[6]);
        bcr:=bcr+sini/tra.Tab[6];

        bkr:=bkr+tra.Tab[8]*tra.Tab[7]*sini/tra.Tab[6];

        ckr:=ckr+tra.Tab[7];
      end;

      {Ligne 900 : Inversion de la matrice}
      aa:=100000000*(aai+aar+aam);
      ab:=100000000*(abm-abi-abr);
      ac:=-50*pi*acr;
      cc:=nr*sqr(pi/200);
      ck:=sqr(pi/200)*ckr;
      ak:=-50*(pi*(aki+akr)+2000*akm);
      bb:=100000000*(bbi+bbr+bbm);
      bc:=bcr*50*pi;
      bk:=50*(pi*(bki+bkr)-2000*bkm);
      if nr<2 then
      begin
        Det:=AA*BB-sqr(AB);
        Detx:=AK*BB-BK*AB;
        Dety:=AA*BK-AB*AK;
      end else
      begin
       Det:=AA*(BB*CC-BC*BC)-AB*(AB*CC-AC*BC)+AC*(AB*BC-AC*BB);
       Detx:=AK*(BB*CC-BC*BC)-AB*(BK*CC-CK*BC)+AC*(BK*BC-CK*BB);
       Dety:=AA*(BK*CC-BC*CK)-AK*(AB*CC-AC*BC)+AC*(AB*CK-AC*BK);
       Detv:=AA*(BB*CK-BC*BK)-AB*(AB*CK-AC*BK)+AK*(AB*BC-AC*BB);
      end;
      dx:=-detx/det;
      dy:=-dety/det;
      dv:=-detv/det;
      m.X:=ma.X+dx;
      m.Y:=ma.Y+dy;
      g0:=g0a+dv/10000;

      {Ligne 930 : Calcul de Emq et Rmq}
      femq:=0;
      frmq:=0;
      for j:=0 to nr-1 do
      begin
      	tra:=getatindex(j,rtrelevement);
        xa:=m.X;
        ya:=m.Y;
        xb:=tra.FX;
        yb:=tra.FY;
        a:=Distance(xa,ya,xb,yb);
        b:=Gisement(xa,ya,xb,yb);
        ga:=b-tra.FData;
        if ga<0 then ga:=ga+400;
        femq:=emq+sqr((ga-g0)*1000);
        frmq:=rmq+sqr(1.57*a*(ga-g0));
      end;

      for j:=0 to nm-1 do
      begin
      	tra:=getatindex(j,rtmultilateration);
      	frmq:=rmq+sqr((sqrt(sqr(m.X-tra.FX)+sqr(m.Y-tra.FY))-tra.FData)*100);
      end;

      for j:=0 to ni-1 do
      begin
      	tra:=getatindex(j,rtintersection);
        xb:=m.X;
        yb:=m.Y;
        xa:=tra.FX;
        ya:=tra.FY;
        a:=Distance(xa,ya,xb,yb);
        b:=Gisement(xa,ya,xb,yb);
        femq:=emq+sqr((tra.Tab[7]-b)*1000);
        frmq:=rmq+sqr((tra.Tab[7]-b)*1.57*a);
      end;

      frmq:=sqrt(rmq/(ni+nr+nm-1));
      femq:=sqrt(emq/(ni+nr+nv-1));

      if ns=2 then Final.Add('Solution '+inttostr(i)+' :');
      Final.Add('Station '+FPtRecherche);
      Final.Add('    X= '+realtostr(m.X,4)+' m');
      Final.Add('    Y= '+realtostr(m.y,4)+' m');
      if nr>=2 then
      begin
        Final.Add('');
        Final.Add('G0 Moyen : '+realtostr(g0,5)+' gon');
      end;
      Final.Add('');
      Final.Add('** Ecarts et tolérances **');
      Final.Add('------------------------------------');
      Final.Add('Emq= '+realtostr(emq,2)+' mgon , Tolérance '+realtostr(tolemq,2)+' mgon');
      Final.Add('Rmq= '+realtostr(rmq,2)+' cm   , Tolérance '+realtostr(tolrmq,2)+' cm');
      if (emq<tolemq) and (rmq<tolrmq) then
      begin
        Final.Add('=>  ** Solution convenable **');
        cpt:=cpt+1;
        stok.X:=m.X;
        stok.y:=m.y;
        case ns of
        	1:begin
              FResult1.X:=m.X;
			        FResult1.Y:=m.Y;
          	end;
        	2:begin
              FResult2.X:=m.X;
			        FResult2.Y:=m.Y;
          	end;
        end;
        ok:=true;
      end else Final.Add('=>  ** Solution non convenable **');

    //Altimétrie
    
	    FAlti:=TList.Create;
			if (((not ok) and (messagedlg('La solution trouvée n''est pas convenable'+#13+#10+'Voulez-vous tout de même calculer l''altimétrie?',mtconfirmation,[mbyes,mbno],0)=mryes)) or (ok)) and (FCalculAlti) then
    	begin
	    	cptrelev:=0;
	  	  cptmulti:=0;
		    cptinter:=0;
    	  for j:=0 to FList.Count-1 do
      	begin
	      	tra:=GetVisee(j);
  	      if tra.FZ<>0 then
    	    case tra.FrtType of
      	  	rtRelevement:inc(cptrelev);
        	  rtMultilateration:inc(cptmulti);
          	rtIntersection:inc(cptinter);
	        end;
  	    end;

		    if (cptrelev>0) or (cptmulti>0) or (cptinter>0) then
  	  	begin
    	  	Final.Add('');
		      Final.Add('** Calul de l''altimétrie **');
    		  Final.Add('-----------------------------------');
		      Final.Add('');
    		  if cptrelev>0 then
		      begin
    		    Final.Add('Nombre de points du relèvement : '+inttostr(cptrelev));
        		for j:=0 to nr-1 do
		        begin
    		    	tra:=getatindex(j,rtrelevement);
        		  if tra.FZ<>0 then
		        		Final.Add('Point : '+tra.FPoint+' , X= '+realtostr(tra.FX,4)+'m , Y= '+realtostr(tra.FY,4)+'m , Z= '+realtostr(tra.FZ,4)+'m, Angle vertical= '+realtostr(tra.FAV,4)+'gon ');
		        end;
 				    Final.Add('');
		      end;

    		  if cptMulti>0 then
		      begin
    		    Final.Add('Nombre de points de la multilatération : '+inttostr(cptMulti));
        		for j:=0 to nm-1 do
		        begin
    		    	tra:=getatindex(j,rtmultilateration);
        		  if tra.FZ<>0 then
		        		Final.Add('Point : '+tra.FPoint+' , X= '+realtostr(tra.FX,4)+'m , Y= '+realtostr(tra.FY,4)+'m , Z= '+realtostr(tra.FZ,4)+'m, Angle vertical= '+realtostr(tra.FAV,4)+'gon ');
		        end;
 				    Final.Add('');
		      end;

    		  if cptInter>0 then
		      begin
    		    Final.Add('Nombre de points de l''intersection : '+inttostr(cptInter));
        		for j:=0 to nm-1 do
		        begin
    		    	tra:=getatindex(j,rtintersection);
        		  if tra.FZ<>0 then
		        		Final.Add('Point : '+tra.FPoint+' , X= '+realtostr(tra.FX,4)+'m , Y= '+realtostr(tra.FY,4)+'m , Z= '+realtostr(tra.FZ,4)+'m, Angle vertical= '+realtostr(tra.FAV,4)+'gon ');
		        end;
    		    Final.Add('');
		      end;

    		  for j:=0 to FList.Count-1 do
		      begin
    		  	tra:=getvisee(j);
        		if tra.FZ<>0 then
		        begin
    		    	new(h);
        		  h^.Num:=tra.FPoint;
		          h^.X:=tra.FX;
    		      h^.Y:=tra.FY;
        		  h^.Z:=tra.FZ;
		          h^.AV:=tra.FAV;
    		      FAlti.Add(h);
        		end;
		      end;
      
    		  Final.Add('Nombre total de points : '+inttostr(FAlti.Count));
		      Final.Add('');
    		  for j:=0 to FAlti.Count-1 do
		      begin
    		  	h:=FAlti.Items[j];
        		h^.Distance:=Distance(h^.X,h^.Y,Fresult1.X,fresult1.Y); //5
		        h^.DZ:=h^.Z-h^.Distance*CotanG(h^.AV); //6
    		  end;
		      a:=0;
    		  b:=0;
		      for j:=0 to FAlti.Count-1 do
    		  begin
      			h:=FAlti.Items[j];
		        a:=a+h^.DZ*h^.Distance;
    		    b:=b+h^.Distance;
		      end;
    		  xa:=a/b;
		      for j:=0 to FAlti.Count-1 do
    		  begin
      			h:=FAlti.Items[j];
		        h^.ZErr:=h^.DZ-xa;
    		  end;
		      Final.Add('-------------------------------------------------------------------------------------------------------------');
    		  Final.Add('Num'+chr(vk_tab)+'Z (m)'+chr(vk_tab)+chr(vk_tab)+'Distanceance (m)'+chr(vk_tab)+'AV (gon)'+chr(vk_tab)+'ZCalc (m)'+chr(vk_tab)+'Z final (m)'+chr(vk_tab)+'e (cm)'+chr(vk_tab)+chr(vk_tab)+'Num');
		      Final.Add('-------------------------------------------------------------------------------------------------------------');
    		  for j:=0 to FAlti.Count-1 do
		      begin
    		  	h:=FAlti.Items[j];
        		phr:=h^.Num+chr(vk_tab);
        		phr:=phr+realtostr(h^.Z,4)+chr(vk_tab);
		        phr:=phr+realtostr(h^.Distance,4)+chr(vk_tab);
            phr:=phr+' '+realtostr(h^.AV,4)+chr(vk_tab);
	  	      phr:=phr+realtostr(h^.DZ,4)+chr(vk_tab);
  	  	    if j=0 then phr:=phr+realtostr(xa,4)+chr(vk_tab) else
		        phr:=phr+'           '+chr(vk_tab);
    		    phr:=phr+realtostr(h^.ZErr*100,4)+chr(vk_tab)+chr(vk_tab)+h^.Num;
        		Final.Add(phr);
		      end;
		      Final.Add('-------------------------------------------------------------------------------------------------------------');
	        case ns of
  	      	1:FResult1.Z:=xa;
    	    	2:FResult2.Z:=xa;
      	  end;
		    end;

      end;
    
    	Final.Add('');
	    Final.Add('** Point définitif **');
  	  Final.Add('---------------------------');
    	Final.Add('');
	    Final.Add('Station : '+FPtRecherche);
      if ns=1 then
      begin
	  	  Final.Add(chr(vk_tab)+'X= '+realtostr(FResult1.X,4)+' m');
	    	Final.Add(chr(vk_tab)+'Y= '+realtostr(FResult1.Y,4)+' m');
      end else
      begin
	  	  Final.Add(chr(vk_tab)+'X= '+realtostr(FResult2.X,4)+' m');
	    	Final.Add(chr(vk_tab)+'Y= '+realtostr(FResult2.Y,4)+' m');
      end;
	    if (FCalculAlti) and (FAlti.Count>0) then
      begin
	      if ns=1 then
	  		  Final.Add(chr(vk_tab)+'Z= '+realtostr(FResult1.Z,4)+' m') else
	  		  Final.Add(chr(vk_tab)+'Z= '+realtostr(FResult2.Z,4)+' m');
      end;
    	Final.Add('');
	    Final.Add(chr(vk_tab)+'G0= '+realtostr(G0,4)+' gon');
   		if FAlti.Count>0 then
	    begin
  		  for j:=0 to FAlti.Count-1 do Dispose(FAlti[j]);
	      FAlti.Clear;
   		end;
	    FAlti.Free;
    end;
  	
    final.SaveToFile(fich);
    final.Free;
		if fautoopen then executefile('NotePad.exe '+fich);
  end;
end;

procedure Register;
begin
  RegisterComponents('PedroComponents', [TPedroRattachement]);
end;

end.
