Media pembelajaran polygon berbasis Delphi

Poligon adalah geometri dengan banyak sudut seperti segitiga, segi empat dan nonagon dan lainnya. poligon terdiri atas beberapa titik atau vertex yang terhubung menjadi sebuah bentuk geometri. Poligon memiliki penamaan khusus sesuai jumlah sudutnya.

Poligon merupakan geometri yang dapat dikembangkan secara luas sehingga digunakan di berbagai bidang.

Untuk memudahkan mengenal atau memperkenalkan polygon, salah satu media yang bisa digunakan adalah pc/laptop. Fitur dasar seperti create dan modify adalah sebagai langkah awal  untuk membangun sebuah media pembelajaran geometri. Selanjutnya  bisa dikembangkan menjadi lebih fungsional sesuai kebutuhan pengembangannya.

Screenshoot media pembelajaran polygin menggunakan delphi :

Kode delphi pengembangan media belajar geometri polygon :

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Buttons, Grids;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    Image1: TImage;
    GroupBox1: TGroupBox;
    GroupBox3: TGroupBox;
    GroupBox2: TGroupBox;
    LabelPosisi: TLabel;
    ButtonClose: TButton;
    LabelVertex: TLabel;
    GroupBox4: TGroupBox;
    StringGrid1: TStringGrid;
    ButtonDelete: TButton;
    ButtonDraw: TButton;
    ButtonEdit: TButton;
    ButtonInsert: TButton;
    ButtonClear: TButton;
    ButtonSave: TButton;
    ButtonOpen: TButton;
    Label1: TLabel;
    procedure ButtonDrawClick(Sender: TObject);
    procedure ButtonEditClick(Sender: TObject);
    procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure Image1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ButtonCloseClick(Sender: TObject);
    procedure ButtonSaveClick(Sender: TObject);
    procedure ButtonLoadClick(Sender: TObject);
    procedure refreshCanvas();
    procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    procedure ButtonDeleteClick(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure ButtonInsertClick(Sender: TObject);
    procedure ButtonClearClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type Point = record
 X : integer;
 Y : integer;
end;

var
  Form1: TForm1;
  modeOperasi : integer;
  posisi : Point;
  tinggiCanvas : integer;
  startPolygon : boolean;
  polygon : array[0..20] of Point;
  polygonCount : integer;
  editIndex : integer;

const
  modeIdle = 0;
  modeDraw = 1;
  modeEdit = 3;
  modeInsert = 4;

implementation

{$R *.dfm}

procedure TForm1.refreshCanvas();
var
  i : integer;
begin
  StringGrid1.RowCount := polygonCount + 1;

  i := 0;
  while true do
  begin
    if polygon[i].X = -1 then
      break;
    StringGrid1.Cells[0,i+1] := inttostr(i+1);
    StringGrid1.Cells[1,i+1] := inttostr(polygon[i].X);
    StringGrid1.Cells[2,i+1] := inttostr(polygon[i].Y);

    if i = 0 then
    begin
      image1.Canvas.rectangle(0,0,image1.width-1, image1.height-1);
      image1.Canvas.MoveTo(polygon[0].X, tinggiCanvas - polygon[0].Y);
    end
    else
    begin
      if (modeOperasi = modeInsert) and (editIndex = i) then
      begin
        Image1.Canvas.Pen.Color := clRed;
      end
      else
      begin
        Image1.Canvas.Pen.Color := clBlack;
      end;
      image1.Canvas.LineTo(polygon[i].X, tinggiCanvas - polygon[i].Y);
    end;

    i := i + 1;
    if i = 20 then
      break;

  end;

   if modeOperasi = modeEdit then
   begin
    image1.Canvas.Rectangle(polygon[editIndex].X-5, tinggiCanvas - polygon[editIndex].Y - 5,
      polygon[editIndex].X+5, tinggiCanvas - polygon[editIndex].Y + 5);
   end;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  StringGrid1.Cells[0,0] := 'No';
  StringGrid1.Cells[1,0] := 'X';
  StringGrid1.Cells[2,0] := 'Y';
end;


procedure TForm1.FormResize(Sender: TObject);
begin
  tinggiCanvas := Image1.Height;

end;

procedure TForm1.ButtonDrawClick(Sender: TObject);
begin
  buttonDraw.Font.Style := [fsBold];
  ButtonEdit.Font.Style := [];
  ButtonInsert.Font.Style := [];

  modeOperasi := modeDraw;
  startPolygon := true;
  polygonCount := 0;
  polygon[polygonCount].X := -1;

  refreshCanvas();
end;

procedure TForm1.ButtonCloseClick(Sender: TObject);
begin

  if (modeOperasi = modeDraw) and (polygonCount > 1) then
  begin
    polygon[polygonCount] := polygon[0];
    polygonCount := polygonCount + 1;

    polygon[polygonCount].X := -1;

    LabelVertex.Caption := 'Vertex ' + inttostr(polygonCount);

    refreshCanvas();

    buttonDraw.Font.Style := [];
    ButtonEdit.Font.Style := [];
    ButtonInsert.Font.Style := [];
    modeOperasi := modeIdle;
  end;

end;

procedure TForm1.ButtonEditClick(Sender: TObject);
begin
  buttonDraw.Font.Style := [];
  ButtonEdit.Font.Style := [fsBold];
  ButtonInsert.Font.Style := [];
  modeOperasi := modeEdit;
  editIndex := 1;
  refreshCanvas();
end;

procedure TForm1.ButtonInsertClick(Sender: TObject);
begin
  buttonDraw.Font.Style := [];
  ButtonEdit.Font.Style := [];
  ButtonInsert.Font.Style := [fsBold];
  modeOperasi := modeInsert;
  editIndex := 1;
  refreshCanvas();
end;


procedure TForm1.ButtonClearClick(Sender: TObject);
begin
  polygonCount := 0;
  polygon[polygonCount].X := -1;

  refreshCanvas();
end;

procedure TForm1.ButtonDeleteClick(Sender: TObject);
var
  i : integer;
begin
  if editIndex <> 0 then
  begin
    for i := editIndex to polygonCount do
    begin
      polygon[i].X := polygon[i+1].X;
      polygon[i].Y := polygon[i+1].Y;
    end;
    polygonCount := polygonCount - 1;
    refreshCanvas();
  end;
end;


procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  posisi.X := X;
  posisi.Y := tinggiCanvas - Y;
  LabelPosisi.Caption := 'Posisi ' + inttostr(posisi.X) + ', ' + inttostr(posisi.Y);
end;

procedure TForm1.Image1Click(Sender: TObject);
var
  i : integer;
begin
  if (modeOperasi = modeDraw) and (polygonCount < 20) then
  begin
    polygon[polygonCount].X := posisi.X;
    polygon[polygonCount].Y := posisi.Y;
    polygonCount := polygonCount + 1;
    polygon[polygonCount].X := -1;
    LabelVertex.Caption := 'Vertex ' + inttostr(polygonCount);

    refreshCanvas();
  end
  else if (modeOperasi = modeEdit) and (editIndex > 0)then
  begin
    if (editIndex = 1) or (editIndex = polygonCount-1) then
    begin
      polygon[1].X := posisi.X;
      polygon[1].Y := posisi.Y;
      polygon[polygonCount-1].X := posisi.X;
      polygon[polygonCount-1].Y := posisi.Y;
    end
    else if (editIndex > 0) then
    begin
      polygon[editIndex].X := posisi.X;
      polygon[editIndex].Y := posisi.Y;

    end;

    refreshCanvas();
  end
  else if (modeOperasi = modeInsert) and (editIndex > 0) and (polygonCount < 20) then
  begin
    for i := polygonCount downto editIndex do
    begin
      polygon[i+1].X := polygon[i].X;
      polygon[i+1].Y := polygon[i].Y;
    end;
    polygon[editIndex].X := posisi.X;
    polygon[editIndex].Y := posisi.Y;
    polygonCount := polygonCount + 1;
    refreshCanvas();
 end;

end;


procedure TForm1.ButtonSaveClick(Sender: TObject);
var
  Stream: TStream;
begin
  Stream:= TFileStream.Create('polygon.bin', fmCreate);
  Stream.WriteBuffer(polygonCount, SizeOf(integer));
  Stream.WriteBuffer(polygon, (polygonCount+1) * SizeOf(Point));
  Stream.Free;
end;

procedure TForm1.ButtonLoadClick(Sender: TObject);
var
  Stream: TStream;
begin
  Stream:= TFileStream.Create('polygon.bin', fmOpenRead);
  Stream.ReadBuffer(polygonCount, SizeOf(integer));
  Stream.ReadBuffer(polygon, (polygonCount+1) * SizeOf(Point));
  Stream.Free;

  refreshCanvas();
  LabelVertex.Caption := 'Vertex ' + inttostr(polygonCount);

end;

procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol,
  ARow: Integer; var CanSelect: Boolean);
