Skip to content

Commit

Permalink
Fixed a bug when offsetting, using delta callback, a path with a sing…
Browse files Browse the repository at this point in the history
…le point. (#752)

Minor code tidy (Delphi).
  • Loading branch information
AngusJohnson committed Dec 21, 2023
1 parent 84b30f1 commit 348e9c4
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 86 deletions.
9 changes: 8 additions & 1 deletion CPP/Clipper2Lib/src/clipper.offset.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 28 November 2023 *
* Date : 21 December 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : Path Offset (Inflate/Shrink) *
Expand Down Expand Up @@ -516,6 +516,13 @@ void ClipperOffset::DoGroupOffset(Group& group)

if (pathLen == 1) // single point
{
if (deltaCallback64_)
{
group_delta_ = deltaCallback64_(*path_in_it, norms, 0, 0);
if (group.is_reversed) group_delta_ = -group_delta_;
abs_delta = std::fabs(group_delta_);
}

if (group_delta_ < 1) continue;
const Point64& pt = (*path_in_it)[0];
//single vertex so build a circle or square ...
Expand Down
25 changes: 20 additions & 5 deletions CSharp/Clipper2Lib/Clipper.Offset.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 28 November 2023 *
* Date : 21 December 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : Path Offset (Inflate/Shrink) *
Expand Down Expand Up @@ -420,13 +420,21 @@ private void DoBevel(Path64 path, int j, int k)
if (j == k)
{
double absDelta = Math.Abs(_groupDelta);
pt1 = new Point64(path[j].X - absDelta * _normals[j].x, path[j].Y - absDelta * _normals[j].y);
pt2 = new Point64(path[j].X + absDelta * _normals[j].x, path[j].Y + absDelta * _normals[j].y);
pt1 = new Point64(
path[j].X - absDelta * _normals[j].x,
path[j].Y - absDelta * _normals[j].y);
pt2 = new Point64(
path[j].X + absDelta * _normals[j].x,
path[j].Y + absDelta * _normals[j].y);
}
else
{
pt1 = new Point64(path[j].X + _groupDelta * _normals[k].x, path[j].Y + _groupDelta * _normals[k].y);
pt2 = new Point64(path[j].X + _groupDelta * _normals[j].x, path[j].Y + _groupDelta * _normals[j].y);
pt1 = new Point64(
path[j].X + _groupDelta * _normals[k].x,
path[j].Y + _groupDelta * _normals[k].y);
pt2 = new Point64(
path[j].X + _groupDelta * _normals[j].x,
path[j].Y + _groupDelta * _normals[j].y);
}
pathOut.Add(pt1);
pathOut.Add(pt2);
Expand Down Expand Up @@ -743,6 +751,13 @@ private void DoGroupOffset(Group group)
{
Point64 pt = p[0];

if (DeltaCallback != null)
{
_groupDelta = DeltaCallback(p, _normals, 0, 0);
if (group.pathsReversed) _groupDelta = -_groupDelta;
absDelta = Math.Abs(_groupDelta);
}

// single vertex so build a circle or square ...
if (group.endType == EndType.Round)
{
Expand Down
35 changes: 34 additions & 1 deletion Delphi/Clipper2Lib/Clipper.Core.pas
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

(*******************************************************************************
* Author : Angus Johnson *
* Date : 5 November 2023 *
* Date : 21 December 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : Core Clipper Library module *
Expand Down Expand Up @@ -337,6 +337,11 @@ procedure QuickSort(SortList: TPointerList;

procedure CheckPrecisionRange(var precision: integer);

function Iif(eval: Boolean; trueVal, falseVal: Boolean): Boolean; overload;
function Iif(eval: Boolean; trueVal, falseVal: integer): integer; overload;
function Iif(eval: Boolean; trueVal, falseVal: Int64): Int64; overload;
function Iif(eval: Boolean; trueVal, falseVal: double): double; overload;

const
MaxInt64 = 9223372036854775807;
MinInt64 = -MaxInt64;
Expand Down Expand Up @@ -655,6 +660,34 @@ procedure TListEx.Swap(idx1, idx2: integer);
// Miscellaneous Functions ...
//------------------------------------------------------------------------------

function Iif(eval: Boolean; trueVal, falseVal: Boolean): Boolean;
{$IFDEF INLINING} inline; {$ENDIF}
begin
if eval then Result := trueVal else Result := falseVal;
end;
//------------------------------------------------------------------------------

function Iif(eval: Boolean; trueVal, falseVal: integer): integer;
{$IFDEF INLINING} inline; {$ENDIF}
begin
if eval then Result := trueVal else Result := falseVal;
end;
//------------------------------------------------------------------------------

function Iif(eval: Boolean; trueVal, falseVal: Int64): Int64;
{$IFDEF INLINING} inline; {$ENDIF}
begin
if eval then Result := trueVal else Result := falseVal;
end;
//------------------------------------------------------------------------------

function Iif(eval: Boolean; trueVal, falseVal: double): double;
{$IFDEF INLINING} inline; {$ENDIF}
begin
if eval then Result := trueVal else Result := falseVal;
end;
//------------------------------------------------------------------------------

procedure CheckPrecisionRange(var precision: integer);
begin
if (precision < -MaxDecimalPrecision) or (precision > MaxDecimalPrecision) then
Expand Down
57 changes: 22 additions & 35 deletions Delphi/Clipper2Lib/Clipper.Engine.pas
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

(*******************************************************************************
* Author : Angus Johnson *
* Date : 1 December 2023 *
* Date : 21 December 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : This is the main polygon clipping module *
Expand Down Expand Up @@ -1721,23 +1721,18 @@ procedure TClipperBase.SetWindCountForClosedPathEdge(e: PActive);
if (Abs(e2.windCnt) > 1) then
begin
// outside prev poly but still inside another.
if (e2.windDx * e.windDx < 0) then
// reversing direction so use the same WC
e.windCnt := e2.windCnt else
// otherwise keep 'reducing' the WC by 1 (ie towards 0) ...
e.windCnt := e2.windCnt + e.windDx;
e.windCnt := Iif(e2.windDx * e.windDx < 0,
e2.windCnt, // reversing direction so use the same WC
e2.windCnt + e.windDx);
end
// now outside all polys of same polytype so set own WC ...
else e.windCnt := e.windDx;
end else
begin
//'e' must be inside 'e2'
if (e2.windDx * e.windDx < 0) then
// reversing direction so use the same WC
e.windCnt := e2.windCnt
else
// otherwise keep 'increasing' the WC by 1 (ie away from 0) ...
e.windCnt := e2.windCnt + e.windDx;
e.windCnt := Iif(e2.windDx * e.windDx < 0,
e2.windCnt, // reversing direction so use the same WC
e2.windCnt + e.windDx); // else keep 'increasing' the WC
end;
e.windCnt2 := e2.windCnt2;
e2 := e2.nextInAEL;
Expand Down Expand Up @@ -1778,8 +1773,8 @@ procedure TClipperBase.SetWindCountForOpenPathEdge(e: PActive);
else if not IsOpen(e2) then inc(cnt1);
e2 := e2.nextInAEL;
end;
if Odd(cnt1) then e.windCnt := 1 else e.windCnt := 0;
if Odd(cnt2) then e.windCnt2 := 1 else e.windCnt2 := 0;
e.windCnt := Iif(Odd(cnt1), 1, 0);
e.windCnt2 := Iif(Odd(cnt2), 1, 0);
end else
begin
// if FClipType in [ctUnion, ctDifference] then e.WindCnt := e.WindDx;
Expand Down Expand Up @@ -2637,12 +2632,10 @@ function TClipperBase.IntersectEdges(e1, e2: PActive; pt: TPoint64): POutPt;
e2.windCnt := e1WindCnt;
end else
begin
if e1.windCnt + e2.windDx = 0 then
e1.windCnt := -e1.windCnt else
Inc(e1.windCnt, e2.windDx);
if e2.windCnt - e1.windDx = 0 then
e2.windCnt := -e2.windCnt else
Dec(e2.windCnt, e1.windDx);
e1.windCnt := Iif(e1.windCnt + e2.windDx = 0,
-e1.windCnt, e1.windCnt + e2.windDx);
e2.windCnt := Iif(e2.windCnt - e1.windDx = 0,
-e2.windCnt, e2.windCnt - e1.windDx);
end;
end else
begin
Expand Down Expand Up @@ -2909,14 +2902,14 @@ function HorzontalsOverlap(const horz1a, horz1b, horz2a, horz2b: TPoint64): bool
begin
if horz1a.X < horz1b.X then
begin
if horz2a.X < horz2b.X then
Result := HorzOverlapWithLRSet(horz1a, horz1b, horz2a, horz2b) else
Result := HorzOverlapWithLRSet(horz1a, horz1b, horz2b, horz2a);
Result := Iif(horz2a.X < horz2b.X,
HorzOverlapWithLRSet(horz1a, horz1b, horz2a, horz2b),
HorzOverlapWithLRSet(horz1a, horz1b, horz2b, horz2a));
end else
begin
if horz2a.X < horz2b.X then
Result := HorzOverlapWithLRSet(horz1b, horz1a, horz2a, horz2b) else
Result := HorzOverlapWithLRSet(horz1b, horz1a, horz2b, horz2a);
Result := Iif(horz2a.X < horz2b.X,
HorzOverlapWithLRSet(horz1b, horz1a, horz2a, horz2b),
HorzOverlapWithLRSet(horz1b, horz1a, horz2b, horz2a));
end;
end;
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -3175,12 +3168,8 @@ procedure TClipperBase.AddNewIntersectNode(e1, e2: PActive; topY: Int64);
ip := GetClosestPointOnSegment(ip, e2.bot, e2.top)
else
begin
if (ip.Y < topY) then
ip.Y := topY else
ip.Y := fBotY;
if (absDx1 < absDx2) then
ip.X := TopX(e1, ip.Y) else
ip.X := TopX(e2, ip.Y);
ip.Y := Iif(ip.Y < topY, topY , fBotY);
ip.X := Iif(absDx1 < absDx2, TopX(e1, ip.Y), TopX(e2, ip.Y));
end;
end;
new(node);
Expand Down Expand Up @@ -4031,9 +4020,7 @@ function TPolyPathBase.GetLevel: Integer;

function TPolyPathBase.GetIsHole: Boolean;
begin
if not Assigned(Parent) then
Result := false else
Result := not Odd(GetLevel);
Result := Iif(Assigned(Parent), not Odd(GetLevel), false);
end;
//------------------------------------------------------------------------------

Expand Down
11 changes: 3 additions & 8 deletions Delphi/Clipper2Lib/Clipper.Minkowski.pas
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

(*******************************************************************************
* Author : Angus Johnson *
* Date : 15 October 2022 *
* Date : 21 December 2023 *
* Copyright : Angus Johnson 2010-2022 *
* Purpose : Minkowski Addition and Difference *
* License : http://www.boost.org/LICENSE_1_0.txt *
Expand Down Expand Up @@ -51,9 +51,7 @@ function Minkowski(const Base, Path: TPath64;
tmp: TPaths64;
quad: TPath64;
begin
if IsClosed then
delta := 0 else
delta := 1;
delta := Iif(IsClosed, 0 , 1);
baseLen := Length(Base);
pathLen := Length(Path);
setLength(tmp, pathLen);
Expand All @@ -71,10 +69,7 @@ function Minkowski(const Base, Path: TPath64;

SetLength(quad, 4);
SetLength(Result, (pathLen - delta) * baseLen);

if IsClosed then
g := pathLen - 1 else
g := 0;
g := Iif(IsClosed, pathLen - 1, 0);

for i := delta to pathLen - 1 do
begin
Expand Down
38 changes: 21 additions & 17 deletions Delphi/Clipper2Lib/Clipper.Offset.pas
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

(*******************************************************************************
* Author : Angus Johnson *
* Date : 28 November 2023 *
* Date : 21 December 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : Path Offset (Inflate/Shrink) *
Expand Down Expand Up @@ -426,9 +426,7 @@ function GetPerpendicD(const pt: TPoint64; const norm: TPointD; delta: double):
function ToggleBoolIf(val, condition: Boolean): Boolean;
{$IFDEF INLINING} inline; {$ENDIF}
begin
if condition then
Result := not val else
Result := val;
Result := Iif(condition, not val, val);
end;
//------------------------------------------------------------------------------

Expand All @@ -444,13 +442,10 @@ procedure TClipperOffset.DoGroupOffset(group: TGroup);
if group.endType = etPolygon then
begin
if (group.lowestPathIdx < 0) then fDelta := Abs(fDelta);
if group.reversed then
fGroupDelta := -fDelta else
fGroupDelta := fDelta;
end else
begin
fGroupDelta := Abs(fDelta);// * 0.5;
end;
fGroupDelta := Iif(group.reversed, -fDelta, fDelta);
end
else
fGroupDelta := Abs(fDelta);

absDelta := Abs(fGroupDelta);
if not ValidateBounds(group.boundsList, absDelta) then
Expand All @@ -467,9 +462,10 @@ procedure TClipperOffset.DoGroupOffset(group: TGroup);
// curve imprecision that's allowed is based on the size of the
// offset (delta). Obviously very large offsets will almost always
// require much less precision. See also offset_triginometry2.svg
if fArcTolerance > 0.01 then
arcTol := Min(absDelta, fArcTolerance) else
arcTol := Log10(2 + absDelta) * 0.25; // empirically derived
arcTol := Iif(fArcTolerance > 0.01,
Min(absDelta, fArcTolerance),
Log10(2 + absDelta) * 0.25); // empirically derived

//http://www.angusj.com/clipper2/Docs/Trigonometry.htm
stepsPer360 := Pi / ArcCos(1 - arcTol / absDelta);
if (stepsPer360 > absDelta * Pi) then
Expand All @@ -493,6 +489,14 @@ procedure TClipperOffset.DoGroupOffset(group: TGroup);
begin
if fGroupDelta < 1 then Continue;
pt0 := fInPath[0];

if Assigned(fDeltaCallback64) then
begin
fGroupDelta := fDeltaCallback64(fInPath, fNorms, 0, 0);
if TGroup(fGroupList[0]).reversed then fGroupDelta := -fGroupDelta;
absDelta := Abs(fGroupDelta);
end;

if (group.endType = etRound) then
begin
r := absDelta;
Expand Down Expand Up @@ -955,9 +959,9 @@ procedure TClipperOffset.DoRound(j, k: Integer; angle: double);
// when fDeltaCallback64 is assigned, fGroupDelta won't be constant,
// so we'll need to do the following calculations for *every* vertex.
absDelta := Abs(fGroupDelta);
if fArcTolerance > 0.01 then
arcTol := Min(absDelta, fArcTolerance) else
arcTol := Log10(2 + absDelta) * 0.25; // empirically derived
arcTol := Iif(fArcTolerance > 0.01,
Min(absDelta, fArcTolerance),
Log10(2 + absDelta) * 0.25); // empirically derived
//http://www.angusj.com/clipper2/Docs/Trigonometry.htm
stepsPer360 := Pi / ArcCos(1 - arcTol / absDelta);
if (stepsPer360 > absDelta * Pi) then
Expand Down
14 changes: 6 additions & 8 deletions Delphi/Clipper2Lib/Clipper.RectClip.pas
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

(*******************************************************************************
* Author : Angus Johnson *
* Date : 9 September 2023 *
* Date : 21 December 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : FAST rectangular clipping *
Expand Down Expand Up @@ -282,7 +282,7 @@ function GetAdjacentLocation(loc: TLocation; isClockwise: Boolean): TLocation;
var
delta: integer;
begin
if isClockwise then delta := 1 else delta := 3;
delta := Iif(isClockwise, 1 , 3);
Result := TLocation((Ord(loc) + delta) mod 4);
end;
//------------------------------------------------------------------------------
Expand All @@ -291,9 +291,9 @@ function IsClockwise(prev, curr: TLocation;
const prevPt, currPt, rectMidPt: TPoint64): Boolean;
{$IFDEF INLINING} inline; {$ENDIF}
begin
if AreOpposites(prev, curr) then
Result := CrossProduct(prevPt, rectMidPt, currPt) < 0 else
Result := HeadingClockwise(prev, curr);
Result := Iif(AreOpposites(prev, curr),
CrossProduct(prevPt, rectMidPt, currPt) < 0,
HeadingClockwise(prev, curr));
end;
//------------------------------------------------------------------------------

Expand Down Expand Up @@ -517,9 +517,7 @@ procedure TRectClip64.AddCorner(prev, curr: TLocation);
cnrIdx: integer;
begin
if prev = curr then Exit;
if (HeadingClockwise(prev, curr)) then
cnrIdx := Ord(prev) else
cnrIdx := Ord(curr);
cnrIdx := Iif(HeadingClockwise(prev, curr), Ord(prev), Ord(curr));
Add(fRectPath[cnrIdx]);
end;
//------------------------------------------------------------------------------
Expand Down
Loading

0 comments on commit 348e9c4

Please sign in to comment.