⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ezctrls.pas

📁 很管用的GIS控件
💻 PAS
📖 第 1 页 / 共 5 页
字号:
      finally
        free;
      end;

    FDBTable := EzBaseGIS.BaseTableClass.Create( Gis, AFilename, Not GIS.ReadOnly, true );
    With FDBTable Do
    Begin
      SetUseDeleted( true );
      //Index( AFileName, '' );
    End;
  End;
End;

Function TEzLayer.GetActive: Boolean;
Begin
  Result := FEzDStream <> Nil;
End;

Procedure TEzLayer.SetActive( Value: Boolean );
Begin
  If Value Then Open Else Close;
End;

Procedure TEzLayer.Close;
Var
  EzxHeader: TEzxData;
  I: Integer;
  sl: TStringList;
  ReadOnly: Boolean;
  Gis: TEzBaseGIS;
Begin
  ReadOnly:= Layers.GIS.ReadOnly;
  Gis:= Layers.Gis;

  If Active Then
  Begin
    If Not ReadOnly And Modified Then
    Begin
      FEzDStream.Seek( 0, 0 );
      FEzDStream.Write( FHeader, SizeOf( TEzLayerHeader ) );
    End;
    FreeAndNil( FEzDStream );
    FreeAndNil( FBuffEnt );
  End;
  If FEzXStream <> Nil Then
  Begin
    If Not ReadOnly And Modified Then
    Begin
      FEzXStream.Seek( 0, 0 );
      FEzXStream.Read( EzxHeader, SizeOf( TEzxData ) );
      EzxHeader.RecordCount := FHeader.RecordCount;
      FEzXStream.Seek( 0, 0 );
      FEzXStream.Write( EzxHeader, SizeOf( TEzxData ) );
    End;
    FreeAndNil( FEzXStream );
  End;
  { save the projection information on file xxx.apj }
  sl := TStringList.Create;
  Try
    sl.Add( '[Projection]' );
    sl.Add( 'CoordSystem=' + IntToStr( Ord( GIS.MapInfo.CoordSystem ) ) );
    sl.Add( 'CoordsUnits=' + IntToStr( Ord( GIS.MapInfo.CoordsUnits ) ) );
    For I := 0 To GIS.ProjectionParams.Count - 1 Do
      sl.Add( GIS.ProjectionParams[I] );
    sl.SaveToFile( FileName + EPJEXT );
  Finally
    sl.free;
  End;
  // free the r-tree
  If Frt <> Nil Then FreeAndNil( Frt );
  If FDBTable <> Nil Then FreeAndNil( FDBTable );
  Modified := false;
End;

Procedure TEzLayer.ForceOpened;
Begin
  If FEzDStream = Nil Then Open;
End;

Procedure TEzLayer.WriteHeaders( FlushFiles: Boolean );
Var
  EzxData: TEzxData;
  Readonly: Boolean;
Begin
  Readonly:= Layers.GIS.ReadOnly;

  If ReadOnly Or ( FEzDStream = Nil ) Then
  Begin
    Modified := false;
    Exit;
  End;

  If Modified Then
  Begin
    FEzDStream.Seek( 0, 0 );
    FEzDStream.Write( FHeader, SizeOf( TEzLayerHeader ) );
    If FlushFiles Then
    Begin
      Windows.FlushFileBuffers( TFileStream( FEzDStream ).Handle );
    End;
  End;
  If FEzXStream <> Nil Then
  Begin
    FEzXStream.Seek( 0, 0 );
    FEzXStream.Read( EzxData, SizeOf( TEzxData ) );
    EzxData.RecordCount := FHeader.RecordCount;
    FEzXStream.Seek( 0, 0 );
    FEzXStream.Write( EzxData, SizeOf( TEzxData ) );
    If FlushFiles Then
    Begin
      Windows.FlushFileBuffers( TFileStream( FEzXStream ).Handle );
    End;
  End;
  If ( Frt <> Nil ) And FlushFiles Then Frt.FlushFiles;

  If ( FDBTable <> Nil ) And FlushFiles Then FDBTable.FlushDB;
  Modified := false;
End;

Procedure TEzLayer.UpdateMapExtension( Const R: TEzRect );
Var
  MapExt: TEzRect;
Begin
  { New map extension }
  With Layers.GIS Do
  Begin
    MapExt := MapInfo.Extension;
    MaxBound( MapExt.Emax, R.Emax );
    MinBound( MapExt.Emin, R.Emin );
    MapInfo.Extension := MapExt;
    Modified := true;
  End;
End;

// this function will return the recno of the added entity

Function TEzLayer.AddEntity( Entity: TEzEntity ): Integer;
Var
  EzxData, EzxHeader: TEzxData;
  TmpID: TEzEntityID;
  NewRecNo: Integer;
  TmpSize: Longint;
  RecordSize: Integer;
