ezthematics.pas

来自「很管用的GIS控件」· PAS 代码 · 共 1,602 行 · 第 1/4 页

PAS
1,602
字号
Function TEzThematicRanges.Add: TEzThematicItem;
Begin
  Result := TEzThematicItem( Inherited Add );
End;

function TEzThematicRanges.Down( Index: Integer ): Boolean;
begin
  Result:= False;
  if ( Index < 0 ) or ( Index >= Count - 1 ) then Exit;
  GetItem( Index ).Index := Index + 1;
  Result:= True;
End;

function TEzThematicRanges.Up( Index: Integer ): Boolean;
begin
  Result:= False;
  if ( Index <= 0 ) or ( Index > Count - 1 ) then Exit;
  GetItem( Index ).Index := Index - 1;
  Result:= True;
end;

{$IFDEF DELPHI4}
Procedure TEzThematicRanges.Delete(Index: Integer );
Begin
  if ( Index < 0 ) or ( Index > Count - 1 ) then Exit;
  GetItem( Index ).Free;
End;
{$ENDIF}

{-------------------------------------------------------------------------------}
{                  Implements TEzThematicBuilder                                    }
{-------------------------------------------------------------------------------}

Constructor TEzThematicBuilder.Create( AOwner: TComponent );
Begin
  Inherited Create( AOwner );
  FThematicRanges := TEzThematicRanges.Create( Self );
  FPenStyle:= TEzPentool.Create;
  FBrushStyle:= TEzBrushtool.Create;
  FFontStyle:= TEzFonttool.Create;
  FSymbolStyle:= TEzSymboltool.Create;
  FApplyPen:=false;
  FApplyBrush:=false;
  FApplyColor:=true;
  FApplySymbol:=false;
  FApplyFont:=false;
  FShowThematic:= True;
End;

Destructor TEzThematicBuilder.Destroy;
Begin
  FThematicRanges.Free;
  FPenStyle.free;
  FBrushStyle.Free;
  FFontStyle.Free;
  FSymbolStyle.Free;
  if FExprList <> Nil then
    EndThematic;
  Inherited Destroy;
End;

function TEzThematicBuilder.GetAbout: TEzAbout;
begin
  Result:= SEz_GisVersion;
end;

procedure TEzThematicBuilder.SetAbout(const Value: TEzAbout);
begin
end;

procedure TEzThematicBuilder.Assign(Source: TPersistent);
begin
  if Source is TEzThematicBuilder then
  begin
    LayerName := TEzThematicBuilder( Source ).LayerName;
    ThematicRanges.Assign( TEzThematicBuilder( Source ).ThematicRanges );
    Title := TEzThematicBuilder( Source ).Title;
    ShowThematic := TEzThematicBuilder( Source ).ShowThematic;
    ApplyPen := TEzThematicBuilder( Source ).ApplyPen;
    ApplyBrush:= TEzThematicBuilder( Source ).ApplyBrush;
    ApplySymbol:= TEzThematicBuilder( Source ).ApplySymbol;
    ApplyFont := TEzThematicBuilder( Source ).ApplyFont;
  end else
    inherited Assign( Source );
end;

const
  ThematicFileID = 890504;

procedure TEzThematicBuilder.SaveToStream(Stream: TStream);
var
  I, n, IDFile: Integer;
begin
  IDFile:= ThematicFileID;
  with Stream do
  begin
    Write(IDFile,sizeof(IDFile));
    EzWriteStrToStream( FTitle, stream );
    EzWriteStrToStream( FLayerName, stream );
    Write(FShowThematic,sizeof(FShowThematic));
    Write(FApplyPen,sizeof(FApplyPen));
    Write(FApplyBrush,sizeof(FApplyBrush));
    Write(FApplySymbol,sizeof(FApplySymbol));
    Write(FApplyFont,sizeof(FApplyFont));

    n:= ThematicRanges.Count;
    Write(n,sizeof(n));
    for I:= 0 to n-1 do
    begin
      with ThematicRanges[I] do
      begin
        EzWriteStrToStream( FLegend, stream );
        EzWriteStrToStream( FExpression, stream );
        Write(FFrequency,sizeof(FFrequency));
        FPenStyle.SaveToStream(Stream);
        FBrushStyle.SaveToStream(Stream);
        FSymbolStyle.SaveToStream(Stream);
        FFontStyle.SaveToStream(Stream);
      end;
    end;
  end;
end;

procedure TEzThematicBuilder.LoadFromStream(Stream: TStream);
var
  I, n, IDFile: Integer;
