From b970995a3dfcdb2a3fdf592fedbed92371a232de Mon Sep 17 00:00:00 2001 From: Wizzup? Date: Tue, 6 Oct 2009 03:40:44 +0000 Subject: [PATCH] Woot. git-svn-id: http://www.villavu.com/repositories/merlijn/mufasa@107 3f818213-9676-44b0-a9b4-5e4c4e03d09d --- Projects/SAMufasaGUI/project1.lpi | 227 +++++++------- Projects/SAMufasaGUI/project1.lpr | 2 +- Tests/PS/dtmtest2.txt | 35 ++- Units/MMLAddon/PSInc/Wrappers/dtm.inc | 7 + Units/MMLAddon/PSInc/pscompile.inc | 2 + Units/MMLCore/dtm.pas | 407 +++++++++++++++++++++++++- Units/MMLCore/mufasatypes.pas | 5 + 7 files changed, 566 insertions(+), 119 deletions(-) diff --git a/Projects/SAMufasaGUI/project1.lpi b/Projects/SAMufasaGUI/project1.lpi index 4b3d787..4df4806 100644 --- a/Projects/SAMufasaGUI/project1.lpi +++ b/Projects/SAMufasaGUI/project1.lpi @@ -33,15 +33,15 @@ - + - + - + @@ -172,8 +172,8 @@ - - + + @@ -305,17 +305,17 @@ - + - - + + - + @@ -331,7 +331,7 @@ - + @@ -339,7 +339,7 @@ - + @@ -353,8 +353,8 @@ - - + + @@ -377,7 +377,7 @@ - + @@ -392,7 +392,7 @@ - + @@ -404,10 +404,10 @@ - - - - + + + + @@ -515,10 +515,10 @@ - - - - + + + + @@ -539,7 +539,7 @@ - + @@ -557,9 +557,9 @@ - - - + + + @@ -691,7 +691,7 @@ - + @@ -750,7 +750,7 @@ - + @@ -832,20 +832,20 @@ - - - - + + + + - - + + - + @@ -861,8 +861,8 @@ - - + + @@ -888,7 +888,7 @@ - + @@ -922,23 +922,25 @@ - - + + - - + + + + - - - - + + + + @@ -953,124 +955,149 @@ - - + + + + + + + + + + + + + + + + + + + - + - + - + - - + + - - + + - - + + - + - - + + - + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + + + + + + + + + diff --git a/Projects/SAMufasaGUI/project1.lpr b/Projects/SAMufasaGUI/project1.lpr index 7b4fb96..b10d0e9 100644 --- a/Projects/SAMufasaGUI/project1.lpr +++ b/Projects/SAMufasaGUI/project1.lpr @@ -9,7 +9,7 @@ uses Interfaces, // this includes the LCL widgetset Forms, LResources, Window, files, MufasaTypes, Client, TestUnit, finder, MMLThread, mmlpsthread, bitmaps, colour_conv, plugins, DTM, colourpicker, - windowselector, dtmutil; + windowselector, dtmutil, mmath; {$IFDEF WINDOWS}{$R project1.rc}{$ENDIF} diff --git a/Tests/PS/dtmtest2.txt b/Tests/PS/dtmtest2.txt index 347373d..1165df9 100644 --- a/Tests/PS/dtmtest2.txt +++ b/Tests/PS/dtmtest2.txt @@ -9,27 +9,28 @@ const var ppdtm: pdtm; - w,h,x,y,dtm: integer; + w,h,x,y,dtm,i: integer; + + p,pp: TPointArray; + c,t,asz,ash: TIntegerArray; + begin + p := [Point(0,0), Point(1,1)]; + c := [clWhite, clWhite]; + t := [0, 0]; + asz := [0, 0]; + ash := [dtm_Rectangle, dtm_Rectangle]; setlength(ppdtm.p,2); setlength(ppdtm.c,2); setlength(ppdtm.t,2); setlength(ppdtm.asz,2); setlength(ppdtm.ash,2); - ppdtm.p[0].x := 0; - ppdtm.p[0].y := 0; - ppdtm.c[0] := 16777215; - ppdtm.t[0] := 0; - ppdtm.asz[0] := 0; - ppdtm.asz[0] := dtm_Rectangle; - - ppdtm.p[1].x := 1; - ppdtm.p[1].y := 1; - ppdtm.c[1] := 16777215; - ppdtm.t[1] := 0; - ppdtm.asz[1] := 0; - ppdtm.asz[1] := dtm_Rectangle; + ppdtm.p := p; + ppdtm.c := c; + ppdtm.t := t; + ppdtm.asz := asz; + ppdtm.ash := ash; dtm := AddpDTM(ppdtm); @@ -40,4 +41,10 @@ begin movemouse(x,y); end; + if FindDTMs(dtm, p, 0, 0, w-1, h-1) then + begin + writeln('Found ' + inttostr(length(p)) + ' DTM(s). First one at ' + + inttostr(p[0].x) + ', ' + inttostr(p[0].y)); + movemouse(p[0].x,p[0].y); + end; end. diff --git a/Units/MMLAddon/PSInc/Wrappers/dtm.inc b/Units/MMLAddon/PSInc/Wrappers/dtm.inc index dc46509..2378d34 100644 --- a/Units/MMLAddon/PSInc/Wrappers/dtm.inc +++ b/Units/MMLAddon/PSInc/Wrappers/dtm.inc @@ -3,6 +3,13 @@ begin Result := CurrThread.Client.MDTM.FindDTM(DTM, x, y, x1, y1, x2, y2); end; +function ps_FindDTMs(DTM: Integer; var p: TPointArray; x1, y1, x2, y2: Integer): Boolean; +begin + Result := CurrThread.Client.MDTM.FindDTMs(DTM, p, x1, y1, x2, y2); +end; + + + function ps_DTMFromString(DTMString: String): Integer; var dtm: pDTM; diff --git a/Units/MMLAddon/PSInc/pscompile.inc b/Units/MMLAddon/PSInc/pscompile.inc index 2c3af75..0388323 100644 --- a/Units/MMLAddon/PSInc/pscompile.inc +++ b/Units/MMLAddon/PSInc/pscompile.inc @@ -22,6 +22,7 @@ Sender.AddFunction(@tDTMTopDTM, 'Function tDTMTopDTM(Const DTM: TDTM): pDTM;'); Sender.AddFunction(@ps_DTMFromString, 'function DTMFromString(DTMString: String): Integer;'); Sender.AddFunction(@ps_FreeDTM, 'procedure FreeDTM(DTM: Integer);'); Sender.AddFunction(@ps_FindDTM, 'function FindDTM(DTM: Integer; var x, y: Integer; x1, y1, x2, y2: Integer): Boolean;'); +Sender.AddFunction(@ps_FindDTMs, 'function FindDTMs(DTM: Integer; var p: TPointArray; x1, y1, x2, y2: Integer): Boolean;'); Sender.AddFunction(@ps_addDTM, 'function AddDTM(d: TDTM): Integer;'); Sender.AddFunction(@ps_addpDTM, 'function AddpDTM(d: pDTM): Integer;'); @@ -30,6 +31,7 @@ sender.AddFunction(@power,'function pow(base,exponent : extended) : extended'); Sender.AddFunction(@max,'function Max(a, b: Integer): Integer;'); Sender.AddFunction(@min,'function Min(a, b: Integer): Integer;'); Sender.AddFunction(@pssqr,'function Sqr(e : extended) : extended;'); +Sender.AddFunction(@point,'function Point(x,y:integer) : TPoint;'); Sender.AddFunction(@Freeze, 'function freeze:boolean;'); Sender.AddFunction(@Unfreeze, 'function unfreeze: boolean;'); diff --git a/Units/MMLCore/dtm.pas b/Units/MMLCore/dtm.pas index b0d9693..caa7e46 100644 --- a/Units/MMLCore/dtm.pas +++ b/Units/MMLCore/dtm.pas @@ -18,7 +18,7 @@ type function FindDTM(DTM: Integer; var x, y: Integer; x1, y1, x2, y2: Integer): Boolean; - { function FindDTMs(DTM: Integer; var Points: TPointArray; x1, y1, x2, + function FindDTMs(DTM: Integer; var Points: TPointArray; x1, y1, x2, y2: Integer): Boolean; function FindDTMRotated(DTM: Integer; var x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; @@ -26,9 +26,18 @@ type function FindDTMsRotated(DTM: Integer; var Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; var aFound: T2DExtendedArray) - : Boolean; } + : Boolean; function pFindDTM(DTM: pDTM; var x, y: Integer; x1, y1, x2, y2: Integer): Boolean; + function pFindDTMs(DTM: pDTM; var Points: TPointArray; x1, y1, x2, + y2: Integer): Boolean; + function pFindDTMRotated(DTM: pDTM; var x, y: Integer; x1, y1, x2, + y2: Integer; sAngle, eAngle, aStep: Extended; + var aFound: Extended): Boolean; + function pFindDTMsRotated(DTM: pDTM; var Points: TPointArray; x1, + y1, x2, y2: Integer; sAngle, eAngle, + aStep: Extended; var aFound: T2DExtendedArray) + : Boolean; constructor Create(Owner: TObject); destructor Destroy; override; @@ -43,6 +52,7 @@ type DTMList: Array Of pDTM; FreeSpots: Array Of Integer; end; + const dtm_Rectangle = 0; dtm_Cross = 1; @@ -215,6 +225,31 @@ Begin Result := False; End; +function RotatePoints(P: TPointArray; A, cx, cy: Extended): TPointArray; inline; + +var + I, L: Integer; + +begin + L := High(P); + SetLength(Result, L + 1); + for I := 0 to L do + begin + Result[I].X := Round(cx + cos(A) * (p[i].x - cx) - sin(A) * (p[i].y - cy)); + Result[I].Y := Round(cy + sin(A) * (p[i].x - cx) + cos(A) * (p[i].y - cy)); + end; +end; + +{/\ + Rotates the given point (p) by A (in radians) around the point defined by cx, cy. +/\} + +function RotatePoint(p: TPoint; angle, mx, my: Extended): TPoint; inline; + +begin + Result.X := Round(mx + cos(angle) * (p.x - mx) - sin(angle) * (p.y - my)); + Result.Y := Round(my + sin(angle) * (p.x - mx) + cos(angle) * (p.y- my)); +end; function HexToInt(HexNum: string): LongInt;inline; begin @@ -390,8 +425,8 @@ begin MaxSubPointDist.Y := Max(DTM.p[I].y, MaxSubPointDist.Y); end; - X2 := X2 - MaxSubPointDist.X; - Y2 := Y2 - MaxSubPointDist.Y; + X2 := X2 - MaxSubPointDist.X - 1; + Y2 := Y2 - MaxSubPointDist.Y - 1; X1 := X1 + MaxSubPointDist.X; Y1 := Y1 + MaxSubPointDist.Y; {If X2 > X1 then @@ -442,5 +477,369 @@ begin Result := False; end; +{/\ + Tries to find the given DTM (index). Will return true if it has found one or more + DTM's. All the occurances are stored in the Points (TPointArray) +/\} + +function TMDTM.FindDTMs(DTM: Integer; Var Points: TPointArray; x1, y1, x2, y2: Integer): Boolean; +Var + temp: pDTM; +Begin + If GetDTM(DTM, temp) Then + Result := pFindDTMs(temp, Points, x1, y1, x2, y2) + Else + Begin + SetLength(Points, 0); + Result := False; + End; +End; + + + +{/\ + Tries to find the given pDTM. Will return true if it has found one or more + DTM's. All the occurances are stored in the Points (TPointArray) +/\} + +Function TMDTM.pFindDTMs(DTM: pDTM; Var Points: TPointArray; x1, y1, x2, y2: Integer): Boolean; + +Var + mP: TPointArray; + I, J, H, dH: Integer; + Found: Boolean; + TempTP: TPoint; + MaxSubPointDist: TPoint; + +Begin + Result := False; + MaxSubPointDist := Point(0,0); + SetLength(Points, 0); + For I := 1 To High(DTM.p) Do + Begin + DTM.p[I].x := DTM.p[I].x - DTM.p[0].x; + DTM.p[I].y := DTM.p[I].y - DTM.p[0].y; + End; + + X2 := X2 - MaxSubPointDist.X - 1; + Y2 := Y2 - MaxSubPointDist.Y - 1; + X1 := X1 + MaxSubPointDist.X; + Y1 := Y1 + MaxSubPointDist.Y; + {If X2 > X1 then + //Exit; + If Y2 > Y1 then } + //Exit; + // Will make sure there are no out of bounds exceptions, and will make it faster + + with TClient(Client) do + begin + MWindow.Freeze(); + + MFinder.FindColorsTolerance(mP, DTM.c[Low(DTM.c)], x1, y1, x2, y2, + DTM.t[Low(DTM.t)]); + MWindow.GetDimensions(H, dH); + end; + H := High(mP); + dH := High(DTM.p); + For I := 0 To H Do + Begin + Found := True; + For J := 1 To dH Do + Begin + TempTP.X := DTM.p[J].X + mP[I].X; + TempTP.Y := DTM.p[J].Y + mP[I].Y; + If Not AreaShape(DTM.c[J], DTM.t[J], DTM.asz[J], DTM.ash[J], TempTP) Then + Begin + Found := False; + Break; + End; + End; + + If Found Then + Begin + Result := True; + SetLength(Points, Length(Points) + 1); + Points[High(Points)] := mP[I]; + End; + End; + + TClient(Client).MWindow.UnFreeze(); + Result := Length(Points) > 0; +End; + +{/\ + Tries to find the given DTM (index). If found will put the point the dtm has + been found at in x, y and result to true. + Will rotate the DTM starting at sAngle, increasing by aStep until eAngle has been reached, or when the DTM has been found. + Returns all Angles in an Extended array. +/\} + +Function TMDTM.FindDTMRotated(DTM: Integer; Var x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; Var aFound: Extended): Boolean; +Var + temp: pDTM; +Begin + If GetDTM(DTM, temp) Then + Result := pFindDTMRotated(temp, x, y, x1, y1, x2, y2, sAngle, eAngle, aStep, aFound) + Else + Begin + x := 0; + y := 0; + aFound := 0.0; + Result := False; + End; +End; + +{/\ + Tries to find the given pDTM. If found will put the point the dtm has + been found at in x, y and result to true. + Will rotate the DTM starting at sAngle, increasing by aStep until eAngle has been reached, or when the DTM has been found. + Returns all Angles in an Extended array. +/\} + +Function TMDTM.pFindDTMRotated(DTM: pDTM; Var x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; Var aFound: Extended): Boolean; + +Var + mP: TPointArray; + I, J, H, dH, R, W: Integer; + Angle: Array Of Extended; + tAngle: Extended; + Found: Boolean; + TempTP: TPoint; + MaxSubPointDist: TPoint; + +Begin + MaxSubPointDist := Point(0,0); + For I := 1 To High(DTM.p) Do + Begin + DTM.p[I].x := DTM.p[I].x - DTM.p[0].x; + DTM.p[I].y := DTM.p[I].y - DTM.p[0].y; + End; + + X2 := X2 - MaxSubPointDist.X - 1; + Y2 := Y2 - MaxSubPointDist.Y - 1; + X1 := X1 + MaxSubPointDist.X; + Y1 := Y1 + MaxSubPointDist.Y; + {If X2 > X1 then + //Exit; + If Y2 > Y1 then } + //Exit; + // Will make sure there are no out of bounds exceptions, and will make it faster + + with TClient(Client) do + begin + MWindow.Freeze(); + + MFinder.FindColorsTolerance(mP, DTM.c[Low(DTM.c)], x1, y1, x2, y2, + DTM.t[Low(DTM.t)]); + MWindow.GetDimensions(H, dH); + end; + + H := High(mP); + dH := High(DTM.p); + For I := 0 To H Do + Begin + // Use MainPoint's AreaSize and Shape. + // For Loop on mP, depending on the AreaShape. Then on all the code beneath + // this point, use the var that is retrieved from the for loop. + Found := True; + SetLength(Angle, 0); + Found := True; + For J := 1 To dH Do + Begin + If Length(Angle) = 0 Then + Begin + tAngle := sAngle; + While tAngle <= eAngle Do + Begin + TempTP.X := DTM.p[J].X + mP[I].X; + TempTP.Y := DTM.p[J].Y + mP[I].Y; + TempTP := RotatePoint(TempTP, tAngle, mP[I].X, mP[I].Y); + If AreaShape(DTM.c[J], DTM.t[J], DTM.asz[J], DTM.ash[J], TempTP) Then + Begin + SetLength(Angle, Length(Angle) + 1); + Angle[High(Angle)] := tAngle; + Found := True; + End; + tAngle := tAngle + aStep; + End; + End; + + Found := Length(Angle) > 0; + + For R := 0 To High(Angle) Do + Begin + TempTP.X := DTM.p[J].X + mP[I].X; + TempTP.Y := DTM.p[J].Y + mP[I].Y; + TempTP := RotatePoint(TempTP, Angle[R], mP[I].X, mP[I].Y); + If Not AreaShape(DTM.c[J], DTM.t[J], DTM.asz[J], DTM.ash[J], TempTP) Then + Begin + For W := R To High(Angle) - 1 Do + Angle[W] := Angle[W + 1]; + SetLength(Angle, Length(Angle) - 1); + If Length(Angle) = 0 Then + Begin + Found := False; + Break; + End; + End; + End; + If Not Found Then + Break; + End; + + If Found Then + Begin + Result := True; + x := mP[I].X; + y := mP[I].Y; + aFound := Angle[0]; + TClient(Client).MWindow.UnFreeze(); + Exit; + End; + End; + + TClient(Client).MWindow.UnFreeze(); + Result := False; +End; + +{/\ + Tries to find the given DTM (index). Will return true if it has found one or more + DTM's. All the occurances are stored in the Points (TPointArray) + Will rotate the DTM starting at sAngle, increasing by aStep until eAngle has been reached. + Does not stop rotating when one occurance of a DTM has been found. + Returns all Angles in a Two Dimensional Extended array. +/\} + +Function TMDTM.FindDTMsRotated(DTM: Integer; Var Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; Var aFound: T2DExtendedArray): Boolean; +Var + temp: pDTM; +Begin + If GetDTM(DTM, temp) Then + Result := pFindDTMsRotated(temp, Points, x1, y1, x2, y2, sAngle, eAngle, aStep, aFound) + Else + Begin + SetLength(Points, 0); + SetLength(aFound, 0); + Result := False; + End; +End; + +{/\ + Tries to find the given pDTM. Will return true if it has found one or more + DTM's. All the occurances are stored in the Points (TPointArray) + Will rotate the DTM starting at sAngle, increasing by aStep until eAngle has been reached. + Does not stop rotating when one occurance of a DTM has been found. + Returns all Angles in a Two Dimensional Extended array. +/\} + +Function TMDTM.pFindDTMsRotated(DTM: pDTM; Var Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; Var aFound: T2DExtendedArray): Boolean; + +Var + mP: TPointArray; + I, J, H, dH, R, W, PCount: Integer; + Angle: TExtendedArray; + tAngle: Extended; + Found: Boolean; + TempTP: TPoint; + MaxSubPointDist: TPoint; + +Begin + MaxSubPointDist := Point(0,0); + For I := 1 To High(DTM.p) Do + Begin + DTM.p[I].x := DTM.p[I].x - DTM.p[0].x; + DTM.p[I].y := DTM.p[I].y - DTM.p[0].y; + End; + + X2 := X2 - MaxSubPointDist.X - 1; + Y2 := Y2 - MaxSubPointDist.Y - 1; + X1 := X1 + MaxSubPointDist.X; + Y1 := Y1 + MaxSubPointDist.Y; + {If X2 > X1 then + //Exit; + If Y2 > Y1 then } + //Exit; + // Will make sure there are no out of bounds exceptions, and will make it faster + + with TClient(Client) do + begin + MWindow.Freeze(); + + MFinder.FindColorsTolerance(mP, DTM.c[Low(DTM.c)], x1, y1, x2, y2, + DTM.t[Low(DTM.t)]); + MWindow.GetDimensions(H, dH); + end; + + H := High(mP); + dH := High(DTM.p); + PCount := 0; + For I := 0 To H Do + Begin + //WriteLn('I: ' + IntToStr(I)); + // Use MainPoint's AreaSize and Shape. + // For Loop on mP, depending on the AreaShape. Then on all the code beneath + // this point, use the var that is retrieved from the for loop. + //Found := True; + SetLength(Angle, 0); + Found := True; + For J := 1 To dH Do + Begin + If Length(Angle) = 0 Then + Begin + tAngle := sAngle; + While tAngle <= eAngle Do + Begin + TempTP.X := DTM.p[J].X + mP[I].X; + TempTP.Y := DTM.p[J].Y + mP[I].Y; + TempTP := RotatePoint(TempTP, tAngle, mP[I].X, mP[I].Y); + If AreaShape(DTM.c[J], DTM.t[J], DTM.asz[J], DTM.ash[J], TempTP) Then + Begin + SetLength(Angle, Length(Angle) + 1); + Angle[High(Angle)] := tAngle; + Found := True; + End; + tAngle := tAngle + aStep; + End; + End; + + Found := Length(Angle) > 0; + {If Found Then + WriteLn('Angle length after first search: ' + IntToStr(Length(Angle))); } + For R := 0 To High(Angle) Do + Begin + TempTP.X := DTM.p[J].X + mP[I].X; + TempTP.Y := DTM.p[J].Y + mP[I].Y; + TempTP := RotatePoint(TempTP, Angle[R], mP[I].X, mP[I].Y); + If Not AreaShape(DTM.c[J], DTM.t[J], DTM.asz[J], DTM.ash[J], TempTP) Then + Begin + For W := R To High(Angle) - 1 Do + Angle[W] := Angle[W + 1]; + SetLength(Angle, Length(Angle) - 1); + If Length(Angle) = 0 Then + Begin + Found := False; + Break; + End; + End; + End; + If Not Found Then + Break; + End; + + If Found Then + Begin + SetLength(Points, PCount + 1); + Points[PCount] := mP[I]; + PCount := PCount + 1; + SetLength(aFound, Length(aFound) + 1); + aFound[High(aFound)] := Angle; + Continue; + End; + End; + + TClient(Client).MWindow.UnFreeze(); + Result := Length(Points) > 0; +End; + end. diff --git a/Units/MMLCore/mufasatypes.pas b/Units/MMLCore/mufasatypes.pas index 4a34b7f..3ee4997 100644 --- a/Units/MMLCore/mufasatypes.pas +++ b/Units/MMLCore/mufasatypes.pas @@ -29,9 +29,14 @@ type TVariantArray = Array of Variant; TIntegerArray = Array of Integer; + TExtendedArray = Array of Extended; T2DExtendedArray = Array of Array of Extended; { DTM Types } + { + Possibly add .name too? + Then one could give DTM names, which would be easy for debugging. + } pDTM = record p: TPointArray; c, t, asz, ash: TIntegerArray;