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

📄 ezgraphics.pas

📁 很管用的GIS控件
💻 PAS
📖 第 1 页 / 共 5 页
字号:
            ClipRes := ClipLineUpBottom2D( Clip, TmpPt1.X, TmpPt1.Y, TmpPt2.X, TmpPt2.Y );
            If Not ( ccNotVisible In ClipRes ) Then
            Begin
              TmpPts^[VisPoints] := TmpPt1;
              Inc( VisPoints );
            End;
            If ccSecond In ClipRes Then
            Begin
              TmpPts^[VisPoints] := TmpPt2;
              Inc( VisPoints );
            End;
          End;
        End;
        If VisPoints > 1 Then
        Begin
          { save to total array of points }
          For cnt := 0 To VisPoints - 1 Do
          Begin
            EntPts^[n1] := TmpPts^[cnt];
            Inc( n1 );
          End;
          Parts^[PartCount] := PartStart;
          Inc( PartStart, VisPoints );
          Inc( PartCount );
        End;
        If Ent.Points.Parts.Count < 2 Then
          Break;
        Inc( n );
        If n >= Ent.Points.Parts.Count Then
          Break;
        Idx1 := Ent.Points.Parts[n];
        If n < Ent.Points.Parts.Count - 1 Then
          Idx2 := Ent.Points.Parts[n + 1] - 1
        Else
          Idx2 := Ent.Points.Count - 1;
      Until False;
      Ent.Points.Clear;
      If PartCount > 1 Then
        For cnt := 0 To PartCount - 1 Do
          Ent.Points.Parts.Add( Parts^[cnt] );
      For cnt := 0 To n1 - 1 Do
        Ent.Points.Add( EntPts^[cnt] );
    Finally
      FreeMem( TmpPts, TmpSize );
      FreeMem( FirstClipPts, TmpSize );
      FreeMem( EntPts, TmpSize * 2 );
      FreeMem( Parts, PartSize );
    End;
  End;

  Procedure AddToNewLayer( ALayer: TEzBaseLayer; ARecno: Integer );
  Var
    TmpEntity, WorkEnt, clipent, rsltent: TEzEntity;
    TheRecno, I, J, n, PartCount: Integer;
    Pass, MustFree: Boolean;
    subject, clipping, rslt: TEzEntityList;
    EntityID: TEzEntityID;
  Begin
    Try
      With DrawBox, ALayer Do
      Begin
        EntityID := RecEntityID;
        TmpEntity := Entities[EntityID];
        RecLoadEntity2( TmpEntity );
        // clip the entity
        Pass := False;
        MustFree := False;
        WorkEnt := TmpEntity;
        If hasClippedThis Then
          Pass := True
            // clipped the selected entities (not need to clip against anything)
        Else If DrawBox.Gis.MapInfo.IsAreaClipped Then
        Begin
          // first check if entity is inside area clipped
          If Not IsBoxInBox2D( WorkEnt.FBox, WCRect ) Then Exit;
          // detect the entities that can be clipped
          If EntityID In [idPolyline, idPolygon, idRectangle, idArc, idEllipse, idSpline] Then
          Begin
            If DrawBox.Gis.MapInfo.ClipAreaKind = cpkPolygonal Then
            Begin
              // clip to a polygonal area
              If WorkEnt.IsClosed Then
              Begin
                If Not ( EntityID = idPolygon ) Then
                Begin
                  WorkEnt := TEzPolygon.CreateEntity( [Point2D( 0, 0 )] );
                  WorkEnt.Points.Assign( TmpEntity.DrawPoints );
                  TEzClosedEntity( WorkEnt ).Pentool.Assign( TEzClosedEntity( TmpEntity ).Pentool );
                  TEzClosedEntity( WorkEnt ).Brushtool.assign( TEzClosedEntity( TmpEntity ).Brushtool );
                  MustFree := True;
                End;
                subject := TEzEntityList.Create;
                clipping := TEzEntityList.Create;
                rslt := TEzEntityList.Create;
                clipent := DrawBox.CreateEntity( idPolygon );
                Try
                  clipent.Points.Assign( DrawBox.Gis.ClipPolygonalArea );
                  clipping.add( clipent );
                  subject.add( WorkEnt );
                  PolygonClip( pcINT, subject, clipping, rslt, Nil );
                  For I := 0 To rslt.count - 1 Do
                    With TEzEntity( rslt[I] ) Do
                      If Not EzLib.EqualPoint2D( Points[0],
                        Points[Points.Count - 1] ) Then
                        Points.Add( Points[0] );
                  WorkEnt.Points.Clear;
                  PartCount := 0;
                  For I := 0 To rslt.count - 1 Do
                  Begin
                    rsltent := TEzEntity( rslt[I] );
                    n := rsltent.Points.Count;
                    For J := 0 To n - 1 Do
                      WorkEnt.Points.add( rsltent.Points[J] );
                    WorkEnt.Points.Parts.Add( PartCount );
                    Inc( PartCount, n );
                  End;
                  With WorkEnt.Points.Parts Do
                    If Count < 2 Then
                      Clear;
                Finally
                  clipent.free;
                  subject.free;
                  clipping.free;
                  rslt.free;
                  //rslt.free;
                End;
              End
              Else
              Begin
                // warning: the entity is clipped against the bounding box of
                // the polygonal defined in this release
                {clipent:= DrawBox.CreateEntity(idPolygon);
                try
                   clipent.Points.Assign(DrawBox.Gis.FClipPolygonalArea);
                   if TmpEntity.IsInsideEntity(clipent,false) then }
                If Not ( EntityID = idPolyline ) Then
                Begin
                  WorkEnt := TEzPolyline.CreateEntity( [Point2D( 0, 0 )] );
                  WorkEnt.Points.Assign( TmpEntity.DrawPoints );
                  TEzClosedEntity( WorkEnt ).Pentool.assign( TEzClosedEntity( TmpEntity ).Pentool );
                  TEzClosedEntity( WorkEnt ).Brushtool.assign( TEzClosedEntity( TmpEntity ).Brushtool );
                  MustFree := True;
                End;
                ClipOpenedEntity( WorkEnt, WCRect );
                {finally
                   clipent.free;
                end; }
              End;
            End
            Else
            Begin
              // clip to a rectangular area
              If WorkEnt.IsClosed Then
                ClipClosedEntity( WorkEnt, WCRect )
              Else
                ClipOpenedEntity( WorkEnt, WCRect );
            End;
            Pass := WorkEnt.Points.Count > 0;
          End
          Else
          Begin
            // all other entities are considered if are full or partially inside the clipped area
            clipent := DrawBox.CreateEntity( idPolygon );
            Try
              If DrawBox.Gis.MapInfo.ClipAreaKind = cpkPolygonal Then
              Begin
                clipent.Points.Assign( DrawBox.Gis.ClipPolygonalArea );
                Pass := WorkEnt.IsInsideEntity( clipent, false );
              End
              Else
              Begin
                Pass := IsRectVisible( WorkEnt.FBox, WCRect );
              End;
            Finally
              clipent.free;
            End;
          End;
        End;
        If Not Pass Then Exit;

        // EXPORT THIS ENTITY TO NEW LAYER
        TheRecno:= NewLayer.AddEntity( WorkEnt );
        If MustFree Then
          WorkEnt.Free;
        // now copy DB record information
        If ( ALayer.DBTable <> Nil ) And ( NewLayer.DBTable <> Nil ) Then
        Begin
          //ALayer.Recno:= ARecno;
          ALayer.DBTable.Recno := ARecno;
          NewLayer.DBTable.Recno:= TheRecno;
          NewLayer.DBTable.Edit;
          For J := 1 To ALayer.DBTable.FieldCount Do
            NewLayer.DBTable.AssignFrom( ALayer.DBTable, J, J );
          NewLayer.DBTable.Post;
        End;
      End;
    Except
      // ignore errors
    End;
  End;

