123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- unit Clipper.Minkowski;
- (*******************************************************************************
- * Author : Angus Johnson *
- * Date : 21 December 2023 *
- * Copyright : Angus Johnson 2010-2022 *
- * Purpose : Minkowski Addition and Difference *
- * License : http://www.boost.org/LICENSE_1_0.txt *
- *******************************************************************************)
- {$I Clipper.inc}
- interface
- uses
- Classes, Math, Clipper.Core;
- function MinkowskiSum(const Pattern, Path: TPath64;
- PathIsClosed: Boolean): TPaths64; overload;
- function MinkowskiSum(const Pattern, Path: TPathD;
- PathIsClosed: Boolean; decimalPlaces: integer = 2): TPathsD; overload;
- function MinkowskiDiff(const path1, path2: TPath64): TPaths64; overload;
- function MinkowskiDiff(const Pattern, Path: TPathD;
- PathIsClosed: Boolean; decimalPlaces: integer): TPathsD; overload;
- implementation
- uses
- Clipper;
- function AddPoints(val1, val2: TPoint64): TPoint64;
- {$IFDEF INLINING} inline; {$ENDIF}
- begin
- Result.X := val1.X + val2.X;
- Result.Y := val1.Y + val2.Y;
- end;
- //------------------------------------------------------------------------------
- function SubtractPoints(val1, val2: TPoint64): TPoint64;
- {$IFDEF INLINING} inline; {$ENDIF}
- begin
- Result.X := val1.X - val2.X;
- Result.Y := val1.Y - val2.Y;
- end;
- //------------------------------------------------------------------------------
- function Minkowski(const Base, Path: TPath64;
- IsSum: Boolean; IsClosed: Boolean): TPaths64;
- var
- i,j,k,g,h, delta, baseLen, pathLen: integer;
- tmp: TPaths64;
- quad: TPath64;
- begin
- delta := Iif(IsClosed, 0 , 1);
- baseLen := Length(Base);
- pathLen := Length(Path);
- setLength(tmp, pathLen);
- for i := 0 to pathLen -1 do
- begin
- setLength(tmp[i], baseLen);
- if IsSum then
- for j := 0 to baseLen -1 do
- tmp[i][j] := AddPoints(Path[i], Base[j])
- else
- for j := 0 to baseLen -1 do
- tmp[i][j] := SubtractPoints(Path[i], Base[j]);
- end;
- SetLength(quad, 4);
- SetLength(Result, (pathLen - delta) * baseLen);
- g := Iif(IsClosed, pathLen - 1, 0);
- for i := delta to pathLen - 1 do
- begin
- h := baseLen - 1;
- k := (i - delta) * baseLen;
- for j := 0 to baseLen - 1 do
- begin
- quad[0] := tmp[g][h];
- quad[1] := tmp[i][h];
- quad[2] := tmp[i][(j)];
- quad[3] := tmp[g][(j)];
- if not IsPositive(quad) then
- Result[k + j] := ReversePath(quad) else
- Result[k + j] := copy(quad, 0, 4);
- h := j;
- end;
- g := i;
- end;
- end;
- //------------------------------------------------------------------------------
- function MinkowskiSum(const Pattern, Path: TPath64; PathIsClosed: Boolean): TPaths64;
- begin
- Result := Union( Minkowski(Pattern, Path, true, PathIsClosed), frNonZero);
- end;
- //------------------------------------------------------------------------------
- function MinkowskiSum(const Pattern, Path: TPathD;
- PathIsClosed: Boolean; decimalPlaces: integer): TPathsD;
- var
- tmp: TPaths64;
- scale: double;
- begin
- scale := Power(10, decimalPlaces);
- tmp := Union( Minkowski(ScalePath(Pattern, scale),
- ScalePath(Path, scale), true, PathIsClosed), frNonZero);
- Result := ScalePathsD(tmp, 1/scale);
- end;
- //------------------------------------------------------------------------------
- function MinkowskiDiff(const path1, path2: TPath64): TPaths64;
- begin
- Result := Union( Minkowski(path1, path2, false, true), frNonZero);
- end;
- //------------------------------------------------------------------------------
- function MinkowskiDiff(const Pattern, Path: TPathD;
- PathIsClosed: Boolean; decimalPlaces: integer): TPathsD;
- var
- tmp: TPaths64;
- scale: double;
- begin
- scale := Power(10, decimalPlaces);
- tmp := Union( Minkowski(ScalePath(Pattern, scale),
- ScalePath(Path, scale), false, PathIsClosed), frNonZero);
- Result := ScalePathsD(tmp, 1/scale);
- end;
- //------------------------------------------------------------------------------
- end.
|