begin
  editIndex := ARow - 1;
  refreshCanvas();
end;

end.

code lengkap media pengajaran geometri poligon:
library :

Kontrol motor servo dengan delphi melalui port parallel lpt

Motor servo berputar ke posisi sudut tertentu berdasarkan lebar pulsa yang diberikan padanya. Pada umumnya lebar pulsa yang dibutuhkan adalah 1ms – 2ms, dengan perida 20ms seperti diagram berikut :

Membangkitkan sinyal pulsa ini menjadi masalah tersendiri jika menggunakan pc melalui port paralel, karena disisi komputer cara ini (akses langsung ke perangkat) dianggap tidak aman.

Beberapa metode/trik bisa dilakukan untuk menggerakkan motor servo melalui lpt port seperti kode berikut :


for i:=1 to 10 do
begin
Out32($378, $01);
delay(1);
Out32($378, $00);
delay(19);
end;

cara ini menjadi tidak efektif karena fungsi ‘delay()’ tidak bisa menjamin timingnya. contohnya jika delay(1) tidak ada garansi akan tepat 1ms. Maka yang terjadi adalah servo agak bergerak tidak beraturan.

jadi kunci memitar motor servo tepat pada posisinya adalah timing yang pas dan tepat. untuk itu digunakan fungsi ‘QueryPerformanceCounter(lastTick);’ yang lebih presisi pewaktuannya.