Begin

  With DrawBox, DrawBox.Gis.MapInfo Do
  Begin
    //WCRect := Extension;
    hasClipped := Gis.ClippedEntities.Count > 0;
    If Not ( IsAreaClipped Or HasClipped ) Then  Exit;
    If IsAreaClipped Then
    Begin
      If ClipAreaKind = cpkPolygonal Then
        WCRect := Gis.ClipPolygonalArea.Extension
      Else
        WCRect := AreaClipped;
    End
    Else
    Begin
      Gis.ClippedEntities.DrawBox := DrawBox;
      WCRect := Gis.ClippedEntities.GetExtension;
    End;
    For Cont := Low( TEzEntityID ) To High( TEzEntityID ) Do
      Entities[Cont] := GetClassFromID( Cont ).Create( 4 );
    SavedLimit := Ez_Preferences.MinDrawLimit;
    Ez_Preferences.MinDrawLimit := 0;
    SavedCursor:= crDefault;
    If Gis.ShowWaitCursor Then
    Begin
      SavedCursor := DrawBox.Cursor;
      DrawBox.Cursor := crHourglass;
    End;
    Try
      NewGis.MapInfo.Assign( Gis.MapInfo );
      With NewGis.MapInfo Do
      Begin
        Extension := INVALID_EXTENSION;
        NumLayers := 0;
      End;
      NewGis.ClearClippedArea;
      // now search all the layers
      For I := 0 To Gis.Layers.Count - 1 Do
      Begin
        Layer := Gis.Layers[I];
        ClipIndex:= -1;
        If HasClipped Then
        Begin
          ClipIndex := Gis.ClippedEntities.IndexOf( Layer );
          hasClippedThis := ClipIndex >= 0;
        End
        Else
          hasClippedThis := false;
        With Layer Do
        Begin
          If Not LayerInfo.Visible Or ( Layer.Recordcount = 0 ) Or
            ( HasClipped And Not hasClippedThis ) Then
            Continue;

          // Create the new layer
          FieldList := TStringList.Create;
          Try
            With Layer Do
            Begin
              If Layer.DBTable <> Nil Then
              Begin
                For J := 1 To Layer.DBTable.FieldCount Do
                  FieldList.Add( Format( '%s;%s;%d;%d', [Layer.DBTable.Field( J ),
                    Layer.DBTable.FieldType( J ),
                      Layer.DBTable.FieldLen( J ),
                      Layer.DBTable.FieldDec( J )] ) );
              End;
              With LayerInfo Do
                NewLayer :=
                  //NewGis.Layers.CreateNew(ExtractFilePath(Filename) +
                NewGis.Layers.CreateNewEx( ExtractFilePath( NewGis.Filename ) +
                  Layer.Name + '_', CoordSystem, CoordsUnits, FieldList );
            End;
          Finally
            FieldList.Free;
          End;

          NewGis.MapInfo.CurrentLayer := NewLayer.Name;

          SetGraphicFilter( stOverlap, WCRect );

          Gis.StartProgress( Layer.Name, 1, Layer.RecordCount );
          N := 0;
          First;
          StartBuffering;
          Try
            While Not Eof Do
            Begin
              Try
                Inc( N );
                Gis.UpdateProgress( N );
                ARecno := Recno;

                If RecIsDeleted Or
                  ( hasClippedThis And Not Gis.ClippedEntities[ClipIndex].IsSelected( ARecno ) ) Then
                  Continue;

                AddToNewLayer( Layer, ARecno );
              Finally
                Next;
              End;
            End;
          Finally
            EndBuffering;
            CancelFilter;
            Gis.EndProgress;
          End;
        End;
      End;
      NewGis.Save;
    Finally
      NewGis.Free;
      For Cont := Low( TEzEntityID ) To High( TEzEntityID ) Do
        Entities[Cont].Free;
      Ez_Preferences.MinDrawLimit := SavedLimit;
      If Gis.ShowWaitCursor Then
        DrawBox.Cursor := SavedCursor;
    End;
  End;
