From c0132294be8d3949e5b069685c8dc8badb873921 Mon Sep 17 00:00:00 2001 From: Wizzup? Date: Tue, 1 Dec 2009 23:41:43 +0000 Subject: [PATCH] Added new DTM Finding. Not done yet, but getting there. Needs a few obvious optimizations, and rotated isn't implemented yet. Needs a stress-test script. Added a script to test the difference between FindColorsTolerance and FindColorsToleranceOptimisation. git-svn-id: http://www.villavu.com/repositories/merlijn/mufasa@260 3f818213-9676-44b0-a9b4-5e4c4e03d09d --- Projects/MufasaTests/project1.lpi | 234 ++++++----- Projects/MufasaTests/project1.lpr | 116 ++++-- Projects/SAMufasaGUI/project1.lpi | 279 ++++++------- Tests/PS/ColourTest.mufa | 31 ++ Units/MMLAddon/PSInc/Wrappers/dtm.inc | 50 ++- Units/MMLCore/dtm.pas | 547 +++----------------------- Units/MMLCore/dtmutil.pas | 118 +++++- Units/MMLCore/finder.pas | 255 +++++++++++- Units/MMLCore/mufasatypes.pas | 2 + 9 files changed, 832 insertions(+), 800 deletions(-) create mode 100644 Tests/PS/ColourTest.mufa diff --git a/Projects/MufasaTests/project1.lpi b/Projects/MufasaTests/project1.lpi index 9ea1113..e83d8c5 100644 --- a/Projects/MufasaTests/project1.lpi +++ b/Projects/MufasaTests/project1.lpi @@ -11,7 +11,7 @@ - + @@ -30,15 +30,15 @@ - + - - + + - + @@ -46,15 +46,15 @@ - + - - - - + + + + @@ -62,15 +62,15 @@ - + - - - - + + + + @@ -78,31 +78,33 @@ - + - - - + + + + + - - + + - - - - + + + + @@ -110,195 +112,220 @@ - - + + - + - + - + - - - - + + + + - + - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -309,6 +336,13 @@ + + + + + + + diff --git a/Projects/MufasaTests/project1.lpr b/Projects/MufasaTests/project1.lpr index 2836824..46fc705 100644 --- a/Projects/MufasaTests/project1.lpr +++ b/Projects/MufasaTests/project1.lpr @@ -10,7 +10,7 @@ uses Forms,Interfaces, LCLIntf, Client, - bitmaps,x ,mufasatypes + bitmaps,x ,mufasatypes,dtm,dtmutil { you can add units after this }; @@ -36,7 +36,9 @@ var ErrorMsg: String; Time: DWord; C: TClient; - I{, W, H, X, Y}: Integer; + I: Integer; + dtm: pdtm; + p:tpointarray; bmp: TMufasaBitmap; begin @@ -57,7 +59,74 @@ begin { add your program here } C := TClient.Create; - {$WARNING Change This Path!} + + bmp := TMufasaBitmap.Create; + bmp.SetSize(10,10); + FillChar(bmp.FData[0],sizeof(trgb32)*100, 0); + bmp.FastSetPixel(8,8,255); + bmp.FastSetPixel(9,9,255); + bmp.FastSetPixel(7,7,255); + bmp.FastSetPixel(9,8,255); + bmp.FastSetPixel(8,9,255); + C.MWindow.SetTarget(bmp); + + + initdtm(dtm, 3); + dtm.p[0] := Point(2, 2); + dtm.p[1] := Point(-3, -3); + dtm.p[2] := Point(0, 0); + dtm.c[0] := 255; + dtm.asz[1] := 0; + dtm.ash[1] := dtm_Rectangle; + + setlength(p, 0); + + C.MFinder.FindDTMs(dtm, p, 0, 0, 9, 9); + for i := 0 to high(p) do + writeln(format('%d: (%d, %d)', [i, p[i].x, p[i].y])); + + + + + //bmp.OnDestroy:=nil; + bmp.Free; + C.Free; + + // stop program loop + Terminate; +end; + +constructor MufasaTests.Create(TheOwner: TComponent); +begin + inherited Create(TheOwner); + StopOnException:=True; +end; + +destructor MufasaTests.Destroy; +begin + inherited Destroy; +end; + +procedure MufasaTests.WriteHelp; +begin + { add your help code here } + writeln('Usage: ',ExeName,' -h'); +end; + +var + Application: MufasaTests; + +{$IFDEF WINDOWS}{$R project1.rc}{$ENDIF} + +begin + Application:=MufasaTests.Create(nil); + Application.Title:='My Application'; + Application.Run; + Application.Free; +end. + + +{ {$WARNING Change This Path!} C.MOCR.InitTOCR('/home/merlijn/Programs/mufasa/Fonts/'); //C.MOCR.InitTOCR('/home/merlijn/Programs/mufasa/ben/'); @@ -95,43 +164,4 @@ begin //C.MInput.ClickMouse(5,5, mouse_Left); sleep(2000); - C.MInput.SendText('a'); - - C.Free; - bmp.OnDestroy:=nil; - bmp.Free; - - - // stop program loop - Terminate; -end; - -constructor MufasaTests.Create(TheOwner: TComponent); -begin - inherited Create(TheOwner); - StopOnException:=True; -end; - -destructor MufasaTests.Destroy; -begin - inherited Destroy; -end; - -procedure MufasaTests.WriteHelp; -begin - { add your help code here } - writeln('Usage: ',ExeName,' -h'); -end; - -var - Application: MufasaTests; - -{$IFDEF WINDOWS}{$R project1.rc}{$ENDIF} - -begin - Application:=MufasaTests.Create(nil); - Application.Title:='My Application'; - Application.Run; - Application.Free; -end. - + C.MInput.SendText('a'); } diff --git a/Projects/SAMufasaGUI/project1.lpi b/Projects/SAMufasaGUI/project1.lpi index 4bd3d5d..78bad60 100644 --- a/Projects/SAMufasaGUI/project1.lpi +++ b/Projects/SAMufasaGUI/project1.lpi @@ -33,16 +33,14 @@ - + - - + - @@ -65,7 +63,7 @@ - + @@ -155,7 +153,7 @@ - + @@ -164,9 +162,9 @@ - - - + + + @@ -182,7 +180,7 @@ - + @@ -221,9 +219,9 @@ - - - + + + @@ -231,8 +229,8 @@ - - + + @@ -256,9 +254,9 @@ - - - + + + @@ -272,9 +270,9 @@ - - - + + + @@ -283,26 +281,24 @@ - - - - + + + + - - @@ -315,9 +311,9 @@ - - - + + + @@ -339,14 +335,14 @@ - + - + @@ -366,7 +362,7 @@ - + @@ -384,9 +380,9 @@ - - - + + + @@ -408,7 +404,7 @@ - + @@ -417,7 +413,7 @@ - + @@ -477,27 +473,21 @@ - - - - - - @@ -541,16 +531,14 @@ - + - - @@ -568,8 +556,8 @@ - - + + @@ -588,10 +576,8 @@ - - + - @@ -631,9 +617,7 @@ - - @@ -690,9 +674,7 @@ - - @@ -725,9 +707,11 @@ - - + + + + @@ -742,16 +726,14 @@ - - - + @@ -782,9 +764,7 @@ - - @@ -816,9 +796,11 @@ - - + + + + @@ -921,15 +903,13 @@ - - - + @@ -1013,7 +993,7 @@ - + @@ -1212,9 +1192,7 @@ - - - + @@ -1528,8 +1506,8 @@ - - + + @@ -1780,9 +1758,7 @@ - - - + @@ -1794,11 +1770,9 @@ - + - - - + @@ -1807,7 +1781,7 @@ - + @@ -1817,9 +1791,7 @@ - - - + @@ -1831,140 +1803,149 @@ - - - - + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/Tests/PS/ColourTest.mufa b/Tests/PS/ColourTest.mufa new file mode 100644 index 0000000..eb396f6 --- /dev/null +++ b/Tests/PS/ColourTest.mufa @@ -0,0 +1,31 @@ +program new; +var + p1, p2: TPointArray; + w, h: integer; + i, col: integer; + bmp: integer; + +begin + SetColorToleranceSpeed(2); + bmp := LoadBitmap('/home/merlijn/Pictures/Mooi/Carina_1_by_Eeitam.png'); + SetTargetBitmap(bmp); + GetClientDimensions(W, H); + writeln(inttostr(w) + ' : ' + inttostr(h)); + + for i := 0 to 100 do + begin + col := Random(clWhite); + writeln(inttostr(col)); + FindColorsTolerance(p1, col, 0, 0, W - 1, H - 1, 40); + FindColorsToleranceOptimised(p2, col, 0, 0, W - 1, H - 1, 40); + writeln(inttostr(length(p1)) + ' : ' + inttostr(length(p2))); + if(length(p1) <> length(p2)) then + writeln('wat!'); + + setlength(p1,0); + setlength(p2,0); + + end; + + FreeBitmap(bmp); +end. diff --git a/Units/MMLAddon/PSInc/Wrappers/dtm.inc b/Units/MMLAddon/PSInc/Wrappers/dtm.inc index d3bc1a9..8fe1f7a 100644 --- a/Units/MMLAddon/PSInc/Wrappers/dtm.inc +++ b/Units/MMLAddon/PSInc/Wrappers/dtm.inc @@ -22,39 +22,67 @@ } function ps_FindDTM(DTM: Integer; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean; +var + temp: pDTM; begin - Result := CurrThread.Client.MDTM.FindDTM(DTM, x, y, x1, y1, x2, y2); + if CurrThread.Client.MDTM.GetDTM(DTM, temp) then + Result := CurrThread.Client.MFinder.FindDTM(temp, x, y, x1, y1, x2, y2) + else + begin + x := 0; + y := 0; + Result := False; + end; end; function ps_FindDTMs(DTM: Integer; out p: TPointArray; x1, y1, x2, y2: Integer): Boolean; +var + temp: pDTM; begin - Result := CurrThread.Client.MDTM.FindDTMs(DTM, p, x1, y1, x2, y2); + if CurrThread.Client.MDTM.GetDTM(DTM, temp) then + Result := CurrThread.Client.MFinder.FindDTMs(temp, p, x1, y1, x2, y2) + else + begin + setlength(p,0); + Result := False; + end; end; function ps_FindDTMRotated(DTM: Integer; out x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: Extended): Boolean; +var + temp: pDTM; begin - Result := CurrThread.Client.MDTM.FindDTMRotated(DTM, x, y, x1, y1, x2, y2, - sAngle, eAngle, aStep, aFound); + if CurrThread.Client.MDTM.GetDTM(DTM, temp) then + Result := CurrThread.Client.MFinder.FindDTMRotated(temp, x, y, x1, y1, x2, y2, sAngle, eAngle, aStep, aFound) + else + begin + x := 0; + y := 0; + Result := False; + end; end; -function ps_FindDTMsRotated(DTM: Integer; out x, y: Integer; x1, y1, x2, y2: - Integer; sAngle, eAngle, aStep: Extended; - out aFound: Extended): Boolean; +function ps_FindDTMsRotated(DTM: Integer; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray): Boolean; +var + temp: pDTM; begin - Result := CurrThread.Client.MDTM.FindDTMRotated(DTM, x, y, x1, y1, x2, y2, - sAngle, eAngle, aStep, aFound); + if CurrThread.Client.MDTM.GetDTM(DTM, temp) then + Result := CurrThread.Client.MFinder.FindDTMsRotated(temp, Points, x1, y1, x2, y2, + sAngle, eAngle, aStep, aFound) + else + Result := False; end; -function ps_FindDTMsRotated(DTM: Integer; out Points: TPointArray; x1, +{function ps_FindDTMsRotated(DTM: Integer; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray) : Boolean; begin Result := CurrThread.Client.MDTM.FindDTMsRotated(DTM, Points, x1, y1, x2, y2, sAngle, eAngle, aStep, aFound); -end; +end; } function ps_DTMFromString(DTMString: String): Integer; var diff --git a/Units/MMLCore/dtm.pas b/Units/MMLCore/dtm.pas index e409069..371c93f 100644 --- a/Units/MMLCore/dtm.pas +++ b/Units/MMLCore/dtm.pas @@ -33,13 +33,17 @@ uses type TMDTM = class(TObject) + private + + + public function AddDTM(d: TDTM): Integer; function AddpDTM(d: pDTM): Integer; function GetDTM(index: Integer; out dtm: pDTM): Boolean; procedure FreeDTM(DTM: Integer); Function StringToDTM(S: String): pDTM; - function FindDTM(DTM: Integer; out x, y: Integer; x1, y1, x2, + { function FindDTM(DTM: Integer; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean; function FindDTMs(DTM: Integer; out Points: TPointArray; x1, y1, x2, y2: Integer): Boolean; @@ -50,22 +54,18 @@ type y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray) : Boolean; - function pFindDTM(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: - Integer): Boolean; - function pFindDTMs(DTM: pDTM; out Points: TPointArray; x1, y1, x2, - y2: Integer): Boolean; + function pFindDTM(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: + Integer): Boolean; function pFindDTMRotated(DTM: pDTM; out x, y: Integer; x1, y1, x2, - y2: Integer; sAngle, eAngle, aStep: Extended; - out aFound: Extended): Boolean; + y2: Integer; sAngle, eAngle, aStep: Extended; + out aFound: Extended): Boolean; function pFindDTMsRotated(DTM: pDTM; out Points: TPointArray; x1, - y1, x2, y2: Integer; sAngle, eAngle, - aStep: Extended; out aFound: T2DExtendedArray) - : Boolean; - + y1, x2, y2: Integer; sAngle, eAngle, + aStep: Extended; out aFound: T2DExtendedArray) + : Boolean; + } constructor Create(Owner: TObject); destructor Destroy; override; - private - function AreaShape(Color, Tolerance, Size, Shape: Integer; P: TPoint) : Boolean; inline; private Client: TObject; @@ -76,13 +76,6 @@ type FreeSpots: Array Of Integer; end; -const - dtm_Rectangle = 0; - dtm_Cross = 1; - dtm_DiagonalCross = 2; - dtm_Circle = 3; - dtm_Triangle = 4; - { I am not sure wether I should simply copy and paste the old DTM implementation, or rewrite it from scratch. @@ -112,6 +105,7 @@ type TBufferByteArray = Array[0..524287] of Byte; PBufferByteArray = ^TBufferByteArray; + constructor TMDTM.Create(Owner: TObject); begin inherited Create; @@ -152,102 +146,13 @@ begin inherited Destroy; end; -type - PMSimColor = function (Color1,Color2,Tolerance : Integer) : boolean of object; - PMGetCol = function (x, y: integer): TColor of object; - -Function TMDTM.AreaShape(Color, Tolerance, Size, Shape: Integer; P: TPoint) : Boolean; inline; - -Var - X, Y, S: Integer; - SimCol: PMSimColor; - GetCol: PMGetCol; +Function AreaShape(Color, Tolerance, Size, Shape: Integer; P: TPoint) : Boolean; inline; Begin - SimCol := @TClient(Client).MFinder.SimilarColors; - GetCol := @TClient(Client).MWindow.GetColor; - Case Shape Of - dtm_Rectangle: - Begin - { - Example: - 3x3 - X X X - X X X - X X X - } - For X := P.X - Size To P.X + Size Do - For Y := P.Y - Size To P.Y + Size Do - If SimCol(GetCol(X, Y), Color, Tolerance) Then - Begin - Result := True; - Exit; - End; - End; - dtm_Cross: - { - Example: - 3x3 - X - X X X - X - } - Begin - For X := P.X - Size To P.X + Size Do - If SimCol(GetCol(X, P.Y), Color, Tolerance) Then - Begin - Result := True; - Exit; - End; - For Y := P.Y - Size To P.Y + Size Do - If SimCol(GetCol(P.X, Y), Color, Tolerance) Then - Begin - Result := True; - Exit; - End; - End; - - dtm_DiagonalCross: - { - Example: - 3x3 - X X - X - X X - - } - Begin - For S := -Size To Size Do - Begin - If SimCol(GetCol(P.X + S, P.Y + S), Color, Tolerance) Then - Begin - Result := True; - Exit; - End; - If SimCol(GetCol(P.X + S, P.Y - S), Color, Tolerance) Then - Begin - Result := True; - Exit; - End; - End; - End; - - 4: - Begin - raise Exception.CreateFmt('The given DTM Shape ([%d]) is not yet' + - ' implemented.', [Shape]); - End; - - Else - WriteLn('Incorrect Shape'); - End; - Result := False; End; -{/\ - Rotates the given point (p) by A (in radians) around the point defined by cx, cy. -/\} +// 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; @@ -306,6 +211,7 @@ begin Result.t[i] := PInteger(@b^[c+24])^; end; end; + result.l := length(result.p); end; function TMDTM.AddDTM(d: TDTM): Integer; @@ -380,61 +286,21 @@ begin SetLength(DTMList[DTM].t, 0); SetLength(DTMList[DTM].asz, 0); SetLength(DTMList[DTM].ash, 0); + DTMList[DTM].l := 0; except + raise Exception.CreateFmt('Invalid DTM passed to FreeDTM', []); //WriteLn('Invalid DTM'); end; SetLength(FreeSpots, Length(FreeSpots) + 1); FreeSpots[High(FreeSpots)] := DTM; end; -procedure DTMBounds(dtm: pDTM; var x1, y1, x2, y2: Integer); -var - i: Integer; - B: TBox; -begin - FillChar(b,sizeOf(TBox),0); - for i := 0 to high(dtm.p) do - begin - B.X1 := Min(B.X1, dtm.p[i].X - dtm.asz[i]); - B.Y1 := Min(B.Y1, dtm.p[i].Y - dtm.asz[i]); - B.X2 := Max(B.X2, dtm.p[i].X + dtm.asz[i]); - B.Y2 := Max(B.Y2, dtm.p[i].Y + dtm.asz[i]); - end; - {writeln(inttostr(B.x1) + ', ' + inttostr(b.y1) + ', ' + inttostr(b.x2) + - ', ' + inttostr(b.y2)); } - x1 += -B.X1; - y1 += -B.Y1; - X2 -= B.X2; - Y2 -= B.Y2; -end; - -// TODO -procedure DTMRotatedBounds(dtm: pDTM; var x1, y1, x2, y2: Integer); -var - i: Integer; - B: TBox; - -begin - FillChar(b,sizeOf(TBox),0); - for i := 0 to high(dtm.p) do - begin - B.X1 := Min(B.X1, dtm.p[i].X - dtm.asz[i]); - B.Y1 := Min(B.Y1, dtm.p[i].Y - dtm.asz[i]); - B.X2 := Max(B.X2, dtm.p[i].X + dtm.asz[i]); - B.Y2 := Max(B.Y2, dtm.p[i].Y + dtm.asz[i]); - end; - - x1 += -Sqr(B.X1); - y1 += -Sqr(B.Y1); - X2 -= Sqr(B.X2); - Y2 -= Sqr(B.Y2); -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. } -function TMDTM.FindDTM(DTM: Integer; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean; +{function TMDTM.FindDTM(DTM: Integer; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean; var temp: pDTM; begin @@ -446,90 +312,26 @@ begin y := 0; Result := False; end; -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. } -function TMDTM.pFindDTM(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean; - -var - mP: TPointArray; - I, J, H, dH: Integer; - Found: Boolean; - TempTP: TPoint; +{function TMDTM.pFindDTM(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean; begin - 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; - - {writeln(inttostr(x1) + ', ' + inttostr(y1) + ', ' + inttostr(x2) + - ', ' + inttostr(y2)); } - DTMBounds(DTM, x1, y1, x2, y2); - {writeln(inttostr(x1) + ', ' + inttostr(y1) + ', ' + inttostr(x2) + - ', ' + inttostr(y2)); } - {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; - 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; - //Now would be the time to Rotate TempTP - 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; - x := mP[I].X; - y := mP[I].Y; - TClient(Client).MWindow.UnFreeze(); - Exit; - end; - end; - TClient(Client).MWindow.UnFreeze(); - Result := False; -end; +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; out Points: TPointArray; x1, y1, x2, y2: Integer): Boolean; +{function TMDTM.FindDTMs(DTM: Integer; out Points: TPointArray; x1, y1, x2, y2: Integer): Boolean; Var temp: pDTM; Begin @@ -540,78 +342,36 @@ Begin SetLength(Points, 0); Result := False; End; -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; out Points: TPointArray; x1, y1, x2, y2: Integer): Boolean; -Var - mP: TPointArray; - I, J, H, dH: Integer; - Found: Boolean; - TempTP: TPoint; -Begin - Result := False; - 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; +{wat} +// Then, first find all occurances of all colours on the given client. +// Each point has a colour, and we call them C_0...C_n. +// MP denotes the points of the main point colour on the client. +// P_i denotes the points on the client for C_i +// O_i denotes the point offset, and possible area shape and size. +// B_i denotes a boolean representation of P_i for C_i, for C_1...C_n. +// B_0 and O_0 are the merry exception here, as we don't need them for C_0, +// which we will show later. - {writeln(inttostr(x1) + ', ' + inttostr(y1) + ', ' + inttostr(x2) + - ', ' + inttostr(y2)); } - DTMBounds(DTM, x1, y1, x2, y2); - { writeln(inttostr(x1) + ', ' + inttostr(y1) + ', ' + inttostr(x2) + - ', ' + inttostr(y2)); } - {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 +// I hope it is clear how this will be respresented in computer data +// structures. - with TClient(Client) do - begin - MWindow.Freeze(); +// Now, we iterate for i in range(1, n), + // We use MP_i, and iterate for j in range(0, dtm_points), + // Calculate the B_j indices (with MP_i and O_j) for each j, and + // see if B_j is not true, go on with MP_i + 1. + // Possible using areasize/shape. - 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; + // else, if B_j is true, continue with this inner loop. + // If B_{0...dtm_points} were all true, the point is valid. {/\ Tries to find the given DTM (index). If found will put the point the dtm has @@ -620,7 +380,7 @@ End; Returns all Angles in an Extended array. /\} -Function TMDTM.FindDTMRotated(DTM: Integer; out x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: Extended): Boolean; +{Function TMDTM.FindDTMRotated(DTM: Integer; out x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: Extended): Boolean; Var temp: pDTM; Begin @@ -633,7 +393,7 @@ Begin aFound := 0.0; Result := False; End; -End; +End; } {/\ Tries to find the given pDTM. If found will put the point the dtm has @@ -642,115 +402,11 @@ End; Returns all Angles in an Extended array. /\} -Function TMDTM.pFindDTMRotated(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out 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; +{Function TMDTM.pFindDTMRotated(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: Extended): Boolean; Begin - 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; - writeln(inttostr(x1) + ', ' + inttostr(y1) + ', ' + inttostr(x2) + - ', ' + inttostr(y2)); - DTMRotatedBounds(DTM, x1, y1, x2, y2); - writeln(inttostr(x1) + ', ' + inttostr(y1) + ', ' + inttostr(x2) + - ', ' + inttostr(y2)); - {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 - writeln('dtm: ' + inttostr(dtm.p[j].x) + ', ' + inttostr(dtm.p[j].y)); - writeln('mP: ' + inttostr(mP[i].x) + ', ' + inttostr(mP[i].y)); - TempTP.X := DTM.p[J].X + mP[I].X; - TempTP.Y := DTM.p[J].Y + mP[I].Y; - writeln('TempTP: ' + inttostr(TempTP.x) + ', ' + inttostr(TempTP.y)); - TempTP := RotatePoint(TempTP, Angle[R], mP[I].X, mP[I].Y); - writeln('TempTP: ' + inttostr(TempTP.x) + ', ' + inttostr(TempTP.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; +End; } {/\ Tries to find the given DTM (index). Will return true if it has found one or more @@ -760,7 +416,7 @@ End; Returns all Angles in a Two Dimensional Extended array. /\} -Function TMDTM.FindDTMsRotated(DTM: Integer; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray): Boolean; +{Function TMDTM.FindDTMsRotated(DTM: Integer; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray): Boolean; Var temp: pDTM; Begin @@ -772,7 +428,7 @@ Begin SetLength(aFound, 0); Result := False; End; -End; +End; } {/\ Tries to find the given pDTM. Will return true if it has found one or more @@ -782,109 +438,12 @@ End; Returns all Angles in a Two Dimensional Extended array. /\} -Function TMDTM.pFindDTMsRotated(DTM: pDTM; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray): Boolean; - -Var - mP: TPointArray; - I, J, H, dH, R, W, PCount: Integer; - Angle: TExtendedArray; - tAngle: Extended; - Found: Boolean; - TempTP: TPoint; +{Function TMDTM.pFindDTMsRotated(DTM: pDTM; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray): Boolean; Begin - 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; - - DTMBounds(DTM, x1, y1, x2, y2); - {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; + // Don't forget to pre calculate the rotated points at the start. + // Saves a lot of rotatepoint() calls. +End; } end. diff --git a/Units/MMLCore/dtmutil.pas b/Units/MMLCore/dtmutil.pas index 5694961..0c102bb 100644 --- a/Units/MMLCore/dtmutil.pas +++ b/Units/MMLCore/dtmutil.pas @@ -35,7 +35,43 @@ Function pDTMToTDTM(Const DTM: pDTM): TDTM; Function tDTMTopDTM(Const DTM: TDTM): pDTM; Procedure PrintpDTM(tDTM : pDTM); +procedure initdtm(var d: pdtm; len: integer); +function ValidMainPointBox(var dtm: pDTM; const x1, y1, x2, y2: Integer): TBox; +function ValidMainPointBoxRotated(var dtm: pDTM; const x1, y1, x2, y2: Integer): TBox; +function DTMConsistent(var dtm: pdtm): boolean; +procedure NormalizeDTM(var dtm: pdtm); + +const + dtm_Rectangle = 0; + dtm_Cross = 1; + dtm_DiagonalCross = 2; + dtm_Circle = 3; + dtm_Triangle = 4; + implementation +uses math; + +// macro +procedure initdtm(var d: pdtm; len: integer); +var + i: integer; +begin + d.l := len; + setlength(d.p, len); + setlength(d.c, len); + setlength(d.t, len); + setlength(d.ash, len); + setlength(d.asz, len); + FillChar(d.p[0], SizeOf(TPoint) * len, 0); + FillChar(d.c[0], SizeOf(Integer) * len, 0); + FillChar(d.t[0], SizeOf(Integer) * len, 0); + FillChar(d.ash[0], SizeOf(Integer) * len, 0); + + // Better set it to 1, than fill with 0. + FillChar(d.asz[0], SizeOf(Integer) * len, 0); + {for i := 0 to len - 1 do + d.asz[i] := 1; } +end; Procedure PrintpDTM(tDTM : pDTM); var @@ -65,7 +101,7 @@ Begin Result.MainPoint := Temp; SetLength(Result.SubPoints, Length(DTM.p) - 1); - For I := 1 To High(DTM.p) Do + For I := 1 To DTM.l-1 Do Begin Temp.X := 0; Temp.Y := 0; Temp.AreaSize := 0; Temp.AreaShape := 0; Temp.Color := 0; Temp.Tolerance := 0; Temp.X := DTM.p[i].x; @@ -111,7 +147,87 @@ Begin Result.asz[I] := DTM.SubPoints[I - 1].AreaSize; Result.ash[I] := DTM.SubPoints[I - 1].AreaShape; End; + Result.l := length(Result.p); End; +{ TODO: Check if bounds are correct? } +function DTMConsistent(var dtm: pdtm): boolean; +var + i: integer; +begin + if dtm.l = 0 then + Exit(False); + if dtm.l <> length(dtm.p) then + Exit(False); + if dtm.l <> length(dtm.c) then + Exit(False); + if dtm.l <> length(dtm.t) then + Exit(False); + if dtm.l <> length(dtm.asz) then + Exit(False); + if dtm.l <> length(dtm.ash) then + Exit(False); + for i := 0 to dtm.l-1 do + if dtm.asz[i] < 0 then + Exit(False); + for i := 0 to dtm.l-1 do + if dtm.c[i] < 0 then + Exit(False); + for i := 0 to dtm.l-1 do + if dtm.t[i] < 0 then + Exit(False); + for i := 0 to dtm.l-1 do + if dtm.ash[i] < 0 then + Exit(False); +end; + +procedure NormalizeDTM(var dtm: pdtm); +var + i:integer; +begin + for i := 0 to dtm.l do + dtm.p[i] := dtm.p[i] - dtm.p[0]; +end; + +Function ValidMainPointBox(var dtm: pDTM; const x1, y1, x2, y2: Integer): TBox; + +var + i: Integer; + b: TBox; + +begin + // writeln(format('%d, %d', [0,0])); + for i := 1 to high(dtm.c) do + begin + dtm.p[i] := dtm.p[i] - dtm.p[0]; + // writeln(format('%d, %d', [dtm.p[i].x, dtm.p[i].y])); + end; + dtm.p[0] := dtm.p[0] - dtm.p[0]; + + + FillChar(b, SizeOf(TBox), 0); + for i := 0 to high(dtm.c) do + begin + b.x1 := min(b.x1, dtm.p[i].x - dtm.asz[i]); + b.y1 := min(b.y1, dtm.p[i].y - dtm.asz[i]); + b.x2 := max(b.x2, dtm.p[i].x + dtm.asz[i]); + b.y2 := max(b.y2, dtm.p[i].y + dtm.asz[i]); + end; + + //FillChar(Result, SizeOf(TBox), 0); + writeln(Format('DTM Bounding Box: %d, %d : %d, %d', [b.x1, b.y1,b.x2,b.y2])); + Result.x1 := x1 - b.x1; + Result.y1 := y1 - b.y1; + Result.x2 := x2 - b.x2; + Result.y2 := y2 - b.y2; +end; + +Function ValidMainPointBoxRotated(var dtm: pDTM; const x1, y1, x2, y2: Integer): TBox; + +begin + +end; + + end. diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index ad02609..d3e1b05 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -77,7 +77,14 @@ type function FindBitmapSpiralTolerance(bitmap: TMufasaBitmap; var x, y: Integer; xs, ys, xe, ye,tolerance : integer): Boolean; function FindBitmapsSpiralTolerance(bitmap: TMufasaBitmap; x, y: Integer; out Points : TPointArray; xs, ys, xe, ye,tolerance: Integer): Boolean; function FindDeformedBitmapToleranceIn(bitmap: TMufasaBitmap; out x, y: Integer; xs, ys, xe, ye: Integer; tolerance: Integer; Range: Integer; AllowPartialAccuracy: Boolean; var accuracy: Extended): Boolean; - protected + + function FindDTM(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean; + function FindDTMs(DTM: pDTM; out Points: TPointArray; x1, y1, x2, y2: Integer): Boolean; + function FindDTMRotated(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: Extended): Boolean; + function FindDTMsRotated(DTM: pDTM; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray): Boolean; + + + protected Client: TObject; Percentage : array[0..255] of Extended; //We store all the possible RGB / 255 divisions. CachedWidth, CachedHeight : integer; @@ -90,7 +97,8 @@ implementation uses Client, // For the Client Casts. colour_conv, // For RGBToColor, etc. - math //min/max + math, //min/max + dtmutil ; type TPRGB32Array = array of PRGB32; @@ -1570,5 +1578,248 @@ begin end; end; +function TMFinder.FindDTM(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: Integer): Boolean; + +var + P: TPointArray; +begin + Self.FindDTMs(DTM, P, x1, y1, x2, y2); + if(Length(p) > 0) then + begin + x := p[0].x; + y := p[0].y; + Exit(True); + end; + Exit(False); +end; + +// TODO: Add a max count, so we can use it more efficiently for FindDTM? +function TMFinder.FindDTMs(DTM: pDTM; out Points: TPointArray; x1, y1, x2, y2: Integer): Boolean; +var + // Colours of DTMs + C: Array of Integer; + + // Bitwise + b: Array of Array of Integer; + + // bounds + W, H: integer; + MA: TBox; + + // for loops, etc + xx, yy: integer; + i, xxx,yyy: Integer; + + // for comparions. + clR, clG, clB: Integer; + + //clientdata + cd: TPRGB32Array; + + PtrData: TRetData; + Ptr: PRGB32; + PtrInc: Integer; + + // point count + pc: Integer = 0; + + label EndOfLoop; + label AnotherLoopEnd; + + + +begin + if not DTMConsistent(dtm) then + begin + raise Exception.CreateFmt('FindDTMs: DTM is not consistent.', []); + Exit; + end; + + // Get the area we should search in for the Main Point. + writeln(Format('%d, %d, %d, %d', [x1,y1,x2,y2])); + MA := ValidMainPointBox(DTM, x1, y1, x2, y2); + writeln(Format('%d, %d, %d, %d', [MA.x1,MA.y1,MA.x2,MA.y2])); + + DefaultOperations(MA.x1, MA.y1, MA.x2, MA.y2); + + // Init data structure B. + W := x2 - x1; + H := y2 - y1; + setlength(b, W + 1); + for i := 0 to W do + begin + setlength(b[i], H + 1); + // does setlength init already? if it doesn't, do we want to init here? + // or do we want to init in the loop, as we loop over every b anyway? + //FillChar(b[i][0], SizeOf(Integer) * H, 0); + end; + + // C = DTM.C + C := DTM.c; + + // Now, we must find the occurances of all colours. + // This part should be turned into a more general function (for DTM Finding). + // Something like FindColorsMultiBooleanArray (?) + + // Retreive Client Data. + PtrData := TClient(Client).MWindow.ReturnData(x1, y1, W + 1, H + 1); + + // Do we want to "cache" these vars? + // We will, for now. Easier to type. + Ptr := PtrData.Ptr; + PtrInc := PtrData.IncPtrWith; + + cd := CalculateRowPtrs(PtrData, h + 1); + writeln(format('w,h: %d, %d', [w,h])); + for yy := 0 to h do + for xx := 0 to w do + begin + //writeln(format('x,y: %d, %d', [xx,yy])); + + // main point + if not TClient(Client).MFinder.SimilarColors(dtm.c[0], RGBToColor(cd[yy][xx].R, cd[yy][xx].G, cd[yy][xx].B), dtm.t[0]) then + goto AnotherLoopEnd; + b[xx][yy] := B[xx][yy] or 1; + for i := 1 to dtm.l - 1 do + begin // use square areashape - it covers all. + for xxx := xx - dtm.asz[i] + dtm.p[i].x to xx + dtm.asz[i] + dtm.p[i].x do + for yyy := yy - dtm.asz[i] + dtm.p[i].y to yy + dtm.asz[i]+ dtm.p[i].y do + // may want to remove this line, but I think it is a good optimisation. + if B[xxx][yyy] and (1 shl i) = 0 then + if TClient(Client).MFinder.SimilarColors(dtm.c[i], RGBToColor(cd[yyy][xxx].R, cd[yyy][xxx].G, cd[yyy][xxx].B), dtm.t[i]) then + b[xxx][yyy] := B[xxx][yyy] or (1 shl i) + else + goto AnotherLoopEnd; + end; + + AnotherLoopEnd: + //writeln(format('b[%d][%d]: %d' ,[xx,yy,b[xx][yy]])); + end; + + {for yy := 0 to h do + for xx := 0 to w do + writeln(format('b[%d][%d]: %d' ,[xx,yy,b[xx][yy]])); } + + // Now iterate over the data. (Main Point Bounds) + for yy := MA.y1-y1 to MA.y2-y1 do + for xx := MA.x1-x1 to MA.x2-x1 do + begin + //writeln(format('Testing for MP at %d, %d', [xx,yy])); + //writeln(format('Testing for MP RealPoints at %d, %d', [xx+x1,yy+y1])); + if (b[xx][yy] and 1) = 0 then + continue; + //writeln(format('Got a MP at %d, %d', [xx,yy])); + //writeln(format('Got a MP Real Points at %d, %d', [xx+x1,yy+y1])); + for i := 1 to dtm.l - 1 do + begin + //writeln(format('i: %d',[i])); + case dtm.ash[i] of + + { Example: + 3x3 (AreaSize = 1) + X X X + X X X + X X X } + //areasize and areashape. areasize = 0 is completly valid + dtm_Rectangle: + begin + //writeln(Format('X - From, To: %d, %d', [xx - dtm.asz[i]+ dtm.p[i].x, xx + dtm.asz[i]+ dtm.p[i].x])); + for xxx := xx - dtm.asz[i] + dtm.p[i].x to xx + dtm.asz[i] + dtm.p[i].x do + for yyy := yy - dtm.asz[i] + dtm.p[i].y to yy + dtm.asz[i]+ dtm.p[i].y do + if b[xxx][yyy] and (1 shl i) = 0 then + goto EndOfLoop; + end; + + { Example: + 3x3 (AreaSize = 1) + X + X X X + X } + dtm_Cross: + begin + for xxx := xx - dtm.asz[i] + dtm.p[i].x to xx + dtm.asz[i] + dtm.p[i].x do + begin + //writeln(format('Cross - One. %d, %d', [xxx,dtm.p[i].y + yy])); + if b[xxx][dtm.p[i].y + yy] and (1 shl i) = 0 then + goto EndOfLoop; + + end; + for yyy := yy - dtm.asz[i] + dtm.p[i].y to yy + dtm.asz[i]+ dtm.p[i].y do + begin + //writeln(format('Cross - One. %d, %d', [dtm.p[i].x + xx,yyy])); + if b[dtm.p[i].x + xx][yyy] and (1 shl i) = 0 then + goto EndOfLoop; + end; + end; + + { Example: + 3x3 (AreaSize = 1) + X X + X + X X } + dtm_DiagonalCross: + begin + for xxx := -dtm.asz[i] to dtm.asz[i] do + begin + if b[xx + dtm.p[i].x + xxx][yy + dtm.p[i].y + xxx] and (1 shl i) = 0 then + goto EndOfLoop; + if b[xx + dtm.p[i].x + xxx][yy + dtm.p[i].y + xxx] and (1 shl i) = 0 then + goto EndOfLoop; + end; + end + + else + begin + raise exception.createFMT('FindDTMs: Invalid Areashape!', []); + Exit; + end; + end; + // point [xx,yy] found if we make it to here + //writeln(Format('Wat (Real Points): %d, %d', [xx+x1, yy+y1])); //Good old wat! + end; + ClientTPA[pc] := Point(xx+x1, yy+y1); + Inc(pc); + //writeln(Format('Found a Point: %d, %d', [xx+x1, yy+y1])); + EndOfLoop: + end; + TClient(Client).MWindow.FreeReturnData; + SetLength(Points, pc); + Move(ClientTPA[0], Points[0], pc * SizeOf(TPoint)); +end; + +function TMFinder.FindDTMRotated(DTM: pDTM; out x, y: Integer; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: Extended): Boolean; + +begin + raise Exception.CreateFmt('Not done yet!', []); +end; + +function TMFinder.FindDTMsRotated(DTM: pDTM; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray): Boolean; + +begin + // Don't forget to pre calculate the rotated points at the start. + // Saves a lot of rotatepoint() calls. + raise Exception.CreateFmt('Not done yet!', []); +end; + end. + +{ crap code } + + // this is the probably the slowest part of the algorithm. +{ for yy := y1 to y2 do + begin + for xx := x1 to x2 do + begin + {for i := 0 to dtm.l - 1 do + begin + // optimise this later... + if TClient(Client).MFinder.SimilarColors(dtm.c[i], RGBToColor(Ptr^.R,Ptr^.G,Ptr^.B) , dtm.t[i]) then + B[xx][yy] := B[xx][yy] or (1 shl i); + end; } + inc(Ptr); + end; + inc(Ptr, PtrInc); + end; + } + diff --git a/Units/MMLCore/mufasatypes.pas b/Units/MMLCore/mufasatypes.pas index 22a90a2..933d448 100644 --- a/Units/MMLCore/mufasatypes.pas +++ b/Units/MMLCore/mufasatypes.pas @@ -86,7 +86,9 @@ type x1, y1, x2, y2: Integer; end; + { TODO: add cts per colour/tolerance? } pDTM = record + l: Integer; p: TPointArray; c, t, asz, ash: TIntegerArray; end;