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