0

線の始点と終点を表す X、Y 値のリストから画像を描画しようとしています。インチなので、現在は 10 進数にフォーマットされています。

私が抱えている問題は、図面にあります。およびコマンドMoveToLineToは、double ではなく整数が必要です。Round(float)数学演算を使用すると、以下の出力が表示されます。丸めによって開始点と終了点が同じになるため、何も描画されません。

10 進数の X、Y ポイントのリストから図形を描画するにはどうすればよいですか?

入力値 (10 進数) のデバッグ コード:

LineStartVal: -88.988857, 36.265838
LineEndVal: -89.094923, 36.371904
LineStartVal: -89.094923, 36.371904
LineEndVal: -95.000423, 36.371904
LineStartVal: -95.000423, 36.371904
LineEndVal: -95.000423, 32.828604
LineStartVal: -95.000423, 32.828604
LineEndVal: -99.134273, 32.828604

丸め後の出力ポイントのコードをデバッグします。

MoveTo: -89, 36
LineTo: -89, 36
MoveTo: -89, 36
LineTo: -95, 36
MoveTo: -95, 36
LineTo: -95, 33
MoveTo: -95, 33
LineTo: -99, 33

描画コード スニペット:

//Function used to to get start and stop points
LSNLineObj.GetEndPoints(X1,Y1,X2,Y2);


//OutputMemo.Text := OutputMemo.Text + #13#10 + 'LineStartVal: ' + FloatToStrF(X1, ffGeneral, 8, 4) + ', ' + FloatToStrF(Y1, ffGeneral, 8, 4);
//OutputMemo.Text := OutputMemo.Text + #13#10 + 'LineEndVal: ' + FloatToStrF(X2, ffGeneral, 8, 4) + ', ' + FloatToStrF(Y2, ffGeneral, 8, 4);

X1int := Round(X1); X2int := Round(X2);
Y1int := Round(Y1); Y2int := Round(Y2);

PartImage.Canvas.MoveTo(X1int,X2int);

OutputMemo.Text := OutputMemo.Text + #13#10 + 'MoveTo: ' + IntToStr(X1int) + ', ' + IntToStr(Y1int);

PartImage.Canvas.LineTo(X2int,Y2int);

OutputMemo.Text := OutputMemo.Text + #13#10 + 'LineTo: ' + IntToStr(X2int) + ', ' + IntToStr(Y2int);
4

3 に答える 3

0

この質問にはいくつかの部分があります。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;

正しく実行すると、結果は次のようになります。

ここに画像の説明を入力

提供されたデータと結果の形状を見ると、要求者が配列を使用して形状を正しく描画したい順序でデータがリストされていない可能性があることに気付きました (クロスオーバーに注意してください)。交差は、最初の点から始めて時計回りまたは反時計回りの順序で点をリストし、次に最初の点で終了することによって修正できます。形状は、最初の点で描画を終了することによって閉じなければなりません。

于 2013-05-28T15:52:26.900 に答える
0

" 10 進数の X、Y ポイントのリストから図形を描くにはどうすればよいですか? "

http://graphics32.org/

var
  pts: TArrayOfFixedPoint;
  fr: TFloatRect;
begin
  ...
  pts := MakeArrayOfFixedPoints(fr);   
  SimpleFill(Bitmap, pts, Color32(clBlack), clCornSilk32);

GR32_Lines、GR32_Misc、GR32_Misc2、GR32_Text のエクストラを探します。ファイルをランタイム パッケージに追加します。設計時パッケージは r/t パッケージに適切に依存しているため、余分な手順はありません。最近、XE5 と XE7 を組み込みました。

于 2015-01-16T10:17:52.427 に答える