End;


{ Procedure for clipping a line against a polygon
  Polygon is the source polygons
  Polyline is the polyline to clip against Polygon
  Result is the resulting polylines
}

type
  Tedge = record
    xA, yA, xB, yB: Double;
    nx, ny: Double;
  end;

Function ClipParam(const denom, num: Double; var tE, tL: Double): Boolean;
Var
  t: Double;
begin
  Result:= False;
  if denom > 0 then
  begin
    t := num / denom;
    if t > tL then Exit;
    tE := t;
  end else if denom < 0 then
  begin
    t := num / denom;
    if t < tE then Exit;
    tL := t;
  end else if num > 0 then
    Exit;
  Result:= True;
end;

procedure CyrusBeckLineClip(Polyline, Polygon, Result: TEzVector);
Var
  num, denom, dx, dy, tE, tL: Double;
  e: TEdge;
  I, J, N: Integer;
  p: TEzPoint;
  x0, y0, x1, y1: Double;
  LastPt: TEzPoint;
  Accepted: Boolean;
begin
  if EzLib.IsCounterClockWise( Polygon ) then
    Polygon.RevertDirection;

  LastPt:= Point2d(MAXCOORD, MAXCOORD);
  N:= 0;
  for J:= 0 to Polyline.Count-2 do
  begin
    x0:= Polyline[J].x;
    y0:= Polyline[J].y;
    x1:= Polyline[J + 1].x;
    y1:= Polyline[J + 1].y;
    dx:= x1 - x0;
    dy:= y1 - y0;
    tE:= 0.0;
    tL:= 1.0;
    Accepted:= True;
    for I:= 0 to Polygon.Count-2 do
    begin
      e.xA := Polygon[I].x;
      e.yA := Polygon[I].y;
      e.xB := Polygon[I + 1].x;
      e.yB := Polygon[I + 1].y;
      { compute normal }
      p:= TransformPoint2d( Polygon[I + 1], Rotate2d( System.Pi / 2, Polygon[I] ) );
      e.nx:= p.x;
      e.ny:= p.y;
      // denom is -Ni.D; num is Ni.(A-P)
      denom := -e.nx * dx - e.ny * dy;
      num := e.nx * (e.xA - x0) + e.ny * (e.yA - y0);
      if not ClipParam (denom, num, tE, tL) then
      begin
        Accepted:= False;
        Break;
      end;
    end;
    if not Accepted then Continue;

    // compute clipped end points
    if tL < 1 then
    begin
      x1 := x0 + tL*dx;
      y1 := y0 + tL*dy;
    end;
    if tE > 0 then
    begin

⌨️ 快捷键说明

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