begin
  ThematicRanges.Clear;
  with Stream do
  begin
    Read(IDFile,sizeof(IDFile));
    if IDFile <> ThematicFileID then Exit;
    FTitle:= EzReadStrFromStream( stream );
    FLayerName:= EzReadStrFromStream( stream );
    Read(FShowThematic,sizeof(FShowThematic));
    Read(FApplyPen,sizeof(FApplyPen));
    Read(FApplyBrush,sizeof(FApplyBrush));
    Read(FApplySymbol,sizeof(FApplySymbol));
    Read(FApplyFont,sizeof(FApplyFont));

    Read(n,sizeof(n));
    for I:= 0 to n-1 do
    begin
      with ThematicRanges.Add do
      begin
        FLegend:= EzReadStrFromStream( stream );
        FExpression:= EzReadStrFromStream( stream );
        Read(FFrequency,sizeof(FFrequency));
        FPenStyle.LoadFromStream(Stream);
        FBrushStyle.LoadFromStream(Stream);
        FSymbolStyle.LoadFromStream(Stream);
        FFontStyle.LoadFromStream(Stream);
      end;
    end;
  end;
end;

procedure TEzThematicBuilder.LoadFromFile( const FileName: string );
var
  stream: TStream;
begin
  if not FileExists(FileName) then exit;
  stream:= TFileStream.create(FileName, fmOpenRead or fmShareDenyNone);
  try
    LoadFromStream(stream);
  finally
    stream.free;
  end;
end;

procedure TEzThematicBuilder.SaveToFile( const FileName: string );
var
  stream: TStream;
begin
  stream:= TFileStream.Create(FileName, fmCreate);
  try
    SaveToStream(stream);
  finally
    stream.free;
  end;
end;

Procedure TEzThematicBuilder.SetThematicRanges( Value: TEzThematicRanges );
Begin
  FThematicRanges.Assign( Value );
End;

Function TEzThematicBuilder.StartThematic( Layer: TEzBaseLayer ): Boolean;
Var
  MainExpr: TEzMainExpr;
  I: Integer;
Begin
  Result:= False;
  if (FThematicRanges.Count = 0) Or (Layer = Nil) Or Not (Layer.LayerInfo.Visible) then Exit;
  EndThematic;
  FExprList := TList.Create;
  Try
    For I := 0 To FThematicRanges.Count - 1 Do
    Begin
      if Length(FThematicRanges[I].Expression) = 0 then
        Raise EExpression.Create( SExprFail )
      else
      begin
        // evaluate expression
        MainExpr := TEzMainExpr.Create( Layer.Layers.Gis, Layer );
        MainExpr.ParseExpression( FThematicRanges[I].Expression );
        If ( MainExpr.Expression <> Nil ) And
           ( MainExpr.Expression.ExprType <> ttBoolean ) Then
        Begin
          MainExpr.Free;
          Raise EExpression.Create( SExprFail );
        End;
        If MainExpr.Expression <> Nil Then
          FExprList.Add( MainExpr )
        Else
        begin
          MainExpr.Free;
          Raise EExpression.Create( SExprFail );
        end;
      end;
    End;
  Except
    Self.FShowThematic := False;
    EndThematic;
    Raise;
  End;
  Result := True;
End;

Function TEzThematicBuilder.CalcThematicInfo( Layer: TEzBaseLayer; Recno: Integer ): Boolean;
Var
  I: Integer;
Begin
  Result:= False;
  If Layer.Recno <> Recno Then
    Layer.Recno := Recno;
  Layer.Synchronize;
  For I := 0 To FExprList.Count - 1 Do
    If TEzMainExpr(FExprList[I]).Expression.AsBoolean = true Then
      Begin
        Self.FPenStyle.Assign( FThematicRanges[I].PenStyle );
        Self.FBrushstyle.Assign( FThematicRanges[I].BrushStyle );
        Self.FSymbolstyle.Assign( FThematicRanges[I].SymbolStyle );
        Self.FFontStyle.Assign( FThematicRanges[I].FontStyle );
        Result:= True;
        Exit;
      End;
End;

Procedure TEzThematicBuilder.EndThematic;
var
  I: Integer;
Begin
  if FExprList = Nil then Exit;
  for I:= 0 to FExprList.Count - 1 do
    TEzMainExpr( FExprList[I] ).Free;
  FreeAndNil( FExprList );
End;

procedure TEzThematicBuilder.Recalculate( Gis: TEzBaseGis );
var
  Layer: TEzBaseLayer;
  I: Integer;
begin
  Layer:= Gis.Layers.LayerByName( FLayerName );
  if Layer = Nil then Exit;
  if Not StartThematic( Layer ) then Exit;
  for I:= 0 to FThematicRanges.Count-1 do
    FThematicRanges[I].FFrequency:= 0;
  Screen.Cursor:= crHourglass;
  try
    Layer.First;
    Layer.StartBuffering;
    Try
      While Not Layer.Eof Do
      Begin
        Try
          If Layer.RecIsDeleted Then Continue;
          Layer.Synchronize;
          For I := 0 To FExprList.Count - 1 Do
            If TEzMainExpr(FExprList[I]).Expression.AsBoolean = true Then
              Begin
                Inc( FThematicRanges[I].FFrequency );
                Break;
              End;
        Finally
          Layer.Next;
        End;
      End;
    Finally
      Layer.EndBuffering;
    End;
  finally
    EndThematic;
    Screen.Cursor:= crDefault;
  end;
