📄 ezctrls.pas
字号:
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 + -