Drawing sine math function with FMX in Delphi

 





unit MUnit; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, System.Math, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.StdCtrls, FMX.Layouts, FMX.Objects; type TMForm = class(TForm) MRect: TRectangle; Timer1: TTimer; Circle1: TCircle; Pie1: TPie; Text_Angle: TText; Text_Circle: TText; Text1: TText; StartTimer: TTimer; procedure FormShow(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure StartTimerTimer(Sender: TObject); private procedure OnePointCircle(x, y: single; setColor : cardinal); procedure Draw_Line2P(x1, y1, x2, y2: single; setColor: cardinal); procedure Sin_OnePoint(xD: single); procedure Init_Screen; { Private declarations } public { Public declarations } AngleXD : single; end; var MForm: TMForm; implementation {$R *.fmx} procedure TMForm.FormShow(Sender: TObject); begin Draw_Line2P( 0,0, 1320,0, $FF252525 ); // Pie Solid Color MForm.ClientWidth := 1920; MForm.ClientHeight := 1080; MForm.Fill.Color := $FF000000; MForm.FullScreen := TRUE; Init_Screen(); end; // 실행하고 3초 이후 작동. procedure TMForm.StartTimerTimer(Sender: TObject); begin StartTimer.Enabled := FALSE; Init_Screen(); Timer1.Enabled := TRUE; end; procedure TMForm.Init_Screen(); var i : integer; begin AngleXD := 0; Pie1.EndAngle := 0; for i := MRect.ComponentCount - 1 downto 0 do if MRect.Components[i] is TCircle then MRect.Components[i].Free; MForm.Realign; // MRect 밖으로 삐져나온 원 자국 제거. end; //------------------------------------------------------------------------------- procedure TMForm.Draw_Line2P( x1,y1, x2,y2 : single; setColor : cardinal ); var d, xtemp, ytemp, rAngle : single; drawLine : TLine; begin if x1 > x2 then begin xtemp := x1; ytemp := y1; x1 := x2; y1 := y2; x2 := xtemp; y2 := ytemp; end; d := SQRT( Power( x2-x1, 2 ) + Power( y2-y1, 2 ) ); // Uses System.Math rAngle := RadToDeg( ArcSin( (y2-y1)/d )); drawLine := TLine.Create( MRect ); drawLine.Parent := MRect; drawLine.LineLocation := TLineLocation.Inner; drawLine.LineType := TLineType.Bottom; drawLine.RotationCenter.X := 0; drawLine.RotationCenter.Y := 0; drawLine.Stroke.Thickness := 6; drawLine.Stroke.Color := setColor; drawLine.Height := 1; drawLine.Width := d; drawLine.Position.X := x1; drawLine.Position.Y := MRect.Height * 0.5 - y1; drawLine.RotationAngle := rAngle; end; //------------------------------------------------------------------------------- procedure TMForm.OnePointCircle( x, y : single; setColor : cardinal ); var cc : TCircle; xInterval : single; // X 간격 begin cc := TCircle.Create( MRect ); cc.Parent := MRect; cc.Fill.Color := setColor; cc.Stroke.Kind := TBrushKind.None; cc.Width := 6; cc.Height := 6; xInterval := 2; cc.Position.X := ( x * xInterval - cc.Width * 0.5 ); // * xInterval 는 x 간격을 더 넓게 cc.Position.y := MRect.Height * 0.5 - y - cc.Height * 0.5; // 500 - y Text_Angle.Position.X := cc.Position.X + 10; Text_Angle.Position.Y := cc.Position.y - 30; end; //--------------------------------------------- // xd : 0 ~ 360 도 Degree procedure TMForm.Sin_OnePoint( xD : single ); var radianA, yp : single; yStr : string; begin radianA := DegToRad( xD ); yp := SIN( radianA ) * MRect.Height * 0.5; yStr := Format( '%5f', [ SIN( radianA ) ] ); OnePointCircle( xD, yp, $FF00FFFF ); Text_Angle.Text := '( ' + AngleXD.ToString + ' ,' + yStr + ' )'; Text_Circle.Text := AngleXD.ToString; end; //***************************************************************** procedure TMForm.Timer1Timer(Sender: TObject); begin if AngleXD > 540 then begin Timer1.Enabled := FALSE; StartTimer.Enabled := TRUE; end else begin Sin_OnePoint( AngleXD ); Pie1.EndAngle := -1 * ( AngleXD - 360 * ( Round( AngleXD ) div 360 ) ); // 360도 초과 해도 360으로 인식하므로 360 주기로변환. end; AngleXD := AngleXD + 1; // 1도 씩 증가 end; end.


Gradient Color Timer Change

 



procedure TForm1.Gradation_Draw( angle : integer );

begin

  GRect.Fill.Gradient.Points[0].Color := GColor1;

  GRect.Fill.Gradient.Points[0].Offset := 0;


  GRect.Fill.Gradient.Points[1].Color := GColor2;

  GRect.Fill.Gradient.Points[1].Offset := 1;


  if IsAType then

  begin

    GRect.Fill.Gradient.StartPosition.X := 0.0;

    GRect.Fill.Gradient.StartPosition.Y := 0.0;

    GRect.Fill.Gradient.StopPosition.X :=  angle / 10;    

    GRect.Fill.Gradient.StopPosition.Y :=  1.0;

  end

  else

  begin

    GRect.Fill.Gradient.StartPosition.X := 0.0;

    GRect.Fill.Gradient.StartPosition.Y := 0.1;

    GRect.Fill.Gradient.StopPosition.X :=  1.0;

    GRect.Fill.Gradient.StopPosition.Y :=  angle / 10;   

  end;


  GRect.Repaint;

end;



//***************************************************************************************************************************

procedure TForm1.ColorTimer1Timer(Sender: TObject);

begin

  if ( R1 = $ff0000 ) and ( G1 = 0 ) and ( B1 < $0000ff ) then                           

    B1 := B1 + $000001


  else if (( 0 < R1 ) and ( R1 <= $ff0000 )) and ( G1 = 0 ) and ( B1 = $0000ff ) then     

    R1 := R1 - $010000


  else if ( R1 = 0 ) and ( G1 < $00ff00 ) and  ( B1 = $0000ff ) then                        

    G1 := G1 + $000100


  else if ( R1 = 0 ) and ( G1 = $00ff00 ) and (( 0 < B1 ) and ( B1 <= $0000ff ))  then       

    B1 := B1 - $000001


  else if ( R1 < $ff0000 ) and ( G1 = $00ff00 ) and ( B1 = $000000 )  then                  

    R1 :=  R1 + $010000


  else if ( R1 = $ff0000 ) and (( 0 < G1 ) and ( G1 <= $00ff00 )) and ( B1 = $000000 ) then  

    G1 := G1 - $000100


  else

    ColorTimer1.Enabled := FALSE;


  GColor1 := $FF000000 +  R1 + G1 + B1;

  Rectangle1.Fill.Color := GColor1;

end;

Post How to send a web page.

This method creates a temporary file called temp post request.html, puts parameters in it, and calls it using a web browser.


procedure OpenBrowserWithPostRequest;

var

  HTMLFileName, HTMLContent: string;

  HTMLFile: TextFile;

begin

  // temp HTML file

  HTMLFileName := ExtractFilePath( ParamStr(0)) + 'temp_post_request.html';


  // HTML file write

  HTMLContent :=

 '<html>' +

    '<body onload="document.forms[0].submit()">' +

    '<form action="http://127.0.0.1/exam1" method="POST">' +

    '<input type="hidden" name="param1" value="exam">' +

    '<input type="hidden" name="param2" value="1">' +

    '<input type="hidden" name="param3" value="3">' +

    '</form>' +

    '</body>' +

    '</html>';


  AssignFile( HTMLFile, HTMLFileName );

  Rewrite( HTMLFile );

  Write( HTMLFile, HTMLContent );

  CloseFile( HTMLFile );

  ShellExecute(0, 'open', PChar( HTMLFileName ), nil, nil, SW_SHOWNORMAL);

end;


How to dramatically reduce code conversion work when moving from Tier 2 to Tier 3.

 When converting a 2-tier project to 3-tier, you often have to move the SQL queries used in the 2-tier app to the 3-tier middleware server, which increases the workload and makes the project on the server huge.

In this case, there is a way to send the SQL statement itself as a String parameter without moving the query statement used in the second-tier project to the server.

In this case, the middleware server receives the sql string, processes it, and makes the result visible to the client app.

Depending on the SQL query statement, the column names retrieved from the database or the field names replaced with AS in the SQL query statement are all different, so you can output the field names like below.

       for i := 0 to FDQueryI.FieldCount - 1 do

           JsubObj.AddPair( FDQueryI.Fields[ i ].FullName, FDQueryI.Fields[ i ].AsString );

In some cases, you may know the field names of the queried results in the database, but FireDAC can show the field names of the queried results in the same way as the sample source, so you can use it.

The sample source outputs the result as Json, so you can utilize Rad server or Datasnap Rest method.


function TRTestResource1.QueryText_sql( sqlText : string ) : String;

var

  JTopObj, JsubObj : TJSONObject;

  JArr  : TJSONArray;

  JPair : TJSONPair;

  i : integer;


begin

  JTopObj := TJSONObject.Create;  


  try

    FDConnection1.Open;


    try

      FDQueryI.Close;

      FDQueryI.SQL.Clear;

      FDQueryI.SQL.Add( sqlText );


      FDQueryI.Open;

      FDQueryI.First;


      JArr :=  TJSONArray.Create;   

      while Not FDQueryI.EOF do

      begin

        JsubObj := TJSONObject.Create; 


        for i := 0 to FDQueryI.FieldCount - 1 do

           JsubObj.AddPair( FDQueryI.Fields[ i ].FullName,  FDQueryI.Fields[ i ].AsString );  // 조회 결과값의 필드명과 데이터를 같이 출력 하는 방법


        JArr.AddElement( JsubObj ); 

        FDQueryI.Next;

      end;


      JPair := TJSONPair.Create( 'Items', JArr );                           

      JTopObj.AddPair( 'Count', TJSONNumber.Create( FDQueryI.RecordCount ) );  

      JTopObj.AddPair( JPair );                                                


    except

      on e: Exception do begin

            result := 'Error';

            Exit;

      end;

    end;



  finally

      FDConnection1.Close;


      result := JTopObj.ToString;   // 결과값 전달.

      JTopObj.Free;

  end;

end;

FireMonkey TLine Demo

This video is created by connecting two planets orbiting the sun with different orbital periods with a line.

You can visually see the distance between two destination lines by the length of the line.



The length between the two points was calculated in the following way.

procedure TMForm.Draw_Line2P( x1,y1, x2,y2 : single;  setColor : cardinal );

var

  d, xtemp, ytemp, rAngle : single;

  drawLine : TLine;

begin

  if x1 > x2 then

  begin

    xtemp := x1;     ytemp := y1;

    x1 := x2;          y1 := y2;

    x2 := xtemp;     y2 := ytemp;

  end;


  d := SQRT( Power( x2-x1, 2 ) + Power( y2-y1, 2 ) );   // Uses System.Math

  rAngle := RadToDeg( ArcSin( (y2-y1)/d ));


  drawLine := TLine.Create( BLayout );

  drawLine.Parent := BLayout;

  drawLine.LineLocation := TLineLocation.Inner;

  drawLine.LineType := TLineType.Bottom;

  drawLine.RotationCenter.X := 0;

  drawLine.RotationCenter.Y := 0;

  drawLine.Stroke.Thickness := 1;

  drawLine.Stroke.Color := setColor;

  drawLine.Height := 1;

  drawLine.Width  := d;

  drawLine.Position.X := x1;

  drawLine.Position.Y := y1;

  drawLine.RotationAngle := rAngle;

end;