この質問にはいくつかの部分があります。1) ワールド座標をスクリーン座標にスケーリングする方法。2) 形状データの読み込み方法、3) データの画面へのプロット方法。
データ変換に関する情報は、Buro Tshaggelar の記事 ( http://www.ibrtses.com/delphi/dmcs.html ) から得られます。彼は、データ変換を行う方法について説明します。
Tpaintbox または Timage の左上隅の x、y 座標は 0, 0 です。これらは整数値でなければなりません。オフセット値に対してスケーリングすることにより、ワールド座標からスクリーン座標に、またはスクリーン座標からワールド座標に変換できます。
Tpaintbox または TImage Canvas のいずれかにシェイプをプロットできます。Tpaintbox にプロットする場合、結果は永続的ではありません。
個々の線を描画して形状を作成する代わりに、Tpoint の配列を使用して形状を描画することをお勧めします。以下は XE2 VCL で動作します。
パート1
ワールド座標が 10 進値の場合、座標は xLowvalue、xHighValue、yLowVaue、yHighValue の座標を持つボックスで囲まれ、スクリーン ウィンドウは tlx..brx、tly..bry として定義でき、座標は整数値です。
次の関数は、ワールド座標とスクリーン座標の間で変換します。アンドレアスの変換も機能します。私はそれらが好きで、座標ペアを同時に変換するという点でより効率的です。プロセスを説明するために、以下の変換を好みます。
ワールド座標からスクリーン座標に変換します。
関数 mapW2SxLin(xf:double):integer; 結果の開始:= round(tlx + (xf - xlow) * (brx - tlx) / (xhigh - xlow)); 終わり;
関数 mapW2SyLin(yf:double):integer; 結果の開始:= round(bry - (yf - ylow) * (bry - tly) / (yhigh - ylow)); 終わり;
スクリーン座標からワールド座標に変換します。
関数 mapS2WxLin(xs:integer):double; 結果の開始:= xlow +(xs - tlx) * (xhigh - xlow )/ (brx - tlx); 終わり;
関数 mapS2WyLin(ys:integer):double; 結果の開始:= yhigh - (ys - tly) * (yhigh - ylow) / (bry - tly); 終わり;
ikathygreat が提供する例では、必要な変換はデカルトからスクリーン座標データへの変換であるように見えます (提供される値は、10 進数の緯度と経度の値として表示される緯度と経度の位置のペアのようです)。
パート 2
データ ファイルをロードする代わりに、データはここでハード コードされます。 xy 動的配列をロードする例として、ファイルから tpoint 配列を生成するための Goodle。テキスト ファイルからデータをロードできるようにするコードがあります。データをロードするときは、SetLength で配列 (6) のサイズを変更するコードを提供し (現在は Setlength(xy, 6); とコード化されています)、配列のサイズを 6 に設定する必要があることに注意してください。これを行うには、別の問題にする必要があります。シェイプの頂点の数によって値が変わります。
パート 3
Tpoint 配列を使用して形状をプロットします。要求されたが、要求者の方法論を使用していないもの。個々の線を描画することは、形状をプロットするためにコード化するのが少し厄介です。以下の例はより簡単な解決策であり、仕事を成し遂げると思います。
以下を使用して、ワールド座標の最大制限を反映する境界を持つペイント ボックスを設定します。
xLow := -88; // 提供された最も東の経度 xHigh:= -100; // 提供された最西端の経度 yLow:= 37; // 提供された最高緯度 yHigh:= 32; // 提供された最低緯度
グローバル変数は次のように定義することをお勧めします。
var xLow、xHigh、yLow、yHigh:double; tlx、brx、tly、bry:整数;
xy: TPoint の配列。
配列を使用して形状をプロットするには、型を定義する必要があります
type TMyPolygon = TPoint の配列。// 動的配列
OnCreate フォーム イベント ハンドラにこれらの値を割り当てます。
brx:=Paintbox1.Left; tlx:=Paintbox1.Left + paintbox1.Width ; bry:= Paintbox1.Top; tly :=Paintbox1.Top + paintbox1.Height;
Image、Paintbox、および Button をフォームに追加します。次に、ボタンとフォームの OnCreate ハンドラーで次のコードを使用します。また、変換関数とグローバル変数 (xLow,xHigh,yLow,yHigh:double; tlx,brx,tly,bry:integer; xy: ポイントの配列;) を追加し、忘れずに Tpoint タイプを追加します: ( type TMyPolygon = array of Tポイント;)
implementation
{$R *.dfm}
function mapW2SxLin(xf:double):integer;
begin
result:=round(tlx+(xf-xlow)*(brx-tlx)/(xhigh-xlow));
end;
function mapW2SyLin(yf:double):integer;
begin
result:=round(bry-(yf-ylow)*(bry-tly)/(yhigh-ylow));
end;
function mapS2WxLin(xs:integer):double;
begin
result:=xlow+(xs-tlx)*(xhigh-xlow)/(brx-tlx);
end;
function mapS2WyLin(ys:integer):double;
begin
result:=yhigh-(ys-tly)*(yhigh-ylow)/(bry-tly);
end;
procedure TPlotShapeFm.Button1Click(Sender: TObject);
var
// xy: array of TPoint; //probably want to define this globally
x,y,x1,y1,x2,y2,x3,y3:integer;
ax,ay,ax2,ay2:integer;
begin
{ Your values
-88.988857, 36.265838
-89.094923, 36.371904
-89.094923, 36.371904
-95.000423, 36.371904
-95.000423, 36.371904
-95.000423, 32.828604
-95.000423, 32.828604
-99.134273, 32.828604
-88.988857, 36.265838 //repeat the first value to close the shape
}
//convert from World to screen coordinates
// these values are hard coded for this example
// there are many ways to load these from a text file
x:= mapW2SxLin(-88.988857);
y:= mapW2SyLin( 36.265838 );
ax:= mapW2SxLin(-89.094923);
ay:= mapW2SyLin(36.371904);
x1:= mapW2SxLin(-95.000423);
y1:= mapW2SyLin(36.371904);
x2:= mapW2SxLin(-95.000423);
y2:= mapW2SyLin(32.828604);
ax2:= mapW2SxLin(-99.134273);
ay2:= mapW2SyLin(32.828604);
x3:= mapW2SxLin(-88.988857); //return to the starting coordinates to finish off the shape
y3:= mapW2SyLin(36.265838 );
// populate the dynamic array
Setlength(xy, 6);
xy[0] := point(x,y);
xy[1] := point(ax,ay);
xy[2] := point(x1,y1);
xy[3] := point(x2,y2);
xy[4] := point(ax2,ay2);
xy[5] := point(x3,y3);
Paintbox1.Canvas.Brush.Color := Random($FFFFFF);
//plot the shape
//canvas.Polygon(xy); //generic or plot on the form itself
// or
Image1.canvas.polygon(xy); //to plot on a Timage
Paintbox1.canvas. polygon(xy); //to plot on a Tpaintbox
end;
procedure TPlotShapeFm.FormCreate(Sender: TObject);
begin
//You can set up you paint box using:
{ xLow := 0;
xHigh:=-180;
yLow:= 50;
yHigh:= 30; //to display part of North America or
xLow := 180;
xHigh:=-180;
yLow:= 90;
yHigh:= 00; //to display the entire World, North of the equator.
}
// but to display the info provided as a large image
xLow := -88;
xHigh:=-100;
yLow:= 37;
yHigh:= 32;
// scale the paintbox to World coordinates
brx:= Paintbox1.Left;
tlx:= Paintbox1.Left + paintbox1.Width;
bry:= Paintbox1.Top;
tly := Paintbox1.Top + paintbox1.Height;
end;
正しく実行すると、結果は次のようになります。
提供されたデータと結果の形状を見ると、要求者が配列を使用して形状を正しく描画したい順序でデータがリストされていない可能性があることに気付きました (クロスオーバーに注意してください)。交差は、最初の点から始めて時計回りまたは反時計回りの順序で点をリストし、次に最初の点で終了することによって修正できます。形状は、最初の点で描画を終了することによって閉じなければなりません。