skema simulasi gerak servo untuk membuka pintu menggunakan port parallel:

 

program delphi penggerak motor servo, simulasi buka tutup:

 

unit servo;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    ButtonBuka: TButton;
    ButtonTutup: TButton;
    Label1: TLabel;
    Label2: TLabel;
    procedure ButtonBukaClick(Sender: TObject);
    procedure ButtonTutupClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  nilaiPort : byte;

const
  //cek alamat resource lpt port melalui device manager
  baseRegister = $DC00;
  dataRegister = baseRegister + 0;
  statusRegister = baseRegister + 1;
  controlRegister = baseRegister + 2;

  sudutBuka = 180;
  sudutTutup = 0;
  maskPinServo = $01;


implementation

{$R *.dfm}

function Inp32(PortAdr: word): byte; stdcall; external 'inpout32.dll';
function Out32(PortAdr: word; Data: byte): byte; stdcall; external 'inpout32.dll';

procedure gerakServo(maskPort : byte; sudut : byte);
var
	lastTick, tick : Int64;
	lastTick20 : Int64;
	mikroDetik : integer;
	Frequency : Int64;
	i : integer;
begin
	QueryPerformanceFrequency(Frequency);
	mikroDetik := 500 + (Round(sudut/180) * 2000);

	for i := 1 to 20 do
	begin
		nilaiPort := nilaiPort or maskPort;
		Out32(dataRegister, nilaiPort);

		QueryPerformanceCounter(lastTick);
		lastTick20 := lastTick + round((20000 / 1000000) * Frequency);
		lastTick := lastTick + round((mikroDetik / 1000000) * Frequency);

		while true do
		begin
			QueryPerformanceCounter(tick);
			if tick > lastTick then
				break;
		end;

		nilaiPort := nilaiPort and (not maskPort);
		Out32(dataRegister, nilaiPort);

		while true do
		begin
			QueryPerformanceCounter(tick);
			if tick > lastTick20 then
				break;
		end;
	end;
end;

procedure TForm1.ButtonBukaClick(Sender: TObject);
begin
	gerakServo(maskPinServo, sudutBuka);
end;

procedure TForm1.ButtonTutupClick(Sender: TObject);
begin
	gerakServo(maskPinServo, sudutTutup);
end;

end.