H
Huzzz
Unregistered / Unconfirmed
GUEST, unregistred user!
我在做一个缩小放大的矢量画图程序,当比例太大时画多边形出现异常:
屏幕上出现了奇怪的线条。(打印也一样)
这此线条好像是连接到坐标零点(0,0),但跟踪发现,没有一个坐标是为0的。
这是为什么?
下面是实例程序,运行一下就可见分晓。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
//根据缩放比例和坐标平移输出画图
procedure ExportTo(Cnv: TCanvas; AWidth, AHeight: Integer;
AScale, ACenterX, ACenterY: Double);
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.ExportTo(Cnv: TCanvas; AWidth, AHeight: Integer;
AScale, ACenterX, ACenterY: Double);
var
Rect: TRect;
pWinExt, pViewExt: PSize;
pWinOrg, pViewOrg: PPoint;
Imm: Integer;
pPto: PPoint;
procedure SaveGraphicMode;
begin
pWinExt := New(PSize);
pViewExt := New(PSize);
pWinOrg := New(PPoint);
pViewOrg := New(PPoint);
pPto := New(PPoint);
Imm := GetMapMode(Cnv.Handle);
getWindowExtEx(Cnv.Handle, pWinExt^);
getWindowOrgEx(Cnv.Handle, pWinOrg^);
getViewportExtEx(Cnv.Handle, pViewExt^);
GetViewPortOrgEx(Cnv.Handle, pViewOrg^);
end;
procedure MapGraphicMode(Cnv: TCanvas; CvWidth, CvHeight: Integer);
begin //这个映射是为了使屏幕中心为(ACenterX,ACenterY)
SetMapMode(Cnv.Handle, MM_ISOTROPIC);
SetWindowExtEx(Cnv.Handle, Round(360 * 16.0), Round(180 * 16.0), nil);
SetWindowOrgEx(Cnv.Handle, Round(ACenterX), Round(ACenterY), nil);
SetViewportExtEx(Cnv.Handle, CvWidth, -CvHeight, nil);
SetViewportOrgEx(Cnv.Handle, Round(CvWidth / 2), Round(CvHeight / 2), nil);
end;
procedure RestoreGraphicMode;
begin
SetMapMode(Cnv.Handle, Imm);
SetWindowExtEx(Cnv.Handle, pWinExt^.cX, pWinExt^.cY, nil);
SetWindowOrgEx(Cnv.Handle, pWinOrg^.X, pWinOrg^.Y, nil);
SetViewportExtEx(Cnv.Handle, pViewExt^.cX, pViewExt^.cY, nil);
SetViewportOrgEx(Cnv.Handle, pViewOrg^.X, pViewOrg^.Y, nil);
Dispose(pWinExt);
Dispose(pViewExt);
Dispose(pWinOrg);
Dispose(pViewOrg);
Dispose(pPto);
end;
procedure DrawIt;
var
APoints: array[0..4] of TPoint;
VectCounts: array[0..0] of Integer;
PolyCount: Integer;
SclX: Double;
SclY: Double;
OrgX: Double;
OrgY: Double;
function GetDrX(X: Integer): Integer;
var
R: Int64;
begin
R := Round((X - OrgX) * SclX);
if R > High(Integer) then
R := High(Integer)
else if R < Low(Integer) then
R := Low(Integer);
Result := R;
end;
function GetDrY(Y: Integer): Integer;
var
R: Int64;
begin
R := Round((Y - OrgY) * SclY);
if R > High(Integer) then
R := High(Integer)
else if R < Low(Integer) then
R := Low(Integer);
Result := R;
end;
const
RctW = 100;
RctH = 100;
begin
OrgX := ACenterX;
OrgY := ACenterY;
SclX := AScale;
SclY := AScale;
//;左下界:-24176.01, -17054.55
//;右上界:-18897.51, -12732.45
//SetLength(APoints, 5);
APoints[0].X := GetDrX(0);
APoints[0].Y := GetDrY(0);
APoints[1].X := GetDrX(100);
APoints[1].Y := GetDrY(10);
APoints[2].X := GetDrX(110);
APoints[2].Y := GetDrY(110);
APoints[3].X := GetDrX(10);
APoints[3].Y := GetDrY(100);
APoints[4].X := GetDrX(0);
APoints[4].Y := GetDrY(0);
//SetLength(VectCounts, 1);
VectCounts[0] := 5;
PolyCount := 1;
Canvas.Pen.Color := clRed;
Canvas.Brush.Style := bsClear;
PolyPolygon(Canvas.Handle, APoints, VectCounts, PolyCount);
end;
begin
SaveGraphicMode;
Cnv.Pen.Style := psSolid;
Cnv.Pen.Color := Color;
Cnv.Brush.Color := clWhite;
Cnv.Brush.Style := bsSolid;
Rect.Left := 0;
Rect.Top := 0;
Rect.Right :=AWidth ;
Rect.Bottom := AHeight;
Cnv.Rectangle(Rect);
Cnv.Pen.Color := clBlack;
Cnv.Pen.Width := 0;
Cnv.Pen.Style := psSolid;
MapGraphicMode(Cnv, AWidth, AHeight);
Cnv.Pen.Color := clFuchsia;
Cnv.Brush.Style := bsClear;
DrawIt;
RestoreGraphicMode;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ExportTo(Canvas, Width, Height, 10, 50, 50);
//正常
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ExportTo(Canvas, Width, Height, 40000000, 50, 50);
//比例太大就有异赏
end;
end.
屏幕上出现了奇怪的线条。(打印也一样)
这此线条好像是连接到坐标零点(0,0),但跟踪发现,没有一个坐标是为0的。
这是为什么?
下面是实例程序,运行一下就可见分晓。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
//根据缩放比例和坐标平移输出画图
procedure ExportTo(Cnv: TCanvas; AWidth, AHeight: Integer;
AScale, ACenterX, ACenterY: Double);
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.ExportTo(Cnv: TCanvas; AWidth, AHeight: Integer;
AScale, ACenterX, ACenterY: Double);
var
Rect: TRect;
pWinExt, pViewExt: PSize;
pWinOrg, pViewOrg: PPoint;
Imm: Integer;
pPto: PPoint;
procedure SaveGraphicMode;
begin
pWinExt := New(PSize);
pViewExt := New(PSize);
pWinOrg := New(PPoint);
pViewOrg := New(PPoint);
pPto := New(PPoint);
Imm := GetMapMode(Cnv.Handle);
getWindowExtEx(Cnv.Handle, pWinExt^);
getWindowOrgEx(Cnv.Handle, pWinOrg^);
getViewportExtEx(Cnv.Handle, pViewExt^);
GetViewPortOrgEx(Cnv.Handle, pViewOrg^);
end;
procedure MapGraphicMode(Cnv: TCanvas; CvWidth, CvHeight: Integer);
begin //这个映射是为了使屏幕中心为(ACenterX,ACenterY)
SetMapMode(Cnv.Handle, MM_ISOTROPIC);
SetWindowExtEx(Cnv.Handle, Round(360 * 16.0), Round(180 * 16.0), nil);
SetWindowOrgEx(Cnv.Handle, Round(ACenterX), Round(ACenterY), nil);
SetViewportExtEx(Cnv.Handle, CvWidth, -CvHeight, nil);
SetViewportOrgEx(Cnv.Handle, Round(CvWidth / 2), Round(CvHeight / 2), nil);
end;
procedure RestoreGraphicMode;
begin
SetMapMode(Cnv.Handle, Imm);
SetWindowExtEx(Cnv.Handle, pWinExt^.cX, pWinExt^.cY, nil);
SetWindowOrgEx(Cnv.Handle, pWinOrg^.X, pWinOrg^.Y, nil);
SetViewportExtEx(Cnv.Handle, pViewExt^.cX, pViewExt^.cY, nil);
SetViewportOrgEx(Cnv.Handle, pViewOrg^.X, pViewOrg^.Y, nil);
Dispose(pWinExt);
Dispose(pViewExt);
Dispose(pWinOrg);
Dispose(pViewOrg);
Dispose(pPto);
end;
procedure DrawIt;
var
APoints: array[0..4] of TPoint;
VectCounts: array[0..0] of Integer;
PolyCount: Integer;
SclX: Double;
SclY: Double;
OrgX: Double;
OrgY: Double;
function GetDrX(X: Integer): Integer;
var
R: Int64;
begin
R := Round((X - OrgX) * SclX);
if R > High(Integer) then
R := High(Integer)
else if R < Low(Integer) then
R := Low(Integer);
Result := R;
end;
function GetDrY(Y: Integer): Integer;
var
R: Int64;
begin
R := Round((Y - OrgY) * SclY);
if R > High(Integer) then
R := High(Integer)
else if R < Low(Integer) then
R := Low(Integer);
Result := R;
end;
const
RctW = 100;
RctH = 100;
begin
OrgX := ACenterX;
OrgY := ACenterY;
SclX := AScale;
SclY := AScale;
//;左下界:-24176.01, -17054.55
//;右上界:-18897.51, -12732.45
//SetLength(APoints, 5);
APoints[0].X := GetDrX(0);
APoints[0].Y := GetDrY(0);
APoints[1].X := GetDrX(100);
APoints[1].Y := GetDrY(10);
APoints[2].X := GetDrX(110);
APoints[2].Y := GetDrY(110);
APoints[3].X := GetDrX(10);
APoints[3].Y := GetDrY(100);
APoints[4].X := GetDrX(0);
APoints[4].Y := GetDrY(0);
//SetLength(VectCounts, 1);
VectCounts[0] := 5;
PolyCount := 1;
Canvas.Pen.Color := clRed;
Canvas.Brush.Style := bsClear;
PolyPolygon(Canvas.Handle, APoints, VectCounts, PolyCount);
end;
begin
SaveGraphicMode;
Cnv.Pen.Style := psSolid;
Cnv.Pen.Color := Color;
Cnv.Brush.Color := clWhite;
Cnv.Brush.Style := bsSolid;
Rect.Left := 0;
Rect.Top := 0;
Rect.Right :=AWidth ;
Rect.Bottom := AHeight;
Cnv.Rectangle(Rect);
Cnv.Pen.Color := clBlack;
Cnv.Pen.Width := 0;
Cnv.Pen.Style := psSolid;
MapGraphicMode(Cnv, AWidth, AHeight);
Cnv.Pen.Color := clFuchsia;
Cnv.Brush.Style := bsClear;
DrawIt;
RestoreGraphicMode;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ExportTo(Canvas, Width, Height, 10, 50, 50);
//正常
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ExportTo(Canvas, Width, Height, 40000000, 50, 50);
//比例太大就有异赏
end;
end.