{
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Original Author: Sean Owen
* Delphi Implementation by E. Spelt and K. Gossens
}
unit ZXing.QrCode.Internal.FinderPattern;
interface
uses
ZXing.ResultPoint;
type
///
/// As we did for ResultPoint, we use an interfaced object to implement automatic deallocation
/// of TAligmnentPattern instances
/// the actual implementation of this interface is in unit ZXing.QrCode.Internal.FinderPatternImplementation
///
IFinderPattern = interface(IResultPoint)
['{EF95BB2F-8863-4A83-840E-699779592EC0}']
function GetCount:integer;
procedure SetCount(value:integer);
///
Determines if this finder pattern "about equals" a finder pattern at the stated
/// position and size -- meaning, it is at nearly the same center with nearly the same size.
///
function aboutEquals(const moduleSize, i, j: Single): Boolean;
///
/// Combines this object's current estimate of a finder pattern position and module size
/// with a new estimate. It returns a new {@code FinderPattern} containing a weighted average
/// based on count.
///
/// The i.
/// The j.
/// New size of the module.
///
function combineEstimate(const i, j, newModuleSize: Single): IFinderPattern;
///
/// Gets the size of the estimated module.
///
///
/// The size of the estimated module.
///
function estimatedModuleSize : Single;
property count : Integer read GetCount write SetCount;
end;
///
/// contains all static methods for using IFinderPattern instances
///
TFinderPatternHelpers= class(TResultPointHelpers)
class function CreateFinderPattern(const posX, posY, estimatedModuleSize: Single;
const count: Integer):IFinderPattern; overload;
class function CreateFinderPattern(const posX, posY, estimatedModuleSize: Single):IFinderPattern; overload;
class procedure orderBestPatterns(const patterns: TArray); static;
end;
implementation
uses ZXing.QrCode.Internal.FinderPatternImplementation;
class function TFinderPatternHelpers.CreateFinderPattern(const posX, posY, estimatedModuleSize: Single; const count: Integer):IFinderPattern;
begin
result := ZXing.QrCode.Internal.FinderPatternImplementation.NewFinderPattern(posX, posY, estimatedModuleSize ,count);
end;
class function TFinderPatternHelpers.CreateFinderPattern(const posX, posY, estimatedModuleSize: Single):IFinderPattern;
begin
result := ZXing.QrCode.Internal.FinderPatternImplementation.NewFinderPattern(posX, posY, estimatedModuleSize);
end;
class procedure TFinderPatternHelpers.orderBestPatterns( const patterns: TArray);
var
zeroOneDistance,
oneTwoDistance,
zeroTwoDistance: Single;
pointA,
pointB,
pointC,
temp: IFinderPattern;
begin
// Find distances between pattern centers
zeroOneDistance := distance(patterns[0], patterns[1]);
oneTwoDistance := distance(patterns[1], patterns[2]);
zeroTwoDistance := distance(patterns[0], patterns[2]);
// Assume one closest to other two is B; A and C will just be guesses at first
if ((oneTwoDistance >= zeroOneDistance) and
(oneTwoDistance >= zeroTwoDistance)) then
begin
pointB := patterns[0];
pointA := patterns[1];
pointC := patterns[2];
end
else if ((zeroTwoDistance >= oneTwoDistance) and
(zeroTwoDistance >= zeroOneDistance)) then
begin
pointB := patterns[1];
pointA := patterns[0];
pointC := patterns[2];
end
else
begin
pointB := patterns[2];
pointA := patterns[0];
pointC := patterns[1];
end;
// Use cross product to figure out whether A and C are correct or flipped.
// This asks whether BC x BA has a positive z component, which is the arrangement
// we want for A, B, C. If it's negative, then we've got it flipped around and
// should swap A and C.
if (TResultPointHelpers.crossProductZ(pointA, pointB, pointC) < 0) then
begin
temp := pointA;
pointA := pointC;
pointC := temp;
end;
patterns[0] := pointA;
patterns[1] := pointB;
patterns[2] := pointC;
end;
end.