123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- unit GR32_VectorUtils.Clipper2;
- (* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1 or LGPL 2.1 with linking exception
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (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.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * Alternatively, the contents of this file may be used under the terms of the
- * Free Pascal modified version of the GNU Lesser General Public License
- * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
- * of this license are applicable instead of those above.
- * Please see the file LICENSE.txt for additional information concerning this
- * license.
- *
- * The Original Code is Polyline builder for Graphics32
- *
- * The Initial Developer of the Original Code is
- * Anders Melander <[email protected]>
- *
- * Portions created by the Initial Developer are Copyright (C) 2008-2012
- * the Initial Developer. All Rights Reserved.
- *
- * ***** END LICENSE BLOCK ***** *)
- interface
- {$include GR32.inc}
- {$BOOLEVAL OFF}
- uses
- Math,
- Types,
- GR32,
- GR32_VectorUtils,
- GR32_Polygons;
- //------------------------------------------------------------------------------
- //
- // Grow and BuildPoly*line replacements using Clipper2
- //
- //------------------------------------------------------------------------------
- // Note: Clipper miters using square joins instead of bevel joins.
- //------------------------------------------------------------------------------
- type
- PolyLineBuilderClipper = class(TPolyLineBuilder)
- protected
- // Float
- class function Grow(const Points: TArrayOfFloatPoint; const Normals: TArrayOfFloatPoint; const Delta: TFloat; JoinStyle: TJoinStyle = jsMiter; Closed: Boolean = True; MiterLimit: TFloat = DEFAULT_MITER_LIMIT): TArrayOfFloatPoint; overload; override;
- // Fixed
- class function Grow(const Points: TArrayOfFixedPoint; const Normals: TArrayOfFixedPoint; const Delta: TFixed; JoinStyle: TJoinStyle = jsMiter; Closed: Boolean = True; MiterLimit: TFixed = DEFAULT_MITER_LIMIT_FIXED): TArrayOfFixedPoint; overload; override;
- public
- class function SupportedJoinStyles: TJoinStyles; override;
- class function SupportedEndStyles: TEndStyles; override;
- // Float
- class function Grow(const Points: TArrayOfFloatPoint; const Delta: TFloat; JoinStyle: TJoinStyle; Closed: Boolean; MiterLimit: TFloat): TArrayOfFloatPoint; overload; override;
- // Fixed
- class function Grow(const Points: TArrayOfFixedPoint; const Delta: TFixed; JoinStyle: TJoinStyle; Closed: Boolean; MiterLimit: TFixed): TArrayOfFixedPoint; overload; override;
- // Float
- class function BuildPolyLine(const Points: TArrayOfFloatPoint; StrokeWidth: TFloat; JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt; MiterLimit: TFloat = DEFAULT_MITER_LIMIT): TArrayOfFloatPoint; overload; override;
- class function BuildPolyPolyLine(const Points: TArrayOfArrayOfFloatPoint; Closed: Boolean; StrokeWidth: TFloat; JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt; MiterLimit: TFloat = DEFAULT_MITER_LIMIT): TArrayOfArrayOfFloatPoint; overload; override;
- // Fixed
- class function BuildPolyLine(const Points: TArrayOfFixedPoint; StrokeWidth: TFixed; JoinStyle: TJoinStyle; EndStyle: TEndStyle; MiterLimit: TFixed): TArrayOfFixedPoint; overload; override;
- class function BuildPolyPolyLine(const Points: TArrayOfArrayOfFixedPoint; Closed: Boolean; StrokeWidth: TFixed; JoinStyle: TJoinStyle; EndStyle: TEndStyle; MiterLimit: TFixed): TArrayOfArrayOfFixedPoint; overload; override;
- end;
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- //------------------------------------------------------------------------------
- implementation
- uses
- Clipper,
- Clipper.Core,
- Clipper.Offset,
- GR32_Clipper2,
- GR32_Math,
- GR32_Geometry,
- GR32_LowLevel;
- const
- JoinStyleToJoinType: array[TJoinStyle] of TJoinType = (jtMiter, jtBevel, jtRound, jtRound, jtSquare);
- EndStyleToEndType: array[TEndStyle] of TEndType = (etButt, etSquare, etRound);
- //------------------------------------------------------------------------------
- class function PolyLineBuilderClipper.SupportedEndStyles: TEndStyles;
- begin
- Result := [esButt, esSquare, esRound];
- end;
- class function PolyLineBuilderClipper.SupportedJoinStyles: TJoinStyles;
- begin
- Result := [jsMiter, jsBevel, jsRound, jsSquare];
- end;
- //------------------------------------------------------------------------------
- function GrowClipper(const Points: TPaths64; const Delta: TFloat; JoinStyle: TJoinStyle; Closed: Boolean; MiterLimit: TFloat): TPaths64; overload;
- var
- EndType: TEndType;
- begin
- if (Closed) then
- EndType := etPolygon
- else
- EndType := etJoined;
- Result := Clipper.InflatePaths(Points, Delta, JoinStyleToJoinType[JoinStyle], EndType, MiterLimit);
- Result := Clipper.Core.RamerDouglasPeucker(Result, 1);
- end;
- //------------------------------------------------------------------------------
- // Grow
- //------------------------------------------------------------------------------
- class function PolyLineBuilderClipper.Grow(const Points, Normals: TArrayOfFloatPoint; const Delta: TFloat; JoinStyle: TJoinStyle; Closed: Boolean; MiterLimit: TFloat): TArrayOfFloatPoint;
- begin
- Result := Grow(Points, Delta, JoinStyle, Closed, MiterLimit);
- end;
- class function PolyLineBuilderClipper.Grow(const Points: TArrayOfFloatPoint; const Delta: TFloat; JoinStyle: TJoinStyle; Closed: Boolean; MiterLimit: TFloat): TArrayOfFloatPoint;
- var
- Points64, Result64: TPaths64;
- Res: TArrayOfArrayOfFloatPoint;
- begin
- Points64 := [GR32_Clipper2.FloatPointsToPath64(Points)];
- Result64 := GrowClipper(Points64, Delta * GR32_Clipper2.ClipperFloat.GrowScale, JoinStyle, Closed, MiterLimit);
- Res := GR32_Clipper2.Paths64ToFloatPoints(Result64);
- if (Length(Res) > 0) then
- Result := Res[0]
- else
- SetLength(Result, 0);
- end;
- class function PolyLineBuilderClipper.Grow(const Points, Normals: TArrayOfFixedPoint; const Delta: TFixed; JoinStyle: TJoinStyle; Closed: Boolean; MiterLimit: TFixed): TArrayOfFixedPoint;
- begin
- Result := Grow(Points, Delta, JoinStyle, Closed, MiterLimit);
- end;
- class function PolyLineBuilderClipper.Grow(const Points: TArrayOfFixedPoint; const Delta: TFixed; JoinStyle: TJoinStyle; Closed: Boolean; MiterLimit: TFixed): TArrayOfFixedPoint;
- var
- Points64, Result64: TPaths64;
- Res: TArrayOfArrayOfFixedPoint;
- begin
- Points64 := [GR32_Clipper2.FixedPointsToPath64(Points)];
- Result64 := GrowClipper(Points64, Delta * FixedToFloat, JoinStyle, Closed, MiterLimit);
- Res := GR32_Clipper2.Paths64ToFixedPoints(Result64);
- if (Length(Res) > 0) then
- Result := Res[0]
- else
- SetLength(Result, 0);
- end;
- //------------------------------------------------------------------------------
- // BuildPoly*line
- //------------------------------------------------------------------------------
- class function PolyLineBuilderClipper.BuildPolyline(const Points: TArrayOfFloatPoint; StrokeWidth: TFloat; JoinStyle: TJoinStyle; EndStyle: TEndStyle; MiterLimit: TFloat): TArrayOfFloatPoint;
- var
- Paths64: TPaths64;
- EndType: TEndType;
- Result64: TPaths64;
- Res: TArrayOfArrayOfFloatPoint;
- begin
- Paths64 := [GR32_Clipper2.FloatPointsToPath64(Points)];
- EndType := EndStyleToEndType[EndStyle];
- Result64 := Clipper.InflatePaths(Paths64, StrokeWidth * GR32_Clipper2.ClipperFloat.GrowScale, JoinStyleToJoinType[JoinStyle], EndType, MiterLimit);
- Result64 := Clipper.Core.RamerDouglasPeucker(Result64, 1);
- Res := GR32_Clipper2.Paths64ToFloatPoints(Result64);
- if (Length(Res) > 0) then
- Result := Res[0]
- else
- SetLength(Result, 0);
- end;
- class function PolyLineBuilderClipper.BuildPolyPolyLine(const Points: TArrayOfArrayOfFloatPoint; Closed: Boolean; StrokeWidth: TFloat; JoinStyle: TJoinStyle; EndStyle: TEndStyle; MiterLimit: TFloat): TArrayOfArrayOfFloatPoint;
- var
- Paths64: TPaths64;
- EndType: TEndType;
- Result64: TPaths64;
- begin
- Paths64 := GR32_Clipper2.FloatPointsToPaths64(Points);
- if (Closed) then
- EndType := etJoined
- else
- EndType := EndStyleToEndType[EndStyle];
- Result64 := Clipper.InflatePaths(Paths64, StrokeWidth * GR32_Clipper2.ClipperFloat.GrowScale, JoinStyleToJoinType[JoinStyle], EndType, MiterLimit);
- Result64 := Clipper.Core.RamerDouglasPeucker(Result64, 1);
- Result := GR32_Clipper2.Paths64ToFloatPoints(Result64);
- end;
- class function PolyLineBuilderClipper.BuildPolyline(const Points: TArrayOfFixedPoint; StrokeWidth: TFixed; JoinStyle: TJoinStyle; EndStyle: TEndStyle; MiterLimit: TFixed): TArrayOfFixedPoint;
- var
- Paths64: TPaths64;
- Result64: TPaths64;
- Res: TArrayOfArrayOfFixedPoint;
- begin
- Paths64 := [GR32_Clipper2.FixedPointsToPath64(Points)];
- Result64 := Clipper.InflatePaths(Paths64, StrokeWidth * GR32_Clipper2.ClipperFloat.GrowScale, JoinStyleToJoinType[JoinStyle], EndStyleToEndType[EndStyle], MiterLimit);
- Result64 := Clipper.Core.RamerDouglasPeucker(Result64, 1);
- Res := GR32_Clipper2.Paths64ToFixedPoints(Result64);
- if (Length(Res) > 0) then
- Result := Res[0]
- else
- SetLength(Result, 0);
- end;
- class function PolyLineBuilderClipper.BuildPolyPolyLine(const Points: TArrayOfArrayOfFixedPoint; Closed: Boolean; StrokeWidth: TFixed; JoinStyle: TJoinStyle; EndStyle: TEndStyle; MiterLimit: TFixed): TArrayOfArrayOfFixedPoint;
- var
- Paths64: TPaths64;
- EndType: TEndType;
- Result64: TPaths64;
- begin
- Paths64 := GR32_Clipper2.FixedPointsToPaths64(Points);
- if (Closed) then
- EndType := etJoined
- else
- EndType := EndStyleToEndType[EndStyle];
- Result64 := Clipper.InflatePaths(Paths64, StrokeWidth * GR32_Clipper2.ClipperFloat.GrowScale, JoinStyleToJoinType[JoinStyle], EndType, MiterLimit);
- Result64 := Clipper.Core.RamerDouglasPeucker(Result64, 1);
- Result := GR32_Clipper2.Paths64ToFixedPoints(Result64);
- end;
- end.
|