|
このページはEtoJ逐語翻訳フィルタによって翻訳生成されました。 |
Bookmark this on Delicious
Recommend to StumbleUpon
This is the first of three web pages explaining the 開発 of a small 使用/適用 which I wrote for turning data in とじ込み/提出するs into graphs on the 審査する, and to give me a way to draw lines on the graph. The placement of the lines is "remembered" by the system from one 開会/開廷/会期 to the next.
Many general techniques are illustrated along the way. A 収集するd .exe is 利用できる so that you can play with the 使用/適用 without having to 収集する it. The Lazarus sourcecode is in the same zip とじ込み/提出する you can download. Both are there for you to play with... but I reserve all 権利s to any 使用/適用s derived from the sourcecode. It is there to show you programming techniques, not to be the basis of a 商業の 製品. 井戸/弁護士席... anyone else's 商業の 製品, anyway.
I buy and sell 株 in the 株式市場. It is NOT just about looking at past prices, 協議するing a 水晶 ball, and placing your "bets"... but the pattern in past prices is not "useless", either.
その上に, on any given date, I will have an opinion a variety of 在庫/株s. I may buy or sell that day, but more often I will, after updating my 研究 feel that I want to "watch" something. See if it is behaving the way I think it is going to. If I think it is rising, and it is, I would make more money by buying 権利 away. But that "if" is 重要な. By 定期的に giving up a little 可能性のある 利益(をあげる), I 定期的に save myself getting into something which is NOT doing what one day's 調査 says it is. (And the converse 適用するs to selling.)
I have a way of sketching my thoughts. I hope that the に引き続いて diagram gives you an idea of how I quantify my 予測s...
That diagram isn't やめる 権利... but should give you the idea until I can do a better one for you. The dots are the price for the 在庫/株...rising nicely, as you see! The green lines are by me, using my 裁判/判断. They define my guess as to the 限界s of what might happen in the 未来. The 根底となる feature of the 使用/適用 that this tutorial discusses is to make managing those green lines, for 多重の 在庫/株s, 使用者 friendly. The 使用/適用 will only 現在の one such graph at a time, but it will be 平易な to switch between data 始める,決めるs. Each data 始める,決める will have and remember its own green lines.
For years, I've dreamed of a computer program to help me with my 投資するing, and I am finally getting の近くに to producing one.... which is not what I am going to do in this tutorial. But I will go into some of the 成分s of my 在庫/株 prices watching program, 一般に useful 成分s which you may have your own uses for.
Getting the computer to draw my diagrams will lead to several 利益s... I won't be lost in a sea of bits of paper. I will be able to find the one I want. But more importantly, I can get the computer to routinely and rigorously check the 進歩 of any 在庫/株 about which I've drawn a diagram, and bring different classes of 在庫/株 to my attention... those I 港/避難所't reviewed recently, those which are 成し遂げるing as I thought they would, those that aren't. With the diagrams I can see what's rising (or 落ちるing) 速く, or not so 速く, etc.
This tutorial is 抱擁する. Not at all typical of my tutorials. But it covers a lot of ground. It looks at a "grown up" 使用/適用, not a little デモ. The sourcecode will be 利用できる.
The programming is done. The tree pages of tutorial are "done"... but they need 編集(者)の work. The (警察などへの)密告,告訴(状) in the tutorial is good. But the 質 of the 贈呈 and the English in the text still needs work. But it is already 価値(がある) at least what you're going to 支払う/賃金 for it.
Here's an 輪郭(を描く) of what is in the 残り/休憩(する) of this page... the first of three which between them tell the whole story.
First you'll be shown a simple way to make a 始める,決める of data 利用できる to a program. In the final 見解/翻訳/版 of the 使用/適用, the data on prices (many Date/ Price 記録,記録的な/記録するs) will come from an 外部の data とじ込み/提出するs. 最初, while building my way to 陳列する,発揮する that data and put some "予測" lines on the graph, I'm going to hardcode the data inside the program, so it is easily 利用できる, and we won't have to think about 外部の data とじ込み/提出するs... at first. Apart from anything else, this "data from hardcode" bit will be an example of a 開発 technique: Don't try to do everything at once... but always keep in mind where you are going. I'm "shirking" data FILES for the moment, getting my data more easily. But I will be building the デモ app in such a way that in 予定 course the "平易な" data source can be swapped out for "data- from- 外部の- とじ込み/提出する".
Then we'll build a tiny app which 単に gives us a "bit of paper" to draw the diagram on.
We'll take a moment to look at making that 柔軟な, making it 答える/応じる nicely to the 使用者's wishes as to how big it is.
We'll take a 深い breath, and 押し進める through two not-trivial bits: "Just" 製図/抽選 a graph with the 在庫/株 prices on it for different days, using "平易な" data. Not hard, really, but it took me over a day to 令状 it up... so not "平易な", either.
Once we have that much working, we will make things fancier: We will 供給する 規模ing services so that different date 範囲s can be shown, the size of the graph can change, and the 範囲 陳列する,発揮するd on the Y axis can change. that will be "fun".
延長するing it from there to fully 会合,会う our wants is a little tedious. 特に if, as we will, we make the 規模ing 柔軟な... but we will do it.
Once we've got that much working, 適用するing the two green lines to show what we think the upper and lower 限界s of the 在庫/株's price will be in the weeks ahead is 比較して simple. Not so simple is making it possible to draw AND RE-DRAW those lines... but we'll do that too, as the grand finale, which I have put in my separate web page about 製図/抽選 and moving two lines on a graph..
Along the way, we will develop a way to 蓄える/店 efficiently our idea of where the price 限界 lines should be.
There was once a language called BBC Basic. Some would 非難する it today, and certainly it permitted the use of bad techniques. Other Basics remain to this day ("Beginners All-目的 象徴的な 指示/教授/教育 Code"). They may or may not have something BBC (and other 早期に) Basic(s) had... the "Read" and "Data" 声明s.
They worked as illustrated by the に引き続いて....
The program...
10 for c1=0 to 5 20 read x,y 30 print x '---' y 40 next //ends "For" 宙返り飛行 50 Data 1,11,2,200,5,123 52 Data 300,5,60,70
Would 生成する...
1 --- 11 2 --- 200 5 --- 123 300 --- 5 60 --- 70
Do you see? The "Data" lines were like hardcoded data とじ込み/提出するs. The first call of a "Read" 声明 設立する the first data line, 選ぶd up what it needed **and remembered what it had already used.** Thus, when any その上の "Read" 声明 遂行する/発効させるd, you got the next datum, then the next, and so on and so on.
When I 令状 my price watching program, I will of course be using 外部の data とじ込み/提出するs to 持つ/拘留する the data. But for this demonstration program, that's extra 複雑化 we don't need.
The data for the デモ will consist of pairs of numbers, both 肯定的な integers, The first will be やめる large, and stand for the day the price was seen. The second number will stand for a price, in pennies. There will be many pairs of such numbers, in 逆転する chronological order. (That order is something I am 明示するing in the design. A datafile of prices could have other 始める,決める ups, of course, but for my program, I will 確実にする that data とじ込み/提出するs arranged as I have 明示するd will be 利用できる.
Using a large number for the date isn't as daft as it seems. qexpand why not daft, perhaps.
I am starting this tutorial on May 7th, 2014. The number for that date, in "my" system is 41766. Tomorrow, May 8th, will be "day" 41767, and yesterday was 41765.
This numbering system isn't "地雷" of course. It is the system used by Apache Open Office. (Put then numbers into an Open Office spreadsheet, and play with the formatting 適用するd to the 独房, to see this in 活動/戦闘. Day "無" was December 30,1899.) Delphi and Lazarus use a 類似の system, but I can't 約束 you they use the same start day, although I think maybe they do. (Very 早期に Delphis used a different start day. The "useful" things you learn in a Sheepdog Guides tutorial!)
ANYWAY... for this デモ program, I'm going to 蓄える/店 my data in a very big string called sData. I will separate 記録,記録的な/記録するs with 今後 削除するs, and the fields in a given 記録,記録的な/記録する with hyphens.
So: If the price on May 7th 2014 of the 在庫/株 we are 利益/興味d in was $23.50, and on the 6th, it was $22.80, then sData would start....
41766-2350/41765-2280
I'll use a 全世界の variable (bad... but いつかs you break the 支配するs... carefully) called wWhereInData which will point to the next 未使用の character in sData.
And I create a 手続き called ReadRecord which will return the next two numbers from sData.
999999 will be a rogue value. If ReadRecord finds that for the date, it will know not to read any その上の 記録,記録的な/記録するs. (The 999999 記録,記録的な/記録する should have a price datum to go with the "date" of 999999)
To get all that up and running, I've built....
Run it. Click "Read Data from hardcoded string" 繰り返して, and a new 記録,記録的な/記録する should appear at the 最高の,を越す of the 名簿(に載せる)/表(にあげる) (押し進めるing the older ones 負かす/撃墜する) each time.
部隊 LD007u1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, 支配(する)/統制するs, Graphics, Dialogs, StdCtrls;
const vers='7 May 14';
sData='41746-2350/41745-2280/'+
'41729-2292/41728-2289/41727-2279/9999-1000';
type
{ Tld007f1 }
Tld007f1 = class(TForm)
buReadData: TButton;
buQuit: TButton;
laAppInfo: TLabel;
laFileMT: TLabel;
laVer: TLabel;
laDisplayOrder: TLabel;
meOutput: TMemo;
手続き buQuitClick(Sender: TObject);
手続き buReadDataClick(Sender: TObject);
手続き FormCreate(Sender: TObject);
私的な
{ 私的な 宣言s }
public
{ public 宣言s }
c1,wWhereInData,wDate,wPrice:word;
sTmp, sTmp2:string;
手続き ReadRecord(var w1,w2:word);
end;
var
ld007f1: Tld007f1;
実施
{$R *.lfm}
{ Tld007f1 }
手続き Tld007f1.buQuitClick(Sender: TObject);
begin
の近くに;
end;
手続き Tld007f1.buReadDataClick(Sender: TObject);
begin
//Using "挿入する:" so that newest data is at 最高の,を越す of 名簿(に載せる)/表(にあげる)
ReadRecord(wDate,wPrice);
meOutput.lines.挿入する(0,inttostr(wDate)+' '+inttostr(wPrice));
end;
手続き Tld007f1.FormCreate(Sender: TObject);
begin
wWhereInData:=1;//1 for next data to 選ぶ up starts at (string)[1];
meOutput.(疑いを)晴らす;
laVer.caption:='見解/翻訳/版 '+vers;
lafileMT.caption:='';
end;
手続き Tld007f1.ReadRecord(var w1,w2:word);
//w1, w2 can have anything in them when the SR is called. Irrelevant.
//wWhereInData must have a 訂正する value. Should be 1 when ReadRecord
// first called
//選ぶ up two numbers from 全世界の constant sData.
//(Using 全世界のs, the way wWhereInData and sData are 存在 used is
// a Bad Idea... and I will probably be punished. We shall see.)
begin
sTmp:='';
while (sData[wWhereInData] <>'-') and
(sTmp<>'9999') do begin
sTmp:=sTmp+sData[wWhereInData];
inc(wWhereInData);
end;//"While..."
inc(wWhereInData);
w1:=strtoint(sTmp);
if w1<>9999 then begin //Read w2
sTmp:='';
while sData[wWhereInData]<>'/' do begin
sTmp:=sTmp+sData[wWhereInData];
inc(wWhereInData);
end;//"While..."
inc(wWhereInData);
w2:=strtoint(sTmp);
end;//Read w2
if w1=9999 then begin
wWhereInData:=wWhereInData-5;
laFileMT.caption:='All 利用できる data has been read.';
buReadData.enabled:=誤った;
end;
end;
end.
========================
=-=-=-=-= So! We have a 機械装置 for 供給(する)ing a 量 of dates and prices to our graphing program.
Put that bit of knowledge to one 味方する for the moment.
It isn't hard to 始める,決める up a 製図/抽選 surface on a Lazarus 使用/適用's window. See....
https://sheepdogguides.com/lut/lt1Graphics.htm
... for the basics.
(Visit https://sheepdogguides.com/lut/PixelProblem.htm first, for a "Stop 圧力(をかける)")
Once it is 始める,決める up, assuming we've called it Bitmap, we can 陰謀(を企てる) a point on the 製図/抽選 surface at x=10, y=20 with...
Image1.Picture.Bitmap.canvas.pixels[10,20] := clGreen;//or another color
(An 孤立するd dot can いつかs be hard to see. The 基準 Windows "Magnifier" 道具 (at 従犯者s/ Accessibility, from the XP start menu) will help you see small 詳細(に述べる)s.)
However, to do even just the basic graph of prices we talked about, we're going to have to get a whole lot more clever, to を取り引きする the 問題/発行するs of "squeezing" our real world data (even the ふりをするd "real world data" we will create for 実験(する)ing our code) into the 調整する system of the 製図/抽選 area on our 審査する.
The first of several secrets is this: Develop your "answer" using simple numbers which you can get your 長,率いる around. But your "answer" must be done in a way which can "digest" any numbers.
Another secret is to think of the 調整するs-based 製図/抽選 わずかに 異なって than I 嫌疑者,容疑者/疑う many people do. The "usual", I would guess, way of thinking of 製図/抽選 with 調整するs is to think ーに関して/ーの点でs of infinitesimal points. In 製図/抽選 on a computer 審査する, you are really talking about switching on or off pixels of very real widths and 高さs. On a modern 審査する, they may by tiny, but they are there.
For my 早期に 開発 work, to keep the numbers 負かす/撃墜する to things I can を取り引きする in my Tiny Little Mind, and draw (署名/調印する on paper.) For this, I am using a 製図/抽選 area which is only 30 pixels wide and 20 high... and before you 急ぐ on, and say, "Okay, that's 平易な enough"... stop and think.
Lazarus (and Delphi... there's almost nothing in this that doesn't 適用する 平等に to both. The only difference in anything we're doing here is that in Lazarus, you have to take two tiny steps (shown earlier) when first setting up the 製図/抽選 area to have a white background for what you are going to draw.)....
As I was 説, Lazarus 供給するs a built-in way to draw a line.
If you put the に引き続いて into your code...
Image1.Picture.Bitmap.canvas.pen.color:=clGreen; Image1.Picture.Bitmap.canvas.moveto(5,5); Image1.Picture.Bitmap.canvas.lineto(15,15);
...You will get a green line from 5,5 TO 15,15. (Pixel 5,5 will be green, and the line will END just BEFORE pixel 15,15. (The 命令(する) is lineTO, after all.)
So... we are working with a 20 x 30 製図/抽選 area. What numbers do you think you use to draw from the upper left to the lower 権利 corners. To. Not past. What are the EXACT numbers to JUST get both the corner pixels colored green (and all the others in between, too, of course)?
qspoiler gap
The 権利 answer: 0,0 and 30,20. There is no "pixel 30,20"... but the lineTO 命令(する) doesn't color the "to" pixel. The pixel at the 底(に届く) 権利 is pixel 29,19, but if we did lineto(29,19), the last pixel, the lower 権利-手渡す pixel would not be colored. (You are 許すd to "draw off the page"... even in 消極的な directions.)
=== 柔軟性
Now... I said we'd start with "human sized" numbers, and then "do things" so that we can take advantage of the computer's 力/強力にする. And we will. And we are going to start building in those "things" now.
The way we make our program 柔軟な is by careful use of variables and constants.
If you know that you will never want to change some number, until you one day re-令状 the program, put it in a constant.
If you MAY want to give the 使用者 接近 to something, put it in a variable.
At this 行う/開催する/段階, in this 事業/計画(する), I see nothing that I'd want in a constant.
We will put a few things in variables which we won't やむを得ず give 使用者s a way to change. But we will keep the 可能性 open. Those parameters will be "constants", in 影響, for the 使用者, until we 追加する code. But 始める,決める things up so that you COULD 追加する code.
(The 決定/判定勝ち(する) is rarely hard to 逆転する. You can usually 変える a variable to a constant, or 副/悪徳行為 versa. But do think about the 可能性s.)
We're going to go 支援する to our growing 使用/適用 now, and 簡単に build something which 始める,決めるs up the 製図/抽選 area, and draws a line from upper left to lower 権利.... but is 始める,決める up with 柔軟性 built in.
First, we'll do it "不正に", NOT flexibly. All the に引き続いて will do is 始める,決める up a 製図/抽選 area, and, when you click the Do It button, put a diagonal line across it.
部隊 LD008u1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, 支配(する)/統制するs, Graphics, Dialogs, StdCtrls,
ExtCtrls;
const vers='8 May 14- just draw diagonal 行う/開催する/段階-tweaked';
type
{ Tld008f1 }
Tld008f1 = class(TForm)
buQuit: TButton;
buDoIt: TButton;
Image1: TImage;
laAppInfo: TLabel;
laVer: TLabel;
手続き buDoItClick(Sender: TObject);
手続き buQuitClick(Sender: TObject);
手続き FormCreate(Sender: TObject);
私的な
{ 私的な 宣言s }
Bitmap:TBitmap;
iImageLeft, iImageTop, iImageWidth, iImageHeight:integer;
public
{ public 宣言s }
end;
var
ld008f1: Tld008f1;
実施
{$R *.lfm}
{ Tld008f1 }
手続き Tld008f1.buQuitClick(Sender: TObject);
begin
の近くに;
end;
手続き Tld008f1.buDoItClick(Sender: TObject);
begin
Image1.Picture.Bitmap.canvas.pen.color:=clGreen;
Image1.Picture.Bitmap.canvas.moveto(0,0);
Image1.Picture.Bitmap.canvas.lineto(30,20);
end;
手続き Tld008f1.FormCreate(Sender: TObject);
begin
laVer.caption:='見解/翻訳/版 '+vers;
//Variables 関係のある to the TImage 反対する...
//See https://sheepdogguides.com/lut/lt1Graphics.htm for 詳細(に述べる)s
// of the basics of this part of the 事業/計画(する), getting a useable
// 製図/抽選 surface to work with...
//This "two tier" system... value into iImageLeft, and then
// Image1.left filled from that... may seem 半端物. There are
// 推論する/理由s we need it, 信用 me!
iImageLeft:=32;
iImageTop:=120;
iImageWidth:=30;
iImageHeight:=20;
Image1.left:=iImageLeft;
Image1.最高の,を越す:=iImageTop;
Image1.width:=iImageWidth;
Image1.高さ:=iImageHeight;
Bitmap:=TBitmap.create;//Create a bitmap 反対する
Bitmap.width:=iImageWidth;//割り当てる dimensions
Bitmap.高さ:=iImageHeight;
//In Delphi, bitmap background is white to begin with. 黒人/ボイコット in Lazarus
Bitmap.canvas.pen.color:=clWhite;//1 of 2 lines not needed in Delphi...
Bitmap.canvas.Rectangle(0,0,iImageWidth,iImageHeight);//2 of 2 not needed, Delphi
Image1.Picture.Graphic:=Bitmap; //割り当てる the bitmap to the image 構成要素
//That brings us to the end of the things covered in the earlier tutorial,
// https://sheepdogguides.com/lut/lt1Graphics.htm
end;
end.
==code
Now 追加する two input boxes to the 使用/適用, one for 製図/抽選 area width, one for 製図/抽選 area 高さ.
Use edit boxes. Put labels beside them. Yes... if you put something other than a number in the edit box, it would 原因(となる) problems in a 商業の 使用/適用, but you are not going to 解放(する) this, are you? You can remember: These edit boxes should only have numbers put in them.
And in a 商業の 使用/適用, you would 直す/買収する,八百長をする things so that as soon as what was in the edit box changed, the 使用者 would see a result. For our デモ program, we will put "take notice of what is in the edit boxes" into a "Resize It" button. (Put that button on the form now; we'll 令状 its code in a moment. 指名する it buResizeIt, caption it "Resize It" to keep your "resize" 際立った from the system's "resize".)
Hard-code the 初期の text 所有物/資産/財産 values for the width and 高さ edit boxes 35 and 25... yes, わずかに different from the width and 高さ we have been using.
Now. It "should" be simple to Just Do It, and it would be... apart from just one line.
Create/ Destroy/ Create...
I may be making this more 複雑にするd that it NEEDS to be. Better than not 複雑にするd enough. There's nothing wrong with what we are doing (as far as I know), but it may not be necessary to go "支援する" やめる so far if you want to change the size of the bitmap.
In our form's handler for its FormCreate event, we have the line...
Bitmap:=TBitmap.create;
The Create method 始める,決めるs aside some memory for the 反対する's use, apart from other things. Whenever you do a Create, there must be a matching "Destroy".
At the moment, we are relying on the "Destroy" that takes place as part of the の近くにing of the 使用/適用 to 供給(する) the "Destroy" we need. But if we want a different sized bitmap on Image1, we will have to proceed carefully.
As is always the 事例/患者 when we want to do something more than once somewhere in an 使用/適用, it is best to put the code to be 遂行する/発効させるd 多重の times in a subroutine of its own.
We need to do TBitmap.create both when the 使用/適用 opens for the first time, and also after we have decided on a new size. And called the destroy method for the first bitmap before we create the new, different size one.
A few 半端物s and end go with the TBitmap.create code. I've put them all in a 手続き I've called EstablishBitmap. (A discussion of the に引き続いて occurs after the sourcecode.)
Here is an 早期に 行う/開催する/段階 of LD008. (公式文書,認める the 任命 thus in the "ver" constant. We will be 拡大するing LD008 すぐに.)
部隊 LD008u1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, 支配(する)/統制するs, Graphics, Dialogs, StdCtrls,
ExtCtrls;
const vers='10 May 14- 早期に 行う/開催する/段階- tweaked';
type
{ Tld008f1 }
Tld008f1 = class(TForm)
buQuit: TButton;
buDoIt: TButton;
buResizeIt: TButton;
eWidth: TEdit;
eHeight: TEdit;
Image1: TImage;
laAppInfo: TLabel;
laTxtWidth: TLabel;
laTxtHeight: TLabel;
laVer: TLabel;
手続き buDoItClick(Sender: TObject);
手続き buQuitClick(Sender: TObject);
手続き buResizeItClick(Sender: TObject);
手続き FormCreate(Sender: TObject);
私的な
{ 私的な 宣言s }
Bitmap:TBitmap;
iImageLeft, iImageTop, iImageWidth, iImageHeight:integer;
手続き EstablishBitmap;
public
{ public 宣言s }
end;
var
ld008f1: Tld008f1;
実施
{$R *.lfm}
{ Tld008f1 }
手続き Tld008f1.FormCreate(Sender: TObject);
begin
laVer.caption:='見解/翻訳/版 '+vers;
//Variables 関係のある to the TImage 反対する...
//See https://sheepdogguides.com/lut/lt1Graphics.htm for 詳細(に述べる)s
// of using a bitmap as a 製図/抽選 surface to work with...
iImageLeft:=32;//始める,決める 初期の values for 核心 variables
iImageTop:=120;
iImageWidth:=30;
iImageHeight:=20;
Image1.left:=iImageLeft;//始める,決める 初期の size of TImage 支配(する)/統制する
Image1.最高の,を越す:=iImageTop;
Image1.width:=iImageWidth;
Image1.高さ:=iImageHeight;
EstablishBitmap;
end;
手続き Tld008f1.buDoItClick(Sender: TObject);
begin
Image1.Picture.Bitmap.canvas.pen.color:=clGreen;
Image1.Picture.Bitmap.canvas.moveto(0,0);
Image1.Picture.Bitmap.canvas.lineto(iImageWidth,iImageHeight);
end;
手続き Tld008f1.buResizeItClick(Sender: TObject);
begin
Bitmap.destroy;
iImageWidth:=strtoint(eWidth.text);
iImageHeight:=strtoint(eHeight.text);
EstablishBitmap;
end;
手続き Tld008f1.EstablishBitmap;
//A purist would pass things like iImageWidth to this 手続き
// as parameters. I am "breaking the 支配する" deliberately,
// 裁判官ing the value, here, not 価値(がある) the nuisance.
begin
Image1.width:=iImageWidth;
Image1.高さ:=iImageHeight;
Bitmap:=TBitmap.create;//Create a bitmap 反対する
Bitmap.width:=iImageWidth;//Adjust dimensions
Bitmap.高さ:=iImageHeight;
//In Delphi, bitmap background is white to begin with. 黒人/ボイコット in Lazarus
Bitmap.canvas.pen.color:=clWhite;//1 of 2 lines not needed in Delphi...
Bitmap.canvas.Rectangle(0,0,iImageWidth,iImageHeight);//2 of 2 not needed, Delphi
Image1.Picture.Graphic:=Bitmap; //割り当てる the bitmap to the image 構成要素
//公式文書,認める how we have adjusted the size of the image to the size of the bitmap
// we will be 割り当てるing to it.
end;
手続き Tld008f1.buQuitClick(Sender: TObject);
begin
の近くに;
end;
end.
The code above creates a little app which will put a "graph" on the 使用/適用's window. If you change one or both of the values for "width" and "高さ", and click "Resize it", you get a new, blank bitmap 陳列する,発揮するd on the new, different size TImage 支配(する)/統制する. Clicking DoIt at any time draws a line diagonally across the bitmap.
I 信用 that code is 十分に readable?
In the handler for the FormCreate event, we 始める,決める some 全世界の variables to 初期の values, and call EstablishBitmap.
EstablishBitmap creates a 製図/抽選 surface on Image1. And it fills wGrGAWidth and wGrGAHeight with the Width and 高さ of the "Graph Area". (I will try to say more about this in 予定 course. The "Graph Area" is that part of the bitmap to the left, and above, the two axes.
And that's about all that happens until we click DoIt or ResizeIt.
Clicking DoIt draws a diagonal line across whatever bitmap 現在/一般に 存在するs.
Clicking ResizeIt calls the Destroy method of the 現在の bitmap, but then calls EstablishBitmap, to put a new one in place, after first 協議するing the "width" and "高さ" edit boxes.
So far, so good!
======
Let me remind you of two things I said earlier...
The first of several secrets is this: Develop your "answer" using simple numbers which you can get your 長,率いる around. But your "answer" must be done in a way which can "digest" any numbers.
Another secret is to think of the 調整するs-based 製図/抽選 わずかに 異なって than I 嫌疑者,容疑者/疑う many people do. The "usual", I would guess, way of thinking of 製図/抽選 with 調整するs is to think ーに関して/ーの点でs of infinitesimal points. In 製図/抽選 on a computer 審査する, you are really talking about switching on or off pixels of very real widths and 高さs. On a modern 審査する, they may by tiny, but they are there.
We're now going to work for a bit on an image with nice "human size" numbers... the whole 製図/抽選 area will be 30 x 20. (水平の number will be first throughout. Beware the vertical number, though. While it will always be second, いつかs it will tell you how far 負かす/撃墜する from the 最高の,を越す a point is... that's the usual way in computer graphics... and いつかs it will be how far up from the 底(に届く) something is, as in your earliest graph 製図/抽選. And いつかs where "無" is won't be the 辛勝する/優位 of Image1... but we will 打ち勝つ all these ways to go wrong.
Diag1 {{{ TO BE SUPPLIED STILL
I'm 説 several things in the diagram above...
I'm going to have two axis lines. They will run to the 最高の,を越す of the 製図/抽選 area and to the 権利 手渡す 辛勝する/優位. They will be one pixel wide. A left 利ざや (6 pixels wide, for now) and a 底(に届く) 利ざや (4 pixels) will be created.
I will put 4 in wGrMarBott and 6 in wGrMarLeft and use those variable anywhere that I am using either 利ざや dimension. If I 後継する in always referring to those dimensions thus, it should be simple to draw the graph with different 利ざやs, should I choose to do so. The 指名するs may need comment:
w for "word" type data
Gr for "to do with the GRaph"
損なう for "MARgin"
Left/ Bott for "left" and "BOTTom".
While I will be surprised if I ever use more than a pixel for the width of the axis line, I will still 始める,決める up two variables to make it (比較して) 平易な to have second thoughts. I will put 1 in bGrAxWidX and bGrAxWidY. ("b" for "byte", as I am comfortable in locking myself in to never having an axis line wider than 255 pixels(!). (Ha! The "決定/判定勝ち(する)" to skimp on 実施 of 製図/抽選 axis lines wider than one pixel cost me about three hours of 長,率いる-scratching. But useful 長,率いる scratching, I suppose... I was wiser by the end of 解決するing the puzzles which arose. All of the arising puzzling 事柄s have been edited out of this, unless I 行方不明になるd something in the 続いて起こるing rewrite.)
Here's LDN008 改訂するd to draw in the 水平の axis. 公式文書,認める that a separate "DrawGraph" 手続き has been 始める,決める up, to "含む/封じ込める" the 製図/抽選 of the graph, and the "Do It" button has been re-目的d... it now 簡単に calls DrawGraph.
Don't let the コンビナート/複合体 things like....
Image1.Picture.Bitmap.canvas.moveto
(wGrMarLeft, iImageHeight-wGrMarBott-1);
Image1.Picture.Bitmap.canvas.lineto
(iImageWidth, iImageHeight-wGrMarBott);
... 圧倒する you. We're going to "get rid" of them! But I 手配中の,お尋ね者 you to see how "messy" things are... INTERNALLY. And don't underestimate them. (We'll discuss in a moment.)
(The さまざまな dimension variables have all been given 初期の values in the FormCreate handler.)
WHY is it so messy? Because we ARE 取引,協定ing with 製図/抽選 on a surface with point 0,0 at the upper left, and with the biggest X and Y 調整するs at the lower 権利. Most eople are used, in "everyday life" to things 存在 "the other way up", and even once that's taken care of, the 0,0 of our graph is not at the lower 権利 of our bigger 製図/抽選 area.
For now, we are only going to try to 陰謀(を企てる) the に引き続いて X/Y pairs, by the way...
9,13 11,13 13,12 15,8 18,10 20,7
You can pretend that says "on day 9, the price was $13, on day 11, the price was still $13, on day 13, the price had fallen to $12", and so on. Don't worry... we'll be doing "proper" dates and prices by the end!
So... going 支援する to the messy....
Image1.Picture.Bitmap.canvas.moveto
(wGrMarLeft, iImageHeight-wGrMarBott-1);
Image1.Picture.Bitmap.canvas.lineto
(iImageWidth, iImageHeight-wGrMarBott-1);
... which "簡単に" draws the 底(に届く), X, axis line.
That really does have to be EXACTLY 権利. An extra "-1", or a MISSING "-1" will come 支援する to haunt you terribly... even though a big part of my 推論する/理由 for 令状ing this was to lay the ghosts of my own 混乱 in these 事柄s, I still, even while "支払う/賃金ing attention", frequently made such "errors of one". They DO 事柄!
Look closely at...
Diag 2 {{ DIAGRAM TO BE SUPPLIED
You have to get the endpoints of the line (最高潮の場面d in red) in just the 権利 places.
I've shown the 調整するs, as used in moveto and lineto in green. Such numbers will be called the bitmap 調整するs, to distinguish them.
I 決定するd the bitmap 調整するs for the left 手渡す end of the axis lines by going 支援する almost to "counting on my fingers". I drew the diagram. For the X bitmap 調整する, I knew that the first pixel of the 利ざや was in column 0, then next was column 1, and the one AFTER the 6th 利ざや pixel would therefor be pixel NUMBER 6.
I again "counted on my fingers" for the Y bitmap 調整する of the left 手渡す end of the line. It had to be 15.
Now, from my dimension variables, where could I get 6 and 15? The six was 平易な: wGrMarLeft. Not wGrLeft 加える 1 or minus 1... which you often need... but 簡単に wGrMarLeft.
And the 15? 井戸/弁護士席, it was going to be something like the 高さ of the whole 製図/抽選 area minus the 高さ of the 底(に届く) 利ざや... iImageHeight-wGrMarBott. But with the size and 利ざや we are using, that gives you 16... so, here, we need a "-1". It is all to do with whether you are starting from 無, and whether you want "THAT" one, or the one after it. (For the axis, we want the pixel AFTER the last pixel of the 利ざや.)
It is a bit of a 黒人/ボイコット art... just remember: You have to get EXACTLY the 権利 number, and a +1 or a -1 may be needed, and you should draw a diagram and count on your fingers. 人物/姿/数字 out what it needs to be for 明確な/細部 事例/患者s, and develop a variables-based 決まり文句/製法 which gives you the 権利 numbers.
So.... having 人物/姿/数字d out where the X axis line goes, and assuming that a line a 選び出す/独身 pixel wide is 適する, doing the vertical axis line is 平易な, isn't it?
Image1.Picture.Bitmap.canvas.moveto (wGrMarLeft, iImageHeight-wGrMarBott-1); Image1.Picture.Bitmap.canvas.lineto (wGrMarLeft, -1);
(If you've noticed that the four lines to draw the axes can be 取って代わるd by just three... one moveto, two lineto's, then congratulations. If you 港/避難所't, it isn't a big 取引,協定.)
(While doing asides... you may be surprised to learn this, but I am not going to inscribe 従来の 規模s on my graph, i.e. numbers along the axes to say what a given point 代表するs. Those 使用者 wants aren't going to be 全く ignored, but they will be dealt with unconventionally. I begrudge the 審査する space the numbers would 要求する, and the 成果/努力 it would be to do that programming. It can be done, by all means do it. but I won't (sorry) be 供給するing THAT answer.)
Sigh.
It was genuinely only when I got to this point, and looked closely at the result that I discovered something.
(The Windows "magnifier" helped me to "look closely", by the way. In XP, it is in the "従犯者s/ Accessibility" sub-menu.)
Image1 on my 使用/適用's window, with its two axis lines (after I've clicked "DoIt") had a 黒人/ボイコット line across the 底(に届く) and up the 権利 手渡す 味方する.
I wrote several paragraphs "explaining" this, its consequences and cures. And then realized that the 黒人/ボイコット lines (機の)カム from a different source than I 推定する/予想するd. And so threw them away, and dealt with the 問題/発行する 異なって. You, with the 利益 of this tutorial, may never see those 黒人/ボイコット lines.
Onwards!!!
We have some コンビナート/複合体 "stuff" where things should be simple. Look again at the code to draw the 水平の axis line...
Image1.Picture.Bitmap.canvas.moveto
(wGrMarLeft, iImageHeight-wGrMarBott-1);
Image1.Picture.Bitmap.canvas.lineto
(iImageWidth, iImageHeight-wGrMarBott-1);
Surely that should be...
Image1.Picture.Bitmap.canvas.moveto
(-1,-1);
Image1.Picture.Bitmap.canvas.lineto
(22,-1)
When we start trying to 陰謀(を企てる) the points on our graph to show the prices of the 在庫/株 on different dates, we don't want to be fooling around with 許すing for 利ざやs, flipping the y 調整する from "big at 底(に届く)" to "big at 最高の,を越す"... SO THIS IS WHAT WE DO....
We make two 機能(する)/行事s: iBitMapFrmHumX and iBitMapFrmHumY.
(In the course of developing this 事業/計画(する), this wheel was invented twice. The 指名する iBitMapFrmHumX was discarded in 好意 of iGAtoBitmapX, which was used for everything 以前 done with iBitMapFrmHumX after a 確かな 行う/開催する/段階 in the program's 開発. 計画(する)s were in place to 類似して わずかな/ほっそりした 負かす/撃墜する the corresponding 機能(する)/行事s for Y 調整するs, but with humans and bitmaps numbering the Y axis in opposite directions, perhaps both 機能(する)/行事s will remain necessary to 扱う subtle differences?
We'll start them in "爆撃する" form... they won't, at first 現実に do anything to the numbers passed to them. 結局, they will return the "BitMap" number if given the "Human" number. What do I mean by "BitMap" and "Human" numbers? Go 支援する to the 事例/患者 of 製図/抽選 the 水平の axis. We draw it TO....
iImageWidth, iImageHeight-wGrMarBott-1
i.e., with things as we are doing them, TO (but not 含むing... which is just 同様に, as it is off the 権利 手渡す 辛勝する/優位 of the 製図/抽選 area... 30,15. (Last pixel is at 29 across.) But, ーに関して/ーの点でs of where that is on the part of the bitmap we are using for 陳列する,発揮するing data points, that would be
22, -1 {{ TO BE CHECKED. MAY HAVE Error-of-one
So, 結局, iBitMapFrmHumX will 変える 22 to 29, and iBitMapFrmHumY will 変える -1 to 15. {{CHECK THESE NUMBERS
Here's the 核心 of the code at start of the 過程....
手続き Tld008f1.DrawGraph;
begin
Image1.Picture.Bitmap.canvas.pen.color:=clBlack;
Image1.Picture.Bitmap.canvas.moveto
(iBitMapFrmHumX(wGrMarLeft),iBitMapFrmHumY(iImageHeight-wGrMarBott-1));
Image1.Picture.Bitmap.canvas.lineto
(iBitMapFrmHumX(iImageWidth-1),iBitMapFrmHumY(iImageHeight-wGrMarBott-1));
Image1.Picture.Bitmap.canvas.moveto
(iBitMapFrmHumX(wGrMarLeft),iBitMapFrmHumY(iImageHeight-wGrMarBott-1));
Image1.Picture.Bitmap.canvas.lineto
(iBitMapFrmHumX(wGrMarLeft),iBitMapFrmHumY(0));
end;
機能(する)/行事 Tld008f1.iBitMapFrmHumX(iConvert:integer):integer;
begin
result:=iConvert;
end;
機能(する)/行事 Tld008f1.iBitMapFrmHumY(iConvert:integer):integer;
begin
result:=iConvert;
end;
"This is PROGRESS?", I hear you wail? Yes! It is! Really!
井戸/弁護士席... it will be when we put "the guts" into the two 機能(する)/行事s.
When we've done that, if we want, say, to draw a line from the pixel one to the left of the area for our graph, the area INSIDE the axes, and one below the 底(に届く) of the area for our graph, we will start that line with...
Image1.Picture.Bitmap.canvas.moveto( iBitMapFrmHumX(-1),iBitMapFrmHumY(-1));
That IS better than what we need at the moment, isn't it?!
There's just the little 事柄 of 令状ing "the guts". And let me 警告する you up 前線: They are 類似の, but NOT the same.
Always start such work by 人物/姿/数字ing out how to を取り引きする the end points. Get the 決まり文句/製法 for them 権利, and the everything else will just 落ちる into place.
So... with our 現在の image size and 利ざやs, and an axis line that is one pixel wide, we need....
X: vvv NUMBERS NEED CHECKING FOR off-by-one ERRORS -1 in human 条件 should 変える to 6 for the bitmap 調整するs.. this from the left 手渡す end of the 水平の axis 22 in human 条件 should 変える to 29.. this from the 権利 手渡す end of the 水平の axis. Y: -1 in human 条件 should 変える to 15 for the bitmap 調整するs.. this from the 底(に届く) end of the vertical axis 14 in human 条件 should 変える to 0.. this from the 最高の,を越す end of the vertical axis
To 強固にする/合併する/制圧する that:
X: -1 -> 6 {{{ CHECK NUMBERS
22 -> 29
Y: -1 -> 15
14 -> 0
Notice, の中で other things that with X as one number goes up, so does the other one. But for Y, as the human number goes up, the bitmap number goes DOWN.
When you've worked out those values, and if you keep the "成分s" (利ざや, 全体にわたる size, axis width) in mind, you will probably be able to come up with the に引き続いて. More importantly, those numbers will give you the means to 実験(する) your guesses... I mean "deductions"!... as to what the 決まり文句/製法 せねばならない be.
機能(する)/行事 Tld008f1.iBitMapFrmHumX(iConvert:integer):integer; //ver 13 May 14, 16:18 begin iConvert:=iConvert+wGrMarLeft+bGrAxWidY; result:=iConvert; end; 機能(する)/行事 Tld008f1.iBitMapFrmHumY(iConvert:integer):integer; //ver 13 May 14, 16:18 begin //With iImageHeight=20, wGrMarBott=4, bGrAxWidY=1, the number that // iConvert is taken away from should be 14. //The brackets aren't necessary for the mathematics, but are there // to help you see the basic "trick" of inverting a 一連の // numbers: take a 変化させるing but 増加するing "input" number away // from a constant to 得る a 変化させるing but DEcreasing "生産(高)". iConvert:=wGrGAHeight-iConvert; result:=iConvert; end;
Now that we have those two 機能(する)/行事s (and yes, they could be 連合させるd into a 選び出す/独身 手続き, using "var" type parameters to return the new 調整するs)... Now that we have them, we can 令状 the に引き続いて to draw the two axes....
手続き Tld008f1.DrawXAxis;
var bTmpL:byte;
begin
for bTmpL:=0 to bGrAxWidX-1 do begin
Image1.Picture.Bitmap.canvas.moveto
(iBitMapFrmHumX(-1), iBitMapFrmHumY(-1-bTmpL));
Image1.Picture.Bitmap.canvas.lineto
(iImageWidth,iBitMapFrmHumY(-1-bTmpL));
end;//for
end;
手続き Tld008f1.DrawYAxis;
var bTmpL:byte;
begin
for bTmpL:=0 to bGrAxWidY-1 do begin
Image1.Picture.Bitmap.canvas.moveto
(iBitMapFrmHumX(-1-bTmpL),iBitMapFrmHumY(-1)+bGrAxWidX-1);
Image1.Picture.Bitmap.canvas.lineto
(iBitMapFrmHumX(-1-bTmpL),-1);
end;//for
end;
That IS simpler than what we had before... really. And now, when working with moveto's and lineto's, the programmer can think ーに関して/ーの点でs of the 調整するs of the graphing area, "human" 味方する up (Y 増加するing UP the page)
There IS a fair bit of text in the most 最近の code snippet, but it is very "正規の/正選手". Once you 分析する the pattern, there's not really a lot of 複雑さ there. The "詳細(に述べる)s" have been swept away into inside the iBitMapFrmHumX and -Y 機能(する)/行事s.
=======
I 令状 these tutorials for you as I develop new 使用/適用s. When I first wrote this paragraph, the above was WORKING... for iImageWidth=30, iImageHeight=20, wGrMarLeft=6, etc.... but I hadn't tried to USE the code's 柔軟性 yet.
At the time, I would have said. "If all is 井戸/弁護士席, the Resize button should still work just 罰金. (That will change the values in iImageWidth and 高さ)."
Whew! It did! Work.
"Should" have done... but we know how much that counts for in programming. What you said always trumps what you meant it to say.
Before going on, I checked one or two other things, even though they can't be changed as easily as the 全体にわたる 高さ and width of Image1. But, because the code is written for it, it isn't too hard to try different 利ざや sizes.
Hurrah! 平易な 実験(する)s passed. It doesn't mean that the code can 対処する with "anything"... but at least it 対処するs with some of the things I've thought of.
Notice: Because of the way the program is written, I can change my 利ざやs and my image size without making ANY changes to lineto and moveto 声明s.
The one thing I couldn't EASILY do with the 存在するing code at the time I wrote the paragraphs above was to make 厚い axis lines. I could tell the program that the axis line WILL be 厚い, say 3 pixels, just by changing the values in bGrAxWidX and bGrAxWidY.
Ha! I was in a relaxed でっちあげる,人を罪に陥れる of mind just after doing the 実験(する)s, when I wrote the first 見解/翻訳/版 of the previous paragraphs. I thought all was 井戸/弁護士席, that I could get on to the next 段階. I also wrote "But I won't see 厚い axis lines. It would be 平易な to 供給する for 厚い axis lines, though."
井戸/弁護士席, and it was just 同様に, I thought I'd TRY changing the values in bGrAxWidX and bGrAxWidY. I thought I could 心配する what I would see. I didn't see what I 心配するd. And for several hours I misinterpreted what I was seeing. 結局, I wrote the code which 許すs axis lines of any thickness. (It was やめる 平易な, but not without the 半端物 little "gotcha" getting me, at first.
Why to I moan? To 警告する you against complacency. To encourage you to make 実験(する)s whenever you see one that can be made. To explain why the code, やめる a way up the page, HAS the "extra bits" which 許す 製図/抽選 wide axis lines.
We have a bitmap. On that bitmap, we have two axis lines. To the left of, and above the lines is a sub-section of the bitmap which I am going to call the "Graph Area" because that is where we will be doing our graph, and the lines 予報するing the movement of the 在庫/株 price.
Two その上の variables will be useful. They 持つ/拘留する the width and 高さ of the Graph Area (in pixels). The variables' 指名するs are...
wGrGAWidth, and
wGrGAHeight
公式文書,認める: If wGrGAWidth is, say, 20, that means that the "指名する" of the 権利 手渡す pixel, when you base the "指名する" on calling the first pixel to the 権利 of the axis "0" is "19". But, because lineTO draws TO, but not 含むing a 目的地, to draw all the way to the 権利 手渡す 辛勝する/優位 of the graph area 要求するs a lineto(iBitMapFrmHumX(20),y); 命令(する). Yes... it is a little hard to stay on 最高の,を越す of it all. But I don't think it can be made any "simpler".
In the ting we just did, we cheated わずかに. We "drew" past the 辛勝する/優位 of "the paper". That will work if our line needs to go to the 辛勝する/優位, and is nearly vertical or nearly 水平の. In other 事例/患者s, we'll need a fancier answer, which we will put in a subroutine we will call MoveLineToAndInclude. It will have four parameters... the start and end points, in "human" 条件, with 0,0 存在 the lower left-手渡す corner of the Graph Area.
Once we have that, MoveLineToAndInclude(0,0,wGrGAWidth-1,wGrGAHeight-1) will draw a line, in whatever color the "pen" happens to be 始める,決める to, from the lower left 手渡す corner of the graph area to the upper 権利-手渡す corner of the graph area, which is also the upper 権利-手渡す corner of the bitmap. When you 実験(する) it, you won't be alarmed if it draws 11, not 10, pixels, will you? If you draw one at 0,0 and one at 10,10, and one at all the pixels in between, you ARE going to draw 11, aren't you? It is this sort of "error-of-one", or "fencepost" error that can 運動 you potty.
Believe it or not... the 運命/宿命s relenting?... I was able to 生成する and 実験(する)....
手続き Tld008f1.MoveLineToAndInclude(iX1,iY1,iX2,iY2:integer); begin Image1.Picture.Bitmap.canvas.moveto(iBitMapFrmHumX(iX1),iBitMapFrmHumY(iY1)); Image1.Picture.Bitmap.canvas.lineto(iBitMapFrmHumX(iX2),iBitMapFrmHumY(iY2)); Image1.Picture.Bitmap.canvas.pixels[iBitMapFrmHumX(iX2),iBitMapFrmHumY(iY2)]:=Image1.Pic ture.Bitmap.canvas.pen.color; end; //MoveLineToAndInclude
... in under 15 minutes. There must be a bug in it which I won't 位置/汚点/見つけ出す until it is much harder to を取り引きする. Sigh.
About an hour ago, we were talking of putting some datapoints on the graph. We'll do it very crudely, at first. The に引き続いて go in the DrawGraph subroutine..
Image1.Picture.Bitmap.canvas.pixels[iBitMapFrmHumX(9),iBitMapFrmHumY(13)]:=Image1.Pictu re.Bitmap.canvas.pen.color; Image1.Picture.Bitmap.canvas.pixels[iBitMapFrmHumX(11),iBitMapFrmHumY(13)]:=Image1.Pict ure.Bitmap.canvas.pen.color; Image1.Picture.Bitmap.canvas.pixels[iBitMapFrmHumX(13),iBitMapFrmHumY(12)]:=Image1.Pict ure.Bitmap.canvas.pen.color; Image1.Picture.Bitmap.canvas.pixels[iBitMapFrmHumX(15),iBitMapFrmHumY(8)]:=Image1.Pictu re.Bitmap.canvas.pen.color; Image1.Picture.Bitmap.canvas.pixels[iBitMapFrmHumX(18),iBitMapFrmHumY(10)]:=Image1.Pict ure.Bitmap.canvas.pen.color; Image1.Picture.Bitmap.canvas.pixels[iBitMapFrmHumX(20),iBitMapFrmHumY(7)]:=Image1.Pictu re.Bitmap.canvas.pen.color;
天然のまま! But it WORKS! Hurrah! A graph with some "在庫/株 prices" on it.
The program so far... 陳謝s for "捨てるs" this may 含む/封じ込める. I wouldn't 示唆する 収集するing THIS, but here it is, for what it is 価値(がある)....
部隊 LD008u1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, 支配(する)/統制するs, Graphics, Dialogs, StdCtrls,
ExtCtrls;
const vers='9 May 14- middle 行う/開催する/段階- 陰謀(を企てる)s unscaled simple data';
type
{ Tld008f1 }
Tld008f1 = class(TForm)
buQuit: TButton;
buDoIt: TButton;
buResizeIt: TButton;
eWidth: TEdit;
eHeight: TEdit;
Image1: TImage;
laAppInfo: TLabel;
laTxtWidth: TLabel;
laTxtHeight: TLabel;
laVer: TLabel;
手続き buDoItClick(Sender: TObject);
手続き buQuitClick(Sender: TObject);
手続き buResizeItClick(Sender: TObject);
手続き FormCreate(Sender: TObject);
私的な
{ 私的な 宣言s }
Bitmap:TBitmap;
iImageLeft, iImageTop, iImageWidth, iImageHeight:integer;
bGrAxWidX,bGrAxWidY:byte;
wGrMarBott,wGrMarLeft,wGrGAWidth,wGrGAHeight:word;
手続き EstablishBitmap;
手続き DrawGraph;
機能(する)/行事 iBitMapFrmHumX(iConvert:integer):integer;
機能(する)/行事 iBitMapFrmHumY(iConvert:integer):integer;
手続き DrawXAxis;
手続き DrawYAxis;
手続き MoveLineToAndInclude(iX1,iY1,iX2,iY2:integer);
public
{ public 宣言s }
end;
var
ld008f1: Tld008f1;
実施
{$R *.lfm}
{$R+}//Enable 範囲 checking
{ Tld008f1 }
手続き Tld008f1.FormCreate(Sender: TObject);
begin
laVer.caption:='見解/翻訳/版 '+vers;
//Variables 関係のある to the TImage 反対する...
//See https://sheepdogguides.com/lut/lt1Graphics.htm for 詳細(に述べる)s
// of using a bitmap as a 製図/抽選 surface to work with...
iImageLeft:=32;//始める,決める 初期の values for 核心 variables
iImageTop:=120;
iImageWidth:=57;
iImageHeight:=37;
bGrAxWidX:=1;
bGrAxWidY:=1;
wGrMarBott:=4;
wGrMarLeft:=6;
EstablishBitmap;//Must happen AFTER 核心 variables have values
end;
手続き Tld008f1.buResizeItClick(Sender: TObject);
begin
Bitmap.destroy;
iImageWidth:=strtoint(eWidth.text);
iImageHeight:=strtoint(eHeight.text);
EstablishBitmap;
end;
手続き Tld008f1.EstablishBitmap;
//A purist would pass things like iImageWidth to this 手続き
// as parameters. I am "breaking the 支配する" deliberately,
// 裁判官ing the value, here, not 価値(がある) the nuisance.
//Besides 設立するing the bitmap, this 決まりきった仕事 changes the
// values in some variables referred to どこかよそで when
// 規模ing things to fit graph 井戸/弁護士席.
begin
Image1.left:=iImageLeft;//始める,決める size and posn of TImage 支配(する)/統制する
Image1.最高の,を越す:=iImageTop;
Image1.width:=iImageWidth;
Image1.高さ:=iImageHeight;
Bitmap:=TBitmap.create;//Create a bitmap 反対する
Bitmap.width:=iImageWidth;//Adjust dimensions
Bitmap.高さ:=iImageHeight;
//In Delphi, bitmap background is white to begin with. 黒人/ボイコット in Lazarus
Bitmap.canvas.pen.color:=clWhite;//1 of 2 lines not needed in Delphi...
Bitmap.canvas.Rectangle(0,0,iImageWidth,iImageHeight);//2 of 2 not needed, Delphi
Image1.Picture.Graphic:=Bitmap; //割り当てる the bitmap to the image 構成要素
//公式文書,認める how we have adjusted the size of the image to the size of the bitmap
// we will be 割り当てるing to it.
//Now fill two variables with values for the width and 高さ of the
// "Graph Area", i.e. that part of the bitmap to the left of, and
// above the two axes.
//If there are 15 列/漕ぐ/騒動s of pixels and and 25 columns of pixels in the
// Graph Area, then you would 始める,決める wGrGAWidth:=15, wGrGAHeight:=25
wGrGAWidth:=iImageWidth-wGrMarLeft-bGrAxWidY;
wGrGAHeight:=iImageHeight-wGrMarBott-bGrAxWidX;
end; // of EstablishBitmap
手続き Tld008f1.DrawGraph;
begin
Image1.Picture.Bitmap.canvas.pen.color:=clBlack;
DrawXAxis;
DrawYAxis;
//MoveLineToAndInclude(0,0,wGrGAWidth-1,wGrGAHeight-1);
Image1.Picture.Bitmap.canvas.pixels
[iBitMapFrmHumX(9),iBitMapFrmHumY(13)]:=
Image1.Picture.Bitmap.canvas.pen.color;
Image1.Picture.Bitmap.canvas.pixels
[iBitMapFrmHumX(11),iBitMapFrmHumY(13)]:=
Image1.Picture.Bitmap.canvas.pen.color;
Image1.Picture.Bitmap.canvas.pixels
[iBitMapFrmHumX(13),iBitMapFrmHumY(12)]:=
Image1.Picture.Bitmap.canvas.pen.color;
Image1.Picture.Bitmap.canvas.pixels
[iBitMapFrmHumX(15),iBitMapFrmHumY(8)]:=
Image1.Picture.Bitmap.canvas.pen.color;
Image1.Picture.Bitmap.canvas.pixels
[iBitMapFrmHumX(18),iBitMapFrmHumY(10)]:=
Image1.Picture.Bitmap.canvas.pen.color;
Image1.Picture.Bitmap.canvas.pixels
[iBitMapFrmHumX(20),iBitMapFrmHumY(7)]:=
Image1.Picture.Bitmap.canvas.pen.color;
end;
機能(する)/行事 Tld008f1.iBitMapFrmHumX(iConvert:integer):integer;
//ver 13 May 14, 16:18... see LT3Nf.htm, if you need to alter.
begin
iConvert:=iConvert+wGrMarLeft+bGrAxWidY;
result:=iConvert;
end;
機能(する)/行事 Tld008f1.iBitMapFrmHumY(iConvert:integer):integer;
//ver 13 May 14, 16:18... see LT3Nf.htm, if you need to alter.
begin
//With iImageHeight=20, wGrMarBott=4, bGrAxWidY=1, the number that
// iConvert is taken away from should be 14.
//The brackets aren't necessary for the mathematics, but are there
// to help you see the basic "trick" of inverting a 一連の
// numbers: take a 変化させるing but 増加するing "input" number away
// from a constant to 得る a 変化させるing but DEcreasing "生産(高)".
iConvert:=wGrGAHeight-iConvert;
result:=iConvert;
end;
手続き Tld008f1.DrawXAxis;
var bTmpL:byte;
begin
for bTmpL:=0 to bGrAxWidX-1 do begin
Image1.Picture.Bitmap.canvas.moveto
(iBitMapFrmHumX(-1), iBitMapFrmHumY(-1-bTmpL));
Image1.Picture.Bitmap.canvas.lineto
(iImageWidth, iBitMapFrmHumY(-1-bTmpL));
end;//for
end; //DrawXAxis
手続き Tld008f1.DrawYAxis;
var bTmpL:byte;
begin
for bTmpL:=0 to bGrAxWidY-1 do begin
Image1.Picture.Bitmap.canvas.moveto
(iBitMapFrmHumX(-1-bTmpL),iBitMapFrmHumY(-1)+bGrAxWidX-1);
Image1.Picture.Bitmap.canvas.lineto
(iBitMapFrmHumX(-1-bTmpL),-1);
end; //for
end; //DrawYAxis
手続き Tld008f1.MoveLineToAndInclude(iX1,iY1,iX2,iY2:integer);
begin
Image1.Picture.Bitmap.canvas.moveto(iBitMapFrmHumX(iX1),iBitMapFrmHumY(iY1));
Image1.Picture.Bitmap.canvas.lineto(iBitMapFrmHumX(iX2),iBitMapFrmHumY(iY2));
Image1.Picture.Bitmap.canvas.pixels[iBitMapFrmHumX(iX2),
iBitMapFrmHumY(iY2)]:=Image1.Picture.Bitmap.canvas.pen.color;
end; //MoveLineToAndInclude
手続き Tld008f1.buQuitClick(Sender: TObject);
begin
の近くに;
end;
手続き Tld008f1.buDoItClick(Sender: TObject);
begin
DrawGraph;
end;
end.
We've built an 使用/適用 which can be 陳列する,発揮するd in different sized windows. And the area 充てるd to the graph can be changed. But, so far, the 規模s (X and Y) are 直す/買収する,八百長をするd. This means that a larger graph just shows more blank space, and it means that the data 範囲 the 使用/適用 can 陳列する,発揮する is 制限するd.
We're going to make some changes to the program, to dispense with those 制限s.
In 予定 course, the program will ざっと目を通す the data which is to be plotted. First, a 範囲 of dates to have their data 陳列する,発揮するd will be 決定するd. Then, the prices for that 範囲 of dates will be 分析するd, and the high and low price will be known. From those data, 規模ing constants will be derived, to be 適用するd to the data so that it uses a suitable 部分 of the Graph Area. (That part of the bitmap to the 権利 of, and above, the axis lines.)
We will 確実にする that the program is always 現在のd with data, from whatever source, in 逆転する chronological order. If we can assume that, 面s of the programming are 簡単にするd, and 死刑執行 times are 改善するd. Think about it: If the 使用者 has said that he/ she only wants the graph to look 支援する from today for 6 weeks, if you know the data is in chronological order, you ざっと目を通す the data until you 遭遇(する) a date from more than 6 weeks ago. When you 遭遇(する) that, you can dispense with the 残り/休憩(する) of the data とじ込み/提出する.
最初, we're going to hardcode the data 限界s. We'll create the に引き続いて variables for keeping 跡をつける:
PrHigh PrLow
We will, for the moment anyway, continue using the same data, i.e.
9,13 11,13 13,12 15,8 18,10 20,7
You can pretend that says "on day 9, the price was $13, on day 11, the price was still $13, on day 13, the price had fallen to $12", and so on. Don't worry... we'll be doing "proper" dates and prices by the end!
Dates are 表明するd as days since an 独断的な start date. For our 開発 work, we will 最初 say that "today" is day 20, and we only want to go 支援する to day 9.
For our 開発 work, the highest price in our data (above) 13 and the lowest is 8
So... to use all of the Graph Area, we should be 規模ing things so that on the X axis, we 陰謀(を企てる) "9" at the left 手渡す end, and "20" at the 権利 手渡す end.
Now... the number of pixels 利用できる to us for this changes from time to time. Every time, in fact, that we resize the bitmap that the Graph Area is part of.
However: although we don't know "the number" for the 現在の width of the Graph Area, we do know that whatever it is, it will have been 蓄える/店d in wGrGAWidth, and is thus 利用できる to us.
We'll put the date we want to be shown at the left 手渡す end of the graph in DateBackTo, and the most 最近の date we want shown in DateFrom. Both are inclusive. In other words, in the 明確な/細部 事例/患者 of our 実験(する) data we want day 9's column at the left and day 20's at the 権利... and both ON the graph. (In 予定 course, we may wish to arrange for some blank space to the 権利 of the last data point, but that's something we can introduce later. I'm not just 説 that wishfully. I've worked out that we can.
So... not unlike the challenge that 直面するd us before when we were 変えるing from bitmap pixel 調整するs to human and graph friendly 調整するs, we have what is a 規模ing problem.
For the X axis, in our 明確な/細部 事例/患者, we want some numbers which go from 9 to 20 (inclusive) to be 平等に spread across the 範囲 0 to whatever's in wGrGAWidth-1, inclusive. (And yes, the "-1" is important, and 権利.
Wouldn't it be nice if wGrGAWidth-1 were always 11? Then the 支配する would be simple: Date m should be shown on the graph at m-9. What if wGrGAWidth-1 were always 22? Then the 支配する would be (m-9) times 2, wouldn't it?
All such 規模ing problems come 負かす/撃墜する to the same 決まり文句/製法: The number you need is your previous number minus some constant (k1), and then that is 多重のd by some other constant (k2).
If your high and low numbers (for the data, 9 and 20, in our 事例/患者) are in the variables DateFrom and DateBackTo, as we said they would be, then k1 is 簡単に DateBackTo.
The other constant, k2, is a little いっそう少なく obvious. It can be 得るd from....
((wGrGAWidth-1)-(0))/(DateFrom-DateBackTo)
ーに関して/ーの点でs of the シナリオ we've been speaking of, that is (22-0)/(20-9)... i.e. 2
Ah... is nothing ever simple?
Think about the に引き続いて numbers...
5, -5, 300, 15.7, 15.72342, one third, "pi", as in 3.1415...
In our day to day life, those are "just numbers". Few of us have got beyond elementary school, and thus still dislike "fractions", but even so, they're still "just numbers", even if yucky numbers.
When you put numbers into computers, a whole bunch of question arise about how you are going to turn even the short 名簿(に載せる)/表(にあげる) I gave above into 1s and 0s. Some 計画/陰謀s work 井戸/弁護士席 for a whole bunch of types of numbers... but they tend to be コンビナート/複合体, use up memory and 貯蔵, and have associated 速度(を上げる) 刑罰,罰則s. Simple, efficient, 急速な/放蕩な 計画/陰謀s tend to 控訴 only a 限られた/立憲的な 範囲 of numbers.
Everything we've done so far has been "computer friendly". I've used byte, word and integer data types やめる deliberately, always using the "best" type (in the 狭くする, programmer's sense of that word) for any given need.
Now, however, as part of our 規模ing wants, a 分割 is 伴う/関わるd. Sigh. That leads to "difficult" (for the computer, too) numbers.
So what we're going to do is this: We're going to take our nice byte-, word-, and integer- type numbers, turn them into "real"(-type) numbers... using that 称する,呼ぶ/期間/用語 "real" in the 幅の広い "mathematician's" sense, not the 狭くする Pascal (Lazarus, Delphi) sense. (I will be using the Pascal "選び出す/独身" data type.
So... to repeat the heart of that!... we will turn our numbers into 選び出す/独身-type numbers long enough to do the work that we need fractions for, and then we will "throw away" the 選び出す/独身-type number we've arrived at when it has done its 職業.
I'll give you a 明確な/細部 example. Let's suppose we want to 陰謀(を企てる) a price of, say, $25 on our graph. And that the combination of all the 関連した things means that we need to subtract 5 and multiply by 5/15 to get the 相殺する from the x-axis line for the Y 調整する for that data point. We will have 0.3333 蓄える/店d in a variable, we'll call it siScY (for "選び出す/独身-type data, 規模ing factor, Y 調整する). We will do...
25 minus 5 times siScY
... which comes to 6.666..
And so we will put that data point 7 部隊s above the x-axis line.
Not so very "difficult" in underlying 原則, just hard to 表明する succinctly, if you're trying to 伝える the why behind the what.
And the program isn't so very コンビナート/複合体, either... even though it will look pretty dreadful, 特に as "the numbers" we want to work with are starting as things like....
iBitMapFrmHumY(7)
We will, of course, use 機能(する)/行事s... one to 変える from our raw data to an X 調整する, one for 変えるing to a Y 調整する.
I 格闘するd with something here.
At the moment, while we still have 人工的な data which doesn't need 規模ing, we 陰謀(を企てる) a data point thus...
Image1.Picture.Bitmap.canvas.pixels
[iBitMapFrmHumX(20),iBitMapFrmHumY(7)]:=
Image1.Picture.Bitmap.canvas.pen.color;
The "Pixels" method is built into Lazarus, and assumes that if you give it, say, 5 and 12, you want to color in the pixel 5 across, and 12 負かす/撃墜する on the bitmap.
iBitMapFrmHumX, and iBitMapFrmHumY are our 機能(する)/行事s, which take our raw data and 変える it to suitable numbers for the Pixels method. All this we have discussed. Those 機能(する)/行事s could be simple because I'd "cooked the 調書をとる/予約するs" and 供給するd only data which would, without 規模ing, fit nicely on a sensibly sized (if rather small) bitmap.
Half of me wants to be "clever", and do an all singing, all dancing 機能(する)/行事, and do both the 規模ing and the 転換 from x, y numbers we might 認める the x, y 調整するs needed by Pixels. (Different 範囲 that the numbers in their raw 明言する/公表する, and Y 調整する "flipped" so that small raw numbers turn into big 変えるd numbers, and 副/悪徳行為 versa, because the Y numbers on a bitmap go UP as you go DOWN the bitmap- the opposite to the way we usually draw graphs.
The programming artist in me has a "gut feeling" that there might be advantages to "all in one" 機能(する)/行事s. 特に, we might get a better mapping between raw numbers and final bitmap.Pixel 調整するs.
And then the programming scientist in me says "No! Divide and 征服する/打ち勝つ!"
At one point in the design 過程, I thought I'd go ahead with the "Divide and 征服する/打ち勝つ" approach. I was going to take our 存在するing....
Image1.Picture.Bitmap.canvas.pixels
[iBitMapFrmHumX(20),
iBitMapFrmHumY(7)]:=
Image1.Picture.Bitmap.canvas.
pen.color;
... and make it....
Image1.Picture.Bitmap.canvas.pixels
[iScaleX(iBitMapFrmHumX(20)),
iScaleY(iBitMapFrmHumY(7))]:=<
br>
Image1.Picture.Bitmap.canvas.
pen.color;
That "should" be possible. It "should" only 要求する....
機能(する)/行事 Tld008f1.iScaleX(iConvert:integer):integer; //ver 13 May 14, 16:18... see LT3Nf.htm, if you need to alter. var siTmp:選び出す/独身; begin siTmp:=(iConvert-iScXOffset)*siScXStretch; iTmp:=trunc(siTmp); result:=iTmp; end;
(and something 平等に simple for iScaleY, just different constants.)
It really "should", I think, work that way... if you can 供給する the 権利 規模ing constants in iScXOffset and siScXStretch... which I'm not at all sure about.
(Please 公式文書,認める... I am skipping over some 詳細(に述べる)s of my 仮定/引き受けることs. (Really!) You will have to be very on your toes to take this program and re-目的 it for different sorts of data than the data I told you at the beginning that this program would 扱う.)
(Sidebar ends)
The sidebar, above, if that's not an oxymoron, went into some of my thinking which boils 負かす/撃墜する to the に引き続いて:
In developing this program, I got to a 行う/開催する/段階 where I knew there were at least two ways 今後. One "felt 権利". The other 固執するd to 支配するs I know to be good.
One was コンビナート/複合体, fraught with ways to go wrong, and 可能性のある hard-to-debug コンビナート/複合体 messes... but it was a path which might have been "necessary". I knew there was a way through by that 計画(する)... but could I find it?
The other path kept the 支配するs, but there was one little "niggle"... how hard would it be to come up with, and 持続する, the 規模ing constants.
I was puzzling over "Which way should I proceed?"
I realized that I hadn't taken my own advice, not in 詳細(に述べる), not with the sorts of numbers I 手配中の,お尋ね者 to use "for real". So far we have been working with "make believe" numbers which were chosen to 避ける some of the 複雑さs that the real-world numbers introduce.
The advice I wasn't taking was to consider the extremes. See how everything 作品 with the biggest and smallest numbers you want to use, see how you might 扱う them, and the other numbers will 落ちる into place.
I had 現実に done that, without showing you, for the "make believe" numbers. Now it was time to do it for the real-world numbers....
The "raw", "real-world" X and Y which will give rise to a data point at the lower left of the graph will be something like 47800,5832. The first (X) number will always be "big", and an integer. The second (Y) number might be 近づく 無, but will never be 消極的な.
The "raw", "real-world" X and Y which will give rise to a data point at the upper 権利 of the graph will be something like 49000,5832. The first (X) number will always be greater than the X number for the lower left corner, and an integer. The second (Y) number will always be greater than the Y number for the lower left corner, and an integer, perhaps as high as 5,000,000. (As I was typing this paragraph for the first time, I worked that out for the first time... way to late to be doing so. It might be a minor nuisance, 要求するing some re-working of data types I laid 負かす/撃墜する earlier. Sigh. Oh 井戸/弁護士席... will help me learn the lesson of "know where you are going before you start the 旅行. I should have looked more closely at my 可能性のある data 範囲 earlier.
So: Lower left: 47,800 / 5,832
Upper 権利: 49,000 / 5,000,000
If we are working with a bitmap that is 45 x 30, and if we have a left 利ざや of 6 and a 底(に届く) 利ざや of 4, and axis lines which are 1 pixel wide, those numbers need to be 変えるd, to (概略で... there may be errors-of-one in the に引き続いて)...
Lower left Upper 権利
X Y ~ X Y
47,800 5,832 ~ 49,000 5,000,000 Raw numbers
0 0 30 20 "Graph Area" 調整するs
6 26 39 0 Bitmap 調整するs
Yes, Virginia, you really do have to look at these things that closely.
Working out the numbers with a pen on a sheet of paper is easier than doing them with a keyboard, it must be said.
In trying to come up with those 人物/姿/数字s, I "just 自然に" went from the raw to the Graph Area to the bitmap. That doesn't mean that I've automatically come up with the best sequence... but I will 調査/捜査する that first, as it seems "論理(学)の" to me.
How hard is it to get from the raw numbers to the Graph Area 調整するs (GACs)? Or, alternatively, how hard is it to get from the GACs to the bitmap 調整するs (BMCs)?
井戸/弁護士席... From GAC to BMC: not hard at all. We've already written 機能(する)/行事s for this. So let's think closely about the raw numbers to GACs 転換....
It will entail a 分割, and thus the number-type nuisance. Not insuperable. To make the 転換s, we'll need to know the 範囲 of the "input" numbers. We can manage that. We need to know the 範囲, the 限界s, of the "生産(高)" numbers that we want... Umm.. Yes! We can 接近 those, to!
So it looks like our algorithm should be....
Take raw numbers, 変える to Graph Area 調整するs. We will make iScaleX and iScaleY do this, by setting up the constants they use accordingly.
Take Graph Area 調整するs, 変える to bitmap 調整するs.
We could 令状, for, say, the X 調整する, and ignoring the prefix to 示す number type, for the moment....
Tmp:=RawToGAX(RawX); Tmp:=GAtoBitmapX(Tmp);
... as long as we 令状 機能(する)/行事s "RawToGA" and "GAtoBitmap".. which I know I can do.
The above can be made more compact....
Tmp:=GAtoBitmapX(RawToGAX(RawX));
.. and it will be a CLOSE 親族 to that, and something 類似の for the Y 調整する, which will be at the heart of the datapoint plotting 決まりきった仕事 in our final program.
Courage, mon 勇敢に立ち向かうs!!
It seems I have reinvented some wheels in the course of the 最近の discussions. Earlier, I 生成するd iBitMapFrmHum, which has "再現するd" out of the above theoretical discussion under the 指名する "GAtoBitmapX. And earlier, I 生成するd the "iScaleX" 機能(する)/行事, which did what the theoretical GAtoBitmapX 機能(する)/行事 should do.
As an 演習 in seeing that all is REALLY 井戸/弁護士席, that the earlier "testbed" 機能(する)/行事s really do do all that is needed for plotting the datapoints, I am going to 存在 in the new 機能(する)/行事s, and 徐々に 少しのd out all traces of the 初めの ones. Amazing what "little 詳細(に述べる)s" you いつかs "trip over" during such 開発 work. Sigh.
For a little while, I am not going to take you line by line through the 開発 過程. Sorry!
Now "all" that's left, for this part of the programming, is to put into 影響 what the above careful work has planned. And "weeding" the "捨てるs" of the 原型 機能(する)/行事s iBitmapFrmHum and iScale. Because of the care during planning, we "should" not have trouble with it working. There will be a little work to 会社にする/組み込む all we planned, and do everything at the 権利 time and place, but no 仕事 should be bigger than my brain can 持つ/拘留する at one time.
Particular care will be needed over the 決意 of the constants we will be using, both in the GAtoBitmapX and RawToGAX 機能(する)/行事s, and their "Y" cousins. We must get the RIGHT constants, and we must re-calculate them at the 権利 times.
The RawToGAX constants need recalculation whenever we change the 始める,決める of raw data to be 陳列する,発揮するd.
The GAtoBitmapX constants need recalculation whenever we change the dimensions of the Graph Area, either because we've changed the size of the bitmap, or because we've chosen different 利ざや sizes or axis line widths.
Tedious 詳細(に述べる). No ロケット/急騰する Science.
As I said, we've already done the GAtoBitmapX (and -Y) 機能(する)/行事s once. (As iBitMapFrmHumX and -Y.) We'll need to look closely at what worked for the 見本 data, make sure it is still all we need, but I don't 心配する any big hassles.
I have no 悔いるs about going into such 詳細(に述べる) above. It shows you what is a Very Good Idea, and it has made sure that I really know where I am going.
A small thing....
We had a number of lines like...
Image1.Picture.Bitmap.canvas.pixels
[iBitMapFrmHumX(9),iBitMapFrmHumY(13)]:=
Image1.Picture.Bitmap.canvas.pen.color;
... for plotting individual points on the graph.
I'm changing that, first to...
wTmpX:=9;
liTmpY:=13;
Image1.Picture.Bitmap.canvas.pixels
[iBitMapFrmHumX(wTmpX),iBitMapFrmHumY(liTmpY)]:=
Image1.Picture.Bitmap.canvas.pen.color;
... and when I've done all that needs to be done to have that in place, I will go a その上の step...
I will put all of "the stuff" in a small 手続き which I'll call PlotDataPoint, with a word and a longint passed to it, and so where ever I want to 陰謀(を企てる) a datapoint, the coder will only see....
wTmpX:=9; liTmpY:=13; PlotDataPoint(wTmpX,liTmpY); wTmpX:=11; liTmpY:=13; PlotDataPoint(wTmpX,liTmpY); .. etc...
...unless he/ she chooses to delve more 深く,強烈に.
That is possible once....
手続き Tld008f1.PlotDataPoint(wX:word;liY:longint);
begin
Image1.Picture.Bitmap.canvas.pixels
[iBitMapFrmHumX(wX),iBitMapFrmHumY(liY)]:=
Image1.Picture.Bitmap.canvas.pen.color;
end;
... is 利用できる.
The other 利益 of this rearrangement is that as I make the PlotDataPoint 過程 more コンビナート/複合体 (to introduce the re-規模ing we've discussed), all of the work of that is in one place. I won't be editing 多重の lines which should all have 類似の code on them.
AND the 過程 of 供給(する)ing a "stream" of data pairs to the plotting 過程 becomes more (疑いを)晴らす. At 現在の, we are using a hardcoded 一連の 陰謀(を企てる) this, 陰謀(を企てる) this, 陰謀(を企てる) this... 声明s. Not brilliant, but nice and simple. We will be switching over to fetching our 実験(する) data from a string, as discussed long, long ago at the start of this. If the "生成する stream of data to 陰謀(を企てる)" part of the program isn't やめる so 深く,強烈に 絡まるd into the "how we 陰謀(を企てる) one point, Things Will Go Better!
結局, we will need a 柔軟な program, which can 査定する/(税金などを)課す a data 始める,決める, and alter the values in the 規模ing constants accordingly. For now, we are going to manage that part of the 過程 by 手渡す, but in a manner 一貫した with what we will want (and be able) to do later.
We have to change some of the data 規模ing constants whenever we change data 始める,決めるs. These are the constants which take, say, 47800 to 49000 and 規模 them 負かす/撃墜する to 0 to whatever is the 権利 手渡す column of the Graph Area at the time.
At this point, その上の variables must be introduced, to 持つ/拘留する important (警察などへの)密告,告訴(状). I am 追加するing....
The first will be 大部分は a "placeholder" for the moment. In 予定 course, it will tell us which company's prices are 存在 watched. It is 始める,決める in ChangeDataStep1, and at the same time a label is updated, so that the 使用者 knows what data is 存在 looked at.
The "Max/ Min" variables are to 持つ/拘留する the 最大限 and 最小限 X and Y values in the 現在の data. For the moment, we are setting these by 手渡す. In 予定 course, the 使用/適用 will have to ざっと目を通す the data... only as far 支援する as we want to look (The data とじ込み/提出するs will be sorted, newest data at the 最高の,を越す.)
The data types for the Max/ Min variables were dictated by the nature of the data we want the program to be able to 扱う.
Earlier, we put in place the code to 改訂する さまざまな variables whenever we change the size of the Graph area. We can (indeed must) use some of the numbers from that work in our 現在の work.
What are the 規模ing factors?
When do we re-calculate the 規模ing factors?
The 権利 time for doing that is a time which is not yet 代表するd in the program. We're going to change that, now. First 追加する the buttons, etc, that the 使用者 will see....
追加する a button. Call it buChangeData, label it Change Data.
追加する two labels, call them laTxtDataSet and laDataSet. Caption them "見解(をとる)ing:", and "laDataSet". The caption of laTxtDataSet won't change: That label is just to, umm... label... the OTHER label, the contents of which WILL change, to tell us what data 始める,決める, i.e. what company's prices, we are looking at.
But don't worry... we aren't 現実に going to 器具/実施する ALL of changing data 始める,決めるs, yet. Just put in place the program structures where that stuff WILL go.
As with anything, there's a コンビナート/複合体 web of initializations to get 権利.
As part of the Change Data (始める,決める) 過程, we will recalculate the 規模ing factors. But we can't do that until the variables which depend on the Graph Area's size are 設立するd. But if they (GA variables) change, we must recalculate the 規模ing factors. All very tedious. We just have to take it step by step.
At the moment, we have the subroutine EstablishBitmap, in which the GA variables are filled. It is called during the FormCreate handler, and if we click on the ResizeIt button.
We are, "of course", going to put the ChangeData code into a self 含む/封じ込めるd 手続き... ChangeData. 現実に, it 現れるd (not the ideal way to "program") that what I 想像するd for "ChangeData" was in two parts, one of which was appropriate in some places, the both of them 存在 needed in others. Some messy, and 潜在的に bug-introducing, work 続いて起こるd in which ChangeData was broken into ChangeDataStep1 and ChangeDataStep2.
The 初めの 計画(する) was: "We will call ChangeData during the FormCreate handler, just after we have 遂行する/発効させるd EstablishBitmap." That too 要求するd re-thinking. Not all of that may have made it into this essay, but, I hope, all of the 要求するd finer points are now in the sourcecode, which will be 名簿(に載せる)/表(にあげる)d in 十分な, for this 行う/開催する/段階 of the 使用/適用's 開発, a little その上の 負かす/撃墜する the page.
We will call ChangeData if someone clicks the Change Data button. Do you see the OTHER place we need parts of it? Yes! In the code 遂行する/発効させるd upon a "Resize".
"Parts of it"... that's ominous. And messy. Instead of trying to do 正確に/まさに what I said above, I'm 簡単に going to わずかに 改訂する it.
We will have TWO 手続きs which, between them, do all of the ChangeData 仕事s. I'm giving them the rather unimaginative 指名するs of ChangeDataStep1 and ChangeDataStep2.
Part one will, 結局, 許す us to switch to a different 始める,決める of data, and it will 査定する/(税金などを)課す that data to 設立する the biggest and smallest X and Y values 現在の in it. 結局, it will have a parameter which will either direct it to 接近 the data of a particular 在庫/株, or to 許す the 使用者 to interactively 明示する which 在庫/株 should be looked at next.
ChangeDataStep2 will take the maxima and minima 決定するd in Pt1, 連合させる them with other values, and 生成する the 規模ing factors we need for the 機能(する)/行事s which, in two 行う/開催する/段階s, turn raw data points into bitmap 調整するs, as extensively discussed 以前.
We must call both parts.. 直接/まっすぐに or 間接に... during the FormCreate handler. We must call both parts if we want to change the data 始める,決める.
It is because we only need to call the second part when we do a Resize that the whole 商売/仕事 of splitting ChangeData into two parts was done. (if we are only resizing, the (警察などへの)密告,告訴(状) collected during Pt1 hasn't changed, has it?
井戸/弁護士席... here I sit typing after about a week of working on this. And I'm about to ignore my own advice, even though I KNOW it will come 支援する to haunt me.
It doesn't work.
井戸/弁護士席... not やめる 正確に, anyway.
What we have so far is a pretty good 始める,決める of 決まりきった仕事s to draw a re-sizable graph.
But there's something not やめる 権利 in the 規模ing of the data. The 規模ing in the X direction may be NEARLY 権利. I have a "+1" which I snuck in, '原因(となる) it "made things work". The datapoint associated with the smallest X value, and that associated with the largest X value now appear at the left and 権利 of the graph area. Good! (Not 完全に 実験(する)d, but "seems to work."... which is one of those phrases which you should be 極度の慎重さを要する to. When you find yourself using it, you are probably trying to gloss over something that you need to re-診察する.)
The 規模ing in the Y axis isn't as good. The biggest Y doesn't 陰謀(を企てる) at the 最高の,を越す of the 審査する, and the lowest 陰謀(を企てる)s on or below the Y axis, or even below the bitmap 完全に. (In which 事例/患者, there is no "problem"... we just don't see the datum.)
And I really, really should get to the 底(に届く) of these 問題/発行するs, 直す/買収する,八百長をする them.
But I'm not going to.
I genuinely always ーするつもりであるd to have a 禁止(する)d of white above and below the plotted data points, and to the 権利 of them. For now (famous last words), I am going to rely on the 準備/条項s for them to take care of the shortcomings in my 規模ing 決まり文句/製法 (another dangerous 仮定/引き受けること... how do you know where the problem is, unless you know what the problem is?)... going to rely on those 準備/条項s to be enough, so that I can go on to the more 利益/興味ing (to me) question of the two "境界" lines.
I DO have 信用/信任 that the program is 十分に 井戸/弁護士席 built that the problem which is 主要な to the 予期しない 規模ing will be 孤立するd, probably in the 決まり文句/製法 in ChangeDataStep2 which calculate siScXStretch and siScYStretch, and that one day I will be able to see what is wrong with them, and get that part working better. And if the 問題/発行するs are 孤立するd, as I hope, then a 直す/買収する,八百長をする there won't have cascading 影響s and mess up other things. If I find myself having to 会社にする/組み込む その上の fudges to 融通する earlier fudges, I hope I will show the craftsmanship to say "enough!", and go 支援する and 直す/買収する,八百長をする what I am leaving behind now.
P.S.: Later, I 設立する part of the problem. As ever, cheats never 栄える. Instead of having the computer ざっと目を通す the data it was going to 陰謀(を企てる), and RELIABLY find the 最大限 and 最小限 Xs and Ys, I was doing that by 手渡す... and I hadn't put in the 権利 numbers. Putting in the 権利 numbers, 加える a new "+1" kludge helped... but didn't 完全に 直す/買収する,八百長をする the problems.
We 現在の have a program which will "自動車-fit" our data points, and produce....
{{To be 挿入するd here: Image of a graph with datapoints nicely filling graph area}}
What would be even better for my 目的s is a graph with space above, below, and to the 権利 of the data points....
{{TO BE INSERTED HERE: Image of that
To create what I want is やめる simple. As ever, I want to put 批判的な numbers into variables, and as ever I want to work in 多重のs, not 絶対の increments. In other words I don't want to say "make the blank area to the 権利 of the plotted points say 100 wide", I want to say something like "make the blank area to the 権利 of the plotted points 40% of the width of the GraphArea.
I'm setting up three new variables...
They are all "byte" type variables. The numbers in them are 百分率s.
If I were to 始める,決める them to...
... I would want the graph to draw with a blank 地域 the 権利 of the datapoints consisting of 40% of the width of the GraphArea.
The other two numbers should be 解釈する/通訳するd to 達成する 20% of the 高さ of the GraphArea 存在 blank above the plotted data points, and 10% of the 高さ of the GraphArea below the data points 存在 empty
{{INSERT HERE: DIAGRAM OF SAME}}
Happily, unless I'm 行方不明の something, all of this can be 達成するd just by 挿入するing a little code between....
... and...
(I WAS 行方不明の something... but not too much. I'll explain in a moment. That was indeed all that was needed to 達成する the blank area to the 権利 of the data points.)
We will "嘘(をつく) to" the 決まり文句/製法 which are 決定するing our 規模s. We will "pretend" that we have some X and Y values bigger and smaller than the actual maxima and minima, and 達成する our blank areas that way.
To take some exceedingly convenient numbers as an example, assuming the blank area 百分率s I said I 手配中の,お尋ね者....
Suppose our X values 現実に go from 0 to 59... We'll "tell" the 規模ing 決まり文句/製法 that they go from 0 to 99.
And suppose that our Y values go from 100 to 790. We'll "tell" the 規模ing 決まり文句/製法 that they go from 0-1000.
Of course, in the "real world" the numbers will be messier. But the 量 of "extra" X and Y to 追加する in the さまざまな places shouldn't be hard to 会社にする/組み込む.
At the moment, with no 準備/条項 for the blank areas, the 関連した parts of ChangeDataStep2 look like....
手続き Tld008f1.ChangeDataStep2; begin wScXOffset:=wXMinRaw; liScYOffset:=liYMaxRaw; siScXStretch:=wGrGAWidth/(wXMaxRaw-wXMinRaw+1);//The "+1" is a KLUDGE... //with it, the 範囲 isn't stretched TOO far. (Without it, the last //data point is off the 辛勝する/優位 (or 最高の,を越す... 底(に届く)(?) of page.) //showmessage(inttostr(wGrGAHeight)); siScYStretch:=wGrGAHeight/(liYMaxRaw+1-liYMinRaw);//The "+1" is a KLUDGE. //showmessage(inttostr(一連の会議、交渉/完成する(siScYStretch*1000))); end;
We're going to start with a 天然のまま 実施. We'll make the space to the 権利 of the cloud of plotted points as wide as the cloud, and an area above, and an area below as high as the area of the cloud. Here's what the code for that looks like...
手続き Tld008f1.ChangeDataStep2;
var wFakeXMax:word;
liFakeYMin,liFakeYMax:longint;
begin
wFakeXMax:=wXMaxRaw+wXMaxRaw;
liFakeYMin:=liYMinRaw-liYMinRaw;
liFakeYMax:=liYMaxRaw+liYMaxRaw;
wScXOffset:=wXMinRaw;
liScYOffset:=liFakeYMax;
siScXStretch:=wGrGAWidth/(wFakeXMax-wXMinRaw+1);//The "+1" is a KLUDGE...
siScYStretch:=wGrGAHeight/(liFakeYMax+1-liFakeYMin);//The "+1" is a KLUDGE.
end;
That takes care of most of the "create-gaps" work... all of it in the 事例/患者 of the X axis, but not やめる all of it in the 事例/患者 of the Y axis.
Take a moment to think 深く,強烈に about the whole 規模ing 過程. And as you think about it, don't assume that what I've said and done above is 100% 権利. it has a problem at the upper end of the mapping 過程. A "too small to 事柄" problem, with the sort of numbers I want to work with, and with the blank areas around the plotted data points... but that "small" problem will come 支援する to haunt me one day. Sigh.
Let's say we have data with X=100, 110, 120, 130, 140, 150, 160, 170, 180, and 190. (We'll think about the Y part another time.) Ten points to be plotted. Numbers from 100 to 190.
Let's その上の say that want to 陰謀(を企てる) these on an X axis consisting of 10 pixels, the first 存在 number "0", the last 存在... if there are 10... number (or "索引") "9".
The way to 取り組む such things is first to "slide" all the numbers you want to 陰謀(を企てる) 負かす/撃墜する (or, in some 事例/患者s, up) so that the first one will go on the first pixel. So: Using CAPITAL A to stand for the number we start with, and a lower 事例/患者 "a" to stand for the number we need to turn it into, to get the points plotted on our 11 pixel-wide GraphArea, we start by taking 100 off of each number.
The data with value 100 (A=100) will be plotted in the column of pixel 0 (a=0)... just because of the "事情に応じて変わる" step, as long as the next step doesn't change then number we get from "事情に応じて変わる", which it won't, as you will see.
But! We not only need to "slide" the data, we also need to squeeze (or, いつかs, stretch) it. In this 事例/患者, we can "just see" that a factor of ten is what we need.
Where A=190, we start by taking off 100... that brings the number 負かす/撃墜する to 90. We then divide that by 10... making a=9... which tells us that the data for A=190 should be plotted in pixel NUMBER nine's column, i.e. the tenth column. a=9.
So far, so good. All 作品 nicely with nice tidy numbers. And of course, we have to work out what the 支配するs are for how much to slide, and how much to squeeze or stretch.
But even before we do that, there's another problem.
Take the same 事例/患者 we have been working on. What column of pixels do you use for a data point where the X value is 152. Probably column 5, UI would guess. Or 158? That may turn out to be column 6 if we are 一連の会議、交渉/完成するing, or column 5 if we are truncating. (Trun(5.8) is 5). And it will sort of work either way, as long as we are 一貫した, in the middle part of the graph. But what happens at the ends, 特に the 最高の,を越す end? Probably, if we use truncation, which is my gut instinct, ONLY data (in our example) with an X value of 190 will 陰謀(を企てる) in that last column. 反して for every other column, there is a 範囲 of 10 numbers which all result in a data point in that pixel column. Hmmm. I hate inconsistencies. They often come 支援する to haunt you.
But I'm leaving that there for now, for the same 推論する/理由s I've fudged a few other things in this department.
罰金. (Almost) when the problem is as simple as "How do we 地図/計画する 100-190 (inclusive) の上に 0-9". However... the same 支配するs 適用する, even for more コンビナート/複合体 numbers. It is just harder to be sure that you have the 相殺する and 規模 numbers 権利.
That's enough 深い Thinking for the moment. Let's get 支援する to making it work.
We already (mostly) had things working to fill the GraphArea with our data. We'd started working on creating empty areas on three 味方するs of the cloud of data points.
We got part way to "the answer" by "lying" to the program, and telling it that the 範囲 of numbers in X and in Y was greater than it was. This did the 職業 for the gap to the 権利, and it 拡大するd the 規模 in the Y dimension.... but the datapoints were all at the 底(に届く) of the GraphArea. Both of the 水平の 禁止(する)d of empty space were above the data points.
All we need to do is to "押し進める" them up the page a bit. We don't want to change how much they've been stretched or squeezed. It is almost as if we want to change the program's idea of where Y=0. That isn't 正確に/まさに what we're doing, but it is の近くに. We are changing where, in pixel 部隊s, we want the lowest plotted points.
And the place to "押し進める up" the Y's is in iGAtoBitmapY. 以前, our pixel=0 列/漕ぐ/騒動 and out "put smallest Ys here" 列/漕ぐ/騒動 was the same. Now we want the smallest Ys その上の up the page... which means a SMALLER pixel 列/漕ぐ/騒動 number, remember. Sigh.
Our new will be....
result:=(wGrGAHeight-iConvert-1)-iGrBelowDataCloudGap;
... but that just gives a 指名する to the problem. We need to put a number in that "iGrBelowDataCloudGap" variable. And we do that in ChangeDataStep2
Lesson in program 開発: While building this, I first just made iGrBelowDataCloudGap 10, and ran some 実験(する)s to see if even that would work as 推定する/予想するd... and it did. Which meant it was 安全な(-er) to go 今後 with "存在 clever".
やめる a while ago we said that we didn't want just an "as wide as the data cloud" gap to the 権利 of the data cloud. (And 平等に over-simple sizing of the gaps above and below the cloud). We said we 手配中の,お尋ね者 to 決定する the width and 高さs with...
Now that we've got the basics (mostly) working, we can get "fancy". We'll start with the X gap, because our 必要物/必要条件 is simpler (just a blank area to the 権利 of the data cloud) AND the X 面 is easier because we don't have to を取り引きする the wretched inversion 問題/発行するs.
Our old, 直す/買収する,八百長をするd-sized gap answer (機の)カム out of "mis-報告(する)/憶測ing" the 最大限 X value in the data. 二塁打ing it, with the 実験(する) data we were using "squashed" the plotted data 負かす/撃墜する into 概略で the lower half of the area 利用できる. (If our X data had run from, say, 780-999, I bet the width of the blank area to the 権利 of the data cloud would have been much more than half of the total X axis. But that's a story for another time.
We've chosen to 表明する the width of blank area we want as a パーセント. If we say bGrGapRight:=40, we 推定する/予想する the datacloud to take the first 60% of the width of the 審査する.
We have already 分析するd WHAT numbers we need, WHEN to 得る them, and WHERE to 適用する them.... to 達成する our blank area at the 権利 of the data cloud.
WHAT we need is a value in iGrBelowDataCloudGap.
And this is how we calculate it.
We will start with what 範囲 of X values were going to be mapped の上に the pixels we have 利用できる? (That comes from wXMaxRaw-wXMinRaw. Let's say that in the 現在の 事例/患者 it is 1260.) And we need the number from bGrGapRight, let's say 40(%) for working the example.
Now, on the road to what 少しの need to 追加する use for wFakeXMax. we say, "井戸/弁護士席. if 1260 is 60% of the number we need, then we what we need to 追加する is 1260/60)*40... 840". More 正式に, and 一般に, that is...
siTmp:=(wXMaxRaw-wXMinRaw)/(100-bGrGapRight); iTmp:=trunc(siTmp*bGrGapRight); wFakeXMax:=wXMaxRaw+iTmp;
That code goes very 近づく the beginning of ChangeDataStep2, but after bGrGapRight, bGrGapAbove and bGrGapBelow have been given values.
Now for the gaps above and below. Sigh.
We already have them working, sort of, remember.
But for the Y gaps, we need three numbers. We need liFakeYMin and liFakeYMax for the 目的s of ChangeDataStep2. (We need them to calculate siScYStretch) And we need to calculate iGrBelowDataCloudGap, which is used in iGAtoBitmapY to "押し進める" the data cloud up.
Our method will be 類似の. We know what gap, as a パーセント, we want above. Call it, for this, TopGapPercent. We know what gap, as a パーセント, we want below. Call it, for this, BelowGapPercent. So the パーセント of the Y axis 占領するd by the datacloud, as a パーセント, will be 100-TopGapPercent-BelowGapPercent. We know the 範囲 of raw Ys which will be going into creating the data cloud (liYMaxRaw-liYMinRaw). And with all of that, we can know how much to 拡大する the 範囲 of "supposed" Y values, so that the numbers for making the data cloud AND the 最高の,を越す and 底(に届く) gaps fill the 要求するd 範囲 of pixel 列/漕ぐ/騒動s.
And finally, we know how many 部隊s (in the 部隊s of the raw data) of the Y axis is 充てるd to the 底(に届く) gap. 初めは I said: "It can't be hard (we'll find out!) to 変える that to pixels-献身的な, to put in iGrBelowDataCloudGap." 井戸/弁護士席, 現実に it was, going by that 大勝する. But there was a MUCH simpler 大勝する, which you can see in the code below.
Hmmm. Good theory. I hadn't done it yet, at the time I'd just written out the above for you, to help you see how programs are developed.
(Some time later....)
Whew! That bit done. いっそう少なく than the usual hassle. Code for it...
liTmp:=liYMaxRaw-liYMinRaw; siTmp:=liTmp/(100-bGrGapAbove-bGrGapBelow); liTmp:=trunc(siTmp*bGrGapAbove); liTmp2:=trunc(siTmp*bGrGapBelow); liFakeYMax:=liYMaxRaw+liTmp; liFakeYMin:=liYMinRaw-liTmp2; wScXOffset:=wXMinRaw; liScYOffset:=liFakeYMax; siScXStretch:=wGrGAWidth/(wFakeXMax-wXMinRaw+1);//The "+1" is a KLUDGE... //with it, the 範囲 isn't stretched TOO far. (Without it, the last //data point is off the 辛勝する/優位 (or 最高の,を越す... 底(に届く)(?) of page.) siScYStretch:=wGrGAHeight/(liFakeYMax+1-liFakeYMin);//The "+1" is a KLUDGE. siTmp:=(wGrGAHeight*bGrGapBelow)/100; iGrBelowDataCloudGap:=trunc(siTmp);
... and all of iGAtoBitmapY is now...
result:=(wGrGAHeight-iConvert-1)-iGrBelowDataCloudGap;
(The minus 1 in that is a kludge, 関係のない to the "make blank area at 底(に届く)" bit.)
使用者 will, of course, be able to change the values in the blank-area-sizing variables. 器具/実施するing that should be (famous last words) 平易な, because as I was doing the 早期に work, shown above, I was looking ahead, planning the 使用者 接近.
Long, long ago, I 現在のd, in 孤立/分離, a way to 供給する a program with data.
Then, until now, I didn't use that, choosing instead to get LD008 "working" with a very simple, very small, data 始める,決める.
Now the time has come to change where the 使用/適用 gets it's data, how it uses it. We won't go to the final 行う/開催する/段階 yet, but we will be very の近くに to it when we finish the next 構成要素.
Before I make those major changes, I am going to save LD008 as "finished", and move on to LDN009 for the "bigger and better" 見解/翻訳/版.
We will be making some changes in DrawGraph.
At the moment, it just marches through some hard-coded triplets of 声明s, e.g....
wTmpX:=9; liTmpY:=13; PlotDataPoint(wTmpX,liTmpY);
... one triplet for each data point.
Very 天然のまま. Very 平易な to 器具/実施する, understand.
We're going to move to something like the に引き続いて. I am not using the variable 指名するs I will use in 予定 course. And this is pseudo-code, not, unless there's been a coincidence, valid Lazarus code...
Fetch a data 記録,記録的な/記録する. (A date and a price, put Date and Price)
If 無効の then 報告(する)/憶測 that,
else begin
repeat
PlotDataPoint(Date,Price);
Fetch a data 記録,記録的な/記録する
until newly fetched date is too old, or
とじ込み/提出する is empty
end else
Before the code which will be (手先の)技術d from that can work, we need to 確実にする that どこかよそで (and the 権利 どこかよそで) we always open the data stream, and 始める,決める the "where to find next 記録,記録的な/記録する" pointer pointing at the first 記録,記録的な/記録する. We need to have the program aware of what "too old" would be.
And after the data has been read, we will の近くに the data stream, 推定する/予想するing to re-open it again, later, if we want to look at the data again.
The data in the とじ込み/提出する must be in 逆転する chronological order for the 計画(する) to work. I will probably arrange for the oldest possible date to be 蓄える/店d in a rogue 記録,記録的な/記録する at the end of the とじ込み/提出する. This should stop the program from ever trying to read the 記録,記録的な/記録する "after" the last 記録,記録的な/記録する... but the programming should be 強健な enough to 扱う that 事例/患者, should it arise.
"Simple" enough 計画(する). Ha. Now I am going to go away and 器具/実施する it, without doing all the 詳細(に述べる) you have been getting in the other parts of this tutorial.
Some 詳細(に述べる)s of the variables, etc, used to 器具/実施する the above...
While I am still using the "偽の" datasource, as 述べるd in the 早期に part of this tutorial (LDN007), the pointer telling the system where to go for the start of the next data 記録,記録的な/記録する will be in wWhereInData. The data will be in the constant sDataSource. The value in wWhereInData will 簡単に be the 相殺する into the string. If the 記録,記録的な/記録する we want to read next is the first in the string, wWhereInData will equal 無. If the 記録,記録的な/記録する we want next starts at the 15th character of the string, wWhereInData will be 15. (The 15th character might 井戸/弁護士席 be called "Character 14" in some 状況s, as the first is probably "Character 0"... but for our needs, the "usual", "human" way of counting the characters is more suitable.)
When the final 見解/翻訳/版 is done, I won't need to keep wWhereInData manually. The system will keep 跡をつける of that for me... but it will be kept 跡をつける of somewhere.
Dates are 蓄える/店d in the program as word type values. The oldest date we want to have in the 陳列する,発揮する is held in wOldestToDisplay. That, notice, is inclusive.
The sourcecode, after setting things up to fetch data from the constant sDataSource, looks as follows. If you decide to run it, be advised that you have to look closely for the datapoints on the graph, they are just 選び出す/独身 pixels... but I think you will find that they are there, after you've clicked "Do It"
部隊 LD009u1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, 支配(する)/統制するs, Graphics, Dialogs, StdCtrls,
ExtCtrls;
const vers='10 May 14- Earliest 明言する/公表する';
//拡張 of LD008... a graph 製図/抽選 使用/適用. In this form,
// it draws its data from a constant, sDataSource.
sDataSource='41746-2300/41745-2280/'+
'41744-2270/41743-2265/41742-2270/'+
'41741-2245/41740-2198/41739-2196/41738-2195/41737-2190/41736-2180/'+
'41735-2155/41734-2158/41733-2165/41732-2175/41731-2180/41730-2175/'+
'41729-2180/41728-2175/41727-2180/9999-1000/0000-1000';
type
{ Tld009f1 }
Tld009f1 = class(TForm)
buQuit: TButton;
buDoIt: TButton;
buResizeIt: TButton;
buChangeData: TButton;
Edit1: TEdit;
eWidth: TEdit;
eHeight: TEdit;
Image1: TImage;
laAppInfo: TLabel;
laTxtDataSet: TLabel;
laDataSet: TLabel;
laTxtWidth: TLabel;
laTxtHeight: TLabel;
laVer: TLabel;
手続き buChangeDataClick(Sender: TObject);
手続き buDoItClick(Sender: TObject);
手続き buQuitClick(Sender: TObject);
手続き buResizeItClick(Sender: TObject);
手続き FormCreate(Sender: TObject);
私的な
{ 私的な 宣言s }
Bitmap:TBitmap;
liScYOffset,liPrice:longint;//-2x10^9 to +2x10^9, smallest able to 持つ/拘留する
//the numbers I may 現在の for price-in-pennies. (word can only 対処する
//with up to $655.35, (in pennies: 65535)
iTmp,iImageLeft, iImageTop, iImageWidth, iImageHeight:integer;
bGrAxWidX,bGrAxWidY,bGrGapRight,bGrGapAbove,bGrGapBelow:byte;
wGrMarBott,wGrMarLeft,wGrGAWidth,wGrGAHeight,
wOldestToDisplay,wWhereInData,wDate:word;
iScXOffset,iGrBelowDataCloudGap:integer;
sTmp,sDataSet:string;
wXMaxRaw, wXMinRaw:word;
liTmp,liTmp2,liYMaxRaw, liYMinRaw:longint;
wScXOffset:word;
siTmp,siScXStretch,siScYStretch:選び出す/独身;
手続き EstablishBitmap;
手続き DrawGraph;
機能(する)/行事 iBitMapFrmHumY(iConvert:integer):integer;
手続き DrawXAxis;
手続き DrawYAxis;
手続き MoveLineToAndInclude(iX1,iY1,iX2,iY2:integer);
機能(する)/行事 iScaleX(iConvert:integer):integer;
手続き PlotDataPoint(wX:word;liY:longint);
手続き ChangeDataStep1;
手続き ChangeDataStep2;
機能(する)/行事 iRawToGAX(wConvert:word):integer;
機能(する)/行事 iRawToGAY(liConvert:longint):integer;
機能(する)/行事 iGAtoBitmapX(iConvert:integer):integer;
機能(する)/行事 iGAtoBitmapY(iConvert:integer):integer;
手続き ReadRecord(var w1:word;var li1:longint);
public
{ public 宣言s }
end;
var
ld009f1: Tld009f1;
実施
{$R *.lfm}
{$R+}//Enable 範囲 checking
{ Tld009f1 }
手続き Tld009f1.FormCreate(Sender: TObject);
begin
laVer.caption:='見解/翻訳/版 '+vers;
//Variables 関係のある to the TImage 反対する...
//See https://sheepdogguides.com/lut/lt1Graphics.htm for 詳細(に述べる)s
// of using a bitmap as a 製図/抽選 surface to work with...
iImageLeft:=32;//始める,決める 初期の values for 核心 variables
iImageTop:=120;
iImageWidth:=200;
iImageHeight:=120;
bGrAxWidX:=1;
bGrAxWidY:=1;
wGrMarBott:=4;
wGrMarLeft:=6;
ChangeDataStep1;//Must happen BEFORE EstablishBitMap can occur
EstablishBitmap;//Must happen AFTER 核心 variables have values
//ChangeDataStep2;Is done during EstablishBitMap
end;
手続き Tld009f1.buResizeItClick(Sender: TObject);
begin
Bitmap.destroy;
iImageWidth:=strtoint(eWidth.text);
iImageHeight:=strtoint(eHeight.text);
EstablishBitmap;
//ChangeDataStep2; This happens inside EstablishBitmap.
end;
手続き Tld009f1.EstablishBitmap;
//A purist would pass things like iImageWidth to this 手続き
// as parameters. I am "breaking the 支配する" deliberately,
// 裁判官ing the value, here, not 価値(がある) the nuisance.
//Besides 設立するing the bitmap, this 決まりきった仕事 changes the
// values in some variables referred to どこかよそで when
// 規模ing things to fit graph 井戸/弁護士席.
begin
Image1.left:=iImageLeft;//始める,決める size and posn of TImage 支配(する)/統制する
Image1.最高の,を越す:=iImageTop;
Image1.width:=iImageWidth;
Image1.高さ:=iImageHeight;
Bitmap:=TBitmap.create;//Create a bitmap 反対する
Bitmap.width:=iImageWidth;//Adjust dimensions
Bitmap.高さ:=iImageHeight;
//In Delphi, bitmap background is white to begin with. 黒人/ボイコット in Lazarus
Bitmap.canvas.pen.color:=clWhite;//1 of 2 lines not needed in Delphi...
Bitmap.canvas.Rectangle(0,0,iImageWidth,iImageHeight);//2 of 2 not needed, Delphi
Image1.Picture.Graphic:=Bitmap; //割り当てる the bitmap to the image 構成要素
//公式文書,認める how we have adjusted the size of the image to the size of the bitmap
// we will be 割り当てるing to it.
//Now fill two variables with values for the width and 高さ of the
// "Graph Area", i.e. that part of the bitmap to the left of, and
// above the two axes.
//If there are 15 列/漕ぐ/騒動s of pixels and and 25 columns of pixels in the
// Graph Area, then you would 始める,決める wGrGAWidth:=15, wGrGAHeight:=25
wGrGAWidth:=iImageWidth-wGrMarLeft-bGrAxWidY;
wGrGAHeight:=iImageHeight-wGrMarBott-bGrAxWidX;
//At this point, ChangeDataStep2 must be called to recalc the 規模ing
// factors, but ChangeDataStep1 doesn't need to be called every
// time we are doing EstablishBitmap because いつかs
// we are still 取引,協定ing with the same data, and any data changing
// or 査定する/(税金などを)課すing the 範囲 of values in the data takes place in Pt1
ChangeDataStep2;
end; // of EstablishBitmap
手続き Tld009f1.PlotDataPoint(wX:word;liY:longint);
//This 手続き does 接近 外部の "constants" 同様に.
//X was put in a word-type variable, and Y in a longint
// because of the data 心配するd in the 明確な/細部
// 使用/適用 this was written for. (Word wasn't big
// enough for some of the Y data.)
var iTmpXL,iTmpYL:integer;
begin
iTmpXL:=iGAtoBitmapX(iRawToGAX(wX));
iTmpYL:=iGAtoBitmapY(iRawToGAY(liY));
Image1.Picture.Bitmap.canvas.pixels
[iTmpXL,iTmpYL]:=Image1.Picture.Bitmap.canvas.pen.color;
end;//of PlotDataPoint
手続き Tld009f1.DrawGraph;
begin
Image1.Picture.Bitmap.canvas.pen.color:=clBlack;
DrawXAxis;
DrawYAxis;
//Connect to data stream
wWhereInData:=1;
//Datastream is already 実証するd... happened 支援する in
// ChangeDataStep1 before max/mins 設立する
ReadRecord(wDate,liPrice);
repeat
PlotDataPoint(wDate,liPrice);
ReadRecord(wDate,liPrice);
until {out of data or}wDate<wOldestToDisplay;
//解放(する) 関係 to datastream
//MoveLineToAndInclude(0,0,wGrGAWidth-1,wGrGAHeight-1);
end;//of DrawGraph
//======
機能(する)/行事 Tld009f1.iScaleX(iConvert:integer):integer;
//ver 13 May 14, 16:18... see LT3Nf.htm, if you need to alter.
//This no longer has a 役割 in the code, but remains because
// 言及/関連 is made to a "iScaleX" 機能(する)/行事 in LT3N.htm, a
// tutorial explaining the 開発 of this 使用/適用.
begin
siTmp:=(iConvert-iScXOffset)*siScXStretch;
iTmp:=trunc(siTmp);
result:=iTmp;
end;//iScaleX
//=========
手続き Tld009f1.DrawXAxis;
//Could be made clearer? Use wGrGAHeight/wGrGAWidth, or just work lineto in Bitmap 部隊s?
//Re-word DrawYAxis at same time
var bTmpL:byte;
begin
for bTmpL:=0 to bGrAxWidX-1 do begin
Image1.Picture.Bitmap.canvas.moveto
(iGAtoBitmapX(-1), iBitMapFrmHumY(-1-bTmpL));
Image1.Picture.Bitmap.canvas.lineto
(iImageWidth, iBitMapFrmHumY(-1-bTmpL));
end;//for
end; //DrawXAxis
手続き Tld009f1.DrawYAxis;
//Could be made clearer? Use wGrGAHeight/wGrGAWidth, or just work lineto in Bitmap 部隊s?
//Re-work DrawXAxis at same time
var bTmpL:byte;
begin
for bTmpL:=0 to bGrAxWidY-1 do begin
Image1.Picture.Bitmap.canvas.moveto
(iGAtoBitmapX(-1-bTmpL),iBitMapFrmHumY(-1)+bGrAxWidX-1);
Image1.Picture.Bitmap.canvas.lineto
(iGAtoBitmapX(-1-bTmpL),-1);
end; //for
end; //DrawYAxis
手続き Tld009f1.MoveLineToAndInclude(iX1,iY1,iX2,iY2:integer);
//If you call lineto(0,0,3,3), only pixels 0,0/ 1,1/ and 2,2 are
// 影響する/感情d. This 手続き, when called with the same parameters
// 影響する/感情s all of those pixels AND pixel 3,3.
begin
Image1.Picture.Bitmap.canvas.moveto(iGAtoBitmapX(iX1),iBitMapFrmHumY(iY1));
Image1.Picture.Bitmap.canvas.lineto(iGAtoBitmapX(iX2),iBitMapFrmHumY(iY2));
Image1.Picture.Bitmap.canvas.pixels[iGAtoBitmapX(iX2),
iBitMapFrmHumY(iY2)]:=Image1.Picture.Bitmap.canvas.pen.color;
end; //MoveLineToAndInclude
手続き Tld009f1.buQuitClick(Sender: TObject);
begin
の近くに;
end;
手続き Tld009f1.buDoItClick(Sender: TObject);
//In 予定 course, the "DoIt" button can probably
// be retired, if "DrawGraph" calls can be 挿入するd
// in 戦略の places... 近づく the end of FormCreate
// and ChangeData and Resize seem about 権利, on
// 限られた/立憲的な reflection.
begin
DrawGraph;
end;
手続き Tld009f1.buChangeDataClick(Sender: TObject);
begin
showmessage('In 予定 course, 使用者 will have chance here to say '+
'what data 始める,決める to switch to. At the moment, there is just '+
'the one data 始める,決める. Consider yourself "switched"... from "a" to "a"!');
ChangeDataStep1;
EstablishBitmap;//to (疑いを)晴らす previous data from graph
//ChangeDataStep2; Is done inside EstablishBitmap;
end;
機能(する)/行事 Tld009f1.iBitMapFrmHumY(iConvert:integer):integer;
//ver 13 May 14, 16:18... see LT3Nf.htm, if you need to alter.
//To be written out, 取って代わるd by iGAtoBitmapY. Make 公式文書,認める in
// LT3Nf at place where iBitMap... was developed when it is
// written out.
begin
//With iImageHeight=20, wGrMarBott=4, bGrAxWidY=1, the number that
// iConvert is taken away from should be 14.
//The brackets aren't necessary for the mathematics, but are there
// to help you see the basic "trick" of inverting a 一連の
// numbers: take a 変化させるing but 増加するing "input" number away
// from a constant to 得る a 変化させるing but DEcreasing "生産(高)".
iConvert:=wGrGAHeight-iConvert;
result:=iConvert;
end;
手続き Tld009f1.ChangeDataStep1;
//設立する which data stream is to be read, and "connect" it.
//Do an 分析 of the data, 決定する max and min X and Y
//結局 始める,決める up with a parameter to say "This data", or
// "Ask 使用者 which data".
//Update on-審査する 陳列する,発揮する 指名するing the data 始める,決める we are using.
begin
sDataSet:='SampleData';//This will 結局 be changeable,
// and will tell you what company's prices you are looking
// at, and will be part of 指定するing which data とじ込み/提出する to read.
laDataSet.caption:=sDataSet;//Tell the 使用者 what data we are reading.
//The 使用/適用 is 始める,決める up to ざっと目を通す data とじ込み/提出するs, which must be in
// chronological order, oldest first. The 使用/適用 will not
// always read ALL of the data 利用できる. It will only ざっと目を通す 支援する
// as far as it has been told to by the value in wOldestToDisplay,
// which 使用者s will, one day, be able to change as they wish.
wOldestToDisplay:=41729;
//"Connect" to data, and put pointer to "what 記録,記録的な/記録する we want to read
// next to first 記録,記録的な/記録する.
wWhereInData:=1;
//wWhereInData:=1; is all that's needed to "open the datastream" as
//long as I am using the simple "data source" of the string sDataSource.
//For now, we aren't using a data stream. We are hardcoding the data
//So first two lines of comment in this 封鎖する 単に 示す place of
// things to come
//Put "prep to ざっと目を通す data" in a SR.
//の近くに and re-open datastream between "ざっと目を通す to find max/min" and "ざっと目を通す to 陰謀(を企てる)"
//ざっと目を通す the data, 決定する max/min X and Y
wXMinRaw:=65533;
wXMaxRaw:=0;
liYMinRaw:=99999;
liYMaxRaw:=-5000000;
ReadRecord(wDate,liPrice);
//if 無効の(ior wDate<wOldestToDisplay, 報告(する)/憶測 and 中止する 残り/休憩(する). Else...
begin// "1"
repeat
if wDate<wXMinRaw then wXMinRaw:=wDate;
if wDate>wXMaxRaw then wXMaxRaw:=wDate;
if liPrice<liYMinRaw then liYMinRaw:=liPrice;
if liPrice>liYMaxRaw then liYMaxRaw:=liPrice;
ReadRecord(wDate,liPrice);
until {とじ込み/提出する is empty or} wDate<wOldestToDisplay;
end;//begin "1"
//showmessage(' wXMinRaw'+inttostr(wXMinRaw)+' wXMaxRaw'+inttostr(wXMaxRaw)+
// ' liYMinRaw'+inttostr(liYMinRaw)+' liYMaxRaw'+inttostr(liYMaxRaw));
//の近くに 関係 to datastream. (Code WILL be needed... but not needed until
// using fancier data source than sDataSource
end;
手続き Tld009f1.ChangeDataStep2;
//Work out the 規模ing factors needed for plotting, using
// the 現在の 陳列する,発揮する area (警察などへの)密告,告訴(状) (from variables)
// and the 現在の data 始める,決める's 特徴 (max and
// min X and Y.
//The idea of the 相殺するs and streches are to 地図/計画する data from
// 範囲s defined by the Min/Max variables filled in ChangeDataStep1
// to 範囲s which 控訴 our graphing needs better... from 0 to the
// 最大限 X or Y 調整する, as 表明するd in pixels.
//If, on say the Y axis, our data went from 10 to 110, and we had
// pixels 0 to 10 利用できる to 陳列する,発揮する that data, the 相殺する would
// be 10, to bring 10 to 110 負かす/撃墜する to 0 to 100, and the 規模 factor
// would be 0.1 to bring the 0 to 100 負かす/撃墜する to 0 to 10.
//The first 列/漕ぐ/騒動 (or colum) of pixels in the 陳列する,発揮する area will be
// 列/漕ぐ/騒動 or column "=0", at least as far as the plotting 決まりきった仕事s are
// concerened. It can STAND FOR anything, of course, standing for
// 10 in the example developed above.
var wFakeXMax:word;
liFakeYMin,liFakeYMax:longint;//These variables are not
//really necessary, but I hope they help make more (疑いを)晴らす the
//logic of how the blank areas on the graph are created.
begin
//Fill the 関連した variables with the values which 決定する
// the size of the blank areas above, below, and to the
// 権利 of the cloud of plotted data points.
//These numbers are "パーセントs", in other words, if
// bGrGapRight is 始める,決める to 40, then the 権利 手渡す 40% of
// the width of the GraphArea should be blank.
bGrGapRight:=40;
bGrGapAbove:=20;
bGrGapBelow:=20;
//を取り引きする creating blank area to 権利 of data cloud
//Everything 関連した is here.
siTmp:=(wXMaxRaw-wXMinRaw)/(100-bGrGapRight);
iTmp:=trunc(siTmp*bGrGapRight);
wFakeXMax:=wXMaxRaw+iTmp;
//を取り引きする creating blank areas above and below data cloud.
//Most of what is 関連した here, and a slight change
// was also needed in iGAtoBitmapY. The "-iGrBelowDataCloudGap"
// 称する,呼ぶ/期間/用語 is about creating the 底(に届く) gap.
liTmp:=liYMaxRaw-liYMinRaw;
siTmp:=liTmp/(100-bGrGapAbove-bGrGapBelow);
liTmp:=trunc(siTmp*bGrGapAbove);
liTmp2:=trunc(siTmp*bGrGapBelow);
liFakeYMax:=liYMaxRaw+liTmp;
liFakeYMin:=liYMinRaw-liTmp2;
wScXOffset:=wXMinRaw;
liScYOffset:=liFakeYMax;
siScXStretch:=wGrGAWidth/(wFakeXMax-wXMinRaw+1);//The "+1" is a KLUDGE...
//with it, the 範囲 isn't stretched TOO far. (Without it, the last
//data point is off the 辛勝する/優位 (or 最高の,を越す... 底(に届く)(?) of page.)
//showmessage(inttostr(wGrGAHeight));
siScYStretch:=wGrGAHeight/(liFakeYMax+1-liFakeYMin);//The "+1" is a KLUDGE.
//showmessage(inttostr(一連の会議、交渉/完成する(siScYStretch*1000)));
siTmp:=(wGrGAHeight*bGrGapBelow)/100;
iGrBelowDataCloudGap:=trunc(siTmp);
end;
//=====================
//Raw data to GraphArea 調整する 転換 機能(する)/行事s....
機能(する)/行事 Tld009f1.iRawToGAX(wConvert:word):integer;
//Believed 完全に "sound".
begin
result:=trunc((wConvert-wScXOffset)*siScXStretch);
end;
機能(する)/行事 Tld009f1.iRawToGAY(liConvert:longint):integer;
//This will do 相殺する and 規模 but NOT the inversion which the
// "upside 負かす/撃墜する" Y axis of the bitmap 需要・要求するs. That's taken care
// of withing iGAtoBitmap. The numbers from iRawToGAY run from
// 無 to wGrGAHeight (-1) (or not.. there may be a "off-by-one"
// problem lurking here... change calc of 規模 factor, if so,
// but as I 計画(する) some whitespace above and below, this "isn't"(?)
// a major problem?
//NOTE: There are strange things going on, because of the inverted
// 規模... fiddle carefully, if you must do it at all!
begin
result:=trunc((liConvert-liYMinRaw)*siScYStretch);//));//-liScYOffset*);
end;
//=====================
//GraphArea to Bitmap 調整する 転換 機能(する)/行事s....
機能(する)/行事 Tld009f1.iGAtoBitmapX(iConvert:integer):integer;
begin
result:=iConvert+wGrMarLeft+bGrAxWidY;
end;
機能(する)/行事 Tld009f1.iGAtoBitmapY(iConvert:integer):integer;
//Remember: Bitmap "Y" coord has 無 at TOP. The values
// passed to this 機能(する)/行事 will be "権利", but, in bitmap
// Y coords 条件, "upside 負かす/撃墜する".
//Happily, because, once in bitmap coords, we are working
// from the 最高の,を越す 負かす/撃墜する, we don't have to worry about the
// axis line and the 底(に届く) 利ざや... they are "above" the
// datapoints we want to put on bitmap.
begin
result:=(wGrGAHeight-iConvert-1)-iGrBelowDataCloudGap;
//The "-1" is a KLUDGE! 直す/買収する,八百長をするs "show the thing that should
// be at the 底(に届く) of the graph...
// But may 押し進める "thing that should be at 最高の,を越す" over the 辛勝する/優位,
// past the 最高の,を越す of the Bitmap.
//As I ーするつもりである having some "white space" above and below
// the plotted data points, I can, though I shouldn't,
// live with this... IF it is happening. It may be
// that max values 陰謀(を企てる) 適切に, i.e. in 最高の,を越す 列/漕ぐ/騒動, too.
//The MINUS iGrBelowDataCloudGap is to create the blank
// area below the data cloud. It has to be minus as the
// 調整するs of the bitmap go up as you go 負かす/撃墜する the 審査する.
end;
手続き Tld009f1.ReadRecord(var w1:word;var li1:longint);
//w1, li1 can have anything in them when the SR is called. Irrelevant.
//wWhereInData must have a 訂正する value. Should be 1 when ReadRecord
// first called
//選ぶ up two numbers from 全世界の constant sDataSource.
//(Using 全世界のs, the way wWhereInData and sDataSource are 存在 used is
// a Bad Idea... and I will probably be punished. We shall see.)
begin
sTmp:='';
while (sDataSource[wWhereInData] <>'-') and
(sTmp<>'9999') do begin
sTmp:=sTmp+sDataSource[wWhereInData];
inc(wWhereInData);
end;//"While..."
inc(wWhereInData);
w1:=strtoint(sTmp);
if w1<>9999 then begin //Read li1
sTmp:='';
while sDataSource[wWhereInData]<>'/' do begin
sTmp:=sTmp+sDataSource[wWhereInData];
inc(wWhereInData);
end;//"While..."
inc(wWhereInData);
li1:=strtoint(sTmp);
end;//Read li1
if w1=9999 then begin
wWhereInData:=wWhereInData-5;
end;
end;//ReadRecord
end.
That's a lot done! But now we go on to the "fancy bit... in LT3Nf-2.htm....
Search across all my 場所/位置s with the Google search...
|
|
Page 実験(する)d for 同意/服従 with INDUSTRY (not MS-only) 基準s, using the 解放する/自由な, 公然と accessible validator at validator.w3.org. Mostly passes. There were two "unknown せいにするs" in Google+ button code. Sigh.
....... P a g e . . . E n d s .....