end;

Procedure TEzThematicBuilder.Prepare( Layer: TEzBaseLayer );
Begin
  If FShowThematic And ( AnsiCompareText( Layer.Name, Self.FLayerName ) = 0 ) then
  begin
    FThematicOpened := Self.StartThematic( Layer );

    If FThematicOpened then
    begin
      //FSaveBeforePaintEntity := Layer.OnBeforePaintEntity;
      //FIsBeforePaintEntity := Assigned( FSaveBeforePaintEntity );

      Layer.OnBeforePaintEntity := Self.BeforePaintEntity;
    end;
  end;
End;

Procedure TEzThematicBuilder.UnPrepare( Layer: TEzBaseLayer );
Begin
  If FThematicOpened And ( AnsiCompareText( Layer.Name, Self.FLayerName ) = 0 ) then
  begin
    EndThematic;
    //Layer.OnBeforePaintEntity := FSaveBeforePaintEntity;
    Layer.OnBeforePaintEntity := Nil;
  end;
  FThematicOpened := False;
End;

Procedure TEzThematicBuilder.BeforePaintEntity( Sender: TObject;
  Layer: TEzBaseLayer; Recno: Integer; Entity: TEzEntity;
  Grapher: TEzGrapher; Canvas: TCanvas; Const Clip: TEzRect;
  DrawMode: TEzDrawMode; Var CanShow: Boolean; Var EntList: TEzEntityList;
  Var AutoFree: Boolean );
Begin
  { call the old event handler }
  {If FIsBeforePaintEntity And (FSaveBeforePaintEntity <> BeforePaintEntity) Then
    FSaveBeforePaintEntity( Sender, Layer, Recno, Entity, Grapher, Canvas,
      Clip, DrawMode, CanShow ); }
  if not CanShow then Exit;

  With Layer Do
  Begin
    If FThematicOpened And ( Entity.EntityID In [idPoint, idPlace,
      idPolyline, idPolygon, idRectangle, idArc, idEllipse, idSpline] ) Then
    Begin
      if not Self.CalcThematicInfo( Layer, Recno ) then Exit;

      if (Entity is TEzOpenedEntity) and FApplyPen then
      begin
        TEzOpenedEntity(Entity).Pentool.Assign(Self.FPenstyle);
      end;
      if Entity is TEzClosedEntity and FApplyBrush then
      begin
        TEzClosedEntity(Entity).Brushtool.Assign(Self.FBrushstyle);
      end;
      if (Entity.EntityID = idPoint) and FApplyPen then
      begin
        TEzPointEntity(Entity).Color:= Self.FPenstyle.Color;
      end;
      if (Entity.EntityID = idPlace) and FApplySymbol then
      begin
        TEzPlace(Entity).Symboltool.Assign( Self.FSymbolStyle );
      end;
      if (Entity.EntityID = idTrueTypeText) and FApplyFont then
      begin
        TEzTrueTypeText(Entity).Fonttool.Assign( Self.FFontStyle );
      end;
      if (Entity.EntityID = idJustifVectText) and FApplyFont then
      begin
        with TEzJustifVectorText(Entity) do
        begin
          FontName:= self.FFontStyle.Name;
          Height:= self.FFontStyle.Height;
          Fontcolor:= self.FFontStyle.Color;
        end;
      end;
      if (Entity.EntityID = idFittedVectText) and FApplyFont then
      begin
        with TEzFittedVectorText(Entity) do
        begin
          FontName:= self.FFontStyle.Name;
          Height:= self.FFontStyle.Height;
          Fontcolor:= self.FFontStyle.Color;
        end;
      end;
    End;
  End;
End;

{ for string fields only }
Procedure TEzThematicBuilder.CreateAutomaticThematicRangeStrField( Gis: TEzBaseGis;
  const ThematicLayer, FieldName: String;
  BrushStartColor, BrushStopColor: TColor; BrushPattern: Integer;
  LineStartColor, LineStopColor: TColor; LineStyle: Integer; AutoLineWidth: Boolean );
var
  Layer: TEzBaseLayer;
  DiscreteValues: TStrings;
  EdExpr, TmpStr, Pivot, Value: string;
  Cnt, NumRanges, Index: Integer;
  BeginColor, EndColor, StepColor: TColor;
  LineBeginColor, LineEndColor, LineStepColor: TColor;
  R, G, B: Byte;
  BeginRGBValue, LineBeginRGBValue: Array[0..2] Of Byte;
  RGBDiff, LineRGBDiff: Array[0..2] Of Integer;

⌨️ 快捷键说明

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