Begin
  result := 0;
  ForceOpened;
  If Layers.GIS.ReadOnly Or ( FEzDStream = Nil ) Or LayerInfo.Locked Then Exit;

  NormalizePolygon( Entity );

  ReReadEntHeader;

  TmpID := Entity.EntityID;

  With EzxData Do
  Begin
    Offset := FEzDStream.Size;
    EntityID := TmpID;
    IsDeleted := false;
    Extension := Entity.FBox;
  End;
  With FHeader.Extension Do
  Begin
    MaxBound( Emax, EzxData.Extension.Emax );
    MinBound( Emin, EzxData.Extension.Emin );
  End;

  //TmpSize := FEzXStream.Size;
  //NewRecNo := TmpSize div SizeOf(TEzxData);
  NewRecno := FHeader.RecordCount + 1;
  TmpSize := NewRecno * SizeOf( TEzxData );

  If FProposedID = 0 Then
  Begin
    Inc( FHeader.IDCounter );
    { Entity.ID solo se usa en caso de que se necesite un identificador
      unico para cada entidad. De otra manera, se utilizara el numero de
      registro fisico como identificador en una base de datos que no
      soporta registro fisico.
    }
    Entity.ID := FHeader.IDCounter;
  End
  Else
    Entity.ID := FProposedID;
  FProposedID := 0;
  If FDBTable <> Nil Then
  Begin
    FDBTable.Append( NewRecno );
  End;
  FEzXStream.Seek( TmpSize, 0 );
  FEzXStream.Write( EzxData, SizeOf( TEzxData ) );

  RecordSize := 0;
  With FEzDStream Do
  Begin
    Seek( EzxData.Offset, 0 );
    Write( RecordSize, SizeOf( Integer ) );
    Write( RecordSize, SizeOf( Integer ) );
    Write( EzxData.EntityID, SizeOf( TEzEntityID ) );
    Write( EzxData.IsDeleted, SizeOf( Boolean ) );
    Entity.SaveToStream( FEzDStream );
    RecordSize := Position - EzxData.Offset;
    Seek( EzxData.Offset, 0 );
    Write( RecordSize, SizeOf( Integer ) );
    Write( RecordSize, SizeOf( Integer ) );
  End;

  // re-write to disk the header of .Enx file
  With FEzXStream Do
  Begin
    Seek( 0, 0 );
    Read( EzxHeader, SizeOf( TEzxData ) );
    EzxHeader.RecordCount := NewRecno;
    EzxHeader.MaxRecSize := EzLib.IMax( EzxHeader.MaxRecSize, RecordSize );
    Seek( 0, 0 );
    Write( EzxHeader, SizeOf( TEzxData ) );
  End;
  FreeAndNil( FBuffEnt );

  // add to the r-tree
  If ( TmpID <> idNone ) And FUpdateRTree And FHeader.IsIndexed Then
    Frt.Insert( FloatRect2Rect( EzxData.Extension ), NewRecno );

  FHeader.RecordCount := NewRecNo;
  With FEzDStream Do
  Begin // re-write to disk
    Seek( 0, 0 );
    Write( FHeader, SizeOf( TEzLayerHeader ) );
  End;

  Result := NewRecno;

  UpdateMapExtension( EzxData.Extension );
  
  If AutoFlush Then
    WriteHeaders( True );
End;

Procedure TEzLayer.UndeleteEntity( RecNo: Integer );
Var
  EzxData: TEzxData;
  TmpDeleted: Boolean;
Begin
  If Layers.GIS.ReadOnly Or ( FEzDStream = Nil ) Or LayerInfo.Locked Or
    ( RecNo < 1 ) Or ( RecNo > FHeader.RecordCount ) Then Exit;


  { Undelete first in the ENX file }
  With FEzXStream Do
  Begin
    Seek( RecNo * SizeOf( TEzxData ), 0 );
    Read( EzxData, SizeOf( TEzxData ) );
    EzxData.IsDeleted := false;
    Seek( RecNo * SizeOf( TEzxData ), 0 );
    Write( EzxData, SizeOf( TEzxData ) );
  End;
  { now in the ENT file. A deleted record is
    marked in the two files for rebuilding of ENX file purposes }
  TmpDeleted := False;
  With FEzDStream Do
  Begin
    Seek( EzxData.Offset + SizeOf( Integer ) * 2 + SizeOf( TEzEntityID ), 0 );
    Write( TmpDeleted, SizeOf( Boolean ) );
  End;

  FreeAndNil( FBuffEnt );

  // add to the r-tree
  If ( EzxData.EntityID <> idNone ) And FHeader.IsIndexed Then
    Frt.Insert( FloatRect2Rect( EzxData.Extension ), Recno );

  {now undelete the DBF record}
  If FDBTable <> Nil Then
  Begin
    FDBTable.SetTagTo( '' );
    FDBTable.Recno:= RecNo;
    FDBTable.Recall;
    FDBTable.Refresh;
  End;
  UpdateMapExtension( EzxData.Extension );
End;

Procedure TEzLayer.DeleteEntity( RecNo: Integer );
Var
  EzxData: TEzxData;
  TmpDeleted: Boolean;
  Entity: TEzEntity;
Begin
  If Layers.GIS.ReadOnly Or ( FEzDStream = Nil ) Or LayerInfo.Locked Then Exit;

  { First, mark deleted flag in Enx file }
  FEzXStream.Seek( RecNo * SizeOf( TEzxData ), 0 );
  FEzXStream.Read( EzxData, SizeOf( TEzxData ) );
  If EzxData.IsDeleted Then Exit;

  { for nodes and nodelinks }
  If EzxData.EntityID = idNode then
  begin
    Entity:= LoadEntityWithRecno( Recno );
    Try
      TEzNode( Entity ).BeforeDelete( Recno, Self );
    Finally
      Entity.Free;
    end;
  end else If EzxData.EntityID = idNodeLink then
  begin
    Entity:= LoadEntityWithRecno( Recno );
    Try
      TEzNodeLink( Entity ).BeforeDelete( Recno, Self );
    Finally
      Entity.Free;
    end;
  end;

  EzxData.IsDeleted := true;
  FEzXStream.Seek( RecNo * SizeOf( TEzxData ), 0 );
  FEzXStream.Write( EzxData, SizeOf( TEzxData ) );
  // now write to the .ENT file
  With FEzDStream Do
  Begin
    Seek( EzxData.Offset + sizeof( Integer ) * 2 + sizeof( TEzEntityID ), 0 );
    TmpDeleted := True;
    Write( TmpDeleted, SizeOf( Boolean ) );
  End;

  FreeAndNil( FBuffEnt );
  // Delete from r-tree
  If ( EzxData.EntityID <> idNone ) And FHeader.IsIndexed Then
  Begin
    Try
      Frt.Delete( FloatRect2Rect( EzxData.Extension ), Recno );
    Except
      MessageToUser( 'record ' + inttostr( Recno ), smsgerror, MB_ICONERROR );
      Raise;
    End;
  End;

  { now delete the DBF record }
  If FDBTable <> Nil Then
  Begin
    FDBTable.SetTagTo( '' );
    FDBTable.RecNo := RecNo;
    FDBTable.Delete;
  End;
  Modified := True;
  If AutoFlush Then
    WriteHeaders( True );
  Modified := False;
End;

Procedure TEzLayer.ReReadEntHeader;
Begin
  If FEzDStream = Nil Then Exit;

  With FEzDStream Do
  Begin
    Seek( 0, 0 );
    If Modified And Not Layers.GIS.ReadOnly Then
      Write( FHeader, SizeOf( TEzLayerHeader ) )
    Else
      Read( FHeader, SizeOf( TEzLayerHeader ) );
  End;
  Modified := false;
End;

Function TEzLayer.QuickUpdateExtension: TEzRect;
Var
  cnt, RecCount: Integer;
  EzxData: TEzxData;
  Gis: TEzBaseGIS;
Begin
  Assert( Not FFiltered, SFilterEnabled );

  GIS := Layers.GIS;
  If GIS.ReadOnly Then Exit;
  ForceOpened;

  Result := INVALID_EXTENSION;

  RecCount := Self.RecordCount;
  If RecCount > 0 Then
    GIS.StartProgress( Format( SUpdateExtension, [Name] ), 1, RecCount );
  Try
    For cnt := 1 To RecCount Do
    Begin
      GIS.UpdateProgress( cnt );
      FEzXStream.Seek( cnt * SizeOf( EzxData ), 0 );
      FEzXStream.Read( EzxData, SizeOf( TEzxData ) );
      If EzxData.IsDeleted Then Continue;

      MaxBound( Result.Emax, EzxData.Extension.Emax );
      MinBound( Result.Emin, EzxData.Extension.Emin );
    End;
  Finally
    If RecCount > 0 Then
      GIS.EndProgress;
  End;
  Modified := true;
  FHeader.Extension := Result;
  If AutoFlush Then
    WriteHeaders( True );
End;

Function TEzLayer.UpdateExtension: TEzRect;
Var
  cnt, RecCount: Integer;
  EzxData: TEzxData;
  Entity: TEzEntity;
  GIS: TEzBaseGIS;
Begin
  Assert( Not FFiltered, SFilterEnabled );

  GIS := Layers.GIS;
  If GIS.ReadOnly Then Exit;
  ForceOpened;
  Result := INVALID_EXTENSION;
  //FHeader.RecordCount := Pred(FEzXStream.Size div SizeOf(TEzxData));
  RecCount := Self.RecordCount;
  If RecCount > 0 Then
    GIS.StartProgress( Format( SUpdateExtension, [Name] ), 1, RecCount );
  Try
    For cnt := 1 To RecCount Do
    Begin
      GIS.UpdateProgress( cnt );
      FEzXStream.Seek( cnt * SizeOf( EzxData ), 0 );
      FEzXStream.Read( EzxData, SizeOf( TEzxData ) );
      If Not EzxData.IsDeleted Then
      Begin
        BuffEnt.Seek( EzxData.Offset, 0 );
        Entity := InternalLoadEntity( EzxData.EntityID, BuffEnt );
        EzxData.Extension := Entity.FBox;
        if Entity.EntityID = idNone then
          EzxData.Extension := Result;
        Entity.Free;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -